/* ============================================================
   Bitbas6x HS Manager — admin dashboard
   Modern SaaS / FinTech / network-management design system.
   Same class names as before throughout - only the visual tokens
   and component styling changed, so no template changes needed.
   ============================================================ */

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

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; }

:root {
    /* Surfaces */
    --bg:              #F3F7FB;   /* app background - never pure white */
    --bg-sidebar:      #F6FBFF;
    --surface-1:       #ffffff;   /* cards, panels */
    --surface-2:       #ffffff;   /* raised cards (router cards) */
    --surface-muted:   #F8FAFC;   /* read-only / de-emphasised blocks */
    --bg-hover:        #F1F7FC;
    --bg-selected:     #EAF6FF;
    --bg-table-head:   #EFF8FF;

    /* Text */
    --text:            #071120;
    --text-secondary:  #334155;
    --text-muted:      #64748B;
    --text-light:      #94A3B8;
    --text-accent:     #0878EA;

    /* Lines */
    --border:          #D9E5EF;
    --border-light:    #E5EDF5;
    --border-medium:   #CBDCEB;
    --border-accent:   #0B84F3;
    --border-danger:   #f3b8b3;

    /* Accent + status */
    --fill-accent:     #0878EA;
    --cyan-accent:     #00A9E8;
    --accent-deep:     #0666D6;
    --gradient-primary:       linear-gradient(135deg, #0878EA 0%, #00A9E8 100%);
    --gradient-primary-hover: linear-gradient(135deg, #0666D6 0%, #0096D6 100%);

    --text-success:    #15803D;
    --bg-success:      #ECFDF3;
    --text-danger:     #DC2626;
    --bg-danger:       #FEF2F2;
    --text-warning:    #B45309;
    --bg-warning:      #FFFBEB;
    --text-info:       #0284C7;
    --bg-info:         #EFF8FF;

    --radius:          9px;       /* cards */
    --radius-input:    6px;
    --radius-modal:    12px;
    --radius-pill:     999px;

    --shadow-xs: 0 1px 2px rgba(15,23,42,0.03);
    --shadow-sm: 0 1px 3px rgba(15,23,42,0.05), 0 1px 2px rgba(15,23,42,0.03);
    --shadow-md: 0 4px 12px rgba(15,23,42,0.06), 0 1px 3px rgba(15,23,42,0.04);
    --shadow-lg: 0 10px 30px rgba(15,23,42,0.08);
    --shadow-card: 0 1px 3px rgba(15,23,42,0.035);
    --shadow-dropdown: 0 8px 24px rgba(15,23,42,0.10);
    --shadow-modal: 0 20px 50px rgba(15,23,42,0.15);

    /* Elevated "bubble" treatment for cards/rows/buttons - light and dark
       genuinely use different techniques rather than one inverted from
       the other. Light mode: a visibly stronger solid border plus a
       proper lift shadow. Dark mode (see .dark below) swaps in a full
       metallic bevel - light mode was tested with the same bevel
       technique and it barely registered on white, so it isn't worth
       chasing there. */
    --bubble-border-width: 2px;
    --bubble-border-color: #94A3B8;
    --bubble-shadow: 0 4px 12px rgba(15,23,42,0.16);
    --bubble-shadow-hover: 0 6px 18px rgba(15,23,42,0.22);
    --metal-1: #B8C4D4;
    --metal-2: #64748B;

    --font-mono:       ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Consolas, monospace;
}

body {
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    font-size: 14px;
}

/* ── Top bar ── */
.topbar {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 24px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-1);
    margin-bottom: 20px;
}
.topbar-left { display: flex; align-items: center; gap: 20px; }
.topbar img { height: 26px; }
.brandname { font-size: 15px; font-weight: 700; color: var(--text); }
.topbar nav { display: flex; gap: 18px; }
.topbar nav a { font-size: 13px; font-weight: 500; color: var(--text-secondary); text-decoration: none; padding-bottom: 2px; }
.topbar nav a:hover { color: var(--text-accent); }
.topbar nav a.active { color: var(--text-accent); border-bottom: 2px solid var(--fill-accent); }

.container { width: 94%; max-width: 1600px; margin: 0 auto; padding: 24px 0 60px; }

/* ── Page header (breadcrumb + title) ── */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; padding: 4px 4px 12px; gap: 16px; }
.crumb { font-size: 12px; color: var(--text-secondary); text-decoration: none; display: block; }
.crumb:hover { color: var(--text-accent); }
.page-title { font-size: 26px; font-weight: 700; letter-spacing: -0.6px; margin-top: 4px; color: var(--text); }
.page-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

/* ── Metric cards ── */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 18px; }
.metric { position: relative; overflow: hidden; background: var(--surface-1); border: var(--bubble-border-width) solid var(--bubble-border-color); border-radius: var(--radius); box-shadow: var(--bubble-shadow); padding: 16px; }
.dark .metric {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.metric::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: var(--gradient-primary);
}
.metric-label { font-size: 12px; font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; }
.metric-value { font-size: 24px; font-weight: 700; color: var(--text); }
.metric-value.danger { color: var(--text-danger); }
.metric-sub { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

/* ── Router cards ── */
.router-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }

.router-card {
    background: var(--surface-2); border: var(--bubble-border-width) solid var(--bubble-border-color); border-radius: var(--radius);
    box-shadow: var(--bubble-shadow);
    padding: 1rem 1.25rem; text-decoration: none; color: inherit; display: flex; flex-direction: column;
    min-height: 240px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dark .router-card {
    background:
        linear-gradient(var(--surface-2), var(--surface-2)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.router-card:hover {
    border-color: var(--border-accent);
    box-shadow: var(--bubble-shadow-hover);
}
.router-card.is-offline { border-color: var(--border-danger); }
.dark .router-card.is-offline {
    background:
        linear-gradient(var(--surface-2), var(--surface-2)) padding-box,
        linear-gradient(135deg, #F09595, #E24B4A, #F09595) border-box;
}
.router-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.router-card-name { font-size: 15px; font-weight: 700; color: var(--text); }
.router-card table { width: 100%; font-size: 13px; }
.router-card table td { padding: 3px 0; }
.router-card table td:first-child { color: var(--text-secondary); }
.router-card table td:last-child { text-align: right; }
.router-card table td.danger { color: var(--text-danger); }
.router-card table td.warn { color: var(--text-warning); }
.router-open { font-size: 12px; font-weight: 600; color: var(--text-accent); margin-top: auto; padding-top: 10px; }

/* ── Router identity block (model, serial, firmware, LAN IP) ── */
.router-identity {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-light);
    font-size: 12px;
    color: var(--text-secondary);
}
.router-identity-row { display: flex; align-items: center; gap: 6px; }
.router-identity-row svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--text-muted); }
.router-identity-row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Flashing online/offline status LED ── */
.status-led {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}
.status-led.online {
    background: #16A34A;
    animation: led-pulse 2s infinite;
}
.status-led.offline { background: var(--text-danger); }
.status-led.unknown { background: var(--text-muted); }

@keyframes led-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(22,163,74,0.55); }
    70%  { box-shadow: 0 0 0 6px rgba(22,163,74,0); }
    100% { box-shadow: 0 0 0 0 rgba(22,163,74,0); }
}
@media (prefers-reduced-motion: reduce) {
    .status-led.online { animation: none; }
}

/* ── Pills / badges ── */
.pill { font-size: 10px; font-weight: 600; padding: 3px 10px; border-radius: var(--radius-pill); white-space: nowrap; display: inline-block; }
.pill-success { background: var(--bg-success); color: var(--text-success); }
.pill-danger  { background: var(--bg-danger);  color: var(--text-danger); }
.pill-warning { background: var(--bg-warning); color: var(--text-warning); }
.pill-muted   { background: var(--surface-muted); color: var(--text-secondary); }
.pill-accent  { background: var(--bg-selected); color: var(--text-accent); }
.pill-sm { font-size: 10px; padding: 2px 8px; }

/* ── Tabs ── */
.tabs { display: flex; gap: 18px; border-bottom: 1px solid var(--border); margin-bottom: 16px; padding: 0 4px; }
.tabs a { font-size: 13px; font-weight: 500; color: var(--text-secondary); text-decoration: none; padding-bottom: 8px; }
.tabs a:hover { color: var(--text-accent); }
.tabs a.active { color: var(--text-accent); border-bottom: 2px solid var(--fill-accent); }

/* ── Section headers ── */
.section-head { display: flex; align-items: center; justify-content: space-between; margin: 0 0 10px; gap: 12px; }
.section-label { font-size: 16px; font-weight: 700; color: var(--text); }
.section-divider { border: none; border-top: 1px solid var(--border); margin: 24px 0; }
.section-note { font-size: 12px; color: var(--text-muted); margin: 0 0 10px; }

/* ── List cards (packages, vouchers, generic rows) — each item is now
   its own independent bubble, not a stitched row in one shared box ── */
.list { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; margin-bottom: 18px; }
.list-vouchers { grid-template-columns: 1fr; }
.list-single { grid-template-columns: 1fr; }

/* ── External-content toggle (foreign packages, unpackaged profiles,
   unrecognized vouchers) - hidden by default, but never silently, since
   the toggle itself always shows how many items are behind it. A
   compact inline control (switch + label), not a full-width bordered
   button - it's a visibility toggle, not an action to press. */
.external-toggle {
    display: inline-flex; align-items: center; gap: 8px;
    margin-bottom: 12px;
    cursor: pointer; user-select: none; font-size: 13px; color: var(--text-secondary);
    transition: color 0.15s ease;
}
.external-toggle:hover { color: var(--text); }
.external-toggle-switch {
    width: 34px; height: 20px; border-radius: 10px; background: var(--border-medium);
    position: relative; flex-shrink: 0; transition: background 0.15s ease;
}
.external-toggle-switch::after {
    content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
    border-radius: 50%; background: var(--surface-1); transition: transform 0.15s ease;
}
.external-toggle.open .external-toggle-switch { background: var(--fill-accent); }
.external-toggle.open .external-toggle-switch::after { transform: translateX(14px); }
.external-content { display: none; }
.external-content.open { display: block; }

