/* MarketPulse terminal base — themes, layout, components.
   Extracted from dashboard.html's inline <style> blocks (Epic P / P3): a strict
   style-src cannot keep 'unsafe-inline' while inline <style> elements exist.
   Load ORDER is the contract — see the <link> sequence in dashboard.html. */
  /* ═══════════════════════════════════════════════════════════════
     THEME SYSTEM — multiple palettes, swappable via [data-theme].
     Each theme defines: bg/fg/dim/line/panel + pos/neg/warn (up/down/caution).
     Font is swappable via --font (set on <html> data-font).
     ═══════════════════════════════════════════════════════════════ */

  /* MONO — pure black & white terminal (default original) */
  :root, html[data-theme="mono"] {
    --bg: #000; --fg: #fff; --dim: #888; --dim2: #555;
    --line: #2a2a2a; --hi: #fff; --panel: #050505;
    --pos: #fff; --neg: #fff; --warn: #fff; --accent: #fff;
  }

  /* DARK — easy-on-eyes dark with RED/GREEN/AMBER signals */
  html[data-theme="dark"] {
    --bg: #0d1117; --fg: #e6edf3; --dim: #8b949e; --dim2: #4d5560;
    --line: #21262d; --hi: #fff; --panel: #161b22;
    --pos: #3fb950; --neg: #f85149; --warn: #d29922; --accent: #58a6ff;
  }

  /* LIGHT — bright trading-desk light with RED/GREEN/AMBER */
  html[data-theme="light"] {
    --bg: #ffffff; --fg: #1c2128; --dim: #57606a; --dim2: #8c959f;
    --line: #d0d7de; --hi: #000; --panel: #f6f8fa;
    --pos: #1a7f37; --neg: #cf222e; --warn: #9a6700; --accent: #0969da;
  }

  /* BLOOMBERG — classic amber/orange on black terminal.
     --dim lifted for WCAG AA at small sizes (was #b3701a ≈ 4.0:1 on black). */
  html[data-theme="bloomberg"] {
    --bg: #000000; --fg: #ff9e1b; --dim: #c9821e; --dim2: #7d5417;
    --line: #3d2e10; --hi: #ffce5c; --panel: #0a0700;
    --pos: #41d97a; --neg: #ff4d4d; --warn: #ffce5c; --accent: #ff9e1b;
  }

  /* NEON — colorful vivid theme */
  html[data-theme="neon"] {
    --bg: #0a0e1a; --fg: #e0e7ff; --dim: #8b9cc8; --dim2: #4a5680;
    --line: #1e2a4a; --hi: #fff; --panel: #111831;
    --pos: #00e5a0; --neg: #ff4d6d; --warn: #ffd43b; --accent: #b388ff;
  }

  /* LEGACY ALIASES — map old variable names to the active theme tokens so all
     pre-existing JS-rendered markup stays readable in every theme. var() here
     resolves to whatever the current [data-theme] sets, keeping the hierarchy. */
  :root, html {
    --surface: var(--panel);  --surface2: var(--panel);  --border: var(--line);
    --text: var(--fg);        --muted: var(--dim);        --bg3: var(--bg);
    --green: var(--pos);      --red: var(--neg);          --yellow: var(--warn);
    --orange: var(--warn);    --blue: var(--accent);      --purple: var(--accent);
    /* Brand identity — the login page's orange→blue signature, now shared by
       the app shell (logo hairline, active-nav edge, hero accent). */
    --brand-a: #FF6A2C; --brand-b: #2D5BFF;
    --brand-grad: linear-gradient(90deg, var(--brand-a), var(--brand-b));
    /* Brand orange used as TEXT (the "Pulse" word, the BiGMoDa "M"). #FF6A2C is
       2.7:1 on a white/near-white surface — below the 3:1 large-text floor — so
       the light theme darkens it to #D9531A (4.0:1 on white, 3.8:1 on the
       #F5F7FB splash) while keeping the same hue. Fills/gradients still use
       --brand-a: 1.4.3 governs text, not decoration. */
    --brand-ink: #FF6A2C;
  }
  html[data-theme="light"] { --brand-ink: #D9531A; }
  /* MONO stays deliberately pure black & white — no brand chroma. */
  html[data-theme="mono"] { --brand-a: #fff; --brand-b: #fff;
    --brand-grad: linear-gradient(90deg, #fff, #fff); }

  * { box-sizing: border-box; margin: 0; padding: 0; }
  html { --font: 'Cascadia Mono','Consolas','SF Mono','Menlo','Courier New',monospace; }
  html[data-font="system"] { --font: 'Segoe UI',system-ui,-apple-system,sans-serif; }
  html[data-font="mono"]   { --font: 'Cascadia Mono','Consolas','SF Mono','Menlo',monospace; }
  html[data-font="ibm"]    { --font: 'IBM Plex Mono','Cascadia Mono',monospace; }
  html[data-font="roboto"] { --font: 'Roboto Mono','Cascadia Mono',monospace; }
  html[data-font="serif"]  { --font: 'Georgia','Times New Roman',serif; }
  html { background: var(--bg); }
  body { background: transparent; }
  html, body { color: var(--fg);
    font-family: var(--font);
    font-size: 12px; line-height: 1.45; -webkit-font-smoothing: antialiased;
    transition: color .2s; }

  /* Dynamic animated colour background — theme-derived glows that slowly drift.
     Content surfaces stay opaque so all text / boxes / icons remain readable. */
  #bg-fx { position: fixed; inset: 0; z-index: 0; pointer-events: none;
    background:
      radial-gradient(42% 38% at 18% 18%, color-mix(in srgb, var(--accent) 24%, transparent), transparent 70%),
      radial-gradient(40% 36% at 84% 28%, color-mix(in srgb, var(--pos) 20%, transparent), transparent 70%),
      radial-gradient(44% 44% at 66% 88%, color-mix(in srgb, var(--neg) 15%, transparent), transparent 70%),
      radial-gradient(40% 40% at 26% 82%, color-mix(in srgb, var(--warn) 13%, transparent), transparent 70%);
    background-repeat: no-repeat; background-size: 200% 200%;
    animation: bgDrift 30s ease-in-out infinite; }
  @keyframes bgDrift {
    0%   { background-position: 0% 0%, 100% 0%, 50% 100%, 0% 100%; }
    50%  { background-position: 100% 100%, 0% 100%, 0% 0%, 100% 0%; }
    100% { background-position: 0% 0%, 100% 0%, 50% 100%, 0% 100%; }
  }
  @media (prefers-reduced-motion: reduce) { #bg-fx { animation: none; } }
  /* Keep app + login above the background layer */
  .app, #login-page { position: relative; z-index: 1; }
  /* Slight translucency on big surfaces so the colour shows through subtly */
  .main { background: transparent; }
  ::selection { background: var(--fg); color: var(--bg); }

  /* P/L semantic colors — used by .pos / .neg / .flat */
  .pos { color: var(--pos) !important; }
  .neg { color: var(--neg) !important; }
  .flat { color: var(--dim) !important; }
  .pos-bg { background: var(--pos); color: var(--bg); }
  .neg-bg { background: var(--neg); color: var(--bg); }

  /* ── Layout ────────────────────────────────────────────── */
  /* The app shell reserves room for the fixed legal footer (~26px) so the
     sidebar's bottom rows (status, Theme/Term/Exit) are never covered. */
  .app { display: flex; height: calc(100vh - 26px); }
  .sidebar { width: 200px; background: var(--bg); border-right: 1px solid var(--line);
    display: flex; flex-direction: column; flex-shrink: 0; }
  .main { flex: 1; overflow: auto; min-width: 0; }

  /* ── Sidebar ───────────────────────────────────────────── */
  .logo { padding: 14px 14px 12px; border-bottom: 1px solid var(--line); position: relative; }
  .logo::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
    height: 2px; background: var(--brand-grad); opacity: .85; }
  .logo h1 { font-size: 13px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; }
  .logo p { font-size: 10px; color: var(--dim); margin-top: 3px; letter-spacing: 1.5px; text-transform: uppercase; }
  .nav { flex: 1; padding: 4px 0 8px; overflow-y: auto; }
  /* Collapsible groups: header is a button with a rotating chevron; items hide
     unless the group is .open. Active page's group is auto-expanded by JS. */
  .nav-group { display: flex; align-items: center; justify-content: space-between;
    width: 100%; font-size: 9px; letter-spacing: 1.8px; text-transform: uppercase;
    color: var(--dim); padding: 10px 14px 6px; font-weight: 700;
    border: none; background: none; cursor: pointer; text-align: left;
    font-family: inherit; }
  .nav-group:hover { color: var(--fg); }
  /* The chevron carries expanded/collapsed STATE, so it is not decorative and
     AA contrast applies. --dim2 is a hairline/border token (2.7:1 in neon);
     --dim is the lifted text token that clears 4.5:1 in all five themes. */
  .nav-group .chev { font-size: 10px; transition: transform .15s ease; color: var(--dim); }
  .nav-sec.open .nav-group .chev { transform: rotate(90deg); }
  .nav-sec-items { display: none; }
  .nav-sec.open .nav-sec-items { display: block; }
  .nav-item { display: block; padding: 7px 14px 7px 20px; cursor: pointer;
    color: var(--dim); font-size: 11px; letter-spacing: 1px; text-transform: uppercase;
    border: none; background: none; width: 100%; text-align: left;
    border-left: 2px solid transparent; }
  .nav-item.nav-top { padding-left: 14px; font-weight: 600; }
  .nav-item:hover { background: var(--panel); color: var(--fg); }
  .nav-item.active { color: var(--fg); background: var(--panel);
    border-image: var(--brand-grad) 1; border-left: 2px solid; }
  .nav-item .icon { display: none; }     /* text-only */
  .server-status { display: flex; align-items: center; gap: 6px; padding: 9px 14px;
    border-top: 1px solid var(--line); font-size: 10px; letter-spacing: 1px; min-width: 0; }
  .chip-email { color: var(--fg); font-weight: 600; margin-left: auto; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; max-width: 55%; text-transform: none; letter-spacing: 0; }
  .util-row { display: flex; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--line); }
  .util-row button { flex: 1; background: transparent; border: 1px solid var(--dim2);
    padding: 7px 6px; color: var(--dim); font-size: 10px; cursor: pointer;
    font-family: inherit; letter-spacing: 1px; text-transform: uppercase; }
  .util-row button:hover { border-color: var(--fg); color: var(--fg); }
  .util-row .util-logout:hover { border-color: var(--neg); color: var(--neg); }
  .status-dot { display: inline-block; margin-right: 6px; }
  .status-dot.green::before { content: '●'; color: var(--fg); }
  .status-dot.red::before   { content: '○'; color: var(--dim); }
  .status-dot.green, .status-dot.red { width: auto; height: auto; background: none; box-shadow: none; }

  /* ── Topbar + hamburger (mobile/tablet only) ───────────── */
  .topbar { display: none; align-items: center; gap: 12px; padding: 10px 14px;
    border-bottom: 1px solid var(--line); background: var(--bg); position: sticky; top: 0; z-index: 80; }
  .hamburger { display: none; flex-direction: column; gap: 4px; background: none; border: 1px solid var(--dim2);
    padding: 7px 8px; cursor: pointer; }
  .hamburger span { width: 18px; height: 2px; background: var(--fg); display: block; }
  .topbar-title { font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; }
  .sidebar-backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 90; }

  /* ── Pages ─────────────────────────────────────────────── */
  .page { display: none; padding: 16px 20px 24px; }
  .page.active { display: block; }
  /* Type scale: 20px page title / 12px section / 12px body. Uppercase is
     reserved for the small labels (nav, badges, card labels) — titles read as
     titles, not as another label. */
  .page-title { font-size: 20px; font-weight: 700; letter-spacing: .3px;
    border-bottom: 1px solid var(--line); padding-bottom: 8px; margin-bottom: 4px; }
  .page-sub { color: var(--dim); font-size: 12px; letter-spacing: .3px; margin-bottom: 18px; }

  /* ── In-page sub-navigation (submenu tabs for dense pages e.g. Admin) ──────
     A horizontally-scrollable pill strip that partitions an overloaded page
     into one-at-a-time sections. On mobile the strip scrolls internally so it
     never widens the page (avoids the whole-page horizontal scroll). */
  .subnav { display: flex; gap: 2px; overflow-x: auto; -webkit-overflow-scrolling: touch;
    border-bottom: 1px solid var(--line); margin-bottom: 18px; scrollbar-width: none;
    max-width: 100%; }
  .subnav::-webkit-scrollbar { height: 0; display: none; }
  .subnav-item { flex: 0 0 auto; background: transparent; border: none;
    border-bottom: 2px solid transparent; color: var(--dim); font-family: inherit;
    font-size: 11px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
    padding: 9px 14px; cursor: pointer; white-space: nowrap; }
  .subnav-item:hover { color: var(--fg); }
  .subnav-item.active { color: var(--fg); border-bottom-color: var(--fg); }
  .subnav-item .cnt { display: inline-block; margin-left: 6px; font-size: 9px; color: var(--dim);
    background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 0 5px;
    font-weight: 700; }
  .subpage { display: none; }
  .subpage.active { display: block; }

  /* ── Cards (dense data tiles) ──────────────────────────── */
  .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 1px; background: var(--line); border: 1px solid var(--line); margin-bottom: 18px; }
  .card { background: var(--bg); padding: 10px 14px; }
  .card-label { font-size: 9px; text-transform: uppercase; letter-spacing: 1.4px;
    color: var(--dim); margin-bottom: 4px; }
  .card-value { font-size: 20px; font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; }
  .card-sub { font-size: 10px; color: var(--dim); margin-top: 2px; letter-spacing: .5px; }
  .card.green .card-value  { color: var(--pos); }
  .card.red .card-value    { color: var(--neg); }
  .card.yellow .card-value { color: var(--warn); }
  .card.blue .card-value   { color: var(--accent); }
  .card.orange .card-value { color: var(--warn); }

  /* ── Banner ────────────────────────────────────────────── */
  .banner { padding: 8px 12px; margin-bottom: 14px;
    display: flex; align-items: center; gap: 10px; font-size: 11px;
    border: 1px solid var(--line); background: var(--panel);
    text-transform: uppercase; letter-spacing: 1px; color: var(--fg); }
  .banner.red::before    { content: '[!]'; font-weight: 700; }
  .banner.orange::before { content: '[!]'; font-weight: 700; }
  .banner.green::before  { content: '[OK]'; font-weight: 700; }
  .banner.blue::before   { content: '[i]'; font-weight: 700; }

  /* ── Table ─────────────────────────────────────────────── */
  .table-wrap { background: var(--bg); border: 1px solid var(--line); overflow: hidden; }
  .table-header { padding: 8px 12px; border-bottom: 1px solid var(--line);
    display: flex; justify-content: space-between; align-items: center; }
  .table-header h3 { font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; }
  table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
  td.num, th.num { text-align: right; }   /* numeric columns right-align */
  th { padding: 6px 10px; text-align: left; font-size: 9px; text-transform: uppercase;
    letter-spacing: 1.3px; color: var(--dim); border-bottom: 1px solid var(--line); font-weight: 700;
    background: var(--panel); }
  td { padding: 6px 10px; border-bottom: 1px solid var(--line); font-size: 11px; color: var(--fg); }
  tr:last-child td { border-bottom: none; }
  tr:hover td { background: var(--panel); }
  .empty { padding: 22px 16px; text-align: center; color: var(--dim);
    font-size: 11px; border: 1px dashed var(--line); }
  /* The hint is the sentence that says what to DO about the emptiness ("configure
     Alpaca market-data credentials", "add feeds under News & Research"), so it is
     the most load-bearing text in an empty state, not decoration. It was on
     --dim2 — the hairline token noted above, 4.1:1 as measured by the e2e audit
     and under 4.5:1 on every theme. --dim clears it everywhere; the hint stays
     distinct from its parent by size (10px vs 11px) and by sitting on its own
     line, which is what separated them to the eye in the first place. */
  .empty .hint { display: block; margin-top: 6px; font-size: 10px; color: var(--dim); }

  /* ── Badge — bracketed terminal tags ───────────────────── */
  .badge { display: inline-block; padding: 1px 6px; font-size: 10px; font-weight: 700;
    letter-spacing: 1px; text-transform: uppercase; border: 1px solid var(--fg);
    color: var(--fg); background: transparent; }
  .badge.green,
  .badge.red,
  .badge.blue,
  .badge.yellow,
  .badge.orange,
  .badge.muted { border-color: var(--fg); color: var(--fg); background: transparent; }
  .badge.muted { border-color: var(--dim2); color: var(--dim); }
  .badge.green  { background: var(--pos); border-color: var(--pos); color: var(--bg); }   /* up = positive */
  .badge.red    { background: var(--neg); border-color: var(--neg); color: var(--bg); }   /* down = negative */
  .badge.yellow { background: var(--warn); border-color: var(--warn); color: var(--bg); } /* caution = amber */
  .badge.orange { border-color: var(--warn); color: var(--warn); }
  .badge.blue   { border-color: var(--accent); color: var(--accent); }
  /* Status glyphs available for inline use */
  .arrow-up::before   { content: '▲ '; }
  .arrow-down::before { content: '▼ '; }
  .dot-on::before     { content: '● '; }
  .dot-off::before    { content: '○ '; }

  .score-bar { display: flex; align-items: center; gap: 8px; }
  .bar { flex: 1; height: 2px; background: var(--line); overflow: hidden; }
  .bar-fill { height: 100%; background: var(--fg); transition: width .3s; }

  /* ── Buttons ───────────────────────────────────────────── */
  /* WCAG 2.2 AA 2.5.8 asks for 24x24 at EVERY width, and neither height here was
     reaching it. A `.btn` measured **23px** — a 10px font's normal line-height
     plus 10px of padding and 2px of border — and `.btn-sm` measured **18px**.
     Both are shared rules, so this was every button in the app on tablet and
     desktop, not a defect of one screen; the mobile-viewport gate found 15 of
     them the moment it was pointed at #page-settings (Epic Z / Z4), among them
     the per-session "Sign out", and the browser journeys' a11y pass reports the
     23px one on the sign-in button.
     Phones were never affected and are not changed here: design-system.css's
     <=640px block already floors every button at 44px.
     inline-flex rather than more padding, because padding that clears 24px has
     to be derived from a font's normal line-height, and a layout floor should
     not depend on a number this file cannot see. The floor lives on `.btn`
     alone: every `.btn-sm` in the tree also carries `.btn`.
     min-WIDTH was missed the first time and is the other half of the same
     criterion: the settings page's per-broker remove buttons are a single `✕`
     glyph and measured 23x24 — one pixel short, on every one of them. The
     e2e a11y pass could not see it until Epic Z / Z2 made #page-settings a
     measured surface. */
  .btn { padding: 5px 12px; border: 1px solid var(--fg); cursor: pointer;
    font-size: 10px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
    font-family: inherit; background: var(--bg); color: var(--fg); transition: none;
    min-height: 24px; min-width: 24px; display: inline-flex; align-items: center; justify-content: center; }
  .btn:hover { background: var(--fg); color: var(--bg); }
  .btn-primary { background: var(--fg); color: var(--bg); }
  .btn-primary:hover { background: var(--bg); color: var(--fg); }
  .btn-sm { padding: 3px 8px; font-size: 9px; }
  .btn-ghost { background: transparent; color: var(--dim); border-color: var(--dim2); }
  .btn-ghost:hover { color: var(--fg); border-color: var(--fg); background: transparent; }
  .btn-green, .btn-red { background: var(--bg); color: var(--fg); border: 1px solid var(--fg); }
  .btn-green:hover, .btn-red:hover { background: var(--fg); color: var(--bg); }
  .btn:disabled { opacity: .35; cursor: not-allowed; }

  /* ── Login — BiGMo branded entry ───────────────────────── */
  #login-page { display: flex; flex-direction: column; align-items: center; justify-content: center;
    min-height: 100vh; background: var(--bg); position: relative; overflow: hidden; gap: 24px;
    padding: 36px 16px calc(20px + env(safe-area-inset-bottom)); }
  /* faint ECG heartbeat sweeping behind the card */
  #login-ecg { position: absolute; left: 0; top: 50%; width: 100%; transform: translateY(-50%);
    pointer-events: none; }
  #login-ecg svg { width: 100%; height: clamp(120px, 20vh, 200px); display: block; }
  #login-ecg .base { opacity: .14; }
  #login-ecg .beat { stroke-dasharray: 16 84; stroke-dashoffset: 100; animation: mpBeat 3.2s linear infinite; }
  .login-brand { text-align: center; position: relative; font-family: 'Archivo','Segoe UI',Arial,sans-serif; }
  .login-brand .t { font-size: clamp(32px, 8vw, 54px); font-weight: 900; letter-spacing: -.02em;
    color: var(--fg); line-height: 1.04; }
  .login-brand .t .pulse-word { color: var(--brand-ink); }
  .login-brand .k { margin-top: 7px; font-size: clamp(10px, 2vw, 14px); font-weight: 700;
    letter-spacing: .4em; color: var(--dim); text-transform: uppercase; }
  .login-brand .g { margin-top: 8px; font-size: clamp(10px, 1.8vw, 13px); font-weight: 600; color: var(--dim); }
  .login-card { position: relative; background: var(--panel); border: 1px solid var(--line);
    padding: 26px 28px; width: min(380px, 100%); box-shadow: 0 24px 60px rgba(0,0,0,.35); }
  .login-card::before { content: ''; position: absolute; top: -1px; left: -1px; right: -1px; height: 3px;
    background: linear-gradient(90deg, #FF6A2C, #2D5BFF); }
  html[data-theme="light"] .login-card { box-shadow: 0 24px 60px rgba(10,14,26,.12); }
  .login-card h2 { font-size: 14px; font-weight: 700; letter-spacing: 3px; text-transform: uppercase;
    margin-bottom: 4px; border-bottom: 1px solid var(--fg); padding-bottom: 8px; }
  .login-card p { color: var(--dim); font-size: 10px; margin-bottom: 22px; letter-spacing: 1.5px; text-transform: uppercase; }
  #login-btn { background: linear-gradient(90deg, #FF6A2C, #2D5BFF); border: 1px solid transparent;
    color: #fff; font-weight: 700; letter-spacing: 2px; padding: 11px 12px; font-size: 12px; }
  #login-btn:hover { filter: brightness(1.15); background: linear-gradient(90deg, #FF6A2C, #2D5BFF); color: #fff; }
  .login-foot { text-align: center; position: relative; font-family: 'Archivo','Segoe UI',Arial,sans-serif; }
  .login-foot .pow { display: block; font-size: 11px; font-weight: 600; color: var(--dim); }
  .login-foot .wm { margin-top: 4px; font-size: 20px; font-weight: 900; letter-spacing: -.02em;
    display: inline-flex; align-items: center; gap: 7px; color: var(--fg); }
  .login-foot .wm .m { color: var(--brand-ink); }
  .login-foot .wm .oo { color: #2D5BFF; }
  .login-foot .wm svg polygon { fill: #2D5BFF; }
  .login-foot .site { display: block; margin-top: 2px; font-size: 10px; font-weight: 600; color: var(--dim); opacity: .8; }
  .field { margin-bottom: 14px; }
  .field label { display: block; font-size: 9px; color: var(--dim); margin-bottom: 4px; letter-spacing: 1.5px; text-transform: uppercase; }
  /* `outline: none` here is (0,1,1) and the app's global focus ring at :781 is
     (0,1,0), so THIS RULE WON and the two sign-in fields were the only controls
     in the app with no focus outline — falling back to a 1px border-colour
     change. Scoped to :not(:focus-visible) so the reset still suppresses the UA
     ring on mouse focus, which is what it was for, without out-specifying the
     keyboard one. (Epic AC / AC3 phase 2.) */
  .field input { width: 100%; padding: 7px 10px; background: var(--bg); border: 1px solid var(--line);
    color: var(--fg); font-family: inherit; font-size: 12px; }
  .field input:not(:focus-visible) { outline: none; }
  .field input:focus { border-color: var(--fg); }
  .error-msg { color: var(--fg); font-size: 10px; margin-top: 8px; letter-spacing: 1px; text-transform: uppercase; }

  /* ── Config grid ───────────────────────────────────────── */
  .config-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1px; background: var(--line); border: 1px solid var(--line); margin-bottom: 18px; }
  .config-item { background: var(--bg); padding: 10px 12px; display: flex; align-items: center; gap: 10px; }
  .config-icon { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center;
    font-size: 11px; flex-shrink: 0; border: 1px solid var(--fg); font-weight: 700; }
  .config-icon.ok::before   { content: '✓'; }
  .config-icon.fail::before { content: '✗'; }
  .config-icon.ok, .config-icon.fail { background: transparent; }
  .config-icon.fail { border-style: dashed; }
  .config-text { flex: 1; }
  .config-text strong { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
  .config-text p { font-size: 10px; color: var(--dim); margin-top: 1px; }

  /* ── Refresh ───────────────────────────────────────────── */
  /* min-height + inline-flex for WCAG 2.2 AA 2.5.8: measured 78x21, three
     pixels short. Not a `.btn`, so Z4's floor on that class did not reach it.
     (Epic AC / AC3 phase 2.) */
  .refresh-btn { background: transparent; border: 1px solid var(--dim2); color: var(--dim);
    padding: 4px 10px; cursor: pointer; font-size: 10px; font-family: inherit;
    letter-spacing: 1.4px; text-transform: uppercase;
    min-height: 24px; display: inline-flex; align-items: center; justify-content: center; }
  .refresh-btn:hover { border-color: var(--fg); color: var(--fg); }
  /* The per-row queue checkbox is a bare 13x13 input in a <td> — the only one
     of the four flagged checkboxes with NO wrapping label, which is why the
     label allowance in a11y-rules.mjs cleared the other three and not this one.
     A wrapping label is the right fix rather than a bigger glyph: it makes the
     24px box the activation area, which is what 2.5.8 measures, and clicking
     the padding now toggles the row. (Epic AC / AC3 phase 2.) */
  .queue-cb-hit { display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; min-height: 24px; cursor: pointer; }

  /* ── Ticker pill ───────────────────────────────────────── */
  .ticker { display: inline-block; border: 1px solid var(--fg); color: var(--fg);
    padding: 0 5px; font-size: 10px; font-weight: 700; letter-spacing: 1px; margin: 1px;
    background: transparent; cursor: pointer; transition: background .12s, color .12s; }
  .ticker:hover { background: var(--fg); color: var(--bg); }

  /* ── Loader ────────────────────────────────────────────── */
  .loader { display: inline-block; width: 10px; height: 10px;
    border: 1px solid var(--dim2); border-top-color: var(--fg); border-radius: 50%;
    animation: spin .8s linear infinite; }
  @keyframes spin { to { transform: rotate(360deg); } }

  /* ── Skeleton loading states — shaped placeholders instead of dashes ────── */
  .skel { display: block; height: 14px; border-radius: 3px;
    background: linear-gradient(90deg, var(--panel) 25%,
      color-mix(in srgb, var(--fg) 9%, var(--panel)) 50%, var(--panel) 75%);
    background-size: 200% 100%; animation: skelShimmer 1.3s linear infinite; }
  .skel-lg { height: 22px; width: 70%; }
  .skel-sm { height: 10px; width: 45%; margin-top: 6px; }
  .skel-block { height: 64px; }
  @keyframes skelShimmer { to { background-position: -200% 0; } }
  @media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

  /* ── Progress bar ──────────────────────────────────────── */
  .progress-bar { height: 2px; background: var(--line); overflow: hidden; margin-top: 6px; }
  .progress-fill { height: 100%; background: var(--fg); transition: width .4s; }

  /* ── Toast (js/ui-utils.js showToast) ─────────────────────
     Colors are fixed, not theme tokens: white on the Tailwind-500 pair
     measured 2.28:1 (success) and 3.76:1 (error) — both under WCAG AA's
     4.5:1 for body text, on a control that carries the only confirmation
     some actions give. The 700/800 shades below keep the semantic colour
     and clear the bar (7.13:1 and 6.47:1). */
  #toast-el { position: fixed; bottom: 28px; right: 28px; padding: 12px 20px;
    border-radius: 8px; font-size: 14px; font-weight: 500; color: #fff;
    z-index: 9999; opacity: 0; pointer-events: none; transition: opacity .3s;
    background: #166534; }
  #toast-el.error { background: #b91c1c; }
  #toast-el.show { opacity: 1; }

  /* ── Layout helpers ────────────────────────────────────── */
  .two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 18px; }
  @media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }
  /* A grid item defaults to `min-width:auto`, so its track cannot shrink below
     the item's min-content — and with `table{min-width:480px}` below, any
     .two-col cell holding a table has a 480px floor. Collapsing to one column
     therefore did NOT make the report fit a phone: at 390px the second .two-col
     resolved a 482px TRACK inside a 366px box and pushed "By ticker" and
     "TradeOS agent" 104px off the screen, with nothing to scroll to them. The
     table is already inside .table-wrap, which scrolls; this just lets the
     track shrink so the wrapper can do its job. (Epic Q / Q2.) */
  .two-col > * { min-width: 0; }

  .section-title { font-size: 12px; font-weight: 600; color: var(--fg);
    letter-spacing: .4px; margin-bottom: 8px;
    border-bottom: 1px solid var(--line); padding-bottom: 4px; }

  /* ── Override colored inline backgrounds from old code ─── */
  [style*="rgba(99,102,241"],
  [style*="rgba(74,222,128"],
  [style*="rgba(248,113,113"],
  [style*="rgba(251,146,60"],
  [style*="rgba(96,165,250"],
  [style*="rgba(251,191,36"] { background: transparent !important; border-color: var(--line) !important; }
  /* Hardcoded light text hex → theme fg (legacy var names are handled by aliases) */
  [style*="color:#a78bfa"], [style*="color:#e2e8f0"], [style*="color:#fff"],
  [style*="color:#8892b0"], [style*="color:#e6edf3"], [style*="color:#0f1117"],
  [style*="color:#0d0f1a"] { color: var(--fg) !important; }
  /* Hardcoded dark surface hex → theme panel */
  [style*="background:#0f1117"],
  [style*="background:#0d0f1a"],
  [style*="background:#0a0c14"],
  [style*="background:#0d0b1a"] { background: var(--panel) !important; }
  [style*="border:1px solid #3730a3"],
  [style*="border:1px solid #1e2035"],
  [style*="border-color:rgba(99,102,241"] { border-color: var(--line) !important; }
  [style*="border-radius"] { border-radius: 0 !important; }
  code, pre { font-family: inherit; color: var(--fg); }

  /* Sidebar utility-row button override */
  .sidebar .util-row > button { background: transparent !important;
    border: 1px solid var(--dim2) !important; color: var(--dim) !important;
    font-family: inherit !important; letter-spacing: 1px; text-transform: uppercase; }
  .sidebar .util-row > button:hover { border-color: var(--fg) !important; color: var(--fg) !important; }

  /* ── Dashboard hero + collapsible secondary sections ─────────────────────
     The P/L band answers "how am I doing" at a glance: Today reads largest,
     the rest support it. Secondary blocks (Infographics, Instance Overview,
     Accounts) collapse behind <details> so the first screen stays calm. */
  .cards.hero { grid-template-columns: 1.7fr repeat(5, 1fr) !important; gap: 0; }
  .cards.hero .card { border: 1px solid var(--line); border-left-width: 0; }
  .cards.hero .card:first-child { border-left-width: 1px; position: relative; padding: 14px 16px; }
  .cards.hero .card:first-child::before { content: ''; position: absolute; left: 0; right: 0;
    top: 0; height: 2px; background: var(--brand-grad); }
  .cards.hero .card:first-child .card-value { font-size: 32px; line-height: 1.15; }
  details.collapse { border: 1px solid var(--line); margin-bottom: 14px; background: var(--bg); }
  details.collapse > summary { list-style: none; cursor: pointer; padding: 9px 12px;
    font-size: 12px; font-weight: 600; color: var(--fg); display: flex; align-items: center; gap: 8px; }
  details.collapse > summary::-webkit-details-marker { display: none; }
  details.collapse > summary::before { content: '\25B8'; font-size: 10px; color: var(--dim);
    transition: transform .15s ease; }
  details.collapse[open] > summary::before { transform: rotate(90deg); }
  details.collapse > summary:hover { background: var(--panel); }
  details.collapse > .collapse-body { padding: 10px 12px 12px; border-top: 1px solid var(--line); }

  /* ── Trade Terminal — centered modal ─────────────────────────────────────
     dvh (visual viewport) sizing + a pinned input row mean the command line
     can never be pushed under the footer, taskbar, or on-screen keyboard. */
  #cmd-backdrop { display: none; position: fixed; inset: 0;
    background: rgba(0,0,0,.55); z-index: 1090; }
  #cmd-backdrop.show { display: block; }
  #cmd-panel { display: none; position: fixed; left: 50%; top: 50%;
    transform: translate(-50%,-50%);
    width: min(860px, calc(100vw - 24px));
    height: min(72vh, 560px); height: min(72dvh, 560px);
    max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px);
    background: #0a0c14; border: 1px solid var(--accent); border-radius: 10px;
    box-shadow: 0 18px 60px rgba(0,0,0,.6); z-index: 1100; overflow: hidden;
    font-family: 'Cascadia Code','Consolas',monospace; font-size: 13px;
    flex-direction: column; }
  #cmd-panel.open { display: flex; }
  .cmd-head { display: flex; justify-content: space-between; align-items: center;
    padding: 8px 14px; border-bottom: 1px solid #1e2035; background: #0d0f1a;
    flex: 0 0 auto; }
  .cmd-title { color: var(--accent); font-weight: 600; }
  .cmd-head-right { display: flex; gap: 12px; align-items: center; min-width: 0; }
  .cmd-hint { color: var(--muted); font-size: 11px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
  .cmd-close { background: none; border: none; color: var(--muted);
    cursor: pointer; font-size: 16px; line-height: 1; flex: 0 0 auto; }
  #cmd-log { flex: 1 1 auto; min-height: 0; overflow-y: auto;
    padding: 10px 14px; line-height: 1.7; white-space: pre-wrap; }
  .cmd-input-row { display: flex; align-items: center; gap: 10px;
    border-top: 1px solid #1e2035; background: #0d0f1a; padding: 8px 14px;
    padding-bottom: max(8px, env(safe-area-inset-bottom)); flex: 0 0 auto; }
  .cmd-prompt { color: var(--accent); }
  .cmd-input-row input { flex: 1; background: transparent; border: none;
    outline: none; color: #e2e8f0; font-family: inherit; font-size: 13px; }
  .cmd-run { background: var(--accent); border: none; color: #fff;
    padding: 4px 14px; border-radius: 5px; cursor: pointer; font-size: 12px; }
  [data-theme="mono"] #cmd-panel { border-radius: 0; }
  @media (max-width: 640px) {
    #cmd-panel { width: calc(100vw - 12px);
      height: min(85vh, 560px); height: min(85dvh, 560px); }
    .cmd-hint { display: none; }
  }

  /* ═══════════════ RESPONSIVE — tablet & mobile ═══════════════ */
  /* Tables scroll horizontally instead of squishing on narrow screens */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table { min-width: 480px; }

  /* Tablet & mobile: sidebar becomes a slide-in drawer behind a hamburger */
  @media (max-width: 1024px) {
    .app { flex-direction: column; height: auto; min-height: 100vh; }
    .topbar { display: flex; }
    .hamburger { display: flex; }
    .sidebar {
      position: fixed; top: 0; left: 0; bottom: 0; width: 240px; max-width: 82vw;
      transform: translateX(-100%); transition: transform .22s ease; z-index: 100;
      box-shadow: 2px 0 16px rgba(0,0,0,.5);
    }
    .sidebar.open { transform: translateX(0); }
    .sidebar.open ~ .sidebar-backdrop,
    .sidebar-backdrop.show { display: block; }
    .main { width: 100%; }
    /* nav links bigger touch targets on the drawer */
    .nav-item { padding: 12px 16px; font-size: 12px; }
  }

  /* Phones: tighten spacing, single-column grids, smaller type */
  @media (max-width: 640px) {
    html, body { font-size: 11px; }
    .page { padding: 12px 12px 20px; }
    .cards { grid-template-columns: repeat(2, 1fr) !important; gap: 8px; }
    .two-col { grid-template-columns: 1fr !important; }
    .card-value { font-size: 17px; }
    .page-title { font-size: 12px; letter-spacing: 1.5px; }
    /* stack the config/credential grids */
    .config-grid, #cred-grid, #pnl-cards { grid-template-columns: 1fr !important; }
    /* modals fill the screen */
    #log-modal, #td-modal, #theme-modal { width: 100vw !important; max-width: 100vw !important;
      height: 100vh !important; max-height: 100vh !important; top: 0 !important; left: 0 !important;
      transform: none !important; }
    .topbar-title { font-size: 11px; }
    /* hero cards stack on phones — restore each card's own left border */
    .cards.hero .card { border-left-width: 1px; }
    .cards.hero .card:first-child .card-value { font-size: 24px; }
    /* comfortable touch targets (WCAG 2.5.5 / Fitts) */
    .btn, button { min-height: 38px; }
    .nav-item { min-height: 44px; }
    /* room for the bottom tab bar */
    .main { padding-bottom: calc(58px + env(safe-area-inset-bottom, 0px)); }
    .tabbar { display: flex; }

    /* ── Kill the whole-page horizontal ("right") scroll on long displays ──────
       Anything genuinely wide (tables, sub-nav) keeps its OWN scroll container;
       the page itself is clamped to the viewport so it can only scroll down. */
    html, body { overflow-x: hidden; }
    .main, .page, .subpage { max-width: 100vw; overflow-x: hidden; }
    /* Long tokens/urls/hashes wrap instead of stretching the page */
    .page, .subpage { overflow-wrap: anywhere; word-break: break-word; }
    /* Fixed multi-column grids (forms, KPI rows) collapse so they never overflow */
    .form-grid, .cols-2, .cols-3 { grid-template-columns: 1fr !important; }
    /* Media/inputs/pre can't exceed their column */
    img, video, canvas, pre, table { max-width: 100%; }
    pre { white-space: pre-wrap; word-break: break-word; }
    input, select, textarea { max-width: 100%; }
  }

  /* ── Mobile bottom tab bar — the 4 core destinations + Menu (drawer) ────────
     Hidden ≥641px; the sidebar remains the full nav. One-thumb reach, 44px+
     targets, safe-area aware. Active state synced by showPage(). */
  .tabbar { display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
    background: var(--bg); border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom, 0px); }
  .tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 8px 2px 6px; min-height: 52px; background: transparent; border: none;
    color: var(--dim); font-family: inherit; font-size: 8px; font-weight: 700;
    letter-spacing: .8px; text-transform: uppercase; cursor: pointer; }
  .tab-item .t-ico { font-size: 16px; line-height: 1; }
  .tab-item.active { color: var(--fg); }
  .tab-item.active .t-ico { color: var(--accent, var(--fg)); }
  /* must follow the base .tabbar rule — same specificity, source order decides */
  @media (max-width: 640px) { .tabbar { display: flex; } }

  /* Honor iOS safe-area insets (notch) */
  @supports (padding: env(safe-area-inset-top)) {
    .topbar { padding-top: calc(10px + env(safe-area-inset-top)); }
    .sidebar { padding-bottom: env(safe-area-inset-bottom); }
  }

  /* ── PWA install: default-on banner + guided install sheet ─────────────────
     The banner is the DEFAULT install affordance for anyone not running the
     installed app: one-tap install where the browser exposes a prompt
     (Android/desktop Chromium), a guided Share → Add to Home Screen sheet on
     iOS. "Later" snoozes it; the sidebar's Install App entry always remains. */
  .install-banner { position: fixed; left: 12px; right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px)); z-index: 1500;
    display: none; align-items: center; gap: 12px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
    padding: 12px 14px; box-shadow: 0 12px 40px rgba(0,0,0,.55);
    transform: translateY(16px); opacity: 0;
    transition: transform .28s ease, opacity .28s ease; }
  .install-banner.show { display: flex; transform: translateY(0); opacity: 1; }
  /* phones: sit above the bottom tab bar */
  @media (max-width: 640px) {
    .install-banner { bottom: calc(70px + env(safe-area-inset-bottom, 0px)); }
  }
  /* desktop/tablet: compact card, bottom-right */
  @media (min-width: 641px) {
    .install-banner { left: auto; right: 18px; bottom: 18px; max-width: 400px; }
  }
  .install-banner .ib-icon { width: 40px; height: 40px; border-radius: 9px; flex-shrink: 0; }
  .install-banner .ib-title { font-size: 12px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase; }
  .install-banner .ib-sub { font-size: 10px; color: var(--dim); margin-top: 2px; line-height: 1.45; }
  .install-banner .ib-install { background: var(--fg); color: var(--bg); border: 1px solid var(--fg);
    font-family: inherit; font-size: 10px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
    padding: 9px 14px; border-radius: 5px; cursor: pointer; white-space: nowrap; min-height: 38px; }
  .install-banner .ib-later { background: transparent; color: var(--dim); border: none;
    font-family: inherit; font-size: 10px; letter-spacing: .5px; padding: 9px 4px; cursor: pointer;
    white-space: nowrap; min-height: 38px; }
  .install-banner .ib-install:hover, .install-banner .ib-later:hover { filter: brightness(1.2); }

  .install-sheet-backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.65); z-index: 1510; }
  .install-sheet { display: none; position: fixed; left: 50%; bottom: 0; transform: translateX(-50%);
    width: min(460px, 100vw); max-height: 86vh; overflow-y: auto; background: var(--bg);
    border: 1px solid var(--line); border-bottom: none; border-radius: 14px 14px 0 0; z-index: 1511;
    padding: 18px 18px calc(18px + env(safe-area-inset-bottom, 0px)); }
  @media (min-width: 641px) {
    .install-sheet { bottom: auto; top: 50%; transform: translate(-50%, -50%);
      border-radius: 12px; border-bottom: 1px solid var(--line); }
  }
  .install-sheet .is-step { display: flex; gap: 12px; align-items: flex-start; margin: 14px 0; }
  .install-sheet .is-num { width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--fg);
    display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; flex-shrink: 0; }
  .install-sheet .is-glyph { color: var(--accent, var(--fg)); vertical-align: -3px; }
  /* Running as the installed app: every install affordance disappears */
  html.standalone .install-banner, html.standalone #install-app-btn,
  html.standalone #ios-install-hint, html.standalone #nav-install { display: none !important; }

  /* Page switch: subtle fade+rise so SPA navigation feels intentional */
  @media (prefers-reduced-motion: no-preference) {
    .page.active { animation: pageIn .18s ease; }
    @keyframes pageIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
  }

  /* ═══════════════ BRAND: logo mark, splash, logout ═══════════════ */
  /* Logo mark — inherits theme color via currentColor */
  .logo-row { display: flex; align-items: center; gap: 9px; }
  .logo-mark { color: var(--fg); flex-shrink: 0; }
  .logo-mark .pulse { stroke-dasharray: 60; stroke-dashoffset: 0; }
  .logo .logo-sub { font-size: 9px; color: var(--dim); letter-spacing: 1.5px;
    text-transform: uppercase; margin-top: 3px; }
  .topbar .logo-mark { color: var(--fg); }

  /* Logout button */
  /* (user-chip / logout-row retired — identity + sign-out live in the compact
     .server-status / .util-row stack now) */

  /* Interstitial loading splash — BiGMo brand interstitial (fixed midnight palette,
     independent of app theme so the entry moment is always on-brand). */
  #loading-screen { position: fixed; inset: 0; z-index: 3000;
    background: radial-gradient(130% 120% at 88% -20%, #16223C, #0A0E1A 62%);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    overflow: hidden; transition: opacity .45s ease;
    font-family: 'Archivo','Segoe UI',Arial,sans-serif; }
  #loading-screen.hidden { opacity: 0; pointer-events: none; }
  /* constellation motif */
  .splash-const { position: absolute; right: -60px; top: -60px; opacity: .45; pointer-events: none;
    width: clamp(220px, 40vw, 520px); height: auto; }
  .splash-const * { stroke: #2D5BFF; }
  /* ECG sweep */
  .splash-ecg-wrap { position: absolute; left: 0; top: 36%; width: 100%;
    transform: translateY(-50%); pointer-events: none; }
  .splash-ecg { width: 100%; height: clamp(120px, 22vh, 220px); display: block; }
  .splash-ecg .base { stroke: url(#mpPulseGrad); opacity: .16; }
  .splash-ecg .beat { stroke: url(#mpPulseGrad);
    stroke-dasharray: 16 84; stroke-dashoffset: 100; animation: mpBeat 2.4s linear infinite; }
  @keyframes mpBeat { to { stroke-dashoffset: 0; } }
  /* lockup */
  .splash-lockup { position: relative; text-align: center; padding: 0 18px;
    animation: mpRise .9s cubic-bezier(.2,.7,.2,1) both; }
  @keyframes mpRise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
  .splash-title { font-size: clamp(38px, 9vw, 92px); font-weight: 900; letter-spacing: -.02em;
    color: #E8ECF2; line-height: 1.05; }
  .splash-title .pulse-word { color: var(--brand-ink); }
  .splash-kicker { margin-top: 10px; font-size: clamp(11px, 2.4vw, 24px); font-weight: 700;
    letter-spacing: .42em; color: #C6CBD3; text-transform: uppercase; }
  .splash-tag { margin-top: 18px; font-size: clamp(11px, 2vw, 20px); font-weight: 600; color: #C6CBD3; }
  .splash-bar { margin: 42px auto 0; width: min(600px, 72vw); height: 8px; border-radius: 4px;
    background: rgba(255,255,255,.10); overflow: hidden; position: relative; }
  .splash-bar > i { position: absolute; inset: 0; width: 38%; border-radius: 4px;
    background: linear-gradient(90deg, #FF6A2C, #2D5BFF);
    animation: mpSlide 1.6s cubic-bezier(.45,.05,.55,.95) infinite; }
  @keyframes mpSlide { 0% { transform: translateX(-110%); } 55%,100% { transform: translateX(180%); } }
  .splash-msg { margin-top: 18px; font-size: clamp(12px, 1.6vw, 16px); font-weight: 600; color: #C6CBD3; }
  .splash-msg span { animation: mpBlink 1.4s infinite; }
  .splash-msg span:nth-child(2) { animation-delay: .2s; }
  .splash-msg span:nth-child(3) { animation-delay: .4s; }
  @keyframes mpBlink { 0%,60%,100% { opacity: .15; } 30% { opacity: 1; } }
  /* powered-by footer */
  .splash-foot { position: absolute; bottom: max(22px, env(safe-area-inset-bottom)); left: 0; right: 0;
    text-align: center; }
  .splash-foot .pow { font-size: 12px; font-weight: 600; color: #C6CBD3; }
  .splash-foot .wm { margin-top: 6px; font-size: clamp(20px, 3vw, 28px); font-weight: 900;
    letter-spacing: -.02em; display: inline-flex; align-items: center; gap: 9px; color: #E8ECF2; }
  .splash-foot .wm .m { color: var(--brand-ink); }
  .splash-foot .wm .oo { color: #5C82FF; }
  .splash-foot .wm svg polygon { fill: #2D5BFF; }
  .splash-foot .site { margin-top: 4px; font-size: 11px; font-weight: 600; color: #C6CBD3; opacity: .8; }
  /* light theme keeps the brand's light interstitial */
  html[data-theme="light"] #loading-screen { background: #F5F7FB; }
  html[data-theme="light"] .splash-title,
  html[data-theme="light"] .splash-foot .wm { color: #0A0E1A; }
  html[data-theme="light"] .splash-kicker, html[data-theme="light"] .splash-tag,
  html[data-theme="light"] .splash-msg, html[data-theme="light"] .splash-foot .pow,
  html[data-theme="light"] .splash-foot .site { color: #5A6478; }
  html[data-theme="light"] .splash-foot .wm .oo { color: #2D5BFF; }
  html[data-theme="light"] .splash-bar { background: rgba(10,14,26,.10); }
  @media (prefers-reduced-motion: reduce) {
    .splash-lockup, .splash-bar > i, .splash-msg span,
    .splash-ecg .beat, #login-ecg .beat { animation: none; }
    .splash-ecg .beat, #login-ecg .beat { stroke-dasharray: none; stroke-dashoffset: 0; opacity: .5; }
  }

  /* ── Doc modal (rendered markdown) ─────────────────────── */
  #doc-backdrop { display:none; position:fixed; inset:0; background:rgba(0,0,0,.7); z-index:1300; }
  #doc-modal { display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);
    width:min(860px,94vw); max-height:88vh; background:var(--bg); border:1px solid var(--fg);
    z-index:1301; flex-direction:column; }
  #doc-head { display:flex; justify-content:space-between; align-items:center; padding:12px 18px;
    border-bottom:1px solid var(--line); background:var(--panel); }
  #doc-head b { font-size:13px; letter-spacing:2px; text-transform:uppercase; }
  #doc-main { display:flex; flex:1; overflow:hidden; min-height:0; }
  #doc-toc { width:210px; flex-shrink:0; border-right:1px solid var(--line); overflow-y:auto;
    padding:14px 10px; background:var(--panel); }
  #doc-toc a { display:block; padding:4px 8px; font-size:11px; color:var(--dim); text-decoration:none;
    border-left:2px solid transparent; line-height:1.4; }
  #doc-toc a:hover { color:var(--fg); }
  #doc-toc a.h3 { padding-left:20px; font-size:10px; }
  #doc-toc a.active { color:var(--fg); border-left-color:var(--accent); }
  #doc-body { overflow-y:auto; -webkit-overflow-scrolling:touch; padding:20px 24px; flex:1; min-width:0; }
  .md mark { background:var(--warn); color:var(--bg); }
  .md mark.cur { background:var(--accent); }
  /* Markdown render styles */
  .md { font-size:13px; line-height:1.7; color:var(--fg); }
  .md h1 { font-size:20px; margin:6px 0 12px; padding-bottom:6px; border-bottom:1px solid var(--fg); letter-spacing:1px; }
  .md h2 { font-size:16px; margin:20px 0 10px; padding-bottom:4px; border-bottom:1px solid var(--line); letter-spacing:.5px; }
  .md h3 { font-size:14px; margin:16px 0 8px; color:var(--fg); }
  .md p { margin:10px 0; }
  .md ul, .md ol { margin:10px 0 10px 22px; }
  .md li { margin:4px 0; }
  .md a { color:var(--accent); text-decoration:underline; }
  .md code { font-family:'Cascadia Mono',monospace; background:var(--panel); border:1px solid var(--line);
    padding:1px 5px; font-size:12px; }
  .md pre { background:var(--panel); border:1px solid var(--line); padding:12px 14px; overflow-x:auto; margin:12px 0; }
  .md pre code { background:none; border:none; padding:0; font-size:12px; line-height:1.5; }
  .md blockquote { border-left:3px solid var(--accent); padding:4px 14px; margin:12px 0; color:var(--dim); }
  .md hr { border:none; border-top:1px solid var(--line); margin:18px 0; }
  .md table { width:100%; border-collapse:collapse; margin:12px 0; font-size:12px; display:block; overflow-x:auto; }
  .md th, .md td { border:1px solid var(--line); padding:6px 10px; text-align:left; }
  .md th { background:var(--panel); }
  .md img { max-width:100%; }
  @media (max-width:900px) {
    #doc-toc-toggle { display:block !important; }
    #doc-toc { position:absolute; top:0; bottom:0; left:0; z-index:5; width:230px;
      transform:translateX(-100%); transition:transform .2s; box-shadow:2px 0 12px rgba(0,0,0,.4); }
    #doc-main.toc-open #doc-toc { transform:translateX(0); }
  }
  @media (max-width:640px) {
    #doc-modal { width:100vw; max-width:100vw; height:100vh; max-height:100vh; top:0; left:0; transform:none; border:none; }
    #doc-main { position:relative; }
    #doc-body { padding:14px 16px; }
    #doc-search { width:110px; }
    .md { font-size:13px; } .md h1 { font-size:18px; } .md h2 { font-size:15px; }
  }
  /* Review-queue item detail modal */
  #item-backdrop { display:none; position:fixed; inset:0; background:rgba(0,0,0,.7); z-index:1300; }
  #item-modal { display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);
    width:min(680px,94vw); max-height:88vh; overflow:hidden; background:var(--bg); border:1px solid var(--fg);
    z-index:1301; flex-direction:column; }
  .queue-title-link { cursor:pointer; }
  .queue-title-link:hover { text-decoration:underline; }
  @media (max-width:640px) {
    #item-modal { width:100vw; max-width:100vw; height:100vh; max-height:100vh; top:0; left:0; transform:none; border:none; }
  }
  /* Accessibility: visible keyboard focus + reduced-motion support */
  :focus-visible { outline: 2px solid var(--accent, #3ad36a); outline-offset: 2px; border-radius: 3px; }
  @media (prefers-reduced-motion: reduce) { * { animation-duration:.001ms !important; transition-duration:.001ms !important; } }
