/* ────────────────────────────────────────────────────────────────────────────
   THE TYPEFACE. One family, self-hosted.

   Inter variable, latin subset, 48KB. Self-hosted rather than linked from Google so
   first paint does not depend on a third party — and because a font request to another
   origin is a request this desk cannot see, cache or guarantee.

   ONE @font-face for the whole 400-700 range: a variable font carries every weight in a
   single file, so asking for 600 costs nothing beyond the 400 already downloaded. That is
   most of why one family can replace three without a payload increase — the three faces
   this replaces were three separate downloads.

   `swap` because the alternative is invisible text: this is a data product read at a
   glance, and a metrics-compatible fallback shifting to Inter is a smaller cost than a
   blank board while a font loads.
   ──────────────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ────────────────────────────────────────────────────────────────────────────
   THE EDITORIAL FACES. Two more, and ONLY the editorial palette ever asks for them.

   A @font-face file is fetched when a rule that USES the family first matches a
   rendered element — never merely because the declaration was parsed. Both families
   below are named only from `:root[data-palette="editorial"]`, so a reader on slate,
   warm or teal downloads neither and pays nothing for their existence. That is also
   why neither is <link rel=preload>ed the way Inter is: Inter is on every page in
   every palette and is worth discovering early, whereas preloading these two would
   hand every reader a 213KB bill for a palette they may never select.

   Self-hosted for the same reason Inter is — a font request to another origin is a
   request this desk cannot see, cache or guarantee — even though the CSP would in
   fact still permit fonts.gstatic.com. Both are SIL Open Font License 1.1; see
   fonts/OFL.txt. Latin subset only, matching Inter's unicode-range exactly, and both
   variable, so the whole weight range costs one file.

   The editorial design draws headlines at weight 500 and labels at 600; the ranges
   below cover both without a second file.
   ──────────────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Merriweather";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("../fonts/merriweather-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ════════════════════════════════════════════════════════════════════════════
   DESIGN TOKEN LAYER  —  four palettes × two modes, on two independent axes.
   ────────────────────────────────────────────────────────────────────────────
       <html data-palette="slate|warm|teal|editorial" data-theme="light|dark">

   The file is laid out in four parts and nothing else may define a colour:

     1. :root — STRUCTURAL only. Type, the radius scale, the motion system.
        Nothing here varies by palette or mode.
     2. Eight complete palette blocks, one per palette × mode. Each block defines
        the SAME full token list; none omits a token and leans on inheritance,
        because a missing token would silently inherit the previous palette's
        value and no test would notice.
     3. The no-attribute default (slate/dark) plus the prefers-color-scheme
        light fallback for :root:not([data-theme]) — the no-JS first paint.
        A palette block's specificity (0,3,0) beats these (0,1,0)/(0,2,0), so
        source order between them does not matter.
     4. The LEGACY ALIAS block, exactly once. Custom-property substitution
        resolves at USE time, so `--panel: var(--surface)` automatically follows
        whichever palette block won — which is why the aliases are declared once
        rather than six times.

   PALETTES
     slate  the original Pinstripe Ledger. Byte-for-byte what production shipped
            before palettes existed — it is the reference, so it is not retuned.
            ⚠ It carries two known accessibility shortfalls that are DELIBERATELY
            left in place: bull-vs-bear separates by only 1.17:1 (dark) / 1.008:1
            (light) under deuteranopia against a 1.25 bar, and --text-faint runs
            2.6–3.4:1 against a 4.5 bar.
     warm   brown/ochre-leaning charcoal and stone (dark) / oat paper (light),
            copper-bronze accent. warn sits at a yellower gold than the accent so
            "interactive" and "caution" stay distinguishable in a warm palette.
     teal   deep blue-green canvas and desaturated teal surfaces (dark) / pale
            mint-grey (light), clear cyan-teal accent.
     editorial  the financial-press look: cool paper and white cards (light) /
            ink-navy (dark), a saturated print blue, and the ONLY palette whose
            up/down pair is the newsprint green-against-red rather than the
            blue/terracotta the other three share. It is also the flattest — its
            --shadow-1 is a 1px hairline drop, because this palette carries depth
            with a rule rather than a glow, so a card here sits ON the page instead
            of above it. Its greens and reds are far enough apart in LIGHTNESS that
            the pair survives colour blindness (below); do not retune one leg
            without re-running that check, since green/red is exactly the pair that
            fails it by default.

   warm, teal and editorial were not eyeballed. Every foreground is declared as an
   intended hue/saturation/lightness and then VERIFIED: body text ≥7:1 on every surface it
   appears on; secondary, muted, faint and every semantic text ≥4.5:1 against both
   the plain surface AND its own tint composited over that surface; hairlines
   visible but quieter than muted text; and bull-vs-bear separated by ≥1.25:1
   under a Viénot deuteranopia projection AND by ≥8 L* — so up and down stay
   distinct by lightness, not by hue alone. Measured worst cases at the time of
   writing: warm/dark 4.51 · warm/light 4.56 · teal/dark 4.54 · teal/light 4.61 ·
   editorial/dark 5.17 · editorial/light 4.59, body text 11.3–16.3:1 throughout.
   Editorial's bull/bear text pair separates by 1.50:1 (dark) / 1.81:1 (light)
   under deuteranopia at ΔL* 18.9 / 10.3 — the widest of the four, which is what
   buys a green/red palette the right to exist here.

   Hairlines keep the SAME alpha across palettes; only the RGB triplet swaps, via
   --hairline-rgb. Borders are written as rgba(var(--hairline-rgb), <alpha>) so
   they track the palette without a second token per alpha.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── 1. STRUCTURAL — theme-invariant ──────────────────────────────────────── */
:root {
  /* ---- type ----
     TWO tokens, and the second is an alias of the first. This replaced a trio — Space
     Grotesk for running text, IBM Plex Mono for every label and figure, Newsreader for
     headlines — where the family itself carried meaning: serif said "editorial voice",
     mono said "machine output".

     That distinction is now carried by WEIGHT, SIZE, TRACKING and COLOUR instead. It has
     to be, because there is only one family left to say it with.

     `--font-display` is kept as a separate name even though it resolves to the same
     stack, so the ~25 headline sites stay addressable: putting a display face back is
     then one line here rather than a hunt through nine stylesheets. Today they are
     identical and must stay identical.

     The mono face was doing real work — aligning digits down the strength board, the
     score columns, the countdown. That job moves to `font-variant-numeric: tabular-nums`
     below, which is an OpenType feature of THIS font rather than a second family. */
  --font-sans:    "Inter", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --font-display: var(--font-sans);
  /* The third role the page stylesheets already name for themselves (--cd-mono,
     --pd-mono): the face figures and tracked-caps labels are set in. It resolves to
     the sans here, which is what those files were doing by hand, so naming it changes
     nothing for slate, warm or teal — it just gives the editorial palette one place
     to answer differently. `font-variant-numeric: tabular-nums` below still does the
     column-alignment work whichever family wins. */
  --font-mono:    var(--font-sans);

  /* ---- radius scale ----
     Nested surfaces step DOWN one rung: an --r-md panel holds --r-sm children.
     A child radius equal to or larger than its parent's reads as a mistake, so
     the rung is chosen by what a component CONTAINS, not by its own size.
     Data-table CELLS stay square; only a table's outer frame rounds. Full-bleed
     dividers, hairlines and the pinstripe never take a radius. */
  /* Rungs taken from the design's own measured values rather than guessed: it
     draws at 2-3px (marks), 5-7px (chips), 8-9px (buttons, inner panels) and
     11-12px (cards), which is exactly this ladder. */
  --r-xs:   3px;    /* marks, meter fills, pips */
  --r-sm:   7px;    /* chips, tags, inline badges */
  --r-md:   10px;   /* buttons, inputs, inner panels */
  --r-lg:   13px;   /* cards */
  --r-xl:   16px;   /* section groups, the header bar */
  --r-frame: 24px;  /* the page shell and full-screen modals */
  --r-pill: 999px;  /* toggles, segmented controls, status pills only */

  /* The vertical rhythm between a view's top-level cards. It is a TOKEN because
     two files need to agree on it: the view stacks its real blocks with it, and
     the skeleton stacks its placeholders with it. When only the view had it, the
     skeleton sat flush and every page shifted by ~90px on the swap to data. */
  --gap-stack: clamp(14px, 1.8vw, 22px);
  /* Legacy aliases. They exist because ~130 call sites across the per-page
     stylesheets were authored against `var(--r)` / `var(--r, 0)` before the scale
     existed; renaming every one of them in a restyle would be a diff nobody could
     review. They are kept so those call sites keep resolving, and they now point
     AT the scale rather than at the old square geometry:
       --r       -> --r-md   (the panel/card default the old sites mostly wanted)
       --r-soft  -> --r-xs   (the chip/tag escape hatch it always meant)
     New code names a rung directly; these two are for the legacy sites only. */
  --r:      var(--r-md);
  --r-soft: var(--r-xs);

  /* ---- motion system — the single source of timing ----
     Every duration and easing in the app comes from here. A literal ms or
     cubic-bezier() anywhere else is a bug: it puts one component on a clock
     nothing else shares, and it is what makes a palette swap smear. */
  --dur-instant: 0ms;      /* palette/theme token swaps — never animated */
  --dur-micro:   90ms;     /* hover tint, focus ring, pip fill */
  --dur-fast:    140ms;    /* press, checkbox, chip select */
  --dur-base:    220ms;    /* element reveal, tab crossfade, tooltip */
  --dur-slow:    320ms;    /* panel expand/collapse, drawer, modal */
  --dur-flash:   600ms;    /* changed-value tint flash (fade-out only) */
  --dur-shimmer: 1400ms;   /* skeleton sweep cycle */
  --dur-pulse:   1800ms;   /* the live-feed dot's breath — slow enough to read
                              as a heartbeat rather than a blink, and the only
                              thing on the page that loops indefinitely */

  --ease-out:     cubic-bezier(.22,.61,.36,1);    /* things arriving (default) */
  --ease-in:      cubic-bezier(.55,.06,.68,.19);  /* things leaving */
  --ease-inout:   cubic-bezier(.45,.05,.55,.95);  /* moving in place / height */
  --ease-shimmer: ease-in-out;                    /* skeleton only */

  /* Three delays the system needs by name. A tooltip opens late and closes
     later still, so crossing between two adjacent triggers cannot strobe; an
     incoming panel starts while the outgoing one is still leaving, which is a
     short overlap rather than a hard cut. */
  /* Every digit the same width, everywhere. This is what replaces the monospace face:
     without it, Inter's proportional figures make a column of scores ragged and a ticking
     countdown jitter as the numerals change width. It is INHERITED, so declaring it once
     here covers the whole tree; the few places proportional figures genuinely read better
     (digits inside running prose) can opt out locally. This is a data product — when in
     doubt the column wins. */
  font-variant-numeric: tabular-nums;

  --delay-pop-open:      120ms;
  --delay-pop-close:      60ms;
  --delay-swap-overlap:   60ms;

  --stagger-step: 40ms;    /* per-child delay */
  --stagger-max:  8;       /* children past the 8th share the 8th delay */
}


/* ── 2. PALETTE BLOCKS — six complete sets ────────────────────────────────── */

/* slate/dark — Cool Slate at night. Slate-green canvas, the accent lifts to a pale blue. */
:root[data-palette="slate"][data-theme="dark"] {
  /* canvas */
  --app-bg: #1B2224;
  --surface: #242D2F;
  --surface-raised: #242D2F;
  --surface-sunken: #262f31;
  --surface-row-active: #2E3839;
  --surface-kpi: #293234;
  /* frame */
  --hairline-rgb: 62,74,74;
  --frame-border: rgba(62,74,74,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(62,74,74,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(62,74,74,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.55);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.55);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.62);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.70);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.70);
  --scrim: rgba(0,0,0,.55);
  /* text */
  --text: #DCEDFF;
  --text-2: #A9BFD8;
  --text-muted: #A9BFD8;
  --text-faint: #90a1ab;
  --colhead: #90a1ab;
  /* accent */
  --accent: #94B0DA;
  --on-accent: #242D2F;
  --accent-edge: rgba(148,176,218,.42);
  --diff-hi: rgba(148,176,218,.18);
  --cell-hi: rgba(148,176,218,.16);
  --seg-empty: rgba(62,74,74,.45);
  /* semantic */
  --bull-text: #c4d4f1;
  --bull-tint: rgba(148,176,218,.15);
  --bull-edge: rgba(148,176,218,.4);
  --bull-dot: #94B0DA;
  --bear-text: #daada1;
  --bear-tint: rgba(201,139,127,.17);
  --bear-edge: rgba(201,139,127,.44);
  --bear-dot: #C98B7F;
  --warn-text: #d0b386;
  --warn-tint: rgba(196,167,110,.15);
  --warn-edge: rgba(196,167,110,.42);
  --warn-dot: #c4a76e;
  --mixed-text: #c3a6e0;
  --mixed-tint: rgba(167,110,196,.18);
  --mixed-edge: rgba(167,110,196,.44);
  --mixed-dot: #a76ec4;
  --info-text: #a2b5de;
  --info-tint: rgba(110,147,196,.16);
  --info-edge: rgba(110,147,196,.42);
  --info-dot: #6e93c4;
  --risk-text: #d9ac98;
  --risk-tint: rgba(196,142,110,.16);
  --risk-edge: rgba(196,142,110,.42);
  --risk-dot: #c48e6e;
  --new-text: #7acab9;
  --new-tint: rgba(110,196,179,.16);
  --new-edge: rgba(110,196,179,.42);
  --new-dot: #6ec4b3;
  /* chart */
  --candle-up: #94B0DA;
  --candle-down: #C98B7F;
  --chart-grid: rgba(62,74,74,.35);
  --chart-rate1: #6E90C4;
  --chart-rate2: #cf916e;
  --bull-dot-rgb: 148,176,218;
  --bear-dot-rgb: 201,139,127;
  --live-rgb: 201,139,127;
  /* identity */
  --cat-1: #7398c9;
  --cat-2: #73c97f;
  --cat-3: #c9b273;
  --cat-4: #ac73c9;
  --cat-5: #c97673;
  --cat-6: #73b8c9;
  --cat-7: #c9739e;
  --cat-8: #afc973;
  --cat-9: #73c9b8;
  --cat-10: #c973c9;
}

/* slate/light — Cool Slate. Pale blue ground, white cards, a mid-blue accent. */
:root[data-palette="slate"][data-theme="light"] {
  /* canvas */
  --app-bg: #F1F6FE;
  --surface: #FFFFFF;
  --surface-raised: #FFFFFF;
  --surface-sunken: #f9fcff;
  --surface-row-active: #DCEDFF;
  --surface-kpi: #eef6ff;
  /* frame */
  --hairline-rgb: 203,220,243;
  --frame-border: rgba(203,220,243,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(203,220,243,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(203,220,243,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.30);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.28);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.30);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.35);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.35);
  --scrim: rgba(20,28,40,.34);
  /* text */
  --text: #343F3E;
  --text-2: #505A5B;
  --text-muted: #505A5B;
  --text-faint: #5d6c76;
  --colhead: #5d6c76;
  /* accent */
  --accent: #4C74AE;
  --on-accent: #FFFFFF;
  --accent-edge: rgba(76,116,174,.42);
  --diff-hi: rgba(76,116,174,.18);
  --cell-hi: rgba(76,116,174,.16);
  --seg-empty: rgba(203,220,243,.45);
  /* semantic */
  --bull-text: #316184;
  --bull-tint: rgba(62,110,158,.15);
  --bull-edge: rgba(62,110,158,.4);
  --bull-dot: #3E6E9E;
  --bear-text: #633f36;
  --bear-tint: rgba(176,115,106,.17);
  --bear-edge: rgba(176,115,106,.44);
  --bear-dot: #B0736A;
  --warn-text: #79591e;
  --warn-tint: rgba(163,126,51,.15);
  --warn-edge: rgba(163,126,51,.42);
  --warn-dot: #a37e33;
  --mixed-text: #7e33a3;
  --mixed-tint: rgba(126,51,163,.18);
  --mixed-edge: rgba(126,51,163,.44);
  --mixed-dot: #7e33a3;
  --info-text: #2b5c93;
  --info-tint: rgba(51,100,163,.16);
  --info-edge: rgba(51,100,163,.42);
  --info-dot: #3364a3;
  --risk-text: #854d24;
  --risk-tint: rgba(163,92,51,.16);
  --risk-edge: rgba(163,92,51,.42);
  --risk-dot: #a35c33;
  --new-text: #1a6b56;
  --new-tint: rgba(49,155,134,.16);
  --new-edge: rgba(49,155,134,.42);
  --new-dot: #319b86;
  /* chart */
  --candle-up: #3E6E9E;
  --candle-down: #B0736A;
  --chart-grid: rgba(203,220,243,.35);
  --chart-rate1: #94B0DA;
  --chart-rate2: #a15d36;
  --bull-dot-rgb: 62,110,158;
  --bear-dot-rgb: 176,115,106;
  --live-rgb: 176,115,106;
  /* identity */
  --cat-1: #3364a3;
  --cat-2: #30993e;
  --cat-3: #a18433;
  --cat-4: #7e33a3;
  --cat-5: #a33733;
  --cat-6: #338da3;
  --cat-7: #a3336b;
  --cat-8: #74912e;
  --cat-9: #2f9581;
  --cat-10: #a333a3;
}

/* warm/dark — Warm Ash at night. Near-black olive, the accent lifts to pale ash. */
:root[data-palette="warm"][data-theme="dark"] {
  /* canvas */
  --app-bg: #1D201C;
  --surface: #262A25;
  --surface-raised: #262A25;
  --surface-sunken: #282c27;
  --surface-row-active: #31352F;
  --surface-kpi: #2c302a;
  /* frame */
  --hairline-rgb: 69,74,67;
  --frame-border: rgba(69,74,67,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(69,74,67,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(69,74,67,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.55);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.55);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.62);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.70);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.70);
  --scrim: rgba(0,0,0,.55);
  /* text */
  --text: #E0E2DB;
  --text-2: #B8BDB5;
  --text-muted: #B8BDB5;
  --text-faint: #909e9e;
  --colhead: #909e9e;
  /* accent */
  --accent: #B8BDB5;
  --on-accent: #262A25;
  --accent-edge: rgba(184,189,181,.42);
  --diff-hi: rgba(184,189,181,.18);
  --cell-hi: rgba(184,189,181,.16);
  --seg-empty: rgba(69,74,67,.45);
  /* semantic */
  --bull-text: #cdd2ca;
  --bull-tint: rgba(184,189,181,.15);
  --bull-edge: rgba(184,189,181,.4);
  --bull-dot: #B8BDB5;
  --bear-text: #d4aea0;
  --bear-tint: rgba(199,154,134,.17);
  --bear-edge: rgba(199,154,134,.44);
  --bear-dot: #C79A86;
  --warn-text: #ceb182;
  --warn-tint: rgba(196,167,110,.15);
  --warn-edge: rgba(196,167,110,.42);
  --warn-dot: #c4a76e;
  --mixed-text: #c2a4df;
  --mixed-tint: rgba(167,110,196,.18);
  --mixed-edge: rgba(167,110,196,.44);
  --mixed-dot: #a76ec4;
  --info-text: #9eb1dc;
  --info-tint: rgba(110,147,196,.16);
  --info-edge: rgba(110,147,196,.42);
  --info-dot: #6e93c4;
  --risk-text: #d7a894;
  --risk-tint: rgba(196,142,110,.16);
  --risk-edge: rgba(196,142,110,.42);
  --risk-dot: #c48e6e;
  --new-text: #74c7b6;
  --new-tint: rgba(110,196,179,.16);
  --new-edge: rgba(110,196,179,.42);
  --new-dot: #6ec4b3;
  /* chart */
  --candle-up: #B8BDB5;
  --candle-down: #C79A86;
  --chart-grid: rgba(69,74,67,.35);
  --chart-rate1: #889696;
  --chart-rate2: #cf916e;
  --bull-dot-rgb: 184,189,181;
  --bear-dot-rgb: 199,154,134;
  --live-rgb: 199,154,134;
  /* identity */
  --cat-1: #7398c9;
  --cat-2: #73c97f;
  --cat-3: #c9b273;
  --cat-4: #ac73c9;
  --cat-5: #c97673;
  --cat-6: #73b8c9;
  --cat-7: #c9739e;
  --cat-8: #afc973;
  --cat-9: #73c9b8;
  --cat-10: #c973c9;
}

/* warm/light — Warm Ash. Oat ground, bone cards, a grey-green accent. */
:root[data-palette="warm"][data-theme="light"] {
  /* canvas */
  --app-bg: #E9EBE3;
  --surface: #F8F9F4;
  --surface-raised: #F8F9F4;
  --surface-sunken: #f4f5ef;
  --surface-row-active: #DDDFD4;
  --surface-kpi: #eaece4;
  /* frame */
  --hairline-rgb: 184,189,181;
  --frame-border: rgba(184,189,181,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(184,189,181,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(184,189,181,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.30);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.28);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.30);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.35);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.35);
  --scrim: rgba(20,28,40,.34);
  /* text */
  --text: #2C3432;
  --text-2: #55605E;
  --text-muted: #55605E;
  --text-faint: #566568;
  --colhead: #566568;
  /* accent */
  --accent: #4F6564;
  --on-accent: #F8F9F4;
  --accent-edge: rgba(79,101,100,.42);
  --diff-hi: rgba(79,101,100,.18);
  --cell-hi: rgba(79,101,100,.16);
  --seg-empty: rgba(184,189,181,.45);
  /* semantic */
  --bull-text: #304444;
  --bull-tint: rgba(79,101,100,.15);
  --bull-edge: rgba(79,101,100,.4);
  --bull-dot: #4F6564;
  --bear-text: #645241;
  --bear-tint: rgba(158,111,94,.17);
  --bear-edge: rgba(158,111,94,.44);
  --bear-dot: #9E6F5E;
  --warn-text: #6f511b;
  --warn-tint: rgba(161,124,51,.15);
  --warn-edge: rgba(161,124,51,.42);
  --warn-dot: #a17c33;
  --mixed-text: #742d97;
  --mixed-tint: rgba(126,51,163,.18);
  --mixed-edge: rgba(126,51,163,.44);
  --mixed-dot: #7e33a3;
  --info-text: #255687;
  --info-tint: rgba(51,100,163,.16);
  --info-edge: rgba(51,100,163,.42);
  --info-dot: #3364a3;
  --risk-text: #7b481f;
  --risk-tint: rgba(163,92,51,.16);
  --risk-edge: rgba(163,92,51,.42);
  --risk-dot: #a35c33;
  --new-text: #18614d;
  --new-tint: rgba(46,145,125,.16);
  --new-edge: rgba(46,145,125,.42);
  --new-dot: #2e917d;
  /* chart */
  --candle-up: #4F6564;
  --candle-down: #9E6F5E;
  --chart-grid: rgba(184,189,181,.35);
  --chart-rate1: #889696;
  --chart-rate2: #a15d36;
  --bull-dot-rgb: 79,101,100;
  --bear-dot-rgb: 158,111,94;
  --live-rgb: 158,111,94;
  /* identity */
  --cat-1: #3364a3;
  --cat-2: #2d8f3a;
  --cat-3: #957a2f;
  --cat-4: #7e33a3;
  --cat-5: #a33733;
  --cat-6: #32879d;
  --cat-7: #a3336b;
  --cat-8: #6a862a;
  --cat-9: #2c8c78;
  --cat-10: #a333a3;
}

/* teal/dark — Deep Teal at night. Deep blue-green, a bright cyan accent. */
:root[data-palette="teal"][data-theme="dark"] {
  /* canvas */
  --app-bg: #0C1D1F;
  --surface: #122B2B;
  --surface-raised: #122B2B;
  --surface-sunken: #132d2e;
  --surface-row-active: #183A3B;
  --surface-kpi: #153233;
  /* frame */
  --hairline-rgb: 34,73,75;
  --frame-border: rgba(34,73,75,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(34,73,75,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(34,73,75,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.55);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.55);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.62);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.70);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.70);
  --scrim: rgba(0,0,0,.55);
  /* text */
  --text: #EAF3E5;
  --text-2: #BFD7B5;
  --text-muted: #BFD7B5;
  --text-faint: #81a598;
  --colhead: #81a598;
  /* accent */
  --accent: #12A8B8;
  --on-accent: #122B2B;
  --accent-edge: rgba(18,168,184,.42);
  --diff-hi: rgba(18,168,184,.18);
  --cell-hi: rgba(18,168,184,.16);
  --seg-empty: rgba(34,73,75,.45);
  /* semantic */
  --bull-text: #12c4d4;
  --bull-tint: rgba(18,168,184,.15);
  --bull-edge: rgba(18,168,184,.4);
  --bull-dot: #12A8B8;
  --bear-text: #ebc2ab;
  --bear-tint: rgba(226,149,95,.17);
  --bear-edge: rgba(226,149,95,.44);
  --bear-dot: #E2955F;
  --warn-text: #ceb182;
  --warn-tint: rgba(196,167,110,.15);
  --warn-edge: rgba(196,167,110,.42);
  --warn-dot: #c4a76e;
  --mixed-text: #c2a4df;
  --mixed-tint: rgba(167,110,196,.18);
  --mixed-edge: rgba(167,110,196,.44);
  --mixed-dot: #a76ec4;
  --info-text: #a0b3dd;
  --info-tint: rgba(110,147,196,.16);
  --info-edge: rgba(110,147,196,.42);
  --info-dot: #6e93c4;
  --risk-text: #d7a894;
  --risk-tint: rgba(196,142,110,.16);
  --risk-edge: rgba(196,142,110,.42);
  --risk-dot: #c48e6e;
  --new-text: #78c9b8;
  --new-tint: rgba(110,196,179,.16);
  --new-edge: rgba(110,196,179,.42);
  --new-dot: #6ec4b3;
  /* chart */
  --candle-up: #12A8B8;
  --candle-down: #E2955F;
  --chart-grid: rgba(34,73,75,.35);
  --chart-rate1: #F7D2B5;
  --chart-rate2: #cf916e;
  --bull-dot-rgb: 18,168,184;
  --bear-dot-rgb: 226,149,95;
  --live-rgb: 226,149,95;
  /* identity */
  --cat-1: #7398c9;
  --cat-2: #73c97f;
  --cat-3: #c9b273;
  --cat-4: #ac73c9;
  --cat-5: #c97673;
  --cat-6: #73b8c9;
  --cat-7: #c9739e;
  --cat-8: #afc973;
  --cat-9: #73c9b8;
  --cat-10: #c973c9;
}

/* teal/light — Deep Teal. Pale sage ground, white cards, a strong cyan accent. */
:root[data-palette="teal"][data-theme="light"] {
  /* canvas */
  --app-bg: #F3F7EF;
  --surface: #FFFFFF;
  --surface-raised: #FFFFFF;
  --surface-sunken: #fbfcf9;
  --surface-row-active: #E3EEDC;
  --surface-kpi: #f1f6ee;
  /* frame */
  --hairline-rgb: 201,220,190;
  --frame-border: rgba(201,220,190,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(201,220,190,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(201,220,190,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.30);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.28);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.30);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.35);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.35);
  --scrim: rgba(20,28,40,.34);
  /* text */
  --text: #103A3D;
  --text-2: #265E5F;
  --text-muted: #265E5F;
  --text-faint: #507066;
  --colhead: #507066;
  /* accent */
  --accent: #028090;
  --on-accent: #FFFFFF;
  --accent-edge: rgba(2,128,144,.42);
  --diff-hi: rgba(2,128,144,.18);
  --cell-hi: rgba(2,128,144,.16);
  --seg-empty: rgba(201,220,190,.45);
  /* semantic */
  --bull-text: #025253;
  --bull-tint: rgba(2,128,144,.15);
  --bull-edge: rgba(2,128,144,.4);
  --bull-dot: #028090;
  --bear-text: #894f21;
  --bear-tint: rgba(206,116,64,.17);
  --bear-edge: rgba(206,116,64,.44);
  --bear-dot: #CE7440;
  --warn-text: #79591e;
  --warn-tint: rgba(163,126,51,.15);
  --warn-edge: rgba(163,126,51,.42);
  --warn-dot: #a37e33;
  --mixed-text: #7e33a3;
  --mixed-tint: rgba(126,51,163,.18);
  --mixed-edge: rgba(126,51,163,.44);
  --mixed-dot: #7e33a3;
  --info-text: #2b5c93;
  --info-tint: rgba(51,100,163,.16);
  --info-edge: rgba(51,100,163,.42);
  --info-dot: #3364a3;
  --risk-text: #854d24;
  --risk-tint: rgba(163,92,51,.16);
  --risk-edge: rgba(163,92,51,.42);
  --risk-dot: #a35c33;
  --new-text: #1a6954;
  --new-tint: rgba(49,155,134,.16);
  --new-edge: rgba(49,155,134,.42);
  --new-dot: #319b86;
  /* chart */
  --candle-up: #028090;
  --candle-down: #CE7440;
  --chart-grid: rgba(201,220,190,.35);
  --chart-rate1: #1A5E63;
  --chart-rate2: #a15d36;
  --bull-dot-rgb: 2,128,144;
  --bear-dot-rgb: 206,116,64;
  --live-rgb: 206,116,64;
  /* identity */
  --cat-1: #3364a3;
  --cat-2: #30993e;
  --cat-3: #9f8232;
  --cat-4: #7e33a3;
  --cat-5: #a33733;
  --cat-6: #338da3;
  --cat-7: #a3336b;
  --cat-8: #74912e;
  --cat-9: #2f9581;
  --cat-10: #a333a3;
}

/* editorial/dark — Editorial at night. Ink-navy ground, the accent lifts to a bright sky
   blue, and up/down are the newsprint pair (emerald against rose) rather than the
   blue/terracotta the other three use. */
