/* ============================================================================
   22-GLASS. shared design system
   ----------------------------------------------------------------------------
   Deep space glass aesthetic for CONNECTED AI.
   Dark midnight base with frosted glass cards, teal/violet accents,
   Montserrat everywhere. including the small-caps "mono" labels
   (eyebrows, pills, table heads). JetBrains Mono is reserved for true
   code rendering via the separate --font-code token below; pages should
   not need a per-page Montserrat override.
   ============================================================================ */

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

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Reserve the scrollbar gutter so centered containers (e.g. admin
   .content at max-width: 1100px) don't shift horizontally when a
   tab's content goes from short (no scrollbar) to tall (scrollbar
   appears). Without this the viewport narrows by ~15px when the
   scrollbar materialises and everything re-centered 7px to the left
  . very obvious on the admin page when switching between Insights
   (short) and Query Logs (tall). */
html { scrollbar-gutter: stable; }

/* ─── Core Glass Tokens ──────────────────────────────────────────────────── */
:root {
  /* Background */
  --bg:              #0f0f1a;
  --glass:           rgba(255,255,255,.07);
  --glass-border:    rgba(255,255,255,.12);

  /* Text. --mute was #6a6a88. too faint against brand-tinted background
     meshes. Bumped ~20% lighter so secondary copy / empty states / hint
     text stay readable on both default-teal and brand-tinted dark backdrops. */
  --ink:             #f0f0f5;
  --ink2:            #b0b0c8;
  --mute:            #8585a8;

  /* Accent colours.
     --teal and --violet are the primary/secondary brand slots: JS overrides
     them with branding.primary_color / branding.accent_color when set, so
     buttons and gradients pick up tenant brand. The matching --*-rgb vars
     hold the same colour as RGB triplets so rgba(var(--*-rgb), .x) can be
     used inside the page-background mesh and any other tinted surface. */
  --teal:            #2dd4bf;
  --teal-glow:       rgba(45,212,191,.25);
  --teal-soft:       rgba(45,212,191,.15);
  --violet:          #7c3aed;
  --violet-soft:     rgba(124,58,237,.2);
  --accent-rgb:      45,212,191;     /* default teal RGB. used by mesh + accent UI */
  --accent2-rgb:     124,58,237;     /* default violet RGB */
  --teal-rgb:        45,212,191;     /* matches --teal hex; light theme overrides */
  --rose:            #e11d48;
  --rose-soft:       rgba(225,29,72,.15);

  /* Semantic */
  --ok:              #2dd4bf;
  --ok-soft:         rgba(45,212,191,.15);
  --warn:            #f59e0b;
  --warn-soft:       rgba(245,158,11,.15);
  --danger:          #e11d48;
  --danger-soft:     rgba(225,29,72,.15);
  --info:            #60a5fa;
  --info-soft:       rgba(96,165,250,.15);

  /* ── Legacy aliases. existing HTML keeps working ── */
  --nav:             rgba(15,15,26,.85);
  --surface:         rgba(255,255,255,.07);
  --surface2:        rgba(255,255,255,.04);
  --border:          rgba(255,255,255,.12);
  --text:            #f0f0f5;
  --text-dim:        #b0b0c8;
  --text-faint:      #6a6a88;
  --rule:            rgba(255,255,255,.08);
  --rule-strong:     rgba(255,255,255,.18);
  --rule-w:          1px;
  --paper:           #f0f0f5;

  /* Accent alias (tenant-overridable) */
  --accent:          #2dd4bf;
  --accent2:         #5eead4;
  --accent-soft:     rgba(45,212,191,.15);
  --accent-faint:    rgba(45,212,191,.08);
  --accent-grad:     linear-gradient(135deg, var(--teal), var(--violet));

  /* Typography
     ─ --font-mono is the editorial small-caps face used for eyebrows,
       pills, table heads, KPI labels, etc. It's Montserrat (NOT a true
       monospace) so the brand reads consistently across every page.
       Tabular-nums + slashed-zero are applied via font-variant-numeric
       on numeric cells when needed; Montserrat 600+ supports both.
     ─ --font-code is the actual monospace, reserved for rendered code
       (<pre>/<code> in chat, stack traces, error boxes, anywhere the
       reader expects fixed-width). Use this. never JetBrains Mono
       directly. so we have one place to retune the code face. */
  --font-display:    'Montserrat', ui-sans-serif, system-ui, sans-serif;
  --font-body:       'Montserrat', ui-sans-serif, system-ui, sans-serif;
  --font-mono:       'Montserrat', ui-sans-serif, system-ui, sans-serif;
  --font-code:       'JetBrains Mono', ui-monospace, 'SF Mono', Consolas, monospace;
  /* Short aliases for admin/users which use --display / --mono / --font */
  --display:         var(--font-display);
  --mono:            var(--font-mono);
  --font:            var(--font-body);

  /* Spacing / shape */
  --radius:          18px;
  --radius-lg:       24px;
  --radius-sm:       10px;

  /* Shadows */
  --shadow-1:        0 4px 24px rgba(0,0,0,.35);
  --shadow-2:        0 8px 48px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.06);

  /* Chart colour palette (glass-friendly) */
  --green:           #2dd4bf;
  --amber:           #f59e0b;
  --red:             #e11d48;
  --blue:            #60a5fa;
  --purple:          #7c3aed;

  /* Admin/users legacy semantic tokens */
  --sage:            #2dd4bf;
  --brass:           #f59e0b;
  --brick:           #e11d48;
  --ink-soft:        rgba(255,255,255,.05);
  --ink-deep:        #0f0f1a;
  --parchment:       rgba(255,255,255,.04);
  --cream:           #f0f0f5;
}

/* ─── Light theme override ──────────────────────────────────────────────── */
html.light {
  --bg: #f4f5fb;
  --glass: rgba(255,255,255,.6);
  --glass-strong: rgba(255,255,255,.82);
  --glass-border: rgba(15,15,40,.07);
  --ink: #15162b;
  --ink2: #4a4a6a;
  --mute: #8a8aa8;
  --teal: #0d9488;
  --teal-glow: rgba(var(--teal-rgb),.2);
  --teal-soft: rgba(var(--teal-rgb),.1);
  --violet: #7c3aed;
  --violet-soft: rgba(124,58,237,.15);
  --rose: #be123c;
  --rose-soft: rgba(190,18,60,.1);
  /* also override any aliased vars used in the CSS */
  --nav: rgba(255,255,255,.7);
  --surface: rgba(255,255,255,.6);
  --surface2: rgba(255,255,255,.5);
  --border: rgba(15,15,40,.08);
  --accent: #0d9488;
  --accent2: #14b8a6;
  --accent-soft: rgba(var(--teal-rgb),.12);
  --accent-faint: rgba(var(--teal-rgb),.06);
  --text: #15162b;
  --text-dim: #4a4a6a;
  --text-faint: #8a8aa8;
  --rule: rgba(15,15,40,.06);
  --rule-strong: rgba(15,15,40,.14);
  --ink-soft: rgba(15,15,40,.04);
  --ink-deep: #f4f5fb;
  --paper: #15162b;
  --parchment: rgba(15,15,40,.03);
  --cream: #15162b;
  /* Light-theme defaults for the page-background gradient mesh. JS overrides
     these with the tenant's brand RGB when branding.primary_color /
     branding.accent_color are set, so the mesh subtly picks up brand. */
  --accent-rgb:  167,139,250;   /* default lavender. used by light mesh */
  --accent2-rgb: 244,114,182;   /* default pink. used by light mesh */
  --teal-rgb:    13,148,136;    /* matches --teal hex; used by accent UI */
}

