
/* ============================================================================
   v4.4 DESIGN SYSTEM — the token layer.
   The rule that governs every choice below: this is a professional trading
   instrument, not a consumer dashboard. Concretely that means depth comes from
   surface value, not from drawing another border; radii are small enough to
   read as a tool; the accent is reserved for things you can act on; and every
   figure on the screen is monospaced and tabular so columns of numbers line up
   on the decimal without anyone having to think about it.
   ========================================================================= */
:root{
/* --- surfaces: a real elevation ladder, each step a small lightness delta --- */
--bg:#090b0f;--sunk:#06080b;--panel:#11141a;--panel2:#171b23;--panel3:#1e232c;
--line:#222833;--line2:#2e3542;--linesoft:#1a1f27;
--fg:#e9edf3;--fg2:#c2cad6;--dim:#8b95a5;--faint:#5d6674;
/* --- semantics: money colours are deliberately not the accent -------------- */
--green:#2fb85f;--amber:#e0a325;--red:#f05252;--grey:#6e7681;--blue:#4c8dff;--accent:#4c8dff;
--violet:#a279f5;--teal:#2bb3ae;
--green-soft:color-mix(in srgb,var(--green) 13%,transparent);
--red-soft:color-mix(in srgb,var(--red) 13%,transparent);
--amber-soft:color-mix(in srgb,var(--amber) 13%,transparent);
--accent-soft:color-mix(in srgb,var(--accent) 13%,transparent);
/* --- elevation ------------------------------------------------------------- */
--shadow:0 1px 2px rgba(0,0,0,.34),0 4px 14px rgba(0,0,0,.22);
--shadow-lg:0 2px 4px rgba(0,0,0,.32),0 16px 44px rgba(0,0,0,.42);
--shadow-inset:inset 0 1px 0 rgba(255,255,255,.028);
/* --- geometry: a 4px rhythm, and radii small enough to read as a tool -------
   v5.0 point 7, "add more spacing between sections": the two step sizes that separate one thing
   from the next thing (s4 upward) all open by roughly a quarter, while s1–s3 — the distances
   INSIDE a component, where tightening is what makes a number read as belonging to its label —
   are left exactly where they were. Rooms get bigger; furniture does not drift apart. */
--radius:10px;--radius-sm:7px;--radius-lg:13px;--radius-pill:999px;
--s1:4px;--s2:8px;--s3:12px;--s4:20px;--s5:24px;--s6:32px;--s7:44px;
/* --- type ------------------------------------------------------------------
   v5.0 points 1 and 2. Reading text goes up (base 13.5 -> 15, and every hardcoded size in this
   stylesheet moved with it), because the owner reads this page on a laptop at arm's length and
   not through a Bloomberg terminal's face. The display sizes come DOWN a step, because when
   every metric on the screen is 28px none of them is the important one — 3xl is now reserved
   for the single hero figure on a page and 2xl for the handful that answer "how am I doing".  */
--mono:"SF Mono",ui-monospace,SFMono-Regular,"JetBrains Mono",Menlo,Consolas,monospace;
--sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
   v5.6 — the scale was declared in v5.0 and then ignored: 559 raw pixel sizes across 22 view files,
   thirty distinct values, nine of which differed from the nearest token by less than half a pixel.
   Thirty sizes is not a scale, it is thirty separate opinions about how big a label should be, and
   the reason a page looks amateur is almost never one bad size — it is six sizes where a reader
   expects two. Every raw size in every view now names one of these ten tokens, and a test fails the
   next one that does not.

   --t-nano is the tenth, added in v5.6 rather than pretending the scale already covered its cases.
   Six sites sat below micro: the sort arrows in a table head, three uppercase micro-badges, and the
   phone nav labels, which had come DOWN to 10.5px on purpose so six of them would not wrap onto two
   lines. Snapping those up to 11.5px would have undone a deliberate fix and wrapped the phone bar.
   A caps tier below the body-micro tier is ordinary typography; two of them (9.5 and 10.5) written
   by different hands for the same badge was not, and both collapse here. */
--t-nano:10.5px;
--t-micro:11.5px;--t-label:12px;--t-sm:13.5px;--t-base:15px;--t-md:16.5px;
--t-lg:20px;--t-xl:23px;--t-2xl:27px;--t-3xl:35px;
--lbl:700 var(--t-label)/1.3 var(--sans);
--tight:-.012em;--wide:.055em}
html.light{
--bg:#eef1f6;--sunk:#e4e9f0;--panel:#ffffff;--panel2:#f4f6fa;--panel3:#eaeef4;
--line:#dde3ec;--line2:#c8d1de;--linesoft:#e8ecf2;
--fg:#0f1620;--fg2:#3b4655;--dim:#5c6775;--faint:#8b95a5;
--green:#137a3c;--amber:#8a5d00;--red:#c9252d;--grey:#6e7781;--blue:#0a5fd6;--accent:#0a5fd6;
--violet:#6d3fd4;--teal:#0f7a76;
--shadow:0 1px 2px rgba(16,24,40,.07),0 4px 14px rgba(16,24,40,.06);
--shadow-lg:0 2px 6px rgba(16,24,40,.08),0 18px 44px rgba(16,24,40,.14);
--shadow-inset:inset 0 1px 0 rgba(255,255,255,.7)}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);font:var(--t-base)/1.5 var(--sans);
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
font-feature-settings:"cv05" 1,"ss01" 1;text-rendering:optimizeLegibility}
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
::-webkit-scrollbar{height:9px;width:9px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line2);border-radius:var(--radius-pill);border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--faint);background-clip:content-box}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--radius-sm)}
/* The chrome is a single continuous surface from the top of the window down to the first
   content row: header, ticker and alert bar all sit on --panel with hairline dividers, so
   the eye reads one instrument bezel instead of three stacked bars. */
header{position:sticky;top:0;z-index:20;background:color-mix(in srgb,var(--panel) 88%,transparent);backdrop-filter:blur(14px) saturate(1.4);
border-bottom:1px solid var(--line);padding:0 var(--s4);height:52px;display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
header .brand{font-weight:700;letter-spacing:var(--tight);font-size:var(--t-md);color:var(--fg)}
/* v6.37.0 — the brand is a link now. It keeps the brand's own colour rather than the link colour,
   because a masthead that turns accent-coloured reads as a nav item rather than as the title. */
header a.brand{text-decoration:none}
header a.brand:hover{opacity:.85}
/* v6.38.0 — the top bar carries STATUS now, not navigation, so it says which section you are in
   rather than offering all five. Where you GO is the rail; what you are LOOKING AT is this. */
header .secname{font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);color:var(--dim);
  padding-left:var(--s3);border-left:1px solid var(--line);margin-left:var(--s2)}
@media(max-width:700px){header .secname{display:none}}
/* ============================================================================
   v6.38.0 — THE APP FRAME. Stage 1 of docs/platform.md.
   ============================================================================
   The owner put this beside tastytrade and ThinkorSwim: "this looks NOTHING like
   tastytrade or thinkorswim… Even the menu system sucks."

   He is right and the reason is not styling. This was a set of PAGES with a top
   menu; those are WORKSPACES with a permanent rail. A top bar with hover pop-outs
   is a website pattern — it asks you to LEAVE where you are in order to get
   somewhere else. A platform never moves you; it changes what is in a panel.

   So: a permanent icon rail down the left, an account bar that never moves, and
   the existing pages rendering unchanged inside the workspace. NOTHING in any
   page was rewritten for this — the chrome changed and the pages became its
   content, which is the whole reason this stage is the safe one to do first.

   The pop-outs are GONE rather than reduced. Everything they reached is in the
   section bar at the top of the workspace, which already listed every page in
   the group including the ones the pop-out filed under "more", and ⌘K still
   finds all of them by name. */
.applayout{display:flex;min-height:60vh;align-items:stretch}
/* v6.38.1 — THE DEAD GUTTER. (No backticks in this comment: the whole stylesheet is a template
   literal and one would end it. That has broken this file before.)
   main carries width:94%, max-width:1500px and margin:0 auto from when it was the only thing on the
   page. Inside a flex row those auto margins CENTRE it in the space left over beside the rail, which
   on a wide monitor put several hundred pixels of nothing between the rail and the content and made
   the rail look detached from the page it navigates.
   Left-aligned against the rail instead, and given more room: a workspace fills its window. The
   measure is still capped, because a card grid stretched across 2500px is sparse rather than dense,
   which is the mistake v6.32.0 fixed in the other direction. */
/* Fills the workspace. Capping it at 1680 moved the dead space from the left of the content to
   the right of it rather than removing it, and a platform fills its window. The card grids are
   auto-fit minmax(), so extra width becomes another COLUMN rather than wider cards — which is
   density, and is the behaviour v6.32.0 was reaching for when it capped the measure instead. */
.applayout>main{margin:0;width:auto;flex:1 1 auto;min-width:0;max-width:none}
.applayout>main.wide{max-width:none}
/* The rail scrolls VERTICALLY, so it deliberately does NOT hide its scrollbar: the app's edge-cue
   technique draws a horizontal fade and would be the wrong signal here. With six destinations it
   never overflows in practice, and on the day it does, a scrollbar is the honest thing to show. */
.navrail{flex:none;width:80px;background:var(--panel);border-right:1px solid var(--line);
  display:flex;flex-direction:column;gap:2px;padding:8px 6px;position:sticky;top:0;
  height:100vh;overflow-y:auto}
.navrail a{display:flex;flex-direction:column;align-items:center;gap:3px;padding:9px 2px;border-radius:10px;
  color:var(--dim);text-decoration:none;font-size:var(--t-nano);font-weight:600;text-align:center;
  line-height:1.15;transition:background .13s ease,color .13s ease;overflow:hidden}
/* v6.38.1 — the label is constrained to the rail rather than allowed to overflow it.
   "Portfolio" is wider than the icon it sits under, and an unconstrained centred span overflows
   BOTH sides — so on the live page the P was being clipped by the left edge of the window. */
.navrail a>span{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.navrail a:hover{background:color-mix(in srgb,var(--panel2) 80%,transparent);color:var(--fg2)}
.navrail a.on{background:var(--panel2);color:var(--fg)}
/* The accent edge is the only thing on the rail allowed a colour, so "where am I" is answerable
   from the corner of the eye rather than by reading six labels. */
.navrail a.on::before{content:'';position:absolute;left:0;width:3px;height:26px;border-radius:0 3px 3px 0;
  background:var(--accent)}
.navrail a{position:relative}
.navrail .nicon{width:21px;height:21px;display:block}
.navrail .rsep{flex:1}
/* The account bar. Permanent, because on a platform the money is not something you navigate to. */
/* Padded to the same gutter as the header above it, so the first figure is not flush against the
   window edge — on the live page the A of ACCOUNT was touching x=0. */
.acctbar{display:flex;align-items:stretch;gap:0;background:var(--sunk);border-bottom:1px solid var(--line);
  overflow-x:auto;scrollbar-width:none;padding-left:var(--s4)}
.acctbar::-webkit-scrollbar{display:none}
.acctbar .ac{padding:5px 13px;border-right:1px solid var(--linesoft);white-space:nowrap;flex:none}
.acctbar .ac .k{font-size:var(--t-nano);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);display:block;font-weight:700}
.acctbar .ac .v{font-family:var(--mono);font-size:var(--t-sm);font-variant-numeric:tabular-nums;
  letter-spacing:var(--tight);display:block}
.acctbar .pos{color:var(--green)}.acctbar .neg{color:var(--red)}
.acctbar .grow{flex:1 1 auto;min-width:0;border-right:none}
/* v6.40.0 — the two figures stage 1 could not afford. They arrive after the page has painted, from
   /api/frame, so a dash here means "not back yet" as well as "could not be read" — and both of
   those are better than a page that waits on a chain read before it draws anything. */
.acctbar .ac.late .v{color:var(--dim)}
/* ============================================================================
   v6.59.0 — THE STANDING ASK.
   ============================================================================
   The owner: "when it proposes a ticket of ANY type it should be alerting me on
   my desktop until I clear it."

   So this bar is NOT dismissible, on purpose. Every other banner in this app can
   be closed because every other banner is information; this one is the only one
   that means a decision is sitting unmade, and a close button on it would make it
   the same as the others. It leaves when the ticket is actioned and at no other
   time.

   Fixed to the top of the viewport rather than in the document, because the
   request was "until I clear it" and a banner you can scroll past is cleared by
   scrolling. It pushes the page down by its own height so it never covers
   content — a bar that hides the thing it is telling you to go and look at
   would be worse than no bar. */
.askbar{position:fixed;top:0;left:0;right:0;z-index:900;
  background:color-mix(in srgb,var(--amber) 22%,var(--panel));
  border-bottom:2px solid var(--amber);
  padding:9px var(--s4);display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap}
.askbar b{font-size:var(--t-md)}
.askbar .lbl{font-family:var(--mono);font-size:var(--t-sm)}
.askbar .grow{flex:1 1 auto}
.askbar a.go{background:var(--amber);color:var(--bg);padding:5px 13px;border-radius:var(--radius-sm);
  font-weight:700;text-decoration:none;font-size:var(--t-sm);white-space:nowrap}
.askbar button.perm{background:transparent;border:1px solid var(--amber);color:var(--fg);
  padding:4px 10px;border-radius:var(--radius-sm);font-size:var(--t-label);cursor:pointer}
html.has-ask body{padding-top:52px}
@media(max-width:700px){html.has-ask body{padding-top:78px}}
/* ============================================================================
   v6.40.0 — THE SYMBOL CONTEXT. Stage 2 of docs/platform.md.
   ============================================================================
   What makes this a platform rather than a site is that a symbol is selected and
   everything on screen can be about it. The panel is the visible half; the
   mechanism is that the selection lives in the BROWSER and no page knows about
   it, which is why stage 2 changed no page either.

   It is the third column of the workspace and it is the first thing to go when
   the window narrows: below 1200px a third column would squeeze the content to
   nothing, and everything in here has a page of its own to be read on. */
.ctxpanel{flex:none;width:330px;background:var(--panel);border-left:1px solid var(--line);
  position:sticky;top:0;height:100vh;overflow-y:auto;padding:var(--s3);
  display:flex;flex-direction:column;gap:var(--s3)}
html.ctxoff .ctxpanel{display:none}
.ctxpanel .cxhd{display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap}
.ctxpanel .cxsym{font-weight:750;font-size:var(--t-lg);letter-spacing:var(--tight);color:var(--fg)}
.ctxpanel .cxpx{font-family:var(--mono);font-size:var(--t-lg);font-variant-numeric:tabular-nums;
  letter-spacing:var(--tight);margin-left:auto}
.ctxpanel .cxch{font-family:var(--mono);font-size:var(--t-sm);font-variant-numeric:tabular-nums;width:100%;
  text-align:right}
.ctxpanel .cxsrc{font-size:var(--t-nano);color:var(--faint);width:100%;text-align:right}
.ctxpanel .cxsec{border-top:1px solid var(--linesoft);padding-top:var(--s2)}
.ctxpanel .cxsec>h4{font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);margin:0 0 var(--s2)}
.ctxpanel .cxrow{display:flex;justify-content:space-between;gap:var(--s2);
  font-size:var(--t-sm);padding:2px 0;line-height:1.45}
.ctxpanel .cxrow .k{color:var(--dim);min-width:0}
.ctxpanel .cxrow .v{font-family:var(--mono);font-variant-numeric:tabular-nums;
  white-space:nowrap;color:var(--fg2)}
.ctxpanel .cxnone{font-size:var(--t-sm);color:var(--faint);line-height:1.5}
.ctxpanel .cxttl{font-size:var(--t-sm);font-weight:600;color:var(--fg);margin-bottom:2px}
.ctxpanel .cxsub{font-size:var(--t-micro);color:var(--dim);line-height:1.45;margin-bottom:var(--s2)}
.ctxpanel .cxitem{padding:var(--s2) 0;border-bottom:1px solid var(--linesoft)}
.ctxpanel .cxitem:last-child{border-bottom:none}
.ctxpanel .pos{color:var(--green)}.ctxpanel .neg{color:var(--red)}
.ctxpanel .cxlink{display:block;font-size:var(--t-micro);color:var(--accent);margin-top:var(--s1)}
/* v6.40.1 — A BOX TO TYPE A SYMBOL INTO, which the owner asked for and was right to.
   The ⌘K argument — one input, no second navigation — holds for NAVIGATION. This is not
   navigation: it is a field on a panel that does exactly one thing to that panel, and every
   trading platform in existence has one because reaching for a palette to change the subject of
   what you are already looking at is a keystroke too many. */
.ctxpanel .cxfind{display:flex;gap:var(--s1)}
.ctxpanel .cxfind input{flex:1 1 auto;min-width:0;background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:5px 9px;color:var(--fg);font-family:var(--mono);
  font-size:var(--t-sm);letter-spacing:var(--wide);text-transform:uppercase}
.ctxpanel .cxfind input:focus{outline:none;border-color:var(--accent)}
.ctxpanel .cxfind input::placeholder{color:var(--faint);letter-spacing:normal;text-transform:none}
.ctxpanel .cxfind button{flex:none;background:var(--panel2);border:1px solid var(--line);
  border-radius:var(--radius-sm);color:var(--dim);padding:5px 11px;cursor:pointer}
.ctxpanel .cxfind button:hover{color:var(--fg);border-color:var(--accent)}
/* The selected symbol, in the one bar that is on every page. It is a button and not a link: it
   changes what the frame is about, it does not take you anywhere. */
header .symchip{display:inline-flex;align-items:center;gap:var(--s2);background:var(--panel2);
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:3px 10px;cursor:pointer;
  color:var(--fg);font-family:var(--sans);font-weight:700;font-size:var(--t-sm);
  letter-spacing:var(--tight);margin-left:var(--s3)}
header .symchip:hover{border-color:var(--accent);color:var(--fg)}
header .symchip .sq{font-family:var(--mono);font-weight:500;color:var(--dim);
  font-variant-numeric:tabular-nums}
/* v6.40.1 — the caret. Without it this read as a label rather than a control, and the owner tried
   to click into it as though it were a text field. It is a button; now it looks like one. */
header .symchip .cv{color:var(--faint);font-size:var(--t-nano);margin-left:2px}
/* Anything anywhere in the app carrying data-ccsym selects that symbol when clicked. The ticker is
   the first taker; every page becomes symbol-aware by adding the attribute, not by being rewritten. */
[data-ccsym]{cursor:pointer}
/* ============================================================================
   v6.42.0 — THE STRIKE LADDER. Stage 3 of docs/platform.md.
   ============================================================================
   The rows the rulebook would sell are the ones that read normally. Everything
   else is dimmed and carries its reason in the last column instead of a button.
   That is the whole visual argument of the page: on forty strikes, the eye
   should land on the four that are actually available without reading a word. */
.chainhd{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s3)}
.chainsym{font-weight:750;font-size:var(--t-lg);letter-spacing:var(--tight)}
.chainmeta{color:var(--dim);font-size:var(--t-sm);flex:1 1 auto;min-width:0}
.chaintbl tr.ch-no td{color:var(--faint)}
.chaintbl tr.ch-ok td{color:var(--fg2)}
.chaintbl tr.ch-ok{background:color-mix(in srgb,var(--green) 5%,transparent)}
/* Where the money is. A single line, because the ladder is read by distance from it. */
.chaintbl tr.ch-atm td{border-top:1px solid var(--amber)}
.chaintbl .ch-why{font-size:var(--t-micro);line-height:1.4}
/* The accent is reserved for things you can act on — token layer, v4.4 — and on this page the
   things you can act on are exactly the strikes the rulebook would sell. */
.chaintbl .sellbtn{background:var(--accent-soft);border:1px solid var(--accent);color:var(--fg);
  border-radius:var(--radius-sm);padding:4px 11px;font-size:var(--t-micro);white-space:nowrap}
.chaintbl .sellbtn:hover{background:var(--accent);color:#08121f}
/* v6.42.1 — the scanner's live decision feed. Capped and scrolling: forty names is more than a
   progress area should ever grow to, and the interesting end is the top. */
.scnfeed{margin-top:var(--s2);max-height:190px;overflow-y:auto;border-top:1px solid var(--linesoft)}
.scnfeed-i{font-size:var(--t-micro);color:var(--dim);padding:3px 0;border-bottom:1px solid var(--linesoft);
  line-height:1.45}
.scnfeed-i:last-child{border-bottom:none}
/* ============================================================================
   v6.43.0 — THE CHART. Stage 4 of docs/platform.md.
   ============================================================================
   Hand-drawn SVG. The candles are deliberately quiet and the OVERLAYS carry the
   colour, because the candles are the part every chart in the world has and the
   overlays are the part only this application can draw. */
.chtsvg{width:100%;height:auto;display:block}
.chtgrid{stroke:var(--linesoft);stroke-width:1}
.chtax{fill:var(--faint);font-size:var(--t-nano);font-family:var(--mono)}
.chtw{stroke-width:1}
.chtw.up,.chtb.up{stroke:var(--green)}
.chtw.dn,.chtb.dn{stroke:var(--red)}
.chtb.up{fill:color-mix(in srgb,var(--green) 55%,transparent)}
.chtb.dn{fill:color-mix(in srgb,var(--red) 55%,transparent)}
/* A level is a fact about the position, so it is drawn solid and full width. */
.chtline{stroke-width:1.2;stroke-dasharray:5 4;opacity:.9}
.chtlt{font-size:var(--t-nano);font-family:var(--mono);font-weight:600}
/* A date is a fact about the calendar. Dotted, so it reads as a different KIND of thing. */
.chtmark{stroke:var(--line2);stroke-width:1;stroke-dasharray:2 4}
.chtmark-manage{stroke:var(--amber)}
.chtmark-expiry{stroke:var(--violet)}
.chtmarkt{fill:var(--dim);font-size:var(--t-nano);font-family:var(--mono)}
.chtkey{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);margin-top:var(--s2);
  padding-top:var(--s2);border-top:1px solid var(--linesoft)}
.chtkey .chtk{display:inline-flex;align-items:center;gap:5px;font-size:var(--t-micro);color:var(--dim)}
.chtkey .chtk i{width:13px;height:2px;border-radius:2px;display:inline-block}
.chtkey .chtk i.dash{background:repeating-linear-gradient(90deg,var(--dim) 0 3px,transparent 3px 6px)}
/* ============================================================================
   v6.50.0 — THE MANUAL SCREENER FORM.
   ============================================================================
   A grid of small labelled fields rather than a long column of them: these are
   read as PAIRS — price from/to, delta from/to, days from/to — and a single
   column makes the reader hold the first half in their head. */
.scrform{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));
  gap:var(--s3);align-items:end}
.scrform label{display:flex;flex-direction:column;gap:3px;min-width:0}
.scrform label>span:first-child{font:var(--lbl);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--dim)}
.scrform .scrwide{grid-column:1/-1}
.scrform .scrhint{font-size:var(--t-nano);color:var(--faint);line-height:1.4}
.scrform .scrcheck{flex-direction:row;flex-wrap:wrap;align-items:baseline;gap:var(--s2)}
.scrform .scrcheck input{flex:none;width:auto}
.scrform .scrcheck>span:first-of-type{text-transform:none;font:inherit;color:var(--fg2)}
/* A row the rulebook would not take is dimmed and carries its reasons instead of a button —
   the same treatment a refused strike gets on the chain ladder, for the same reason. */
tr.scrno td{color:var(--faint)}
.scrwhy{font-size:var(--t-micro);line-height:1.4;color:var(--dim)}
/* ============================================================================
   v6.44.0 — THE AGENT, MADE VISIBLE. Stage 6 of docs/platform.md.
   ============================================================================
   The feed is deliberately quiet — one dot, one time, one sentence. It is meant
   to be scanned down the left edge for the coloured dot that is not green, which
   is the only reason to look at a feed at all. */
.agrow{display:flex;gap:var(--s3);padding:3px 0;font-size:var(--t-sm);line-height:1.5}
.agrow .k{color:var(--dim);flex:none;min-width:118px}
.agrow .v{color:var(--fg2);min-width:0}
.agwait{margin:0;padding-left:18px}
.agwait li{font-size:var(--t-sm);line-height:1.6;color:var(--fg2);padding:2px 0}
.agfeed{display:flex;flex-direction:column;max-height:420px;overflow-y:auto}
.agi{display:flex;align-items:baseline;gap:var(--s2);padding:4px 0;
  border-bottom:1px solid var(--linesoft);text-decoration:none;color:inherit}
.agi:last-child{border-bottom:none}
a.agi:hover{background:color-mix(in srgb,var(--panel2) 60%,transparent);text-decoration:none}
.agdot{flex:none;width:7px;height:7px;border-radius:99px;background:currentColor;
  align-self:center}
.agi .agt{flex:none;font-family:var(--mono);font-size:var(--t-nano);color:var(--faint);
  font-variant-numeric:tabular-nums}
.agi .agx{font-size:var(--t-micro);color:var(--fg2);line-height:1.45;min-width:0}
/* A refused name is still a name: clicking it puts it in the side panel, which is usually the very
   next thing you want after reading why it was turned down. */
.agsym{font-family:var(--mono);font-size:var(--t-nano);color:var(--dim);
  border:1px solid var(--linesoft);border-radius:var(--radius-sm);padding:1px 5px;margin-right:2px;
  display:inline-block}
.agsym:hover{color:var(--fg);border-color:var(--accent)}
.chaintbl .chiplet{font-size:var(--t-nano);color:var(--amber);text-transform:uppercase;
  letter-spacing:var(--wide);font-weight:700}
@media(max-width:1200px){.ctxpanel{display:none}}
@media(max-width:900px){
  /* The rail becomes the bottom bar that already existed for phones. One navigation, two shapes. */
  .navrail{display:none}
  .applayout{display:block;min-height:0}
  .acctbar .ac{padding:4px 10px}
}
nav{display:flex;gap:2px;flex-wrap:wrap}
nav a{color:var(--dim);padding:6px 11px;border-radius:var(--radius-sm);font-weight:600;font-size:var(--t-sm);
letter-spacing:.005em;transition:background .13s ease,color .13s ease;position:relative}
nav a:hover{color:var(--fg2);text-decoration:none;background:color-mix(in srgb,var(--panel2) 70%,transparent)}
nav a.on{color:var(--fg);background:var(--panel2);box-shadow:none}
/* v5.6 — the current-section underline. It is on ::before, and that is not a stylistic preference.
   Five of the six top-level destinations are groups, and a group tab draws a dropdown caret with
   element, and the caret rule is (0,2,2) against this one's (0,1,3) — so on the active tab, which is
   a group tab on five pages out of six, the caret won the size and the shape while this rule still
   supplied the position and the colour. The result was neither thing: no underline anywhere, no
   caret beside the label, and a 4px blue diamond floating fifteen pixels below the tab in empty
   space, which is exactly what a rendering fault looks like. A pseudo-element is a single slot and
   two independent decorations cannot share one. Absolute positioning means moving to ::before costs
   nothing in layout or in source order. */
nav a.on::before{content:'';position:absolute;left:11px;right:11px;bottom:-15px;height:2px;border-radius:2px;background:var(--accent)}
.spacer{flex:1}
/* The header's status cluster; the long note beside the markup says why it is grouped at all.
   The flex values are the whole of the behaviour and they are not interchangeable. A flex line
   breaks BEFORE anything on it shrinks, so 0 1 auto gives three outcomes in the right order: it
   sits on the nav row while the nav row has 504px to spare, it takes a whole row of its own intact
   the moment it does not, and only on a phone — where a row of its own is still too narrow — does it
   shrink and wrap inside itself. Writing this as flex:none instead, which is what it said for about
   ten minutes, is the same defect this release fixed on the drawer labels: an item that may not
   shrink does not stay inside its container, it leaves. Measured at 390px it hung 98px off the right
   edge of the phone, with the clip on main guaranteeing nobody could scroll across to find it.
   margin-left:auto keeps it against the right edge on whichever row it lands on, so it never slides
   under the brand; justify-content matches for the phone case, where it is the wrapped rows inside
   that need aligning rather than the box itself. */
.hdrtools{display:flex;align-items:center;justify-content:flex-end;gap:var(--s3);
flex:0 1 auto;min-width:0;flex-wrap:wrap;margin-left:auto}
/* Below 700px the nav is gone from the header entirely, so there is no orphan to prevent and the
   grouping only costs. Measured at 390px it cost a whole row: the cluster reserved a line of its own
   and wrapped to two inside it, where ungrouped the chip had been sitting up beside the brand — a
   109px sticky header instead of 75px, on the screen that can least afford it. display:contents
   dissolves the box and hands the seven children straight back to the header, which is the exact
   layout the phone had before this rule existed. Grouping is a desktop answer; this is where it
   stops applying. */
@media(max-width:700px){.hdrtools{display:contents}}
/* v3.1 — market ticker strip (pro-terminal signature) */
.ticker{display:flex;overflow-x:auto;background:var(--sunk);border-bottom:1px solid var(--line);scrollbar-width:none}
.ticker::-webkit-scrollbar{display:none}
.ticker .tk{display:flex;align-items:center;gap:7px;padding:6px 14px;border-right:1px solid var(--linesoft);white-space:nowrap;font-size:var(--t-sm)}
.ticker .tk b{font-weight:700;letter-spacing:.02em;font-size:var(--t-label);text-transform:uppercase;color:var(--fg2)}
.ticker .tk.tk-pos b{color:var(--accent)}
.ticker .tk .px{font-family:var(--mono);color:var(--dim);font-variant-numeric:tabular-nums;letter-spacing:var(--tight)}
.ticker .tk .ch{font-family:var(--mono);font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:var(--tight)}
.clock{font-family:var(--mono);color:var(--dim);font-size:var(--t-sm);font-variant-numeric:tabular-nums;letter-spacing:var(--tight)}
.chip{display:inline-flex;align-items:center;gap:4px;padding:2px 9px;border-radius:var(--radius-pill);
font-size:var(--t-sm);font-weight:650;letter-spacing:.004em;border:1px solid var(--line2);
background:color-mix(in srgb,var(--panel2) 70%,transparent);white-space:nowrap;line-height:1.55}
/* A status chip that reads as a state machine value rather than prose: caps, mono, tracked out. */
.chip.st{font-family:var(--mono);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);font-weight:700;padding:2px 8px}
.c-green{color:var(--green);border-color:color-mix(in srgb,var(--green) 45%,transparent);background:color-mix(in srgb,var(--green) 12%,transparent)}
.c-amber{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 45%,transparent);background:color-mix(in srgb,var(--amber) 12%,transparent)}
.c-red{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent);background:color-mix(in srgb,var(--red) 12%,transparent)}
.c-blue{color:var(--blue);border-color:color-mix(in srgb,var(--blue) 45%,transparent);background:color-mix(in srgb,var(--blue) 12%,transparent)}
.c-grey{color:var(--dim)}
.alertbar{display:flex;gap:var(--s2);flex-wrap:wrap;padding:7px var(--s4);background:var(--panel2);border-bottom:1px solid var(--line)}
.alertbar a{font-size:var(--t-sm);font-weight:650;padding:3px 10px;border-radius:var(--radius-pill);border:1px solid;text-decoration:none}
.alertbar .red{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent);background:color-mix(in srgb,var(--red) 10%,transparent)}
.alertbar .amber{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 45%,transparent);background:color-mix(in srgb,var(--amber) 10%,transparent)}
.alertbar .clear{color:var(--green);border-color:color-mix(in srgb,var(--green) 45%,transparent);background:color-mix(in srgb,var(--green) 10%,transparent)}
/* overflow-x:clip, and specifically clip rather than hidden.
   A data-tip bubble is absolutely positioned inside its anchor, up to 260px wide, and it counts
   toward the page's scrollable width even while invisible. Anchor it to something narrow — a tile in
   a five-across grid collapsed to two columns on a phone — and the bubble sticks 33px past the right
   edge, so the whole page slides sideways under the thumb on a layout that otherwise fits. It looks
   like a broken page and it is invisible in a screenshot, which is why it survived this long.
   The word clip is load-bearing: hidden would force the vertical axis into a scroll container and
   break every sticky header on the site, while clip contains the horizontal axis and leaves the
   vertical one alone. */
