  /* ── Environment badge (Phase B6: dev/prod identification) ───────────────
     Hidden by default; auth-bootstrap toggles display + adds a tier class
     (env-dev / env-staging / etc.) when /api/config.instance is non-prod.
     Sits in the header next to the live indicator and admin badge. */
  .env-badge {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.14em;
    padding: 4px 8px;
    border-radius: 4px;
  }
  .env-badge.env-dev {
    background: rgba(245, 158, 11, 0.15);          /* amber-500 @ 15% */
    color: #fbbf24;                                  /* amber-400 */
    border: 1px solid rgba(245, 158, 11, 0.45);
  }
  /* Future tiers slot in the same way: .env-badge.env-staging { ... } */

  /* Font families are managed by src/frontend/fonts.js (4/29/26).
     Default = system stacks (zero egress, instant). Three Google
     Fonts options (JetBrains / IBM Plex / Geist) are loaded lazily
     when the user picks one in the header dropdown. The previous
     self-hosted Atkinson Hyperlegible setup was 404'ing in
     production because the .woff2 files weren't being copied into
     the deployed bundle — every browser was already falling back
     to system anyway, so this is a clean cut. */

  /* ─── THEME TOKENS ───────────────────────────────────────────────
     Three themes selected via <html data-theme="…">:
       (default — no attr)         → Original  (terminal-dense, purple-accent)
       [data-theme="compass-black"] → Compass Black  (clean dark, less chrome)
       [data-theme="compass-white"] → Compass White  (light, professional)

     Brand data-encoding colors (--pika = positive GEX yellow, --barney =
     negative GEX purple, --king = orange, --gate = teal) are PRESERVED
     across themes so users don't need to relearn the visual encoding —
     they just shift saturation slightly for white-bg readability when
     needed. The themes vary the CHROME (bg, text, borders, grid pattern,
     glow/shadow) more than the data colors.

     Adding a new theme: copy a [data-theme=…] block below, tweak values,
     add an entry to the THEMES registry in app.js + a row in
     renderLadderCogPopover()'s theme picker.
  */
  :root {
    --bg: #080b0f;
    --bg2: #0d1117;
    --bg3: #111820;
    --bg4: #161e28;
    --border: rgba(255,255,255,0.06);
    --border2: rgba(255,255,255,0.1);
    --text: #e8eaed;
    --text2: #8b95a1;
    --text3: #4a5568;
    --pika: #f5c842;
    --pika2: rgba(245,200,66,0.15);
    --pika3: rgba(245,200,66,0.06);
    --barney: #9b5de5;
    --barney2: rgba(155,93,229,0.15);
    --barney3: rgba(155,93,229,0.06);
    --king: #ff6b35;
    --king2: rgba(255,107,53,0.2);
    --gate: #00d4aa;
    --gate2: rgba(0,212,170,0.15);
    --red: #ef4444;
    --green: #22c55e;
    --blue: #3b82f6;
    --flip: #60a5fa;
    /* fonts.js overrides these via inline style on <html> when the
       user picks a non-system family. The values below are the
       initial-paint defaults; ANY non-system choice is applied
       before first render via the import side-effect in fonts.js. */
    --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
    --sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* Theme-tunable chrome flags. Original keeps the grid pattern + glow
       effects characteristic of the terminal-dense look; the White theme
       drops them to read cleaner. */
    --grid-color:   rgba(255,255,255,0.015);
    --shadow-card:  0 4px 16px rgba(0,0,0,0.25);
    --shadow-glow:  0 0 18px rgba(255,107,53,0.06);
    --bg-input:     rgba(255,255,255,0.04);
    /* Spot-row anchor — these mark the strike-row containing current spot.
       Original uses a near-white left zone to make spot pop on dark bg.
       Light themes invert to a dark accent so the zone stays a visual
       anchor rather than disappearing into the white surface. Replaces
       the previous hardcoded rgba(255,255,255,0.92) values in
       app.js DS object. */
    --spot-pill-bg:     rgba(255,255,255,0.92);
    --spot-pill-color:  #080b0f;
    --spot-arrow-color: rgba(255,255,255,0.35);
    --spot-zone-bg:     rgba(255,255,255,0.92);
    --spot-border-color:rgba(255,255,255,0.9);
    --badge-pill-bg:    rgba(0,0,0,0.55);
    /* Faint text — non-flagged strike numbers, dim labels. Replaces
       hardcoded rgba(255,255,255,0.55) at call sites so light themes
       can flip to a dark variant. */
    --text-faint:       rgba(255,255,255,0.55);
    /* Subtle backgrounds — hover states, dim panels, table-row stripes.
       Replace the dozen+ hardcoded `rgba(255,255,255,0.0X)` uses across
       app.css. White theme gets dark-on-white inversions so subtle
       affordances (hover, alt-row) stay visible. */
    --bg-hover:         rgba(255,255,255,0.025);
    --bg-subtle:        rgba(255,255,255,0.04);
    /* Spot-row pulse animation endpoints — used by spotBorderPulse +
       spotShadowPulse keyframes. Original hardcoded full-bright white
       at peak; themes can supply contrast-appropriate values. */
    --spot-pulse-strong: rgba(255,255,255,0.95);
    --spot-pulse-faint:  rgba(255,255,255,0.25);
  }

  /* ── White ────────────────────────────────────────────────────
     Light professional. Bg flips to near-white; text to near-black;
     borders to subtle dark; data-encoding accents shift darker for
     contrast on white surfaces (yellow→amber, light-violet→darker
     violet, etc.). Spot-row zone inverts to a near-black panel so
     the visual anchor remains. */
  [data-theme="white"] {
    --bg:    #f7f8fa;
    --bg2:   #ffffff;
    --bg3:   #f1f3f6;
    --bg4:   #e8ecf1;
    --border:  rgba(0,0,0,0.07);
    --border2: rgba(0,0,0,0.11);
    --text:    #0f172a;
    --text2:   #475569;
    --text3:   #94a3b8;
    /* Darker accents for white-bg readability */
    --pika:    #b45309;        /* amber — yellow is illegible on white */
    --pika2:   rgba(180,83,9,0.12);
    --pika3:   rgba(180,83,9,0.05);
    --barney:  #7c3aed;        /* darker violet */
    --barney2: rgba(124,58,237,0.12);
    --barney3: rgba(124,58,237,0.05);
    --king:    #dc2626;        /* red — high importance */
    --king2:   rgba(220,38,38,0.13);
    --gate:    #0d9488;        /* darker teal */
    --gate2:   rgba(13,148,136,0.13);
    --red:    #dc2626;
    --green:  #16a34a;
    --blue:   #2563eb;
    --flip:   #2563eb;
    --grid-color:   rgba(0,0,0,0);
    --shadow-card:  0 1px 0 rgba(0,0,0,0.04);
    --shadow-glow:  none;
    --bg-input:     rgba(0,0,0,0.04);
    /* Spot-row anchor inverted: dark panel on light bg, light text on it. */
    --spot-pill-bg:     #0f172a;
    --spot-pill-color:  #f7f8fa;
    --spot-arrow-color: rgba(15,23,42,0.45);
    --spot-zone-bg:     rgba(15,23,42,0.92);
    --spot-border-color:rgba(15,23,42,0.85);
    --badge-pill-bg:    rgba(255,255,255,0.85);
    /* Faint strike text reads on white bg */
    --text-faint:       rgba(15,23,42,0.55);
    /* Subtle backgrounds inverted: dark-on-white for hover / alt-row
       affordances. Slightly stronger than the dark-theme equivalents
       since subtle dark on white is harder to perceive than subtle
       light on black. */
    --bg-hover:         rgba(15,23,42,0.04);
    --bg-subtle:        rgba(15,23,42,0.05);
    /* Spot-row pulse animation — invert to dark-on-white. */
    --spot-pulse-strong: rgba(15,23,42,0.92);
    --spot-pulse-faint:  rgba(15,23,42,0.30);
  }

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

  body {
    background: var(--bg);
    color: var(--text);
    font-family: var(--sans);
    min-height: 100vh;
    overflow-x: hidden;
  }

  /* Subtle grid background. Color sourced from --grid-color so themes
     can drop it (Compass themes set it to transparent). */
  body::before {
    content: '';
    position: fixed;
    inset: 0;
    background-image:
      linear-gradient(var(--grid-color) 1px, transparent 1px),
      linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
    background-size: 40px 40px;
    pointer-events: none;
    z-index: 0;
  }

  /* ── HEADER ──
     bg uses --bg with backdrop-blur for the sticky-translucent feel.
     Themes set --bg appropriately so this transparency-overlay works
     on both dark and light surfaces.
     4/29/26: scoped to .app-navbar (the top-level page header) so it
     no longer cascades into nested <header> elements like the
     collapsible-sidebar section heads — which were inheriting
     height:52px and reading as huge bars on the Heatmap rail. */
  .app-navbar {
    position: sticky;
    top: 0;
    z-index: 100;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
    padding: 0 24px;
    height: 52px;
    display: flex;
    align-items: center;
    gap: 32px;
  }

  .logo {
    font-family: var(--sans);
    font-size: 15px;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text);
  }
  .logo span { color: var(--pika); }

  .nav-tabs {
    display: flex;
    gap: 2px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 3px;
  }
  .nav-tab {
    font-family: var(--mono);
    font-size: 11px;
    padding: 5px 14px;
    border-radius: 5px;
    cursor: pointer;
    color: var(--text2);
    letter-spacing: 0.04em;
    transition: all 0.15s;
    border: none;
    background: none;
  }
  .nav-tab.active {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border2);
  }
  .nav-tab:hover:not(.active) { color: var(--text); }

  /* (.nav-cluster* removed — flat tabs; the GEX category prefix was
     dropped in favor of a per-view GEX/VEX toggle.) */

  .header-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .live-badge {
    display: flex;
    align-items: center;
    gap: 6px;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--green);
    letter-spacing: 0.08em;
  }
  /* Market phase chip — sits left of the .live-badge. Hidden during
     regular session; reveals during extended + overnight to flag that
     server-side polling + WS broadcasts are throttled. Phase is set by
     app.js on init + transition (body[data-market-phase=...]). */
  .market-phase-chip {
    display: none;
    align-items: center;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    padding: 4px 8px;
    border-radius: 4px;
    margin-right: 8px;
  }
  body[data-market-phase="extended"] .market-phase-chip {
    display: inline-flex;
    background: rgba(245, 200, 66, 0.10);
    color: var(--pika);
    border: 1px solid rgba(245, 200, 66, 0.30);
  }
  body[data-market-phase="extended"] .market-phase-chip::before {
    content: '◐ Extended Hours';
  }
  body[data-market-phase="overnight"] .market-phase-chip {
    display: inline-flex;
    background: rgba(155, 93, 229, 0.10);
    color: var(--barney);
    border: 1px solid rgba(155, 93, 229, 0.30);
  }
  body[data-market-phase="overnight"] .market-phase-chip::before {
    content: '⏸ Markets Closed';
  }
  .live-dot {
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--green);
    animation: pulse 2s infinite;
  }
  @keyframes pulse {
    0%,100% { opacity: 1; box-shadow: 0 0 0 0 rgba(34,197,94,0.4); }
    50% { opacity: 0.8; box-shadow: 0 0 0 4px rgba(34,197,94,0); }
  }

  .regime-badge {
    font-family: var(--mono);
    font-size: 10px;
    padding: 4px 10px;
    border-radius: 4px;
    letter-spacing: 0.06em;
    font-weight: 700;
  }
  .regime-pos { background: var(--pika2); color: var(--pika); border: 1px solid rgba(245,200,66,0.3); }
  .regime-neg { background: var(--barney2); color: var(--barney); border: 1px solid rgba(155,93,229,0.3); }

  .data-source {
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
    letter-spacing: 0.04em;
  }

  /* ── VIEWS ── */
  .view { display: none; padding: 20px 24px; position: relative; z-index: 1; }
  .view.active { display: block; }

  /* ── SINGLE INSTRUMENT LAYOUT ──
     4/29/26 tighten pass: dropped from 3-column (sidebar / ladder /
     detail) to 2-column (sidebar / ladder). Per-node detail moved to
     hover tooltip (multiTooltip), pattern detector + key levels moved
     into the left sidebar. Ladder gets the freed space — no longer
     squeezed by a 320px right rail. */
  .instrument-layout {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 14px;
    height: calc(100vh - 92px);
  }

  /* ── PANELS ── */
  .panel {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .panel-header {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
  }

  .panel-title {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text2);
  }

  .panel-body {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
  }

  .panel-body::-webkit-scrollbar { width: 3px; }
  .panel-body::-webkit-scrollbar-track { background: transparent; }
  .panel-body::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

  /* ── TICKER SELECTOR ──
     4/29/26 tighten pass: cards collapsed to single-row chips. Symbol +
     price + change% on one line; the long ticker name (e.g. "iShares
     Russell 2000 ETF") moved into a title attribute (visible on hover)
     so the rail stays dense at four+ instruments. */
  .ticker-select {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px;
  }

  .ticker-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    text-align: left;
    width: 100%;
    padding: 6px 10px;
    border-radius: 5px;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s;
    border: 1px solid transparent;
    background: none;
    min-height: 28px;
  }
  .ticker-btn:hover { background: var(--bg3); border-color: var(--border); }
  .ticker-btn.active {
    background: var(--bg4);
    border-color: var(--border2);
  }

  .ticker-btn-left {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
  }
  .ticker-btn-right {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-shrink: 0;
  }

  .ticker-name {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: 0.02em;
  }
  .ticker-price {
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text2);
  }
  .ticker-change {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 600;
    min-width: 38px;
    text-align: right;
  }
  .pos { color: var(--green); }
  .neg { color: var(--red); }

  /* Legacy .ticker-meta — preserved for any in-flight use; the row
     layout no longer renders it, but admin pages or other consumers
     might. */
  .ticker-meta {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.04em;
    margin-top: 2px;
  }

  /* ── REGIME PANEL ── */
  .regime-section {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
  }

  .regime-state {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
  }

  .regime-icon {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    flex-shrink: 0;
  }

  .regime-label {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 700;
  }

  .regime-desc {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text2);
    line-height: 1.6;
    letter-spacing: 0.03em;
  }

  .regime-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-top: 10px;
  }

  .stat-cell {
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
  }

  .stat-label {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: 3px;
  }

  .stat-value {
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
  }

  /* ── NODE LADDER ── */
  .node-ladder {
    padding: 8px 0;
    position: relative;
  }

  .price-line {
    position: sticky;
    top: 0;
    z-index: 10;
    background: #130e06;
    border-top: 1px solid rgba(255,107,53,0.5);
    border-bottom: 1px solid rgba(255,107,53,0.5);
    padding: 6px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-shadow: 0 0 18px rgba(255,107,53,0.07), 0 2px 10px rgba(0,0,0,0.7);
  }

  .price-line-label {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--king);
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .price-line-value {
    font-family: var(--mono);
    font-size: 14px;
    font-weight: 700;
    color: var(--king);
  }

  .node-row {
    display: flex;
    align-items: center;
    padding: 3px 16px 3px 12px;
    gap: 8px;
    transition: background 0.1s;
    position: relative;
    -webkit-font-smoothing: antialiased;
    text-rendering: geometricPrecision;
  }
  .node-row:hover { background: var(--bg-hover); }
  .king-node { background: rgba(255,107,53,0.11); box-shadow: inset 0 0 18px rgba(255,107,53,0.06); }
  .gate-node { border-left: 2px solid rgba(0,212,170,0.3); }

  /* Spot price row — separator lines + animated left border. Top/bottom
     shadows use --spot-border-color so they're visible on both themes. */
  .node-row.at-price {
    box-shadow: 0 -2px 0 var(--spot-border-color), 0 2px 0 var(--spot-border-color);
    z-index: 1;
    position: relative;
  }
  .spot-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 13px;
    flex-shrink: 0;
    line-height: 1;
    will-change: opacity;
    animation: spotArrowPulse 1.8s ease-in-out infinite;
  }
  @keyframes spotArrowPulse {
    0%,100% { opacity: 1; }
    50%      { opacity: 0.3; }
  }
  @keyframes spotBorderPulse {
    0%,100% { border-left-color: var(--spot-pulse-strong); }
    50%      { border-left-color: var(--spot-pulse-faint); }
  }
  @keyframes spotShadowPulse {
    0%,100% { box-shadow: inset 3px 0 0 var(--spot-pulse-strong); }
    50%      { box-shadow: inset 3px 0 0 var(--spot-pulse-faint); }
  }

  .strike-label {
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text2);
    width: 54px;
    flex-shrink: 0;
    letter-spacing: 0.02em;
  }
  .strike-label.king { color: var(--king); font-weight: 700; }
  .strike-label.gate { color: var(--gate); font-weight: 600; }

  /* ── NODE BADGE — left-side icon column ── */
  .node-badge {
    width: 26px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
    filter: drop-shadow(0 0 4px currentColor);
  }
  .node-badge.empty { width: 26px; }

  .node-badge-label {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    flex-shrink: 0;
    padding-right: 4px;
  }

  .node-bar-container {
    flex: 1;
    height: 20px;
    display: flex;
    align-items: center;
    position: relative;
  }

  .node-bar {
    height: 14px;
    border-radius: 2px;
    position: absolute;
    transition: width 0.8s cubic-bezier(0.16, 1, 0.3, 1);
    min-width: 2px;
  }

  .node-bar.pika {
    background: linear-gradient(90deg, var(--pika2), var(--pika));
    left: 50%;
  }
  .node-bar.barney {
    background: linear-gradient(90deg, var(--barney), var(--barney2));
    right: 50%;
  }

  .node-center-line {
    position: absolute;
    left: 50%;
    width: 1px;
    height: 20px;
    background: var(--border2);
    transform: translateX(-0.5px);
  }

  /* ── Volume-profile bar overlay ─────────────────────────────────────
     Per-row bar zone for Profile variants A / B / C. The zone fills the
     row's flex middle area and is `position:relative` so child .node-vp-bar
     elements absolute-position inside it. Bar widths are linear in the
     value (NOT power-law — see dsProfileBarHTML doc-block). */
  .node-vp-zone {
    position: relative;
    align-self: stretch;
    display: flex;
    align-items: center;
    overflow: hidden;
    /* No min-height: zone stretches to whatever the row's text content
       dictates so profile rows match heat-default row height exactly.
       Bars use a fixed pixel height instead of a percentage so they
       stay readable regardless of how short the row collapses. */
  }
  .node-vp-bar {
    position: absolute;
    /* Fixed 10px bar height (was height:70%) — vertical centering via
       top:50% + translateY keeps the bar centered in whatever row
       height the text dictates. Predictable visual weight across all
       row densities. */
    height: 10px;
    top: 50%;
    transform: translateY(-50%);
    border-radius: 2px;
    transition: width 0.4s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s linear;
    min-width: 1px;
  }
  /* Variant A — single magnitude bar, left-anchored. */
  .node-vp-bar.node-vp-a { left: 0; }
  /* Variant B — stacked: call segment then put segment, both left of center. */
  .node-vp-bar.node-vp-b-call { /* width + left set inline */ }
  .node-vp-bar.node-vp-b-put { /* width + left set inline; abuts call segment */ }
  /* Variant C — center-axis split. */
  .node-vp-bar.node-vp-c-call { /* width inline; left:50% */ }
  .node-vp-bar.node-vp-c-put { /* width inline; right:50% */ }

  /* (Extras removed 4/27/26 — POC accent / VA bracket / distance-fade /
     air-pocket dashed didn't earn their visual cost. Reintroduce only
     when there's a concrete trader-utility concept worth shipping —
     candidates: per-strike sparkline of recent change using partner's
     Phase 4.1 rolling-delta data; rapid-velocity glyph using the
     existing isRapidVelocity flag.) */

  /* ── Display cog button + popover ──────────────────────────────────
     Single labeled "Display" entry in the legend bar; popover opens
     below and reflects whichever ladder (Heatmap or Multi) is active.
     The label is the discoverability fix — without it the icon alone
     was easy to skim past. */
  .ladder-cog {
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 4px 10px;
    cursor: pointer;
    color: var(--text2);
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: 4px;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
  }
  .ladder-cog:hover {
    background: var(--bg);
    color: var(--text);
    border-color: var(--border2);
  }
  .ladder-cog[aria-expanded="true"] {
    background: var(--bg);
    color: var(--text);
    border-color: var(--king);
  }
  .ladder-cog-label {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1;
  }
  .ladder-cog-popover {
    position: fixed;
    /* z-index 9500 — above sb-section-hover-card (9000) and the
       other 9k-tier floating UI, below tour overlay (10000) so the
       tour can still spotlight the cog if needed. Was 1000; bumped
       4/30 evening when popover was getting visually obscured by
       higher-z-index sidebar hover cards on Heatmap/Multi. */
    z-index: 9500;
    min-width: 280px;
    max-width: 340px;
    padding: 12px 14px;
    background: var(--bg2);
    border: 1px solid var(--border2);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35), 0 2px 4px rgba(0, 0, 0, 0.2);
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text2);
  }
  .ladder-cog-header {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text);
    margin-bottom: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
  }
  /* Settings → DISPLAY category label (4/29 evening). Sits below the
     "Settings" header and groups the actual settings sections. Future
     categories (Alerts, Notifications, Account) slot in alongside. */
  .ladder-cog-category {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text2);
    margin: 0 0 8px 0;
    padding: 2px 4px;
    background: var(--bg3);
    border-radius: 3px;
    text-align: center;
  }
  /* "page" tag next to per-page section titles — distinguishes them
     from global settings at a glance. */
  .ladder-cog-section-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 0 5px;
    border-radius: 8px;
    font-size: 8px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--text3);
    background: var(--bg3);
    border: 1px solid var(--border);
    text-transform: uppercase;
    vertical-align: middle;
  }
  .ladder-cog-section-title {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text3);
    margin: 4px 0 4px;
  }
  .ladder-cog-radio,
  .ladder-cog-checkbox {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    column-gap: 8px;
    align-items: center;
    padding: 5px 4px;
    border-radius: 3px;
    cursor: pointer;
  }
  .ladder-cog-radio:hover,
  .ladder-cog-checkbox:hover {
    background:var(--bg-subtle);
  }
  .ladder-cog-radio input[type="radio"],
  .ladder-cog-checkbox input[type="checkbox"] {
    grid-row: 1 / span 2;
    margin: 0;
    accent-color: var(--king);
  }
  .ladder-cog-radio-label,
  .ladder-cog-checkbox-label {
    font-size: 11px;
    color: var(--text);
    line-height: 1.2;
  }
  .ladder-cog-radio-hint,
  .ladder-cog-checkbox-hint {
    font-size: 9px;
    color: var(--text3);
    line-height: 1.2;
  }
  .ladder-cog-reset {
    margin-top: 10px;
    width: 100%;
    padding: 5px 0;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--text3);
    font-family: var(--mono);
    font-size: 10px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
  }
  .ladder-cog-reset:hover {
    background: var(--bg);
    color: var(--text);
  }
  /* ── Sound section (5/01/26) ──
     Nested 2-column layout for the volume slider, output preset, and
     per-channel mutes with inline Test buttons. Tight checkbox variant
     drops the vertical hint slot since channel labels are self-explanatory
     once you see them paired with the channel symbol. */
  .ladder-cog-checkbox-tight {
    grid-template-rows: auto;
    padding: 4px 6px;
  }
  .ladder-cog-checkbox-tight .ladder-cog-checkbox-label {
    grid-row: 1;
  }
  .ladder-cog-audio-row {
    display: flex;
    gap: 8px;
    margin-top: 6px;
    padding: 0 6px;
  }
  .ladder-cog-audio-row-dim { opacity: 0.45; pointer-events: none; }
  .ladder-cog-audio-vol {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    font-size: 10px;
    color: var(--text2);
  }
  .ladder-cog-audio-vol > span:first-child { min-width: 44px; color: var(--text3); }
  .ladder-cog-audio-vol input[type="range"] { flex: 1; accent-color: var(--king); }
  .ladder-cog-audio-vol-num {
    min-width: 24px;
    text-align: right;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
  }
  .ladder-cog-audio-output,
  .ladder-cog-audio-quiet {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    font-size: 10px;
    color: var(--text3);
  }
  .ladder-cog-audio-output > span,
  .ladder-cog-audio-quiet > span { min-width: 44px; }
  .ladder-cog-audio-output select,
  .ladder-cog-audio-quiet input[type="time"] {
    flex: 1;
    padding: 3px 6px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--text);
    font-family: var(--mono);
    font-size: 10px;
  }
  .ladder-cog-audio-channels {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 4px;
    padding: 6px;
    background: var(--bg-subtle, var(--bg3));
    border-radius: 4px;
  }
  /* Inline Test pill — clicking previews that channel's apex sound.
     stops onclick propagation so it doesn't toggle the parent checkbox. */
  .ladder-cog-audio-test {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text2);
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.05em;
    cursor: pointer;
    transition: color 0.12s, border-color 0.12s, background 0.12s;
  }
  .ladder-cog-audio-test:hover {
    color: var(--text);
    background: var(--bg);
    border-color: var(--border2);
  }
  /* Tour-replay button (Help category — 4/29 evening). Shares the
     reset-button visual treatment so the popover footer reads as a
     row of action buttons. */
  .ladder-cog-tour-btn {
    margin-top: 4px;
    width: 100%;
    padding: 5px 0;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--text3);
    font-family: var(--mono);
    font-size: 10px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
  }
  .ladder-cog-tour-btn:hover {
    background: var(--bg);
    color: var(--text);
  }
  /* Section divider — separates Ladder / Annotations / Palette / Font */
  .ladder-cog-divider {
    height: 1px;
    background: var(--border);
    margin: 10px 0;
  }
  /* Section hint — small italicized note below a section. Used to
     explain when extras are gated (only meaningful in Profile views). */
  .ladder-cog-section-hint {
    font-size: 9px;
    color: var(--text3);
    font-style: italic;
    line-height: 1.35;
    padding: 2px 4px 0;
  }
  /* Dimmed radio — used to signal "this option is selectable but won't
     render anything in the current context." E.g. profile views on
     Heatmap-Weekly: the multi-expiry grid layout doesn't carry profile
     bars, so the option is dimmed with an explanatory hint underneath. */
  .ladder-cog-radio-dimmed { opacity: 0.5; }
  /* Compact radio — used for Palette section so 6 options don't sprawl */
  .ladder-cog-radio-compact {
    grid-template-rows: auto;
    padding: 3px 4px;
  }
  .ladder-cog-radio-compact .ladder-cog-radio-label {
    grid-column: 2;
  }
  /* Font row — two compact field selects side-by-side */
  .ladder-cog-fontrow {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 4px 4px 0;
  }
  .ladder-cog-fontfield {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 9px;
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    cursor: pointer;
  }
  .ladder-cog-fontfield select {
    background: var(--bg3);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 3px 5px;
    font-family: var(--mono);
    font-size: 11px;
  }
  .ladder-cog-fontfield select:hover {
    border-color: var(--border2);
  }
  /* Wide variant — used by the Font Family picker (one full-width
     select instead of two side-by-side sizing fields). */
  .ladder-cog-fontfield-wide {
    flex: 1;
  }
  .ladder-cog-fontfield-wide select {
    width: 100%;
  }
  /* Palette + View dropdowns (4/29/26) — replace the radio lists.
     Same styling as the font selects so the cog reads consistently. */
  .ladder-cog-palette-select,
  .ladder-cog-view-select {
    width: 100%;
    background: var(--bg3);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: 5px 7px;
    font-family: var(--mono);
    font-size: 11px;
    cursor: pointer;
  }
  .ladder-cog-palette-select:hover,
  .ladder-cog-view-select:hover {
    border-color: var(--border2);
  }
  /* Mobile — popover renders as bottom-sheet on narrow viewports */
  @media (max-width: 520px) {
    .ladder-cog-popover {
      position: fixed !important;
      left: 8px !important;
      right: 8px !important;
      top: auto !important;
      bottom: 12px !important;
      max-width: none;
    }
  }

  .node-value {
    font-family: var(--mono);
    font-size: 11px;
    min-width: 90px;
    text-align: right;
    flex-shrink: 0;
    letter-spacing: 0.02em;
  }

  .node-tag {
    font-family: var(--mono);
    font-size: 8px;
    padding: 2px 5px;
    border-radius: 3px;
    letter-spacing: 0.06em;
    flex-shrink: 0;
    font-weight: 700;
  }
  .tag-king { background: rgba(255,107,53,0.18); color: var(--king); border: 1px solid rgba(255,107,53,0.5); font-size: 9px; letter-spacing: 0.1em; text-shadow: 0 0 8px rgba(255,107,53,0.6); }
  .tag-gate { background: var(--gate2); color: var(--gate); border: 1px solid rgba(0,212,170,0.3); }
  .tag-fresh { background: rgba(34,197,94,0.1); color: var(--green); border: 1px solid rgba(34,197,94,0.2); }
  .tag-tested { background: rgba(245,200,66,0.1); color: var(--pika); border: 1px solid rgba(245,200,66,0.2); }
  .tag-weak { background: rgba(239,68,68,0.1); color: var(--red); border: 1px solid rgba(239,68,68,0.2); }

  /* ── DETAIL PANEL ── */
  .detail-section {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
  }

  .detail-title {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text3);
    margin-bottom: 10px;
  }

  .node-detail-card {
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 8px;
  }

  .node-detail-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
  }

  .node-detail-strike {
    font-family: var(--mono);
    font-size: 16px;
    font-weight: 700;
  }

  .tap-dots {
    display: flex;
    gap: 3px;
    align-items: center;
  }

  .tap-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--border2);
  }
  .tap-dot.filled { background: var(--pika); }
  .tap-dot.used { background: var(--text3); }

  .prob-bar {
    height: 4px;
    background: var(--bg4);
    border-radius: 2px;
    margin: 8px 0 4px;
    overflow: hidden;
  }

  .prob-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 1s;
  }

  .prob-label {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    display: flex;
    justify-content: space-between;
  }

  .gex-vex-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    margin-top: 8px;
  }

  .gvex-cell {
    background: var(--bg4);
    border-radius: 5px;
    padding: 6px 8px;
  }

  .gvex-label {
    font-family: var(--mono);
    font-size: 8px;
    color: var(--text3);
    letter-spacing: 0.08em;
  }

  .gvex-value {
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 700;
    margin-top: 2px;
  }

  /* ── PATTERN DETECTOR ── */
  .pattern-card {
    background: var(--bg3);
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 8px;
    border: 1px solid var(--border);
    position: relative;
    overflow: hidden;
  }

  .pattern-card::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
  }
  /* Pattern accent stripes — kind-specific, see patterns.js
     _PATTERN_DIR_COLOR for the framework. Trade bias gets semantic
     green/red; regime states match the regime card's pika/barney
     data encoding; structural patterns get king (level magnetism)
     or gate (cluster). */
  /* Trade bias */
  .pattern-card.bull::before    { background: var(--green); }
  .pattern-card.bear::before    { background: var(--red); }
  /* Regime state — aligned with the left-rail regime card */
  .pattern-card.regime-pos::before { background: var(--pika); }
  .pattern-card.regime-neg::before { background: var(--barney); }
  /* Structural */
  .pattern-card.level::before   { background: var(--king); }
  .pattern-card.cluster::before { background: var(--gate); }
  /* No signal */
  .pattern-card.neutral::before { background: var(--text3); }
  /* Legacy aliases — match the renderer's backward-compat mapping */
  .pattern-card.bullish::before { background: var(--green); }
  .pattern-card.bearish::before { background: var(--red); }
  .pattern-card.caution::before { background: var(--king); }

  .pattern-name {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 700;
    margin-bottom: 3px;
  }

  .pattern-desc {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text2);
    line-height: 1.6;
    letter-spacing: 0.02em;
  }

  .pattern-conf {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
  }

  .conf-bar {
    flex: 1;
    height: 3px;
    background: var(--bg4);
    border-radius: 1px;
    overflow: hidden;
  }

  .conf-fill {
    height: 100%;
    border-radius: 1px;
    background: var(--pika);
  }

  .conf-label {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
  }

  /* ── HEATMAP GRID (multi-expiry) ── */
  .heat-grid {
    display: grid;
    font-family: var(--mono);
  }
  .heat-grid-head {
    background: var(--bg3);
    color: var(--text3);
    font-size: 10px;
    padding: 6px 8px;
    text-align: right;
    letter-spacing: 0.03em;
    font-weight: 500;
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 2;
  }
  .heat-grid-strike-head {
    text-align: center;
    z-index: 3;
  }
  .heat-grid-strike {
    background: var(--bg);
    color: var(--text2);
    font-weight: 600;
    padding: 0;
    -webkit-font-smoothing: antialiased;
    text-rendering: geometricPrecision;
    letter-spacing: 0.02em;
    position: sticky;
    left: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .heat-grid-strike.atprice {
    /* visual handled inline — keep only structural */
  }
  .heat-grid-cell {
    padding: 0 8px;
    text-align: right;
    white-space: nowrap;
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    text-rendering: geometricPrecision;
    overflow: hidden;
    text-overflow: ellipsis;
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }
  .heat-grid-cell.king { font-weight: 800; }
  .heat-grid-cell.empty { color: var(--text3); opacity: 0.5; }
  .heat-grid-cell:not(.empty) { cursor: default; }
  .heat-grid-strike { cursor: default; }

  /* ── GRID MODE (1W) — hide right detail panel, expand ladder ── */
  /* grid-mode (Weekly view) is now identical to default since the
     right detail panel was retired in the 4/29/26 tighten pass.
     Selector kept as a no-op so any code paths that toggle it
     don't error. */
  .instrument-layout.grid-mode { grid-template-columns: 260px 1fr; }

  /* ── TRINITY MODE ── */
  .multi-layout {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    height: calc(100vh - 92px);
  }

  .multi-panel {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .multi-header {
    padding: 6px 12px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
  }

  .multi-ticker {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 0.04em;
  }

  /* Heat gauge sits between the ticker name and the price block.
     Compact variant — drops the "Heat" label, narrows the sparkline
     so it fits cleanly in a header row that already carries ticker
     + price + %change. Inherits all .heat-gauge zone classes. */
  .multi-header .ladder-heat-gauge {
    padding: 2px 6px;
    font-size: 8px;
    flex-shrink: 0;
  }
  .multi-header .ladder-heat-gauge .heat-gauge-label { display: none; }
  .multi-header .ladder-heat-gauge .heat-gauge-sparkline { width: 38px; height: 12px; }

  /* Push price block to the right edge regardless of how many siblings
     are in the header (ticker + heat gauge + price block). */
  .multi-price-block {
    text-align: right;
    margin-left: auto;
  }

  .multi-price {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 700;
  }

  .multi-change {
    font-family: var(--mono);
    font-size: 9px;
  }

  .multi-regime {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 12px;
    border-bottom: 1px solid var(--border);
    background: var(--bg3);
    flex-shrink: 0;
  }

  .multi-regime-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
  }

  .multi-regime-text {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.04em;
  }

  .multi-regime-net {
    margin-left: auto;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
  }

  .multi-ladder {
    flex: 1;
    overflow-y: auto;
    padding: 4px 0;
  }

  .multi-ladder::-webkit-scrollbar { width: 2px; }
  .multi-ladder::-webkit-scrollbar-thumb { background: var(--border); border-radius: 1px; }

  .multi-node {
    display: flex;
    align-items: center;
    padding: 1px 8px;
    /* Gap bumped 4→8px (4/27/26) to match Heatmap's row gap so role-label
       pills (which float at left:100% of .tn-strike) have proportional
       breathing room before the bar zone — fixes the "labels overlap
       the bar" perception on Multi profile modes. */
    gap: 8px;
    -webkit-font-smoothing: antialiased;
    text-rendering: geometricPrecision;
  }
  .tn-strike {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 600;
    color: var(--text2);
    /* Width bumped 44→60px (4/27/26) to match Heatmap's effective strike
       column width. Centers strike text in a wider zone so the floating
       role-label pill sits within proportional space before reaching
       the bar zone. */
    width: 60px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .tn-strike.king { color: var(--king); font-weight: 700; }

  .tn-bar-wrap {
    flex: 1;
    height: 12px;
    position: relative;
    display: flex;
    align-items: center;
  }

  .tn-bar {
    height: 7px;
    border-radius: 1px;
    position: absolute;
    min-width: 1px;
    transition: width 1s cubic-bezier(0.16, 1, 0.3, 1);
  }
  .tn-bar.pika { background: var(--pika); left: 50%; opacity: 0.85; }
  .tn-bar.barney { background: var(--barney); right: 50%; opacity: 0.85; }
  .tn-center { position: absolute; left: 50%; width: 1px; height: 12px; background: var(--border2); }

  .tn-val {
    font-family: var(--mono);
    font-size: 11px;
    min-width: 72px;
    text-align: right;
    flex-shrink: 0;
  }

  /* ── ALIGNMENT SCORE ── */
  .alignment-bar {
    padding: 14px 16px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
    background: var(--bg3);
  }

  .alignment-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }

  .alignment-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text3);
  }

  .alignment-score {
    font-family: var(--mono);
    font-size: 14px;
    font-weight: 700;
  }

  .alignment-track {
    height: 6px;
    background: var(--bg4);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 6px;
  }

  .alignment-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 1.5s cubic-bezier(0.16, 1, 0.3, 1);
  }

  .alignment-verdict {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.04em;
  }

  /* ── TRINITY FOOTER — SYSTEM STATUS ── */
  .multi-footer {
    grid-column: 1 / -1;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 20px;
    display: flex;
    align-items: center;
    gap: 24px;
  }

  .system-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text3);
    white-space: nowrap;
  }

  .verdict-chip {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 700;
    padding: 6px 16px;
    border-radius: 6px;
  }
  .verdict-full { background: rgba(34,197,94,0.15); color: var(--green); border: 1px solid rgba(34,197,94,0.3); }
  .verdict-partial { background: rgba(245,200,66,0.15); color: var(--pika); border: 1px solid rgba(245,200,66,0.3); }
  .verdict-diverge { background: rgba(239,68,68,0.15); color: var(--red); border: 1px solid rgba(239,68,68,0.3); }

  .verdict-detail {
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text2);
    line-height: 1.6;
    letter-spacing: 0.02em;
  }

  .key-levels {
    margin-left: auto;
    display: flex;
    gap: 16px;
  }

  .kl-item {
    text-align: center;
  }
  .kl-label {
    font-family: var(--mono);
    font-size: 8px;
    color: var(--text3);
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .kl-value {
    font-family: var(--mono);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
  }

  /* ── REFRESH COUNTER ── */
  .refresh-ring {
    width: 24px;
    height: 24px;
    position: relative;
    flex-shrink: 0;
  }
  .refresh-svg { transform: rotate(-90deg); }
  .refresh-track { fill: none; stroke: var(--border2); stroke-width: 2.5; }
  .refresh-fill {
    fill: none;
    stroke: var(--green);
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-dasharray: 63;
    stroke-dashoffset: 63;
    transition: stroke-dashoffset 1s linear;
  }

  /* ── LEGEND ── */
  .legend {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 24px;
    height: 36px;
    border-bottom: 1px solid var(--border);
    background: var(--bg2);
    position: sticky;
    top: 52px;
    z-index: 99;
  }
  .legend.hidden { display: none; }

  .legend-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.04em;
    position: relative;
  }

  .legend-item.has-tip { cursor: default; }

  .legend-tip {
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    width: 260px;
    background: var(--bg2);
    border: 1px solid var(--border2);
    border-radius: 7px;
    padding: 11px 13px;
    z-index: 999;
    transition: opacity 0.15s ease, visibility 0.15s ease;
    box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  }
  .legend-tip::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--border2);
  }
  .legend-item.has-tip:hover .legend-tip {
    visibility: visible;
    opacity: 1;
  }

  .tip-header {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 7px;
  }
  .tip-icon {
    font-size: 15px;
    line-height: 1;
    filter: drop-shadow(0 0 4px currentColor);
  }
  .tip-label {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
  }
  .tip-body {
    font-family: var(--mono);
    font-size: 9.5px;
    color: var(--text2);
    line-height: 1.55;
    margin-bottom: 8px;
  }
  .tip-strategy {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    line-height: 1.5;
    border-top: 1px solid var(--border);
    padding-top: 7px;
  }
  .tip-strategy strong {
    color: var(--text2);
    font-weight: 700;
  }

  .legend-dot {
    width: 8px;
    height: 8px;
    border-radius: 2px;
  }

  .last-update {
    margin-left: auto;
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.04em;
  }

  /* ── HEAT-DECAY GAUGE ── small toolbar pill on the heatmap. Color
     reflects how today's king magnitude compares to trailing 5-day avg.
     Painted by setHeatGaugeRatio() in app.js; .heat-gauge-* zone classes
     control color. */
  .heat-gauge {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    border-radius: 4px;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    background: var(--bg3);
    /* Slightly stronger border than the rest of the legend chrome so the
       sparkline reads as its own widget instead of dissolving into
       background. Pairs with the punchier polyline below. */
    border: 1px solid var(--border2);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
    cursor: help;
    transition: all 0.15s;
  }
  .heat-gauge-label {
    color: var(--text3);
    text-transform: uppercase;
  }
  .heat-gauge-ratio {
    color: var(--text);
    font-weight: 700;
  }
  .heat-gauge-sparkline {
    width: 56px;
    height: 14px;
    display: inline-block;
    overflow: visible;
    margin-left: 2px;
  }
  .heat-gauge-sparkline polyline {
    fill: none;
    stroke: var(--text2);
    stroke-width: 1.6;
    stroke-linejoin: round;
    stroke-linecap: round;
    opacity: 1;
  }
  .heat-gauge-sparkline circle {
    fill: var(--text);
    stroke: var(--bg);
    stroke-width: 0.6;
    r: 1.8;
  }
  /* Sparkline color follows the gauge zone so the visual reinforces
     the ratio reading. */
  .heat-gauge.heat-zone-elevated .heat-gauge-sparkline polyline { stroke: var(--pika); }
  .heat-gauge.heat-zone-elevated .heat-gauge-sparkline circle   { fill:   var(--pika); }
  .heat-gauge.heat-zone-heavy    .heat-gauge-sparkline polyline { stroke: var(--king); }
  .heat-gauge.heat-zone-heavy    .heat-gauge-sparkline circle   { fill:   var(--king); }
  .heat-gauge.heat-zone-extreme  .heat-gauge-sparkline polyline { stroke: var(--red); }
  .heat-gauge.heat-zone-extreme  .heat-gauge-sparkline circle   { fill:   var(--red); }
  /* Hide the gauge entirely when the active tab isn't Heatmap. Set
     in switchView() — fixes the "appears differently on different
     tabs" symptom where the legend gauge retained stale state from
     a previous Heatmap render after the user switched away. */
  .heat-gauge.tab-hidden { display: none !important; }

  /* Zone classes — restrained per-zone background tinting that carries
     the heat-multiplier signal. Sparkline color + ratio-text color
     reinforce. Previous attempt swapped saturated bg colors which read
     as "the widget keeps changing its mind"; these are softer (~12-16%
     alpha against the chip's bg3) so the chip frame stays recognisable
     across regime transitions. */
  .heat-gauge.heat-zone-suppressed {
    background: color-mix(in srgb, var(--text3) 8%, var(--bg3));
  }
  .heat-gauge.heat-zone-suppressed .heat-gauge-sparkline polyline { stroke: var(--text3); opacity: 0.65; }
  .heat-gauge.heat-zone-suppressed .heat-gauge-ratio { color: var(--text2); }

  .heat-gauge.heat-zone-normal { /* default — bg3, no tint */ }

  .heat-gauge.heat-zone-elevated {
    background: color-mix(in srgb, var(--pika) 12%, var(--bg3));
    border-color: color-mix(in srgb, var(--pika) 35%, var(--border2));
  }
  .heat-gauge.heat-zone-elevated .heat-gauge-ratio { color: var(--pika); }

  .heat-gauge.heat-zone-heavy {
    background: color-mix(in srgb, var(--king) 14%, var(--bg3));
    border-color: color-mix(in srgb, var(--king) 40%, var(--border2));
  }
  .heat-gauge.heat-zone-heavy .heat-gauge-ratio { color: var(--king); }

  .heat-gauge.heat-zone-extreme {
    background: color-mix(in srgb, var(--red) 16%, var(--bg3));
    border-color: color-mix(in srgb, var(--red) 50%, var(--border2));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--red) 25%, transparent);
  }
  .heat-gauge.heat-zone-extreme .heat-gauge-ratio { color: var(--red); }

  /* Bootstrap = <2 sessions of baseline. Shows absolute magnitude
     instead of a ratio. Sparkline still renders if we have ≥1 prior
     point. Visual frame stays the same as active mode. */
  .heat-gauge.heat-zone-bootstrap .heat-gauge-ratio { color: var(--text3); }

  /* Atlas ghost-levels styles retired 4/29/26 (toggle removed). */

  /* ── FLOW BASELINE BADGE — appears next to the ticker in the flow
     tape when today's session premium is unusually high vs 30-day avg. */
  .flow-baseline-badge {
    display: inline-block;
    margin-left: 4px;
    padding: 1px 5px;
    border-radius: 3px;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    background: var(--king2);
    color: var(--king);
    border: 1px solid rgba(255,107,53,0.3);
  }
  .flow-baseline-badge.flow-baseline-mild  { background: var(--pika3); color: var(--pika); border-color: rgba(245,200,66,0.3); }
  .flow-baseline-badge.flow-baseline-quiet { background:var(--bg-subtle); color: var(--text3); border-color: var(--border); }

  /* ── TOGGLE SWITCH ── */
  .toggle-row {
    display: flex;
    gap: 4px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 2px;
  }

  .toggle-opt {
    font-family: var(--mono);
    font-size: 9px;
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text3);
    letter-spacing: 0.06em;
    transition: all 0.12s;
    border: none;
    background: none;
    text-transform: uppercase;
  }
  .toggle-opt.active {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border2);
  }

  /* ── TRINITY TOOLTIP ── */
  .multi-tooltip {
    position: fixed;
    z-index: 9999;
    pointer-events: none;
    background: var(--bg2);
    border: 1px solid var(--border2);
    border-radius: 10px;
    padding: 12px;
    width: 220px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.7);
    opacity: 0;
    transition: opacity 0.1s;
  }
  .multi-tooltip.visible { opacity: 1; }

  /* ── PALETTE SELECTOR ── */
  .palette-select {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.05em;
    background: var(--bg3);
    color: var(--text2);
    border: 1px solid var(--border2);
    border-radius: 5px;
    padding: 3px 22px 3px 8px;
    cursor: pointer;
    outline: none;
    appearance: none;
    -webkit-appearance: none;
    /* Caret SVG uses fill="currentColor" so the arrow inherits the
       text color of the select — automatically themes (gray on dark,
       slate on light). The fill is encoded in the URL so we use a
       computed-style approach via CSS mask + background-color in
       browsers that support it; for broad support we ship the SVG
       inline and let CSS color the parent. Inline-svg fill cannot
       reference a CSS variable directly, so we rely on currentColor
       inside the data URL — which DOES work because currentColor
       resolves at paint time using the parent's color. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='currentColor'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
    transition: border-color 0.12s, color 0.12s;
  }
  .palette-select:hover { border-color: var(--border2); color: var(--text); }
  /* Dropdown options use the theme's panel bg + text color so the open
     menu list matches the page. Native <select> styling is OS-controlled
     in some browsers (Safari ignores option styling entirely); these
     work in Chrome/Firefox/Edge. */
  .palette-select option { background: var(--bg3); color: var(--text); }

  /* scrollable multi */
  .multi-wrapper {
    display: flex;
    flex-direction: column;
    /* 5/02/26 — was `100vh - 92px`, which only accounted for the
       header (52px) and a thin slice of view padding. The legend bar
       (36px) + the view's 20px top + 20px bottom padding push the
       actual chrome to 128px. The old value pushed the multi-footer
       row off the bottom of the viewport at non-tall window sizes
       (cropped the System Alignment verdict). 128 leaves the footer
       visible at any height. */
    height: calc(100vh - 128px);
    gap: 12px;
  }
  .multi-panels-row {
    display: grid;
    /* 1×N grid driven by --multi-panel-count (set inline by renderMulti
       based on Object.keys(TICKERS).length). Defaults to 4 for the
       SPX/SPY/QQQ/IWM canonical set; gracefully scales to 3 if a
       deployment turns IWM off via INSTRUMENTS env. Gap drops as
       count grows so 4 panels fit cleanly at 1280px+. */
    grid-template-columns: repeat(var(--multi-panel-count, 4), 1fr);
    gap: 10px;
    flex: 1;
    min-height: 0;
  }
  .multi-footer-row { flex-shrink: 0; }
.node-bar-container{flex:1;height:20px;display:flex;align-items:center;position:relative}.node-bar{height:14px;border-radius:2px;position:absolute;transition:width 0.8s;min-width:2px}.node-bar.pika{background:linear-gradient(90deg,var(--pika2),var(--pika));left:50%}.node-bar.barney{background:linear-gradient(90deg,var(--barney),var(--barney2));right:50%}.node-center-line{position:absolute;left:50%;width:1px;height:20px;background:var(--border2);transform:translateX(-0.5px)}

  /* ── ALERTS ── */
  /* ── ALERTS HEADER ── */
  .alerts-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg2);
    flex-shrink: 0;
  }
  .alerts-title {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: 0.03em;
    margin-right: 2px;
    flex-shrink: 0;
  }
  .alerts-filters { display: flex; gap: 4px; }
  .alert-filter-btn {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    padding: 3px 9px;
    border-radius: 4px;
    border: 1px solid var(--border2);
    background: transparent;
    color: var(--text3);
    cursor: pointer;
    transition: all 0.12s;
  }
  .alert-filter-btn:hover { color: var(--text2); }
  .alert-filter-btn.active { background: var(--bg4); color: var(--text); border-color: var(--border2); }

  /* ── Alerts subtabs + settings panel (added by alert-prefs work) ── */
  .alerts-subtabs { display: flex; gap: 4px; flex: 1; }
  .alert-subtab {
    background: transparent;
    border: 1px solid transparent;
    color: var(--text3);
    padding: 4px 11px;
    border-radius: 5px;
    font-family: var(--mono);
    font-size: 10px;
    cursor: pointer;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .alert-subtab:hover { color: var(--text2); }
  .alert-subtab.active { background: var(--bg4); color: var(--text); border-color: var(--border2); }
  /* Subtab icons — colorable text-mode symbols matching channel hues. 4/29/26.
     Icon stays its channel color whether the pill is active or inactive,
     so the channel identity is always visible at a glance. */
  .subtab-icon {
    font-size: 11px;
    line-height: 1;
    margin-right: 2px;
  }
  .subtab-conviction .subtab-icon { color: #f5cc56; }            /* gold */
  .subtab-gex        .subtab-icon { color: var(--barney); }      /* purple */
  .subtab-flow       .subtab-icon { color: var(--gate); }        /* teal */
  .subtab-count {
    display: inline-block;
    min-width: 18px;
    padding: 1px 5px;
    background: rgba(155,93,229,0.18);
    color: var(--barney);
    border-radius: 9px;
    font-size: 9px;
    font-weight: 700;
    text-align: center;
  }
  .subtab-count:empty, .subtab-count[data-zero="true"] { display: none; }
  .alerts-critical-chip {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    background: rgba(239,68,68,0.12);
    color: var(--red);
    border: 1px solid rgba(239,68,68,0.35);
    border-radius: 5px;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.08em;
    margin-right: 8px;
  }
  .alerts-critical-chip[data-zero="true"] { display: none; }
  .alerts-settings-btn {
    background: transparent;
    color: var(--text3);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 4px 10px;
    font-family: var(--mono);
    font-size: 10px;
    cursor: pointer;
    margin-right: 4px;
  }
  .alerts-settings-btn:hover { color: var(--text); border-color: var(--border2); }
  /* Expanded state — mirrors .navbar-settings-btn so the Toggles button
     reads as "open" while the panel is showing. */
  .alerts-settings-btn[aria-expanded="true"] {
    color: var(--text);
    background: var(--bg3);
    border-color: var(--border2);
  }

  /* (Header master switches retired 5/01/26 evening — now live inside
     the Toggles panel as .alerts-master-pill — see below.) */

  .alerts-type-panel {
    background: var(--bg2);
    border-bottom: 1px solid var(--border);
    padding: 12px 16px;
  }
  .alerts-type-panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 6px;
  }
  /* Description sits on its own line BELOW the header (5/01/26 evening
     fix — previously was inline-flex sibling of the title which caused
     it to smush directly against "ALERT TOGGLES" with no gap). */
  .alerts-type-panel-sub {
    display: block;
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    text-transform: none;
    letter-spacing: 0.02em;
    margin-bottom: 14px;
    line-height: 1.4;
  }
  /* ── Master switches inside Toggles panel (5/01/26 evening) ──
     Three explicit ON/OFF pills for ALERTS / TOASTS / SOUNDS. Moved
     here from the alerts header. Each pill shows the layer name PLUS
     "ON" or "OFF" text so state is unmissable — color/dot alone was
     too easy to skim past. */
  .alerts-master-section {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
  }
  .alerts-master-section-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text3);
    flex-shrink: 0;
  }
  .alerts-master-pills {
    display: flex;
    gap: 6px;
    flex: 1;
  }
  .alerts-master-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 10px;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 5px;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    color: var(--text2);
    cursor: pointer;
    transition: all 0.12s;
  }
  .alerts-master-pill:hover {
    background: var(--bg);
    border-color: var(--border2);
    color: var(--text);
  }
  .alerts-master-pill.on {
    color: var(--text);
    border-color: rgba(52,211,153,0.45);
  }
  .alerts-master-pill.off {
    opacity: 0.65;
    color: var(--text3);
  }
  .alerts-master-pill-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #6b7280;
    transition: background 0.12s, box-shadow 0.12s;
  }
  .alerts-master-pill.on .alerts-master-pill-dot {
    background: #34d399;
    box-shadow: 0 0 6px rgba(52,211,153,0.5);
  }
  .alerts-master-pill-label {
    font-weight: 600;
    text-transform: uppercase;
  }
  .alerts-master-pill-state {
    padding: 1px 6px;
    border-radius: 3px;
    background: rgba(255,255,255,0.06);
    font-weight: 700;
    font-size: 9px;
    letter-spacing: 0.08em;
  }
  .alerts-master-pill.on .alerts-master-pill-state {
    background: rgba(52,211,153,0.15);
    color: #34d399;
  }
  .alerts-master-pill.off .alerts-master-pill-state {
    background: rgba(239,68,68,0.10);
    color: #fca5a5;
  }
  /* Reset-to-default button — sits on the right of the Toggles panel
     header. Quieter than the channel section labels but distinct enough
     to read as an action button. Same shape as .alerts-clear-btn. */
  .alerts-type-reset-btn {
    margin-left: auto;
    padding: 4px 10px;
    background: transparent;
    color: var(--text3);
    border: 1px solid var(--border);
    border-radius: 5px;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color 0.12s, border-color 0.12s;
  }
  .alerts-type-reset-btn:hover { color: var(--text); border-color: var(--border2); }
  .alerts-type-grid {
    display: flex;
    flex-direction: column;
    gap: 14px;
  }
  /* Section grouping by channel (Conviction / GEX / Flow). 4/29/26 */
  .alerts-type-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .alerts-type-section-header {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--text3);
    padding: 4px 0 2px 0;
    border-bottom: 1px solid var(--border);
  }
  .alerts-type-section-header.ch-conviction { color: #f5cc56; } /* gold — matches Conviction channel + cross-ticker tier badges */
  .alerts-type-section-header.ch-gex        { color: var(--barney); } /* purple — matches GEX channel (negative-GEX data color) */
  .alerts-type-section-header.ch-flow       { color: var(--gate); }
  .alerts-type-row {
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 12px;
  }
  .alerts-type-row-info {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
  }
  .alerts-type-row-name {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 700;
    color: var(--text);
    display: flex;
    align-items: center;
    flex-wrap: wrap;
  }
  .alerts-type-row-desc {
    font-family: var(--sans);
    font-size: 10px;
    color: var(--text3);
    line-height: 1.4;
  }
  .alerts-type-row-toggles {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
  }
  .alerts-type-toggle {
    flex: 1;
    background: var(--bg2);
    border: 1px solid var(--border);
    color: var(--text3);
    padding: 4px 8px;
    border-radius: 4px;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .alerts-type-toggle:hover { border-color: var(--border2); }
  .alerts-type-toggle.on { color: var(--green); border-color: rgba(34,197,94,0.35); background: rgba(34,197,94,0.06); }
  .alerts-type-toggle.off { color: var(--text3); }
  .alerts-type-toggle .dot {
    width: 6px; height: 6px; border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 4px currentColor;
  }
  /* Preview button — fires a sample alert so users can see what this type
     looks like (toast + briefly in feed marked TEST). 4/29/26 */
  .alerts-type-preview {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text2);
    padding: 4px 10px;
    border-radius: 4px;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 0.12s;
  }
  .alerts-type-preview:hover {
    color: var(--text);
    border-color: #a78bfa;
    background: rgba(167,139,250,0.08);
  }
  /* 🔊 audio-only test button (5/01/26) — sits next to ✦ Preview.
     Plays just the sound for that alert type (no toast). Font matches
     .alerts-type-preview so the two buttons read as a paired set. */
  .alerts-type-audio {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text2);
    padding: 4px 10px;
    border-radius: 4px;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 0.12s;
  }
  .alerts-type-audio:hover {
    color: var(--text);
    border-color: #34d399;
    background: rgba(52,211,153,0.08);
  }

  /* ── Audio settings block inside the Toggles panel (5/01/26) ──
     Sits at the top of the panel above per-channel sections. Compact
     layout: volume slider + output preset on row 1, three signature
     test buttons on row 2, bias/quiet-hours toggles on row 3 with the
     time-range inputs adjacent. */
  .alerts-audio-section {
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 12px;
    margin-bottom: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .alerts-audio-row {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
  }
  .alerts-audio-row-tight { gap: 16px; }
  .alerts-audio-vol {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 180px;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
  }
  .alerts-audio-vol > span:first-child { min-width: 44px; letter-spacing: 0.05em; }
  .alerts-audio-vol input[type="range"] { flex: 1; accent-color: var(--king); }
  .alerts-audio-vol-num {
    min-width: 28px;
    text-align: right;
    color: var(--text2);
    font-size: 10px;
  }
  .alerts-audio-output {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
  }
  .alerts-audio-output > span { min-width: 44px; letter-spacing: 0.05em; }
  .alerts-audio-output select {
    padding: 3px 6px;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--text);
    font-family: var(--mono);
    font-size: 10px;
    cursor: pointer;
  }
  .alerts-audio-signatures {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
  }
  .alerts-audio-signatures-label {
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
    letter-spacing: 0.05em;
    margin-right: 4px;
  }
  .alerts-audio-sig-btn {
    padding: 3px 9px;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text2);
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.05em;
    cursor: pointer;
    transition: color 0.12s, border-color 0.12s, background 0.12s;
  }
  .alerts-audio-sig-btn:hover {
    color: var(--text);
    border-color: #34d399;
    background: rgba(52,211,153,0.06);
  }
  .alerts-audio-toggle {
    display: flex;
    flex-direction: column;
    gap: 1px;
    cursor: pointer;
    font-size: 10px;
    color: var(--text);
  }
  .alerts-audio-toggle input[type="checkbox"] {
    accent-color: var(--king);
    margin-right: 4px;
    vertical-align: middle;
  }
  .alerts-audio-toggle-hint {
    margin-left: 18px;
    font-size: 9px;
    color: var(--text3);
  }
  .alerts-audio-quiet-range {
    display: flex;
    align-items: center;
    gap: 4px;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
  }
  .alerts-audio-quiet-range input[type="time"] {
    padding: 2px 4px;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 3px;
    color: var(--text);
    font-family: var(--mono);
    font-size: 10px;
  }
  .alerts-audio-quiet-range-dim { opacity: 0.45; pointer-events: none; }

  /* Archive button on each alert card */
  .alert-card-archive {
    position: absolute;
    top: 6px; right: 8px;
    background: transparent;
    border: none;
    color: var(--text3);
    cursor: pointer;
    font-size: 13px;
    padding: 2px 6px;
    border-radius: 3px;
    line-height: 1;
  }
  .alert-card-archive:hover { color: var(--text); background: var(--bg3); }
  .alerts-clear-btn {
    margin-left: auto;
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    padding: 3px 9px;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text3);
    cursor: pointer;
    transition: all 0.12s;
    flex-shrink: 0;
  }
  .alerts-clear-btn:hover { color: var(--red); border-color: var(--red); }

  /* Test alert indicator — preview alerts (fired from Toggles panel
     "✦ Preview" buttons) are visually marked with a dashed border + a
     "· TEST" suffix on the channel chip so they're clearly distinguishable
     from real alerts that happen to land at the same time. The DEV-mode
     panel that originally drove these was retired 5/01/26; the styling
     stays since previewAlertType() still flags _isTest=true. */
  .alert-card.is-test { border-style: dashed; opacity: 0.9; }
  .alert-channel.is-test::after { content: ' · TEST'; color: #a78bfa; }

  /* ── TYPE TOGGLES ── */
  .alerts-type-toggles {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    flex-shrink: 0;
    flex-wrap: wrap;
  }
  .type-toggles-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    color: var(--text3);
    flex-shrink: 0;
  }
  .type-toggle {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.05em;
    padding: 3px 9px;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text3);
    cursor: pointer;
    transition: all 0.12s;
  }
  .type-toggle.active {
    border-color: var(--border2);
    color: var(--text2);
    background: var(--bg3);
  }
  .type-toggle.active::before { content: '✓ '; }
  .type-toggle:hover { color: var(--text2); border-color: var(--border2); }

  /* ── NAV BADGE ── */
  .alert-count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    margin-left: 5px;
    border-radius: 8px;
    background: var(--red);
    color: #fff;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    vertical-align: middle;
    line-height: 1;
  }

  /* ── FEED ── */
  .alerts-feed {
    flex: 1;
    overflow-y: auto;
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .alerts-feed::-webkit-scrollbar { width: 4px; }
  .alerts-feed::-webkit-scrollbar-track { background: transparent; }
  .alerts-feed::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

  /* Channel section headers in the All-feed (4/29/26).
     Renders only on the All subtab; other subtabs already filter to one
     channel so headers would be redundant. Order: CONVICTION → GEX → FLOW. */
  .alerts-feed-section-header {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: var(--text3);
    padding: 6px 0 4px 0;
    border-bottom: 1px solid var(--border);
    margin-top: 4px;
  }
  .alerts-feed-section-header:first-child { margin-top: 0; }
  .alerts-feed-section-header.ch-conviction { color: #f5cc56; }
  .alerts-feed-section-header.ch-gex        { color: var(--barney); }
  .alerts-feed-section-header.ch-flow       { color: var(--gate); }

  /* Alerts view overrides the generic .view padding/display */
  #view-alerts { display: none; flex-direction: column; height: calc(100vh - 52px); padding: 0; }
  #view-alerts.active { display: flex; }

  .alerts-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    gap: 8px;
    color: var(--text3);
    padding: 60px 0;
  }
  .alerts-empty-icon { font-size: 28px; opacity: 0.3; }
  .alerts-empty-title { font-family: var(--sans); font-size: 14px; font-weight: 600; color: var(--text3); }
  .alerts-empty-sub { font-family: var(--mono); font-size: 10px; letter-spacing: 0.04em; }

  /* ── ALERT CARD ── */
  @keyframes alertSlideIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .alert-card {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 0;
    animation: alertSlideIn 0.2s ease;
    transition: border-color 0.15s;
  }
  .alert-card:hover { border-color: var(--border2); }

  /* Channel header row */
  .alert-channel {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--text3);
    margin-bottom: 6px;
  }
  .alert-channel.ch-conviction { color: #f5cc56; } /* gold for Conviction — matches cross-ticker tier badges + signals elevated channel */
  .alert-channel.ch-gex        { color: var(--barney); } /* purple for GEX — matches our negative-GEX data-encoding color */
  .alert-channel.ch-flow       { color: var(--gate); } /* teal for Flow — visually distinct from GEX purple + Conviction gold */

  /* Channel + tier-badge row (4/29/26).
     Tier badge encodes ladder rung (Full Quorum → Quorum → Pattern Conviction
     CRITICAL/HIGH/MEDIUM) independently of severity color (red/amber/yellow).
     Severity says "how urgent"; tier says "how structurally deep." */
  .alert-channel-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
  }
  .alert-channel-row .alert-channel { margin-bottom: 0; }

  .alert-tier-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.08em;
    line-height: 1.4;
    white-space: nowrap;
  }
  /* Rung 1 — Apex (Full Quorum): gold filled + glow */
  .alert-tier-badge.tier-apex {
    background: linear-gradient(180deg, #f5cc56 0%, #e69500 100%);
    color: #1a0e00;
    box-shadow: 0 0 8px rgba(245,200,86,0.55);
  }
  /* Rung 2 — Cross-ticker (Quorum): gold filled, no glow */
  .alert-tier-badge.tier-crossT {
    background: linear-gradient(180deg, #f5cc56 0%, #e69500 100%);
    color: #1a0e00;
  }
  /* Per-ticker tier badges (tier-perT-*) retired 4/29/26.
     Pattern Conviction now routes by channel based on severity:
       CRITICAL → 'conviction' channel (gold label, no badge)
       HIGH/MED → 'gex' channel (purple label, no badge)
     Channel encodes structural depth; severity color encodes urgency. */

  /* Apex card glow — applied only to Full Quorum (rung 1).
     Subtle outline + soft outer halo so apex alerts are spottable
     from a scan-distance away without being gaudy. */
  .alert-card.tier-apex-card {
    border-color: rgba(245,200,86,0.45);
    box-shadow: 0 0 0 1px rgba(245,200,86,0.25), 0 0 16px rgba(245,200,86,0.12);
  }
  .alert-card.tier-apex-card:hover {
    border-color: rgba(245,200,86,0.7);
  }
  .toast-card.tier-apex-card {
    border-color: rgba(245,200,86,0.5);
    box-shadow: 0 4px 14px rgba(0,0,0,0.4), 0 0 16px rgba(245,200,86,0.18);
  }

  /* Title row: severity dot + bold title */
  .alert-title-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 8px;
  }
  .alert-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    margin-top: 3px;
  }
  .alert-dot.CRITICAL { background: var(--red); box-shadow: 0 0 6px rgba(239,68,68,0.5); }
  .alert-dot.HIGH     { background: var(--king); box-shadow: 0 0 6px rgba(255,107,53,0.4); }
  .alert-dot.MEDIUM   { background: var(--pika); box-shadow: 0 0 6px rgba(245,200,66,0.3); }

  .alert-title-text {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.4;
    flex: 1;
  }

  /* Description */
  .alert-desc {
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text2);
    line-height: 1.6;
    letter-spacing: 0.02em;
    margin-bottom: 10px;
  }

  /* Two-column footer (Ticker | Severity) */
  .alert-footer {
    display: flex;
    gap: 24px;
    border-top: 1px solid var(--border);
    padding-top: 8px;
    align-items: flex-end;
  }
  .alert-footer-col {}
  .alert-footer-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.06em;
    color: var(--text3);
    margin-bottom: 2px;
  }
  .alert-footer-value {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 700;
    color: var(--text);
  }
  .alert-footer-value.CRITICAL { color: var(--red); }
  .alert-footer-value.HIGH     { color: var(--king); }
  .alert-footer-value.MEDIUM   { color: var(--pika); }
  .alert-footer-time {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    margin-left: auto;
    align-self: flex-end;
  }

  /* ── TOASTS ── */
  #toastContainer {
    position: fixed;
    bottom: 20px;
    left: 20px;
    z-index: 10000;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 370px;
    pointer-events: none;
  }
  @keyframes toastIn {
    from { opacity: 0; transform: translateX(-10px); }
    to   { opacity: 1; transform: translateX(0); }
  }
  @keyframes toastOut {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(-10px); }
  }
  .toast-card {
    background: var(--bg2);
    border: 1px solid var(--border2);
    border-left: 3px solid var(--border2);
    border-radius: 8px;
    padding: 9px 11px;
    display: flex;
    flex-direction: column;
    gap: 0;
    cursor: pointer;
    pointer-events: all;
    animation: toastIn 0.18s ease;
    box-shadow: 0 6px 24px rgba(0,0,0,0.7);
  }
  .toast-card.CRITICAL { border-left-color: var(--red); }
  .toast-card.HIGH     { border-left-color: var(--king); }
  .toast-card.MEDIUM   { border-left-color: var(--pika); }

  /* Top row: channel label + severity badge + close */
  .toast-header {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 5px;
  }
  .toast-channel {
    font-family: var(--mono);
    font-size: 8px;
    letter-spacing: 0.07em;
    color: var(--text3);
    flex: 0 0 auto;
  }
  /* Channel-aware toast tinting — matches the alert card .ch-* rules
     so the same alert reads consistently across toast + feed. */
  .toast-channel.toast-channel-conviction { color: #f5cc56; } /* gold — matches alert-card .ch-conviction */
  .toast-channel.toast-channel-gex        { color: var(--barney); } /* purple — matches alert-card .ch-gex */
  .toast-channel.toast-channel-flow       { color: var(--gate); }
  /* Push severity + close to the right, leaving channel + tier-badge on the left */
  .toast-header .toast-sev { margin-left: auto; }
  /* Smaller tier badges in toasts to fit the tighter row */
  .toast-header .alert-tier-badge {
    font-size: 8px;
    padding: 1px 6px;
  }
  .toast-sev {
    font-family: var(--mono);
    font-size: 8px;
    font-weight: 700;
    letter-spacing: 0.07em;
    padding: 1px 5px;
    border-radius: 3px;
  }
  .toast-sev.CRITICAL { background: rgba(239,68,68,0.18); color: var(--red); }
  .toast-sev.HIGH     { background: rgba(255,107,53,0.18); color: var(--king); }
  .toast-sev.MEDIUM   { background: rgba(245,200,66,0.15); color: var(--pika); }
  .toast-close {
    font-size: 11px;
    color: var(--text3);
    flex-shrink: 0;
    line-height: 1;
    padding: 1px 2px;
    transition: color 0.1s;
  }
  .toast-close:hover { color: var(--text); }

  /* Title row: dot + bold title */
  .toast-title-row {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin-bottom: 5px;
  }
  .toast-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    margin-top: 3px;
  }
  .toast-dot.CRITICAL { background: var(--red); }
  .toast-dot.HIGH     { background: var(--king); }
  .toast-dot.MEDIUM   { background: var(--pika); }
  .toast-title {
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.4;
  }

  /* Description */
  .toast-desc {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text2);
    line-height: 1.55;
    letter-spacing: 0.02em;
    margin-bottom: 7px;
    padding-left: 14px; /* align under title (past dot+gap) */
  }

  /* Footer: ticker + timestamp */
  .toast-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-top: 1px solid var(--border);
    padding-top: 5px;
  }
  .toast-ticker {
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--text2);
  }
  .toast-time {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
  }

  /* ── ATLAS VIEW ── */
  #view-chart { display: none; flex-direction: column; height: calc(100vh - 52px); }
  #view-chart.active { display: flex; }

  .atlas-toolbar {
    background: var(--bg2);
    border-bottom: 1px solid var(--border);
    padding: 6px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .atlas-toolbar-row {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
  }
  .atlas-tf-group {
    display: flex;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 2px;
    gap: 1px;
  }
  .atlas-tf-btn {
    font-family: var(--mono);
    font-size: 10px;
    padding: 4px 10px;
    border: none;
    border-radius: 4px;
    background: transparent;
    color: var(--text3);
    cursor: pointer;
    transition: all 0.15s;
  }
  .atlas-tf-btn:hover { color: var(--text); }
  .atlas-tf-btn.active {
    background: var(--border2);
    color: var(--text);
  }
  .atlas-select {
    font-family: var(--mono);
    font-size: 10px;
    padding: 4px 8px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text2);
    cursor: pointer;
    outline: none;
  }
  .atlas-select:focus { border-color: var(--pika); }

  .atlas-toggle {
    position: relative;
    display: inline-block;
    width: 32px;
    height: 16px;
  }
  .atlas-toggle input { opacity: 0; width: 0; height: 0; }
  .atlas-toggle-slider {
    position: absolute;
    cursor: pointer;
    inset: 0;
    background: var(--bg3);
    border-radius: 16px;
    border: 1px solid var(--border);
    transition: 0.2s;
  }
  .atlas-toggle-slider::before {
    content: '';
    position: absolute;
    height: 10px;
    width: 10px;
    left: 2px;
    bottom: 2px;
    background: var(--text3);
    border-radius: 50%;
    transition: 0.2s;
  }
  .atlas-toggle input:checked + .atlas-toggle-slider {
    background: rgba(34,197,94,0.3);
    border-color: rgba(34,197,94,0.5);
  }
  .atlas-toggle input:checked + .atlas-toggle-slider::before {
    transform: translateX(16px);
    background: #22c55e;
  }

  .atlas-main {
    display: flex;
    flex: 1;
    min-height: 0;
  }
  .atlas-chart-container {
    flex: 1;
    position: relative;
    background: var(--bg);
    min-height: 0;
  }
  .atlas-sidebar {
    width: 260px;
    border-left: 1px solid var(--border);
    background: var(--bg2);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
  }

  .atlas-mini-panel {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
  }
  .atlas-mini-header {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
  }
  .atlas-mini-symbol {
    font-family: var(--sans);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
  }
  .atlas-mini-spot {
    font-family: var(--mono);
    font-size: 12px;
    color: var(--text);
  }
  .atlas-mini-change {
    font-family: var(--mono);
    font-size: 10px;
  }
  /* Heat-decay chip on Atlas mini-panel header. Same zone classes as
     the heatmap toolbar gauge so colors stay consistent across views. */
  .atlas-mini-heat {
    margin-left: 8px;
    padding: 2px 6px;
    border-radius: 4px;
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.04em;
    background: var(--bg3);
    border: 1px solid var(--border);
    cursor: help;
  }
  .atlas-mini-heat.heat-zone-suppressed { color: var(--text2); }
  .atlas-mini-heat.heat-zone-elevated   { background: var(--pika3); color: var(--pika); border-color: rgba(245,200,66,0.35); }
  .atlas-mini-heat.heat-zone-heavy      { background: var(--king2); color: var(--king); border-color: rgba(255,107,53,0.45); }
  .atlas-mini-heat.heat-zone-extreme    { background: rgba(239,68,68,0.18); color: var(--red); border-color: rgba(239,68,68,0.55); }
  .atlas-mini-heat.heat-zone-bootstrap  { color: var(--text3); border-style: dashed; }
  .atlas-mini-bar-row {
    display: flex;
    align-items: center;
    gap: 4px;
    height: 14px;
    margin-bottom: 2px;
  }
  .atlas-mini-strike {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    width: 32px;
    text-align: right;
    flex-shrink: 0;
  }
  .atlas-mini-bar-track {
    flex: 1;
    height: 8px;
    background: var(--bg3);
    border-radius: 2px;
    overflow: hidden;
    position: relative;
  }
  .atlas-mini-bar-fill {
    height: 100%;
    border-radius: 2px;
    min-width: 2px;
  }
  .atlas-mini-pct {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    width: 28px;
    text-align: right;
    flex-shrink: 0;
  }

  /* ── FLOW VIEW ── */
  #view-flow { display: none; }
  #view-flow.active { display: block; }
  .flow-view { display:flex; flex-direction:column; gap:16px; }
  .flow-header { display:flex; flex-direction:column; gap:4px; }
  .flow-title { font-family:var(--sans); font-size:22px; font-weight:700; letter-spacing:-0.01em; }
  .flow-subtitle { font-family:var(--mono); font-size:10px; color:var(--text3); letter-spacing:0.15em; text-transform:uppercase; }
  .flow-stats { display:grid; grid-template-columns:repeat(4, 1fr); gap:12px; }
  .flow-stat { background:var(--bg2); border:1px solid var(--border); border-radius:8px; padding:14px 16px; display:flex; align-items:center; gap:12px; }
  .flow-stat-icon { width:28px; height:28px; border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:14px; flex-shrink:0; }
  .flow-stat-ic-bull  { background:rgba(34,197,94,0.12); color:var(--green); }
  .flow-stat-ic-bear  { background:rgba(239,68,68,0.12); color:var(--red); }
  .flow-stat-ic-total { background:rgba(155,93,229,0.12); color:var(--barney); }
  .flow-stat-ic-prem  { background:rgba(96,165,250,0.12); color:var(--flip); }
  .flow-stat-body { display:flex; flex-direction:column; line-height:1.1; }
  .flow-stat-val { font-family:var(--mono); font-size:20px; font-weight:700; }
  .flow-stat-lbl { font-family:var(--mono); font-size:10px; color:var(--text3); letter-spacing:0.08em; text-transform:uppercase; margin-top:3px; }
  .flow-card { background:var(--bg2); border:1px solid var(--border); border-radius:8px; overflow:hidden; }
  .flow-card-head { display:flex; align-items:center; justify-content:space-between; padding:10px 14px; border-bottom:1px solid var(--border); font-family:var(--mono); font-size:11px; color:var(--text2); letter-spacing:0.08em; text-transform:uppercase; }
  .flow-card-meta { display:flex; gap:12px; color:var(--text3); font-size:10px; }
  .flow-meta-dot { width:6px; height:6px; border-radius:50%; background:var(--green); box-shadow:0 0 6px var(--green); display:inline-block; margin-right:5px; vertical-align:middle; }
  .flow-table-wrap { overflow-x:auto; max-height:65vh; overflow-y:auto; }
  .flow-table { width:100%; border-collapse:collapse; font-family:var(--mono); font-size:11px; }
  .flow-table thead th { position:sticky; top:0; background:var(--bg2); color:var(--text3); font-weight:500; font-size:9px; letter-spacing:0.1em; text-transform:uppercase; text-align:right; padding:10px 10px; border-bottom:1px solid var(--border); white-space:nowrap; z-index:1; }
  .flow-table thead th:nth-child(1),
  .flow-table thead th:nth-child(2),
  .flow-table thead th:nth-child(7),
  .flow-table thead th:nth-child(8),
  .flow-table thead th:nth-child(15),
  .flow-table thead th:nth-child(16) { text-align:left; }
  .flow-table tbody td { padding:8px 10px; border-bottom:1px solid var(--border); text-align:right; white-space:nowrap; font-feature-settings:"tnum"; }
  .flow-table tbody tr:hover { background:var(--bg-subtle); }
  .flow-table tbody td:nth-child(1),
  .flow-table tbody td:nth-child(2),
  .flow-table tbody td:nth-child(7),
  .flow-table tbody td:nth-child(8),
  .flow-table tbody td:nth-child(15),
  .flow-table tbody td:nth-child(16) { text-align:left; }
  .flow-time { color:var(--text3); }
  .flow-sym { font-weight:700; letter-spacing:0.02em; }
  .flow-tag { display:inline-block; padding:2px 6px; font-size:9px; border-radius:3px; letter-spacing:0.08em; margin-left:6px; font-weight:600; }
  .flow-tag-block { background:rgba(155,93,229,0.15); color:var(--barney); }
  .flow-tag-print { background:var(--bg-subtle); color:var(--text3); }
  .flow-tag-sweep { background:rgba(0,200,150,0.18); color:#4fe3b6; }
  .flow-tag-sweep-block { background:linear-gradient(90deg, rgba(0,200,150,0.22), rgba(155,93,229,0.22)); color:#ffeead; }
  .flow-tag-ern { background:rgba(255,175,45,0.18); color:#ffc86e; }
  .flow-tag-ern::before { content:'⚡'; margin-right:3px; }
  .flow-score { display:inline-block; padding:3px 8px; border-radius:4px; font-weight:700; min-width:34px; text-align:center; }
  /* 5-tier score bucketing (4/27/26 PM peer-recon): cutoffs 9 / 7 / 5 / 3.
     Was 9 / 8 / 6 with no LOW tier — peer's earlier tiering means a
     score-7 print now reads "hi" (visually distinct red) instead of
     getting lumped into mid amber. Brings hierarchy in line with the
     industry baseline.
       elite (≥9)  → orange (rarest, 1-3/session)
       hi    (≥7)  → red
       mid   (≥5)  → amber
       low   (≥3)  → sky      (NEW tier — was lumped into "low")
       muted (<3)  → zinc dim (NEW tier — effectively hidden) */
  .flow-score-muted { background:var(--bg-subtle); color:var(--text3); }
  .flow-score-low   { background:rgba(56,189,248,0.10); color:#7dd3fc; }
  .flow-score-mid   { background:rgba(245,200,66,0.12); color:var(--pika); }
  .flow-score-hi    { background:rgba(239,68,68,0.15); color:var(--red); }
  /* Elite (≥9) — rarest tier, ~1-3 prints per session. Orange (king-node
     brand color) keeps it visually distinct from red 'hi' and signals the
     escalation. Border ring + slight letter spacing draw the eye. */
  .flow-score-elite {
    background:var(--king2); color:var(--king);
    box-shadow:0 0 0 1px rgba(255,107,53,0.45);
    letter-spacing:0.5px; font-weight:800;
  }
  .flow-type-call { color:var(--green); font-weight:700; }
  .flow-type-put  { color:var(--red); font-weight:700; }
  .flow-side-ask  { color:var(--green); }
  .flow-side-bid  { color:var(--red); }
  .flow-side-mid  { color:var(--text3); }
  .flow-sent-bull { color:var(--green); }
  .flow-sent-bear { color:var(--red); }
  .flow-sent-neu  { color:var(--text3); }
  .flow-empty { padding:60px 24px; text-align:center; color:var(--text3); font-family:var(--mono); font-size:12px; }

  /* ── FLOW collapsible cards (Watchlist + Alerts panel) ── */
  .flow-collapsible .flow-card-head { cursor:pointer; user-select:none; }
  .flow-collapsible .flow-card-head:hover { background:var(--bg-hover); }
  .flow-collapsible .flow-card-body { padding:12px 14px; border-top:1px solid var(--border); display:block; }
  .flow-collapsible.collapsed .flow-card-body { display:none; }
  .flow-collapsible.collapsed .flow-card-head { border-bottom:none; }
  .flow-card-count { display:inline-block; margin-left:8px; padding:1px 8px; background:var(--bg3); color:var(--text2); border-radius:10px; font-family:var(--mono); font-size:9px; font-weight:700; }
  .flow-card-count-crit { background:rgba(155,93,229,0.15); color:var(--barney); }
  .flow-alert-clear { background:transparent; border:1px solid var(--border); color:var(--text3); padding:3px 8px; font-family:var(--mono); font-size:9px; border-radius:4px; cursor:pointer; letter-spacing:0.06em; }
  .flow-alert-clear:hover { color:var(--text); border-color:var(--border2); }

  /* ── Watchlist ── */
  .flow-watch-row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-bottom:10px; }
  .flow-watch-chips { display:flex; flex-wrap:wrap; gap:6px; }
  .flow-watch-chips:empty::before { content:'No tickers yet — add one above to narrow the flow feed.'; font-family:var(--mono); font-size:10px; color:var(--text3); font-style:italic; }
  .flow-watch-chip { display:inline-flex; align-items:center; gap:6px; padding:4px 10px; background:var(--bg3); border:1px solid var(--border2); border-radius:14px; font-family:var(--mono); font-size:10px; color:var(--text); }
  .flow-watch-chip button { background:transparent; border:none; color:var(--text3); cursor:pointer; padding:0 2px; font-size:12px; line-height:1; }
  .flow-watch-chip button:hover { color:var(--red); }

  /* ── Flow Alerts panel ── */
  .flow-alerts-list { display:flex; flex-direction:column; gap:6px; max-height:340px; overflow-y:auto; }
  .flow-alerts-list:empty::before { content:'No flow alerts yet. Accumulation / whale / extreme V/OI prints will surface here.'; font-family:var(--mono); font-size:10px; color:var(--text3); font-style:italic; padding:14px 4px; text-align:center; display:block; }
  .flow-alert-row { display:flex; align-items:center; gap:10px; padding:8px 10px; background:var(--bg3); border:1px solid var(--border); border-radius:6px; }
  .flow-alert-row .sev { font-family:var(--mono); font-size:9px; font-weight:700; padding:2px 6px; border-radius:3px; letter-spacing:0.06em; flex-shrink:0; }
  .flow-alert-row .sev-CRITICAL { background:rgba(239,68,68,0.15); color:var(--red); }
  .flow-alert-row .sev-HIGH     { background:rgba(245,200,66,0.15); color:var(--pika); }
  .flow-alert-row .sev-MEDIUM   { background:rgba(96,165,250,0.15); color:var(--flip); }
  .flow-alert-row .type-tag { font-family:var(--mono); font-size:9px; color:var(--text2); letter-spacing:0.08em; text-transform:uppercase; flex-shrink:0; }
  .flow-alert-row .title { font-family:var(--mono); font-size:11px; color:var(--text); font-weight:700; flex-shrink:0; }
  .flow-alert-row .desc  { font-family:var(--mono); font-size:10px; color:var(--text2); flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .flow-alert-row .ts    { font-family:var(--mono); font-size:9px; color:var(--text3); flex-shrink:0; }

  /* ── FLOW filter chips ── */
  .flow-filters { display:flex; gap:8px; align-items:center; flex-wrap:wrap; padding:8px 0; }
  .flow-filter-input, .flow-filter-select { background:var(--bg2); color:var(--text); border:1px solid var(--border); border-radius:6px; padding:7px 10px; font-family:var(--mono); font-size:11px; outline:none; }
  .flow-filter-input { min-width:180px; }
  .flow-filter-input::placeholder { color:var(--text3); }
  .flow-filter-input:focus, .flow-filter-select:focus { border-color:var(--barney); }
  .flow-chip-toggle { background:var(--bg2); color:var(--text2); border:1px solid var(--border); border-radius:6px; padding:7px 10px; font-family:var(--mono); font-size:10px; letter-spacing:0.06em; cursor:pointer; text-transform:uppercase; }
  .flow-chip-toggle.active { background:rgba(155,93,229,0.15); color:var(--barney); border-color:var(--barney); }
  .flow-filter-spacer { flex:1; }
  .flow-filter-clear { background:transparent; color:var(--text3); border:1px solid var(--border); border-radius:6px; padding:7px 12px; font-family:var(--mono); font-size:10px; cursor:pointer; text-transform:uppercase; letter-spacing:0.06em; }
  .flow-filter-clear:hover { color:var(--text); border-color:var(--border2); }

  /* ── FLOW row click / detail modal ── */
  .flow-table tbody tr { cursor:pointer; }
  .flow-modal-backdrop { position:fixed; inset:0; background:rgba(5,8,12,0.7); backdrop-filter:blur(4px); z-index:999; display:none; align-items:center; justify-content:center; padding:32px; }
  .flow-modal-backdrop.active { display:flex; }
  .flow-modal { background:var(--bg2); border:1px solid var(--border2); border-radius:10px; width:100%; max-width:940px; max-height:90vh; display:flex; flex-direction:column; box-shadow:0 20px 60px rgba(0,0,0,0.5); overflow:hidden; }
  .flow-modal-head { display:flex; align-items:center; gap:12px; padding:14px 18px; border-bottom:1px solid var(--border); flex-shrink:0; }
  .flow-modal-sym { font-family:var(--mono); font-weight:700; font-size:15px; }
  .flow-modal-spot { font-family:var(--mono); font-size:13px; color:var(--text2); }
  .flow-modal-pill { font-family:var(--mono); font-size:10px; font-weight:700; padding:3px 8px; border-radius:4px; letter-spacing:0.06em; }
  .flow-modal-pill-call { background:rgba(34,197,94,0.15); color:var(--green); }
  .flow-modal-pill-put  { background:rgba(239,68,68,0.15); color:var(--red); }
  .flow-modal-exp { font-family:var(--mono); font-size:12px; color:var(--text2); }
  .flow-modal-dte { font-family:var(--mono); font-size:11px; color:var(--text3); padding:2px 6px; border-radius:3px; background:var(--bg3); }
  .flow-modal-tag { font-family:var(--mono); font-size:10px; font-weight:700; padding:3px 8px; border-radius:4px; letter-spacing:0.06em; }
  .flow-modal-tag-block { background:rgba(155,93,229,0.15); color:var(--barney); }
  .flow-modal-tag-print { background:rgba(245,200,66,0.15); color:var(--pika); }
  .flow-modal-score { font-family:var(--mono); font-size:10px; font-weight:700; padding:3px 8px; border-radius:4px; background:rgba(255,107,53,0.15); color:var(--king); letter-spacing:0.04em; }
  .flow-modal-close { margin-left:auto; background:transparent; border:none; color:var(--text3); font-size:18px; cursor:pointer; padding:2px 8px; border-radius:4px; }
  .flow-modal-close:hover { color:var(--text); background:var(--bg3); }
  .flow-modal-body { padding:16px 18px; overflow-y:auto; flex:1; }
  .flow-metric-grid { display:grid; grid-template-columns:repeat(4, 1fr); gap:10px; margin-bottom:16px; }
  .flow-metric-cell { background:var(--bg3); border:1px solid var(--border); border-radius:6px; padding:10px 12px; }
  .flow-metric-lbl { font-family:var(--mono); font-size:9px; color:var(--text3); letter-spacing:0.1em; text-transform:uppercase; margin-bottom:3px; display:flex; gap:4px; align-items:center; }
  .flow-metric-val { font-family:var(--mono); font-size:14px; font-weight:700; color:var(--text); }
  .flow-modal-tabs { display:flex; gap:4px; border-bottom:1px solid var(--border); margin-bottom:12px; overflow-x:auto; scrollbar-width:none; }
  .flow-modal-tabs::-webkit-scrollbar { display:none; }
  .flow-modal-tab { background:transparent; border:none; color:var(--text3); padding:8px 14px; font-family:var(--sans); font-size:12px; font-weight:500; cursor:pointer; border-bottom:2px solid transparent; white-space:nowrap; }
  .flow-modal-tab.active { color:var(--text); border-bottom-color:var(--barney); }
  .flow-modal-tab:hover:not(.active) { color:var(--text2); }
  .flow-trades-summary { display:flex; gap:22px; padding:10px 0; font-family:var(--mono); font-size:11px; color:var(--text2); border-bottom:1px solid var(--border); flex-wrap:wrap; }
  .flow-trades-summary strong { color:var(--text); font-weight:700; }
  .flow-trades-summary .ask  { color:var(--green); }
  .flow-chart-wrap { padding:14px 0; }
  .flow-chart-svg  { width:100%; height:260px; display:block; }
  .flow-chart-legend { display:flex; gap:16px; padding:8px 0 12px; font-family:var(--mono); font-size:10px; color:var(--text2); flex-wrap:wrap; }
  .flow-chart-legend-dot { width:10px; height:10px; border-radius:50%; display:inline-block; margin-right:5px; vertical-align:middle; }
  .flow-trades-list { width:100%; border-collapse:collapse; font-family:var(--mono); font-size:11px; }
  .flow-trades-list th { text-align:left; font-size:9px; letter-spacing:0.1em; text-transform:uppercase; color:var(--text3); font-weight:500; padding:8px 10px; border-bottom:1px solid var(--border); }
  .flow-trades-list th:not(:first-child) { text-align:right; }
  .flow-trades-list td { padding:6px 10px; border-bottom:1px solid var(--border); text-align:right; }
  .flow-trades-list td:first-child { text-align:left; color:var(--text3); }
  .flow-trades-list td.side-ask { color:var(--green); font-weight:700; }
  .flow-trades-list td.side-bid { color:var(--red);   font-weight:700; }
  .flow-trades-list td.side-mid { color:var(--text3); }
  .flow-tab-placeholder { padding:40px 20px; text-align:center; color:var(--text3); font-family:var(--mono); font-size:11px; background:var(--bg3); border-radius:6px; margin:10px 0; line-height:1.5; }
  /* Loading shell — same look as placeholder but in a "working" tone. */
  .flow-tab-loading { padding:40px 20px; text-align:center; color:var(--text2); font-family:var(--mono); font-size:11px; background:var(--bg3); border-radius:6px; margin:10px 0; opacity:0.7; }

  /* ── Price Chart pane ─────────────────────────────────────────── */
  .flow-pricechart-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 10px 0;
  }
  .flow-pricechart-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 10px;
    font-family: var(--mono);
    font-size: 10px;
    color: var(--text3);
    letter-spacing: 0.04em;
  }
  .flow-pricechart-meta { white-space: nowrap; }
  .flow-pricechart-container {
    width: 100%;
    height: 280px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
  }

  /* ── Outcome pane ─────────────────────────────────────────────── */
  .flow-outcome-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 22px 16px;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: 6px;
  }
  .flow-outcome-hero-label {
    font-family: var(--mono);
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.10em;
    text-transform: uppercase;
    margin-bottom: 6px;
  }
  .flow-outcome-hero-value {
    font-family: var(--mono);
    font-size: 32px;
    font-weight: 700;
    line-height: 1;
    margin-bottom: 8px;
    letter-spacing: -0.02em;
  }
  .flow-outcome-hero-sub {
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text2);
    line-height: 1.5;
  }

  /* ── FLOW modal panels (Volume / Put-Call) ── */
  .flow-panel { background:var(--bg3); border:1px solid var(--border); border-radius:6px; padding:12px 14px; }
  .flow-panel-title { font-family:var(--mono); font-size:10px; letter-spacing:0.1em; text-transform:uppercase; color:var(--text3); margin-bottom:14px; }
  .flow-vol-chart { position:relative; padding-bottom:22px; }
  .flow-vol-row { display:flex; align-items:center; gap:12px; margin-bottom:10px; }
  .flow-vol-lbl { width:80px; font-family:var(--mono); font-size:11px; color:var(--text2); flex-shrink:0; }
  .flow-vol-bar-wrap { flex:1; height:22px; background:var(--bg2); border-radius:3px; overflow:hidden; position:relative; }
  .flow-vol-bar { height:100%; border-radius:3px; transition:width 0.3s ease; }
  .flow-vol-axis { position:relative; height:14px; margin-left:92px; font-family:var(--mono); font-size:9px; color:var(--text3); }
  .flow-vol-axis span { position:absolute; transform:translateX(-50%); top:0; }
  .flow-total-row td { border-top:1px solid var(--border2); background:var(--bg-hover); }

  /* ── FLOW Put/Call chart ── */
  .flow-pc-chart { display:flex; gap:10px; align-items:stretch; height:180px; }
  .flow-pc-yaxis { display:flex; flex-direction:column; justify-content:space-between; font-family:var(--mono); font-size:9px; color:var(--text3); padding:4px 0; width:50px; text-align:right; flex-shrink:0; }
  .flow-pc-bars { flex:1; display:flex; gap:14%; padding:0 12%; align-items:flex-end; border-left:1px solid var(--border); border-bottom:1px solid var(--border); position:relative; }
  .flow-pc-bar-col { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height:100%; gap:6px; }
  .flow-pc-bar { width:100%; max-width:120px; border-radius:4px 4px 0 0; min-height:2px; }
  .flow-pc-bar-col span { font-family:var(--mono); font-size:10px; color:var(--text2); letter-spacing:0.04em; }
  .flow-pc-split { display:flex; height:16px; border-radius:3px; overflow:hidden; background:var(--bg2); }
  .flow-pc-split-call { background:var(--green); transition:width 0.3s ease; }
  .flow-pc-split-put  { background:var(--red);   transition:width 0.3s ease; }
  .flow-pc-split-lbl { display:flex; justify-content:space-between; font-family:var(--mono); font-size:10px; margin-top:6px; }

  /* ── FLOW gear / settings modal ── */
  .flow-chip-gear { background:var(--bg2); color:var(--text2); border:1px solid var(--border); border-radius:6px; padding:6px 10px; font-size:14px; line-height:1; cursor:pointer; }
  .flow-chip-gear:hover { color:var(--text); border-color:var(--border2); }
  .fs-date-row { display:flex; align-items:center; gap:10px; padding:10px 12px; background:var(--bg3); border:1px solid var(--border); border-radius:6px; margin-bottom:16px; flex-wrap:wrap; }
  .fs-date-row label { font-family:var(--mono); font-size:10px; color:var(--text3); letter-spacing:0.08em; text-transform:uppercase; display:flex; align-items:center; gap:6px; }
  .fs-date-row input[type=date] { background:var(--bg2); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:5px 8px; font-family:var(--mono); font-size:11px; }
  .fs-live-pill { font-family:var(--mono); font-size:10px; color:var(--green); display:inline-flex; align-items:center; gap:5px; }
  .fs-live-pill::before { content:''; width:6px; height:6px; background:var(--green); box-shadow:0 0 5px var(--green); border-radius:50%; }
  .fs-section { margin-bottom:18px; }
  .fs-section-title { font-family:var(--mono); font-size:10px; color:var(--text3); letter-spacing:0.12em; text-transform:uppercase; margin-bottom:10px; }
  .fs-grid2 { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
  .fs-field { display:flex; flex-direction:column; gap:4px; }
  .fs-field-lbl { font-family:var(--sans); font-size:11px; color:var(--text2); }
  .fs-field-lbl.has-help { border-bottom:1px dotted var(--text3); display:inline-block; cursor:help; }
  .fs-field input[type=text], .fs-field input[type=number] { background:var(--bg2); color:var(--text); border:1px solid var(--border); border-radius:4px; padding:7px 9px; font-family:var(--mono); font-size:11px; outline:none; }
  .fs-field input:focus { border-color:var(--barney); }
  .fs-field input::placeholder { color:var(--text3); }
  .fs-helper { font-family:var(--mono); font-size:10px; color:var(--text3); margin-top:6px; line-height:1.4; }
  .fs-chip-row { display:flex; flex-wrap:wrap; gap:6px; }
  .fs-chip { background:var(--bg2); border:1px solid var(--border); color:var(--text2); padding:6px 11px; border-radius:16px; font-family:var(--mono); font-size:10px; cursor:pointer; letter-spacing:0.04em; }
  .fs-chip.active { background:rgba(155,93,229,0.14); color:var(--barney); border-color:var(--barney); }
  .fs-flag-row { display:flex; gap:8px; }
  .fs-flag { padding:6px 14px; border-radius:16px; font-family:var(--mono); font-size:10px; letter-spacing:0.06em; cursor:pointer; border:1px solid transparent; }
  .fs-flag.sweep  { background:rgba(245,158,11,0.15); color:#f59e0b; border-color:#f59e0b; }
  .fs-flag.sweep.off  { background:transparent; color:var(--text3); border-color:var(--border); }
  .fs-flag.block  { background:rgba(6,182,212,0.15); color:#06b6d4; border-color:#06b6d4; }
  .fs-flag.block.off  { background:transparent; color:var(--text3); border-color:var(--border); }
  .fs-flag.normal { background:var(--bg-subtle); color:var(--text); border-color:var(--border2); }
  .fs-flag.normal.off { color:var(--text3); border-color:var(--border); background:transparent; }
  .fs-presets-row { display:flex; justify-content:space-between; align-items:center; margin-bottom:10px; }
  .fs-presets-empty { font-family:var(--mono); font-size:10px; color:var(--text3); font-style:italic; }
  .fs-preset-save { display:flex; align-items:center; gap:6px; background:var(--bg3); border:1px solid var(--border); color:var(--text2); padding:6px 10px; border-radius:6px; font-family:var(--mono); font-size:10px; cursor:pointer; }
  .fs-preset-save:hover { color:var(--text); border-color:var(--border2); }
  .fs-preset-item { display:flex; justify-content:space-between; align-items:center; padding:8px 12px; background:var(--bg2); border:1px solid var(--border); border-radius:4px; margin-bottom:6px; font-family:var(--mono); font-size:11px; }
  .fs-preset-item button { background:transparent; color:var(--text3); border:none; cursor:pointer; padding:2px 6px; font-size:13px; }
  .fs-preset-item button:hover { color:var(--text); }
  .fs-preset-name { color:var(--text); cursor:pointer; }
  .fs-preset-name:hover { color:var(--barney); }

  /* ── NARRATIVE VIEW ── */
  #view-narrative { display: none; }
  #view-narrative.active { display: block; }
  #view-narrative.view { padding:0; }
  .narrative-view { display:flex; flex-direction:column; min-height:0; }
  .narrative-header { display:flex; gap:16px; padding:12px 24px; border-bottom:1px solid var(--border); align-items:center; flex-wrap:wrap; flex-shrink:0; }
  .narrative-bias { font-family:var(--mono); font-weight:700; font-size:15px; }
  .narrative-confidence-bar { height:4px; border-radius:2px; background:var(--bg3); margin-top:4px; width:120px; overflow:hidden; }
  .narrative-confidence-fill { height:100%; border-radius:2px; transition:width 0.4s; }
  .narrative-chip { font-family:var(--mono); font-size:11px; color:var(--text2); padding:4px 10px; background:var(--bg3); border-radius:4px; white-space:nowrap; }
  .narrative-timeline-wrap { display:flex; align-items:center; gap:10px; padding:8px 24px; border-bottom:1px solid var(--border); flex-shrink:0; overflow:hidden; }
  .narrative-timeline-label { font-family:var(--mono); font-size:9px; letter-spacing:0.1em; color:var(--text3); text-transform:uppercase; white-space:nowrap; }
  .narrative-timeline { display:flex; gap:6px; overflow-x:auto; scrollbar-width:none; flex:1; }
  .narrative-timeline::-webkit-scrollbar { display:none; }
  .narrative-snap { flex-shrink:0; background:var(--bg2); border:1px solid var(--border2); border-radius:6px; padding:6px 10px; cursor:pointer; transition:border-color 0.1s; min-width:70px; }
  .narrative-snap:hover { border-color:var(--border); }
  .narrative-snap.active { border-color:var(--king); }
  .narrative-snap-time { font-family:var(--mono); font-size:9px; color:var(--text3); }
  .narrative-snap-bias { font-family:var(--mono); font-size:10px; font-weight:700; margin-top:2px; }
  .narrative-snap-conf { font-family:var(--mono); font-size:9px; color:var(--text3); }
  .narrative-delta { font-family:var(--mono); font-size:9px; color:var(--text3); padding:3px 6px; background:var(--bg3); border-radius:3px; margin-top:3px; }
  .narrative-body { display:flex; flex-direction:column; gap:16px; padding:16px 24px; }
  .narrative-col-main { min-width:0; }
  .narrative-greeks-row { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:4px; }
  .narrative-section { background:var(--bg2); border:1px solid var(--border); border-radius:8px; padding:18px 20px; margin-bottom:12px; }
  .narrative-thesis { font-family:var(--mono); font-size:13px; font-weight:700; color:var(--text); line-height:1.5; padding:12px 14px; margin-bottom:14px; background:rgba(212,175,55,.06); border:1px solid rgba(212,175,55,.15); border-radius:5px; letter-spacing:0.01em; }
  .narrative-section-title { font-family:var(--mono); font-size:9px; letter-spacing:0.12em; color:var(--text3); text-transform:uppercase; margin-bottom:10px; }
  .narrative-setup-note { font-family:var(--mono); font-size:13px; color:var(--text2); line-height:1.65; }
  .scenario-favored-tag { font-size:7.5px; font-weight:700; letter-spacing:0.1em; color:var(--king); opacity:0.7; margin-left:6px; }
  .scenario-alt-tag { font-size:7.5px; font-weight:700; letter-spacing:0.1em; color:var(--text3); opacity:0.5; margin-left:6px; }
  .scenario-shared-context { margin-top:12px; padding:10px 14px; background:var(--bg-hover); border:1px solid var(--border); border-radius:5px; }
  .scenario-shared-item { font-family:var(--mono); font-size:11px; color:var(--text2); line-height:1.55; margin-top:6px; }
  .scenario-shared-item:first-child { margin-top:0; }
  .scenario-shared-label { font-size:8px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--king); opacity:0.5; margin-right:6px; }
  .scenario-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:12px; }
  .scenario-grid-single { grid-template-columns:1fr; }
  /* Confidence factor chip — short "+8 king · −6 misaligned · …" string
     under the score bar. Reveals which factors drove the score. */
  .narrative-confidence-chip { font-family:var(--mono); font-size:10px; color:var(--text3); margin-top:2px; line-height:1.3; }
  /* Phase playbook — action-first one-liner pinned to the current session
     phase. Sits between the header chips and the thesis. */
  .narrative-phase-playbook { font-family:var(--mono); font-size:11px; color:var(--text2); line-height:1.55; padding:8px 12px; margin-bottom:12px; background:var(--bg-hover); border-left:2px solid var(--text3); border-radius:0 4px 4px 0; }
  /* Pin callout — surfaces above the scenario grid when an active or
     watch-state pin candidate exists. Two color states: ACTIVE (gold/king)
     for qualifying pins, WATCH (faded) for sub-threshold candidates. */
  .narrative-pin-callout { display:flex; align-items:flex-start; gap:10px; padding:10px 14px; margin:14px 0 8px; border-radius:5px; }
  .narrative-pin-active { background:rgba(212,175,55,.08); border:1px solid rgba(212,175,55,.25); }
  .narrative-pin-watch  { background:var(--bg-hover); border:1px solid var(--border); }
  .narrative-pin-label { font-family:var(--mono); font-size:9px; font-weight:700; letter-spacing:0.12em; color:var(--king); white-space:nowrap; padding-top:1px; }
  .narrative-pin-watch  .narrative-pin-label { color:var(--text3); }
  .narrative-pin-text { font-family:var(--mono); font-size:12px; color:var(--text2); line-height:1.5; }
  /* Watch list — structured next-30-min triggers. Bulleted compact list. */
  .narrative-watchlist { padding:10px 14px; margin:8px 0; background:var(--bg-hover); border:1px solid var(--border); border-radius:5px; }
  .narrative-watchlist-title { font-family:var(--mono); font-size:9px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--text3); margin-bottom:8px; }
  .narrative-watchlist-items { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:5px; }
  .narrative-watchlist-item { font-family:var(--mono); font-size:11px; color:var(--text2); line-height:1.5; display:flex; align-items:baseline; gap:8px; }
  /* Priority indicator combines shape + color so it remains readable
     for colorblind users / screen readers (a11y fix 4/27/26).
       high   → ▲  red
       medium → ●  gold
       low    → ▫  grey
     Default is the low marker so any unknown priority still renders. */
  .narrative-watchlist-item::before { content:'\25AB'; color:var(--text3); font-size:13px; }
  .narrative-watchlist-high::before   { content:'\25B2'; color:var(--barney); }
  .narrative-watchlist-medium::before { content:'\25CF'; color:var(--king); }
  .narrative-watchlist-low::before    { content:'\25AB'; color:var(--text3); }
  .narrative-watchlist-trigger { font-weight:700; color:var(--text); }
  .narrative-watchlist-arrow { color:var(--text3); }
  .narrative-watchlist-consequence { color:var(--text2); }
  /* Invalidation callout — replaces the contrarian scenario when bias is
     high-conviction. Single-line, full-width, faintly red. */
  .narrative-invalidation-callout { display:flex; align-items:flex-start; gap:10px; padding:10px 14px; margin-top:10px; background:rgba(155,93,229,.05); border:1px solid rgba(155,93,229,.15); border-radius:5px; }
  .narrative-invalidation-label { font-family:var(--mono); font-size:9px; font-weight:700; letter-spacing:0.12em; color:var(--barney); white-space:nowrap; padding-top:1px; }
  .narrative-invalidation-text { font-family:var(--mono); font-size:12px; color:var(--text2); line-height:1.5; }
  .scenario-box { background:var(--bg3); border:1px solid var(--border2); border-radius:6px; padding:16px; }
  .scenario-header { font-family:var(--mono); font-size:10px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; margin-bottom:12px; padding-bottom:8px; border-bottom:1px solid var(--border); }
  .scenario-context { margin:12px -16px -16px; padding:12px 16px; border-top:1px solid var(--border); background:var(--bg-hover); border-radius:0 0 6px 6px; }
  .scenario-context-item { font-family:var(--mono); font-size:11px; color:var(--text2); line-height:1.6; margin-top:8px; }
  .scenario-context-item:first-child { margin-top:0; }
  .scenario-context-label { font-size:8px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--king); margin-bottom:3px; opacity:0.6; }
  .scenario-inner { display:flex; gap:16px; }
  .scenario-fields { flex:1; min-width:0; }
  .scenario-field-label { font-family:var(--mono); font-size:9px; color:var(--king); text-transform:uppercase; letter-spacing:0.1em; margin-top:10px; font-weight:700; opacity:0.5; }
  .scenario-field-label:first-child { margin-top:0; }
  .scenario-field-value { font-family:var(--mono); font-size:12px; color:var(--text); margin-top:3px; line-height:1.55; }
  /* Strike ladder — vertical price reference on left of scenario */
  .scenario-ladder { position:relative; width:72px; flex-shrink:0; min-height:130px; margin:4px 0; }
  .scenario-ladder-line { position:absolute; left:4px; top:6px; bottom:6px; width:1px; }
  .scenario-ladder-node { position:absolute; left:0; transform:translateY(-50%); white-space:nowrap; }
  .scenario-ladder-dot { width:7px; height:7px; border-radius:50%; flex-shrink:0; border:1px solid var(--border2); position:absolute; left:0; top:4px; }
  .scenario-ladder-dot.spot { width:9px; height:3px; border-radius:1px; border:none; top:6px; left:-1px; }
  .scenario-ladder-price { font-family:var(--mono); font-size:11px; font-weight:700; line-height:1; margin-left:14px; }
  .scenario-ladder-role { font-family:var(--mono); font-size:9px; letter-spacing:0.06em; text-transform:uppercase; opacity:0.5; margin-left:14px; margin-top:2px; }
  .level-table { width:100%; }
  .level-header-row { display:grid; grid-template-columns:90px 1fr 60px 1fr; gap:10px; padding:6px 0; border-bottom:1px solid rgba(212,175,55,.12); }
  .level-header { font-family:var(--mono); font-size:8px; letter-spacing:0.12em; text-transform:uppercase; color:rgba(212,175,55,.4); }
  .level-row { display:grid; grid-template-columns:90px 1fr 60px 1fr; gap:10px; padding:10px 0; border-bottom:1px solid var(--border); align-items:center; }
  .level-price { font-family:var(--mono); font-size:15px; font-weight:700; }
  .level-signal { font-family:var(--mono); font-size:10px; letter-spacing:0.08em; }
  .level-bar-cell { display:flex; align-items:center; }
  .level-bar-track { width:100%; height:4px; background:var(--bg-subtle); border-radius:2px; overflow:hidden; }
  .level-bar-fill { height:100%; border-radius:2px; transition:width 0.3s; }
  .level-mechanic { font-family:var(--mono); font-size:10px; color:var(--text3); }
  /* Spot indicator row */
  .level-spot-row { display:grid; grid-template-columns:90px auto 1fr; gap:8px; padding:6px 0; align-items:center; }
  .level-spot-price { font-family:var(--mono); font-size:14px; font-weight:700; color:#fff; }
  .level-spot-label { font-family:var(--mono); font-size:7.5px; letter-spacing:0.1em; color:var(--text2); text-transform:uppercase; }
  .level-spot-line { height:1px; background:linear-gradient(90deg, #fff, transparent); }
  .greek-node-row { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
  .greek-node-label { font-family:var(--mono); font-size:11px; min-width:56px; flex-shrink:0; }
  .greek-bar-track { flex:1; height:5px; background:var(--bg3); border-radius:3px; overflow:hidden; }
  .greek-bar-fill { height:100%; border-radius:3px; transition:width 0.3s; }
  .greek-node-val { font-family:var(--mono); font-size:10px; color:var(--text3); min-width:48px; text-align:right; }
  .greek-note { font-family:var(--mono); font-size:11px; color:var(--text2); line-height:1.55; margin-bottom:12px; }
  .narrative-empty { display:flex; align-items:center; justify-content:center; flex:1; font-family:var(--mono); font-size:11px; color:var(--text3); }
  .narrative-stale { font-family:var(--mono); font-size:9px; color:var(--pika); padding:3px 8px; background:rgba(255,193,7,0.15); border-radius:4px; }

  /* ── CLOSING NARRATIVE ── */
  .closing-badge { font-family:var(--mono); font-size:9px; letter-spacing:0.12em; text-transform:uppercase; color:var(--pika); padding:3px 10px; background:var(--pika3); border:1px solid var(--pika2); border-radius:4px; }

  /* ── PRE-MARKET BRIEF ──
     Distinct from closing — uses the king (orange) color family to
     read as "morning / sunrise" rather than the closing pika (yellow). */
  .closing-badge.premarket-badge {
    color: var(--king);
    background: rgba(255,107,53,0.10);
    border-color: rgba(255,107,53,0.35);
  }
  .narrative-thesis.premarket {
    /* Brief's thesis line is a one-sentence pivot framing — slightly
       smaller + king-colored vs the live narrative's high-contrast white. */
    color: var(--king);
    font-weight: 600;
  }
  .premarket-watch {
    margin-top: 12px;
    padding: 10px 12px;
    border-left: 2px solid var(--king);
    background: rgba(255,107,53,0.05);
    border-radius: 0 4px 4px 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text);
  }
  .premarket-watch-label {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--king);
    margin-right: 8px;
  }

  /* ── ATLAS NARRATIVE CARD ── */
  .atlas-narrative-card { padding:10px; border-top:1px solid var(--pika2); }
  .atlas-nc-title { font-family:var(--mono); font-size:8px; letter-spacing:0.12em; text-transform:uppercase; color:var(--pika); margin-bottom:8px; }
  .atlas-nc-header { display:flex; align-items:center; gap:8px; }
  .atlas-nc-bias { font-family:var(--mono); font-size:11px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:180px; }
  .atlas-nc-conf { font-family:var(--mono); font-size:10px; color:var(--text3); }
  .atlas-nc-regime { font-family:var(--mono); font-size:9px; padding:2px 6px; border-radius:3px; flex-shrink:0; }
  .atlas-nc-thesis { font-family:var(--mono); font-size:10px; color:var(--pika); line-height:1.4; margin:8px 0; overflow:hidden; display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; }
  .atlas-nc-scenario { display:grid; grid-template-columns:1fr 1fr; gap:3px 8px; margin-bottom:8px; }
  .atlas-nc-field { font-family:var(--mono); font-size:10px; color:var(--text2); }
  .atlas-nc-label { color:var(--text3); text-transform:uppercase; font-size:8px; letter-spacing:0.08em; margin-right:4px; }
  .atlas-nc-phase { font-family:var(--mono); font-size:9px; color:var(--text3); }

  /* ── ATLAS LEVEL LEGEND ── */
  /* Background uses var(--bg2) so the legend panel adapts to theme.
     Previously was hardcoded rgba(8,11,15,0.85) (dark navy) which left
     a black panel visible on the white theme — fixed 4/29/26. Solid
     (not translucent) so the chart underneath doesn't bleed through
     and reduce legibility. */
  .atlas-legend { position:absolute; top:12px; left:12px; background:var(--bg2); border:1px solid var(--border); border-radius:6px; padding:8px 12px; z-index:10; pointer-events:none; display:flex; flex-direction:column; gap:4px; }
  .atlas-legend-item { display:flex; align-items:center; gap:6px; font-family:var(--mono); font-size:9px; color:var(--text3); white-space:nowrap; }
  .atlas-legend-line { display:inline-block; flex-shrink:0; border-radius:1px; }
  .narrative-thesis.closing { background:rgba(245,200,66,0.06); border-color:rgba(245,200,66,0.15); color:var(--pika); }
  .closing-positioning { font-family:var(--mono); font-size:13px; color:var(--text2); line-height:1.65; }
  .closing-structure { font-family:var(--mono); font-size:12px; color:var(--text3); line-height:1.55; margin-top:14px; padding-top:14px; border-top:1px solid var(--border); }
  .closing-section-divider { height:1px; background:linear-gradient(90deg, var(--pika2), transparent); margin:16px 0; }

  /* ═════════════════════════════════════════════════════════════════════
     RESPONSIVE — phone + tablet breakpoints (Phase: mobile MVP)
     ─────────────────────────────────────────────────────────────────────
     Three-tier layout: phone (≤640px), tablet (641–1024px), desktop
     (>1024px). Desktop is the original design and is unchanged.

     Priority views per the mobile-MVP scope: Heatmap (Single instrument
     view), Multi, Narrative. Other views (Atlas, Flow, Alerts) get the
     header / global polish but their internal layouts are not yet tuned —
     they're usable but not optimized.

     Approach: keep all changes here in one clearly-marked section so
     future tweaks are easy to find. No JS or markup changes — pure CSS
     overrides on the existing classes.
     ═════════════════════════════════════════════════════════════════════ */

  /* ─── Tablet (641–1024px) ─────────────────────────────────────────── */
  @media (max-width: 1024px) {
    /* Single instrument: collapse the right detail panel below the chart so
       the main heatmap gets full width. Left ticker panel stays narrow. */
    .instrument-layout {
      grid-template-columns: 240px 1fr;
      grid-template-rows: 1fr auto;
      grid-template-areas:
        "left main"
        "right right";
      height: auto;
      min-height: calc(100vh - 92px);
    }
    .instrument-layout > .panel:nth-child(1)  { grid-area: left;  }
    .instrument-layout > .panel:nth-child(2)  { grid-area: main;  }
    #rightDetailPanel                          { grid-area: right; max-height: 320px; }

    /* Hide low-priority header-right text on smaller screens */
    .data-source { display: none; }

    /* Narrative: cap line length for readability on wider tablets */
    .narrative-section { max-width: 920px; }
  }

  /* ─── Phone (≤640px) ──────────────────────────────────────────────── */
  @media (max-width: 640px) {
    /* Header — tabs become horizontally scrollable; non-essential right-
       cluster items hide. Logo shrinks. */
    header {
      padding: 0 12px;
      gap: 12px;
      height: 48px;
    }
    .logo {
      font-size: 13px;
      letter-spacing: 0.08em;
    }
    .nav-tabs {
      overflow-x: auto;
      flex-wrap: nowrap;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: none;     /* Firefox */
      max-width: 100%;
    }
    .nav-tabs::-webkit-scrollbar { display: none; }
    .nav-tab {
      flex-shrink: 0;
      padding: 5px 10px;
      font-size: 10px;
    }
    .header-right {
      gap: 8px;
    }
    /* Drop the Atlas/TV download button + refresh ring + data-source on
       phone. Live indicator + regime badge + DEV/ADMIN badges + sign-out
       all stay (they're informationally cheap). */
    .header-right > button[onclick*="downloadPineScript"],
    .header-right > .refresh-ring {
      display: none;
    }

    /* View padding: tighter so content uses the full width */
    .view {
      padding: 10px 10px;
    }

    /* Legend bar wraps gracefully across rows. The .legend has two inner
       flex containers (#legendItems on the left + a dropdowns container
       on the right with inline margin-left:auto). On phone we override
       both so each can wrap independently and dropdowns don't slip off
       the right edge of the viewport.
       Two key things that were missing in pass 1:
         (a) max-width: 100% + box-sizing: border-box on every level so
             nothing can escape the viewport horizontally
         (b) min-width:0 on flex children so their natural content-width
             isn't preserved at the cost of pushing siblings off-screen */
    .legend {
      flex-wrap: wrap !important;
      gap: 6px 10px !important;
      height: auto !important;
      padding: 8px 10px !important;
      /* Drop the sticky behavior on phone so the legend doesn't double
         up with the header (which is also sticky). Slot it back into
         normal flow above the view content. */
      position: static !important;
      max-width: 100vw;
      box-sizing: border-box;
      overflow: hidden;
    }
    .legend > div {
      flex-wrap: wrap !important;
      gap: 6px 10px !important;
      /* Kill any inline margin-left:auto that was pushing the right
         cluster off-screen on narrow widths. */
      margin-left: 0 !important;
      /* Let both clusters span the full row, stacked vertically */
      flex: 1 1 100%;
      min-width: 0;
      max-width: 100%;
      box-sizing: border-box;
    }
    /* Each individual dropdown widget (e.g. "Model", "Gamma", "Expiry",
       "Strikes") is itself an inline-styled <div style="display:flex">.
       Force them to flex-shrink and clamp width so wrapping behaves. */
    .legend > div > div {
      flex: 0 1 auto;
      min-width: 0;
      max-width: 100%;
    }
    /* Native <select> dropdowns get a usable min width when wrapped, but
       cap so they can't dominate the row */
    .palette-select,
    .legend select {
      min-width: 80px;
      max-width: 160px;
    }
    /* The "Last update: —" text on the far right of the legend is purely
       informational; hide it on phone to free up space */
    #lastUpdate {
      display: none;
    }

    /* Single instrument: stack vertically. The 100vh height calc was
       designed for desktop; on phone we let content flow and scroll the
       page naturally. */
    .instrument-layout {
      display: flex;
      flex-direction: column;
      gap: 10px;
      height: auto;
      min-height: 0;
    }
    .instrument-layout .panel {
      min-height: 220px;
    }
    /* Make the heatmap panel taller since it's the primary content */
    .instrument-layout > .panel:nth-child(2) {
      min-height: 60vh;
    }

    /* Multi: ladders stack vertically. Each gets full width and a
       sensible min-height so the strikes are still readable. */
    .multi-layout {
      display: flex;
      flex-direction: column;
      height: auto;
      gap: 10px;
    }
    .multi-panels-row {
      grid-template-columns: 1fr;
      gap: 10px;
    }
    .multi-panel {
      min-height: 60vh;
    }
    /* Multi footer (System Alignment + verdict + key-levels) renders
       as horizontal context on desktop. On phone it had been stacking
       vertically but visually felt like a misplaced "sidebar in the
       middle of the charts" when sandwiched between three full-width
       panels. The summary information here is also redundant on phone
       — users scrolling through panels can read each instrument's
       regime and alignment directly on its panel. Hiding entirely on
       phone keeps the Multi tab to "3 vertical panels, nothing else."
       Desktop unchanged. */
    .multi-footer-row,
    .multi-footer {
      display: none !important;
    }
    /* Also drop the legend bar on Multi specifically — its per-feature
       dropdowns (Mode / Strikes / Display cog) operate on a single
       active ticker, which doesn't apply when 3 panels each have their
       own. Less visual noise above the panel stack. */
    body.tab-multi .legend {
      display: none !important;
    }

    /* Narrative: full-width, no two-column greeks row */
    .narrative-greeks-row {
      grid-template-columns: 1fr;
    }
    .narrative-section {
      padding: 14px 14px;
    }
    .narrative-thesis {
      font-size: 12px;
      padding: 10px 12px;
    }
    .narrative-body {
      padding: 12px 14px !important;
    }
  }

  /* ─── Phone landscape / very small (≤480px) ───────────────────────── */
  @media (max-width: 480px) {
    /* Drop ADMIN badge on the smallest screens — sign-out + LIVE indicator
       are the only non-tab things really worth keeping. */
    .header-right > #adminBadge { display: none; }
    /* Logo can disappear entirely on the smallest screens — the active
       nav-tab is visually anchoring enough. */
    .logo { display: none; }
  }

  /* ═════════════════════════════════════════════════════════════════════
     RESPONSIVE — Pass 2: Atlas, Flow, Alerts (and the Flow detail modal)
     ─────────────────────────────────────────────────────────────────────
     These views were skipped in the mobile-MVP commit; they're usable on
     desktop unchanged but need their own reflow at small widths. Atlas
     is the hardest (chart + sidebar); Flow has a wide table that already
     scrolls horizontally; Alerts is mostly card-based and only needs
     the header + subtabs to wrap.
     ═════════════════════════════════════════════════════════════════════ */

  /* ─── Tablet (641–1024px) — pass 2 ────────────────────────────────── */
  @media (max-width: 1024px) {
    /* Atlas: narrow the sidebar so the chart gets more room */
    .atlas-sidebar { width: 220px; }
    /* Flow stats grid: 4 → 2 columns so each stat card has room for its
       value at tablet widths */
    .flow-stats { grid-template-columns: repeat(2, 1fr); }
    /* Alerts header: tighter gap so the subtabs row fits */
    .alerts-header { gap: 6px; padding: 8px 12px; }
  }

  /* ─── Phone (≤640px) — pass 2 ─────────────────────────────────────── */
  @media (max-width: 640px) {
    /* ── Atlas ── stack chart on top, sidebar (mini panels + narrative
       card) below. Chart gets the lion's share of vertical space; the
       sidebar is compact and scrolls within itself if the user wants
       to drill into the per-ticker stats. */
    .atlas-main {
      flex-direction: column;
    }
    .atlas-chart-container {
      min-height: 60vh;
      flex: 1 1 auto;
    }
    .atlas-sidebar {
      width: 100%;
      border-left: none;
      border-top: 1px solid var(--border);
      max-height: 30vh;       /* was 50vh — too dominant; chart matters more */
      flex: 0 0 auto;
    }
    /* Sidebar mini panels (SPX/SPY/QQQ stats) get tighter padding on
       phone so 3 fit in roughly one screenful of scroll */
    .atlas-mini-panel {
      padding: 6px 10px;
    }
    /* Narrative card at the bottom of the sidebar: tighter padding */
    .atlas-sidebar .narrative-section {
      padding: 10px 12px;
      margin: 8px 10px;
    }

    /* ── Flow ── stats become 1-col so each card has full readability;
       the table relies on its existing overflow-x scroll, but we
       tighten cell padding + font so more columns fit at once. */
    .flow-stats {
      grid-template-columns: 1fr;
    }
    .flow-stat-val { font-size: 17px; }
    .flow-table { font-size: 10px; }
    .flow-table thead th,
    .flow-table tbody td {
      padding: 7px 6px !important;
    }
    .flow-table-wrap {
      max-height: 70vh;
      /* Hint to mobile browsers to scroll smoothly */
      -webkit-overflow-scrolling: touch;
    }
    /* Flow header / filter rows wrap so dropdowns don't overflow */
    .flow-card-head {
      flex-wrap: wrap;
      gap: 6px;
    }

    /* ── Flow detail modal ── full-screen on phone (the 32px backdrop
       padding wastes too much room on small displays) */
    .flow-modal-backdrop {
      padding: 0;
    }
    .flow-modal {
      max-height: 100vh;
      height: 100vh;
      max-width: 100vw;
      width: 100vw;
      border-radius: 0;
    }

    /* ── Alerts header ── allow filter buttons + subtabs to wrap to
       multiple rows; tighten paddings + sub-tab font so more chips fit
       in each row. */
    .alerts-header {
      flex-wrap: wrap;
      gap: 6px;
      padding: 8px 10px;
    }
    .alerts-subtabs {
      flex-wrap: wrap;
      gap: 3px;
    }
    .alert-subtab {
      padding: 3px 8px;
      font-size: 9px;
    }
    .alerts-filters {
      flex-wrap: wrap;
    }

    /* ── Alert prefs panel ── if there's a multi-column grid of alert
       type cards, collapse to single column so the toggle UI doesn't
       crush. The selector is broad on purpose — covers any inline
       grid-template-columns: repeat(N, 1fr) within the alerts view. */
    #alertsTypePanel,
    .alerts-types-grid {
      grid-template-columns: 1fr !important;
    }

  }

  /* ═══════════════════════════════════════════════════════════════════
     Phase 4.3 / 4.4 — Trending Nodes UI variants
     (Pulse panel + inline ladder micro-labels + sparkline column)
     ═══════════════════════════════════════════════════════════════════ */

  /* ── Variant 1: Pulse panel ── Floating right-edge panel listing the
     top-N strikes by significance. Anchored fixed so it overlays the
     Heatmap right-detail panel without resizing the layout. */
  .trending-pulse-panel {
    position: fixed;
    right: 12px;
    top: 130px;
    width: 360px;
    max-height: calc(100vh - 160px);
    overflow-y: auto;
    z-index: 900;
    background: var(--bg2);
    border: 1px solid var(--border2);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.25);
    font-family: var(--mono);
    font-size: 11px;
    color: var(--text2);
    padding: 10px 12px;
  }
  .trending-pulse-panel::-webkit-scrollbar { width: 4px; }
  .trending-pulse-panel::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }

  .trending-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 8px;
  }
  .trending-title {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text);
    flex: 1;
  }
  .trending-count {
    font-size: 9px;
    color: var(--text3);
    letter-spacing: 0.04em;
  }
  .trending-close {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text3);
    font-size: 12px;
    line-height: 1;
    width: 18px;
    height: 18px;
    border-radius: 3px;
    cursor: pointer;
    padding: 0;
  }
  .trending-close:hover { color: var(--text); border-color: var(--border2); }

  .trending-controls {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-bottom: 8px;
  }
  .trending-chips,
  .trending-thresholds {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
  }
  .trending-thr-label {
    font-size: 9px;
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-right: 2px;
  }
  .trending-chip {
    background: var(--bg3);
    border: 1px solid var(--border);
    color: var(--text2);
    font-family: var(--mono);
    font-size: 9px;
    padding: 2px 8px;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .trending-chip:hover { border-color: var(--border2); color: var(--text); }
  .trending-chip.active {
    background: rgba(255, 107, 53, 0.15);
    border-color: var(--king);
    color: var(--king);
  }

  .trending-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .trending-row {
    display: grid;
    grid-template-columns: 22px 60px 50px 80px 22px 30px 1fr;
    gap: 6px;
    align-items: center;
    padding: 5px 6px;
    border-radius: 3px;
    cursor: pointer;
    border-left: 2px solid transparent;
    background: var(--bg-hover);
  }
  .trending-row:hover {
    background:var(--bg-subtle);
  }
  .trending-row.dir-up    { border-left-color: var(--green); }
  .trending-row.dir-down  { border-left-color: var(--red); }
  .trending-row.dir-neutral { border-left-color: var(--text3); }
  .trending-rank {
    font-size: 9px;
    color: var(--text3);
    font-weight: 700;
  }
  .trending-strike {
    font-size: 11px;
    color: var(--text);
    font-weight: 600;
    letter-spacing: 0.02em;
  }
  .trending-sig {
    font-size: 10px;
    color: var(--king);
    font-weight: 700;
    letter-spacing: 0.04em;
  }
  .trending-delta {
    font-size: 10px;
    color: var(--text2);
    text-align: right;
    letter-spacing: 0.02em;
  }
  .trending-row.dir-up .trending-delta { color: var(--green); }
  .trending-row.dir-down .trending-delta { color: var(--red); }
  .trending-arrow {
    font-size: 10px;
    text-align: center;
    line-height: 1;
  }
  .trending-row.dir-up .trending-arrow { color: var(--green); }
  .trending-row.dir-down .trending-arrow { color: var(--red); }
  .trending-row.dir-neutral .trending-arrow { color: var(--text3); }
  .trending-horizon {
    font-size: 9px;
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .trending-tags {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
    overflow: hidden;
  }
  .trending-tag {
    font-size: 8px;
    padding: 1px 4px;
    border-radius: 2px;
    background:var(--bg-subtle);
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }
  .trending-tag.tag-king        { background: rgba(255, 107, 53, 0.18); color: var(--king); }
  .trending-tag.tag-signflip    { background: rgba(96, 165, 250, 0.18); color: var(--flip); }
  .trending-tag.tag-cohortleader{ background: rgba(34, 197, 94, 0.16);  color: var(--green); }
  .trending-tag.tag-accelspike  { background: rgba(245, 200, 66, 0.16); color: var(--pika); }
  .trending-tag.tag-bleeding    { background: rgba(239, 68, 68, 0.18);  color: var(--red); }
  .trending-tag.tag-persistent  { background: rgba(155, 93, 229, 0.16); color: var(--barney); }
  .trending-tag.tag-selfoutlier { background: rgba(0, 212, 170, 0.16);  color: var(--gate); }

  .trending-empty {
    font-size: 10px;
    color: var(--text3);
    padding: 12px 6px;
    line-height: 1.4;
    font-style: italic;
  }

  /* Brief flash on click-to-scroll (Pulse panel → ladder row) */
  @keyframes trending-flash {
    0%   { box-shadow: 0 0 0 2px var(--king), 0 0 12px var(--king); }
    100% { box-shadow: 0 0 0 0 transparent; }
  }
  .node-row.trending-flash {
    animation: trending-flash 1.4s ease-out;
  }

  /* ── Variant 2: Inline ladder micro-labels (B2 + B4) ── */
  /* Side-rail: 4px vertical bar at the LEFT edge of qualifying rows.
     Color = direction; height = magnitude bucket. Anchored relative to
     the .node-row (already position:relative). */
  .trending-rail {
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    border-radius: 2px;
    pointer-events: none;
    z-index: 6;
    box-shadow: 0 0 4px currentColor;
    opacity: 0.85;
  }
  /* Pulse-rank chip: small numbered badge at the RIGHT edge for top-5. */
  .trending-rankchip {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0, 0, 0, 0.65);
    color: var(--king);
    font-family: var(--mono);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 1px 5px;
    border-radius: 2px;
    border: 1px solid rgba(255, 107, 53, 0.4);
    pointer-events: none;
    z-index: 6;
    line-height: 1;
  }

  /* ── Variant 3: Inline sparkline + ROC pill ── */
  .trending-spark {
    position: absolute;
    right: 95px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    pointer-events: none;
    z-index: 6;
    background: rgba(0, 0, 0, 0.5);
    padding: 2px 4px;
    border-radius: 3px;
  }
  .trending-spark svg {
    display: block;
  }
  .trending-pill {
    font-family: var(--mono);
    font-size: 8px;
    font-weight: 700;
    padding: 1px 3px;
    border-radius: 2px;
    line-height: 1;
    letter-spacing: 0.02em;
  }
  .trending-pill.pill-up   { background: rgba(34, 197, 94, 0.18);  color: var(--green); }
  .trending-pill.pill-down { background: rgba(239, 68, 68, 0.18);  color: var(--red); }

  /* Mobile/narrow viewport — Pulse panel slides in as bottom-sheet */
  @media (max-width: 720px) {
    .trending-pulse-panel {
      left: 8px;
      right: 8px;
      width: auto;
      top: auto;
      bottom: 12px;
      max-height: 60vh;
    }
  }

/* ═══ KNOWLEDGE BASE ════════════════════════════════════════════════════
   Sidebar nav + reading pane. Compass-inspired layout: left rail with
   sections + article list, right pane with the rendered markdown. All
   tokens come from the theme system so it inherits Original / White
   automatically. */

#view-knowledge { padding: 0; }

.knowledge-view {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: 0;
  height: calc(100vh - var(--nav-h, 56px));
  background: var(--bg);
}

.knowledge-sidebar {
  border-right: 1px solid var(--border);
  background: var(--bg2);
  overflow-y: auto;
  padding: 18px 0 24px 0;
}
.knowledge-sidebar-head {
  padding: 0 18px 14px 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.knowledge-sidebar-title {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text2);
}
.knowledge-sidebar-sub {
  font-size: 11px;
  color: var(--text3);
  margin-top: 2px;
}

.knowledge-nav { padding: 0 8px; }

.knowledge-section { margin-bottom: 16px; }
.knowledge-section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text2);
}
.knowledge-section-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
  align-items: center;
  justify-content: center;
  color: var(--text3);
  font-size: 11px;
}
.knowledge-section-summary {
  padding: 0 10px 6px 34px;
  font-size: 11px;
  color: var(--text3);
  line-height: 1.4;
}

