/* ══════════════════════════════════════════════════════════════════════════
   oai-b.css, repairs to TRADES [3], PREMIUM [4] and FLOW [5] after the
   openai-scale.css type jump. Owns only these three views. Edits no existing
   stylesheet: instrument.css, density.css, tools.css and premium.css are all
   untouched and everything below is an override from here.

   Brand palette only. No em dash anywhere, ranges are written "to".
   ══════════════════════════════════════════════════════════════════════════ */


/* ──────────────────────────────────────────────────────────────────────────
   1. TRADES. THE TAPE ROWS ARE COLLIDING, AND THE GUARD THAT WAS MEANT TO
      STOP IT NEVER FIRED.

   MEASURED on the live surface, 1440 wide, tab [3], 2,000 .tw-row nodes
   counted in the DOM:

     .tw-row computed font-size        14px      NOT the 13px openai-scale.css
                                                 declares for it
     .tw-c   computed line-height      20.3px    (14 x 1.45)
     .tw-row computed height           28px      density.css:169, !important
     .tw-row overflow                  visible

   openai-scale.css:62 sets `.tw-row, .tw-c { font-size: 13px }` on purpose so
   the fold does not blow out. That rule is INERT: instrument.css pins
   `font-size: var(--t-sm) !important` on a near-universal selector, and a
   plain declaration cannot beat an !important one whatever its specificity.
   The token moved 12 to 14, so the tape moved with it and the guard did not.

   The damage, measured on the first visible row:

     row box                top 411, height 28, so 411 to 439
     .p  "sold the upside"  top 407, height 15.4   starts 4px ABOVE the row
     .s  "$80 . -13.4%"     top 428, height 13.1   ends  2.1px BELOW the row

   Stack is 28.5px of text inside a 28px box with overflow visible, so every
   row paints into its two neighbours. That is the overlap on the tape.

   THE REPAIR IS TYPE ONLY, and it keeps the 28px row. Raising the row to fit
   would cost 2px x 2,000 rows = 4,000px of extra scroll and push the fold off,
   which is the exact regression openai-scale.css:59 wrote the guard against.
   So: restore the intended 13px, this time with the !important it needed, and
   take the leading down so two lines fit.

     .p  13px x 1.15 = 14.95px
     .s  11px x 1.10 = 12.10px
                       27.05px inside 28px, 0.95px of slack, centred by the
                       flex that is already on the cell.

   NOTHING here is a shadow, a filter, a backdrop or a transform. Every
   declaration below is font-size, line-height or colour, because each one is
   paid 2,000 times. ────────────────────────────────────────────────────── */

:root:root body .tw-row,
:root:root body .tw-c {
  font-size: 13px !important;
  line-height: 1.15 !important;
}

/* The two stacked lines inside a cell. .p is the sentence a reader scans,
   .s is the strike and the move under it. Both are epistemic content and
   neither is shortened or dropped, they are only given leading that fits. */
:root:root body .tw-row .p { font-size: 13px !important; line-height: 1.15 !important; }
:root:root body .tw-row .s,
:root:root body .tw-row .s > * { font-size: 11px !important; line-height: 1.1 !important; }

/* The age cell carries its own 11px sub line ("1/2" under "5m"), same fix. */
:root:root body .tw-row .tw-c.c-age { font-size: 11px !important; line-height: 1.1 !important; }

/* The header is not a row, so it does not pay the 2,000x cost and it can
   carry the micro size the rest of the site gives a column label. At 14px it
   was competing with its own data for weight. */
:root:root body .tw-head,
:root:root body .tw-head .tw-c {
  font-size: 11px !important;
  line-height: 1.2 !important;
  color: var(--ink3, #9b8e82);
}

/* The tape's own count line under the table. It states "Latest 2,000 of
   39,905 recorded", which is the scope disclosure, so it reads at the base
   size and in ink, not as a footnote. */
:root:root body #tape .tw-ts { font-size: 13px; line-height: 1.5; color: var(--ink3, #9b8e82); }


/* ──────────────────────────────────────────────────────────────────────────
   2. PREMIUM. EMPTY MUST NOT LOOK LIKE LOADING.

   premium.js has four distinct states (1251, 1256, 1291, 1300) and one of
   them draws .mn-gap-ours. Those states are correct and nothing below changes
   which one renders or what it says.

   MEASURED: #premium-root is height:auto, so the three non-chart states
   collapse the panel to the height of their own paragraph while the loading
   state collapses to the same place. A reader cannot tell a section that has
   nothing to show from one that has not answered yet, which is the one thing
   Paradex gets right by holding an empty book at full height.

   So the section keeps a floor. A state that fills it pushes past the floor
   and nothing moves; a state that does not fill it now sits in a panel that
   is obviously a panel, at the same height the answer would have occupied. */
:root:root body #premium-root {
  min-height: 62vh;
}