:root[data-palette="editorial"][data-theme="dark"] {
  /* canvas */
  --app-bg: #0B1120;
  --surface: #0D1528;
  --surface-raised: #0D1528;
  --surface-sunken: #141F38;
  --surface-row-active: #141F38;
  --surface-kpi: #141F38;
  /* frame */
  --hairline-rgb: 44,57,75;
  --frame-border: rgba(44,57,75,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(44,57,75,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(44,57,75,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 2px 8px -2px rgba(0,0,0,.55);
  --shadow-1: 0 1px 2px rgba(0,0,0,.45);
  --shadow-2: 0 2px 6px -1px rgba(0,0,0,.50);
  --modal-shadow: 0 12px 34px -14px rgba(0,0,0,.72);
  --drawer-shadow: -12px 0 34px -14px rgba(0,0,0,.72);
  --scrim: rgba(6,11,22,.62);
  /* text */
  --text: #F8FAFC;
  --text-2: #CBD5E1;
  --text-muted: #CBD5E1;
  --text-faint: #94A3B8;
  --colhead: #94A3B8;
  /* accent */
  --accent: #35A5FF;
  --on-accent: #0B1120;
  --accent-edge: rgba(53,165,255,.42);
  --diff-hi: rgba(53,165,255,.18);
  --cell-hi: rgba(53,165,255,.16);
  --seg-empty: rgba(44,57,75,.45);
  /* semantic */
  --bull-text: #6EE7B7;
  --bull-tint: rgba(52,211,153,.15);
  --bull-edge: rgba(52,211,153,.4);
  --bull-dot: #34D399;
  --bear-text: #FB7185;
  --bear-tint: rgba(244,63,94,.17);
  --bear-edge: rgba(244,63,94,.44);
  --bear-dot: #F43F5E;
  --warn-text: #FCD34D;
  --warn-tint: rgba(251,191,36,.15);
  --warn-edge: rgba(251,191,36,.42);
  --warn-dot: #FBBF24;
  --mixed-text: #C4B5FD;
  --mixed-tint: rgba(167,139,250,.18);
  --mixed-edge: rgba(167,139,250,.44);
  --mixed-dot: #A78BFA;
  --info-text: #7DD3FC;
  --info-tint: rgba(56,189,248,.16);
  --info-edge: rgba(56,189,248,.42);
  --info-dot: #38BDF8;
  --risk-text: #FDBA74;
  --risk-tint: rgba(251,146,60,.16);
  --risk-edge: rgba(251,146,60,.42);
  --risk-dot: #FB923C;
  --new-text: #5EEAD4;
  --new-tint: rgba(45,212,191,.16);
  --new-edge: rgba(45,212,191,.42);
  --new-dot: #2DD4BF;
  /* chart */
  --candle-up: #34D399;
  --candle-down: #F43F5E;
  --chart-grid: rgba(44,57,75,.35);
  --chart-rate1: #018DFF;
  --chart-rate2: #FB923C;
  --bull-dot-rgb: 52,211,153;
  --bear-dot-rgb: 244,63,94;
  --live-rgb: 244,63,94;
  /* identity */
  --cat-1: #60A5FA;
  --cat-2: #4ADE80;
  --cat-3: #FBBF24;
  --cat-4: #A78BFA;
  --cat-5: #FB7185;
  --cat-6: #22D3EE;
  --cat-7: #F472B6;
  --cat-8: #A3E635;
  --cat-9: #2DD4BF;
  --cat-10: #E879F9;
}

/* editorial/light — Editorial. Cool paper, white cards, a saturated print blue, and the
   flattest shadow of the four: this palette carries depth with a hairline, not a glow. */
:root[data-palette="editorial"][data-theme="light"] {
  /* canvas */
  --app-bg: #F8FAFC;
  --surface: #FFFFFF;
  --surface-raised: #FFFFFF;
  --surface-sunken: #F1F5F9;
  --surface-row-active: #F1F5F9;
  --surface-kpi: #F1F5F9;
  /* frame */
  --hairline-rgb: 206,216,229;
  --frame-border: rgba(206,216,229,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(206,216,229,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(206,216,229,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 2px 8px -2px rgba(11,17,32,.16);
  --shadow-1: 0 1px 2px rgba(11,17,32,.06),0 1px 1px rgba(11,17,32,.04);
  --shadow-2: 0 2px 6px -1px rgba(11,17,32,.10),0 1px 2px rgba(11,17,32,.06);
  --modal-shadow: 0 12px 34px -14px rgba(11,17,32,.24);
  --drawer-shadow: -12px 0 34px -14px rgba(11,17,32,.24);
  --scrim: rgba(11,17,32,.34);
  /* text */
  --text: #0F172A;
  --text-2: #334155;
  --text-muted: #334155;
  --text-faint: #5D6B7E;
  --colhead: #5D6B7E;
  /* accent */
  --accent: #0066CC;
  --on-accent: #FFFFFF;
  --accent-edge: rgba(0,102,204,.42);
  --diff-hi: rgba(0,102,204,.18);
  --cell-hi: rgba(0,102,204,.16);
  --seg-empty: rgba(206,216,229,.45);
  /* semantic */
  --bull-text: #14532D;
  --bull-tint: rgba(22,101,52,.15);
  --bull-edge: rgba(22,101,52,.4);
  --bull-dot: #166534;
  --bear-text: #C21100;
  --bear-tint: rgba(227,20,0,.13);
  --bear-edge: rgba(227,20,0,.44);
  --bear-dot: #E31400;
  --warn-text: #92400E;
  --warn-tint: rgba(180,83,9,.15);
  --warn-edge: rgba(180,83,9,.42);
  --warn-dot: #B45309;
  --mixed-text: #6D28D9;
  --mixed-tint: rgba(109,40,217,.16);
  --mixed-edge: rgba(109,40,217,.44);
  --mixed-dot: #6D28D9;
  --info-text: #075985;
  --info-tint: rgba(3,105,161,.16);
  --info-edge: rgba(3,105,161,.42);
  --info-dot: #0369A1;
  --risk-text: #9A3412;
  --risk-tint: rgba(194,65,12,.16);
  --risk-edge: rgba(194,65,12,.42);
  --risk-dot: #C2410C;
  --new-text: #0F5A55;
  --new-tint: rgba(15,118,110,.16);
  --new-edge: rgba(15,118,110,.42);
  --new-dot: #0F766E;
  /* chart */
  --candle-up: #166534;
  --candle-down: #E31400;
  --chart-grid: rgba(206,216,229,.35);
  --chart-rate1: #018DFF;
  --chart-rate2: #C2410C;
  --bull-dot-rgb: 22,101,52;
  --bear-dot-rgb: 227,20,0;
  --live-rgb: 227,20,0;
  /* identity */
  --cat-1: #2563EB;
  --cat-2: #16A34A;
  --cat-3: #A16207;
  --cat-4: #7C3AED;
  --cat-5: #E11D48;
  --cat-6: #0891B2;
  --cat-7: #DB2777;
  --cat-8: #65A30D;
  --cat-9: #0D9488;
  --cat-10: #C026D3;
}

/* ── 2b. THE EDITORIAL SUPPLEMENT — type and masthead ────────────────────────
   Two things Editorial carries that a colour block cannot say, both keyed on the
   PALETTE alone because neither varies by light/dark.

   TYPE. The other three palettes are Inter throughout: one family, with weight,
   size, tracking and colour carrying the distinctions a second family used to.
   Editorial is the palette that puts the families back, because that IS the look —
   a Merriweather headline over tracked JetBrains Mono labels is what makes it read
   as a printed page rather than a terminal. Naming them here rather than in :root
   keeps the other three byte-identical and keeps both downloads opt-in.

   MASTHEAD. Editorial's signature move is a dark band at the top of the page in
   BOTH modes — white headline on ink navy even when the rest of the page is paper.
   The tokens below describe that band; the desks apply them to the hero they
   already lay out. They are deliberately NOT given :root defaults: a default of
   `--hero-text: var(--text)` would form a reference cycle the moment the hero
   rebinds `--text: var(--hero-text)`, and a cycle makes BOTH properties invalid
   rather than falling back. So the rebinding rules are palette-scoped instead, and
   the other three palettes never see them.

   These are supplementary rules, not palette blocks: part 2's eight blocks each
   define the same canvas token list and are identified by carrying --app-bg.
   ──────────────────────────────────────────────────────────────────────────── */
:root[data-palette="editorial"] {
  /* type */
  --font-display: "Merriweather", Georgia, "Times New Roman", serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  /* masthead — mode-invariant half */
  --hero-text: #FFFFFF;
  --hero-text-2: #CBD5E1;
  --hero-text-3: #94A3B8;
  --hero-line: #1E293B;
  --hero-panel: #0D1528;
  --hero-accent: #35A5FF;
  --hero-bull: #34D399;
  --hero-bear: #FB7185;
  /* the band bleeds back out through the page padding it sits inside, which on
     both desks is 36px 40px — hence exactly these three numbers. */
  --hero-pad: 40px 40px 44px;
  --hero-bleed-y: -36px;
  --hero-bleed-x: -40px;
  /* light-mode ground: the band is darker than the page, which is the whole point */
  --hero-bg: #0B1120;
  --hero-panel-2: #101A31;
}
/* In dark mode the band has to go DARKER than an already-dark page or it stops
   reading as a band at all. */
:root[data-palette="editorial"][data-theme="dark"] {
  --hero-bg: #060B16;
  --hero-panel-2: #141F38;
}

/* ── 3. DEFAULTS — no attributes at all (no-JS, or a pre-paint fault) ──────── */
/* slate/dark, matching part 2 value-for-value. The pre-paint script in
   index.html normally stamps both attributes before the stylesheet is read, so
   this is the safety net rather than the usual path. */
:root {
  --app-bg: #1B2224;
  --surface: #242D2F;
  --surface-raised: #242D2F;
  --surface-sunken: #262f31;
  --surface-row-active: #2E3839;
  --surface-kpi: #293234;
  --hairline-rgb: 62,74,74;
  --frame-border: rgba(62,74,74,.55);
  --header-grad: linear-gradient(var(--surface-raised),var(--surface));
  --header-rule: 1px solid rgba(62,74,74,.55);
  --pinstripe: repeating-linear-gradient(90deg,rgba(62,74,74,.28) 0 1px,transparent 1px 7px);
  --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.55);
  --shadow-1: 0 6px 18px -12px rgba(0,0,0,.55);
  --shadow-2: 0 12px 30px -18px rgba(0,0,0,.62);
  --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.70);
  --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.70);
  --scrim: rgba(0,0,0,.55);
  --text: #DCEDFF;
  --text-2: #A9BFD8;
  --text-muted: #A9BFD8;
  --text-faint: #90a1ab;
  --colhead: #90a1ab;
  --accent: #94B0DA;
  --on-accent: #242D2F;
  --accent-edge: rgba(148,176,218,.42);
  --diff-hi: rgba(148,176,218,.18);
  --cell-hi: rgba(148,176,218,.16);
  --seg-empty: rgba(62,74,74,.45);
  --bull-text: #c4d4f1;
  --bull-tint: rgba(148,176,218,.15);
  --bull-edge: rgba(148,176,218,.4);
  --bull-dot: #94B0DA;
  --bear-text: #daada1;
  --bear-tint: rgba(201,139,127,.17);
  --bear-edge: rgba(201,139,127,.44);
  --bear-dot: #C98B7F;
  --warn-text: #d0b386;
  --warn-tint: rgba(196,167,110,.15);
  --warn-edge: rgba(196,167,110,.42);
  --warn-dot: #c4a76e;
  --mixed-text: #c3a6e0;
  --mixed-tint: rgba(167,110,196,.18);
  --mixed-edge: rgba(167,110,196,.44);
  --mixed-dot: #a76ec4;
  --info-text: #a2b5de;
  --info-tint: rgba(110,147,196,.16);
  --info-edge: rgba(110,147,196,.42);
  --info-dot: #6e93c4;
  --risk-text: #d9ac98;
  --risk-tint: rgba(196,142,110,.16);
  --risk-edge: rgba(196,142,110,.42);
  --risk-dot: #c48e6e;
  --new-text: #7acab9;
  --new-tint: rgba(110,196,179,.16);
  --new-edge: rgba(110,196,179,.42);
  --new-dot: #6ec4b3;
  --candle-up: #94B0DA;
  --candle-down: #C98B7F;
  --chart-grid: rgba(62,74,74,.35);
  --chart-rate1: #6E90C4;
  --chart-rate2: #cf916e;
  --bull-dot-rgb: 148,176,218;
  --bear-dot-rgb: 201,139,127;
  --live-rgb: 201,139,127;
  --cat-1: #7398c9;
  --cat-2: #73c97f;
  --cat-3: #c9b273;
  --cat-4: #ac73c9;
  --cat-5: #c97673;
  --cat-6: #73b8c9;
  --cat-7: #c9739e;
  --cat-8: #afc973;
  --cat-9: #73c9b8;
  --cat-10: #c973c9;
}

/* Honour the OS preference when the reader has made no explicit choice. Scoped
   to :root:not([data-theme]) so it can never fight an attribute that IS set. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --app-bg: #F1F6FE;
    --surface: #FFFFFF;
    --surface-raised: #FFFFFF;
    --surface-sunken: #f9fcff;
    --surface-row-active: #DCEDFF;
    --surface-kpi: #eef6ff;
    --hairline-rgb: 203,220,243;
    --frame-border: rgba(203,220,243,.55);
    --header-grad: linear-gradient(var(--surface-raised),var(--surface));
    --header-rule: 1px solid rgba(203,220,243,.55);
    --pinstripe: repeating-linear-gradient(90deg,rgba(203,220,243,.28) 0 1px,transparent 1px 7px);
    --tooltip-shadow: 0 12px 30px -18px rgba(0,0,0,.30);
    --shadow-1: 0 6px 18px -12px rgba(0,0,0,.28);
    --shadow-2: 0 12px 30px -18px rgba(0,0,0,.30);
    --modal-shadow: 0 30px 80px -40px rgba(0,0,0,.35);
    --drawer-shadow: -30px 0 80px -40px rgba(0,0,0,.35);
    --scrim: rgba(20,28,40,.34);
    --text: #343F3E;
    --text-2: #505A5B;
    --text-muted: #505A5B;
    --text-faint: #5d6c76;
    --colhead: #5d6c76;
    --accent: #4C74AE;
    --on-accent: #FFFFFF;
    --accent-edge: rgba(76,116,174,.42);
    --diff-hi: rgba(76,116,174,.18);
    --cell-hi: rgba(76,116,174,.16);
    --seg-empty: rgba(203,220,243,.45);
    --bull-text: #316184;
    --bull-tint: rgba(62,110,158,.15);
    --bull-edge: rgba(62,110,158,.4);
    --bull-dot: #3E6E9E;
    --bear-text: #633f36;
    --bear-tint: rgba(176,115,106,.17);
    --bear-edge: rgba(176,115,106,.44);
    --bear-dot: #B0736A;
    --warn-text: #79591e;
    --warn-tint: rgba(163,126,51,.15);
    --warn-edge: rgba(163,126,51,.42);
    --warn-dot: #a37e33;
    --mixed-text: #7e33a3;
    --mixed-tint: rgba(126,51,163,.18);
    --mixed-edge: rgba(126,51,163,.44);
    --mixed-dot: #7e33a3;
    --info-text: #2b5c93;
    --info-tint: rgba(51,100,163,.16);
    --info-edge: rgba(51,100,163,.42);
    --info-dot: #3364a3;
    --risk-text: #854d24;
    --risk-tint: rgba(163,92,51,.16);
    --risk-edge: rgba(163,92,51,.42);
    --risk-dot: #a35c33;
    --new-text: #1a6b56;
    --new-tint: rgba(49,155,134,.16);
    --new-edge: rgba(49,155,134,.42);
    --new-dot: #319b86;
    --candle-up: #3E6E9E;
    --candle-down: #B0736A;
    --chart-grid: rgba(203,220,243,.35);
    --chart-rate1: #94B0DA;
    --chart-rate2: #a15d36;
    --bull-dot-rgb: 62,110,158;
    --bear-dot-rgb: 176,115,106;
    --live-rgb: 176,115,106;
    --cat-1: #3364a3;
    --cat-2: #30993e;
    --cat-3: #a18433;
    --cat-4: #7e33a3;
    --cat-5: #a33733;
    --cat-6: #338da3;
    --cat-7: #a3336b;
    --cat-8: #74912e;
    --cat-9: #2f9581;
    --cat-10: #a333a3;
  }
}

/* ── The palette switcher's swatch previews ───────────────────────────────────
   Each swatch must show a palette OTHER than the active one, so it cannot read
   var(--app-bg) — that resolves to whichever palette is live. These are the four
   palettes' own ground and accent, and they vary by MODE only, which is why they
   are declared once per mode rather than eight times.
   The GROUND is previewed rather than the card: this design's cards are white or
   near-white in all four light palettes, so a card-based swatch gave four chips
   nobody could tell apart. Keep these in step with the palette blocks above — a
   preview that has drifted is worse than no preview. */
:root {
  --sw-slate-bg: #1B2224; --sw-slate-fg: #94B0DA;
  --sw-warm-bg:  #1D201C; --sw-warm-fg:  #B8BDB5;
  --sw-teal-bg:  #0C1D1F; --sw-teal-fg:  #12A8B8;
  --sw-editorial-bg: #0B1120; --sw-editorial-fg: #35A5FF;
}
:root[data-theme="light"] {
  --sw-slate-bg: #F1F6FE; --sw-slate-fg: #4C74AE;
  --sw-warm-bg:  #E9EBE3; --sw-warm-fg:  #4F6564;
  --sw-teal-bg:  #F3F7EF; --sw-teal-fg:  #028090;
  --sw-editorial-bg: #F8FAFC; --sw-editorial-fg: #0066CC;
}

/* ── 4. LEGACY ALIASES — declared ONCE; they follow whichever palette won ──── */
/* --line / --line2 carry a much higher alpha than they used to. The palette this
   replaces drew hairlines as a CONTRASTING triplet at .12 (light lines on a dark
   ground); this design ships a solid line colour meant to be used near full
   strength, so the old alphas rendered it invisible — 1.04:1 against the card. */
:root {
  --bg:     var(--surface);
  --bg2:    var(--surface-raised);
  --panel:  var(--surface);
  --panel2: var(--surface-row-active);
  --line:   rgba(var(--hairline-rgb), .55);
  --line2:  rgba(var(--hairline-rgb), .80);
  --txt:    var(--text);
  --muted:  var(--text-muted);
  --faint:  var(--text-faint);
  --grn: var(--bull-text); --grn-dim: var(--bull-dot); --grn-soft-fg: var(--bull-text); --grn-bg: var(--bull-tint);
  --red: var(--bear-text); --red-dim: var(--bear-dot); --red-soft-fg: var(--bear-text); --red-bg: var(--bear-tint);
  --amber: var(--warn-text); --amber-dim: var(--warn-dot);
  --vio: var(--mixed-text); --vio-dim: var(--mixed-dot);
  --accent-dim: var(--diff-hi);
  /* Banner = info (amber/warn family); Warn = alert (bear/red family). */
  --banner-bg: var(--warn-tint); --banner-border: var(--warn-edge); --banner-fg: var(--warn-text);
  --warn-bg:   var(--bear-tint); --warn-border:   var(--bear-edge); --warn-fg:   var(--bear-text);
  --login-grad: var(--surface-raised);
  --frame-shadow: var(--shadow-2);
}


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

/* A view being switched TO. selectView writes `hidden` on every section, so an
   incoming view is just a section losing that attribute -- enough to trigger an
   animation with no JS at all. Gated on data-revealed="1", which the staged
   reveal sets once a view has had its first entrance: on first paint the reveal
   owns the sequence, and running both would fade the container while its own
   children were still staggering inside it. */
/* `backwards`, NOT `both`. With `both` the view keeps the animation's final
   keyframe applied for ever, and a keyframed `transform: none` computes to the
   identity matrix rather than releasing the property. A non-`none` transform --
   even the identity -- makes the element a containing block for every
   `position: fixed` descendant, so the pair drawer's `top: 0; bottom: 0` resolved
   against the whole scrolling view instead of the viewport: open it from a
   section near the foot of the page and it appeared a screen and a half ABOVE the
   fold, stretched to the full height of the document. `backwards` still applies
   the first keyframe before the animation starts, so the entrance is unchanged;
   it just lets go afterwards. This is view-wide on purpose -- every page's
   drawers and modals live inside a `.view` and had the same latent bug. */
.view[data-revealed="1"]:not([hidden]) {
  animation: g10-view-in var(--dur-base) var(--ease-out) backwards;
}
@keyframes g10-view-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .view[data-revealed="1"]:not([hidden]) {
    animation: g10-view-fade var(--dur-fast) linear backwards;
  }
  @keyframes g10-view-fade { from { opacity: 0; } to { opacity: 1; } }
}
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0;
  background: var(--app-bg);          /* warm-grey canvas behind the card frame */
  color: var(--txt);
  font: 14px/1.6 var(--font-mono);
  /* AFTER the shorthand on purpose -- `font:` resets font-variant-numeric to normal, so
     declaring it before this line would be silently undone. See the [class][class] rule
     below for the other half. */
  font-variant-numeric: tabular-nums;
  /* Inter at these sizes is noticeably heavy without smoothing on both engines; the
     Firefox/macOS half was missing, so the same text rendered darker there. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* Tabular figures, for real. The :root and body declarations above cover everything that
   inherits; this covers everything that does NOT, because its own rule sets type with the
   `font:` shorthand and so resets the feature. (0,2,0) beats the single-class rules that
   do that, in any stylesheet, in any load order. */
[class][class] { font-variant-numeric: tabular-nums; }

button { font: inherit; cursor: pointer; }
/* Form controls do not inherit type from the document -- they take a UA default, which is
   how a select on Standing and one hidden input were still rendering in Arial while every
   other glyph on the page was not. FAMILY only, deliberately: `font: inherit` would pull
   the size across too and move the boxes, and this pass is not allowed to change layout.
   `option` is listed because the native popup list is a separate rendering surface. */
input, select, textarea, optgroup, option { font-family: inherit; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.mono  { font-family: var(--font-sans); font-size: 12px; }

/* ── Login / landing masthead ────────────────────────────────────────────── */
/* Full-bleed pinstripe canvas (same warm-grey / navy as the app gutters); the
   hero content floats centred with no card frame (design landing). */
.login {
  position: fixed; inset: 0; overflow: auto;
  display: grid; place-items: center;
  background: var(--app-bg); padding: 40px 20px;
}
.login::before {
  content: ""; position: fixed; inset: 0; z-index: 0;
  background-image: var(--pinstripe); pointer-events: none;
}
.login-hero { position: relative; z-index: 1; width: 400px; max-width: 100%; text-align: center; }

/* Pre-login theme toggle — borderless ☾/☀, pinned top-right of the canvas. */
.login-theme-switch { position: fixed; top: 16px; right: 20px; z-index: 3; }

/* Masthead wordmark. The wide POSITIVE tracking is deliberate and survives the move to
   one family: this is a logotype, not running text, and its letterspacing is what makes
   it read as a mark. It is the one place on the page where large type carries positive
   tracking. */
.login-brand {
  font: 600 30px/1 var(--font-display); letter-spacing: .22em;
  color: var(--text); margin-left: .22em;   /* optical-centre the tracked caps */
}
.login-sub {
  margin-top: 9px; font: 600 10px/1 var(--font-mono); letter-spacing: .34em;
  text-transform: uppercase; color: var(--colhead);
}
.login-tagline {
  margin: 20px auto 0; max-width: 360px;
  font: 400 13px/1.55 var(--font-sans); color: var(--text-muted);
}

/* Feature grid — 4 hairline-bordered cells (KPI-strip aesthetic). */
.login-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  margin: 22px 0 0; background: rgba(var(--hairline-rgb), .18);
  border: 1px solid rgba(var(--hairline-rgb), .55);
}
.login-feat { background: var(--surface); padding: 11px 8px; }
.login-feat-l { font: 600 11.5px/1.2 var(--font-sans); color: var(--text); }
.login-feat-s { margin-top: 4px; font: 400 9px/1.3 var(--font-sans); color: var(--text-muted); }

/* Sign-in — navy cosmetic button with the real (transparent) GIS button on top
   receiving the clicks. */
.login-google { position: relative; width: 100%; height: 46px; margin: 22px 0 0; }
.login-google-btn {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  gap: 10px; background: var(--accent); color: var(--on-accent);
  border: 0; border-radius: var(--r-sm); pointer-events: none;
  font: 600 13px/1 var(--font-sans); letter-spacing: .01em;
}
.login-google-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--on-accent); color: var(--accent); font: 700 11px/1 var(--font-display);
}
.login-google-gis { position: absolute; inset: 0; opacity: 0; z-index: 2; }
.login-google-gis > div, .login-google-gis iframe { width: 100% !important; }

.login-foot { margin: 14px 0 0; font: 11px/1.5 var(--font-sans); color: var(--text-faint); }
.login-error { color: var(--red); margin: 12px 0 0; font-size: 13px; }

/* ── Shell ─────────────────────────────────────────────────────────────────── */
/* Widened 1100 → 1520 → 1800 so both tables read like a wide institutional
   scoreboard: currency rows (Last Changed + What Changed columns) and the
   pairs view get a generous Summary; the +3-card currencies sidebar still
   leaves the list column wide on a 1920 screen (1800 + 48 pad = 1848). */
/* The whole terminal is a bordered card floating on the warm-grey canvas
   (matches the design frame: 1px hairline + soft shadow, square corners). The
   header is full-bleed inside it via a negative inline margin. */
/* Content is centred at a comfortable max-width (no ultra-wide stretch); the
   page background is the surface colour so there are no empty margins around it. */
#app {
  max-width: 1800px; margin: 0 auto; padding: 0 22px 40px;
  background: var(--surface);
  border: 1px solid var(--frame-border); box-shadow: var(--frame-shadow);
  min-height: 100vh;
}

.topbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 18px;
  height: 50px; margin: 0 -22px; padding: 0 22px;
  background: var(--header-grad);
  border-bottom: var(--header-rule);     /* dark: 1px hairline · light: 3px double broadsheet rule */
}
/* Header pinstripe overlay (subtle vertical hairlines every 7px) sits behind
   the header content. */
.topbar::before {
  content: ""; position: absolute; inset: 0;
  background-image: var(--pinstripe);
  pointer-events: none; z-index: 0;
}
.topbar > * { position: relative; z-index: 1; }

/* Wordmark; "Thesis Evolution" is the muted subtitle beside it. */
.brand {
  font: 600 14px/1 var(--font-display); letter-spacing: .16em;
  color: var(--text); white-space: nowrap;
}
/* "Thesis Evolution" subtitle — a separate header child (design spacing via the
   topbar's gap:18px), plain colhead-grey sans (no serif, no leading bullet);
   --colhead (#8e99b0) byte-matches the design subtitle. */
.brand-sub {
  font: 400 12px/1 var(--font-sans); letter-spacing: normal; color: var(--colhead);
  white-space: nowrap;
}

/* Nav — sits LEFT, right after the wordmark + subtitle (design header);
   underline-on-active (no pills). The ☾/Log-out group is pushed right by
   .theme-toggle's margin-left:auto below. */
.tabs  { display: flex; gap: 20px; margin-left: 14px; align-items: center; }
.tab {
  background: transparent; border: 0;
  border-bottom: 2px solid transparent; border-radius: 0;   /* underline tab: the 2px bottom rule IS the control, nothing to round */
  color: var(--text-muted); padding: 5px 1px;
  font: 500 12.5px/1 var(--font-sans);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.tab.active { color: var(--text); border-bottom-color: var(--accent); }
.tab:hover:not(.active) { color: var(--text); }

/* ── Grouped nav (dropdowns) ─────────────────────────────────────────────────
   A `.navgroup` bundles related tabs behind a trigger that matches .tab
   typography. The menu opens on HOVER (desktop) or on click/Enter (touch +
   keyboard, via js/nav.js). js/nav.js hides a group whose child tabs are all
   ungranted and mirrors the active child's underline onto the trigger.
   On mobile the groups FLATTEN (display:contents) back into the single
   scrollable tab strip, so touch users keep today's flat nav. */
.navgroup { position: relative; display: inline-flex; align-items: center; }
.navgroup[hidden] { display: none; }
.navgroup-btn {
  background: transparent; border: 0;
  border-bottom: 2px solid transparent; border-radius: 0;   /* underline tab, as .tab above */
  color: var(--text-muted); padding: 5px 1px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
  font: 500 12.5px/1 var(--font-sans);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.navgroup-btn:hover, .navgroup:hover .navgroup-btn { color: var(--text); }
.navgroup-btn.active { color: var(--text); border-bottom-color: var(--accent); }
.navgroup-caret { font-size: 9px; line-height: 1; opacity: .65; }

.navgroup-menu {
  position: absolute; top: 100%; left: -8px; z-index: 50;
  display: none; flex-direction: column; min-width: 176px;
  padding: 6px; margin-top: 7px; gap: 2px;
  background: var(--surface-raised); border: 1px solid rgba(var(--hairline-rgb), .80);
  border-radius: var(--r-md); box-shadow: var(--shadow-2);
}
/* Invisible hover bridge across the trigger→menu gap so the menu doesn't close
   when the cursor crosses the 7px margin. */
.navgroup-menu::before {
  content: ""; position: absolute; top: -9px; left: 0; right: 0; height: 9px;
}
.navgroup:hover .navgroup-menu, .navgroup.open .navgroup-menu { display: flex; }
.navgroup-menu .tab {
  border-bottom: 0; padding: 7px 10px; text-align: left; white-space: nowrap;
  border-radius: var(--r-sm);   /* inset 6px inside the --r-md menu, so it steps down a rung */
}
.navgroup-menu .tab:hover:not(.active) {
  color: var(--text); background: var(--surface-sunken);
}
.navgroup-menu .tab.active {
  color: var(--text); border-bottom: 0; background: rgba(var(--hairline-rgb), .18);
}
.navgroup-menu .tab[hidden] { display: none; }

.ghost {
  background: transparent; border: 1px solid rgba(var(--hairline-rgb), .80);
  color: var(--text-muted); border-radius: var(--r-sm); padding: 5px 11px;
  font: 500 12px/1 var(--font-sans);
  transition: color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}
.ghost:hover { color: var(--text); border-color: rgba(var(--hairline-rgb), 1); }

/* ☾ + Log-out group — borderless plain-text spans, pushed to the far right,
   14px apart (design header). */
.topbar-actions {
  margin-left: auto; display: flex; align-items: center; gap: 14px;
}
/* ── Palette switcher ─────────────────────────────────────────────────────────
   Three swatches showing each palette's own surface + accent, then the existing
   sun/moon. The active ring is drawn on the GROUP, not on each swatch, so it can
   slide between them (a ring that disappears and reappears reads as two events).
   Sized to the header's existing 12px/1 density — no row-height change. */
.theme-switch {
  position: relative; display: inline-flex; align-items: center; gap: 6px;
  padding: 3px; border-radius: var(--r-pill);
  border: 1px solid rgba(var(--hairline-rgb), .55);
}
.theme-switch::before {
  /* the sliding active ring; --pal-i is set by app.js (0|1|2) */
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  box-shadow: 0 0 0 1.5px var(--accent);
  transform: translateX(calc(var(--pal-i, 0) * 22px));
  transition: transform var(--dur-fast) var(--ease-inout);
  pointer-events: none;
}
.pal-swatch {
  background: transparent; border: 0; padding: 0; cursor: pointer;
  width: 16px; height: 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
}
.pal-swatch-i {
  width: 14px; height: 14px; border-radius: 50%;
  border: 1px solid rgba(var(--hairline-rgb), .80);
  /* half the palette's surface, half its accent — the swatch IS the palette */
  transition: border-color var(--dur-micro) var(--ease-out);
}
.pal-swatch:hover .pal-swatch-i { border-color: rgba(var(--hairline-rgb), .44); }
.pal-swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Each swatch previews ITS palette, not the active one, so the choice is legible
   before it is made. Values are the palettes' own --surface / --accent. */
.pal-swatch-i {
  background: linear-gradient(135deg,
              var(--sw-surface) 0 50%, var(--sw-accent) 50% 100%);
}
[data-palette-set="slate"] .pal-swatch-i { --sw-surface: var(--sw-slate-bg); --sw-accent: var(--sw-slate-fg); }
[data-palette-set="warm"]  .pal-swatch-i { --sw-surface: var(--sw-warm-bg);  --sw-accent: var(--sw-warm-fg); }
[data-palette-set="teal"]  .pal-swatch-i { --sw-surface: var(--sw-teal-bg);  --sw-accent: var(--sw-teal-fg); }
[data-palette-set="editorial"] .pal-swatch-i { --sw-surface: var(--sw-editorial-bg); --sw-accent: var(--sw-editorial-fg); }

/* Screen-reader-only label for each swatch (the visual is the colour itself). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* A palette swap must be INSTANT. A 200ms colour interpolation across a whole
   terminal reads as a fault, and every frame in between belongs to neither
   palette. app.js sets this attribute for exactly one frame around the swap,
   which also stops in-flight hover/tint transitions from finishing in the wrong
   palette. */
:root[data-theme-switching] *,
:root[data-theme-switching] *::before,
:root[data-theme-switching] *::after {
  transition: none !important;
  animation-duration: var(--dur-instant) !important;
}

/* Theme toggle — icon-only, borderless; swaps glyph via ::before per theme. */
.theme-toggle {
  background: transparent; border: 0; border-radius: var(--r-sm); padding: 0;
  display: inline-flex; align-items: center; cursor: pointer;
  font: 12px/1 var(--font-sans); color: var(--colhead);
  transition: color var(--dur-micro) var(--ease-out);
}
.theme-toggle:hover { color: var(--text); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle .theme-toggle-i {
  display: inline-block;
  transition: opacity var(--dur-fast) var(--ease-out);
}
/* Log out — borderless plain sans text, design colour. */
.logout-btn {
  background: transparent; border: 0; border-radius: var(--r-sm); padding: 0;
  cursor: pointer; font: 12px/1 var(--font-sans); color: var(--colhead);
  transition: color var(--dur-micro) var(--ease-out);
}
.logout-btn:hover { color: var(--text); }
/* Show moon in dark mode (click → go light); sun in light mode (click → go dark). */
:root[data-theme="light"] .theme-toggle .theme-toggle-i::before { content: "☀"; }
:root[data-theme="dark"]  .theme-toggle .theme-toggle-i::before,
:root:not([data-theme]) .theme-toggle .theme-toggle-i::before  { content: "☾"; }

.banner {
  background: var(--banner-bg); border: 1px solid var(--banner-border); color: var(--banner-fg);
  padding: 9px 36px 9px 14px; border-radius: var(--r-md); margin: 16px 0 0;
  font-size: 12.5px; position: relative;
}
.banner-x {
  position: absolute; right: 10px; top: 7px; background: none; border: 0;
  color: var(--banner-fg); font-size: 16px; line-height: 1;
}
.warnings {
  background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-fg);
  padding: 10px 14px; border-radius: var(--r-md); margin: 8px 0;
  font-size: 12.5px; white-space: pre-wrap;
}

/* ── Generic row / accordion ───────────────────────────────────────────────── */
/* Rows are hairline-divided lines inside one table frame (NOT separate cards) —
   the compact ledger look from the design. Square corners; the divider is the
   only border. */
.row {
  background: transparent; border: 0;
  border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
  border-radius: 0;   /* full-bleed ledger row: its bottom hairline is the only edge */ margin: 0; overflow: hidden;
}
.row:last-child { border-bottom: 0; }
.row-head {
  display: flex; align-items: center; gap: 12px;
  min-height: 40px; padding: 0 12px; cursor: pointer; flex-wrap: nowrap;
}
.row-head:hover { background: var(--surface-row-active); }
.row.open .row-head {
  background: var(--surface-row-active);
  border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
}

/* Fixed-width columns so every row aligns regardless of content length */
.code {
  font-weight: 500; font-family: var(--font-sans); font-size: 13px; color: var(--text);
  flex: 0 0 72px;   /* fits "GBP/USD" (pairs) and "NZD" (currencies) */
}
.name { flex: 0 0 154px; color: var(--text-muted); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* "New Zealand Dollar" */

/* Bias/direction chip — widest is "strong bearish" (~95px text + 20px padding) */
.row-head .chip  { flex: 0 0 118px; text-align: center; }
/* Confidence / conviction — widest is "MEDIUM-HIGH" */
.row-head .conf  { flex: 0 0 94px; }
/* Policy rate — widest is "4.35%" */
.row-head .rate  { flex: 0 0 50px; }
/* Last bias/confidence change — absolute "YYYY-MM-DD HH:MMZ" form
   (currencies + pairs share the same width). */
.row-head .changed {
  flex: 0 0 130px; font-family: var(--font-sans); font-size: 11px; color: var(--muted);
}
.row-head .changed.none { color: var(--faint); }
/* Which field moved at that change — "bias" / "confidence" / "bias/confidence"
   for currencies; pairs widen this in #view-pairs scope below to fit the
   joined "direction · conviction" / "direction · persistence" forms. */
.row-head .whatchanged {
  flex: 0 0 116px; font-size: 12px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-head .whatchanged.none { color: var(--faint); }
#view-pairs .row-head .whatchanged { flex: 0 0 156px; }
/* Forward durability of the current bias/direction (V3_09 §4.11 /
   V3_06 §4.3b) — a separate column from confidence (present strength). */
.row-head .persist {
  flex: 0 0 134px; font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.row-head .persist.none { color: var(--faint); }
/* In book / dropped badge */
.row-head .badge { flex: 0 0 74px; text-align: center; }

/* Two-line preview (line-clamp) — much more readable than 1-line + "..." */
.summary {
  flex: 1; color: var(--text-muted); font-size: 11.5px; line-height: 1.45;
  overflow: hidden; display: -webkit-box;
  -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  min-width: 0;
}
.caret { color: var(--accent); transition: transform var(--dur-fast) var(--ease-out); flex: 0 0 auto; margin-left: 2px; font-size: 11px; }
.row.open .caret { transform: rotate(90deg); }

/* Currency-list column header. Padding = .row border (1px) + .row-head
   padding-left (18px) so each label sits exactly over its column's values;
   widths mirror the .code/.name/.chip/.conf/.rate/.changed/.whatchanged/
   .summary flex-basis above. */
.cur-colhead {
  display: flex; align-items: center; gap: 12px;
  height: 32px; padding: 0 12px; margin: 0;
  background: var(--surface-sunken);
  font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .09em;
  color: var(--colhead); border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
}
.cur-colhead > span { flex: 0 0 auto; }
.cur-colhead .h-code { flex: 0 0 72px; }
.cur-colhead .h-name { flex: 0 0 154px; }
.cur-colhead .h-bias { flex: 0 0 118px; text-align: center; }
.cur-colhead .h-conf { flex: 0 0 94px; }
.cur-colhead .h-rate { flex: 0 0 50px; }
.cur-colhead .h-changed { flex: 0 0 130px; }
.cur-colhead .h-whatchanged { flex: 0 0 116px; }
.cur-colhead .h-persist { flex: 0 0 134px; }
.cur-colhead .h-sum  { flex: 1; min-width: 0; }
.cur-colhead .h-caret { flex: 0 0 auto; width: 12px; margin-left: 2px; }

/* ── Column-header tooltips (design gm-tip) — BIAS / CONFIDENCE / PERSISTENCE ── */
.cur-colhead .gm-tip {
  position: relative; display: inline-flex; align-items: center; gap: 5px; cursor: help;
}
.gm-tip .gm-tip-i {
  font: 8px/1 var(--font-sans); color: var(--text-faint); text-transform: none;
  border: 1px solid rgba(var(--hairline-rgb), .4); border-radius: 50%;
  width: 12px; height: 12px; display: inline-flex; align-items: center; justify-content: center;
}
.gm-tipbox {
  position: absolute; z-index: 60; top: 100%; left: 0; width: 252px; margin-top: 4px;
  opacity: 0; visibility: hidden; transform: translateY(4px);
  /* 4px rise, with a delayed open and a delayed close so crossing between two
     adjacent triggers cannot strobe. `visibility` is named because it HOLDS its
     old value for the duration -- that hold is what keeps the box painted while
     it fades out. */
  transition: opacity var(--dur-micro) var(--ease-out) var(--delay-pop-close),
              visibility var(--dur-micro) var(--ease-out) var(--delay-pop-close),
              transform var(--dur-micro) var(--ease-out) var(--delay-pop-close);
  background: var(--surface); border: 1px solid rgba(var(--hairline-rgb), .80);
  box-shadow: var(--tooltip-shadow); padding: 12px 13px;
  text-transform: none; letter-spacing: normal;
}
.gm-tip:hover .gm-tipbox, .gm-tip:focus-within .gm-tipbox {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity var(--dur-micro) var(--ease-out) var(--delay-pop-open),
              visibility var(--dur-micro) var(--ease-out) var(--delay-pop-open),
              transform var(--dur-micro) var(--ease-out) var(--delay-pop-open);
}
.gm-tip-t     { display: block; font: 600 11px/1.2 var(--font-display); color: var(--text); margin-bottom: 6px; }
.gm-tip-intro { display: block; font: 10.5px/1.5 var(--font-sans); color: var(--text-muted); margin-bottom: 10px; }
.gm-tip-row   { display: flex; gap: 9px; margin-bottom: 6px; }
.gm-tip-rl    { font: 600 10px/1.4 var(--font-sans); width: 64px; flex: none; }
.gm-tip-rd    { font: 10px/1.4 var(--font-sans); color: var(--text-muted); }
.gm-tip-foot  {
  display: block; font: 9.5px/1.45 var(--font-sans); color: var(--text-faint);
  margin-top: 7px; padding-top: 8px; border-top: 1px solid rgba(var(--hairline-rgb), .80);
}

/* Pairs-list column header — rendered ONCE per .group-h conviction-tier
   band so the labels sit directly above the rows they describe (a reader
   scanning a tier never has to glance back to the top of the list). Same
   19px left pad as .cur-colhead (1px .row border + 18px .row-head
   padding-left) so labels sit over their values; widths mirror the pair
   .code/.chip/.conf/.badge/.persist/.summary flex-basis above. */
.pair-colhead {
  display: flex; align-items: center; gap: 12px;
  height: 30px; padding: 0 12px; margin: 0;
  background: var(--surface-sunken);
  font: 600 9px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .08em;
  color: var(--colhead); border-bottom: 1px solid rgba(var(--hairline-rgb), .80);
}
.pair-colhead > span { flex: 0 0 auto; }
.pair-colhead .h-pair    { flex: 0 0 72px; }
.pair-colhead .h-dir     { flex: 0 0 118px; text-align: center; }
.pair-colhead .h-conv    { flex: 0 0 94px; }
.pair-colhead .h-changed { flex: 0 0 130px; }
.pair-colhead .h-whatchanged { flex: 0 0 156px; }
.pair-colhead .h-persist { flex: 0 0 134px; }
.pair-colhead .h-reinf   { flex: 0 0 224px; }
.pair-colhead .h-sum     { flex: 1; min-width: 0; }
.pair-colhead .h-caret   { flex: 0 0 auto; width: 12px; margin-left: 2px; }

.row-body {
  padding: 18px 20px 22px; display: none;
  background: var(--surface-raised);
  border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
}
.row.open .row-body {
  display: block;
  /* Content entrance only -- the HEIGHT still snaps, deliberately. Easing it
     means grid-template-rows 0fr->1fr, which requires the collapsed body to stay
     in layout. Here that would put 35 pair expansions (one of them holding a
     chart that measures its own width at mount) through layout on every render
     instead of being display:none, and would expose collapsed content to screen
     readers, which display:none currently hides. The entrance already carries
     the causality; the height is not worth those three costs. */
  animation: g10-row-open var(--dur-slow) var(--ease-out) both;
}
@keyframes g10-row-open {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .row.open .row-body { animation: g10-row-fade var(--dur-fast) linear both; }
  @keyframes g10-row-fade { from { opacity: 0; } to { opacity: 1; } }
}
/* Two-column expansions (design currency 1.35fr / 1fr, pair 1.3fr / 1fr). */
.cur-exp-grid  { display: grid; grid-template-columns: 1.35fr 1fr; gap: 30px; }
.pair-exp-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 28px; }
.cur-exp-col   { min-width: 0; }
@media (max-width: 1100px) {
  .cur-exp-grid, .pair-exp-grid { grid-template-columns: 1fr; gap: 18px; }
}

/* Full directional-bias text above the breakdown — same text the row shows
   clipped; now readable in full without clicking into the breakdown */
.pair-bias-full {
  font-size: 14.5px; color: var(--txt); line-height: 1.7;
  margin: 10px 0 18px; padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

/* ── Chips ─────────────────────────────────────────────────────────────────── */
/* Square ~21px chip: semantic TEXT on a same-hue tint + same-hue border. */
.chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 21px; padding: 0 9px;
  font: 500 11px/1 var(--font-sans); white-space: nowrap;
  border-radius: var(--r-xs); border: 1px solid rgba(var(--hairline-rgb), .80);
  color: var(--text-2); flex-shrink: 0;
}
/* Bias maps to four semantic kinds: bullish→bull, bearish→bear, neutral→warn
   (range/neutral share the amber axis per the handoff), mixed→mixed. The
   slight_* variants ride the same hue as their full counterpart. */
.b-strong_bullish, .b-bullish, .b-slight_bullish, .dir-long, .badge.in {
  color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge);
}
.b-strong_bearish, .b-bearish, .b-slight_bearish, .dir-short, .badge.out {
  color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge);
}
.b-neutral, .dir-range {
  color: var(--warn-text); background: var(--warn-tint); border-color: var(--warn-edge);
}
.b-mixed {
  color: var(--mixed-text); background: var(--mixed-tint); border-color: var(--mixed-edge);
}

/* ── Market Drivers (V3_13) ─────────────────────────────────────────────────── */
.dir-watch { color: var(--text-2); background: rgba(var(--hairline-rgb), .22); border-color: rgba(var(--hairline-rgb), .80); }
.drv-head { margin: 4px 0 14px; }
.drv-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.drv-class { font: 600 13px/1 var(--font-sans); text-transform: capitalize; letter-spacing: .04em; color: var(--accent); }
.drv-driver { font: 500 18px/1.35 var(--font-sans); margin: 8px 0 4px; }
.drv-meta { font-size: 11px; }
.drv-plain-toggle { margin-top: 8px; font: 500 11px/1 var(--font-sans); padding: 5px 10px; border: 1px solid rgba(var(--hairline-rgb), .80); background: none; color: var(--text-2); cursor: pointer; }
.drv-plain-toggle:hover { border-color: rgba(var(--hairline-rgb), .45); }
.drv-conf-high { color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge); }
.drv-conf-medium { color: var(--warn-text); background: var(--warn-tint); border-color: var(--warn-edge); }
.drv-conf-low, .drv-conf-none { color: var(--text-2); background: var(--surface-sunken); }
.drv-hold { margin: 0 0 14px; padding: 9px 12px; border-left: 3px solid var(--warn-edge); background: var(--warn-tint); color: var(--warn-text); font: 500 12px/1.5 var(--font-sans); }
/* Data vintage strip — how old the feeds under this page are. Quiet by
   intent: it is a standing fact, not an alert, and an amber freshness line on
   every page every day is a line nobody reads by the second week. */
.vintage-strip {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px;
  margin: 0 0 12px; padding: 6px 0;
  border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
  font: 400 11.5px/1.4 var(--font-sans); color: var(--text-muted);
}
.vintage-lead { text-transform: uppercase; letter-spacing: .1em; font-size: 10px; }
.vintage-item { display: inline-flex; align-items: baseline; gap: 5px; cursor: help; }
.vintage-label { color: var(--text-muted); }
.vintage-val { color: var(--text-2); font-variant-numeric: tabular-nums; }
.vintage-item.is-missing .vintage-val { color: var(--warn-text); font-style: italic; }
@media (max-width: 520px) { .vintage-strip { gap: 2px 10px; font-size: 11px; } }

/* Explains the hold above rather than raising a second alarm — deliberately
   neutral, not amber, because the two surfaces disagreeing is expected. */
.drv-bridge {
  margin: -6px 0 14px; padding: 9px 12px;
  border-left: 3px solid rgba(var(--hairline-rgb), .80);
  color: var(--text-2); font: 400 12px/1.55 var(--font-sans);
}
.drv-card { margin: 0 0 14px; padding: 12px 14px; border: 1px solid rgba(var(--hairline-rgb), .55); }
.drv-card-h { font: 600 11px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); margin-bottom: 8px; }
.drv-card-b { font: 400 13px/1.55 var(--font-sans); }
.drv-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.drv-tk { padding: 10px 0; border-top: 1px solid rgba(var(--hairline-rgb), .55); }
.drv-tk:first-of-type { border-top: 0; }
.drv-tk-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.drv-tk-pair { font: 600 13px/1 var(--font-sans); letter-spacing: .02em; }
.drv-tk-rat { font: 400 12.5px/1.5 var(--font-sans); margin-top: 6px; }
.drv-tk-fals { font-size: 11.5px; margin-top: 4px; }
.drv-tk-note { font: 500 11.5px/1.45 var(--font-sans); margin-top: 4px; color: var(--warn-text); }
.drv-flag-conflict { color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge); }
.drv-flag-tension { color: var(--warn-text); background: var(--warn-tint); border-color: var(--warn-edge); }
.drv-gap { font-size: 11.5px; line-height: 1.5; }
.drv-tl-row { display: flex; gap: 10px; align-items: baseline; padding: 5px 0; border-top: 1px solid rgba(var(--hairline-rgb), .22); }
.drv-tl-row:first-of-type { border-top: 0; }
.drv-tl-date { flex: 0 0 92px; font-size: 11px; color: var(--text-2); }
.drv-tl-class { flex: 0 0 130px; font: 600 11.5px/1.4 var(--font-sans); text-transform: capitalize; color: var(--accent); }
.drv-tl-drv { font: 400 12px/1.4 var(--font-sans); }