/* Hide dark gradient mesh; swap in light mesh */
html.light body::before { opacity: 0 !important; }
html.light body {
  background-image:
    radial-gradient(ellipse 700px 600px at 10% 10%, rgba(var(--accent-rgb),  .30), transparent),
    radial-gradient(ellipse 600px 500px at 85% 15%, rgba(var(--accent2-rgb), .22), transparent),
    radial-gradient(ellipse 500px 500px at 70% 80%, rgba(var(--accent-rgb),  .18), transparent),
    radial-gradient(ellipse 400px 350px at 20% 90%, rgba(var(--accent2-rgb), .16), transparent);
  background-attachment: fixed;
  color: var(--ink);
}
/* When a tenant brand is active, dial mesh opacities down ~40% so the
   colour wash stays subtle instead of dominating. Default unbranded look
   above is unchanged. */
html.light body.has-brand {
  background-image:
    radial-gradient(ellipse 700px 600px at 10% 10%, rgba(var(--accent-rgb),  .18), transparent),
    radial-gradient(ellipse 600px 500px at 85% 15%, rgba(var(--accent2-rgb), .13), transparent),
    radial-gradient(ellipse 500px 500px at 70% 80%, rgba(var(--accent-rgb),  .11), transparent),
    radial-gradient(ellipse 400px 350px at 20% 90%, rgba(var(--accent2-rgb), .10), transparent);
}
html.light ::selection { background: var(--teal); color: #fff; }

/* Topbar */
html.light .topbar { background: rgba(255,255,255,.7) !important; border-bottom: 1px solid rgba(15,15,40,.07) !important; }
html.light .topbar-logo { filter: none !important; opacity: 1 !important; }
html.light .topbar-sep { background: rgba(15,15,40,.12) !important; }
html.light .topbar-product { color: var(--ink2) !important; }
html.light .topbar-product em { color: var(--teal) !important; }
html.light .topbar-section { color: var(--mute) !important; }
html.light .topbar-navlink { color: var(--mute) !important; }
html.light .topbar-navlink:hover { color: var(--ink) !important; background: rgba(15,15,40,.05) !important; }
html.light .topbar-navlink.active { color: var(--teal) !important; }
html.light .topbar-navlink.active::after { background: var(--teal) !important; }

/* Icon / utility buttons in topbar */
html.light .theme-btn,
html.light .refresh-btn,
html.light .ds-icon-btn { background: rgba(255,255,255,.7) !important; border-color: rgba(15,15,40,.1) !important; color: var(--ink2) !important; }
html.light .theme-btn:hover,
html.light .refresh-btn:hover,
html.light .ds-icon-btn:hover { background: rgba(255,255,255,.9) !important; color: var(--ink) !important; border-color: var(--teal) !important; }

/* User chip + dropdown */
html.light .user-chip,
html.light .ds-chip { background: rgba(255,255,255,.7) !important; border-color: rgba(15,15,40,.1) !important; color: var(--ink2) !important; }
html.light .user-chip:hover,
html.light .ds-chip:hover { border-color: var(--teal) !important; color: var(--ink) !important; }
html.light .user-dropdown,
html.light .ds-chip-dropdown { background: rgba(255,255,255,.98) !important; border-color: rgba(15,15,40,.1) !important; box-shadow: 0 8px 48px rgba(15,15,40,.15) !important; }
html.light .dd-item,
html.light .user-dropdown-item,
html.light .ds-dd-item { color: var(--ink2) !important; }
html.light .dd-item:hover,
html.light .user-dropdown-item:hover,
html.light .ds-dd-item:hover { background: rgba(15,15,40,.05) !important; color: var(--ink) !important; }

/* Chat sidebar */
html.light .sidebar { background: rgba(255,255,255,.5) !important; border-right-color: rgba(15,15,40,.08) !important; }
html.light .sidebar-label { color: var(--mute) !important; }
html.light .sidebar-footer-item { color: var(--ink2) !important; }
html.light .sidebar-footer-item:hover { background: rgba(15,15,40,.05) !important; color: var(--ink) !important; }
html.light .new-chat-btn { background: rgba(var(--teal-rgb),.1) !important; color: var(--teal) !important; border-color: rgba(var(--teal-rgb),.25) !important; }
html.light .new-chat-btn:hover { background: rgba(var(--teal-rgb),.18) !important; border-color: rgba(var(--teal-rgb),.4) !important; }
html.light .history-item { color: var(--ink2) !important; }
html.light .history-item:hover { background: rgba(15,15,40,.04) !important; color: var(--ink) !important; }
html.light .history-item.active { background: rgba(var(--teal-rgb),.08) !important; color: var(--ink) !important; }

/* Messages / welcome */
html.light .welcome h1,
html.light .welcome-title { color: var(--ink) !important; }
html.light .welcome-sub,
html.light .welcome p { color: var(--ink2) !important; }
html.light .welcome-logo { filter: none !important; }
html.light .msg-user .bubble,
html.light .bubble.user { background: rgba(var(--teal-rgb),.1) !important; border-color: rgba(var(--teal-rgb),.25) !important; color: var(--ink) !important; }
html.light .msg-assistant .bubble,
html.light .bubble.assistant { background: rgba(255,255,255,.7) !important; border-color: rgba(15,15,40,.08) !important; color: var(--ink) !important; }

/* Input bar */
html.light .input-area { background: transparent !important; border-top-color: rgba(15,15,40,.08) !important; }
html.light .input-wrap { background: rgba(255,255,255,.8) !important; border-color: rgba(15,15,40,.1) !important; }
html.light textarea,
html.light input[type="text"],
html.light input[type="email"],
html.light input[type="password"],
html.light input[type="url"],
html.light input[type="number"],
html.light input[type="search"],
html.light select,
html.light .settings-input,
html.light .ds-input,
html.light .ds-select,
html.light .ds-textarea { background: rgba(255,255,255,.8) !important; border-color: rgba(15,15,40,.1) !important; color: var(--ink) !important; }
html.light textarea::placeholder,
html.light input::placeholder { color: var(--mute) !important; }

/* Glass cards / surfaces */
html.light .glass,
html.light .stat-card,
html.light .settings-card,
html.light .query-card,
html.light .answer-box,
html.light .prompt-box,
html.light .ds-card,
html.light .ds-card-flat,
html.light .ds-kpi,
html.light .ds-modal { background: rgba(255,255,255,.65) !important; border-color: rgba(15,15,40,.07) !important; color: var(--ink) !important; }

/* Admin tabs */
html.light .admin-tabs { background: rgba(255,255,255,.5) !important; border-color: rgba(15,15,40,.08) !important; }
html.light .admin-tab { color: var(--mute) !important; }
html.light .admin-tab.active { background: rgba(255,255,255,.9) !important; color: var(--teal) !important; }

/* ââ Login page ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
   The left decorative panel stays intentionally dark in both themes â itâs
   a fixed brand graphic. Only the right pane (login form + buttons) needs
   to flip light so contrast reads properly against a light body background. */
html.light .login-right {
  background: rgba(255,255,255,.7) !important;
  border-left: 1px solid rgba(15,15,40,.08) !important;
}
html.light .login-sub-label { color: var(--ink) !important; }
html.light .login-sub       { color: var(--ink2) !important; }
html.light .login-badge     { color: var(--mute) !important; }
html.light .form-group label { color: var(--mute) !important; }
html.light .form-group input {
  background: rgba(255,255,255,.95) !important;
  border: 1px solid rgba(15,15,40,.15) !important;
  color: var(--ink) !important;
}
html.light .form-group input::placeholder { color: var(--mute) !important; }
html.light .form-group input:focus {
  border-color: var(--teal) !important;
  box-shadow: 0 0 0 3px rgba(var(--teal-rgb),.18) !important;
}
html.light .login-btn {
  color: #fff !important;  /* contrast against the purple accent */
}
html.light .sso-btn {
  background: rgba(255,255,255,.7) !important;
  border: 1px solid rgba(15,15,40,.15) !important;
  color: var(--ink2) !important;
}
html.light .sso-btn:hover {
  background: rgba(var(--teal-rgb),.05) !important;
  border-color: var(--teal) !important;
  color: var(--teal) !important;
}
html.light .login-footer {
  border-top: 1px solid rgba(15,15,40,.08) !important;
  color: var(--mute) !important;
}
html.light .login-error {
  background: rgba(190,18,60,.06) !important;
  border-color: rgba(190,18,60,.25) !important;
}
html.light .forgot-link,
html.light .login-right a { color: var(--teal) !important; }

/* ââ Settings page dividers + inline code chips âââââââââââââââââââââââââââ
   `.settings-input`, `.settings-card` already flip via earlier rules; the
   section dividers and inline `<code>` snippets inside hints still use the
   dark-only rgba(255,255,255,.0X) tints. */
html.light .settings-section { border-top: 1px solid rgba(15,15,40,.06) !important; }
html.light .settings-hint code {
  background: rgba(15,15,40,.04) !important;
  border: 1px solid rgba(15,15,40,.08) !important;
  color: var(--ink2) !important;
}
html.light .settings-input option {
  background: #fff !important;
  color: var(--ink) !important;
}
html.light .settings-title em,
html.light .settings-card em { color: var(--teal) !important; }

/* Generic checkbox accent in light mode */
html.light input[type="checkbox"] { accent-color: var(--teal) !important; }

/* ââ Dashboards page ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
   Control bar (tab strip + period filter + refresh) and tab hover states
   used rgba(15,15,26,.6) / rgba(255,255,255,.0X) hardcodes. */
html.light .ctrl-bar {
  background: rgba(255,255,255,.6) !important;
  border-bottom: 1px solid rgba(15,15,40,.08) !important;
}
html.light .tab { color: var(--ink2) !important; }
html.light .tab:hover:not(.active) {
  background: rgba(15,15,40,.05) !important;
  color: var(--ink) !important;
}
html.light select.ctrl-select {
  background: rgba(255,255,255,.8) !important;
  border: 1px solid rgba(15,15,40,.12) !important;
  color: var(--ink2) !important;
}
html.light select.ctrl-select option {
  background: #fff !important;
  color: var(--ink) !important;
}
html.light .refresh-info { color: var(--ink2) !important; }

/* Dashboard empty / error messages (set via JS with inline colour) â we donât
   override the inline style, but bump the surrounding .dash-content contrast. */
html.light .dash-content { color: var(--ink) !important; }

/* ââ Users & Roles chips ââââââââââââââââââââââââââââââââââââââââââââââââââ
   Chip backgrounds/borders were teal-tinted rgba(45,212,191,.XX) hardcodes,
   which look dull on a light background. Flip to the purple accent. */
html.light .entity-chip {
  background: rgba(15,15,40,.03) !important;
  border: 1px solid rgba(15,15,40,.08) !important;
  color: var(--ink2) !important;
}
html.light .entity-chip.allowed {
  background: rgba(var(--teal-rgb),.08) !important;
  border-color: rgba(var(--teal-rgb),.3) !important;
  color: var(--teal) !important;  /* teal token is already purple in light */
}
html.light .entity-chip.denied {
  color: var(--mute) !important;
  opacity: .5 !important;
}
html.light .role-tag {
  background: rgba(var(--teal-rgb),.08) !important;
  border: 1px solid rgba(var(--teal-rgb),.25) !important;
  color: var(--teal) !important;
}
html.light .role-tag.unrestricted {
  background: rgba(162,28,175,.08) !important;
  border-color: rgba(162,28,175,.3) !important;
  color: var(--violet) !important;
}
html.light .unrestricted-label,
html.light .unrestricted-label::before { color: var(--teal) !important; background: var(--teal); }
html.light .unrestricted-label { background: transparent !important; color: var(--teal) !important; }
html.light .role-row { border-bottom: 1px solid rgba(15,15,40,.06) !important; }
html.light .empty-msg code {
  background: rgba(var(--teal-rgb),.08) !important;
  border: 1px solid rgba(var(--teal-rgb),.25) !important;
  color: var(--teal) !important;
}
html.light .role-section-title { color: var(--mute) !important; }

/* Status pill */
html.light .status-pill { background: rgba(255,255,255,.7) !important; border-color: rgba(15,15,40,.1) !important; color: var(--mute) !important; }
html.light .status-dot { background: var(--teal) !important; box-shadow: 0 0 0 3px rgba(var(--teal-rgb),.15) !important; }

/* ──────────────────────────────────────────────────────────────────────
   Canonical status pill — `data-tone="success|warn|neutral|danger"`.
   Use this for any "sent / drafted / failed / unknown" style indicator
   so contrast is right on both themes (the page-local `.pill.sent` etc.
   colour schemes were designed for dark backgrounds and washed out on
   light). Pages map their own status strings to a tone in JS.
   ────────────────────────────────────────────────────────────────────── */
.ds-status-pill{
  display:inline-block;padding:2px 9px;border-radius:999px;
  font-family:var(--font-mono);font-size:9.5px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;line-height:1.55;
  border:1px solid;white-space:nowrap;
}
.ds-status-pill[data-tone="success"]{background:rgba(20,184,166,.18);color:#5eead4;border-color:rgba(20,184,166,.45)}
.ds-status-pill[data-tone="warn"]   {background:rgba(251,191,36,.18);color:#fcd34d;border-color:rgba(251,191,36,.45)}
.ds-status-pill[data-tone="neutral"]{background:rgba(148,163,184,.16);color:#cbd5e1;border-color:rgba(148,163,184,.40)}
.ds-status-pill[data-tone="danger"] {background:rgba(239,68,68,.18);color:#fca5a5;border-color:rgba(239,68,68,.45)}

html.light .ds-status-pill[data-tone="success"]{background:rgba(13,148,136,.12);color:#0f766e;border-color:rgba(13,148,136,.40)}
html.light .ds-status-pill[data-tone="warn"]   {background:rgba(217,119,6,.10); color:#92400e;border-color:rgba(217,119,6,.40)}
html.light .ds-status-pill[data-tone="neutral"]{background:rgba(71,85,105,.08); color:#334155;border-color:rgba(71,85,105,.30)}
html.light .ds-status-pill[data-tone="danger"] {background:rgba(190,18,60,.10); color:#9f1239;border-color:rgba(190,18,60,.40)}

/* ──────────────────────────────────────────────────────────────────────
   Canonical pager — pagination controls for paginated lists.
   `.ds-pager`              outer flex container (info + controls)
   `.ds-pager.is-card-footer` modifier — adds in-card padding + top rule
                              for pagers sitting at the bottom of a card
   `.ds-pager-info`         left-side counter ("Showing 1–10 of 24")
   `.ds-pager-controls`     right-side group (size selector + Prev/Next)
   `.ds-pager-btn`          Prev / Next chip (disabled state included)
   `.ds-pager-size`         per-page <select>
   Uses theme-aware tokens (--teal, --mute, --ink2, --ink, --border) so
   no separate html.light overrides are needed.
   ────────────────────────────────────────────────────────────────────── */
.ds-pager {
  display:flex; align-items:center; justify-content:space-between;
  gap:14px; flex-wrap:wrap;
  font-family:var(--font-mono); font-size:10.5px;
  color:var(--mute); letter-spacing:.04em;
}
.ds-pager.is-card-footer { padding:12px 18px; border-top:1px solid var(--border); }
.ds-pager-info { color:var(--ink2); }
.ds-pager-info strong { color:var(--ink); font-weight:600; }
.ds-pager-controls { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.ds-pager-btn {
  font-family:var(--font-mono); font-size:9.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink2);
  padding:5px 12px; border:1px solid var(--border); border-radius:999px;
  cursor:pointer; background:transparent;
  transition:color .15s, border-color .15s;
}
.ds-pager-btn:hover:not(:disabled) { color:var(--teal); border-color:var(--teal); }
.ds-pager-btn:disabled { opacity:.35; cursor:not-allowed; }
.ds-pager-size {
  font-family:var(--font-mono); font-size:10.5px; color:var(--ink2);
  background:transparent; border:1px solid var(--border); border-radius:6px;
  padding:4px 10px; cursor:pointer; outline:none;
}
.ds-pager-size:focus { border-color:var(--teal); }

/* Tables */
html.light thead th,
html.light .ds-table thead th { background: rgba(15,15,40,.03) !important; color: var(--mute) !important; border-bottom-color: rgba(15,15,40,.1) !important; }
html.light tbody td,
html.light .ds-table tbody td { color: var(--ink) !important; border-bottom-color: rgba(15,15,40,.06) !important; }
html.light tbody tr:hover td,
html.light .ds-table tbody tr:hover td { background: rgba(15,15,40,.03) !important; }
html.light .detail-row td { background: rgba(15,15,40,.02) !important; }
html.light .detail-inner { border-top-color: rgba(15,15,40,.05) !important; }

/* Tags / source tags */
html.light .source-tag { background: rgba(var(--teal-rgb),.08) !important; border-color: rgba(var(--teal-rgb),.25) !important; color: var(--teal) !important; }

/* Section headers / page head */
html.light .page-head,
html.light .ds-section,
html.light .ds-hero { border-bottom-color: rgba(15,15,40,.08) !important; }
html.light .page-title,
html.light .ds-hero-title { color: var(--ink) !important; }
html.light .page-sub,
html.light .ds-hero-sub { color: var(--ink2) !important; }
html.light .ds-eyebrow,
html.light .ds-hero-eyebrow,
html.light .settings-hint,
html.light .ds-muted,
html.light .ds-faint { color: var(--mute) !important; }
html.light .settings-section { border-top-color: rgba(15,15,40,.06) !important; }

/* Buttons (ghost/base) */
html.light .ds-btn { background: rgba(255,255,255,.7) !important; border-color: rgba(15,15,40,.1) !important; color: var(--ink2) !important; }
html.light .ds-btn:hover { background: rgba(255,255,255,.9) !important; color: var(--ink) !important; }
html.light .ds-btn-primary { background: var(--teal) !important; color: #fff !important; border-color: var(--teal) !important; }

/* Autofill */
html.light input:-webkit-autofill,
html.light input:-webkit-autofill:hover,
html.light input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink) !important;
  -webkit-box-shadow: 0 0 0 30px #fff inset !important;
  caret-color: var(--ink);
}

/* Scrollbar */
html.light *::-webkit-scrollbar-thumb { background: rgba(15,15,40,.15) !important; }
html.light *::-webkit-scrollbar-thumb:hover { background: var(--teal) !important; }

/* Colophon / footer */
html.light .ds-colophon { border-top-color: rgba(15,15,40,.08) !important; color: var(--mute) !important; }

/* ─── Base ────────────────────────────────────────────────────────────────── */
html, body { min-height: 100vh; }
body {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-variant-numeric: tabular-nums;
}

/* Gradient mesh background. dark theme. Same shape as light, but the deep
   navy anchor stays so the mesh keeps its night-sky feel. The two teal
   blobs and the rose accent now follow brand RGB vars set by JS, so a
   tenant's accent colour subtly washes through. Defaults below match the
   original teal+rose palette when no brand is set. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    radial-gradient(ellipse 600px 600px at 15% 20%, rgba(26,26,78,.8), transparent),
    radial-gradient(ellipse 500px 500px at 80% 15%, rgba(var(--accent-rgb),  .35), transparent),
    radial-gradient(ellipse 400px 400px at 60% 70%, rgba(var(--accent-rgb),  .30), transparent),
    radial-gradient(ellipse 350px 350px at 25% 80%, rgba(var(--accent2-rgb), .20), transparent);
}
/* Branded dark mesh: keep the navy anchor, halve the brand-tint layers so
   secondary copy (ink2 / mute) stays readable on top of it. */
body.has-brand::before {
  background-image:
    radial-gradient(ellipse 600px 600px at 15% 20%, rgba(26,26,78,.85), transparent),
    radial-gradient(ellipse 500px 500px at 80% 15%, rgba(var(--accent-rgb),  .18), transparent),
    radial-gradient(ellipse 400px 400px at 60% 70%, rgba(var(--accent-rgb),  .15), transparent),
    radial-gradient(ellipse 350px 350px at 25% 80%, rgba(var(--accent2-rgb), .10), transparent);
}

/* Ensure content sits above background */
body > * { position: relative; z-index: 1; }

/* Autofill override */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 30px rgba(15,15,26,1) inset;
  caret-color: var(--text);
}

::selection { background: var(--teal); color: #0f0f1a; }

/* ─── Glass utility class ────────────────────────────────────────────────── */
.glass {
  background: rgba(255,255,255,.07);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px;
}

/* ─── Typography primitives ──────────────────────────────────────────────── */
.ds-display {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.ds-display-italic {
  font-family: var(--font-display);
  font-weight: 300;
  letter-spacing: -0.015em;
}
.ds-serif { font-family: var(--font-display); font-weight: 600; }
.ds-mono  { font-family: var(--font-mono); font-feature-settings: 'ss02','cv01'; letter-spacing: -0.01em; }
.ds-eyebrow {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--text-faint);
}
.ds-section-num { font-family: var(--font-display); font-weight: 300; color: var(--teal); }
.ds-num {
  font-family: var(--font-display);
  font-weight: 600;
  font-variant-numeric: tabular-nums slashed-zero;
  letter-spacing: -0.02em;
  line-height: 1;
}

/* ─── Rules ──────────────────────────────────────────────────────────────── */
.ds-rule        { height: 1px; background: var(--rule); border: none; margin: 0; }
.ds-rule-strong { height: 1px; background: var(--rule-strong); border: none; margin: 0; }
.ds-rule-double { height: 5px; border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong); margin: 0; }

/* ─── Topbar / chrome ────────────────────────────────────────────────────── */
.ds-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  background: rgba(15,15,26,.85);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(255,255,255,.08);
  position: sticky;
  top: 0;
  z-index: 30;
}
.ds-topbar-left  { display: flex; align-items: center; gap: 18px; }
.ds-topbar-right { display: flex; align-items: center; gap: 14px; }

.ds-brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
}
.ds-brand-mark {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--teal);
}
.ds-brand-sub {
  font-family: var(--font-body);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.24em;
  color: var(--text-faint);
  padding-left: 10px;
  border-left: 1px solid rgba(255,255,255,.12);
  line-height: 1;
}

.ds-topbar-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 24px;
  padding-left: 24px;
  border-left: 1px solid rgba(255,255,255,.1);
}
.ds-navlink {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-decoration: none;
  padding: 6px 12px;
  border-radius: 8px;
  transition: color .15s ease, background .15s ease;
  white-space: nowrap;
  position: relative;
}
.ds-navlink:hover  { color: var(--text); background: rgba(255,255,255,.06); }
.ds-navlink.active { color: var(--teal); }
.ds-navlink.active::after {
  content: '';
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -2px;
  height: 1.5px;
  background: var(--teal);
}

/* User chip + icon button */
.ds-icon-btn {
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 8px;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13px;
  transition: all .15s ease;
  padding: 0;
}
.ds-icon-btn:hover { color: var(--text); border-color: var(--teal); background: rgba(45,212,191,.1); }

.ds-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 10px 5px 5px;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  font-size: 12px;
  color: var(--text-dim);
  cursor: pointer;
  position: relative;
  transition: all .15s ease;
  background: rgba(255,255,255,.05);
  font-family: var(--font-body);
}
.ds-chip:hover { border-color: var(--teal); color: var(--text); }
.ds-chip-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--violet), var(--teal));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 10px;
  flex-shrink: 0;
}
.ds-chip-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: rgba(20,20,36,.95);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px;
  padding: 6px;
  min-width: 180px;
  z-index: 100;
  box-shadow: var(--shadow-2);
}
.ds-chip.open .ds-chip-dropdown { display: block; }
.ds-dd-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--text-dim);
  cursor: pointer;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  border-radius: 8px;
  text-decoration: none;
  transition: all .12s ease;
}
.ds-dd-item:hover { background: rgba(255,255,255,.08); color: var(--text); }