/* v6.32.0 — 1800px was too wide, and the Desk is what proved it.
   A row of eight account figures stretched across 1800px is not dense, it is sparse: the eye has to
   travel the whole width to read numbers that belong together, and every card becomes a thin band
   with its content pushed to the edges. Density on a trading screen is not decoration — it is what
   lets you take in a position without moving your eyes.
   1500 is roughly the width the type scale was designed against, and it leaves the 1440 laptop —
   the commonest there is — using essentially the full window. */
main{padding:16px clamp(16px,2.4vw,32px);max-width:1500px;width:94%;margin:0 auto;overflow-x:clip}
@media(max-width:1100px){main{width:100%;padding:12px}}
hr.div{border:none;border-top:1px solid var(--line);margin:12px 0}
.panel-rows>div{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 55%,transparent)}
.panel-rows>div:last-child{border-bottom:none}
.grid{display:grid;gap:var(--s3)}.g2{grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr))}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s4);
box-shadow:var(--shadow),var(--shadow-inset)}
.card h2{margin:0 0 var(--s3);font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);color:var(--dim);
display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap;row-gap:3px}
/* v4.3 — in a narrow column the title used to break across two lines while the deep link kept
   its own corner, which left the header looking like two separate headers. Wrapping the whole
   row and letting the link fall to a line of its own keeps it readable at any column width. */
.card h2 .htext{white-space:nowrap}
.card h2::before{content:'';flex:none;width:3px;height:12px;border-radius:2px;background:var(--accent);opacity:.75;align-self:center}
/* v5.6 — a card's <h2> is the card's LABEL: small, uppercase, dim, with an accent tick. That is
   right for the ~60 cards that title themselves, and exactly wrong for the handful of places where
   the heading IS the finding — the Autopsy verdict was rendering the app's single most important
   sentence as dim uppercase chrome, because an inline font-size cannot override text-transform or
   colour. The .stmt class opts a heading out of the label treatment without opting it out of being a
   heading, so those places stop reaching for inline styles that only half-work. */
.card h2.stmt{font:750 var(--t-2xl)/1.2 var(--sans);text-transform:none;letter-spacing:-.01em;
color:var(--fg);margin:9px 0 0;display:block}
.card h2.stmt::before{display:none}
table{border-collapse:collapse;width:100%}
th{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint);text-align:left;
padding:var(--s2) 10px;border-bottom:1px solid var(--line);font-weight:700;white-space:nowrap}
td{padding:9px 10px;border-bottom:1px solid var(--linesoft);vertical-align:middle}
tbody tr{transition:background .1s}tr:hover td{background:color-mix(in srgb,var(--panel2) 60%,transparent)}
/* Every figure in the app is monospaced and tabular. A column of prices has to line up on the
   decimal without any per-page effort, and a number that changes must not reflow its neighbours. */
.num{font-family:var(--mono);text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums;
letter-spacing:var(--tight);font-feature-settings:"zero" 1}
/* v5.6 — THE TWO CLASSES THE VIEW LAYER KEPT REINVENTING.
   A survey of every inline style in src/views found the same small uppercase label written out by
   hand more than forty times, with seven different tracking values between them: .1em, .5px, .12em,
   .6px, .7px, .14em, .4px. Nothing chose those numbers; they were typed one page at a time over
   months, and the result is that the same element is drawn differently depending on which tab you
   are looking at. That is precisely the thing that makes an app feel assembled rather than designed.
   The canonical version already existed and was already used by every rule in this stylesheet and by
   the th element four lines up — 700 weight, micro size, --wide tracking, uppercase. .eyb is that
   rule and nothing more. It deliberately sets no colour, because the call sites already carry .dimc
   or .faintc and should keep deciding how loud their label is.
   .ar is the other half. Thirty-six of the forty-two text-align:right sites are table cells, and
   most of them wanted .num all along — it right-aligns AND makes the digits tabular so a column of
   prices lines up on the decimal. The half-dozen that are genuinely a header over a numeric column
   want the alignment without the monospace, and there was no class for that, so they hand-rolled it.
   Now there is one. */
.eyb{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide)}
.ar{text-align:right}
/* The tier above .eyb: the heading that separates one band of a long page from the next, sitting
   between cards rather than inside one. Five pages each wrote their own version of it — same size,
   same colour, same .7px tracking — and the only thing that varied was whether the top margin was
   4px or 18px, which is a spacing decision and stays at the call site. Not to be confused with
   .card h2, which titles a single card; this one titles a group of them. */
.sechd{font:600 var(--t-sm)/1.3 var(--sans);text-transform:uppercase;letter-spacing:var(--wide);
color:var(--dim);margin:4px 2px 10px}
.sechd.gap{margin-top:18px}
.pos{color:var(--green)}.neg{color:var(--red)}.dimc{color:var(--dim)}.warnc{color:var(--amber)}
.big{font-family:var(--mono);font-size:var(--t-xl);font-weight:700;letter-spacing:var(--tight);font-variant-numeric:tabular-nums}
.kv{display:flex;gap:var(--s5);flex-wrap:wrap}
.kv div span{display:block;font:var(--lbl);font-size:var(--t-micro);color:var(--faint);text-transform:uppercase;letter-spacing:var(--wide);margin-bottom:3px}
.bar{height:8px;background:var(--panel2);border-radius:5px;overflow:hidden;min-width:80px}
.bar i{display:block;height:100%;border-radius:5px}
.dot{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:5px;vertical-align:middle}
.d-green{background:var(--green)}.d-amber{background:var(--amber)}.d-red{background:var(--red)}.d-grey{background:var(--grey)}
details summary{cursor:pointer;color:var(--dim);font-size:var(--t-sm)}
pre{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:11px;overflow:auto;font-size:var(--t-sm)}
.mdsec{white-space:pre-wrap;font-family:var(--mono);font-size:var(--t-sm);background:var(--panel2);border-radius:10px;padding:10px;margin:6px 0}
input,select,button,textarea{background:var(--panel2);color:var(--fg);border:1px solid var(--line2);
border-radius:var(--radius-sm);padding:7px 11px;font-size:var(--t-base);font-family:inherit}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
button{cursor:pointer;font-weight:650;letter-spacing:.005em;transition:background .13s ease,border-color .13s ease,transform .08s ease}
button:hover{background:var(--panel3);border-color:var(--faint)}
button:active{transform:translateY(.5px)}
button:disabled{opacity:.45;cursor:not-allowed;transform:none}
button.primary{background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}
button.primary:hover{background:color-mix(in srgb,var(--accent) 86%,#fff);border-color:color-mix(in srgb,var(--accent) 86%,#fff)}
button.danger{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent);background:var(--red-soft)}
button.danger:hover{background:color-mix(in srgb,var(--red) 22%,transparent);border-color:var(--red)}
button.ghost{background:transparent;border-color:var(--line2);color:var(--dim)}
button.ghost:hover{background:var(--panel2);color:var(--fg)}
/* v5.6 — .scroll used to live here. There were three ways to make a table scroll: this class, a
   .tblwrap further down, and an inline overflow-x on the div, and which one a page used depended on
   who wrote the page. Two of the three drew no border, which is why nobody noticed that half the
   tables in the app said "there is more to the right" and half said nothing at all. All 70 now use
   .tblwrap; nothing referenced .scroll any more, so the rule and its border override are gone
   rather than left behind for the next person to copy. */
/* v5.6 — the pinned column has to win the paint order, not merely ask for it.
   Sticky positioning made this cell positioned but left z-index at auto, and a positioned element
   with z-index auto is beaten by any later positioned sibling in the same stacking context. Every
   header cell carrying a tooltip is position:relative, because that is how the bubble anchors — so
   on every pinned table with an explained column heading, the scrolled-under heading painted its
   text straight over the pinned one and the top-left corner read as two words on top of each other.
   The body rows were fine, which is exactly why nobody caught it: the defect only appears in the row
   where the tooltips live. z-index:2 settles it. The divider is the other half — a pinned column
   with nothing on its right edge gives the eye no reason to believe the columns beside it moved, so
   content appeared to melt into it rather than slide behind it. */
.tbl-pin td:first-child,.tbl-pin th:first-child{position:sticky;left:0;background:var(--panel);
z-index:2;box-shadow:1px 0 0 var(--line)}
.warnbox{border:1px solid color-mix(in srgb,var(--amber) 45%,transparent);background:color-mix(in srgb,var(--amber) 9%,transparent);color:var(--amber);border-radius:10px;padding:10px 12px;margin:8px 0;font-size:var(--t-sm)}
/* v4.3 — the two non-warning flavours of the same box. These were previously produced by writing
   inline style attributes at the call site, which meant the colour of a message was decided in the
   middle of a page template and could not be changed anywhere. A blue box is informational: the
   trading agent is doing something differently but nothing is wrong. A green box is an obligation the
   rulebook has taken on and intends to honour. */
.warnbox.bx-blue{border-color:color-mix(in srgb,var(--blue) 45%,transparent);background:color-mix(in srgb,var(--blue) 9%,transparent);color:var(--blue)}
.warnbox.bx-green{border-color:color-mix(in srgb,var(--green) 45%,transparent);background:color-mix(in srgb,var(--green) 9%,transparent);color:var(--green)}
.warnbox b{color:inherit}

/* v5.5 OPERATOR CONTROLS — four switches that must read as four switches.
   The grid is auto-fit rather than a fixed column count so the four cards become two-and-two on a
   tablet and one column on a phone without a media query, and each card carries its own coloured
   left edge so the one that is currently ACTIVE is findable without reading any of them. The
   destructive controls live behind a details element: a summary that has to be opened is one
   deliberate act between an anxious hand and an irreversible sell. */
.opsgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(258px,100%),1fr));gap:12px}
.opsc{border:1px solid var(--line);border-radius:12px;padding:12px 14px;
  background:color-mix(in srgb,var(--panel2) 55%,transparent);display:flex;flex-direction:column;gap:6px}
.opsh{display:flex;align-items:center;gap:8px}
.opsi{font-size:var(--t-md);line-height:1}
.opst{font-weight:750;font-size:var(--t-base);letter-spacing:.2px}
.opsnow{font-size:var(--t-sm);line-height:1.45}
.opsnow.a{color:var(--amber)}
.opsnow.r{color:var(--red)}
.opsd{font-size:var(--t-label);color:var(--dim);line-height:1.45}
.opsd b{color:var(--fg);font-weight:650}
.opsb{margin-top:auto;padding-top:8px}
.opsf{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
/* v6.126.0 — the hold form grew from one field to three. Stacked, because a textarea in a row of
   inputs collapses to a slit and nobody writes a measurement into a slit. */
.opsfcol{flex-direction:column;align-items:stretch;gap:8px;max-width:64ch}
.opsfcol textarea{font:inherit;font-size:var(--t-sm);color:var(--fg2);background:var(--sunk);
  border:1px solid var(--line);border-radius:var(--radius-sm);padding:8px 10px;resize:vertical;
  line-height:1.5;width:100%}
.opsfcol button{align-self:flex-start}
/* v6.131.0 — scoping a hold is a sentence, not a word, so the label wraps beside the box. */
.opschk{display:flex;gap:8px;align-items:flex-start;font-size:var(--t-micro);color:var(--dim);
  line-height:1.5;cursor:pointer}
.opschk input{margin-top:2px;flex:none}
/* v6.130.1 — a long job's own progress, on the card that started it. */
.opsu{margin-bottom:10px;padding:9px 11px;background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--radius-sm)}
.opsun{font-size:var(--t-sm);color:var(--fg2);line-height:1.5}
.opsud{font-size:var(--t-micro);color:var(--dim);line-height:1.5;margin-top:4px}
.opsf input{flex:1 1 120px;min-width:0}
.opsdet summary{cursor:pointer;font-size:var(--t-sm);color:var(--red);font-weight:650;list-style:none}
.opsdet summary::-webkit-details-marker{display:none}
.opsdet summary::before{content:"▸ "}
.opsdet[open] summary::before{content:"▾ "}
.opswarn{font-size:var(--t-label);color:var(--red);margin:8px 0 6px;line-height:1.45}
.opslog{margin-top:14px;border-top:1px solid var(--line);padding-top:10px}
.opslr{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;padding:3px 0;font-size:var(--t-sm)}
.footer{color:var(--dim);font-size:var(--t-sm);margin-top:16px;opacity:.85}
/* v3.3 position drawer */
tr[data-drawer],article[data-drawer]{cursor:pointer}
#drawer-scrim{display:none;position:fixed;inset:0;z-index:80;background:rgba(0,0,0,.45)}
#drawer{position:fixed;top:0;right:0;bottom:0;z-index:81;width:min(460px,92vw);transform:translateX(100%);transition:transform .18s ease;
  background:var(--panel);border-left:1px solid var(--line);box-shadow:-12px 0 40px rgba(0,0,0,.35);padding:16px 18px;overflow-y:auto}
#drawer.open{transform:none}#drawer-scrim.open{display:block}
#drawer .dclose{position:absolute;top:12px;right:14px;background:none;border:1px solid var(--line);border-radius:8px;padding:4px 9px}
/* v2.13 dashboard — tiles */
.dash{display:grid;gap:var(--s3);grid-template-columns:repeat(12,1fr)}
.tile{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:var(--s3) var(--s4);
grid-column:span 3;min-width:0;display:flex;flex-direction:column;gap:2px;box-shadow:var(--shadow-inset)}
.tile.wide{grid-column:span 6}.tile.half{grid-column:span 6}.tile.full{grid-column:span 12}.tile.kpi{grid-column:span 2}
.tile.s2{grid-column:span 2}.tile.s3{grid-column:span 3}.tile.s4{grid-column:span 4}.tile.s5{grid-column:span 5}.tile.s6{grid-column:span 6}
.tile.s7{grid-column:span 7}.tile.s8{grid-column:span 8}.tile.s9{grid-column:span 9}
.nicon{width:15px;height:15px;vertical-align:-2px;margin-right:6px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex:none}
.bottomnav .nicon{width:20px;height:20px;margin:0;display:block;margin:0 auto 2px}
.tile .tl{font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint)}
/* v5.0 point 2 — three sizes, and the size is the claim about importance.
   .tv        an ordinary metric. Most tiles. Big enough to scan, not big enough to shout.
   .tv.key    one of the handful that answer "how am I doing" — account value, day P&L, risk.
   .tv.hero   the single figure a page exists to show. At most one per screen. */
.tile .tv{font-family:var(--mono);font-size:var(--t-xl);font-weight:700;line-height:1.15;
letter-spacing:var(--tight);font-variant-numeric:tabular-nums;margin-top:2px}
.tile .tv.key{font-size:var(--t-2xl)}
.tile .tv.hero{font-size:var(--t-3xl)}
.tile .td{font-size:var(--t-sm);font-weight:650}
.tile.wide{background:linear-gradient(158deg,color-mix(in srgb,var(--accent) 6%,var(--panel)),var(--panel) 58%)}
.card,.tile{transition:box-shadow .16s ease,border-color .16s ease}
.card:hover,.tile:hover{border-color:var(--line2)}
.tile .tsub{font-size:var(--t-sm);color:var(--dim)}
.tile a.tlink{margin-top:auto;font-size:var(--t-sm);font-weight:600}
.tilehead{display:flex;align-items:center;justify-content:space-between;gap:8px}
.deltapos{color:var(--green)}.deltaneg{color:var(--red)}
.poscard{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;display:flex;flex-direction:column;gap:8px}
.poscard .sym{font-size:var(--t-lg);font-weight:700}
.poscard .row{display:flex;justify-content:space-between;font-size:var(--t-sm)}
.poscard .row span:first-child{color:var(--dim)}
.stopmeter{height:6px;border-radius:3px;background:var(--panel2);overflow:hidden}
.stopmeter i{display:block;height:100%;border-radius:3px}
.miniposgrid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr))}
@media(max-width:1000px){.tile,.tile.kpi,.tile.s2,.tile.s3,.tile.s4,.tile.s5,.tile.s7{grid-column:span 6}.tile.wide,.tile.full,.tile.half,.tile.s6,.tile.s8,.tile.s9{grid-column:span 12}}
/* the phone rules live in the v4.1 block at the end of this stylesheet — one breakpoint, 700px,
   so the bottom nav and the single-column tiles can never disagree about what a phone is. */
.hero{display:flex;gap:12px;align-items:center;border-radius:14px;padding:14px 16px;margin-bottom:12px;text-decoration:none;color:var(--fg);border:1px solid var(--line);background:var(--panel)}
.hero.ok{border-color:var(--green)}
.hero.red{border-color:var(--red);background:color-mix(in srgb,var(--red) 8%,var(--panel))}
.hero.amber{border-color:var(--amber);background:color-mix(in srgb,var(--amber) 8%,var(--panel))}
.hero .hicon{font-size:var(--t-2xl)}.hero .cta{margin-left:auto;white-space:nowrap;font-weight:700;color:var(--blue)}
a.hero:hover{text-decoration:none;filter:brightness(1.06)}
.feed{display:flex;flex-direction:column;gap:6px}
.fitem{display:flex;gap:10px;padding:8px 10px;border-radius:8px;background:var(--panel2);border-left:3px solid var(--line)}
.fitem.s-red{border-left-color:var(--red)}.fitem.s-amber{border-left-color:var(--amber)}.fitem.s-ok{border-left-color:var(--green)}
.ftime{font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);white-space:nowrap;padding-top:2px;min-width:52px}
.fbody{flex:1;min-width:0}.fsub{color:var(--dim);font-size:var(--t-sm);margin-top:2px}
.fbody details{margin-top:4px}.fbody summary{font-size:var(--t-label)}.fbody pre{margin:4px 0 0;font-size:var(--t-label);white-space:pre-wrap}
.subnav{display:flex;gap:8px;flex-wrap:wrap;padding:7px 14px;background:var(--panel);border-bottom:1px solid var(--line)}
.subnav a{color:var(--dim);padding:4px 12px;border-radius:14px;font-size:var(--t-sm)}
.subnav a.on{color:var(--fg);background:var(--panel2);font-weight:600}
/* v6.32.0 — ONE CONTEXT BAR INSTEAD OF TWO STRIPS.
   Before this there were four full-width bands above every page: the header, the quote ticker, the
   section subnav, and the alert strip. Four bands is most of a laptop's first screenful spent on
   chrome, and it is the difference the owner named between this and a trading platform — ThinkorSwim
   gives you one.
   The subnav and the ticker are now one row: where you are on the left, what the market is doing on
   the right. They are still their own elements, so every rule and every test that names either of
   them is untouched; what changed is that they share a line. */
.ctxbar{display:flex;align-items:stretch;background:var(--panel);border-bottom:1px solid var(--line)}
.ctxbar>.subnav{border-bottom:none;flex:0 1 auto;min-width:0;overflow-x:auto;flex-wrap:nowrap;
  scrollbar-width:none}
.ctxbar>.subnav::-webkit-scrollbar{display:none}
.ctxbar>.subnav a{white-space:nowrap;flex:none}
.ctxbar>.ticker{border-bottom:none;margin-left:auto;flex:1 1 auto;min-width:0;justify-content:flex-end;
  background:transparent;border-left:1px solid var(--line)}
/* Below a laptop the two genuinely do not fit on one line, and the subnav wins: it is how you move
   around, and the ticker is a glance. The quotes are on Today and the Desk regardless. */
@media(max-width:1000px){.ctxbar{display:block}.ctxbar>.ticker{display:none}}
.themebtn{background:none;border:1px solid var(--line);border-radius:14px;padding:3px 10px;font-size:var(--t-base)}
.bottomnav{display:none}
/* ============================================================================
   v3.5 TERMINAL UX — density modes, session-aware chrome, sortable columns,
   command palette, segmented timeframe controls, adversary + calibration cards.
   ========================================================================= */
/* DENSITY: html.compact tightens every surface at once (press "d"). A trading
   desk wants more rows on screen; a review session wants breathing room. */
html.compact body{font-size:var(--t-sm)}
html.compact main{padding:10px clamp(10px,2vw,24px);width:96%;max-width:2200px}
html.compact .dash{gap:8px}
html.compact .tile{padding:9px 11px;border-radius:10px;gap:1px}
html.compact .card{padding:11px 12px;border-radius:10px}
html.compact .card h2{margin-bottom:7px}
html.compact .tile .tv{font-size:var(--t-lg)}
html.compact .tile .tv.key{font-size:var(--t-xl)}
html.compact .tile .tv.hero{font-size:var(--t-2xl)}
html.compact th{padding:4px 7px}
html.compact td{padding:4.5px 7px;font-size:var(--t-sm)}
html.compact .fitem{padding:5px 8px}
html.compact .poscard{padding:10px 12px}
/* FEWER BORDERS: a table inside a panel does not need a second frame. The scroll-container half of
   this rule moved to section 8, where the rest of the nested-frame suppression lives, and became a
   descendant selector — a table two levels down inside a <details> was never a child of the card. */
.card table th:first-child,.card table td:first-child{padding-left:0}
.card table th:last-child,.card table td:last-child{padding-right:0}
.card table tr:last-child td{border-bottom:none}
/* SESSION-AWARE CHROME: the app should not look identical at 04:00 and 10:30. */
body.sess header{position:sticky}
body.sess-pre header::after,body.sess-open header::after,body.sess-post header::after,body.sess-closed header::after{
  content:'';position:absolute;left:0;right:0;bottom:-1px;height:2px;pointer-events:none}
body.sess-open header::after{background:linear-gradient(90deg,var(--green),color-mix(in srgb,var(--green) 15%,transparent))}
body.sess-pre header::after{background:linear-gradient(90deg,var(--amber),color-mix(in srgb,var(--amber) 15%,transparent))}
body.sess-post header::after{background:linear-gradient(90deg,var(--blue),color-mix(in srgb,var(--blue) 15%,transparent))}
body.sess-closed header::after{background:color-mix(in srgb,var(--line) 85%,transparent)}
body.sess-closed .ticker{opacity:.7}
body.sess-closed .ticker .ch{filter:saturate(.55)}
body.sess-open .ticker .ch{font-weight:750}
/* SORTABLE COLUMNS */
table.srt th{cursor:pointer;user-select:none;position:relative;padding-right:17px}
table.srt th:hover{color:var(--fg)}
/* The sort glyph lives on ::before, and that is load-bearing rather than arbitrary.
   A header can be both sortable and explained, and most of them are. When the glyph sat on ::after
   it was asking one pseudo-element to be two decorations at once: the sort rule won content and
   opacity, the tooltip rule kept its background, border, radius and shadow, and .tdn pushed the
   merged result downward — so every tipped sortable header painted a permanent faint plaque with a
   stray double-arrow inside it, sitting over the first row of the table body. On the Portfolio page
   that landed across a green PROTECTIVE STOP chip and read as a rendering fault.
   ::after now belongs to the tooltip alone. The selector is written twice, plainly, because the
   [data-tip] variant has to outrank [data-tip].tdn::before to keep the glyph beside the label
   instead of below it. The cost is the tooltip's little 5px triangle on sortable headers; a bubble
   with a border and a shadow still reads as a bubble. Do not move this back to ::after. */
table.srt th::before,table.srt th[data-tip]::before{content:'\2195';position:absolute;right:5px;left:auto;top:50%;bottom:auto;transform:translateY(-50%);opacity:.28;font-size:var(--t-micro);border:0;z-index:1}
table.srt th.asc::before{content:'\25B2';opacity:1;color:var(--accent);font-size:var(--t-nano)}
table.srt th.desc::before{content:'\25BC';opacity:1;color:var(--accent);font-size:var(--t-nano)}
table.srt th.nosort{cursor:default;padding-right:10px}table.srt th.nosort::before{content:''}
/* COMMAND PALETTE (⌘K / Ctrl-K / "/") */
#cmdk{display:none;position:fixed;inset:0;z-index:120;background:rgba(4,7,12,.62);backdrop-filter:blur(3px)}
#cmdk.open{display:block}
#cmdk .box{max-width:580px;margin:9vh auto 0;background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:0 24px 70px rgba(0,0,0,.55);overflow:hidden}
#cmdk input{width:100%;border:none;border-bottom:1px solid var(--line);border-radius:0;background:transparent;padding:15px 17px;font-size:var(--t-md)}
#cmdk input:focus{box-shadow:none;border-color:var(--line)}
#cmdk .res{max-height:54vh;overflow-y:auto;padding:6px}
#cmdk .r{display:flex;gap:10px;align-items:center;padding:9px 11px;border-radius:9px;cursor:pointer;font-size:var(--t-base)}
#cmdk .r.sel{background:var(--panel2)}
/* v4.3 — a row that FIRES something is not the same kind of row as one that navigates, and it must
   not look like one. The accent edge and the second line are the difference between "take me there"
   and "do this now"; the second line is what the command will actually do. */
#cmdk .r .l{display:flex;flex-direction:column;gap:1px;min-width:0}
#cmdk .r .s{font-size:var(--t-label);color:var(--dim);line-height:1.35}
#cmdk .r.act{border-left:2px solid var(--accent);padding-left:9px}
#cmdk .r.act.sel{background:color-mix(in srgb,var(--accent) 13%,var(--panel2))}
#cmdk .r .g{margin-left:auto;color:var(--dim);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.5px}
#cmdk .r .kb{margin-left:6px}
#cmdk .empty{padding:16px;color:var(--dim);font-size:var(--t-sm)}
#cmdk .hint{padding:8px 14px;border-top:1px solid var(--line);color:var(--dim);font-size:var(--t-label);display:flex;gap:14px;flex-wrap:wrap}
kbd{font-family:var(--mono);font-size:var(--t-label);background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:1px 5px;color:var(--dim)}
/* SEGMENTED CONTROL (equity timeframe 1W/1M/3M/ALL) */
.seg{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;flex:none}
.seg button{background:transparent;border:none;border-radius:0;padding:4px 11px;font-size:var(--t-label);color:var(--dim);font-weight:700;letter-spacing:.5px}
.seg button.on{background:var(--panel2);color:var(--fg)}
.seg button+button{border-left:1px solid var(--line)}
.tfpane{display:none}.tfpane.on{display:block}
/* ADVERSARY verdict card */
.advcard{border:1px solid color-mix(in srgb,var(--red) 42%,transparent);background:color-mix(in srgb,var(--red) 7%,transparent);border-radius:12px;padding:11px 13px;margin:8px 0}
.advcard.surv{border-color:color-mix(in srgb,var(--green) 34%,transparent);background:color-mix(in srgb,var(--green) 6%,transparent)}
.advcard.abst{border-color:var(--line);background:color-mix(in srgb,var(--panel2) 65%,transparent)}
.advcard .ah{display:flex;gap:8px;align-items:center;font-weight:700;font-size:var(--t-sm);margin-bottom:4px;flex-wrap:wrap}
.advcard .who{margin-left:auto;font-family:var(--mono);font-size:var(--t-micro);color:var(--dim);font-weight:400}
.advcard ul{margin:6px 0 0 17px;padding:0;font-size:var(--t-sm)}
.advcard li{margin:2px 0}
.advcard .counter{margin-top:7px;font-size:var(--t-sm);color:var(--dim);border-left:2px solid var(--line);padding-left:9px}
/* CALIBRATION bars — claimed vs actual, side by side */
.calbar{position:relative;height:18px;background:var(--panel2);border-radius:4px;overflow:hidden;min-width:110px}
.calbar i{display:block;height:100%;background:color-mix(in srgb,var(--accent) 50%,transparent)}
.calbar u{position:absolute;top:-1px;bottom:-1px;width:2px;background:var(--amber);text-decoration:none}
.thinflag{font-size:var(--t-micro);font-weight:700;letter-spacing:.4px;color:var(--amber);text-transform:uppercase}
/* ============================================================================
   v4.1 THE COCKPIT — the narrative Today page.
   Three blocks, in the order a person actually asks: what do I do, what changed,
   what is it waiting on. Everything here is phone-first: the desktop rules are
   the enhancement, not the other way round.
   ========================================================================= */
.ckh{font-size:var(--t-md);font-weight:750;letter-spacing:-.1px;margin:2px 0 9px;display:flex;align-items:center;gap:9px}
.ckh::before{content:'';width:3px;height:15px;border-radius:2px;background:var(--accent)}
.card h2 .hsub{font-weight:500;letter-spacing:0;text-transform:none;font-size:var(--t-label);color:var(--dim);opacity:.85}
.card h2 .hlink{margin-left:auto;font-size:var(--t-label);font-weight:600;text-transform:none;letter-spacing:0}
/* --- the "right now" strip ------------------------------------------------ */
.ckdo{display:flex;gap:16px;align-items:center;flex-wrap:wrap;background:linear-gradient(150deg,color-mix(in srgb,var(--accent) 9%,var(--panel)),var(--panel) 62%);
  border:1px solid var(--line);border-radius:16px;padding:15px 18px;margin-bottom:14px;box-shadow:var(--shadow)}
.ckdo-main{flex:1 1 340px;min-width:0}
.ckdo-tag{font-size:var(--t-label);text-transform:uppercase;letter-spacing:.6px;color:var(--dim);font-weight:700;margin-bottom:6px}
.ckdo-line{font-size:var(--t-xl);font-weight:700;letter-spacing:-.35px;line-height:1.3}
.ckdo-sub{font-size:var(--t-sm);color:var(--dim);margin-top:4px}
.ckdo-money{display:flex;gap:22px;flex-wrap:wrap;flex:0 1 auto}
.ckdo-money .m1{display:flex;flex-direction:column;gap:2px}
.ckdo-money em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.5px;color:var(--dim);font-weight:700}
.ckdo-money b{font-family:var(--mono);font-size:var(--t-md);font-weight:700;font-variant-numeric:tabular-nums}
/* --- the decision block --------------------------------------------------- */
.ckact{margin-bottom:14px}
.dcard{display:flex;gap:14px;align-items:flex-start;padding:15px 17px;border-radius:15px;margin-bottom:9px;
  border:1px solid var(--line);background:var(--panel);color:var(--fg);text-decoration:none;box-shadow:var(--shadow);
  transition:filter .12s,border-color .12s}