/* Evidence panel (Phase 7) — the deterministic proof: correlation heatmap +
   σ-move / z-score tables + self-grade. All values are computed, not LLM-authored. */
.drv-ev-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 18px; align-items: start; }
.drv-ev-sub { font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); margin: 2px 0 8px; }
.drv-heat { border-collapse: collapse; }
.drv-heat th { font: 500 11px/1 var(--font-sans); color: var(--muted); padding: 5px 8px; text-align: center; font-weight: 500; }
.drv-heat td { padding: 9px 11px; text-align: center; min-width: 50px; font: 500 13px/1 var(--font-sans); border: 1px solid rgba(var(--hairline-rgb), .55); color: var(--text); }
.drv-heat td.rowh { text-align: right; color: var(--muted); border: 0; padding-right: 11px; min-width: 0; font-size: 11px; }
/* Correlation-heatmap legend — green/red swatch key + a plain-English how-to-read. */
.drv-heat-legend { margin-top: 13px; max-width: 48ch; }
.drv-heat-key { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 7px; }
.drv-heat-keyitem { display: inline-flex; align-items: center; gap: 6px; font: 500 11px/1 var(--font-sans); color: var(--text-2); }
.drv-heat-sw { width: 13px; height: 13px; display: inline-block; border: 1px solid rgba(var(--hairline-rgb), .80); }
/* Sampled from the SAME ramp _drvCorrColor draws (js/app.js): the triplet is
   the token, the alpha is the correlation magnitude. .55 is |r| ~= 0.61. A key
   that restates the colour instead of sampling it stops matching the map. */
.drv-heat-sw.pos { background: rgba(var(--bull-dot-rgb), .55); }
.drv-heat-sw.neg { background: rgba(var(--bear-dot-rgb), .55); }
.drv-heat-note { font: 400 11.5px/1.55 var(--font-sans); color: var(--muted); }
.drv-master { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.drv-proof { width: 100%; border-collapse: collapse; }
.drv-proof th { font: 600 9px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .05em; color: var(--text-2); text-align: right; padding: 2px 7px 6px; }
.drv-proof th:first-child { text-align: left; }
.drv-proof td { padding: 4px 7px; text-align: right; font: 500 11px/1.3 var(--font-sans); border-top: 1px solid rgba(var(--hairline-rgb), .22); color: var(--text); }
.drv-proof td:first-child { text-align: left; font-family: var(--font-sans); font-weight: 400; }
.drv-held { color: var(--bull-text); }
.drv-reverted { color: var(--muted); }
.drv-grade-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.drv-grade-correct { color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge); }
.drv-grade-wrong { color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge); }

/* Drivers — narrative-spine view (2026-06-24) */
.drv-controls { display: flex; align-items: center; justify-content: flex-end; margin: 2px 0 16px; }
.drv-controls .drv-plain-toggle { margin-top: 0; }

.drv-hero { margin: 0 0 16px; padding: 16px 18px; border: 1px solid rgba(var(--hairline-rgb), .18); border-left: 3px solid var(--accent); background: var(--surface-sunken); }
.drv-hero-tags { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.drv-hero-line { font: 500 22px/1.4 var(--font-sans); letter-spacing: -.01em; }
.drv-hero-meta { margin-top: 10px; font-size: 11.5px; text-transform: capitalize; }

.drv-section { margin: 0 0 18px; }
.drv-sec-h { font: 600 11px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .07em; color: var(--accent); margin-bottom: 9px; padding-bottom: 6px; border-bottom: 1px solid rgba(var(--hairline-rgb), .55); }
.drv-story { font: 400 14.5px/1.65 var(--font-sans); color: var(--text-2); }
.drv-gap-lead { font: 400 12px/1.55 var(--font-sans); color: var(--muted); margin-bottom: 8px; max-width: 76ch; }
.drv-proof-read { margin-bottom: 16px; }
.drv-keymoves { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 12px; }
.drv-keymoves-lab { font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .06em; margin-right: 2px; }
.drv-proof-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 28px; align-items: start; }
.drv-two-up { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 22px; margin-bottom: 18px; }
.drv-two-up .drv-section { margin-bottom: 0; }
.drv-more { margin-top: 6px; padding-top: 8px; border-top: 1px solid rgba(var(--hairline-rgb), .55); }
.drv-more .drv-sec-h { color: var(--text-2); }

.conf  { font-size: 10.5px; color: var(--text-2); text-transform: capitalize; letter-spacing: .03em; flex-shrink: 0; }
/* Bias-persistence indicator + label, both painted by the durability colour
   (anchored→accent, firm→muted, fragile→warn). Per the design the glyph differs
   by table: PAIRS use a 6px round dot (base rule), CURRENCIES use a 2px×16px
   vertical bar (scoped below). The renderer's glyph text is collapsed to
   font-size:0 so .pp-g reads purely as the shape. */
.persist { color: var(--text-muted); letter-spacing: 0; flex-shrink: 0; font-size: 11.5px; display: inline-flex; align-items: center; gap: 7px; }
.persist .pp-g {
  font-size: 0; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; display: inline-block; flex: 0 0 auto;
}
#view-currencies .persist .pp-g { width: 2px; height: 16px; border-radius: 0;   /* currencies use a 2x16 tick BAR, not a dot - a radius on a 2px-wide bar is invisible */ }
.pp-anchored, .pp-v.pp-anchored { color: var(--accent); }
.pp-firm,     .pp-v.pp-firm     { color: var(--text-muted); }
.pp-fragile,  .pp-v.pp-fragile  { color: var(--warn-text); }
.pp-v { font-weight: 500; }
/* Bias-persistence breakdown card: chip headline, one-line "flips if:"
   rationale, then the ≤5 "what keeps it here" durability bullets (§4.11
   drivers). Full-width block inside the fcard value column. */
.pp-card { width: 100%; display: flex; flex-direction: column; gap: 7px; }
.pp-rat  { font-size: 13px; color: var(--muted); line-height: 1.55; }
/* "Flips if:" / "Falsifier:" prefix rides in the gold warn accent per design
   (dark #d8b072 / light #876625 = --warn-text); the catalyst text stays muted. */
.pp-rat-lbl { color: var(--warn-text); font-weight: 600; }
.pp-grp  {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--faint); margin-top: 3px;
}
.pp-bul li { font-size: 13px; }
/* list / driver nodes used AS an fcard value must span the value column
   (the §4.12 stance_drivers card reuses the change_drivers .snode-bullets
   renderer; framework drivers use .fdrv which is already width:100%). */
.fv > .pp-card, .fv > .snode-bullets, .fv > .fdrv { flex: 1 1 100%; }
.rate  { font-family: var(--font-sans); font-size: 12.5px; color: var(--accent); flex-shrink: 0; text-align: right; }
.rate.stale { color: var(--warn-text); }
/* Book status — a small square lifecycle chip (in book = bull, dropped = bear). */
.badge {
  display: inline-flex; align-items: center; justify-content: center;
  height: 18px; padding: 0 8px;
  font: 600 9px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .05em;
  border-radius: var(--r-xs); border: 1px solid rgba(var(--hairline-rgb), .80);
  color: var(--text-faint); flex-shrink: 0;
}
.badge.in  { color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge); }
.badge.out { color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge); }
.src-producer { color: var(--bull-text); border-color: var(--bull-edge); }
.src-diff     { color: var(--accent); border-color: var(--accent-dim); }
.src-initial, .src-unchanged { color: var(--faint); }

/* ── Stance-changes list (collapsible, plain stacked — no timeline rail) ────── */
/* Rows sit flush (no gaps) — adjacent borders collapse so the history reads as
   one continuous list, per design. */
.chain { margin: 10px 0 0; display: flex; flex-direction: column; gap: 0; }
.chain .snode + .snode { border-top: none; }

.snode {
  border: 1px solid rgba(var(--hairline-rgb), .55); border-radius: 0;   /* stacked stance rows collapse their borders into one continuous list (see .chain above) - rounding each node would pinch every join */
  background: var(--surface); overflow: hidden;
}
.snode.open { border-color: var(--accent); }
.snode-h {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  cursor: pointer; flex-wrap: nowrap; min-width: 0;
}
.snode-h:hover { background: var(--surface-row-active); }
.snode.open > .snode-h { background: var(--surface-row-active); border-bottom: 1px solid rgba(var(--hairline-rgb), .55); }
.snode-h .caret { order: -1; }
.snode.open > .snode-h .caret { transform: rotate(90deg); }
.snode-date { font-family: var(--font-sans); font-size: 12px; color: var(--muted); flex: 0 0 auto; }
/* Fixed-width bias chip so every row's chip is the same length and the bias
   word reads centred down the column (user request — not in the handoff). */
.snode-h .chip { flex: 0 0 110px; justify-content: center; }
/* Fixed-width too, so confidence lines up down the column alongside the bias
   chip (longest value "MODERATE" fits 78px). */
.snode-h .conf { flex: 0 0 78px; text-transform: uppercase; letter-spacing: .05em; }
.snode-h .rate { flex: 0 0 auto; }
/* delta_source badge (diff/producer/initial) is internal pipeline metadata */
.snode-h .badge { display: none; }
/* one-line preview of what changed; hidden once expanded (the bullets in the
   body restate it more precisely) */
.snode-prev {
  flex: 1; color: var(--muted); font-size: 13px; line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.snode.open .snode-prev { display: none; }
/* "reinforced N× since DATE" badge — surfaced when the server collapsed
   adjacent same-signature regens into one row. */
.snode-reinforced {
  flex: 0 0 auto; margin-left: auto;
  font-family: var(--font-sans); font-size: 10px; color: var(--text-faint);
  background: none; border: 0; border-radius: 0;   /* bare text button: no fill, no border, no padding - nothing to round */ padding: 0;
  white-space: nowrap; cursor: help;
}
/* Collapsed pair-row "Reinforced" column — "N× Reinforcement since DATE"
   (date-only). Plain text matching the sibling meta columns; faint "—" when the
   stance has no reinforcement yet. Fixed width so it aligns under its header
   (.pair-colhead .h-reinf) instead of crowding Summary. The full badge + log
   live in the expanded pair timeline. */
.row-head .pair-reinf {
  flex: 0 0 224px; font-family: var(--font-sans); font-size: 10px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-head .pair-reinf.none { color: var(--faint); }
/* Earlier-reinforcements disclosure body (option 2 client-side grouping):
   each row is one prior regen's narrative with a tiny mono date prefix. */
.earlier-reinf-list { display: flex; flex-direction: column; gap: 8px; }
.earlier-reinf-item {
  display: flex; gap: 10px; padding: 6px 8px;
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-sm);
  font-size: 12.5px; line-height: 1.5; color: var(--txt);
}
.earlier-reinf-date {
  flex: 0 0 auto; font-family: var(--font-sans); font-size: 11px;
  color: var(--muted); white-space: nowrap;
}
.earlier-reinf-text { flex: 1; min-width: 0; }
.earlier-reinf-count {
  flex: 0 0 auto; font-family: var(--font-sans); font-size: 11px;
  color: var(--faint); white-space: nowrap; cursor: help; align-self: flex-start;
}
.snode-b { display: none; padding: 12px 14px 14px; }
.snode.open > .snode-b { display: block; }

/* Stance-change body: the delta catalyst box at the top, then a "what
   changed" group of computed transition bullets, then the long-form
   thesis narrative. */
.snode-grp {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--faint); margin: 14px 0 6px;
}
.snode-grp:first-child { margin-top: 0; }
.snode-bullets { list-style: none; margin: 0; padding: 0; }
.snode-bullets li {
  position: relative; padding-left: 16px; margin: 5px 0;
  font-size: 13.5px; line-height: 1.6; color: var(--txt);
}
.snode-bullets li::before {
  content: "–"; position: absolute; left: 2px; color: var(--faint);
}
/* transition bullet: "<label> <from> → <to>" */
.snode-bullets li.chg { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.chg-k {
  font-size: 10px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--muted); flex: 0 0 auto;
}
.chg-from { color: var(--faint); text-decoration: line-through; opacity: .8; }
.chg-to   { color: var(--txt); font-weight: 600; }
.chg-arrow { color: var(--faint); }
.snode-bullets li.chg-held { color: var(--muted); font-style: italic; }

/* Delta catalyst box (now top-of-row) + long-form narrative. */
.delta {
  margin: 6px 0 8px; padding: 10px 14px; border-left: 3px solid var(--line2);
  background: var(--bg2); border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 14px; line-height: 1.6;
}
.delta.producer { border-left-color: var(--grn); }
.delta.none     { border-left-color: var(--faint); color: var(--muted); }
.snode-long { font-size: 13.5px; color: var(--muted); margin: 8px 0 0; line-height: 1.65; }
.toggle-long {
  background: none; border: 0; color: var(--accent);
  font-size: 12.5px; padding: 0; margin-top: 4px;
}

/* "What drove this" / "What drives the stance" — {drove,text} bullets. The
   dimension tag trails the text and is ONE neutral colour (never the blue/
   amber it used to be) so the eye reads the text straight down and the tag
   never competes for attention. The li is a plain block list-item, so every
   bullet's text starts at the same left edge regardless of tag width. */
.snode-bullets li.drv { display: block; }
/* "what this impacts" pill (Bias / Conf / Direction / Conviction …) — matches
   the design's single accent tag: accent text, accent-tint fill + border, sharp.
   One style for every type (no per-type colour), uppercase, 9px. */
.drv-tag {
  display: inline-block; vertical-align: baseline;
  margin-left: 8px; white-space: nowrap;
  font: 9px var(--font-mono); text-transform: uppercase; letter-spacing: .05em;
  padding: 1px 6px; border-radius: var(--r-xs);
  color: var(--accent);
  background: var(--diff-hi);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--line2);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.drv-txt { color: var(--txt); }

/* ── Stance-row: calm, low-glare reading ──────────────────────────────────
   The expanded stance-change row read too bright (everything in --txt).
   Drop the whole body to --muted so it never dominates — the faint
   uppercase labels still carry the structure. Delta is plain text (no
   green/bg box), aligned to the bullet indent; "stance held" is not italic.
   (Pills are neutral + text-trailing globally, see the .drv-tag block.) */
.snode-b .snode-bullets li,
.snode-b .drv-txt,
.snode-b .chg-to { color: var(--muted); }
.snode-b .snode-bullets li.chg-held { color: var(--muted); font-style: normal; }
.snode-b .delta,
.snode-b .delta.producer,
.snode-b .delta.none {
  margin: 5px 0; padding: 0 0 0 16px;
  background: none; border: 0; border-radius: 0;   /* stripped back to bare indented prose - no fill, no border, nothing to round */
  font-size: 13.5px; line-height: 1.6; color: var(--muted);
}

/* the rationale disclosure body inside a stance node — tighten the default
   disc padding so the folded prose lines up with the bullets above it */
.snode-b .disc { margin-top: 10px; }
.snode-rat { margin-top: 2px; }

/* ── Currency expectation summary block ────────────────────────────────────── */
.expect {
  background: transparent; border: 0;
  border-left: 2px solid var(--accent); border-radius: 0;   /* transparent, and its only edge is the 2px left rule - a radius would draw nothing */
  padding: 0 0 0 14px; margin: 2px 0 18px;
}
.expect-h {
  font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; display: block;
  letter-spacing: .12em; color: var(--colhead); margin: 0 0 6px;
}
.expect-line {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  font: 600 15px/1.3 var(--font-display); color: var(--text);
}
.expect-line b { color: var(--text); font-weight: 600; }
.expect-drop {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--red); padding: 2px 7px; border: 1px solid var(--red);
  border-radius: var(--r-xs);
}
.expect-why  { font-size: 13px; color: var(--text-2); margin: 6px 0 0; line-height: 1.65; }
.expect-note { font-size: 12px; color: var(--text-faint); margin: 8px 0 0; font-style: italic; }
/* "What drives the stance" + "Bias persistence" — flat sections on the
   Expectation background (no cards). Heading on top (faint uppercase; the
   persistence chip rides inline keeping its own stability colour), bullets
   below, a hairline rule separating each section from what precedes it. */
.esec { margin-top: 16px; padding-top: 14px; border-top: 1px solid rgba(var(--hairline-rgb), .55); }
.esec-h {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .12em;
  color: var(--colhead); margin: 0 0 9px;
}
/* Persistence VALUE ("firm · 55–70%") — weight 500, soft off-white (--text-2). NOT
   pure white, and NOT the durability colour — that stays on the dot/bar only (overrides
   below). It used to be set in the mono face to mark it as a figure; that distinction is
   now carried by weight and colour alone. */
.esec-h .pp-v {
  text-transform: none; letter-spacing: 0;
  font-family: var(--font-sans); font-weight: 500; font-size: 12.5px;
  color: var(--text-2);
}
/* Colour the persistence GLYPH (the .pp-g dot-styling is scoped to the collapsed
   .persist row, so here .pp-g is the raw ● glyph — colour it, don't give it a
   background, which would render as a tinted box / "shadow" behind the glyph). */
/* Dot takes the persistence VALUE colour (user request) — reads as one unit
   "● firm · 70–85%" rather than a separate durability-coloured status light. */
.esec-h .pp-v .pp-g { color: inherit; }
/* Modal-cone calibration counter on the Scenarios header — the scorecard for the
   zones rendered beneath it. Deliberately quiet (muted, mono, lower-case): it is
   context on the block's own reliability, not a headline number. */
.esec-h .scn-calib {
  text-transform: none; letter-spacing: 0;
  font-family: var(--font-sans); font-weight: 500; font-size: 11px;
  color: var(--text-muted); margin-left: auto;
}
/* Panel body text (driver bullets + persistence durability bullets) reads at
   --text-muted (#9aa5bc), never the near-white --text. Labels stay --colhead
   (.esec-h), values stay mono/--text-2 above. */
.esec .snode-bullets li,
.esec .drv-txt { color: var(--text-muted); }
.esec-sub { font-size: 11px; color: var(--text-faint); margin-top: 7px; }
.esec .pp-rat { margin-top: 8px; }

/* Per-pair price chart (Lightweight Charts) inside the Expectation block.
   Fixed host height so the card doesn't jump when the chart lazily mounts
   on first expand. Tooltip is a sibling absolutely positioned to the host —
   chart canvas has no native marker hover, so we drive it ourselves off
   subscribeCrosshairMove (see app.js _mountPairChart). Granularity pills
   toggle the bar resolution (1D Supabase daily fallback, 4H/1H Massive). */
.esec-chart .ppc-heading {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; margin: 0 0 6px; flex-wrap: wrap;
}
.esec-chart .ppc-heading .esec-h { margin: 0; }
.esec-chart .ppc-cluster {
  display: flex; justify-content: flex-end; align-items: center;
  gap: 14px; flex-wrap: wrap; margin: 6px 0 8px;
}
.esec-chart .ppc-pills { display: inline-flex; gap: 4px; }
.esec-chart .ppc-pill {
  background: transparent; border: 1px solid var(--line);
  color: var(--muted); border-radius: var(--r-pill);
  padding: 2px 10px; font-size: 11px; font-family: var(--font-sans);
  line-height: 1.5; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.esec-chart .ppc-pill:hover:not(:disabled):not(.active) {
  border-color: var(--line2); color: var(--txt);
}
.esec-chart .ppc-pill.active {
  background: var(--panel2); color: var(--txt); border-color: var(--line2);
}
.esec-chart .ppc-pill:disabled {
  opacity: 0.5; cursor: not-allowed;
}
.esec-chart .ppc-host {
  position: relative;
  width: 100%;
  height: 420px;
  margin-top: 8px;
}
.esec-chart .ppc-empty {
  height: 420px;
  display: grid; place-items: center;
  color: var(--faint); font-size: 13px; text-align: center; padding: 0 16px;
  border: 1px dashed var(--line); border-radius: var(--r-md); margin-top: 8px;
}
.esec-chart .ppc-note {
  font-family: var(--font-sans); font-size: 11px; color: var(--faint);
}
/* Rate-overlay legend chips inside the chart note ("rates ▬EUR ▬USD"). */
.esec-chart .ppc-rate-key {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 2px;
}
.esec-chart .ppc-rate-dot {
  display: inline-block; width: 10px; height: 2px; border-radius: 0;   /* 10x2 hairline colour key - a radius on a 2px-tall bar is not visible */
}
.ppc-tip {
  position: absolute; top: 0; left: 0;
  display: none; pointer-events: none;
  background: var(--panel2); border: 1px solid var(--line2);
  border-radius: var(--r-md); padding: 7px 10px;
  font-size: 12px; line-height: 1.45; color: var(--txt);
  max-width: 260px; z-index: 4;
  box-shadow: var(--tooltip-shadow);
}
.ppc-tip-d { color: var(--muted); font-family: var(--font-sans); font-size: 11px; margin-bottom: 3px; }
.ppc-tip-line { white-space: nowrap; }
.ppc-tip-field { color: var(--muted); }
.ppc-tip .ppc-arrow { color: var(--faint); }
.ppc-tip-empty { color: var(--muted); font-style: italic; }

/* "How to read this chart" legend — lives inside a disc-b, so margins are
   already handled by the disclosure helper. Each row is a colored dot
   sample + a small description block. */
.esec-chart .disc { margin: 8px 0 10px; background: var(--panel2); }
.ppc-legend { display: flex; flex-direction: column; gap: 12px; }
.ppc-legend-row {
  display: grid; grid-template-columns: 18px 1fr; column-gap: 12px;
  align-items: start;
}
.ppc-legend-dot {
  width: 12px; height: 12px; border-radius: 50%;
  margin-top: 4px; align-self: start;
  /* hairline, not white: a white overlay lightens a LIGHT surface too, so it
     disappears in exactly the theme it was supposed to separate things in. */
  box-shadow: 0 0 0 1px rgba(var(--hairline-rgb), .22);
}
.ppc-legend-body { display: flex; flex-direction: column; gap: 3px; }
.ppc-legend-label { color: var(--txt); font-weight: 600; font-size: 13px; }
.ppc-legend-meaning { color: var(--muted); font-size: 12.5px; line-height: 1.55; }
.ppc-legend-ex {
  color: var(--faint); font-size: 12px; line-height: 1.55; font-style: italic;
}
.ppc-legend-foot {
  margin-top: 4px; padding-top: 10px; border-top: 1px dashed var(--line);
  color: var(--muted); font-size: 12px; line-height: 1.55;
}

/* "more detail" disclosure inside the Expectation block (the full thesis
   rationale moved here from the Expectation breakdown). */
.expect .disc { margin: 8px 0 0; background: var(--panel2); }
.expect-detail { font-size: 13.5px; line-height: 1.7; color: var(--muted); }
.expect-detail p { margin: 0; }

.expressed { margin: 0; }

/* ── Disclosure sections (book / Expectation "more detail") ────────────────── */
.disc {
  border: 1px solid rgba(var(--hairline-rgb), .55); border-radius: var(--r-md);
  margin: 8px 0; background: var(--surface);
}
.disc-h {
  display: flex; align-items: center; gap: 9px; padding: 9px 13px;
  cursor: pointer; font: 600 9.5px/1 var(--font-mono); text-transform: uppercase;
  letter-spacing: .12em; color: var(--colhead);
}
.disc-h:hover { color: var(--txt); }
.disc-h .caret { color: var(--faint); }
.disc.open > .disc-h { color: var(--txt); border-bottom: 1px solid var(--line); }
.disc.open > .disc-h .caret { transform: rotate(90deg); }
.disc-h .disc-t { flex: 1; }
.disc-h .cnt {
  color: var(--muted); font-family: var(--font-sans);
  text-transform: none; letter-spacing: 0; font-size: 12.5px;
}
.disc-b { display: none; padding: 10px 16px 14px; }
.disc.open > .disc-b { display: block; }
.disc-note {
  font-size: 12.5px; color: var(--text-2); background: var(--surface-raised);
  border-left: 2px solid rgba(var(--hairline-rgb), .80); border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 9px 13px; margin: 2px 0 12px; line-height: 1.6;
}
.disc-note b { color: var(--txt); font-weight: 600; }

/* ── Expectation breakdown ─────────────────────────────────────────────────── */
.brk { padding: 2px 0 4px; }
.brk-cur {
  display: flex; align-items: center; justify-content: flex-start; gap: 10px;
  padding: 4px 0 12px; border-bottom: 1px solid var(--line); margin-bottom: 12px;
}
.brk-code { font-family: var(--font-sans); font-weight: 700; font-size: 16px; color: var(--txt); }

/* ── Connected-card flow → 2-column property list ──────────────────────────── */

/* Single bordered container — replaces individual boxed cards with arrows */
.flow {
  display: flex; flex-direction: column;
  max-width: none;
  margin: 6px 0 12px;
  border: 1px solid rgba(var(--hairline-rgb), .55);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface);
}

/* Each property row: label | value stacked in right column */
.fcard {
  display: flex; flex-direction: row; align-items: start;
  padding: 11px 16px; gap: 0;
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--line);
  background: transparent;
}
.fcard:last-child { border-bottom: none; }
.fcard.acc-pos  { border-left-color: var(--grn); }
.fcard.acc-neg  { border-left-color: var(--red); }
.fcard.acc-warn { border-left-color: var(--amber); }

/* Left column: property label */
.fk {
  flex: 0 0 128px;
  font: 600 9.5px/1.4 var(--font-mono); text-transform: uppercase; letter-spacing: .12em;
  color: var(--colhead); padding-top: 3px; padding-right: 14px;
}

/* Right column wrapper (value + optional sub) */
.fright {
  flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0;
}

/* Property value */
.fv {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 14px; color: var(--txt); min-width: 0; line-height: 1.5;
}

/* Property sub-text */
.fsub { font-size: 12px; color: var(--faint); line-height: 1.4; }

/* Framework driver list */
.fdrv { display: flex; flex-direction: column; gap: 10px; width: 100%; }
.fdrv-row { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }
.fdrv-ref  { font-size: 13px; color: var(--accent); flex: 0 0 auto; font-family: var(--font-sans); }
.fdrv-ef {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .4px;
  padding: 2px 8px; border-radius: var(--r-xs); border: 1px solid var(--line2); flex: 0 0 auto;
}
.fdrv-ef.e-bull { color: var(--bull-text); border-color: var(--bull-edge); background: var(--bull-tint); }
.fdrv-ef.e-bear { color: var(--bear-text); border-color: var(--bear-edge); background: var(--bear-tint); }
.fdrv-ef.e-cv   { color: var(--warn-text); border-color: var(--warn-edge); background: var(--warn-tint); }
.fdrv-ef.e-neu  { color: var(--text-muted); }
.fdrv-note { flex: 1 1 100%; font-size: 13px; color: var(--muted); line-height: 1.55; }

/* Compact pairs framework-driver layout (design: code chip · label + accent
   magnitude bar · magnitude word). Full note on hover of the label/magnitude;
   the code keeps its own rule popover. */