/* ─── Section headers ────────────────────────────────────────────────────── */
.ds-section {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  margin-bottom: 24px;
}
.ds-section-tag   { font-family: var(--font-display); font-weight: 300; font-size: 16px; color: var(--teal); line-height: 1; }
.ds-section-title { font-family: var(--font-display); font-weight: 600; font-size: 20px; letter-spacing: -0.01em; line-height: 1; }
.ds-section-meta  { margin-left: auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.08em; }

/* Hero typography */
.ds-hero {
  padding: 48px 0 28px;
  border-bottom: 1px solid rgba(255,255,255,.08);
  margin-bottom: 32px;
}
.ds-hero-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-faint);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ds-hero-eyebrow::before {
  content: '';
  display: inline-block;
  width: 32px;
  height: 1px;
  background: var(--teal);
}
.ds-hero-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(40px, 6vw, 72px);
  line-height: 1;
  letter-spacing: -0.03em;
  margin-bottom: 10px;
}
/* Headings carry no colour emphasis. hierarchy comes from weight +
   size only. Keep the <em> tag inert so existing markup still parses
   without rendering a teal split word. */
.ds-hero-title em { font-style: normal; color: inherit; font-weight: inherit; }
.ds-hero-sub {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--text-dim);
  max-width: 560px;
  line-height: 1.6;
}