.knowledge-article-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.knowledge-article-list li { margin: 0; }
.knowledge-article-list a {
  display: block;
  padding: 6px 10px 6px 34px;
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
  line-height: 1.35;
  border-left: 2px solid transparent;
  transition: background 90ms ease, border-color 90ms ease, color 90ms ease;
}
.knowledge-article-list a:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.knowledge-article-list a.active {
  background: var(--bg-subtle);
  border-left-color: var(--accent, #3b82f6);
  color: var(--text);
  font-weight: 500;
}

.knowledge-pane {
  overflow-y: auto;
  padding: 28px 36px 60px 36px;
  background: var(--bg);
}

.knowledge-empty,
.knowledge-empty-state {
  color: var(--text3);
  font-size: 13px;
  padding: 24px;
  text-align: center;
}

.knowledge-article {
  max-width: 760px;
  margin: 0 auto;
  color: var(--text);
  line-height: 1.6;
  font-size: 14.5px;
}
.knowledge-article-meta {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text3);
  margin-bottom: 14px;
}
.knowledge-article h1 {
  font-size: 26px;
  font-weight: 600;
  margin: 0 0 18px 0;
  letter-spacing: -0.01em;
  color: var(--text);
}
.knowledge-article h2 {
  font-size: 17px;
  font-weight: 600;
  margin: 28px 0 10px 0;
  color: var(--text);
}
.knowledge-article h3 {
  font-size: 14px;
  font-weight: 600;
  margin: 22px 0 8px 0;
  color: var(--text2);
}
.knowledge-article p {
  margin: 0 0 14px 0;
  color: var(--text);
}
.knowledge-article ul,
.knowledge-article ol {
  margin: 0 0 14px 24px;
  padding: 0;
  color: var(--text);
}
.knowledge-article li {
  margin: 4px 0;
}
.knowledge-article code {
  font-family: var(--mono);
  font-size: 12.5px;
  padding: 1px 5px;
  background: var(--bg-subtle);
  border-radius: 3px;
  color: var(--text);
}
.knowledge-article a {
  color: var(--accent, #3b82f6);
  text-decoration: none;
  border-bottom: 1px dashed color-mix(in srgb, var(--accent, #3b82f6) 50%, transparent);
}
.knowledge-article a:hover {
  border-bottom-style: solid;
}
/* ── KB images + figures (5/02/26) ──
   `![alt](src)` on its own line renders as <figure> with the alt
   text as <figcaption>. Inline images render as plain <img>. Both
   variants are constrained to the article width and rounded for
   visual cohesion with the platform UI. */
.knowledge-article img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 18px auto;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg2);
}
.knowledge-article .kb-figure {
  margin: 24px 0;
  padding: 0;
}
.knowledge-article .kb-figure img {
  margin: 0 auto 8px auto;
}
.knowledge-article .kb-figure figcaption {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text3);
  text-align: center;
  letter-spacing: 0.02em;
  line-height: 1.4;
  padding: 0 12px;
}
.knowledge-article hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 22px 0;
}
.knowledge-article strong { font-weight: 600; }
.knowledge-article em { font-style: italic; }

