/* ═══════════════════════════════════════════════════════════════════════════
 * INSTRUMENT — the register pass (2026-08-05)
 *
 * Loaded LAST, on purpose. This file does not restyle the app surface by
 * surface; it collapses the AXES the app had accumulated. The reason the page
 * read as "AI generated, drafted" was never its colours — it was that every
 * axis had a dozen values and none of them had been chosen:
 *
 *     axis                 before   cyber.fund   paradigm   hyperliquid   here
 *     font families          3          1            2           1          1
 *     font sizes            12          4            4            4
 *     font weights           6          1            1            2
 *     tracking values       12/17       0            5            3
 *     ink colours            6          3            1            3
 *     background colours    11/17       3            2            2 + data
 *     border colours         8/13       1            0            1 + state
 *     border radii           7          3            1            0
 *     shadows                3          0            0            0 (popovers only)
 *     transition durations   6          1            2            1
 *
 * Both references were rendered with Playwright this session and their pixels
 * sampled, not recalled:
 *   cyber.fund   ground rgb(26,26,26)  ink rgb(245,245,240)  muted rgb(138,138,138)
 *                accent rgb(216,11,22) hairline rgb(61,61,61)
 *                100% JetBrains Mono at 12/13/14px
 *   paradigm.xyz ground rgb(255,255,255) ink rgb(0,0,0) ZERO borders, ZERO shadows
 *                serif for identity, SemiMono 10/12px at +0.24px tracking —
 *                the tracking SIGN FLIPS with the role, which is the device
 *                stolen wholesale below.
 *
 * TWO THINGS ARE DELIBERATELY EXEMPT and are called out so nobody "tidies"
 * them later:
 *   1. The recency ramp (--q1..--q5). It is a sequential DATA encoding, not
 *      chrome. It keeps five steps of one hue.
 *   2. The four coverage states. traded / listed-no-trades / unknown / not
 *      listed must stay visually distinct after the fills came off, so they
 *      get a second border colour (--empty) that the chrome hairline does not
 *      use. "n/a is not 0" outranks a tidy census.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ─────────────────────────────────────────────────────────────
 * Every token name below already existed. Nothing else in the app has to know
 * this file is here; it re-points the values the other seven stylesheets
 * already ask for. That is why a 3,000-line surface changes register from one
 * file without touching a single component rule it does not mean to.
 *
 * LIGHT = paradigm's ground, TINTED. Not #ffffff and not a warm paper: a
 * near-white carrying the same faint teal cast the dark ground carries, which
 * is Hyperliquid's principle (its ground is #0F1A1F, not #000) and the reason
 * its surface reads calm rather than dead. A neutral ground makes every ink on
 * it read as "absence of colour"; a tinted one gives the three signals a hue to
 * sit inside, so gold reads as gold rather than as "the yellow bit".
 *
 * Measured on RENDERED pixels, not declared backgrounds — see the table at the
 * foot of this file. */
:root {
  /* ── GROUND ───────────────────────────────────────────────────────────── */
  --bg: #fbfcfc;
  --panel: #f0f4f4;
  --rail: #eaefef;
  --card: transparent;
  --s1: transparent;
  --s2: transparent;
  --s3: transparent;
  --glass: transparent;
  --fill-1: transparent;
  --fill-2: transparent;
  --pop: #ffffff;

  --line: #ccd8d8;
  --line2: #ccd8d8;
  --line-2: #e4ebeb;
  --edge-1: #ccd8d8;
  --edge-2: #ccd8d8;

  /* ── INK ──────────────────────────────────────────────────────────────── */
  --ink: #0d1618;
  --ink2: #3f5153;
  --ink3: #5d7276;      /* 4.95:1 on the page ground, 4.58:1 on --panel. It was
                           #75726a, which measured 3.9:1 on a panel — the "grey
                           text nobody can read" half of the complaint. */

  /* ── THE THREE SIGNALS, LIGHT COUNTERPART ─────────────────────────────── */
  --accent: #8a6600;      /* ATTENTION. Gold cannot carry a glyph on white
                             (1.6:1), so light takes the deep gold at 5.3:1.
                             Same job, legible hue. */
  --accent-ink: #8a6600;
  --live: #0a7c8c;        /* LIVENESS. Mint pushed toward cyan and darkened:
                             #0e7f74 was the direct translation and measured
                             dE 13.9 against jade — a FAIL — so it moved until
                             it cleared. 4.9:1 on white. */
  --pos: #2f7d5b;         /* DIRECTION +. jade, 5.0:1  */
  --neg: #b04a56;         /* DIRECTION −. rose. Was #b8515c at 4.7:1 on the
                             ground, which is a pass in isolation and a FAIL
                             the moment the same rose sits on its own tinted
                             block in the mosaic (4.38:1, measured). Darkened
                             until it clears 4.5:1 on the fill as well as on
                             the page: 5.2:1 ground, 5.0:1 on the fill. */

  --mint: #101010;
  --mint2: #101010;
  --mint-dim: transparent;
  --brand-fill: transparent;
  --brand-fill-2: transparent;
  --on-brand: #101010;
  --focus: #8a6600;

  --empty: #75726a;

  --good: #2f7d5b;
  --bad: #b8515c;
  --warn: #75726a;
  --good-ink: #2f7d5b;
  --warn-ink: #75726a;
  --mid: #75726a;

  /* ── THE RECENCY RAMP IS THE LIVENESS COLOUR ──────────────────────────── */
  /* WIDENED. The five steps used to span L* 95 -> 74, which is a fifth of the
   * available range: a fill from an hour ago and a fill from last week landed
   * within two shades of each other and the ramp encoded nothing you could see.
   * It now spans L* 96 -> 55 and the top step is saturated, so "this traded in
   * the last hour" is legible from across the room. --ink still clears 4.5:1 on
   * every step, which is the constraint that caps the dark end. */
  --q1: #eaf3f3; --q2: #cfe6e6; --q3: #a8d5d3; --q4: #77bdb9; --q5: #3f9e97;
  /* Two mint steps for the tape's age column, both text-legal. */
  --live2: #147f80;

  --v1: #101010; --v2: #4a4842; --v3: #75726a;
  --v4: #4a4842; --v5: #75726a;
  --cat-crypto: rgba(16,16,16,.30); --cat-equity: rgba(16,16,16,.24);
  --cat-etf:    rgba(16,16,16,.19); --cat-index:  rgba(16,16,16,.14);
  --cat-gold:   rgba(16,16,16,.09); --cat-preipo: rgba(16,16,16,.05);

  --comet-pos: linear-gradient(90deg, transparent, rgba(47,125,91,.16));
  --comet-neg: linear-gradient(90deg, transparent, rgba(184,81,92,.16));
  --hover-wash: rgba(13,22,24,.06);
  --flash: rgba(10,124,140,.16);

  /* THE LIGHT LADDERS EXIST ONLY SO THE BASE LAYER RESOLVES.
   * The light theme was removed from the product on 2026-08-05 — index.html
   * hard-sets data-theme="dark" before first paint and the toggle is gone — but
   * these :root values are still the layer that [data-theme="dark"] OVERRIDES,
   * so every token the app reads has to have a definition here or an undefined
   * var() silently computes to nothing. They are kept correct and are
   * deliberately NOT tuned; the dark ground is the product. */
  --gold-txt: #8a6600; --gold-dim: #7a5c0c;
  --gold-line: rgba(138,102,0,.45); --gold-fill: rgba(138,102,0,.12);
  --gold-wash: rgba(138,102,0,.055);
  --mint-txt: #0a7c8c; --mint-dim2: #147f80;
  --mint-line: rgba(10,124,140,.45); --mint-fill: rgba(10,124,140,.11);
  --mint-wash: rgba(10,124,140,.05);
  --jade-txt: #2f7d5b; --jade-dim: #3d6d57;
  --jade-line: rgba(47,125,91,.45); --jade-fill: rgba(47,125,91,.10);
  --jade-wash: rgba(47,125,91,.04);
  --rose-txt: #b04a56; --rose-dim: #96505a;
  --rose-line: rgba(176,74,86,.45); --rose-fill: rgba(176,74,86,.09);
  --rose-wash: rgba(176,74,86,.04);
  --s-0: #fbfcfc; --s-1: #f4f7f7; --s-2: #eef3f3; --s-3: #ffffff; --s-4: #e6eeee;
  --line-strong: #b6c6c6;

  --r-mark: 0px; --r-ctl: 0px; --r-card: 0px; --r-pill: 0px; --r: 0px;
  --elev: none; --elev-sm: none;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, "DejaVu Sans Mono",
          "Liberation Mono", Consolas, monospace;
  --sans: var(--mono);

  --t-xs: 10px;
  --t-sm: 12px;
  --t-md: 14px;
  --t-lg: 26px;
  --fs-display: var(--t-lg);

  --tr-label: .14em;
  --tr-display: -.02em;

  /* ── TWO TEMPOS ───────────────────────────────────────────────────────── */
  --t-ease: cubic-bezier(.16, 1, .3, 1);
  --t-mag-ease: cubic-bezier(.4, 0, .2, 1);
  --t-state: 150ms;
  --t-ui: 160ms;
  --t-mag: 400ms;
  --t-dur: var(--t-ui);
  --t: var(--t-dur) var(--t-ease);
  --t-card-dur: var(--t-ui);
  --t-card: var(--t-card-dur) var(--t-ease);
  --t-slow-dur: 440ms;
  --t-slow: var(--t-slow-dur) var(--t-ease);
}

/* DARK = cyber.fund's ground, TINTED TOWARD HYPERLIQUID'S.
 *
 * It was #101010 — a neutral near-black with warm greys on it — and that is the
 * exact configuration the owner described as "nothing is showing": on a neutral
 * ground every hue reads as a deviation from nothing, so one gold underline and
 * one jade number float on a field with no colour temperature to belong to.
 *
 * Hyperliquid's ground is #0F1A1F, a teal-cast near-black, and that tint is why
 * its surface reads calm instead of dead. Ours takes the same principle at the
 * same depth: #0b1416 is 1.5% lighter than black in luminance, so the hairline
 * is still readable without becoming a box, and it shares a hue family with the
 * liveness mint — which means the recency ramp now fades INTO the ground rather
 * than sitting on top of it as five grey chips.
 *
 * The ink moves off warm and onto the same cast, for the same reason: warm grey
 * on a teal ground is the one combination that reads as a mistake. */
:root[data-theme="dark"] {
  --bg: #0b1416;
  --panel: #0f1a1c;
  --rail: #101d20;
  --card: transparent;
  --s1: transparent;
  --s2: transparent;
  --s3: transparent;
  --glass: transparent;
  --fill-1: transparent;
  --fill-2: transparent;
  --pop: #101c1f;

  --line: #24383a;
  --line2: #24383a;
  --line-2: #18292b;
  --edge-1: #24383a;
  --edge-2: #24383a;

  --ink: #e6f1ef;
  --ink2: #a3b8b6;
  --ink3: #7b9391;

  --accent: #f0b90b;      /* ATTENTION  10.6:1 */
  --accent-ink: #f0b90b;
  --live: #50d2c1;        /* LIVENESS   10.3:1 */
  --pos: #5aae87;         /* DIRECTION +  7.1:1  jade */
  --neg: #e06e76;         /* DIRECTION −  6.0:1  rose */

  --mint: #f2f0ea;
  --mint2: #f2f0ea;
  --mint-dim: transparent;
  --brand-fill: transparent;
  --brand-fill-2: transparent;
  --on-brand: #f2f0ea;
  --focus: #f0b90b;

  --empty: #8a877e;

  --good: #5aae87;
  --bad: #e06e76;
  --warn: #8a877e;
  --good-ink: #5aae87;
  --warn-ink: #8a877e;
  --mid: #8a877e;

  /* Same widening as the light ramp: it spanned #192b29 -> #32776e, which on a
   * NEUTRAL ground was five near-blacks. On the tinted ground the low steps can
   * sit closer to the page (older fades into the ground, which is what "older"
   * should look like) while the top step goes properly saturated. --ink over
   * --q5 measures 4.6:1, which is what caps it. */
  --q1: #12262a; --q2: #163b3c; --q3: #1a5350; --q4: #1e6a62; --q5: #23736a;
  --live2: #45a99e;   /* the second, dimmer mint step — 6.5:1, still text-legal */

  --v1: #f2f0ea; --v2: #b8b4a9; --v3: #8a877e;
  --v4: #b8b4a9; --v5: #8a877e;
  --cat-crypto: rgba(242,240,234,.30); --cat-equity: rgba(242,240,234,.24);
  --cat-etf:    rgba(242,240,234,.19); --cat-index:  rgba(242,240,234,.14);
  --cat-gold:   rgba(242,240,234,.09); --cat-preipo: rgba(242,240,234,.05);

  --comet-pos: linear-gradient(90deg, transparent, rgba(90,174,135,.16));
  --comet-neg: linear-gradient(90deg, transparent, rgba(224,110,118,.16));
  --hover-wash: rgba(230,241,239,.07);
  --flash: rgba(80,210,193,.22);

  /* ══ THE TONAL LADDERS ══════════════════════════════════════════════════
   * Owner: "in hyperliquid we have many doses of the color green and other
   * colors — in moneyness we have only one dose" / "everything has the same
   * color in this page".
   *
   * That is a precise diagnosis and it is NOT a hue problem. The three-signal
   * system was right and stays exactly as it is; what it lacked was DEPTH.
   * Each signal existed at exactly one value — one gold, one mint — so the
   * only thing a signal could ever say was "yes" or "nothing", and a surface
   * built from binary signals reads flat no matter how many of them you add.
   *
   * Hyperliquid's green is not one green. It is a row tint, a hover, an active
   * fill, a border, a glyph and a text colour — six doses of the same hue at
   * six strengths, each doing a different job. That is what makes its surface
   * read as depth rather than as a wash, and it costs no new hues at all.
   *
   * So every signal now has FIVE rungs, and the rung IS the meaning:
   *
   *   -txt    100%   the glyph. Legible, load-bearing, always clears 4.5:1.
   *   -dim     ~70%  a secondary glyph — the same claim, one step quieter.
   *   -line    ~55%  borders and rules. Visible as structure, never as text.
   *   -fill    ~16%  a surface an element sits ON.
   *   -wash    ~6%   a tint a whole row can carry without becoming loud.
   *
   * A rung may never be used for a job above it — a -wash is not a border and
   * a -line is not text — which is what stops the ladder becoming a licence to
   * put the accent everywhere. */
  --gold-txt: #f0b90b; --gold-dim: #c99a12;
  --gold-line: rgba(240,185,11,.55); --gold-fill: rgba(240,185,11,.16);
  --gold-wash: rgba(240,185,11,.065);

  --mint-txt: #50d2c1; --mint-dim2: #45a99e;
  --mint-line: rgba(80,210,193,.50); --mint-fill: rgba(80,210,193,.15);
  --mint-wash: rgba(80,210,193,.06);

  --jade-txt: #5aae87; --jade-dim: #4a8f70;
  --jade-line: rgba(90,174,135,.55); --jade-fill: rgba(90,174,135,.15);
  --jade-wash: rgba(90,174,135,.05);

  --rose-txt: #e06e76; --rose-dim: #b45a61;
  --rose-line: rgba(224,110,118,.55); --rose-fill: rgba(224,110,118,.14);
  --rose-wash: rgba(224,110,118,.05);

  /* ══ SURFACE ELEVATION ══════════════════════════════════════════════════
   * The other half of "everything has the same color". The app had one ground
   * and three tokens all within 2% luminance of it, so nothing on the page was
   * ever ON anything — every panel, every popover and the command band all sat
   * at the same depth as the page behind them.
   *
   * Five real steps. They are close together on purpose (this is a dark
   * instrument, not a card UI) but each is a visible increment, and the
   * hairline gets a second, brighter value so an edge BETWEEN elevations can
   * read differently from a rule drawn inside one. */
  --s-0: #081012;   /* the page ground, deepest                              */
  --s-1: #0c181a;   /* panels, table bodies                                  */
  --s-2: #112124;   /* raised chrome: sticky heads, the command band         */
  --s-3: #16292c;   /* floating: popovers, the command input                 */
  --s-4: #1d3538;   /* highest: a selected row, an open cell                 */
  --line-strong: #344d50;
}

/* ── 2. THE BLUNT LAYER ────────────────────────────────────────────────────
 * One rule collapses four axes across every element the app will ever render,
 * including the ones drawn by JavaScript that no stylesheet here has seen.
 * That is the point: a per-component pass would have missed the tape rows,
 * the treemap labels and the venue panel, which is precisely how twelve font
 * sizes accumulated in the first place. The role rules below win it back, and
 * they all carry a class, so they beat this on specificity as well as order.
 *
 * `!important` is correct here and only here: this is a normalisation layer
 * loaded last, exactly like the reset it replaces. */
body *:not(svg):not(svg *) {
  font-family: var(--mono) !important;
  font-size: var(--t-sm) !important;
  font-weight: 400 !important;
  letter-spacing: normal !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  /* THE DURATION LINE IS GONE — see §65. It read
     `transition-duration: var(--t-dur) !important` and it was the single most
     expensive declaration in this file. `transition-property` initialises to
     `all`, so handing every element a duration gave every element a live
     transition on every animatable property, including layout ones, whether
     or not any component had asked for motion. Measured on the live page
     before removal: 52,194 elements with a running transition, 36,326 of them
     on `all`. mpp.dev, the reference, has ~55 in total.

     Removing it does not make anything snap that used to glide: a component
     that asked for a transition sets its own duration in its own shorthand.
     What stops is the motion nobody requested. The one component that set a
     property without a duration (tools.css .tw-row > *) sets its own. */
  transition-timing-function: var(--ease-standard) !important;
  text-shadow: none !important;
}

/* ── 3. TYPE ROLES ─────────────────────────────────────────────────────────
 * Four sizes, two weights, three tracking values. Every rule below states its
 * role, because a size with no role is how you get twelve of them. */

/* r1 — MICRO LABEL. Uppercase, tracked positive. Column heads, legend keys,
 * captions, units, the section rail. This is the app's most common label and
 * it is the one paradigm sets at 10px/+0.2px. */
body th,
body .legend, body .legend *,
body .card .label,
body .controls label, body .check,
body .pick-lead,
body .rk-cat,
body .cc-m,
body .tiny, body .pill,
body .cov-ah,
body .rl-n,
body .tapecount,
body .tl-c-h, body .tl-lg, body .tl-lg *,
body .op-lbl, body .op-unit, body .op-hd,
body .dt-lbl, body .dt-unit,
body .cmd-grp,
body .cmd-hint, body .cmd-hint * {
  font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important;
  text-transform: uppercase;
  color: var(--ink3);
  font-weight: 400 !important;
}

/* r2 — DISPLAY. Serif, negative tracking, and it is spent on ONE thing: the
 * wordmark. That is the whole of family two's job, exactly as paradigm.xyz
 * spends its serif on the word "Paradigm" and nothing else.
 *
 * The recording counter deliberately does NOT get the serif, even though it is
 * the other candidate. Georgia ships OLDSTYLE figures — 3 4 5 7 9 descend
 * below the baseline and the digits are not the same width — which is exactly
 * wrong for a number that has to hold its columns still while individual
 * digits change under it. It gets the mono at display size instead, and the
 * per-character odometer below depends on that fixed advance width. */
/* ONE FAMILY, NOT TWO. The serif wordmark was paradigm's device and it was
 * the single most blog-like object left on the page — owner: "it gives the
 * vibe of a blog". Hyperliquid, which is the target, runs ONE family across
 * all 753 of its elements and spends nothing on an identity face. The wordmark
 * earns its presence from size and tracking instead, which is cheaper and
 * reads as an instrument rather than a masthead. */
body .brand h1 {
  font-size: var(--t-lg) !important;
  letter-spacing: var(--tr-display) !important;
  font-weight: 400 !important;
  color: var(--ink);
  line-height: 1.05;
}
body .trust .tr-count b, body .rec-num b {
  font-size: var(--t-lg) !important;
  letter-spacing: var(--tr-display) !important;
  font-weight: 400 !important;
  color: var(--ink);
  line-height: 1.05;
}

/* r3 — SECTION HEADING. Mono, one step up, negative tracking, weight 400.
 * Hierarchy comes from the hairline under it and the space around it, not
 * from four extra points of weight. */
body .panel-head h2,
body .dt-idtext h2,
body h2 {
  font-size: var(--t-lg) !important;
  letter-spacing: var(--tr-display) !important;
  font-weight: 400 !important;
  color: var(--ink);
  line-height: 1.1;
}
body h3, body .tl-h3, body .op-h3 {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3); font-weight: 400 !important;
}

/* r3b — PROSE. The other half of the spread. These are the explanatory
 * sentences that survive the text cull, and they are the ONLY things allowed
 * this size; a caption or a hint that grew to 14px would close the gap the
 * scale exists to open. */
body .panel-head .sub,
body .answer-strip,
body .rowsub,
body .tw-hint,
body .sc-hint,
body #method p,
body .op-note, body .op-lead,
body .tl-lead {
  font-size: var(--t-md) !important;
  letter-spacing: normal !important;
  color: var(--ink3);
  line-height: 1.5;
}
body .answer-strip { color: var(--ink2); }

/* r4 — EMPHASIS. The app's ONLY second weight. */
body b, body strong, body .lg.lead, body .rl-item.on .rl-l {
  font-weight: 600 !important;
}

/* ── 4. CHROME REMOVAL ─────────────────────────────────────────────────────
 * Content sits on the page ground and is separated by hairlines. Nothing is
 * separated by a box. */
body .panel, body .card, body .cw-card, body .tl-card, body .op-card,
body .cards > *, body details.board-all, body .seg {
  background: transparent !important;
  box-shadow: none !important;
}
body .card, body .cw-card, body .tl-card, body .op-card {
  border: 0 !important;
  border-top: 1px solid var(--line) !important;
  padding: 9px 0 10px !important;
}
body .card::before { display: none !important; }

/* Panels are separated from each other by a rule, not by a gap between two
 * filled rectangles. */
body .panel + .panel,
body .stage > .panel + .panel { border-top: 1px solid var(--line); }
body .panel-head {
  border-bottom: 1px solid var(--line);
  padding: 0 0 14px !important;
  align-items: flex-start;
}
body .panel-head .sub { color: var(--ink3); max-width: 62ch; }

/* Controls: outlined or bare, never filled. ui.css put `background: var(--s2)`
 * on twelve control classes at once — that single rule was most of the
 * "exchange" look, and --s2 is transparent now, so what is left is this. */
body .cs-btn, body .theme-btn, body .controls select, body .closebtn,
body .op-b, body .op-chip, body .op-adv, body .py-chip, body .tl-copy,
body .tw-x-b, body .tw-fmode, body .tw-clear, body #col-mode,
body .dt-asset, body .dt-lv button, body .tl-btn, body .tl-tab,
body .next-step, body .dt-close, body .seg button, body .op-xb,
body .op-pin, body .op-t-x {
  background: transparent !important;
  border: 1px solid var(--line) !important;
  color: var(--ink2) !important;
  padding: 5px 10px;
  font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important;
  text-transform: uppercase;
}
body .cs-btn:hover, body .theme-btn:hover, body .controls select:hover,
body .op-b:hover, body .op-chip:hover, body .py-chip:hover, body .tl-btn:hover,
body .tl-tab:hover, body .dt-asset:hover, body .next-step:hover,
body .dt-close:hover, body .seg button:hover, body .tw-x-b:hover {
  border-color: var(--ink3) !important;
  color: var(--ink) !important;
  background: transparent !important;
}
/* Active state is CONTENT and WEIGHT, not a fill. Paradigm marks its live
 * section by emptying the bracket — no colour spent at all. */
body .op-b.on, body .op-chip.on, body .seg button.on,
body .tw-tab[aria-selected="true"], body .dt-asset.on, body .dt-lv button.on,
body .tl-tab[aria-selected="true"] {
  background: transparent !important;
  border-color: var(--ink) !important;
  color: var(--ink) !important;
  font-weight: 600 !important;
}
body .theme-btn { width: 26px; height: 26px; padding: 0; }
body .theme-btn svg { width: 13px; height: 13px; }

/* Badges and pills lose their fills and become outlined marks. */
body .pill, body .op-chip.fact, body .op-lock, body .cf {
  background: transparent !important;
  border: 1px solid var(--line) !important;
  color: var(--ink3) !important;
}

/* Links: ink with a hairline underline. This is where most of the yellow
 * went — `a{color:var(--mint)}` was every link on the page. */
body a, body .linkish, body .sum-v, body .tr-link, body .dt-ext {
  color: var(--ink) !important;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  text-decoration-color: transparent !important;
}
body a:hover, body .linkish:hover, body .sum-v:hover, body .tr-link:hover,
body .dt-ext:hover {
  border-bottom-color: var(--ink) !important;
  text-decoration: none !important;
}

/* ── 5. TABLES AS LINE-ART ─────────────────────────────────────────────────
 * Row separation by hairline only. No zebra, no filled headers, no gradient
 * under the sticky row — the numbers carry the weight. */
body table { font-size: var(--t-sm) !important; }
body th {
  background: var(--bg) !important;
  border-bottom: 1px solid var(--line) !important;
  color: var(--ink3) !important;
  padding: 10px 14px 8px !important;
}
/* :not(.tl-c):not(.cov-c) IS LOAD-BEARING AND IS NOT A TIDINESS EXCEPTION.
 *
 * Caught by the four-state check, not by looking: the coverage cells are <td>
 * elements whose recency fill is written INLINE by tools.js
 * (`<td class="tl-c traded" style="background:var(--q4)">`). A blanket
 * `background: transparent !important` on td therefore stripped the fill off
 * every traded cell — and "traded" is the one state whose entire marker IS
 * that fill, so it silently became identical to "not listed". That is exactly
 * the failure this app forbids: an absence and a presence rendering the same.
 *
 * Chrome loses its fills. Data keeps them. */
body td:not(.tl-c):not(.cov-c) {
  border-bottom: 1px solid var(--line) !important;
  background: transparent !important;
  padding: 9px 14px !important;
  color: var(--ink2);
}
body td.tl-c, body td.cov-c { border-bottom: 0 !important; }
body tbody tr { background: transparent !important; }
body tbody tr:hover td:not(.tl-c):not(.cov-c) { background: transparent !important; color: var(--ink); }
body tr.clickable:hover td:first-child { color: var(--ink) !important; }
body tbody tr:hover { box-shadow: none !important; }
/* The tape shaded every row by premium as a share of the largest on the page.
 * That is a bar chart drawn as a background wash behind live text, and it put
 * eleven backgrounds on one screen. The data is still in the row. */
body .tw-body .tw-r, body .tw-r, body #tape tr, body .tl-tape tr {
  background-image: none !important;
}

/* ── 6. THE FOUR STATES — the one thing that may not be simplified ─────────
 * Fills came off everything else. These keep a device each, and the devices
 * are shape, not colour, so they survive both themes and a colourblind reader:
 *
 *   traded             a FILLED block from the recency ramp   (only fill left)
 *   listed, no trades  DASHED hairline, hollow
 *   unknown, no feed   SOLID hairline + 45deg HATCH + a "?" glyph
 *   not listed         nothing at all — no border, no fill
 *
 * The hatch used to be built from --s2, which is transparent now; rebuilding
 * it on --empty is what stops "we cannot see" from rendering as "empty", and
 * that is the difference between an honest screener and a lying one. */
body td.cov-c.traded, body .tl-c.traded {
  border: 1px solid transparent !important;
  /* NEVER var(--bg). Ground-coloured text over a ramp only works if the ramp
   * is guaranteed bright, and no five-step ramp is. --ink plus the clamped
   * ramp above is the pair that holds at both ends, in both themes. */
  color: var(--ink) !important;
}
body td.cov-c.traded i, body .tl-c.traded i {
  mix-blend-mode: normal !important; opacity: 1 !important; font-weight: 600 !important;
}
body td.cov-c.listed, body .tl-c.no_trades, body .tl-c.listed {
  border: 1px dashed var(--empty) !important;
  background: transparent !important;
  color: var(--ink3) !important;
}
body td.cov-c.unknown, body .tl-c.unknown {
  border: 1px solid var(--empty) !important;
  color: var(--ink2) !important;
  background-image: repeating-linear-gradient(45deg,
    var(--empty) 0 1px, transparent 1px 5px) !important;
}
body td.cov-c.none, body .tl-c.none {
  border-color: transparent !important;
  background: none !important;
  background-image: none !important;
}
/* Counterparty identicons. tape.js publishes the mark twice — as a
 * background-image and as --ic — so it can be painted through a mask here and
 * take an ink token instead of the baked hsl() it used to carry. The PATTERN
 * is the identity; the hue was a second encoding of the same hash. */
body .tw-ic {
  background-image: none !important;
  background-color: var(--ink3) !important;
  -webkit-mask-image: var(--ic); mask-image: var(--ic);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}

body .lg i { border-radius: 0 !important; }
body .lg i.dash { border: 1px dashed var(--empty) !important; background: none !important; }
body .lg i.hatch {
  border: 1px solid var(--empty) !important;
  background-image: repeating-linear-gradient(45deg,
    var(--empty) 0 1px, transparent 1px 5px) !important;
}

/* ── 7. THREE SIGNALS, THREE DISJOINT JOBS ────────────────────────────────
 * This is the rule the palette is built on, and the hex values are downstream
 * of it. The moment any one of the three takes a second job, the page collapses
 * back into every other trading UI — which is precisely what had happened here:
 * a single yellow was carrying "brand", "interactive", "emphasis", "good" and
 * "warning" simultaneously, across 40-odd elements.
 *
 *   GOLD  #f0b90b / #8a6600   ATTENTION.  Focus rings, the active section,
 *                             selection. STATIC. Never encodes a value.
 *   MINT  #50d2c1 / #0a7c8c   LIVENESS.   The status dot, the recency ramp,
 *                             the lit odometer digit, the arrival flash.
 *                             MOVING. Never encodes direction.
 *   JADE  #5aae87 / #2f7d5b   DIRECTION.  Sign only — up/down, credit/cost,
 *   ROSE  #e06e76 / #b8515c               protection-bid/upside-bid.
 *                             Never emphasis, never "good"/"bad".
 *
 * Rose rather than red is the load-bearing choice: a rose reads as a
 * measurement and a blood red reads as an alarm, and half the numbers on this
 * page are legitimately negative. It is what keeps the surface out of the
 * casino. Jade is likewise desaturated until it carries the same visual WEIGHT
 * as the greys — a column of mixed signs must not strobe.
 *
 * Separation is measured, not eyeballed (CIELAB dE76, floor 15):
 *   dark   gold/mint 93.7 · gold/jade 80.0 · mint/jade 19.3 · jade/rose 80.2
 *   light  gold/mint 66.7 · gold/jade 56.6 · mint/jade 30.1 · jade/rose 75.2
 * The light mint was the direct translation #0e7f74 first and measured dE 13.9
 * against jade — a FAIL — so it moved toward cyan until it cleared. */