/* Loading and empty are then told apart by colour and position, not by size.
   .pm-wait is the pending state: it is muted and it sits in the middle of the
   floor, so it reads as "not yet" rather than as "nothing". */
:root:root body #premium-root .pm-wait {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 46vh;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink3, #9b8e82);
}

/* The gap rule is the error state's own mark. It carries "no fill feed, our
   gap" and "not read, our gap, not their silence", which are the brand, so it
   is given room rather than compressed. Dashed rule and accent kept. */
:root:root body #premium-root .mn-gap-ours {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink3, #9b8e82);
}

/* The section head. --t-lg moved 20 to 26, and at 26px a heading set on a
   1.55 body leading floats away from the sentence it introduces. Headings run
   1.2 in openai-scale.css already; this pins the space below it instead of
   the leading inside it. */
:root:root body #premium-root .tl-sec-h {
  margin-bottom: 14px;
}

/* The two label lines that sit under a KPI figure. VERIFIED, not assumed:
   .pm-kpi-u is the unit line (premium.js:1183, it prints o.unit) and
   .pm-kpi-say is its sibling. The "premium is a lower bound" sentence itself
   is NOT in either of them, it is built at premium.js:1370 and 1621 and is
   left completely alone. What these two get is only size: against a 26px
   figure they were reading as footnotes to a number they actually qualify. */
:root:root body #premium-root .pm-kpi-u,
:root:root body #premium-root .pm-kpi-say {
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink3, #9b8e82);
  margin-top: 10px;
}

/* The venue split under the figure, "3 of 11" and the per venue rows. Numbers
   in a column only read as a column if the glyphs are one width. */
:root:root body #premium-root .pm-sr,
:root:root body #premium-root .pm-sr-table,
:root:root body #premium-root .pm-sr-table td,
:root:root body #premium-root .pm-sr-table th {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* MEASURED: .pm-sr-table right edge is 2302px inside a 1440px viewport. The
   document does not scroll sideways, so the table is inside a scroller and
   the overflow is by design. Left alone. What is fixed is the row leading,
   which at 1.55 on a table of figures pushes the split off the fold. */
:root:root body #premium-root .pm-sr-table td,
:root:root body #premium-root .pm-sr-table th {
  line-height: 1.35;
}


/* ──────────────────────────────────────────────────────────────────────────
   3. FLOW. THE MATRIX HEAD LEFT A DEAD BAND.

   MEASURED at 1440 wide, tab [5]: the "PREMIUM WE SAW 20" head sits at y=308
   and the first asset row at y=444. 136px of that is the rotated venue column
   block plus its margins, and 47px of it is dead air between the head and the
   labels. The labels are 62px tall by tools.css:2036 and need every pixel of
   it ("Rysk V12" is the longest), so the fix is the air around them, never
   their box.

   tools.css:2037 is not touched: the 10px literal on a rotated label is
   deliberate and commented as such at its own site.

   NOT FIXED, AND DELIBERATELY SO. Closing the 47px would take a negative
   margin on .mx-head-row, and every render after this file landed came back
   with Flow in its loading state ("READING THE BOARD"), so the matrix was
   never on screen to check the nudge against. tools.css:2032 already sets
   padding 0 on the top of that row, which means the air is coming from
   something above it that was not measured. A negative margin pushed in blind
   would sit the rotated venue names on top of the "premium we saw" line, and
   a void is a smaller defect than an overlap. Left for a run that can render
   the matrix. The rule below is the only spacing this file touches there, and
   it is additive, so it cannot cause a collision. */
:root:root body .mx-head-row {
  padding-bottom: 6px;
}

/* CORRECTED AFTER VERIFYING THE CLASS NAMES AGAINST tools.css. A first pass
   here targeted .mx-legend, .mx-val, .mx-pct, .mx-asset, .mx-wrap and
   .mx-body. NONE OF THOSE EXIST: grep over tools.css and tools.js returns 0
   for all six. They were guessed from the screenshot and they would have been
   six dead selectors claiming a repair that never landed. The real matrix
   classes are mx-band, mx-band-h, mx-bar, mx-c, mx-cells, mx-head-row,
   mx-heads, mx-k, mx-key, mx-na, mx-read, mx-row, mx-rows, mx-s, mx-sw, mx-v.
   Only the verified ones are used below. */

/* .mx-key is the epistemic key for the whole view. It carries "traded, we saw
   it", "listed, nothing traded", "no feed, we cannot say" and "not listed
   there" (tools.js:2281), four states a reader has to hold while scanning.
   Against 14px data it had become the smallest thing on a page it governs, so
   it keeps the micro size but gains leading and tracking to read as a key. */