@media (max-width: 720px) {
  .knowledge-view {
    grid-template-columns: 1fr;
    height: auto;
  }
  .knowledge-sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--border);
    max-height: 40vh;
  }
  .knowledge-pane { padding: 18px; }
}

/* ═══ CHART DRAWING TOOLS ═════════════════════════════════════════════
   Vertical toolbar pinned to the chart's left edge + overlay layer for
   drawings (vlines, rectangles). Toolbar buttons are square mono icons
   in the same chrome family as the legend chips so they don't compete
   visually with the chart. */

.chart-drawing-toolbar {
  position: absolute;
  top: 50%;
  left: 8px;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: 5px;
  padding: 3px;
  z-index: 12;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}
.cdt-btn {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: var(--text2);
  font-family: var(--mono);
  font-size: 14px;
  border-radius: 3px;
  cursor: pointer;
  transition: background 90ms ease, color 90ms ease;
}
.cdt-btn:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.cdt-btn.active {
  background: color-mix(in srgb, var(--accent, #3b82f6) 25%, transparent);
  color: var(--accent, #3b82f6);
}
.cdt-sep {
  height: 1px;
  background: var(--border);
  margin: 3px 2px;
}

/* When a drawing tool is active, replace the chart cursor with a
   crosshair so users see they're in drawing mode. */
.atlas-chart-container.drawing-mode { cursor: crosshair; }
.atlas-chart-container[data-active-tool="eraser"] { cursor: not-allowed; }

/* Drawing overlays — vlines and rectangle edges/fills. The host div
   has pointer-events:none; only the actual drawings opt in so the
   chart stays interactive everywhere else. */
.chart-drawings-overlay { /* set inline */ }
.chart-drawing { transition: opacity 80ms ease; }
.chart-drawing:hover { opacity: 0.8; }
.chart-drawing-preview { z-index: 6; }

/* ─── Drawing tools v2: color picker, handles, labels ─────────────── */

.cdt-color-btn { padding: 0; }
.cdt-color-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #3b82f6;
  border: 1px solid var(--border2);
}

.chart-drawing-color-popup {
  position: absolute;
  left: 44px;          /* sits to the right of the toolbar */
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  grid-template-columns: repeat(4, 22px);
  gap: 4px;
  padding: 6px;
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: 5px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.22);
  z-index: 13;
}
.chart-drawing-color-swatch {
  width: 22px;
  height: 22px;
  border-radius: 4px;
  border: 1px solid var(--border2);
  cursor: pointer;
  padding: 0;
  transition: transform 80ms ease;
}
.chart-drawing-color-swatch:hover { transform: scale(1.08); }
.chart-drawing-color-swatch.active {
  outline: 2px solid var(--accent, #3b82f6);
  outline-offset: 1px;
}

/* Selection handle dots — appear on the selected drawing in cursor
   mode. Pure presentation; pointer-events live on the .style.cssText
   inline so click-through behaviour stays consistent across browsers. */
.chart-drawing-handle {
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* Drawing labels — small chip rendered as overlay near the drawing's
   anchor point. Color comes from the drawing inline. */
.chart-drawing-label {
  letter-spacing: 0.04em;
  text-transform: none;
  user-select: none;
}

/* ── ONBOARDING TOUR ─────────────────────────────────────────────
   Spotlight overlay + step card. Activated on first sign-in for a
   user (controlled by tour.js, gated by localStorage). Replayable
   from the 🧭 link in the header. */
.tour-root {
  position: fixed;
  inset: 0;
  z-index: 10000;
  pointer-events: none;
}
.tour-spotlight {
  position: fixed;
  inset: 0;
  background: rgba(8, 11, 15, 0.78);
  pointer-events: auto;
  cursor: pointer;
  transition: clip-path 0.18s ease;
}
.tour-spotlight.full-dim { clip-path: none; }

.tour-card {
  position: fixed;
  width: 360px;
  max-width: calc(100vw - 24px);
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: 10px;
  padding: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.04);
  pointer-events: auto;
  outline: none;
  transition: top 0.2s ease, left 0.2s ease;
}
.tour-card-progress {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
}
.tour-progress-dot {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: var(--bg3);
}
.tour-progress-dot.active {
  background: var(--pika);
  box-shadow: 0 0 6px var(--pika2);
}
.tour-progress-dot.done {
  background: var(--text3);
}
.tour-card-title {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
  letter-spacing: 0.01em;
}
.tour-card-body {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text2);
  line-height: 1.6;
  letter-spacing: 0.02em;
  margin-bottom: 14px;
}
.tour-card-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--mono);
  font-size: 9px;
  color: var(--text3);
}
.tour-card-step {
  flex: 1;
  text-align: center;
  letter-spacing: 0.08em;
}
.tour-nav-btns {
  display: flex;
  gap: 6px;
}
.tour-btn {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 6px 12px;
  border-radius: 5px;
  border: 1px solid var(--border2);
  background: var(--bg3);
  color: var(--text);
  cursor: pointer;
  transition: background 0.1s, border-color 0.1s;
}
.tour-btn:hover {
  background: var(--bg4);
  border-color: var(--text3);
}
.tour-btn-skip {
  background: transparent;
  border-color: transparent;
  color: var(--text3);
  font-weight: 500;
}
.tour-btn-skip:hover {
  color: var(--text2);
  background: transparent;
  border-color: transparent;
}
.tour-btn-next {
  background: var(--pika);
  border-color: var(--pika);
  color: #080b0f;
}
.tour-btn-next:hover {
  background: var(--pika);
  filter: brightness(1.1);
}
.tour-btn-prev:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Tour link in the header */
.tour-link {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  color: var(--text3);
  letter-spacing: 0.06em;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  transition: color 0.1s, background 0.1s;
  background: transparent;
  border: 1px solid transparent;
  text-decoration: none;
}
.tour-link:hover {
  color: var(--pika);
  background: var(--bg3);
  border-color: var(--border2);
}