.fdrv-compact { gap: 11px; }
.fdrv-row.fdrv-row-c {
  display: grid; grid-template-columns: 58px 1fr 68px;
  align-items: center; gap: 11px; flex-wrap: nowrap;
}
.fdrv-row-c .fdrv-ref {
  font: 500 10.5px var(--font-sans); color: var(--accent);
  padding: 3px 4px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: var(--diff-hi);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--line2);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
}
/* the compact chip is a full box, not the inline dotted-underline variant */
.fdrv-row-c .fdrv-ref.has-pop {
  border-bottom: 1px solid var(--line2);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
}
.fdrv-row-c .fdrv-i { display: none; }   /* design chip shows only the code */
.fdrv-c-mid {
  min-width: 0; cursor: pointer; appearance: none; -webkit-appearance: none;
  background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit;
  text-align: left; width: 100%;
}
.fdrv-c-label {
  display: block; font: 11px var(--font-sans); color: var(--text-muted);
  margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Tapped open: the label stops being one ellipsised line and shows the whole note, which
   is what the tooltip carries for a mouse. */
.fdrv-row-c.is-open .fdrv-c-label {
  white-space: normal; overflow: visible; text-overflow: clip;
}
.fdrv-c-bar { display: block; height: 4px; background: rgba(var(--hairline-rgb), .18); }
.fdrv-c-fill { display: block; height: 100%; background: var(--accent); }
.fdrv-c-mag {
  font: 10.5px var(--font-sans); color: var(--text-2); text-align: right;
  white-space: nowrap; cursor: help;
}

/* Hoverable framework-driver code → live thesis rule popover. The popover is
   position:fixed (JS sets top/left from the code's rect) so the ancestor
   .row{overflow:hidden} can't clip it. */
.fdrv-ref.has-pop { cursor: help; border-bottom: 1px dotted var(--accent); }
.fdrv-i {
  font-size: 10px; color: var(--faint); margin-left: 4px;
  vertical-align: super; font-family: var(--font-sans);
}
.fdrv-ref.has-pop:hover .fdrv-i,
.fdrv-ref.has-pop:focus .fdrv-i { color: var(--accent); }
.fdrv-pop {
  display: none; position: fixed; z-index: 50; width: 360px;
  max-height: 56vh; overflow-x: hidden; overflow-y: auto;
  /* The popover is a child of the code chip, which is white-space:nowrap +
     overflow:hidden/ellipsis — reset both here so the rule text WRAPS instead
     of running off the side (previously only .fdrv-full overrode it). */
  white-space: normal; overflow-wrap: anywhere;
  background: var(--panel2); border: 1px solid var(--line2);
  border-radius: var(--r-md); box-shadow: var(--shadow-2);
  padding: 10px 13px;
}
.fdrv-ref.has-pop:hover .fdrv-pop,
.fdrv-ref.has-pop:focus .fdrv-pop,
.fdrv-ref.has-pop.pinned .fdrv-pop { display: block; }
.fdrv-pop-h {
  font-family: var(--font-sans); font-size: 12px; color: var(--accent);
  margin: 0 0 6px; padding-bottom: 6px; border-bottom: 1px solid var(--line);
}
.fdrv-pop-b {
  font-size: 12.5px; line-height: 1.6; color: var(--txt);
  word-break: break-word;
}
/* Tier 1 — condensed rulebook one-liner */
.fdrv-rule-t {
  font-weight: 600; color: var(--txt); font-size: 12.5px; margin: 0 0 4px;
}
.fdrv-rule-l { color: var(--muted); font-size: 12.5px; line-height: 1.6; }
/* Tier 2 — expandable full FRAMEWORK_V3 section */
.fdrv-more {
  background: none; border: 0; color: var(--accent); padding: 0;
  font-size: 11.5px; margin: 8px 0 0;
}
.fdrv-more:hover { text-decoration: underline; }
.fdrv-full {
  margin: 8px 0 0; padding-top: 8px; border-top: 1px solid var(--line);
  font-size: 12px; line-height: 1.6; color: var(--muted);
  white-space: pre-wrap; word-break: break-word;
}

/* Suppress the ↓ connector arrows entirely */
.fconn { display: none; }

/* Terminal verdict row — full-width card at the bottom of the flow */
.fcard.fend {
  flex-direction: column; gap: 8px;
  padding: 14px 18px;
  background: var(--panel2);
  border-left-width: 4px;
  border-bottom: none;
}
.fend-top {
  font-family: var(--font-sans); font-weight: 700; font-size: 16px;
  color: var(--txt); display: flex; align-items: center; gap: 8px;
}
.fend.acc-pos .fend-arrow { color: var(--grn); }
.fend.acc-neg .fend-arrow { color: var(--red); }
.fend.acc-warn .fend-arrow { color: var(--amber); }
.fend-meter { display: flex; align-items: center; gap: 9px; }
.fend-lab   { font-size: 10px; text-transform: uppercase; letter-spacing: 1px; color: var(--muted); }
.fmeter     { display: inline-flex; gap: 3px; }
.fmeter .seg     { width: 22px; height: 5px; border-radius: var(--r-xs);   /* 22x5 meter segment - was 3px; the nearest rung, not squared */ background: var(--line2); }
.fmeter .seg.on  { background: var(--accent); }
.fend-cf    { font-size: 13.5px; color: var(--txt); text-transform: capitalize; }
.fend-corro { font-size: 12.5px; color: var(--faint); }
.fend-corro .cor.pos { color: var(--grn); }
.fend-corro .cor.neg { color: var(--red); }

/* Macro-bias sub-elements */
.brk-bias { display: flex; align-items: center; gap: 8px; }
.brk-num  { font-family: var(--font-sans); font-size: 12.5px; color: var(--muted); }
.brk-dots { font-family: var(--font-sans); font-size: 11px; letter-spacing: 1px; }
.brk-dots.dpos { color: var(--grn); }
.brk-dots.dneg { color: var(--red); }
.brk-dots.d0   { color: var(--faint); }

/* ── Currency Expectation breakdown — design grid (rebuilt) ────────────────── */
.ebrk-grid {
  display: grid; grid-template-columns: 108px 1fr;
  border: 1px solid rgba(var(--hairline-rgb), .55);
}
/* Macro bias — full-width row */
.ebrk-mbrow {
  grid-column: 1 / 3; display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 9px 12px; border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
  background: var(--surface-raised);
}
.ebrk-k {
  font: 600 9.5px var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--colhead);
}
.ebrk-mbrow .chip { min-width: 120px; }
.ebrk-num { font: 11px var(--font-sans); color: var(--text-muted); }
/* Framework drivers — full-width, label on TOP */
.ebrk-fw {
  grid-column: 1 / 3; padding: 11px 12px;
  border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
}
.ebrk-fw-h {
  font: 600 9.5px var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--colhead); margin: 0 0 10px;
}
.ebrk-sub { font: 11px var(--font-sans); color: var(--text-faint); }
/* Meta rows — label | value; the value wraps to multiple lines */
/* Both cells STRETCH to the row height (grid default) so their bottom hairlines
   meet at the same line; flex-centre the content so the label stays inline with
   its value despite the font-size difference. */
.ebrk-ml {
  padding: 9px 12px; border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
  font: 600 9.5px var(--font-mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--colhead); display: flex; align-items: center;
}
.ebrk-mv {
  padding: 9px 12px; border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
  min-width: 0; line-height: 1.5;
  display: flex; align-items: center; flex-wrap: wrap; gap: 0 6px;
}
.ebrk-mval { font: 500 12px var(--font-sans); color: var(--text-2); }
.ebrk-mval.acc-pos  { color: var(--grn); }
.ebrk-mval.acc-neg  { color: var(--red); }
.ebrk-mval.acc-warn { color: var(--amber); }
.ebrk-msub { font: 10.5px var(--font-sans); color: var(--text-faint); }
/* (every meta row keeps its hairline, matching the design — uniform borders) */
/* Compact verdict box */
.ebrk-verdict {
  border-left: 2px solid var(--line2); padding: 10px 13px; margin-top: 11px;
}
.ebrk-verdict.acc-pos  { border-left-color: var(--bull-dot); background: var(--bull-tint); }
.ebrk-verdict.acc-neg  { border-left-color: var(--bear-dot); background: var(--bear-tint); }
.ebrk-verdict.acc-warn { border-left-color: var(--warn-dot); background: var(--warn-tint); }
.ebrk-vtop { display: flex; align-items: center; gap: 9px; margin-bottom: 5px; }
.ebrk-vdir { font: 600 11px var(--font-sans); }
.ebrk-verdict.acc-pos  .ebrk-vdir { color: var(--bull-text); }
.ebrk-verdict.acc-neg  .ebrk-vdir { color: var(--bear-text); }
.ebrk-verdict.acc-warn .ebrk-vdir { color: var(--warn-text); }
.ebrk-vcorro { margin-left: auto; font: 10.5px var(--font-sans); color: var(--text-faint); }
.ebrk-vconf { display: flex; align-items: center; gap: 8px; }
.ebrk-vconf-l { font: 10px var(--font-sans); color: var(--colhead); }
.ebrk-vdots { font: 11px var(--font-sans); color: var(--text-2); letter-spacing: 1px; }
.ebrk-vconf-w { font: 11px var(--font-sans); color: var(--text-2); text-transform: capitalize; }
/* Framework-driver tweaks (currency rich layout) to match the design */
/* rule code trimmed to ONE line + ellipsis; full text on hover (the popover) */
.ebrk-fw .fdrv-row-enh .fdrv-ref {
  font-size: 11px; max-width: 100%; margin-top: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ebrk-fw .fdrv-i { display: none; }                     /* hide ⓘ in the trimmed code */
.ebrk-fw .fdrv-ref.has-pop { border-bottom: 0; }        /* no dotted line under the code */
.ebrk-fw .fdrv-note { font-size: 11.5px; }              /* driver note smaller */
.ebrk-fw .fdrv-footer { font-size: 10px; }
.ebrk-fw .fdrv-foot-l { font-weight: 400; }             /* pull label not bold */
/* firing + effect tags smaller (design 9px); no leading dot on "firing" */
.ebrk-fw .actpill { font-size: 9px; font-weight: 600; padding: 1px 6px; }
.ebrk-fw .actpill .act-sym { display: none; }
.ebrk-fw .fdrv-ef { font-size: 9px; padding: 1px 6px; }
/* firing tag = green — scoped above the later global .act-firing rule */
.ebrk-fw .actpill.act-firing {
  background: var(--bull-tint); color: var(--bull-text); border: 1px solid var(--bull-edge);
}
/* weight segments stay SHARP here — the base .wbar .wseg carries --r-xs, and inside
   a framework-weight breakdown they read as a pinstripe meter, so this scoped rule
   squares them; pull pills smaller, carrying the same --r-xs as every other chip */
.ebrk-fw .wbar .wseg { border-radius: 0;   /* meter segment, full-bleed inside .wbar */ }
.ebrk-fw .fdrv-p { border-radius: var(--r-xs); font-size: 10px; padding: 1px 6px; }
.brk-trade { display: flex; align-items: center; gap: 8px; }

/* Recent-shift row */
.brk-shift { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; flex-wrap: wrap; }
.brk-when  { font-family: var(--font-sans); font-size: 11px; color: var(--faint); flex: 0 0 auto; }
.brk-delta { color: var(--muted); font-size: 13px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Thesis-rationale text — still used by the pairs view's "thesis rationale"
   disclosure (pairRow). The currencies view moved its rationale to the
   Expectation block's "more detail" disclosure (.expect-detail). */
.brk-rat   { font-size: 14px; line-height: 1.7; color: var(--muted); }
.brk-rat p { margin: 4px 0 8px; }
.brk-rat p:last-child { margin-bottom: 0; }

/* Expressed-positions table rows ("Trading this view via — live Pairs book") */
.xp { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px dashed var(--line); font-size: 13px; }
.xp:first-of-type { border-top: 0; }
.xpair { min-width: 90px; color: var(--txt); }
.xdir  { min-width: 46px; color: var(--muted); text-transform: lowercase; }
.xdir.dir-long  { color: var(--grn); }
.xdir.dir-short { color: var(--red); }
.xdir.dir-range { color: var(--amber); }
.xarrow { color: var(--faint); }

/* Trading-via rows (design): position bias = plain coloured text (no tint box);
   direction chip = bordered box with NO fill; conviction = larger + UPPERCASE.
   Scoped to .xp so the shared .chip/.conf/.dir-* aren't affected elsewhere. */
.xp .xdir { background: none; }
.xp .chip { background: none; }
.xp .conf { font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em; }

.chain-h {
  font: 600 9.5px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .12em;
  color: var(--colhead); margin: 22px 0 10px;
}

/* ── Pairs groups ───────────────────────────────────────────────────────────── */
.group-h {
  display: flex; align-items: center; gap: 9px;
  margin: 16px 0 8px; font: 600 11px/1 var(--font-mono); text-transform: uppercase;
  letter-spacing: .1em; color: var(--text);
}
/* 3px × 13px accent rule that opens each conviction band. */
.group-h::before {
  content: ""; flex: 0 0 auto; width: 3px; height: 13px; background: var(--accent);
}
/* Each conviction band = a bordered sub-table (colhead + rows) under its title,
   matching the design's banded book frame. */
.pair-band { border: 1px solid rgba(var(--hairline-rgb), .55); margin-bottom: 22px; }
.group-h .ln  { flex: 1; height: 1px; background: var(--surface-sunken); }
.group-h .cnt { color: var(--text-faint); font-family: var(--font-sans); letter-spacing: 0; font-weight: 400; }

/* ── Pair event list ────────────────────────────────────────────────────────── */
.events { margin: 6px 0 0; }
.event  {
  display: flex; gap: 14px; padding: 11px 0;
  border-top: 1px dashed var(--line);
}
.event .when  {
  font-family: var(--font-sans); font-size: 11.5px; color: var(--faint);
  min-width: 108px; flex-shrink: 0; padding-top: 1px;
}
.event .etype {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .5px;
  min-width: 132px; flex-shrink: 0; padding-top: 1px;
}
.et-added, .et-baseline   { color: var(--accent); }
.et-removed               { color: var(--red); }
.et-conviction_change     { color: var(--amber); }
.et-direction_change      { color: var(--vio); }
.event .ebody  { flex: 1; }

/* Change lines — plain font so long conviction paths wrap comfortably */
.chg { font-size: 13.5px; color: var(--txt); line-height: 1.6; margin-bottom: 4px; }

/* Pair-event body reuses the .snode-* primitives (snode-grp / snode-bullets /
   delta / snode-long) for parity with the currency stance-change layout.
   Match the calm-reading scope applied to .snode-b in the currency section so
   the pair event reads with the same muted, low-glare styling — same labels,
   same bullet feel, same flat delta line (no green-bordered box). */
.event .ebody .snode-grp:first-child { margin-top: 0; }
.event .ebody .snode-bullets li,
.event .ebody .drv-txt,
.event .ebody .chg-to { color: var(--muted); }
.event .ebody .snode-bullets li.chg-held { color: var(--muted); font-style: normal; }
.event .ebody .delta,
.event .ebody .delta.producer,
.event .ebody .delta.none {
  margin: 5px 0; padding: 0 0 0 16px;
  background: none; border: 0; border-radius: 0;   /* stripped back to bare indented prose - no fill, no border, nothing to round */
  font-size: 13.5px; line-height: 1.6; color: var(--muted);
}
.event .ebody .disc { margin-top: 10px; }

/* ── Pairs "Stance change history" — collapsible cards (design 1:1) ─────────── */
.sc-history { margin: 16px 0 0; }
.sc-history-head {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 0 0 12px;
}
.sc-bar { width: 2px; height: 13px; background: var(--accent); display: inline-block; }
.sc-history-h {
  font: 600 10px var(--font-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-2);
}
.sc-history-meta { font: 10.5px var(--font-sans); color: var(--text-faint); }

/* Rows sit flush (no gaps) — adjacent borders collapse so the history reads as
   one continuous list, matching the currency stance-change list. */
.sc-item {
  border: 1px solid var(--line); background: var(--surface); margin-bottom: 0;
}
.sc-item + .sc-item { border-top: none; }
.sc-item.open { border-color: var(--accent); }
.sc-head {
  display: flex; align-items: center; gap: 10px; padding: 10px 13px; flex-wrap: wrap;
}
.sc-item .sc-caret {
  color: var(--accent); font-size: 10px; flex: 0 0 auto;
  transition: transform var(--dur-fast) var(--ease-out);
}
.sc-item.open > .sc-head .sc-caret { transform: rotate(90deg); }
.sc-caret-spacer { width: 10px; flex: 0 0 auto; }
.sc-ts { font: 11px var(--font-sans); color: var(--text-muted); flex: 0 0 auto; }
/* Uniform-width, centred kind chip so the kinds line up down the column for
   readability (mirrors the fixed-width bias chip on the currency list). min-
   width pads the short kinds; the rare long "in book (window start)" extends. */
.sc-kind {
  display: inline-flex; align-items: center; justify-content: center;
  height: 18px; padding: 0 8px; min-width: 104px;
  font: 600 9px var(--font-mono); letter-spacing: .05em; white-space: nowrap;
  text-transform: uppercase; flex: 0 0 auto;
}
.sc-kind-in  { color: var(--bull-text); background: var(--bull-tint); border: 1px solid var(--bull-edge); }
.sc-kind-out { color: var(--bear-text); background: var(--bear-tint); border: 1px solid var(--bear-edge); }
.sc-kind-delta { color: var(--accent); border: 1px solid var(--accent); background: transparent; }
/* from→to transitions, right-aligned in the header */
.sc-deltas {
  margin-left: auto; display: flex; flex-wrap: wrap; gap: 16px; align-items: center;
}
.sc-delta { display: inline-flex; align-items: center; gap: 6px; }
.sc-d-field {
  font: 9px var(--font-mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-faint);
}
.sc-d-from { font: 11px var(--font-sans); color: var(--text-muted); }
.sc-d-arrow { color: var(--accent); font-size: 11px; }
.sc-d-to { font: 11px var(--font-sans); color: var(--text-2); }

.sc-body { display: none; padding: 0 14px 13px; }
.sc-item.open > .sc-body { display: block; }
.sc-grp {
  font: 600 9px var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--colhead); margin: 4px 0 9px;
}
/* Calm reading inside the body — compact, muted text, accent bullets (matches design) */
.sc-body .snode-bullets li { font-size: 11.5px; line-height: 1.55; }
.sc-body .snode-bullets li,
.sc-body .drv-txt { color: var(--text-muted); }
.sc-body .snode-bullets li::before { color: var(--accent); }
/* Nested "Earlier reinforcements" disclosure → the design's inset panel */
.sc-body .disc {
  border: 1px solid var(--line); background: var(--surface-sunken); margin-top: 10px;
}
.sc-body .disc-h { padding: 8px 12px; }
.sc-body .disc-b { padding: 0 12px 8px; }

/* ── Currencies layout + right-hand reference card ─────────────────────────── */
/* Single full-width table — the reference removed the right-hand reading rail
   in favour of column-header tooltips. */
.cur-layout { display: block; }
.cur-list {
  min-width: 0;
  border: 1px solid rgba(var(--hairline-rgb), .55);   /* the single table frame */
  background: var(--surface);
}

/* The reference-card column (Reading the bias / persistence / confidence).
   Sticky lives here, not on the cards, so the whole stack scrolls together;
   8px top margin lines the stack up with the first currency row. */
.cur-aside {
  position: sticky; top: 84px; margin-top: 8px; min-width: 0;
  display: flex; flex-direction: column; gap: 16px;
}

.bias-card {
  background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-1);
  padding: 18px 18px 20px;
}
/* The confidence card is deliberately the lightest of the three. */
.bias-card.sm { padding: 15px 18px 16px; }
.bias-card.sm .bl-lead { margin-bottom: 12px; }
.bias-card h4 { margin: 0 0 10px; font-size: 14px; letter-spacing: .3px; color: var(--txt); }

/* Collapsible legend cards: the header (caret + title) is the click target;
   the body is hidden until .open. Collapsed = a tidy single-line card so the
   sidebar stays calm until the reader asks for help. */
.bias-card.legend    { padding: 14px 18px; }
.bias-card.legend.sm { padding: 13px 18px; }
.bias-card.legend.open { padding-bottom: 18px; }
.bias-card.legend .bl-head {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
}
.bias-card.legend .bl-head .caret { margin-left: 0; }
.bias-card.legend .bl-head h4 { margin: 0; }
.bias-card.legend .bl-head:hover h4 { color: var(--txt); }
.bias-card.legend.open .caret { transform: rotate(90deg); }
.bias-card.legend .bl-body { display: none; }
.bias-card.legend.open .bl-body { display: block; }
.bias-card.legend.open .bl-head {
  border-bottom: 1px solid var(--line);
  padding-bottom: 12px; margin-bottom: 14px;
}

.bias-card h5 {
  margin: 16px 0 8px; font-size: 10.5px; letter-spacing: .5px;
  text-transform: uppercase; color: var(--faint);
}
.bl-lead  { margin: 0 0 14px; font-size: 13px; color: var(--muted); line-height: 1.6; }
.bl-scale {
  display: flex; flex-direction: column; gap: 7px; padding: 12px 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.bl-item { display: flex; align-items: flex-start; gap: 9px; }
.bl-item .chip,
.bl-item .persist,
.bl-item .conf {
  flex: none; display: inline-flex; align-items: center;
  justify-content: center; min-width: 110px;
}
/* confidence swatch: a calm neutral pill so it parallels the bias chips /
   persistence swatches without competing for attention */
.bl-item .conf {
  padding: 3px 8px; border: 1px solid var(--line2);
  border-radius: var(--r-xs); color: var(--muted);
}
.bl-gloss { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.bl-sec p { margin: 7px 0; }
/* term · meaning rows for the persistence card's band/horizon/flips-if */
.bl-defs { display: flex; flex-direction: column; gap: 8px; }
.bl-def  { display: flex; align-items: baseline; gap: 9px; }
.bl-dt {
  flex: none; min-width: 64px; font-size: 11px; color: var(--faint);
  text-transform: uppercase; letter-spacing: .4px;
}
.bl-dd { font-size: 12.5px; color: var(--muted); line-height: 1.5; }

.empty { color: var(--faint); padding: 32px; text-align: center; font-size: 14px; }

@media (max-width: 900px) {
  .cur-layout { grid-template-columns: 1fr; }
  .cur-aside  { position: static; order: -1; }
}
@media (max-width: 640px) {
  .name, .cur-colhead .h-name,
  .row-head .persist, .cur-colhead .h-persist,
  .pair-colhead .h-persist,
  .row-head .changed, .row-head .whatchanged,
  .cur-colhead .h-changed, .cur-colhead .h-whatchanged,
  .pair-colhead .h-changed, .pair-colhead .h-whatchanged { display: none; }
  .event { flex-direction: column; gap: 4px; }
}

/* Retained from the removed AI-chat panel: chat-md.js still renders the
   AI-compare weekly judge verdict (app.js _aiAppendVerdict) with this class. */
.chat-tail { white-space: pre-wrap; word-break: break-word; }

/* ── Phase 4 — Section 10 site components ─────────────────────────────────── */
/* T4.7 — Causal-chain activation heatmap (redesigned: compact strip default) */
.heatmap {
  margin: 8px 0 16px; padding: 10px 14px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.heatmap-h {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 10px; gap: 12px;
}
.heatmap-h-left { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.heatmap-t { font-weight: 600; letter-spacing: .3px; }
.heatmap-sub { color: var(--muted); font-size: 12.5px; }
.heatmap-toggle {
  background: var(--bg2); border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-sm); padding: 4px 10px; font-size: 12px;
}
.heatmap-toggle:hover { color: var(--accent); border-color: var(--accent); }

/* Always-visible colour legend: border = activity, fill tint = push direction */
.heatmap-legend {
  display: flex; flex-direction: column; gap: 5px;
  margin: 0 0 10px; padding: 8px 10px;
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-sm);
  font-size: 11.5px;
}
.heatmap-legend .hl-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.heatmap-legend .hl-cap {
  color: var(--muted); font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; font-size: 10px; min-width: 46px;
}
.heatmap-legend .hl-item { display: inline-flex; align-items: center; gap: 5px; }
.heatmap-legend .hl-lbl { color: var(--txt); }
.heatmap-legend .hl-dot {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--line); box-sizing: border-box; flex-shrink: 0;
}
.heatmap-legend .hl-dot.hc-firing    { border-color: var(--accent); }
.heatmap-legend .hl-dot.hc-armed     { border-color: var(--amber); }
.heatmap-legend .hl-dot.hc-falsified { border-color: var(--red); }
.heatmap-legend .hl-dot.hc-dormant   { border-color: var(--faint); }
.heatmap-legend .hl-swatch {
  width: 13px; height: 13px; border-radius: var(--r-xs);
  border: 1px solid var(--line); box-sizing: border-box; flex-shrink: 0;
}
.heatmap-legend .hl-swatch.he-bullish        { background: var(--bull-tint); }
.heatmap-legend .hl-swatch.he-bearish        { background: var(--bear-tint); }
.heatmap-legend .hl-swatch.he-countervailing { background: var(--warn-tint); }
/* matches the default (no he-* class) cell fill — neutral / no directional push */
.heatmap-legend .hl-swatch.he-neutral        { background: var(--cell-hi); }

/* Compact strip — single line. Anything past the right edge is clipped + faded
   out; the "show expanded grid ▾" toggle is the way to see all of it. */
.heatmap-strip {
  display: flex; gap: 6px; flex-wrap: nowrap;
  padding: 4px 2px 6px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 48px), transparent);
          mask-image: linear-gradient(to right, black calc(100% - 48px), transparent);
}
.hc-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: var(--r-xs);
  font-size: 11.5px; white-space: nowrap; flex-shrink: 0;
  background: var(--surface-sunken); border: 1px solid rgba(var(--hairline-rgb), .55);
  cursor: help;
}
/* Activation = border: solid firing · dashed armed (design convention). */
.hc-pill.hc-firing    { border-color: var(--accent); border-style: solid; }
.hc-pill.hc-armed     { border-color: var(--warn-dot); border-style: dashed; }
.hc-pill.hc-falsified { border-color: var(--bear-dot); opacity: .65; }
.hc-pill.hc-dormant   { opacity: .45; }
.hc-pill.he-bullish        { background: var(--bull-tint); }
.hc-pill.he-bearish        { background: var(--bear-tint); }
.hc-pill.he-countervailing { background: var(--warn-tint); }
.hc-pill .hc-pill-cur { font-weight: 700; color: var(--txt); }
.hc-pill .hc-pill-ref { color: var(--accent); }
.hc-pill .hc-pill-w {
  color: var(--muted); font-family: var(--font-sans); font-size: 10.5px;
  padding-left: 4px; border-left: 1px solid var(--line);
}