/* ─── Glass cards / surfaces ─────────────────────────────────────────────── */
.ds-card {
  background: rgba(255,255,255,.07);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px;
  padding: 24px;
  position: relative;
}
.ds-card-flat {
  background: transparent;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 18px;
  padding: 24px;
}

/* KPI tile */
.ds-kpi {
  padding: 24px;
  background: rgba(255,255,255,.07);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px;
  position: relative;
  overflow: hidden;
}
.ds-kpi-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  margin-bottom: 12px;
}
.ds-kpi-value {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.ds-kpi-value .unit { font-size: 20px; color: var(--text-faint); font-weight: 400; margin-left: 4px; }
.ds-kpi-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--text-dim);
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,.08);
  display: flex;
  align-items: center;
  gap: 6px;
}
.ds-kpi-delta-up   { color: var(--teal); }
.ds-kpi-delta-down { color: var(--rose); }

/* ─── Buttons ────────────────────────────────────────────────────────────── */
.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 38px;
  padding: 0 20px;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  color: var(--ink2);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: all .15s ease;
  line-height: 1;
}
.ds-btn:hover { background: rgba(255,255,255,.1); color: var(--text); }
.ds-btn-primary {
  background: var(--teal);
  color: #0f0f1a;
  border-color: var(--teal);
  font-weight: 600;
}
.ds-btn-primary:hover { filter: brightness(1.1); }
.ds-btn-ghost {
  background: transparent;
  border-color: rgba(255,255,255,.1);
  color: var(--text-dim);
}
.ds-btn-ghost:hover { background: rgba(255,255,255,.08); color: var(--text); }
.ds-btn-danger { color: var(--rose); border-color: rgba(225,29,72,.3); }
.ds-btn-danger:hover { background: rgba(225,29,72,.1); }
.ds-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.ds-btn-sm { height: 28px; padding: 0 12px; font-size: 11px; }
.ds-btn-lg { height: 46px; padding: 0 28px; font-size: 14px; }