/* Settings cog button in the navbar (4/29 evening — moved from per-tab
   legend bar). Same visual weight as .tour-link so the right side of
   the navbar stays consistent. */
.navbar-settings-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  color: var(--text3);
  letter-spacing: 0.06em;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  transition: color 0.1s, background 0.1s;
  background: transparent;
  border: 1px solid transparent;
}
.navbar-settings-btn:hover {
  color: var(--text);
  background: var(--bg3);
  border-color: var(--border2);
}
.navbar-settings-btn[aria-expanded="true"] {
  color: var(--text);
  background: var(--bg3);
  border-color: var(--border2);
}
.navbar-settings-btn svg {
  flex-shrink: 0;
}

/* ═══ PAYWALL VIEW ════════════════════════════════════════════════════════
   Surfaced when /api/me resolves with every feature denied. Body carries
   data-paywalled="on" to hide the normal app shell (header / legend /
   layout / footer chrome) and reveal #paywallView. Sign-out + the toast
   container stay reachable so account-switch works.

   No motion / no chart / no live data — this is a sales surface. Single
   centered card, mono wordmark logo, one-line value prop, disabled CTA
   placeholder until Whop wiring lands. Theme tokens used so light-mode
   inherits correctly. */

body[data-paywalled="on"] > header,
body[data-paywalled="on"] > .legend,
body[data-paywalled="on"] > .app-layout,
body[data-paywalled="on"] > div:not(#paywallView):not(#toastContainer):not(.tour-overlay):not(#multiTooltip) {
  display: none !important;
}