/* Expanded grid — same shape as before, now opt-in via the toggle */
.heatmap-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 6px;
}
.heatmap-col {
  background: var(--surface-raised); border: 1px solid rgba(var(--hairline-rgb), .55); border-radius: var(--r-sm);
  padding: 8px; display: flex; flex-direction: column; gap: 4px;
}
.heatmap-col-t {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 4px 6px 6px; border-bottom: 1px solid var(--line); margin-bottom: 2px;
}
.heatmap-col-code { font-family: var(--font-sans); font-weight: 700; color: var(--accent); font-size: 13px; }
.heatmap-col-n { color: var(--muted); font-size: 11px; }
.heatmap-cell {
  display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap;
  padding: 5px 7px; border-radius: 0;   /* activation-matrix CELL - table cells stay square, only .heatmap-col frames round */
  font-size: 12px;
  background: var(--surface-sunken);
  border-left: 3px solid rgba(var(--hairline-rgb), .55);
  overflow-wrap: anywhere;
}
.heatmap-cell .hc-act { font-family: var(--font-sans); width: 12px; font-weight: 700; }
.heatmap-cell.hc-firing .hc-act { color: var(--accent); }
.heatmap-cell.hc-armed .hc-act { color: var(--amber); }
.heatmap-cell.hc-falsified .hc-act { color: var(--red); }
.heatmap-cell.hc-dormant .hc-act { color: var(--faint); }
.heatmap-cell .hc-w {
  color: var(--muted); font-family: var(--font-sans); font-size: 10.5px;
  margin-left: auto; padding-left: 4px; border-left: 1px solid var(--line);
}
.heatmap-cell.hc-firing { border-left-color: var(--accent); border-left-style: solid; }
.heatmap-cell.hc-armed { border-left-color: var(--warn-dot); border-left-style: dashed; }
.heatmap-cell.hc-falsified { border-left-color: var(--bear-dot); opacity: .65; }
.heatmap-cell.hc-dormant { opacity: .45; }
.heatmap-cell.he-bullish { background: var(--bull-tint); }
.heatmap-cell.he-bearish { background: var(--bear-tint); }
.heatmap-cell.he-countervailing { background: var(--warn-tint); }
.heatmap-cell .hc-ref {
  flex: 1; min-width: 0;
  display: inline-flex; align-items: baseline; gap: 6px;
}
.heatmap-cell .hc-code { color: var(--accent); font-weight: 700; flex-shrink: 0; }
.heatmap-cell .hc-label {
  color: var(--muted); font-size: 11px; flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.heatmap-cell .hc-note {
  color: var(--muted); font-size: 11.5px;
  flex-basis: 100%; padding-left: 18px; line-height: 1.4;
}
.heatmap-cell .hc-note-more {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  color: var(--accent);
  font: inherit;
  font-size: 10.5px;
  cursor: pointer;
  vertical-align: baseline;
}
.heatmap-cell .hc-note-more:hover {
  background: var(--diff-hi);
}

/* ── Causal-chain activation matrix (Currencies, rebuilt to design) ── */
.cc-panel{border:1px solid rgba(var(--hairline-rgb), .55);background:var(--surface-sunken);margin-bottom:16px;}
.cc-head{display:flex;align-items:center;gap:9px;padding:9px 13px;border-bottom:1px solid rgba(var(--hairline-rgb), .55);flex-wrap:wrap;}
.cc-tick{width:2px;height:12px;background:var(--accent);display:inline-block;}
.cc-title{font:600 10.5px var(--font-sans);letter-spacing:.11em;color:var(--text-2);}
.cc-firing{font:400 11px var(--font-sans);color:var(--bull-dot);}
.cc-armed{font:400 11px var(--font-sans);color:var(--text-muted);}
.cc-legend{margin-left:auto;display:flex;align-items:center;gap:11px;font:400 10px var(--font-sans);color:var(--text-faint);flex-wrap:wrap;}
.cc-leg{display:flex;align-items:center;gap:5px;}
.cc-sw{width:9px;height:9px;display:inline-block;}
.cc-sw.bull{background:var(--bull-dot);}.cc-sw.bear{background:var(--bear-dot);}.cc-sw.warn{background:var(--warn-dot);}
.cc-toggle{font:500 11px var(--font-sans);color:var(--accent);border:1px solid var(--accent);background:transparent;padding:4px 12px;cursor:pointer;border-radius:var(--r-sm);white-space:nowrap;}
.cc-gridwrap{padding:10px 13px;overflow-x:auto;}
.cc-grid,.cc-frow{display:grid;align-items:center;}
.cc-ghead{padding:7px 4px;text-align:center;}
.cc-ghead.selected{box-shadow:inset 0 0 0 2px var(--accent);background:var(--surface-sunken);}
.cc-cur{display:block;font:600 11px var(--font-sans);color:var(--text);}
.cc-curbias{display:block;font:400 9px var(--font-sans);color:var(--text-faint);}
.cc-fname{text-align:right;padding-right:11px;font:400 11px var(--font-sans);color:var(--text-muted);}
.cc-cell{display:flex;align-items:center;justify-content:center;height:28px;margin:1px 2px;font:600 11px var(--font-sans);border:1px solid transparent;}
.cc-cell.firing{border-style:solid;}.cc-cell.armed{border-style:dashed;}
.cc-cell.e-bull{color:var(--bull-text);background:var(--bull-tint);border-color:var(--bull-edge);}
.cc-cell.e-bear{color:var(--bear-text);background:var(--bear-tint);border-color:var(--bear-edge);}
.cc-cell.e-warn{color:var(--warn-text);background:var(--warn-tint);border-color:var(--warn-edge);}
.cc-cell.clickable{cursor:pointer;}
.cc-cell.selected{box-shadow:inset 0 0 0 2px var(--accent);}
.cc-cards-wrap{border-top:1px solid rgba(var(--hairline-rgb), .55);padding:10px;}
.cc-cards-bar{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap;}
.cc-intro{font:400 11px var(--font-sans);color:var(--text-muted);}
.cc-showing{margin-left:auto;font:400 11px var(--font-sans);color:var(--text);}
.cc-showing b{color:var(--accent);font-weight:400;}
.cc-clear{font:400 10.5px var(--font-sans);color:var(--text-muted);border:1px solid rgba(var(--hairline-rgb), .55);background:transparent;padding:3px 10px;cursor:pointer;border-radius:var(--r-sm);}
.cc-cards{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;}
.cc-card{border:1px solid rgba(var(--hairline-rgb), .55);background:var(--surface);min-width:0;}
.cc-card.dim{opacity:.4;}
.cc-card-h{display:flex;align-items:center;gap:7px;padding:6px 9px;border-bottom:1px solid rgba(var(--hairline-rgb), .55);}
.cc-card-cur{font:600 11px var(--font-sans);color:var(--text);}
.cc-card-bias{display:inline-flex;align-items:center;height:16px;padding:0 6px;font:600 9px/1 var(--font-sans);border:1px solid;}
.cc-card-bias.bull{color:var(--bull-text);background:var(--bull-tint);border-color:var(--bull-edge);}
.cc-card-bias.bear{color:var(--bear-text);background:var(--bear-tint);border-color:var(--bear-edge);}
.cc-card-bias.warn{color:var(--warn-text);background:var(--warn-tint);border-color:var(--warn-edge);}
.cc-card-bias.mixed{color:var(--mixed-text);background:var(--mixed-tint);border-color:var(--mixed-edge);}
.cc-card-n{margin-left:auto;font:400 9.5px var(--font-sans);color:var(--text-faint);}
.cc-card-body{padding:6px 8px;}
.cc-driver{border:1px solid rgba(var(--hairline-rgb), .55);background:var(--surface);padding:5px 8px;margin-bottom:4px;}
.cc-driver:last-child{margin-bottom:0;}
.cc-driver.match{border-color:var(--accent);background:var(--surface-sunken);}
.cc-driver.ddim{opacity:.3;}
.cc-d-r1{display:flex;align-items:center;gap:6px;margin-bottom:2px;}
.cc-d-dot{width:7px;height:7px;border-radius:50%;flex:none;}
.cc-d-dot.firing{background:currentColor;}
.cc-d-dot.armed{background:transparent;border:1px solid currentColor;}
.cc-d-dot.e-bull,.cc-d-code.e-bull{color:var(--bull-dot);}
.cc-d-dot.e-bear,.cc-d-code.e-bear{color:var(--bear-dot);}
.cc-d-dot.e-warn,.cc-d-code.e-warn{color:var(--warn-dot);}
.cc-d-code{font:500 10px var(--font-sans);cursor:help;}
.cc-d-code.e-bull{color:var(--bull-text);}.cc-d-code.e-bear{color:var(--bear-text);}.cc-d-code.e-warn{color:var(--warn-text);}
.cc-d-title{font:600 10.5px var(--font-sans);color:var(--text);min-width:0;overflow-wrap:anywhere;}
.cc-d-w{margin-left:auto;font:400 9px var(--font-sans);color:var(--text-faint);}
.cc-d-r2{display:flex;align-items:center;gap:5px;margin-bottom:0;}
.cc-d-tag{font:400 8px var(--font-sans);letter-spacing:.06em;color:var(--text-muted);border:1px solid rgba(var(--hairline-rgb), .55);padding:0 4px;}
.cc-d-status{font:400 9px var(--font-sans);color:var(--text-muted);}
/* Driver: the rule code leads; its long framework label is a hover tooltip on
   the code (cursor:help). The plain-English description stays visible. */
.cc-d-desc{font:400 10px/1.4 var(--font-sans);color:var(--text-muted);margin:3px 0 0;}
@media (max-width:1100px){.cc-cards{grid-template-columns:repeat(3,1fr);}}

/* Partial-emission tag on the Trade ticket */
.pos-partial {
  background: var(--amber); color: var(--bg);
  padding: 2px 9px; border-radius: var(--r-pill); font-size: 11px; font-weight: 700;
  letter-spacing: .3px; margin-left: 10px;
}

/* T4.1 — F-Stage Clock pill row (with leading label + ⓘ explainer) */
.fstage-wrap { margin: 6px 0 10px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.fstage-lbl {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 1px; color: var(--muted);
  display: inline-flex; align-items: center; gap: 4px;
}
.fstage-info {
  display: inline-block; width: 16px; height: 16px;
  text-align: center; line-height: 16px;
  border-radius: 50%; background: var(--bg2);
  border: 1px solid var(--line);
  color: var(--muted); font-size: 10px;
  cursor: help; position: relative;
}
.fstage-info:hover, .fstage-info:focus { color: var(--accent); border-color: var(--accent); outline: none; }
.fstage-pop {
  position: absolute; top: 22px; left: -8px;
  width: 360px; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--line2);
  border-radius: var(--r-md); box-shadow: var(--shadow-2);
  font-size: 12px; line-height: 1.5; color: var(--txt);
  opacity: 0; visibility: hidden; pointer-events: none;
  /* `visibility` is discrete and never interpolates — but naming it HOLDS the old
     value for the duration, and that is exactly what keeps the popover painted
     while opacity falls. Drop it and the fade-out renders as an instant
     disappearance. It is not a layout property, so the no-layout-animation rule
     is not what governs it. */
  transition: opacity var(--dur-base) var(--ease-out),
              visibility var(--dur-base) var(--ease-out);
  z-index: 50; text-transform: none; letter-spacing: 0;
}
.fstage-info:hover .fstage-pop, .fstage-info:focus .fstage-pop {
  opacity: 1; visibility: visible; pointer-events: auto;
}
/* Right-anchor when popup would overflow viewport (set by initPopupAutoFlip
   on mouseover/focus — e.g. the Scenarios collapsible ⓘ sits on the right
   edge of a full-width row and the default left-anchor spilled off-screen). */
.fstage-info.pop-flip .fstage-pop {
  left: auto; right: -8px;
}
/* "Stage" label doubles as the explainer popover host — the standalone ⓘ badge
   was removed per design. Reset the circular-badge look back to a plain label,
   with a subtle dotted underline as the hover affordance (app convention). */
.fstage-lbl.fstage-lbl-info {
  width: auto; height: auto; line-height: inherit;
  border-radius: 0;   /* reset back to a plain inline label - no box, so nothing to round */ background: none; padding: 0;
  color: var(--muted); font-size: 11px; font-weight: 700;
  border: 0; border-bottom: 1px dotted var(--line); cursor: help;
}
.fstage-lbl.fstage-lbl-info:hover,
.fstage-lbl.fstage-lbl-info:focus {
  color: var(--accent); background: none;
  border: 0; border-bottom: 1px dotted var(--accent); outline: none;
}
.fstage-pop-h { font-weight: 700; margin-bottom: 4px; color: var(--accent); }
.fstage-pop-sub { color: var(--muted); margin-bottom: 6px; }
.fstage-legend { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
.fstage-leg-row { display: flex; gap: 6px; font-size: 11.5px; }
.fstage-leg-n {
  width: 16px; text-align: center; font-family: var(--font-sans); font-weight: 700;
  color: var(--accent);
}
.fstage-leg-lab { width: 70px; font-weight: 600; }
.fstage-leg-d { flex: 1; color: var(--muted); }
.fstage-row { display: inline-flex; gap: 4px; }
.fstage-pill {
  display: inline-flex; gap: 4px; align-items: baseline;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--bg2); border: 1px solid var(--line);
  font-size: 11.5px; color: var(--muted);
}
.fstage-pill.active {
  background: var(--cell-hi); color: var(--txt);
  border-color: var(--accent); font-weight: 700;
  box-shadow: 0 0 0 2px var(--cell-hi);
}
.fstage-pill .fstage-n { font-family: var(--font-sans); font-weight: 700; }
.fstage-pill .fstage-l { text-transform: uppercase; letter-spacing: .5px; font-size: 10.5px; }
.fstage-crowding {
  background: var(--warn-tint); color: var(--amber);
  border: 1px solid var(--amber); border-radius: var(--r-xs);
  padding: 2px 9px; font-size: 11.5px; font-weight: 600;
}
.fstage-rat { color: var(--muted); font-size: 12.5px; flex-basis: 100%; font-style: italic; }
/* Pairs legs: stage rationale hidden behind a "show more" toggle (compact leg). */
.fstage-rat-collapse { flex-basis: 100%; }
.fstage-rat-toggle {
  color: var(--accent); font-size: 11px; font-weight: 600; letter-spacing: .04em;
  cursor: pointer; user-select: none;
}
.fstage-rat-toggle:hover { text-decoration: underline; }
.fstage-rat-collapse .fstage-rat { margin-top: 6px; }
.fstage-rat.fstage-rat-hidden { display: none; }
/* Currencies: stage description lives in the active-pill tooltip (cursor cue). */
.fstage-has-rat { cursor: help; }
/* Pair view — base + quote stacked vertically; currency label OWN A ROW
   above its pill row so EUR / GBP aren't squashed in line with the pills. */
.fstage-pair { display: flex; flex-direction: column; gap: 10px; margin: 6px 0 12px; }
.fstage-pair-leg {
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 12px 14px;
}
.fstage-pair-head {
  display: flex; gap: 9px; align-items: center; margin-bottom: 0; flex-wrap: wrap;
}
/* stage pills inline on the same row as the code + bias chip, pushed right */
.fstage-pair-pills { margin-left: auto; display: inline-flex; gap: 4px; flex-wrap: wrap; }
/* whole leg is click-to-expand (no "show more"): caret + pointer + hover */
.fstage-leg-clickable { cursor: pointer; }
.fstage-leg-clickable:hover { background: var(--surface-row-active); }
.fstage-leg-caret { color: var(--accent); font-size: 10px; flex: 0 0 auto; transition: transform var(--dur-fast) var(--ease-out); }
.fstage-pair-leg.open .fstage-leg-caret { transform: rotate(90deg); }
/* Crowding-risk flag rides inline in the leg head (after the bias chip) as a
   compact inline form — not a rounded badge dropped to a second line. */
.fstage-pair-leg .fstage-crowding {
  margin: 0; border-radius: var(--r-xs); flex: 0 0 auto;
  display: inline-flex; align-items: center;
  height: 21px; padding: 0 8px; font-size: 10.5px;
}
.fstage-pair-leg .fstage-rat { margin: 9px 0 0; }
.fstage-pair-code {
  font-family: var(--font-sans); font-weight: 500; font-size: 13px; color: var(--accent);
}
.fstage-pair-bias { color: var(--muted); font-size: 12px; }

/* T4.2 — Driver magnitude bar + activation pills + pull footer (redesigned) */
/* Activation pill: leading symbol + label, soft background tint per state. */
/* Design driver-row layout: top line = firing pill + effect tag + weight dots
   (dots pushed right); code on its own line; description below. The DOM order
   is actpill, code(ref), tag(ef), note, wbar — reordered here via `order`. */
.fdrv-row-enh { gap: 5px 8px; align-items: center; flex-wrap: wrap; }
.fdrv-row-enh .actpill   { order: 1; }
.fdrv-row-enh .fdrv-ef   { order: 2; }
.fdrv-row-enh .wbar      { order: 3; margin-left: auto; }
.fdrv-row-enh .fdrv-ref  { order: 4; flex: 0 0 100%; font-weight: 500; margin-top: 3px; }
.fdrv-row-enh .fdrv-note { order: 5; flex: 0 0 100%; }
.actpill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px 1px 5px; border-radius: var(--r-pill);
  font-size: 11px; font-weight: 600;
  font-family: var(--font-sans);
  white-space: nowrap;
}
.actpill .act-sym { font-family: var(--font-sans); font-size: 12px; }
.actpill.act-firing { background: var(--cell-hi); color: var(--accent); border: 1px solid var(--accent); }
.actpill.act-armed { background: var(--warn-tint); color: var(--amber); border: 1px solid var(--amber); }
.actpill.act-falsified { background: var(--bear-tint); color: var(--red); border: 1px solid var(--red); opacity: .85; }
.actpill.act-dormant { background: var(--bg2); color: var(--faint); border: 1px solid var(--line); }
/* Segmented weight bar — proper CSS, not Unicode. 5 segments fill by weight. */
.wbar {
  display: inline-flex; gap: 2px; margin-left: 8px;
  vertical-align: middle;
}
.wbar .wseg {
  width: 12px; height: 8px; border-radius: var(--r-xs);   /* 12x8 weight segment - was 2px; the nearest rung, not squared */
  background: var(--line);
}
.wbar .wseg.on { background: var(--muted); }
.wbar-w5 .wseg.on { background: var(--accent); }
.wbar-w4 .wseg.on { background: var(--vio); }
.wbar-w3 .wseg.on { background: var(--muted); }
.wbar-w2 .wseg.on { background: var(--faint); }
.wbar-w1 .wseg.on { background: var(--faint); opacity: .7; }
/* Pull-distribution footer — relabelled + count + weight-sum */
.fdrv-footer {
  margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line);
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  font-size: 12px; color: var(--muted);
}
.fdrv-foot-l { font-weight: 600; display: inline-flex; gap: 4px; align-items: center; }
.fdrv-pull { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.fdrv-p {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: var(--r-xs);
  font-size: 12px; font-weight: 600;
  background: var(--bg2); border: 1px solid var(--line);
}
.fdrv-p-sym { font-family: var(--font-sans); }
.fdrv-p.bull { background: var(--bull-tint); color: var(--grn); border-color: var(--grn-dim); }
.fdrv-p.bear { background: var(--bear-tint); color: var(--red); border-color: var(--red-dim); }
.fdrv-p.cv   { background: var(--warn-tint); color: var(--amber); border-color: var(--amber); }
.fdrv-p.neu  { background: var(--bg2); color: var(--muted); }
.fdrv-warn {
  background: var(--red); color: var(--on-accent);
  padding: 2px 8px; border-radius: var(--r-xs); font-size: 11px; font-weight: 700;
  letter-spacing: .3px;
}

/* Phase 4 — Native <details> collapsible (Trade ticket, Scenarios) */
.p4-coll {
  margin: 10px 0;
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.p4-coll[open] > .p4-coll-sum { border-bottom: 1px solid var(--line); }
.p4-coll-sum {
  list-style: none; /* hide default disclosure marker */
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  cursor: pointer; user-select: none;
}
.p4-coll-sum::-webkit-details-marker { display: none; }
/* Replace with our own rotating caret */
.p4-coll-sum::before {
  content: "▸";
  font-size: 11px; color: var(--muted);
  transition: transform var(--dur-fast) var(--ease-out);
  display: inline-block;
}
.p4-coll[open] > .p4-coll-sum::before { transform: rotate(90deg); }
.p4-coll-l { font-weight: 600; letter-spacing: .3px; display: inline-flex; align-items: center; gap: 6px; }
.p4-coll-r {
  margin-left: auto; display: inline-flex; align-items: center; gap: 8px;
}
.p4-coll-b { padding: 10px 14px; }

/* T4.8 — Positions execution block (overrides applied via .pos-block.p4-coll) */
.pos-block .pos-hdr-t { font-weight: 600; letter-spacing: .3px; }
.pos-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
}
.pos-sec {
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 8px 10px; min-width: 0;        /* allow flex-grid children to shrink */
  overflow-wrap: anywhere;                /* prevent long words from overflowing */
}
.pos-sec-h {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .8px;
  color: var(--muted); margin-bottom: 6px;
  display: flex; align-items: center; gap: 5px;
}
/* Stance falsifier — promoted to its own section (was buried inside Fragility).
   Visually distinct so it reads as a "what would break this" block. */
.pos-sec-falsifier {
  border-left: 3px solid var(--amber);
  background: linear-gradient(to right, var(--warn-tint), var(--bg2) 80%);
}
.pos-sf-grid { display: flex; flex-direction: column; gap: 4px; }
.pos-sf-row { display: flex; gap: 8px; font-size: 12.5px; }
.pos-sf-k { color: var(--muted); min-width: 80px; font-weight: 600; }
.pos-sf-v { color: var(--txt); flex: 1; overflow-wrap: anywhere; }
.pos-sf-string { font-size: 12.5px; color: var(--txt); }
/* Hedge basket rows — explicit wrap so long "neutralises:" notes don't overflow. */
.pos-hedge { flex-wrap: wrap; }
.pos-hn { flex-basis: 100%; padding-left: 8px; }
.pos-kv {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 13px; line-height: 1.5;
}
.pos-k { color: var(--muted); }
.pos-v { font-family: var(--font-sans); }
.pos-tp, .pos-hedge {
  display: flex; gap: 6px; align-items: baseline; font-size: 12.5px;
  padding-top: 2px;
}
.pos-tp-p, .pos-hp { font-family: var(--font-sans); font-weight: 600; }
.pos-tp-w, .pos-hr { color: var(--accent); font-family: var(--font-sans); }
.pos-tp-sc, .pos-tp-h, .pos-hn { color: var(--muted); font-size: 11.5px; }
.pos-hd { padding: 0 5px; border-radius: var(--r-xs); font-size: 11px; }
.pos-hd.dir-long { background: var(--bull-tint); color: var(--grn); }
.pos-hd.dir-short { background: var(--bear-tint); color: var(--red); }
.pos-hc { color: var(--muted); font-family: var(--font-sans); font-size: 11.5px; }
.pos-audit {
  font-family: var(--font-sans); font-size: 11.5px; color: var(--muted);
  margin-top: 4px;
}
.pos-notes { font-size: 12px; color: var(--muted); margin-top: 4px; font-style: italic; }
.pos-frag {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-xs);
  font-size: 11.5px; font-weight: 600;
}
.pos-frag.frag-stable { background: var(--bull-tint); color: var(--grn); }
.pos-frag.frag-sensitive { background: var(--cell-hi); color: var(--accent); }
.pos-frag.frag-fragile { background: var(--warn-tint); color: var(--amber); }
.pos-frag.frag-stretched { background: var(--bear-tint); color: var(--red); }
.pos-falsifier {
  margin-top: 5px; font-size: 12px; color: var(--muted);
  background: var(--bg2); border-left: 3px solid var(--amber);
  padding: 4px 8px; border-radius: 0 var(--r-xs) var(--r-xs) 0;
}

/* T4.9 — Copy-ticket button */
.copy-ticket-btn {
  background: var(--accent); color: var(--on-accent); border: 0;
  border-radius: var(--r-xs); padding: 4px 10px; font-size: 12px; font-weight: 600;
}
.copy-ticket-btn:hover { filter: brightness(1.1); }

/* T4.4 — Scenario picker */
.scenario-picker {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  margin: 8px 0; padding: 4px 0;
}
.scenario-picker .sp-lbl { color: var(--muted); font-size: 12px; margin-right: 4px; }
.sp-pill {
  background: var(--bg2); border: 1px solid var(--line); color: var(--txt);
  border-radius: var(--r-pill); padding: 3px 10px; font-size: 12px;
}
.sp-pill.active {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
  font-weight: 600;
}
.sp-tail { margin-left: auto; color: var(--amber); font-size: 11.5px; }
.scenario-info {
  margin: 4px 0 12px; padding: 8px 12px;
  background: var(--bg2); border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: 12.5px;
}
.scenario-info .si-h { font-weight: 600; margin-bottom: 4px; }
.scenario-info .si-w { color: var(--accent); }
.scenario-info .si-stage { color: var(--muted); }
.scenario-info .si-rat,
.scenario-info .si-zone,
.scenario-info .si-fal,
.scenario-info .si-codes {
  margin-top: 3px; color: var(--muted);
}
.scenario-info .si-fal { color: var(--amber); }

/* T4.5 — Binary catalyst pills */
.binary-cats {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin: 6px 0; font-size: 12px;
}
.binary-cats .bc-lbl { color: var(--muted); }
.bc-tag {
  background: var(--bg2); border: 1px solid var(--vio); color: var(--vio);
  border-radius: var(--r-xs); padding: 2px 8px; font-family: var(--font-sans);
}

/* T4.4 — Scenario block — now wrapped in .p4-coll, so body styling lives here */
.scenarios-body { padding: 0; }

/* T4.10 — pairs view filter bar (default: in-book only) */
.pairs-filter {
  display: flex; gap: 8px; align-items: center;
  margin: 8px 0 16px; padding: 6px 0;
}
.pairs-filter .pairs-filter-l {
  font: 600 10px var(--font-mono); color: var(--colhead); text-transform: uppercase; letter-spacing: .1em;
}
.pairs-filter-btn {
  background: var(--bg2); border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-sm); padding: 4px 12px; font-size: 12.5px;
}
.pairs-filter-btn.active {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
  font-weight: 600;
}
.pairs-filter-btn:hover { color: var(--txt); }
.pairs-filter-btn.active:hover { color: var(--on-accent); filter: brightness(1.05); }

/* 2026-05-26 — extended filter bar (status + pair + chips: tier/persistence/setup) */
.pairs-filter.pairs-filter-rows {
  flex-direction: column; align-items: stretch;
  gap: 6px;
}
.pairs-filter-row {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.pairs-filter-sep {
  width: 1px; height: 18px; background: rgba(var(--hairline-rgb), .18); margin: 0 8px;
}
.pairs-filter-sel {
  background: var(--bg2); border: 1px solid var(--line); color: var(--txt);
  border-radius: var(--r-sm); padding: 3px 10px; font-size: 12.5px;
  font-family: inherit;
  appearance: none; -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 12px) 50%, calc(100% - 7px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 22px;
  cursor: pointer;
}
.pairs-filter-sel:hover { border-color: var(--accent); }
.pairs-filter-chip {
  background: var(--bg2); border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-xs); padding: 4px 10px; font-size: 11px;
  cursor: pointer;
  font-family: inherit;
}
.pairs-filter-chip:hover { color: var(--txt); border-color: var(--accent); }
.pairs-filter-chip.active {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
  font-weight: 600;
}
.pairs-filter-chip.active:hover { color: var(--on-accent); filter: brightness(1.05); }
.pairs-filter-reset {
  background: transparent; border: 1px dashed var(--line); color: var(--muted);
  border-radius: var(--r-sm); padding: 3px 10px; font-size: 12px;
  margin-left: auto;
  cursor: pointer;
  font-family: inherit;
}
.pairs-filter-reset:hover { color: var(--txt); border-color: var(--accent); }

/* 2026-06-10 — pairs watch alerts (bell + email-rule modal). The bell takes
   the right edge of Row 1; when Reset is also present it sits left of the
   bell (only the bell keeps the auto margin). */
.pairs-alerts-btn { margin-left: auto; cursor: pointer; font-family: inherit; }
.pairs-alerts-btn ~ .pairs-filter-reset { margin-left: 0; }
.pairs-alerts-modal { max-height: 84vh; overflow-y: auto; }
.pairs-sub-card {
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 10px 12px; margin: 10px 0;
}
.pairs-sub-card.off { opacity: .55; }
.pairs-sub-card .tr-modal-btns { margin-top: 8px; }
.pairs-sub-card-h { font-size: 13px; color: var(--txt); }
.pairs-sub-sum { font-size: 12px; margin-top: 4px; line-height: 1.45; }
.pairs-sub-pairgrid {
  max-height: 150px; overflow-y: auto; margin: -6px 0 14px;
  padding: 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
}
.pairs-sub-preview {
  font-size: 12px; margin: 10px 0 2px; line-height: 1.45;
}

/* ── Summary view ─────────────────────────────────────────────────────────
   Chronological change-ledger grouped by UTC date. Each row reuses the
   shared .row / .row-head / .row-body accordion; the only bespoke bits are
   the head's fixed-width date+day columns and the body's one-liner list. */
.sum-intro {
  color: var(--muted); font-size: 13px; line-height: 1.55;
  margin: 12px 4px 14px;
}
/* Each Summary day is a discrete bordered card (collapsed = hairline stack;
   open = accent border + raised surface), matching the design. */
#view-summary .row { border: 1px solid rgba(var(--hairline-rgb), .22); border-radius: 0;   /* collapsed days stack flush with their borders collapsed (see + .row below) - rounding each would pinch every join */ }
#view-summary .row + .row { border-top: none; }
#view-summary .row.open {
  border-color: var(--accent); background: var(--surface-raised); margin-bottom: 7px;
}
#view-summary .row-head { min-height: 0; padding: 11px 16px; gap: 14px; }
.row-head .sum-date {
  flex: 0 0 110px; font-family: var(--font-sans); font-weight: 500;
  font-size: 13px; color: var(--text);
}
.row-head .sum-dayname {
  flex: 0 0 30px; color: var(--muted); font-size: 11px;
}
.row-head .sum-count {
  flex: 1; color: var(--faint); font-size: 11px;
}
.sum-list { display: flex; flex-direction: column; gap: 0; padding: 6px 0 10px; }
.sum-line {
  font-size: 12px; line-height: 1.55; color: var(--txt);
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  padding: 5px 0; border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
}
.sum-line .sum-time {
  flex: 0 0 42px; font-family: var(--font-sans); font-size: 11px;
  color: var(--faint);
}
.sum-line .sum-entity {
  flex: 0 0 74px; font-family: var(--font-sans); font-weight: 500;
  font-size: 11.5px; color: var(--accent);
}
.sum-line .sum-change {
  font-size: 12px; color: var(--text); font-family: var(--font-sans);
}
.sum-line .sum-entity-link {
  cursor: pointer; border-bottom: 1px dotted transparent;
  outline: none;
}
.sum-line .sum-entity-link:hover,
.sum-line .sum-entity-link:focus { color: var(--accent); border-bottom-color: var(--accent); }

/* Summary entity popover — modal-style preview of the matching Pairs/
   Currencies row. Backdrop catches outside-clicks; the panel is wide enough
   to show the full row (head columns + body) without horizontal scroll on
   typical desktops, scrollable on smaller. */
.sum-pop-bd {
  position: fixed; inset: 0; background: var(--scrim);
  z-index: 200; display: flex; align-items: flex-start;
  justify-content: center; padding: 5vh 3vw; overflow-y: auto;
}
.sum-pop {
  background: var(--surface); border: 1px solid var(--frame-border);
  border-radius: var(--r-lg); box-shadow: var(--modal-shadow);
  max-width: 1400px; width: 100%; max-height: 90vh;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.sum-pop-h {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.sum-pop-t {
  font-family: var(--font-sans); font-weight: 700; font-size: 14px;
  color: var(--accent); letter-spacing: .5px;
}
.sum-pop-x {
  background: none; border: 0; color: var(--muted); font-size: 22px;
  line-height: 1; cursor: pointer; padding: 0 6px; border-radius: var(--r-sm);
}
.sum-pop-x:hover { color: var(--txt); background: var(--panel2); }
.sum-pop-inner {
  padding: 12px 14px 18px;
  overflow: auto; flex: 1 1 auto;
}

/* ── Setup pill (Currencies tab) ──────────────────────────────────────────────
   Playbook-rolled trade-readiness verdict. Solid pill so the verdict reads at
   a glance from across the table; dotted underline + cursor:help hint that
   the native title= tooltip carries the per-check breakdown. READY/PASS use
   solid fill (loud signal); WATCH/WAIT use outline (calmer, still distinct). */
.setup {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 64px; padding: 3px 11px;
  font-size: 11px; font-weight: 700; letter-spacing: .9px;
  font-family: var(--font-sans); border-radius: var(--r-pill);
  border: 1px solid var(--line2); background: var(--panel2); color: var(--muted);
  cursor: help; text-decoration: underline dotted transparent;
  text-underline-offset: 3px;
  /* text-decoration-color is a COLOUR property, so it belongs with `color` on the
     allow-list rather than off it — this is the dotted underline warming on hover,
     not a layout property being animated. */
  transition: text-decoration-color var(--dur-micro) var(--ease-out);
}
.setup:hover { text-decoration-color: currentColor; }
.setup-w { line-height: 1; }
.setup-ready {
  background: var(--grn-dim); border-color: var(--grn); color: var(--on-accent);
}
.setup-watch {
  background: transparent; border-color: var(--amber); color: var(--amber);
}
.setup-wait {
  background: transparent; border-color: var(--red-dim); color: var(--red);
}
.setup-pass {
  background: var(--red-dim); border-color: var(--red); color: var(--on-accent);
}

/* ── Playbook view ─────────────────────────────────────────────────────────────
   Step-by-step reading guide. Static content — no live data. Constrains
   line-length to ~74ch so the prose is comfortable; the rest of the site is
   institutional-scoreboard wide, this is a help document. Uses the same
   tokens as the rest of the app, with green/red/amber left-edge accents on the
   "good / pause / define" sub-blocks (same accent vocabulary as .fcard). */
#view-playbook { max-width: 880px; margin: 18px auto 60px; }

.pb-hero {
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--accent); border-radius: 0 var(--r-md) var(--r-md) 0; box-shadow: var(--shadow-1);
  padding: 22px 26px; margin: 0 0 18px;
}
.pb-hero-t {
  margin: 0 0 10px; font-size: 22px; letter-spacing: .3px; color: var(--txt);
}
.pb-hero-s {
  margin: 0 0 12px; color: var(--muted); font-size: 14px; line-height: 1.65;
}
.pb-hero-n {
  margin: 0; padding: 10px 14px;
  background: var(--bg2); border-left: 2px solid var(--line2);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 13px; color: var(--muted); line-height: 1.6;
}
.pb-hero-n b { color: var(--txt); font-weight: 600; }

.pb-step {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-1); padding: 0; margin: 0 0 14px; overflow: hidden;
}
.pb-step-h {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 18px 22px 14px; background: var(--panel2);
  border-bottom: 1px solid var(--line);
}
.pb-num {
  flex: 0 0 36px; height: 36px;
  display: grid; place-items: center;
  background: var(--bg2); color: var(--accent);
  border: 1px solid var(--line2); border-radius: 50%;
  font-family: var(--font-sans); font-weight: 700; font-size: 15px;
}
.pb-step-tw { flex: 1; min-width: 0; }
.pb-step-t {
  margin: 4px 0 4px; font-size: 17px; color: var(--txt); letter-spacing: .1px;
  font-weight: 600;
}
.pb-step-s {
  margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.6;
}
.pb-step-b { padding: 12px 22px 18px; display: flex; flex-direction: column; gap: 12px; }

/* "Where to look" — a small breadcrumb under the step title. */
.pb-where {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; background: var(--bg2);
  border: 1px dashed var(--line); border-radius: var(--r-sm);
}
.pb-where-l {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--faint); flex: 0 0 auto;
}
.pb-trail {
  display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.pb-crumb {
  font-family: var(--font-sans); font-size: 12px; color: var(--txt);
  background: var(--panel2); border: 1px solid var(--line2);
  border-radius: var(--r-xs); padding: 2px 8px;
}
.pb-sep { color: var(--faint); font-size: 12px; }

/* Sub-blocks: do / good (green) / pause (red) / define (neutral). Same
   left-edge accent vocabulary as .fcard. */
.pb-block {
  background: var(--bg2); border: 1px solid var(--line);
  border-left: 3px solid var(--line2); border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 10px 14px 12px;
}
.pb-block-l {
  font-size: 10px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--faint); margin-bottom: 6px;
}
.pb-block-t { color: var(--muted); font-size: 13.5px; line-height: 1.65; }
.pb-do      { border-left-color: var(--accent); }
.pb-do      .pb-block-l { color: var(--accent); }
.pb-good    { border-left-color: var(--grn); }
.pb-good    .pb-block-l { color: var(--grn); }
.pb-pause   { border-left-color: var(--red); }
.pb-pause   .pb-block-l { color: var(--red); }
.pb-define  { border-left-color: var(--amber); }
.pb-define  .pb-block-l { color: var(--amber); }

/* Bulleted lists inside good/pause blocks. Custom marker so the cadence
   matches the rest of the site (snode-bullets uses "·" too). */
.pb-list { list-style: none; margin: 0; padding: 0; }
.pb-list li {
  position: relative; padding-left: 18px; margin: 6px 0;
  color: var(--muted); font-size: 13.5px; line-height: 1.6;
}
.pb-list li::before {
  position: absolute; left: 4px; top: 0;
  content: "·"; color: var(--faint); font-weight: 700;
}
.pb-list.pb-good   li::before { color: var(--grn); }
.pb-list.pb-pause  li::before { color: var(--red); }

/* Definition list — term + gloss. Used for "what each column means" /
   "how to read the chart dots" / sizing scale. */
.pb-def {
  margin: 0; display: grid; grid-template-columns: 160px 1fr;
  column-gap: 14px; row-gap: 8px;
}
.pb-def dt {
  color: var(--txt); font-size: 13px; font-weight: 600;
  font-family: var(--font-sans); padding-top: 1px;
}
.pb-def dd { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.6; }

/* Closing tips & disclaimer block — same chrome as the hero. */
.pb-tips {
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--line2); border-radius: 0 var(--r-md) var(--r-md) 0; box-shadow: var(--shadow-1);
  padding: 20px 26px 22px; margin: 18px 0 0;
}
.pb-tips-t {
  margin: 14px 0 8px; font-size: 14px; color: var(--txt);
  letter-spacing: .2px;
}
.pb-tips-t:first-child { margin-top: 0; }
.pb-tips-l li { font-size: 13.5px; }
.pb-tips-d {
  margin: 10px 0 0; padding: 10px 14px;
  background: var(--bg2); border-left: 2px solid var(--line2);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  color: var(--muted); font-size: 12.5px; line-height: 1.65;
  font-style: italic;
}

/* — In-hero callout pointing to the new Setup pill column. Same chrome as
     .pb-hero-n but with extra room for the inline pills. */
.pb-hero-pill { margin-top: 10px; }
.pb-hero-pill .setup { margin: 0 2px; vertical-align: 1px; }

/* — Dedicated section explaining the Setup pill. Same chrome as a step card
     but no number-badge (it's a roll-up, not a check). */
.pb-pill-sec {
  background: var(--panel); border: 1px solid var(--line);
  border-left: 3px solid var(--accent); border-radius: 0 var(--r-md) var(--r-md) 0; box-shadow: var(--shadow-1);
  padding: 22px 26px; margin: 0 0 14px;
}
.pb-pill-h {
  margin: 0 0 10px; font-size: 17px; color: var(--txt);
  letter-spacing: .1px; font-weight: 600;
}
.pb-pill-l {
  margin: 0 0 16px; color: var(--muted); font-size: 13.5px; line-height: 1.65;
}
/* 4 level rows — chip on the left, meaning + action stacked on the right. */
.pb-pill-grid {
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px 14px; background: var(--bg2);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  margin-bottom: 18px;
}
.pb-pill-row {
  display: grid; grid-template-columns: 80px 1fr;
  column-gap: 14px; align-items: start; padding: 4px 0;
}
.pb-pill-row .setup { justify-self: start; cursor: default; }
.pb-pill-row .setup:hover { text-decoration-color: transparent; }
.pb-pill-body { display: flex; flex-direction: column; gap: 3px; }
.pb-pill-m { color: var(--txt); font-size: 13px; line-height: 1.55; }
.pb-pill-a {
  color: var(--muted); font-size: 12.5px; line-height: 1.55; font-style: italic;
}
.pb-pill-sh {
  margin: 14px 0 8px; font-size: 13px; color: var(--txt);
  letter-spacing: .3px; font-weight: 600;
}
.pb-pill-cav {
  margin: 18px 0 0; padding: 10px 14px;
  background: var(--bg2); border-left: 2px solid var(--line2);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  color: var(--muted); font-size: 12.5px; line-height: 1.65;
}
.pb-pill-cav b { color: var(--txt); font-weight: 600; font-style: normal; }

/* Narrow-screen: collapse the def list to single column so terms stack
   above their glosses instead of clipping. */
@media (max-width: 720px) {
  #view-playbook { padding: 0 12px; }
  .pb-step-h { padding: 14px 16px 12px; gap: 12px; }
  .pb-step-b { padding: 10px 16px 14px; }
  .pb-hero,
  .pb-tips,
  .pb-pill-sec { padding: 18px 18px; }
  .pb-def     { grid-template-columns: 1fr; row-gap: 4px; }
  .pb-def dd  { padding-bottom: 6px; }
  .pb-pill-row { grid-template-columns: 72px 1fr; column-gap: 10px; }
}

/* ── Track Record tab ──────────────────────────────────────────────────────
   Forward-only paper-position ledger. Open positions + historic closed
   positions + win rate. Reuses --grn / --red / --amber and the existing
   .chip / .dir-* / .mono / .muted / .faint tokens; just adds layout for
   the stats row, table, and filter chips. */
.tr-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 24px; margin: 18px 0 6px;
}
.tr-header-l { max-width: 820px; }
.tr-h { margin: 0 0 6px; font: 600 22px/1.1 var(--font-display); letter-spacing: -.015em; }
.tr-sub { margin: 0; font-size: 13px; line-height: 1.55; }
/* Right of the subtitle — model-management controls on top, dates below. */
.tr-header-r { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.tr-header-dates { font-family: var(--font-sans); font-size: 11px; text-align: right; color: var(--muted); }
.tr-stats {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 18px;
}
.tr-stat {
  background: var(--surface-kpi); border: 1px solid rgba(var(--hairline-rgb), .55);
  border-radius: var(--r-md); padding: 12px 14px; min-width: 120px; flex: 0 1 auto;
}
.tr-stat-l {
  font: 600 9px/1 var(--font-mono); color: var(--colhead); text-transform: uppercase;
  letter-spacing: .1em; margin-bottom: 7px;
}
.tr-stat-v {
  font-family: var(--font-sans); font-weight: 500; font-size: 19px; color: var(--text);
  letter-spacing: -.01em;
}
/* ── Track Record KPI grid (top big tiles + dense 8-col hairline strip) ── */
.tr-kpi-top { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 10px; }
@media (max-width: 900px) { .tr-kpi-top { grid-template-columns: repeat(3, 1fr); } }
.tr-kpi-tile { background: var(--surface-kpi); border: 1px solid rgba(var(--hairline-rgb), .55); padding: 12px 14px; }
.tr-kpi-tile-l { display: block; font: 600 9px var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 7px; }
.tr-kpi-tile-v { display: block; font: 500 19px var(--font-sans); letter-spacing: -.01em; color: var(--text); }
.tr-kpi-strip { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px; background: rgba(var(--hairline-rgb), .55); border: 1px solid rgba(var(--hairline-rgb), .55); margin-bottom: 22px; }
/* Second strip has 5 stats — stretch them across the full width (no empty cell). */
.tr-kpi-strip-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 900px) { .tr-kpi-strip, .tr-kpi-strip-5 { grid-template-columns: repeat(3, 1fr); } }
.tr-kpi-cell { background: var(--surface-kpi); padding: 9px 12px; }
/* A KPI cell carrying an explanatory tooltip — hint it with the help cursor. */
.tr-kpi-cell[title] { cursor: help; }
.tr-kpi-cell-l { display: block; font: 600 8.5px var(--font-mono); letter-spacing: .07em; text-transform: uppercase; color: var(--colhead); margin-bottom: 5px; }
.tr-kpi-cell-v { display: block; font: 500 14px var(--font-sans); color: var(--text); }
/* "Closed" cell — total count + a small W/L split (winners green, losers red). */
.tr-closed-wl { font-size: 11px; }
.tr-closed-wl .tr-wl-w { color: var(--bull-text); }
.tr-closed-wl .tr-wl-l { color: var(--bear-text); }
/* Open-positions section sub-caption (mono, faint) — the design's inline note. */
.tr-section-note { font: 400 10.5px var(--font-sans); color: var(--text-faint); letter-spacing: 0; text-transform: none; }
.tr-section-h {
  margin: 22px 0 8px; font: 600 11px var(--font-mono); letter-spacing: .1em;
  text-transform: uppercase; color: var(--text);
  display: flex; align-items: center; gap: 9px;
}
/* 2px × 13px accent bar the renderer prepends to each section header. */
.tr-section-h .tr-section-bar { flex: 0 0 auto; width: 2px; height: 13px; background: var(--accent); }
.tr-empty {
  padding: 18px; font-size: 13px; background: var(--surface);
  border: 1px dashed rgba(var(--hairline-rgb), .55); border-radius: var(--r-md);
}
.tr-table {
  background: var(--surface); border: 1px solid rgba(var(--hairline-rgb), .55);
  border-radius: var(--r-md); overflow: hidden;   /* only the FRAME rounds - .tr-tr / .tr-th cells stay square */
}
.tr-tr {
  display: grid; gap: 12px; align-items: center;
  padding: 0 12px; min-height: 40px; border-bottom: 1px solid rgba(var(--hairline-rgb), .22);
  font-size: 12.5px;
}
.tr-tr:last-child { border-bottom: 0; }
.tr-th {
  background: var(--surface-sunken); color: var(--colhead);
  min-height: 30px;
  font: 600 9px/1 var(--font-mono); text-transform: uppercase; letter-spacing: .07em;
  border-bottom: 1px solid rgba(var(--hairline-rgb), .80);
}
/* Header cells inherit the per-column .tr-c-* classes (tr-c-pair, tr-c-pnl,
   tr-c-exc, …) which each set their own font-size / font-family / weight — that
   bled into the header row and made the column titles look mismatched (some
   mono/13px, some 12.5px, some bold). Normalize EVERY header cell to one style;
   the two-class selector outranks the single-class .tr-c-* rules. Body cells
   (no .tr-th ancestor) keep their per-column styling. */
