<?php
/**
 * Standard logged-in page header (Tabler.io v1.0 from CDN).
 *
 * Page must `require_once 'includes/config.php';` and call `require_login()`
 * before including this. Set $pageTitle before including for a custom title.
 */
$user = current_user();
$pageTitle = $pageTitle ?? 'Dashboard';
$here = basename($_SERVER['PHP_SELF']);

/* Current user's role label (shown in the top-bar so you can see which role view you're in). */
$myRoleLabel = 'No role';
try {
    if ($user) {
        $rs = db()->prepare('SELECT r.name FROM user_roles ur JOIN roles r ON r.id = ur.role_id WHERE ur.user_id = ? ORDER BY r.name');
        $rs->execute([$user['id']]);
        $rn = $rs->fetchAll(PDO::FETCH_COLUMN);
        if ($rn) $myRoleLabel = implode(', ', $rn);
    }
} catch (Throwable $e) {}

/* Quick "View as" switcher — a sysadmin (incl. one already impersonating) can hop between users
 * without logging out. Uses the existing /admin/impersonate.php controller. */
$switchUsers = [];
try {
    $adminId = is_impersonating() ? (int) impersonator_id() : (int) ($user['id'] ?? 0);
    if ($adminId && user_has_role($adminId, 'sysadmin')) {
        $sw = db()->prepare("SELECT u.id, u.name, COALESCE(GROUP_CONCAT(DISTINCT r.name ORDER BY r.id SEPARATOR ', '),'') roles
            FROM users u LEFT JOIN user_roles ur ON ur.user_id=u.id LEFT JOIN roles r ON r.id=ur.role_id
            WHERE u.user_type='internal' AND u.status='active' AND u.id<>?
            GROUP BY u.id, u.name ORDER BY u.name LIMIT 60");
        $sw->execute([(int) ($user['id'] ?? 0)]);
        $switchUsers = $sw->fetchAll();
    }
} catch (Throwable $e) {}

/* Build a quick-search index for the command palette (pages + recent reports + clients). */
$navIndex = [
    ['t' => 'Dashboard',          'u' => url('/dashboard.php'),                'i' => 'home',            'g' => 'Pages'],
    ['t' => 'Verticals',          'u' => url('/admin/verticals.php'),          'i' => 'building',        'g' => 'Master data'],
    ['t' => 'Clients',          'u' => url('/admin/clients.php'),            'i' => 'users',          'g' => 'Master data'],
    ['t' => 'Processes',        'u' => url('/admin/processes.php'),          'i' => 'list-tree',      'g' => 'Master data'],
    ['t' => 'Report builder',   'u' => url('/admin/report-builder.php'),     'i' => 'template',       'g' => 'Reports'],
    ['t' => 'Reports browser',  'u' => url('/admin/reports.php'),            'i' => 'report-analytics','g' => 'Reports'],
    ['t' => 'Users',            'u' => url('/admin/users.php'),              'i' => 'user-cog',       'g' => 'Users & access'],
    ['t' => 'Audit log',        'u' => url('/admin/audit.php'),              'i' => 'history',        'g' => 'Logs'],
    ['t' => 'Login activity',   'u' => url('/admin/login-logs.php'),         'i' => 'shield-lock',    'g' => 'Logs'],
    ['t' => 'Report Access',    'u' => url('/admin/access.php'),             'i' => 'key',            'g' => 'Logs'],
    ['t' => 'Scheduled reports','u' => url('/admin/scheduled.php'),          'i' => 'clock-play',     'g' => 'Settings'],
    ['t' => 'Notifications',    'u' => url('/admin/notifications.php'),      'i' => 'bell',           'g' => 'Settings'],
    ['t' => 'Settings',         'u' => url('/admin/settings.php'),           'i' => 'settings',       'g' => 'Settings'],
    ['t' => 'System Reference', 'u' => url('/admin/reference.php'),          'i' => 'info-circle',    'g' => 'Settings'],
];
try {
    $palRows = db()->query(
        "SELECT r.id, r.name, c.name AS cname FROM reports r
         JOIN processes p ON p.id=r.process_id JOIN clients c ON c.id=p.client_id
         WHERE r.deleted_at IS NULL ORDER BY r.updated_at DESC LIMIT 12"
    )->fetchAll();
    foreach ($palRows as $r) {
        $navIndex[] = ['t' => $r['name'], 'u' => url('/admin/report-view.php?id='.$r['id']),
                       'i' => 'chart-pie-2', 'g' => 'Reports · '.$r['cname']];
    }
} catch (Throwable $e) { /* ignore — DB might not be ready on first run */ }
?><!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta name="theme-color" content="#0f1825"/>
    <title><?= e($pageTitle) ?> &mdash; <?= e(APP_NAME) ?></title>
    <link rel="icon" type="image/svg+xml" href="<?= e(url('/favicon.svg')) ?>"/>
    <link rel="mask-icon" href="<?= e(url('/favicon.svg')) ?>" color="#7c3aed"/>

    <!-- Pre-paint theme toggle to avoid FOUC -->
    <script>(function(){try{var t=localStorage.getItem('m_theme')||'light';document.documentElement.setAttribute('data-bs-theme',t);document.documentElement.setAttribute('data-m-theme',t);}catch(e){}})();</script>

    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/@tabler/core@1.0.0-beta20/dist/css/tabler.min.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@2.47.0/tabler-icons.min.css" rel="stylesheet"/>
    <link href="https://cdn.datatables.net/1.13.8/css/dataTables.bootstrap5.min.css" rel="stylesheet"/>
    <link href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.bootstrap5.min.css" rel="stylesheet"/>
    <link href="https://cdn.datatables.net/rowgroup/1.5.0/css/rowGroup.bootstrap5.min.css" rel="stylesheet"/>
    <link href="https://cdn.datatables.net/fixedheader/3.4.0/css/fixedHeader.bootstrap5.min.css" rel="stylesheet"/>

    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script src="https://cdn.datatables.net/1.13.8/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.13.8/js/dataTables.bootstrap5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
    <script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.print.min.js"></script>
    <script src="https://cdn.datatables.net/rowgroup/1.5.0/js/dataTables.rowGroup.min.js"></script>
    <script src="https://cdn.datatables.net/fixedheader/3.4.0/js/dataTables.fixedHeader.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts@3.45.2/dist/apexcharts.min.js"></script>

    <style>
        :root {
            --tblr-primary: #206bc4;
            --m-bg: #f4f6fb;
            --m-bg-elev: #ffffff;
            --m-surface: #ffffff;
            --m-surface-2: #f8fafc;
            --m-border: #e6eaf0;
            --m-border-strong: #d8dee8;
            --m-text: #1a2332;
            --m-text-soft: #6c7a89;
            --m-shadow-sm: 0 1px 2px rgba(15,23,37,.04), 0 1px 3px rgba(15,23,37,.04);
            --m-shadow-md: 0 4px 14px rgba(15,23,37,.08);
            --m-side-bg: linear-gradient(180deg, #1a2332 0%, #0f1825 100%);
            --m-side-text: #cfd6e4;
            --m-side-mute: #8893a8;
            --m-accent: #206bc4;
            --m-accent-2: #4f46e5;
            --m-good: #16a34a;
            --m-warn: #f59e0b;
            --m-bad:  #dc2626;
        }
        html[data-bs-theme="dark"] {
            --m-bg: #0b1220;
            --m-bg-elev: #111a2c;
            --m-surface: #131e34;
            --m-surface-2: #0e1729;
            --m-border: #1e2a44;
            --m-border-strong: #28365a;
            --m-text: #e7ecf5;
            --m-text-soft: #97a2b6;
            --m-shadow-sm: 0 1px 2px rgba(0,0,0,.3);
            --m-shadow-md: 0 6px 24px rgba(0,0,0,.45);
            --m-side-bg: linear-gradient(180deg, #0a1220 0%, #060c18 100%);
            --tblr-body-bg: var(--m-bg);
            --tblr-body-color: var(--m-text);
            --tblr-card-bg: var(--m-surface);
            --tblr-border-color: var(--m-border);
        }

        body {
            background: var(--m-bg);
            color: var(--m-text);
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            font-feature-settings: 'cv02','cv03','cv04','cv11';
        }
        code, pre, .text-code, .font-mono { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Consolas, monospace; }

        /* ============= SIDEBAR ============= */
        .navbar-vertical.navbar-expand-lg {
            background: var(--m-side-bg) !important;
            border-right: 0;
        }
        .navbar-vertical .navbar-brand { padding: 1rem 1rem .5rem; }
        .navbar-vertical .navbar-brand a { letter-spacing: .01em; }
        .navbar-vertical .nav-link { transition: all .15s ease; color: var(--m-side-text); border-radius: 6px; margin: 1px 8px; }
        .navbar-vertical .nav-link:hover { background: rgba(255,255,255,.06); color: #fff; }
        .navbar-vertical .nav-link.active,
        .navbar-vertical .nav-item.active .nav-link {
            background: linear-gradient(90deg, rgba(32,107,196,.22) 0%, rgba(32,107,196,.05) 100%) !important;
            border-left: 3px solid var(--tblr-primary);
            padding-left: calc(0.75rem - 3px);
            color: #fff;
            box-shadow: inset 0 0 0 1px rgba(255,255,255,.04);
        }
        .navbar-vertical .nav-link-icon { color: rgba(255,255,255,.55); }
        .navbar-vertical .nav-link.active .nav-link-icon,
        .navbar-vertical .nav-link:hover .nav-link-icon { color: #38bdf8; }
        .nav-header > span { letter-spacing: .12em; padding: 0 0.95rem; opacity: .55; font-size: .68rem; font-weight: 600; }

        /* denser items + collapsible section groups (standard, modern, short-by-default) */
        .navbar-vertical .nav-link { padding-top: .4rem; padding-bottom: .4rem; font-size: .9rem; }
        .navbar-vertical .nav-link-icon { font-size: 1.05rem; }
        .navbar-vertical .nav-group { display: block; margin-top: .25rem; }
        .navbar-vertical .nav-group > .nav-group-h { display: flex; align-items: center; padding: .35rem .75rem; margin: 1px 8px; }
        .navbar-vertical .nav-group > .nav-group-h:hover { background: rgba(255,255,255,.05); }
        .navbar-vertical .nav-group-h .nav-link-title { letter-spacing: .1em; font-size: .66rem; font-weight: 700; opacity: .6; }
        .navbar-vertical .nav-group-h .nav-chev { margin-left: auto; font-size: 1rem; opacity: .45; transition: transform .2s ease; }
        .navbar-vertical .nav-group.open > .nav-group-h .nav-chev { transform: rotate(90deg); }
        .navbar-vertical .nav-group > .nav-group-items { list-style: none; padding: 0; margin: 0 0 .15rem; overflow: hidden; max-height: 0; transition: max-height .22s ease; }
        .navbar-vertical .nav-group.open > .nav-group-items { max-height: 3000px; }
        /* one level of nesting: a client row with its processes mapped under it */
        .navbar-vertical .nav-sub { display: block; }
        .navbar-vertical .nav-sub > .nav-sub-h { display: flex; align-items: center; cursor: pointer; }
        .navbar-vertical .nav-sub > .nav-sub-h .nav-chev { margin-left: auto; font-size: .95rem; opacity: .45; transition: transform .2s ease; }
        .navbar-vertical .nav-sub.open > .nav-sub-h .nav-chev { transform: rotate(90deg); }
        .navbar-vertical .nav-sub > .nav-sub-items { list-style: none; padding: 0; margin: 0; overflow: hidden; max-height: 0; transition: max-height .22s ease; }
        .navbar-vertical .nav-sub.open > .nav-sub-items { max-height: 1200px; }
        .navbar-vertical .nav-sub > .nav-sub-items .nav-link { padding-left: 2.6rem; font-size: .78rem; }

        /* ============= TOP NAV ============= */
        .navbar.m-topbar {
            background: var(--m-bg-elev);
            border-bottom: 1px solid var(--m-border);
            min-height: 56px;
            position: sticky; top: 0; z-index: 1020;
            backdrop-filter: saturate(180%) blur(12px);
        }
        html[data-bs-theme="dark"] .navbar.m-topbar { background: rgba(17,26,44,.85); }
        .m-topbar .m-search {
            display: inline-flex; align-items: center; gap: 8px;
            background: var(--m-surface-2); border: 1px solid var(--m-border);
            border-radius: 8px; padding: 6px 10px;
            color: var(--m-text-soft); font-size: .85rem;
            cursor: pointer; transition: all .12s;
            min-width: 260px;
        }
        .m-topbar .m-search:hover { border-color: var(--tblr-primary); color: var(--m-text); }
        .m-topbar .m-search kbd {
            background: var(--m-surface); border: 1px solid var(--m-border);
            color: var(--m-text-soft); font-size: .7rem;
            padding: 2px 6px; border-radius: 4px; margin-left: auto;
            font-family: inherit;
        }

        /* ============= CARDS ============= */
        .card { box-shadow: var(--m-shadow-sm); border: 1px solid var(--m-border); background: var(--m-surface); }
        .card.kpi-tile { transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
        .card.kpi-tile:hover { transform: translateY(-2px); box-shadow: var(--m-shadow-md); border-color: var(--m-border-strong); }
        .card-header { background: transparent; border-bottom: 1px solid var(--m-border); }
        .stat-value { font-size: 1.75rem; font-weight: 700; line-height: 1.1; color: var(--m-text); font-variant-numeric: tabular-nums; }
        .stat-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; color: var(--m-text-soft); }

        /* ============= LEGACY TABLE PALETTE (preserved) ============= */
        .table-legacy {
            border: 1px solid #cbd5e1;
            font-size: .76rem;
        }
        html[data-bs-theme="dark"] .table-legacy { border-color: #334155; }
        .table-legacy thead th {
            background: #475569;
            color: #fff; font-weight: 600; text-align: center;
            border-color: #334155 !important;
            padding: 5px 6px;
            font-size: .72rem;
            text-transform: uppercase;
            letter-spacing: .02em;
            white-space: nowrap;
        }
        .table-legacy tbody td {
            background: #ffffff;
            border-color: #e2e8f0 !important;
            vertical-align: middle;
            padding: 4px 6px;
            color: #1e293b;
        }
        html[data-bs-theme="dark"] .table-legacy tbody td { background: var(--m-surface); border-color: var(--m-border) !important; color: var(--m-text); }
        html[data-bs-theme="dark"] .table-legacy tbody tr:nth-child(even) td { background: var(--m-surface-2); }
        .table-legacy tbody tr:nth-child(even) td { background: #f8fafc; }
        .table-legacy tbody td.num { text-align: right; font-variant-numeric: tabular-nums; }
        .table-legacy tbody td.dollar-col { text-align: right; padding-right: 2px; width: 14px; color:#64748b; font-weight: 500; }
        .table-legacy tbody td.dollar-num { text-align: right; padding-left: 2px; font-variant-numeric: tabular-nums; }
        .table-legacy tbody tr.total-row td {
            background: #fef3c7 !important;
            font-weight: 700;
            border-top: 2px solid #94a3b8 !important;
            color: #1e293b;
        }
        html[data-bs-theme="dark"] .table-legacy tbody tr.total-row td { background: #3a2f0c !important; color: #fde68a; border-top-color:#52525b !important; }
        /* Grand-total row pinned to the bottom of a scrolling scorecard so it's always visible. */
        .table-legacy tbody tr.total-row.sticky-total td { position: sticky; bottom: 0; z-index: 6; box-shadow: 0 -2px 0 #94a3b8; }
        .badge-op-select { background:#d3f9d8; color:#2b8a3e; }
        .badge-op-insert { background:#d0ebff; color:#1864ab; }
        .badge-op-update { background:#fff3bf; color:#5c3c00; }
        .badge-op-delete { background:#ffe3e3; color:#c92a2a; }
        .legacy-title {
            background: #334155;
            color: #fff; padding: 7px 14px; border-radius: 4px 4px 0 0;
            font-weight: 600; letter-spacing: .03em; font-size: .82rem;
            text-transform: uppercase; text-align: left;
        }
        /* Pivot rows */
        .pivot-facility td { background:#334155 !important; color:#fff !important; font-weight:600; cursor:pointer; }
        .pivot-facility td:hover { background:#1e293b !important; }
        .pivot-month td { background:#e2e8f0 !important; color:#1e293b !important; font-weight:600; cursor:pointer; }
        .pivot-month td:hover { background:#cbd5e1 !important; }
        .pivot-day td { background:#fff !important; color:#475569; }
        html[data-bs-theme="dark"] .pivot-month td { background:#1f2a44 !important; color:#cbd5e1 !important; }
        html[data-bs-theme="dark"] .pivot-month td:hover { background:#2a3756 !important; }
        html[data-bs-theme="dark"] .pivot-day td { background: var(--m-surface) !important; color: var(--m-text); }

        /* ============= COMMAND PALETTE ============= */
        .m-cmdk-backdrop {
            position: fixed; inset: 0; background: rgba(15,23,37,.55);
            z-index: 2000; display: none; align-items: flex-start; justify-content: center;
            backdrop-filter: blur(4px); padding-top: 12vh;
            animation: fadeIn .15s ease-out;
        }
        .m-cmdk-backdrop.open { display: flex; }
        .m-cmdk {
            width: 640px; max-width: 92vw;
            background: var(--m-bg-elev); border: 1px solid var(--m-border-strong);
            border-radius: 14px; box-shadow: 0 24px 48px rgba(0,0,0,.35);
            overflow: hidden; animation: pop .15s cubic-bezier(.2,.9,.4,1.2);
        }
        .m-cmdk-input {
            width: 100%; padding: 16px 20px; border: 0; outline: 0;
            font-size: 1rem; background: transparent; color: var(--m-text);
            border-bottom: 1px solid var(--m-border);
            font-family: inherit;
        }
        .m-cmdk-list { max-height: 50vh; overflow: auto; padding: 6px 0; }
        .m-cmdk-group { padding: 8px 16px 4px; font-size: .68rem; text-transform: uppercase; letter-spacing: .08em; color: var(--m-text-soft); font-weight: 600; }
        .m-cmdk-item {
            display: flex; align-items: center; gap: 12px;
            padding: 8px 16px; cursor: pointer; color: var(--m-text);
            font-size: .9rem; border-radius: 0;
        }
        .m-cmdk-item .ti { color: var(--m-text-soft); font-size: 1.1rem; width: 22px; text-align: center; }
        .m-cmdk-item.active, .m-cmdk-item:hover { background: rgba(32,107,196,.12); }
        .m-cmdk-item.active .ti, .m-cmdk-item:hover .ti { color: var(--tblr-primary); }
        .m-cmdk-foot { padding: 8px 16px; border-top: 1px solid var(--m-border); font-size: .72rem; color: var(--m-text-soft); display: flex; gap: 14px; }
        .m-cmdk-foot kbd { background: var(--m-surface-2); border: 1px solid var(--m-border); padding: 1px 6px; border-radius: 4px; font-size: .7rem; font-family: inherit; }
        @keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
        @keyframes pop { from { opacity: 0; transform: translateY(-8px) scale(.98) } to { opacity: 1; transform: none } }

        /* ============= MISC ============= */
        .m-toast-stack { position: fixed; top: 70px; right: 16px; z-index: 1080; display: flex; flex-direction: column; gap: 8px; }
        .m-toast { background: var(--m-bg-elev); border: 1px solid var(--m-border); padding: 10px 14px; border-radius: 8px; box-shadow: var(--m-shadow-md); font-size: .88rem; }
        .m-toast.success { border-left: 3px solid var(--m-good); }
        .m-toast.error   { border-left: 3px solid var(--m-bad); }
        .breadcrumb-bar { padding: .55rem 0; font-size: .82rem; color: var(--m-text-soft); border-bottom: 1px solid var(--m-border); margin-bottom: .25rem; background: var(--m-bg-elev); }
        .breadcrumb-bar a { color: inherit; text-decoration: none; }
        .breadcrumb-bar a:hover { color: var(--tblr-primary); }
        .breadcrumb-bar .sep { opacity: .35; margin: 0 6px; }

        /* Better scrollbars in dark mode */
        html[data-bs-theme="dark"] ::-webkit-scrollbar { width: 10px; height: 10px; }
        html[data-bs-theme="dark"] ::-webkit-scrollbar-track { background: var(--m-bg); }
        html[data-bs-theme="dark"] ::-webkit-scrollbar-thumb { background: #28365a; border-radius: 6px; }
        html[data-bs-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #344571; }

        /* Buttons polish */
        .btn-primary { background: var(--m-accent); border-color: var(--m-accent); }
        .btn-primary:hover { background: #1c5fad; border-color: #1c5fad; }

        /* TomSelect (multi/searchable selects) — give the control + dropdown an OPAQUE,
           theme-aware surface so options never render see-through over the page behind them. */
        .ts-wrapper .ts-control,
        .ts-wrapper.focus .ts-control { background: var(--m-surface, #fff); border-color: var(--m-border, #ccc); color: var(--m-text, #1f2733); }
        .ts-control input, .ts-control input::placeholder { color: var(--m-text, #1f2733); }
        .ts-dropdown {
            background: var(--m-bg-elev, #fff) !important;
            border: 1px solid var(--m-border-strong, #b7c0cd) !important;
            box-shadow: 0 18px 44px rgba(0,0,0,.28) !important;
            color: var(--m-text, #1f2733);
            z-index: 1085;
        }
        .ts-dropdown .option, .ts-dropdown .optgroup-header, .ts-dropdown .no-results { background: transparent; color: var(--m-text, #1f2733); }
        .ts-dropdown .optgroup-header { color: var(--m-text-soft, #6c7a89); font-weight: 700; }
        .ts-dropdown .option.active, .ts-dropdown .option:hover { background: rgba(79,70,229,.16) !important; color: var(--m-text, #1f2733); }
        .ts-dropdown .active.create, .ts-dropdown .create:hover { background: rgba(79,70,229,.16) !important; }
        .ts-wrapper.multi .ts-control > .item { background: var(--m-surface-2, #eef1f5); color: var(--m-text, #1f2733); border:1px solid var(--m-border, #ccc); }

        /* Print */
        @media print {
            .navbar-vertical, .m-topbar, .breadcrumb-bar, .m-cmdk-backdrop, .impersonate-bar { display: none !important; }
            .page-wrapper { margin: 0 !important; }
            body { background: #fff !important; }
        }

    </style>
    <?php require __DIR__ . '/compact-css.php'; ?>
</head>
<body>
<div class="page">
    <aside class="navbar navbar-vertical navbar-expand-lg" data-bs-theme="dark">
        <div class="container-fluid">
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu">
                <span class="navbar-toggler-icon"></span>
            </button>
            <h1 class="navbar-brand navbar-brand-autodark">
                <a href="<?= e(url('/dashboard.php')) ?>" class="d-flex align-items-center text-white text-decoration-none">
                    <span class="d-inline-flex align-items-center justify-content-center me-2"
                          style="width:34px;height:34px;border-radius:9px;background:linear-gradient(135deg,#38bdf8,#a855f7);box-shadow:0 6px 18px rgba(56,189,248,.35);">
                        <i class="ti ti-chart-pie-2" style="font-size:1.2rem"></i>
                    </span>
                    <span style="font-weight:700;letter-spacing:.01em"><?= e(APP_NAME) ?></span>
                </a>
            </h1>
            <div class="collapse navbar-collapse" id="sidebar-menu">
                <?php
                /* Role-based menu. SysAdmin gets the full admin menu; report-viewer roles
                   (Supervisor / Manager / …) get a focused Home + Browse-by-vertical + Reports.
                   'p'=>null shows always; a section header hides when it has no visible child. */
                $isSysNav = is_sysadmin();
                if ($isSysNav) {
                    $navMenu = [
                        ['h'=>'dashboard.php','u'=>'/dashboard.php','i'=>'home','t'=>'Dashboard','p'=>null],
                        ['hdr'=>'MASTER DATA'],
                        ['h'=>'verticals.php','u'=>'/admin/verticals.php','i'=>'building','t'=>'Verticals','p'=>['vertical.view']],
                        ['h'=>'clients.php','u'=>'/admin/clients.php','i'=>'users','t'=>'Clients','p'=>['client.view']],
                        ['h'=>'processes.php','u'=>'/admin/processes.php','i'=>'list-tree','t'=>'Processes','p'=>['process.view']],
                        ...coding_master_nav_items(),   // Facilities / Providers / Hierarchy under MASTER DATA
                        ['h'=>'clone-tree.php','u'=>'/admin/clone-tree.php','i'=>'copy','t'=>'Clone tree','p'=>null],
                        ['hdr'=>'REPORTS'],
                        ['h'=>'report-builder.php','u'=>'/admin/report-builder.php','i'=>'template','t'=>'Report builder','p'=>['report.definition.view','report.definition.manage']],
                        ['h'=>'reports.php','u'=>'/admin/reports.php','i'=>'report-analytics','t'=>'Reports browser','p'=>['report.view']],
                        ['hdr'=>'USERS &amp; ACCESS'],
                        ['h'=>'users.php','u'=>'/admin/users.php','i'=>'user-cog','t'=>'Users','p'=>['user.internal.view','user.client.view','user.internal.manage','user.client.manage']],
                        ['h'=>'access.php','u'=>'/admin/access.php','i'=>'key','t'=>'Report Access','p'=>['report.access.view','report.access.grant']],
                        ['h'=>'user-alignment.php','u'=>'/admin/user-alignment.php','i'=>'user-shield','t'=>'User alignment','p'=>['coding.access.manage','ar.supervise','billing.supervise']],
                        ['h'=>'access-control.php','u'=>'/admin/access-control.php','i'=>'lock-cog','t'=>'Permissions','p'=>null],
                        ['h'=>'roles.php','u'=>'/admin/roles.php','i'=>'shield-cog','t'=>'Roles &amp; features','p'=>null],
                        ['hdr'=>'LOGS &amp; SETTINGS'],
                        ['h'=>'data-cleanup.php','u'=>'/admin/data-cleanup.php','i'=>'trash-x','t'=>'Data cleanup','p'=>null],
                        ['h'=>'errors.php','u'=>'/admin/errors.php','i'=>'bug','t'=>'Error log','p'=>null],
                        ['h'=>'audit.php','u'=>'/admin/audit.php','i'=>'history','t'=>'Audit log','p'=>['audit.view']],
                        ['h'=>'login-logs.php','u'=>'/admin/login-logs.php','i'=>'shield-lock','t'=>'Login activity','p'=>['audit.view']],
                        ['h'=>'scheduled.php','u'=>'/admin/scheduled.php','i'=>'clock-play','t'=>'Scheduled reports','p'=>['schedule.manage']],
                        ['h'=>'notifications.php','u'=>'/admin/notifications.php','i'=>'bell','t'=>'Notifications','p'=>null],
                        ['h'=>'settings.php','u'=>'/admin/settings.php','i'=>'settings','t'=>'Settings','p'=>['settings.view','settings.manage']],
                        ['h'=>'reference.php','u'=>'/admin/reference.php','i'=>'info-circle','t'=>'System Reference','p'=>['reference.view']],
                    ];
                    $navMenu = array_merge($navMenu, coding_nav_items(), billing_nav_items(), ar_nav_items());
                } else {
                    // Module-only users (coding and/or billing, no report access) land on their module home —
                    // their module group already carries that home link, so we DON'T add a second top-level
                    // "Home" (that was the duplicate, and for billing-only users it would bounce to a page
                    // they can't open). Report-viewers keep the workspace Home.
                    $moduleOnly = (is_coding_user() || is_billing_user() || is_ar_user()) && !can('report.view');
                    $navMenu = [];
                    if (!$moduleOnly) {
                        $navMenu[] = ['h'=>'workspace.php','h2'=>'dashboard.php','u'=>'/admin/workspace.php','i'=>'home','t'=>'Home','p'=>null];
                    }
                    $navMenu[] = ['h'=>'reports.php','u'=>'/admin/reports.php','i'=>'report-analytics','t'=>'Reports browser','p'=>['report.view']];
                    $navMenu[] = ['hdr'=>'CLIENTS'];
                    try {
                      if (can('report.view')) {
                        /* One row per accessible report (process), GROUPED BY CLIENT NAME so the duplicate
                           per-vertical client records collapse to a single unique name with their processes
                           mapped under it: a client with one process links straight to it; a client with
                           several processes becomes a collapsible row listing each process. */
                        $crows = db()->query("
                            SELECT c.name cname, p.id pid, p.name pname, c.code ccode, r.id rid, r.handler
                              FROM clients c
                              JOIN processes p ON p.client_id = c.id
                              JOIN reports   r ON r.process_id = p.id AND r.deleted_at IS NULL AND r.status='active'
                             WHERE c.deleted_at IS NULL" . report_scope_sql('r.id') . "
                             ORDER BY c.name, p.name LIMIT 400")->fetchAll();
                        $byName = [];
                        foreach ($crows as $cr) {
                            $u = ($cr['handler'] === 'collection_dashboard' ? '/admin/collection.php?id=' : '/admin/report-view.php?id=') . (int) $cr['rid'];
                            $lbl = trim((string) $cr['pname']) !== '' ? $cr['pname'] : (trim((string) $cr['ccode']) !== '' ? $cr['ccode'] : $cr['cname']);
                            $byName[$cr['cname']][] = ['h'=>'__r'.(int)$cr['rid'], 'u'=>$u, 't'=>e($lbl)];
                        }
                        foreach ($byName as $cname => $procs) {
                            if (count($procs) === 1) {
                                $navMenu[] = ['h'=>$procs[0]['h'], 'u'=>$procs[0]['u'], 'i'=>'building', 't'=>e($cname), 'p'=>null];
                            } else {
                                $navMenu[] = ['h'=>'__cg'.substr(md5($cname),0,8), 'i'=>'building', 't'=>e($cname), 'p'=>null, 'children'=>$procs];
                            }
                        }
                      }
                    } catch (Throwable $e) {}
                    if (is_coding_user()) $navMenu = array_merge($navMenu, coding_nav_items());
                    if (is_billing_user()) $navMenu = array_merge($navMenu, billing_nav_items());
                    if (is_ar_user())      $navMenu = array_merge($navMenu, ar_nav_items());
                    // Team data-access alignment — each vertical's MANAGER / SUPERVISOR (mirrors user-alignment.php's route gate).
                    // The empty-section guard below hides this header for anyone without one of these perms (e.g. coders).
                    $navMenu[] = ['hdr'=>'USERS &amp; ACCESS'];
                    // Users page — for managers (or anyone holding a user-management perm). The per-item can() filter +
                    // empty-section guard below surface it only for those perms and hide it from coders / billers.
                    $navMenu[] = ['h'=>'users.php','u'=>'/admin/users.php','i'=>'user-cog','t'=>'Users','p'=>['user.internal.view','user.client.view','user.internal.manage','user.client.manage']];
                    $navMenu[] = ['h'=>'user-alignment.php','u'=>'/admin/user-alignment.php','i'=>'user-shield','t'=>'User alignment','p'=>['coding.access.manage','ar.supervise','billing.supervise']];
                    // Shared master data (Facilities / Providers / Hierarchy) — ANY vertical's supervisor/reference-admin.
                    if (can_manage_master_data()) {
                        $navMenu[] = ['hdr'=>'MASTER DATA'];
                        $navMenu = array_merge($navMenu, coding_master_nav_items());
                    }
                    $navMenu[] = ['hdr'=>'ACCOUNT'];
                    $navMenu[] = ['h'=>'notifications.php','u'=>'/admin/notifications.php','i'=>'bell','t'=>'Notifications','p'=>null];
                }
                /* Keep only visible links + headers that still have at least one child. */
                $visible = [];
                foreach ($navMenu as $it) {
                    if (isset($it['hdr'])) { $visible[] = $it; continue; }
                    /* A per-page grant must also SHOW the link, not just permit the URL.
                     * medmecs_grantable_pages() exists so "any single page can be granted to any user
                     * irrespective of role", and admin_route_permissions() already injects page.<file> into the
                     * route gate — but this menu filter only looked at the item's ROLE permissions. So a user
                     * granted, say, the Reconciliation report could reach it by typing the URL yet had no link
                     * anywhere in the UI: the grant looked like it did nothing. Accept the page grant here too. */
                    if (empty($it['p']) || can(...$it['p'])
                        || (!empty($it['h']) && can(page_perm_code($it['h'])))) $visible[] = $it;
                }
                $render = [];
                for ($i = 0; $i < count($visible); $i++) {
                    if (isset($visible[$i]['hdr'])) {
                        $next = $visible[$i+1] ?? null;
                        if ($next === null || isset($next['hdr'])) continue;   // empty section → skip header
                    }
                    $render[] = $visible[$i];
                }
                /* Group into collapsible sections: items before the first header (Dashboard/Home) stay
                   as always-visible top links; every section header becomes a collapsible group that is
                   collapsed by default and auto-opens only for the section holding the current page. */
                $top = []; $groups = []; $cur = null;
                foreach ($render as $it) {
                    if (isset($it['hdr'])) { if ($cur) $groups[] = $cur; $cur = ['hdr'=>$it['hdr'], 'items'=>[]]; }
                    elseif ($cur)         { $cur['items'][] = $it; }
                    else                  { $top[] = $it; }
                }
                if ($cur) $groups[] = $cur;
                $navActive = fn($it) => ($here === ($it['h'] ?? '~') || (isset($it['h2']) && $here === $it['h2']));
                ?>
                <ul class="navbar-nav pt-lg-2">
                    <?php foreach ($top as $it): ?>
                        <li class="nav-item<?= $navActive($it) ? ' active' : '' ?>">
                            <a class="nav-link" href="<?= e(url($it['u'])) ?>">
                                <span class="nav-link-icon"><i class="ti ti-<?= e($it['i']) ?>"></i></span>
                                <span class="nav-link-title"><?= $it['t'] ?></span>
                            </a>
                        </li>
                    <?php endforeach; ?>
                    <?php foreach ($groups as $g):
                        $gid  = 'navg-' . preg_replace('/[^a-z0-9]+/', '-', strtolower(strip_tags((string) $g['hdr'])));
                        $open = false; foreach ($g['items'] as $it) { if ($navActive($it)) { $open = true; break; } if (!empty($it['children'])) { foreach ($it['children'] as $ch) if ($navActive($ch)) { $open = true; break 2; } } } ?>
                        <li class="nav-item nav-group<?= $open ? ' open' : '' ?>" data-group="<?= e($gid) ?>">
                            <a class="nav-link nav-group-h" href="#" role="button" aria-expanded="<?= $open?'true':'false' ?>">
                                <span class="nav-link-title"><?= $g['hdr'] ?></span>
                                <i class="ti ti-chevron-right nav-chev"></i>
                            </a>
                            <ul class="nav-group-items">
                                <?php foreach ($g['items'] as $it): ?>
                                <?php if (!empty($it['children'])):
                                    $subOpen = false; foreach ($it['children'] as $ch) if ($navActive($ch)) { $subOpen = true; break; } ?>
                                <li class="nav-item nav-sub<?= $subOpen ? ' open' : '' ?>">
                                    <a class="nav-link nav-sub-h" href="#" role="button" aria-expanded="<?= $subOpen?'true':'false' ?>">
                                        <span class="nav-link-icon"><i class="ti ti-<?= e($it['i']) ?>"></i></span>
                                        <span class="nav-link-title"><?= $it['t'] ?></span>
                                        <i class="ti ti-chevron-right nav-chev"></i>
                                    </a>
                                    <ul class="nav-sub-items">
                                        <?php foreach ($it['children'] as $ch): ?>
                                        <li class="nav-item<?= $navActive($ch) ? ' active' : '' ?>">
                                            <a class="nav-link" href="<?= e(url($ch['u'])) ?>"><span class="nav-link-title"><?= $ch['t'] ?></span></a>
                                        </li>
                                        <?php endforeach; ?>
                                    </ul>
                                </li>
                                <?php else: ?>
                                <li class="nav-item<?= $navActive($it) ? ' active' : '' ?>">
                                    <a class="nav-link" href="<?= e(url($it['u'])) ?>">
                                        <span class="nav-link-icon"><i class="ti ti-<?= e($it['i']) ?>"></i></span>
                                        <span class="nav-link-title"><?= $it['t'] ?></span>
                                    </a>
                                </li>
                                <?php endif; ?>
                                <?php endforeach; ?>
                            </ul>
                        </li>
                    <?php endforeach; ?>
                </ul>
                <script>
                (function(){
                    var KEY='m_nav_open';
                    function load(){ try{ return JSON.parse(localStorage.getItem(KEY)||'[]'); }catch(e){ return []; } }
                    function save(a){ try{ localStorage.setItem(KEY, JSON.stringify(a)); }catch(e){} }
                    var open=load();
                    [].forEach.call(document.querySelectorAll('.nav-group'), function(g){
                        var id=g.getAttribute('data-group');
                        if(open.indexOf(id)>=0) g.classList.add('open');           // restore remembered sections
                        var h=g.querySelector('.nav-group-h');
                        if(h) h.addEventListener('click', function(e){ e.preventDefault();
                            g.classList.toggle('open');
                            var cur=load(), i=cur.indexOf(id), on=g.classList.contains('open');
                            if(on && i<0) cur.push(id); else if(!on && i>=0) cur.splice(i,1);
                            save(cur); h.setAttribute('aria-expanded', on?'true':'false');
                        });
                    });
                    // nested client → processes toggle
                    [].forEach.call(document.querySelectorAll('.nav-sub-h'), function(h){
                        h.addEventListener('click', function(e){ e.preventDefault();
                            var s=h.closest('.nav-sub'); if(s){ s.classList.toggle('open'); h.setAttribute('aria-expanded', s.classList.contains('open')?'true':'false'); }
                        });
                    });
                })();
                </script>
            </div>
        </div>
    </aside>

    <header class="navbar navbar-expand-md d-print-none m-topbar">
        <div class="container-xl">
            <div class="d-flex align-items-center w-100">
                <!-- Command palette trigger -->
                <button type="button" class="m-search border-0" onclick="window.mCmdK && mCmdK.open()" aria-label="Open command palette">
                    <i class="ti ti-search"></i>
                    <span>Jump to a page or report</span>
                    <kbd>Ctrl K</kbd>
                </button>

                <div class="ms-auto d-flex align-items-center gap-2">
                    <!-- Theme toggle -->
                    <button id="m_theme_btn" class="btn btn-icon btn-ghost-secondary" title="Toggle theme" onclick="mToggleTheme()">
                        <i class="ti ti-sun" id="m_theme_icon_l"></i>
                        <i class="ti ti-moon d-none" id="m_theme_icon_d"></i>
                    </button>

                    <!-- Report timezone toggle (supervisor / manager) — VIEW only; records always stamp in EST -->
                    <?php if (can_toggle_report_tz()): $curTz = report_tz_label(); $otherTz = $curTz === 'EST' ? 'IST' : 'EST'; ?>
                    <form method="POST" action="<?= e(url('/admin/set-report-tz.php')) ?>" class="d-inline">
                        <?= csrf_field() ?><input type="hidden" name="tz" value="<?= e($otherTz) ?>">
                        <button class="btn btn-sm btn-outline-primary text-nowrap" title="Report times are shown in <?= e($curTz) ?> — click to switch to <?= e($otherTz) ?>. (Records are always stamped in EST.)">
                            <i class="ti ti-clock-hour-4 me-1"></i>Reports: <?= e($curTz) ?>
                        </button>
                    </form>
                    <?php endif; ?>

                    <!-- Notifications -->
                    <?php
                    $unread = 0;
                    if ($user) {
                        try {
                            $st = db()->prepare('SELECT COUNT(*) FROM notifications WHERE user_id=? AND is_read=0');
                            $st->execute([$user['id']]);
                            $unread = (int) $st->fetchColumn();
                        } catch (Throwable $e) {}
                    }
                    ?>
                    <a href="<?= e(url('/admin/notifications.php')) ?>" class="btn btn-icon btn-ghost-secondary position-relative" title="Notifications">
                        <i class="ti ti-bell"></i>
                        <?php if ($unread > 0): ?>
                            <span class="position-absolute top-0 end-0 translate-middle badge rounded-pill bg-red" style="font-size:.6rem"><?= $unread > 99 ? '99+' : $unread ?></span>
                        <?php endif; ?>
                    </a>

                    <!-- User menu -->
                    <div class="nav-item dropdown">
                        <a href="#" class="nav-link d-flex lh-1 text-reset p-1 rounded" data-bs-toggle="dropdown" style="border:1px solid var(--m-border); background: var(--m-surface-2);">
                            <span class="avatar avatar-sm" style="background: linear-gradient(135deg,#38bdf8,#a855f7); color:#fff; font-weight:600;">
                                <?= e(strtoupper(substr($user['name'] ?? 'U', 0, 2))) ?>
                            </span>
                            <div class="d-none d-xl-block ps-2">
                                <div style="font-size:.85rem;font-weight:600;line-height:1.1"><?= e($user['name'] ?? 'User') ?></div>
                                <div class="mt-1 small text-secondary" style="font-size:.7rem"><i class="ti ti-shield-check me-1"></i><?= e($myRoleLabel) ?></div>
                            </div>
                        </a>
                        <div class="dropdown-menu dropdown-menu-end">
                            <div class="dropdown-header text-secondary small">
                                Signed in as<br><strong class="text-body"><?= e($user['email'] ?? '') ?></strong>
                                <div class="mt-1"><span class="badge bg-blue-lt"><i class="ti ti-shield-check me-1"></i><?= e($myRoleLabel) ?></span></div>
                            </div>
                            <div class="dropdown-divider"></div>
                            <a href="<?= e(url('/change-password.php')) ?>" class="dropdown-item">
                                <i class="ti ti-key me-2"></i>Change password
                            </a>
                            <button onclick="mToggleTheme()" class="dropdown-item">
                                <i class="ti ti-sun-moon me-2"></i>Toggle theme <span class="text-secondary small ms-auto" id="m_theme_label">light</span>
                            </button>
                            <?php if (!empty($switchUsers)): ?>
                            <div class="dropdown-divider"></div>
                            <div class="dropdown-header text-secondary small d-flex align-items-center"><i class="ti ti-eye me-1"></i>View&nbsp;as&nbsp;/&nbsp;switch role</div>
                            <div style="max-height:244px;overflow-y:auto">
                            <?php foreach ($switchUsers as $su): ?>
                                <form method="POST" action="<?= e(url('/admin/impersonate.php')) ?>"><?= csrf_field() ?><input type="hidden" name="id" value="<?= (int)$su['id'] ?>">
                                    <button type="submit" class="dropdown-item d-flex align-items-center" style="gap:8px">
                                        <span class="avatar avatar-xs" style="background:var(--m-surface-2);color:var(--m-text-soft);font-weight:700"><?= e(strtoupper(substr($su['name'] ?: 'U', 0, 2))) ?></span>
                                        <span class="flex-fill" style="min-width:0"><span class="d-block text-truncate" style="font-weight:600;line-height:1.15"><?= e($su['name']) ?></span><span class="d-block text-truncate text-secondary" style="font-size:.68rem"><?= e($su['roles'] ?: 'no role') ?></span></span>
                                        <i class="ti ti-arrow-right text-secondary"></i>
                                    </button>
                                </form>
                            <?php endforeach; ?>
                            </div>
                            <?php endif; ?>
                            <div class="dropdown-divider"></div>
                            <form method="POST" action="<?= e(url('/logout.php')) ?>"><?= csrf_field() ?>
                                <button type="submit" class="dropdown-item text-danger">
                                    <i class="ti ti-logout me-2"></i>Sign out
                                </button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </header>

    <div class="page-wrapper">
        <?php if (is_impersonating()): ?>
            <div class="bg-warning text-dark py-2 px-3 d-flex align-items-center impersonate-bar">
                <i class="ti ti-eye me-2"></i>
                <strong>Viewing as: <?= e($user['name']) ?></strong>
                <span class="ms-2 small">(<?= e($user['email']) ?> &mdash; <?= e($user['user_type']) ?>)</span>
                <form method="POST" action="<?= e(url('/admin/impersonate.php')) ?>" class="ms-auto">
                    <?= csrf_field() ?><input type="hidden" name="stop" value="1">
                    <button class="btn btn-sm btn-dark"><i class="ti ti-x me-1"></i>Stop impersonating</button>
                </form>
            </div>
        <?php endif; ?>

        <?php foreach (flash_take('success') as $m): ?>
            <div class="container-xl mt-3"><div class="alert alert-success d-flex align-items-center"><i class="ti ti-circle-check me-2"></i><?= e($m) ?></div></div>
        <?php endforeach; ?>
        <?php foreach (flash_take('error') as $m): ?>
            <div class="container-xl mt-3"><div class="alert alert-danger d-flex align-items-center"><i class="ti ti-alert-triangle me-2"></i><?= e($m) ?></div></div>
        <?php endforeach; ?>
        <?php foreach (flash_take('warning') as $m): ?>
            <div class="container-xl mt-3"><div class="alert alert-warning d-flex align-items-center"><i class="ti ti-alert-triangle me-2"></i><?= e($m) ?></div></div>
        <?php endforeach; ?>

<!-- ============= COMMAND PALETTE ============= -->
<div id="m_cmdk_backdrop" class="m-cmdk-backdrop" onclick="if(event.target===this)mCmdK.close()">
    <div class="m-cmdk" role="dialog" aria-modal="true" aria-label="Command palette">
        <input id="m_cmdk_input" class="m-cmdk-input" placeholder="Search pages, reports, clients..." autocomplete="off">
        <div id="m_cmdk_list" class="m-cmdk-list"></div>
        <div class="m-cmdk-foot">
            <span><kbd>↑</kbd><kbd>↓</kbd> navigate</span>
            <span><kbd>Enter</kbd> open</span>
            <span><kbd>Esc</kbd> close</span>
            <span class="ms-auto">Powered by <?= e(APP_NAME) ?></span>
        </div>
    </div>
</div>

<script>
/* ============= THEME TOGGLE ============= */
function mApplyTheme(t) {
    document.documentElement.setAttribute('data-bs-theme', t);
    document.documentElement.setAttribute('data-m-theme', t);
    try { localStorage.setItem('m_theme', t); } catch(e){}
    var l = document.getElementById('m_theme_icon_l'), d = document.getElementById('m_theme_icon_d');
    if (l && d) {
        if (t === 'dark') { l.classList.add('d-none'); d.classList.remove('d-none'); }
        else              { d.classList.add('d-none'); l.classList.remove('d-none'); }
    }
    var lbl = document.getElementById('m_theme_label'); if (lbl) lbl.textContent = t;
    /* Notify ApexCharts to re-render in new theme if any are present */
    try { window.dispatchEvent(new CustomEvent('m-theme-change', { detail: { theme: t } })); } catch(e){}
}
function mToggleTheme() {
    var cur = document.documentElement.getAttribute('data-bs-theme') === 'dark' ? 'dark' : 'light';
    mApplyTheme(cur === 'dark' ? 'light' : 'dark');
}
mApplyTheme(localStorage.getItem('m_theme') || 'light');

/* ============= TOAST ============= */
window.mToast = function(msg, type) {
    var stack = document.querySelector('.m-toast-stack');
    if (!stack) { stack = document.createElement('div'); stack.className='m-toast-stack'; document.body.appendChild(stack); }
    var t = document.createElement('div'); t.className = 'm-toast ' + (type||''); t.textContent = msg;
    stack.appendChild(t);
    setTimeout(function(){ t.style.opacity='0'; t.style.transform='translateX(20px)'; t.style.transition='all .25s'; }, 2800);
    setTimeout(function(){ t.remove(); }, 3200);
};

/* ============= COMMAND PALETTE ============= */
window.mCmdK = (function(){
    var idx = <?= json_encode($navIndex, JSON_HEX_TAG | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_HEX_APOS) ?>;
    var bd = document.getElementById('m_cmdk_backdrop');
    var inp = document.getElementById('m_cmdk_input');
    var list = document.getElementById('m_cmdk_list');
    var active = 0, current = [];

    function score(item, q) {
        if (!q) return 1;
        var t = (item.t + ' ' + item.g).toLowerCase();
        if (t.indexOf(q) === 0) return 100;
        if (t.indexOf(' ' + q) > -1) return 80;
        if (t.indexOf(q) > -1) return 50;
        return 0;
    }
    function render() {
        var q = inp.value.trim().toLowerCase();
        var hits = idx.map(function(i){ return [score(i, q), i]; })
                      .filter(function(x){ return x[0] > 0; })
                      .sort(function(a,b){ return b[0]-a[0]; })
                      .map(function(x){ return x[1]; })
                      .slice(0, 24);
        current = hits;
        if (active >= hits.length) active = 0;

        var html = '', lastG = null;
        hits.forEach(function(i, k){
            if (i.g !== lastG) {
                if (lastG !== null) html += '';
                html += '<div class="m-cmdk-group">' + i.g + '</div>';
                lastG = i.g;
            }
            html += '<div class="m-cmdk-item ' + (k===active?'active':'') + '" data-k="' + k + '" data-u="' + i.u + '">'
                  + '<i class="ti ti-' + i.i + '"></i><span>' + i.t + '</span></div>';
        });
        if (!hits.length) html = '<div class="m-cmdk-group">No matches</div>';
        list.innerHTML = html;
        list.querySelectorAll('.m-cmdk-item').forEach(function(el){
            el.onmouseenter = function(){ active = parseInt(el.dataset.k,10); refresh(); };
            el.onclick = function(){ go(el.dataset.u); };
        });
    }
    function refresh() {
        list.querySelectorAll('.m-cmdk-item').forEach(function(el){
            el.classList.toggle('active', parseInt(el.dataset.k,10) === active);
        });
        var act = list.querySelector('.m-cmdk-item.active');
        if (act) act.scrollIntoView({block:'nearest'});
    }
    function go(u) { window.location.href = u; }
    function open() {
        bd.classList.add('open'); inp.value=''; active=0; render();
        setTimeout(function(){ inp.focus(); }, 30);
    }
    function close() { bd.classList.remove('open'); }

    inp.addEventListener('input', render);
    inp.addEventListener('keydown', function(e){
        if (e.key === 'ArrowDown') { e.preventDefault(); if (active < current.length-1) { active++; refresh(); } }
        else if (e.key === 'ArrowUp') { e.preventDefault(); if (active > 0) { active--; refresh(); } }
        else if (e.key === 'Enter')   { e.preventDefault(); var c = current[active]; if (c) go(c.u); }
        else if (e.key === 'Escape')  { close(); }
    });
    document.addEventListener('keydown', function(e){
        if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); open(); }
        if (e.key === '/' && !['INPUT','TEXTAREA','SELECT'].includes(document.activeElement.tagName)) {
            e.preventDefault(); open();
        }
    });
    return { open: open, close: close };
})();
</script>