.paywall-view {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: var(--bg);
  align-items: center;
  justify-content: center;
  padding: 24px;
  box-sizing: border-box;
}
body[data-paywalled="on"] .paywall-view {
  display: flex;
}

.paywall-card {
  width: 100%;
  max-width: 460px;
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 36px 32px 28px;
  font-family: var(--font);
  color: var(--text);
  text-align: center;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
}

.paywall-logo {
  font-family: var(--mono);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text);
  margin-bottom: 10px;
}

.paywall-tagline {
  font-size: 12px;
  color: var(--text2);
  letter-spacing: 0.02em;
  margin-bottom: 22px;
  line-height: 1.5;
}

.paywall-body {
  font-size: 13px;
  color: var(--text2);
  line-height: 1.55;
  margin-bottom: 22px;
}

.paywall-cta {
  width: 100%;
  padding: 12px 16px;
  background: var(--bg3);
  border: 1px solid var(--border2);
  border-radius: 6px;
  color: var(--text2);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: not-allowed;
  margin-bottom: 18px;
}
/* When the CTA goes live (Whop wiring), the disabled attr is removed
   and an href / onclick is wired. These hover styles take effect then. */
.paywall-cta:not([disabled]) {
  cursor: pointer;
  background: var(--king);
  color: #0a0d11;
  border-color: var(--king);
}
.paywall-cta:not([disabled]):hover {
  filter: brightness(1.08);
}