.tr-th .tr-c {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  color: var(--colhead);
  text-transform: uppercase;
  letter-spacing: .07em;
}
/* Sortable header cells: clickable, with a ▲/▼ caret on the active column (a
   faint ↕ otherwise). The two-class `.tr-th .tr-c-sortable` outranks the
   single-class `.tr-c-pair`'s flex AND ties `.tr-th .tr-c` (later source wins),
   so every header lays out label + caret in one row regardless of column. */
.tr-th .tr-c-sortable {
  display: flex; align-items: center; gap: 4px; flex-wrap: nowrap;
  cursor: pointer; user-select: none; -webkit-user-select: none;
}
.tr-th .tr-c-sortable:hover { color: var(--txt); }
.tr-th .tr-c-sortable.tr-sort-active { color: var(--txt); }
.tr-th .tr-c-sortable:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-xs);
}
/* Keep long labels (e.g. "Peak profit (MFE)") on one line in the narrow 1fr
   columns — truncate with an ellipsis rather than wrapping to a 2-line header
   (full text stays in the title + aria-label). */
.tr-sort-label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tr-sort-caret { font-size: 9px; line-height: 1; opacity: .35; flex: 0 0 auto; }
.tr-sort-caret-on { opacity: 1; color: var(--accent); }
/* Open positions table: Pair | Dir | Opened | Held | Entry | Mark | Unrealized |
   MFE | MAE (9 cols). Unrealized carries % · pips · $; MFE/MAE are the % only
   (pips/$/price/time in the hover title). */
.tr-table-open .tr-tr {
  grid-template-columns: 138px 96px 160px 72px 1fr 1fr 264px 1fr 1fr;
}
/* Closed positions table: Pair | Dir | Opened | Closed | Held | Entry | Exit |
   PnL | MFE | MAE | Reason (11 cols). */
.tr-table-closed .tr-tr {
  grid-template-columns:
    120px 110px 148px 148px 72px 1fr 1fr 252px 1fr 1fr 1.3fr;
}
.tr-c { min-width: 0; }
/* Pair cell holds the name + lots/double-down badges; flex-wrap so a badge drops
   to a new line inside the cell instead of bleeding into the next column. */
.tr-c-pair {
  font-weight: 600; font-size: 13px;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 1px 5px;
  overflow: hidden;
}
.tr-c-dir .chip { flex: 0 0 auto; }
.tr-c-date  { color: var(--muted); font-family: var(--font-sans); font-size: 10.5px; }
.tr-c-days  { color: var(--muted); font-size: 12.5px; font-family: var(--font-sans); }
.tr-c-price { font-size: 12px; }
.tr-c-pnl   { font-family: var(--font-sans); font-size: 11px; }
.tr-c-exc   { font-family: var(--font-sans); font-size: 10.5px; }
/* Excursion cell: % on top, pips · $ on a smaller second line. */
.tr-c-exc .tr-exc-top { line-height: 1.35; }
.tr-c-exc .tr-exc-sub { font-size: 11px; line-height: 1.35; }
.tr-c-reason { color: var(--muted); font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tr-pnl-pos { color: var(--grn); }
.tr-pnl-neg { color: var(--red); }
.tr-pnl-flat { color: var(--muted); }

/* Dollar accounting (v5): headline $ row, lots/tranche badge, double-down form. */
.tr-stats-usd { margin-bottom: 4px; }
.tr-stats-usd .tr-stat-v { font-size: 20px; }
.tr-lots {
  font-family: var(--font-sans); font-size: 10.5px; color: var(--muted);
  font-weight: 500; white-space: nowrap;
}
.tr-modal-num { max-width: 220px; }
.tr-dd-section { display: block; }
.tr-dd-body {
  margin-top: 8px; padding-left: 12px; border-left: 2px solid var(--line);
}
/* What-if view filter bar (exclude pairs from the displayed results) */
.tr-viewfilter {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 8px 0 4px; font-size: 12.5px;
}
.tr-viewfilter .tr-excl { display: inline-block; }
.tr-viewfilter .tr-excl-toggle { width: auto; }
.tr-viewfilter .tr-excl-panel { min-width: 260px; }
/* Exclude-pairs checkbox dropdown */
.tr-excl { display: block; }
.tr-excl-toggle { width: 100%; text-align: left; }
.tr-excl-panel {
  margin-top: 6px; max-height: 200px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 8px 10px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 4px 12px;
}
.tr-excl-row {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-sans); font-size: 12.5px; cursor: pointer; white-space: nowrap;
}

/* Attribution post-mortem — closed-trade expandable card */
.tr-row-clickable { cursor: pointer; }
.tr-row-clickable:hover { background: var(--bg2); }
.pm-chip {
  display: inline-flex; align-items: center; height: 17px;
  font: 600 9px var(--font-sans); letter-spacing: .04em;
  padding: 0 7px; border-radius: var(--r-xs); border: 1px solid; margin-right: 6px; white-space: nowrap;
}
.pm-good { background: var(--bull-tint); color: var(--bull-text); border-color: var(--bull-edge); }
.pm-bad  { background: var(--bear-tint); color: var(--bear-text); border-color: var(--bear-edge); }
.pm-warn { background: var(--warn-tint); color: var(--warn-text); border-color: var(--warn-edge); }
.pm-neu  { background: var(--bg2); color: var(--muted); border-color: var(--line); }
.tr-pm {
  padding: 14px 18px; background: var(--bg2);
  border-bottom: 1px solid var(--line); font-size: 13px; line-height: 1.5;
}
.tr-pm-verdict { margin-bottom: 6px; }
.tr-pm-rat { color: var(--muted); font-size: 12px; }
.tr-pm-summary { font-weight: 600; margin-bottom: 6px; }
.tr-pm-p { color: var(--txt); margin: 4px 0; max-width: 74ch; }
.tr-pm-toggle { margin-top: 8px; color: var(--accent); cursor: pointer; font-size: 12px; user-select: none; }
.tr-pm-numbers { margin-top: 8px; padding: 8px 10px; background: var(--panel); border-radius: var(--r-xs);   /* steps down inside .tr-detail-pm (--r-sm) */ }
.tr-pm-rh { font-size: 11px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); margin: 6px 0 2px; }
.tr-pm-li { font-family: var(--font-sans); font-size: 12px; margin: 1px 0; }

/* Per-position detail panel (price chart + entries list), expanded on row click.
   Full-width block appended to .tr-table as a sibling of the rows. */
.tr-detail {
  padding: 16px 18px; background: var(--bg2);
  border-top: 1px solid var(--accent-dim);
  border-bottom: 1px solid var(--line);
}
.tr-detail:last-child { border-bottom: 0; }
/* Entries (tranche) table — one row per leg (base + double-down adds). */
.tr-en-h {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); font-weight: 600; margin: 0 0 7px;
}
.tr-entries {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-sm); overflow: hidden;   /* frame only; .tr-en-row cells stay square */
}
.tr-en-row {
  display: grid; grid-template-columns: 1.4fr 70px 110px 160px 130px 90px;
  gap: 10px; align-items: center; padding: 8px 12px;
  border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.tr-en-row:last-child { border-bottom: 0; }
.tr-en-th {
  background: var(--bg2); color: var(--muted);
  font-size: 9px; text-transform: uppercase; letter-spacing: .07em; font-weight: 600;
}
.tr-en-c { min-width: 0; }
.tr-en-label { display: flex; align-items: center; gap: 7px; font-weight: 500; }
.tr-en-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.tr-en-dot-base { background: var(--accent); }
.tr-en-dot-add { background: var(--warn-dot); }
/* Excursion (MFE/MAE) block inside the detail panel — peak profit & max DD. */
.tr-exc-block { margin-top: 14px; }
.tr-exc-sub { font-size: 11.5px; margin: 0 0 7px; line-height: 1.4; }
.tr-exc {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-sm); overflow: hidden;   /* frame only; .tr-exc-row cells stay square */
}
.tr-exc-row {
  display: grid; grid-template-columns: 1.4fr 1.6fr 1.4fr;
  gap: 10px; align-items: center; padding: 9px 12px;
  border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.tr-exc-row:last-child { border-bottom: 0; }
.tr-exc-l { display: flex; align-items: center; gap: 7px; font-weight: 600; }
.tr-exc-l::before {
  content: ""; width: 9px; height: 9px; border-radius: var(--r-xs); flex: 0 0 auto;
}
.tr-exc-mfe::before { background: var(--bull-text); }
.tr-exc-mae::before { background: var(--bear-text); }
.tr-exc-meta { font-size: 11.5px; text-align: right; }
/* Chart section inside the detail panel — reuses .esec-chart/.ppc-* styling. */
.tr-detail .tr-chart { margin-top: 14px; }
/* Closed-trade detail: chart LEFT + attribution RIGHT (design 1.5fr / 1fr),
   below the full-width entries + excursion blocks. */
.tr-detail-grid {
  display: grid; grid-template-columns: 1.5fr 1fr; gap: 20px;
  align-items: start; margin-top: 14px;
}
/* Chart sits flush in its grid column — drop the .esec section separator + its
   own top margin (the grid owns the spacing). */
.tr-detail-grid > .esec-chart { margin-top: 0; border-top: 0; padding-top: 0; }

/* Attribution card (design): left-accent + faint tint coloured by verdict. */
.tr-detail-pm {
  margin: 0; padding: 13px 15px; border: 0; border-radius: 0 var(--r-sm) var(--r-sm) 0;
  border-left: 2px solid var(--text-faint); background: var(--surface-raised);
}
.tr-detail-pm.tr-pmc-good {
  border-left-color: var(--bull-dot); background: var(--bull-tint);
  background: color-mix(in srgb, var(--bull-text) 7%, transparent);
}
.tr-detail-pm.tr-pmc-bad {
  border-left-color: var(--bear-dot); background: var(--bear-tint);
  background: color-mix(in srgb, var(--bear-text) 7%, transparent);
}
.tr-detail-pm.tr-pmc-warn {
  border-left-color: var(--warn-dot); background: var(--warn-tint);
  background: color-mix(in srgb, var(--warn-text) 7%, transparent);
}
.tr-detail-pm.tr-pmc-neu { border-left-color: var(--text-faint); background: var(--surface); }
/* Card internals — match the design typography 1:1. */
.tr-detail-pm .tr-pm-verdict { margin-bottom: 10px; }
.tr-detail-pm .pm-chip { height: 18px; font-size: 9.5px; margin: 0; }
.tr-detail-pm .tr-pm-summary { font: 600 13px var(--font-display); color: var(--text); margin: 0 0 8px; }
.tr-detail-pm .tr-pm-p { font: 12px/1.6 var(--font-sans); color: var(--text-2); margin: 0 0 8px; max-width: none; }
.tr-detail-pm .pp-rat { font: 11.5px/1.55 var(--font-sans); color: var(--text-muted); margin: 0 0 10px; }
.tr-detail-pm .tr-pm-toggle { margin: 0; font: 11px var(--font-sans); color: var(--accent); }
.tr-detail-pm .tr-pm-numbers { margin-top: 10px; }

/* Outcome Attribution card (spec §8) — the closed-trade taxonomy. Nested inside
   the post-mortem box (or standalone in .tr-oa-wrap when there is no post-mortem);
   theme-agnostic, reuses the desk colour vars. */
.tr-oa-wrap { padding: 0; }
.tr-oa {
  margin: 12px 0 0; padding: 11px 12px 4px; border-radius: 0 var(--r-xs) var(--r-xs) 0;
  border-top: 1px solid var(--line2);
  border-left: 2px solid var(--text-faint);
}
.tr-oa.tr-oa-good { border-left-color: var(--bull-dot); }
.tr-oa.tr-oa-bad  { border-left-color: var(--bear-dot); }
.tr-oa.tr-oa-warn { border-left-color: var(--warn-dot); }
.tr-oa.tr-oa-neu  { border-left-color: var(--text-faint); }
.tr-oa-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 7px; }
.tr-oa-class {
  /* square for the same reason as .tr-oa-chip below */
  border-radius: 0;
  font: 700 11px var(--font-mono); text-transform: uppercase; letter-spacing: .4px;
  padding: 2px 8px; border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--text-faint) 16%, transparent); color: var(--text);
}
.tr-oa-cls-good { background: color-mix(in srgb, var(--bull-text) 16%, transparent); color: var(--bull-text); }
.tr-oa-cls-bad  { background: color-mix(in srgb, var(--bear-text) 16%, transparent); color: var(--bear-text); }
.tr-oa-cls-warn { background: color-mix(in srgb, var(--warn-text) 18%, transparent); color: var(--warn-text); }
.tr-oa-r { font: 600 12px var(--font-sans); color: var(--text-2); }
.tr-oa-conf, .tr-oa-src { font: 10.5px var(--font-sans); color: var(--text-muted); }
.tr-oa-src { margin-left: auto; text-transform: uppercase; letter-spacing: .3px; }
.tr-oa-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.tr-oa-chip {
  font: 11px var(--font-sans); color: var(--text-2);
  /* Square: .tr-oa is already at the bottom rung (--r-xs), so a chip inside it
     has nowhere to step down to except 0. A child at its parent's radius reads
     as a mistake. */
  padding: 2px 7px; border-radius: 0;
  background: color-mix(in srgb, var(--text-faint) 10%, transparent);
}
.tr-oa-chip-k { font-size: 9.5px; text-transform: uppercase; letter-spacing: .3px; margin-right: 3px; }
.tr-oa-reason { font: 12px/1.6 var(--font-sans); color: var(--text-2); margin: 0 0 8px; }
.tr-oa-list { margin: 0 0 8px; padding: 0; list-style: none; }
.tr-oa-list li { font: 11.5px/1.55 var(--font-sans); margin: 2px 0; }
.tr-oa-worked li { color: var(--bull-text); }
.tr-oa-failed li { color: var(--bear-text); }
.tr-oa-recs li { color: var(--text-2); }

/* Track Record — Lessons (Learning Engine, spec §9) */
.tr-lessons { margin-top: 14px; border-top: 1px solid var(--line2); padding-top: 10px; }
.tr-lessons-toggle { font: 12px var(--font-sans); color: var(--accent); cursor: pointer; user-select: none; }
.tr-lessons-body { margin-top: 10px; }
.tr-lessons-grid { display: flex; flex-direction: column; gap: 14px; }
.lr-summary { font: 11.5px var(--font-sans); margin-bottom: 2px; }
.lr-block-h { font: 600 12px var(--font-display); color: var(--text); margin: 0 0 6px; }
.lr-table { display: table; width: 100%; border-collapse: collapse; font: 11.5px var(--font-sans); }
.lr-tr { display: table-row; }
.lr-th, .lr-td { display: table-cell; padding: 3px 8px 3px 0; border-bottom: 1px solid var(--line); vertical-align: middle; }
.lr-thead .lr-th { font-size: 9.5px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); }
.lr-td { color: var(--text-2); }
.lr-chip { font: 10px var(--font-sans); padding: 1px 6px; border-radius: var(--r-xs); white-space: nowrap;
  background: color-mix(in srgb, var(--text-faint) 14%, transparent); color: var(--text-2); }
.lr-good { background: color-mix(in srgb, var(--bull-text) 16%, transparent); color: var(--bull-text); }
.lr-bad  { background: color-mix(in srgb, var(--bear-text) 16%, transparent); color: var(--bear-text); }
.lr-warn { background: color-mix(in srgb, var(--warn-text) 18%, transparent); color: var(--warn-text); }
.lr-neu  { background: color-mix(in srgb, var(--text-faint) 14%, transparent); color: var(--text-muted); }
.lr-rec { padding: 7px 0; border-bottom: 1px solid var(--line); }
.lr-rec-head { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-bottom: 3px; }
.lr-rec-subj { font: 600 11.5px var(--font-sans); color: var(--text); text-transform: capitalize; }
.lr-rec-n { font: 10px var(--font-sans); margin-left: auto; }
.lr-rec-text { font: 11.5px/1.55 var(--font-sans); color: var(--text-2); }
.lr-wf { margin: 0; padding: 0; list-style: none; }
.lr-wf li { font: 11px/1.5 var(--font-sans); margin: 1px 0; }
.lr-worked li { color: var(--bull-text); }
.lr-failed li { color: var(--bear-text); }

.tr-filters {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px; margin: 6px 0 10px; font-size: 12.5px;
}
.tr-filter-sep { color: var(--faint); margin: 0 2px; }
.tr-filter-in {
  background: var(--bg2); border: 1px solid var(--line2); color: var(--txt);
  border-radius: var(--r-sm); padding: 5px 12px; font-size: 12.5px;
  outline: none; width: 180px;
}
.tr-filter-in:focus { border-color: var(--accent); }
.tr-filter-btn {
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-sm); padding: 5px 12px; font-size: 12px;
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.tr-filter-btn.active {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
}
.tr-filter-btn:hover:not(.active) { color: var(--txt); border-color: var(--line2); }
.tr-filter-reset {
  background: transparent; border: 1px solid var(--line); color: var(--red);
  border-radius: var(--r-sm); padding: 5px 12px; font-size: 12px; margin-left: auto;
}
.tr-filter-reset:hover { border-color: var(--red-dim); }

/* ── Track Record model tab strip + manager controls ── */
/* A faint rule separates the strip from the KPI grid below. */
.tr-modelbar {
  margin: 6px 0 16px; padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
/* Single row — all models on one line; scroll sideways to reach the rest.
   Thin, sharp, hairline scrollbar themed to match the site (accent on hover). */
.tr-modeltabs {
  display: flex; flex-wrap: nowrap; gap: 2px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(var(--hairline-rgb), 1) transparent;
}
.tr-modeltabs::-webkit-scrollbar { height: 8px; }
.tr-modeltabs::-webkit-scrollbar-track { background: transparent; }
.tr-modeltabs::-webkit-scrollbar-thumb { background: rgba(var(--hairline-rgb), .18); border-radius: 0;   /* deliberately sharp: an 8px hairline scrollbar thumb (see the note above) */ }
.tr-modeltabs::-webkit-scrollbar-thumb:hover { background: var(--accent); }
/* One card per model — name (+ ⭐/🔔 badges) over a WR / return / DD stats line.
   Borderless, content-width, never shrinks (the row scrolls); active = gold
   underline + raised tint + brighter name. */
.tr-modeltab {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 7px 14px 8px; cursor: pointer; text-align: left; white-space: nowrap;
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  border-radius: 0;   /* underline tab - the 2px bottom rule is the control */
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.tr-modeltab:hover:not(.active) { background: var(--bg2); }
.tr-modeltab.active { background: var(--panel2); border-bottom-color: var(--warn-dot); }
.tr-mtab-name {
  display: flex; align-items: center; gap: 5px;
  font: 600 12.5px/1.1 var(--font-sans); color: var(--text-muted); white-space: nowrap;
}
.tr-modeltab.active .tr-mtab-name { color: var(--text); }
.tr-modeltab.archived .tr-mtab-name { opacity: .55; font-style: italic; }
.tr-mtab-stats {
  display: flex; align-items: center; gap: 6px;
  font: 500 11px/1 var(--font-mono); font-variant-numeric: tabular-nums;
}
.tr-mtab-wr      { color: var(--colhead); }
.tr-mtab-ret.pos { color: var(--bull-text); }
.tr-mtab-ret.neg { color: var(--bear-text); }
.tr-mtab-dd      { color: var(--bear-text); }
/* ⭐/🔔 badges inside a card name — drop the hairline separator the pill carries
   elsewhere; just a small gap. */
.tr-mtab-name .tr-modeltab-star,
.tr-mtab-name .tr-modeltab-bell {
  margin-left: 2px; padding-left: 0; border-left: 0; font-size: 11px; opacity: 1;
}

/* Per-model subscribe bell + favorite star pills (also reused in the header
   manage cluster for the selected model). */
.tr-modeltab-bell {
  margin-left: 1px; padding-left: 7px; border-left: 1px solid var(--line);
  font-size: 12px; line-height: 1; opacity: .6; cursor: pointer;
  transition: opacity var(--dur-micro) var(--ease-out);
}
.tr-modeltab-bell:hover { opacity: 1; }
.tr-modeltab-bell.on { opacity: 1; }
.tr-modeltab-star {
  margin-left: 1px; padding-left: 7px; border-left: 1px solid var(--line);
  font-size: 12px; line-height: 1; opacity: .6; cursor: pointer;
  transition: opacity var(--dur-micro) var(--ease-out);
}
.tr-modeltab-star:hover { opacity: 1; }
.tr-modeltab-star.on { opacity: 1; }

/* ── Compare lens — side-by-side model comparison (the "Compare" AI-lens segment).
   A multi-select picker (cards carry an AI badge + current return) over a metric-row
   × model-column grid. Differing rule rows are highlighted; the best value in each
   performance row is green-marked. The grid scrolls horizontally inside its wrapper;
   the metric-label column stays pinned. ── */
.tr-cmp-head { margin: 6px 0 4px; }
.tr-cmp-sub { max-width: 780px; margin: 0 0 16px; }
.tr-cmp-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px; }
.tr-cmp-toolbar-r { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-left: auto; }
.tr-cmp-search {
  flex: 0 1 240px; padding: 6px 10px; font: 400 12.5px var(--font-sans); color: var(--text);
  background: var(--surface-kpi); border: 1px solid rgba(var(--hairline-rgb), .80); border-radius: var(--r-sm);
}
.tr-cmp-search:focus { outline: none; border-color: var(--accent); }
.tr-cmp-filters { display: flex; flex-wrap: wrap; gap: 4px; }
.tr-cmp-chip {
  padding: 4px 10px; font: 500 11px var(--font-sans); cursor: pointer; color: var(--text-muted);
  background: transparent; border: 1px solid rgba(var(--hairline-rgb), .80); border-radius: var(--r-xs);
}
.tr-cmp-chip:hover { color: var(--text); }
.tr-cmp-chip.on { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.tr-cmp-count { font: 500 11.5px var(--font-sans); color: var(--text-muted); }
.tr-cmp-capnote { font: 400 11px var(--font-sans); color: var(--bear-text); }
.tr-cmp-clear {
  padding: 4px 10px; font: 500 11px var(--font-sans); cursor: pointer; color: var(--text-muted);
  background: transparent; border: 1px solid rgba(var(--hairline-rgb), .80); border-radius: var(--r-sm);
}
.tr-cmp-clear:hover { color: var(--text); border-color: var(--accent); }
/* picker card list */
.tr-cmp-list {
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 20px; padding: 2px 2px 16px;
  max-height: 240px; overflow-y: auto; border-bottom: 1px solid var(--line);
}
.tr-cmp-card {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 7px 12px; cursor: pointer; text-align: left; white-space: nowrap; border-radius: var(--r-sm);
  background: var(--surface-kpi); border: 1px solid rgba(var(--hairline-rgb), .55);
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.tr-cmp-card:hover { border-color: var(--accent); }
.tr-cmp-card.tr-cmp-sel { border-color: var(--accent); background: var(--panel2); box-shadow: inset 0 0 0 1px var(--accent); }
.tr-cmp-card.tr-cmp-dis { opacity: .4; cursor: not-allowed; }
.tr-cmp-tick { color: var(--accent); font-weight: 700; margin-right: 4px; }
.tr-cmp-none { padding: 12px; font-size: 12.5px; }
/* metric-row × model-column grid */
.tr-cmp-gridwrap { overflow-x: auto; }
.tr-cmp-grid {
  display: grid; gap: 1px; min-width: min-content;
  background: rgba(var(--hairline-rgb), .55); border: 1px solid rgba(var(--hairline-rgb), .55);
}
.tr-cmp-corner { background: var(--surface); position: sticky; left: 0; z-index: 2; }
.tr-cmp-colh { position: relative; background: var(--surface-kpi); padding: 10px 26px 10px 12px; }
.tr-cmp-colh-name { font: 600 12.5px var(--font-sans); color: var(--text); white-space: normal; }
.tr-cmp-colh-ai { font: 500 10.5px var(--font-sans); color: var(--accent); margin-top: 3px; }
.tr-cmp-colx {
  position: absolute; top: 6px; right: 6px; width: 16px; height: 16px; line-height: 14px; padding: 0;
  font-size: 13px; cursor: pointer; color: var(--text-faint); background: transparent; border: 0;
}
.tr-cmp-colx:hover { color: var(--bear-text); }
.tr-cmp-sech {
  background: var(--surface); padding: 8px 12px; color: var(--colhead);
  font: 600 10px var(--font-mono); letter-spacing: .09em; text-transform: uppercase;
}
.tr-cmp-metric {
  background: var(--surface); padding: 8px 12px; position: sticky; left: 0; z-index: 1;
  font: 500 11.5px var(--font-sans); color: var(--text-muted); white-space: nowrap;
}
.tr-cmp-cell {
  background: var(--surface-kpi); padding: 8px 12px; white-space: nowrap;
  font: 500 12px var(--font-mono); color: var(--text); font-variant-numeric: tabular-nums;
}
.tr-cmp-cell.hl { background: var(--diff-hi); color: var(--text-2); }
.tr-cmp-cell.tr-cmp-best { background: var(--bull-tint); color: var(--bull-text); font-weight: 700; }
.tr-cmp-empty { margin-top: 8px; }

/* Header manage cluster — model controls right of the subtitle. */
.tr-manage {
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 6px;
}
.tr-manage .tr-modeltab-star,
.tr-manage .tr-modeltab-bell {
  margin-left: 0; padding-left: 0; border-left: 0; font-size: 14px; opacity: .8;
}
.tr-manage .tr-modeltab-star.on,
.tr-manage .tr-modeltab-bell.on { opacity: 1; }

.tr-model-btn {
  background: transparent; border: 1px solid var(--line2); color: var(--text-2);
  border-radius: var(--r-sm); padding: 5px 11px; font: 500 11px var(--font-sans); cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.tr-model-btn:hover:not(.active) { color: var(--txt); border-color: var(--line2); }
.tr-model-btn.active { background: var(--panel2); color: var(--txt); border-color: var(--line2); }
.tr-model-btn-pri { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.tr-model-btn-pri:hover { color: var(--on-accent); border-color: var(--accent); opacity: .92; }
.tr-model-btn-pri:disabled { opacity: .6; cursor: default; }
.tr-model-btn-danger { color: var(--red); }
.tr-model-btn-danger:hover { border-color: var(--red-dim); color: var(--red); }

/* ── Track Record email subscription popover (bell lives per-pill above) ── */
.tr-sub-modal { max-width: 420px; }
.tr-sub-note { margin: 0 0 12px; font-size: 12.5px; }

/* ── create / edit model modal ── */
.tr-modal-scrim {
  position: fixed; inset: 0; background: var(--scrim);
  display: flex; align-items: flex-start; justify-content: center;
  z-index: 50; padding: 40px 16px; overflow-y: auto;
}
.tr-modal {
  background: var(--panel); border: 1px solid var(--line2); border-radius: var(--r-lg);
  width: 100%; max-width: 540px; padding: 22px 24px;
  box-shadow: var(--modal-shadow);
}
.tr-modal-h { margin: 0 0 14px; font-size: 16px; color: var(--txt); }
.tr-modal-field { margin: 0 0 14px; }
.tr-modal-label {
  display: block; font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); margin-bottom: 6px;
}
.tr-modal-in {
  width: 100%; background: var(--bg2); border: 1px solid var(--line2); color: var(--txt);
  border-radius: var(--r-sm); padding: 8px 11px; font-size: 13px; outline: none; box-sizing: border-box;
}
.tr-modal-in:focus { border-color: var(--accent); }
.tr-modal-ta { min-height: 58px; resize: vertical; font-family: inherit; }
.tr-modal-knobs { margin: 4px 0 0; }
.tr-chiprow { display: flex; flex-wrap: wrap; gap: 6px; }
.tr-chip {
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-xs); padding: 5px 11px; font-size: 12px; cursor: pointer;
  font-family: var(--font-sans); transition: border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.tr-chip:hover { color: var(--txt); border-color: var(--line2); }
.tr-chip.on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.tr-modal-check { display: block; font-size: 12.5px; color: var(--txt); margin: 8px 0; cursor: pointer; }
.tr-modal-err {
  background: var(--bear-tint); border: 1px solid var(--red-dim); color: var(--red);
  border-radius: var(--r-md); padding: 8px 11px; font-size: 12.5px; margin: 6px 0 0;
}
.tr-modal-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* Expand-to-modal button on the pair chart (sits with the timeframe pills). */
.esec-chart .ppc-pill.ppc-expand { font-family: var(--font-sans); letter-spacing: .02em; }
/* Expanded pair price chart modal — wider panel, taller chart host. */
.ppc-modal-scrim { align-items: center; }
.ppc-modal { max-width: 1180px; width: 92vw; padding: 16px 18px; }
.ppc-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 6px;
}
.ppc-modal-head .tr-modal-h { margin: 0; }
.ppc-modal-x {
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-sm); width: 26px; height: 26px; line-height: 1; font-size: 13px;
  cursor: pointer; flex: 0 0 auto;
}
.ppc-modal-x:hover { color: var(--txt); border-color: var(--line2); }
.ppc-modal .esec-chart { margin: 0; padding: 0; border-top: 0; }
.ppc-modal .esec-chart .ppc-heading { display: none; }   /* modal head carries the title */
.ppc-modal .esec-chart .ppc-host { height: 70vh; }

/* ── Take-profit + re-entry: leg rows, badges, explainer drawer ── */
.tr-tp-legs { display: flex; flex-direction: column; gap: 6px; margin: 4px 0; }
.tr-tp-leg {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 12px; color: var(--muted);
}
.tr-tp-leg input { width: 70px; }
.tr-tp { color: var(--grn) !important; }
.tr-sl { color: var(--amber) !important; }
.tr-so { color: var(--grn) !important; opacity: .85; }
.tr-ts-exit { color: var(--muted) !important; }
.tr-reentry { color: var(--accent) !important; }
.tr-ts-exphint { font-size: 11.5px; color: var(--muted); margin: 4px 0 2px; line-height: 1.4; }
.tr-tphelp-btn { margin-top: 6px; font-size: 12px; }
/* Read-only take-profit config shown on the EDIT form (create-only feature). */
.tr-tp-ro-note { font-size: 11.5px; color: var(--muted); margin-bottom: 6px; }
.tr-tp-ro-line {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 12.5px; padding: 4px 0; border-bottom: 1px solid var(--line);
}
.tr-tp-ro-label { color: var(--muted); }
.tr-tp-ro-val { color: var(--txt); font-family: var(--font-sans); }
.tr-tphelp-scrim {
  position: fixed; inset: 0; background: var(--scrim);
  display: flex; justify-content: flex-end; z-index: 60;
}
.tr-tphelp {
  background: var(--panel); border-left: 1px solid var(--line2);
  width: 100%; max-width: 470px; height: 100%; overflow-y: auto;
  padding: 20px 22px; box-sizing: border-box;
  box-shadow: var(--drawer-shadow);
}
.tr-tphelp-head {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px;
}
.tr-tphelp-h { margin: 0; font-size: 15px; color: var(--txt); }
.tr-tphelp-x {
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  border-radius: var(--r-sm); padding: 3px 9px; font-size: 13px; cursor: pointer;
}
.tr-tphelp-x:hover { color: var(--txt); border-color: var(--line2); }
.tr-tphelp-preview {
  background: var(--bg2); border: 1px solid var(--line2); border-radius: var(--r-md);
  padding: 12px 14px; margin-bottom: 16px;
}
.tr-tphelp-sub {
  font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); margin-bottom: 8px;
}
.tr-tphelp-ctl { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
.tr-tphelp-ctl .tr-modal-field { margin: 0; }
.tr-tphelp-out { font-family: var(--font-sans); font-size: 12px; color: var(--txt); }
.tr-tphelp-line { padding: 5px 0; border-bottom: 1px solid var(--line); line-height: 1.45; }
.tr-tphelp-re { color: var(--accent); }
.tr-tphelp-note { color: var(--muted); font-style: italic; padding: 5px 0; line-height: 1.45; }
.tr-tphelp-warn { color: var(--red); padding: 5px 0; line-height: 1.45; }
.tr-tphelp-sect { margin-top: 14px; }
.tr-tphelp-explain h4 { font-size: 12.5px; color: var(--txt); margin: 14px 0 5px; }
.tr-tphelp-explain p { font-size: 12.5px; color: var(--muted); line-height: 1.55; margin: 0 0 8px; }

/* ── Mirror to MT5 modal ── */
.tr-mt5-modal { max-width: 640px; }
.tr-modal-input {
  width: 100%; background: var(--bg2); border: 1px solid var(--line2); color: var(--txt);
  border-radius: var(--r-sm); padding: 8px 11px; font-size: 13px; outline: none; box-sizing: border-box;
}
.tr-modal-input:focus { border-color: var(--accent); }
.tr-mt5-body { display: block; }
.tr-mt5-h {
  margin: 18px 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); border-bottom: 1px solid var(--line); padding-bottom: 5px;
}
.tr-mt5-banner {
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 8px 11px; font-size: 12px; color: var(--muted); margin: 0 0 10px;
}
.tr-mt5-banner.warn { background: var(--bear-tint); border-color: var(--red-dim); color: var(--red); }
.tr-mt5-linkrow, .tr-mt5-acctrow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 0; border-bottom: 1px solid var(--line);
}
.tr-mt5-linkhead { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12.5px; }
.tr-mt5-acct { color: var(--txt); font-weight: 600; }
.tr-mt5-pill {
  font-family: var(--font-mono); font-size: 11px; padding: 2px 8px; border-radius: var(--r-pill);
  border: 1px solid var(--line2); color: var(--muted); text-transform: uppercase; letter-spacing: .3px;
}
.tr-mt5-pill-dry_run { color: var(--muted); }
.tr-mt5-pill-demo { color: var(--accent); border-color: var(--accent); }
.tr-mt5-pill-live { color: var(--on-accent); background: var(--red); border-color: var(--red); }
.tr-mt5-pill-kill { color: var(--on-accent); background: var(--red); border-color: var(--red); }
.tr-mt5-pill-confirm { color: var(--warn-text); border-color: var(--warn-text); }
.tr-mt5-err { color: var(--red); font-size: 11.5px; }
.tr-mt5-linkbtns { display: flex; gap: 6px; flex-shrink: 0; }
/* Phase-7 human-confirmation: staged-open approvals panel below a link row. */
.tr-mt5-pending, .tr-mt5-limits { margin: 2px 0 10px; padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--r-md); }
.tr-mt5-pendrow {
  display: flex; align-items: center; gap: 8px; padding: 5px 0;
  border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.tr-mt5-pendrow:last-child { border-bottom: 0; }
.tr-mt5-pendsym { font-family: var(--font-sans); color: var(--txt); flex: 1; }
.tr-mt5-live {
  margin: 4px 0 8px; padding: 8px 11px; border: 1px solid var(--red-dim);
  border-radius: var(--r-md); background: var(--bear-tint);
}
.tr-mt5-reg { margin-top: 12px; }
.tr-mt5-regsum { cursor: pointer; font-size: 12.5px; color: var(--accent); padding: 6px 0; }

/* ── MT5 accounts overview modal ── */
/* Read-only: every model grouped under the account it mirrors to. Reuses the
   Mirror modal's pills and account styling so one link reads identically on
   both surfaces; only the layout is new. */
.tr-mt5o-modal { max-width: 720px; }
.tr-mt5o-group { margin: 16px 0 0; }
.tr-mt5o-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding-bottom: 6px; border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.tr-mt5o-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  width: 100%; text-align: left; padding: 9px 0; margin: 0;
  border: 0; border-bottom: 1px solid var(--line); background: none;
  color: var(--txt); font: inherit; font-size: 12.5px;
}
.tr-mt5o-row-pick { cursor: pointer; }
.tr-mt5o-row-pick:hover .tr-mt5o-name { color: var(--accent); }
.tr-mt5o-name { font-weight: 600; }
.tr-mt5o-empty { color: var(--muted); font-size: 12.5px; padding: 9px 0; }
.tr-mt5o-note { margin: 18px 0 0; color: var(--muted); font-size: 11.5px; line-height: 1.55; }

