// ── Advanced Security · Row-Level Security ───────────────────────────────
// Clean, guided, per-table accordion. Each group gets a None / Owner / Custom
// rule with tooltips and column dropdowns populated per table. The console only
// STORES the rules here; the generated app enforcement is wired separately.

let rlsTables = [];
let rlsGroups = [];
let rlsRuleMap = {};          // "table|groupId" -> { rule_type, owner_column, condition }
let rlsInitialKeys = new Set();
let rlsColumns = {};          // table -> [cols] | null (fallback) | undefined (unloaded)
let rlsColLoading = new Set();
let rlsExpanded = new Set();
let rlsIsOwner = false;

const rlsEsc = (s) => (window.escapeHtml ? window.escapeHtml(String(s ?? '')) :
    String(s ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])));
const rlsKey = (t, g) => `${t}|${g}`;
const OPERATORS = ['=', '!=', '>', '<', '>=', '<=', 'LIKE'];

const RLS_TIP = {
    none: 'No row restriction. This group sees every row it already has table permission to view.',
    owner: 'Per-user. Each user sees only rows where the chosen column holds THEIR OWN user ID — e.g. created_by, user_id, assigned_to.',
    custom: "Fixed rule for the whole group. Everyone in the group sees only rows matching one condition — e.g. region = 'APAC'. Not tied to the individual user.",
    ownerCol: 'Pick the column that stores the record owner’s user ID. At sign-in it is compared to the logged-in user.',
    field: 'The column to test.', value: 'The value to compare against (quotes for text are added automatically).'
};

async function renderAdvanced() {
    if (!window.securitySettings?.db_auth_enabled) {
        const c = document.getElementById('securityPageContainer');
        if (c) c.innerHTML = '<div class="alert alert-warning m-2">Database authentication is not enabled. Please enable it in the Settings tab first.</div>';
        return;
    }
    const container = document.getElementById('securityPageContainer');
    if (!container) return;
    container.innerHTML = '<div class="text-center py-5"><div class="spinner-border text-primary"></div></div>';

    try {
        const [tablesRes, groupsRes, rulesRes] = await Promise.all([
            fetch(`${baseUrl}/project/${projectSlug}/security/tables`),
            fetch(`${baseUrl}/project/${projectSlug}/security/groups`),
            fetch(`${baseUrl}/project/${projectSlug}/security/row-security`)
        ]);
        const tablesData = await tablesRes.json();
        const groupsData = await groupsRes.json();
        const rulesData = await rulesRes.json();
        if (!tablesData.success) throw new Error(tablesData.message || 'Could not load tables');
        if (!groupsData.success) throw new Error(groupsData.message || 'Could not load groups');
        if (!rulesData.success) throw new Error(rulesData.message || 'Could not load rules');

        // Owner sees every table (incl. system); everyone else sees only their own
        // project/business tables. Classification via the shared window.PP_SYSTEM
        // (mirrors core/SystemTables.php) — one source of truth, no private list.
        rlsIsOwner = !!tablesData.isOwner;
        const allTables = tablesData.allTables || tablesData.tables || [];
        rlsTables = (rlsIsOwner || !window.PP_SYSTEM)
            ? allTables
            : allTables.filter(t => !window.PP_SYSTEM.isSystem(t));
        rlsGroups = groupsData.groups || [];

        rlsRuleMap = {};
        (rulesData.rules || []).forEach(r => {
            const key = rlsKey(r.table_name, r.group_id);
            let condition = null;
            try { condition = r.condition_json ? (typeof r.condition_json === 'string' ? JSON.parse(r.condition_json) : r.condition_json) : null; } catch (e) { condition = null; }
            rlsRuleMap[key] = { rule_type: r.rule_type || 'owner_column', owner_column: r.owner_column || '', condition };
        });
        rlsInitialKeys = new Set(Object.keys(rlsRuleMap));

        renderRLSShell(container);
    } catch (e) {
        console.error('renderAdvanced error:', e);
        container.innerHTML = `<div class="alert alert-danger m-2">Failed to load data: ${rlsEsc(e.message)}</div>`;
    }
}

function rlsRuleCount(table) {
    let n = 0;
    for (const g of rlsGroups) if (rlsRuleMap[rlsKey(table, g.id)]) n++;
    return n;
}