/* ── Pagination ── */
.pagination {
    display: flex; align-items: center; justify-content: center; gap: 16px;
    padding: 16px 0; margin-top: 8px;
}
.pagination .btn-sm.disabled { opacity: 0.4; pointer-events: none; }
.pagination-info { font-size: 13px; color: var(--text-secondary); }
.pagination-total { color: var(--text-muted); font-size: 12px; }

/* ── Real data table (report drill-down pages, and now every list) ── */
.data-table { width: 100%; border-collapse: collapse; background: var(--surface-1); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.data-table th {
    text-align: left; font-size: 10px; font-weight: 700; color: #52657A;
    text-transform: uppercase; letter-spacing: 0.02em; height: 34px; padding: 0 16px;
    background: var(--bg-table-head); border-bottom: 1px solid var(--border);
}
.data-table td { height: 42px; padding: 0 16px; font-size: 12px; color: #1E293B; border-bottom: 1px solid var(--border-light); }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr:hover td { background: #F8FBFE; }
.data-table td.code { font-family: var(--font-mono); font-weight: 600; }
.data-table td.num, .data-table th.num { text-align: right; }

/* Sortable column headers - one consistent look for the clickable
   affordance and the arrow indicator, shared by every list that sorts
   client-side via bb6xInitClientSort(). */
.data-table th[data-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table th[data-sort]:hover { color: var(--text-accent); }
.data-table th[data-sort]:focus-visible {
    outline: 2px solid var(--text-accent);
    outline-offset: -2px;
}
.data-table .sort-arrow { display: inline-block; margin-left: 4px; font-size: 9px; color: var(--text-accent); }

/* First-column checkbox and last-column actions - narrow, never
   wrapping, so the real content columns keep the rest of the width. */
.data-table th.checkbox-col, .data-table td.checkbox-col { width: 36px; padding: 0 0 0 16px; }
.data-table td.checkbox-col input[type="checkbox"],
.data-table th.checkbox-col input[type="checkbox"] { width: auto; margin: 0; }
.data-table th.actions-col, .data-table td.actions-col { text-align: right; white-space: nowrap; }
.data-table tr.row-selected td { background: var(--bg-selected); }
.data-table tr.clickable-row { cursor: pointer; }
.data-table tr.clickable-row:hover td { background: var(--bg-hover); }

/* Dashboard router list specifically - tighter, denser columns than the
   default data-table padding, with every column except Name centered
   under its heading (Name stays left-aligned since it's the row's
   primary identifier, not a value to scan down a column). Scoped to
   this one table's id rather than changing .data-table globally, so
   packages/vouchers/users/etc. keep their existing spacing. */
#routerListTable th, #routerListTable td { padding: 0 10px; white-space: nowrap; }
#routerListTable th:not(:nth-child(2)), #routerListTable td:not(:nth-child(2)) { text-align: center; }
#routerListTable th.num, #routerListTable td.num { text-align: center; }

/* Bulk-action toolbar - was previously hand-styled inline, differently,
   on every page that had one. One real definition now: a count on the
   left, action buttons on the right, disabled until something is
   checked. */
.bulk-toolbar {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px; margin-bottom: 12px;
    background: var(--surface-muted); border: 1px solid var(--border-light); border-radius: var(--radius-input);
}
.bulk-toolbar-count { font-size: 13px; font-weight: 600; color: var(--text); margin-right: auto; }

/* Icon-only action buttons (edit/remove/delete/enable/disable) - used
   across every list's Actions column. 36px touch target meets the
   minimum recommended size for a tappable control, even though the
   icon itself is drawn smaller inside it. The tooltip is a real,
   separately-built CSS element (not the native title attribute, which
   would show its own browser tooltip on top of this one) so it can be
   styled consistently with the rest of the UI; aria-label carries the
   same text to screen readers, which don't reliably announce a
   CSS-only tooltip. Appears on :hover AND :focus-visible, so a
   keyboard user tabbing through the row gets the same description a
   mouse user would. */
.icon-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: var(--surface-1);
    border: 1px solid var(--border);
    border-radius: var(--radius-input);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.icon-btn svg { width: 15px; height: 15px; fill: currentColor; }
.icon-btn:hover, .icon-btn:focus-visible { background: var(--bg-hover); color: var(--text-accent); border-color: var(--text-accent); outline: none; }
.icon-btn.danger { color: var(--text-danger); }
.icon-btn.danger:hover, .icon-btn.danger:focus-visible { background: var(--danger-bg, #fdecec); border-color: var(--text-danger); }
.icon-btn.primary { border-color: var(--border-accent); color: var(--text-accent); }
.icon-btn.primary:hover, .icon-btn.primary:focus-visible { background: var(--bg-selected); }
.icon-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.icon-btn:disabled:hover { background: var(--surface-1); color: var(--text-secondary); border-color: var(--border); }

.icon-btn::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--text);
    color: var(--surface-1);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    padding: 4px 8px;
    border-radius: 5px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.12s ease 0.15s;
    z-index: 20;
}
.icon-btn:hover::after, .icon-btn:focus-visible::after { opacity: 1; }

.icon-btn-group { display: inline-flex; gap: 6px; align-items: center; }

.list-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    background: var(--surface-1); border: var(--bubble-border-width) solid var(--bubble-border-color); border-radius: var(--radius);
    box-shadow: var(--bubble-shadow);
    padding: 14px 16px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dark .list-row {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.list.muted .list-row { background: var(--surface-muted); }
.dark .list.muted .list-row {
    background:
        linear-gradient(var(--surface-muted), var(--surface-muted)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
}
.list-row:hover { border-color: var(--border-accent); box-shadow: var(--bubble-shadow-hover); }
.list-row-title { font-size: 14px; font-weight: 600; margin: 0; color: var(--text); }
.list-row-meta { font-size: 12px; color: var(--text-secondary); margin: 3px 0 0; }
.list-row-actions { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
.list-empty { padding: 16px; font-size: 13px; color: var(--text-muted); grid-column: 1 / -1; }

/* Stacked row variant, for vouchers (code above, meta below, actions under) */
.vrow {
    background: var(--surface-1); border: var(--bubble-border-width) solid var(--bubble-border-color); border-radius: var(--radius);
    box-shadow: var(--bubble-shadow);
    padding: 14px 16px; cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dark .vrow {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.vrow:hover { border-color: var(--border-accent); box-shadow: var(--bubble-shadow-hover); }
.vrow-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
.vrow-code { font-size: 14px; font-weight: 600; margin: 0; font-family: var(--font-mono); letter-spacing: 0.5px; color: var(--text); }
.vrow-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.vrow-meta { font-size: 12px; color: var(--text-secondary); margin: 0 0 8px; }
.vrow-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Action buttons sit inside a clickable card - stop clicks on them from
   also opening the in-depth modal underneath */
.vrow-actions, .vrow-actions * { cursor: default; }

/* ── Voucher in-depth modal ── */
.voucher-modal-overlay {
    display: none;
    position: fixed; inset: 0; background: rgba(7,17,32,0.5);
    z-index: 100; align-items: center; justify-content: center; padding: 20px;
}
.voucher-modal-overlay.open { display: flex; }
.voucher-modal {
    background: var(--surface-1); border-radius: var(--radius-modal); border: var(--bubble-border-width) solid var(--bubble-border-color);
    box-shadow: var(--shadow-modal);
    width: 100%; max-width: 420px; max-height: 85vh; overflow-y: auto;
    padding: 20px 22px;
}
.dark .voucher-modal {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.voucher-modal-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 8px; }
.voucher-modal-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 11px 0; border-bottom: 1px solid var(--border-light); font-size: 13px;
}
.voucher-modal-row:last-of-type { border-bottom: none; }
.voucher-modal-row .label { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); }
.voucher-modal-row .label svg { width: 15px; height: 15px; flex-shrink: 0; }
.voucher-modal-row .value { font-weight: 600; text-align: right; color: var(--text); }
.wizard-review-input {
    font-weight: 600; text-align: right; color: var(--text);
    background: var(--input-bg, rgba(0,0,0,0.02)); border: 1px solid var(--input-border, var(--border));
    border-radius: 6px; padding: 4px 8px; width: 60%; font-family: inherit; font-size: inherit;
    transition: border-color 0.15s, background 0.15s;
}
.wizard-review-input:hover { border-color: var(--blue1, #0094ff); }
.wizard-review-input:focus {
    outline: none; border-color: var(--blue1, #0094ff);
    background: var(--input-focus-bg, rgba(0,148,255,0.06));
}
.voucher-modal-close {
    width: 100%; margin-top: 16px; padding: 10px; border-radius: var(--radius-input); border: 1px solid var(--border);
    background: none; color: var(--text-danger); font-weight: 600; cursor: pointer; font-size: 14px;
}
.voucher-modal-close:hover { background: var(--bg-danger); }

/* ── Form modal (package add/edit) - deliberately wider and grows to fit
   its content rather than scrolling internally, unlike the compact,
   read-only voucher modal above. */
.form-modal-overlay {
    display: none;
    position: fixed; inset: 0; background: rgba(7,17,32,0.5);
    z-index: 100; align-items: center; justify-content: center; padding: 20px;
}
.form-modal-overlay.open { display: flex; }
.form-modal {
    background: var(--surface-1); border-radius: var(--radius-modal); border: var(--bubble-border-width) solid var(--bubble-border-color);
    box-shadow: var(--shadow-modal);
    width: 100%; max-width: 640px;
    padding: 22px 26px;
}
.dark .form-modal {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.form-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }

/* Router scope checklist inside the global package modal - 3 columns so
   a long router list doesn't turn into one tall, awkward single-file
   scroll. Only the router grid itself scrolls once it gets tall, not the
   whole modal - the "only applies to..." note above it stays put and
   visible the whole time, rather than scrolling away with the list. */
.global-scope-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px 12px;
    max-height: 240px;
    overflow-y: auto;
    padding-right: 4px;
}
.global-scope-grid label {
    min-width: 0; /* required for the ellipsis below to actually apply inside a grid cell */
}
.global-scope-grid label span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
@media (max-width: 640px) {
    .global-scope-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── Buttons ── */
.btn {
    display: inline-flex; align-items: center; justify-content: center; height: 34px;
    background: var(--gradient-primary);
    color: #fff !important; border: none; border-radius: var(--radius-input); padding: 0 18px;
    font-size: 12px; font-weight: 600; cursor: pointer; text-decoration: none !important;
    box-shadow: 0 4px 10px rgba(11,132,243,0.18);
    transition: transform 120ms ease, box-shadow 120ms ease, background 120ms ease;
}
.btn:hover { background: var(--gradient-primary-hover); box-shadow: 0 5px 14px rgba(11,132,243,0.24); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-sm {
    font-size: 12px; padding: 4px 12px; border-radius: var(--radius-input);
    background: var(--surface-1); border: var(--bubble-border-width) solid var(--bubble-border-color); color: var(--text-secondary);
    cursor: pointer; text-decoration: none; display: inline-block; font-weight: 600;
    box-shadow: var(--bubble-shadow);
    transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.dark .btn-sm {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.btn-sm:hover { background: var(--bg-hover); border-color: var(--border-medium); color: var(--text-accent); }
.btn-sm:disabled {
    cursor: default; opacity: 1;
    color: var(--text-accent); font-weight: 700;
    border-color: var(--border-accent);
    background: var(--surface-1);
}
.btn-sm:disabled:hover { background: var(--surface-1); border-color: var(--border-accent); color: var(--text-accent); }
.btn-sm.danger { color: var(--text-danger); }
.btn-sm.danger:hover { border-color: var(--border-danger); background: var(--bg-danger); }

/* The generic .btn-sm:disabled above means "this is the active mode"
   (e.g. Tiles/List toggle) - genuinely different from "unavailable right
   now" for bulk-action buttons like Enable/Disable/Delete, which need to
   actually look greyed-out and inert until something's selected. */
.bulk-toolbar .btn-sm:disabled,
.bulk-toolbar .btn-sm.danger:disabled {
    cursor: not-allowed;
    opacity: 0.4;
    color: var(--text-secondary);
    font-weight: 500;
    border-color: var(--bubble-border-color);
    background: transparent;
}
.bulk-toolbar .btn-sm:disabled:hover,
.bulk-toolbar .btn-sm.danger:disabled:hover {
    background: transparent;
    border-color: var(--bubble-border-color);
    color: var(--text-secondary);
}
.btn-sm.primary { border-color: var(--border-accent); color: var(--text-accent); font-weight: 600; }

.link { color: var(--text-accent); text-decoration: none; font-size: 13px; font-weight: 600; }
.link:hover { text-decoration: underline; }

/* ── Filter bar ── */
.filters { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; margin-bottom: 20px; }
.filters-label { font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.02em; margin: 0 0 10px; }
.filters-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.filters input, .filters select {
    font-size: 12px; height: 34px; padding: 0 10px;
    border: 1px solid #CFE0EF; border-radius: var(--radius-input); background: #fff; color: var(--text-secondary);
    transition: border-color 150ms ease, box-shadow 150ms ease;
}
.filters input:hover, .filters select:hover { border-color: #AFC9DD; }
.filters input:focus, .filters select:focus { outline: none; border-color: var(--border-accent); box-shadow: 0 0 0 3px rgba(11,132,243,0.10); }

/* ── Funnel ── */
.funnel { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 8px; }
.funnel-step {
    position: relative; overflow: hidden;
    background: var(--surface-1); border: var(--bubble-border-width) solid var(--bubble-border-color); border-radius: var(--radius);
    box-shadow: var(--bubble-shadow);
    padding: 16px; text-align: center;
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.dark .funnel-step {
    background:
        linear-gradient(var(--surface-1), var(--surface-1)) padding-box,
        linear-gradient(135deg, var(--metal-1), var(--metal-2), var(--metal-1)) border-box;
    border: var(--bubble-border-width) solid transparent;
}
.funnel-step::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: var(--gradient-primary);
}
.funnel-label { font-size: 12px; font-weight: 500; color: var(--text-secondary); margin: 0 0 6px; }
.funnel-value { font-size: 22px; font-weight: 700; margin: 0; color: var(--text); }
.funnel-value.mismatch { color: var(--text-danger); }
.funnel-pct { font-size: 11px; color: var(--text-muted); margin: 2px 0 0; }
.clickable-stat { cursor: pointer; text-decoration: none; color: inherit; display: block; }
.clickable-stat:hover { background: var(--bg-hover); }
.funnel-step.clickable-stat:hover, .metric.clickable-stat:hover { border-color: var(--border-accent); box-shadow: var(--shadow-md); }

/* ── Forms ── */
.form label { display: block; margin-top: 16px; font-weight: 600; font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.02em; }
.form input, .form select { width: 100%; height: 34px; padding: 0 10px; margin-top: 6px; font-size: 12px; border: 1px solid #CFE0EF; border-radius: var(--radius-input); background: #fff; color: var(--text-secondary); transition: border-color 150ms ease, box-shadow 150ms ease; }
.form input:hover, .form select:hover { border-color: #AFC9DD; }
.form input:focus, .form select:focus { outline: none; border-color: var(--border-accent); box-shadow: 0 0 0 3px rgba(11,132,243,0.10); }
.form input:disabled { background: var(--surface-muted); color: var(--text-muted); cursor: not-allowed; }
.form .note { color: var(--text-muted); font-size: 12px; margin-top: 4px; }
.form button { margin-top: 22px; }

/* ── Alerts ── */
.alert { padding: 12px 14px; border-radius: var(--radius-input); font-size: 13px; margin-bottom: 16px; }
.alert-error { background: var(--bg-danger); border: 1px solid #f3c4be; color: var(--text-danger); }
.alert-warn  { background: var(--bg-warning); border: 1px solid #f0d999; color: var(--text-warning); }
.alert-info  { background: var(--bg-info); border: 1px solid #b8dfff; color: var(--text-accent); }

/* ── Stat sections row (revenue by package/router/agent, data usage) ──
   Each section (its label + its own table) flows as one unit. The row
   wraps them side by side whenever there's room, same as text wrapping
   words - narrow tables sit next to each other on a wide screen, and
   drop to stacked, full-width-capped columns as the window narrows. */
.stat-quadrants { display: grid; grid-template-columns: 1fr 1fr; gap: 20px 24px; margin-top: 28px; }
.stat-quadrant .section-label { margin: 0 0 8px; }
.stat-quadrant .data-table { min-height: 118px; }
.stat-quadrant .data-table tr.clickable-row { cursor: pointer; }
.stat-quadrant .quadrant-empty-row td { text-align: center; }
@media (max-width: 640px) {
    .stat-quadrants { grid-template-columns: 1fr; }
}

code { background: var(--surface-muted); padding: 2px 6px; border-radius: 4px; font-size: 12px; font-family: var(--font-mono); }

/* ── Scrollbars ── */
::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: var(--bg-hover); }
::-webkit-scrollbar-thumb { background: #9ED9F8; border-radius: var(--radius-pill); }
::-webkit-scrollbar-thumb:hover { background: #5BC1F0; }
* { scrollbar-width: thin; scrollbar-color: #9ED9F8 var(--bg-hover); }

@media (max-width: 640px) {
    .topbar { flex-wrap: wrap; gap: 10px; padding: 10px 14px; }
    .topbar-left { flex-wrap: wrap; row-gap: 6px; }
    .topbar .btn { width: 100%; text-align: center; }

    .tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 2px;
    }
    .tabs a { flex-shrink: 0; }

    .page-head { flex-direction: column; align-items: flex-start; gap: 8px; }

    .metrics { grid-template-columns: repeat(2, 1fr); }
    .funnel { grid-template-columns: repeat(2, 1fr); }
    .funnel-step:nth-child(2) { border-right: none; }

    .list-row { flex-direction: column; align-items: flex-start; }
    .list-row-actions { width: 100%; }

    .vrow-head { flex-wrap: wrap; gap: 6px; }
    .vrow-actions { flex-direction: column; align-items: stretch; }
    .vrow-actions form { width: 100%; }
    .vrow-actions .btn-sm { width: 100%; text-align: center; padding: 10px; }

    .filters-row { flex-direction: column; align-items: stretch; }
    .filters-row input, .filters-row select, .filters-row .btn, .filters-row .link {
        width: 100%;
        text-align: center;
    }

    .router-card table { font-size: 13px; }
}


/* ============================================================
   DARK THEME — opt-in via .dark on <html>. Light stays the
   default (unchanged above) so nothing looks different for
   anyone until they deliberately toggle it. Dark navy, not
   black, per the design spec.
   ============================================================ */
.dark {
    --bg:              #071120;
    --bg-sidebar:      #091522;
    --surface-1:       #101E2D;
    --surface-2:       #101E2D;
    --surface-muted:   #132235;
    --bg-hover:        #172B40;

    /* Full metallic bevel for dark mode - tested against plain solid
       borders and a lighter bevel; this combination (brighter metal
       ramp, real inset highlight/shadow pairing, stronger lift) is the
       one that actually reads as "clearly above the background". */
    --metal-1: #94A3B8;
    --metal-2: #E8EEF5;
    --bubble-border-width: 2px;
    --bubble-shadow:
        0 4px 14px rgba(0,0,0,0.45),
        inset 0 1.5px 0 rgba(255,255,255,0.18),
        inset 0 -1.5px 0 rgba(0,0,0,0.4);
    --bubble-shadow-hover:
        0 6px 18px rgba(0,0,0,0.55),
        inset 0 1.5px 0 rgba(255,255,255,0.22),
        inset 0 -1.5px 0 rgba(0,0,0,0.45);
    --bg-selected:     #0C304D;
    --bg-table-head:   #102A40;

    --text:            #F8FAFC;
    --text-secondary:  #CBD5E1;
    --text-muted:      #94A3B8;
    --text-light:      #64748B;
    --text-accent:     #38BDF8;

    --border:          #263D53;
    --border-light:    #1E3348;
    --border-medium:   #35516A;
    --border-accent:   #0B84F3;
    --border-danger:   rgba(255,110,100,0.45);

    --fill-accent:     #0878EA;
    --cyan-accent:     #00A9E8;

    --text-success:    #4ade80;
    --bg-success:      rgba(74,222,128,0.12);
    --text-danger:     #ff8a80;
    --bg-danger:       rgba(255,80,80,0.14);
    --text-warning:    #fbbf24;
    --bg-warning:      rgba(251,191,36,0.12);
    --text-info:       #38BDF8;
    --bg-info:         rgba(56,189,248,0.12);
}

.dark body { background: var(--bg); }

.dark .filters input, .dark .filters select,
.dark .form input, .dark .form select { background: var(--surface-muted); color: var(--text-secondary); border-color: var(--border-medium); }
.dark .form input:disabled { background: rgba(255,255,255,0.05); }
.dark code { background: rgba(255,255,255,0.08); }
.dark .alert-error { border-color: rgba(255,110,100,0.35); }
.dark .alert-warn   { border-color: rgba(251,191,36,0.35); }
.dark .alert-info   { background: rgba(56,189,248,0.10); border-color: rgba(56,189,248,0.30); }
.dark .data-table th { color: var(--text-muted); }
.dark .data-table td { color: var(--text); }
.dark .data-table tr:hover td { background: var(--bg-hover); }

/* ── Theme toggle — small pill in the topbar, present on every page ── */
.theme-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--surface-muted);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.theme-toggle:hover { border-color: var(--border-accent); color: var(--text-accent); }
.theme-toggle svg { width: 14px; height: 14px; }
.theme-toggle .i-moon { display: none; }
.dark .theme-toggle .i-sun  { display: none; }
.dark .theme-toggle .i-moon { display: block; }

/* ============================================================
   SIDEBAR NAVIGATION — replaces the old horizontal topbar.
   Manual expand/collapse only, state remembered via localStorage,
   same pattern as the theme toggle. Uses the same theme variables
   above, so it's already correct in both light and dark.
   ============================================================ */

.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: 200px;
    min-width: 200px;
    flex-shrink: 0;
    background: var(--bg-sidebar);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    padding: 16px 12px;
    transition: width 0.2s ease;
}

.sidebar.collapsed { width: 64px; min-width: 64px; }

.sidebar-brand {
    display: flex;
    align-items: center;
    padding: 8px 8px 20px;
    overflow: hidden;
}

.sidebar-brand-logo-full { width: 100%; height: auto; max-width: 176px; flex-shrink: 0; }
.sidebar-brand-logo-mark { display: none; height: 26px; width: auto; flex-shrink: 0; }

.sidebar.collapsed .sidebar-brand-logo-full { display: none; }
.sidebar.collapsed .sidebar-brand-logo-mark { display: block; }

.sidebar-brand-chip { display: flex; align-items: center; width: 100%; text-decoration: none; border-radius: var(--radius-input); transition: opacity 0.15s ease; }
.sidebar-brand-chip:hover { opacity: 0.8; }
/* The wordmark's dark navy text has low contrast against the dark
   sidebar - a soft light glow behind it helps it read clearly without
   resorting to an opaque background chip, which would defeat the
   logo's genuine transparency. */
.dark .sidebar-brand-logo-full,
.dark .sidebar-brand-logo-mark { filter: drop-shadow(0 0 6px rgba(255,255,255,0.55)); }

.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
}

.sidebar-item {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 34px;
    padding: 0 12px;
    border-radius: 7px;
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    cursor: pointer;
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    font-family: inherit;
    transition: background 150ms ease, color 150ms ease;
}

.sidebar-item:hover { background: var(--bg-table-head); color: var(--text-accent); }
.sidebar-item.active { background: var(--bg-selected); color: var(--text); border: 1px solid #8FD5FF; font-weight: 600; }
.dark .sidebar-item.active { border-color: var(--border-accent); }

.sidebar-item svg {
    width: 15px;
    height: 15px;
    stroke-width: 1.8;
    flex-shrink: 0;
}

.sidebar.collapsed .sidebar-item span { display: none; }
.sidebar.collapsed .sidebar-item { justify-content: center; }

.sidebar-toggle-btn {
    margin-top: 8px;
    align-self: flex-end;
}
.sidebar.collapsed .sidebar-toggle-btn { align-self: center; }
.sidebar-toggle-btn svg { transition: transform 0.2s ease; }
.sidebar.collapsed .sidebar-toggle-btn svg { transform: rotate(180deg); }

.app-main {
    flex: 1;
    min-width: 0;
    overflow-x: auto;
}

.mobile-menu-toggle { display: none; }
.sidebar-backdrop { display: none; }
.sidebar-toggle-label-mobile { display: none; }

/* Wraps a wide table so IT scrolls horizontally on a narrow screen,
   rather than the whole page (stat cards, headers, etc. included)
   dragging sideways along with it. -webkit-overflow-scrolling gives a
   real momentum-scroll feel on iOS rather than a stiff, step-by-step
   drag. */
.table-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 8px;
}
.table-responsive .data-table { border-radius: 0; }

@media (max-width: 640px) {
    .data-table th, .data-table td { padding: 0 10px; font-size: 11.5px; }
    .data-table th { height: 30px; }
    .data-table td { height: 38px; }
    .bulk-toolbar { flex-wrap: wrap; row-gap: 8px; }
    .bulk-toolbar-count { flex-basis: 100%; margin-right: 0; }
    .pagination { flex-wrap: wrap; justify-content: center; row-gap: 8px; }

    /* Secondary columns (last poll, data usage, scripts, etc.) drop out
       entirely below 640px rather than just being scrollable - "fits
       the screen" means not needing to scroll sideways for the columns
       that matter most (name, status, revenue, actions); the rest is
       still one tap away via the existing Columns toggle on desktop,
       or simply not relevant to a quick mobile check. */
    .data-table .mobile-hide { display: none !important; }
}

@media (max-width: 640px) {
    .sidebar {
        position: fixed;
        z-index: 30;
        height: 100vh;
        width: 240px;
        min-width: 240px;
        transform: translateX(-100%);
        transition: transform 0.25s ease;
    }
    .sidebar.mobile-open {
        transform: translateX(0);
        box-shadow: 4px 0 24px rgba(0,0,0,0.25);
    }

    /* Icon-only "collapsed" mode is a desktop space-saving concept that
       doesn't apply to a drawer that's only ever open temporarily on top
       of the page - full labels stay readable regardless of whatever
       collapsed state was saved from a previous desktop session. */
    .sidebar.collapsed { width: 240px; min-width: 240px; }
    .sidebar.collapsed .sidebar-item span { display: inline; }
    .sidebar.collapsed .sidebar-item { justify-content: flex-start; }
    .sidebar.collapsed .sidebar-brand-logo-full { display: block; }
    .sidebar.collapsed .sidebar-brand-logo-mark { display: none; }
    .sidebar.collapsed .sidebar-toggle-btn svg { transform: none; }

    /* The existing "Collapse" control becomes "Close" at this width -
       same button, same position, repurposed rather than duplicated.
       !important here because .sidebar.collapsed .sidebar-item span
       above is more specific and would otherwise win when a user's
       saved desktop "collapsed" state happens to also be set, showing
       both labels at once. */
    .sidebar-toggle-label-desktop { display: none !important; }
    .sidebar-toggle-label-mobile { display: inline !important; }
    .sidebar-toggle-btn svg { transform: rotate(180deg); }

    .mobile-menu-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        top: 14px;
        left: 14px;
        z-index: 15;
        width: 40px;
        height: 40px;
        border-radius: var(--radius-input);
        background: var(--surface-1);
        border: 1px solid var(--border);
        box-shadow: var(--shadow-md);
        color: var(--text);
    }

    .sidebar-backdrop.mobile-open {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(15, 23, 42, 0.45);
        z-index: 25;
    }

    /* The hamburger button sits on top of page content (z-index 15) -
       page content itself needs room below it so nothing important
       (like a page title starting at the very top edge) sits underneath
       an opaque button. */
    .app-main { padding-top: 56px; }
}

/* ── Dashboard router list view - each row its own separated, rounded
   bubble rather than a dense bordered table, matching the card-like
   language used everywhere else in this admin (users, packages). */
.router-list {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0 8px;
    font-size: 13px;
}
.router-list thead th {
    text-align: left;
    padding: 0 14px 6px;
    font-weight: 500;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-secondary);
    cursor: pointer;
    white-space: nowrap;
}
.router-list th.num-col, .router-list td.num-col { text-align: right; }
.router-list tbody tr.router-list-row {
    background: var(--surface-1);
    cursor: pointer;
    transition: box-shadow 0.15s;
}
.router-list tbody tr.router-list-row:hover { box-shadow: var(--bubble-shadow); }
.router-list tbody td {
    padding: 12px 14px;
    border-top: var(--bubble-border-width) solid var(--bubble-border-color);
    border-bottom: var(--bubble-border-width) solid var(--bubble-border-color);
    white-space: nowrap;
}
.data-table td.strong { font-weight: 700; }
.data-table td.muted { color: var(--text-secondary); }
.router-list tbody td.list-left-cap {
    border-left: var(--bubble-border-width) solid var(--bubble-border-color);
    border-top-left-radius: var(--radius);
    border-bottom-left-radius: var(--radius);
}
.router-list tbody td.list-right-cap {
    border-right: var(--bubble-border-width) solid var(--bubble-border-color);
    border-top-right-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
}