.paywall-foot {
  font-size: 10.5px;
  color: var(--text3);
  line-height: 1.6;
  letter-spacing: 0.02em;
}

.paywall-signout {
  display: inline-block;
  margin-top: 6px;
  padding: 4px 10px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text2);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.paywall-signout:hover {
  border-color: var(--text2);
  color: var(--text);
}

/* ── MOTION LANGUAGE ────────────────────────────────────────────
   Two opt-in motion features driven by body[data-motion-*] attrs
   (set by src/frontend/motion.js). Both default OFF so the
   platform stays snappy + predictable for users who don't want it.

   1. Breathing king — when spot tests the king node (within 0.3%
      of its strike), the king's row pulses a subtle king-orange
      glow. Renderer adds .king-breathing on the qualifying king
      row; CSS animation drives the pulse. Glance from across the
      room and you can SEE when the king is being tested.
   2. Heat-zone flow — registers --heat-color as an animatable
      color property via @property, then transitions it on the
      heatmap row. When heatmap.js / multi.js stamp inline
      style="--heat-color:rgb(...)", the change eases over ~380ms
      instead of snapping. Gated on data-motion-heat. */
@property --heat-color {
  syntax: '<color>';
  inherits: false;
  initial-value: rgba(0, 0, 0, 0);
}