.dcard:hover{text-decoration:none;filter:brightness(1.06);border-color:color-mix(in srgb,var(--accent) 40%,var(--line))}
.dcard.s-red{border-color:color-mix(in srgb,var(--red) 55%,transparent);background:color-mix(in srgb,var(--red) 8%,var(--panel))}
.dcard.s-amber{border-color:color-mix(in srgb,var(--amber) 55%,transparent);background:color-mix(in srgb,var(--amber) 7%,var(--panel))}
.dcard.s-ok{border-color:color-mix(in srgb,var(--green) 45%,transparent)}
.dcard.s-quiet{border-color:color-mix(in srgb,var(--green) 32%,transparent);background:color-mix(in srgb,var(--green) 5%,var(--panel))}
.dcard .dicon{font-size:var(--t-xl);line-height:1.1;flex:none}
.dcard .dbody{flex:1;min-width:0}
.dcard .dhead{font-size:var(--t-lg);font-weight:700;letter-spacing:-.2px;line-height:1.32}
.dcard .dwhy{font-size:var(--t-base);color:var(--dim);margin-top:4px;line-height:1.45}
.dcard .dmeta{font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);margin-top:6px;font-variant-numeric:tabular-nums}
.dcard .dgo{margin-left:auto;text-align:right;flex:none;display:flex;flex-direction:column;gap:5px;align-items:flex-end}
.dcard .dclock{font-family:var(--mono);font-size:var(--t-md);font-weight:750;color:var(--red)}
.dcard .dcta{font-size:var(--t-sm);font-weight:700;color:var(--accent);white-space:nowrap}
/* --- the stat wall (v4.1.1) ------------------------------------------------
   Seven across on a desktop, two on a phone. Every tile is the same height so the wall reads as a
   grid rather than a ragged list, and the value is the only large thing in it. */
.swall{display:grid;grid-template-columns:repeat(7,1fr);gap:8px;margin-bottom:14px}
.stile{display:block;background:var(--panel);border:1px solid var(--line);border-radius:12px;
  padding:10px 12px;text-decoration:none;color:inherit;min-height:74px;transition:border-color .12s,background .12s}
a.stile:hover{border-color:var(--accent);background:var(--panel2)}
.stile em{display:block;font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stile b{display:block;font-family:var(--mono);font-size:var(--t-lg);font-weight:750;line-height:1.25;
  margin-top:3px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.stile i{display:block;font-style:normal;font-size:var(--t-micro);color:var(--dim);margin-top:2px;line-height:1.3}
.stile b.t-pos{color:var(--green)}
.stile b.t-neg{color:var(--red)}
.stile b.t-warn{color:var(--amber)}
/* A count chip. Used by both the decision cards and the feed, so repeats read as one event that
   happened N times rather than N separate events. */
.rep{display:inline-block;font-family:var(--mono);font-size:var(--t-label);font-weight:700;color:var(--dim);
  border:1px solid var(--line);border-radius:999px;padding:0 6px;margin-left:6px;vertical-align:1px}
.fspan{font-family:var(--mono);font-size:var(--t-micro);color:var(--dim);margin-left:6px}
.quiet.nsc{border-left:2px solid var(--amber);padding-left:10px;margin-bottom:11px}
.quiet b{color:var(--fg)}
/* --- two-column middle ---------------------------------------------------- */
.ckcols{display:grid;grid-template-columns:1.55fr 1fr;gap:14px;margin-bottom:14px;align-items:start}
/* The right rail stacks: what it is waiting on, then today's funnel. Both cards carry their own
   bottom margin already, so the rail only needs to stop that margin doubling at the end. */
.ckrail{display:flex;flex-direction:column}
.ckrail .card:last-child{margin-bottom:0}
.quiet{color:var(--dim);font-size:var(--t-sm);line-height:1.5}
.ckfeed .markread{margin-left:auto}
.ckfeed .mrbtn{background:none;border:1px solid var(--line);border-radius:999px;padding:2px 11px;font-size:var(--t-label);
  font-weight:600;color:var(--dim);text-transform:none;letter-spacing:0}
.ckfeed .fmore{margin-top:9px;font-size:var(--t-sm);color:var(--dim)}
a.fitem.flink{color:var(--fg);text-decoration:none}
a.fitem.flink:hover{text-decoration:none;background:color-mix(in srgb,var(--panel2) 70%,var(--accent) 8%)}
.fsym{font-family:var(--mono);font-size:var(--t-sm);color:var(--accent)}
/* --- waiting list --------------------------------------------------------- */
.wlist{display:flex;flex-direction:column;gap:7px}
.witem{display:flex;gap:10px;align-items:flex-start;padding:9px 11px;border-radius:10px;background:var(--panel2);
  border-left:3px solid var(--line);color:var(--fg);text-decoration:none}
.witem:hover{text-decoration:none;filter:brightness(1.07)}
.witem.t-red{border-left-color:var(--red)}.witem.t-amber{border-left-color:var(--amber)}.witem.t-ok{border-left-color:var(--green)}
.witem .wic{font-size:var(--t-md);flex:none;line-height:1.35}
.witem .wtx{min-width:0}
.witem .wtx b{display:block;font-size:var(--t-base);font-weight:600;line-height:1.35}
.witem .wtx em{display:block;font-style:normal;font-size:var(--t-sm);color:var(--dim);margin-top:2px;line-height:1.4}
/* --- the watch list ------------------------------------------------------- */
.wgrid{display:grid;gap:11px;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr))}
.wcard{border:1px solid var(--line);border-radius:13px;padding:12px 14px;background:var(--panel2);display:flex;flex-direction:column;gap:7px}
.wcard.t-red{border-color:color-mix(in srgb,var(--red) 50%,transparent);background:color-mix(in srgb,var(--red) 7%,var(--panel2))}
.wcard.t-amber{border-color:color-mix(in srgb,var(--amber) 45%,transparent)}
.wtop{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.wsym{font-size:var(--t-lg);font-weight:750;letter-spacing:.2px}
.wdist{font-family:var(--mono);font-size:var(--t-sm);font-weight:700;margin-left:auto}
.wsay{font-size:var(--t-sm);line-height:1.45;color:var(--fg)}
.wnums{display:flex;flex-wrap:wrap;gap:4px 16px}
.wnums span{font-family:var(--mono);font-size:var(--t-sm);font-variant-numeric:tabular-nums}
.wnums em{display:block;font-style:normal;font-family:var(--sans);font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:.5px;color:var(--dim);font-weight:700}
.wfoot{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:var(--t-label);color:var(--dim);border-top:1px solid var(--line);padding-top:7px}
/* --- positions ------------------------------------------------------------ */
.pgrid{display:grid;gap:11px;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr))}
.pcard{border:1px solid var(--line);border-radius:13px;padding:12px 14px;background:var(--panel2);color:var(--fg);text-decoration:none;display:block}
.pcard:hover{text-decoration:none;filter:brightness(1.07)}
.ptop{display:flex;align-items:center;gap:8px;justify-content:space-between}
.ptop b{font-size:var(--t-md);font-weight:750}
.pval{font-family:var(--mono);font-size:var(--t-xl);font-weight:700;margin-top:5px;font-variant-numeric:tabular-nums}
.psub{font-size:var(--t-sm);color:var(--dim);margin-top:2px}
.psub2{font-size:var(--t-label);color:var(--dim);opacity:.85;margin-top:2px}
/* No resting stop at the broker is a risk fact, not a footnote — it gets the red treatment so it
   cannot be read as protection the account does not actually have. */
.psub2.warn{color:var(--red);opacity:1;font-weight:600}
/* --- funnel --------------------------------------------------------------- */
.funnel{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(min(140px,100%),1fr))}
.fstep{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:10px 12px}
.fstep b{display:block;font-family:var(--mono);font-size:var(--t-xl);font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums}
.fstep span{display:block;font-size:var(--t-sm);font-weight:600;margin-top:2px}
.fstep em{display:block;font-style:normal;font-size:var(--t-label);color:var(--dim);margin-top:3px;line-height:1.35}
/* --- the deep-links footer ------------------------------------------------ */
.ckdeep{display:flex;flex-wrap:wrap;gap:7px;margin-top:14px}
.ckdeep a{font-size:var(--t-sm);color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:4px 12px}
.ckdeep a:hover{color:var(--fg);text-decoration:none;background:var(--panel2)}

/* =============================================================================
   v4.2 — THE TODAY PAGE.
   Colour is load-bearing here and is used for one meaning only:
     green  filled / profitable / healthy     blue   watching / informational
     amber  nearing entry / needs attention   orange degraded but still running
     red    trading stopped / risk breach     grey   rejected / expired / inactive
   Nothing on this page is coloured for decoration.
   ========================================================================== */
.amberc{color:var(--amber)}
.mchip{display:inline-block;font-size:var(--t-label);font-weight:600;color:var(--dim);background:color-mix(in srgb,var(--panel2) 80%,transparent);
  border:1px solid color-mix(in srgb,var(--line) 75%,transparent);border-radius:6px;padding:1px 7px;margin:2px 4px 0 0;line-height:1.55}
.rep{font-size:var(--t-label);font-weight:700;color:var(--dim);background:var(--panel2);border-radius:5px;padding:0 5px}

/* --- 1. AUTOPILOT STATUS ------------------------------------------------------- */
.rstat{display:grid;grid-template-columns:1fr 250px;gap:18px;background:var(--panel);border:1px solid var(--line);
  border-left:4px solid var(--grey);border-radius:var(--radius);padding:16px 18px;box-shadow:var(--shadow);margin-bottom:14px}
.rstat.t-green{border-left-color:var(--green)}
.rstat.t-amber{border-left-color:var(--amber)}
.rstat.t-orange{border-left-color:#e08a3c}
.rstat.t-red{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 6%,var(--panel))}
.rs-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.rs-dot{width:9px;height:9px;border-radius:50%;background:var(--grey);flex:none;box-shadow:0 0 0 4px color-mix(in srgb,var(--grey) 18%,transparent)}
.t-green .rs-dot{background:var(--green);box-shadow:0 0 0 4px color-mix(in srgb,var(--green) 20%,transparent);animation:rsp 2.4s ease-in-out infinite}
.t-amber .rs-dot{background:var(--amber);box-shadow:0 0 0 4px color-mix(in srgb,var(--amber) 20%,transparent)}
.t-orange .rs-dot{background:#e08a3c;box-shadow:0 0 0 4px color-mix(in srgb,#e08a3c 20%,transparent)}
.t-red .rs-dot{background:var(--red);box-shadow:0 0 0 4px color-mix(in srgb,var(--red) 22%,transparent)}
@keyframes rsp{0%,100%{opacity:1}50%{opacity:.45}}
.rs-state{font-size:var(--t-lg);font-weight:750;letter-spacing:.4px}
.t-green .rs-state{color:var(--green)}.t-amber .rs-state{color:var(--amber)}
.t-orange .rs-state{color:#e08a3c}.t-red .rs-state{color:var(--red)}
.rs-mkt{font-size:var(--t-sm);color:var(--dim);border:1px solid var(--line);border-radius:999px;padding:2px 10px}
.rs-doing{font-size:var(--t-md);line-height:1.45;margin-top:7px}
.rs-counts{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.rs-c{display:block;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:8px 13px;min-width:96px;text-decoration:none;color:inherit}
a.rs-c:hover{border-color:var(--accent);text-decoration:none}
.rs-c b{display:block;font-family:var(--mono);font-size:var(--t-xl);font-weight:750;line-height:1.15;font-variant-numeric:tabular-nums}
.rs-c b.sm{font-family:var(--sans);font-size:var(--t-sm);font-weight:700;line-height:1.35;padding-top:3px}
.rs-c em{display:block;font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--dim);margin-top:3px}
.rs-c.hot{border-color:color-mix(in srgb,var(--amber) 55%,transparent);background:color-mix(in srgb,var(--amber) 10%,var(--panel2))}
.rs-c.hot b{color:var(--amber)}
.rs-pause{margin-top:13px;display:grid;gap:8px}
.rs-p1{border:1px solid color-mix(in srgb,#e08a3c 50%,transparent);background:color-mix(in srgb,#e08a3c 9%,transparent);border-radius:11px;padding:11px 13px}
.rs-ph{font-weight:650;font-size:var(--t-base);line-height:1.45}
.rs-ps{font-size:var(--t-sm);color:var(--dim);margin-top:4px;line-height:1.45}
.rs-pr{font-size:var(--t-sm);color:var(--dim);margin-top:3px}
.rs-act{margin-top:13px;border:1px solid color-mix(in srgb,var(--red) 50%,transparent);background:color-mix(in srgb,var(--red) 8%,transparent);border-radius:11px;padding:12px 14px}
.rs-acth{font-size:var(--t-label);font-weight:750;letter-spacing:.07em;text-transform:uppercase;color:var(--red)}
.rs-actl{font-size:var(--t-base);line-height:1.5;margin-top:5px}
.rs-actgo{display:inline-block;margin-top:8px;font-size:var(--t-sm);font-weight:650}
.rs-noact{margin-top:13px;font-size:var(--t-sm);color:var(--dim);border-top:1px solid color-mix(in srgb,var(--line) 70%,transparent);padding-top:10px}
/* v4.2.1 — the recover-a-missed-scan block. Amber, not red: nothing is broken, something is late. */
.rs-catch{margin-top:13px;border:1px solid color-mix(in srgb,var(--amber) 55%,transparent);background:color-mix(in srgb,var(--amber) 9%,transparent);border-radius:11px;padding:12px 14px}
.rs-ch{font-size:var(--t-label);font-weight:750;letter-spacing:.07em;text-transform:uppercase;color:var(--amber)}
.rs-cs{font-size:var(--t-base);line-height:1.5;margin-top:5px;color:var(--fg)}
.rs-catch form{margin-top:9px;display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.rs-cbtn{background:var(--amber);border:1px solid var(--amber);color:#14100a;font-family:var(--sans);font-size:var(--t-base);font-weight:750;border-radius:9px;padding:8px 15px;cursor:pointer}
.rs-cbtn:hover{filter:brightness(1.08)}
.rs-cnote{font-size:var(--t-label);color:var(--dim)}
.scanbanner{border-radius:11px;padding:12px 15px;font-size:var(--t-base);line-height:1.5;margin-bottom:14px;border:1px solid}
.scanbanner.ok{border-color:color-mix(in srgb,var(--green) 55%,transparent);background:color-mix(in srgb,var(--green) 10%,transparent);color:var(--green)}
.scanbanner.no{border-color:color-mix(in srgb,var(--amber) 55%,transparent);background:color-mix(in srgb,var(--amber) 10%,transparent);color:var(--amber)}
.rs-side{border-left:1px solid var(--line);padding-left:16px;display:flex;flex-direction:column;gap:7px;justify-content:center}
.rs-ind{display:flex;align-items:center;gap:7px;font-size:var(--t-sm);color:var(--dim)}
.rs-ind.bad{color:var(--red);font-weight:600}
.rs-scan{font-size:var(--t-label);color:var(--dim);margin-top:5px;padding-top:7px;border-top:1px solid color-mix(in srgb,var(--line) 60%,transparent)}

/* --- 2. ACCOUNT AND RISK --------------------------------------------------- */
.rgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:9px}
/* v4.3 — the same tile grid at other widths, so Trades / Performance / Rules can use the shape
   without inheriting the Today page's six-across rhythm. */
.rgrid.c3{grid-template-columns:repeat(3,1fr)}
.rgrid.c4{grid-template-columns:repeat(4,1fr)}
.rgrid.c5{grid-template-columns:repeat(5,1fr)}
/* ── v6.6.0 THE COMMAND CENTER ─────────────────────────────────────────────────────────────────
   WHY THESE EXIST AT ALL, rather than reusing .dash and .rtile.

   v6.5.0 laid the command centre out with "flex:1 1 min(260px,100%)" on children of ".dash".
   ".dash" is a TWELVE-COLUMN GRID: it ignores flex properties entirely, so every block took the
   default single track — about 110px — and the two text columns wrapped to roughly one word per
   line. The bug was not a missing min-width, it was the wrong layout primitive, and no amount of
   tuning the old classes would have found it.

   So every band below is a grid with an explicit FLOOR in its track definition. "minmax(<floor>,
   1fr)" cannot collapse; "min-width:0" on the children stops long values forcing an overflow
   instead. Those two lines together are the whole rule, and nothing in this section may be written
   without both.

   .rtile is deliberately not reused: min-height 76px was built for a card with room to breathe,
   and eight of them in a row is most of a screen. */

/* Today runs wider than the rest of the app. "main" caps at 1800px, which on a 4K workstation is
   most of the display given over to margin — and this is a desktop-first trading surface whose
   whole promise is one screen. */
/* Today keeps more room than the rest — it is the one page built as a wall of panels rather than a
   column of cards — but it came down with everything else. 2400px was wider than any monitor in
   this house. */
main.wide{max-width:1800px;width:96%}
@media(max-width:1100px){main.wide{width:100%}}

/* Band 1 — status. One line, small, and never wraps into a second row on a real monitor. */
.ccstrip{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:6px 10px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);
  font-size:var(--t-label);min-height:30px}
.ccstrip .sep{width:1px;height:13px;background:var(--line);flex:0 0 auto}
.ccstrip b{font-weight:700;letter-spacing:.02em}
.ccdot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:5px;flex:0 0 auto}
.ccdot.ok{background:var(--green)}.ccdot.warn{background:var(--amber)}
.ccdot.bad{background:var(--red)}.ccdot.off{background:var(--dim)}

/* Band 2 — the KPI row. Eight cells, one line each, no card chrome. The floor is 132px because a
   dollar figure with a label under it stops being readable below roughly that. */
.cckpi{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:10px;
  overflow:hidden;grid-template-columns:repeat(auto-fit,minmax(min(132px,100%),1fr))}
.cckpi>div,.cckpi>a{background:var(--panel);padding:8px 11px;min-width:0}
/* v6.33.1 — one cell in this strip is a control, and it has to look like one.
   The NEEDS YOU cell said "click to open" while rendering as a plain div: the label promised an
   interaction the element could not perform, which is worse than no label — it makes a reader
   doubt the page rather than look elsewhere. It is an anchor now, and these three lines are what
   stop it being an anchor nobody can tell is an anchor. */
.cckpi>a{display:block;color:inherit;text-decoration:none;cursor:pointer;
  transition:background .12s ease}
.cckpi>a:hover,.cckpi>a:focus-visible{background:var(--panel2)}
.cckpi>a .k::after{content:' \2197';color:var(--accent);font-weight:700}
.cckpi .k{font-size:var(--t-micro);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
.cckpi .v{font-family:var(--mono);font-size:var(--t-lg);font-weight:750;line-height:1.2;
  font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cckpi .s{font-size:var(--t-label);color:var(--dim);line-height:1.3;margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Band 3 — alerts. Renders nothing at all when empty; an empty alert area is a card that says
   "nothing is wrong", which costs a band of a one-screen page to say what silence already says. */
.ccalert{display:flex;gap:9px;align-items:flex-start;padding:7px 11px;margin-bottom:5px;
  border:1px solid var(--line);border-left-width:3px;border-radius:8px;background:var(--panel2);
  text-decoration:none;color:inherit}
.ccalert.crit{border-left-color:var(--red)}
.ccalert.act{border-left-color:var(--amber)}
.ccalert.warn{border-left-color:var(--amber);opacity:.92}
.ccalert.info{border-left-color:var(--line)}
.ccalert .lvl{font-size:var(--t-micro);font-weight:800;letter-spacing:.07em;flex:0 0 auto;
  padding-top:2px;min-width:62px}
.ccalert .body{flex:1 1 auto;min-width:0;font-size:var(--t-sm);line-height:1.4}
.ccalert .body i{display:block;font-style:normal;color:var(--dim);font-size:var(--t-label);margin-top:1px}

/* A generic two-up row with real floors. Phase 2 puts the chart and Agent Now here. */
.ccrow{display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr))}
.ccrow>*{min-width:0}

/* v6.7.0 — the two-column command area. 65/35 on a workstation, stacked below the floor.
   auto-fit would let the right column wrap up beside the chart at odd widths; explicit tracks with
   a floor keep the ratio the spec asked for and collapse cleanly in one step instead of three. */
.ccmain{display:grid;gap:var(--s3);grid-template-columns:minmax(0,65fr) minmax(0,35fr)}
@media(max-width:1100px){.ccmain{grid-template-columns:minmax(0,1fr)}}
.ccpanel{min-width:0;border:1px solid var(--line);border-radius:10px;background:var(--panel);padding:10px 12px}
.ccph{display:flex;align-items:baseline;gap:8px;margin-bottom:4px}
.cctfs{margin-left:auto;display:flex;gap:2px}
.cctf{font:inherit;font-size:var(--t-label);color:var(--dim);background:none;border:1px solid transparent;
  border-radius:6px;padding:2px 7px;cursor:pointer}
.cctf:hover{background:var(--panel2)}
.cctf.on{color:var(--fg);border-color:var(--line);background:var(--panel2)}
.ccstats{display:flex;gap:var(--s3);flex-wrap:wrap;margin-top:2px}
.ccstats span{display:flex;flex-direction:column;min-width:0}
.ccstats em{font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dim)}
.ccstats b{font-family:var(--mono);font-size:var(--t-base);font-weight:700;font-variant-numeric:tabular-nums}

.ccagentstate{font-weight:800;font-size:var(--t-base);letter-spacing:.02em;margin-top:2px}
.ccagentstate.pos{color:var(--green)}.ccagentstate.warn{color:var(--amber)}.ccagentstate.neg{color:var(--red)}
.ccsched{display:flex;gap:var(--s3);flex-wrap:wrap;margin:6px 0;padding:6px 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);font-size:var(--t-label)}
.ccsched em{font-style:normal;font-weight:700;letter-spacing:.06em;color:var(--dim);margin-right:5px}
/* The feed is capped and scrolls INSIDE itself: this panel is a third of a column on a page
   budgeted to one screen, and a stream that grows the page is a stream that breaks the promise. */
.ccfeed{max-height:150px;overflow-y:auto;font-size:var(--t-label);line-height:1.65}
.ccfeed a,.ccfeed div{display:flex;gap:6px;text-decoration:none;color:inherit;padding:1px 0}
.ccfeed a:hover{background:var(--panel2)}
.ccfeed .fk{flex:0 0 12px;text-align:center}
.ccfeed .fk.fail{color:var(--red)}.ccfeed .fk.warn{color:var(--amber)}
.ccfeed .fk.trade{color:var(--green)}.ccfeed .fk.work,.ccfeed .fk.watch{color:var(--blue)}
.ccfeed .ft{flex:0 0 58px;color:var(--dim);font-family:var(--mono)}
.ccfeed .fx{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* v6.8.0 — COMMAND MODE, as scaffolding rather than a second application.

   The spec asks for a full-screen dense surface on a dedicated monitor, and explicitly asks NOT to
   fork the app for it yet. So it is a body class: the same components, with the page chrome and the
   folded detail removed and the bands given the whole display. Everything Today already renders is
   reused, which is what keeps the two from drifting — a separate Command page would be a second
   surface computing the same numbers, and this repo has spent a week on what that costs.

   Toggled by ?mode=command, so it is a URL a monitor can be parked on and a browser can restore. */
html.cmdmode header, html.cmdmode .ckdeep, html.cmdmode details.fold, html.cmdmode .scanbanner{display:none}
html.cmdmode main{padding:10px 14px;width:100%;max-width:none}
html.cmdmode .cckpi .v{font-size:var(--t-xl)}
html.cmdmode .ccfeed{max-height:min(38vh,420px)}
html.cmdmode .ccmain{grid-template-columns:minmax(0,62fr) minmax(0,38fr)}
html.cmdmode .ccbook td,html.cmdmode .ccbook th{padding:7px 10px;font-size:var(--t-base)}

/* v6.8.0 — the owner's inbox, as a drawer.

   A drawer rather than a page because it is read in the middle of doing something else: the whole
   point is that "what needs me" never costs a navigation. Escape and a click on the backdrop both
   close it, because a panel that traps you is one you stop opening. */
.ccdrawer{position:fixed;inset:0;z-index:60;background:rgba(0,0,0,.45);
  display:flex;justify-content:flex-end}
.ccdrawer[hidden]{display:none}
.ccdrawerbox{background:var(--panel);border-left:1px solid var(--line);width:min(520px,100%);
  height:100%;overflow-y:auto;padding:14px 16px;box-shadow:-24px 0 70px rgba(0,0,0,.4)}
.ccitem{border:1px solid var(--line);border-left-width:3px;border-radius:9px;
  padding:10px 12px;margin-bottom:10px;background:var(--panel2)}
.ccitem.crit{border-left-color:var(--red)}
.ccitem.act{border-left-color:var(--amber)}
.ccitem.warn{border-left-color:var(--amber);opacity:.94}
.ccitemhead{display:flex;gap:8px;align-items:flex-start;font-size:var(--t-sm);line-height:1.45}
.ccitemhead .lvl{font-size:var(--t-micro);font-weight:800;letter-spacing:.07em;color:var(--dim);
  flex:0 0 auto;padding-top:2px;min-width:62px}
/* Each answer labelled, in the order a person asks. An unlabelled paragraph is the format this
   replaced, and it is why the same explanation appeared in three places and was read in none. */
.ccq{font-size:var(--t-label);line-height:1.5;margin-top:6px;color:var(--fg)}
.ccq em{display:block;font-style:normal;font-weight:700;letter-spacing:.06em;color:var(--dim);
  font-size:var(--t-micro)}
.ccacts{display:flex;gap:8px;flex-wrap:wrap;margin-top:9px}

/* The header badge. Zero is stated rather than hidden: "needs you 0" is the sentence that says the
   machine is running unattended, and an absent badge says nothing at all. */
.needsbadge{display:inline-block;min-width:17px;padding:0 5px;border-radius:9px;text-align:center;
  font-size:var(--t-micro);font-weight:800;background:var(--panel2);color:var(--dim);border:1px solid var(--line)}
.needsbadge.on{background:var(--amber);color:#1a1200;border-color:transparent}

/* The positions table. Rows are links: the detail lives on /positions and clicking through is the
   whole point of a compact table. */
.ccbook tbody tr{cursor:pointer}
.ccbook tbody tr:hover{background:var(--panel2)}
.ccbook td,.ccbook th{padding:5px 8px;font-size:var(--t-sm)}

/* Next Up — cells, not cards. 200px is the floor at which a symbol, a distance and a risk figure
   still read as three facts rather than a paragraph. */
.ccnext{display:grid;gap:var(--s2);grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr))}
.ccnext>div{min-width:0;border:1px solid var(--line);border-radius:9px;padding:8px 10px;background:var(--panel2)}

/* The folds. Everything the command centre summarises stays on the page, one click down. */
details.fold{border:1px solid var(--line);border-radius:9px;background:var(--panel);margin-top:8px}
details.fold>summary{cursor:pointer;padding:9px 12px;font-size:var(--t-sm);font-weight:650;
  list-style:none;display:flex;align-items:center;gap:8px}
details.fold>summary::-webkit-details-marker{display:none}
details.fold>summary::before{content:'▸';color:var(--dim);font-size:var(--t-label)}
details.fold[open]>summary::before{content:'▾'}
details.fold>summary:hover{background:var(--panel2)}
details.fold>.foldbody{padding:0 12px 12px}

.rtile{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:11px 13px;min-height:76px}
.rtile em{display:block;font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
.rtile b{display:block;font-family:var(--mono);font-size:var(--t-xl);font-weight:750;line-height:1.3;margin-top:4px;font-variant-numeric:tabular-nums}
.rtile i{display:block;font-style:normal;font-size:var(--t-label);color:var(--dim);margin-top:3px;line-height:1.35}
/* A tile whose "number" is words — a session name, a decision — must not be set in the tabular
   monospace face, which exists to make digits line up and makes prose look like a receipt. */
.rtile b.sm{font-family:var(--sans);font-size:var(--t-md);font-weight:700;line-height:1.35}
.rtile i .chip{margin-right:5px}

/* --- 2b. PERFORMANCE HERO (v4.3) -------------------------------------------
   The Performance home used to open with a 32px number in an inline-styled div and a right-aligned
   grey caption. It now opens the way the Today page does: the number, and then a SENTENCE that
   says what the number means relative to the only benchmark that matters. */
.perfhero{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap;margin-bottom:6px}
.phbig{font-size:var(--t-3xl);font-weight:700;letter-spacing:-.6px;line-height:1.15;font-variant-numeric:tabular-nums}
.phday{font-size:var(--t-md);font-weight:650;letter-spacing:0}
.phsent{font-size:var(--t-base);color:var(--dim);margin-top:5px;line-height:1.5;max-width:62ch}
.phsent b{color:var(--fg)}
.phside{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:var(--t-label);color:var(--dim)}
.meter{margin-top:14px}
.mlab{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap;font-size:var(--t-sm)}
.mlab b{font-weight:700}
.mlab span{color:var(--dim);font-size:var(--t-sm)}
.mbar{height:10px;border-radius:999px;background:var(--panel2);border:1px solid var(--line);overflow:hidden;margin-top:6px}
.mbar i{display:block;height:100%;border-radius:999px}
.mbar.t-green i{background:var(--green)}.mbar.t-amber i{background:var(--amber)}
.mbar.t-red i{background:var(--red)}.mbar.t-blue i{background:var(--blue)}
.msub{font-size:var(--t-label);color:var(--dim);margin-top:4px}
.stopswhen{margin-top:13px;font-size:var(--t-sm)}
.stopswhen summary{cursor:pointer;color:var(--dim);font-weight:600}
.stopswhen ul{margin:8px 0 0;padding-left:18px;color:var(--dim);line-height:1.65}

/* --- 3. WATCHING NOW ------------------------------------------------------- */
.wfilters{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:10px}
.wfil{background:var(--panel2);border:1px solid var(--line);color:var(--dim);border-radius:999px;padding:5px 13px;
  font-size:var(--t-sm);font-weight:650;cursor:pointer;font-family:inherit}
.wfil:hover{color:var(--fg)}
.wfil.on{color:var(--fg);border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent)}
.tscroll{overflow-x:auto}
.wtable{min-width:1050px}
.wtable td{vertical-align:top;font-size:var(--t-sm)}
.wrow.nearrow td{background:color-mix(in srgb,var(--amber) 7%,transparent)}
.wsym b{font-family:var(--mono);font-size:var(--t-md);font-weight:750;letter-spacing:.3px}
.wsym em{display:block;font-style:normal;font-size:var(--t-micro);color:var(--dim);margin-top:2px}
.wrule{max-width:420px;line-height:1.5}
.wchips{margin-top:2px}
.wcancel{font-size:var(--t-label);color:var(--dim);margin-top:4px;line-height:1.4}
.wnext{white-space:nowrap;font-size:var(--t-sm)}

/* --- 4. DECISION FEED ------------------------------------------------------ */
.dfeed{display:flex;flex-direction:column}
.dfrow{display:grid;grid-template-columns:62px 66px 108px 1fr;gap:10px;align-items:start;padding:9px 10px;border-radius:9px;
  border-left:3px solid var(--line);margin-bottom:5px;background:color-mix(in srgb,var(--panel2) 45%,transparent)}
.dfrow.s-green{border-left-color:var(--green)}.dfrow.s-blue{border-left-color:var(--blue)}
.dfrow.s-amber{border-left-color:var(--amber)}
.dfrow.s-red{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 7%,transparent)}
.dft{font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);padding-top:2px;font-variant-numeric:tabular-nums}
.dfs{font-family:var(--mono);font-size:var(--t-base);font-weight:700;padding-top:1px}
.dfh{font-size:var(--t-base);line-height:1.5}