/* ─── Forms ──────────────────────────────────────────────────────────────── */
.ds-label {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.ds-input,
.ds-select,
.ds-textarea {
  width: 100%;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px;
  padding: 11px 14px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13px;
  outline: none;
  transition: border-color .15s, box-shadow .15s;
  font-variant-numeric: tabular-nums;
}
.ds-input:focus,
.ds-select:focus,
.ds-textarea:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-glow);
}
.ds-textarea { resize: vertical; min-height: 80px; }
.ds-input::placeholder,
.ds-textarea::placeholder { color: var(--text-faint); }

/* ─── Tables ─────────────────────────────────────────────────────────────── */
.ds-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums slashed-zero;
}
.ds-table thead th {
  text-align: left;
  padding: 12px 16px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  border-bottom: 1px solid rgba(255,255,255,.1);
  background: transparent;
}
.ds-table tbody td {
  padding: 13px 16px;
  font-size: 13px;
  border-bottom: 1px solid rgba(255,255,255,.06);
  vertical-align: middle;
}
.ds-table tbody tr:hover td { background: rgba(255,255,255,.04); }
.ds-table tbody tr:last-child td { border-bottom: none; }
.ds-table .num { text-align: right; font-family: var(--font-mono); font-size: 12px; }

/* ─── Tags / badges / pills ──────────────────────────────────────────────── */
.ds-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 20px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-dim);
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.1);
  line-height: 1;
}
.ds-tag-accent  { background: var(--teal-soft); color: var(--teal); border-color: rgba(45,212,191,.3); }
.ds-tag-ok      { background: var(--ok-soft);   color: var(--ok);   border-color: rgba(45,212,191,.3); }
.ds-tag-warn    { background: var(--warn-soft);  color: var(--warn); border-color: rgba(245,158,11,.3); }
.ds-tag-danger  { background: var(--danger-soft);color: var(--rose); border-color: rgba(225,29,72,.3); }
.ds-tag-info    { background: var(--info-soft);  color: var(--info); border-color: rgba(96,165,250,.3); }
.ds-tag-solid        { background: var(--teal);       color: #0f0f1a; border-color: var(--teal); }
.ds-tag-ok-solid     { background: var(--ok-soft);    color: var(--ok);   border-color: rgba(45,212,191,.3); }
.ds-tag-danger-solid { background: var(--danger-soft);color: var(--rose); border-color: rgba(225,29,72,.3); }
.ds-tag-warn-solid   { background: var(--warn-soft);  color: var(--warn); border-color: rgba(245,158,11,.3); }

/* Live dot */
.ds-live-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-soft);
  animation: ds-pulse 2.4s ease-in-out infinite;
}
@keyframes ds-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--teal-soft); opacity: 1; }
  50%       { box-shadow: 0 0 0 6px transparent; opacity: 0.5; }
}