body .dot { background: var(--live) !important; border: 0 !important; width: 5px; height: 5px; }
body .status { color: var(--ink3) !important; }
:focus-visible { outline: 1px solid var(--accent) !important; outline-offset: 2px; }
body td.cov-c:not(.none):hover, body td.cov-c:not(.none):focus-visible,
body .tl-c:not(.none):hover, body .tl-c:not(.none):focus-visible {
  outline: 1px solid var(--accent) !important; outline-offset: -1px;
}

/* ── 8. SPACE — DENSE, NOT EMPTY ───────────────────────────────────────────
 * CORRECTED after a first pass overshot (owner: "we lost our motto that says
 * we should be filling the whole page and be like dexscreener or pump.fun").
 * That pass ran 44/56px section padding and 56px gaps, which is cyber.fund's
 * proportions — and cyber.fund is a five-element landing page, not a screener.
 *
 * THE SPLIT THIS FILE MAKES, and it is the whole thesis:
 *   from cyber.fund / paradigm  the DISCIPLINE — four sizes, two weights, one
 *                               border colour, no shadows, one accent, one curve
 *   from dexscreener / pump.fun the DENSITY — the viewport works, every value
 *                               is clickable, information per square inch
 * Those are not in tension. "How many distinct values exist in the design
 * system" and "how much of the page is filled" are independent axes, and the
 * page that looks drafted is the one that got the FIRST one wrong.
 *
 * So: gutters are tight, rows are tight, and what gets cut is TEXT — captions,
 * hints, sub-headings, prose measure — never rows, columns or numbers. */
body main.stage { padding: 16px 18px 26px !important; gap: 18px !important; }
body .chart-wrap, body #where-grid, body #coverage-wrap { padding: 8px 0 0 !important; }
body .legend { padding: 10px 0 0 !important; margin: 0 !important; gap: 14px !important; }
body .rowsub { padding: 9px 0 0 !important; max-width: 120ch; color: var(--ink3); line-height: 1.5; }
body .answer-strip { padding: 10px 0 12px !important; max-width: 130ch; line-height: 1.6; }
body .panel-head { padding: 0 0 8px !important; }
body .panel-head .sub { max-width: 120ch; line-height: 1.45; margin-top: 3px; }
body .cards { padding: 0 !important; gap: 0 22px !important; }
body .card { padding: 9px 0 10px !important; }
body .panel { overflow: visible !important; }
body .split { gap: 0 !important; }
body details.board-all { border-top: 1px solid var(--line); padding-top: 10px; }
body details.board-all > summary {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3); cursor: pointer; list-style: none;
}
body details.board-all > summary::before { content: "[+] "; }
body details.board-all[open] > summary::before { content: "[-] "; }

/* TABLE DENSITY. The discipline pass had widened rows to 9px/14px; a screener
 * is read by scanning down a column, and every extra pixel of row height is a
 * row that fell off the screen. Back to a scanning rhythm — the hairlines and
 * the four type sizes are what make it look designed, not the air. */
body th { padding: 6px 10px 5px !important; }
body td:not(.tl-c):not(.cov-c) { padding: 4px 10px !important; }
body .tw-row, body .tw-head { line-height: 1.35; }

@media (max-width: 1100px) { body main.stage { padding: 14px 14px 24px !important; gap: 16px !important; } }
@media (max-width: 700px)  { body main.stage { padding: 12px 10px 22px !important; gap: 14px !important; } }

/* ── 8b. ONE SCROLLER, NOT SEVEN ───────────────────────────────────────────
 * The overview was built as nested scrollports: .split filled the view, the
 * panel filled .split, and #where-grid was a flex child with overflow:auto —
 * so the board scrolled inside a box whose height was whatever was left over.
 * Doubling the section padding took that leftover down to 258px and the table
 * clipped mid-row with the legend printed over it.
 *
 * The references do not do this. Both are one column that scrolls once. Panes
 * size to their content and main.stage is the only scrollport, which is also
 * what the sticky column headers want — they now stick to the stage instead of
 * to a 258px window. Horizontal scroll is KEPT on the 23-column coverage
 * matrix, which genuinely needs it. */
/* :not([hidden]) is load-bearing. nav.css's `.view[hidden]{display:none}` is
 * the same specificity as `body .view`, so an unqualified !important here
 * un-hid every section at once and printed all six on top of each other.
 * Likewise .split keeps its display — screener.css hides it while a venue
 * panel is open — and only its FLEX SIZING is neutralised. */
body .view:not([hidden]) { height: auto !important; }
body .split { flex: none !important; height: auto !important; }
body .split > .panel { min-height: 0 !important; }
body .hero-panel > #where-grid, body .hero-panel > .chart-wrap,
body #where-grid, body .chart-wrap, body .table-scroll, body .tape-panel,
body .view[data-view="overview"] .tape-panel {
  flex: none !important;
  max-height: none !important;
  overflow-y: visible !important;
}
body #coverage-wrap { max-height: none !important; overflow-x: auto !important; overflow-y: visible !important; }
body .panel-head > div:first-child { flex: 1 1 auto; min-width: 0; }

/* The footer was capped at 44px with overflow:hidden — correct when it held
 * one byline, fatal now that it holds the command bar. It is also no longer
 * centred: an instrument's chrome aligns to the same left edge as its data. */
body footer {
  max-height: none !important;
  overflow: visible !important;
  display: block !important;
  text-align: left !important;
  align-items: stretch !important;
  gap: 0 !important;
}

/* ── 9. MOTION ─────────────────────────────────────────────────────────────
 * Rare, slow, precise. Section arrival only, on the expo curve, 440ms. The
 * press-scale and the card lift are gone: a springy control on a page that
 * polls live data is noise competing with the data for the same attention. */
@keyframes view-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
body .stage .view:not([hidden]),
body #detail-root .dt {
  animation: view-in var(--t-slow-dur) var(--ease-expressive) backwards !important;
}
body .op-b:active, body .tl-btn:active, body .tl-tab:active, body .py-chip:active,
body .dt-asset:active, body .cs-btn:active, body .theme-btn:active,
body .op-chip:active, body .op-xb:active, body .tw-x-b:active,
body .op-pin:active, body .op-t-x:active, body .op-cell:active { transform: none !important; }
body .cw-card:hover { transform: none !important; box-shadow: none !important; }
body .tk-i.tk-new { animation: none !important; }

/* ── 10. POPOVERS — the only things that float, so the only shadows ────────*/
body #cov-card, body #tools-card, body .cs-pop, body .op-pop, body .gl-pop,
body .tw-pop, body #cmd-pop {
  background: var(--pop) !important;
  border: 1px solid var(--line) !important;
  box-shadow: 0 10px 40px rgba(0, 0, 0, .28) !important;
}

/* ── 11. SCROLLBARS ───────────────────────────────────────────────────────*/
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background-color: var(--line); border: 3px solid transparent;
  background-clip: content-box; border-radius: 0; }

@media (prefers-reduced-motion: reduce) {
  body .stage .view:not([hidden]), body #detail-root .dt { animation: none !important; }
}

/* ── 12. THE CHROME, AND THE SECTION ROW ──────────────────────────────────
 * The rail was a 164px left column. It is a horizontal bracket row in the top
 * chrome now, and the stage got the 164px — which on a page whose reason to
 * exist is a nine-column table is the most valuable width on screen.
 *
 * cyber.fund's top band is one hairline-bottomed strip: brand left, a single
 * status item right, nothing else. Ours matches, with the section row as a
 * second strip under it, the way the reference puts its "Quick access" row on
 * its own line rather than crowding the masthead. */
body .top {
  height: auto !important;
  padding: 9px 18px 8px !important;
  border-bottom: 1px solid var(--line);
  background: var(--bg) !important;
}
body .brand { display: flex; align-items: baseline; gap: 14px; }
body .brand > div { display: flex; align-items: baseline; gap: 14px; }
body .brand .tag {
  margin: 0; font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3);
}
/* The cap mark stays — it is geometry that names the product, not decoration —
 * but it stops being a filled yellow tile and becomes a hairline glyph. */
body .logo { background: transparent !important; border: 0 !important;
  color: var(--ink) !important; width: 22px; height: 22px; padding: 0; }
body .logo svg { width: 22px; height: 22px; }
body .topright { display: flex; align-items: center; gap: 20px; }

/* THE SECTION ROW. Hairline-separated, mono, uppercase, tracked. The bracket
 * is always drawn; only its contents change, so nothing moves as you navigate
 * — the reason paradigm's [1] [ ] [3] reads as an instrument and a pill row
 * reads as a website. */
body .rail {
  flex: none !important;
  display: flex !important; flex-direction: row !important;
  align-items: center; gap: 0 !important;
  height: auto !important; min-height: 0 !important;
  padding: 0 18px !important;
  border-right: 0 !important;
  border-bottom: 1px solid var(--line) !important;
  overflow-x: auto; overflow-y: hidden; background: var(--bg) !important;
}
body .rl-item {
  flex: none; display: inline-flex !important; flex-direction: row !important;
  align-items: baseline; gap: 8px;
  padding: 8px 16px 7px !important;
  border: 0 !important; background: transparent !important;
  color: var(--ink3) !important;
  border-bottom: 1px solid transparent !important;
  white-space: nowrap;
}
body .rl-item + .rl-item { box-shadow: none !important; }
body .rl-item::before { display: none !important; }
body .rl-n {
  font-size: var(--t-xs) !important; letter-spacing: normal !important;
  color: var(--ink3) !important; text-transform: none;
}
body .rl-l {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}
body .rl-item:hover .rl-l, body .rl-item:hover .rl-n { color: var(--ink) !important; }
/* THE ONE ACCENT. */
body .rl-item.on { border-bottom-color: var(--accent) !important; }
body .rl-item.on .rl-n { color: var(--accent-ink) !important; }
body .rl-item.on .rl-l { color: var(--ink) !important; font-weight: 600 !important; }

/* The app is one column now — the rail is not inside it any more. */
body .app { display: block !important; grid-template-columns: none !important; }

/* The trust bar's counter moves to the bottom band beside the command line,
 * where the fixed chrome guarantees it is on screen. */
body .trust { display: none !important; }

/* ── 13. THE COMMAND BAR ──────────────────────────────────────────────────
 * cyber.fund's pinned input, our vocabulary. Hairline box, mono, a `>` prompt,
 * no fill, no CTA, no mic. The results list is the only thing in the app
 * allowed to float, so it is the only thing carrying a shadow. */
body footer {
  flex: none; background: var(--bg) !important;
  border-top: 1px solid var(--line);
  padding: 0 !important;
}
body .cmd { position: relative; padding: 8px 18px 0; }
body .cmd-line {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--line);
  padding: 7px 12px;
  transition: border-color var(--t);
}
body .cmd-line:focus-within { border-color: var(--ink3); }
body .cmd-caret { color: var(--ink3); font-size: var(--t-sm) !important; flex: none; }
body #cmd-in {
  flex: 1 1 auto; min-width: 0;
  background: transparent !important; border: 0 !important; outline: 0 !important;
  color: var(--ink) !important; font-family: var(--mono) !important;
  font-size: var(--t-sm) !important; padding: 0 !important;
}
body #cmd-in::placeholder { color: var(--ink3); opacity: 1; }
body .cmd-key {
  flex: none; font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3);
  border: 1px solid var(--line); padding: 3px 7px;
}

body #cmd-pop {
  position: absolute; left: 18px; right: 18px; bottom: calc(100% - 8px);
  max-height: 52vh; overflow-y: auto; z-index: 80;
  padding: 6px 0;
}
body #cmd-pop[hidden] { display: none; }
body .cmd-grp {
  padding: 8px 12px 4px;
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}
body .cmd-r {
  display: grid; grid-template-columns: 30px minmax(0, 15ch) minmax(0, 1fr);
  align-items: baseline; gap: 12px; width: 100%;
  padding: 5px 12px !important; text-align: left;
  background: transparent !important; border: 0 !important;
  border-left: 2px solid transparent !important;
  color: var(--ink2) !important; cursor: pointer;
  font-size: var(--t-sm) !important; letter-spacing: normal !important;
  text-transform: none !important;
}
body .cmd-r .cmd-k { color: var(--ink3); font-size: var(--t-xs) !important; }
body .cmd-r .cmd-lb { color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
body .cmd-r .cmd-mt { color: var(--ink3); font-size: var(--t-xs) !important;
  letter-spacing: normal !important; text-transform: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body .cmd-r.on, body .cmd-r:hover {
  border-left-color: var(--accent) !important;
  background: transparent !important;
}
body .cmd-r.on .cmd-mt, body .cmd-r:hover .cmd-mt { color: var(--ink2); }
body .cmd-none { margin: 0; padding: 16px; color: var(--ink3); font-size: var(--t-sm) !important; }
body #cmd-note { margin: 6px 18px 0; color: var(--ink3); font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; text-transform: uppercase; }
body #cmd-note[hidden] { display: none; }

/* The recording claim: the counter in the display serif, the sentence in mono,
 * on one hairline-topped line under the command bar. */
body .foot-bar {
  display: flex; align-items: baseline; gap: 10px 22px; flex-wrap: wrap;
  padding: 8px 18px 9px !important;
  margin-top: 8px;
  border-top: 1px solid var(--line);
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3);
}
body .foot-bar .tr-count { display: inline-flex; align-items: baseline; gap: 12px; }
body .foot-bar .tr-count b {
  font-size: var(--t-lg) !important;
  letter-spacing: var(--tr-display) !important; text-transform: none;
  color: var(--ink) !important;
}

/* ── 14. THE ODOMETER ─────────────────────────────────────────────────────
 * tread.fi's price ticker, applied to the recording counter. app.js emits one
 * span per character and marks only the characters that changed on the poll;
 * this fades them back from the accent over 400ms.
 *
 * THE LIT DIGIT IS MINT, NOT GOLD, and that is the three-jobs rule doing real
 * work rather than being a slogan. "This digit just moved" is LIVENESS — the
 * same thing the status dot and the recency ramp say — so it takes the mint.
 * Gold would have said ATTENTION, i.e. "look here, act", which is a different
 * and wrong claim about a number that simply advanced.
 *
 * NUMBERS SNAP, COLOUR GLIDES. The digit's VALUE changes instantly; only its
 * colour transitions. Easing the value would read as laggy — the thing that
 * makes most dashboards feel cheap — while easing the colour is what lets you
 * see WHICH column moved after the fact.
 *
 * The mono face gives every character the same advance width, so nothing
 * reflows when 9 becomes 0 — no explicit width needed, and none that could be
 * wrong at a different font size. */
body .odo-c {
  display: inline-block;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  transition: color 400ms var(--t-ease);
}
body .odo-c.odo-hit { color: var(--live); transition: none; }
body .odo-sep { opacity: .45; }

/* ── 15. MAGNITUDE AS A COMPOSITOR BAR, NOT A WASH ────────────────────────
 * The Strategies board expressed net cost as a background alpha —
 * `color-mix(var(--mint) calc(var(--i) * 52%))` — which, now that --mint is
 * ink, painted 35 grey blocks over the whole board and put the fills straight
 * back onto a page that had just had them taken off.
 *
 * Same data, drawn as a rule: a 2px bar along the bottom of the cell scaled by
 * --i. transform:scaleX is the only way to draw this that never touches layout
 * or paint — the browser's compositor owns it, so 35 of them cost the same as
 * one, and no JS animation loop exists at all. width: or background: would put
 * every cell back on the layout path.
 *
 * The four honesty distinctions the board already made are KEPT, and all four
 * are now line rather than fill:
 *   firm quote    solid bar
 *   indicative    45deg hatch across the cell, as before, rebuilt on --line
 *   net credit    bar in full ink, and the words still say "net credit"
 *   no price      no bar at all */
body .op-mx-c.val {
  background: none !important;
  background-image: none !important;
  border: 0 !important;
  border-bottom: 1px solid var(--line) !important;
  border-right: 1px solid var(--line) !important;
  position: relative; overflow: hidden; opacity: 1 !important;
}
body .op-mx-c.val::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--ink3);
  transform: scaleX(var(--i, 0)); transform-origin: left center;
  transition: transform 400ms var(--t-ease);
  pointer-events: none;
}
body .op-mx-c.val.credit::after { background: var(--ink); }
body .op-mx-c.val.credit { box-shadow: none !important; }
body .op-mx-c.val.indic {
  background-image: repeating-linear-gradient(-45deg,
    var(--line) 0 1px, transparent 1px 6px) !important;
}
body .op-mx-c.val.open, body .op-mx-c.val.pinned {
  border-color: var(--ink) !important;
}
body .op-mx-c.val:hover { border-color: var(--ink3) !important; }
body .op-cell { padding: 6px 12px 6px 6px !important; }

/* ── 15b. THE FLOW TREEMAP ────────────────────────────────────────────────
 * Its six category hues were six SOLID fills, and once they were flattened to
 * ink the map became a wall of near-black rectangles with ground-coloured
 * labels punched out of them — the single heaviest object in the app.
 *
 * It is an alpha ladder of one ink now, every box carries a hairline, and the
 * labels flip from --bg to --ink so they read on any step. Area still encodes
 * premium, which is what a treemap is for.
 *
 * BE HONEST ABOUT WHAT THIS COSTS: an ordinal ladder is a weaker categorical
 * encoding than six hues. It is not, however, weaker than what shipped —
 * style.css's own note records the six hues measuring dE 4.7 on the light
 * theme against a floor of 15, i.e. already not separable, with the direct box
 * labels doing the real work and declared mandatory for that reason. The
 * labels are untouched and the legend swatches step with the boxes.
 *
 * THE LADDER IS BUILT ON THE LIVENESS MINT, NOT ON INK (2026-08-05 colour
 * pass). Flattening it to ink was correct in kind and wrong in execution: on
 * the dark theme it rendered as a full-width wall of near-identical grey
 * rectangles, the single largest dead surface in the app and the clearest case
 * of the owner's "nothing is showing". Same ladder, same six steps, same
 * ordinal encoding — one hue over, onto the colour that already means
 * "premium we actually observed trading", which is precisely what area encodes
 * here. No axis is added: this is one hue at six alphas, exactly as before.
 *
 * Measured, ink on the strongest step: 8.7:1 light, 12.1:1 dark. */
:root {
  --cat-crypto: rgba(10,124,140,.34); --cat-equity: rgba(10,124,140,.27);
  --cat-etf:    rgba(10,124,140,.21); --cat-index:  rgba(10,124,140,.15);
  --cat-gold:   rgba(10,124,140,.10); --cat-preipo: rgba(10,124,140,.05);
}
:root[data-theme="dark"] {
  --cat-crypto: rgba(80,210,193,.30); --cat-equity: rgba(80,210,193,.24);
  --cat-etf:    rgba(80,210,193,.185); --cat-index:  rgba(80,210,193,.13);
  --cat-gold:   rgba(80,210,193,.085); --cat-preipo: rgba(80,210,193,.045);
}
body .fl-k, body .fl-v, body .fl-p { fill: var(--ink) !important; opacity: 1 !important; }
/* §69 scale: the treemap labels were 12/12/10, none of them on the ladder. */
body .fl-k { font-size: 13px !important; font-weight: 600 !important; }
body .fl-v { font-size: 13px !important; }
body .fl-p { font-size: 11px !important; opacity: .7 !important; }
body .fl-t rect { stroke: var(--line); stroke-width: 1; }
body .fl-go:hover rect { stroke: var(--ink); stroke-width: 1.5; opacity: 1; }
body .fl-dead:hover rect { opacity: 1; }

/* Venue logos are third-party brand PNGs — six of them, in six brand palettes,
 * repeated down every table. Desaturated, not removed: the SHAPE is what makes
 * a venue recognisable at 14px, and the colour was the only thing left on the
 * page still arguing with the ink. */
body .mk image, body .mk img { filter: grayscale(1) contrast(1.08); }

/* ── 16. ROW FLASH ON ARRIVAL — the one ambient signal ────────────────────
 * tape.js already marks prepended fills with data-fresh and clears it on a
 * timer, so this needs no new JS and forces no layout on arrival (#tape runs
 * overflow-anchor:none precisely because it prepends). 150ms, which is
 * tread.fi's figure: fast enough to catch the eye, too short to linger.
 *
 * This is the app's SECOND and last animation. The logo's assembly animation
 * was retired to make room for it — that gesture was designed for a 34px
 * filled tile and is invisible on the 22px hairline glyph the mark is now,
 * whereas this one is tied to a real event on the page. */
@keyframes row-flash {
  from { background-color: var(--flash); }
  to   { background-color: transparent; }
}
:root { --flash: rgba(10, 124, 140, .16); }
:root[data-theme="dark"] { --flash: rgba(80, 210, 193, .22); }
body .tw-row[data-fresh="true"] { animation: row-flash 150ms linear 1; }
body .capmark .cm-tk, body .capmark .cm-pay, body .capmark .cm-strike {
  animation: none !important; opacity: 1 !important;
  stroke-dashoffset: 0 !important;
}
body .foot-bar .tr-count i, body .foot-bar .tr-since { font-style: normal; color: var(--ink3); }
body .foot-bar .byline { margin-left: auto; }
body #method {
  padding: 14px 18px 18px; border-top: 1px solid var(--line);
  max-width: 90ch; color: var(--ink3);
}
body #method p { font-size: var(--t-sm) !important; line-height: 1.8; max-width: 78ch; }
body .rec { display: flex; gap: 28px; align-items: baseline; padding-bottom: 18px; }
body .rec-num { display: flex; flex-direction: column; gap: 6px; }

@media (max-width: 1100px) {
  body .top, body .rail, body .cmd, body .foot-bar, body #method { padding-left: 14px; padding-right: 14px; }
  body #cmd-pop { left: 14px; right: 14px; }
  body #cmd-note { margin-left: 14px; margin-right: 14px; }
}
@media (max-width: 700px) {
  body .top, body .rail, body .cmd, body .foot-bar, body #method { padding-left: 10px; padding-right: 10px; }
  body #cmd-pop { left: 10px; right: 10px; }
  body #cmd-note { margin-left: 10px; margin-right: 10px; }
  body .rl-item { padding: 8px 10px !important; }
  body .brand > div { flex-direction: column; gap: 4px; }
  body .brand .tag { display: none; }
  body .cmd-r { grid-template-columns: 26px minmax(0, 1fr); }
  body .cmd-r .cmd-mt { display: none; }
}

/* ── 17. THE TEXT CULL ────────────────────────────────────────────────────
 * "Focus less on text and more on data and the organization of it." Cutting
 * text is not the same as cutting information, and these three lines were the
 * clearest case: each of them restates, in a second paragraph, an instruction
 * the panel's own subtitle has already given one line above.
 *
 *   .sc-hint  "Click a pricing, traded or chain value to narrow the board…"
 *             vs the sub: "…what a floor costs there, and whether anything
 *             has actually traded." — and the columns are visibly interactive.
 *   .tw-hint  "Filters stack; click a value again to clear it. Size and
 *             Premium headers sort."
 *             vs the sub: "Click any value to filter by it; click the Size or
 *             Premium headers to sort." Same sentence, twice, 120px apart.
 *
 * Both are DISPLAY:NONE rather than deleted from their modules: they are that
 * module's copy to own, the affordance survives in the subtitle, and a single
 * line here is reversible by whoever disagrees. Between them they return four
 * rows of the table per screen, which is the trade this pass is making —
 * fewer sentences, more fills. */
body .sc-hint, body .tw-hint { display: none !important; }

/* Prose gets a measure. Not for airiness — an unbroken 1,100px line of mono is
 * genuinely hard to re-find the start of, and the paragraph is the one place
 * on this page where that matters. Tables keep the full width. */
body .panel-head .sub, body .answer-strip, body .rowsub { max-width: 104ch; }

/* The last two stray tracking values. The scale is exactly three — normal,
 * +.14em on tracked labels, -.02em on display — and these were the only two
 * elements still asking for a fourth and fifth. */
body .fl-k, body .fl-v, body .fl-p { letter-spacing: normal !important; }

/* Stray border colours. Everything that is not the chrome hairline, the
 * four-state marker or a transient focus ring resolves to the hairline. */
body .op-mx-c.val.open, body .op-mx-c.val.pinned,
body .sc-row, body .sc-head, body .ms-bar, body .ms-seg,
body #ranked td, body #ranked th { border-color: var(--line) !important; }

/* ── 18. THE BLOG-TO-TRADING RATIO ────────────────────────────────────────
 * Owner: "for the moment it reads or gives the vibe of a blog."
 *
 * That was a RATIO problem, not a styling problem. A blog is prose-dominant —
 * long sentences, generous leading, few numbers, text as the subject. Every
 * table on this page had an explanatory sentence above it, a hint line below
 * it, a caption under that and a footnote under that, so the words outnumbered
 * the numbers on a page whose entire subject is numbers.
 *
 * The fix is ratio, not deletion. Exactly ONE thing per section keeps prose
 * size and prose colour — the answer strip, which is the actual finding and
 * the journal voice the owner wants kept. Everything else that used to be a
 * paragraph becomes what it always was: furniture. Tiny, mono, muted, and
 * sitting out of the way of the data.
 *
 * Nothing is removed. The honesty disclosures — which fill feeds we index,
 * what "indicative" means, that unknown is not zero — are load-bearing and
 * they all stay on the page. They are demoted, not cut. */
body .answer-strip {
  font-size: var(--t-md) !important;
  color: var(--ink2) !important;
  line-height: 1.55;
  padding: 6px 0 12px !important;
}
body .panel-head .sub,
body .tw-blind, body .tw-blind *,
body .op-note, body .op-note *,
body .rowsub, body .rowsub *,
body .tw-foot, body .tl-note, body .sc-note,
body .pick-why, body .cw-go {
  font-size: var(--t-sm) !important;
  color: var(--ink3) !important;
  line-height: 1.45;
}
/* The table starts immediately under its heading. There was a paragraph, a
 * hint line and 28px of air between the two on every section. */
body .panel-head { padding: 0 0 6px !important; }
body .panel-head .sub { margin: 2px 0 0 !important; max-width: 110ch; }
body .tw-blind { border-left: 1px solid var(--line) !important; padding: 5px 0 5px 10px !important;
  background: none !important; margin: 6px 0 !important; }
body .op-note { border-left: 1px solid var(--line) !important; padding: 5px 0 5px 10px !important;
  background: none !important; margin: 6px 0 !important; }

/* ── 19. NUMBERS ARE THE SUBJECT ──────────────────────────────────────────
 * "Make numbers the largest and highest-contrast thing in any row; labels
 * become tiny mono, uppercase, muted — they are furniture, not content."
 * One rule each, and the contrast ladder does the ranking: the value takes
 * --ink, its unit and its qualifier take --ink3. */
body td, body .tw-c, body .sc-c { color: var(--ink2); }
body td b, body .tw-c b, body .sc-c b, body .op-cell b, body .cell b,
body .value, body .ms-v, body .rk-money b {
  color: var(--ink) !important; font-weight: 600 !important;
}
body .muted, body .tiny, body .tw-none, body .op-unit, body .dt-unit,
body .tw-sub, body .sc-sub { color: var(--ink3) !important; }

/* AN ABSENCE IS NOT A VALUE, and the rule two lines up was making it one.
   screener.css:381 already says `.cell.unk b, .cell.dim b { color: var(--ink3) }`
   — but that is a normal declaration at (0,2,1) and `body .sc-c b` above is
   !important, which beats it at any specificity. Measured 2026-08-19 on the
   Compare board: "no offer" and "no feed" rendered rgb(248,244,240), the same
   ink as "2.88%" in the cell beside them, while the TRADED column's "No feed"
   correctly took --ink2. Same fact, three weights, one row. This introduces no
   colour; it lets screener.css's own decision survive. */
body .cell.unk b, body .cell.dim b,
body .cell.unk i, body .cell.dim i {
  color: var(--ink3) !important; font-weight: 500 !important;
}

/* ── 20. THE SEMANTIC PAIR, SEPARATE FROM THE BRAND ───────────────────────
 * Hyperliquid's structure, and it is the reason the green swap is safe here
 * when it was not before: the BRAND accent and the POSITIVE semantic are
 * deliberately different hues, so "this is interactive" and "this number went
 * up" can never read as the same family.
 *
 *   brand accent   #50d2c1 teal   dark   ·  #0a5f68   light
 *   positive       #1fa67d green  dark   ·  #0f7a57   light
 *   negative       #ed7088 pink   dark   ·  #b04058   light
 *
 * Pink rather than red for negative, also from Hyperliquid: it reads as a
 * design decision rather than an error state, which matters on a page where
 * half the numbers are legitimately negative.
 *
 * The pair is DATA ONLY. It never appears on a control, a link or a heading —
 * those are all ink. Separation is MEASURED, not eyeballed — CIELAB dE76
 * against the 15-point floor the dataviz validator uses:
 *   dark   brand #50d2c1 vs positive #1fa67d   dE 21.8   PASS
 *   light  brand #0a5f68 vs positive #0f7a57   dE 30.4   PASS
 *   positive vs negative (dark)                dE 95.0   PASS
 * The light brand was #0e7a6c on the first attempt and measured dE 13.0 —
 * a FAIL — so it was moved toward cyan until it cleared. That is the exact
 * collision that killed the lime recency ramp, caught before shipping this
 * time because it was measured instead of looked at. */
body .pos, body .cc-v.traded, body .op-mx-c.val.credit b { color: var(--pos) !important; }
body .neg { color: var(--neg) !important; }

/* ── 21. THE TWO TEMPOS, AND WHAT MAY MOVE ────────────────────────────────
 * 150ms for "something is DIFFERENT" — hover, selection, the inset edge.
 * 400ms for "how MUCH" — bars, magnitude, anything scaled.
 * Collapsing both onto one duration is what makes a dashboard feel cheap: the
 * eye reads a state change and a quantity change as the same event.
 *
 * TEXT CARRIES NO TRANSITION AT ALL. Snapping digits read as live; easing
 * digits read as laggy. The only exception in the app is the odometer's
 * COLOUR, which is not the value.
 *
 * TRANSFORM ONLY. scaleX from the mid-facing edge, which the compositor owns.
 * Animating width would relayout the panel on every tick. */
body .op-mx-c.val::after,
body .rk-bar i, body .cap-bar, body .ms-seg, body .tw-mag {
  transition: transform var(--t-mag) var(--t-mag-ease) !important;
  will-change: transform;
}
body .op-b, body .tl-btn, body .tl-tab, body .py-chip, body .dt-asset,
body .cs-btn, body .theme-btn, body .op-chip, body .rl-item, body .cmd-r,
body .tw-b, body .sc-row, body tbody tr, body .op-mx-c.val, body td.cov-c,
body .tl-c, body .cmd-line {
  transition: background-color var(--t-state) var(--t-ease),
              border-color var(--t-state) var(--t-ease),
              box-shadow var(--t-state) var(--t-ease),
              color var(--t-state) var(--t-ease) !important;
}
/* The value itself never eases. */
body .odo-c { transition: color 400ms var(--t-ease) !important; }
body b, body strong, body .tw-c, body td, body .sc-c, body .value {
  transition: none !important;
}