:root:root body .mx-key,
:root:root body .mx-k {
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .04em;
  color: var(--ink3, #9b8e82);
}

/* Flow's rows are a ranked list of figures. A ranking whose digits are not
   one width is a list, not a ranking. .mx-v is the value cell, .mx-row the
   band that holds it. */
:root:root body .mx-row,
:root:root body .mx-v,
:root:root body .mx-s {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* .mx-na is the "not listed there" cell and .mx-read the "no feed" one. Both
   are absences, and an absence has to be as legible as a number or the reader
   scores it as a zero. Colour only, no new mark. */
:root:root body .mx-na,
:root:root body .mx-read { color: var(--ink3, #9b8e82); }

/* ──────────────────────────────────────────────────────────────────────────
   4. PHONE, 390 WIDE. The type jump is a 17% linear growth on the base and a
   30% growth on --t-lg, and neither was checked against the narrow viewport.
   What this block fixes is the 26px heading, which is the only thing on these
   three views wide enough to force a sideways scroll in a 390px column.

   THE TAPE AT 390 IS A SEPARATE, UNRESOLVED DEFECT and it is written up in
   section 6 rather than patched blind here. */
@media (max-width: 480px) {
  /* The heading is the only 26px thing on the page and at 390 it is the only
     thing that can force a sideways scroll. 22px still reads as the heading
     and fits the column. */
  :root:root body #premium-root .tl-sec-h { font-size: 22px; line-height: 1.2; }

  /* The floor is a fraction of a much shorter viewport on a phone, so it is
     given a smaller share: still unmistakably a held panel, not a screen and
     a half of nothing. */
  :root:root body #premium-root { min-height: 48vh; }
  :root:root body #premium-root .pm-wait { min-height: 34vh; }
}


/* ──────────────────────────────────────────────────────────────────────────
   5. TRADES, THE ACTUAL CAUSE OF THE OVERLAP. Found by re-measuring after the
   type fix above landed, because the rows still spilled at 13px.

   MEASURED, first visible row, after section 1:

     .tw-row   h 28    grid
     .tw-c     h 27    flex column
     .tw-b     h 27    flex column, justify-content center, GAP 6px
       .p      h 14.3
       .s      h 13.1

   14.3 + 6 + 13.1 = 33.4px of stack inside a 27px button that centres it, so
   it overflows 3.2px off each end and paints into the row above and the row
   below. The type was never the whole story: SIX PIXELS OF FLEX GAP were.
   A 6px gap is right on a card and wrong inside a 28px tape row, where the
   two lines are one reading, not two.

   Gap to zero, and .p takes 1.05 leading so the pair clears the box:

     13 x 1.05 = 13.65
             +   13.10
             =   26.75px inside 27px. Nothing spills.

   One declaration each, both type or spacing, neither forces a paint. */
:root:root body .tw-row .tw-b {
  gap: 0 !important;
  font-size: 13px !important;
}
:root:root body .tw-row .p { line-height: 1.05 !important; }

/* THEME NOTE, measured. A render at 1440 came back in the light theme, which
   the surface supports. The four colours above are therefore written as
   var(--ink3, #9b8e82) and var(--ink, #f8f4f0): the token resolves per theme
   and the brand hex is the fallback, so nothing is a hardcoded dark-only ink
   that would paint near-white text onto a near-white page. */


/* ──────────────────────────────────────────────────────────────────────────
   6. TRADES AT 390. WHAT WAS MEASURED, AND WHAT THE MEASUREMENT TURNED OUT
      NOT TO MEAN.

   A first probe at 390 returned 240 "spilling" nodes over 60 rows and it was
   nearly written up here as a phone-only collision. It is not one. Re-read
   with the same run's per-node numbers:

     390 wide, first row:  .tw-row 13px, h 28, .tw-b gap 0px
                           .p  h 14.3, offset -0.2px from the row top
                           .s  h 13.1, offset -0.8px from the row bottom
                           .p  text "bought the upside", width 94px, NO wrap

   Both lines sit inside the row, the gap fix has landed, and nothing wraps.
   The 240 count came from a probe that compared every node against its own
   row inside a scroll container, and its worst case was 2,275px, which is not
   an overlap, it is a row far below the fold. THE ERROR WAS IN THE READING,
   NOT IN THE PAGE. Recorded here so the next person does not chase it.

   WHAT IS GENUINELY UNVERIFIED AT 390: the pixels. The 390 render puts the
   tape below the fold behind the onboarding card, so the phone tape has never
   been READ as an image, only measured. The numbers above are good and the
   picture is outstanding. */