/* ─── Spinner ────────────────────────────────────────────────────────────── */
.ds-spinner {
  width: 18px;
  height: 18px;
  border: 1.5px solid rgba(255,255,255,.15);
  border-top-color: var(--teal);
  border-radius: 50%;
  animation: ds-spin 0.7s linear infinite;
  display: inline-block;
}
.ds-spinner-lg { width: 28px; height: 28px; border-width: 2px; }
@keyframes ds-spin { to { transform: rotate(360deg); } }

/* ─── Loading / empty / error state primitives ───────────────────────────
   Pages used to ship per-call-site inline-styled spinner rows like
     `<div style="font-size:12px;color:var(--ink2);display:flex;
                  align-items:center;gap:8px"><div class="spinner">
      </div>Generating...</div>`
   repeated 10x in a single file. These primitives unify the patterns
   so 'a thing is loading / empty / failed' looks the same wherever it
   shows up. */
.ds-loading-row {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 8px 0;
  font-family: var(--font-body); font-size: 12.5px; color: var(--ink2);
  line-height: 1.4;
}
.ds-loading-block {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 40px 24px;
  font-family: var(--font-body); font-size: 12.5px; color: var(--ink2);
}
.ds-empty {
  display: flex; align-items: center; justify-content: center;
  gap: 8px; padding: 28px 24px;
  font-family: var(--font-mono); font-size: 11px; color: var(--mute);
  text-transform: uppercase; letter-spacing: .12em;
  text-align: center;
}
.ds-empty-tick { color: var(--teal); font-size: 14px; }
.ds-error {
  background: rgba(225,29,72,.10); border: 1px solid rgba(225,29,72,.3);
  border-radius: 10px; padding: 11px 15px;
  font-family: var(--font-body); font-size: 13px; color: var(--rose);
  line-height: 1.5;
}

/* ─── Modal ──────────────────────────────────────────────────────────────── */
.ds-modal-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.7);
  backdrop-filter: blur(8px);
  z-index: 200;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.ds-modal-backdrop.open { display: flex; }
.ds-modal {
  background: rgba(20,20,36,.95);
  backdrop-filter: blur(32px);
  -webkit-backdrop-filter: blur(32px);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 20px;
  padding: 32px;
  width: 520px;
  max-width: 100%;
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: var(--shadow-2);
  position: relative;
}
.ds-modal-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin-bottom: 4px;
}
.ds-modal-title em { font-style: normal; color: inherit; font-weight: inherit; }
.ds-modal-sub {
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 24px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--rule-strong);
}
.ds-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--rule-strong);
}

/* ─── Layout primitives ──────────────────────────────────────────────────── */
.ds-page {
  max-width: 1440px;
  margin: 0 auto;
  padding: 36px 40px 72px;
  position: relative;
}
@media (max-width: 720px) { .ds-page { padding: 28px 20px 48px; } }

.ds-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.ds-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.ds-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
@media (max-width: 900px) {
  .ds-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .ds-grid-3 { grid-template-columns: 1fr; }
  .ds-grid-2 { grid-template-columns: 1fr; }
}

/* ─── Footer colophon ────────────────────────────────────────────────────── */
.ds-colophon {
  margin-top: 64px;
  padding-top: 24px;
  border-top: 1px solid rgba(255,255,255,.08);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--font-body);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-faint);
}
.ds-colophon em { color: var(--teal); text-transform: none; font-size: 13px; letter-spacing: 0; font-style: normal; }

/* ─── Animation: glass fade-up stagger ──────────────────────────────────── */
@keyframes ds-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ds-rise   { animation: ds-rise 0.6s cubic-bezier(.2,.65,.2,1) both; }
.ds-rise-1 { animation-delay: 0.05s; }
.ds-rise-2 { animation-delay: 0.12s; }
.ds-rise-3 { animation-delay: 0.2s; }
.ds-rise-4 { animation-delay: 0.28s; }
.ds-rise-5 { animation-delay: 0.36s; }
.ds-rise-6 { animation-delay: 0.44s; }

/* ─── Utility ────────────────────────────────────────────────────────────── */
.ds-mono   { font-family: var(--font-mono); font-variant-numeric: tabular-nums slashed-zero; }
.ds-serif  { font-family: var(--font-display); }
.ds-italic { font-family: var(--font-display); font-style: italic; }
.ds-tab    { font-variant-numeric: tabular-nums slashed-zero; }
.ds-muted  { color: var(--text-dim); }
.ds-faint  { color: var(--text-faint); }
.ds-accent { color: var(--teal); }

/* Scrollbar */
*::-webkit-scrollbar { width: 6px; height: 6px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12); border-radius: 3px; }
*::-webkit-scrollbar-thumb:hover { background: var(--teal); }

/* ═══════════════════════════════════════════════════════════════════════════
 * App shell. sidebar layout shared across all authenticated pages.
 * Used with /app-shell.js which injects the sidebar DOM into .layout.
 * ═══════════════════════════════════════════════════════════════════════════ */