/* --- 5. POSITION CARDS ----------------------------------------------------- */
.p2grid-wrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(360px,100%),1fr));gap:12px}
.pcard2{background:var(--panel2);border:1px solid var(--line);border-left:3px solid var(--green);border-radius:12px;padding:13px 15px}
.pcard2.unprot{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 5%,var(--panel2))}
.p2top{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.p2sym{font-family:var(--mono);font-size:var(--t-lg);font-weight:750;letter-spacing:.4px}
.p2pnl{margin-left:auto;font-family:var(--mono);font-size:var(--t-md);font-weight:750;font-variant-numeric:tabular-nums}
.p2pnl em{font-style:normal;font-size:var(--t-sm);opacity:.75}
.p2grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:11px}
.p2grid>div{background:color-mix(in srgb,var(--panel) 70%,transparent);border-radius:8px;padding:7px 9px}
.p2grid em{display:block;font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--dim)}
.p2grid b{display:block;font-family:var(--mono);font-size:var(--t-md);font-weight:700;margin-top:2px;font-variant-numeric:tabular-nums}
.p2grid b.sm{font-family:var(--sans);font-size:var(--t-sm)}
.p2grid i{display:block;font-style:normal;font-size:var(--t-micro);color:var(--dim);margin-top:1px}
.p2dec{margin-top:11px;font-size:var(--t-sm);line-height:1.5}
.p2th{margin-top:6px;font-size:var(--t-sm);color:var(--dim);line-height:1.45}
.p2foot{margin-top:9px;font-size:var(--t-sm);font-weight:650;display:flex;gap:16px}

/* --- 5b. BOARD CARDS (v4.3) -------------------------------------------------
   The board used to be a table of candidates: eleven columns of digits with one-word headers,
   which is the exact thing the owner said made the app read like a log file instead of a product.
   A candidate is a small story - here is the name, here is the price that has to print, here is
   how far away that is right now, and here is what it would cost if it fired and then failed - so
   it gets a card, and the card is deliberately the same component family as the position cards
   above: same panel, same radius, same coloured left edge, same label-over-number grid. A name
   that is being watched and a name that is owned should not look like they came from two apps.

   The left edge is the state. Grey is watching. Amber (.st-near) means the price is inside 1.5%
   of the trigger and this is about to become real. Green (.st-hot) means it already triggered. */
.bsec{margin-bottom:14px}
.bwrap{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(460px,100%),1fr));gap:12px}
.bcard{background:var(--panel2);border:1px solid var(--line);border-left:3px solid var(--grey);
  border-radius:12px;padding:13px 15px}
.bcard.st-near{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 5%,var(--panel2))}
.bcard.st-hot{border-left-color:var(--green);background:color-mix(in srgb,var(--green) 7%,var(--panel2))}
.btop{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.bsym{font-family:var(--mono);font-size:var(--t-lg);font-weight:750;letter-spacing:.4px}
.bsetup{margin-top:4px;font-size:var(--t-sm);color:var(--dim);line-height:1.45}
/* The headline is the one number a reader wants before any other: how far from going live.
   .under is below the trigger and therefore still pending; .over has already cleared it. */
.bhead{margin-top:9px;font-size:var(--t-base);font-weight:650;line-height:1.5}
.bhead.under{color:var(--fg)}
.bhead.over{color:var(--green)}
.bgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:11px}
.bgrid>div{background:color-mix(in srgb,var(--panel) 70%,transparent);border-radius:8px;padding:7px 9px}
.bgrid em{display:block;font-style:normal;font-size:var(--t-micro);font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--dim)}
.bgrid b{display:block;font-family:var(--mono);font-size:var(--t-md);font-weight:700;margin-top:2px;
  font-variant-numeric:tabular-nums}
.bgrid b.sm{font-family:var(--sans);font-size:var(--t-sm);line-height:1.35}
.bfoot{margin-top:10px;font-size:var(--t-sm);color:var(--dim);line-height:1.5}
.bfoot .cdown{font-family:var(--mono);font-weight:700;color:var(--fg);font-variant-numeric:tabular-nums}
.bmiss{margin-top:5px;font-size:var(--t-sm);color:var(--dim);line-height:1.45}

/* --- 6. TODAY'S ORDERS ----------------------------------------------------- */
.aclist{display:flex;flex-direction:column;gap:5px}
/* 88px, not 62px: "10:41 AM ET" is eleven characters and the old column wrapped every single row
   onto two lines, which made an audit trail look like a stack of paragraphs. */
.acrow{display:grid;grid-template-columns:88px 92px 1fr;gap:10px;padding:9px 11px;border-radius:9px;
  border-left:3px solid var(--line);background:color-mix(in srgb,var(--panel2) 45%,transparent);font-size:var(--t-base)}
.acrow.s-green{border-left-color:var(--green)}.acrow.s-blue{border-left-color:var(--blue)}
.acrow.s-amber{border-left-color:var(--amber)}.acrow.s-red{border-left-color:var(--red)}
.act{font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);font-variant-numeric:tabular-nums}
.ackind{font-size:var(--t-label);font-weight:750;letter-spacing:.05em;text-transform:uppercase;color:var(--dim)}

/* --- 6b. THE TRADE EVENT CARD (point 10) -----------------------------------
   A filled trade is the only thing on this page that moved real money, so it is the only thing
   allowed to be this loud: a tinted panel, a coloured left edge, the symbol at headline size and
   the numbers in a grid you can read at arm's length. The compact .acrow list underneath keeps the
   order-by-order detail, deliberately quieter — it is the audit trail, not the news. */
.telist{display:flex;flex-direction:column;gap:10px;margin-bottom:14px}
.tecard{border:1px solid var(--line);border-left:4px solid var(--line);border-radius:12px;padding:13px 15px;
  background:color-mix(in srgb,var(--panel2) 60%,transparent)}
.tecard.s-green{border-left-color:var(--green);background:color-mix(in srgb,var(--green) 7%,var(--panel2))}
.tecard.s-red{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 7%,var(--panel2))}
.tecard.s-grey{border-left-color:var(--grey)}
.tehead{display:flex;align-items:baseline;gap:11px;flex-wrap:wrap;margin-bottom:11px}
.tebadge{font-size:var(--t-micro);font-weight:800;letter-spacing:.09em;text-transform:uppercase;padding:3px 9px;border-radius:999px;
  color:var(--fg);background:color-mix(in srgb,var(--fg) 12%,transparent)}
.tecard.s-green .tebadge{color:var(--green);background:color-mix(in srgb,var(--green) 16%,transparent)}
.tecard.s-red .tebadge{color:var(--red);background:color-mix(in srgb,var(--red) 16%,transparent)}
.tesym{font-size:var(--t-xl);font-weight:800;letter-spacing:.02em}
.tetime{font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);font-variant-numeric:tabular-nums}
.tesetup{font-size:var(--t-sm);color:var(--dim);text-transform:capitalize}
.tegrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(104px,100%),1fr));gap:10px 16px}
.tecl{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.5px;color:var(--dim);margin-bottom:2px}
.tecv{font-family:var(--mono);font-size:var(--t-md);font-weight:700;font-variant-numeric:tabular-nums}
.tecs{font-family:var(--sans,inherit);font-size:var(--t-label);font-weight:600;color:var(--dim)}
.teguard{margin-top:11px;padding:7px 10px;border-radius:9px;font-size:var(--t-sm);font-weight:600}
.teguard.ok{color:var(--green);background:color-mix(in srgb,var(--green) 11%,transparent)}
.teguard.bad{color:var(--red);background:color-mix(in srgb,var(--red) 13%,transparent)}
.teguard a{color:inherit;text-decoration:underline}
.tewhy{margin-top:9px;font-size:var(--t-sm);color:var(--fg);line-height:1.5}
.tewl{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.5px;color:var(--dim);font-weight:700;margin-right:6px}
.tesep{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.6px;color:var(--dim);font-weight:700;margin:0 0 7px}

/* --- 6c. TOOLTIPS (v4.3) ---------------------------------------------------
   Every number on this app is the output of a rule, and until now the only way to find out which
   rule was to read the code. The native browser 'title' attribute is not an answer: it waits a
   second, renders in the operating system's font, truncates, and never appears on a phone.

   data-tip is a real bubble — instant, styled, arrow-anchored, and it wraps to a readable width
   so a full sentence fits. It is attached to the CONTAINER of a number rather than the number
   itself, so the whole tile is a hover target instead of six characters of monospace.

   .tipdot marks elements that carry one, with a dotted underline on the label. Discoverability
   matters more than tidiness here: an explanation nobody knows exists is not an explanation. */
[data-tip]{position:relative}
[data-tip]::after{content:attr(data-tip);position:absolute;left:50%;bottom:calc(100% + 9px);transform:translateX(-50%) translateY(3px);
  width:max-content;max-width:260px;padding:8px 11px;border-radius:9px;
  background:var(--panel);color:var(--fg);border:1px solid var(--line);box-shadow:0 10px 30px rgba(0,0,0,.45);
  font-family:var(--sans);font-size:var(--t-label);font-weight:500;line-height:1.5;text-transform:none;letter-spacing:0;text-align:left;
  white-space:normal;opacity:0;pointer-events:none;transition:opacity .12s ease,transform .12s ease;z-index:70}
[data-tip]::before{content:'';position:absolute;left:50%;bottom:calc(100% + 4px);transform:translateX(-50%);
  border:5px solid transparent;border-top-color:var(--line);opacity:0;transition:opacity .12s ease;z-index:71}
[data-tip]:hover::after,[data-tip]:focus-visible::after{opacity:1;transform:translateX(-50%) translateY(0)}
[data-tip]:hover::before,[data-tip]:focus-visible::before{opacity:1}
/* Near the left and right edges the centred bubble would run off screen. */
[data-tip].tl::after{left:0;transform:translateX(0) translateY(3px)}
[data-tip].tl:hover::after{transform:translateX(0)}
[data-tip].tr::after{left:auto;right:0;transform:translateX(0) translateY(3px)}
[data-tip].tr:hover::after{transform:translateX(0)}
/* .tdn drops the bubble BELOW its element instead of above. Table headers need this: the header
   row sits at the top edge of a horizontally-scrolling box, and a bubble drawn upward is clipped
   by that box's own overflow before the reader ever sees it. */
[data-tip].tdn::after{bottom:auto;top:calc(100% + 9px);transform:translateX(-50%) translateY(-3px)}
[data-tip].tdn:hover::after,[data-tip].tdn:focus-visible::after{transform:translateX(-50%) translateY(0)}
[data-tip].tdn::before{bottom:auto;top:calc(100% + 4px);border-top-color:transparent;border-bottom-color:var(--line)}
[data-tip].tdn.tl::after{left:0;transform:translateX(0) translateY(-3px)}
[data-tip].tdn.tl:hover::after{transform:translateX(0)}
[data-tip].tdn.tr::after{left:auto;right:0;transform:translateX(0) translateY(-3px)}
[data-tip].tdn.tr:hover::after{transform:translateX(0)}

/* v5.6 — A TOOLTIP INSIDE A SCROLLING TABLE HAS TO BE DRAWN OUTSIDE IT.
   .tdn above was the first attempt at this and it is not enough, which a screenshot settled in one
   look. A container with overflow-x:auto gets overflow-y:auto whether you ask for it or not — the
   spec computes the other axis from visible to auto, there is no way to have one without the other —
   so the box clips a bubble in every direction, not just upward. Drawn downward from a header the
   sentence came out with its left third cut off by the container's left edge and its last line cut
   off by the container's bottom, which is not a smaller version of the problem, it is the same one.
   Thirty-two explanations sit inside tables, on the pages the owner actually reads: every sector
   column on Signals, every header on Opportunities, both cash definitions on Capital. They have been
   rendering into a clipped strip in production.
   So the bubble becomes a real element on <body>, positioned in viewport coordinates, which no
   ancestor's overflow can touch and which can be clamped to the screen instead of hoping. The
   pseudo-element version stays for every tooltip that is NOT inside a scroll container, because
   there it works and CSS beats JavaScript for something that has to feel instant. The suppression
   below only applies once the script has actually run and added .tipfloat: if it never runs, the old
   clipped bubble is still there, which is worse but is not a blank hover. */
.tipfl{position:fixed;left:0;top:0;z-index:90;
  width:max-content;max-width:min(320px,calc(100vw - 20px));padding:8px 11px;border-radius:9px;
  background:var(--panel);color:var(--fg);border:1px solid var(--line);box-shadow:0 10px 30px rgba(0,0,0,.45);
  font-family:var(--sans);font-size:var(--t-label);font-weight:500;line-height:1.5;
  text-align:left;text-transform:none;letter-spacing:0;white-space:normal;
  pointer-events:none;opacity:0;transition:opacity .12s ease}
.tipfl.on{opacity:1}
/* Written at exactly this weight on purpose. The ::after suppression has to outrank .tdn.tl, which
   is three classes, so it names html. The ::before suppression must NOT outrank the
   table.srt th[data-tip]::before rule, which draws the sort arrow on a sortable header — so it is
   wrapped in :where() to give away its own specificity and leave that rule winning. */
html.tipfloat .tblwrap [data-tip]::after{content:none}
html:where(.tipfloat) .tblwrap :where([data-tip])::before{content:none}
/* font-style:normal is load-bearing, not tidying. <em> is used here purely as the hook that carries
   the dotted underline, and its default italic was leaking into figures — so in a numeric column
   where some cells are hoverable and some are not, half the numbers came out italic and half
   upright for no reason a reader could infer. Mixed italics in a column of prices reads as a
   rendering fault on a platform that is supposed to look like a brokerage. */
.tipdot>em,em.tipdot,.tipdot>.tecl,th.tipdot{text-decoration:underline dotted color-mix(in srgb,var(--dim) 60%,transparent);text-underline-offset:3px;font-style:normal}
.tipdot{cursor:help}
/* v4.4 — hover-less devices used to have NO explanations at all: the rule here was display:none,
   which meant every "where did this number come from" answer was desktop-only. A phone cannot
   hover, but it can tap. layout.js now toggles .tipon on tap, so the same one sentence is
   reachable from a thumb. The bubble is pinned wider and centred on small screens because a
   260px bubble anchored to a narrow cell has nowhere to go. */
@media(hover:none){
  [data-tip]:hover::after,[data-tip]:hover::before{opacity:0}
  [data-tip].tipon::after,[data-tip].tipon::before{opacity:1}
  /* --tipdx is set by layout.js at tap time and is the whole reason a tapped explanation stays
     readable on a phone. The bubble is up to 320px wide and is centred on its anchor, so a tile in
     the right-hand column of a two-across grid centres it about 150px past the edge of the screen.
     main now clips the horizontal axis (see the overflow-x note near the top), which stopped the
     page sliding sideways but would otherwise have sliced the sentence in half instead — the same
     defect, quieter. So the script measures the bubble against the viewport and slides it back in
     by exactly as much as it overhangs. The arrow is left alone deliberately: it stays pinned to
     the number it belongs to, which is what tells the reader WHICH figure is being explained. */
  [data-tip].tipon::after{transform:translateX(calc(-50% + var(--tipdx,0px))) translateY(0);max-width:min(78vw,320px);font-size:var(--t-sm);padding:10px 13px}
  [data-tip].tipon.tl::after,[data-tip].tipon.tr::after{transform:translateX(var(--tipdx,0px)) translateY(0)}
  .tipdot::after{opacity:0}
}

/* --- 7. TIMELINE -----------------------------------------------------------
   v4.3 point 18: each slot is a <details>, so the whole day fits in the same space the four-row
   list used to take while every session can be opened to show what it actually runs. State drives
   the left edge — grey for done, red for missed, blue for the one coming next. */
.tline{display:flex;flex-direction:column;gap:6px}
.tlnext{font-size:var(--t-sm);color:var(--dim);margin-bottom:10px}
.tlnext b{color:var(--fg)}
.tl1{border-radius:9px;background:color-mix(in srgb,var(--panel2) 50%,transparent);
  border-left:3px solid var(--grey)}
.tl1>summary{display:flex;align-items:center;gap:12px;padding:9px 12px;cursor:pointer;list-style:none}
.tl1>summary::-webkit-details-marker{display:none}
.tl1>summary:hover{background:color-mix(in srgb,var(--fg) 4%,transparent);border-radius:9px}
.tl1.st-ran{opacity:.62}
.tl1.st-skipped{opacity:.5}
.tl1.st-missed{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 7%,transparent)}
.tl1.st-due{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 6%,transparent)}
.tl1.nextup{border-left-color:var(--blue);background:color-mix(in srgb,var(--blue) 8%,transparent)}
.tlt{font-family:var(--mono);font-size:var(--t-sm);font-weight:700;min-width:72px;font-variant-numeric:tabular-nums}
.tlb{flex:1}
.tlb b{font-size:var(--t-base);font-weight:650}
.tlb em{font-style:normal;font-size:var(--t-label);color:var(--dim);display:block}
.tlsteps{margin:0;padding:2px 14px 12px 46px;font-size:var(--t-sm);line-height:1.65;color:var(--dim)}
.tlsteps li{margin:2px 0}
.tlsteps li::marker{color:var(--blue);font-weight:700}
.tlnote{padding:0 14px 11px 46px;font-size:var(--t-sm);color:var(--amber);font-weight:600}

/* --- 8. SYSTEM HEALTH ------------------------------------------------------ */
.hsec summary{cursor:pointer;font-size:var(--t-sm);font-weight:650;display:flex;align-items:center;gap:9px;list-style:none}
.hsec summary::-webkit-details-marker{display:none}
.hsec summary::after{content:'▾';margin-left:auto;color:var(--dim);font-size:var(--t-sm)}
.hsec[open] summary::after{content:'▴'}
.hsec .hsub{color:var(--dim);font-weight:500;font-size:var(--t-sm)}
.hlist{display:grid;gap:9px;margin-top:12px}
.hcard{border:1px solid var(--line);border-left:3px solid #e08a3c;border-radius:11px;padding:12px 14px;background:var(--panel2)}
.hcard.s-red{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 6%,var(--panel2))}
.hh{font-size:var(--t-base);font-weight:700;line-height:1.4}
.hw{font-size:var(--t-sm);color:var(--dim);margin-top:5px;line-height:1.5}
.himp{font-size:var(--t-sm);margin-top:6px;font-weight:600}
.hfacts{margin-top:7px}
/* v4.3 point 15 — the repair button sits inside the card that describes the problem, because the
   moment someone understands a fault is the moment they want to act on it. */
.hfix{margin-top:10px;display:flex;align-items:center;gap:11px;flex-wrap:wrap}
.hfix button{font-weight:700;font-size:var(--t-sm);padding:6px 13px;border-radius:8px;border:1px solid var(--accent);
  background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--fg);cursor:pointer}
.hfix button:hover{background:color-mix(in srgb,var(--accent) 28%,transparent)}
.hfixn{font-size:var(--t-label);color:var(--dim);flex:1;min-width:180px}
.hfixn.nofix{margin-top:9px;display:block}
.hcodes{margin-top:7px}
.hcodes code{font-family:var(--mono);font-size:var(--t-micro);color:var(--dim);background:var(--panel);border:1px solid var(--line);border-radius:5px;padding:1px 5px}
.hlinks{margin-top:11px;font-size:var(--t-sm);color:var(--dim)}
@media(max-width:1400px){.rgrid,.rgrid.c4,.rgrid.c5{grid-template-columns:repeat(3,1fr)}}
@media(max-width:1000px){.rstat{grid-template-columns:1fr}
  .rs-side{border-left:none;border-top:1px solid var(--line);padding-left:0;padding-top:12px;flex-direction:row;flex-wrap:wrap;gap:12px}}
@media(max-width:700px){
  /* On a phone the status sentence and the loss meter are the whole point; everything else can
     stack. The watch table keeps its horizontal scroll rather than dropping columns — losing the
     trigger price on a phone would defeat the section. */
  .rstat{padding:13px 14px}
  .rs-state{font-size:var(--t-md)}
  .rs-doing{font-size:var(--t-md)}
  .rs-c{flex:1 1 calc(50% - 4px);min-width:0}
  .rgrid,.rgrid.c3,.rgrid.c4,.rgrid.c5{grid-template-columns:1fr 1fr;gap:7px}
  .rtile{min-height:66px;padding:9px 11px}
  .rtile b{font-size:var(--t-lg)}
  .p2grid-wrap{grid-template-columns:1fr}
  .p2grid{grid-template-columns:1fr 1fr}
  .bwrap{grid-template-columns:1fr}
  .bgrid{grid-template-columns:1fr 1fr}
  .bsym{font-size:var(--t-lg)}
  .dfrow{grid-template-columns:52px 1fr;row-gap:3px}
  .dfrow .dfd{grid-column:2}
  .dfrow .dfb{grid-column:1 / -1}
  .acrow{grid-template-columns:52px 1fr;row-gap:2px}
  .acrow .acbody{grid-column:1 / -1}
  .tegrid{grid-template-columns:repeat(2,1fr)}
  .tesym{font-size:var(--t-lg)}
  .tl1>summary{flex-wrap:wrap;gap:7px}
  .tlsteps,.tlnote{padding-left:16px}
}
/* ---------------------------------------------------------------------------
   PHONE. One column, thumb-sized targets, nothing clipped.
   The 1000px tile rule used to run until 560px while the bottom nav appeared at
   640px — so between those two widths the page had a bottom bar AND two-up
   tiles, which is exactly the width of a large phone in landscape. Both
   breakpoints are now 700px and they move together.
   ------------------------------------------------------------------------ */
@media(max-width:1500px){.swall{grid-template-columns:repeat(5,1fr)}}
@media(max-width:1150px){.swall{grid-template-columns:repeat(4,1fr)}}
@media(max-width:900px){.ckcols{grid-template-columns:1fr}.swall{grid-template-columns:repeat(3,1fr)}}
@media(max-width:700px){
  /* Two across on a phone. Three is legible but the values start truncating, and a truncated
     dollar figure is worse than one less column. */
  .swall{grid-template-columns:1fr 1fr;gap:7px}
  .stile{min-height:64px;padding:9px 11px}
  .stile b{font-size:var(--t-md)}
  .tile,.tile.kpi,.tile.s2,.tile.s3,.tile.s4,.tile.s5,.tile.s6,.tile.s7,.tile.s8,.tile.s9,
  .tile.wide,.tile.full,.tile.half{grid-column:span 12}
  /* There is no phone override for the metric sizes any more. There used to be — 24/29/34 against a
     desktop 23/27/35 — under a comment claiming a full-width tile "can afford to be larger". One
     pixel is not larger, and the hero was in fact one pixel SMALLER, so the rule contradicted its
     own reason for existing. Once both sides named the same scale the three declarations came out
     byte-identical to the base rule, which is how you find out an override was never doing anything.
     The three-tier ordering that matters is set once, above. */
  main{padding:10px 10px 78px}
  header nav{display:none}
  .subnav{overflow-x:auto;flex-wrap:nowrap;scrollbar-width:none}
  .subnav::-webkit-scrollbar{display:none}
  /* v5.6 — nowrap on the CONTAINER stops the flex line breaking; it does nothing about the flex
     items agreeing to shrink instead. Measured at 390px the rail's scrollWidth equalled its
     clientWidth exactly — nothing had overflowed, so there was nothing to scroll — because all four
     links had squeezed themselves narrow and broken their labels over two lines: "Positions &" above
     "risk", a 64px-tall bar of stacked fragments where the design is a single row you swipe. The
     scroll and the edge cue next door were both sitting there ready and neither had anything to do.
     A rail only scrolls if its contents refuse to fit. */
  .subnav a{white-space:nowrap;flex:none}
  button,input,select{padding:10px 14px;font-size:var(--t-md)}
  .themebtn{padding:3px 10px;font-size:var(--t-base)}
  .bottomnav{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:50;background:var(--panel);
    border-top:1px solid var(--line);justify-content:space-around;padding:6px 2px calc(6px + env(safe-area-inset-bottom))}
  .bottomnav a{color:var(--dim);text-align:center;font-size:var(--t-micro);text-decoration:none;flex:1;padding:2px 0}
  .bottomnav a .ic{display:block;font-size:var(--t-lg);line-height:1.15}
  .bottomnav a.on{color:var(--fg);font-weight:600}
  /* cockpit, one-handed */
  .ckdo{padding:13px 14px;gap:11px;border-radius:14px}
  .ckdo-line{font-size:var(--t-lg)}
  .ckdo-money{gap:0;width:100%;display:grid;grid-template-columns:1fr 1fr;row-gap:9px}
  .ckdo-money b{font-size:var(--t-md)}
  .dcard{padding:13px 14px;gap:11px;flex-wrap:wrap;border-radius:14px}
  .dcard .dhead{font-size:var(--t-md)}
  .dcard .dgo{margin-left:0;width:100%;flex-direction:row;justify-content:space-between;align-items:center;
    border-top:1px solid var(--line);padding-top:9px;text-align:left}
  .dcard .dcta{font-size:var(--t-base);padding:2px 0}
  .wgrid,.pgrid{grid-template-columns:1fr}
  .funnel{grid-template-columns:1fr 1fr}
  .ftime{min-width:44px;font-size:var(--t-label)}
  .kv{gap:10px}
  table{font-size:var(--t-sm)}
}
@media(max-width:400px){.ckdo-money{grid-template-columns:1fr 1fr}.funnel{grid-template-columns:1fr 1fr}}

/* ============================================================================
   v4.4 COMPONENT LAYER — 4.1 THE COCKPIT.

   The brief was two sentences long and they pull in opposite directions: three
   answers above the fold, and nothing taken away. The earlier attempt at this
   satisfied the first by violating the second, which is why it was rejected.

   The resolution is the one every real institutional platform uses: a fixed
   instrument strip, then a three-column board where each column OWNS one
   question and scrolls independently, then the full detail underneath. Nothing
   is deleted; it is ranked. The three answers are the only thing above the
   fold because the columns are height-capped, not because the data was thrown
   away.

   The visual language is deliberately quiet. Depth comes from surface value,
   dividers are hairlines, and the accent is spent only on things you can act
   on. A screen where everything is emphasised is a screen with no hierarchy,
   which is what "looks unprofessional" actually means.
   ========================================================================= */

/* --- 1. THE INSTRUMENT STRIP ----------------------------------------------
   One row, always in the same place, that answers "is it on, is it armed, when
   did it last think, when does it think next". It is not a card: it reads as
   part of the chrome, which is why it is flush and hairline-bounded rather
   than floated on a shadow. */
.cbar{display:flex;align-items:stretch;gap:0;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--radius);margin-bottom:var(--s3);overflow:hidden;box-shadow:var(--shadow-inset)}
.cbar>*{padding:9px var(--s4);display:flex;flex-direction:column;justify-content:center;gap:2px;min-width:0;
  border-right:1px solid var(--linesoft)}
.cbar>*:last-child{border-right:none}
.cbar .cb-lbl{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint)}
.cbar .cb-val{font-family:var(--mono);font-size:var(--t-base);font-weight:700;letter-spacing:var(--tight);
  font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cbar .cb-val.v-green{color:var(--green)}.cbar .cb-val.v-red{color:var(--red)}
.cbar .cb-val.v-amber{color:var(--amber)}.cbar .cb-val.v-dim{color:var(--dim)}
.cbar .cb-state{flex:0 0 auto;background:var(--panel2)}
.cbar .cb-grow{flex:1 1 auto}
.cbar .cb-act{flex:0 0 auto;flex-direction:row;align-items:center;gap:var(--s2);background:var(--panel2)}
/* The live pip. It pulses only when the trading agent is genuinely live and the market is open — a light
   that always blinks tells you nothing, so this one is off far more often than it is on. */
.pip{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--grey);flex:none;margin-right:6px;vertical-align:1px}
.pip.on{background:var(--green);box-shadow:0 0 0 0 color-mix(in srgb,var(--green) 60%,transparent);animation:pipp 2.4s ease-out infinite}
.pip.warn{background:var(--amber)}.pip.off{background:var(--red)}
@keyframes pipp{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--green) 55%,transparent)}
  70%{box-shadow:0 0 0 7px transparent}100%{box-shadow:0 0 0 0 transparent}}
@media(prefers-reduced-motion:reduce){.pip.on{animation:none}}

/* --- 2. THE THREE-ANSWER BOARD --------------------------------------------
   Column widths are 1.35 / 1 / .85 on purpose. "What should I do" is the widest
   because its rows carry a reason; "what is it waiting on" is narrowest because
   its rows are one line each. Each column caps its own height and scrolls, so
   a busy day cannot push the other two answers below the fold. */
.tri{display:grid;grid-template-columns:1.35fr 1fr .85fr;gap:var(--s3);margin-bottom:var(--s5);align-items:stretch}
.ansp{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow),var(--shadow-inset);display:flex;flex-direction:column;min-width:0;overflow:hidden}
.ansp>header{position:static;height:auto;flex-wrap:nowrap;padding:10px var(--s4);background:var(--panel2);
  border-bottom:1px solid var(--line);display:flex;align-items:center;gap:var(--s2);backdrop-filter:none}
/* The three headers are one line each, always. A question that wraps to two lines turns the top of
   the panel into a paragraph, and the eye then reads the header instead of skipping past it. */