/* ── MT5 accounts lens (Track Record) ── */
/* A real broker account rendered inside a page of simulated ledgers, so the
   layout borrows the KPI tiles and table frame but never the wording: the
   scope line and the broker chip sit ABOVE the first figure, where a reader
   meets them before the numbers. */
.tr-mt5live-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 10px;
}
.tr-mt5live-lab {
  font: 600 9px var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
  color: var(--colhead);
}
.tr-mt5live-select {
  background: var(--bg2); border: 1px solid var(--line2); color: var(--txt);
  border-radius: var(--r-sm); padding: 7px 10px; font-size: 13px; outline: none;
  max-width: 100%; min-width: 260px;
}
.tr-mt5live-select:focus { border-color: var(--accent); }
.tr-mt5live-stamp {
  margin-left: auto; font-family: var(--font-mono); font-size: 11px;
  color: var(--muted); cursor: help;
}
.tr-mt5live-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; font-size: 11.5px; }
.tr-mt5live-scope { margin: 4px 0 12px; font-size: 12px; line-height: 1.6; color: var(--muted); }
.tr-mt5live-health:empty { display: none; }
.tr-mt5live-defer { margin: 0 0 8px; font-size: 11.5px; line-height: 1.5; }
.tr-mt5live-by { font-weight: 600; }
.tr-mt5live-note { margin: 16px 0 0; font-size: 11.5px; line-height: 1.55; }
/* Symbol | Dir | Lots | Opened | Entry | Now | Stop | Target | P&L | Opened by. */
.tr-table-mt5live .tr-tr {
  grid-template-columns: 1.3fr 96px 64px 150px 1fr 1fr 1fr 1fr 1.1fr 1.5fr;
}
/* "Opened by" carries a model name AND, when something is wrong with its link,
   a KILLED / paused / dry_run pill. .tr-c-reason otherwise ellipsises on one
   line, which between 760px and 1100px clipped the pill off the end — hiding a
   warning about a real position on the one screen built to show it. Let it wrap
   instead; the row grows rather than the warning disappearing. */
.tr-table-mt5live .tr-c-reason {
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px;
  white-space: normal; overflow: visible; text-overflow: clip;
  padding: 4px 0;
}
@media (max-width: 1100px) {
  .tr-table-mt5live .tr-tr {
    grid-template-columns: 110px 92px 56px 1fr 1fr 1fr 1fr 1fr 1fr 1.3fr;
    font-size: 12.5px;
  }
}

.tr-warnings {
  margin: 18px 0 0; padding: 12px 16px;
  background: var(--bg2); border: 1px solid var(--line); border-radius: var(--r-md);
  font-size: 12px;
}
.tr-warning-list { margin: 6px 0 0; padding-left: 20px; }
.tr-warning-list li { line-height: 1.5; }

@media (max-width: 1100px) {
  /* On narrow screens collapse low-information columns rather than hard-wrapping. */
  .tr-header { flex-direction: column; }
  .tr-header-r { align-items: flex-start; }
  .tr-header-dates { text-align: left; }
  .tr-manage { justify-content: flex-start; }
  .tr-table-open .tr-tr {
    grid-template-columns: 80px 100px 1fr 70px 1fr 1fr 1fr 1fr 1fr;
    font-size: 12.5px;
  }
  .tr-table-closed .tr-tr {
    grid-template-columns: 80px 100px 1fr 1fr 70px 1fr 1fr 1fr 1fr 1fr 1.2fr;
    font-size: 12.5px;
  }
}

/* ── Per-pair suggested hedge (offset trade + size ladder) ── */
/* Suggested-hedge card (design): bordered card · micro-label header · offset
   leg row · rationale · full-width calm/elevated/crash regime bar. */
.ph {
  border: 1px solid var(--accent-dim);
  background: var(--surface);
  border-radius: var(--r-md);
  margin: 14px 0;
}
.ph-h {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 12px; border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
}
.ph-t { font: 600 10px/1 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--text-2); }
/* offset leg — the hedge trade itself */
.ph-offset {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 11px 12px; border-radius: 0;   /* bare row: transparent, border 0 - nothing to round */ background: transparent; border: 0;
}
.ph-dir {
  font: 600 9px/1 var(--font-sans); padding: 3px 8px; border-radius: var(--r-xs); letter-spacing: .04em;
}
.ph-dir.dir-long  { background: var(--bull-tint); color: var(--bull-text); border: 1px solid var(--bull-edge); }
.ph-dir.dir-short { background: var(--bear-tint); color: var(--bear-text); border: 1px solid var(--bear-edge); }
.ph-pair  { font-family: var(--font-sans); font-weight: 500; font-size: 12.5px; color: var(--text); }
.ph-ratio { font-family: var(--font-sans); font-size: 11.5px; color: var(--accent); background: transparent; border-radius: 0;   /* bare mono text, no fill and no padding */ padding: 0; }
.ph-corr  { font-family: var(--font-sans); font-size: 10.5px; color: var(--text-faint); margin-left: auto; }
.ph-why   { font-size: 11px; color: var(--text-muted); margin: 0; padding: 0 12px 10px; line-height: 1.55; }
.ph-none  { font-style: italic; }
/* regime bar — full-width 3 segments, active one accent-filled */
.ph-ladder { display: flex; gap: 1px; margin: 0; background: rgba(var(--hairline-rgb), .55); border-top: 1px solid rgba(var(--hairline-rgb), .55); }
.ph-ladder-l { display: none; }
.ph-step {
  flex: 1; display: inline-flex; align-items: baseline; justify-content: center; gap: 5px;
  background: var(--surface); border: 0; border-radius: 0;   /* full-bleed segmented footer of .ph - the segments span edge to edge */ padding: 7px 0; font-size: 11px;
}
.ph-step-k { color: var(--text-muted); text-transform: capitalize; }
.ph-step-v { font-family: var(--font-sans); color: var(--text-muted); }
.ph-step-now { background: var(--accent); }
.ph-step-now .ph-step-k, .ph-step-now .ph-step-v { color: var(--on-accent); font-weight: 500; }
/* Sits ABOVE the % ladder now (grouped with the rationale) — bottom padding. */
.ph-ladder-note { font-size: 11px; color: var(--text-muted); padding: 0 12px 10px; line-height: 1.4; }

/* Trade & price | Stance falsifier — 2-col grid below the suggested hedge
   (the design's fragility|falsifier slot). */
.pair-tf-grid { display: grid; grid-template-columns: 1fr 1.3fr; gap: 12px; margin: 14px 0 0; }
.pair-tf-grid-1 { grid-template-columns: 1fr; }
/* Both cells share the Stance-falsifier styling — warn border + left accent,
   warn header, muted body (user wanted Trade & price to match the falsifier). */
.pair-tf-cell {
  margin: 0; background: var(--surface); padding: 11px 12px;
  border: 1px solid var(--warn-edge); border-left: 2px solid var(--warn-dot);
}
.pair-tf-cell .esec-h { margin: 0 0 7px; color: var(--warn-text); }
.pair-tf-cell .esec-sub { color: var(--text-muted); }
.pair-fals-prose { font-size: 11px; line-height: 1.55; color: var(--text-muted); margin: 0 0 8px; }
.pair-fals-meta { display: flex; flex-wrap: wrap; gap: 16px; font: 10.5px var(--font-sans); }
.pair-fals-mk { color: var(--text-muted); }
.pair-fals-mv { color: var(--text); }

/* Scenarios — non-collapsible: a tab per scenario + the selected detail card
   (design exact: sharp pills, accent-filled active tab, left-accent card). */
.scn-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.scn-tab {
  font: 500 10.5px var(--font-sans); color: var(--text-muted);
  background: transparent; border: 1px solid rgba(var(--hairline-rgb), .80);
  border-radius: var(--r-sm); padding: 4px 9px; cursor: pointer; white-space: nowrap;
}
.scn-tab:hover { border-color: var(--accent); color: var(--text-2); }
.scn-tab.active {
  color: var(--on-accent); background: var(--accent); border-color: var(--accent);
}
.scn-card { border-left: 2px solid var(--accent); background: var(--surface); padding: 11px 13px; }
.scn-title { font: 600 11.5px var(--font-sans); color: var(--text); margin: 0 0 8px; }
.scn-sub { margin-bottom: 7px; }
.scn-sub:last-child { margin-bottom: 0; }
.scn-k {
  font: 9px var(--font-mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--colhead);
}
.scn-sub-warn .scn-k { color: var(--warn-text); }
.scn-v { font: 11.5px/1.55 var(--font-sans); color: var(--text-muted); margin: 3px 0 0; }
.scn-v-mono { font-family: var(--font-sans); line-height: 1.4; color: var(--text-2); }
.scn-v-warn { color: var(--warn-text); line-height: 1.5; }
.ph-assumed { font-size: 11px; color: var(--text-faint); padding: 7px 12px 10px; font-style: italic; margin: 0; }

/* per-pair hedge_basket stress fields (positionsBlock) */
.pos-hc-stress { color: var(--accent); }
.pos-hc-decay { color: var(--red); font-weight: 600; }
.pos-hsv { font-size: 11px; padding: 1px 6px; border-radius: var(--r-xs); margin-left: 4px; }
.pos-hsv.ok   { color: var(--grn-soft-fg); background: var(--grn-bg); }
.pos-hsv.warn { color: var(--warn-fg);     background: var(--warn-bg); }

/* ── AI compare (Claude vs the shadow models: Gemini, Grok) ───────────────── */
.aibar {
  display: flex; align-items: center; gap: 7px; padding: 14px 0 4px; margin: 0;
}
.aibar-inline { margin: 4px 0 8px; }
.aibar-seg {
  border: 1px solid rgba(var(--hairline-rgb), .80); background: transparent; color: var(--text-muted);
  padding: 5px 13px; border-radius: var(--r-pill); cursor: pointer;
  font: 500 11.5px/1 var(--font-sans);
}
.aibar-seg:hover { color: var(--text); }
.aibar-seg.active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.aibar-updated {
  margin-left: auto; display: flex; align-items: center; gap: 7px;
  font: 400 11.5px/1 var(--font-sans); color: var(--text-muted);
}
.aibar-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--bull-dot);
  animation: gmPulse var(--dur-shimmer) var(--ease-shimmer) infinite;
}
/* The canonical "live" pulse. Indefinite ambient attention, not a transition
   or a one-shot reveal, so the "nothing runs longer than --dur-slow" rule does
   not bind it — it rides the shimmer tier alongside the loading bar. */
@keyframes gmPulse { 0%,100% { opacity: 1 } 50% { opacity: .3 } }
.ai-note {
  margin: 0 0 12px; padding: 8px 12px; border-left: 3px solid var(--accent);
  background: var(--panel); color: var(--muted); font-size: 12.5px;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.aidiff-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
@media (max-width: 760px) { .aidiff-grid { grid-template-columns: 1fr; } }
.aidiff-card {
  border: 1px solid rgba(var(--hairline-rgb), .55); background: var(--surface-raised);
  padding: 0; margin: 0;
}
.aidiff-ent {
  display: flex; align-items: center; gap: 8px; margin: 0;
  padding: 9px 13px; border-bottom: 1px solid rgba(var(--hairline-rgb), .55);
}
.aidiff-code { font: 500 13px var(--font-sans); color: var(--text); }
/* Column count is set inline via --aidiff-n (Claude + each present shadow model). */
.aidiff-cols { display: grid; gap: 0; }   /* JS sets grid-template-columns inline to repeat(<#models>,1fr) */
.aidiff-col {
  display: flex; flex-direction: column; padding: 10px 12px;
  border-right: 1px solid rgba(var(--hairline-rgb), .22);
}
.aidiff-col:last-child { border-right: none; }
.aidiff-who {
  font: 600 8.5px var(--font-mono); text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-faint); margin-bottom: 7px;
}
.aidiff-tok { display: block; font: 400 11px var(--font-sans); color: var(--text-muted); padding: 3px 7px; margin-bottom: 5px; }
.aidiff-tok.hl { background: var(--diff-hi); color: var(--text-2); font-weight: 400; }
.aidiff-sub, .aidiff-head {
  font: 600 10px var(--font-mono); text-transform: uppercase;
  letter-spacing: .12em; color: var(--text-2); margin: 20px 0 10px;
}
.aidiff-sub:first-child, .aidiff-head:first-child { margin-top: 0; }
.aidiff-na { font: 400 11px var(--font-sans); color: var(--text-muted); font-style: italic; padding: 3px 7px; }
.aidiff-only { font: 600 8.5px var(--font-mono); text-transform: uppercase; letter-spacing: .1em; }
.aidiff-verdict { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 12px; }
.aidiff-verdict-h {
  background: none; border: none; color: var(--accent); font-weight: 700;
  font-size: 13px; cursor: pointer; padding: 0;
}
.aidiff-verdict-b { margin-top: 10px; }
/* ── AI Consensus ("Agree / Disagree" tab) ───────────────────────────────── */
.consensus-intro {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 6px 0 14px; color: var(--text-muted); font-size: 12.5px;
}
.consensus-intro .aibar-updated { margin-left: auto; }
.consensus-block {
  margin: 0 0 16px; padding: 12px 14px;
  border-left: 3px solid rgba(var(--hairline-rgb), .80); background: var(--surface-raised);
}
.consensus-agree    { border-left-color: var(--grn-soft-fg); }
.consensus-disagree { border-left-color: var(--warn-fg); }
.consensus-h {
  font: 600 10px var(--font-mono); text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-2); margin: 0 0 8px;
}
.consensus-sentence { font: 400 13.5px/1.5 var(--font-sans); color: var(--text); margin: 0 0 10px; }
.consensus-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.consensus-chip {
  font: 500 11.5px var(--font-sans); padding: 3px 9px; border-radius: var(--r-xs);
  border: 1px solid rgba(var(--hairline-rgb), .80); color: var(--text-muted);
}
.consensus-chip.agree { background: var(--grn-bg); color: var(--grn-soft-fg); border-color: transparent; }
/* Not compared. Deliberately neutral — a coverage gap is neither an agreement
   nor a disagreement, and colouring it either way is the misread being fixed. */
.consensus-uncovered { border-left-color: rgba(var(--hairline-rgb), 1); }
.consensus-chip.uncovered {
  background: transparent; color: var(--text-muted);
  border-style: dashed; border-color: rgba(var(--hairline-rgb), 1);
}
/* Alignment headline % + graded 3-segment meter (aligned / partial / opposed). */
.consensus-hero {
  display: flex; align-items: center; gap: 20px;
  margin: 0 0 18px; padding: 14px 16px;
  background: var(--surface-raised); border: 1px solid rgba(var(--hairline-rgb), .55);
}
.consensus-scorebox { display: flex; flex-direction: column; align-items: center; min-width: 92px; }
.consensus-score { font: 700 34px/1 var(--font-sans); color: var(--text); letter-spacing: -.02em; }
.consensus-score-label {
  font: 600 9px var(--font-mono); text-transform: uppercase; letter-spacing: .14em;
  color: var(--text-faint); margin-top: 6px; text-align: center;
}
.consensus-meterwrap { flex: 1; min-width: 0; }
.consensus-meter {
  display: flex; height: 12px; width: 100%; overflow: hidden;
  background: var(--surface-sunken);
}
.consensus-seg { min-width: 2px; }
.consensus-seg.aligned { background: var(--grn-soft-fg); }
.consensus-seg.partial { background: var(--accent); }
.consensus-seg.opposed { background: var(--red); }
.consensus-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; }
.consensus-leg { display: flex; align-items: center; gap: 6px; font: 500 11.5px var(--font-sans); color: var(--text-muted); }
.consensus-dot { width: 9px; height: 9px; display: inline-block; }
.consensus-leg.aligned .consensus-dot { background: var(--grn-soft-fg); }
.consensus-leg.partial .consensus-dot { background: var(--accent); }
.consensus-leg.opposed .consensus-dot { background: var(--red); }
.consensus-bucket-h {
  font: 600 10px var(--font-mono); text-transform: uppercase; letter-spacing: .1em;
  margin: 16px 0 10px;
}
.consensus-bucket-h.partial { color: var(--accent); }
.consensus-bucket-h.opposed { color: var(--red); }
.consensus-badge {
  font: 600 9.5px var(--font-sans); padding: 2px 6px; margin-left: auto;
  letter-spacing: .02em;
}
.consensus-badge.partial { background: var(--accent-dim); color: var(--accent); }
.consensus-badge.opposed { background: var(--red-bg); color: var(--red); }
/* Pairs-card AI-agreement chip variants (plan Phase 6) — pill-shaped so it sits
   with the other right-edge chips; margin-left:auto from the base rule is
   overridden (the chip group flexes, the summary expands). */
.consensus-badge[class*="cons-"] {
  margin-left: 6px; flex: 0 0 auto; align-self: center;
  border-radius: var(--r-pill); padding: 2px 8px; border: 1px solid var(--line); cursor: help;
}
.consensus-badge.cons-aligned { color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge); }
.consensus-badge.cons-partial { background: var(--accent-dim); color: var(--accent); }
.consensus-badge.cons-opposed { background: var(--red-bg); color: var(--red); }
@media (max-width: 520px) {
  .consensus-hero { flex-direction: column; align-items: flex-start; gap: 12px; }
  .consensus-scorebox { flex-direction: row; gap: 10px; align-items: baseline; min-width: 0; }
}
.tr-ai-badge {
  margin: 0 0 12px; padding: 6px 10px; border-radius: var(--r-md);
  background: var(--accent-dim); color: var(--txt); font-size: 12.5px; font-weight: 600;
}

/* ── Spec 2 — macro-buckets level/speed panel (Currencies view) ── */
.mb-panel { margin: 14px 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--panel); }
.mb-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.mb-h { font: 700 12.5px/1.3 var(--font-sans); color: var(--txt); letter-spacing: .02em; }
.mb-sub { font: 500 11px/1.3 var(--font-sans); color: var(--text-2); flex: 1 1 100%; }
.mb-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: -2px 0 9px; }
.mb-leg-k { color: var(--text-muted); font: 500 10px/1.3 var(--font-sans); }
.mb-leg-k::before { content: "·"; margin-right: 6px; color: var(--text-2); }
/* ONE grid on the container (rows are display:contents) so columns align across
   every row AND size to content — code | growth | inflation | nuance. Tiles are
   content-width (justify-self:start), so the speed word sits next to its value
   instead of being flung to a far-right edge by a 1fr-stretched tile. */
.mb-grid { display: grid; grid-template-columns: 40px 190px 190px 1fr;
  align-items: center; column-gap: 12px; row-gap: 5px; }
.mb-row { display: contents; }
.mb-code { font: 700 12px/1.3 var(--font-sans); color: var(--text-muted); cursor: help; text-align: center; }
/* Equal-width Growth/Inflation columns; tile fills its column and centres content. */
.mb-tile { display: flex; align-items: baseline; justify-content: center; gap: 6px; padding: 3px 9px; border-radius: var(--r-sm);
  border: 1px solid var(--line); font: 500 11.5px/1.4 var(--font-sans); cursor: help; }
.mb-tile-l { color: var(--text-2); font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.mb-tile-z { font-weight: 700; font-variant-numeric: tabular-nums; }
.mb-tile-spd { color: var(--text-2); font-size: 10.5px; }
.mb-prov { color: var(--text-muted); font-size: 9.5px; letter-spacing: .02em; }
.mb-nuance-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; justify-self: start; }
.mb-nuance { font: 500 10.5px/1.3 var(--font-sans); color: var(--warn-text); cursor: help; }
/* Shared soft provenance marker (only shown for non-[DATA] reads). */
.prov-tag { color: var(--text-muted); font: 500 9px/1.3 var(--font-sans); letter-spacing: .02em;
  border: 1px solid var(--line); border-radius: var(--r-xs); padding: 0 4px; margin-left: 4px; cursor: help; }
/* z-sign tints: positive (growth/inflation high) = bull family, negative = bear. */
.mb-z-pos2 { background: var(--bull-tint); border-color: var(--bull-edge); color: var(--bull-text); }
.mb-z-pos1 { background: var(--bull-tint); border-color: var(--bull-edge); }
.mb-z-neg2 { background: var(--bear-tint); border-color: var(--bear-edge); color: var(--bear-text); }
.mb-z-neg1 { background: var(--bear-tint); border-color: var(--bear-edge); }
.mb-z-neu, .mb-z-na { background: transparent; }

/* ── Spec 3 — real rates & liquidity panel (Currencies view) ── */
/* ── "On its own terms" panel ──────────────────────────────────────────────
   The absolute per-currency read that sits under the vs-USD Bias column. Shares
   the .rr-panel container language deliberately: it is the same KIND of thing (a
   deterministic, no-model enrichment strip), so it should not look like a new
   feature competing for attention. Colour carries the sign only. */
.os-panel { margin: 0 0 14px; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--panel); }
.os-h { font: 700 12.5px/1.3 var(--font-sans); color: var(--txt); letter-spacing: .02em; margin: 0 0 6px; }
.os-lead { font: 500 11.5px/1.55 var(--font-sans); color: var(--text-2); margin: 0 0 8px; max-width: 78ch; }
.os-lead-sm { font-size: 10.5px; color: var(--text-muted); }
.os-row { border-top: 1px solid var(--line); padding: 7px 0 5px; }
.os-row:first-of-type { border-top: 0; }
.os-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.os-code { font: 700 12px/1.3 var(--font-sans); color: var(--txt); min-width: 34px; }
.os-lean { font: 600 10.5px/1.3 var(--font-mono); text-transform: uppercase; letter-spacing: .04em;
  padding: 2px 7px; border: 1px solid var(--line); }
.os-strong { background: var(--bull-tint); border-color: var(--bull-edge); color: var(--bull-text); }
.os-firm   { background: var(--bull-tint); border-color: var(--bull-edge); color: var(--bull-text); opacity: .82; }
.os-bal    { background: transparent; color: var(--text-muted); }
.os-soft   { background: var(--bear-tint); border-color: var(--bear-edge); color: var(--bear-text); opacity: .82; }
.os-weak   { background: var(--bear-tint); border-color: var(--bear-edge); color: var(--bear-text); }
.os-comp { font: 700 11.5px/1.3 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--text-2); }
.os-counts { font: 500 10.5px/1.4 var(--font-sans); color: var(--text-muted); }
.os-cov { font: 600 10px/1.3 var(--font-mono); color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .04em; border: 1px dashed var(--line); padding: 1px 5px; }
.os-axes { display: flex; flex-direction: column; gap: 3px; padding: 4px 0 2px; }
.os-axis { display: flex; align-items: baseline; gap: 8px; }
.os-axis-n { font: 600 10.5px/1.4 var(--font-sans); color: var(--text-2); min-width: 108px; }
.os-axis-b { font: 500 10.5px/1.5 var(--font-sans); color: var(--text-muted); flex: 1 1 auto; }
.os-chip { font: 700 10px/1.3 var(--font-mono); font-variant-numeric: tabular-nums;
  min-width: 26px; text-align: center; padding: 1px 4px; border: 1px solid var(--line); }
.os-pos  { background: var(--bull-tint); border-color: var(--bull-edge); color: var(--bull-text); }
.os-neg  { background: var(--bear-tint); border-color: var(--bear-edge); color: var(--bear-text); }
.os-flat { color: var(--text-muted); }
.os-gap  { color: var(--text-muted); border-style: dashed; }
.os-foot { font: 500 10px/1.5 var(--font-sans); color: var(--text-muted); margin-top: 8px;
  padding-top: 6px; border-top: 1px solid var(--line); }

.rr-panel { margin: 0 0 14px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--panel); }
.rr-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.rr-h { font: 700 12.5px/1.3 var(--font-sans); color: var(--txt); letter-spacing: .02em; }
.rr-sub { font: 500 11px/1.3 var(--font-sans); color: var(--text-2); flex: 1 1 100%; }
.rr-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: -2px 0 9px; }
.rr-leg-k { color: var(--text-muted); font: 500 10px/1.3 var(--font-sans); }
.rr-leg-k::before { content: "·"; margin-right: 6px; color: var(--text-2); }
/* Same container-grid + display:contents pattern as macro-buckets; the three
   element columns are EQUAL-WIDTH and their contents are centred. */
.rr-grid { display: grid; grid-template-columns: 44px 175px 175px 175px;
  align-items: center; column-gap: 14px; row-gap: 5px; }
.rr-row { display: contents; }
.rr-code { font: 700 12px/1.3 var(--font-sans); color: var(--text-muted); cursor: help; text-align: center; }
.rr-tile { display: flex; align-items: baseline; justify-content: center; gap: 6px; padding: 3px 9px; border-radius: var(--r-sm);
  border: 1px solid var(--line); font: 500 11.5px/1.4 var(--font-sans); cursor: help; }
.rr-tile-l { color: var(--text-2); font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.rr-tile-v { font-weight: 700; font-variant-numeric: tabular-nums; }
.rr-pos { background: var(--bear-tint); border-color: var(--bear-edge); }   /* high real = tight/restrictive */
.rr-neg { background: var(--bull-tint); border-color: var(--bull-edge); }   /* negative real = accommodative */
.rr-neu, .rr-na { background: transparent; }
.rr-lead { font: 600 10.5px/1.3 var(--font-sans); color: var(--text-2); cursor: help; text-align: center; }
.rr-dash { color: var(--text-muted); text-align: center; }
.rr-liq { font: 600 10.5px/1.4 var(--font-sans); padding: 1px 8px; border-radius: var(--r-xs);
  border: 1px solid var(--line); white-space: nowrap; cursor: help; text-align: center; }
.rr-liq-drain { color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge); }
.rr-liq-ease  { color: var(--bull-text); background: var(--bull-tint); border-color: var(--bull-edge); }
.rr-liq-neu   { color: var(--text-2); background: transparent; }

/* ── Part-H failure-mode strip (Drivers tab, FAILURE_MODE_WATCH_ENABLED) ── */
.drv-fmw-strip { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 4px 0 10px; }
.drv-fmw-chip {
  padding: 2px 8px; border-radius: var(--r-xs); border: 1px solid var(--line);
  font: 700 10.5px/1.4 var(--font-sans); letter-spacing: .03em; cursor: help;
}
.drv-fmw-chip.md-strip-hot  { color: var(--bear-text); background: var(--bear-tint); border-color: var(--bear-edge); }
.drv-fmw-chip.md-strip-warm { color: var(--warn-text); background: var(--warn-tint); border-color: var(--warn-edge); }
.drv-fmw-chip.md-strip-cool { color: var(--text-2); }

/* ── Exit-signal audit section (Track Record tab, EXIT_AUDIT_ENABLED) ── */
.tr-exit-audit { margin: 14px 0 6px; }
.tr-exit-audit .tr-table { margin-bottom: 10px; }
.tr-exit-audit-vs { margin-top: 6px; }
.tr-exit-headline {
  font: 600 12px/1.5 var(--font-sans); margin: 4px 0 8px; color: var(--text-2);
}

/* ── Expectation-group chip (Fable S1-4, pair card head) ── */
.expect-chip {
  flex: 0 0 auto; align-self: center; margin-left: 6px; padding: 2px 8px;
  border-radius: var(--r-xs); font: 700 10.5px/1.4 var(--font-sans); letter-spacing: .03em;
  white-space: nowrap; border: 1px solid var(--line); cursor: help;
  color: var(--text-2); background: transparent;
}

/* ── Spec 4 — data-vs-pricing gap block ── */
.gap-sec { border-left: 3px solid var(--accent, var(--bull-edge)); padding-left: 9px; }
.gap-sec .esec-h { color: var(--accent, var(--txt)); }
/* Flowing plain-English prose (feedback 2026-06-29 — replaced the terse
   Data:/Priced:/Gap: label rows). */
.gap-read { margin-top: 3px; font: 400 11.5px/1.5 var(--font-sans); color: var(--text-muted); }
.gap-meta { margin-top: 4px; font: 400 10.5px/1.45 var(--font-sans); color: var(--faint, var(--text-muted)); }
/* The size sits as a chip on the header rather than as a clause in the prose
   (feedback 2026-07-13 — the read is short now; the size is a glance, not a
   sentence). The desk-voice detail folds away below it — kept, not deleted. */
.gap-size { margin-left: 7px; padding: 1px 5px; border: 1px solid var(--line); border-radius: var(--r-xs);
            font: 500 9.5px/1.4 var(--font-mono); color: var(--text-2); letter-spacing: .04em; text-transform: uppercase; }
.gap-more { margin-top: 6px; font: 500 10px/1.4 var(--font-sans); color: var(--text-2); cursor: pointer; user-select: none; }
.gap-more:hover { color: var(--txt); }
.gap-detail { margin-top: 5px; border-top: 1px solid var(--line); padding-top: 5px; }
.gap-detail[hidden] { display: none; }  /* explicit — a stray `div { display: block }` would beat the UA [hidden] rule */
.gap-drow { margin-top: 5px; font: 400 10.5px/1.5 var(--font-sans); color: var(--text-muted); }
.gap-dlab { display: block; font: 600 9.5px/1.4 var(--font-mono); color: var(--text-2); letter-spacing: .04em; text-transform: uppercase; }

/* ── Spec 5 — factor-stripped alpha bar (pairs card + Track Record verdict) ── */
.alpha-sec { }
.alpha-bar { display: flex; height: 8px; border-radius: 0;   /* full-bleed 8px meter, clipped by overflow:hidden - the pinstripe class */ overflow: hidden; margin: 4px 0 5px; border: 1px solid var(--line); }
.alpha-seg { height: 100%; }
.alpha-beta { background: var(--text-muted); }          /* broad market (systematic beta) */
.alpha-alpha { background: var(--accent, var(--bull-dot)); }  /* pair-specific (idiosyncratic alpha) */
/* Plain-English legend + read line (feedback 2026-06-29 — the raw field dump
   was unreadable; suppress [DATA], key the split by colour, explain in prose). */
.alpha-legend { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 6px; font: 500 10.5px/1.3 var(--font-sans); color: var(--text-muted); }
.alpha-leg { display: inline-flex; align-items: center; gap: 5px; }
.alpha-leg::before { content: ""; width: 9px; height: 9px; display: inline-block; border-radius: 0;   /* 9x9 legend swatch: it keys the square bar above, so it stays square too */ }
.alpha-leg-beta::before  { background: var(--text-muted); }
.alpha-leg-alpha::before { background: var(--accent, var(--bull-dot)); }
.alpha-read { font: 400 11.5px/1.5 var(--font-sans); color: var(--text-muted); }
.tr-pm-alpha { max-width: 320px; }

/* ── Move Attribution — numbers-vs-non-numerical split + per-driver breakdown ── */
/* Reuses the .alpha-bar/.alpha-seg/.alpha-legend/.alpha-read meter; only the segment
   semantics differ (Numbers = the informative/bright segment). Palette-var driven —
   no new colours; theme-aware for free. */
.ma-sub { font: 500 11px/1.4 var(--font-sans); color: var(--text-2); margin: 1px 0 6px; }
.ma-sub-2 { color: var(--text-muted); font-size: 10.5px; margin: 6px 0 0; }
.ma-seg-numbers  { background: var(--accent, var(--bull-dot)); }   /* explained by the numbers */
.ma-seg-residual { background: var(--text-muted); }                /* non-numerical remainder */
.ma-leg-numbers::before  { background: var(--accent, var(--bull-dot)); }
.ma-leg-residual::before { background: var(--text-muted); }
.ma-drivers { display: flex; flex-direction: column; gap: 3px; margin: 2px 0 6px; }
.ma-drv { display: flex; align-items: center; gap: 7px; font: 500 11px/1.4 var(--font-sans); }
.ma-drv-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); }
.ma-drv-dot.sig-hi  { background: var(--bull-dot, var(--accent)); }
.ma-drv-dot.sig-med { background: var(--warn-edge, var(--text-2)); }
.ma-drv-dot.sig-lo  { background: var(--line); border: 1px solid var(--text-muted); }
.ma-drv-label { color: var(--txt); flex: 1 1 auto; min-width: 0; }
.ma-drv-val { color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ma-context { display: flex; flex-wrap: wrap; gap: 5px 7px; margin: 2px 0 6px; }
.ma-chip { font: 500 10px/1.4 var(--font-sans); color: var(--text-muted); padding: 1px 7px;
  border: 1px solid var(--line); border-radius: var(--r-xs); white-space: nowrap; }
.ma-read { font: 400 11.5px/1.5 var(--font-sans); color: var(--text-muted); }

/* ── the news overlay on the residual ──
   Move Attribution reports the SIZE of what the numbers cannot explain; these rows
   name it. Story chips wrap rather than truncate (a headline clipped mid-clause can
   invert its own meaning), and the note line carries the coverage disclosure — the
   only thing rendered when the tape has no history for the window. */
.ma-news-head { color: var(--text-2); margin-top: 8px; }
.ma-news .ma-chip { white-space: normal; max-width: 100%; }
.ma-news-against { border-color: var(--warn-edge); color: var(--warn-text); }
.ma-news-with { border-color: var(--accent-edge); color: var(--accent); }
.ma-news-note { color: var(--text-muted); font-size: 10.5px; font-style: italic; margin: 2px 0 0; }

/* ── Spec 3 — Real-Rate heatmap row: coarse [PROXY] cells hatched ── */
/* The real-rate read uses a CPI breakeven proxy; hatch the row's cells so the
   reader sees it's coarse (tooltip names the gap). Only present when the
   real_rates flag splits the 7th row in (off ⇒ no .cc-cell-proxy emitted). */
.cc-cell-proxy {
  background-image: repeating-linear-gradient(45deg,
    transparent, transparent 3px, rgba(var(--hairline-rgb), .55) 3px,
    rgba(var(--hairline-rgb), .55) 5px);
}

/* ── Spec 1 — marginal-driver strip (cohesion / regime / dominant cohort) ── */
.md-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 12px; padding: 7px 12px; border-radius: var(--r-md); border: 1px solid var(--line);
  font: 500 12px/1.4 var(--font-sans); }