:root { --sidebar-w: 248px; --footer-h: 150px; --panel: #14131f; --panel-hi: #161326; --border-hi: rgba(255,255,255,.15); }
html.light { --panel: #ffffff; --panel-hi: #ffffff; --border-hi: rgba(15,15,40,.12); }

.layout { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

/* Sidebar shell */
.sidebar { background: var(--panel); border-right: 1px solid var(--border); display: flex; flex-direction: column; padding: 18px 0 0; position: sticky; top: 0; height: 100vh; overflow-y: auto; z-index: 10; }
/* Tenant identity strip. sits above the product brand row and is only
   rendered when the tenant has configured branding.logo_url. Deliberately
   restrained: centred wordmark, editorial hairline underneath, no
   decoration. Keeps "Powered by MCCS" in the footer true to the attribution
   while letting the customer's own logo own the most prominent real estate. */
.sb-tenant-mark {
  padding: 12px 20px 22px;
  margin: 0;
  display: flex; align-items: center; justify-content: center;
  border-bottom: 1px solid var(--rule);
}
.sb-tenant-mark[hidden] { display: none; }
.sb-tenant-link {
  display: flex; align-items: center; justify-content: center;
  width: 100%; line-height: 0;
  text-decoration: none;
  border-radius: 8px;
  transition: opacity .15s ease;
}
.sb-tenant-link:hover { opacity: .85; }
.sb-tenant-link:focus-visible { outline: 2px solid var(--teal); outline-offset: 4px; }
.sb-tenant-logo {
  max-height: 64px; max-width: 160px; width: auto; height: auto;
  display: block;
  margin: 0 auto;
  opacity: .95;
}
/* In dark mode the supplied tenant logo is dark navy; flip its
   luminance so it reads as light-on-dark while preserving hue. */
html:not(.light) .sb-tenant-logo { filter: invert(1) hue-rotate(180deg) brightness(1.15); }
/* ── Sidebar credit block ────────────────────────────────────────────────
   Single asset per theme: each PNG bakes the CONNECTED wordmark, the
   teal frame, and the "POWERED BY MCCS" tagline (sitting on the
   bottom border with the right cutout) into one image so we don't
   have to fight CSS to recreate the certificate cutout. Theme-aware
   swap below shows the variant whose colour balance matches the
   active background. */
.sb-credit { padding: 8px 10px 6px; margin-top: 4px; border-top: 1px solid var(--rule); }
.sb-credit-frame {
  display: block;
  text-decoration: none;
  line-height: 0;
}
.sb-wordmark { display: block; width: 100%; height: auto; max-width: 100%; }
.sb-wordmark-light { display: none; }
html.light .sb-wordmark-dark  { display: none; }
html.light .sb-wordmark-light { display: block; }

/* Optional product-name fallback (rendered hidden by default; pages can
   reveal via #sb-brand-name when the tenant has no wordmark). */
.sb-brand-name {
  font-family: var(--font-display); font-weight: 800; font-size: 14px;
  color: var(--ink); text-transform: uppercase; letter-spacing: .08em;
  line-height: 1.2; margin-top: 8px;
}
.sb-brand-name em {
  font-style: italic; font-weight: 300; font-size: 0.95em;
  color: var(--teal); letter-spacing: .04em;
}

/* Legacy .sb-logo / .sb-product-mark retained in case any page still
   references them (pre-cache during deploy). */
.sb-logo { height: 26px; cursor: pointer; flex-shrink: 0; }
.sb-product-mark {
  width: 40px; height: 40px; flex-shrink: 0; cursor: pointer;
  border-radius: 10px;
}

.sb-group { margin-top: 14px; }
.sb-group-label { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .18em; color: var(--ink2); padding: 4px 20px 10px; }
/* Top padding equalises the visual gap above the Home link with the
   gap that opens below it (from .sb-group margin-top + .sb-group-label
   padding) so Home sits centred in its slot between the tenant logo
   and the first group label. */
.sb-nav-solo { padding: 18px 0 4px; }
.sb-nav-solo:empty { display: none; }

/* Idle auto log-off warning modal. shown in the final minute before
   the session is terminated. Centred overlay, glass card, prominent
   countdown. Lives at document root so it floats over every page. */
.idle-warning-modal {
  display: none;
  position: fixed; inset: 0;
  z-index: 9999;
  background: rgba(15, 15, 26, .72);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  align-items: center; justify-content: center;
  animation: idle-fade-in .18s ease-out;
}
@keyframes idle-fade-in { from { opacity: 0; } to { opacity: 1; } }
.idle-warning-card {
  background: var(--glass); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--glass-border);
  border-radius: 16px;
  padding: 28px 32px;
  width: min(400px, 90vw);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .4);
  text-align: center;
}
.idle-warning-title {
  font-family: var(--font-display); font-weight: 600; font-size: 20px;
  color: var(--ink); margin-bottom: 10px; letter-spacing: -.01em;
}
.idle-warning-body {
  font-family: var(--font-body); font-size: 14px; color: var(--ink2);
  line-height: 1.5; margin-bottom: 22px;
}
.idle-warning-body #idle-warning-countdown {
  font-family: var(--font-mono); font-weight: 600; color: var(--warn);
  font-variant-numeric: tabular-nums;
}
.idle-warning-actions { display: flex; gap: 10px; justify-content: center; }
.idle-warning-stay {
  background: var(--teal);
  color: #fff; border: none; border-radius: 8px;
  padding: 10px 22px; font-family: var(--font-mono); font-size: 10.5px;
  font-weight: 600; text-transform: uppercase; letter-spacing: .14em;
  cursor: pointer; transition: transform .12s, box-shadow .18s;
  box-shadow: 0 4px 16px rgba(45, 212, 191, .3);
}
.idle-warning-stay:hover { transform: translateY(-1px); box-shadow: 0 6px 22px rgba(45, 212, 191, .4); }
.idle-warning-signout {
  background: transparent; color: var(--ink2);
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 8px;
  padding: 10px 22px; font-family: var(--font-mono); font-size: 10.5px;
  font-weight: 500; text-transform: uppercase; letter-spacing: .14em;
  cursor: pointer; transition: color .15s, border-color .15s;
}
.idle-warning-signout:hover { color: var(--ink); border-color: rgba(255, 255, 255, .22); }
html.light .idle-warning-modal { background: rgba(240, 240, 245, .78); }
html.light .idle-warning-signout { border-color: rgba(0, 0, 0, .12); }
html.light .idle-warning-signout:hover { border-color: rgba(0, 0, 0, .22); }
.sb-subgroup { margin-top: 16px; }
.sb-subgroup:first-child { margin-top: 0; }
.sb-subgroup-label { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .18em; color: var(--ink2); padding: 4px 20px 10px; }
.sb-link { display: flex; align-items: center; gap: 11px; padding: 9px 20px; color: var(--ink2); text-decoration: none; font-size: 13px; font-weight: 400; line-height: 1.2; position: relative; transition: color .12s, background .12s; }
/* Author display:flex above wins over the UA `[hidden]{display:none}` rule,
   so without this override applyEnabledApps() / applyPermissionAndModuleGates()
   set link.hidden=true but the link still renders. Re-assert display:none
   with higher selector specificity. */
