<?php
// T46-t: explicit no-store — belt-and-suspenders on top of PHP's session
// cache limiter, so no proxy/middlebox between owner and host may ever
// cache panel HTML (a cached HTML is the only stale vector left after
// this round removed every local .css/.js reference).
if (!headers_sent()) {
    header('Cache-Control: no-store, max-age=0, must-revalidate');
    header('Pragma: no-cache');
    // T46-w DELIVERY KILL-SWITCH: versioned URLs (?v=39 / &nxv=39) are new
    // cache keys - no stale store anywhere can answer them. The first FRESH
    // response that reaches the browser orders it to purge its whole HTTP
    // cache for this origin, destroying every poisoned entry (including the
    // bare /admin/ bookmark and any old ?page= copies). Safari ignores this
    // header harmlessly; the versioned URL alone still guarantees fresh
    // bytes on the first hit there.
    if ((isset($_GET['v']) && (string)$_GET['v'] === '39')
        || (isset($_GET['nxv']) && (string)$_GET['nxv'] === '39')) {
        header('Clear-Site-Data: "cache"');
    }
}
// Compute the count of tickets AWAITING an admin reply for the bell badge
// (T46-at: never answered OR user replied last — NOT every non-closed row).
// PERF: this runs on EVERY panel page — use two cheap COUNT/bounded queries
// (AdminDB) instead of the old 100-row Database::getAllTickets() fetch.
$__openTicketCount = 0;
$__allTickets = [];
try {
    $__openTicketCount = AdminDB::countOpenTickets();
    $__allTickets = AdminDB::getRecentOpenTickets(8);
} catch (\Throwable $e) { $__allTickets = []; $__openTicketCount = 0; }
?>
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
    <meta name="nx-build" content="39"><!-- T46-v build marker for the network self-heal -->
    <title><?= e($pageTitle ?? 'داشبورد') ?> | نترکس</title>
    <!-- T46-t SELF-CONTAINED SHELL (round 36): the FULL stylesheet is
         inlined into the no-cache HTML — this panel no longer references
         ANY local .css file, so no phone/VPN/proxy cache can ever again
         render it from a stale stylesheet (the round-34/35 «drawer
         sliver» reports were stale-cache renders, not bad CSS).
         assets/style.css stays on disk for reference only; if you edit
         it, mirror the change here. -->
    <style>
/* ═══════════════════════════════════════════════════════════════════
   T46-v PREFLIGHT-LITE — the panel was designed against Tailwind's
   Preflight reset (box-sizing, margin resets, form font inheritance) which
   only arrived from cdn.tailwindcss.com. On networks where that CDN is
   unreachable the pages fell back to raw UA styles: 8px body margin (the
   «فاصله اضافه / nothing is flush» class of reports), content-box overflow,
   native gray buttons, oversized headings. These rules reproduce EXACTLY
   the reset layer the design assumes — locally, unconditionally, in the
   same cascade position (top of the sheet). Zero CDN dependency remains.
   ═══════════════════════════════════════════════════════════════════ */
*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:rgba(34,211,238,0.1);}
html{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;}
body{margin:0;line-height:inherit;}
h1,h2,h3,h4,h5,h6,p,figure,blockquote,dl,dd,pre{margin:0;}
h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit;}
ul,ol{list-style:none;margin:0;padding:0;}
a{color:inherit;text-decoration:inherit;}
b,strong{font-weight:bolder;}
small{font-size:80%;}
code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:1em;}
img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle;}
button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0;}
button,[type=button],[type=submit],[type=reset]{-webkit-appearance:button;appearance:button;background-color:transparent;background-image:none;text-transform:none;cursor:pointer;}
textarea{resize:vertical;}
input::placeholder,textarea::placeholder{color:#5a6b85;opacity:1;}
[hidden]{display:none;} /* T46-w fix */

/* ═══════════════════════════════════════════════════════════════════
   Netrex Admin — Liquid Glass Theme (PHP port, exact match to Next.js)
   T46-v: fully self-contained — reset, layout, utilities and components
   all live in this sheet; no CDN stylesheet or script is required.
   ═══════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700;800;900&display=swap');

:root {
    --radius: 14px;
    --background: #05060f;
    --foreground: #e6f0ff;
    --accent-cyan: #22d3ee;
    --accent-violet: #a78bfa;
    --accent-pink: #f472b6;
    --accent-green: #2dd4bf;
    --accent-orange: #fb923c;
    --accent-red: #f87171;
    --accent-yellow: #fbbf24;
    --text-muted: #5a6b85;
}

* { scrollbar-width: thin; scrollbar-color: rgba(34, 211, 238, 0.2) transparent; }

html { scroll-behavior: smooth; }

body {
    font-family: 'Vazirmatn', sans-serif;
    background: var(--background);
    color: var(--foreground);
    direction: rtl;
    min-height: 100vh;
    position: relative;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    overflow-x: hidden;
}

/* Ambient caustic gradient background */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -2;
    pointer-events: none;
    background:
        radial-gradient(ellipse 60% 50% at 15% 10%, rgba(34, 211, 238, 0.12) 0%, transparent 55%),
        radial-gradient(ellipse 50% 60% at 85% 15%, rgba(167, 139, 250, 0.14) 0%, transparent 55%),
        radial-gradient(ellipse 70% 50% at 50% 95%, rgba(244, 114, 182, 0.08) 0%, transparent 55%),
        radial-gradient(ellipse 40% 40% at 90% 80%, rgba(45, 212, 191, 0.10) 0%, transparent 55%),
        linear-gradient(135deg, #05060f 0%, #0a0c1a 50%, #05060f 100%);
    animation: nx-bg-shift 22s ease-in-out infinite alternate;
}

body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(circle at 30% 30%, rgba(34, 211, 238, 0.06) 0%, transparent 40%),
        radial-gradient(circle at 70% 70%, rgba(167, 139, 250, 0.05) 0%, transparent 40%);
    filter: blur(50px);
    animation: nx-bg-pulse 14s ease-in-out infinite alternate;
}

@keyframes nx-bg-shift {
    0% { transform: translate(0, 0) scale(1); }
    100% { transform: translate(-2%, 1%) scale(1.05); }
}
@keyframes nx-bg-pulse {
    0% { opacity: 0.6; }
    100% { opacity: 1; }
}