/* Breathing king. Animation only runs when both:
     a) body[data-motion-king="on"]   (user toggled it on)
     b) the row carries .king-breathing  (renderer detected proximity)
   so the pulse fires precisely at the moment that matters and stays
   silent the rest of the time. The animation composites on top of
   any inline background — pure box-shadow, no layout impact. */
@keyframes kingBreathe {
  0%, 100% {
    box-shadow: inset 0 0 0 0 rgba(255, 107, 53, 0),
                inset 4px 0 0 var(--king);
  }
  50% {
    box-shadow: inset 0 0 28px 2px rgba(255, 107, 53, 0.45),
                inset 4px 0 0 var(--king);
  }
}
body[data-motion-king="on"] .node-row.king-breathing,
body[data-motion-king="on"] .multi-node.king-breathing {
  position: relative;
  animation: kingBreathe 2.4s ease-in-out infinite;
}

/* Heat-zone smooth transition. Renderer toggles between two inline-
   style shapes based on data-motion-heat at render time:
     OFF: style="background: linear-gradient(...rgb literal...)"
     ON:  style="--heat-color: rgb(...); --heat-flow-break: Npx"
   The .heat-flow class on the row activates the var-driven gradient
   below; @property --heat-color makes it animatable, transition
   declaration eases changes between renders. */