.sb-link[hidden] { display: none; }
.sb-link:hover { background: var(--teal-soft); color: var(--ink); }
.sb-link.active { color: var(--ink); font-weight: 600; background: linear-gradient(90deg, var(--teal-soft) 0%, var(--teal-soft) 55%, transparent 100%); }
.sb-link.active::before { content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 3px; background: var(--teal); border-radius: 0 3px 3px 0; }
.sb-ico { width: 16px; height: 16px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; opacity: .75; }
.sb-ico svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sb-link.active .sb-ico { opacity: 1; color: var(--teal); }
.sb-label { flex: 1; }
.sb-link.locked { opacity: 0.4; pointer-events: none; }

.sb-foot { margin-top: auto; padding: 0 12px; border-top: 1px solid var(--border); min-height: var(--footer-h, 96px); display: flex; flex-direction: column; justify-content: center; position: relative; }
.sb-dropdown { display: none; position: absolute; left: 12px; right: 12px; bottom: calc(100% + 6px); background: var(--panel-hi); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); border: 1px solid var(--border); border-radius: 10px; padding: 5px; box-shadow: 0 8px 24px rgba(0,0,0,.12); z-index: 30; }
.sb-dropdown.open { display: block; }
.sb-dd-item { display: flex; align-items: center; gap: 10px; padding: 9px 12px; font-family: var(--font-body); font-size: 12px; color: var(--ink2); cursor: pointer; background: none; border: none; width: 100%; text-align: left; border-radius: 7px; transition: all .12s; }
.sb-dd-item:hover { background: var(--teal-soft); color: var(--ink); }
.sb-user { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 8px; cursor: pointer; transition: background .15s; user-select: none; }
.sb-user:hover { background: var(--teal-soft); }
.sb-avatar { width: 30px; height: 30px; border-radius: 50%; background: linear-gradient(135deg, var(--violet), var(--teal)); display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-weight: 600; font-size: 12px; color: #0a0818; flex-shrink: 0; overflow: hidden; }
.sb-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sb-user-info { flex: 1; min-width: 0; }
.sb-user-name { font-size: 13px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-user-role { font-family: var(--font-mono); font-size: 9px; text-transform: uppercase; letter-spacing: .14em; color: var(--mute); }
.sb-chevron { color: var(--mute); transition: transform .15s; flex-shrink: 0; }
.sb-user.open .sb-chevron { transform: rotate(180deg); }

/* Main panel + slim topbar (pages fill .page with content) */
.layout > .main { display: flex; flex-direction: column; min-height: 100vh; min-width: 0; }
.layout > .main > .topbar { display: flex; align-items: center; justify-content: space-between; padding: 0 28px; height: 56px; background: rgba(10,8,24,.75); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 20; }
html.light .layout > .main > .topbar { background: rgba(255,255,255,.75); }
.layout > .main > .topbar .crumbs { display: flex; align-items: center; gap: 8px; font-family: var(--font-body); font-size: 12px; color: var(--mute); }
.layout > .main > .topbar .crumbs .here { color: var(--ink); font-weight: 500; }
.layout > .main > .page { padding: 28px 32px 48px; width: 100%; }

/* ═══════════════════════════════════════════════════════════════════════════
 * MOBILE SHELL (≤ 900px)
 * Below this breakpoint, the sidebar becomes a slide-in drawer toggled by
 * a hamburger in a mobile-only top header. Desktop layout is untouched.
 * ═══════════════════════════════════════════════════════════════════════════ */
.app-mobile-header { display: none; }
.sidebar-scrim { display: none; }

@media (max-width: 900px) {
  /* Layout collapses to single column; sidebar is absolute-positioned drawer.
   * z-index:auto here is critical: the global `body > * { z-index:1 }` rule
   * makes .layout a stacking context, which would trap the sidebar's z:100
   * inside the layout's z:1 layer. letting the scrim (z:90, in root) paint
   * over the drawer and swallow every tap on a nav link. */
  .layout { grid-template-columns: 1fr; z-index: auto; }

  /* Mobile-only header with hamburger + brand */
  .app-mobile-header {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 52px;
    padding: 0 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 20;
    flex-shrink: 0;
  }
  .mh-burger {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--ink);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: background .12s, border-color .12s;
  }
  .mh-burger:hover,
  .mh-burger:active { background: var(--teal-soft); border-color: var(--teal); }
  .mh-burger svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
  .mh-brand { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .mh-logo { height: 22px; filter: brightness(0) invert(1); flex-shrink: 0; cursor: pointer; }
  html.light .mh-logo { filter: none; }
  .mh-brand-name {
    font-family: var(--font-display);
    font-weight: 300;
    font-size: 13px;
    color: var(--ink2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: -.005em;
  }
  .mh-brand-name em { color: var(--teal); font-style: normal; font-weight: 300; }

  /* Sidebar becomes fixed slide-in drawer */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 280px;
    max-width: 85vw;
    height: 100vh;
    transform: translateX(-100%);
    transition: transform .25s cubic-bezier(.2,.65,.2,1);
    z-index: 100;
    box-shadow: 0 0 24px rgba(0,0,0,.35);
  }
  .sidebar.open { transform: translateX(0); }

  /* Hamburger must always be reachable. Any wide page content (tabs, tables,
   * SVG charts) that overflows its container would, on iOS Safari, drag the
   * sticky header off-screen along the X-axis when the user pans right.
   * Forcing min-width:0 on the grid/flex chain lets the inner pages shrink
   * to viewport width, and overflow-x:clip stops a misbehaving child from
   * propagating horizontal scroll up to the body. Wide content (data tables,
   * tab rows) is given its own scroll container per page. */
  html, body { overflow-x: hidden; }
  .layout, .layout > .main { min-width: 0; max-width: 100%; overflow-x: hidden; }
  .layout > .main > .page,
  .layout > .main > main.page { min-width: 0; max-width: 100%; }

  /* Scrim behind drawer */
  .sidebar-scrim {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s;
    z-index: 90;
  }
  .sidebar-scrim.open { opacity: 1; pointer-events: auto; }

  /* Page content: tighter padding on mobile */
  .layout > .main > .page { padding: 20px 16px 40px; }
  .layout > .main > .topbar { padding: 0 16px; }

  /* iOS Safari auto-zooms the page when a focused form control has a
   * computed font-size < 16px. Bump every text-entry control to 16px on
   * mobile to suppress the zoom. the column filter inputs (11.5px),
   * admin settings inputs (13px), login form (14px), etc. all qualified.
   * !important is needed because page-level inline <style> blocks (login
   * form, .col-filter etc.) parse after this stylesheet and would
   * otherwise win source-order ties at equal specificity. The visual
   * size is governed by padding/line-height per page, so this rarely
   * changes the apparent input dimensions. */
  input[type=text],
  input[type=email],
  input[type=url],
  input[type=password],
  input[type=search],
  input[type=number],
  input[type=tel],
  input[type=date],
  input[type=time],
  input[type=datetime-local],
  input:not([type]),
  select,
  textarea { font-size: 16px !important; }
}

/* Loading state (used by every authenticated page while AppShell.init runs) */
#loading-state { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; gap: 14px; background: var(--bg); color: var(--mute); font-size: 12px; font-family: var(--font-body); text-transform: uppercase; letter-spacing: 0.14em; z-index: 200; }