.ansp .aq{font:var(--lbl);font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ansp .an{margin-left:auto;flex:0 0 auto;font-family:var(--sans);font-size:var(--t-micro);font-weight:600;color:var(--dim);
  background:var(--panel);border:1px solid var(--line2);border-radius:var(--radius-pill);padding:2px 8px;
  white-space:nowrap;font-variant-numeric:tabular-nums}
/* flex:1 makes the three panels finish at the same baseline — a ragged bottom edge on the most
   important row of the app is the single clearest tell of a page assembled out of widgets. */
.ansp .abody{flex:1 1 auto;padding:var(--s3) var(--s4) var(--s4);overflow-y:auto;max-height:min(52vh,520px);min-height:120px}
.ansp .abody.flush{padding:0}
.ansp>footer{padding:8px var(--s4);border-top:1px solid var(--linesoft);background:var(--sunk);
  font-size:var(--t-sm);color:var(--dim);display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.ansp .aempty{color:var(--dim);font-size:var(--t-base);line-height:1.55;padding:var(--s2) 0}
.ansp .aempty b{color:var(--fg2)}

/* --- 3. THE ACTION ROW ----------------------------------------------------
   A decision is a row, not a card. Cards inside a panel are the boxes-in-boxes
   look; a row with a severity edge and a hairline under it reads like an order
   blotter, which is the correct reference. */
.arow{display:grid;grid-template-columns:auto 1fr auto;gap:var(--s3);align-items:start;
  padding:var(--s3) 0 var(--s3) 11px;border-bottom:1px solid var(--linesoft);position:relative;
  color:inherit;text-decoration:none;transition:background .12s ease}
a.arow:hover{text-decoration:none;background:color-mix(in srgb,var(--accent) 5%,transparent)}
.arow:last-child{border-bottom:none}
.arow::before{content:'';position:absolute;left:0;top:var(--s3);bottom:var(--s3);width:3px;border-radius:2px;background:var(--line2)}
.arow.s-red::before{background:var(--red)}.arow.s-amber::before{background:var(--amber)}
.arow.s-ok::before{background:var(--green)}.arow.s-info::before{background:var(--blue)}
.arow .aic{font-size:var(--t-lg);line-height:1.25;flex:none;width:22px;text-align:center}
.arow .ah{font-size:var(--t-md);font-weight:650;letter-spacing:var(--tight);line-height:1.35}
.arow .awhy{font-size:var(--t-sm);color:var(--dim);margin-top:3px;line-height:1.5}
.arow .amet{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);margin-top:5px;
  font-variant-numeric:tabular-nums;letter-spacing:.01em}
.arow .aside{text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:none}
.arow .acta{font-size:var(--t-sm);font-weight:700;color:var(--accent);white-space:nowrap}
.arow .aclock{font-family:var(--mono);font-size:var(--t-base);font-weight:700;color:var(--red);
  font-variant-numeric:tabular-nums;letter-spacing:var(--tight);white-space:nowrap}
/* A closed window is a state, not a countdown, so it stops shouting and stops claiming the width a
   live "6m left" needs — otherwise one expired row squeezes every headline in the column. */
.arow .aclock.calm{color:var(--dim);font-size:var(--t-sm);font-weight:600}
.arow .asym{font-family:var(--mono);font-size:var(--t-sm);font-weight:700;color:var(--fg2);letter-spacing:.02em}

/* --- 4. THE DIFF FEED -----------------------------------------------------
   Timestamped from the actual last visit. The left gutter is a real rail with a
   spine so a run of events reads as a sequence rather than a stack of chips. */
.dfeed{position:relative;padding-left:0}
.dfrw{display:grid;grid-template-columns:58px 1fr;gap:var(--s3);padding:7px 0;position:relative;
  color:inherit;text-decoration:none}
a.dfrw:hover{text-decoration:none;background:color-mix(in srgb,var(--panel2) 55%,transparent)}
.dfeed::before{content:'';position:absolute;left:58px;top:6px;bottom:6px;width:1px;background:var(--linesoft)}
.dfrw .dft{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);text-align:right;
  padding-top:3px;font-variant-numeric:tabular-nums;white-space:nowrap}
.dfrw .dfc{position:relative;padding-left:14px;min-width:0}
.dfrw .dfc::before{content:'';position:absolute;left:-4px;top:6px;width:7px;height:7px;border-radius:50%;
  background:var(--panel);border:2px solid var(--line2)}
.dfrw.s-red .dfc::before{border-color:var(--red)}.dfrw.s-amber .dfc::before{border-color:var(--amber)}
.dfrw.s-ok .dfc::before{border-color:var(--green)}.dfrw.s-info .dfc::before{border-color:var(--blue)}
.dfrw .dfh{font-size:var(--t-base);line-height:1.42;font-weight:550}
.dfrw .dfs{font-size:var(--t-sm);color:var(--dim);margin-top:2px;line-height:1.45}
.dfrw .dfk{font-family:var(--mono);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);margin-left:6px}
/* The cut line: everything above it happened while you were away. */
.dfcut{display:flex;align-items:center;gap:var(--s2);margin:var(--s3) 0 var(--s2);color:var(--faint);
  font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide)}
.dfcut::after{content:'';flex:1;height:1px;background:var(--linesoft)}

/* --- 5. THE WAITING LIST --------------------------------------------------
   Each row is a gate, a countdown or a dependency. The right-hand column is
   always the answer to "for how long", because that is the only follow-up. */
.wrw{display:flex;align-items:baseline;gap:var(--s2);padding:8px 0;border-bottom:1px solid var(--linesoft);font-size:var(--t-base)}
.wrw:last-child{border-bottom:none}
.wrw .wl{min-width:0;line-height:1.42}
.wrw .wl i{display:block;font-style:normal;font-size:var(--t-sm);color:var(--dim);margin-top:2px;line-height:1.4}
.wrw .wr{margin-left:auto;font-family:var(--mono);font-size:var(--t-sm);color:var(--dim);white-space:nowrap;
  font-variant-numeric:tabular-nums;letter-spacing:var(--tight)}
.wrw .wr.v-amber{color:var(--amber)}.wrw .wr.v-red{color:var(--red)}.wrw .wr.v-green{color:var(--green)}

/* --- 6. METRIC PRIMITIVES -------------------------------------------------
   The institutional pattern for a row of figures is dividers, not boxes. .mrow
   lays out N metrics with hairlines between them; every value is mono and
   tabular so the row scans vertically as well as horizontally. */
.mrow{display:grid;gap:0;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;box-shadow:var(--shadow-inset);grid-auto-flow:column;grid-auto-columns:1fr}
.mrow.m3{grid-template-columns:repeat(3,1fr);grid-auto-flow:row}
.mrow.m4{grid-template-columns:repeat(4,1fr);grid-auto-flow:row}
.mrow.m5{grid-template-columns:repeat(5,1fr);grid-auto-flow:row}
.mrow.m6{grid-template-columns:repeat(6,1fr);grid-auto-flow:row}
.metric{padding:11px var(--s4);border-right:1px solid var(--linesoft);min-width:0;display:flex;flex-direction:column;gap:3px}
.metric:last-child{border-right:none}
/* A six-cell funnel in a three-wide grid wraps to two rows, so the grid needs the hairlines a
   single row gets for free: no right border on the last column, a top border on the second row. */
.mrow.m3>.metric:nth-child(3n){border-right:none}
.mrow.m3>.metric:nth-child(n+4){border-top:1px solid var(--linesoft)}
/* Metrics nested inside one of the three answer panels sit in a much narrower column than the
   full-width rows they were designed for, so they get tighter gutters and no letter-spacing —
   otherwise "TRIGGERED" ellipsises to "TRIGGER…", which is exactly the sort of small sloppiness
   that makes an app feel unfinished. */
.ansp .mrow>.metric{padding:9px 11px}
.ansp .mrow>.metric .ml{letter-spacing:.01em}
.metric .ml{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.metric .mv{font-family:var(--mono);font-size:var(--t-lg);font-weight:700;line-height:1.2;
  letter-spacing:var(--tight);font-variant-numeric:tabular-nums}
.metric .mv.sm{font-size:var(--t-base)}
.metric .md{font-size:var(--t-micro);color:var(--dim);line-height:1.35;font-variant-numeric:tabular-nums}
.metric .mv.v-green{color:var(--green)}.metric .mv.v-red{color:var(--red)}
.metric .mv.v-amber{color:var(--amber)}.metric .mv.v-dim{color:var(--dim)}
/* A section rule. Below the fold everything is grouped under one of these rather than being
   another card, so the page reads as one document with chapters instead of a wall of panels. */
.sect{display:flex;align-items:baseline;gap:var(--s3);margin:var(--s6) 0 var(--s3)}
.sect h3{margin:0;font-size:var(--t-md);font-weight:700;letter-spacing:var(--tight);color:var(--fg)}
.sect .sx{font-size:var(--t-sm);color:var(--dim)}
.sect .sl{margin-left:auto;font-size:var(--t-sm);font-weight:650;white-space:nowrap}
.sect::before{content:'';position:absolute}
.sectrule{height:1px;background:var(--line);margin:0 0 var(--s3)}

/* --- 7. ONE TRADE, ONE PAGE (the episode story) --------------------------- */
.ephead{display:flex;align-items:flex-start;gap:var(--s4);flex-wrap:wrap;background:var(--panel);
  border:1px solid var(--line);border-radius:var(--radius);padding:var(--s4) var(--s5);margin-bottom:var(--s3);
  box-shadow:var(--shadow),var(--shadow-inset)}
.ephead .epsym{font-family:var(--mono);font-size:var(--t-2xl);font-weight:700;letter-spacing:var(--tight);line-height:1.05}
.ephead .epmeta{font-size:var(--t-sm);color:var(--dim);margin-top:4px}
.ephead .epr{margin-left:auto;text-align:right}
.ephead .epr .epv{font-family:var(--mono);font-size:var(--t-2xl);font-weight:700;letter-spacing:var(--tight);
  font-variant-numeric:tabular-nums;line-height:1.05}
.ephead .epr .epl{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint);margin-top:3px}
/* The spine. A trade's life is a sequence, so it gets a real vertical rail with typed nodes:
   where the idea came from, the thesis, the gates, the entry, each management action, the exit,
   the autopsy. This is the connective tissue the brief says only exists in your head. */
.epspine{position:relative;margin:var(--s3) 0 0;padding-left:0}
.epspine::before{content:'';position:absolute;left:104px;top:10px;bottom:10px;width:1px;background:var(--line)}
.epn{display:grid;grid-template-columns:104px 1fr;gap:0;position:relative;padding:0 0 var(--s4)}
/* The gutter WRAPS. A trade that ran twelve days needs the date as well as the time on every node,
   and a nowrap timestamp wider than the gutter does not clip — it overflows to the right and lands
   on top of the kicker. Wrapping right-aligned is the only version of this that cannot break. */
.epn .ent{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);text-align:right;padding:3px var(--s3) 0 0;
  font-variant-numeric:tabular-nums;line-height:1.5}
.epn .enc{position:relative;padding-left:var(--s5);min-width:0}
.epn .enc::before{content:'';position:absolute;left:-5px;top:4px;width:11px;height:11px;border-radius:50%;
  background:var(--panel);border:2px solid var(--line2);z-index:1}
.epn.n-idea .enc::before{border-color:var(--violet)}
.epn.n-gate .enc::before{border-color:var(--blue)}
.epn.n-entry .enc::before{border-color:var(--green)}
.epn.n-manage .enc::before{border-color:var(--amber)}
.epn.n-exit .enc::before{border-color:var(--red)}
.epn.n-post .enc::before{border-color:var(--teal)}
.epn .enh{font-size:var(--t-md);font-weight:650;letter-spacing:var(--tight);line-height:1.35}
.epn .enk{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint);margin-bottom:3px}
.epn .enb{font-size:var(--t-base);color:var(--fg2);margin-top:5px;line-height:1.6}
.epn .enb p{margin:0 0 7px}.epn .enb p:last-child{margin-bottom:0}
/* The fact list under a node. A grid rather than a paragraph, because these are figures the eye
   scans down a column, and it auto-fills so the same markup works at 390px and at 1440px. */
.epn .enf{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(136px,100%),1fr));gap:0;margin-top:var(--s3);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden;background:var(--panel2)}
.epn .enf>div{padding:7px 11px;border-right:1px solid var(--linesoft);border-bottom:1px solid var(--linesoft);min-width:0}
/* Labels and values both WRAP rather than ellipsise. A truncated figure is a lie in a way a
   two-line one is not: DISAGREED WITH T and claude-haiku-4 both read as complete values that
   happen to be odd, and on a page whose whole promise is that no number is a mystery, silently
   eating the end of one is the worst available failure. Rows in a grid equalise their height,
   so a single wrapped cell costs a few pixels and nothing else. */
.epn .enf>div>span{display:block;font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);margin-bottom:2px;line-height:1.35;overflow-wrap:break-word}
.epn .enf>div>b{font-family:var(--mono);font-size:var(--t-sm);font-weight:650;letter-spacing:var(--tight);
  font-variant-numeric:tabular-nums;color:var(--fg);display:block;line-height:1.4;overflow-wrap:anywhere}
/* An inferred node says so on its own face. A story page that silently guesses which board row
   produced a trade is worse than one that admits it, because the guess is invisible. */
.epn .eninf{display:inline-block;font:var(--lbl);font-size:var(--t-nano);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--amber);border:1px solid color-mix(in srgb,var(--amber) 40%,transparent);border-radius:var(--radius-pill);
  padding:1px 6px;margin-left:7px;vertical-align:2px;font-weight:700}
.epn .enl{margin-top:var(--s2);font-size:var(--t-sm);font-weight:600}
/* The phone treatment for this page is NOT here — it lives in the one shared phone block further
   down, with the rest of the responsive rules. A second query for the same elements would sit
   earlier in the sheet and quietly lose every collision to that block, which is exactly the kind
   of bug that only shows up on the device. One place, on purpose. */
/* Gate ledger. "Which gates it passed and which it BARELY passed" is the whole point, so margin
   is a first-class column and a thin margin is coloured amber even though the gate passed. */
.gl{display:grid;grid-template-columns:1fr auto auto auto;gap:0;margin-top:var(--s2);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.gl>div{padding:6px 11px;border-bottom:1px solid var(--linesoft);font-size:var(--t-sm);display:flex;align-items:center}
.gl>div:nth-last-child(-n+4){border-bottom:none}
.gl .glh{font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint);background:var(--panel2)}
.gl .gv{font-family:var(--mono);font-variant-numeric:tabular-nums;justify-content:flex-end;letter-spacing:var(--tight)}
.gl .gs{justify-content:center;font-family:var(--mono);font-size:var(--t-micro);font-weight:700;letter-spacing:var(--wide)}
.gl .gs.g-pass{color:var(--green)}.gl .gs.g-thin{color:var(--amber)}.gl .gs.g-fail{color:var(--red)}
.gl .gs.g-na{color:var(--faint)}
.glbar{position:relative;height:5px;border-radius:3px;background:var(--panel3);min-width:56px;overflow:hidden;align-self:center}
.glbar i{display:block;height:100%;border-radius:3px;background:var(--green)}
.glbar.thin i{background:var(--amber)}.glbar.fail i{background:var(--red)}

/* --- 8. THE SIGNAL ENGINE (4.2) ------------------------------------------
   A score with invisible components is a horoscope. Everything here exists so
   the number can be taken apart on screen. */
.scorehead{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap}
.scorebig{font-family:var(--mono);font-size:var(--t-3xl);font-weight:700;letter-spacing:var(--tight);
  font-variant-numeric:tabular-nums;line-height:1}
.scorebig.q1{color:var(--green)}.scorebig.q2{color:var(--fg)}
.scorebig.q3{color:var(--amber)}.scorebig.q4{color:var(--red)}
/* The stacked contribution bar: one segment per component, width proportional to how many of the
   score's points that component actually contributed. Reading it left to right tells you why. */
.stack{display:flex;height:11px;border-radius:var(--radius-pill);overflow:hidden;background:var(--panel3);flex:1 1 220px;min-width:160px}
.stack i{display:block;height:100%}
.stack i.k-trend{background:var(--blue)}.stack i.k-momentum{background:var(--teal)}
.stack i.k-relativeStrength{background:var(--green)}.stack i.k-quality{background:var(--violet)}
.stack i.k-risk{background:var(--amber)}
.stack i.k-gap{background:var(--panel3)}
.klegend{display:flex;gap:var(--s3);flex-wrap:wrap;margin-top:var(--s2);font-size:var(--t-micro);color:var(--dim)}
.klegend span{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.klegend u{width:8px;height:8px;border-radius:2px;text-decoration:none;flex:none}
.kdot{width:8px;height:8px;border-radius:2px;display:inline-block;flex:none;margin-right:5px;vertical-align:0}
.kdot.k-trend{background:var(--blue)}.kdot.k-momentum{background:var(--teal)}
.kdot.k-relativeStrength{background:var(--green)}.kdot.k-quality{background:var(--violet)}
.kdot.k-risk{background:var(--amber)}
/* Component ledger: raw value, cross-sectional points, weight, contribution. Four columns because
   those are exactly the four numbers needed to reproduce the score by hand. */
.cledger{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
.cledger th{font-size:var(--t-micro)}
.cledger td.cn{font-weight:650}
.cledger tr.uncov td{color:var(--faint)}
.cledger tr.uncov td.cn::after{content:' — no data';font-family:var(--sans);font-size:var(--t-micro);color:var(--faint);font-weight:400}
/* Relative-strength leaderboard. A rank needs a visual length or it is just a number in a list. */
.lb{display:flex;flex-direction:column}
.lbr{display:grid;grid-template-columns:26px minmax(min(64px,100%),auto) 1fr auto;gap:var(--s3);align-items:center;
  padding:6px 0;border-bottom:1px solid var(--linesoft);font-size:var(--t-sm)}
.lbr:last-child{border-bottom:none}
.lbr .lbn{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);text-align:right;font-variant-numeric:tabular-nums}
.lbr .lbs{font-family:var(--mono);font-weight:700;letter-spacing:.02em}
.lbr .lbv{font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right;letter-spacing:var(--tight)}
.lbbar{height:6px;border-radius:3px;background:var(--panel3);overflow:hidden;position:relative}
.lbbar i{display:block;height:100%;border-radius:3px;background:var(--green)}
.lbbar i.neg{background:var(--red)}
/* A bar that can go both ways from a centre line. Relative strength is signed, and drawing it
   one-directional hides the sign, which is the most important part. */
.bibar{height:6px;border-radius:3px;background:var(--panel3);position:relative;overflow:hidden}
.bibar::before{content:'';position:absolute;left:50%;top:0;bottom:0;width:1px;background:var(--line2)}
.bibar i{position:absolute;top:0;bottom:0;border-radius:2px}
.bibar i.up{left:50%;background:var(--green)}
.bibar i.dn{right:50%;background:var(--red)}
/* Catalyst calendar. Days as columns, one chip per event, colour by how much it constrains us. */
.cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:var(--s1);border:1px solid var(--line);
  border-radius:var(--radius);overflow:hidden;background:var(--line)}
.cald{background:var(--panel);padding:8px 9px;min-height:88px;display:flex;flex-direction:column;gap:4px}
.cald.off{background:var(--sunk)}
.cald .cdd{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);font-variant-numeric:tabular-nums;
  display:flex;align-items:baseline;gap:5px}
.cald.today{box-shadow:inset 0 0 0 1px var(--accent)}
.cald.today .cdd{color:var(--accent);font-weight:700}
.cev{font-size:var(--t-micro);font-family:var(--mono);border-radius:var(--radius-sm);padding:2px 5px;
  border:1px solid var(--line2);background:var(--panel2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:var(--fg2);letter-spacing:.01em}
.cev.e-earn{border-color:color-mix(in srgb,var(--red) 50%,transparent);background:var(--red-soft);color:var(--red)}
.cev.e-div{border-color:color-mix(in srgb,var(--blue) 45%,transparent);background:var(--accent-soft);color:var(--blue)}
.cev.e-idx{border-color:color-mix(in srgb,var(--violet) 45%,transparent);background:color-mix(in srgb,var(--violet) 12%,transparent);color:var(--violet)}
.cev.e-lock{border-color:color-mix(in srgb,var(--amber) 45%,transparent);background:var(--amber-soft);color:var(--amber)}
/* The honesty box. When the sample is too thin to conclude anything, the app has to say so in the
   same place it shows the number — not in a footnote. */
.honest{border:1px dashed var(--line2);border-radius:var(--radius-sm);padding:9px 12px;margin:var(--s2) 0;
  font-size:var(--t-sm);color:var(--dim);line-height:1.5;background:color-mix(in srgb,var(--panel2) 60%,transparent)}
.honest b{color:var(--amber)}
.honest.proven{border-style:solid;border-color:color-mix(in srgb,var(--green) 40%,transparent);background:var(--green-soft)}
.honest.proven b{color:var(--green)}
/* Rank-only badge. Mario's decision: the score sorts, it never blocks. The badge is on the page
   so that decision is visible to whoever reads it next, including me. */
.rankonly{display:inline-flex;align-items:center;gap:5px;font:var(--lbl);font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--dim);border:1px solid var(--line2);border-radius:var(--radius-pill);padding:2px 9px}

/* --- 9. NESTED NAVIGATION -------------------------------------------------
   Five top-level destinations. The nested entries live in a hover/focus panel
   on the desktop and in the section subnav everywhere else. */
  transform:rotate(45deg) translateY(-1px);opacity:.5}
  background:var(--panel);border:1px solid var(--line2);border-radius:var(--radius);box-shadow:var(--shadow-lg);padding:6px}
  color:var(--fg2);font-size:var(--t-base);font-weight:600;letter-spacing:0}
/* v5.22.0 — the secondary shelf. A rule plus a quiet word, not a heading: the divider has to be
   legible enough to explain the break and quiet enough that it never competes with the two or three
   destinations above it. The secondary links keep their hints — demoted is not the same as
   undocumented, and a page nobody can identify is why the menu needed splitting in the first
   place — but sit a shade back until hovered, so the eye lands above the line by default. */
  font-size:var(--t-micro);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}

/* --- 10. PHONE, PROPERLY -------------------------------------------------
   The four things Mario asked to work one-handed: the three answers plus
   alerts, approve/reject, the kill switch, and positions with P&L. */
@media(max-width:1150px){.tri{grid-template-columns:1fr 1fr}.tri>.ansp:first-child{grid-column:1 / -1}}
@media(max-width:900px){
  .tri{grid-template-columns:1fr}
  .ansp .abody{max-height:none}
  .cbar{flex-wrap:wrap}
  .cbar>*{flex:1 1 auto}
  .mrow.m5,.mrow.m6{grid-template-columns:repeat(3,1fr)}
  .metric:nth-child(3n){border-right:none}
  .cal{grid-template-columns:repeat(7,minmax(0,1fr))}
  .cald{min-height:72px}
}
@media(max-width:700px){
  /* The alert bar had NO phone rules at all: a row of pills that wrapped to four lines and pushed
     the whole page down. It now scrolls sideways in one row and stays out of the way, which is the
     only behaviour that leaves the three answers above the fold on a phone. */
  .alertbar{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;padding:6px 10px;gap:6px}
  .alertbar::-webkit-scrollbar{display:none}
  .alertbar a{flex:none;font-size:var(--t-sm);padding:4px 11px}
  header{height:auto;padding:8px 12px}
  .ticker .tk{padding:6px 11px}
  /* Instrument strip becomes a 2-up card. Mode and kill stay on the first row because they are the
     two facts that decide whether anything else on the screen matters. */
  .cbar{display:grid;grid-template-columns:1fr 1fr;border-radius:var(--radius)}
  .cbar>*{padding:8px 11px;border-right:1px solid var(--linesoft);border-bottom:1px solid var(--linesoft)}
  .cbar>.cb-act{grid-column:1 / -1;border-right:none;border-bottom:none;justify-content:space-between}
  .cbar .cb-val{font-size:var(--t-sm)}
  .ansp>header{padding:9px 13px}
  .ansp .abody{padding:11px 13px 13px}
  .arow{grid-template-columns:auto 1fr;row-gap:var(--s2);padding-left:10px}
  .arow .aside{grid-column:1 / -1;flex-direction:row;justify-content:space-between;align-items:center;
    width:100%;border-top:1px solid var(--linesoft);padding-top:8px}
  .arow .ah{font-size:var(--t-base)}
  .arow .acta{font-size:var(--t-base)}
  .dfrw{grid-template-columns:46px 1fr;gap:var(--s2)}
  .dfeed::before{left:46px}
  .mrow,.mrow.m3,.mrow.m4,.mrow.m5,.mrow.m6{grid-template-columns:1fr 1fr;grid-auto-flow:row}
  .metric{padding:9px 12px;border-right:1px solid var(--linesoft);border-bottom:1px solid var(--linesoft)}
  .metric:nth-child(2n){border-right:none}
  .metric .mv{font-size:var(--t-md)}
  .sect{margin:var(--s5) 0 var(--s2)}
  .sect h3{font-size:var(--t-base)}
  .ephead{padding:13px 14px;gap:var(--s3)}
  .ephead .epsym{font-size:var(--t-xl)}
  .ephead .epr{margin-left:0;text-align:left;width:100%;border-top:1px solid var(--linesoft);padding-top:9px}
  .ephead .epr .epv{font-size:var(--t-xl)}
  /* 68px, not 60. The node stamp is one unbreakable token once it wraps to its second line, and
     that token is now the time plus ET rather than the time alone, which needs about 54px of
     glyph before padding. At 60 it slid under the node dot. */
  .epspine::before{left:68px}
  .epn{grid-template-columns:68px 1fr}
  .epn .ent{padding-right:var(--s2)}
  .epn .enc{padding-left:var(--s4)}
  /* Two columns of figures at 390px. Left to auto-fill, a 136px minimum would drop to one. */
  .epn .enf{grid-template-columns:1fr 1fr}
  .epn .enf>div{padding:6px 9px}
  /* Three columns on a phone, and the whole "room used" column comes out — CELLS, not just the
     bars inside them. Hiding the bar and leaving its div behind puts four items in a three-column
     grid, which silently slides every following row one place left. */
  .gl{grid-template-columns:1fr auto auto;font-size:var(--t-sm)}
  .gl .glb{display:none}
  /* Every pixel taken back from padding is a pixel the rule name gets, and the rule name is the
     part a person actually reads. */
  .gl>div{padding:6px 8px}
  .gl .gs{font-size:var(--t-micro);padding-left:6px;padding-right:6px}
  /* The trade picker keeps every column on a desktop. On a phone eight of them means a sideways
     scroll, which is the squeezed-desktop failure this release exists to stop, so the three the
     story page repeats anyway come off: setup, the closed stamp, and the trailing link that goes
     to the same place the symbol already does. Nothing here is the only copy of itself. */
  .epick th:nth-child(3),.epick td:nth-child(3),
  .epick th:nth-child(5),.epick td:nth-child(5),
  .epick th:nth-child(8),.epick td:nth-child(8){display:none}
  /* The five that remain are 12px wider than the card at 390px, and 12px is the difference between
     reading the dollars column and seeing it disappear off the right edge. Take it from padding. */
  .epick th,.epick td{padding-left:6px;padding-right:6px}
  .scorebig{font-size:var(--t-2xl)}
  .cal{grid-template-columns:1fr;background:var(--line)}
  .cald{min-height:0;flex-direction:row;align-items:center;flex-wrap:wrap;gap:6px}
  .cald.off{display:none}
  .cald .cdd{min-width:72px}
  .lbr{grid-template-columns:22px minmax(min(56px,100%),auto) 1fr auto;gap:var(--s2)}
}

/* ============================================================================
   v4.5.0 — THE TODAY PAGE, SIX SECTIONS.
   Everything below serves one rule: this must read like the best brokerage
   software, which means numbers are monospaced and tabular so decimals line up,
   labels are small and quiet, values are large and calm, and colour is spent
   only on money and on state. No card announces itself with a border it did not
   earn — depth is surface value, exactly as the token layer above intends.
   ========================================================================= */

/* --- the numbered section head ------------------------------------------- */
.t5h{display:flex;align-items:baseline;gap:var(--s3);margin:var(--s6) 0 var(--s3);padding:0 2px}
.t5h:first-child{margin-top:var(--s2)}
.t5n{flex:0 0 auto;width:21px;height:21px;border-radius:6px;background:var(--panel3);border:1px solid var(--line2);
  color:var(--dim);font:700 var(--t-micro)/20px var(--mono);text-align:center;letter-spacing:0}
.t5t{font-size:var(--t-lg);font-weight:680;letter-spacing:var(--tight);color:var(--fg)}
.t5s{font-size:var(--t-sm);color:var(--dim);flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t5l{font-size:var(--t-sm);font-weight:600;color:var(--dim);white-space:nowrap}
.t5l:hover{color:var(--accent);text-decoration:none}

/* --- 1. autopilot --------------------------------------------------------- */
.ap{border-left:3px solid var(--line2)}
.ap.s-green{border-left-color:var(--green)}
.ap.s-amber{border-left-color:var(--amber)}
.ap.s-red{border-left-color:var(--red)}
.aptop{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s2)}
.apdot{width:9px;height:9px;border-radius:50%;background:var(--grey);flex:0 0 auto}
.apdot.d-green{background:var(--green);box-shadow:0 0 0 3px color-mix(in srgb,var(--green) 20%,transparent)}
.apdot.d-amber{background:var(--amber);box-shadow:0 0 0 3px color-mix(in srgb,var(--amber) 20%,transparent)}
.apdot.d-red{background:var(--red);box-shadow:0 0 0 3px color-mix(in srgb,var(--red) 20%,transparent)}
.apword{font:700 var(--t-label)/1 var(--sans);letter-spacing:var(--wide);text-transform:uppercase;color:var(--fg2)}
.apclock{font:600 var(--t-label)/1 var(--sans);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-left:auto}
.apsent{margin:0 0 var(--s3);font-size:var(--t-md);line-height:1.55;color:var(--fg);max-width:78ch}
.apconf{display:flex;gap:var(--s2);align-items:flex-start;margin:0 0 var(--s3);padding:10px 13px;border-radius:var(--radius-sm);
  background:var(--amber-soft);border:1px solid color-mix(in srgb,var(--amber) 35%,transparent);
  font-size:var(--t-sm);line-height:1.5;color:var(--fg2)}
.apci{flex:0 0 auto;width:16px;height:16px;border-radius:50%;background:var(--amber);color:#0b0d10;
  font:800 var(--t-micro)/16px var(--sans);text-align:center;margin-top:1px}
.apregime{margin:0 0 var(--s3);font-size:var(--t-sm);color:var(--dim)}
.apregime b{color:var(--fg2)}
/* Six facts, and on a wide screen they are one row — the shape is the point, a status you can
   photograph. They wrap to three and then two rather than ever scrolling sideways. */
.apgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.apf{background:var(--panel2);padding:10px 12px;min-width:0}
.apfl{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:5px}
.apfv{font-size:var(--t-base);font-weight:650;letter-spacing:var(--tight);line-height:1.3;overflow-wrap:anywhere}
.apfs{font-size:var(--t-micro);color:var(--dim);margin-top:3px;line-height:1.35;overflow-wrap:anywhere}
.apfv.v-green{color:var(--green)}.apfv.v-amber{color:var(--amber)}.apfv.v-red{color:var(--red)}
.apfv.v-blue{color:var(--fg)}.apfv.v-dim{color:var(--dim)}
/* v5.6 — ONE ROW, ONE BASELINE.
   Six labels of different lengths in six equal columns, and at 1440 exactly one of them — OWNER
   ACTION REQUIRED — needed a second line. Nothing was wrong with that cell. What was wrong was the
   other five, whose values then sat sixteen pixels higher than its own. A status strip meant to be
   read in one glance cannot put its numbers on two baselines because of a word, and the same thing
   happens to the account snapshot below whenever a label runs long.
   Subgrid is the exact tool: each cell hands its three rows back to the grid, so label, value and
   caption line up across all six however long any one label runs, and no cell reserves room it does
   not use. The one-pixel gaps that draw the dividers fall inside the span, where the cell's own
   background paints over them, so the only rule still visible is the one between bands after the
   grid wraps to three columns and then two — which is the divider that ought to be there.
   Where subgrid is missing the fallback reserves two label lines instead: a little air on a wide
   screen, bought for the same alignment. That is the right trade in that order, not the first
   choice. Both blocks must move together — deleting only the @supports leaves ragged baselines
   back on the busiest card in the app. */
@supports (grid-template-rows:subgrid){
  .apf,.sn{display:grid;grid-row:span 3;grid-template-rows:subgrid;align-content:start}
}
@supports not (grid-template-rows:subgrid){
  .apfl,.snl{min-height:calc(var(--t-label)*2.6)}
}
.apblock{margin-top:var(--s3);padding:12px 14px;border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--line)}
.apblock.apneed{background:var(--amber-soft);border-color:color-mix(in srgb,var(--amber) 38%,transparent)}
/* v5.5 — the "also true right now" block, and it is quieter than every other block on this card on
   purpose. These are the facts that did NOT win the headline, so they must not out-shout the one
   that did; the alternative used to be dropping them entirely, which is how a late heartbeat under
   a pause reached the owner only via a different page. Dashed and dim: present, last to be read. */
.apblock.apalso{background:transparent;border-style:dashed}
.apalso .apbt{font-weight:500;font-size:var(--t-sm);color:var(--fg2);line-height:1.55}
.apalso .apbt+.apbt{margin-top:4px}
.apalso .apbt::before{content:"\00B7";color:var(--faint);margin-right:7px}
.apbh{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:7px}
.apbr+.apbr{margin-top:9px;padding-top:9px;border-top:1px solid var(--linesoft)}
.apbt{font-size:var(--t-base);font-weight:620;color:var(--fg)}
.apbs{font-size:var(--t-sm);color:var(--fg2);margin-top:2px;line-height:1.5}
.apbn{font-size:var(--t-sm);color:var(--dim);margin-top:2px}
/* v6.126.0 — the evidence behind an operator hold, and the condition that ends it. Indented under
   the headline because it is subordinate to it, and full-width because it is prose, not a chip. */
.apbe{font-size:var(--t-sm);color:var(--fg2);line-height:1.55;margin-top:8px;padding-left:10px;
  border-left:2px solid var(--linesoft);max-width:82ch}
.apbel{display:block;font-size:var(--t-micro);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--dim);font-weight:700;margin-bottom:2px}
/* v5.1.1 self-repair line: the app says what it is already doing about the pause, in blue rather
   than amber, because it is work in progress and not another warning. */
.apfix1{display:flex;gap:8px;align-items:flex-start;margin-top:10px;padding:8px 10px;border-radius:var(--radius-sm);
  background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--blue) 30%,transparent);
  font-size:var(--t-sm);color:var(--fg2);line-height:1.5}
.apfix1i{flex:none;font-weight:700;color:var(--blue)}
.apgo{display:inline-block;margin-top:8px;font-size:var(--t-sm);font-weight:650}
.apfix{margin-top:var(--s3);padding:12px 14px;border-radius:var(--radius-sm);
  background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 38%,transparent)}
.apfixt{font-size:var(--t-sm);color:var(--fg2);margin-bottom:9px;line-height:1.5}
.apfixb{font:650 var(--t-sm)/1 var(--sans);color:#fff;background:var(--accent);border:0;
  border-radius:var(--radius-sm);padding:9px 15px;cursor:pointer}
.apfixb:hover{filter:brightness(1.1)}
.apfixn{font-size:var(--t-micro);color:var(--dim);margin-left:10px}

/* --- 2. account snapshot -------------------------------------------------- */
.snapgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.sn{background:var(--panel2);padding:13px 14px 12px;min-width:0}
/* The label wraps rather than truncating: "Maximum current risk" clipped to "Maximum current …"
   is a worse outcome than a two-line label, and the six cells are already the same height. */
.snl{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:6px;
  line-height:1.3;min-height:1.3em}
.snv{font:700 var(--t-xl)/1.1 var(--mono);letter-spacing:var(--tight);font-variant-numeric:tabular-nums;color:var(--fg)}
.sns{font-size:var(--t-micro);color:var(--dim);margin-top:5px;line-height:1.35;min-height:14px}
.sn.pos .snv{color:var(--green)}.sn.neg .snv{color:var(--red)}.sn.warn .snv{color:var(--amber)}
/* v5.22.0 — the one cell of the six holding a word rather than a figure. Tabular mono exists so
   columns of numbers line up; applied to "Degraded" it just reads as a machine talking. */
.sn.txt .snv{font-family:inherit;letter-spacing:0;font-size:var(--t-lg)}
/* The remainder, stated where the six figures end. Deliberately not a bar: a bar invites you to
   read a proportion, and the useful fact here is an absolute number of dollars. */
.rgauge{margin-top:var(--s3);padding:11px 13px;border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--line)}
.rgl{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:600}
.rgv{font:700 var(--t-2xl)/1.1 var(--mono);font-variant-numeric:tabular-nums;letter-spacing:var(--tight);color:var(--green);margin-top:3px}
.rgv.neg{color:var(--red)}
.rgs{font-size:var(--t-sm);color:var(--fg2);margin-top:4px;line-height:1.45}
.rgno{font-size:var(--t-label);color:var(--amber);margin-top:5px}

/* v5.22.0 — THE EQUITY CURVE. The SVG stretches with preserveAspectRatio=none, so every stroke
   would stretch with it; vector-effect:non-scaling-stroke on each path is what keeps the line one
   pixel wide at any card width. The labels are ordinary HTML outside the SVG for the same reason —
   text inside a non-uniformly scaled viewBox renders as soup. */
.cv .cvhead{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-bottom:9px}
.cvtfs{display:flex;gap:2px;flex-wrap:wrap}
.cvtf{padding:3px 9px;border-radius:var(--radius-sm);font-size:var(--t-micro);font-weight:600;color:var(--fg2);letter-spacing:.03em}
.cvtf:hover{background:var(--panel2);text-decoration:none}
.cvtf.on{background:var(--accent-soft);color:var(--fg)}
.cvspy{margin-left:auto;padding:3px 9px;border-radius:var(--radius-sm);border:1px solid var(--line2);
  font-size:var(--t-micro);font-weight:600;color:var(--faint)}
.cvspy:hover{color:var(--fg);text-decoration:none}
.cvspy.on{color:var(--fg);border-color:var(--accent)}
.cvnums{display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;margin-bottom:7px}
.cvchg{font:700 var(--t-2xl)/1 var(--mono);font-variant-numeric:tabular-nums;letter-spacing:var(--tight)}
.cvchg.pos{color:var(--green)}.cvchg.neg{color:var(--red)}
/* Neither green nor red: the whole point is that we do not know which it is. */
.cvchg.unk{color:var(--fg2);font-family:inherit;font-size:var(--t-lg);letter-spacing:0}
.cvspyv{font:600 var(--t-md)/1 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg2)}
.cvlbl{font-size:var(--t-micro);color:var(--faint)}
.cvsep{width:1px;height:14px;background:var(--line2);margin:0 3px}
.cvbeat{font-size:var(--t-label);font-weight:600;padding:2px 7px;border-radius:99px;background:var(--panel2)}
.cvbeat.pos{color:var(--green)}.cvbeat.neg{color:var(--amber)}
.cvbox{height:132px}
.cvbox svg{width:100%;height:100%;display:block;overflow:visible}
.cvzero{stroke:var(--line2);stroke-width:1;stroke-dasharray:3 3}
.cvline{stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.cvline.up{stroke:var(--green)}.cvline.dn{stroke:var(--red)}
/* The benchmark is thinner and dashed on purpose: it is the reference, not the subject, and two
   solid lines of equal weight make the reader work out which one is their money. */
.cvspyline{stroke:var(--dim);stroke-width:1.5;stroke-dasharray:4 3;opacity:.85}
.cvfoot{display:flex;gap:var(--s3);flex-wrap:wrap;margin-top:7px;font-size:var(--t-micro);color:var(--faint)}
.cvwarn{border-bottom:1px dotted var(--line2);cursor:help}
.cvbad{color:var(--amber);border-bottom:1px dotted var(--amber);cursor:help}
/* The detection, as a repair rather than a permanent warning. */
.cvfix{margin-top:9px;padding:10px 12px;border-radius:var(--radius-sm);border:1px solid color-mix(in srgb,var(--amber) 42%,var(--line));
  background:color-mix(in srgb,var(--amber) 7%,transparent);display:flex;flex-wrap:wrap;align-items:center;gap:9px}
.cvfixt{flex:1 1 260px;font-size:var(--t-sm);line-height:1.5;color:var(--fg2)}
.cvfixb{border-color:var(--amber);color:var(--amber);font-weight:650}
.cvfixn{flex:1 1 100%;font-size:var(--t-micro);color:var(--faint);line-height:1.5}

/* v5.22.1 — WHAT IT DID TODAY. Buying and selling is the only thing this machine exists to do, and
   until now it appeared on the home page as a grey timeline row. The left border carries the
   verdict so a closed loss is identifiable before a single number is read. */
.tevlist{display:flex;flex-direction:column;gap:var(--s3)}
.tev{border:1px solid var(--line);border-left-width:3px;border-radius:var(--radius-sm);padding:11px 13px;background:var(--panel2)}
.tev.s-green{border-left-color:var(--green)}
.tev.s-red{border-left-color:var(--red)}
.tev.s-blue{border-left-color:var(--blue)}
.tevh{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:9px}
.tevsym{font-size:var(--t-md);font-weight:750;letter-spacing:var(--tight)}
.tevt{font-size:var(--t-micro);color:var(--faint);font-family:var(--mono)}
.tevsp{flex:1}
.tevgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));gap:var(--s3)}
.tevf{display:flex;flex-direction:column;gap:1px;min-width:0}
.tevfl{font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--faint);font-weight:600}
.tevfv{font:700 var(--t-md)/1.15 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg)}
.tevfs{font-size:var(--t-micro);color:var(--dim);min-height:13px}
.tevwhy{margin-top:9px;padding-top:8px;border-top:1px solid var(--line);font-size:var(--t-sm);color:var(--fg2);line-height:1.5}
.tevwl{display:block;font-size:var(--t-micro);text-transform:uppercase;letter-spacing:.05em;color:var(--faint);font-weight:600;margin-bottom:2px}
@media (max-width:560px){
  .cvbox{height:104px}
  .cvspy{margin-left:0}
}
/* v5.4.0 — the age of the figure, on the figure. The dot is drawn ONLY when the source has aged:
   six green dots on a healthy card is decoration, and decoration is what a real warning gets
   ignored next to. The dated source line under the grid says which clock each half runs on. */
.snd{width:6px;height:6px;border-radius:50%;display:inline-block;margin-left:6px;vertical-align:middle}
.snd.a{background:var(--amber)}.snd.r{background:var(--red)}.snd.u{background:var(--dim)}
.snasof{display:flex;flex-wrap:wrap;gap:4px 20px;margin-top:9px;font-size:var(--t-micro);color:var(--dim)}
.snasof b{font-weight:600;color:var(--faint);text-transform:uppercase;letter-spacing:var(--wide);margin-right:6px}
.snasof i{font-style:normal}
.snasof i.a{color:var(--amber)}.snasof i.r{color:var(--red)}
.rdet{margin-top:var(--s3);border-top:1px solid var(--linesoft);padding-top:var(--s3)}
/* The label and its explanation share a line while there is room for both, and the explanation
   drops to its own line when there is not. Without the wrap, flex shrank BOTH children equally and
   at 390px "Risk details" — the two words that say what the drawer is — broke across two lines
   beside a sentence that had plenty of room to break instead. The label is the one thing here that
   must never wrap; the sentence explaining it is the thing that should.
   v5.6 — that rule was enforced with white-space:nowrap and flex:none, which is a promise the label
   cannot always keep. Performance passed a whole sentence as a title, and a nowrap item that is
   forbidden to shrink does not wrap, it leaves: measured at 390px it ran 98px past the right edge of
   the phone, off the screen, with no scrollbar to reveal it because the page does not scroll
   sideways. The wrap on the summary is what actually protects the short label — the line breaks
   before anything shrinks, so "Risk details" gets a line to itself at its natural width and never
   splits. Allowing the label to shrink only ever bites when the label alone is wider than the line,
   which is the one case where wrapping is better than vanishing. */
.rdet>summary{cursor:pointer;list-style:none;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px var(--s2)}
.rdet>summary::-webkit-details-marker{display:none}
.rdet>summary::before{content:"▸";color:var(--dim);font-size:var(--t-label);transition:transform .12s}
.rdet[open]>summary::before{transform:rotate(90deg)}
.rdett{font-size:var(--t-sm);font-weight:650;color:var(--fg2);flex:0 1 auto;min-width:0}
.rdets{font-size:var(--t-sm);color:var(--dim);flex:1 1 14ch;min-width:0}
.rdbody{margin-top:var(--s3);display:grid;grid-template-columns:1fr 1fr;gap:var(--s4)}
.rmeter{min-width:0}
.rml{display:flex;flex-direction:column;gap:2px;margin-bottom:7px}
.rml b{font-size:var(--t-sm);font-weight:650;color:var(--fg2)}
.rml span{font:var(--t-sm)/1.4 var(--mono);font-variant-numeric:tabular-nums;color:var(--dim)}
.rbar{height:7px;border-radius:var(--radius-pill);background:var(--sunk);overflow:hidden;border:1px solid var(--line)}
.rbf{display:block;height:100%;border-radius:var(--radius-pill)}
.rbf.x-green{background:var(--green)}.rbf.x-amber{background:var(--amber)}.rbf.x-red{background:var(--red)}
.rmn{font-size:var(--t-micro);color:var(--dim);margin-top:6px}
.rstops{grid-column:1/-1;border-top:1px solid var(--linesoft);padding-top:var(--s3)}
.rsh{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:6px}
.rsl{font-size:var(--t-sm);color:var(--fg2);padding:3px 0 3px 14px;position:relative;line-height:1.45}
.rsl::before{content:"";position:absolute;left:3px;top:11px;width:4px;height:4px;border-radius:50%;background:var(--faint)}
.rlinks{grid-column:1/-1;display:flex;gap:var(--s4);font-size:var(--t-sm);font-weight:600}

/* --- 3. what it owns ------------------------------------------------------ */
.p3list{display:grid;gap:var(--s3)}
.p3{border:1px solid var(--line);border-radius:var(--radius);background:var(--panel2);padding:14px 15px;box-shadow:var(--shadow-inset)}
.p3h{display:flex;align-items:center;gap:var(--s2);margin-bottom:12px}
.p3sym{font:700 var(--t-lg)/1 var(--sans);letter-spacing:var(--tight);color:var(--fg)}
.p3q{font:var(--t-sm)/1 var(--mono);color:var(--dim)}
.p3sp{flex:1 1 auto}
.p3grid{display:grid;grid-template-columns:repeat(6,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.p3f{background:var(--panel);padding:9px 11px;min-width:0}
.p3f.warnf{background:color-mix(in srgb,var(--red) 8%,var(--panel))}
.p3fl{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:4px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.p3fv{font:700 var(--t-md)/1.15 var(--mono);font-variant-numeric:tabular-nums;letter-spacing:var(--tight);color:var(--fg)}
.p3fs{font-size:var(--t-micro);color:var(--dim);margin-top:3px;line-height:1.3}
.p3f.pos .p3fv{color:var(--green)}.p3f.neg .p3fv{color:var(--red)}
/* The rail. Percentages, not SVG, so it reflows on a phone without scaling its own labels. */
.rail{margin-top:14px}
.rtrack{position:relative;height:12px;border-radius:var(--radius-pill);background:var(--sunk);border:1px solid var(--line)}
.rzone{position:absolute;left:0;top:0;bottom:0;border-radius:var(--radius-pill) 0 0 var(--radius-pill);
  background:color-mix(in srgb,var(--red) 17%,transparent)}
.rfill{position:absolute;top:2px;bottom:2px;border-radius:var(--radius-pill)}
.rfill.up{background:color-mix(in srgb,var(--green) 42%,transparent)}
.rfill.dn{background:color-mix(in srgb,var(--red) 42%,transparent)}
.rmk{position:absolute;top:-3px;bottom:-3px;width:2px;margin-left:-1px;border-radius:1px}
.rmk.m-stop{background:var(--red)}
.rmk.m-entry{background:var(--faint)}
.rmk.m-tgt{background:var(--green)}
.rnow{position:absolute;top:50%;width:13px;height:13px;margin:-6.5px 0 0 -6.5px;border-radius:50%;
  background:var(--fg);border:2px solid var(--panel2);box-shadow:0 0 0 1px var(--line2)}
.rtop{position:relative;height:15px;margin-bottom:3px;font:var(--t-micro)/1 var(--mono);font-variant-numeric:tabular-nums}
.rlbl{position:relative;height:13px;margin-top:9px;font:var(--t-micro)/1 var(--mono);font-variant-numeric:tabular-nums}
.rtop span,.rlbl span{position:absolute;top:0;white-space:nowrap}
.rnone{margin-top:7px;font-size:var(--t-micro);color:var(--dim)}
.rl-stop{color:var(--red)}.rl-entry{color:var(--dim)}.rl-now{color:var(--fg);font-weight:700}.rl-tgt{color:var(--green)}
.p3why{margin-top:12px;display:flex;gap:var(--s2);align-items:baseline;font-size:var(--t-sm);line-height:1.5}
.p3wl{flex:0 0 auto;font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint)}
.p3wv{color:var(--fg2)}
.p3thesis{margin-top:6px;font-size:var(--t-sm);color:var(--dim);line-height:1.5}

/* --- 4. what it is watching ----------------------------------------------- */
.fnl{display:flex;align-items:stretch;gap:var(--s2);margin-bottom:var(--s4);overflow-x:auto;padding-bottom:2px}
.fst{flex:1 1 0;min-width:96px;padding:11px 12px;border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--line)}
.fst.fzero{opacity:.62}

/* v5.22.0 — DISTANCE TO YES, and the tile that answers "why is nothing trading".
   The bar always reads full-is-good regardless of which way the underlying gate faces, so a card
   mixing "needs 2.25 or more" with "0.30% at most" can still be scanned in one pass. A failing bar
   is the only red on the card; a passing one is deliberately quiet, because a card of six green
   bars is decoration and decoration is what a warning gets ignored beside. */
.gbs{display:flex;flex-direction:column;gap:5px;margin-top:10px}
.gb{display:grid;grid-template-columns:minmax(min(84px,100%),26%) 1fr auto;align-items:center;gap:9px;font-size:var(--t-label)}
.gbl{color:var(--fg2);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gbbar{position:relative;height:6px;border-radius:3px;background:var(--panel2);border:1px solid var(--line);overflow:hidden}
.gbbar i{display:block;height:100%;border-radius:3px;background:color-mix(in srgb,var(--green) 55%,transparent)}
.gb.no .gbbar i{background:color-mix(in srgb,var(--amber) 62%,transparent)}
.gbv{font:600 var(--t-micro)/1.25 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg2);text-align:right;white-space:nowrap}
.gbv i{display:block;font-style:normal;font-weight:400;color:var(--faint)}
.gb.no .gbv{color:var(--amber)}
/* "not measured" is not a zero-length bar. An empty bar and a zero bar are a pixel apart and mean
   opposite things, and confusing those two is the whole noVol defect. */
.gbt{grid-column:2/-1;font-size:var(--t-micro);color:var(--faint);font-style:italic}

.card.wn{background:var(--panel2);margin-bottom:var(--s4)}
.wnh{font-weight:700;font-size:var(--t-md);margin-bottom:2px}
.wnsub{font-size:var(--t-sm);color:var(--fg2);margin-bottom:9px}
.wnr{display:grid;grid-template-columns:auto minmax(min(120px,100%),22%) 1fr;align-items:baseline;gap:10px;padding:4px 0;border-top:1px solid var(--line)}
.wnn{font:700 var(--t-md)/1 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg);min-width:2ch;text-align:right}
.wnl{font-size:var(--t-sm);font-weight:600;color:var(--fg2)}
.wnc{font-size:var(--t-label);color:var(--faint)}
.wnfoot{margin-top:9px;font-size:var(--t-micro);color:var(--faint);line-height:1.5}
@media (max-width:560px){
  .gb{grid-template-columns:1fr auto;row-gap:3px}
  .gbbar{grid-column:1/-1;order:3}
  .wnr{grid-template-columns:auto 1fr;row-gap:2px}
  .wnc{grid-column:1/-1}
}
.fstn{font:700 var(--t-2xl)/1 var(--mono);font-variant-numeric:tabular-nums;letter-spacing:var(--tight);color:var(--fg)}
.fstl{font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--fg2);margin-top:5px}
.fstbar{height:3px;border-radius:2px;background:var(--sunk);margin:7px 0 6px;overflow:hidden}
.fstbar i{display:block;height:100%;background:var(--accent);border-radius:2px}
.fstw{font-size:var(--t-micro);color:var(--dim);line-height:1.35}
.fsep{align-self:center;color:var(--faint);font-size:var(--t-md);flex:0 0 auto}
.cndlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(340px,100%),1fr));gap:var(--s3)}
.cnd{border:1px solid var(--line);border-left:3px solid var(--line2);border-radius:var(--radius);
  background:var(--panel2);padding:13px 14px}
.cnd.s-amber{border-left-color:var(--amber)}
.cnd.s-blue{border-left-color:var(--blue)}
.cnd.s-green{border-left-color:var(--green)}
.cnd.s-grey{border-left-color:var(--grey)}
.cndh{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.cndsym{font:700 var(--t-md)/1 var(--sans);letter-spacing:var(--tight);color:var(--fg)}
.cndco{font-size:var(--t-sm);color:var(--dim);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:15ch}
.cndsp{flex:1 1 auto}
.cndsc{display:flex;flex-direction:column;align-items:flex-end;line-height:1;cursor:help}
.cndsc b{font:700 var(--t-md)/1 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg)}
.cndsc i{font:600 var(--t-nano)/1 var(--sans);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);font-style:normal;margin-top:3px}
.cndsetup{font-size:var(--t-sm);color:var(--fg2);margin:8px 0 10px}
.cndgrid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.cndf{background:var(--panel);padding:7px 9px;min-width:0}
.cndf span{display:block;font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cndf b{display:block;font:650 var(--t-sm)/1.3 var(--mono);font-variant-numeric:tabular-nums;color:var(--fg);margin-top:3px}
.cndwhy,.cndnext{margin-top:10px;font-size:var(--t-sm);color:var(--fg2);line-height:1.5}
.cndl{display:block;font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint);margin-bottom:2px}
.cndfoot{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px}

/* --- 5. decision timeline ------------------------------------------------- */
.tl5{list-style:none;margin:0;padding:0 0 0 var(--s4);position:relative}
.tl5::before{content:"";position:absolute;left:5px;top:6px;bottom:6px;width:1px;background:var(--line)}
.tlrow{position:relative}
.tlrow::before{content:"";position:absolute;left:-14px;top:13px;width:7px;height:7px;border-radius:50%;
  background:var(--grey);border:2px solid var(--panel)}
.tlrow.s-green::before{background:var(--green)}
.tlrow.s-blue::before{background:var(--blue)}
.tlrow.s-amber::before{background:var(--amber)}
.tlrow.s-red::before{background:var(--red)}
.tlrow.fut{opacity:.66}
.tlrow.fut::before{background:var(--panel);border-color:var(--line2)}
.tlline{display:flex;align-items:baseline;gap:var(--s2);padding:7px 8px;border-radius:var(--radius-sm);
  cursor:default;list-style:none;min-width:0}
summary.tlline{cursor:pointer}
summary.tlline::-webkit-details-marker{display:none}
.tlrow details[open] .tlline{background:var(--panel2)}
.tlline:hover{background:var(--panel2)}
.tlt{flex:0 0 auto;width:86px;white-space:nowrap;font:600 var(--t-sm)/1.4 var(--mono);
  font-variant-numeric:tabular-nums;color:var(--dim)}
.tlk{flex:0 0 auto;font:700 var(--t-nano)/1.6 var(--sans);letter-spacing:var(--wide);text-transform:uppercase;
  color:var(--faint);border:1px solid var(--line2);border-radius:4px;padding:0 5px}
.tlk.k-trade{color:var(--green);border-color:color-mix(in srgb,var(--green) 45%,transparent)}
.tlk.k-problem{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent)}
.tlk.k-scheduled{color:var(--blue);border-color:color-mix(in srgb,var(--blue) 40%,transparent)}
.tlsym{flex:0 0 auto;font:700 var(--t-sm)/1.4 var(--mono);color:var(--fg2)}
.tlh{flex:1 1 auto;min-width:0;font-size:var(--t-sm);color:var(--fg);line-height:1.45}
.tlcar{flex:0 0 auto;color:var(--faint);font-size:var(--t-micro)}
.tld{margin:0 0 6px 82px;padding:9px 12px;border-left:2px solid var(--line);background:var(--sunk);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.tldl{font:var(--t-sm)/1.55 var(--mono);color:var(--fg2);overflow-wrap:anywhere}
.tlcut{position:relative;margin:10px 0 10px -14px;display:flex;align-items:center;gap:var(--s2)}
.tlcut::after{content:"";flex:1 1 auto;height:1px;background:color-mix(in srgb,var(--accent) 40%,transparent)}
.tlcut span{font:700 var(--t-nano)/1 var(--sans);letter-spacing:var(--wide);text-transform:uppercase;color:var(--accent);
  background:var(--accent-soft);border-radius:var(--radius-pill);padding:4px 9px}
.tlsec .tlnote{margin-top:var(--s3);padding:0 0 0 var(--s4);font-size:var(--t-micro);
  font-weight:400;color:var(--faint);line-height:1.5}
.tlfoot{display:flex;align-items:center;gap:var(--s4);margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--linesoft)}
.tlseen{font:650 var(--t-sm)/1 var(--sans);color:var(--fg2);background:var(--panel3);border:1px solid var(--line2);
  border-radius:var(--radius-sm);padding:7px 13px;cursor:pointer}
.tlseen:hover{color:var(--fg);border-color:var(--faint)}
.tlfl{display:flex;gap:var(--s3);font-size:var(--t-sm);font-weight:600;margin-left:auto}

/* --- 6. alerts ------------------------------------------------------------ */
.alrlist{display:grid;gap:var(--s3)}
.alr{border:1px solid var(--line);border-left:3px solid var(--amber);border-radius:var(--radius);
  background:var(--panel2);padding:13px 15px}
.alr.s-red{border-left-color:var(--red)}
.alrh{display:flex;align-items:center;gap:var(--s2);margin-bottom:5px}
.alrt{font-size:var(--t-md);font-weight:650;letter-spacing:var(--tight);color:var(--fg)}
.alrsp{flex:1 1 auto}
.alrw{font-size:var(--t-sm);color:var(--fg2);line-height:1.55;margin-bottom:11px;max-width:80ch}
.alrgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-sm);overflow:hidden}
.alrf{background:var(--panel);padding:8px 10px;min-width:0}
.alrf span{display:block;font:var(--lbl);letter-spacing:var(--wide);text-transform:uppercase;color:var(--faint)}
.alrf b{display:block;font-size:var(--t-sm);font-weight:600;color:var(--fg2);margin-top:3px;line-height:1.4;overflow-wrap:anywhere}
.alrcta{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-top:11px}
.alrcta form{display:flex;align-items:center;gap:var(--s2)}
.alrb{font:650 var(--t-sm)/1 var(--sans);color:var(--fg);background:var(--panel3);border:1px solid var(--line2);
  border-radius:var(--radius-sm);padding:8px 13px;cursor:pointer}
.alrb:hover{border-color:var(--accent);color:var(--accent)}
.alrn{font-size:var(--t-micro);color:var(--dim)}
.alrl{font-size:var(--t-sm);font-weight:600;margin-left:auto}
.alrc{margin-top:9px;display:flex;flex-wrap:wrap;gap:5px}
.alrc code{font:var(--t-micro)/1.6 var(--mono);color:var(--faint);background:var(--sunk);
  border:1px solid var(--line);border-radius:4px;padding:1px 5px}

/* --- the shared empty state ----------------------------------------------- */
.empty{display:flex;flex-direction:column;gap:4px;padding:22px 4px;text-align:center}
.empty b{font-size:var(--t-md);font-weight:650;color:var(--fg2)}
.empty span{font-size:var(--t-sm);color:var(--dim)}
.empty.ok b{color:var(--green)}

@media(max-width:1100px){
  .apgrid,.snapgrid{grid-template-columns:repeat(3,1fr)}
  .p3grid{grid-template-columns:repeat(3,1fr)}
  .alrgrid{grid-template-columns:repeat(2,1fr)}
  .rdbody{grid-template-columns:1fr}
}
@media(max-width:560px){
  /* Two columns, never one: six facts in a single column is a scroll, and the whole point of the
     status block is that it can be taken in at a glance. */
  .apgrid,.snapgrid,.p3grid,.cndgrid{grid-template-columns:1fr 1fr}
  .t5h{margin:var(--s5) 0 var(--s2);flex-wrap:wrap;gap:var(--s2)}
  .t5s{flex:1 0 100%;white-space:normal}
  .snv{font-size:var(--t-lg)}
  .apsent{font-size:var(--t-base)}
  /* The funnel stops being a scrolling strip. A horizontal scroller hides the last stage, and the
     last stage is ARMED — the one number that says whether anything is about to be bought. */
  .fnl{display:grid;grid-template-columns:1fr 1fr;gap:6px;overflow-x:visible}
  .fst{min-width:0;padding:9px 10px}
  .fst:last-of-type{grid-column:1/-1}
  .fstn{font-size:var(--t-xl)}
  .fsep{display:none}
  .cndlist{grid-template-columns:1fr}
  /* The clock column stops being a fixed gutter and the headline drops under it, because at 390px
     a 74px gutter plus a kind badge leaves nine characters for the sentence. */
  .tlline{flex-wrap:wrap;gap:6px;position:relative;padding-right:18px}
  .tlt{width:auto}
  .tlh{flex:1 0 100%}
  /* The caret rides in the corner of the row instead of dropping onto a line of its own, which is
     what a flex-wrap does to a 10px glyph and it reads as a rendering fault. */
  .tlcar{position:absolute;right:4px;top:9px}
  .tld{margin-left:0}
  .tlfoot{flex-wrap:wrap}
  .tlfl{margin-left:0;flex:1 0 100%}
  /* Three labels will not sit at their true positions in 350px without overlapping, so below this
     width they become an evenly spread legend. The "Now" label above the track keeps its position,
     because it is the only one up there and has nothing to collide with. */
  .rlbl{position:static;display:flex;justify-content:space-between;gap:6px;height:auto}
  .rlbl span{position:static;transform:none!important}
  .alrcta{align-items:flex-start;gap:var(--s2)}
  .alrcta form{flex:1 0 100%;flex-wrap:wrap;gap:6px}
  .alrb{white-space:nowrap}
  .alrl{margin-left:0}
}