function renderRLSShell(container) {
    injectRlsStyles();
    const ownerBadge = rlsIsOwner
        ? '<span class="rls-owner-pill" data-bs-toggle="tooltip" title="You are the platform owner — every table (including system tables) is shown."><i class="bi bi-stars"></i> Owner view · all tables</span>'
        : '';

    container.innerHTML = `
    <div class="rls">
        <div class="rls-bar">
            <div class="rls-flow">
                <span>Sign in</span><i class="bi bi-chevron-right"></i>
                <span>Table permission</span><i class="bi bi-chevron-right"></i>
                <span class="on">Row-Level Security</span><i class="bi bi-chevron-right"></i>
                <span>Visible rows</span>
                ${ownerBadge}
            </div>
            <div class="rls-bar-actions">
                <div class="rls-search"><i class="bi bi-search"></i><input type="text" id="rlsSearch" placeholder="Filter tables…" autocomplete="off"></div>
                <button class="rls-btn ghost" id="rlsTipsBtn"><i class="bi bi-question-circle"></i> Tips</button>
            </div>
        </div>

        <div class="rls-acc" id="rlsAcc"></div>

        <div class="rls-foot">
            <span class="rls-status" id="rlsStatus"><i class="bi bi-shield-check"></i> ${Object.keys(rlsRuleMap).length} rule(s) active across ${rlsTables.length} table(s)</span>
            <button class="rls-btn primary" id="saveRlsRules"><i class="bi bi-save"></i> Save rules</button>
        </div>
    </div>
    ${rlsTipsModalHtml()}
    `;

    renderAccordion('');
    initRlsTooltips(container);

    document.getElementById('rlsSearch')?.addEventListener('input', e => renderAccordion(e.target.value.trim().toLowerCase()));
    document.getElementById('saveRlsRules')?.addEventListener('click', saveRls);
    document.getElementById('rlsTipsBtn')?.addEventListener('click', () => {
        try { new bootstrap.Modal(document.getElementById('rlsTipsModal')).show(); } catch (e) {}
    });
}

function renderAccordion(filter) {
    const acc = document.getElementById('rlsAcc');
    if (!acc) return;
    const tables = filter ? rlsTables.filter(t => t.toLowerCase().includes(filter)) : rlsTables;

    if (!rlsGroups.length) {
        acc.innerHTML = '<div class="rls-empty"><i class="bi bi-people"></i><p>No groups yet. Create a group in <strong>Users &amp; Groups</strong> first — rules are defined per group.</p></div>';
        return;
    }
    if (!tables.length) {
        acc.innerHTML = '<div class="rls-empty"><i class="bi bi-search"></i><p>No tables match your filter.</p></div>';
        return;
    }

    acc.innerHTML = tables.map(table => {
        const count = rlsRuleCount(table);
        const open = rlsExpanded.has(table);
        const badge = count ? `<span class="rls-tbadge active">${count} rule${count > 1 ? 's' : ''}</span>` : `<span class="rls-tbadge">No rules</span>`;
        return `
        <div class="rls-item ${open ? 'open' : ''}" data-table="${rlsEsc(table)}">
            <button type="button" class="rls-item-head" data-table="${rlsEsc(table)}">
                <i class="bi bi-chevron-right rls-caret"></i>
                <i class="bi bi-table rls-item-ic"></i>
                <span class="rls-item-name">${rlsEsc(table)}</span>
                ${badge}
            </button>
            <div class="rls-item-body">${open ? renderGroupsInner(table) : ''}</div>
        </div>`;
    }).join('');

    acc.querySelectorAll('.rls-item-head').forEach(h => h.addEventListener('click', () => toggleTable(h.dataset.table)));
    // Re-bind bodies already open
    tables.forEach(t => { if (rlsExpanded.has(t)) bindGroupEvents(t); });
    initRlsTooltips(acc);
}

async function toggleTable(table) {
    const item = document.querySelector(`.rls-item[data-table="${cssEsc(table)}"]`);
    if (!item) return;
    const body = item.querySelector('.rls-item-body');
    if (rlsExpanded.has(table)) {
        rlsExpanded.delete(table); item.classList.remove('open'); body.innerHTML = '';
        return;
    }
    rlsExpanded.add(table); item.classList.add('open');
    body.innerHTML = '<div class="rls-loading"><div class="spinner-border spinner-border-sm text-primary"></div> Loading columns…</div>';
    await loadColumns(table);
    body.innerHTML = renderGroupsInner(table);
    bindGroupEvents(table);
    initRlsTooltips(body);
}