.md-strip-l { font-weight: 700; letter-spacing: .02em; color: var(--text-2); text-transform: uppercase; font-size: 10.5px; }
.md-strip-regime { font-weight: 700; }
.md-strip-coh { font-variant-numeric: tabular-nums; color: var(--txt); }
.md-strip-cohort { color: var(--text-2); }
.md-strip-prov { margin-left: auto; color: var(--text-muted); font-size: 9.5px; }
/* cohesion intensity → tint family: single-driver = bull (one strong driver),
   decaying = warn/amber, mixed = neutral. */
.md-strip-hot  { background: var(--bull-tint); border-color: var(--bull-edge); }
.md-strip-hot .md-strip-regime { color: var(--bull-text); }
.md-strip-warm { background: var(--warn-tint); border-color: var(--warn-edge); }
.md-strip-warm .md-strip-regime { color: var(--warn-text); }
.md-strip-cool { background: transparent; }

/* ── Spec 7 — flag-and-review HOLD surfacing (coherence_hold / temporal_hold) ── */
/* Amber chip on the Pairs card head — visual parity with the warn/banner family
   (the same --warn-* palette as .drv-conf-medium / .warnings). flex:0 0 auto so
   it sits inline after the persistence/reinforcement chips without perturbing the
   fixed-basis head columns. Only rendered when PAIRS_HOLD_BADGE_ENABLED + held. */
.pair-hold-badge {
  flex: 0 0 auto; align-self: center;
  margin-left: 6px; padding: 2px 8px; border-radius: var(--r-pill);
  font: 700 10.5px/1.4 var(--font-sans); letter-spacing: .04em; white-space: nowrap;
  color: var(--warn-text); background: var(--warn-tint);
  border: 1px solid var(--warn-edge); cursor: help;
}
/* Reason block in the expanded body — left-accent amber, mirrors .drv-hold. */
.esec.esec-hold {
  border-left: 3px solid var(--warn-edge); background: var(--warn-tint);
  padding: 9px 12px; border-radius: 0 var(--r-md) var(--r-md) 0;
}
.esec.esec-hold .esec-h { color: var(--warn-text); }
.esec.esec-hold .esec-sub { color: var(--warn-text); }

/* Living-Pairs divergence — collapsed chip + expanded reason block. Amber = testing
   (price moving against the persisting bias), red = breached (the pair's OWN stated
   invalidation level crossed). Only rendered when PAIR_DIVERGENCE_ENABLED + testing/breached. */
.pair-div-badge {
  flex: 0 0 auto; align-self: center;
  margin-left: 6px; padding: 2px 8px; border-radius: var(--r-pill);
  font: 700 10.5px/1.4 var(--font-sans); letter-spacing: .04em; white-space: nowrap; cursor: help;
}
.pair-div-badge.div-testing  { color: var(--warn-text); background: var(--warn-tint); border: 1px solid var(--warn-edge); }
.pair-div-badge.div-breached { color: var(--red); background: var(--bear-tint); border: 1px solid var(--red-dim); }
.esec.esec-divergence { padding: 9px 12px; border-radius: 0 var(--r-md) var(--r-md) 0; }
.esec.esec-divergence.esec-div-testing  { border-left: 3px solid var(--warn-edge); background: var(--warn-tint); }
.esec.esec-divergence.esec-div-testing  .esec-h { color: var(--warn-text); }
.esec.esec-divergence.esec-div-breached { border-left: 3px solid var(--red); background: var(--bear-tint); }
.esec.esec-divergence.esec-div-breached .esec-h { color: var(--red); }
.esec.esec-divergence .esec-metrics { font-size: 10.5px; color: var(--text-muted); margin-top: 8px; letter-spacing: .02em; }
.esec.esec-divergence .esec-stamp { font-size: 10px; color: var(--text-faint); margin-top: 5px; }

/* Missed winner — the green mirror of the divergence chip + reason block: a
   sub-actionable call moving strongly OUR way (active + qualified episodes only).
   Uses the theme bull-* tokens so light/dark both inherit correct green tones. */
.pair-mw-badge {
  flex: 0 0 auto; align-self: center;
  margin-left: 6px; padding: 2px 8px; border-radius: var(--r-pill);
  font: 700 10.5px/1.4 var(--font-sans); letter-spacing: .04em; white-space: nowrap; cursor: help;
  color: var(--bull-text); background: var(--bull-tint); border: 1px solid var(--bull-edge);
}
.esec.esec-mw { padding: 9px 12px; border-radius: 0 var(--r-md) var(--r-md) 0;
  border-left: 3px solid var(--bull-dot); background: var(--bull-tint); }
.esec.esec-mw .esec-h { color: var(--bull-text); }
.esec.esec-mw .esec-mw-head { font-weight: 700; margin-top: 4px; }
.esec.esec-mw .esec-mw-hindsight { color: var(--text-faint); font-style: italic; }
.esec.esec-mw .esec-metrics { font-size: 10.5px; color: var(--text-muted); margin-top: 8px; letter-spacing: .02em; }
.esec.esec-mw .esec-stamp { font-size: 10px; color: var(--text-faint); margin-top: 5px; }

/* ════════════════════════════════════════════════════════════════════════════
   MOBILE / RESPONSIVE LAYER  —  added 2026-06-29
   ----------------------------------------------------------------------------
   ADDITIVE ONLY. Every rule below lives inside a max-width media query, so
   desktop (>= 761px) renders byte-identical to before this block. Two tiers:
     · <= 760px  "mobile mode"  (tablet / large phone)
     · <= 520px  "phone"        (extra tightening on top of mobile mode)

   The desk reported the mobile experience was unusable; the strategy (verified
   at a true 390/520/700px viewport against live data) is:
     1. Top nav  -> brand + ☾/Log-out on row 1; the 5 tabs become a full-width
        horizontally-SCROLLABLE strip on row 2 (keeps the underline-active look).
     2. Wide fixed-column data grids/headers/tables become horizontal SCROLL
        containers instead of pushing the whole page sideways (the Real-Rate and
        Macro-Buckets banners, the causal matrix, the Track-Record ledger tables,
        the scenario-node + tranche sub-tables).
     3. The accordion list rows (Currencies + Pairs) degrade to a wrapped 2-line
        card: bias chip + conviction + caret on line 1, the summary preview on
        its own full-width second line. Full detail still lives in the expansion,
        so the fixed-track column header (which no longer aligns) is hidden.
     4. Hover-only popovers/tooltips (no touch access AND they inflate page width
        even while hidden) are dropped from layout on touch.
     5. Tap targets grow toward ~40px (tabs, toggles, filter chips, bell/star,
        sort headers, scenario pills).
     6. Shell gutters tighten (22px -> 14px -> 10px) to reclaim usable width.
   Charts are untouched: they already autosize via clientWidth + ResizeObserver.
   ============================================================================ */

@media (max-width: 760px) {
  /* ── Shell gutters (reclaim width); keep the full-bleed header glued to them ── */
  #app { padding-left: 14px; padding-right: 14px; }
  .topbar { margin-left: -14px; margin-right: -14px; padding-left: 14px; padding-right: 14px; }
  .banner { padding-left: 14px; }
  .warnings { padding-left: 14px; padding-right: 14px; }

  /* ── Top navigation: brand + actions on row 1, scrollable tab strip on row 2 ── */
  .topbar { flex-wrap: wrap; height: auto; min-height: 50px; column-gap: 12px; row-gap: 0; padding-top: 4px; padding-bottom: 4px; }
  .brand-sub { display: none; }                 /* decorative subtitle — reclaim ~110px */
  .tabs {
    order: 3; flex: 0 0 100%; width: 100%; margin-left: 0; gap: 4px;
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; border-top: 1px solid rgba(var(--hairline-rgb), .55);
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex: 0 0 auto; white-space: nowrap; display: inline-flex; align-items: center; min-height: 40px; padding: 6px 6px; }
  /* Flatten the nav dropdowns back into the scrollable strip on touch: the group
     boxes unwrap (display:contents) so their `.tab` children become direct flex
     items of `.tabs`, the triggers are dropped, and the menu tabs render exactly
     like the standalone tabs (underline-on-active, 40px tap target). */
  .navgroup:not([hidden]) { display: contents; }
  .navgroup-btn { display: none; }
  .navgroup-menu {
    position: static; display: contents;
    min-width: 0; padding: 0; margin: 0; gap: 0;
    background: transparent; border: 0; box-shadow: none;
  }
  .navgroup-menu::before { display: none; }
  .navgroup-menu .tab {
    border-bottom: 2px solid transparent; padding: 6px 6px; background: transparent; text-align: center;
  }
  .navgroup-menu .tab.active { background: transparent; border-bottom-color: var(--accent); }
  .topbar-actions { gap: 16px; }
  .theme-toggle, .logout-btn { display: inline-flex; align-items: center; min-height: 40px; }

  /* ── Hover-only tooltips/popovers: no touch access + inflate scrollWidth ──── */
  .gm-tipbox { display: none !important; }
  .fstage-pop { display: none !important; }
  .fdrv-pop { width: auto; max-width: calc(100vw - 16px); left: 8px !important; right: 8px !important; }

  /* ── Currencies: Real-Rate + Macro-Buckets banners -> horizontal scroll ───── */
  .rr-panel, .mb-panel, .os-panel { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .rr-grid { min-width: max-content; }
  .mb-grid { grid-template-columns: 40px 190px 190px 200px; min-width: max-content; }

  /* ── Causal-chain matrix: force width so .cc-gridwrap (overflow-x:auto) scrolls
        instead of squishing the 1fr currency columns to nothing ────────────── */
  #view-currencies .cc-grid, #view-currencies .cc-frow { min-width: 560px; }
  .cc-cards { grid-template-columns: repeat(2, 1fr); }

  /* ── Accordion list rows (shared Currencies + Pairs): wrap to 2 lines ─────── */
  .row-head { flex-wrap: wrap; gap: 6px 10px; padding: 8px 12px; min-height: 44px; }
  .row-head .chip { flex: 0 0 auto; min-width: 80px; }
  .row-head .conf { flex: 0 0 auto; }
  .row-head .caret { order: 1; margin-left: auto; font-size: 14px; padding: 6px 4px; }
  .row-head .summary { flex: 1 1 100%; order: 2; margin: 2px 0 0; }
  .row-head .name, .row-head .changed, .row-head .whatchanged, .row-head .persist { display: none; }
  #view-pairs .row-head .pair-reinf { display: none; }   /* 224px column lives in the expansion */
  .cur-colhead, .pair-colhead { display: none; }         /* fixed-track header no longer aligns to wrapped rows */

  /* ── Scenario-tree node headers + framework-stage pills inside the expansion ─ */
  .snode-h { flex-wrap: wrap; gap: 5px 8px; }
  .snode-h .chip { flex: 0 0 auto; }
  .snode-h .conf { flex: 0 0 auto; }
  .snode-reinforced, .snode-prev { flex: 1 1 100%; margin-left: 0; }
  .fstage-row { flex-wrap: wrap; }

  /* ── Track Record: ledger tables clip columns (.tr-table overflow:hidden) ─── */
  .tr-table { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
  .tr-tr { gap: 8px; }
  .tr-table-open .tr-tr { grid-template-columns: 96px 60px 92px 50px 66px 66px 144px 66px 66px; min-width: 772px; font-size: 12px; }
  .tr-table-closed .tr-tr { grid-template-columns: 96px 60px 92px 92px 50px 66px 66px 132px 66px 66px 120px; min-width: 1006px; font-size: 12px; }
  .tr-table-mt5live .tr-tr { grid-template-columns: 104px 60px 52px 92px 66px 66px 66px 66px 90px 132px; min-width: 820px; font-size: 12px; }
  .tr-mt5live-select { min-width: 0; width: 100%; }
  .tr-mt5live-stamp { margin-left: 0; }
  .tr-detail-grid { grid-template-columns: 1fr; gap: 16px; }
  .tr-entries { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tr-en-row { min-width: 560px; }
  .tr-filter-btn, .tr-filter-reset, .tr-model-btn, .tr-chip { min-height: 40px; padding-top: 9px; padding-bottom: 9px; display: inline-flex; align-items: center; }
  .tr-modeltab-bell, .tr-modeltab-star { font-size: 15px; padding: 6px; line-height: 1; }

  /* ── Summary entity popover (re-uses the wide currency/pair grids) ────────── */
  .sum-pop-bd { padding: 3vh 2vw; }
  .sum-pop-inner { padding: 10px 10px 14px; overflow: auto; -webkit-overflow-scrolling: touch; }
  .sum-pop-x { min-width: 40px; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; padding: 0; }

  /* ── Pairs filter bar tap targets ─────────────────────────────────────────── */
  #view-pairs .pairs-filter-btn, #view-pairs .pairs-filter-chip, #view-pairs .pairs-filter-sel,
  #view-pairs .pairs-filter-reset, #view-pairs .pairs-alerts-btn {
    min-height: 40px; display: inline-flex; align-items: center; padding-top: 0; padding-bottom: 0; font-size: 12.5px;
  }
  #view-pairs .pairs-filter-sel { padding-right: 22px; }

  /* ── Scenario picker pills + pre-login theme toggle tap targets ───────────── */
  .sp-pill { padding: 9px 14px; font-size: 13px; line-height: 1; }
  .scenario-picker { gap: 8px; }
  .login-theme-switch { top: 8px; right: 10px; }
  .theme-switch { gap: 10px; padding: 5px; }
  .theme-switch::before { top: 5px; left: 5px; transform: translateX(calc(var(--pal-i, 0) * 26px)); }
}

@media (max-width: 520px) {
  /* ── Tighter shell gutters on a true phone ────────────────────────────────── */
  #app { padding-left: 10px; padding-right: 10px; }
  .topbar { margin-left: -10px; margin-right: -10px; padding-left: 10px; padding-right: 10px; }
  .banner { padding-left: 10px; }
  .warnings { padding-left: 10px; padding-right: 10px; }
  .brand { font-size: 13px; letter-spacing: .12em; }

  /* ── Accordion rows: drop the rate/badge columns (full value in the expansion) ─ */
  .row-head { padding: 9px 12px; }
  .row-head .rate { display: none; }
  .row-head .badge { flex: 0 0 auto; }

  /* ── Causal cards single-column ──────────────────────────────────────────── */
  .cc-cards { grid-template-columns: 1fr; }

  /* ── Track Record KPI grids: repeat(3) -> repeat(2) + let $ values ellipsize ─ */
  .tr-kpi-top, .tr-kpi-strip, .tr-kpi-strip-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tr-kpi-top { gap: 8px; }
  .tr-kpi-tile, .tr-kpi-cell { min-width: 0; }
  .tr-kpi-tile-v, .tr-kpi-cell-v { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tr-modal-scrim { padding: 16px 10px; }
  .tr-modal { padding: 18px 16px; border-radius: var(--r-lg); }
  .tr-modal-btns { flex-wrap: wrap; }
  .tr-detail { padding: 14px 12px; }
  .sum-pop-bd { padding: 2vh 6px; }
  .sum-pop { max-height: 94vh; }

  /* ── Pairs expanded inner grid + scenario tabs ───────────────────────────── */
  #view-pairs .pair-tf-grid { grid-template-columns: 1fr; }
  #view-pairs .scn-tab { padding: 8px 12px; font-size: 12px; }

  /* ── Drivers: toggle + timeline + correlation heatmap ────────────────────── */
  .drv-plain-toggle { min-height: 40px; padding: 10px 14px; font-size: 12px; line-height: 1; }
  .drv-tl-row { flex-wrap: wrap; row-gap: 2px; }
  .drv-tl-date { flex: 0 0 84px; }
  .drv-tl-drv { flex: 1 1 100%; margin-top: 2px; }
  .drv-heat { display: block; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .drv-proof th { padding: 2px 4px 6px; }
  .drv-proof td { padding: 4px 4px; }

  /* ── Summary entity link tap area ─────────────────────────────────────────── */
  #view-summary .sum-line { padding: 7px 0; }

  /* ── Login feature grid -> 2x2 ───────────────────────────────────────────── */
  .login-grid { grid-template-columns: repeat(2, 1fr); }

  /* ── Prose legibility floor (NOT the all-caps column labels) ──────────────── */
  .gm-tip-rd, .gm-tip-foot, .ebrk-msub, .snode-ref, .drv-tk-fals { font-size: 11px; }
}

/* ── Currency Standing (V3_14) — grid of expandable square cards, USD = hub ── */
.standing-controls{display:flex;align-items:center;gap:16px;padding:10px 2px;flex-wrap:wrap;}
.standing-toggle{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:var(--text-2);font-size:13px;}
/* master–detail layout (replaces the square expand-in-place grid) */
.standing-md{display:grid;grid-template-columns:minmax(210px,290px) 1fr;gap:16px;align-items:start;}
.standing-list{display:flex;flex-direction:column;gap:10px;}
.standing-card{background:var(--surface);display:flex;flex-direction:column;overflow:hidden;}
.standing-list-item{gap:6px;padding:11px 13px;border:1px solid var(--line2);cursor:pointer;}
.standing-list-item:hover{border-color:var(--line);}
.standing-list-item.is-active{background:var(--surface-row-active);}
.standing-card--hub{box-shadow:inset 0 0 0 1px var(--accent);}
.standing-detail{background:var(--surface);border:1px solid var(--line2);padding:4px 18px 18px;min-width:0;}
.standing-detail-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding:10px 0 2px;}
.standing-detail-bank{font-size:13px;}
/* M3a cross-tab deep-link (→ Market Expectations engine) */
.standing-mx-link{font-size:12px;color:var(--accent);text-decoration:none;white-space:nowrap;margin-left:auto;align-self:center;}
.standing-mx-link:hover{text-decoration:underline;}
.standing-detail .standing-chips{margin:2px 0 4px;}
.standing-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px;}
.standing-codewrap{display:flex;align-items:baseline;gap:8px;}
.standing-code{font-size:22px;font-weight:600;letter-spacing:.04em;color:var(--text);}
.standing-hub-badge{font-size:10px;letter-spacing:.1em;color:var(--accent);border:1px solid var(--accent);padding:1px 5px;}
.standing-cb-name{font-size:12px;}
.standing-chips{display:flex;flex-wrap:wrap;gap:5px;align-items:center;}
.standing-short{font-size:12.5px;line-height:1.45;color:var(--text-2);margin-top:auto;}
.standing-chip{display:inline-block;font-size:11px;padding:1px 7px;border-radius:var(--r-xs);border:1px solid var(--line2);color:var(--text-2);background:var(--surface-sunken);white-space:nowrap;}
.standing-chip--bull{color:var(--bull-text);border-color:var(--bull-edge);background:var(--bull-tint);}
.standing-chip--bear{color:var(--bear-text);border-color:var(--bear-edge);background:var(--bear-tint);}
.standing-chip--warn{color:var(--warn-text);border-color:var(--warn-edge);background:var(--warn-tint);}
.standing-chip--mixed{color:var(--mixed-text);border-color:var(--mixed-edge);background:var(--mixed-tint);}
.standing-tdot{width:10px;height:10px;border-radius:50%;display:inline-block;background:var(--bull-dot);}
.standing-tdot.sev-low{background:var(--bull-dot);}
.standing-tdot.sev-medium{background:var(--warn-dot);}
.standing-tdot.sev-high{background:var(--bear-dot);}
.standing-body{padding:0;}
.standing-sec{padding:10px 0;border-top:1px solid var(--line);}
.standing-sec:first-child{border-top:none;}
.standing-sec-h{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);margin-bottom:6px;}
.standing-sec-h--toggle{display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;}
.standing-sec-h--toggle:hover{color:var(--text-2);}
.standing-sec-caret{font-size:9px;opacity:.7;width:9px;display:inline-block;}
.standing-sec-body.is-collapsed{display:none;}
.standing-prose{font-size:13px;line-height:1.5;color:var(--text-2);margin:4px 0;}
.standing-kv{display:flex;gap:8px;font-size:12.5px;padding:2px 0;}
.standing-kv-l{min-width:92px;flex:none;}
.standing-kv-v{color:var(--text-2);}
.standing-knums{display:flex;flex-direction:column;}
.standing-knum{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 0;border-top:1px solid var(--line);}
.standing-knum:first-child{border-top:none;padding-top:2px;}
.standing-knum-n{color:var(--text);font-size:12.5px;font-weight:500;}
.standing-knum-m{font-size:12px;line-height:1.45;}
.standing-vsusd{display:flex;flex-direction:column;gap:2px;margin-bottom:8px;}
.standing-vsusd-hub{font-size:12.5px;line-height:1.5;}
.standing-vsusd-jump{font-size:11px;color:var(--accent);background:none;border:1px solid var(--line2);padding:2px 8px;cursor:pointer;border-radius:var(--r-sm);}
.standing-vsusd-jump:hover{border-color:var(--accent);}
.standing-cbhead{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:4px;}
.standing-stance{font-size:12.5px;color:var(--text-2);}
.standing-notsaying-h{font-size:12px;color:var(--warn-text);margin:6px 0 2px;}
.standing-notsaying{margin:0;padding-left:18px;font-size:12.5px;line-height:1.5;color:var(--text-2);}
.standing-prov{font-size:11.5px;margin-top:4px;}
.standing-src{color:var(--accent);}
.standing-pair{padding:6px 0;border-top:1px dashed var(--line);}
.standing-pair:first-of-type{border-top:none;}
.standing-pair-h{display:flex;flex-wrap:wrap;gap:8px;align-items:center;}
.standing-pair-name{font-size:13px;color:var(--text);}
.standing-pair-fals{font-size:12px;margin-top:3px;}
/* The changed-value flash. FADE-OUT ONLY: the tint is present on frame 1 and
   decays to transparent, so a value that just moved catches the eye and then
   hands the row back to whatever background it actually has. It animates
   background-color, never the `background` shorthand, which would reset the
   pinstripe image mid-flash. */
@keyframes standingFlash{from{background-color:var(--cell-hi);}to{background-color:transparent;}}
.standing-card.flash{animation:standingFlash var(--dur-flash) var(--ease-out);}
/* #5 — generic row flash for a cross-page deep-link target (Currencies/Pairs). */
.gm-flash{animation:standingFlash var(--dur-flash) var(--ease-out);}

/* #1 — card accent by cb_language.alignment_verdict (border-left; the USD hub keeps
   its inset ring, so the two never collide). aligned = calm/neutral, not green. */
.standing-card--align-diverging{border-left:3px solid var(--warn-edge);}
.standing-card--align-contradicting{border-left:3px solid var(--bear-edge);}
.standing-card--align-aligned{border-left:3px solid var(--line2);}
.standing-card--align-muted{border-left:3px dashed var(--line2);}

/* #4 — page-level alignment strip (same accent tokens as #1). */
.standing-align-strip{display:flex;flex-wrap:wrap;gap:6px;padding:6px 2px 12px;}
.standing-align-dot{display:inline-flex;align-items:center;gap:5px;font-size:11px;padding:3px 9px;border-radius:var(--r-xs);border:1px solid var(--line2);background:var(--surface-sunken);color:var(--text-2);cursor:pointer;}
.standing-align-dot::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--text-faint);display:inline-block;flex:none;}
.standing-align-dot--diverging::before{background:var(--warn-dot);}
.standing-align-dot--contradicting::before{background:var(--bear-dot);}
.standing-align-dot--aligned::before{background:var(--text-faint);}
.standing-align-dot--muted::before{background:var(--line2);}
.standing-align-dot:hover{border-color:var(--accent);}
.standing-align-dot-code{letter-spacing:.03em;}

/* #3 — shared-driver highlighting: clickable ref/proxy chips + cross-card hit ring. */
.standing-card--drv-hit{outline:2px solid var(--accent);outline-offset:-2px;}
.standing-drv-chip,.standing-proxy-chip{cursor:pointer;}
.standing-drv-chip.is-shared,.standing-proxy-chip.is-shared{border-color:var(--accent);color:var(--accent);}
.standing-drv-chip.is-active,.standing-proxy-chip.is-active{background:var(--accent);border-color:var(--accent);color:var(--surface);}
.standing-tick{opacity:.85;}

/* #5 — cross-page link affordance on chips / pair names. */
.standing-link{cursor:pointer;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px;}
.standing-link:hover{color:var(--accent);}

/* #2 — pairwise GIP-differential comparator (diverging bars). */
.standing-cmp-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px;font-size:12.5px;}
.standing-cmp-base{font-weight:600;color:var(--text);}
.standing-cmp-quote{font-size:12.5px;padding:2px 6px;background:var(--surface-sunken);color:var(--text);border:1px solid var(--line2);border-radius:var(--r-xs);cursor:pointer;}
.standing-cmp-bars{display:flex;flex-direction:column;gap:6px;}
.standing-cmp-row{display:flex;align-items:center;gap:8px;font-size:12px;}
.standing-cmp-l{min-width:78px;flex:none;}
.standing-cmp-info{margin-left:3px;font-size:10px;color:var(--text-2);cursor:help;opacity:.7;}
.standing-cmp-track{position:relative;flex:1;height:14px;background:var(--surface-sunken);border-radius:var(--r-xs);overflow:hidden;}   /* track + fill were 3px/2px - the nearest rung, not squared */
.standing-cmp-track.is-gap{opacity:.45;}
.standing-cmp-zero{position:absolute;left:50%;top:0;bottom:0;width:1px;background:var(--line2);}
.standing-cmp-fill{position:absolute;top:2px;bottom:2px;border-radius:var(--r-xs);}
.standing-cmp-fill.is-base{background:var(--bull-dot);}
.standing-cmp-fill.is-quote{background:var(--bear-dot);}
.standing-cmp-v{min-width:42px;flex:none;text-align:right;color:var(--text-2);}
.standing-cmp-foot{margin-top:8px;font-size:12px;color:var(--text-2);}
.standing-cmp-lean{font-weight:600;color:var(--text);}
/* master–detail stacks on narrow screens: list on top, detail below */
@media (max-width:760px){.standing-md{grid-template-columns:1fr;}}


/* ── Global top loading bar (2026-07-16, js/loading.js) ──────────────────────
   A 2px accent hairline fixed to the top edge while a page-level /api fetch
   burst is in flight; width tracks completed/total. Injected by loading.js;
   hidden the rest of the time. Above every layer (max in-app z-index is 200).
   Its job is now long-request REASSURANCE — the skeletons are the primary
   loading signal — so it reads as a thin accent pill, not a progress slab.
   WIDTH is the one deliberate exception to the "never animate width" rule:
   this bar's width IS its information, so width is precisely the property
   that has to ease. Nothing else in the file may animate it.
   The opacity leg is the fade-out at the end of the finish hold; loading.js
   ends a burst by setting the `hidden` attribute, which the global
   `[hidden]{display:none !important}` reset resolves to display:none, so the
   fade plays only where the bar is dimmed rather than attribute-hidden. The
   timing is declared here so it stays with the rest of the bar's motion. */
#g10-loadbar{position:fixed;top:0;left:0;right:0;height:2px;z-index:400;pointer-events:none;}
#g10-loadbar[hidden]{display:none;}
#g10-loadbar .g10-loadbar-fill{height:100%;width:0;background:var(--accent);
  border-radius:var(--r-pill);
  box-shadow:0 0 8px 1px rgba(var(--hairline-rgb), 1);
  transition:width var(--dur-base) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
  animation:g10LoadPulse var(--dur-shimmer) var(--ease-shimmer) infinite;}
/* An indefinite attention pulse, not a transition or a one-shot reveal: the
   "nothing runs longer than --dur-slow" rule governs those, so a slow ambient
   breath on a loading indicator legitimately sits at the shimmer tier. */
@keyframes g10LoadPulse{0%,100%{opacity:1;}50%{opacity:.55;}}
@media (prefers-reduced-motion:reduce){#g10-loadbar .g10-loadbar-fill{animation:none;}}


/* ── Divergence Log tab (2026-07-21, js/divergences.js) ──────────────────────
   Trade Book group. A per-AI-model history of pair calls that broke their own
   stated line and then closed, with the reason each ended the way it did. Reads
   the divergence archive; presentation only. Tone: good=recovered, bad=flipped,
   warn=still-adverse. Theme-aware via the shared bull/bear/warn tokens. */
.dvg-wrap{max-width:960px;margin:0 auto;padding:14px 16px 40px;}
.dvg-intro{margin-bottom:12px;}
.dvg-title{font-size:19px;font-weight:700;color:var(--text);margin:0 0 4px;}
.dvg-lede{font-size:13px;line-height:1.5;color:var(--text-2);max-width:70ch;margin:0;}
.dvg-lensbar{display:flex;flex-wrap:wrap;gap:6px;margin:14px 0 10px;}
.dvg-lens{font:inherit;font-size:12px;padding:5px 11px;border-radius:var(--r-pill);cursor:pointer;
  background:var(--surface-sunken);color:var(--text-2);border:1px solid var(--line);}
.dvg-lens:hover{color:var(--text);}
.dvg-lens.active{background:var(--accent);color:var(--on-accent);border-color:var(--accent);font-weight:600;}
.dvg-lens-n{opacity:.7;font-variant-numeric:tabular-nums;margin-left:2px;}
.dvg-lens.active .dvg-lens-n{opacity:.85;}
.dvg-filters{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;}
.dvg-chip{font:inherit;font-size:11px;padding:4px 9px;border-radius:var(--r-xs);cursor:pointer;
  background:var(--surface-raised);color:var(--text-muted);border:1px solid var(--line);}
.dvg-chip:hover{color:var(--text-2);}
.dvg-chip.active{background:var(--surface-row-active);color:var(--text);border-color:var(--accent);}
.dvg-chip-n{opacity:.6;font-variant-numeric:tabular-nums;margin-left:1px;}
.dvg-stamp{font-size:11px;color:var(--text-faint);margin-bottom:10px;}
.dvg-list{display:flex;flex-direction:column;gap:10px;}
.dvg-card{background:var(--surface-raised);border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:0 var(--r-md) var(--r-md) 0;box-shadow:var(--shadow-1);padding:11px 13px;}
.dvg-card.dvg-good{border-left-color:var(--bull-edge);}
.dvg-card.dvg-bad{border-left-color:var(--bear-edge);}
.dvg-card.dvg-warn{border-left-color:var(--warn-edge);}
.dvg-head{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:4px;}
.dvg-pair{font-weight:700;font-size:14px;color:var(--text);letter-spacing:.02em;}
.dvg-dir{font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.04em;}
.dvg-tier{font-size:11px;color:var(--text-muted);background:var(--surface-sunken);
  border:1px solid var(--line);border-radius:var(--r-xs);padding:1px 6px;}
.dvg-outcome{margin-left:auto;font-size:11px;font-weight:600;padding:2px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line);}
.dvg-outcome.dvg-good{color:var(--bull-text);background:var(--bull-tint);border-color:var(--bull-edge);}
.dvg-outcome.dvg-bad{color:var(--bear-text);background:var(--bear-tint);border-color:var(--bear-edge);}
.dvg-outcome.dvg-warn{color:var(--warn-text);background:var(--warn-tint);border-color:var(--warn-edge);}
.dvg-flag{font-size:10px;color:var(--accent);border:1px solid var(--line);border-radius:var(--r-xs);padding:1px 5px;}
.dvg-why{background:var(--surface-sunken);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:8px 10px;margin:6px 0 8px;}
.dvg-why-lbl{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:3px;}
.dvg-why-p{font-size:13px;line-height:1.5;color:var(--text);margin:0;}
.dvg-why-news{font-size:12px;line-height:1.45;color:var(--text-2);margin:5px 0 0;}
.dvg-why-note{font-size:11px;line-height:1.4;margin:5px 0 0;}
.dvg-meta{font-size:12px;color:var(--text-muted);margin-bottom:3px;}
.dvg-metrics{font-size:12px;color:var(--text-2);margin-bottom:3px;font-variant-numeric:tabular-nums;}
.dvg-sub{font-size:12px;color:var(--text-2);margin-top:2px;}
.dvg-faint{color:var(--text-faint);}
.dvg-news{font-size:12px;margin-top:7px;padding:6px 9px;border-radius:var(--r-sm);line-height:1.45;}
.dvg-news--bad{background:var(--bear-tint);color:var(--text-2);}
.dvg-news--good{background:var(--bull-tint);color:var(--text-2);}
.dvg-news-lbl{font-weight:600;color:var(--text);}
.dvg-ctx{margin-top:5px;}
.dvg-ctx-tw{font:inherit;font-size:11px;color:var(--text-muted);background:none;border:none;
  padding:2px 0;cursor:pointer;}
.dvg-ctx-tw:hover{color:var(--text-2);}
.dvg-ctx-list{margin:4px 0 0;padding-left:14px;font-size:12px;color:var(--text-2);line-height:1.5;}
.dvg-empty{font-size:13px;color:var(--text-muted);padding:24px 4px;text-align:center;}
@media (max-width:520px){.dvg-outcome{margin-left:0;}}

/* ── Track Record — Top performers lens ──────────────────────────────────────
   The week/month leaderboard. A CSS grid rather than a <table> so a long model
   name can wrap its badge row without breaking column alignment. Colours come
   from the shared bull/bear tokens, which are defined in BOTH themes. */
.tr-top-toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:14px 0 6px;}
.tr-top-note{font-size:12px;margin:0 0 14px;max-width:70ch;line-height:1.55;}
.tr-top-table{display:flex;flex-direction:column;border-top:1px solid var(--line);}
.tr-top-row{
  display:grid;
  grid-template-columns:34px minmax(180px,1fr) 88px 84px 62px 56px 92px 76px;
  gap:8px;align-items:center;padding:8px 6px;
  border-bottom:1px solid rgba(var(--hairline-rgb), .55);font-size:13px;
}
.tr-top-row:hover{background:var(--surface-row-active);}
.tr-top-row--head{
  font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--colhead);
  background:var(--surface-sunken);position:sticky;top:0;z-index:1;
}
.tr-top-row--head:hover{background:var(--surface-sunken);}
.tr-top-c{overflow:hidden;text-overflow:ellipsis;}
.tr-top-c0{color:var(--text-faint);font-variant-numeric:tabular-nums;}
.tr-top-c2,.tr-top-c3,.tr-top-c4,.tr-top-c5,.tr-top-c6,.tr-top-c7{
  text-align:right;font-family:var(--font-sans);font-size:12px;font-variant-numeric:tabular-nums;
}
.tr-top-c1{display:flex;flex-direction:column;gap:3px;min-width:0;}
.tr-top-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.tr-top-tags{display:flex;flex-wrap:wrap;gap:4px;}
.tr-top-ai,.tr-top-lev,.tr-top-flag{
  font-size:10px;line-height:1.5;padding:0 5px;border-radius:var(--r-xs);
  border:1px solid rgba(var(--hairline-rgb), .80);color:var(--text-muted);white-space:nowrap;
}
.tr-top-ai{text-transform:capitalize;background:var(--surface-kpi);}
.tr-top-lev{border-color:var(--bear-edge);color:var(--bear-text);}
.tr-top-up{color:var(--bull-text);}
.tr-top-dn{color:var(--bear-text);}
.tr-top-foot{font-size:11.5px;margin-top:12px;max-width:78ch;line-height:1.6;}
@media (max-width:760px){
  /* Drop the two lifetime/risk columns first — they are context, not the ranking. */
  .tr-top-row{grid-template-columns:28px minmax(140px,1fr) 78px 72px 50px;}
  .tr-top-c6,.tr-top-c7{display:none;}
}
@media (max-width:520px){
  .tr-top-row{grid-template-columns:24px minmax(110px,1fr) 72px;}
  .tr-top-c3,.tr-top-c4,.tr-top-c5{display:none;}
}