/* ============================================================================
   v5.0 DESIGN SYSTEM — the corrections layer.

   The owner gave fourteen numbered instructions. Four of them are colour rules and they are the
   ones with teeth, because a colour on this screen is a claim about what the owner has to do:

     RED    a loss, or a condition that requires him to intervene. Nothing else is ever red.
            A red thing on this page means: stop reading, deal with this.
     AMBER  degraded but operating. The system is doing its job with one hand tied — a stale
            price, a thin sample, a scan that did not run. Worth knowing, not worth waking up for.
     GREEN  a healthy system, a protected position, or a gain. Green is earned, not decorative.
     BLUE   neutral. Navigation, informational state, anything he can act on but need not.

   The rules that follow are written LAST in this stylesheet on purpose: they are corrections to
   four years of accumulated per-page decisions, and a correction has to win the cascade.
   ========================================================================= */

/* --- 7. SPACING BETWEEN SECTIONS ------------------------------------------
   The token bump opened the inside of every component. This opens the space between them, which
   is the part the owner actually complained about: sections that touch read as one long section. */
.grid{gap:var(--s4)}
.dash{gap:var(--s4)}
main>:is(.card,.dash,.grid,.poscard,.phead)+:is(.card,.dash,.grid,.poscard){margin-top:var(--s5)}

/* --- 8. FEWER BORDERS AND NESTED BOXES ------------------------------------
   A frame drawn inside a frame is a line that carries no information. Anything already sitting on
   a card is already grouped by the card; the tint is enough to say "this is a distinct thing", and
   the border it used to draw is removed. The card keeps its own border — it is the outer edge, and
   an outer edge IS information. */
.card .card,.card .tile,.card .poscard,.card .warnbox,.tile .tile{
  border-color:transparent;box-shadow:none}
.card .card,.card .tile,.card .poscard{background:var(--panel2)}
.card pre,.card .mdsec,.card .bar{border-color:transparent}
.card pre,.card .mdsec{background:var(--sunk)}
/* v5.6 — the same rule for a table's scroll container, and the reason it has to be stated here.
   Every table in the app is now wrapped in .tblwrap, because a seven-column table of numbers on a
   phone has to scroll rather than vanish. The wrapper draws a border, which is right when the table
   is the only thing on the page — the frame is what says "the content continues past this edge".
   Inside a card that same border is the second frame this whole section exists to remove, and it
   lands one pixel inside the card's own edge, which is worse than either choice on its own. So the
   container keeps its scrolling and loses its skin whenever a card is already drawing the box. */
.card .tblwrap,.tile .tblwrap{border-color:transparent;background-color:transparent}
/* Tiles keep an edge, but a quieter one — twelve tiles across a dashboard is twelve rectangles,
   and at the old contrast the grid read before the numbers did. */
.tile{border-color:var(--linesoft)}
/* The message boxes stop being boxes. A four-sided border around a sentence is the single most
   common way this app used to turn a note into an alarm; a left rule says the same thing about
   severity and leaves the sentence looking like a sentence. */
.warnbox{border:none;border-left:3px solid var(--amber);border-radius:0 var(--radius-sm) var(--radius-sm) 0;
padding:var(--s3) var(--s4);font-size:var(--t-base)}
.warnbox.bx-blue{border-left-color:var(--blue)}
.warnbox.bx-green{border-left-color:var(--green)}
.warnbox.bx-red{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 9%,transparent);color:var(--red)}
/* A table already has one horizontal rule per row. It does not also need a frame, and its rules do
   not need to be as dark as the card edge that contains them. */
.card table td{border-bottom-color:color-mix(in srgb,var(--line) 55%,transparent)}
details>summary{font-size:var(--t-sm)}

/* --- 10. ONE STATUS CHIP --------------------------------------------------
   There were two chip geometries in this stylesheet and they did not line up when placed in the
   same row, which is exactly the situation a chip exists for. Now there is one silhouette — same
   height, same padding, same radius — and .st is only a glyph treatment for values that are
   literally state-machine names rather than English. Every tone gets a border, including grey:
   a chip that loses its outline when it turns neutral reads as a rendering fault. */
.chip{padding:3px 10px;line-height:1.45;border:1px solid var(--line2);vertical-align:baseline}
.chip.st{font-family:var(--mono);font-size:var(--t-micro);text-transform:uppercase;
letter-spacing:var(--wide);font-weight:700;padding:3px 10px}
.c-grey{color:var(--dim);border-color:var(--line2);background:color-mix(in srgb,var(--panel3) 60%,transparent)}
/* --accent and --blue are the same colour; both names exist in call sites and both must render. */
.c-accent{color:var(--blue);border-color:color-mix(in srgb,var(--blue) 45%,transparent);
background:color-mix(in srgb,var(--blue) 12%,transparent)}
/* A chip that names a thing rather than a state — a sector, a strategy, a tag — is not status and
   must not borrow a status colour. */
.chip.plain{color:var(--fg2);border-color:var(--line);background:transparent;font-weight:600}
/* The filled variant. Exactly one value in the app is entitled to it — ARMED — because a filled
   chip in a list of outlined ones is a shout, and a shout that happens twelve times is noise. */
.chip.solid{color:#fff;font-weight:700}
.chip.solid.c-blue,.chip.solid.c-accent{background:var(--blue);border-color:var(--blue)}
.chip.solid.c-green{background:var(--green);border-color:var(--green)}
.chip.solid.c-amber{background:var(--amber);border-color:var(--amber)}
.chip.solid.c-red{background:var(--red);border-color:var(--red)}

/* --- 3-6. COLOUR SEMANTICS, THE CHROME ------------------------------------
   Pre-market was amber, which said "something is degraded" every single morning when nothing was.
   The session strip is informational, so it is blue before the bell and green only once the market
   is genuinely open and the system is genuinely running. */
body.sess-pre header::after{background:linear-gradient(90deg,var(--blue),color-mix(in srgb,var(--blue) 15%,transparent))}
/* The hero card is the page's headline. Amber on it means degraded-but-operating, so it must not
   also be the colour the card uses for "you have something to approve" — that is blue. */
.hero.info{border-color:color-mix(in srgb,var(--blue) 55%,transparent);
background:color-mix(in srgb,var(--blue) 7%,var(--panel))}

/* --- v5.0 NAVIGATION: six destinations, and they have to fit --------------
   The bar was built for five names, three of them short. Six longer ones overflow a 1280px laptop
   before the clock has anywhere to sit. Rather than truncate a destination — a half-word is not a
   name — the bar sheds ornament in order: first the icons, then the padding, then the letter size.
   The header is also allowed to grow to a second row, because a wrapped nav is a worse-looking
   header and a broken one is a broken app. */
header{height:auto;min-height:52px;row-gap:var(--s2);padding-top:5px;padding-bottom:5px;align-content:center}
@media(max-width:1280px){header nav a .nicon{display:none}}
@media(max-width:1120px){
  header nav a{padding:6px 8px;font-size:var(--t-label)}
  header nav a.on::before{left:8px;right:8px}
  header{gap:var(--s2)}
}
/* Six items on a phone bar means about sixty pixels each. The labels are already shortened in the
   markup; here the type comes down and the icon gives back its bottom margin so two lines never
   happen. */
@media(max-width:700px){
  .bottomnav a{font-size:var(--t-nano);letter-spacing:-.01em;padding:2px 1px;min-width:0}
  .bottomnav .nicon{width:19px;height:19px;margin:0 auto 1px}
}

/* --- v5.0 DETAIL LEVELS (point 13) ----------------------------------------
   Three audiences share one screen and they are not the same person on the same day.
     Owner        the answers. What do I own, what is it risking, is anything wrong.
     Trader       the answers plus the working: the tables, the score components, the gates.
     Diagnostics  everything, including the machinery — raw payloads, source stamps, internals.
   Two markers do the whole job. An element marked lv-t belongs to Trader and above; lv-d belongs
   to Diagnostics alone. Nothing is duplicated and no page renders twice; the level is a class on
   the root element and the browser does the rest, which is why switching is instant and why the
   choice survives a reload without a round trip.

   The default is Trader, deliberately. An owner who has never touched this control should see
   everything he saw yesterday except the raw machinery — a new preference must not silently take
   working detail off his screen. Owner is a thing you choose when you want the page quieter. */
html.lv-owner .lv-t,html.lv-owner .lv-d,html.lv-trader .lv-d{display:none !important}
.lvsw{display:inline-flex;border:1px solid var(--line2);border-radius:var(--radius-pill);overflow:hidden;background:var(--panel2)}
.lvsw button{background:none;border:none;border-radius:0;padding:3px 11px;font-size:var(--t-label);
font-weight:650;color:var(--dim);letter-spacing:.01em}
.lvsw button+button{border-left:1px solid var(--line)}
.lvsw button:hover{background:var(--panel3);color:var(--fg2)}
html.lv-owner .lvsw [data-lv=owner],html.lv-trader .lvsw [data-lv=trader],html.lv-diag .lvsw [data-lv=diag]{
background:var(--accent);color:#fff}
/* A level that hides things has to say so, or a missing section reads as a bug. */
.lvnote{color:var(--faint);font-size:var(--t-label)}
html.lv-diag .lvnote::after{content:'Diagnostics — showing raw payloads and source stamps'}
html.lv-owner .lvnote::after{content:'Owner view — tables and internals hidden'}
@media(max-width:1120px){.lvnote{display:none}}
/* The theme button is a two-state control and should look like the state it is in, not like a
   moon forever. Point 11 asked for both themes offered; offering means legible, not present. */
#themebtn .sun{display:none}
html.light #themebtn .sun{display:inline}
html.light #themebtn .moon{display:none}
@media(max-width:700px){
  .lvsw button{padding:3px 9px;font-size:var(--t-micro)}
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   v5.1 — THE OPPORTUNITIES PAGE
   Three views over one model: a seven-column funnel, a ranked table, and the whole previous
   board kept intact behind a third tab. Two layout decisions here are deliberate and should
   survive future edits.
   1. The pipeline NEVER becomes a horizontally scrolling strip. A data-tip bubble is an
      absolutely positioned pseudo-element inside its anchor, so any ancestor that scrolls
      clips it, and the cards in these columns are almost entirely tooltips. Columns re-flow
      at each breakpoint instead.
   2. Nothing here hides a number to look tidy. Where a figure is unknown the markup says so
      in words, and these rules give that wording a dim treatment rather than a red one — an
      unknown is not an error.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* Two utilities the app has been using without ever defining. Tabular figures are the reason
   a column of prices reads as a column and not as ragged text. */
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
/* One identifier, one timestamp, one ticker: things that mean nothing broken across two lines.
   Declared once here so pages stop reaching for an inline style to say it. */
.nowrap{white-space:nowrap}
.tblwrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--panel)}
/* v5.6 — SIDEWAYS SCROLL THAT ANNOUNCES ITSELF.
   Four rails in this app scroll horizontally with the scrollbar deliberately hidden: the ticker,
   the sub-navigation and the alert row on a phone, and every table wrapper. Hiding the bar was the
   right call — a 9px trough under a row of chips looks broken — but it left nothing at all to say
   that content continues past the edge. On a table inside a card it is worse than nothing, because
   the wrapper's own border is suppressed there to avoid a double frame, so the last visible column
   simply ends at the card edge and reads as the last column there is. The owner has no way to learn
   otherwise except by dragging a table he has no reason to think is draggable.
   This is the background-attachment trick rather than a mask or a scroll listener, and the reason is
   that it turns itself off. Two of the four gradients are attached local, so they travel with the
   content; two are attached scroll, so they stay pinned to the element's edges. At rest the local
   pair sits exactly on top of the scroll pair painting the container's own background colour over
   them, and nothing is visible. Scroll right and the left-hand cover slides away, uncovering the
   shadow underneath; reach the far end and the right-hand cover arrives and puts it out. A rail with
   nothing to scroll never uncovers either one, so a narrow table gets no shadow and no explaining.
   No JavaScript, no resize observer, nothing to keep in sync, and it degrades to a plain background
   in any browser that does not do it.
   The cover is a solid block for its first 24px and only then fades, which is not a detail. The
   first attempt ramped it from opaque to transparent across its whole width, and a linear alpha
   ramp cannot fully mask another linear alpha ramp: measured against the same rail with the effect
   switched off, a bar with nothing at all to scroll still came out up to 13 channel values light at
   both edges — a permanent smudge on every rail in the app, which is worse than no cue at all
   because it is always wrong instead of sometimes right. The cover has to be flatly opaque across
   the full 22px the shadow occupies before it is allowed to start fading.
   --sfade must be whatever colour is actually behind the rail or the cover will not cover. That is
   why .card .tblwrap below switches to background-color rather than the shorthand: the shorthand
   would reset background-image and silently delete this whole effect on precisely the tables that
   need it most. */
.ticker,.subnav,.alertbar,.tblwrap,.acctbar{
  background-image:
    linear-gradient(to right,var(--sfade,var(--panel)) 0 24px,transparent 44px),
    linear-gradient(to left,var(--sfade,var(--panel)) 0 24px,transparent 44px),
    linear-gradient(to right,color-mix(in srgb,var(--fg) 34%,transparent),transparent),
    linear-gradient(to left,color-mix(in srgb,var(--fg) 34%,transparent),transparent);
  background-position:left center,right center,left center,right center;
  background-size:44px 100%,44px 100%,22px 100%,22px 100%;
  background-repeat:no-repeat;
  background-attachment:local,local,scroll,scroll}
.ticker{--sfade:var(--sunk)}
.alertbar{--sfade:var(--panel2)}
.acctbar{--sfade:var(--sunk)}
.tile .tblwrap{--sfade:var(--panel)}
.c-violet{color:var(--violet);border-color:color-mix(in srgb,var(--violet) 45%,transparent);background:color-mix(in srgb,var(--violet) 12%,transparent)}

/* ---- page header ----
   v5.6 — one page header. This block used to exist twice: once here as .ophead/.opht/.ophs/.ophr
   for Opportunities, and again 320 lines down as .pfhead/.pfht/.pfhs/.pfhr for Portfolio. They
   were the same header. Every difference between them was an accident of whoever typed it second
   — weight 750 against 760, tracking -.02em against -.025em, a sub capped at 66ch against one
   capped at 74ch — and none of those differences was visible side by side, because the two pages
   are never on screen at once. What WAS visible: only the Portfolio copy set min-width:0 on its
   left column, so only Portfolio survived a long unbroken word in the sub without the flex row
   growing past the page.
   The converged values take the larger weight-neutral choice on each axis and the middle sub
   width. Two more titles join them here: /backtest opened with a bare h1 against a stylesheet
   that has no h1 rule, so it rendered at the browser default 2em, and /autopsy hand-rolled its
   own inline. Four page titles, one rule. */
.opwrap{padding-bottom:var(--s3)}
.phead{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s4);flex-wrap:wrap}
.phl{min-width:0}
.pht{font-size:var(--t-3xl);font-weight:750;letter-spacing:-.02em;margin:0;line-height:1.1}
.phs{font-size:var(--t-sm);color:var(--dim);margin:6px 0 0;max-width:70ch;line-height:1.5}
.phr{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.opline{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s4);
  padding-top:var(--s3);border-top:1px solid var(--linesoft);font-size:var(--t-sm);color:var(--fg2)}
.opline b{color:var(--fg);font-weight:700}
.opline span:nth-child(even){color:var(--faint)}

/* ---- the funnel strip ---- */
.opfun{display:flex;align-items:stretch;gap:var(--s1);flex-wrap:wrap;margin-top:var(--s4)}
.opfs{flex:1 1 118px;min-width:0;background:var(--panel2);border:1px solid var(--line);
  border-radius:var(--radius-sm);padding:10px 12px 9px;transition:border-color .14s ease,transform .14s ease}
.opfs:hover{border-color:var(--line2);transform:translateY(-1px)}
.opfs.empty{opacity:.52}
.opfsn{font-family:var(--mono);font-size:var(--t-2xl);font-weight:700;line-height:1;letter-spacing:-.02em}
.opfst{font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--dim);font-weight:700;margin-top:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.opfsb{height:3px;border-radius:2px;background:var(--line);margin-top:8px;overflow:hidden}
.opfsb i{display:block;height:100%;border-radius:2px;min-width:2px}
.opfarrow{align-self:center;color:var(--faint);font-size:var(--t-lg);line-height:1;padding:0 1px;user-select:none}
.opfs.f-blue .opfsn{color:var(--blue)}   .opfs.f-blue .opfsb i{background:var(--blue)}
.opfs.f-violet .opfsn{color:var(--violet)} .opfs.f-violet .opfsb i{background:var(--violet)}
.opfs.f-amber .opfsn{color:var(--amber)} .opfs.f-amber .opfsb i{background:var(--amber)}
.opfs.f-green .opfsn{color:var(--green)} .opfs.f-green .opfsb i{background:var(--green)}
.opfs.f-grey .opfsn{color:var(--dim)}    .opfs.f-grey .opfsb i{background:var(--line2)}
@media(max-width:900px){.opfarrow{display:none}.opfs{flex:1 1 96px}}

/* ---- provenance strip and named gaps ---- */
.opsrc{display:flex;gap:var(--s4);flex-wrap:wrap;margin-top:var(--s3);padding-top:var(--s2);
  border-top:1px dashed var(--linesoft);font-size:var(--t-micro);color:var(--faint)}
.opsrc em{font-style:normal;text-transform:uppercase;letter-spacing:var(--wide);margin-right:5px}
.opsrc b{color:var(--fg2)}
.opgaps{margin:6px 0 0;padding-left:18px}
.opgaps li{font-size:var(--t-sm);line-height:1.55;margin-top:3px}
.opadvn{font-size:var(--t-sm);color:var(--dim);line-height:1.55;margin:0 0 var(--s3);
  padding:10px 14px;background:var(--sunk);border-left:2px solid var(--accent);border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.opnote{font-size:var(--t-micro);color:var(--faint);line-height:1.6;margin:var(--s3) 0 0;max-width:100ch}

/* ---- pipeline: seven columns, re-flowed rather than scrolled ---- */
.oppipe{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:var(--s2);margin-top:var(--s4)}
@media(max-width:1500px){.oppipe{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(max-width:1080px){.oppipe{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.oppipe{grid-template-columns:minmax(0,1fr)}}
.opcol{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  display:flex;flex-direction:column;min-width:0}
.opcolh{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
  padding:10px 12px 9px;border-bottom:1px solid var(--linesoft)}
.opcolt{font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);
  font-weight:700;color:var(--fg2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.opcoln{font-family:var(--mono);font-size:var(--t-sm);font-weight:700}
.opcoln.t-blue{color:var(--blue)} .opcoln.t-violet{color:var(--violet)}
.opcoln.t-amber{color:var(--amber)} .opcoln.t-green{color:var(--green)} .opcoln.t-grey{color:var(--dim)}
.opcolm{font-size:var(--t-micro);color:var(--faint);line-height:1.5;margin:0;padding:9px 12px;
  border-bottom:1px solid var(--linesoft)}
.opcolb{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s2)}
.opcole{font-size:var(--t-sm);color:var(--faint);padding:14px 4px;text-align:center;line-height:1.5}

/* ---- the opportunity card ---- */
.opc{background:var(--panel2);border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:9px 10px;cursor:pointer;transition:border-color .14s ease,transform .14s ease,box-shadow .14s ease}
.opc:hover{border-color:color-mix(in srgb,var(--accent) 55%,var(--line2));transform:translateY(-1px);
  box-shadow:0 4px 14px -6px rgba(0,0,0,.55)}
.opctop{display:flex;align-items:center;justify-content:space-between;gap:var(--s2)}
.opcsym{font-size:var(--t-md);font-weight:750;letter-spacing:-.01em}
.opcset{font-size:var(--t-micro);color:var(--dim);line-height:1.45;margin-top:4px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.opcnums{display:flex;flex-wrap:wrap;gap:2px 10px;margin-top:7px;font-size:var(--t-micro);color:var(--faint)}
.opcnums b{font-family:var(--mono);color:var(--fg2);font-weight:700;margin-left:3px}
/* A name nobody has planned yet says so in words. It is deliberately NOT styled like a
   warning: not having an entry plan at the discovery stage is the normal state of the
   world, not a fault, and colouring it amber would train the eye to ignore real amber. */
.opcnp{color:var(--dim)}
.opcnp b{margin-left:0}
/* The stated reason a name was turned down. Left rule rather than a red panel: this is the
   record of a decision that worked, not an incident. It clamps at three lines and the full
   text is in the research panel, so a long reason cannot push the column out of shape. */
.opcwhy{margin-top:7px;padding-left:8px;border-left:2px solid var(--line2);
  font-size:var(--t-micro);line-height:1.5;color:var(--dim);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.opcchips{display:flex;align-items:center;flex-wrap:wrap;gap:5px;margin-top:8px}

/* ---- distance to trigger: coloured by urgency, never by direction ---- */
.opdist{font-family:var(--mono);font-size:var(--t-micro);font-weight:700;padding:2px 7px;
  border-radius:var(--radius-pill);border:1px solid var(--line2);white-space:nowrap}
.opdist.d-hot{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 70%,transparent);
  background:color-mix(in srgb,var(--amber) 22%,transparent)}
.opdist.d-near{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 40%,transparent);
  background:color-mix(in srgb,var(--amber) 10%,transparent)}
.opdist.d-mid{color:var(--blue);border-color:color-mix(in srgb,var(--blue) 36%,transparent);
  background:color-mix(in srgb,var(--blue) 9%,transparent)}
.opdist.d-far{color:var(--dim);background:transparent}
.opdist.d-none{color:var(--faint);border-style:dashed;background:transparent;font-family:inherit;font-weight:600}

/* ---- composite score: a number and a short bar, never a verdict ---- */
.opscore{display:inline-grid;grid-template-columns:24px 46px;align-items:center;gap:6px}
.opscore b{font-family:var(--mono);font-size:var(--t-sm);font-weight:700;text-align:right;color:var(--fg2)}
.opsct{display:block;height:4px;border-radius:2px;background:var(--line);overflow:hidden}
.opsct i{display:block;height:100%;border-radius:2px;min-width:2px}
.opsct i.sc-hi{background:var(--green)}
.opsct i.sc-mid{background:var(--blue)}
.opsct i.sc-lo{background:var(--line2)}

/* ---- ranked table ---- */
.oprank{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
.oprank th{position:sticky;top:0;z-index:1;background:var(--panel2);text-align:left;
  font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);color:var(--dim);
  font-weight:700;padding:9px 10px;border-bottom:1px solid var(--line);white-space:nowrap}
.oprank td{padding:9px 10px;border-bottom:1px solid var(--linesoft);vertical-align:middle}
.oprank tbody tr{cursor:pointer;transition:background .12s ease}
.oprank tbody tr:hover{background:var(--panel2)}
.oprank tbody tr:last-child td{border-bottom:none}
.opsym{font-size:var(--t-base);font-weight:700;letter-spacing:-.01em}
.opsub{font-size:var(--t-micro);color:var(--faint);margin-top:2px;max-width:240px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.opwait{font-size:var(--t-micro);color:var(--fg2);line-height:1.45;max-width:290px;min-width:180px}

/* ═══ THE RESEARCH PANEL (fetched into the right-side drawer) ═══ */
.opppanel{display:flex;flex-direction:column}
.opph{padding-bottom:var(--s4);border-bottom:1px solid var(--line)}
.opphl{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.opphsym{font-size:var(--t-2xl);font-weight:750;letter-spacing:-.02em}
.opphn{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-top:9px}
.opphn b{font-family:var(--mono);font-size:var(--t-lg);font-weight:700}
.opphw{font-size:var(--t-sm);color:var(--fg2);line-height:1.55;margin:10px 0 0}
.opps{padding:var(--s4) 0;border-bottom:1px solid var(--linesoft)}
.opps:last-child{border-bottom:none;padding-bottom:var(--s2)}
.oppst{font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--dim);font-weight:700;margin:0 0 8px}
/* v6.125.0 — a section the drawer was opened ON. Without it the panel simply appears already
   scrolled and the reader cannot tell whether that was deliberate or where they landed. */
.oppfocus{box-shadow:inset 3px 0 0 var(--violet,#8b6ad6);padding-left:10px;
  transition:box-shadow .5s ease,padding-left .5s ease}
.oppsn{font-size:var(--t-micro);color:var(--faint);line-height:1.55;margin:0 0 10px;max-width:78ch}
.oppse{font-size:var(--t-sm);color:var(--dim);line-height:1.6;margin:0;padding:11px 13px;
  background:var(--sunk);border:1px dashed var(--line);border-radius:var(--radius-sm)}
.oppsok{font-size:var(--t-sm);color:var(--green);line-height:1.55;margin:10px 0 0}
.oppq{font-size:var(--t-base);color:var(--fg);line-height:1.65;margin:0 0 12px;
  padding-left:12px;border-left:2px solid var(--accent)}
.oppkv{display:grid;gap:10px}
.oppkv>div{display:flex;flex-direction:column;gap:3px}
.oppkv em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.oppkv span{font-size:var(--t-sm);color:var(--fg2);line-height:1.55}
.oppfoot{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-top:12px}
.oppreq{margin:0;padding-left:19px}
.oppreq li{font-size:var(--t-sm);color:var(--fg2);line-height:1.6;margin-top:6px}
.oppreq li b{font-family:var(--mono);color:var(--fg)}

/* ---- what the checks said: a rejection and a note are opposite outcomes and never share a colour ---- */
.oppv{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;
  padding:10px 13px;border-radius:var(--radius-sm);border:1px solid;margin-bottom:11px}
.oppv b{font-size:var(--t-base);font-weight:700}
.oppv span{font-family:var(--mono);font-size:var(--t-micro);opacity:.8}
.oppv.v-ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 40%,transparent);
  background:color-mix(in srgb,var(--green) 10%,transparent)}
.oppv.v-no{color:var(--red);border-color:color-mix(in srgb,var(--red) 40%,transparent);
  background:color-mix(in srgb,var(--red) 10%,transparent)}
.oppchk{list-style:none;margin:0;padding:0}
.oppchk li{font-size:var(--t-sm);line-height:1.55;padding:5px 0 5px 20px;position:relative}
.oppchk.bad li{color:var(--red)}
.oppchk.bad li::before{content:'\2715';position:absolute;left:2px;top:5px;font-size:var(--t-micro);opacity:.85}
.oppchk.warn{margin-top:10px}
.oppchk.warn li{color:var(--amber)}
.oppchk.warn li::before{content:'\2022';position:absolute;left:4px;top:4px}
.oppchk .oppchkh{color:var(--faint);font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);font-weight:700;padding-left:0}
.oppchk .oppchkh::before{content:''}
.oppbs{display:flex;flex-direction:column;gap:9px;margin-top:12px;padding:11px 13px;
  background:var(--sunk);border-radius:var(--radius-sm)}
.oppb{display:grid;grid-template-columns:1fr auto;gap:2px 10px;align-items:baseline}
.oppb em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.oppb b{font-family:var(--mono);font-size:var(--t-sm);text-align:right}
.oppb span{grid-column:1 / -1;font-size:var(--t-micro);color:var(--dim);line-height:1.55}

/* ---- how the size was worked out ---- */
/* Eight tiles, not one clipped slab. Every cell here carries a data-tip, and a data-tip bubble
   is a pseudo-element positioned INSIDE its anchor — so the hairline-grid trick this used to use
   (gap:1px over a line-coloured background, clipped with overflow:hidden to round the corners)
   was quietly slicing the top row's tooltips in half. Separate bordered tiles round themselves,
   need no clipping, and nothing can eat an explanation. */
.opprisk{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(112px,100%),1fr));gap:var(--s2)}
/* space-between, not a min-height guess. Grid cells in a row already stretch to the same height,
   so pinning the label to the top and the figure to the bottom aligns every figure on one line no
   matter how many lines its label wrapped to — "Share of the account" runs to three lines in a
   phone-width drawer and one on a desktop, and a fixed floor would only ever be right at one of
   those widths. Eight figures that do not sit on a baseline read as eight unrelated facts. */
.opprr{display:flex;flex-direction:column;justify-content:space-between;gap:6px;
  padding:9px 11px;background:var(--panel);border:1px solid var(--line);border-radius:var(--radius-sm)}
.opprr em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700;line-height:1.3}
.opprr b{font-family:var(--mono);font-size:var(--t-md);font-weight:700;letter-spacing:-.01em}

/* ---- price ---- */
.oppchart{background:var(--sunk);border-radius:var(--radius-sm);padding:8px 6px}
.oppchart svg{display:block;width:100%;height:auto}
.oppcx{display:flex;justify-content:space-between;gap:var(--s2);margin-top:6px;
  font-size:var(--t-micro);color:var(--faint);font-family:var(--mono)}

/* ---- dated events ---- */
.oppcal{display:flex;flex-direction:column}
.oppcalr{display:grid;grid-template-columns:auto 1fr auto;gap:var(--s3);align-items:center;
  padding:7px 9px;border-bottom:1px solid var(--linesoft);border-left:2px solid transparent}
.oppcalr:last-child{border-bottom:none}
.oppcalr.soon{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 6%,transparent)}
.oppcald{font-family:var(--mono);font-size:var(--t-micro);color:var(--dim)}
.oppcalk{font-size:var(--t-sm);color:var(--fg2)}
.oppcaln{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);text-align:right;white-space:nowrap}

/* ---- decision history: a real timeline, one rail and a dot per event ---- */
.opptl{list-style:none;margin:0;padding:0 0 0 16px;position:relative}
.opptl::before{content:'';position:absolute;left:3px;top:6px;bottom:6px;width:1px;background:var(--line)}
/* 62px was measured against a bare clock and the stamps carry a zone: "10:12 AM ET" is eleven
   monospace characters and it ran straight into the headline beside it. The column is sized to
   the longest stamp this app can produce, and the gap is part of the promise — a time that
   touches the sentence it belongs to reads as one word. */
.opptl li{display:grid;grid-template-columns:86px 1fr;gap:var(--s3);align-items:baseline;
  padding:6px 0;position:relative}
.opptl li::before{content:'';position:absolute;left:-16px;top:11px;width:7px;height:7px;
  border-radius:50%;background:var(--line2);box-shadow:0 0 0 3px var(--panel)}