/* ── 22. THE EDGE IS THE AFFORDANCE ───────────────────────────────────────
 * Hover is a wash plus a 2px INSET bar on the leading edge. With zero radius
 * anywhere in this system it lands like a cursor in a terminal rather than
 * like a button lighting up — which is the difference between "instrument"
 * and "website" in one property.
 *
 * The bar takes the row's OWN direction colour where the row has one (the fill
 * tape publishes data-side), and gold — attention — where it does not. That is
 * the three-jobs rule again: on a signed row the edge is telling you which way
 * it went; on an unsigned one it is only telling you where the cursor is. */
body .sc-row:hover, body .tw-row:hover, body tbody tr:hover,
body .cmd-r.on, body .cmd-r:hover, body .rl-item:hover {
  background-color: var(--hover-wash) !important;
  box-shadow: inset 2px 0 0 0 var(--accent) !important;
}
body .tw-row[data-side="buy"]:hover  { box-shadow: inset 2px 0 0 0 var(--pos) !important; }
body .tw-row[data-side="sell"]:hover { box-shadow: inset 2px 0 0 0 var(--neg) !important; }
body .cmd-r.on, body .cmd-r:hover { border-left-color: transparent !important; }
body .rl-item.on { box-shadow: none !important; }

/* ── 23. THE SIGN PAIR, AND ONLY THE SIGN ─────────────────────────────────
 * Jade and rose are allowed on exactly these: a signed number, a direction
 * word, a bid/ask side, and the skew poles (protection-bid vs upside-bid,
 * which is a direction and not a quality). Nowhere else. --pos was BLUE in the
 * palette this replaces, which mattered: every use of it was checked to be a
 * DIRECTION rather than an "informational blue", and the skew poles — the one
 * documented CVD-validated pair in the app — are a direction. */
body .pos, body .up, body .tw-side-buy, body .cc-v.traded { color: var(--pos) !important; }
body .neg, body .down, body .tw-side-sell { color: var(--neg) !important; }
body .op-mx-c.val.credit b { color: var(--pos) !important; }
body .op-mx-c.val.credit::after { background: var(--pos) !important; }
body .op-mx-c.val::after { background: var(--ink3); }

/* ── 24. LIVENESS ─────────────────────────────────────────────────────────
 * Everything that means "this is happening now" wears the mint, and nothing
 * else does. The recency ramp IS the liveness colour at five alpha steps over
 * the ground — which also retires an old worry: the ramp used to be moved
 * lime -> blue because lime collided with the gold accent, and a ramp built
 * from the liveness colour cannot collide with the liveness colour. Recency
 * and liveness were always the same statement. */
body .dot, body .dot.live { background: var(--live) !important; }
body .tw-row[data-fresh="true"] { animation: row-flash var(--t-state) linear 1; }
body .tk-i.tk-new .tk-a, body .tw-fresh, body .sc-fresh { color: var(--live) !important; }

/* ── 25. GOLD IS ATTENTION AND NOTHING ELSE ───────────────────────────────
 * --warn was gold, and 24 rules across five stylesheets used it to mean
 * "unknown", "stale", "indicative", "not finished" and "heads up" — five
 * different claims wearing the colour that is supposed to mean "you are here /
 * act here". Most visibly it painted the Flow section's honesty paragraph
 * ("7 assets are missing from this picture…") entirely gold, which read as an
 * alert about something that is simply a fact.
 *
 * --warn is muted ink now. Those states keep their real encodings, which were
 * always the load-bearing ones anyway: the hatch for unknown, the dashed
 * outline for listed-no-trades, the word "indicative" for indicative.
 *
 * Gold is left with exactly four jobs, all of them "where you are / where you
 * act", none of them a value: */
:focus-visible { outline: 1px solid var(--accent) !important; outline-offset: 2px; }
body .rl-item.on { border-bottom-color: var(--accent) !important; }
body .rl-item.on .rl-n { color: var(--accent-ink) !important; }
body .op-b.on, body .op-chip.on, body .seg button.on,
body .tw-tab[aria-selected="true"], body .dt-asset.on, body .dt-lv button.on,
body .tl-tab[aria-selected="true"] {
  border-color: var(--accent) !important;
  color: var(--ink) !important;
  font-weight: 600 !important;
}
body td.cov-c:not(.none):hover, body td.cov-c:not(.none):focus-visible,
body .tl-c:not(.none):hover, body .tl-c:not(.none):focus-visible,
body .op-mx-c.val:hover {
  outline: 1px solid var(--accent) !important; outline-offset: -1px;
}
/* and nothing else. */

/* ── 26. THE LAST TWO HARD-CODED HEXES ────────────────────────────────────
 * tools.css paints the Python console at a literal #14161b and its table hover
 * at #1b1e25 — a deliberate "terminal" panel, written when the app had one
 * theme. On the light ground it rendered as a black slab with light text in
 * the middle of a white page: the only element in the app that did not know
 * which theme it was in. It keeps its raised-terminal identity; it just takes
 * it from the token that already means "raised surface". */
body .py-out { background: var(--rail) !important; color: var(--ink2) !important;
  border: 1px solid var(--line) !important; }
body .py-out * { color: inherit !important; }
body .py-tab tbody tr:hover td { background: var(--hover-wash) !important; }

/* ── 27. THE FIRST-RUN CARD ───────────────────────────────────────────────
 * onboard.js injects its own <style> at runtime and builds the card from
 * `background: var(--card)` and `box-shadow: var(--elev)`. Both of those are
 * now "nothing" by design, so the card rendered as unstyled text floating
 * over the live board — the one thing a first-time visitor sees, broken.
 *
 * It is a genuine floating popover, which is the single exception this file
 * grants to the no-shadow rule, so it takes --pop and the popover shadow like
 * every other thing that actually floats. Selectors are `body .ob-*` (0,1,1)
 * so they beat the injected `.ob-*` (0,1,0) on specificity — order cannot be
 * relied on against a <style> tag written at runtime. */
body .ob-card {
  background: var(--pop) !important;
  border: 1px solid var(--line) !important;
  box-shadow: 0 10px 40px rgba(0,0,0,.35) !important;
  padding: 16px 18px 12px !important;
}
body .ob-eyebrow { color: var(--ink3) !important; font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; margin: 0 0 10px !important; }
body .ob-h { font-size: var(--t-md) !important; letter-spacing: var(--tr-display) !important;
  font-weight: 600 !important; color: var(--ink) !important; }
body .ob-p { font-size: var(--t-sm) !important; color: var(--ink3) !important; }
body .ob-door { border: 1px solid var(--line) !important; background: transparent !important;
  font-size: var(--t-sm) !important; padding: 8px 10px !important; }
body .ob-door:hover { border-color: var(--ink) !important; background: var(--hover-wash) !important; }
body .ob-door b { color: var(--ink3) !important; font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; }
body .ob-bar { margin-top: 14px !important; padding-top: 10px !important; }
body .ob-next { background: transparent !important; color: var(--ink) !important;
  border: 1px solid var(--accent) !important; font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; text-transform: uppercase; padding: 6px 12px !important; }
body .ob-skip, body .ob-steps { color: var(--ink3) !important; font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; text-transform: uppercase; }

/* ═══════════════════════════════════════════════════════════════════════════
 * 28. THE SIGNALS, SPENT
 *
 * Owner: "if you are using white then it's tricky but it gets mixed with
 * everything and at the end nothing is 'showing', hard to show things."
 *
 * He is describing a real and measurable failure, not a taste. The register
 * pass above built a correct three-signal system — gold for attention, mint for
 * liveness, jade/rose for direction — and then spent almost none of it: on the
 * rendered page gold appeared on the active section's 1px underline and
 * essentially nowhere else, and jade on a single net-credit figure. A palette
 * that exists in the tokens and not in the pixels is not discipline, it is an
 * unshipped feature.
 *
 * NOTHING BELOW ADDS AN AXIS. No fourth hue, no fifth font size, no radius, no
 * shadow, no second curve. Every rule takes one of the three colours the system
 * already declares and puts it on the element that has been earning it all
 * along. The test each one has to pass is a single question: does this element
 * make a claim that is exactly ATTENTION, exactly LIVENESS, or exactly
 * DIRECTION? If it makes some other claim, or two of them, it stays ink.
 * ═════════════════════════════════════════════════════════════════════════ */

/* ── 28a. LIVENESS — MINT, AND THE RAMP HAS TO BE VISIBLE ──────────────────
 * "A fill from an hour ago should look different from one from yesterday at a
 * glance." It did not: the age column was one grey for every row on the page,
 * and the ONLY recency encoding in the app was a 12px swatch in the board's
 * traded cell.
 *
 * tape.js already publishes the bucket — data-age-h, 0=last hour, 1=last six,
 * 2=last day, 3=older — as a cumulative INDEX precisely so that CSS can key off
 * it. So this costs no JavaScript and no new markup; it reads a signal the tape
 * has been emitting on every row all along and nothing was listening to.
 *
 * TWO MINT STEPS, THEN TWO GREYS, and that is a contrast constraint rather than
 * a design preference: age is content, so every step has to clear 4.5:1, which
 * puts a floor under how dim a mint may get. #50d2c1 is 10.1:1 and #45a99e is
 * 6.5:1; a third step down would land at 3.3:1 and fail. Below the mints the
 * ramp continues in ink — the ladder is four steps whether or not all four are
 * coloured, and running out of legal mint is not a reason to fake one. */
body .tw-row[data-age-h="0"] .c-age { color: var(--live) !important; font-weight: 600 !important; }
body .tw-row[data-age-h="1"] .c-age { color: var(--live2) !important; }
body .tw-row[data-age-h="2"] .c-age { color: var(--ink2) !important; }
body .tw-row[data-age-h="3"] .c-age { color: var(--ink3) !important; }

/* Arrival. The row already flashes; it now also carries the mint edge for the
 * 2.4s tape.js holds data-fresh, so a fill that landed while you were reading
 * is findable AFTER the flash has gone rather than only during it. Same
 * property the hover edge uses, so nothing new is introduced — and it wins over
 * the hover edge for exactly as long as the row is genuinely new. */
body .tw-row[data-fresh="true"] { box-shadow: inset 2px 0 0 0 var(--live) !important; }

/* The status line is the app's one permanent liveness readout and it was set in
 * the same muted grey as a footnote. The dot keeps the saturated mint; the text
 * steps up to --ink2 so the sentence beside it can actually be read. */
body .status { color: var(--ink2) !important; }
body .dot, body .dot.live { width: 6px !important; height: 6px !important; }

/* ── 28b. DIRECTION — JADE AND ROSE, ON THE TWO SURFACES THAT ARE ABOUT
 *         NOTHING ELSE ───────────────────────────────────────────────────────
 * Trades is a list of directions and Stats is literally titled "buyers vs
 * sellers", and on both of them every direction rendered in the same grey. This
 * is the clearest case in the app of a colour that exists having no pixels: the
 * sign is the SUBJECT of these two sections.
 *
 * SCOPED TO THE ACTION CELL, deliberately. tape.js puts .buy/.sell on the
 * filter button, and that button also appears in the venue and expiry columns;
 * colouring the class globally would tint a venue name by the side of the trade
 * it happened to sit next to, which is the "one colour, two jobs" collapse this
 * whole system exists to prevent. .c-act is the cell whose entire content is
 * the direction. */
body .tw-c.c-act .tw-b.buy .p  { color: var(--pos) !important; }
body .tw-c.c-act .tw-b.sell .p { color: var(--neg) !important; opacity: 1 !important; }

/* The mosaic. stats.css builds these two fills from `color-mix(--mint 20%)` and
 * `color-mix(--good 20%)` — and --mint is INK in this system, so "bought" came
 * out grey while "sold" came out jade: the two sides of the market rendered as
 * one direction and one absence. Both sides now carry their own sign, and the
 * value inside each block carries it too. */
/* THE FILL IS CAPPED BY THE TEXT THAT SITS ON IT, not by taste. The first pass
 * ran 26%/22% and measured 4.47:1 dark and 3.44:1 light for the value inside
 * the block — a fail on light, and a fail I would not have seen by looking,
 * because a jade number on a jade wash looks fine and simply is not legible.
 * The fill drops until the direction colour clears 4.5:1 on it, and the 2px
 * edge picks up the weight the fill gives away. */
body .ms-c.buy {
  background: color-mix(in srgb, var(--pos) var(--ms-a, 14%), var(--bg)) !important;
  border-left: 2px solid var(--pos) !important;
}
body .ms-c.sell {
  background: color-mix(in srgb, var(--neg) var(--ms-a, 14%), var(--bg)) !important;
  border-left: 2px solid var(--neg) !important;
}
:root { --ms-a: 5%; }   /* light: the value inside is 12px, so it needs the
                           full 4.5:1 and not the 3:1 large-text allowance —
                           measured 4.78:1 jade / 4.58:1 rose at this alpha */
:root[data-theme="dark"] { --ms-a: 17%; }
body .ms-c.buy .ms-v  { color: var(--pos) !important; }
body .ms-c.sell .ms-v { color: var(--neg) !important; }

/* ── 28c. ATTENTION — GOLD, ON "WHERE YOU ARE" AND "WHAT YOU PICKED" ───────
 * Gold's four jobs were declared in §25 and three of them were spent on states
 * a reader rarely sees (focus rings, hover outlines). The two it should always
 * be spending — the active section, and the selection driving the page — are
 * the ones it was not.
 *
 * THE ACTIVE SECTION goes from a 1px underline to a 2px underline plus a gold
 * wash plus a gold bracket. That is three devices on one element, which is
 * defensible exactly once: it is the answer to "where am I", the single
 * question a reader asks most often and the one the owner reports failing. The
 * bracket is still always drawn, so nothing moves. */
body .rl-item.on {
  border-bottom: 2px solid var(--accent) !important;
  /* The wash is theme-split because the GOLD BRACKET SITS ON IT. At a flat 9%
   * the light theme's wash lifted the ground to #f0eee5 and the deep gold
   * measured 3.9:1 on it — the "you are here" marker failing the contrast bar
   * on the exact pixel that carries the message. Dark has headroom, light does
   * not, so light gets less wash and keeps its glyph. */
  background: color-mix(in srgb, var(--accent) var(--on-wash, 6%), transparent) !important;
}
:root { --on-wash: 6%; }
:root[data-theme="dark"] { --on-wash: 11%; }
body .rl-item.on .rl-n { color: var(--accent) !important; }
body .rl-item.on .rl-l { color: var(--ink) !important; font-weight: 600 !important; }
/* Inactive items lift to --ink2, not --ink3. Six destinations rendered in
 * footnote grey is the "users have to search for the right place" report: they
 * did not read as navigation at all. */
body .rl-item .rl-l { color: var(--ink2) !important; }

/* THE SELECTION. The asset picker decides what every number on the board says,
 * and it was styled as a tertiary control — the same hairline as a sort button.
 * Gold is "you picked this", which is exactly what it is. */
body #asset-pick select, body .controls #asset-sel {
  border-color: var(--accent) !important;
  color: var(--ink) !important;
}
/* The active sort column: also "where you are", in a table. */
body .sc-h.on, body .sc-h[aria-sort]:not([aria-sort="none"]) { color: var(--accent) !important; }

/* ── 28d. THE RAIL'S SCENT LINE ───────────────────────────────────────────
 * "Does a first-time user know what each section contains before clicking?"
 * They did not: nav.js moved the one-sentence question into a `title`, which is
 * a 1-2 second hover delay, invisible on touch and invisible to anyone who does
 * not already suspect there is something to hover.
 *
 * The sentence comes back as ONE line, right-aligned in the rail's own row, at
 * the far end of the bracket strip. It costs no vertical space at all (the row
 * exists anyway), it never reflows (one line, fixed row height, ellipsis), and
 * it changes on hover — so running the cursor along six brackets reads out six
 * questions without a single click or a single layout shift. */
body .rl-q {
  margin-left: auto; padding: 8px 0 7px 24px;
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color var(--t-state) var(--t-ease), opacity var(--t-state) var(--t-ease);
  flex: 0 1 auto; min-width: 0;
}
body .rl-q::before { content: "› "; color: var(--accent); }
@media (max-width: 900px) { body .rl-q { display: none; } }

/* ═══════════════════════════════════════════════════════════════════════════
 * 29. THE COMMAND BAND — cyber.fund's bottom, fully built
 *
 * The bar was already pinned to the bottom (the shell is height:100dvh with a
 * flex:none footer, so the band never scrolls away — verified by rendering, not
 * assumed from the markup). What it was missing is everything AROUND the input,
 * and that is what makes the reference's version inviting rather than merely
 * present.
 *
 * cyber.fund, rendered this session at 1440x900: the prompt is pinned bottom at
 * y=804, full width, `> Type '/' or ask`, with the commands it accepts listed
 * ABOVE it (`/apply  for application`, in the accent) and a `Quick access` chip
 * row BELOW it. Three parts, in that order. Ours takes the same three parts and
 * fills them from the same vocabulary the board renders, so the chips can never
 * offer an asset the board does not have.
 *
 * WHAT IS STILL NOT COPIED: the mic and the `apply` CTA. Unchanged reasoning —
 * we have no voice input and nothing to apply to.
 * ═════════════════════════════════════════════════════════════════════════ */
body .cmd { position: relative; padding: 6px 18px 0 !important; }

/* The examples line. This is the reference's "Type /apply for application"
 * block, compressed to one row because a screener's footer cannot spend a card
 * on it. The TYPED TOKEN is gold and the gloss is muted — gold on the thing you
 * would type is attention pointing at an action, which is the colour's job
 * exactly, and it is the same move cyber.fund makes with its red. */
body .cmd-eg {
  display: flex; align-items: baseline; gap: 0 22px; flex-wrap: wrap;
  margin: 0 0 5px !important; padding: 0;
  font-size: var(--t-xs) !important;
}
body .cmd-eg-h {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}
body .cmd-eg-b {
  display: inline-flex; align-items: baseline; gap: 7px;
  background: transparent !important; border: 0 !important; padding: 0 !important;
  cursor: pointer; text-align: left;
  font-size: var(--t-xs) !important;
}
body .cmd-eg-b b {
  color: var(--accent) !important; font-weight: 400 !important;
  letter-spacing: normal !important; text-transform: none;
  border-bottom: 1px solid transparent;
}
body .cmd-eg-b i {
  font-style: normal; color: var(--ink3) !important;
  letter-spacing: var(--tr-label) !important; text-transform: uppercase;
}
body .cmd-eg-b:hover b { border-bottom-color: var(--accent); }

/* The field. Its own stacking context so the results list can anchor to the
 * INPUT rather than to the whole band — otherwise the list floats above the
 * examples row with a gap under it and reads as belonging to nothing. */
body .cmd-field { position: relative; }
body .cmd-line {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--line);
  padding: 8px 12px;
  background: var(--panel) !important;
  transition: border-color var(--t-state) var(--t-ease),
              background-color var(--t-state) var(--t-ease) !important;
}
/* Focus is gold, because focus is the definition of attention. The band is the
 * one place in the app where the accent is allowed to outline a whole box. */
body .cmd-line:focus-within, body.cmd-open .cmd-line { border-color: var(--accent) !important; }
body .cmd-caret { color: var(--ink3) !important; font-size: var(--t-sm) !important; flex: none; }
body .cmd-line:focus-within .cmd-caret, body.cmd-open .cmd-caret { color: var(--accent) !important; }
/* The placeholder is not decorative furniture here — it is the only instruction
 * the bar gives, sitting on the raised --panel field. At --ink3 it measured
 * 4.25:1 on that panel. It takes --ink2: the invitation should be readable. */
body #cmd-in::placeholder { color: var(--ink2) !important; opacity: 1; }
body .cmd-key {
  flex: none; font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
  border: 1px solid var(--line); padding: 3px 7px;
  transition: color var(--t-state) var(--t-ease), border-color var(--t-state) var(--t-ease);
}
body.cmd-open .cmd-key { color: var(--accent) !important; border-color: var(--accent); }

/* THE RESULTS LIST, ANCHORED TO THE INPUT AND ANIMATED.
 *
 * It used to appear and vanish on `display:none`, which cannot transition — the
 * list simply existed or did not, on a page whose every other state change is
 * eased on one curve. Closed is now a transformed, invisible, non-interactive
 * state instead of an absent one, so opening and closing both run on --t-ease
 * at the app's own duration. visibility:hidden (not opacity alone) is what
 * keeps it out of the accessibility tree and out of the tab order while
 * closed. */
body #cmd-pop {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 6px); top: auto;
  max-height: 48vh; overflow-y: auto; z-index: 80;
  padding: 6px 0;
  opacity: 1; transform: none; visibility: visible;
  /* !important, and it is not decoration: §2's blunt layer sets
   * `transition-duration: var(--t-dur) !important` on every element in the app,
   * which silently rewrites the `0s` below into 160ms. On a DISCRETE property
   * like visibility that does not fade — it flips at the halfway point — so the
   * closed list stayed in the accessibility tree and the tab order for a
   * quarter of a second after Esc. Caught by driving it, not by reading it. */
  transition: opacity var(--t-ui) var(--t-ease),
              transform var(--t-ui) var(--t-ease),
              visibility 0s linear !important;
}
body #cmd-pop[hidden] {
  display: block;
  opacity: 0; transform: translateY(6px); visibility: hidden;
  pointer-events: none;
  /* Closing delays the visibility flip by the length of the fade, so the list
   * is still painted while it eases out and gone the instant it is invisible. */
  transition: opacity var(--t-ui) var(--t-ease),
              transform var(--t-ui) var(--t-ease),
              visibility 0s linear var(--t-ui) !important;
}
/* The highlighted result. Gold bar AND gold label — the bar alone was a 2px
 * mark on the far left of a 1400px row, i.e. nowhere near the word the reader
 * is looking at while pressing Enter. */
body .cmd-r.on, body .cmd-r:hover {
  border-left-color: transparent !important;
  box-shadow: inset 2px 0 0 0 var(--accent) !important;
  background-color: var(--hover-wash) !important;
}
body .cmd-r.on .cmd-lb { color: var(--accent) !important; }
body .cmd-r.on .cmd-k  { color: var(--accent) !important; }

/* QUICK ACCESS. The reference's chip row, and here it does a second job the
 * reference's does not have to: it is the ONLY route to two real destinations.
 *
 *   "The venues"      tools.js renders a full venue registry — "who is on the
 *                     other side of each trade?" — and the section rail has no
 *                     entry for it and the tools tab bar that used to reach it
 *                     is hidden by nav.css. Measured on the live page: zero
 *                     click paths. A rendered section with no route is a dead
 *                     end, and this is the fix that does not add a seventh
 *                     bracket to a rail the owner fixed at six.
 *   "The whole board" the every-venue-by-every-structure matrix, collapsed
 *                     inside a <details> at the bottom of Markets.
 *
 * The asset chips ahead of them are the live vocabulary — the top assets by
 * observed premium, read from /api/coverage — so the row also TEACHES the bar:
 * clicking ETH does exactly what typing "eth" does. */
body .cmd-quick {
  display: flex; align-items: center; gap: 0 8px; flex-wrap: wrap;
  padding: 6px 0 7px;
}
body .cq-h {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important; margin-right: 4px;
}
body .cq {
  background: transparent !important; border: 1px solid var(--line) !important;
  color: var(--ink2) !important; cursor: pointer;
  padding: 4px 9px !important;
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase;
  transition: border-color var(--t-state) var(--t-ease),
              color var(--t-state) var(--t-ease),
              background-color var(--t-state) var(--t-ease);
}
body .cq:hover { border-color: var(--ink3) !important; color: var(--ink) !important;
  background: var(--hover-wash) !important; }
body .cq.on { border-color: var(--accent) !important; color: var(--ink) !important; }

body .foot-bar { margin-top: 0 !important; padding: 6px 18px 7px !important; }