/* ─── Glass cards ─────────────────────────────────────────────────── */
.glass-card {
    background: rgba(255, 255, 255, 0.04);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid rgba(34, 211, 238, 0.1);
    border-radius: var(--radius);
    padding: 20px;
    margin-bottom: 16px;
    box-shadow: 0 4px 30px rgba(34, 211, 238, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    transition: border-color 0.4s, box-shadow 0.4s, transform 0.4s;
    position: relative;
    overflow: hidden;
}
@media (min-width: 640px) { .glass-card { padding: 24px; } }
.glass-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(34, 211, 238, 0.5), rgba(167, 139, 250, 0.5), transparent);
    opacity: 0.6;
    pointer-events: none;
}
.glass-card-hover:hover {
    border-color: rgba(34, 211, 238, 0.3);
    box-shadow: 0 8px 40px rgba(34, 211, 238, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    transform: translateY(-2px);
}

/* ─── Stat cards ──────────────────────────────────────────────────── */
.stat-card {
    background: rgba(255, 255, 255, 0.04);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid rgba(34, 211, 238, 0.1);
    border-radius: var(--radius);
    padding: 20px;
    box-shadow: 0 4px 24px rgba(34, 211, 238, 0.03), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    position: relative;
    overflow: hidden;
    transition: transform 0.4s, box-shadow 0.4s, border-color 0.4s;
}
.stat-card::before {
    content: '';
    position: absolute;
    top: 0; right: 0; left: 0;
    height: 3px;
    border-radius: 3px 3px 0 0;
}
.stat-card::after {
    content: '';
    position: absolute;
    top: -30px; right: -30px;
    width: 110px; height: 110px;
    border-radius: 50%;
    filter: blur(45px);
    opacity: 0.3;
    pointer-events: none;
}
.stat-card:hover {
    transform: translateY(-4px) scale(1.01);
    box-shadow: 0 12px 40px rgba(34, 211, 238, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    border-color: rgba(34, 211, 238, 0.25);
}
.stat-card.blue::before { background: linear-gradient(90deg, #22d3ee, #38bdf8); }
.stat-card.blue::after { background: #22d3ee; }
.stat-card.pink::before { background: linear-gradient(90deg, #f472b6, #fb923c); }
.stat-card.pink::after { background: #f472b6; }
.stat-card.green::before { background: linear-gradient(90deg, #2dd4bf, #22d3ee); }
.stat-card.green::after { background: #2dd4bf; }
.stat-card.purple::before { background: linear-gradient(90deg, #a78bfa, #f472b6); }
.stat-card.purple::after { background: #a78bfa; }
.stat-card.orange::before { background: linear-gradient(90deg, #fb923c, #fbbf24); }
.stat-card.orange::after { background: #fb923c; }
.stat-card.cyan::before { background: linear-gradient(90deg, #22d3ee, #2dd4bf); }
.stat-card.cyan::after { background: #22d3ee; }
.stat-card.red::before { background: linear-gradient(90deg, #f87171, #f472b6); }
.stat-card.red::after { background: #f87171; }
.stat-card.yellow::before { background: linear-gradient(90deg, #fbbf24, #fb923c); }
.stat-card.yellow::after { background: #fbbf24; }

.stat-card .stat-icon { width: 50px; height: 50px; border-radius: 16px; display: flex; align-items: center; justify-content: center; font-size: 24px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06); }
.stat-card.blue .stat-icon { background: rgba(34, 211, 238, 0.12); color: #22d3ee; }
.stat-card.pink .stat-icon { background: rgba(244, 114, 182, 0.12); color: #f472b6; }
.stat-card.green .stat-icon { background: rgba(45, 212, 191, 0.12); color: #2dd4bf; }
.stat-card.purple .stat-icon { background: rgba(167, 139, 250, 0.12); color: #a78bfa; }
.stat-card.orange .stat-icon { background: rgba(251, 146, 60, 0.12); color: #fb923c; }
.stat-card.cyan .stat-icon { background: rgba(34, 211, 238, 0.12); color: #22d3ee; }
.stat-card.red .stat-icon { background: rgba(248, 113, 113, 0.12); color: #f87171; }
.stat-card.yellow .stat-icon { background: rgba(251, 191, 36, 0.12); color: #fbbf24; }

/* ─── Brand gradient text ─────────────────────────────────────────── */
.text-iridescent {
    background: linear-gradient(135deg, #22d3ee, #a78bfa, #f472b6);
    background-size: 200% 200%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: nx-iridescent 6s ease-in-out infinite;
}
@keyframes nx-iridescent {
    0%, 100% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
}
.text-gradient-cyan {
    background: linear-gradient(135deg, #e6f0ff, #22d3ee);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* ─── Animations ──────────────────────────────────────────────────── */
@keyframes nx-fade-up {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}
.animate-fade-up { animation: nx-fade-up 0.4s cubic-bezier(0.4, 0, 0.2, 1) both; }

@keyframes nx-pulse-dot {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.4); opacity: 0.5; }
}
.animate-pulse-dot { animation: nx-pulse-dot 2s ease-in-out infinite; }

/* ─── Scrollbar ───────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: rgba(34, 211, 238, 0.15);
    border-radius: 4px;
    border: 2px solid transparent;
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(34, 211, 238, 0.3); background-clip: padding-box; }

/* ─── Legacy component classes used by other admin pages ──────────── */
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 12px; font-weight: 600; color: #9fb0c9; margin-bottom: 6px; }
.form-control {
    width: 100%; padding: 10px 14px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(34, 211, 238, 0.1);
    border-radius: 10px;
    color: var(--foreground);
    font-family: inherit; font-size: 14px;
    backdrop-filter: blur(8px);
    transition: all 0.25s;
}
.form-control::placeholder { color: var(--text-muted); }
.form-control:focus {
    outline: none;
    border-color: rgba(34, 211, 238, 0.4);
    box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.1);
    background: rgba(255, 255, 255, 0.05);
}
select.form-control {
    appearance: none;
    background-color: rgba(8, 10, 24, 0.8);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%235a6b85' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
    background-position: left 12px center;
    background-repeat: no-repeat;
    background-size: 16px;
    padding-left: 40px;
}
select.form-control option { background-color: #0a0c1a; color: var(--foreground); }
.form-check { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.form-check input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--accent-cyan); }

.badge, .badge-nx {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 10px; border-radius: 20px;
    font-size: 11px; font-weight: 600; line-height: 1.4;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
    white-space: nowrap;
}
.badge-owner { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
.badge-admin { background: rgba(34, 211, 238, 0.15); color: #22d3ee; }
.badge-active { background: rgba(45, 212, 191, 0.15); color: #2dd4bf; }
.badge-inactive { background: rgba(248, 113, 113, 0.12); color: #f87171; }
.badge-banned { background: rgba(248, 113, 113, 0.18); color: #f87171; }
.badge-open { background: rgba(248, 113, 113, 0.12); color: #f87171; }
.badge-claimed { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
.badge-answered { background: rgba(45, 212, 191, 0.15); color: #2dd4bf; }
.badge-closed { background: rgba(148, 163, 184, 0.12); color: #94a3b8; }
.badge-approved { background: rgba(34, 197, 94, 0.15); color: #22c55e; }
.badge-rejected { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
.badge-paid { background: rgba(34, 197, 94, 0.15); color: #22c55e; }

.alert {
    padding: 12px 16px; border-radius: 14px; margin-bottom: 16px;
    font-size: 13px; font-weight: 500;
    display: flex; align-items: center; gap: 10px;
    backdrop-filter: blur(12px);
}
.alert-success { background: rgba(45, 212, 191, 0.1); border: 1px solid rgba(45, 212, 191, 0.3); color: #2dd4bf; }
.alert-error { background: rgba(248, 113, 113, 0.1); border: 1px solid rgba(248, 113, 113, 0.3); color: #f87171; }
.alert-warning { background: rgba(251, 191, 36, 0.1); border: 1px solid rgba(251, 191, 36, 0.3); color: #fbbf24; }
.alert-info { background: rgba(34, 211, 238, 0.1); border: 1px solid rgba(34, 211, 238, 0.3); color: #22d3ee; }

table { width: 100%; border-collapse: collapse; }
table th, table td { padding: 12px 16px; text-align: right; border-bottom: 1px solid rgba(34, 211, 238, 0.06); font-size: 13px; }
table th { font-weight: 700; color: var(--text-muted); background: rgba(34, 211, 238, 0.03); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }
table td { color: var(--foreground); }
table tr:hover td { background: rgba(34, 211, 238, 0.04); }

.pagination { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 24px; flex-wrap: wrap; }
.pagination a, .pagination span {
    padding: 8px 14px; border-radius: 10px; font-size: 13px; font-weight: 600;
    text-decoration: none; color: #9fb0c9;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(34, 211, 238, 0.1);
    backdrop-filter: blur(8px); transition: all 0.2s;
}
.pagination a:hover { background: rgba(255, 255, 255, 0.08); color: var(--accent-cyan); }
.pagination span.current {
    background: linear-gradient(135deg, #22d3ee, #a78bfa);
    color: #05060f; border-color: transparent;
    box-shadow: 0 2px 12px rgba(34, 211, 238, 0.3);
}

.toggle { position: relative; width: 44px; height: 24px; display: inline-block; }
.toggle input { display: none; }
.toggle .slider { position: absolute; inset: 0; background: rgba(34, 211, 238, 0.12); border-radius: 12px; cursor: pointer; transition: 0.3s; }
.toggle .slider::before { content: ''; position: absolute; width: 18px; height: 18px; border-radius: 50%; background: white; top: 3px; right: 3px; transition: 0.3s; }
.toggle input:checked + .slider { background: linear-gradient(135deg, #22d3ee, #a78bfa); }
.toggle input:checked + .slider::before { transform: translateX(-20px); }

/* Chat bubbles (ticket_detail) */
.tg-chat {
    height: 460px; overflow-y: auto; padding: 12px 16px;
    display: flex; flex-direction: column; gap: 2px;
    background: radial-gradient(rgba(34,211,238,0.04) 1px, transparent 1px) 0 0 / 18px 18px, linear-gradient(135deg, #0a0c1a, #0e1621);
    scroll-behavior: smooth;
    scrollbar-width: thin; scrollbar-color: rgba(34,211,238,0.25) transparent;
}
.tg-chat::-webkit-scrollbar { width: 8px; }
.tg-chat::-webkit-scrollbar-track { background: transparent; }
.tg-chat::-webkit-scrollbar-thumb { background: rgba(34,211,238,0.2); border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; }
.tg-chat::-webkit-scrollbar-thumb:hover { background: rgba(34,211,238,0.35); background-clip: padding-box; }
.tg-row { display: flex; width: 100%; margin-bottom: 2px; }
.tg-row.in { justify-content: flex-start; }
.tg-row.out { justify-content: flex-end; }
.tg-bubble { max-width: 75%; width: fit-content; padding: 6px 10px 5px; border-radius: 14px; font-size: 14px; line-height: 1.5; word-wrap: break-word; }
.tg-row.in .tg-bubble { background: #182533; color: #e8e8e8; border: 1px solid rgba(255,255,255,0.06); border-bottom-left-radius: 5px; box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
.tg-row.out .tg-bubble { background: linear-gradient(135deg, #2b5278, #1e3a5f); color: #e8e8e8; border: 1px solid rgba(34,211,238,0.15); border-bottom-right-radius: 5px; box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
.tg-name { font-size: 11px; font-weight: 700; margin-bottom: 1px; line-height: 1.2; }
.tg-row.in .tg-name { color: #e88b8b; }
.tg-row.out .tg-name { color: #8bc48b; }
.tg-body { display: inline; white-space: pre-wrap; }
.tg-meta { font-size: 10px; float: left; margin-left: 6px; margin-top: 3px; line-height: 1; }
.tg-row.in .tg-meta { color: #6d8a9e; }
.tg-row.out .tg-meta { color: #7ab0d4; }
.tg-clear { clear: both; }

/* ═══════════════════════════════════════════════════════════════════
   LEGACY COMPONENT CLASSES (for non-rewritten admin pages)
   These ensure users/channels/settings/etc pages still render correctly.
   ═══════════════════════════════════════════════════════════════════ */

.btn {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 10px 20px; border-radius: 10px;
    font-family: inherit; font-size: 14px; font-weight: 600;
    border: none; cursor: pointer;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    text-decoration: none; white-space: nowrap;
    position: relative; overflow: hidden;
}
.btn-primary { background: linear-gradient(135deg, #22d3ee, #a78bfa); color: #05060f; box-shadow: 0 4px 16px rgba(34, 211, 238, 0.3); }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 6px 24px rgba(34, 211, 238, 0.4); }
.btn-success { background: linear-gradient(135deg, #2dd4bf, #22d3ee); color: #05060f; box-shadow: 0 4px 16px rgba(45, 212, 191, 0.3); }
.btn-danger { background: linear-gradient(135deg, #f87171, #f472b6); color: #05060f; box-shadow: 0 4px 16px rgba(248, 113, 113, 0.3); }
.btn-danger:hover { transform: translateY(-2px); box-shadow: 0 6px 24px rgba(248, 113, 113, 0.4); }
.btn-warning { background: linear-gradient(135deg, #fb923c, #fbbf24); color: #05060f; box-shadow: 0 4px 16px rgba(251, 146, 60, 0.3); }
.btn-glass { background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(34, 211, 238, 0.15); color: #e6f0ff; backdrop-filter: blur(12px); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); }
.btn-glass:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(34, 211, 238, 0.3); transform: translateY(-1px); }
.btn-sm { padding: 8px 14px; font-size: 13px; }
.btn-xs { padding: 6px 10px; font-size: 12px; }

.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; gap: 12px; flex-wrap: wrap; }
.card-title { font-size: 15px; font-weight: 700; color: #e6f0ff; display: flex; align-items: center; gap: 8px; }

.chart-grid { display: grid; grid-template-columns: 1fr; gap: 20px; margin-bottom: 24px; }
@media (min-width: 1024px) { .chart-grid { grid-template-columns: repeat(2, 1fr); } }

.chart-card {
    background: rgba(255, 255, 255, 0.04);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid rgba(34, 211, 238, 0.1);
    border-radius: 14px;
    padding: 20px;
    box-shadow: 0 4px 30px rgba(34, 211, 238, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    transition: all 0.4s;
}
@media (min-width: 640px) { .chart-card { padding: 24px; } }
.chart-card:hover { box-shadow: 0 8px 40px rgba(34, 211, 238, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.08); }
.chart-card .chart-title { font-size: 15px; font-weight: 700; color: #e6f0ff; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
.chart-card canvas { max-height: 280px; }

.grid-2 { display: grid; grid-template-columns: 1fr; gap: 20px; }
.grid-3 { display: grid; grid-template-columns: 1fr; gap: 20px; }
@media (min-width: 768px) { .grid-2 { grid-template-columns: repeat(2, 1fr); } .grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid-3 { grid-template-columns: repeat(3, 1fr); } }

.empty-state { text-align: center; padding: 60px 20px; color: #5a6b85; }
.empty-state .empty-icon { font-size: 48px; margin-bottom: 16px; opacity: 0.5; }
.empty-state .empty-text { font-size: 16px; font-weight: 600; margin-bottom: 8px; color: #e6f0ff; }

.page-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
.page-header h1 { font-size: 26px; font-weight: 800; background: linear-gradient(135deg, #e6f0ff, #22d3ee); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent; }
.page-header .breadcrumb { font-size: 13px; color: #5a6b85; font-weight: 500; }

.stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 24px; }
@media (min-width: 768px) { .stats-grid { grid-template-columns: repeat(3, 1fr); gap: 18px; } }
@media (min-width: 1280px) { .stats-grid { grid-template-columns: repeat(4, 1fr); } }

.table-container { overflow-x: auto; overflow-y: hidden; border-radius: 14px; -webkit-overflow-scrolling: touch; }

/* Login page */
.login-container { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 20px; }
.login-box {
    background: rgba(8, 10, 24, 0.7);
    backdrop-filter: blur(30px) saturate(160%);
    -webkit-backdrop-filter: blur(30px) saturate(160%);
    border: 1px solid rgba(34, 211, 238, 0.15);
    border-radius: 28px;
    box-shadow: 0 20px 60px rgba(34, 211, 238, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.06);
    padding: 40px 32px; width: 100%; max-width: 440px; text-align: center;
}
.login-box .logo {
    font-size: 36px; font-weight: 900;
    background: linear-gradient(135deg, #22d3ee, #a78bfa, #f472b6);
    background-size: 200% 200%;
    -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
    animation: nx-iridescent 6s ease-in-out infinite; margin-bottom: 8px;
}
.login-box .tagline { color: #5a6b85; font-size: 14px; margin-bottom: 32px; }
.login-box .divider { display: flex; align-items: center; gap: 16px; margin: 24px 0; color: #5a6b85; font-size: 12px; }
.login-box .divider::before, .login-box .divider::after { content: ''; flex: 1; height: 1px; background: rgba(34, 211, 238, 0.1); }

/* Misc buttons used in api_keys page */
.btn-view-key, .copy-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border-radius: 8px;
    font-size: 12px; font-weight: 600;
    background: rgba(34, 211, 238, 0.08);
    border: 1px solid rgba(34, 211, 238, 0.15);
    color: #22d3ee; cursor: pointer;
    transition: all 0.2s; font-family: inherit;
}
.btn-view-key:hover, .copy-btn:hover { background: rgba(34, 211, 238, 0.15); border-color: rgba(34, 211, 238, 0.3); }

.flash { margin-bottom: 16px; }

/* Stat card text classes (used by non-rewritten pages) */
.stat-card .stat-value { font-size: 28px; font-weight: 900; color: #e6f0ff; line-height: 1; margin-top: 16px; }
@media (min-width: 640px) { .stat-card .stat-value { font-size: 32px; } }
.stat-card .stat-label { font-size: 13px; color: #9fb0c9; font-weight: 500; margin-top: 8px; }

/* API keys page specific */
.key-display-box, .view-key-box {
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(34, 211, 238, 0.15);
    border-radius: 12px;
    padding: 16px;
    margin: 12px 0;
    word-break: break-all;
    font-family: monospace;
    font-size: 13px;
    color: #22d3ee;
    direction: ltr;
    text-align: left;
}
.key-display-text, .view-key-title { font-weight: 700; color: #e6f0ff; margin-bottom: 8px; }
.view-key-overlay {
    position: fixed; inset: 0; z-index: 100;
    background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(8px);
    display: flex; align-items: center; justify-content: center; padding: 16px;
}
.view-key-warn { color: #fbbf24; font-size: 12px; margin-top: 8px; }
.view-key-actions { display: flex; gap: 8px; margin-top: 16px; justify-content: flex-end; flex-wrap: wrap; }

/* Permission badges (admins page) */
.perm-badge {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 4px 10px; border-radius: 8px;
    font-size: 11px; font-weight: 600;
    background: rgba(34, 211, 238, 0.1);
    border: 1px solid rgba(34, 211, 238, 0.2);
    color: #22d3ee; margin: 2px;
}

/* Loading state */
.loading { display: inline-block; width: 16px; height: 16px; border: 2px solid rgba(34, 211, 238, 0.2); border-top-color: #22d3ee; border-radius: 50%; animation: nx-spin 0.8s linear infinite; }
@keyframes nx-spin { to { transform: rotate(360deg); } }

/* Main content wrapper for non-rewritten pages */
.main-content { flex: 1; padding: 24px 16px 40px; }
@media (min-width: 640px) { .main-content { padding: 24px 24px 40px; } }
@media (min-width: 1024px) { .main-content { padding: 24px 40px 40px; } }

/* ═══════════════════════════════════════════════════════════════════
   T46-v PRIMITIVE DRAWER — the drawer is now two elements whose ONLY
   state is the wrap's display (block/none). No transform, no transition,
   no opacity, no classes, no backdrop-filter: there is nothing left that
   a stale stylesheet, a weak GPU compositor or a mid-animation freeze can
   mis-place. The PANEL itself is position:fixed right:0 — anchored to the
   viewport regardless of any ancestor — and the controller re-asserts
   this geometry inline-!important on every open, then hard-verifies it
   with getBoundingClientRect. Mirrored here with !important so no
   cached/foreign/CDN-injected sheet can win.
   ═══════════════════════════════════════════════════════════════════ */
#mobileSidebar {
    position: fixed !important; top: 0 !important; right: 0 !important;
    bottom: 0 !important; left: 0 !important; width: 100% !important;
    height: 100% !important; margin: 0 !important; padding: 0 !important;
    background: rgba(3, 4, 12, 0.72) !important;
    z-index: 2147483000 !important;
}
#mobileSidebar > #mobileDrawerPanel {
    position: fixed !important; top: 0 !important; right: 0 !important;
    bottom: 0 !important; left: auto !important;
    width: 300px !important; max-width: 85vw !important;
    margin: 0 !important; padding: 0 !important;
    background: #0a0c19 !important;
    border-left: 1px solid rgba(34, 211, 238, 0.12) !important;
    box-shadow: 4px 0 40px rgba(0, 0, 0, 0.5) !important;
    transform: none !important; transition: none !important; animation: none !important;
    backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
    overflow-y: auto !important; -webkit-overflow-scrolling: touch;
    z-index: 2147483001 !important;
}
/* No ancestor may become a containing block that could displace the
   position:fixed drawer (transform/filter/perspective on html or body). */
html, body { transform: none !important; filter: none !important; perspective: none !important; }
/* Mobile layout lock: desktop sidebar gone, main column full-width. */
@media (max-width: 1023px) {
    .nx-desktop-sidebar { display: none !important; }
    .nx-main-col { margin-right: 0 !important; margin-left: 0 !important; }
    #mobileSidebar, #mobileSidebar > #mobileDrawerPanel { transition: none !important; animation: none !important; }
    body::before, body::after { animation: none !important; }
}

/* Desktop sidebar */
.nx-desktop-sidebar {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: 280px; z-index: 40;
    background: rgba(8, 10, 24, 0.72);
    backdrop-filter: blur(30px) saturate(180%);
    -webkit-backdrop-filter: blur(30px) saturate(180%);
    border-left: 1px solid rgba(34, 211, 238, 0.12);
    box-shadow: -4px 0 40px rgba(34, 211, 238, 0.04);
    overflow-y: auto;
}
@media (min-width: 1024px) {
    .nx-main-col { margin-right: 280px; }
}

/* Main column */
.nx-main-col {
    display: flex; min-height: 100vh; flex-direction: column;
}

/* Topbar */
.nx-topbar {
    position: sticky; top: 0; z-index: 30;
    display: flex; align-items: center; gap: 12px;
    height: 64px; padding: 0 16px;
    background: rgba(5, 6, 15, 0.6);
    backdrop-filter: blur(20px) saturate(160%);
    -webkit-backdrop-filter: blur(20px) saturate(160%);
    border-bottom: 1px solid rgba(34, 211, 238, 0.08);
}
@media (min-width: 640px) { .nx-topbar { padding: 0 24px; } }
@media (min-width: 1024px) { .nx-topbar { padding: 0 40px; } }

/* Mobile hamburger — only shows on mobile */
.nx-hamburger {
    display: none;
    width: 40px; height: 40px;
    border-radius: 12px;
    background: rgba(8, 10, 24, 0.8);
    border: 1px solid rgba(34, 211, 238, 0.15);
    color: #e6f0ff; cursor: pointer;
    align-items: center; justify-content: center;
    flex-shrink: 0;
}
@media (max-width: 1023px) { .nx-hamburger { display: flex; } }

/* Topbar title */
.nx-topbar-title { min-width: 0; flex: 1; }
.nx-topbar-title h1 {
    font-size: 17px; font-weight: 700; line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    background: linear-gradient(135deg, #e6f0ff, #22d3ee);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
}
@media (min-width: 640px) { .nx-topbar-title h1 { font-size: 20px; } }
.nx-topbar-title .crumb {
    display: none;
    font-size: 11px; color: #5a6b85;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (min-width: 640px) { .nx-topbar-title .crumb { display: block; } }

/* Topbar search — visible on all sizes (icon-only on small mobile) */
.nx-topbar-search {
    display: flex;
    align-items: center; gap: 8px;
    border-radius: 12px; padding: 8px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(34, 211, 238, 0.1);
    backdrop-filter: blur(8px);
    flex-shrink: 0;
}
@media (min-width: 768px) { .nx-topbar-search { padding: 8px 12px; } }
.nx-topbar-search svg { width: 16px; height: 16px; color: #5a6b85; flex-shrink: 0; }
.nx-topbar-search input {
    width: 90px; border: none; background: transparent;
    color: #e6f0ff; font-family: inherit; font-size: 13px;
    transition: width 0.3s, padding 0.3s;
    padding: 0 4px; overflow: hidden;
    min-width: 60px; /* CRITICAL: clickable on mobile */
}
/* On small mobile: expand on focus */
@media (max-width: 767px) {
    .nx-topbar-search input { width: 80px; }
    .nx-topbar-search:focus-within input { width: 140px; }
}
@media (min-width: 768px) {
    .nx-topbar-search input { width: 160px; }
}
@media (min-width: 1280px) { .nx-topbar-search input { width: 224px; } }
.nx-topbar-search input::placeholder { color: #5a6b85; }
.nx-topbar-search input:focus { outline: none; }

/* Bell button */
.nx-bell-btn {
    position: relative;
    width: 40px; height: 40px; flex-shrink: 0;
    display: grid; place-items: center;
    border-radius: 12px; cursor: pointer;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(34, 211, 238, 0.1);
    color: #9fb0c9;
    transition: all 0.2s;
}
.nx-bell-btn:hover { background: rgba(255,255,255,0.06); color: #fff; }
.nx-bell-btn svg { width: 18px; height: 18px; }
.nx-bell-btn .dot {
    position: absolute; right: 10px; top: 10px;
    width: 8px; height: 8px; border-radius: 50%;
    background: #f87171; box-shadow: 0 0 6px #f87171;
}

/* Bell dropdown */
.nx-bell-dropdown {
    position: absolute; left: 0; top: 50px; z-index: 50;
    width: 320px; max-width: 90vw;
    border-radius: 16px; padding: 12px;
    background: rgba(8, 10, 24, 0.95);
    border: 1px solid rgba(34, 211, 238, 0.2);
    backdrop-filter: blur(30px);
    box-shadow: 0 20px 60px rgba(0,0,0,0.5);
    display: none;
}
.nx-bell-dropdown.nx-show { display: block; }

/* Main content */
.nx-content { flex: 1; padding: 24px 16px 40px; }
@media (min-width: 640px) { .nx-content { padding: 24px 24px 40px; } }
@media (min-width: 1024px) { .nx-content { padding: 24px 40px 40px; } }

/* Footer */
.nx-footer {
    margin-top: auto; padding: 20px 16px; text-align: center;
    border-top: 1px solid rgba(34, 211, 238, 0.06);
}
@media (min-width: 640px) { .nx-footer { padding: 20px 24px; } }
@media (min-width: 1024px) { .nx-footer { padding: 20px 40px; } }
.nx-footer p { font-size: 12px; color: #5a6b85; }

/* Nav items (used by sidebar renderer) */
.nx-nav-item {
    position: relative; display: flex; align-items: center; gap: 12px;
    padding: 11px 16px; border-radius: 14px;
    color: #9fb0c9; text-decoration: none;
    font-size: 14px; font-weight: 500;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    margin-bottom: 3px; border: 1px solid transparent;
    cursor: pointer;
}
.nx-nav-item:hover { color: #e6f0ff; background: rgba(255, 255, 255, 0.04); transform: translateX(-3px); }
.nx-nav-item.nx-active {
    color: #fff; font-weight: 600;
    background: linear-gradient(135deg, rgba(34, 211, 238, 0.18), rgba(167, 139, 250, 0.18));
    border: 1px solid rgba(34, 211, 238, 0.3);
    box-shadow: 0 0 24px rgba(34, 211, 238, 0.12) inset, 0 4px 20px rgba(34, 211, 238, 0.1);
}
.nx-nav-item.nx-active::after {
    content: ''; position: absolute; right: 0; top: 50%;
    height: 20px; width: 3px; transform: translateY(-50%);
    border-radius: 4px;
    background: linear-gradient(180deg, #22d3ee, #a78bfa);
}
.nx-nav-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.nx-nav-icon-cyan { color: #22d3ee; filter: drop-shadow(0 0 6px rgba(34,211,238,0.3)); }
.nx-nav-icon-muted { color: #7d8fab; }
.nx-nav-item:hover .nx-nav-icon-muted { color: #22d3ee; }

/* Sidebar header */
.nx-sidebar-header { display: flex; align-items: center; gap: 12px; padding: 20px; border-bottom: 1px solid rgba(34,211,238,0.08); }
.nx-logo-icon {
    width: 44px; height: 44px; display: grid; place-items: center;
    border-radius: 16px;
    background: linear-gradient(135deg, rgba(34,211,238,0.18), rgba(167,139,250,0.18));
    border: 1px solid rgba(34, 211, 238, 0.25);
    box-shadow: 0 0 18px rgba(34, 211, 238, 0.2) inset;
}
.nx-logo-text {
    font-size: 22px; font-weight: 900; letter-spacing: 2px; line-height: 1;
    background: linear-gradient(135deg, #22d3ee, #a78bfa, #f472b6);
    background-size: 200% 200%;
    -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
    animation: nx-iridescent 6s ease-in-out infinite;
}
.nx-logo-sub { font-size: 10px; font-weight: 700; color: #5a6b85; text-transform: uppercase; letter-spacing: 1.5px; margin-top: 4px; }

.nx-sidebar-nav { flex: 1; overflow-y: auto; padding: 16px 12px; }
.nx-nav-section { margin-bottom: 20px; }
.nx-nav-section-title { font-size: 10px; font-weight: 700; color: #5a6b85; text-transform: uppercase; letter-spacing: 1.5px; padding: 0 16px 8px; }

/* Sidebar footer / user pill */
.nx-sidebar-footer { padding: 16px; border-top: 1px solid rgba(34,211,238,0.08); }
.nx-user-pill { display: flex; align-items: center; gap: 12px; padding: 10px; border-radius: 14px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); }
.nx-user-avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #22d3ee, #a78bfa); box-shadow: 0 2px 12px rgba(34,211,238,0.35); color: #05060f; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px; flex-shrink: 0; }
.nx-user-info { flex: 1; min-width: 0; }
.nx-user-name { font-size: 13px; font-weight: 600; color: #e6f0ff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nx-user-role { font-size: 11px; color: #5a6b85; }
.nx-logout-btn { color: #5a6b85; text-decoration: none; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 8px; transition: all 0.2s; flex-shrink: 0; }
.nx-logout-btn:hover { background: rgba(248,113,113,0.12); color: #f87171; }

/* Mobile close button */
.nx-drawer-close { position: absolute; top: 16px; left: 16px; z-index: 5; width: 36px; height: 36px; border-radius: 12px; background: rgba(255,255,255,0.04); border: 1px solid rgba(34,211,238,0.15); color: #9fb0c9; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.nx-drawer-close:hover { background: rgba(255,255,255,0.08); color: #fff; }

/* Tables responsive on mobile — horizontal scroll */
.nx-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ═══════════════════════════════════════════════════════════════════
   MOBILE TABLE RESPONSIVENESS — tables scroll + action buttons compact
   ═══════════════════════════════════════════════════════════════════ */

/* Ensure ALL table-containers scroll horizontally on small screens */
.table-container, .nx-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}

/* On mobile, make tables more compact */
@media (max-width: 767px) {
    table { min-width: 600px; } /* force horizontal scroll if needed */
    table th, table td {
        padding: 10px 8px;
        font-size: 12px;
        white-space: nowrap;
    }
    /* Action button columns — icon only, tight */
    table td:last-child,
    table th:last-child {
        white-space: nowrap;
        min-width: 44px;
    }
    /* Buttons in tables become icon-only */
    table .btn { padding: 6px; gap: 0; }
    table .btn span { display: none; } /* hide text labels, keep icons */
    table .btn svg { width: 16px; height: 16px; }
}

/* Make action button groups wrap nicely */
table td .btn-group,
table td div[style*="display:flex"][style*="gap"] {
    display: inline-flex;
    gap: 4px;
    flex-wrap: nowrap;
    align-items: center;
}

/* Long text cells — truncate on mobile */
@media (max-width: 767px) {
    table td.truncate-mobile {
        max-width: 120px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* Icon button — small, square, icon-only */
.nx-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    padding: 0;
    flex-shrink: 0;
}
.nx-icon-btn svg { width: 16px; height: 16px; }
@media (max-width: 767px) {
    .nx-icon-btn { width: 28px; height: 28px; }
    .nx-icon-btn svg { width: 14px; height: 14px; }
}

/* ═══════════════════════════════════════════════════════════════════
   T46-r MOBILE RESPONSIVENESS PASS (round 34) — owner phone fixes
   1) Stat-card numbers no longer clip on phones: .stat-value scales
      with viewport (7–13 digit totals were clipped by overflow:hidden
      at 360–430px with the fixed 28px font).
   2) Tap targets: .btn-xs pagination/edit buttons and icon buttons
      were 25–30px — raised to ≥34px on phones (was below 32px floor).
   3) Table action buttons keep icon-only compaction but regain a
      comfortable padding (9px 12px) instead of 6px.
   ═══════════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
    .stat-card { padding: 16px; }
    .stat-card .stat-value { font-size: clamp(18px, 5.5vw, 28px); }
    table .btn { padding: 9px 12px; }
    .btn-xs { min-height: 36px; min-width: 36px; }
    .nx-icon-btn { width: 34px; height: 34px; }
    .nx-icon-btn svg { width: 15px; height: 15px; }
}
    </style>
    <script>/* T46-t bfcache auto-heal, T46-ak FORM-SAFE: Chrome/Safari restore
         tabs from the back-forward cache WITHOUT any network request, so a
         restored tab would keep showing a pre-fix render forever — one reload
         on restore, real navigations (persisted=false) untouched. T46-ak
         (owner: «صفحه همش ریفرش میشه»): the restore-reload must NEVER fire
         while an admin is mid-form (mafia login wizard — typing the code or
         the 2FA password), so when any form field holds typed input the
         reload is skipped and the stale-render heal happens on the next
         real navigation instead. */
    (function () {
        window.addEventListener('pageshow', function (e) {
            if (!e.persisted) { return; }
            var dirty = false;
            try {
                for (var i = 0; i < document.forms.length && !dirty; i++) {
                    var els = document.forms[i].elements;
                    for (var j = 0; j < els.length; j++) {
                        var el = els[j];
                        if (!el || el.type === 'hidden' || el.type === 'submit' || el.type === 'button' || el.type === 'fieldset') { continue; }
                        if (el.type === 'checkbox' || el.type === 'radio') {
                            if (el.checked !== el.defaultChecked) { dirty = true; break; }
                            continue;
                        }
                        if ((el.value || '') !== (el.defaultValue || '')) { dirty = true; break; }
                    }
                }
            } catch (err) { dirty = false; }
            if (!dirty) { location.reload(); }
        });
    })();
    </script>
    <!-- CSRF token exposed to JS for AJAX POST requests (fetch sends it in the
         X-CSRF-Token header; the server verifies it via csrf_verify()). -->
    <meta name="csrf-token" content="<?= e(csrf_token()) ?>">
    <!-- T46-v: the Tailwind PLAY CDN script REMOVED. That CDN is unreachable
         on some networks (sanctions / DNS pollution) — pages then rendered
         with raw UA styles (8px body margin, content-box, native buttons)
         and the mafia page had literally no styling. Its reset layer is
         reproduced locally by the T46-v PREFLIGHT-LITE block in the sheet
         below, and the mafia/login pages were rewritten onto the panel's
         own design system. No page depends on any CDN stylesheet or script
         anymore. (Chart.js stays: it only draws optional graphs, never
         layout.) -->
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
</head>
<body>

    <!-- ═══ T46-v PRIMITIVE DRAWER — two elements, one state bit:
         display:block on the wrap IS the entire open state. The panel is
         position:fixed right:0 (viewport-anchored — no ancestor, no
         stylesheet can displace it), the dim is the wrap's own background.
         There is no transform, no transition, no opacity and no class to
         freeze mid-slide or to re-place. The controller re-asserts the
         geometry inline on every open and hard-verifies it. ═══ -->
    <div id="mobileSidebar" style="display:none;position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;margin:0;padding:0;background:rgba(3,4,12,0.72);z-index:2147483000;">
        <nav id="mobileDrawerPanel" aria-label="منوی موبایل" style="position:fixed;top:0;right:0;bottom:0;left:auto;width:300px;max-width:85vw;margin:0;padding:0;background:#0a0c19;border-left:1px solid rgba(34,211,238,0.12);box-shadow:4px 0 40px rgba(0,0,0,0.5);overflow-y:auto;-webkit-overflow-scrolling:touch;">
            <button type="button" class="nx-drawer-close" onclick="NetrexSidebar.close()" aria-label="بستن منو">
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
            </button>
            <?= NetrexSidebarContent::render($currentPage, $adminAuth, $currentUser) ?>
        </nav>
    </div>

    <!-- ═══ Desktop sidebar ═══ -->
    <aside class="nx-desktop-sidebar">
        <?= NetrexSidebarContent::render($currentPage, $adminAuth, $currentUser) ?>
    </aside>

    <!-- ═══ Main column ═══ -->
    <div class="nx-main-col">
        <!-- Topbar -->
        <header class="nx-topbar">
            <!-- Hamburger (mobile only) -->
            <button class="nx-hamburger" onclick="NetrexSidebar.open()" aria-label="باز کردن منو">
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
            </button>

            <!-- Title -->
            <div class="nx-topbar-title">
                <h1><span class="text-gradient-cyan"><?= e($pageTitle ?? 'داشبورد') ?></span></h1>
                <div class="crumb"><?= e($pageTitle ?? 'داشبورد') ?></div>
            </div>

            <!-- Search (functional) -->
            <div class="nx-topbar-search">
                <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
                <input id="nxGlobalSearch" oninput="NxGlobalSearch.filter(this.value)" placeholder="جستجو در صفحه..." />
            </div>

            <!-- Bell (functional) -->
            <div style="position:relative;">
                <button class="nx-bell-btn" onclick="NxBell.toggle(event)" aria-label="اعلان‌ها">
                    <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>
                    <?php if ($__openTicketCount > 0): ?>
                    <span class="dot"></span>
                    <?php endif; ?>
                </button>
                <div id="bellDropdown" class="nx-bell-dropdown">
                    <div style="display:flex;align-items:center;justify-content:space-between;padding:0 8px 8px;">
                        <span style="font-size:13px;font-weight:700;color:#e6f0ff;">اعلان‌ها</span>
                        <span style="font-size:11px;color:#5a6b85;"><?= $__openTicketCount ?> تیکت در انتظار پاسخ</span>
                    </div>
                    <div id="bellList" style="max-height:320px;overflow-y:auto;">
                        <?php if (empty($__allTickets)): ?>
                        <div style="padding:24px 12px;text-align:center;font-size:12px;color:#5a6b85;">اعلانی وجود ندارد.</div>
                        <?php else: foreach (array_slice(array_filter($__allTickets, fn($t) => $t['status'] !== 'closed'), 0, 8) as $__t): ?>
                        <a href="?page=ticket_detail&id=<?= (int)$__t['id'] ?>" style="display:block;padding:10px 12px;border-radius:10px;text-decoration:none;color:inherit;transition:background 0.2s;" onmouseover="this.style.background='rgba(255,255,255,0.04)'" onmouseout="this.style.background='transparent'">
                            <div style="display:flex;align-items:center;justify-content:space-between;">
                                <span style="font-size:12px;font-weight:700;color:#22d3ee;">تیکت #<?= (int)$__t['id'] ?></span>
                                <span class="badge <?= ($__t['last_sender'] ?? null) === null ? 'badge-claimed' : 'badge-open' ?>"><?= ($__t['last_sender'] ?? null) === null ? 'بدون پاسخ' : 'پاسخ جدید کاربر' ?></span>
                            </div>
                            <div style="margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:#9fb0c9;"><?= e(mb_substr($__t['question'], 0, 60)) ?><?= mb_strlen($__t['question']) > 60 ? '...' : '' ?></div>
                        </a>
                        <?php endforeach; endif; ?>
                    </div>
                    <a href="?page=support" style="display:block;margin-top:8px;padding:10px 12px;border-radius:10px;text-align:center;font-size:12px;font-weight:600;color:#22d3ee;text-decoration:none;transition:background 0.2s;" onmouseover="this.style.background='rgba(255,255,255,0.04)'" onmouseout="this.style.background='transparent'">مشاهده همه تیکت‌ها</a>
                </div>
            </div>
        </header>

        <!-- Content -->
        <main class="nx-content">
            <div class="animate-fade-up">
<?php
/** Sidebar content renderer (shared between desktop + mobile drawer). */
class NetrexSidebarContent {
    public static function render(string $currentPage, $adminAuth, $currentUser): string {
        // T46-v: the old hidden close button was dead markup (defined but
        // never rendered — the drawer markup carries its own visible one).

        $header = '<div class="nx-sidebar-header">'
            . '<div class="nx-logo-icon">'
            . '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#22d3ee" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="filter:drop-shadow(0 0 4px rgba(34,211,238,0.6))"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></svg>'
            . '</div>'
            . '<div><div class="nx-logo-text">NETREX</div><div class="nx-logo-sub">پنل مدیریت</div></div>'
            . '</div>';

        $nav = '<nav class="nx-sidebar-nav">';
        $nav .= self::section('منوی اصلی', $currentPage, [
            ['key' => 'dashboard', 'label' => 'داشبورد', 'svg' => '<rect width="7" height="9" x="3" y="3" rx="1"/><rect width="7" height="5" x="14" y="3" rx="1"/><rect width="7" height="9" x="14" y="12" rx="1"/><rect width="7" height="5" x="3" y="16" rx="1"/>'],
            ['key' => 'analytics', 'label' => 'آمار و تحلیل', 'svg' => '<path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="m19 9-5 5-4-4-3 3"/>'],
        ]);
        $nav .= self::section('مدیریت', $currentPage, [
            ['key' => 'users', 'label' => 'کاربران', 'svg' => '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><path d="M16 3.128a4 4 0 0 1 0 7.744"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><circle cx="9" cy="7" r="4"/>'],
            ['key' => 'channels', 'label' => 'کانال‌ها و ربات‌ها', 'svg' => '<path d="m3 11 18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/>'],
            ['key' => 'tasks', 'label' => 'تسک‌ها', 'svg' => '<path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/>'],
            ['key' => 'mafia', 'label' => 'مافیا صوتی', 'svg' => '<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>'],
            ['key' => 'rate_limits', 'label' => 'محدودیت نرخ', 'svg' => '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/>'],
            ['key' => 'support', 'label' => 'پشتیبانی و برداشت‌ها', 'svg' => '<circle cx="12" cy="12" r="10"/><path d="m4.93 4.93 4.24 4.24"/><path d="m14.83 9.17 4.24-4.24"/><path d="m14.83 14.83 4.24 4.24"/><path d="m9.17 14.83-4.24 4.24"/><circle cx="12" cy="12" r="4"/>'],
            ['key' => 'satisfactions', 'label' => 'رضایت‌ها', 'svg' => '<path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"/>'],
            ['key' => 'recharge_codes', 'label' => 'کدهای شارژ', 'svg' => '<rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/>'],
            ['key' => 'tod_questions', 'label' => 'سوالات جرات/حقیقت', 'svg' => '<path d="M9 12l2 2 4-4"/><path d="M12 3a9 9 0 1 0 9 9 9 9 0 0 0-9-9z"/>'],
        ]);
        if ($adminAuth->isOwner()) {
            $nav .= self::section('تنظیمات', $currentPage, [
                ['key' => 'settings', 'label' => 'تنظیمات ربات', 'svg' => '<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/>'],
                ['key' => 'messages', 'label' => 'متون ربات', 'svg' => '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>'],
                ['key' => 'buttons', 'label' => 'دکمه‌ها', 'svg' => '<path d="m9 9 5 12 1.8-5.2L21 14Z"/><path d="M7.2 2.2 8 5.1"/><path d="m5.1 8-2.9-.8"/><path d="M14 4.1 12 6"/><path d="m6 12-1.9 2"/>'],
                ['key' => 'broadcast', 'label' => 'پیام همگانی', 'svg' => '<path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9"/><path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"/><circle cx="12" cy="12" r="2"/><path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"/><path d="M19.1 4.9C23 8.8 23 15.2 19.1 19.1"/>'],
                ['key' => 'admins', 'label' => 'مدیران', 'svg' => '<path d="M2 18v3c0 1 1 2 2 2h3"/><path d="M19 18v3c0 1-1 2-2 2h-3"/><path d="M2 6V3c0-1 1-2 2-2h3"/><path d="M19 6V3c0-1-1-2-2-2h-3"/><circle cx="12" cy="12" r="3"/>'],
                ['key' => 'api_keys', 'label' => 'کلیدهای API', 'svg' => '<path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/>'],
                ['key' => 'audit_log', 'label' => 'گزارش فعالیت', 'svg' => '<path d="M15 12h-5"/><path d="M15 8h-5"/><path d="M19 17V5a2 2 0 0 0-2-2H4"/><path d="M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"/>'],
            ]);
        }
        $nav .= '</nav>';

        $footer = '<div class="nx-sidebar-footer"><div class="nx-user-pill">'
            . '<div class="nx-user-avatar">' . e(mb_substr($currentUser['display_name'], 0, 1)) . '</div>'
            . '<div class="nx-user-info"><div class="nx-user-name">' . e($currentUser['display_name']) . '</div><div class="nx-user-role">' . ($currentUser['role'] === 'owner' ? 'مالک' : 'مدیر') . '</div></div>'
            . '<a href="?action=logout" class="nx-logout-btn" title="خروج"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg></a>'
            . '</div></div>';

        return '<div style="display:flex;flex-direction:column;height:100%;">' . $header . $nav . $footer . '</div>';
    }

    private static function section(string $title, string $currentPage, array $items): string {
        $out = '<div class="nx-nav-section"><div class="nx-nav-section-title">' . e($title) . '</div>';
        foreach ($items as $it) {
            // Active check: optional per-item callable, else default to key match.
            if (isset($it['active']) && is_callable($it['active'])) {
                $active = (bool)($it['active'])($currentPage);
            } else {
                $active = $currentPage === $it['key'];
            }
            // Href: optional per-item override, else default to ?page=KEY.
            $href = $it['href'] ?? ('?page=' . $it['key']);
            $cls = $active ? 'nx-nav-item nx-active' : 'nx-nav-item';
            $iconCls = $active ? 'nx-nav-icon-cyan' : 'nx-nav-icon-muted';
            $out .= '<a href="' . $href . '" class="' . $cls . '">'
                . '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="' . $iconCls . '" style="filter:drop-shadow(0 0 6px rgba(34,211,238,0.3))">' . $it['svg'] . '</svg>'
                . '<span>' . e($it['label']) . '</span>'
                . '</a>';
        }
        return $out . '</div>';
    }
}
?>