.opptl li.t-blue::before{background:var(--blue)}
.opptl li.t-amber::before{background:var(--amber)}
.opptl li.t-green::before{background:var(--green)}
.opptl li.t-red::before{background:var(--red)}
.opptl li.t-grey::before{background:var(--line2)}
/* v5.1 — the lifecycle timeline tones a research memo violet, matching the memo chip everywhere
   else in the app. Without this rule that event fell through to the default grey dot and read as
   an unclassified record. */
.opptl li.t-violet::before{background:var(--violet)}
.opptlt{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);white-space:nowrap}
.opptlb{font-size:var(--t-sm);color:var(--fg2);line-height:1.5}
.opptlb b{color:var(--fg);font-weight:650}
.opptlr{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px}

/* ---- v5.2 bar-data audit: our numbers next to the broker's, side by side ----
   Two columns of figures rather than a verdict badge, because the point of the section is that the
   reader can check the arithmetic instead of taking our word for it. Rows that carry a real
   accusation get the left rail; a method difference is tinted amber in the diff cell only and never
   marks the whole row, so the eye is not pulled toward something that is not evidence. */
.opaudh{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-bottom:8px;
  font-size:var(--t-micro);font-family:var(--mono)}
.opaudd{margin:0 0 10px;font-size:var(--t-sm);line-height:1.5;color:var(--fg2)}
table.opaud{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
table.opaud th{text-align:left;font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);padding:6px 9px;border-bottom:1px solid var(--line2);white-space:nowrap}
table.opaud th.num,table.opaud td.num{text-align:right}
table.opaud td{padding:7px 9px;border-bottom:1px solid var(--linesoft);color:var(--fg2);
  border-left:2px solid transparent}
table.opaud tr:last-child td{border-bottom:none}
table.opaud tr.bad td:first-child{border-left-color:var(--red)}
table.opaud tr.bad{background:var(--red-soft)}

/* ---- v5.2 company fundamentals: what the company reports, as the broker carries it ----
   The least opinionated block on the panel by design. No verdict colour anywhere: a P/E is a fact,
   not a signal, and tinting it green or red would be this app taking a view it is not allowed to
   take. The only colour in here is on the quarter-over-quarter margin delta, which is a direction
   rather than a judgement, and on the staleness chip, which is about our data and not the company. */
.opcfh{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;
  margin-bottom:10px}
.opcfid{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;min-width:0}
.opcfind{font-size:var(--t-micro);color:var(--dim);letter-spacing:var(--wide);text-transform:uppercase}
.opcfg{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(132px,100%),1fr));gap:8px;margin-bottom:12px}
.opcft{background:var(--panel2);border:1px solid var(--linesoft);border-radius:var(--radius-sm);
  padding:9px 11px;display:flex;flex-direction:column;gap:3px;min-width:0}
.opcft em{font:var(--lbl);font-style:normal;text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);font-size:var(--t-micro)}
.opcft b{font-family:var(--mono);font-size:var(--t-md);color:var(--fg);letter-spacing:var(--tight)}

.opcfr{margin:0 0 12px;padding:11px 12px;background:var(--panel2);border:1px solid var(--linesoft);
  border-radius:var(--radius-sm)}
.opcfrh{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);margin-bottom:9px}
.opcfrh em{font:var(--lbl);font-style:normal;text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);font-size:var(--t-micro)}
.opcfrh b{font-family:var(--mono);font-size:var(--t-sm);color:var(--fg2)}
.opcfrb{position:relative;height:8px;border-radius:var(--radius-pill);background:var(--panel3);
  overflow:visible}
.opcfrf{position:absolute;left:0;top:0;bottom:0;border-radius:var(--radius-pill);
  background:linear-gradient(90deg,var(--accent-soft),var(--accent));min-width:2px}
.opcfrm{position:absolute;top:-4px;bottom:-4px;width:2px;background:var(--fg);border-radius:2px;
  transform:translateX(-1px);box-shadow:0 0 0 2px var(--panel2)}
.opcfrx{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);margin-top:9px;
  font-family:var(--mono);font-size:var(--t-micro);color:var(--fg2)}

.opcfd{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;margin:0 0 12px;padding:9px 12px;
  background:var(--panel2);border:1px solid var(--linesoft);border-radius:var(--radius-sm)}
.opcfd em{font:var(--lbl);font-style:normal;text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);font-size:var(--t-micro)}
.opcfd b{font-family:var(--mono);font-size:var(--t-sm);color:var(--fg)}
.opcfd span{font-size:var(--t-micro);color:var(--dim);flex:1 1 160px}

table.opcfq{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
table.opcfq th{text-align:left;font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);
  color:var(--faint);padding:6px 9px;border-bottom:1px solid var(--line2);white-space:nowrap}
table.opcfq th.num,table.opcfq td.num{text-align:right}
table.opcfq td{padding:7px 9px;border-bottom:1px solid var(--linesoft);color:var(--fg2);white-space:nowrap}
table.opcfq tr:last-child td{border-bottom:none}
table.opcfq tbody tr:hover{background:var(--panel2)}

@media(max-width:700px){
  .opcfg{grid-template-columns:repeat(auto-fit,minmax(min(112px,100%),1fr))}
}

/* ---- where each number came from ---- */
.oppst2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(158px,100%),1fr));gap:10px}
.oppst2>div{display:flex;flex-direction:column;gap:3px}
.oppst2 em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.oppst2 b{font-family:var(--mono);font-size:var(--t-sm);color:var(--fg2);font-weight:650}

@media(max-width:700px){
  .pht{font-size:var(--t-2xl)}
  .phead{flex-direction:column;align-items:stretch}
  .opline{font-size:var(--t-micro)}
  .opphsym{font-size:var(--t-xl)}
}

/* ============================================================================================
   PORTFOLIO — v5.1
   The Opportunities language, applied to the book. Same header shape, same segmented panes,
   same provenance footnotes, so moving between the two pages costs nothing to re-learn.
   One rule is load-bearing here and nowhere else: no ancestor of a position card may set
   overflow. Tooltips render inside their anchor, so an overflow on .pfcards or .pfc would
   clip every explanation on the page against the tile it belongs to.
   ============================================================================================ */
.pfwrap{padding-bottom:var(--s4)}
.pfline{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:var(--s4);
  padding-top:var(--s3);border-top:1px solid var(--linesoft);
  font-size:var(--t-sm);color:var(--dim)}
.pfline b{font-family:var(--mono);color:var(--fg);font-weight:700}
.pfline b.neg{color:var(--red)}

/* ---- the protection band: outside the panes, so it shows in all three views ---- */
.pfprot{margin:var(--s3) 0 var(--s4);padding:var(--s4);border-radius:var(--radius);
  background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--line2)}
.pfprot.w-good{border-left-color:var(--green);background:color-mix(in srgb,var(--green) 5%,var(--panel))}
.pfprot.w-warn{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 6%,var(--panel))}
.pfprot.w-bad{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 7%,var(--panel))}
.pfprot.w-idle{border-left-color:var(--dim)}
.pfprh{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
.pfprk{font-size:var(--t-label);text-transform:uppercase;letter-spacing:var(--wide);
  font-weight:700;color:var(--fg2)}
.pfpra{font-size:var(--t-micro);color:var(--faint);position:relative;border-bottom:1px dotted var(--line2)}
.pfprl{font-size:var(--t-md);color:var(--fg);line-height:1.55;margin:10px 0 0;max-width:92ch;font-weight:600}
.pfprc{display:flex;align-items:stretch;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s4)}
.pfprcc{position:relative;display:flex;align-items:baseline;gap:7px;padding:7px 12px;
  border-radius:var(--radius-sm);border:1px solid var(--line2);background:var(--panel2)}
.pfprcc b{font-family:var(--mono);font-size:var(--t-lg);font-weight:750;line-height:1}
.pfprcc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--dim);font-weight:700}
.pfprcc.k-verified b{color:var(--green)}
.pfprcc.k-partial b{color:var(--amber)}
.pfprcc.k-missing b{color:var(--red)}
.pfprcc.k-unknown b{color:var(--dim)}
/* A count of zero is not news. It stays legible and stops competing for the eye, so the one
   non-zero count in a row of four is the thing that gets read first. */
.pfprcc.zero{opacity:.5;background:transparent}
.pfprcc.zero b{color:var(--faint)}
.pfprcu{position:relative;display:flex;flex-direction:column;gap:3px;padding:7px 13px;margin-left:auto;
  border-radius:var(--radius-sm);border:1px dashed var(--line2);background:var(--sunk)}
.pfprcu b{font-family:var(--mono);font-size:var(--t-md);font-weight:750}
.pfprcu em{font-style:normal;font-size:var(--t-micro);color:var(--faint);line-height:1.4}

/* ---- section headers, shared by every card on the page ---- */
.pfsech{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s4)}
.pfsech h2{font-size:var(--t-lg);font-weight:700;letter-spacing:-.015em;margin:0}
.pfsecn{font-size:var(--t-micro);color:var(--faint);line-height:1.5;max-width:82ch}

/* ---- capital ---- */
.pfcapg{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(168px,100%),1fr));gap:var(--s2)}
.pfcapc{position:relative;display:flex;flex-direction:column;gap:4px;padding:12px 14px;
  border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--linesoft)}
.pfcapc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pfcapc b{font-family:var(--mono);font-size:var(--t-xl);font-weight:750;letter-spacing:-.015em;line-height:1.1}
.pfcapc i{font-style:normal;font-size:var(--t-micro);color:var(--dim);line-height:1.45}

/* ---- position cards ---- */
.pfcards{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(340px,100%),1fr));gap:var(--s3);margin:var(--s4) 0}
@media(max-width:760px){.pfcards{grid-template-columns:minmax(0,1fr)}}
.pfc{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--line2);
  border-radius:var(--radius);padding:var(--s4);cursor:pointer;min-width:0;
  transition:border-color .14s ease,transform .14s ease,box-shadow .14s ease}
.pfc:hover{transform:translateY(-1px);box-shadow:0 6px 20px -8px rgba(0,0,0,.6);
  border-color:color-mix(in srgb,var(--accent) 50%,var(--line2))}
/* The left rule is the protection state and nothing else. It is the one piece of colour on the
   tile that never means performance, so a red edge on a green position reads correctly. */
.pfc.s-verified{border-left-color:var(--green)}
.pfc.s-partial{border-left-color:var(--amber)}
.pfc.s-missing{border-left-color:var(--red)}
.pfc.s-unknown{border-left-color:var(--dim)}
/* v6.38.3 — the price is ALWAYS top-right. This wrapped per-card depending on how wide the
   status chips happened to be, so three cards in a row put the last print in the corner and
   the fourth put it underneath. Four cards side by side that do not agree on where a number
   lives is the thing that reads as unfinished. nowrap plus a truncating left block. */
.pfctop{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);flex-wrap:nowrap}
.pfctl{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0;flex:1 1 auto}
.pfctr{flex:none}
.pfcsym{font-size:var(--t-xl);font-weight:760;letter-spacing:-.02em}
.pfctr{display:flex;flex-direction:column;align-items:flex-end;gap:2px;white-space:nowrap}
.pfctr b{font-family:var(--mono);font-size:var(--t-md);font-weight:700}
.pfctr span{font-family:var(--mono);font-size:var(--t-micro);font-weight:650}
.pfcsec{font-size:var(--t-micro);color:var(--faint);margin-top:6px}
.pfcst{font-size:var(--t-sm);color:var(--fg2);line-height:1.55;margin:10px 0 0}
.pfcbar{position:relative;margin-top:12px}
.pfcbar::before{content:'';position:absolute;left:0;right:0;top:0;height:4px;
  border-radius:var(--radius-pill);background:var(--line)}
.pfcbar i{position:relative;display:block;height:4px;border-radius:var(--radius-pill);
  background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 70%,transparent),var(--accent));
  min-width:4px}
.pfcbar span{display:block;font-size:var(--t-micro);color:var(--faint);margin-top:5px}
.pfcg{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2);margin-top:12px}
.pfcgc{position:relative;display:flex;flex-direction:column;gap:2px;padding:9px 11px;
  border-radius:var(--radius-sm);background:var(--panel2);min-width:0}
.pfcgc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pfcgc b{font-family:var(--mono);font-size:var(--t-base);font-weight:700;letter-spacing:-.01em}
.pfcgc span{font-size:var(--t-micro);color:var(--dim);line-height:1.4}
.pfcf{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:11px;
  padding-top:10px;border-top:1px solid var(--linesoft)}

/* ---- resting instructions and the stress table ---- */
.pford td,.pfstress td{vertical-align:top}
.pfmean{font-size:var(--t-micro);color:var(--dim);line-height:1.5;max-width:46ch;white-space:normal}
.pfstress tr.mod td{background:color-mix(in srgb,var(--dim) 5%,transparent)}

/* ---- whole-book risk ---- */
.pfrt{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(186px,100%),1fr));gap:var(--s2)}
.pfrtc{position:relative;display:flex;flex-direction:column;gap:4px;padding:13px 15px;
  border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--linesoft)}
.pfrtc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pfrtc b{font-family:var(--mono);font-size:var(--t-2xl);font-weight:750;letter-spacing:-.02em;line-height:1.05}
.pfrtc i{font-style:normal;font-size:var(--t-micro);color:var(--dim);line-height:1.45}
.pfgrid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
@media(max-width:1080px){.pfgrid2{grid-template-columns:minmax(0,1fr)}}
.pfclu{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:var(--s2)}
.pfcluc{padding:11px 13px;border-radius:var(--radius-sm);background:var(--panel2);
  border:1px solid var(--linesoft)}
.pfcluc.hot{border-color:color-mix(in srgb,var(--amber) 45%,transparent);
  background:color-mix(in srgb,var(--amber) 7%,var(--panel2))}
.pfclut{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.pfclut b{font-size:var(--t-sm);font-weight:700}
.pfclus{font-family:var(--mono);font-size:var(--t-micro);color:var(--dim);margin-top:5px;line-height:1.5}
.pfclub{height:4px;border-radius:var(--radius-pill);background:var(--line);margin-top:9px;overflow:hidden}
.pfclub i{display:block;height:100%;background:var(--violet);min-width:3px}
.pfcluv{font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);margin-top:5px}

/* ---- the lifecycle timeline: the Opportunities rail, plus day dividers ---- */
.pfsrc{display:block;font-size:var(--t-micro);color:var(--faint);margin-top:4px;
  font-family:var(--mono);opacity:.85}
.pflife li.opptld{grid-template-columns:1fr;padding:12px 0 3px;font-size:var(--t-micro);
  text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pflife li.opptld::before{display:none}
.pflife li.opptld span{display:inline-block;padding-right:10px;background:var(--panel)}

@media(max-width:700px){
  .pfline{font-size:var(--t-micro)}
  .pfprcu{margin-left:0}
  .pfcg{grid-template-columns:minmax(0,1fr)}
}

/* ============================================================================================
   v5.2 · THE PERFORMANCE PAGE (.pg*)
   ============================================================================================
   One rule governs the type scale on this page: --t-3xl belongs to the verdict headline and to
   nothing else. It is the answer to the only question the page asks, and if a second figure on
   the screen is set at the same size then the page has two heroes and therefore none.
   ---------------------------------------------------------------------------------------- */

/* ---- 0. the verdict hero ---- */
.pgv{position:relative;overflow:hidden;padding:var(--s5) var(--s5) var(--s4)}
.pgv::before{content:'';position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--grey)}
.pgv.v-good::before{background:var(--green)}
.pgv.v-bad::before{background:var(--red)}
.pgv.v-warn::before{background:var(--amber)}
.pgv.v-neutral::before{background:var(--blue)}
.pgv.v-good{background:linear-gradient(100deg,var(--green-soft),transparent 46%),var(--panel)}
.pgv.v-bad{background:linear-gradient(100deg,var(--red-soft),transparent 46%),var(--panel)}
.pgv.v-warn{background:linear-gradient(100deg,var(--amber-soft),transparent 46%),var(--panel)}
.pgv.v-neutral{background:linear-gradient(100deg,var(--accent-soft),transparent 46%),var(--panel)}
.pgvq{font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);color:var(--faint)}
.pgvh{font-size:var(--t-3xl);font-weight:760;letter-spacing:var(--tight);line-height:1.1;
  margin:var(--s2) 0 var(--s3);color:var(--fg)}
.pgv.v-good .pgvh{color:var(--green)}
.pgv.v-bad .pgvh{color:var(--red)}
.pgv.v-warn .pgvh{color:var(--amber)}
.pgvs{font-size:var(--t-md);line-height:1.55;color:var(--fg2);max-width:82ch}
.pgvb{list-style:none;margin:var(--s4) 0 0;padding:0;display:grid;gap:var(--s2);max-width:96ch}
.pgvb li{position:relative;padding-left:17px;font-size:var(--t-sm);line-height:1.6;color:var(--fg2)}
.pgvb li::before{content:'';position:absolute;left:0;top:8px;width:6px;height:6px;border-radius:50%;
  background:var(--faint)}
/* The confidence line is a label and a sentence, and it has to read as one. Left inline, the
   sentence wraps back underneath the chip on the second line and the eye loses the hang, so the
   row is a flex pair with the text as its own block. */
.pgvc{display:flex;align-items:flex-start;gap:9px;margin-top:var(--s4);padding-top:var(--s3);
  border-top:1px solid var(--linesoft);
  font-size:var(--t-micro);line-height:1.6;color:var(--dim);max-width:96ch}
.pgvci{flex:none;margin-top:1px;padding:2px 7px;border-radius:var(--radius-pill);
  background:var(--panel3);border:1px solid var(--line2);font-family:var(--mono);
  font-size:var(--t-nano);letter-spacing:var(--wide);color:var(--faint)}

/* ---- the shared cell grid ---- */
.pggrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(196px,100%),1fr));gap:var(--s2);
  margin:var(--s3) 0}
.pggrid.pgg3{grid-template-columns:repeat(auto-fit,minmax(min(214px,100%),1fr))}
.pggrid.pgg5{grid-template-columns:repeat(auto-fit,minmax(min(160px,100%),1fr))}
/* Six and twelve cells are the two counts this page actually uses, and auto-fit gets both wrong:
   it packs five across and leaves the sixth stranded alone on a second row, which reads as a
   layout accident rather than a group. These two are counted, not fitted — 6 lays out 3x2 and 12
   lays out 4x3, so every row is full at every width. */
/* .rdbody is a two-column body, which is right for the research drawer it was built for and wrong
   for a drawer whose whole content is one full-width grid — that one lands in the left column at
   half width with dead space beside it. These drawers opt out and stack. */
.rdbody.pgwide{display:block}
.pggrid.pgg6{grid-template-columns:repeat(3,minmax(0,1fr))}
.pggrid.pgg4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:980px){.pggrid.pgg4{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:860px){.pggrid.pgg6{grid-template-columns:repeat(2,minmax(0,1fr))}
  .pggrid.pgg4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.pggrid.pgg6,.pggrid.pgg4{grid-template-columns:minmax(0,1fr)}}
.pgc{position:relative;display:flex;flex-direction:column;gap:4px;padding:13px 15px;
  border-radius:var(--radius-sm);background:var(--panel2);border:1px solid var(--linesoft)}
.pgc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pgc b{font-family:var(--mono);font-size:var(--t-2xl);font-weight:750;letter-spacing:-.02em;
  line-height:1.05}
.pgc i{font-style:normal;font-size:var(--t-micro);color:var(--dim);line-height:1.45}
.pggrid.pgg5 .pgc b,.pggrid.pgg4 .pgc b{font-size:var(--t-lg)}

/* ---- charts and axes ---- */
.pgchart{margin:var(--s3) 0 0;padding:var(--s2) 0;border-radius:var(--radius-sm);
  background:var(--sunk);border:1px solid var(--linesoft)}
.pgax{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);
  font-family:var(--mono);font-size:var(--t-micro);color:var(--faint);margin-top:6px}
.pglegend{display:inline-flex;align-items:center;gap:7px;font-family:var(--sans);color:var(--dim)}
.pgld,.pgls{display:inline-block;width:15px;height:0;border-top:2px dashed var(--dim);
  vertical-align:middle}
.pgls{border-top-style:solid;margin-left:9px}
.pgempty{padding:18px 0;font-size:var(--t-sm);line-height:1.6;color:var(--dim);max-width:84ch}

/* ---- the two prose registers: a verdict sentence, and a quiet footnote ---- */
.pgverd{font-size:var(--t-base);line-height:1.6;color:var(--fg2);max-width:88ch;
  margin-top:var(--s3);padding-left:11px;border-left:2px solid var(--line2)}
.pgnote{font-size:var(--t-micro);line-height:1.6;color:var(--dim);max-width:92ch;margin-top:9px}
.pgsay{font-size:var(--t-micro);line-height:1.6;color:var(--dim);max-width:92ch;margin:2px 0 10px}
.pgsub{font:var(--lbl);text-transform:uppercase;letter-spacing:var(--wide);color:var(--dim);
  margin:var(--s4) 0 var(--s1)}
.pgul{margin:6px 0 0;padding-left:17px;display:grid;gap:5px}
.pgul li{font-size:var(--t-micro);line-height:1.6;color:var(--dim)}

/* ---- 2. banked versus marked ---- */
.pgsplit{display:grid;grid-template-columns:1fr auto 1fr auto 1fr;align-items:stretch;
  gap:var(--s2);margin:var(--s3) 0}
.pgsc{display:flex;flex-direction:column;gap:5px;padding:15px 17px;border-radius:var(--radius-sm);
  background:var(--panel2);border:1px solid var(--linesoft);min-width:0}
.pgsc-real{border-color:color-mix(in srgb,var(--green) 26%,transparent)}
.pgsc-open{border-color:color-mix(in srgb,var(--amber) 26%,transparent)}
.pgsc-tot{background:var(--panel3)}
.pgsc em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pgsc b{font-family:var(--mono);font-size:var(--t-2xl);font-weight:750;letter-spacing:-.02em;
  line-height:1.05}
.pgsc i{font-style:normal;font-size:var(--t-micro);color:var(--dim);line-height:1.45}
.pgscx{font-size:var(--t-micro);color:var(--faint);line-height:1.45;margin-top:2px}
.pgsjoin{align-self:center;font-family:var(--mono);font-size:var(--t-lg);color:var(--faint)}
.pgbar{display:flex;height:8px;border-radius:var(--radius-pill);overflow:hidden;
  background:var(--line);margin-top:var(--s2)}
.pgbar i{display:block;height:100%}
.pgbr{background:var(--green)}
.pgbu{background:color-mix(in srgb,var(--amber) 70%,transparent)}
.pgbarl{display:flex;justify-content:space-between;font-size:var(--t-micro);color:var(--faint);
  margin-top:4px}
@media(max-width:940px){
  .pgsplit{grid-template-columns:minmax(0,1fr)}
  .pgsjoin{display:none}
}

/* ---- 4. the cost flow ---- */
.pgflow{display:grid;grid-template-columns:1fr auto 1fr auto 1fr;align-items:stretch;
  gap:var(--s2);margin:var(--s3) 0 var(--s4)}
.pgfs{display:flex;flex-direction:column;gap:4px;padding:14px 16px;border-radius:var(--radius-sm);
  background:var(--panel2);border:1px solid var(--linesoft);min-width:0}
.pgfs-net{background:var(--panel3);border-color:var(--line2)}
.pgfs em{font-style:normal;font-size:var(--t-micro);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);font-weight:700}
.pgfs b{font-family:var(--mono);font-size:var(--t-xl);font-weight:750;letter-spacing:-.02em}
.pgfs i{font-style:normal;font-size:var(--t-micro);color:var(--dim);line-height:1.45}
.pgfarrow{align-self:center;font-family:var(--mono);font-size:var(--t-lg);color:var(--faint)}
.pgclines{display:grid;gap:var(--s2)}
.pgcl{padding:11px 13px;border-radius:var(--radius-sm);background:var(--panel2);
  border:1px solid var(--linesoft)}
.pgcl.est{border-style:dashed;border-color:color-mix(in srgb,var(--amber) 38%,transparent)}
.pgclh{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.pgcll{font-size:var(--t-sm);font-weight:650}
.pgclv{margin-left:auto;font-size:var(--t-base);font-weight:700;color:var(--red)}
.pgclb{height:4px;border-radius:var(--radius-pill);background:var(--line);margin:8px 0 7px;
  overflow:hidden}
.pgclb i{display:block;height:100%;background:color-mix(in srgb,var(--red) 62%,transparent);
  min-width:3px}
.pgcls{font-size:var(--t-micro);color:var(--dim);line-height:1.55;max-width:92ch}
@media(max-width:940px){
  .pgflow{grid-template-columns:minmax(0,1fr)}
  .pgfarrow{display:none}
}

/* ---- 5 and 6. attribution ---- */
.pgt{width:100%;border-collapse:collapse;font-size:var(--t-sm)}
.pgt th{text-align:left;padding:9px 12px;font:var(--lbl);text-transform:uppercase;
  letter-spacing:var(--wide);color:var(--faint);border-bottom:1px solid var(--line);
  white-space:nowrap}
.pgt td{padding:10px 12px;border-bottom:1px solid var(--linesoft);vertical-align:middle}
.pgt tr:last-child td{border-bottom:none}
.pgt tbody tr:hover{background:var(--panel2)}
.pgt tr.thinrow td{opacity:.62}
.pgak{font-weight:650;letter-spacing:var(--tight)}
.pgabar{width:110px}
.pgabar i{display:block;height:6px;border-radius:var(--radius-pill);min-width:3px}
.pgabar i.up{background:var(--green)}
.pgabar i.dn{background:var(--red)}

@media(max-width:700px){
  .pgvh{font-size:var(--t-2xl)}
  .pgvs{font-size:var(--t-base)}
  .pgv{padding:var(--s4)}
}

:root{--bg:#101416;--panel:#181e21;--panel2:#202b2d;--panel3:#263335;--line:#2c3a38;--fg:#e9eeec;--fg2:#c8d5cf;--dim:#a1b3a9;--accent:#a9e6cd;--blue:#a9e6cd;--accent-soft:#243b33}
html.light{--bg:#edf1ef;--panel:#ffffff;--panel2:#f2f6f3;--panel3:#e6eee8;--line:#d7e0db;--fg:#172a24;--fg2:#344f42;--dim:#576b62;--accent:#186746;--blue:#186746;--accent-soft:#e0eee5}
body{background:var(--bg)}header{height:auto;min-height:62px;box-shadow:none;padding:12px 22px}.themebtn{border-radius:7px;padding:7px 10px}#themebtn{min-width:112px;font-size:var(--t-sm)}
.navrail{width:190px;padding:20px 12px;background:var(--panel);top:0}.navrail a{flex-direction:row;justify-content:flex-start;gap:12px;padding:13px 12px;font-size:var(--t-sm)}.navrail a.on{background:var(--accent-soft);color:var(--accent)}.navrail .nicon{width:19px;height:19px;flex:none}.navrail a>span{white-space:normal;text-align:left}.applayout>main{padding:24px;min-width:0}.ctxbar{background:var(--panel)}.acctbar{background:var(--panel);padding-top:14px;padding-bottom:14px}.acctbar .ac{border-right:1px solid var(--line);padding-right:20px}.subnav a.on{color:var(--accent)}
.overview-page .lvsw,.overview-page .lvnote{display:none}.overview-page .ctxbar{display:none}.overview-page .overview{max-width:1380px;margin:0 auto}.overview-page .ov-card{display:block!important}
.ov-heading{display:flex;justify-content:space-between;align-items:center;gap:16px;margin-bottom:22px}.ov-heading h1{font-size:var(--t-3xl);font-weight:600;letter-spacing:-1px;margin:4px 0}.ov-heading p,.ov-hero p{color:var(--dim);margin:8px 0 20px}.ov-kicker{font-size:var(--t-micro);font-weight:700;text-transform:uppercase;letter-spacing:1.5px;color:var(--accent)}
.ov-account{display:grid;grid-template-columns:1fr 1fr 1.2fr 1.6fr;gap:20px;padding:20px 22px;background:var(--panel);border:1px solid var(--line);border-radius:10px;margin-bottom:22px}.ov-account small{display:block;color:var(--dim);font-size:var(--t-micro)}.ov-account strong{display:block;font-size:var(--t-2xl);font-variant-numeric:tabular-nums;font-weight:600}.ov-account .ov-text{font-size:var(--t-sm);padding-top:7px}.ov-account>div+div{border-left:1px solid var(--line);padding-left:20px}
.ov-card{background:var(--panel);padding:23px;border:1px solid var(--line);border-radius:11px;margin:0 0 20px;box-shadow:0 5px 20px #00000008}.ov-card h2{font-size:var(--t-lg);font-weight:600;margin:0}.ov-card p{line-height:1.6}.ov-hero{background:linear-gradient(110deg,var(--accent-soft),var(--panel));border-left:3px solid var(--accent)}.ov-hero h2{font-size:var(--t-2xl);margin:10px 0;letter-spacing:-.6px}.ov-primary{display:inline-block;background:var(--accent);color:var(--bg);font-weight:700;padding:11px 16px;border-radius:7px}.ov-secondary{margin-left:18px}.ov-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:20px}.ov-cardhead{display:flex;justify-content:space-between;align-items:center;gap:15px;margin-bottom:18px}.ov-cardhead>a{font-size:var(--t-sm)}.ov-row{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:16px 0;border-top:1px solid var(--line)}.ov-row strong,.ov-row small{display:block}.ov-row small{font-size:var(--t-micro);color:var(--dim);margin-top:5px}.ov-pill{font-size:var(--t-micro);background:var(--accent-soft);color:var(--accent);padding:4px 8px;border-radius:5px;white-space:nowrap}.ov-pill.warn{color:var(--amber);background:var(--amber-soft)}.ov-foot{font-size:var(--t-micro);color:var(--dim);margin:16px 0 0}.ov-unknown{color:var(--amber)}.overview details{margin-top:16px}.overview summary{cursor:pointer;padding:8px 0}.overview a:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
@media(max-width:1100px){.ov-grid{grid-template-columns:1fr}.ov-account{grid-template-columns:1fr 1fr}.ov-account>div+div{border:0;padding-left:0}}
@media(max-width:900px){.bottomnav{overflow-x:auto;justify-content:flex-start}.bottomnav a{flex:0 0 78px;min-width:78px}.overview-page .hdrtools{display:flex;flex-wrap:wrap;gap:6px;width:100%;justify-content:flex-end}.navrail{display:none}.applayout>main{padding:16px 12px}.ov-heading{align-items:flex-start;flex-direction:column}.ov-heading h1{font-size:var(--t-2xl)}.ov-card{padding:18px}.ov-account{padding:16px;gap:16px}.ov-row{flex-wrap:wrap}.ov-secondary{display:inline-block;margin:12px 0 0}.ov-cardhead{align-items:flex-start;flex-wrap:wrap}#themebtn{min-width:98px}}