async function loadColumns(table) {
    if (rlsColumns[table] !== undefined) return rlsColumns[table];
    if (rlsColLoading.has(table)) return;
    rlsColLoading.add(table);
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/security/columns`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ table })
        });
        const data = await res.json();
        rlsColumns[table] = (data.success && Array.isArray(data.columns) && data.columns.length) ? data.columns : null;
    } catch (e) {
        rlsColumns[table] = null; // fallback to text inputs
    } finally {
        rlsColLoading.delete(table);
    }
    return rlsColumns[table];
}

function renderGroupsInner(table) {
    const cols = rlsColumns[table];
    const colNote = Array.isArray(cols)
        ? `<span class="rls-body-note"><i class="bi bi-list-columns"></i> ${cols.length} column${cols.length > 1 ? 's' : ''}</span>`
        : `<span class="rls-body-note warn"><i class="bi bi-exclamation-triangle"></i> columns unavailable — type names manually</span>`;

    const rows = rlsGroups.map(g => {
        const key = rlsKey(table, g.id);
        const rule = rlsRuleMap[key];
        const mode = !rule ? 'none' : (rule.rule_type === 'custom_condition' ? 'custom' : 'owner');
        return `
        <div class="rls-grp" data-table="${rlsEsc(table)}" data-group="${g.id}">
            <div class="rls-grp-name"><i class="bi bi-people-fill"></i> ${rlsEsc(g.name)}</div>
            <div class="rls-seg" role="group" aria-label="Rule type">
                ${segBtn('none', 'None', 'bi-eye', mode)}
                ${segBtn('owner', 'Owner', 'bi-person-badge', mode)}
                ${segBtn('custom', 'Custom', 'bi-sliders', mode)}
            </div>
            <div class="rls-cfg">${renderCfg(table, g.id, mode)}</div>
        </div>`;
    }).join('');

    return `<div class="rls-body-bar">${colNote}<span class="rls-body-hint">Pick how each group is restricted on <strong>${rlsEsc(table)}</strong>.</span></div>${rows}`;
}

function segBtn(mode, label, icon, current) {
    return `<button type="button" class="rls-seg-btn ${current === mode ? 'on' : ''}" data-mode="${mode}" data-bs-toggle="tooltip" title="${rlsEsc(RLS_TIP[mode])}"><i class="bi ${icon}"></i> ${label}</button>`;
}

function renderCfg(table, groupId, mode) {
    const key = rlsKey(table, groupId);
    const rule = rlsRuleMap[key] || {};
    const cols = rlsColumns[table];

    if (mode === 'none') {
        return '<div class="rls-hint muted"><i class="bi bi-eye"></i> Sees all rows this group can view.</div>';
    }
    if (mode === 'owner') {
        const val = rule.owner_column || '';
        const picker = Array.isArray(cols)
            ? `<select class="rls-input rls-owner-col">${optList(cols, val, '— select column —')}</select>`
            : `<input type="text" class="rls-input rls-owner-col" value="${rlsEsc(val)}" placeholder="e.g. user_id">`;
        return `
        <label class="rls-field">Owner column <i class="bi bi-info-circle rls-i" data-bs-toggle="tooltip" title="${rlsEsc(RLS_TIP.ownerCol)}"></i></label>
        <div class="rls-owner-wrap">${picker}</div>
        <div class="rls-preview" data-role="preview">${ownerPreview(val)}</div>`;
    }
    // custom
    const cond = rule.condition || { field: '', operator: '=', value: '' };
    const fieldPicker = Array.isArray(cols)
        ? `<select class="rls-input rls-c-field">${optList(cols, cond.field, 'Field')}</select>`
        : `<input type="text" class="rls-input rls-c-field" value="${rlsEsc(cond.field)}" placeholder="Field">`;
    return `
    <div class="rls-cond">
        <span class="rls-cond-lead">Rows where</span>
        ${fieldPicker}
        <select class="rls-input rls-c-op">${OPERATORS.map(o => `<option ${cond.operator === o ? 'selected' : ''}>${o}</option>`).join('')}</select>
        <input type="text" class="rls-input rls-c-val" value="${rlsEsc(cond.value)}" placeholder="value" data-bs-toggle="tooltip" title="${rlsEsc(RLS_TIP.value)}">
    </div>
    <div class="rls-preview" data-role="preview">${customPreview(cond)}</div>`;
}

function optList(cols, selected, placeholder) {
    let o = `<option value="">${rlsEsc(placeholder)}</option>`;
    for (const c of cols) o += `<option value="${rlsEsc(c)}" ${selected === c ? 'selected' : ''}>${rlsEsc(c)}</option>`;
    return o;
}
function ownerPreview(col) {
    return col
        ? `<i class="bi bi-funnel"></i> Shows rows where <b>${rlsEsc(col)}</b> = <b>the signed-in user’s ID</b>.`
        : '<i class="bi bi-dash-circle"></i> Choose a column to activate this rule.';
}
function customPreview(cond) {
    if (!cond.field || cond.value === '' || cond.value == null) return '<i class="bi bi-dash-circle"></i> Fill in a field and value to activate this rule.';
    const q = /^-?\d+(\.\d+)?$/.test(String(cond.value)) ? cond.value : `'${cond.value}'`;
    return `<i class="bi bi-funnel"></i> Shows rows where <b>${rlsEsc(cond.field)}</b> ${rlsEsc(cond.operator)} <b>${rlsEsc(q)}</b>.`;
}

function bindGroupEvents(table) {
    const item = document.querySelector(`.rls-item[data-table="${cssEsc(table)}"] .rls-item-body`);
    if (!item) return;

    item.querySelectorAll('.rls-seg-btn').forEach(btn => btn.addEventListener('click', () => {
        const grp = btn.closest('.rls-grp');
        const groupId = grp.dataset.group;
        grp.querySelectorAll('.rls-seg-btn').forEach(b => b.classList.toggle('on', b === btn));
        grp.querySelector('.rls-cfg').innerHTML = renderCfg(table, groupId, btn.dataset.mode);
        bindCfgEvents(grp, table, groupId);
        initRlsTooltips(grp);
        commitGroup(table, groupId);
    }));

    item.querySelectorAll('.rls-grp').forEach(grp => bindCfgEvents(grp, table, grp.dataset.group));
}

function bindCfgEvents(grp, table, groupId) {
    grp.querySelectorAll('.rls-input').forEach(el => {
        const handler = () => { updatePreview(grp); commitGroup(table, groupId); };
        el.addEventListener('change', handler);
        if (el.tagName === 'INPUT') el.addEventListener('input', handler);
    });
}

function currentMode(grp) {
    const on = grp.querySelector('.rls-seg-btn.on');
    return on ? on.dataset.mode : 'none';
}

function readGroup(grp) {
    const mode = currentMode(grp);
    if (mode === 'none') return { rule_type: 'none' };
    if (mode === 'owner') {
        const col = grp.querySelector('.rls-owner-col')?.value.trim() || '';
        return col ? { rule_type: 'owner_column', owner_column: col } : { rule_type: 'none' };
    }
    const field = grp.querySelector('.rls-c-field')?.value.trim() || '';
    const operator = grp.querySelector('.rls-c-op')?.value || '=';
    const value = grp.querySelector('.rls-c-val')?.value ?? '';
    return (field && value !== '') ? { rule_type: 'custom_condition', condition: { field, operator, value } } : { rule_type: 'none' };
}

function updatePreview(grp) {
    const preview = grp.querySelector('[data-role="preview"]');
    if (!preview) return;
    const r = readGroup(grp);
    if (r.rule_type === 'owner_column') preview.innerHTML = ownerPreview(r.owner_column);
    else if (r.rule_type === 'custom_condition') preview.innerHTML = customPreview(r.condition);
}

// Update the in-memory model for one group + refresh badges/status; then auto-save.
function commitGroup(table, groupId) {
    const grp = document.querySelector(`.rls-grp[data-table="${cssEsc(table)}"][data-group="${groupId}"]`);
    if (!grp) return;
    const key = rlsKey(table, groupId);
    const r = readGroup(grp);
    if (r.rule_type === 'none') delete rlsRuleMap[key];
    else rlsRuleMap[key] = r;
    refreshTableBadge(table);
    refreshStatus();
    if (window.securityAutoSave) window.securityAutoSave();
}

function refreshTableBadge(table) {
    const head = document.querySelector(`.rls-item[data-table="${cssEsc(table)}"] .rls-item-head .rls-tbadge`);
    if (!head) return;
    const n = rlsRuleCount(table);
    head.className = 'rls-tbadge' + (n ? ' active' : '');
    head.textContent = n ? `${n} rule${n > 1 ? 's' : ''}` : 'No rules';
}
function refreshStatus() {
    const s = document.getElementById('rlsStatus');
    if (s) s.innerHTML = `<i class="bi bi-shield-check"></i> ${Object.keys(rlsRuleMap).length} rule(s) active across ${rlsTables.length} table(s)`;
}

function collectPayload() {
    const payload = [];
    for (const key in rlsRuleMap) {
        const [t, g] = key.split('|');
        const r = rlsRuleMap[key];
        payload.push({ table_name: t, group_id: +g, rule_type: r.rule_type, owner_column: r.owner_column || null, condition: r.condition || null });
    }
    // Explicit clears for rules that existed on load but are now gone.
    for (const key of rlsInitialKeys) {
        if (!(key in rlsRuleMap)) {
            const [t, g] = key.split('|');
            payload.push({ table_name: t, group_id: +g, rule_type: 'none' });
        }
    }
    return payload;
}

async function saveRls() {
    const btn = document.getElementById('saveRlsRules');
    const prev = btn ? btn.innerHTML : '';
    if (btn) { btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Saving…'; }
    try {
        const res = await fetch(`${baseUrl}/project/${projectSlug}/security/row-security`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ rules: collectPayload() })
        });
        const data = await res.json();
        if (data.success) {
            rlsInitialKeys = new Set(Object.keys(rlsRuleMap));
            pp.dialog.toast('success', data.message || 'Row-level rules saved');
        } else {
            pp.dialog.alert('Error', data.message || 'Could not save rules', 'error');
        }
    } catch (e) {
        console.error(e);
        pp.dialog.toast('error', 'Network error while saving');
    } finally {
        if (btn) { btn.disabled = false; btn.innerHTML = prev; }
    }
}

// Bootstrap tooltips (dispose+recreate to avoid duplicates).
function initRlsTooltips(scope) {
    if (!window.bootstrap || !scope) return;
    scope.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => {
        try { bootstrap.Tooltip.getInstance(el)?.dispose(); new bootstrap.Tooltip(el, { container: 'body' }); } catch (e) {}
    });
}

// Escape a value for use inside a CSS attribute selector.
function cssEsc(s) { return (window.CSS && CSS.escape) ? CSS.escape(s) : String(s).replace(/["\\]/g, '\\$&'); }

function rlsTipsModalHtml() {
    return `
    <div class="modal fade" id="rlsTipsModal" tabindex="-1" aria-hidden="true">
      <div class="modal-dialog modal-lg modal-dialog-scrollable">
        <div class="modal-content">
          <div class="modal-header"><h5 class="modal-title"><i class="bi bi-lightbulb me-2"></i>Row-Level Security — how it works</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
          <div class="modal-body">
            <p class="text-muted">RLS filters the <em>rows</em> a group can see, <strong>after</strong> table permission has already allowed access. If a group can’t view a table, RLS never applies.</p>
            <div class="rls-tip"><span class="rls-tip-ic none"><i class="bi bi-eye"></i></span><div><h6>None</h6><p>${RLS_TIP.none}</p></div></div>
            <div class="rls-tip"><span class="rls-tip-ic owner"><i class="bi bi-person-badge"></i></span><div><h6>Owner column</h6><p>${RLS_TIP.owner}</p><code>WHERE created_by = &lt;current user id&gt;</code></div></div>
            <div class="rls-tip"><span class="rls-tip-ic custom"><i class="bi bi-sliders"></i></span><div><h6>Custom condition</h6><p>${RLS_TIP.custom}</p><code>WHERE region = 'APAC'</code></div></div>
            <hr>
            <h6 class="mb-1">Good to know</h6>
            <ul class="small text-muted mb-0">
                <li>If a user is in several groups, their rules combine with <strong>OR</strong> (they see rows matching any of their groups’ rules).</li>
                <li>The platform owner and administrators are not restricted by RLS.</li>
                <li>Index the columns you filter on for good performance on large tables.</li>
                <li>Always test with a normal (non-admin) user before going live.</li>
            </ul>
          </div>
          <div class="modal-footer"><button class="btn btn-secondary" data-bs-dismiss="modal">Close</button></div>
        </div>
      </div>
    </div>`;
}

function injectRlsStyles() {
    if (document.getElementById('rlsStyles')) return;
    const css = `
    .rls{max-width:1080px;margin:0 auto;padding:2px 4px 24px}
    .rls-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:11px}
    .rls-bar-actions{display:flex;gap:8px;align-items:center;margin-left:auto}
    .rls-search{display:flex;align-items:center;gap:7px;background:var(--bs-body-bg,#fff);border:1px solid var(--bs-border-color,#e2e8f0);border-radius:9px;padding:6px 10px;color:#64748b}
    .rls-search input{border:0;outline:0;background:transparent;font-size:12.5px;width:140px;color:inherit}
    .rls-btn{display:inline-flex;align-items:center;gap:7px;border-radius:9px;font-size:12.5px;font-weight:650;padding:7px 13px;cursor:pointer;border:1px solid transparent;transition:.15s}
    .rls-btn.ghost{background:var(--bs-body-bg,#fff);border-color:var(--bs-border-color,#e2e8f0);color:var(--bs-body-color,#334155)}
    .rls-btn.ghost:hover{border-color:#a5b4fc;color:#4f46e5}
    .rls-btn.primary{background:#4f46e5;color:#fff}.rls-btn.primary:hover{filter:brightness(1.08)}
    .rls-btn.primary:disabled{opacity:.7;cursor:default}
    .rls-flow{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:10.5px;font-weight:700;color:#94a3b8;text-transform:uppercase;letter-spacing:.04em;background:var(--bs-tertiary-bg,#f8fafc);border:1px solid var(--bs-border-color,#eef2f7);border-radius:9px;padding:6px 12px}
    .rls-flow .bi{font-size:9px}.rls-flow .on{color:#4f46e5}
    .rls-owner-pill{display:inline-flex;align-items:center;gap:6px;color:#7c3aed;background:#7c3aed18;border-radius:999px;padding:3px 10px;font-size:10px}
    .rls-acc{border:1px solid var(--bs-border-color,#e2e8f0);border-radius:11px;overflow:hidden;background:var(--bs-body-bg,#fff)}
    .rls-item{border:0}
    .rls-item+.rls-item{border-top:1px solid var(--bs-border-color,#eef2f7)}
    .rls-item.open{background:color-mix(in srgb,#4f46e5 4%,transparent)}
    .rls-item-head{display:flex;align-items:center;gap:10px;width:100%;border:0;background:transparent;padding:8px 13px;cursor:pointer;font:inherit;text-align:left;color:var(--bs-body-color,#0f172a);transition:background .12s}
    .rls-item-head:hover{background:var(--bs-tertiary-bg,#f6f8fc)}
    .rls-item.open .rls-item-head:hover{background:transparent}
    .rls-caret{font-size:11px;color:#94a3b8;transition:transform .18s}
    .rls-item.open .rls-caret{transform:rotate(90deg);color:#4f46e5}
    .rls-item-ic{font-size:15px;color:#4f46e5}
    .rls-item-name{font-weight:650;font-size:13px;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .rls-tbadge{flex:0 0 auto;font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.04em;padding:2px 8px;border-radius:999px;background:var(--bs-tertiary-bg,#f1f5f9);color:#94a3b8}
    .rls-tbadge.active{background:#16a34a;color:#fff}
    .rls-item-body{display:none}
    .rls-item.open .rls-item-body{display:block;border-top:1px solid var(--bs-border-color,#eef2f7)}
    .rls-loading{padding:16px;color:#64748b;font-size:13px;display:flex;gap:9px;align-items:center}
    .rls-body-bar{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:10px 16px;background:var(--bs-tertiary-bg,#fafbfe);border-bottom:1px solid var(--bs-border-color,#f1f5f9)}
    .rls-body-note{font-size:11.5px;font-weight:700;color:#64748b;display:inline-flex;gap:5px;align-items:center}
    .rls-body-note.warn{color:#b45309}
    .rls-body-hint{font-size:12px;color:#94a3b8}
    .rls-grp{display:flex;align-items:center;gap:14px;padding:12px 16px;flex-wrap:wrap}
    .rls-grp+.rls-grp{border-top:1px dashed var(--bs-border-color,#eef2f7)}
    .rls-grp-name{flex:0 0 150px;font-weight:700;font-size:13px;color:var(--bs-body-color,#334155);display:flex;gap:7px;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
    .rls-grp-name .bi{color:#4f46e5}
    .rls-seg{flex:0 0 auto;display:inline-flex;background:var(--bs-tertiary-bg,#f1f5f9);border-radius:9px;padding:3px}
    .rls-seg-btn{border:0;background:transparent;border-radius:7px;font-size:12px;font-weight:650;padding:5px 11px;cursor:pointer;color:#64748b;display:inline-flex;gap:5px;align-items:center;transition:.14s}
    .rls-seg-btn:hover{color:#4f46e5}
    .rls-seg-btn.on{background:var(--bs-body-bg,#fff);color:#4f46e5;box-shadow:0 1px 3px rgba(15,23,42,.12)}
    .rls-cfg{flex:1;min-width:220px}
    .rls-field{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.04em;color:#94a3b8;margin:0 0 5px;display:flex;gap:6px;align-items:center}
    .rls-i{color:#a5b4fc;cursor:help}
    .rls-input{border:1px solid var(--bs-border-color,#dbe2ea);border-radius:9px;padding:7px 10px;font-size:13px;background:var(--bs-body-bg,#fff);color:var(--bs-body-color,#0f172a)}
    .rls-input:focus{outline:0;border-color:#a5b4fc;box-shadow:0 0 0 3px #4f46e522}
    .rls-owner-col{min-width:200px}
    .rls-cond{display:flex;gap:7px;align-items:center;flex-wrap:wrap}
    .rls-cond-lead{font-size:12px;color:#94a3b8;font-weight:600}
    .rls-c-field{min-width:130px}.rls-c-op{min-width:64px}.rls-c-val{min-width:110px}
    .rls-preview{margin-top:7px;font-size:12px;color:#475569;background:var(--bs-tertiary-bg,#f8fafc);border-radius:8px;padding:6px 10px;display:inline-flex;gap:6px;align-items:center}
    .rls-preview b{color:#4f46e5}.rls-preview .bi{color:#94a3b8}
    .rls-hint{font-size:12.5px;color:#64748b;display:inline-flex;gap:7px;align-items:center}
    .rls-hint.muted{color:#94a3b8}
    .rls-foot{position:sticky;bottom:0;display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:16px;padding:12px 4px;background:linear-gradient(transparent,var(--bs-body-bg,#fff) 40%)}
    .rls-status{font-size:12.5px;color:#64748b;display:inline-flex;gap:7px;align-items:center}.rls-status .bi{color:#16a34a}
    .rls-empty{text-align:center;padding:40px 20px;color:#94a3b8}.rls-empty .bi{font-size:30px;opacity:.6}.rls-empty p{margin:10px 0 0;font-size:13px}
    .rls-tip{display:flex;gap:12px;padding:10px 0}
    .rls-tip-ic{flex:0 0 auto;width:38px;height:38px;border-radius:10px;display:grid;place-items:center;font-size:17px;color:#fff}
    .rls-tip-ic.none{background:#94a3b8}.rls-tip-ic.owner{background:#4f46e5}.rls-tip-ic.custom{background:#0ea5e9}
    .rls-tip h6{margin:0 0 3px;font-size:14px;font-weight:750}.rls-tip p{margin:0 0 5px;font-size:12.5px;color:#64748b}
    .rls-tip code{font-size:11.5px;background:#0f172a0d;padding:2px 7px;border-radius:6px;color:#4f46e5}
    @media(max-width:640px){.rls-grp-name{flex-basis:100%}.rls-cfg{min-width:100%}}
    `;
    const style = document.createElement('style');
    style.id = 'rlsStyles'; style.textContent = css;
    document.head.appendChild(style);
}

window.renderAdvanced = renderAdvanced;