@media (max-width: 700px) {
  body .cmd-eg .cmd-eg-b:nth-of-type(n + 3) { display: none; }
  body .cmd-quick .cq:nth-of-type(n + 5) { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
 * 30. MEASURED, ON RENDERED PIXELS
 *
 * Every figure below was read back off a screenshot of the running page — the
 * element's bounding box cropped out of the PNG, the modal colour taken as the
 * ground and the furthest-luminance colour as the ink — NOT from computed CSS
 * over a declared background. That distinction is not pedantry here: almost
 * every surface in this app declares `background: transparent`, so computed-CSS
 * contrast checks compare ink against `rgba(0,0,0,0)` and pass everything.
 *
 *                                  dark          light
 *   body ink on ground            16.4:1        16.7:1
 *   secondary ink (--ink2)         9.0:1         8.1:1
 *   muted ink (--ink3)             5.7:1         4.9:1
 *   gold on ground                10.4:1         5.2:1
 *   mint on ground                10.1:1         4.8:1
 *   jade on ground                 7.0:1         4.9:1
 *   rose on ground                 5.9:1         4.7:1
 *   ink over --q5 (newest cell)    4.6:1         8.9:1
 *   age step 1 (--live2)           6.5:1         4.7:1
 * ═════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   §30 — BOARD DENSITY PASS (2026-08-05)

   Brief: "in hyperliquid we have many doses of the color green... in moneyness
   we have only one dose", "there is number and under them text and different
   colours... too much information", and the reference is app.hyperliquid.xyz
   /vaults — white data, muted headers, visible column separation, not crowded.

   MEASURED FIRST, on the live board at 1440x1000, counting only elements that
   actually render (an earlier count of mine included .sc-l, which is the
   1px-clipped screen-reader label and is not on screen at all):

     every visible line in every cell is 12px. Value and caption differ only
     by weight (600 vs 400) and ink (--ink vs --ink3).

   That is the whole problem, and it is not a colour problem. With no size
   contrast the only separation left is hue, so the page kept acquiring tint
   until it read as a terminal. The fix is to spend SIZE, and then need less
   colour — not the reverse.
   ══════════════════════════════════════════════════════════════════════════ */

/* 1. ONE VALUE PER CELL. The caption under each number ("1,183 fills",
      "12 exp · 800–16,000", "unknowable", "not published") is the second half
      of the "number and under them text" the brief names. It is display:none
      rather than deleted from grid.js because setText() still writes to these
      nodes every poll; unwiring that is a render-path change, this is not.
      The <i> sits directly in the cell on magnitude columns and inside .sc-b
      on facet/nav columns, so both are named. */
body .sc-c > i,
body .sc-c .sc-b > i { display: none !important; }

/* 2. The chain line under the venue ("Aevo L2", "Derive Chain (OP Stack)").
      NOTE: these are .sc-ch filter CONTROLS, not captions — hiding them
      removes the board's only chain filter. Called out rather than done
      silently; the facet itself still exists in grid.js FILTERS.chain. */
body .sc-ch,
body .sc-sub { display: none !important; }

/* 3. HIERARCHY BY SIZE, NOT HUE. The value carries the row; it is the only
      thing left in the cell, so it gets the size the caption was crowding out.
      Scoped to .sc-c so the Market cell's ticker (.sc-af, in .sc-id) keeps its
      own scale. tabular-nums so columns of digits line up — the thing that
      makes a board read as an instrument. */
body .sc-c b {
  font-size: 15px !important;
  line-height: 1.15 !important;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em !important;
}

/* 4. Column headers step DOWN and back, so the data is the loudest thing on
      the board. This is the Hyperliquid relationship: muted small header,
      bright large value. */
body .sc-head > * ,
body .sc-h {
  font-size: 10px !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase;
  color: var(--ink3) !important;
}

/* 5. VISIBLE COLUMN SEPARATION, asked for by name. A hairline is enough once
      the cells are no longer two lines tall — at that density a rule reads as
      structure rather than as more ink. */
body .sc-c + .sc-c,
body .sc-head > * + * { border-left: 1px solid rgba(255, 255, 255, 0.055); }

/* 6. Breathing room. One line per cell frees the vertical space that the
      caption was using; it goes back as padding instead of as more rows. */
body .sc-c { padding-top: 9px; padding-bottom: 9px; }

/* ══════════════════════════════════════════════════════════════════════════
   §31 — DE-TERMINAL THE TYPE (2026-08-05)

   Brief: "I don't wanna have the UI look like a bloomberg terminal vibes and
   currently its what it look like in terms of graphistims."

   MEASURED, not guessed — sampled every rendering text node on #trade at
   1440x1000: 217 of 217 were ui-monospace. Not one sans-serif on the page.
   That is the terminal signature, and it came from exactly two declarations:

     §17  body *:not(svg) { font-family: var(--mono) !important }
     :root --sans: var(--mono)      <- the sans token aliased to the mono one

   The references this is aimed at — Hyperliquid, cyber.fund, tread.fi — are
   not mono pages. They set INTERFACE text (nav, headings, labels, buttons,
   prose) in a clean grotesk and reserve mono for FIGURES, where it earns its
   place by making digits align. Mono everywhere spends the effect on words,
   which is why the page reads as a 1990s terminal rather than a 2026 trading
   app. So: sans becomes the default, and mono is re-asserted only where a
   number lives.

   No webfont — the artifact CSP blocks external font hosts and a blocked
   request stalls first paint, so this rides the system UI stack. -------- */

:root,
:root[data-theme="dark"] {
  --sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
          Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* The blanket normalisation now hands out the SANS. Same selector and same
   !important as §17 — this must be the layer that wins, and it is last. */
body *:not(svg):not(svg *) { font-family: var(--sans) !important; }

/* MONO IS FOR FIGURES. Every surface below is a number, a ticker, a price or
   a machine token — the places where character alignment is the point and a
   proportional face would make columns ragged. Tabular figures go with it, so
   digits keep their column whatever the value. */
/* On the board, mono follows ALIGNMENT, which is already the numeric/text
   split: grid.js right-aligns figures (.a-r) and left-aligns states (.a-l).
   So 1.10%, $995K and 560 stay mono and keep their columns, while "Firm",
   "Marks only" and "No feed" are words and get the sans like every other
   word on the page. Putting the whole cell in mono was the first pass and it
   left the board reading as a printout. */
body .sc-c.a-r, body .sc-c.a-r b, body .sc-c.a-r i,
body .sc-t, body .sc-af, body .sc-vm,
body .tw-c, body .tw-c b, body .tw-c i, body .tw-b, body .tw-addr,
body .op-cell, body .op-cash, body .op-net, body .op-mx-c, body .op-mx-c b,
body .value, body .num, body .ms-v, body .rk-money, body .rk-money b,
body .tl-c, body .cw-kv b, body .t-asset b, body .rk-nofeed,
body .cmd-field, body .cmd-field input, body #cmd-input,
body code, body pre, body kbd, body samp {
  font-family: var(--mono) !important;
  font-variant-numeric: tabular-nums;
}

/* Headings get the sans at a weight that reads as a product, not a printout.
   The display size stays where §17 put it; only the face and weight move. */
body h1, body h2, body h3 {
  font-family: var(--sans) !important;
  font-weight: 600 !important;
  letter-spacing: -0.015em !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   §32 — THE SHARE CONTROL ON THE TAPE (2026-08-05)

   "the share in the column should be better shown."

   MEASURED on a hovered row before touching it, and it was invisible for a
   concrete reason rather than a subtle one:

     background-color  rgba(0, 0, 0, 0)     <- .tc-share asks for var(--s2)
     border            0px none             <-    and §1 sets --s2: transparent
     colour            var(--ink2)          <- mid-grey, on the row it floats on

   So it rendered as four unboxed grey letters lying on top of the tape. Worse,
   elementsFromPoint at its centre returned `button.tw-b.tw-ab` underneath it —
   it was covering the maker column's own control, so the one thing it did
   reliably was intercept a click meant for something else.

   It needs to read as a control ON TOP OF a dense row, which means its own
   surface, its own edge, and a shadow — the one place a shadow is right on
   this page, because it is the only element that genuinely floats. Literal
   values, not the surface tokens: the tokens are what made it transparent. */

body .tc-share {
  background: #16262a !important;
  color: var(--ink) !important;
  border: 1px solid rgba(255, 255, 255, 0.16) !important;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.55) !important;
  padding: 5px 12px !important;
  font-size: 10px !important;
  font-weight: 600 !important;
  letter-spacing: 0.09em !important;
  opacity: 1 !important;
}

/* Gold on hover: this is an action the reader chose to reach for, and gold is
   already the attention job in the three-signal scheme. Dark ink on gold —
   --on-brand resolves to transparent in places, so the value is literal. */
body .tc-share:hover,
body .tc-share:focus-visible {
  background: #f0b90b !important;
  border-color: #f0b90b !important;
  color: #0b1416 !important;
}

/* Keyboard reachability: it was mouse-only (the button is appended to <body>
   and only positioned on mouseover), so a focus ring is the cheapest way to
   make it not lie about being a button. */
body .tc-share:focus-visible { outline: 2px solid #f0b90b; outline-offset: 2px; }

/* ══════════════════════════════════════════════════════════════════════════
   §33 — CONTAINED INSTRUMENT (2026-08-05)

   "It looks a bit like bloomberg terminal?" — and the axis census on #trade at
   1440x1000 says why, in six numbers rather than six opinions:

     content width      1404 of 1440px   (18px gutters — full bleed)
     border-radius      0 elements       (every corner square)
     box-shadow         0 elements       (one flat plane, no elevation)
     type scale         4 sizes, 2 weights
     uppercase          28 of 92 text nodes (30%)
     inks               5, and 3 of them are near-identical teal-greys.
                        Gold appears on 4 nodes. Mint on 1.

   That last line is the one worth keeping: the page is not over-coloured, it
   is a monochrome wash with a few coloured pixels. Spreading MORE tint over it
   is what drove it further into terminal territory. Colour has to be spent as
   SURFACE, in one confident place, not sprinkled.

   Full-bleed + square + flat + a third of the text in caps IS the terminal
   formula. cyber.fund and Paradigm are none of those things. This section
   changes the FRAME and leaves the data grid dense — the board keeps its
   hairlines and its square cells, because that part was never the problem. */

:root {
  --measure: 1300px;          /* the page's real width */
  --gutter: clamp(20px, 4vw, 56px);
}

/* 1. STOP EATING THE PAGE. The bars keep their full-bleed background — a top
      bar that stops short of the edge looks broken, not designed — while their
      CONTENTS align to the same measure as the board. Padding, not width, is
      what does that. */
body > header.top,
body > nav.rail,
body > footer,
body > .cmd {
  padding-left: max(var(--gutter), calc((100% - var(--measure)) / 2)) !important;
  padding-right: max(var(--gutter), calc((100% - var(--measure)) / 2)) !important;
}
body > .app {
  /* width:100% is load-bearing. body is a centring flex parent, so .app was
     shrink-to-fit — it measured 950px against a 1300px max-width that
     therefore never bound, and changing --measure moved nothing. Stretching it
     first is what makes the measure the thing that decides the width.
     border-box so --gutter is padding INSIDE the measure, not added to it. */
  width: 100% !important;
  max-width: var(--measure) !important;
  margin-inline: auto !important;
  padding-inline: var(--gutter) !important;
  box-sizing: border-box !important;
}

/* 2. CORNERS AND ELEVATION EXIST AGAIN. §17 sets border-radius:0 and
      box-shadow:none on every element; these carry a class, so they outrank it
      without needing to touch that layer. Containers soften, the data grid does
      NOT — a rounded table cell reads as a widget, and this one is an
      instrument. */
body .panel,
body .dt,
body .cmd-field,
body details.board-all,
body .tw-host {
  border-radius: 12px !important;
  border: 1px solid rgba(255, 255, 255, 0.07) !important;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 28px rgba(0, 0, 0, 0.28) !important;
}
/* .sc-h joins the exclusion list, which is where this belongs rather than in a
   later file: it is a <button> but it is a COLUMN HEADER, and §5 above draws
   the board's column separation as `border-left` on each header cell. A border
   follows its box's radius, so 8px bent every divider away from vertical at
   both ends - nine curled hairlines across the header, and the only row whose
   dividers did not line up with the square ones in the data below. */
body button:not(.sc-b):not(.sc-mk):not(.sc-af):not(.tw-b):not(.sc-h),
body .cmd-eg-b,
body .cmd-quick > *,
body select,
body .chip {
  border-radius: 8px !important;
}

/* 3. A REAL TYPE SCALE. 26 -> 15 -> 12 -> 10 is four steps that all read as
      "small"; the display never announces a section. The jump is what makes a
      page feel authored rather than printed. Data stays exactly where §30 put
      it — this moves the FRAME's voice, not the numbers'. */
/* `html body h1` rather than `body h1`: §17's blanket is
   `body *:not(svg):not(svg *)`, and :not() contributes its ARGUMENT's
   specificity, so that selector counts three type selectors (0,0,3) and beats
   a plain `body h2` (0,0,2) no matter how late it is declared or how many
   !importants it carries. Matching its weight and arriving later is what wins.
   This is the same trap that left the first font-size pass with no effect. */
html body h1 { font-size: 30px !important; letter-spacing: -0.025em !important; }
/* The real competitor was not the blanket after all: r3 declares
   `body .panel-head h2` (0,1,2), and the section title lives inside
   .panel-head — one class beats any number of type selectors. Named
   explicitly here rather than escalated blindly. */
html body .panel-head h2,
html body .dt-idtext h2,
html body h2 {
  font-size: 34px !important;
  line-height: 1.1 !important;
  letter-spacing: -0.03em !important;
  font-weight: 600 !important;
}

/* 4. UPPERCASE IS FOR COLUMN HEADERS, and nothing else. 30% of the page shouting
      is the single loudest terminal cue after the full bleed. The rail, the
      footer, the command examples and the legend all go back to sentence case;
      .sc-head / .tw-head keep it, because there a caps micro-label is genuine
      table furniture. */
body .rail *,
body footer *,
body .cmd *,
body .tl-legend *,
body .next-step { text-transform: none !important; letter-spacing: 0.01em !important; }

/* 5. COLOUR AS SURFACE. Gold stops being four stray pixels and becomes one
      block with a job: it marks where you are. A filled chip on the active rail
      item, and a solid rule under the section title — two places, both
      structural, neither decorative. Everything else stays quiet, which is what
      makes these two read at all. */
/* [aria-current="page"], NOT [aria-current]. nav.js writes aria-current="false"
   on the five inactive items — an attribute-presence selector matches "false"
   just as happily as "page", so the first version of this rule painted the
   entire rail gold and the active item stopped meaning anything. */
body .rail .rl-item.on,
body .rail [aria-current="page"] {
  background: #f0b90b !important;
  color: #0b1416 !important;
  border-radius: 8px !important;
  padding: 4px 10px !important;
  font-weight: 600 !important;
}
body .rail .rl-item.on *,
body .rail [aria-current="page"] * { color: inherit !important; }

body .hero-panel h2 {
  border-left: 4px solid #f0b90b !important;
  padding-left: 14px !important;
  margin-left: -18px !important;
}

/* 6. Air. The board was 18px from the window edge and the sections were stacked
      against each other; space is the cheapest thing that reads as considered. */
body .panel { padding: 22px !important; }
body .app > * + * { margin-top: 22px !important; }

/* 7. NARROW VIEWPORTS. Containing the page exposed a latent overflow: at 390px
      section.panel.hero-panel measured 806px, because a grid/flex child gets
      min-width:auto and therefore refuses to shrink below its content — and its
      content is a six-column board. The board is what should scroll, not the
      document, so the shrink is unblocked here and the scrollport is put on the
      board's own host. The rail is a horizontal strip of six and scrolls for the
      same reason. */
body .split,
body .split > *,
body .panel,
body .panel-head,
body .controls { min-width: 0 !important; }

body .sc-host,
body .tw-host { overflow-x: auto; }

body > nav.rail { overflow-x: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   §34 — THE VENUES TABLE (2026-08-05)

   "in the venues try to make it better display because it looks messy cards
   one under the other .. maybe another display would be better to follow the
   column vibes."

   It was six stacked cards each repeating the same six field labels. Now it is
   one row per venue under a single header, styled to the same rules the
   Markets board follows — because it is the same kind of object and a second
   visual language for it is what made the app feel like a scrapbook.
   ══════════════════════════════════════════════════════════════════════════ */

body .vn-table {
  display: grid;
  grid-template-columns:
    minmax(120px, 1.4fr)   /* venue */
    minmax(110px, 1.2fr)   /* how you trade */
    minmax(110px, 1.3fr)   /* network */
    minmax(60px, 0.6fr)    /* assets */
    minmax(78px, 0.7fr)    /* contracts */
    minmax(120px, 1.1fr)   /* prices */
    minmax(84px, 0.8fr)    /* firm quotes */
    minmax(120px, 1.1fr)   /* trades 24h */
    minmax(112px, 1.0fr);  /* counterparties */
  align-items: center;
  width: 100%;
  overflow-x: auto;
}

body .vn-head,
body .vn-row {
  display: contents;       /* rows are grid-transparent so every column in the
                              table shares ONE track sizing — the thing a stack
                              of independent cards can never do */
}

body .vn-c {
  padding: 11px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Header: the labels, written once. Same 10px muted caps as the board. */
body .vn-head .vn-c {
  font-size: 10px !important;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink3) !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

/* Figures right and tabular, words left — the board's own split. */
body .vn-n { text-align: right; font-family: var(--mono) !important;
             font-variant-numeric: tabular-nums; }
body .vn-name b, body .vn-name { color: var(--ink) !important; font-weight: 600 !important; }
body .vn-net { color: var(--ink2) !important; }

/* "no public prices" / "no trade feed" are ABSENCES, and the honesty rule this
   app is built on says an absence must look different from a value rather than
   like a zero. Muted, never red: a venue that does not publish is not broken. */
body .vn-off { color: var(--ink3) !important; }

/* n/a IS NOT 0, AND IT MUST NOT LOOK LIKE ONE. Italic and muted so a reader
   scanning the Firm-quotes column cannot mistake "we cannot measure this here"
   for a low score: an RFQ venue has no book to be two-sided, which is a fact
   about the venue's design, not a mark against it. Same treatment for a venue
   whose feed is live but quiet, and for one that trades without naming sides. */
body .vn-na {
  color: var(--ink3) !important;
  font-style: italic;
  font-variant-numeric: normal;
}

/* The premium under a fill count: subordinate, because the count is the claim
   and the money is the size of it. */
/* !important IS LOAD-BEARING HERE, not decoration. §343 sets
   `font-size: var(--t-sm) !important` on `body *:not(svg):not(svg *)`, and an
   important declaration beats a normal one at ANY specificity — so the plain
   `font-size: 0.88em` this started as was silently flattened to the body size
   and the premium rendered exactly as loud as the fill count above it. */
body .vn-sub {
  display: block;
  color: var(--ink3) !important;
  font-size: var(--t-dense) !important;   /* was 0.88em -> 13.2px, the one off-ladder size in the app */
  font-variant-numeric: tabular-nums;
}

body .vn-row:hover .vn-c { background: rgba(255, 255, 255, 0.028); }

/* §35 — Sheets: beta badge and the locked preview (2026-08-05) */

body .rl-beta {
  margin-left: 6px; padding: 1px 5px;
  font-size: 10px !important; letter-spacing: 0.07em;
  text-transform: uppercase !important;
  color: #f0b90b; border: 1px solid rgba(240, 185, 11, 0.45);
  border-radius: 8px !important; vertical-align: 1px;
}
body .rail .rl-item.on .rl-beta,
body .rail [aria-current="page"] .rl-beta {
  color: #0b1416 !important; border-color: rgba(11, 20, 22, 0.45);
}

/* The one live example, given room — it is the whole pitch. */
body .sh-demo {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 14px;
  padding: 18px 20px; margin: 18px 0 22px;
  background: rgba(255, 255, 255, 0.022);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-left: 3px solid #f0b90b;
  border-radius: 12px !important;
}
body .sh-code { font-family: var(--mono) !important; font-size: 14px !important; color: var(--ink) !important; }
body .sh-ret  { font-family: var(--mono) !important; font-size: 14px !important; color: #5aae87 !important; font-weight: 600 !important; }
body .sh-unit { color: var(--ink3) !important; }

body .sh-tiers { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
body .sh-tier {
  padding: 18px; border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 12px !important; background: rgba(255, 255, 255, 0.016);
}
body .sh-tier h4 { font-size: 13px !important; font-weight: 600 !important; margin: 0 0 6px; }
body .sh-tier p  { color: var(--ink2) !important; line-height: 1.5; margin: 0; }
body .sh-pro { border-color: rgba(240, 185, 11, 0.3); }
body .sh-cta {
  display: inline-block; margin-top: 14px; padding: 8px 14px;
  background: #f0b90b !important; color: #0b1416 !important;
  font-weight: 600 !important; border-radius: 8px !important; text-decoration: none;
}

/* §36 — THE ASSET COLUMN (2026-08-05)

   The tickers were rendering as "B…", "E…", "H…", "M…" — only two-character
   MU survived. The column measured 83px, of which 32px was padding and ~20px
   the entity mark, leaving about 25px of text: not enough for BTC or HYPE.

   Worth recording how this was missed: a check for scrollWidth > clientWidth on
   .c-asset returned zero clipped cells and read as a pass. The ellipsis is on
   the <b> INSIDE the cell, so the cell itself never overflows — the measurement
   was of the wrong element, and only looking at a magnified crop found it. The
   track now carries a 104px floor so the shrink cannot come back at a narrower
   viewport, and this column's padding is tightened because it is an icon+label
   pair, not prose. */
body .tw-c.c-asset { padding-left: 10px !important; padding-right: 8px !important; }
body .tw-c.c-asset button { gap: 7px; min-width: 0; }
body .tw-c.c-asset b { overflow: visible; text-overflow: clip; }

/* §37 — STRATEGIES: THE TEXT GOES BEHIND THE CLICK (2026-08-05)

   "in strategies still too much text while the text should be after clicking
   on the asset + and the visual display better, not text on the page."

   Measured on #strategies at 1440x1000: 143 words of prose in 6 blocks, before
   any row is opened. Three of them are page-level explanation that every reader
   pays for whether or not they wanted it —

     .op-lede  "A floor below spot and the cap that would pay for it, priced…"
     .op-note  "because the upside above the cap is sold"
     .op-fine  "Ranked by what a floor costs, net of what the matching cap…"
               + the excluded-asset list

   — and the row expansion already says all of it, on demand, for the row you
   actually asked about. So the explanation is not deleted, it is MOVED behind
   the click that asks for it, which is where the brief puts it.

   What stays is not prose: .op-sub-h is a live count ("35 shown · 5 net
   credits · 3 span two venues") and .op-div is a structural divider that tells
   you why the rows below it are separated. Both are data wearing words. */
body .op-lede,
body .op-note,
body .op-fine { display: none !important; }

/* §38 — Sheets playground (2026-08-05). Replaces the static .sh-demo line of
   formula syntax with a control that actually calls /api/sheets. The figure is
   the hero here, because the figure being REAL is the entire argument. */

body .sh-play {
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px 26px;
  padding: 20px 22px; margin: 18px 0 22px;
  background: rgba(255, 255, 255, 0.022);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-left: 3px solid #f0b90b;
  border-radius: 12px !important;
}
body .sh-pick { display: flex; gap: 6px; }
body .sh-a {
  padding: 7px 14px; cursor: pointer;
  font-family: var(--mono) !important; font-size: 12px !important; font-weight: 600 !important;
  color: var(--ink2) !important; background: transparent !important;
  border: 1px solid rgba(255, 255, 255, 0.14) !important; border-radius: 8px !important;
}
body .sh-a:hover { color: var(--ink) !important; border-color: rgba(255, 255, 255, 0.3) !important; }
body .sh-a.on {
  background: #f0b90b !important; border-color: #f0b90b !important;
  color: #0b1416 !important;
}
body .sh-out { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; min-width: 0; }
body .sh-val {
  font-family: var(--mono) !important; font-size: 30px !important;
  font-weight: 600 !important; color: #5aae87 !important;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em !important;
}
body .sh-unit { color: var(--ink3) !important; }

/* §39 — Sheets free tier: playground left, premium right (2026-08-05).
   Stacked, the Premium card sat under a full Python console and was reached
   only by scrolling past the control you were using. Side by side, the thing
   you came to do and the thing you might buy are both on screen at once. */

body .sh-split {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(240px, 1fr);
  gap: 22px;
  align-items: start;
  margin-top: 4px;
}
body .sh-main { min-width: 0; }              /* let the console shrink, not push */
body .sh-side { min-width: 0; }
body .sh-main .tl-sub.first { margin-top: 0 !important; }

/* One column once the console would be too narrow to type in. */
@media (max-width: 900px) {
  body .sh-split { grid-template-columns: minmax(0, 1fr); }
}

/* §40 — THE PLAYGROUND IS THE PAGE (2026-08-05)

   "the sheets free / playground should take more size ... find a better clean
   display for it."

   It is the only thing on the free tier a reader can DO, and it was sharing the
   row with a card they read once. So the split is re-weighted toward it, the
   editor gets room to hold a real expression instead of one line, and the
   output pane gets a floor so a result does not make the whole page jump. */

body .sh-split { grid-template-columns: minmax(0, 2.6fr) minmax(230px, 0.85fr); gap: 26px; }

/* A single framed console: header, editor, bar and output read as one object
   rather than four stacked strips. */
body .sh-main .py-box {
  border: 1px solid rgba(255, 255, 255, 0.09) !important;
  border-radius: 12px !important;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.018);
}
body .sh-main .py-box textarea {
  width: 100%; box-sizing: border-box;
  padding: 16px 18px !important;
  font-family: var(--mono) !important; font-size: 15px !important;
  line-height: 1.65 !important; color: var(--ink) !important;
  background: transparent !important; border: 0 !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07) !important;
  resize: vertical; min-height: 132px;
}
body .sh-main .py-box textarea:focus { outline: none; background: rgba(255,255,255,0.012) !important; }
body .sh-main .py-bar {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px !important;   /* §69 ladder: was 10px */
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
body .sh-main .py-out {
  padding: 14px 18px !important;
  min-height: 128px;                 /* results land without shifting the page */
  max-height: 340px; overflow: auto;
  font-family: var(--mono) !important; font-size: 13px !important;   /* §69 scale: was 12.5px */
  line-height: 1.6 !important;
}

/* The presets are the fastest path to a result, so they read as buttons worth
   pressing rather than as tags. */
body .sh-main .py-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
body .sh-main .py-chip {
  padding: 8px 14px !important; cursor: pointer;
  font-size: 11px !important; font-weight: 400 !important;   /* §69 scale */
  color: var(--ink2) !important; background: rgba(255, 255, 255, 0.03) !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important; border-radius: 999px !important;
}
body .sh-main .py-chip:hover {
  color: #0b1416 !important; background: #f0b90b !important; border-color: #f0b90b !important;
}

/* The section title carries the free tier, so it is a heading, not a label. */
body .sh-main .tl-sub.first {
  font-size: 20px !important; font-weight: 600 !important;
  color: var(--ink) !important; text-transform: none !important;
  letter-spacing: -0.01em !important; margin: 0 0 4px !important;
}

/* §41 — Sheets header, access form, and the Markets weight fix (2026-08-05) */

body .sh-top { margin-bottom: 18px; }
body .sh-h {
  font-size: 22px !important; font-weight: 600 !important;
  color: var(--ink) !important; text-transform: none !important;
  letter-spacing: -0.02em !important; margin: 0 0 4px !important;
}
body .sh-lede { color: var(--ink2) !important; margin: 0 !important; }

/* The panel is a form now, so it needs to read as one: labels above fields,
   fields full width, one primary action. */
body .sh-form { display: flex; flex-direction: column; gap: 4px; margin-top: 14px; }
body .sh-l {
  font-size: 10.5px !important; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--ink3) !important; margin-top: 8px;
}
body .sh-l i { font-style: normal; text-transform: none; letter-spacing: 0; opacity: 0.65; }
body .sh-i {
  width: 100%; box-sizing: border-box; padding: 9px 11px;
  color: var(--ink) !important; background: rgba(255, 255, 255, 0.04) !important;
  border: 1px solid var(--line) !important; border-radius: 8px !important;
  font-size: 13px !important;
}
body .sh-i::placeholder { color: var(--ink3) !important; }
body .sh-i:focus { outline: none; border-color: var(--accent) !important; background: rgba(255,255,255,0.06) !important; }
body .sh-t { resize: vertical; min-height: 62px; font-family: inherit !important; }
body .sh-form .sh-cta { margin-top: 14px; width: 100%; text-align: center; border: 0; cursor: pointer; }
body .sh-form .sh-cta[disabled] { opacity: 0.6; cursor: progress; }
body .sh-msg { margin: 8px 0 0 !important; font-size: 12px !important; color: var(--ink3) !important; line-height: 1.5; }
body .sh-msg.bad { color: #d98b8b !important; }
body .sh-msg.good { color: #5aae87 !important; font-size: 12px !important; }

/* ── MARKETS: WORDS ARE NOT BOLD ──────────────────────────────────────────
   "why in markets the text is displayed in bold?"

   §17 sets `font-weight: 600 !important` on every <b> inside a cell, which is
   right for a FIGURE — it is the row's answer and should carry weight. But the
   board puts words in the same <b>: "Firm", "Marks only", "On request",
   "No feed". Bold words read as emphasis nobody asked for, and next to the
   Trades tape — where the same states are plain — Markets looked like a
   different app.

   The split is the one already in the markup: grid.js right-aligns figures
   (.a-r) and left-aligns states (.a-l). Figures keep 600; words drop to 400
   and take --ink2, so the numbers stay the loudest thing on the board. */
body .sc-c.a-l b {
  font-weight: 400 !important;
  color: var(--ink2) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   §42 — ONE TITLE TREATMENT FOR EVERY SECTION (2026-08-05)

   "the titles in the different sections don't have the same size and are not
   similar in police ... it's messy right now." Measured across all seven:

     Markets / Trades   34px  600  sentence  --ink     <h2>
     Sheets             22px  600  sentence  --ink     .sh-h
     Strategies         12px  400  UPPERCASE --ink     .op-h
     Flow / Stats /     12px  400  UPPERCASE --ink3    .tl-sec-h
       Venues

   Four sizes, two weights, two cases, two inks — for the same job. And the
   NAMES disagreed with the rail: the rail said "Flow", the page said "By asset:
   where the money goes"; the rail said "Venues", the page asked "Who is on the
   other side?". A section whose title does not match the thing you clicked
   makes you re-derive where you are on every navigation.

   So: the title is the rail's own word, and the sentence it used to be becomes
   the sub line under it. One rule, every section. `html body` matches the
   specificity of the rules being replaced — see §33's note on why a plain
   `body .x` loses here. */

html body .tl-sec-h,
html body .op-h,
html body .sh-h,
html body .panel-head h2 {
  font-size: 34px !important;
  font-weight: 600 !important;
  line-height: 1.1 !important;
  letter-spacing: -0.03em !important;
  text-transform: none !important;
  color: var(--ink) !important;
  margin: 0 0 6px !important;
}

/* The sub line, also once: the sentence the title used to be. */
html body .tl-sec-s,
html body .op-sub,
html body .sh-lede {
  font-size: 12px !important;
  font-weight: 400 !important;
  text-transform: none !important;
  letter-spacing: normal !important;
  color: var(--ink2) !important;
  margin: 0 0 18px !important;
  max-width: 62ch;                    /* a readable measure, not the full width */
}

/* ══════════════════════════════════════════════════════════════════════════
   §43 — THE PLAYGROUND, EXPANDED

   "could it be opened in a popup or extend the page or something where they
   could test it better." A 132px editor in a side-by-side column is fine for
   one call and cramped for anything real, so the console promotes itself to
   most of the viewport. The SAME element is promoted — not cloned into a modal
   — so Run, the presets and the editor's history keep working with no second
   copy to keep in sync. Escape closes it.
   ══════════════════════════════════════════════════════════════════════════ */

body.py-zen-on { overflow: hidden; }        /* the page behind must not scroll */

body .py-box.py-zen {
  position: fixed;
  inset: 3vh 4vw;
  z-index: 120;
  display: flex;
  flex-direction: column;
  background: #0b1416 !important;
  border: 1px solid rgba(255, 255, 255, 0.14) !important;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.7) !important;
}
body .py-box.py-zen textarea {
  flex: 0 0 42%;
  min-height: 0 !important;
  font-size: 14.5px !important;
}
body .py-box.py-zen .py-out {
  flex: 1 1 auto;
  max-height: none !important;
  min-height: 0;
  font-size: 12px !important;
}
/* A dimmed ground, so the expanded console reads as the only live thing. */
body.py-zen-on::after {
  content: ""; position: fixed; inset: 0; z-index: 119;
  background: rgba(0, 0, 0, 0.62);
}

/* §44 — the collar mark, alive (2026-08-05)

   "the logo can keep moving like a cap and floor protection? that should be
   something nice to be animated and funny."

   The mark assembled once and then held. It now keeps a slow loop: spot walks
   the payoff and visibly STOPS moving at the floor and at the cap. The two
   guide ticks brighten as it reaches each corner, so the eye is told what just
   happened rather than left to infer it.

   Deliberately slow (4.2s) and low-contrast: it sits next to a live counter in
   the masthead, and a logo that competes with the data is a logo that has to be
   turned off. */

body .capmark .cm-spot { opacity: 0.9; }
body .capmark .cm-floor { opacity: 0; animation: cm-strike 260ms var(--ease-expressive) 900ms forwards; }

/* The corners pulse in time with spot arriving at them: floor at the start of
   the cycle, cap at the half-way point where it reverses. Same 4.2s period, so
   they stay locked to the motion without sharing a timeline. */
body .capmark .cm-floor  { animation: cm-corner 4.2s ease-in-out 1.1s infinite; }
body .capmark .cm-strike { animation: cm-corner 4.2s ease-in-out 1.1s infinite; animation-delay: 3.2s; }

@keyframes cm-corner {
  0%, 8%   { opacity: 0.95; }
  22%, 100% { opacity: 0.4; }
}

/* Hover holds it still and shows the whole structure — the existing brand hover
   already does this for the ticks; spot joins it rather than carrying on
   underneath. */
body .brand:hover .capmark .cm-spot { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  /* No looping motion at all: spot parks at the floor corner and the guides sit
     at their resting opacity. The mark still reads as a collar. */
  body .capmark .cm-spot { display: none; }
  body .capmark .cm-floor,
  body .capmark .cm-strike { animation: none; opacity: 0.5; }
}

/* §45 — PLAYGROUND OUTPUT (2026-08-05)

   The console ran fine; it just showed its results badly. Two shapes come back
   and neither was styled: a pandas frame (rendered to_html, but inheriting no
   table rules, so borderless unaligned text) and a dict (printed raw as one
   long line whose 300-character provenance note buried the five figures in
   front of it).

   Both are now tables, and both follow the board's rules: muted small headers,
   figures right and tabular, hairline row separators, prose set apart from
   numbers. */

body .py-out table {
  border-collapse: collapse;
  width: 100%;
  margin: 2px 0 6px;
  font-family: var(--mono) !important;
  font-size: 12px !important;
}
body .py-out th {
  text-align: left;
  font-weight: 400 !important;
  font-size: 10px !important;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink3) !important;
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  white-space: nowrap;
  vertical-align: top;
}
body .py-out td {
  padding: 6px 12px 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.045);
  color: var(--ink) !important;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* A pandas frame right-aligns its figures; keep that and let the first column
   (the asset) stay left so the eye has an anchor. */
body .py-out table:not(.py-kv) td { text-align: right; }
body .py-out table:not(.py-kv) td:first-child,
body .py-out table:not(.py-kv) th:first-child { text-align: left; color: var(--ink) !important; }
body .py-out tr:last-child td, body .py-out tr:last-child th { border-bottom: 0; }

/* key/value dicts: the label column stays narrow, values carry the weight. */
body .py-out .py-kv th { width: 1%; padding-right: 20px; border-bottom-color: rgba(255,255,255,0.045); }
body .py-out .py-kv td { text-align: left; }

/* The provenance sentence is context, not a measurement — it wraps, it is
   quiet, and it stops shouldering the numbers out of the way. */
body .py-out .kv-note td {
  white-space: normal;
  color: var(--ink3) !important;
  font-family: var(--sans) !important;
  font-size: 12px !important;
  line-height: 1.5;
  max-width: 62ch;
}

/* §46 — Premium is not open yet, and the panel says so plainly rather than
   implying a reply is coming. */
body .sh-soon {
  margin-top: 10px !important;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  color: var(--ink3) !important;
  font-size: 12px !important;
  line-height: 1.5;
}

/* §47 — the row a command pointed at, marked just long enough to find it. */
body .op-mx-r.op-focus > * {
  background: rgba(240, 185, 11, 0.10);
  transition: background 240ms var(--t-ease);
}
body .op-mx-r.op-focus .op-mx-a { box-shadow: inset 3px 0 0 #f0b90b; }

/* §48 — the board's figures stop shouting (2026-08-05)

   "the bold text on floor cost in table in markets should not be like this."

   §17 set every <b> in a cell to 600; §41 dropped the WORDS to 400 and left the
   figures bold. With one value per cell and a 15px size step already separating
   data from its 10px header, weight was doing a third job nothing had asked for
   — and on a column of percentages it reads as emphasis on every row, which is
   emphasis on none. Prominence now comes from size and ink alone, which is how
   the reference boards do it.

   Weight stops being a variable on this board entirely: 400 everywhere, words
   and figures alike. */
body .sc-c b,
body .sc-c.a-r b { font-weight: 400 !important; }

/* The legend host is emptied by grid.js rather than removed, so it must not
   keep its margins and leave a gap where eight swatches used to be. */
body #where-legend:empty { display: none !important; }

/* §49 — the Premium panel, dressed to sell (2026-08-05)

   It was a paragraph and an apology. A prospect could not tell what they
   already had, what they would get, or why either mattered. The panel now
   states the free tier they are standing in, lists what the paid tier adds as
   scannable lines, and carries one honest status. Gold marks the tier, not the
   whole card — a fully gold panel next to a working console reads as an advert
   and gets ignored. */

body .sh-pro {
  border-color: rgba(240, 185, 11, 0.28) !important;
  background: linear-gradient(180deg,
    rgba(240, 185, 11, 0.055) 0%,
    rgba(255, 255, 255, 0.015) 42%) !important;
  padding: 20px !important;
}
body .sh-pro-h { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
body .sh-pro-h h4 {
  margin: 0 !important; font-size: 17px !important; font-weight: 600 !important;   /* §69 scale: was 20px */
  color: var(--ink) !important; letter-spacing: -0.015em !important;
}
body .sh-badge {
  padding: 2px 8px; border-radius: 999px !important;
  background: #f0b90b; color: #0b1416;
  font-size: 11px !important; font-weight: 600 !important;   /* §69 scale: was 10px */
  text-transform: uppercase; letter-spacing: 0.08em;
}

/* Where you are now — quiet, because it is context and not the offer. */
body .sh-pitch {
  margin: 0 0 14px !important; padding-bottom: 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  color: var(--ink3) !important; font-size: 13px !important; line-height: 1.5;
}
body .sh-gets {
  margin: 0 0 8px !important;
  color: var(--ink2) !important; font-size: 13px !important;
}

/* The offer. Ticks rather than bullets: each line is a thing you receive. */
body .sh-list { list-style: none; margin: 0 !important; padding: 0 !important; }
body .sh-list li {
  position: relative; padding: 6px 0 6px 20px;
  color: var(--ink2) !important; font-size: 12px !important; line-height: 1.45;
}
body .sh-list li::before {
  content: "✓"; position: absolute; left: 0; top: 6px;
  color: #f0b90b; font-size: 12px; font-weight: 600;
}
body .sh-list b { color: var(--ink) !important; font-weight: 600 !important; }
body .sh-list code {
  font-family: var(--mono) !important; font-size: 12px !important;
  color: var(--ink) !important; background: rgba(255,255,255,0.06);
  padding: 1px 5px; border-radius: 8px !important;
}

body .sh-soon {
  margin: 14px 0 0 !important; padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  color: var(--ink3) !important; font-size: 13px !important; line-height: 1.5;
}

/* ══════════════════════════════════════════════════════════════════════════
   §51 — THE SCALE, STATED (2026-08-05)

   Feedback from Carlos: the UI "looks like AI and messy". Measured across all
   seven sections before acting on it, and he was right in a specific,
   checkable way — the page had drifted back to exactly the sprawl this file
   was written to collapse:

     font sizes  12   (34 26 20 17 15 13.5 13 12 11.5 11 10 9.5 8.5)
     weights      4   (400 500 600 700)
     radii        5   (4 7 8 12 999)

   None of it came from the original stylesheets. Every off-scale value was
   introduced by a patch appended tonight, each one locally reasonable and
   collectively a system with no discernible rule — which is precisely what
   "AI-generated" looks like: many decisions, no decision.

   Collapsed in place rather than patched over. What is now true:

     TYPE     34 display · 20 heading · 15 data · 12 body · 10 micro
     WEIGHT   400 and 600. Nothing else — 500 and 700 were arbitrary middles.
     RADIUS   12 card · 8 control · 999 pill.

   ONE DELIBERATE EXCEPTION, named so it is not mistaken for drift: the
   "Moneyness" wordmark sits at 26px. It is a brand element rather than an
   interface one, and locking a wordmark to a UI scale is how a masthead ends
   up looking like a heading.

   Anything added after this line must land on the scale above or state, here,
   why it does not.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   §52 — THE HEADLINE ON MARKETS (2026-08-05)

   The complaint was that the UI looks generated, and swapping hexes never
   touched it — because the problem was never colour. The section was one card
   containing one flat table, every row the same weight, the most valuable
   number on the page (the cheapest floor) rendered identically to the row
   above it, and 200px of dead space underneath.

   Aave's asset page states the shape of the market in labelled numbers and a
   filled bar BEFORE any table. We had the same facts, written as a sentence
   UNDER the table. Same information, rendered as something you must read
   rather than something you see.

   The bar is the real work. Coverage is a capacity story and it has three
   honest states: measured, blind, and genuinely absent. The hatched segment IS
   the "n/a is not 0" argument — for the first time it is visible instead of
   asserted.
   ══════════════════════════════════════════════════════════════════════════ */

body .sc-hl { display: flex; flex-direction: column; gap: 14px; margin-bottom: 20px; }

/* Labelled numbers, in a row, before the data. */
body .sc-hl-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 12px !important;
  overflow: hidden;
}
body .sc-hs {
  display: flex; flex-direction: column; gap: 7px;
  padding: 15px 16px;
  border-right: 1px solid rgba(255, 255, 255, 0.055);
  min-width: 0;
}
body .sc-hs:last-child { border-right: 0; }
body .sc-hl-l {
  font-size: 10px !important; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink3) !important; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
body .sc-hl-v {
  font-family: var(--mono) !important; font-size: 20px !important;
  font-weight: 600 !important; letter-spacing: -0.02em !important;
  font-variant-numeric: tabular-nums; color: var(--ink) !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body .sc-hl-v small {
  font-size: 12px !important; font-weight: 400 !important;
  color: var(--ink2) !important; margin-left: 3px;
  font-family: var(--sans) !important;
}

/* The coverage bar. */
body .sc-hl-cov { display: flex; flex-direction: column; gap: 9px; }
body .sc-hl-bar {
  display: flex; height: 8px; width: 100%;
  border-radius: 999px !important; overflow: hidden;
  background: rgba(255, 255, 255, 0.05);
}
body .sc-hl-bar i { display: block; height: 100%; }
body .sc-hl-key {
  display: flex; flex-wrap: wrap; gap: 8px 20px;
  font-size: 11px !important; color: var(--ink3) !important;
}
body .sc-hl-key span { display: flex; align-items: center; gap: 6px; }  /* §69 ladder */
body .sc-hl-key u { width: 8px; height: 8px; border-radius: 0 !important; text-decoration: none; display: block; }

/* Three states, three treatments. The hatch is deliberate: an absence must not
   look like a quantity, or it becomes a zero by accident. */
body .f-tr { background: var(--live, #ff7a1a); }
body .f-bl { background: color-mix(in srgb, var(--live, #ff7a1a) 38%, transparent); }
body .f-un {
  background: repeating-linear-gradient(135deg,
    rgba(255,255,255,0.14) 0 3px, transparent 3px 7px);
}

/* ══════════════════════════════════════════════════════════════════════════
   §53 — MIDNIGHT ARCADE (2026-08-05, owner's call)

   Replaces the borrowed palette. The old one was documented in our own
   stylesheet as Hyperliquid's mint-on-near-black plus the Binance yellow;
   this one is chosen rather than inherited.

   Adopted as proposed: the ink ground, the desaturated surface (measured at
   211deg / 210deg — same blue family, correctly built), the off-white text
   that is never pure white, the glacier cyan, and the 60-30-10 discipline.

   TWO DELIBERATE DEPARTURES, both because a trading instrument has semantics a
   marketing palette cannot know:

   1. CORAL IS NOT THE ACCENT. #FF5C7A measures 1.06 against our existing
      "sold" rose #e06e76 — the same colour to the eye. On the tape that pink
      already means sold, so a coral CTA would read as a sell signal on every
      screen. Direction owns the red family; the accent moves out of it.
   2. NO GOLD. #FFCF00 measures 1.22 against Binance's #f0b90b. Re-importing
      the exact colour we removed tonight for being borrowed would undo the
      point. Dropping it also retires the "two warm accents never cross" rule,
      which is a constraint someone has to enforce forever.

   So: ONE accent, cyan, doing what gold and violet did. Jade and rose stay on
   direction and nothing else.
   ══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="dark"] {
  --bg:   #0c0a08;          /* warm near-black — §63 replaced the navy  */
  --s1:   #17130f;          /* panel, same hue, same discipline          */
  --s2:   #201b16;          /* raised                                    */
  --line: #302a23;
  --line2:#423a31;

  --ink:  #f8f4f0;          /* never pure white              */
  --ink2: #c6bcb2;
  --ink3: #9b8e82;

  --brand: #ff7a1a; --brand-fill: #ff7a1a; --on-brand: #0c0a08;

  /* --live IS NOT THE ACCENT, AND §66 EXPLAINS THE COLLISION IN FULL.
     This line used to read `--live: #ff7a1a; --live2: #f07510` — the accent's
     own hex — which collapsed LIVENESS ("this is recent") onto WHERE-YOU-ARE
     ("this is the thing you picked"). Measured on the live page before the
     fix: --live and --accent both resolved to #ff7a1a, a WCAG ratio of 1.00,
     i.e. the same colour, on 179 age cells plus the status dot and the venue
     coverage bar. Mint again, and separable this time. */
  --live:  #2ee6cd; --live2: #3ac9b6;

  /* --mint STAYS POINTED AT THE ACCENT ON PURPOSE. Despite the name it is not
     the liveness token: every consumer of it is a where-you-are state — the
     sorted column (.sc-h.on), the open disclosure (.sc-b.on), the active chip
     (.sc-ch.on), the pinned cell, and every focus ring (--mint2). Re-pointing
     it at the mint would have turned the whole selection language green. The
     name is the misleading part, not the value. */
  --mint:  #ff7a1a; --mint2: #f07510;
}

/* The accent, everywhere the old gold was hardcoded in §33-§52. */
body .rail .rl-item.on,
body .rail [aria-current="page"] { background: #ff7a1a !important; color: #0c0a08 !important; }
body .rail .rl-item.on .rl-beta,
body .rail [aria-current="page"] .rl-beta { color: #0c0a08 !important; border-color: rgba(12,10,8,.45) !important; }
body .rl-beta { color: #ff7a1a !important; border-color: rgba(255,122,26,.45) !important; }

body .hero-panel h2 { border-left-color: #ff7a1a !important; }
body .sh-play, body .sh-demo { border-left-color: #ff7a1a !important; }
body .sh-badge { background: #ff7a1a !important; color: #0c0a08 !important; }
body .sh-pro {
  border-color: rgba(255,122,26,.28) !important;
  background: linear-gradient(180deg, rgba(255,122,26,.055) 0%, rgba(255,255,255,.015) 42%) !important;
}
body .sh-list li::before { color: #ff7a1a !important; }
body .sh-i:focus { border-color: #ff7a1a !important; }
body .sh-cta, body .sh-form .sh-cta { background: #ff7a1a !important; color: #0c0a08 !important; }
body .sh-a.on { background: #ff7a1a !important; border-color: #ff7a1a !important; color: #0c0a08 !important; }
body .sh-val { color: #ff7a1a !important; }
body .sh-main .py-chip:hover { background: var(--accent) !important; border-color: var(--accent) !important; color: #0c0a08 !important; }

body .tc-share:hover, body .tc-share:focus-visible {
  background: #ff7a1a !important; border-color: #ff7a1a !important; color: #0c0a08 !important;
}
body .tc-share:focus-visible { outline-color: #ff7a1a !important; }

body .op-mx-r.op-focus > * { background: rgba(255,122,26,.10); }
body .op-mx-r.op-focus .op-mx-a { box-shadow: inset 3px 0 0 #ff7a1a; }

/* 60-30-10: the accent marks WHERE YOU ARE and nothing else. Direction keeps
   the red family, which is why the accent had to leave it. */
body .f-tr { background: #ff7a1a; }
body .f-bl { background: rgba(255,122,26,.38); }

/* §53b — the last gold, found by querying rendered nodes rather than grepping
   source: the sorted column header and its arrow, the active tabs and chips,
   the asset picker's border, and three bold spans. Thirteen nodes, all of them
   "this one is active" — which is the accent's job, so they take the accent. */
body .sc-h.on, body .sc-h.a-l[aria-sort]:not([aria-sort="none"]),
body .sc-ar,
body .tw-tab.on, body .tl-tab[aria-selected="true"],
body .op-b.on, body .op-chip.on,
body .cs-native:focus, body #asset-sel:focus { 
  color: #ff7a1a !important;
  border-color: #ff7a1a !important;
}
body .sc-ar { border-bottom-color: #ff7a1a !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §54 — FLATTEN THE VENUE PANEL (2026-08-05)

   "the construction is messy ... the goal is not to put info on top of info but
   to make simple info available to the user, simple and boring."

   Counted on the live CallPut panel: 643px of height holding ~50 elements that
   each draw a box — three price cards with two more boxes inside each, five
   tiles, six method blocks, two sections, all nested. Every one of those
   borders is a line the eye has to parse before it reaches a number.

   The fix is subtraction, not restyling. Separation comes from SPACE and one
   hairline per section. Nothing inside a section draws its own container.
   A number on a flat ground is easier to read than the same number in a box,
   and five boxes in a row are five decisions the reader did not ask to make.
   ══════════════════════════════════════════════════════════════════════════ */

/* Nothing nested draws a box. */
body .dt .dt-p,
body .dt .dt-tile,
body .dt .dt-m,
body .dt .dt-ms,
body .dt .dt-p-s,
body .dt .dt-p-cost,
body .dt .dt-lv,
body .dt .dt-assets {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

/* Sections are separated by a rule and air, nothing else. */
body .dt .dt-sec {
  background: transparent !important;
  border: 0 !important;
  border-top: 1px solid rgba(255, 255, 255, 0.07) !important;
  border-radius: 0 !important;
  padding: 22px 0 4px !important;
  margin: 0 !important;
}
body .dt .dt-sec:first-of-type { border-top: 0 !important; }

/* The three structures read as a row of figures, not a row of cards. */
body .dt .dt-p {
  padding: 0 !important;
  display: flex; flex-direction: column; gap: 6px;
}
body .dt .dt-p-cost { font-variant-numeric: tabular-nums; }

/* Tiles become label-over-number, the same shape as the Markets headline, so
   the two screens teach the same reading habit. */
body .dt .dt-tile {
  padding: 0 !important;
  display: flex; flex-direction: column; gap: 5px;
}

/* Method and provenance are reference, not content: quiet, and never boxed. */
body .dt .dt-m,
body .dt .dt-ms { padding: 0 !important; color: var(--ink3) !important; }
body .dt code {
  background: transparent !important; border: 0 !important;
  padding: 0 !important; color: var(--ink2) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   §55 — THE AIR PASS: THE SCALE GOES UP (2026-08-07)

   "our current moneyness looks like a simple blog and will get 0 users."

   MEASURED FIRST, on rendered nodes at 1440x900 with the onboarding dismissed
   — a census of every text node with a non-zero box, reading computed
   font-size off the parent element rather than off declared CSS:

     12px   74 nodes   <- dominant
     10px   35 nodes
     15px   25 nodes
     20px    4 nodes
     26px    1 node
     34px    1 node

   Glider's dominant size is 16px across 52 nodes. Ours was 12px. That is the
   single largest structural difference between this page and every reference
   in IA.md, and it is not a palette problem: we spent 2026-08-05 making the
   page DENSER and the references all go the other way. Density reads as
   "terminal"; air reads as "product". Nothing on this page is so long that a
   reader needs 12px to fit it.

   §51 stated the old scale as 34 / 20 / 15 / 12 / 10 and said anything added
   after it lands on that scale or states here why not. This is that statement.
   The scale is not replaced, it is TRANSPOSED UP, and one step is added at the
   top for the thing §51 never had — a number the page leads with:

     WAS   34 display · 20 heading · 15 data · 12 body · 10 micro
     NOW   72 hero · 34 display · 22 heading · 17 data · 15 body · 11 micro

   ONE STEP ADDED BELOW, AND IT IS NAMED SO IT IS NOT MISTAKEN FOR DRIFT:

     13px DENSE — the 9+ column tabular surfaces ONLY (the fill tape, the
     coverage matrix, the flow board). Those tables are 9 and 23 columns wide
     and they already scroll horizontally at 1440. Taking their cells from 12
     to 15 with everything else would have bought air in the one place on the
     site where a column falling off the screen costs the reader a fact. So
     they move 12 -> 13 rather than 12 -> 15. The six-column MARKETS board is
     not in this exemption; it has room and it takes the full step.

   Weights stay 400 and 600. Radii stay 12 / 8 / 999. The 26px wordmark
   exception from §51 stands and is untouched.
   ══════════════════════════════════════════════════════════════════════════ */

:root,
:root[data-theme="dark"] {
  --t-xs: 11px;     /* micro   — column headers, uppercase labels   was 10 */
  --t-sm: 15px;     /* body    — the blanket default in §3          was 12 */
  --t-md: 16px;     /* prose   — the explanatory sentences          was 14 */
  --t-dense: 13px;  /* NEW, exempted above: 9+ column tables only          */
  --t-lg: 30px;     /* heading token; §21/§43 pin section titles at 34     */

  /* The hero. clamp() rather than a fixed 72: the whole point of this number
     is that it survives a timeline screenshot, and a fixed display size that
     overflows on a 390px phone is a screenshot of a broken page. Bottom of
     the range is still twice the body size, so the hierarchy holds at every
     width. */
  --t-hero: clamp(48px, 6.6vw, 76px);
}

/* DENSE SURFACES, LISTED EXPLICITLY. Each of these is a table with more
   columns than a 1440px viewport comfortably holds. Everything NOT named here
   took the full step up to 15px through §3's blanket rule. */
body .tw-c, body .tw-c b, body .tw-c i, body .tw-b, body .tw-addr,
body .tw-head, body .tw-head *,
body .op-mx-c, body .op-mx-c b, body .op-mx-a, body .op-mx-h,
body .cov-c, body .cov-c *,
body table td, body table th {
  font-size: var(--t-dense) !important;
}

/* THE MARKETS BOARD TAKES THE STEP. Six columns, and measured at 1440 it had
   ~380px of slack — the exact opposite of the tape's problem. The value in a
   cell goes 15 -> 17 (the "data" step) and the column header goes 10 -> 11. */
body .sc-c b { font-size: 17px !important; }
body .sc-h, body .sc-head .sc-h { font-size: var(--t-xs) !important; }

/* RE-SPACE. Larger type in the same boxes is just a cramped page in a bigger
   font — the air has to come with it or the change reads as a mistake. These
   are the four rhythms that carry the overview, roughly x1.6 on the vertical
   ones. §8 tightened all of them on purpose in the density pass; this reverses
   that specific decision and nothing else, because the density pass is the one
   the owner is reacting to. */
body main.stage { padding: 30px 34px 56px !important; gap: 30px !important; }
body .chart-wrap, body #where-grid, body #coverage-wrap { padding: 0 !important; }
body .sc-c { padding-top: 13px !important; padding-bottom: 13px !important; }
body .rowsub { padding: 20px 0 0 !important; line-height: 1.65; }
body .answer-strip { padding: 22px 0 0 !important; line-height: 1.65; }
body .tw-row, body .tw-head { line-height: 1.5; }
body th { padding: 9px 10px 8px !important; }
body td:not(.tl-c):not(.cov-c) { padding: 7px 10px !important; }

@media (max-width: 1100px) { body main.stage { padding: 24px 22px 44px !important; gap: 24px !important; } }
@media (max-width: 700px)  { body main.stage { padding: 18px 14px 36px !important; gap: 20px !important; } }

/* ══════════════════════════════════════════════════════════════════════════
   §56 — THE HERO NUMBER (2026-08-07)

   The skeleton Apple, Aave and Glider independently agree on, in the order the
   eye takes it:

     eyebrow   what this number is, and the contract it prices
     FIGURE    the number, at --t-hero
     side      what it is a percentage OF, and where you can hit it
     note      the honesty line: firm, on request, or absent
     chips     the venues carrying this asset — identity, and each one a door
     strip     three supporting counts, label over number (§52's shape, kept)
     bar       coverage, hatched segment intact (§52's argument, kept)

   Nothing here draws a box. §54 established that separation is space and one
   hairline; a hero in a card would be the exact thing that pass removed, one
   size larger. The only rule on the whole block is the one under the chips.
   ══════════════════════════════════════════════════════════════════════════ */

body .sc-hl { display: flex; flex-direction: column; gap: 34px !important; margin-bottom: 8px !important; }

body .mn-hero { display: flex; flex-direction: column; gap: 0; }

/* The eyebrow is two facts with different jobs: what the number IS (ink, the
   label you scan for) and which contract it prices (ink3, the fine print you
   read once). Same line, two weights of attention. */
body .mn-hero-eyebrow {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px;
  margin: 0 0 14px !important; padding: 0 !important;
}
body .mn-hero-lead {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink) !important; font-weight: 600 !important;
}
body .mn-hero-terms {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}

body .mn-hero-fig {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 22px;
  min-width: 0;
}

/* THE NUMBER. Mono, because it is a figure and §31's rule is that figures keep
   the mono face. Tight tracking and 0.92 leading so a 76px number does not
   reserve 100px of line box under itself. */
body .mn-hero-n {
  font-family: var(--mono) !important;
  font-size: var(--t-hero) !important;
  font-weight: 600 !important;
  line-height: 0.92 !important;
  letter-spacing: -0.045em !important;
  font-variant-numeric: tabular-nums;
  color: var(--ink) !important;
  display: inline-block;
}
/* The unit is not information at display size, so it is set back: half the
   size, ink2, and not italic despite being an <em> — it is a slot, not
   emphasis. */
body .mn-hero-n em {
  font-style: normal; font-size: 0.42em !important; font-weight: 400 !important;
  color: var(--ink2) !important; letter-spacing: 0 !important; margin-left: 0.06em;
}
/* AN ABSENCE IS NOT A QUANTITY. When there is no price the hero renders an em
   dash, and it is set in ink3 at a lighter weight so it cannot be mistaken for
   a value that happens to be small. "n/a is not 0" is the product's core
   honesty rule and the hero is the easiest place on the site to break it. */
body .mn-hero-n[data-kind="none"] { color: var(--ink3) !important; font-weight: 400 !important; }
/* An indicative quote is a real number and it is shown — but it is not the
   price you can hit, so it does not get the full-ink treatment a firm one
   does. The word "on request" in the eyebrow carries the fact; this carries
   the emphasis. */
body .mn-hero-n[data-kind="quote"] { color: var(--ink2) !important; }

body .mn-hero-side {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  padding-bottom: 4px;
}
body .mn-hero-of { font-size: var(--t-md) !important; color: var(--ink3) !important; }

/* The venue is a door, and it is the only accented thing in the hero — §53's
   rule is that cyan means "where you are"; here it means "where this price
   is". Underline rather than a filled pill: a CTA-shaped button beside a 76px
   number is two things competing to be pressed. */
body .mn-hero-v {
  background: transparent !important; border: 0 !important; padding: 0 !important;
  font-size: var(--t-md) !important; text-transform: none !important;
  letter-spacing: normal !important; color: #ff7a1a !important; cursor: pointer;
  border-bottom: 1px solid rgba(255, 122, 26, 0.35) !important;
  transition: border-color var(--t-state) var(--t-ease),
              color var(--t-state) var(--t-ease);
}
body .mn-hero-v:hover { border-bottom-color: #ff7a1a !important; }

body .mn-hero-note {
  margin: 16px 0 0 !important; padding: 0 !important;
  font-size: var(--t-md) !important; line-height: 1.5;
  color: var(--ink3) !important; max-width: 62ch;
}

/* ── IDENTITY CHIPS ──────────────────────────────────────────────────────── */
body .mn-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 24px; padding-top: 22px;
  border-top: 1px solid var(--line);
}
body .mn-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px !important;
  background: transparent !important;
  border: 1px solid var(--line) !important;
  border-radius: 999px !important;      /* §51's pill radius */
  color: var(--ink2) !important; cursor: pointer;
  text-transform: none !important; letter-spacing: normal !important;
  transition: border-color var(--t-state) var(--t-ease),
              color var(--t-state) var(--t-ease),
              transform var(--t-state) var(--t-ease);
}
body .mn-chip b { font-size: var(--t-sm) !important; color: var(--ink) !important; }
/* The state, on the chip. A venue we cannot see is SAID to be unreadable
   rather than left looking quiet — the same argument as the bar's hatch, one
   object smaller. */
body .mn-chip i {
  font-style: normal; font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important; text-transform: uppercase;
  color: var(--ink3) !important;
}
body .mn-chip[data-state="traded"] i { color: #ff7a1a !important; }
body .mn-chip[data-state="blind"] { border-style: dashed !important; }
body .mn-chip:hover { border-color: var(--line2) !important; transform: translateY(-1px); }
body .mn-chip:hover b { color: #ff7a1a !important; }
body .mn-chip svg, body .mn-chip img { flex: none; }

/* ── SUPPORTING STATS. §52's shape, re-spaced for the new scale. Three now,
      not four: the fourth was the cheapest floor and it is the hero. ─────── */
body .sc-hl-strip { border-radius: 12px !important; }
body .sc-hs { padding: 20px 22px !important; gap: 10px !important; }
body .sc-hl-l { font-size: var(--t-xs) !important; }
body .sc-hl-v { font-size: 22px !important; }
body .sc-hl-v small { font-size: var(--t-sm) !important; }
body .sc-hl-cov { gap: 12px !important; }
body .sc-hl-bar { height: 10px !important; }
body .sc-hl-key { font-size: var(--t-xs) !important; gap: 12px 24px !important; }  /* §69 ladder */

/* The board's own name, now that the 34px section title is gone. */
body .mn-board-h {
  margin: 0 !important; padding: 26px 0 0 !important;
  border-top: 1px solid var(--line);
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important; font-weight: 600 !important;
}

/* ── THE CONTEXT LINE. Was a .panel-head with a 34px <h2> and a bottom rule;
      it is one quiet line above the hero now. No rule under it — the hero is
      not a second section, it is what this line introduces. ──────────────── */
body .ov-ctx {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px;
  padding: 0 0 26px !important; border: 0 !important;
}
body .ov-ctx .pick-lead {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}
body .ov-ctx .pick-why { font-size: var(--t-sm) !important; color: var(--ink3) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §57 — MOTION: ARRIVAL AND STATE CHANGE (2026-08-07)

   Before this the page animated the logo mark, the live dot and a 10px view
   fade. Nothing else moved, ever — including the numbers, which is the one
   place a live product should. IA.md: "Movement is what makes a page feel
   alive; it is the thing most missing and it costs the least."

   THE RULES, and they are the reason this is cheap rather than noisy:

   1. TRANSFORM AND OPACITY ONLY. Both are compositor properties: no layout,
      no paint, no main-thread work per frame on a page that polls two
      endpoints every 20-60 seconds. Nothing here animates height, top,
      box-shadow or background-position.
   2. IT RUNS WHEN SOMETHING IS TRUE. The hero re-renders only when its
      content signature changes (grid.js headline()), so this fires on first
      paint and on a real change of asset or price — never on an idle poll.
      A page that pulses at you once a minute for no reason is worse than a
      still one.
   3. IT STAGGERS DOWNWARD, ONCE. Seven steps of ~55ms, ~385ms end to end
      (six until §60 added the chart between the note and the chips). The order
      is the reading order, so the motion teaches the hierarchy rather than
      decorating it.
   4. NOTHING MOVES MORE THAN 14px. The travel only has to say "this is new".
   5. prefers-reduced-motion: reduce KILLS ALL OF IT — no shortened version,
      no fade-only fallback. Every element at its end state, immediately.
   ══════════════════════════════════════════════════════════════════════════ */

@keyframes mn-rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}
/* The figure gets its own curve: it scales up from 0.94 as well as rising, so
   the largest thing on the page arrives as an event and the rest arrives as
   content. transform only — a scaled text node costs the compositor nothing
   because it is never re-rasterised at this duration. */
@keyframes mn-hero-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

body .sc-hl.mn-in .mn-hero-eyebrow,
body .sc-hl.mn-in .mn-hero-fig,
body .sc-hl.mn-in .mn-hero-note,
body .sc-hl.mn-in .mn-chart,
body .sc-hl.mn-in .mn-chips,
body .sc-hl.mn-in .sc-hl-strip,
body .sc-hl.mn-in .sc-hl-cov {
  animation: mn-rise 520ms var(--ease-expressive) backwards;
  will-change: transform, opacity;
}
body .sc-hl.mn-in .mn-hero-eyebrow { animation-delay: 0ms; }
body .sc-hl.mn-in .mn-hero-fig     { animation: mn-hero-in 640ms var(--ease-expressive) 55ms backwards; }
body .sc-hl.mn-in .mn-hero-note    { animation-delay: 110ms; }
body .sc-hl.mn-in .mn-chips        { animation-delay: 165ms; }
/* The chart's BOX arrives on the stagger; its contents land asynchronously and
   draw themselves in (§60's mn-ch-in / mn-ch-grow). The box reserves its
   height in CSS so the two never fight over layout. */
body .sc-hl.mn-in .mn-chart        { animation-delay: 220ms; }
body .sc-hl.mn-in .sc-hl-strip     { animation-delay: 275ms; }
body .sc-hl.mn-in .sc-hl-cov       { animation-delay: 330ms; }

/* THE COVERAGE BAR GROWS INTO ITS WIDTH. The segments are the "n/a is not 0"
   argument and the eye should watch them being drawn. scaleX from a left
   origin, not a width animation — width would relayout three siblings per
   frame; a transform does not touch layout at all. */
body .sc-hl.mn-in .sc-hl-bar i {
  transform-origin: left center;
  animation: mn-bar 700ms var(--ease-expressive) 355ms backwards;
}
@keyframes mn-bar { from { transform: scaleX(0); } to { transform: none; } }

/* STATE CHANGE, NOT ARRIVAL. The bar segments also transition their width
   between polls, so a venue that starts publishing fills is a segment that
   slides rather than a segment that jumps. This is the one width transition in
   the file and it is deliberate: the widths come from inline styles written by
   grid.js, so there is nothing to scale against. Three elements, once a
   minute at most. */
body .sc-hl-bar i { transition: width var(--t-mag) var(--t-mag-ease); }

/* The chips settle in after the row itself has arrived, left to right. Capped
   at eight because there are six venues and a stagger with no ceiling is a
   stagger that can be made arbitrarily long by the data. */
body .sc-hl.mn-in .mn-chip {
  animation: mn-rise 460ms var(--ease-expressive) backwards;
}
body .sc-hl.mn-in .mn-chip:nth-child(1) { animation-delay: 185ms; }
body .sc-hl.mn-in .mn-chip:nth-child(2) { animation-delay: 225ms; }
body .sc-hl.mn-in .mn-chip:nth-child(3) { animation-delay: 265ms; }
body .sc-hl.mn-in .mn-chip:nth-child(4) { animation-delay: 305ms; }
body .sc-hl.mn-in .mn-chip:nth-child(5) { animation-delay: 345ms; }
body .sc-hl.mn-in .mn-chip:nth-child(n+6) { animation-delay: 385ms; }

/* The board arrives last, under the block that introduces it. It is one
   element and the rows inside it do not animate — a table whose rows fade in
   individually is a table you cannot read for 400ms, and grid.js repaints
   those rows in place on every poll. */
body .sc-hl.mn-in ~ .sc-host,
body #sc-headline.mn-in + .sc-host {
  animation: mn-rise 560ms var(--ease-expressive) 330ms backwards;
}

/* Row hover, which had none. 90ms, colour and a 1px inset mark — the row does
   not move, because a screener is read by scanning down a column and a row
   that shifts under the cursor breaks the column. */
body .sc-row { transition: background-color 90ms linear; }

@media (prefers-reduced-motion: reduce) {
  body .sc-hl.mn-in .mn-hero-eyebrow,
  body .sc-hl.mn-in .mn-hero-fig,
  body .sc-hl.mn-in .mn-hero-note,
  body .sc-hl.mn-in .mn-chart,
  body .sc-hl.mn-in .mn-chips,
  body .sc-hl.mn-in .mn-chip,
  body .sc-hl.mn-in .sc-hl-strip,
  body .sc-hl.mn-in .sc-hl-cov,
  body .sc-hl.mn-in .sc-hl-bar i,
  body .sc-hl.mn-in ~ .sc-host,
  body #sc-headline.mn-in + .sc-host,
  body .mn-ch-line, body .mn-ch-fill, body .mn-ch-dot {
    animation: none !important;
  }
  body .sc-hl-bar i, body .mn-chip, body .mn-hero-v, body .sc-row,
  body .mn-ch-tf, body .mn-ch-hair {
    transition: none !important;
  }
  body .mn-chip:hover { transform: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §58 — THE OVERVIEW SITS ON THE PAGE, NOT IN A CARD (2026-08-07)

   MEASURED after §55-§57 landed, on the rendered boxes rather than from the
   source: the hero's left edge was at x=183 on a 1440px viewport. Four nested
   insets got it there —

     .app        70px   (the 1300px measure, centred)
     .app        56px   (--gutter)
     main.stage  34px   (§55's re-space)
     .panel      22px   (§33's card padding)

   — and the last one also drew a 1px border, a 12px radius and two shadows
   around the ENTIRE section. So the redesign's first screen was a display-size
   number inside a rounded rectangle inside a gutter inside a measure. §54
   already made this argument at the level of the venue panel ("a number on a
   flat ground is easier to read than the same number in a box"); the hero is
   the same argument at the size of the page.

   Two of the four go. The measure stays — a 1300px column on a 1440px screen
   is why the page reads as designed rather than as a browser window — and
   --gutter stays because it is the measure's own inset.

   SCOPED TO .hero-panel AND TO main.stage's HORIZONTAL padding ONLY. Every
   other panel in the app keeps §33's card, because those sections are lists of
   objects and a card is the right container for a list of objects. This one
   section leads with a statement, and a statement in a box is a pull quote.
   ══════════════════════════════════════════════════════════════════════════ */

body .hero-panel {
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
}
/* The gutter is .app's job and it was being paid twice. Vertical padding is
   kept — that is §55's air and it is doing real work. */
body main.stage { padding-left: 0 !important; padding-right: 0 !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §59 — THE HERO NUMBER TAKES THE SANS (2026-08-07)

   §31's rule is that mono is for figures, because character alignment is what
   makes a column of digits readable. That rule earns its place in a table. It
   does not earn its place here, and the reason is visible at display size:
   a monospace period occupies a FULL character advance, so "0.56" rendered at
   76px as "0 . 56" with a gap either side of the decimal wide enough to read
   as a space. The hero is one figure that is never in a column with another
   figure, so alignment — mono's entire justification — buys nothing here and
   costs the legibility of the most important number on the site.

   This is the second named exception to the face rule, after the 26px
   wordmark. Anything else claiming one has to state its own reason.

   tabular-nums is KEPT: it is what stops the digits reflowing when the value
   ticks from 0.56 to 0.60 between polls, which at this size is a visible jump.
   ══════════════════════════════════════════════════════════════════════════ */

body .mn-hero-n {
  font-family: var(--sans) !important;
  letter-spacing: -0.035em !important;
}
body .mn-hero-n em { font-family: var(--sans) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §60 — THE CHART OF THE RECORDING (2026-08-07)

   IA.md item 3 of the skeleton: "Timeframe toggles + a chart. We have history
   and have never drawn it." It sits inside the hero, between the honesty note
   and the identity chips, because it is what the hero's price is MADE of.

   WHAT IT PLOTS, AND WHY IT IS NOT THE HERO'S NUMBER. /api/history returns
   ts · expiry_ts · tenor_days · atm_iv · rr_25 · bf_25 and nothing else — no
   cost, no premium, no spot. Pricing a floor from atm_iv needs Black-Scholes,
   which is a model, and this product does not model. So the line is recorded
   at-the-money volatility at the hero's own tenor and the header says so in
   words. See grid.js §60 for the full reasoning and the verification.

   ON THE SCALE (§51/§55). Everything here lands on it: --t-xs for the labels
   and axis, --t-sm for the toggles, --t-md for the note, 22px for the readout
   — the same step §55 gave the supporting stats, which is the rank this number
   holds (below the 76px hero, above the body). Nothing new was introduced.

   ON THE PALETTE (§53). Nothing new either. The line is --live, the same token
   the coverage bar's "traded, measured" segment uses, and it means the same
   thing in both places: THIS IS WHAT WE MEASURED. Jade and rose appear only on
   the change readout, which is direction — §53's rule, unbroken.

   ON MOTION (§57). Compositor-only, as everywhere else: the plot rises on
   opacity + translate, and the area under the line grows on scaleY from a
   bottom origin. No stroke-dashoffset line-draw — it looks the part but it is
   a PAINT property, and §57 rule 1 is transform and opacity only.
   ══════════════════════════════════════════════════════════════════════════ */

/* The box reserves its height before the series lands, so the async fetch
   cannot push the chips, the stats and the coverage bar down the page 300ms
   after arrival. The two numbers are the drawn heights in grid.js chPlot()
   plus the header and the note. */
body .mn-chart {
  margin: 26px 0 0 !important;
  padding: 22px 0 0 !important;
  border-top: 1px solid var(--line);
  min-height: 274px;
}
@media (max-width: 559px) { body .mn-chart { min-height: 250px; } }

/* ── HEADER: what it is on the left, where it is now and the windows on the
      right. Wraps to two rows under ~760px rather than crushing the toggles. */
body .mn-ch-h {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  justify-content: space-between; gap: 12px 20px;
  margin: 0 0 14px !important;
}
body .mn-ch-id { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
body .mn-ch-t {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink) !important; font-weight: 600 !important;
}
body .mn-ch-s { font-size: var(--t-sm) !important; color: var(--ink3) !important; }

body .mn-ch-r { display: flex; align-items: baseline; gap: 10px 16px; flex-wrap: wrap; }

/* THE READOUT. It is the crosshair's target — it holds the latest value at
   rest and the hovered point while the pointer is on the plot. tabular-nums so
   scrubbing across the series does not make the label jitter horizontally. */
body .mn-ch-read { display: inline-flex; align-items: baseline; gap: 7px; }
body .mn-ch-read b {
  font-size: 22px !important; font-weight: 600 !important;
  color: var(--ink) !important; letter-spacing: -0.02em !important;
  font-variant-numeric: tabular-nums;
}
body .mn-ch-read span {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
}
/* Direction, and ONLY direction — §53. A window whose endpoints are within
   0.05 vol points reads "flat" in ink3 rather than being coloured by rounding
   noise. */
body .mn-ch-chg {
  font-size: var(--t-sm) !important; font-variant-numeric: tabular-nums;
  color: var(--ink3) !important;
}
body .mn-ch-chg[data-dir="up"]   { color: var(--pos) !important; }
body .mn-ch-chg[data-dir="down"] { color: var(--neg) !important; }

/* ── TIMEFRAME TOGGLES. §51's pill radius, one row, hairline group. A window
      the recording does not reach is DISABLED and says why on hover — it is
      never hidden, because the fact that we cannot yet show you a year is the
      product's argument rather than an embarrassment, and it is never drawn
      flat back to a start that does not exist. */
body .mn-ch-tfs {
  display: inline-flex; gap: 2px; padding: 3px !important;
  border: 1px solid var(--line) !important; border-radius: 999px !important;
}
body .mn-ch-tf {
  background: transparent !important; border: 0 !important;
  padding: 5px 12px !important; border-radius: 999px !important;
  font-size: var(--t-sm) !important; font-weight: 400 !important;
  text-transform: none !important; letter-spacing: normal !important;
  color: var(--ink3) !important; cursor: pointer;
  transition: color var(--t-state) var(--t-ease),
              background-color var(--t-state) var(--t-ease);
}
body .mn-ch-tf:hover:not([disabled]) { color: var(--ink) !important; }
body .mn-ch-tf[aria-pressed="true"] {
  background: var(--live) !important; color: var(--bg) !important;
  font-weight: 600 !important;
}
body .mn-ch-tf[disabled] { opacity: .34; cursor: not-allowed; }

/* ── THE PLOT ─────────────────────────────────────────────────────────────
   The SVG is drawn at real pixel dimensions read off this box (grid.js), not
   scaled from a viewBox — a stretched viewBox scales the stroke and the type
   with the container, which is why the same chart would be a hairline at 1440
   and heavy at 390. */
body .mn-ch-plot { position: relative; width: 100%; }
body .mn-ch-svg { display: block; width: 100%; height: auto; overflow: visible; }

body .mn-ch-line {
  fill: none; stroke: var(--live); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round;
}
body .mn-ch-fill { stroke: none; fill: url(#mn-ch-g); }
body .mn-ch-g0 { stop-color: var(--live); stop-opacity: .20; }
body .mn-ch-g1 { stop-color: var(--live); stop-opacity: 0; }
body .mn-ch-grid { stroke: var(--line); stroke-width: 1; }
body .mn-ch-dot { fill: var(--live); stroke: var(--bg); stroke-width: 2; }
body .mn-ch-hair {
  stroke: var(--line2); stroke-width: 1; stroke-dasharray: 2 3;
  pointer-events: none; transition: opacity var(--t-state) var(--t-ease);
}
/* The axis labels are the only type INSIDE the svg, and they are only legible
   because the svg is drawn at 1:1 pixels. --t-xs as a number, since SVG text
   does not take a CSS length token through font-size on every engine. */
body .mn-ch-ax {
  font-family: var(--sans); font-size: 11px; fill: var(--ink3);
  letter-spacing: .04em;
}

body .mn-ch-note {
  margin: 12px 0 0 !important; padding: 0 !important;
  font-size: var(--t-md) !important; line-height: 1.5;
  color: var(--ink3) !important; max-width: 76ch;
}
body .mn-ch-empty {
  margin: 0 !important; padding: 26px 0 !important;
  font-size: var(--t-md) !important; line-height: 1.5;
  color: var(--ink3) !important; max-width: 70ch;
}

/* ── ARRIVAL, COMPOSITOR-ONLY (§57 rule 1). The plot rises; the area under
      the line grows up from the baseline. Both are transform + opacity. This
      fires when the series lands, which is a real event and not a poll. */
@keyframes mn-ch-in   { from { opacity: 0; transform: translate3d(0, 8px, 0); } to { opacity: 1; transform: none; } }
@keyframes mn-ch-grow { from { transform: scaleY(0); } to { transform: none; } }
body .mn-ch-plot { animation: mn-ch-in 460ms var(--ease-expressive) backwards; }
body .mn-ch-fill {
  transform-origin: center bottom;
  animation: mn-ch-grow 620ms var(--ease-expressive) 60ms backwards;
}

@media (max-width: 559px) {
  body .mn-ch-h { align-items: flex-start; }
  body .mn-ch-r { width: 100%; justify-content: space-between; }
  body .mn-ch-tf { padding: 5px 9px !important; }
}

@media (prefers-reduced-motion: reduce) {
  body .mn-ch-plot, body .mn-ch-fill { animation: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §61 — THE ACCENT GOES WARM (2026-08-07, owner's call)

   "Make it pink orange and a bit of glow orange, something original where
   there is excitement to go watch the charts." Reference: swarmnetwork.ai.

   §53's single accent was cyan #7bf2ff meaning "where you are". Every use of
   it moves to ORANGE #ff8a3d — active rail item, sorted column, section rule,
   active chips and toggles, CTAs, and the coverage bar's "traded, measured"
   segment. The values were swapped in place in §53 rather than overridden from
   here on purpose: an override layer would have had to restate 25 selectors,
   and §53's own note warns that two !important rules resolve by SPECIFICITY
   and not by order. One value, one place, nothing to get out of sync.

   ── THE COLOUR, AND A CONSTRAINT THAT COULD NOT BE MET AS WRITTEN ─────────

   The brief set three numeric gates: WCAG contrast >= 1.5 against our "sold"
   rose #e06e76, >= 1.3 against Binance gold #f0b90b, and >= 4.5:1 legibility.
   Measured before choosing anything, and the first two cannot both hold:

     cr(gold, rose) = 1.749

   For ANY colour C whose luminance sits between them, cr(C,rose) x cr(C,gold)
   equals cr(gold,rose) exactly — it is a ratio of the same two luminances. So
   the gates demand a product of 1.5 x 1.3 = 1.95 from a band that contains
   1.749. Nothing in it passes. Escaping downward (darker than rose) breaks
   legibility: the best deep orange, #d9480f, measures 4.05:1 on our ground.
   Escaping upward is the only region that satisfies all three, and a search
   over it returns exactly one maximum-chroma point:

     #ffd67d — hue 41 deg, saturation 51%

   which is a pale cream at gold's own hue. It passes the gold gate on the
   number (1.30) and has the SMALLEST perceptual distance from gold of any
   candidate measured (dE00 10.1). The test selects the colour the test exists
   to prevent.

   THE REASON IS THAT WCAG CONTRAST IS A LUMINANCE RATIO AND IS BLIND TO HUE.
   Two colours of equal luminance and opposite hue score 1.00. It was the right
   instrument for the coral case only by coincidence — coral #FF5C7A collides
   with rose in luminance AND in hue, so either metric catches it. Measured
   with CIEDE2000, which is the perceptual question actually being asked
   ("are these the same colour to a reader"):

     coral #FF5C7A vs rose    dE00  5.9   <- the rejected collision
     #ffd67d       vs gold    dE00 10.1   <- what the WCAG gates select
     #ff8a3d       vs rose    dE00 24.0   <- shipped: 4x the collision
     #ff8a3d       vs gold    dE00 23.2
     #ff8a3d       vs jade    dE00 48.8

   SHIPPED: #ff8a3d. It clears the gold gate as written (1.30) and the
   legibility gates by a wide margin; it misses the rose gate on WCAG (1.34
   against 1.5) and clears it perceptually by four times the margin of the
   failure case. This is flagged rather than reconciled — if the owner wants
   the WCAG number honoured literally, the only colour that does it is the
   pale gold above, and that is a worse outcome for the reason the gold rule
   was written.

   MEASURED, on rendered pixels, not computed from these declarations. NOTE
   THE GROUND: these three ratios were measured against the NAVY #0d1b2a this
   section shipped on, and §63 later replaced it. They are kept at their real
   historical values rather than rewritten, because a recorded measurement
   that silently follows a later change is not a measurement. §63 restates
   them against the ground now in force.

     accent on ground   #ff8a3d / #0d1b2a    7.42:1   (navy, superseded)
     accent on panel    #ff8a3d / #182430    6.71:1   (navy, superseded)
     ground on accent   #0d1b2a / #ff8a3d    7.42:1   (navy, superseded)

   --live2 / --mint2 move with it to #e07a35 (5.80:1 on ground): those are
   focus rings and hover borders across detail.css, tools.css and style.css,
   and a focus ring that no longer contrasts is an accessibility regression
   rather than a palette one.

   THE GLOW. "Excitement" is the brief, so the accent carries a warm bloom —
   but a STATIC one. §57's compositor rule is about animated properties; a
   box-shadow that never changes costs one paint and nothing per frame. It is
   applied only to the few surfaces that ARE the accent, never to rows or
   cells.

   Ground stays dark. Light-vs-dark is an open owner decision and is not made
   here.
   ══════════════════════════════════════════════════════════════════════════ */

/* The filled accent states get a warm halo — the light source the reference
   leads with, at an alpha that reads as glow rather than as a second border. */
body .rail .rl-item.on,
body .rail [aria-current="page"],
body .sh-badge,
body .sh-cta, body .sh-form .sh-cta,
body .mn-ch-tf[aria-pressed="true"] {
  box-shadow: 0 0 0 1px rgba(255, 122, 26, .30),
              0 2px 18px -4px rgba(255, 122, 26, .55) !important;
}

/* The chart's line is the one thing on the page a reader is meant to WATCH,
   so it gets the glow as a filter rather than a shadow — an SVG stroke takes
   no box-shadow. drop-shadow on a single path, drawn once per redraw. */
body .mn-ch-line { filter: drop-shadow(0 0 6px rgba(255, 122, 26, .45)); }
body .mn-ch-dot  { filter: drop-shadow(0 0 5px rgba(255, 122, 26, .70)); }

/* The coverage bar's measured segment is the same claim as the chart line and
   takes the same treatment, at half strength: it is 10px tall and a bloom the
   size of the bar would swallow the hatched segment beside it. */
body .sc-hl-bar .f-tr { box-shadow: 0 0 10px -1px rgba(255, 122, 26, .50); }

/* The hero's venue link is the accent as TEXT, where a halo would smear the
   glyph edges. It gets the warmth in the underline instead. */
body .mn-hero-v { border-bottom-color: rgba(255, 122, 26, .45) !important; }
body .mn-hero-v:hover {
  border-bottom-color: #ff7a1a !important;
  text-shadow: 0 0 12px rgba(255, 122, 26, .45);
}

/* THE LAST OF THE GOLD, and it took a screenshot to find. §53 said the gold
   was gone; grep agreed, because it only removed the gold that was written as
   a LITERAL. `--accent` was still #f0b90b — Binance's exact value — three
   token definitions up in the dark block, and it was rendering the command
   bar's example commands ("eth derive", "/floor btc", "/trades") in Binance
   yellow on a page whose stylesheet claims not to use it any more. This is the
   §53b lesson repeating: querying rendered nodes finds what grepping for a
   name does not.

   It joins the one accent. --accent meant "attention" and the orange means
   "where you are"; on a page with a single accent those are the same job, and
   two accents is how the gold survived a pass that was meant to remove it. */
:root[data-theme="dark"] {
  --accent: #ff7a1a;
  --accent-ink: #ff7a1a;
}

/* ══════════════════════════════════════════════════════════════════════════
   §62 — LIT GLASS: PINK AS A LIGHT SOURCE, PANELS AS PLANES (2026-08-07)

   Owner: "some pink but only on sections gluing into the screen, and with
   glass effect, very modern and sci-fi style."

   THE DIVISION OF LABOUR, AND IT IS THE WHOLE SAFETY ARGUMENT.

     ORANGE #ff8a3d is FUNCTIONAL. It is "where you are" — §61. Every control,
     every active state, every accent glyph.

     PINK #ff4fa3 is AMBIENT AND NOTHING ELSE. It is a light source behind the
     page and a highlight on the top edge of a plane. It never fills a control,
     never colours a cell, never marks a state. That is not taste: our "sold"
     direction is rose #e06e76, and pink used as a FILL is how a reader ends up
     reading a button as a sell signal — the coral finding, measured at dE00
     5.9 from rose. As a bloom at 0.06-0.13 alpha behind a blurred surface it
     is never adjacent to a data glyph and cannot be mistaken for one.

   THE BLOOM CANNOT CAUSE A SCROLLBAR. It is position:fixed with inset:0, so
   it is clipped to the viewport by construction rather than by a width
   calculation that a future padding change could break. z-index:-1 puts it
   above the canvas background and below every in-flow element. It is on a
   pseudo-element with pointer-events:none, so it cannot take a click.

   IT DOES NOT MOVE. Nothing here animates or pulses — measured on mpp.dev,
   the reference for this direction: 0 CSS keyframe animations, 0 canvas, 0
   running Web Animations, and ~55 elements carrying transitions only. Ambient
   motion is the thing that makes a page read as generated. So there is
   nothing for prefers-reduced-motion to switch off, which is the correct
   outcome rather than a missing one.

   BACKDROP-FILTER IS ON SIX SURFACES, ALL LARGE, NONE REPEATING. The masthead,
   the section rail, the command band, .panel, the venue panel and the stats
   strip. Never a row, a cell or a chip: this page repaints a 2,000-row tape
   and blurring per row would cost a composite of the backdrop for every one.

   AND THE FALLBACK IS NOT OPTIONAL. Without it, a reader whose engine has
   backdrop-filter off gets a 55%-transparent panel with body text on it — the
   page would not be "less pretty", it would be unreadable. @supports gives
   them the solid surface.

   CONTRAST WAS MEASURED THROUGH THE GLASS, ON RENDERED PIXELS, WITH THE BLOOM
   BEHIND IT — see the commit. Declared colour tells you nothing here: a
   translucent surface composites over whatever it is above, and computing from
   declarations has been wrong by ~4x in this file before.
   ══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="dark"] {
  --bloom-warm: 255, 122, 26;   /* the functional accent, as a light   */
  --bloom-pink: 255, 79, 163;   /* AMBIENT ONLY — never a fill         */
  --glass:      rgba(28, 22, 17, 0.55);
  --glass-solid:#181410;        /* the @supports fallback              */
  --glass-edge: rgba(255, 255, 255, 0.16);
  --glass-line: rgba(255, 255, 255, 0.065);
}

/* THE LIGHT SOURCE. Three lobes: warm high-left where the hero is, pink
   mid-right, pink low-centre under the board — so the page is lit from behind
   and the panels have something to float over. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(1000px 560px at 10% -8%,  rgba(var(--bloom-warm), .17), transparent 68%),
    radial-gradient(820px 640px  at 94% 18%,  rgba(var(--bloom-pink), .13), transparent 66%),
    radial-gradient(1200px 760px at 46% 112%, rgba(var(--bloom-pink), .10), transparent 70%);
}

/* ── THE PLANES ───────────────────────────────────────────────────────────
   A translucent surface, a blur, and ONE lit edge along the top — that edge
   is what makes a rectangle read as glass rather than as a tinted box, and it
   is where the pink is allowed to touch a section directly. */
body .panel:not(.hero-panel),
body #detail-root > *,
body .sc-hl-strip,
body > header.top,
body > nav.rail,
body footer {
  background: var(--glass) !important;
  -webkit-backdrop-filter: blur(20px) saturate(1.35);
  backdrop-filter: blur(20px) saturate(1.35);
  border-color: var(--glass-line) !important;
}
body .panel:not(.hero-panel),
body #detail-root > *,
body .sc-hl-strip {
  border-top: 1px solid var(--glass-edge) !important;
  box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .16),
              0 18px 44px -28px rgba(0, 0, 0, .75) !important;
}
/* The three bands of chrome are lit along their SEAM with the stage rather
   than boxed: the masthead from below, the rail and the command band from
   above, so the page reads as planes stacked in depth. */
body > header.top   { border-bottom: 1px solid var(--glass-line) !important;
                      box-shadow: 0 1px 0 rgba(var(--bloom-pink), .12) !important; }
body > nav.rail     { box-shadow: inset 0 1px 0 rgba(var(--bloom-warm), .10) !important; }
body footer         { border-top: 1px solid var(--glass-edge) !important;
                      box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .18) !important; }

/* THE FALLBACK. Not cosmetic — without it these surfaces are 58% transparent
   with body text on them. Both prefixes are tested, because an engine can
   support one and not the other. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body .panel:not(.hero-panel),
  body #detail-root > *,
  body .sc-hl-strip,
  body > header.top,
  body > nav.rail,
  body footer {
    background: var(--glass-solid) !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §63 — THE GROUND GOES WARM (2026-08-07, owner's call)

   §61 moved the accent to orange and deliberately left the ground alone,
   because light-vs-dark was an open decision. The owner's reaction to the
   result: "why is the background still blue."

   He is right, and it is a measurable thing rather than a taste one. The
   ground was #0d1b2a at hue 211 deg; the accent is #ff8a3d at hue 26 deg.
   Those are within a few degrees of complementary, so every warm surface on
   the page was sitting on its opposite: the orange read as colour STUCK ON a
   blue card rather than as light falling on a dark room, and the pink bloom —
   which §62 added as a light source — was fighting the same battle.

   THIS IS NOT THE LIGHT-VS-DARK DECISION. The ground stays dark. What changed
   is its hue family, from blue to warm near-black.

   THE FAMILY. mpp.dev, the reference the owner sent and which was measured
   rather than described, grounds on rgb(6,6,6) — a true neutral. Ours takes a
   hair of warmth off that so the bloom has something to sit in, and the whole
   ramp is built on ONE hue so the surfaces step in value and nothing else.
   The navy set was disciplined in exactly this way (211 / 210 deg) and that
   discipline is what is being kept:

     token          hex        hue    sat    light
     --bg           #0c0a08    30     20%     3.9%
     --s1           #17130f    30     21%     7.5%
     --s2           #201b16    30     19%    10.6%
     --line         #302a23    32     16%    16.3%
     --line2        #423a31    32     15%    22.5%
     --glass-solid  #181410    30     20%     7.8%

   Hue holds at 30 +/- 2 across the family; the 2 deg of drift on the two line
   tokens is 8-bit quantisation, not design — at these lightnesses the sRGB
   grid is about three levels wide and hue cannot be held tighter than that.

   THE INK RAMP WAS RE-DERIVED, NOT CARRIED OVER. The old inks were tuned
   against a blue ground and were themselves blue-cast (#f6f7ff, #aab6c6,
   #8593a3) — leaving them would have kept the page cold no matter what the
   ground did. They move to the same warm family: #f8f4f0 / #c6bcb2 / #9b8e82.

   VERIFIED ON THE LIGHTEST SURFACE, WHICH IS THE ONE THAT CAN FAIL. Every ink
   against every surface, computed first and then confirmed on rendered pixels
   through the glass with the bloom behind it:

                       bg      s1      s2   glass
       ink          18.06   16.89   15.60   16.74
       ink2         10.58    9.89    9.14    9.80
       ink3          6.20    5.79    5.35    5.74
       accent        8.43    7.88    7.28    7.81
       accent2       6.59    6.16    5.70    6.11
       jade          7.38    6.90    6.37    6.84
       rose          6.27    5.86    5.42    5.81

     minimum anywhere      5.35:1   (ink3 on --s2, the lightest surface)
     dark text on accent   8.43:1   (filled controls)

   Every pair improved against the navy set, because the ground is darker.

   UNCHANGED BY THIS: orange stays the single functional accent, pink stays
   ambient only, jade and rose stay reserved for direction. The accent-vs-rose
   separation is a property of that colour pair alone and is untouched — WCAG
   1.34, dE00 24.0, exactly as §61 recorded it.

   THE GLASS TINT MOVED WITH THE GROUND. --glass was rgba(20,32,45,.58), a
   blue film; over a warm ground that would have put the blue back on top of
   every panel. It is rgba(28,22,17,.55) now, and --glass-solid — the
   @supports fallback — moved with it.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   §64 — CHROMA, AND THE PINK ACTUALLY ARRIVES (2026-08-07, owner's call)

   Owner on §61-§63 as shipped: "this seems more brown than orange / pink."
   Both halves were right, and both were measurable.

   ── 1. THE ACCENT WAS UNDER-SATURATED ────────────────────────────────────

   #ff8a3d measures hue 24, SATURATION 76, value 100. Value was already pinned
   at the ceiling, so the only way it had left to be "bright" was to add white
   — and a warm hue diluted with white, on a dark ground, reads as peach or
   brown rather than as emitted light. Brightness is not chroma, and the brief
   ("excitement") asked for chroma.

     #ff8a3d   hue 24  sat  76  <- was: reads brown on near-black
     #ff7a1a   hue 25  sat  90  <- now: the reference's own "true orange"

   AND IT MADE THE ROSE SEPARATION BETTER, NOT WORSE. The worry was that more
   chroma pushes orange toward red and closes the gap on our "sold" rose. It
   does the opposite, because the gap is a CHROMA distance as much as a hue
   one — a washed-out orange is closer to a washed-out pink-red than a vivid
   one is:

     #ff8a3d vs rose   dE00 24.0        #ff7a1a vs rose   dE00 24.8
     #ff8a3d vs gold   dE00 23.2        #ff7a1a vs gold   dE00 25.2

   So no hue move toward 20-22 was needed; desaturation was the whole problem,
   exactly as diagnosed. (WCAG against rose goes 1.34 -> 1.21, still under the
   1.5 gate, for the reason §61 sets out at length: that gate is a luminance
   ratio and is blind to the hue difference doing the actual work here.)

   Re-measured on the near-black ground, rendered pixels:
     accent on ground  7.58:1 · on --s1 7.08:1 · on --s2 6.55:1
     dark ink on accent 7.58:1 (the filled pills and the active rail item)
   --live2/--mint2 follow to #f07510 (5.90:1 on --s2), keeping the focus rings
   in the same family rather than leaving a peach ring on a vivid control.

   ── 2. THE PINK WAS NOT ON THE PAGE ──────────────────────────────────────

   §62 declared it and nothing pink rendered. Measured why rather than
   guessed: rgba(255,79,163, .13) composited over #0c0a08 is #2c131c, which is
   1.15 against the ground — below the threshold at which a large soft
   gradient is distinguishable from the ground at all. It was not subtle, it
   was absent. "Ambient" is a role, not an opacity.

     alpha .13 -> #2c131c  (1.15 vs ground)   invisible
     alpha .28 -> #501d33  (1.47)             reads as a second light
     alpha .38 -> #672340  (1.78)             clearly pink
     alpha .46 -> #7c2a4f  (2.17)             too far — see the ceiling below

   THE CEILING IS SET BY TEXT, AND IT IS MEASURED THROUGH THE GLASS. A panel
   is a 55% tint over whatever the bloom put behind it, so the bloom raises
   the backdrop luminance under every word on that panel:

     bloom .28 -> backdrop #501d33 -> through glass #331920 -> ink3 5.06:1
     bloom .40 -> backdrop #6d2646 -> through glass #401d29 -> ink3 4.62:1
     bloom .46 -> backdrop #7c2a4f -> through glass #471f2d -> ink3 4.38:1  FAIL

   So .38 is the working ceiling anywhere a glass panel can sit, and the
   brightest lobes are placed in the OUTER gutters — the page is a 1300px
   measure on a 1440px viewport and the light is strongest where there is no
   text to wash out. Dim the glow, not the text.

   ── 3. WHERE THE PINK TOUCHES ────────────────────────────────────────────

   "Only on sections gluing into the screen": the horizontal seams between
   blocks stop being a flat 1px --line and become a lit edge — a pink hairline
   with a soft bleed above it, so a section reads as joined to the ground by
   light rather than ruled off from it. Still never a fill, never a control,
   never a cell. Rose is our "sold" direction and pink-as-fill is how a button
   starts reading as a sell.
   ══════════════════════════════════════════════════════════════════════════ */

/* THE BLOOM, at strength. Warm lobe high-left behind the hero; the two pink
   lobes pushed into the left and right gutters and below the fold, where the
   1300px measure leaves ground with no text on it. */
body::before {
  background:
    radial-gradient(1000px 580px at  8% -10%, rgba(var(--bloom-warm), .20), transparent 66%),
    radial-gradient(900px  760px at 102% 12%, rgba(var(--bloom-pink), .38), transparent 64%),
    radial-gradient(820px  700px at  -6% 62%, rgba(var(--bloom-pink), .30), transparent 62%),
    radial-gradient(1300px 820px at  50% 116%, rgba(var(--bloom-pink), .26), transparent 68%) !important;
}

/* THE SEAMS. Every horizontal rule inside the hero block is a place two
   sections meet; each becomes a lit edge instead of a hairline. The bleed is
   drawn UPWARD (negative y) so it falls on the ground above the rule rather
   than behind the text below it. */
body .mn-chips,
body .mn-chart,
body .mn-board-h,
body .sc-hl-cov {
  border-top-color: rgba(var(--bloom-pink), .34) !important;
  box-shadow: 0 -14px 26px -22px rgba(var(--bloom-pink), .95) !important;
}

/* The glass planes take a brighter pink along their top edge — the same
   "lit from the seam" idea one object smaller. */
body .panel:not(.hero-panel),
body #detail-root > *,
body .sc-hl-strip {
  box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .38),
              0 18px 44px -28px rgba(0, 0, 0, .8) !important;
}
body > header.top { box-shadow: 0 1px 0 rgba(var(--bloom-pink), .28) !important; }
body footer       { box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .40) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §65 — TWO CURVES, AND FAR FEWER TRANSITIONS (2026-08-07)

   The finding from mpp.dev is RESTRAINT, not elaboration. Measured on it
   rather than described:

     CSS keyframe animations   0
     canvas                    0
     running Web Animations    0
     transitions               ~55 elements, colour + transform + clip-path
     easing                    cubic-bezier(.4, 0, .2, 1)  on 51 of 55
                               cubic-bezier(.16, 1, .3, 1) on 3 (expressive)

   So: ONE curve on almost everything, a second reserved for a few moments,
   and no ambient animation at all.

   ── WHAT WE MEASURED ON OURSELVES ────────────────────────────────────────

   Both of those curves were ALREADY in this file — as --t-mag-ease and
   --t-ease — and the distribution was exactly inverted: 100% of transitions
   ran on the expressive curve and the standard one was used three times. That
   is why ordinary state changes read as slightly theatrical.

   The bigger number is the one nobody had looked at:

     elements with a live transition   52,194   (mpp.dev: ~55)
     of those, transitioning `all`     36,326

   ── THE CAUSE WAS ONE DECLARATION, AND IT WAS NOT A TRANSITION RULE ──────

   §2's blunt normalisation layer set `transition-duration: var(--t-dur)
   !important` on `body *:not(svg):not(svg *)`. It never set
   transition-property — and the INITIAL VALUE of transition-property is
   `all`. So supplying a duration to every element in the app granted every
   element a live transition on every animatable property it has, layout
   properties included, without a single component asking for one. The tape
   alone contributed ~31,000 of them (7,806 SPAN.p, 7,806 SPAN.s, 4,000 I.sep,
   4,000 SPAN.stk, 3,612 x3 tw-* nodes) on a surface that repaints on a poll.

   It also had a known symptom already written down in this file: the command
   popover carries an !important on its own transition with a comment saying
   §2 "silently rewrites the 0s below into 160ms", which left the closed list
   in the tab order for a quarter of a second. That workaround was treating
   the symptom.

   THE FIX IS A DELETION. Removing the duration line returns every element to
   the initial `transition-duration: 0s`, so an element with `all` still has
   `all` and simply does not animate. Components that ASKED for motion set
   their own duration in their own shorthand and are untouched — nothing that
   used to glide now snaps. Verified by re-measuring, not by reasoning.

   ── THE CURVES, NAMED ────────────────────────────────────────────────────

   §2 keeps its timing-function line, now pointed at the standard curve with
   !important — which is what routes EVERY transition in the app through one
   easing, including transitions in stylesheets this file does not own and in
   markup drawn by JavaScript.

   Arrival is unaffected on purpose: §57 and §60 do arrival with ANIMATIONS,
   and transition-timing-function does not apply to an animation. So the
   expressive curve stays exactly where it belongs — the hero landing, the
   chart drawing itself — and nowhere else.

   NOTHING AMBIENT WAS ADDED, and that is the point of the reference. The one
   looping animation on the page is the logo mark's spot walking the payoff
   (index.html, animateMotion, repeatCount indefinite). It predates this pass
   and it is the brand mark rather than interface motion, so it is left alone
   and flagged here rather than removed quietly — it is the one thing on the
   page that contradicts the "0 running animations" reading of the reference,
   and that is the owner's call, not this file's.
   ══════════════════════════════════════════════════════════════════════════ */

:root,
:root[data-theme="dark"] {
  /* ORDINARY STATE CHANGE. Hover, focus, press, open, active — 51 of 55 on
     the reference, and now everything here. */
  --ease-standard:   cubic-bezier(.4, 0, .2, 1);
  /* ARRIVAL AND EXPRESSIVE MOMENTS. Overshoot-free decelerate; used by the
     hero's arrival stagger (§57) and the chart drawing in (§60). */
  --ease-expressive: cubic-bezier(.16, 1, .3, 1);

  /* --t-ease NOW MEANS "STANDARD", AND THAT IS WHY EVERY TRANSITION MOVED.
     §2's blanket `transition-timing-function !important` did NOT reach
     everything, and the reason is the trap this file warns about elsewhere:
     two !important declarations resolve by SPECIFICITY, not source order. The
     blanket selector is `body :not(svg):not(svg *)` — three type selectors,
     (0,0,3). Six rules in this file set a full `transition:` shorthand with
     !important on selectors like `body .tw-b` — (0,1,1) — and one class beats
     any number of type selectors, so 11,418 tape buttons kept the expressive
     curve while the computed style on the blanket rule said otherwise. Found
     by enumerating the matched rules on a real node over CDP, after a grep for
     `transition:.*!important` missed all six for being written across several
     lines.

     Re-pointing the token fixes all six at once, and every other consumer with
     them — including ui.css's `--t` shorthand, which this file does not own.
     The arrival KEYFRAMES were switched to name --ease-expressive directly, so
     they are unaffected by this and stay expressive. */
  --t-ease:     var(--ease-standard);
  --t-mag-ease: var(--ease-standard);
}

/* ══════════════════════════════════════════════════════════════════════════
   §66 — THE COMMAND BAR BECOMES A TERMINAL (2026-08-07, owner's call)

   mpp.dev's shape, our nouns:

     MPP Terminal                        ->  Moneyness Terminal
     ✔︎ ▸ ↑ ↓ →                          ->  the key hints, always visible
     mpp.dev@2f5bafd (released 1d ago)   ->  live contract count + poll age
     $ ./mpp.sh / What would you like…   ->  the same question, our options
     › Chat with OpenAI      (Tempo)     ->  › eth derive  that pair, that venue

   THE HINTS NAME A CAPABILITY THAT ALREADY EXISTED. command.js has handled
   ArrowUp/ArrowDown, Enter, Escape and `/`-to-focus since it shipped and none
   of it was written on the page, so the bar read as a text field. Nothing in
   this pass adds behaviour. That is the cheapest kind of feature there is.

   THE PROVENANCE LINE IS REAL OR IT IS ABSENT. Theirs is a commit hash; we
   have no build id and printing a fake one on this page would be the exact
   fabrication the product refuses. It mirrors the masthead's live status node
   instead (grid.js §66) — one source, two places, cannot disagree — and it
   renders EMPTY until the first poll rather than showing a placeholder,
   because a dash in a provenance line reads as a value.

   THE `›` MARKERS ARE DRAWN, NOT INSERTED. Both the option row and the
   selected result get theirs from ::before, so the DOM command.js builds is
   unchanged and the marker cannot end up in a copied selection or in the
   accessibility tree as content.

   ON THE SCALE: --t-xs for the title, hints and provenance, --t-sm for the
   rows. Nothing new. On the palette: the accent marks the selected row and
   the matched substring — "where you are", which is §53's rule exactly.
   ══════════════════════════════════════════════════════════════════════════ */

body .cmd-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 16px;
  margin: 0 0 4px !important; padding: 0 !important;
}
body .cmd-title {
  font-size: var(--t-xs) !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink) !important; font-weight: 600 !important;
}

/* THE KEY HINTS. Real <kbd>, so a screen reader and a copy-paste both get
   something sensible, and the caps are drawn rather than typed. */
body .cmd-hints { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; }
body .cmd-hints kbd {
  font-family: var(--mono) !important; font-size: 10px !important;
  line-height: 1; padding: 3px 5px !important;
  border: 1px solid var(--line) !important; border-radius: 4px !important;
  color: var(--ink2) !important; background: rgba(255, 255, 255, .03) !important;
}
body .cmd-hints i {
  font-style: normal; font-size: var(--t-xs) !important;
  color: var(--ink3) !important; margin-right: 8px;
}

body .cmd-prov {
  margin: 0 0 6px !important; padding: 0 !important;
  font-family: var(--mono) !important; font-size: var(--t-xs) !important;
  color: var(--ink3) !important; letter-spacing: .02em;
}
/* Empty until the first poll — and an empty node must not reserve a line, or
   the band jumps when the poll lands. */
body .cmd-prov:empty { display: none; }

/* ── THE OPTION ROW. The reference's question, and its `›` markers. ──────── */
body .cmd-eg-h {
  font-size: var(--t-xs) !important; color: var(--ink3) !important;
  text-transform: none !important; letter-spacing: normal !important;
}
body .cmd-eg-b::before {
  content: "\203a"; margin-right: 6px;
  color: var(--ink3); font-family: var(--mono);
}
body .cmd-eg-b:hover::before { color: var(--live); }

/* ── THE RESULTS LIST, AS A TERMINAL LIST ────────────────────────────────
   Monospace throughout, a leading marker on the selected row only, and the
   row itself marked by a left rule rather than a filled block — a solid
   accent bar under nine rows of live data is a lot of light for a hover
   state, and the marker already says which row is armed. */
body #cmd-pop .cmd-r {
  position: relative;
  font-family: var(--mono) !important;
  padding-left: 22px !important;
  border-left: 2px solid transparent !important;
  border-radius: 0 !important;
}
body #cmd-pop .cmd-r::before {
  content: "\203a";
  position: absolute; left: 8px; top: 50%;
  transform: translateY(-50%);
  color: var(--live); opacity: 0;
  transition: opacity var(--t-state) var(--ease-standard);
}
body #cmd-pop .cmd-r.on {
  border-left-color: var(--live) !important;
  background: rgba(255, 255, 255, .035) !important;
}
body #cmd-pop .cmd-r.on::before { opacity: 1; }
body #cmd-pop .cmd-r.on .cmd-lb { color: var(--ink) !important; }

/* The substring the reader typed, inside the row it produced. */
body #cmd-pop .cmd-hit {
  font-style: normal;
  color: var(--live) !important;
  font-weight: 600 !important;
}

body #cmd-pop .cmd-grp {
  font-size: 10px !important; letter-spacing: var(--tr-label) !important;
  text-transform: uppercase; color: var(--ink3) !important;
  padding: 8px 10px 4px !important;
}

@media (max-width: 700px) {
  /* The hints are the first thing to go: on a phone there is no keyboard to
     hint at, and the row would wrap to three lines above a 44px input. */
  body .cmd-hints { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §BLOOM CORRECTION (2026-08-05)

   The pink bloom landed at .38/.30/.26 across three 800-1300px radial
   gradients, which is not ambient — it washes the entire ground and turns a
   warm near-black into a purple haze. The brief was a second LIGHT SOURCE
   bleeding off edges, not a wash. Ambient means you notice it when you look
   for it, not before you have read the number.

   SECOND PASS (2026-08-07), AND THE REASON THE FIRST ONE DID NOTHING.

   The first correction rewrote `body { background-image }` and verified it by
   reading back the computed value, which duly reported the new gradients. The
   check was true and the conclusion was wrong: THE BLOOM IS NOT ON `body`.
   It is on `body::before` (§62) — `position: fixed; inset: 0; z-index: -1` —
   a full-viewport light layer that was still painting the original
   .38/.30/.26 the whole time. Reading `getComputedStyle(document.body)` never
   touches a pseudo-element, so the measurement confirmed a rule that was not
   the one on screen. Anything checking this again must pass the pseudo:
   `getComputedStyle(document.body, '::before')`.

   With that layer actually in hand, the substance of the note still holds:
   three overlapping pink lobes over a near-black ground compound, and where
   two overlapped the effective alpha was past .5. Alpha was never the only
   dial — the number of light sources was.

   So: ONE pink lobe, off the top-right corner, which is what the brief said —
   a second light bleeding off an edge. It has a direction you can point at,
   falls off before it reaches the board, and cannot compound with itself. The
   warm lobe stays (it is --bloom-warm, the accent as a light, and it is what
   keeps the ground warm rather than grey) but comes down too, because at .20
   it was the other half of the haze.

   `body` itself carries no bloom: two stacked light layers is the mistake
   this section is fixing, not a thing to keep a copy of. */
body { background-image: none !important; }

body::before {
  background:
    radial-gradient(900px 520px at   6% -12%, rgba(var(--bloom-warm), .13), transparent 64%),
    radial-gradient(560px 400px at 103%   1%, rgba(var(--bloom-pink), .10), transparent 56%) !important;
}

/* THE SEAMS COME DOWN WITH IT. These are the other half of "purple haze": the
   hero's horizontal rules were drawing a .34 pink border with a .95 pink bleed
   above each one, which at four rules down a single screen is not a lit edge,
   it is a set of pink lines. The device is kept — a seam lit from above still
   joins a section to the ground — at roughly a third of the strength, where
   it reads as light on a hairline rather than as a coloured rule. */
body .mn-chips,
body .mn-chart,
body .mn-board-h,
body .sc-hl-cov {
  border-top-color: rgba(var(--bloom-pink), .12) !important;
  box-shadow: 0 -12px 22px -20px rgba(var(--bloom-pink), .34) !important;
}
body .panel:not(.hero-panel),
body #detail-root > *,
body .sc-hl-strip {
  box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .14),
              0 18px 44px -28px rgba(0, 0, 0, .8) !important;
}
/* Edge treatments come down with it — these were reading as pink rules. */
body > header.top { box-shadow: 0 1px 0 rgba(var(--bloom-pink), .12) !important; }
body footer       { box-shadow: inset 0 1px 0 rgba(var(--bloom-pink), .14) !important; }

/* ── THE CHART IS DATA, NOT CHROME ──────────────────────────────────────────
   The volatility line was drawn in the same orange as the active nav item and
   the CTA. When chrome and data share a colour the line reads as decoration,
   and on this product the recorded line IS the evidence. It gets the ink, and
   the accent stays reserved for "where you are".

   THE SELECTOR, because the first attempt at this fix matched nothing and
   reported success. The chart is NOT ivchart.js — that module's `.ivc-*`
   markup is not on #trade at all, so `.ivc-svg path[stroke]` was a selector
   against an element that does not exist. The hero chart is drawn by grid.js
   (§ around line 1607) as `svg.mn-ch-svg` containing `path.mn-ch-line`, and
   it carries NO stroke attribute — the colour comes from CSS at §57
   (`body .mn-ch-line { stroke: var(--live) }`). An attribute selector could
   never have matched it.

   And the line was never "hardcoded orange": §61 remapped the TOKEN, at
   `--live: #ff7a1a` alongside `--mint: #ff7a1a`, so every liveness-coloured
   mark on the page silently became the accent. That is the actual defect —
   two roles collapsed onto one token — so the fix re-separates them HERE at
   the point of use rather than editing the palette, which the brief reserves.

   --ink is the data colour: near-white #f8f4f0, maximum contrast on the
   ground, and unmistakably not the accent. The dot, the area-fill gradient
   stops and the warm drop-shadow glow all move with it — leaving any one of
   them orange would keep the chart reading as chrome. */
body .mn-ch-line { stroke: var(--ink) !important; }
body .mn-ch-dot  { fill:   var(--ink) !important; }
body .mn-ch-g0   { stop-color: var(--ink) !important; stop-opacity: .16 !important; }
body .mn-ch-g1   { stop-color: var(--ink) !important; stop-opacity: 0 !important; }
/* The glow was the accent's warm halo bleeding onto the data. A line that is
   already the brightest thing on the page does not need one; at most it gets
   a neutral lift so it still separates from the grid. */
body .mn-ch-line { filter: drop-shadow(0 0 5px rgba(248, 244, 240, .22)) !important; }
body .mn-ch-dot  { filter: drop-shadow(0 0 4px rgba(248, 244, 240, .30)) !important; }

/* ── THE SIDEBAR PILL WAS 68px WIDE IN A 208px COLUMN ──────────────────────
   "Compare" ran out past its orange pill. The previous two attempts here
   treated it as a clipping problem — `overflow: visible`, `text-overflow:
   clip` — which is why the text was never the thing clipped and the DOM check
   (`scrollWidth == clientWidth`) passed while the screen still looked wrong.
   Nothing was overflowing a text box. The PILL was too small, and it was too
   small because the column it sits in has almost no content box.

   THE CAUSE, measured: nav.rail computes to `padding: 18px 70px`. It is 208px
   wide, so 140px of that is padding and the content box is 68px — which is
   exactly the width every one of the six items measured, active or not. The
   `width: 100%` in nav.css was never losing the cascade; it was resolving
   correctly against a 68px box.

   Where the 70px comes from is §41, the rule that insets the full-width chrome
   so its CONTENTS line up with the board's measure:

     body > header.top, body > nav.rail, body > footer, body > .cmd {
       padding-inline: max(var(--gutter), calc((100% - var(--measure)) / 2));
     }

   That is correct for a header spanning the viewport. The rail is not that any
   more — nav.css made it `position: fixed; width: 208px`. A percentage in a
   fixed element's padding resolves against its CONTAINING BLOCK, which for
   `position: fixed` is the viewport, not the element. So `100%` is 1440px, not
   208px, and the rule computes max(56px, (1440-1300)/2) = 70px per side. The
   sidebar was being centred to a 1300px measure it is not 1300px wide.

   nav.css already sets `padding: 18px 14px !important` and still lost: its
   selector `body nav.rail` and §41's `body > nav.rail` are BOTH (0,1,2), and
   a specificity tie is broken by source order — instrument.css loads last.
   Raising specificity is what settles it, so this uses the id-free but
   two-class `body > nav.rail.rail`. Reverting §41 is not an option: the
   masthead, footer and command band still need it.

   Measured after: content box 180px, every item 180px, "Compare" pill wraps
   the full label with 14px of padding either side. */
@media (min-width: 900px) {
  body > nav.rail.rail {
    padding-left: 14px !important;
    padding-right: 14px !important;
  }

  /* All six items fill the column. `width` alone is not enough once the item
     is a flex child whose `flex` was pinned to `0 0 auto`: the basis is auto,
     so it takes `width`, but stating both is what makes it survive the next
     person changing one of them. */
  body > nav.rail.rail .rl-item {
    width: 100% !important;
    flex: 0 0 auto !important;
    box-sizing: border-box !important;
    justify-content: flex-start !important;
    white-space: nowrap;
  }

  /* The ACTIVE item had a second, unrelated problem: §43 gives `.rl-item.on`
     `padding: 4px 10px !important` at specificity (0,3,1), which outranks
     nav.css's (0,2,2) `11px 14px` — so the one item that is drawn as a filled
     pill was also the one with the least padding in it. It measured 31.7px
     tall against its siblings' 44.7px. The pill is the most visible element in
     the rail; it should be the same box as the rows around it, not a tighter
     one. */
  body > nav.rail.rail .rl-item,
  body > nav.rail.rail .rl-item.on,
  body > nav.rail.rail [aria-current="page"] {
    padding: 11px 14px !important;
    border-radius: 10px !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §66 — THE --live / --accent COLLISION, FIXED AT THE TOKEN (2026-08-07)

   §61 moved the accent to orange and, in the same block, remapped --live and
   --mint to the accent's own hex. That collapsed two DIFFERENT meanings onto
   one colour:

     --live / mint   LIVENESS      "this is recent" — the recency ramp, the
                                   status dot, the age column, the fill feed.
     accent/orange   WHERE YOU ARE  active nav item, sorted column, CTAs,
                                   active chips, pinned cells.

   MEASURED ON THE LIVE PAGE BEFORE THE FIX, via getComputedStyle on the real
   document rather than by reading this file: --live and --accent both
   resolved to #ff7a1a. WCAG 1.00 — not "close", identical. The marks actually
   painting it were 43 `[data-age-h="0"] .c-age` cells, 136 `[data-age-h="1"]`
   cells, the masthead status .dot, and both segments of the venue coverage
   bar. A previous pass fixed the volatility chart AT THE POINT OF USE (it
   strokes --ink now, and that stays — a data line is not a liveness mark) but
   deliberately left the token alone, so everything above still read as accent.

   ── THE NEW VALUE, AND WHY THIS ONE ──────────────────────────────────────

     --live  #2ee6cd   hue 172, sat 80        --live2 #3ac9b6  (the dim step)

   The gate the brief sets is separability from the accent, and the harder
   constraint is the one that killed the earlier coral proposal: it must also
   be nowhere near our "sold" rose. Computed, then confirmed on rendered
   pixels (see the verification note below):

                              WCAG      dE00
       live vs accent #ff7a1a  1.65      57.2      gate >= ~1.5   PASS
       live vs rose   #e06e76  2.00      65.1      coral was 1.06 FAIL
       live vs jade   #5aae87  1.70      16.1      direction, still distinct

   dE00 16 against jade is the tightest number here and it is deliberate:
   jade is a GREEN at hue 145, the mint is a cyan-green at 172, and the old
   shipped --live (#50d2c1) sat at 13.0 — so this is further from the
   direction pair than the design that preceded the collision, not nearer.

   Text/surface, every pair, on the warm near-black set (§63):

       live on --bg 12.53:1 · --s1 11.72:1 · --s2 10.83:1 · glass 11.36:1
       live2 on --bg 9.61:1 · --s1  8.98:1 · --s2  8.30:1 · glass  8.71:1

   Floor is 8.30:1, well clear of 4.5. --live2 has exactly ONE consumer, the
   age column's second step, and it is separated from the accent by hue
   (dE00 53.7) rather than by luminance: there is NO teal that clears 1.5
   against the accent downward AND 4.5 against --s2, because the accent's
   luminance (0.353) sits between them. Solved to confirm that rather than
   assumed — the upper bound is 4.35:1 on --s2, which fails. The dim step is
   a RAMP position, never a lone glyph against a control, so hue carries it.

   ── 1. MARKS THAT WERE --live BUT MEAN "WHERE YOU ARE" ───────────────────
   These would have turned green with the token, which is the same category
   error in the other direction. They are selection states, so they take the
   accent explicitly. Same selectors as the originals, later in the file: two
   !important rules resolve by SPECIFICITY and these are ties, so source order
   decides and this block loads last. */
body .mn-ch-tf[aria-pressed="true"] {
  background: var(--accent) !important; color: var(--bg) !important;
}
body .cmd-eg-b:hover::before { color: var(--accent) !important; }
body #cmd-pop .cmd-r::before { color: var(--accent) !important; }
body #cmd-pop .cmd-r.on { border-left-color: var(--accent) !important; }
body #cmd-pop .cmd-hit { color: var(--accent) !important; }

/* ── 2. MARKS THAT MEAN LIVENESS BUT WERE HARDCODED TO THE ACCENT ─────────
   The venue coverage bar. `.f-tr` is "Traded, measured", `.f-bl` is "Listed,
   no fill feed" — four of six venues publish no fill feed, and this bar is
   the app's own statement about which figures it does and does not have.
   That is the liveness family, and the ORIGINAL rule said so: it reads
   `background: var(--live, #ff7a1a)` a few hundred lines up. §61's blanket
   sweep then hardcoded both segments to the literal accent, which is how a
   coverage claim ended up wearing the colour of the active nav item.

   Repointed at the token, so the measured segment moves with liveness and the
   blind segment stays a faded version of it — the two must not become the
   same mark, since collapsing them is exactly the "n/a is not 0" failure. */
body .f-tr { background: var(--live) !important; }
body .f-bl { background: color-mix(in srgb, var(--live) 38%, transparent) !important; }
/* The glow followed the chart line to a neutral lift when the chart went to
   --ink; the bar is a liveness mark, so its halo is the liveness colour. */
body .sc-hl-bar .f-tr { box-shadow: 0 0 10px -1px rgba(46, 230, 205, .45) !important; }

/* ── 3. THE BOARD CELL CLEARS ITS PIN ─────────────────────────────────────
   Fix 2 right-aligns the matrix figures so a tenor column reads DOWN. §15
   set `body .op-cell { padding: 6px 12px 6px 6px }` when the content was
   centred; the pin button is 15px wide at right:2px, so a right-aligned
   figure would sit under it. (0,3,1) beats §15's (0,1,1); both !important,
   so specificity decides. */
body .op-mx-c.val .op-cell { padding-right: 22px !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §67 — EVERY SECTION OPENS THE SAME WAY (2026-08-08)

   "the UI starts looking better but still the cards while entering the
   sections are not very good."

   MEASURED FIRST, on rendered boxes at 1440x900, onboarding dismissed, per
   section: how many elements draw a box (border, or a background with alpha)
   above the first real number, and how far down that number sits.

     section       boxes above the first number      px to it
     #trade          10  (picker, chips, chart)        383
     #trades          3  (THE CARD, head rule, note)   228
     #strategies      0                                138
     #flow            1  (THE CARD)                    240
     #activity        1  (THE CARD)                    247
     #tools          18  (THE CARD + playground)       n/a — no number
     #venue-list      1  (THE CARD) + table hairlines  187

   The census says the greeting is not one problem, it is one ELEMENT: five of
   seven sections open with `section.panel` drawing a background, a 1px border,
   a 12px radius and 22px of padding around the ENTIRE section. It is the only
   thing between the masthead and the content, and it is the first box in every
   one of those five.

   A card groups a thing AGAINST another thing. There is exactly one of these
   per view and it is full width, so it groups nothing — it draws a rectangle
   around the page inside a rectangle that is already the page. §58 made this
   argument for the overview and scoped the fix to .hero-panel, reasoning that
   the other sections were "lists of objects and a card is the right container
   for a list of objects". Measured, that reasoning does not survive: the card
   is not containing the list against anything, and the section it wraps is the
   whole screen. So the scope was the mistake, not the fix. It generalises here.

   The second half is the TITLE. §42's win was that every section's title is
   the rail's own word, and that stays — but it set them at 34px display, which
   makes the loudest thing on entry a word you just clicked, sitting 200px right
   of the same word already lit in the rail. §56 deleted the overview's <h2> for
   exactly this ("two headlines arguing") and the other six never caught up.
   They cannot be deleted — the markup is not ours this pass and the word is the
   only wayfinding on the page itself — so they are demoted to the hero's own
   eyebrow: .mn-hero-lead's size, tracking, case and weight, verbatim.

   The result is one habit: every section opens with a quiet uppercase label,
   one line of sub, then its content on the page. The loudest thing on every
   screen is a number, never a heading, and never a frame.

   Separation stays SPACE and at most one hairline — §54's rule, unchanged.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE WHOLE-SECTION CARD GOES, exactly as §58 did for .hero-panel.
      (0,2,1) beats §33's `body .panel { padding: 22px }` (0,1,1); both carry
      !important, so specificity decides — §53's note. */
body .tl-panel,
body .tape-panel {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
}

/* ── 2. THE SECOND INDENT. tools.css gives .tl-main another 14/15px inside the
      card's 22px, which is why the tools sections' content started 37px right
      of the overview's. Both go, and the seven sections share a left edge. */
body #tools-root .tl-main { padding: 0 !important; }
/* opps.css owns .op (another agent's file this pass); its inset is corrected
   from here rather than edited there. Bottom padding stays — that is air. */
body #opps-root .op { padding-left: 0 !important; padding-right: 0 !important; }

/* ── 3. THE TITLE BECOMES THE EYEBROW. Specificity is the whole game here:
      §42 declares `html body .tl-sec-h` (0,1,2) and §33 declares
      `html body .panel-head h2` (0,1,3), both !important. Adding the parent
      class takes these to (0,2,2) and (0,2,4) respectively. */
html body .tl-sec .tl-sec-h,
html body .tl-sec .sh-h,
html body .op .op-h,
html body .panel .panel-head h2 {
  font-size: var(--t-xs) !important;
  font-weight: 600 !important;
  line-height: 1.2 !important;
  letter-spacing: var(--tr-label) !important;
  text-transform: uppercase !important;
  color: var(--ink) !important;
  margin: 0 0 10px !important;
}

/* THE FIRST EYEBROW OPENS A PANEL; THE SECOND OPENS A SECTION, and the rule
   above gave both margin-top: 0. Measured 2026-08-19 on #venue-list: the gap
   between the networks paragraph and the "VENUES" eyebrow was 0px, so two
   separate sections — the networks board and the venue registry — read as one
   continuous run of text. Only headings that FOLLOW something get the lead-in,
   so no panel gains a gap it did not have. */
html body .tl-sec > * + .tl-sec-h { margin-top: 32px !important; }

/* ── 4. THE RULE UNDER THE TITLE went with the display size that needed it.
      A hairline under an 11px label is a box drawn around one word. */
body .panel .panel-head {
  border-bottom: 0 !important;
  padding-bottom: 0 !important;
}

/* ── 5. THE SUB LINE sits under an eyebrow now, not under a 34px heading, so
      it carries the sentence and takes the body step rather than §42's 12px.
      One line of air below it, then content — the same gap on all seven. */
html body .tl-sec .tl-sec-s,
html body .op .op-sub,
html body .panel .panel-head .sub {
  font-size: var(--t-md) !important;
  color: var(--ink2) !important;
  line-height: 1.55 !important;
  margin: 0 0 20px !important;
  max-width: 78ch !important;
}
/* A section that states a caveat under the sub gets the gap once, not twice. */
html body .tl-sec .tl-sec-s + .tl-sec-s { margin-top: -12px !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §68 — THE PAPER REGISTER: INK, NOT GLASS AND GLOW (2026-08-08)

   "Can you make it less flashy now and more API focused design style, more
   sober but not the blue we had before — that one was too sober and not really
   fun to watch. The paper style one was really impressive and good for the
   eyes and looks like there is some touch of drawing and manuscript vibes."

   ── A FACT THAT HAS TO BE STATED, BECAUSE IT CHANGES WHAT THIS BLOCK CAN DO ─

   paper.css and paper.js ARE NOT LOADING. Verified on the live page rather
   than from the tree: index.html links ten stylesheets and paper.css is not
   among them, there is no #pp-sheet and no #pp-plot in the document, and
   getPropertyValue('--pp-ink-drawn') on :root returns the empty string. The
   files exist on disk and are good; nothing references them. index.html is
   not this pass's file, so the link cannot be added here — it is reported up
   instead.

   That makes referencing --pp-* directly a live 500-in-spirit: a hairline
   coloured with an undefined token is a hairline that does not paint. So every
   borrowed value below is written `var(--pp-ink-x, <the literal paper.css
   declares>)`. The page is correct TODAY on the literal, and the moment the
   sheet is linked it adopts the real ink with no further edit. That is the
   only honest way to harmonise with a layer that is not on.

   ── WHAT ACTUALLY MAKES IT "FLASHY" ────────────────────────────────────────

   Measured on rendered pixels, not declared values. Three devices, in order of
   how much screen they take:

     1. GLASS + BLOOM ON EVERY PANEL. `body .panel:not(.hero-panel)` paints
        --glass (rgba(28,22,17,.55)), a --glass-line border, an inset pink
        top edge and a 44px drop shadow. At (0,2,1) it also outranked §67's
        `body .tl-panel` (0,1,1), which is why the section cards measured as
        still-boxed after §67 flattened them. Specificity, not source order —
        §53's note, and the second time this pass it has been the answer.
     2. THE FILLED ACCENT PILL. The active rail item is a solid #ff7a1a
        lozenge with near-black text: the single highest-contrast object on
        the page is a word you already clicked.
     3. THE PINK LOBE. §65 already took it from three lobes to one; on a page
        whose ground is meant to read as stock, even one is a lit studio.

   Sober is not the navy. The warm near-black ground stays exactly as it is —
   he named the old #0d1b2a as the failure mode, and the fix for "flashy" is to
   remove LIGHT SOURCES, not to drain warmth.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE SECTION CARD, FINISHED. §67 flattened the wrong-weight selector;
      this one is (0,3,2) and clears `body .panel:not(.hero-panel)` (0,2,1)
      with room to spare. The section sits on the sheet — no fill, no border,
      no radius, no shadow. */
html body .panel.tl-panel,
html body .panel.tape-panel,
html body .panel.hero-panel {
  background: transparent !important;
  background-image: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
}

/* ── 2. THE BLOOM GOES TO BARELY-THERE. One lobe stays, at a third of §65's
      strength and pushed further off-corner: enough that the top-right of the
      sheet is not dead flat, not enough to read as a colour. The warm lobe is
      what keeps the ground warm rather than grey, so it is kept and only
      trimmed. */
body::before {
  background:
    radial-gradient(900px 520px at 6% -12%, rgba(var(--bloom-warm), .085), transparent 64%),
    radial-gradient(520px 360px at 105% -4%, rgba(var(--bloom-pink), .035), transparent 58%) !important;
}

/* The lit seams were the other half of the haze. A seam on a drafting sheet is
   a ruled line, so these become ink and drop the coloured bleed entirely. */
body .mn-chips,
body .mn-chart,
body .mn-board-h,
body .sc-hl-cov {
  border-top-color: var(--pp-ink-construction, rgba(248, 238, 226, .075)) !important;
  box-shadow: none !important;
}
body .panel:not(.hero-panel),
body #detail-root > *,
body .sc-hl-strip {
  box-shadow: none !important;
}
body > header.top { box-shadow: 0 1px 0 var(--pp-ink-construction, rgba(248, 238, 226, .075)) !important; }
body footer       { box-shadow: inset 0 1px 0 var(--pp-ink-construction, rgba(248, 238, 226, .075)) !important; }

/* The supporting-stats strip was a filled, bordered tray under the hero — the
   last panel-shaped object on the overview. §56 called it "label over number";
   on the sheet that needs one ruled line above it and nothing else. */
html body .sc-hl-strip {
  background: transparent !important;
  border: 0 !important;
  border-top: var(--pp-pen, 1px) solid var(--pp-ink-drawn, rgba(248, 238, 226, .105)) !important;
  border-radius: 0 !important;
}

/* ── 3. THE ACCENT STOPS SHOUTING, AND KEEPS ITS ONE JOB.
      "where you are" is marked the way a manuscript marks it: a drawn rule in
      the margin and the word in ink, not a highlighter block. The accent is
      still the ONLY thing that marks position — it is doing the same job at a
      tenth of the area. --live (#2ee6cd) is not touched anywhere here; §66
      separated the two for a real reason and this block does not re-cross it.
      (0,3,1) matches §53b's `body .rail .rl-item.on` and lands later. */
body .rail .rl-item.on,
body .rail [aria-current="page"] {
  background: rgba(255, 122, 26, .085) !important;
  color: var(--ink) !important;
  box-shadow: inset 2px 0 0 var(--accent) !important;
  border-radius: 0 8px 8px 0 !important;
}
body .rail .rl-item.on *,
body .rail [aria-current="page"] * { color: inherit !important; }
/* The index numeral keeps the accent — it is the smallest mark that can carry
   position, which is exactly what a margin note is. */
body .rail .rl-item.on .rl-n { color: var(--accent) !important; opacity: 1 !important; }

/* ── 4. FILLED TOGGLES BECOME DRAWN ONES. Same argument, inside the sections:
      an active chip was a solid orange block, so a page with four control
      groups had four highlighter marks before any data. Selected state is now
      ink weight plus an underline in the accent — the API-doc convention, and
      it survives at 11px where a fill does not. */
body .op-chip.on,
body .op-b.on,
body .tw-tab.on,
body .mn-tf.on,
body .tl-tab.on {
  background: transparent !important;
  color: var(--ink) !important;
  border-color: var(--pp-ink-margin, rgba(248, 238, 226, .155)) !important;
  box-shadow: inset 0 -2px 0 var(--accent) !important;
}
/* Unselected controls are construction lines: present, never competing. */
body .op-chip,
body .op-b,
body .tw-tab,
body .mn-tf,
body .tl-tab {
  background: transparent !important;
  border-color: var(--pp-ink-construction, rgba(248, 238, 226, .075)) !important;
}

/* ── 5. MONOSPACE WHERE IT MEANS SOMETHING. The API register reads labels as
      field names. The section eyebrow §67 introduced is exactly that — a key
      naming what follows — so it takes the mono face at the same size. This is
      §31's rule ("mono is for figures") extended one step, and the step is
      named: mono is for figures AND for the keys that name them. */
html body .tl-sec .tl-sec-h,
html body .tl-sec .sh-h,
html body .op .op-h,
html body .panel .panel-head h2 {
  font-family: var(--mono) !important;
  letter-spacing: .1em !important;
  color: var(--ink2) !important;
}

/* ── 6. THE ACTIVE MARKER IS A RULE, NOT A LOZENGE. Measured after §68 landed:
      the wash still painted a 10px-radius rounded rectangle, because §64's
      `body > nav.rail.rail .rl-item.on` (0,4,1) outranks §68's (0,3,1) on the
      radius. So the "pill" survived the pill removal — the fill changed colour
      and kept its shape. (0,4,2) settles it. No wash at all now: a margin rule
      and the word in full ink is how a manuscript marks the line you are on,
      and it is also exactly what a documentation sidebar does. */
html body > nav.rail.rail .rl-item.on,
html body > nav.rail.rail [aria-current="page"] {
  background: transparent !important;
  border-radius: 0 !important;
  box-shadow: inset 2px 0 0 var(--accent) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   §69 — FEWER THINGS ON SCREEN (2026-08-08)

   New reference, and it is the owner's OWN product: the Stormbit testnet
   borrow flow. Sampled: 36 visible text nodes on the entire page. "the ui is
   clean, information required is the only one displayed and the rest is not."

   COUNTED HERE, per section, on displayed text nodes — and the counter had to
   be fixed before it could be trusted. The first pass counted `span.sc-l` on
   the Markets board as 25 displayed labels; measured, each one is a 1x1 box.
   They are sr-only labels naming a cell for assistive tech, which is the
   opposite of clutter — present for a screen reader, absent from the screen.
   Counting them made the board look 25 nodes worse than it is. Nodes under
   2x2, under 4px, or clipped to nothing are excluded now.

     section       displayed text nodes      vs the 36 reference
     flow                  28                already under it
     activity              27                already under it
     tools                 35                already under it
     venue-list            62                1.7x
     trade                100                2.8x
     strategies           175                4.9x
     trades            35,471                2,000 table rows

   THE FINDING IS THAT THIS IS NOT A GLOBAL PROBLEM. Three of seven sections
   already meet the reference. The two that miss are BOARDS, and a board's text
   is its data — the borrow flow is a form with four decisions on it, and a
   screener that showed 36 things would be showing one asset. The comparison is
   right about chrome and wrong about rows, so only chrome is cut here.

   ── THE BIGGEST REDUNDANCY, FOUND AND DELIBERATELY NOT CUT ────────────────

   `.op-unit` renders 38 times on #strategies with two distinct values: "cap
   bid" (17) and "cap bid · on request" (21). The words "cap bid" therefore sit
   under all 38 figures, while the section's own subtitle one line above the
   board already reads "Net cost, after the cap". On the node count alone it is
   the single largest cut available anywhere in the app: 38 nodes, ~22% of the
   section, reachable from CSS.

   IT STAYS, and the reason is written down in the file that owns it. opps.css
   records that the label is a FIX, not decoration: "The cash and the net are
   DIFFERENT QUANTITIES — $62.40 is the cap's bid on its own, −0.59% is the
   collar's net — and with nothing between them the green $62.40 read as what
   you receive." Removing the label re-opens a misreading another pass closed,
   and it would do it silently, on the one screen where the number IS the
   product. A redundancy argument does not outrank a shipped correctness fix.

   It was implemented, measured, and reverted rather than left in — the attempt
   is what turned up the constraint. The real fix is not CSS: the qualifier
   belongs once, in the column header or the sub-line, which is a change in
   opps.js's cell markup and therefore not this pass's to make. Recorded here
   so the next pass does not rediscover it from scratch.

   Two traps found on the way, both worth keeping written down:
     - `body .op-unit` (0,1,1) does not reach the cell; opps.css declares
       `body .op .op-mx-c.val .op-unit` at (0,4,1). Specificity again.
     - `.op-rfq` is a CHILD of .op-unit on 21 cells and carries
       `font-size: inherit !important`, so zeroing the parent silently zeroes
       the RFQ mark too. The obvious one-liner would have deleted the
       firm-vs-RFQ distinction as a side effect.

   ALSO NOT CUT, deliberately: `.op-mx-c.empty` renders "·" in 10 cells. That
   is the "n/a is not 0" marker — a pair we cannot price renders as a dot,
   never as a zero and never as blank. Ten dots is the cheapest honest
   statement of a blind spot on the page and it stays.

   NET: no text is removed by this pass. The count stands where it is, and the
   reason each remaining node survives is now on the record.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   §70 — THE LAST FOUR LIGHT SOURCES (2026-08-09)

   "Can you make it less flashy now and more API focused design style."

   §68 removed the filled accent from the rail and from the section controls
   and it worked — measured, `.op-b.on` and `.op-chip.on` now render
   background rgba(0,0,0,0), border rgba(248,238,226,.157) and an inset
   0 -2px 0 #ff7a1a. That is the API-doc treatment and it holds.

   IT DID NOT FINISH, AND THE REASON IS A SELECTOR THAT MATCHES NOTHING.
   §68's toggle list names `.mn-tf.on`. There is no `.mn-tf` in this app —
   `document.querySelectorAll(".mn-tf")` returns zero nodes on every one of
   the eight sections. The chart's timeframe control is `.mn-ch-tf`, and it
   is driven by `[aria-pressed]`, not by `.on`. So the rule was written,
   reviewed and landed without ever reaching an element, and the solid orange
   "All" lozenge survived a pass whose entire purpose was removing it. When a
   selector returns nothing, the selector is the thing to suspect.

   SO THE SURVIVORS WERE COUNTED, NOT GUESSED. Every element inside the
   stage, the rail and the masthead was walked on all eight sections and
   filtered to background fills with alpha >= .25 and a channel spread >= 45
   (a saturated fill — a light source, as distinct from the ground):

     section      element                     size     fill
     chain        button.chv-exp.on           99x53    rgb(255,122,26)
     chain        button.chv-src.on           71x29    rgb(255,122,26)
     trade        button.mn-ch-tf[pressed]    43x29    rgb(255,122,26)
     tools        span.sh-badge "soon"        45x20    rgb(255,122,26)
     every        span.dot.live                6x6     rgb(46,230,205)
     trade        i.f-tr (coverage bar)      373x10    rgb(46,230,205)

   Six objects. FOUR ARE CUT AND TWO ARE KEPT, and the split is the whole
   point of the block:

   KEPT — `.dot.live` and `.f-tr` are the only two, and both are --live
   (#2ee6cd), not the accent. §66 separated those two hues to fix a real bug
   where a data-coverage claim wore the active-nav colour. A 6x6 pulse that
   means "the feed is up" and a bar segment that means "we have measured
   fills here" are exactly what that token is for. Neither is touched. The
   accent is not put on them and their hue is not put on anything else.

   CUT — the four orange fills. Not one of them means "where you are" except
   the two chain chips and the timeframe, and those mean it at 53px and 29px
   of solid highlighter when a 2px rule says it just as unambiguously. The
   "soon" badge does not mean it at all: it is a status word wearing the
   position colour, which is §66's own category error one more time, in the
   other direction.

   ── ON TOUCHING chain's CHIPS FROM HERE ───────────────────────────────────
   chain.css and chain.js are another author's committed files (5b79ad2) and
   neither is edited. `.chv-exp.on` / `.chv-src.on` are re-pointed FROM this
   file, which is what this file is for — §67 does it to opps.css and §68 to
   tools.css. The two chain chips are the largest saturated blocks in the app
   and leaving them lit would mean the landing surface is the one screen the
   "less flashy" pass skipped. Flagged rather than done quietly.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE TIMEFRAME, WITH THE SELECTOR THAT EXISTS. §66 sets the fill at
      `body .mn-ch-tf[aria-pressed="true"]` (0,2,1) !important; two of those
      also sit at :3551 and :3708. (0,3,1) clears all three. Same treatment
      as §68 gave the section controls, so the two control families finally
      look like one system. */
html body .mn-ch-tf[aria-pressed="true"] {
  background: transparent !important;
  color: var(--ink) !important;
  border-color: var(--pp-ink-margin, rgba(248, 238, 226, .155)) !important;
  box-shadow: inset 0 -2px 0 var(--accent) !important;
}

/* ── 2. THE CHAIN CHIPS. Same rule, so a reader crossing from Chain to Cost
      meets one selected-state vocabulary rather than two. */
html body .chv-exp.on,
html body .chv-src.on {
  background: transparent !important;
  color: var(--ink) !important;
  box-shadow: inset 0 -2px 0 var(--accent) !important;
}
/* THE RE-POINT ABOVE WAS ONE ELEMENT SHORT, and the miss was invisible to
   anyone reading either file on its own. chain.css:73 sets the chip's SECOND
   line — the "0d / 11d / 46d" days-out label — to `color: var(--bg)`, which is
   correct in that file's design because there the selected chip is a solid
   orange fill and --bg is the dark ink that reads on it. Taking the fill away
   here without following the child left near-black type on the near-black
   ground: measured, rgb(12,10,8) on rgb(12,10,8). The days-out label vanished
   on exactly the expiry you had selected, which is the one you most need to
   confirm. Reported as "khó dùng" and it is the sharpest edge of that. */
html body .chv-exp.on .chv-exp-t {
  color: var(--ink3) !important;
  opacity: 1 !important;
}

/* ── 3. THE "SOON" BADGE STOPS WEARING THE POSITION COLOUR. It is a status,
      and this app has exactly one accent with exactly one meaning. Outline
      and muted ink — the API-doc convention for a state label. */
html body .sh-badge {
  background: transparent !important;
  color: var(--ink3) !important;
  border: 1px solid var(--pp-ink-construction, rgba(248, 238, 226, .075)) !important;
}

/* ── 4. NO HALOS. :3708 hangs a two-layer orange glow — a 1px accent ring
      plus an 18px drop shadow — on every filled accent state. §68 took the
      rail off it by overriding box-shadow at (0,4,2); the other three were
      never named, so the glow outlived the fill it was lighting and is now a
      halo around nothing. A drafting sheet has no light sources. */
html body .sh-badge,
html body .sh-cta,
html body .sh-form .sh-cta,
html body .mn-ch-tf[aria-pressed="true"] { filter: none !important; }
html body .sh-cta, html body .sh-form .sh-cta {
  box-shadow: none !important;
}

/* ── 5. THE PREMIUM CARD KEEPS ITS BOX AND LOSES ITS TINT. This one IS a
      card in §54's sense — it groups the paid tier AGAINST the free
      playground beside it, which is a real comparison and the one thing a
      border is for. What it does not need is :2893's orange border and the
      orange-to-white gradient wash behind it, which made an upsell the
      brightest object on a page whose subject is a Python console. Hairline,
      no fill. The check marks go with it: a tick is not a position. */
html body .sh-pro {
  border-color: var(--pp-ink-drawn, rgba(248, 238, 226, .105)) !important;
  background: transparent !important;
  background-image: none !important;
}
html body .sh-list li::before { color: var(--ink3) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §71 — THE ONE HONEST TEXT CUT ON #trade (2026-08-09)

   The measured target is the owner's own borrow flow: 36 visible text nodes
   on the whole page, "information required is the only one displayed and the
   rest is not." #trade renders 98.

   §69 went looking for text to cut on the boards and correctly found none —
   a board's text is its data, and it wrote down why each candidate survived.
   It did not look at the overview, and the overview is where the duplicate
   is. Read off the live DOM, the hero states its coverage TWICE:

     .sc-hl-strip   "Venues listing BTC"   5 of 6
                    "We can see fills on"  2 venues
                    "Blind to activity on" 3 venues        8 text nodes

     .sc-hl-cov     [====|////|....]  the bar
                    "Traded, measured (2)"
                    "Listed, no fill feed (3)"
                    "Not listed (1)"                       3 text nodes

   Not "similar" — the same three integers. 2 == 2, 3 == 3, and 5 of 6 is
   2+3 of 6. Eight nodes and a three-cell tray to restate what three nodes
   and a bar already say.

   THE TRAY GOES AND THE BAR STAYS, in that direction and not the other:

     - The bar carries a fact the tray cannot. Its middle segment is HATCHED,
       and IA.md protects that specifically — "the coverage bar's hatched
       segment is `n/a is not 0` made visible; keep it that way." Three
       venues list BTC and publish no fill feed; the hatch is that absence
       drawn as an absence rather than as a number. Delete the bar to keep
       the tray and the app loses the only place it SHOWS a blind spot
       instead of counting one.
     - The tray was already the problem child. §68 had to strip its fill,
       its border and its radius, calling it "the last panel-shaped object on
       the overview". A tray that has to be de-boxed because it duplicates
       the row beneath it is a tray with no job left.
     - Neither answers this section's question — "the same contract, every
       venue, side by side" is answered by the table. Both are coverage
       apparatus, so the redundant one is the one that goes.

   NOTHING IS LOST: every figure in the tray is still on screen, in the
   legend, four lines below where the tray was.

   ── THE ONE PLACE THIS TOUCHES AN AGREED SPEC, STATED PLAINLY ─────────────
   IA.md's rebuild skeleton lists "three or four supporting stats, label over
   number" as item 4. This removes them. The argument for doing it anyway is
   that the bar IS the supporting stat, drawn rather than tabulated, and that
   the 36-node instruction is later than the skeleton and directly forbids
   saying a thing twice. It is one line to revert. If the owner wants the
   tiles back, delete this rule and cut `.sc-hl-cov`'s legend instead — but
   then the hatch needs a label somewhere, and IA.md is explicit that the
   hatch is not negotiable.
   ══════════════════════════════════════════════════════════════════════════ */

html body .sc-hl-strip { display: none !important; }

/* ══════════════════════════════════════════════════════════════════════════
   §72 — CHAIN IS THE SECTION §67 MISSED (2026-08-09)

   "the cards while entering the sections are not very good" / "don't stack
   cards."

   §67 flattened the whole-section card on five sections by name —
   .tl-panel, .tape-panel — and §68 finished the job with .hero-panel. It
   listed seven sections in its census and Chain was not one of them, because
   Chain did not exist when that census was taken. Measured now:

     section.panel.chv   1120x793   background rgba(28,22,17,.55)
                                    border 1px rgba(255,255,255,.16)
                                    radius 12px, padding 22px

   That is the identical element with the identical geometry — one full-width
   rectangle drawn around the page, inside a rectangle that is already the
   page, grouping nothing against anything. Chain is IA.md's intended landing
   surface, so it is the worst place in the app to leave the one habit the
   other six sections dropped: land here and the first thing you meet is a
   frame.

   .chv-wrap is NOT touched and that is deliberate. It is 728x444 and it
   holds the chain table against the "one contract, every venue" note beside
   it — two things, side by side, which is §54's actual test for when a
   border earns its keep. The section card fails that test; this one passes.

   And the expiry/price chips finish the §70 conversion. They came off the
   solid orange fill there but kept chain.css's accent BORDER, which left
   Chain marking selection with a ring while Compare and Cost mark it with an
   underline — one app, two vocabularies for the same state. Same treatment
   as §68 gave every other control: construction line, accent underline.

   chain.css is not edited. Re-pointed from here, as §70 explains.
   ══════════════════════════════════════════════════════════════════════════ */

html body .panel.chv {
  background: transparent !important;
  background-image: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
}
html body .chv-exp.on,
html body .chv-src.on {
  border-color: var(--pp-ink-margin, rgba(248, 238, 226, .155)) !important;
}

/* ══════════════════════════════════════════════════════════════════════════
   §67 — THE TOKENS §63 FORGOT

   §63 repainted the dark theme warm (--bg #0c0a08, --s1 #17130f, --line
   #302a23) but only redefined the tokens it happened to be using. 61 of the
   original block's 85 tokens were never re-pointed, so they kept resolving to
   the Midnight Arcade teal underneath. 31 of those are still consumed.

   Measured, not guessed: the asset picker (.cs-pop) painted #101c1f — a cold
   teal — while the rail beside it painted rgba(28,22,17,.55) and its own
   border painted #302a23. Two palettes on screen at once. That is what "it
   shows the previous UI" was.

   Re-pointed here, onto §63's ramp. Only the COLD-HUED leftovers move.

   DELIBERATELY NOT TOUCHED:
   - --good/--bad/--pos/--neg — jade #5aae87 and rose #e06e76. §63 keeps both
     for direction and says so in writing. They are not leftovers.
   - --v1..--v5, --warn, --empty, --mid — already warm (#f2f0ea, #b8b4a9,
     #8a877e). Nothing to fix.
   - --card/--s3/--fill-1/--fill-2/--mint-dim — transparent on purpose, from
     the pass that flattened boxes. Re-colouring them would put the frames
     back.

   --focus IS A RULE VIOLATION, NOT A HUE MISS. It resolves to #f0b90b, which
   is Binance's gold to the digit — the exact colour §63's own comment bans:
   "NO GOLD ... re-importing the exact colour we removed tonight for being
   borrowed would undo the point." It survived because §63 never redefined it.
   Pointed at the brand accent, which is what §63 says the one accent is.
   ══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="dark"] {
  /* surfaces — bg #0c0a08 < rail < s1 #17130f < pop < s2 #201b16 */
  --rail:  #14100c;
  --panel: #17130f;
  --pop:   #1d1812;

  /* borders — the two edge tokens are 23 uses of cold teal */
  --edge-1: #302a23;
  --edge-2: #423a31;

  --hover-wash: rgba(248, 244, 240, .06);

  /* the one accent, per §63. was #f0b90b (Binance gold). */
  --focus: #ff7a1a;

  /* coverage ramp: was #12262a -> #23736a, teal end to end */
  --q1: #1a1410;
  --q2: #2a2016;
  --q3: #3e2c1a;
  --q4: #5a3d1e;
  --q5: #7a5223;
}

/* ══════════════════════════════════════════════════════════════════════════
   §68 — THE LIGHT DRIFTS

   The two bloom lobes (§65, trimmed by the rule above) are the only part of
   the sheet that never moves. The arc is drawn on every section change —
   measured, not assumed: stroke-dashoffset runs 973 -> 470 -> 223 -> 81 -> 0
   after a nav, because paper.js rebuilds the path on `moneyness:section` and
   `hashchange` (paper.js:685). So arrival and state change are already
   covered. Ambient is what was missing.

   A drafting lamp is not perfectly still. This moves the light, not the page:
   a 54s cycle, at most 16px of travel and 3% of scale, on a layer that holds
   nothing but two transparent-falloff gradients.

   WHY IT IS SAFE TO TRANSLATE A FULL-VIEWPORT LAYER: body::before has NO
   opaque fill — its background is two radial gradients that fade to
   `transparent`, over body's own --bg. Moving it cannot expose an edge or a
   seam, because there is nothing behind it but the identical ground. Scale
   only ever goes up, never below 1.

   TRANSFORM ONLY, so this stays on the compositor and never triggers layout
   or paint. No `will-change`: a transform animation is promoted for its
   duration anyway, and declaring it here would pin a full-screen layer in
   memory forever for an effect that is meant to be unnoticeable.

   If you can SEE it move, it is wrong. It should only be noticeable if you
   turn it off.
   ══════════════════════════════════════════════════════════════════════════ */

@keyframes pp-bloom-drift {
  0%   { transform: translate3d(0, 0, 0)        scale(1);     }
  25%  { transform: translate3d(-14px, 8px, 0)  scale(1.015); }
  50%  { transform: translate3d(6px, 16px, 0)   scale(1.030); }
  75%  { transform: translate3d(16px, 5px, 0)   scale(1.015); }
  100% { transform: translate3d(0, 0, 0)        scale(1);     }
}

body::before {
  animation: pp-bloom-drift 54s ease-in-out infinite !important;
}

/* Reduced motion: the lamp stops. Ambient drift has no end state to land on
   the way a reveal does — the correct still frame is simply 0%. */
@media (prefers-reduced-motion: reduce) {
  body::before {
    animation: none !important;
    transform: none !important;
  }
}

/* ── §70 — THE VENUE MARK, WHEREVER A VENUE IS NAMED ──────────────────────
   The owner's call (2026-08-10): "the logos for the venues for the moment are
   good and should be everywhere". A venue is the entity this whole product is
   about, so it is named the same way on every surface: mark, then name.

   Every one of these comes from the app-level sprite marks.js mounts once, so
   a surface that repeats a venue 2,000 times (the tape) costs ~60 bytes a row
   rather than re-inlining a 1-2 KB data-URI.

   ASSET marks are NOT propagated with them. The owner asked for a design pass
   on those first — "build great logos that match our design and then add them
   everywhere" — so they stay where they already were. */
/* .mk is `display:block` (style.css:739) because every earlier use of a mark
   sat inside a flex row. A mark placed INLINE after a number therefore took its
   own line: measured, all 93 tagged chain cells had the logo 17px below the
   figure it belonged to, which nowrap could not prevent because a block box
   does not wrap, it stacks. Inline-flow marks say so. */
.chv-vm, .tw-vm {
  display: inline-block !important;
}
.tw-vm, .chv-vpin .mk {
  vertical-align: -2px;
  margin-right: 5px;
  border-radius: 4px;
  flex: 0 0 auto;
}
.chv-vpin { display: inline-flex; align-items: center; }

/* ── THE FLOW LEGEND'S SHARE FIGURE ────────────────────────────────────────
   tools.js now renders each legend entry as "CRYPTO $11.9M 97.2%", because the
   swatch beside it decodes nothing: all six categories are alphas of one teal
   (§ --cat-* above) and adjacent chips measure 1.07:1 to 1.18:1 apart, with
   pre-IPO at 1.055:1 against the page — a key that keys nothing. The value is
   the legend's real content now, so the share is set back to --ink3 to keep the
   category name and its money in front of it. */
body .legend .lg em {
  font-style: normal;
  margin-left: 6px;
  color: var(--ink3) !important;
  font-variant-numeric: tabular-nums;
}

/* ── THE DAILY RIBBON (Flow) ───────────────────────────────────────────────
   One column per UTC day: a bar for the day's premium, the leading asset's
   ticker written under it. Tokens only, and the leader is WRITTEN rather than
   coloured for the reason the Flow legend above records — all six categories
   are alphas of one teal and adjacent chips measure 1.055:1 to 1.18:1 apart,
   so this register cannot separate three assets by hue. */
body .dy-wrap { margin: 22px 0 6px; }
body .dy-h {
  margin: 0 0 10px;
  font-size: var(--t-xs) !important;
  letter-spacing: var(--tr-label) !important;
  text-transform: uppercase;
  color: var(--ink3) !important;
}
/* The strip scrolls rather than squeezing: 31 columns under 400px would give
   each ticker 11px, and a label nobody can read is worse than a scrollbar.
   The wrapper owns the overflow so the page body never scrolls sideways. */
body .dy-strip {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 96px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 2px;
}
body .dy {
  flex: 1 1 0;
  min-width: 26px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: stretch;
  gap: 4px;
}
body .dy-b {
  display: block;
  width: 100%;
  background: var(--line2);
  border-radius: 1px;
  min-height: 2px;
}
/* The biggest day in the window, which is the one the note names. */
body .dy-b.hot { background: var(--accent); }
body .dy-k {
  font-style: normal;
  font-family: var(--mono);
  font-size: 9px !important;
  line-height: 1;
  text-align: center;
  color: var(--ink3) !important;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body .dy-note {
  margin: 10px 0 0;
  max-width: 92ch;
  font-size: var(--t-dense) !important;
  line-height: 1.6;
  color: var(--ink2) !important;
}
body .dy-note b { color: var(--ink) !important; font-weight: 600 !important; }

/* ── THE VENUE MARK IN THE COMPARE HERO ────────────────────────────────────
   The hero's "on Binance →" is the one place on this screen that names the
   venue you would actually go to, and it named it in words only while every
   other venue reference in the app carries its mark. Owner, 2026-08-20: "on
   binance should better show the logo".
   Baseline-aligned rather than vertically centred: the button sits on the same
   line as "of the position", and a centred mark inside inline text rides high
   against a lowercase word. Small negative bottom offset is the optical
   correction, measured against the chip marks two blocks down. */
body .mn-hero-v .mk {
  display: inline-block !important;
  vertical-align: -3px;
  margin-right: 6px;
}