body[data-motion-heat="on"] .node-row.heat-flow,
body[data-motion-heat="on"] .multi-node.heat-flow {
  background: linear-gradient(90deg,
    var(--bg2) var(--heat-flow-break, 60px),
    var(--heat-color) var(--heat-flow-break, 60px));
  transition: --heat-color 380ms cubic-bezier(.4, .0, .2, 1);
}

/* ═══ COLLAPSIBLE SIDEBAR SECTIONS (Heatmap left rail, 4/29/26) ═══════════
   Each .sb-section toggles between:
     data-collapsed="off" → header + body (full content, summary hidden)
     data-collapsed="on"  → header + summary (compact context, body hidden)

   The chevron rotates 90° on collapse. Header is the click target —
   toggleSidebarSection() in app.js flips the data attr + persists to
   localStorage via state.js persistSidebarCollapsed.

   Renderers (top-bar.js renderRegime / renderKeyLevels, patterns.js
   renderPatternsForTicker) populate BOTH the body container AND the
   matching #<section>Summary container; CSS picks which one shows. */
.sb-section {
  /* Border now lives on .sb-section-head bottom edge (not the section
     wrapper) so each header gets a clean rule even when the body is
     collapsed. No outer border on the wrapper itself. */
}
.sb-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Compact header — 9px text + 4px padding both sides = ~17px row
     total. Below this (we tried 2px) the chevron read as nearly
     touching the section border on collapse and the line lost its
     "divider" feel. 4px gives the chevron breathing room while
     keeping headers visibly thinner than data rows below them
     (.key-level rows are ~24px). The rail's job is to surface
     data, not advertise its own structure — chrome stays thin.
     Single padding / font / line-height set for ALL sidebar headers
     (collapsible + static), so the rail has consistent visual
     rhythm. The [data-static="on"] selector below disables hover /
     cursor for non-clickable variants. */
  padding: 4px 14px;
  cursor: pointer;
  user-select: none;
  background: var(--bg2);
  transition: background 0.12s;
  line-height: 1;
  /* Subtle separator below — replaces the per-section border that used
     to sit on .sb-section. Gives every header a consistent below-line. */
  border-bottom: 1px solid var(--border);
}
.sb-section-head:hover {
  background: var(--bg3);
}
/* Static (non-collapsible) sections — Instruments, Key Levels. Same
   visual header, but no click affordance. */
.sb-section[data-static="on"] > .sb-section-head {
  cursor: default;
}
.sb-section[data-static="on"] > .sb-section-head:hover {
  background: var(--bg2);
}
.sb-section-label {
  /* Matches .detail-title — same font, size, weight, letter-spacing,
     uppercase. Single canonical inline-section-header style across the
     platform, even though the surrounding wrapper differs. */
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text2);
  line-height: 1;
}
.sb-section-chevron {
  font-size: 9px;
  color: var(--text3);
  transition: transform 0.18s ease-out;
  display: inline-block;
  line-height: 1;
}
.sb-section[data-collapsed="on"] .sb-section-chevron {
  transform: rotate(-90deg);
}

/* Body / summary visibility — driven entirely by data-collapsed.
   The renderer keeps both in sync; CSS just picks which is on screen. */
.sb-section[data-collapsed="off"] > .sb-section-summary {
  display: none;
}
.sb-section[data-collapsed="on"] > .sb-section-body {
  display: none;
}
.sb-section-summary {
  padding: 0 14px 10px;
}
.sb-section-body {
  padding: 0 0 4px;  /* per-renderer content provides its own padding */
}

/* Summary chip styles — used by renderers to lay out the compact view.
   Reusable across regime / alignment / levels (one-liners) and
   patterns (multi-row compact list). */
.sb-summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.5;
  padding: 2px 0;
}
.sb-summary-row + .sb-summary-row {
  border-top: 1px dashed var(--border);
  padding-top: 4px;
  margin-top: 4px;
}
.sb-summary-label {
  color: var(--text3);
  letter-spacing: 0.04em;
}
.sb-summary-value {
  color: var(--text);
  font-weight: 700;
}
.sb-summary-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  border-radius: 4px;
  background: var(--bg3);
  border: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* Compact pattern row (collapsed Pattern Detector). User asked
   specifically for "small rows of the active patterns when collapsed,"
   not just a single top-pattern summary. Layout: name (left, colored
   by direction) + confidence pill (right). Entire summary block
   accommodates the full active-pattern list. */
.sb-pattern-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.4;
}
.sb-pattern-row + .sb-pattern-row {
  border-top: 1px dashed var(--border);
}
.sb-pattern-name {
  font-weight: 700;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sb-pattern-conf {
  color: var(--text2);
  font-size: 9px;
  flex-shrink: 0;
}
.sb-pattern-empty {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text3);
  font-style: italic;
}

/* Hover-card for collapsed sidebar sections (4/29/26).
   When a section is collapsed (summary row visible only), hovering
   the summary surfaces the full body content as a floating card to
   the right of the rail. Lets users get the full read without
   expanding/collapsing — preserves the dense rail aesthetic.
   Bound in bindSidebarHoverCards() in app.js. */
.sb-section-hover-card {
  position: fixed;
  z-index: 9000;
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: 8px;
  /* Horizontal padding so cloned-in content (which assumes some host
     padding via .panel-body context) has breathing room. Without this,
     regime-state and stat-cells run edge-to-edge and long copy gets
     pushed against the card border. */
  padding: 10px 14px;
  min-width: 240px;
  max-width: 320px;
  max-height: 400px;
  overflow-y: auto;
  /* Force long content to wrap rather than overflow horizontally.
     Belt-and-suspenders: works for both whitespace-broken text and
     unbreakable strings (rare in our content but safe). */
  overflow-wrap: anywhere;
  word-break: break-word;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  display: none;
  /* Don't intercept hover ourselves — the card appears next to the
     summary row, and we want the user to be able to mouse INTO the
     card to scroll long content. So pointer-events stay enabled. */
  pointer-events: auto;
}
/* Regime-state inside the hover card: the inner label/desc wrapper
   has no class — give the second flex child constrained sizing so
   long descriptions wrap inside the card width instead of pushing
   the icon out. Same fix applies in the regular sidebar — the rule
   is global so both surfaces get it. */
.regime-state > div:not(.regime-icon) {
  flex: 1;
  min-width: 0;
}
/* Regime description carries explicit \n line breaks from the
   renderer ("dealers buy dips · sell rips\nVolatility suppressed").
   pre-line honors them; otherwise they collapse to whitespace. */
.regime-desc {
  white-space: pre-line;
}
.sb-section-hover-card.visible {
  display: block;
}
.sb-section-hover-card::-webkit-scrollbar { width: 6px; }
.sb-section-hover-card::-webkit-scrollbar-track { background: transparent; }
.sb-section-hover-card::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }

/* Summary row — visible when collapsed. Add a subtle hover bg so
   it's clear the row is interactive (the hover-card pops on hover). */
.sb-section-summary {
  cursor: default;
  transition: background 0.12s;
}
.sb-section[data-collapsed="on"] .sb-section-summary:hover {
  background: var(--bg3);
}

/* Key-Level row tooltip (4/29/26). Surfaces the contextual description
   for a structural level on row hover. Smaller / tighter than the
   section hover-card since it carries one line of copy at most.
   Bound in bindKeyLevelTooltips() in app.js. */
.key-level-tooltip {
  position: fixed;
  z-index: 9100;
  background: var(--bg2);
  border: 1px solid var(--border2);
  border-radius: 6px;
  padding: 8px 12px;
  max-width: 280px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
  display: none;
  pointer-events: none;
  font-family: var(--mono);
}
.key-level-tooltip.visible {
  display: block;
}
.key-level-tooltip .klt-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text2);
  margin-bottom: 4px;
}
.key-level-tooltip .klt-body {
  font-size: 10px;
  color: var(--text);
  line-height: 1.5;
  letter-spacing: 0.02em;
}
.key-level-row:hover {
  background: var(--bg3);
}
  /* ───────────────────────────────────────────────────────────────────────
     PHASE 4.3 — Pulse TAB
     Top-level Pulse view styles. Distinct from the V1 floating
     `.trending-pulse-panel` (which stays for admin A/B testing). Pulse
     tab fills the active view region; styling intentionally lean since
     the next phase folds Pulse content into the Heatmap view.
  ─────────────────────────────────────────────────────────────────────── */
  .pulse-wrap {
    font-family: var(--mono);
    color: var(--text2);
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .pulse-header-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
  }
  .pulse-title {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text);
    flex: 1;
  }
  .pulse-instrument-chips {
    display: flex;
    gap: 4px;
  }
  .pulse-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: center;
    padding: 6px 0;
  }
  .pulse-filter-group {
    display: flex;
    align-items: center;
    gap: 4px;
  }
  .pulse-filter-label {
    font-size: 9px;
    color: var(--text3);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-right: 4px;
  }
  .pulse-chip {
    background: var(--bg3);
    border: 1px solid var(--border);
    color: var(--text2);
    font-family: var(--mono);
    font-size: 10px;
    padding: 3px 10px;
    border-radius: 3px;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    line-height: 1;
  }
  .pulse-chip:hover { border-color: var(--border2); color: var(--text); }
  .pulse-chip.active {
    background: rgba(255, 107, 53, 0.15);
    border-color: var(--king);
    color: var(--king);
  }
  .pulse-table-wrap {
    overflow-x: auto;
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 4px;
  }
  .pulse-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 11px;
  }
  .pulse-th {
    text-align: left;
    padding: 8px 10px;
    background: var(--bg3);
    color: var(--text3);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: 1;
  }
  .pulse-row {
    border-bottom: 1px solid rgba(255,255,255,0.04);
    cursor: pointer;
    border-left: 2px solid transparent;
    transition: background 100ms ease;
  }
  .pulse-row:hover {
    background: rgba(255, 255, 255, 0.04);
  }
  .pulse-row.dir-up    { border-left-color: var(--green); }
  .pulse-row.dir-down  { border-left-color: var(--red); }
  .pulse-row.dir-neutral { border-left-color: var(--text3); }
  .pulse-row td {
    padding: 6px 10px;
    vertical-align: middle;
    white-space: nowrap;
  }
  .pulse-rank {
    font-size: 10px;
    color: var(--text3);
    font-weight: 700;
    width: 28px;
  }
  .pulse-sym {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    width: 40px;
  }
  .pulse-sym-spx { color: var(--pika); }
  .pulse-sym-spy { color: var(--gate); }
  .pulse-sym-qqq { color: var(--flip); }
  .pulse-strike {
    font-size: 12px;
    color: var(--text);
    font-weight: 600;
    letter-spacing: 0.02em;
  }
  .pulse-sig {
    font-size: 11px;
    color: var(--king);
    font-weight: 700;
  }
  .pulse-delta {
    font-size: 11px;
    color: var(--text2);
    text-align: right;
    letter-spacing: 0.02em;
  }
  .pulse-row.dir-up .pulse-delta { color: var(--green); }
  .pulse-row.dir-down .pulse-delta { color: var(--red); }
  /* Active timescale column gets a light highlight so the user sees which
     delta is the current secondary-sort key. */
  .pulse-delta-on {
    background: rgba(255, 107, 53, 0.06);
    border-left: 1px solid rgba(255, 107, 53, 0.25);
    border-right: 1px solid rgba(255, 107, 53, 0.25);
  }
  .pulse-arrow {
    font-size: 10px;
    margin-left: 4px;
  }
  .pulse-row.dir-up .pulse-arrow { color: var(--green); }
  .pulse-row.dir-down .pulse-arrow { color: var(--red); }
  .pulse-row.dir-neutral .pulse-arrow { color: var(--text3); }
  .pulse-accel {
    font-size: 10px;
    text-align: center;
    letter-spacing: 0.04em;
  }
  .pulse-tags {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
  }
  .pulse-spark {
    text-align: right;
    font-size: 12px;
    color: var(--text3);
    min-width: 70px;
  }
  .pulse-empty-cell {
    padding: 24px;
    text-align: center;
    color: var(--text3);
    font-style: italic;
    font-size: 11px;
  }
  .pulse-footer {
    font-size: 10px;
    color: var(--text3);
    letter-spacing: 0.04em;
    padding: 4px 2px;
  }
  .pulse-warming {
    background: var(--bg2);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 32px 24px;
    text-align: center;
    max-width: 480px;
    margin: 32px auto;
  }
  .pulse-warming-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--king);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    margin-bottom: 8px;
  }
  .pulse-warming-body {
    font-size: 11px;
    color: var(--text3);
    line-height: 1.5;
    letter-spacing: 0.02em;
  }

  /* Narrow viewport — drop the spark column gracefully (it's the lowest-
     value piece on small screens). */
  @media (max-width: 720px) {
    .pulse-spark, .pulse-table th:last-child {
      display: none;
    }
    .pulse-filters {
      gap: 8px;
    }
  }


/* Phase 4.4 grid port: position rail/chip correctly when attached
   to a CSS Grid strike cell (.heat-grid-strike) instead of a row
   container. The rail's existing rules already work (left:0, top:50%,
   absolute) since the strike cell is position:relative. The chip needs
   a corner-anchored variant so it doesn't overlap the strike number. */
.heat-grid-strike .trending-rankchip {
  right: 2px;
  top: 2px;
  transform: none;
  font-size: 8px;
  padding: 0 3px;
  letter-spacing: 0;
}
.heat-grid-strike .trending-rail {
  /* Override box-shadow magnitude — strike column is narrow, halo
     bleeds into the GEX cell next to it which looks wrong. */
  box-shadow: 0 0 2px currentColor;
}
