/* ============================================================================
   PROJECT MAGNETO — MAGNETO RELAY subscriber radar (LIVE)
   MV7 design tokens, inherited verbatim from cloud/relay/mockups/subscriber_radar_mockup.html
   (the approved design) which lifted them from magneto-prod index.html.

   Deliberately SINGLE-THEME (the product is dark) and every colour is painted
   explicitly, so the page holds its own ground on any host.

   What was DROPPED from the mockup, on purpose:
     · .mock          — the "MOCKUP · replay" banner. This page is live.
     · .divrow        — the "end of replay" divider. There is no replay.
     · .rot/.rot-up/.rot-down — the sector-rotation chips. SUB.PULSE.V1 carries no
       rotation list, and a style for a state the server cannot send is an invitation
       to render one.
   What was ADDED:
     · the sign-in gate, the account bar, the reconnecting pill, the delay note,
       the quiet "pulse coming online" state, .dash (the cells with no reading),
       the SUB.PULSE.V1 live strip (.regime.pstale, .gbr, .sarr, the .flat variants),
       and :focus-visible rings (the mockup had none; a product page must be
       keyboard-navigable).
     · PULSE v2 — the LIFE pass: state colour + a soft glow on the market gauge
       (NEUTRAL is warm AMBER, never grey — grey is reserved for the one state that
       genuinely has no data), direction-tinted sector tiles, gradient
       breadth bars, family-coloured row accents, one notch more saturation on the
       chips and the LIVE pill, plus the two MECHANICAL columns: .act (the written
       interest tier — three dots until 2026-08-28, when the operator ordered words)
       and .dirc (the direction chip). Saturation and glow only — no new animation
       beyond the existing pulse dot, and the reduced-motion block still kills all
       of it.
     · LIFE pass 2 (2026-09-23, operator: "put some more life and colours into the
       system"): every row's surface takes its family colour as an 8% cast (`--fam-tint`
       on `background-image`, see the TINT note), and an active family chip wears its
       family's colour. Still no new keyframe.
     · .tkwrap/.tk — the alert ticket: the full card behind a row, both languages at
       once, each block in its own direction. Same modal language as the sign-in gate.
     · tbody tr.fresh — the 60-second arrival state. A transition, not a keyframe, so
       the page's animation ceiling is unchanged and reduced motion switches it off.
     · tbody tr.crit / .crit-live — the CRITICAL OSINT row (operator order 2026-09-24):
       a light-red surface for its whole life, and inside its 15-minute window the ONE
       keyframe the operator ordered by name (`critflick`, "flickering"), switched off
       by the reduced-motion blocks like every other animation here.
   What was DROPPED:
     · the macro band (2026-10-16, operator order): the strip is gone from the
       product and every one of its rules went with it — a style for a node the
       page never draws is dead vocabulary.
   ============================================================================ */

:root{
  --bg-base:#080C14; --bg-surface:#10182A; --bg-elevated:#161F36; --bg-deeper:#060912;
  --bg-hover:rgba(107,159,255,.07);
  --text-primary:#EAEEF7; --text-secondary:#9DA9C2; --text-tertiary:#6A7591; --text-disabled:#424D6A;
  /* the ONE colour above --text-primary: the tile's price, by operator order 2026-09-10 */
  --px-bright:#FFFFFF;
  --accent:#6B9FFF; --accent-2:#87B5FF; --accent-bg:rgba(107,159,255,.10); --accent-glow:rgba(107,159,255,.35);
  --up:#3BD4A2; --down:#F36E6E; --warn:#E8B04A; --warn-bg:rgba(232,176,74,.10);
  /* RISK WARNING tokens (user 2026-09-24 19:1x ET, after seeing the live opinion footer: "way
     too grey, we need it much more visible") — the user's own red family, declared ONCE here
     and used only by the opinion page's strip + block. Not --down / --crit-*: those mean a
     bearish chip and a critical severity row. */
  --risk:#EF4444; --risk-bg:rgba(239,68,68,.14); --risk-ring:rgba(239,68,68,.35);
  --risk-label:#FCA5A5; --risk-body:#F8FAFC; --risk-strip-bg:rgba(239,68,68,.10);
  --risk-strip-line:rgba(239,68,68,.55); --risk-strip-text:#FECACA;
  /* the third interest tier only — one hot accent, used in exactly one place */
  --hot:#FF8A3D;
  /* the FOURTH and top interest tier only (CRITICAL INTEREST, 2026-08-28). Its own token
     rather than --down: --down means "this alert is bearish" on the direction chip, and a
     shared colour would make the two mechanical columns look like they were agreeing about
     something. Deliberately hotter and more saturated than --hot, because it sits above it. */
  --crit:#FF4D4D;
  --info:#9B8CFF; --info-bg:rgba(155,140,255,.10);
  --osint:#4FC3E8; --osint-bg:rgba(79,195,232,.10); --osint-line:rgba(79,195,232,.38);
  /* two families the mockup never had to draw (its window held none) */
  --news:#E0709B; --news-bg:rgba(224,112,155,.10); --news-line:rgba(224,112,155,.38);
  --market:#8FA3C8; --market-bg:rgba(143,163,200,.10); --market-line:rgba(143,163,200,.34);
  /* the brief (market_update) is BLUE since 2026-09-23 (operator: "the global market update
     blueish") — a sky blue set apart from levels' periwinkle --accent, osint's greener cyan
     and market's desaturated grey-blue. It had been gold. */
  --brief:#5EA8F2; --brief-bg:rgba(94,168,242,.10); --brief-line:rgba(94,168,242,.38);
  /* insider has its OWN token since 2026-09-23 (operator: "make the insider light green") —
     it had borrowed --warn, so an insider row read as a caveat. A light, yellow-leaning green,
     one clear step from momentum's teal --up, so the two greens never read as one family. */
  --insider:#9FE870; --insider-bg:rgba(159,232,112,.12); --insider-line:rgba(159,232,112,.40);
  --aurora:linear-gradient(90deg,var(--accent) 0%,var(--info) 55%,var(--up) 100%);
  --font-sans:'Heebo','Inter',-apple-system,system-ui,sans-serif;
  --font-mono:'JetBrains Mono','SF Mono',Menlo,monospace;
  /* ── sub.alert.v3 · THE EXTREME TIER (2026-09-02) ────────────────────────────────
     Two lanes, two colours, and they are NEVER the same colour: the union of the two
     was measured to dilute the chase lane from 37% to 15.8%, and a subscriber
     scrolling a feed must be able to tell the confirmation lane from the setup lane
     at a glance. Amber for CHASE and violet for EARLY, per CARD_COPY_SPEC §1.
     Their OWN tokens, not --warn / --info borrowed: those two already mean other
     things on this page (a flat regime, a translated card), and a shared colour is
     how two unrelated states start looking like one state. */
  --xchase:#F0A83C; --xchase-bg:rgba(240,168,60,.16); --xchase-line:rgba(240,168,60,.5);
  --xearly:#A98CFF; --xearly-bg:rgba(169,140,255,.16); --xearly-line:rgba(169,140,255,.5);
  /* the HARD STOP line. Its own token, deliberately not --down and not --crit: the stop
     is not a bearish read and it is not an interest tier — it is the line the lane was
     MEASURED with, and it must not read as either of the two mechanical columns. */
  --xstop:#FF6B6B; --xstop-bg:rgba(255,107,107,.10); --xstop-line:rgba(255,107,107,.34);
  /* ── the CRITICAL OSINT row (operator order 2026-09-24: "light red, but noticeable") ──
     Its OWN tokens, deliberately not --crit (the interest tier's text colour, declared and
     used exactly once), not --down (a bearish read) and not --xstop (the printed stop): a
     severity surface must not read as any of the three. Values are for the page's one
     theme — it is dark-only (see the header), so there is no light set to provide.
     --crit-row-bg is the resting surface, --crit-row-bg-strong the flicker's far end and
     the hover, --crit-row-line the hairline edge.
     🔴 OPAQUE and PRE-MIXED since round 2 (2026-09-24). Pass 1 was a translucent red
     (rgba(255,77,77,.20) / .34) laid UNDER the 8% family cast, and the rendered resting row
     came out rgb(64,47,63): plum, hue 304°, only dE76 15.2 from a navy OSINT row, because
     the navy base and the cyan OSINT cast both pulled it toward purple. That is what an
     expired row wears for the rest of its life, and what a reduced-motion reader sees all
     the time. An opaque value paints the same pixel over any base, so the hue belongs to
     the token and not to whatever sits under it: rest #4F1D26 = hue 349.2°, dE76 32.2 from
     the normal OSINT row; far end #6A2531 = hue 349.6°, dE76 41.0, and 10.5 from the rest
     (pass 1's cycle was 13.0). The family cast stands down on a critical row (see the
     CRITICAL block). Primary text holds 11.76 / 9.40:1 on the two, secondary 5.79 / 4.62:1.
     --crit-row-fg is the interest word's (and, since the class-label order, the event
     class label's) colour ON this surface: the tier's own --crit
     (#FF4D4D) falls to 4.18 / 3.34:1 here, below AA for 11.5px text; #FFA8A8 holds
     7.43 / 5.94:1. The chip is FILLED, white on #E03131 = 4.51:1 (a white-on-#FF4D4D chip
     would sit near 3.3:1). Pass 1's note said 5.7:1 for the chip; measured, it is 4.51. */
  --crit-row-bg:#4F1D26; --crit-row-bg-strong:#6A2531;
  --crit-row-line:rgba(255,77,77,.45); --crit-row-fg:#FFA8A8;
  --crit-chip-bg:#E03131; --crit-chip-fg:#FFFFFF;
  --line:rgba(107,159,255,.13);
}
*{box-sizing:border-box;}
html,body{margin:0; padding:0;}
body{background:var(--bg-base); color:var(--text-primary); font-family:var(--font-sans);
     overflow-x:hidden; min-height:100vh; -webkit-text-size-adjust:100%;}

/* FAIL-CLOSED. <html> ships with .relay-locked, so the radar is hidden from the first
   byte and is revealed ONLY by a successful ID-token mint. Same doctrine as the MV7
   console's html.mv7-locked — the visible gate is not the gate. */
html.relay-locked #relay-root{display:none !important;}

:focus-visible{outline:2px solid var(--accent-2); outline-offset:2px; border-radius:4px;}

.page{background:var(--bg-base); min-height:100vh; padding:0 0 48px;}
.mono{font-family:var(--font-mono); font-variant-numeric:tabular-nums;}
.wrap{max-width:1180px; margin:0 auto; padding:0 20px;}
.vh{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;}

/* ── header (v3 three-zone grid) ───────────────────────────────────────── */
.top{border-bottom:1px solid var(--line); background:linear-gradient(180deg,var(--bg-deeper),var(--bg-base));}
/* three zones: minmax(0,1fr) side rails keep the wordmark optically dead-centre on the
   content column no matter how wide the rail contents get; the end rail wraps inside its
   own track instead of shoving the centre off-axis. v3 carries NO tagline. */
.top .wrap{display:grid; grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
           align-items:center; column-gap:10px; padding-top:18px; padding-bottom:15px;}
.hz{display:flex; align-items:center; gap:8px; min-width:0;}
.hz-start{justify-self:start;}
.hz-mid{justify-self:center;}
.hz-end{justify-self:end; flex-wrap:wrap; justify-content:flex-end; row-gap:6px;}
.brand{font-weight:800; letter-spacing:.16em; font-size:19px;
       direction:ltr; white-space:nowrap;}   /* its Inter: the >=721px block in §PHONE */
.brand em{font-style:normal; background:var(--aurora); -webkit-background-clip:text; background-clip:text; color:transparent;}
/* ── the BETA mark (2026-09-18, operator order: "the same design of the logo") ──
   NOT a new visual family: it is the wordmark's OWN paint — the `--aurora` gradient
   clipped to the glyphs, exactly as `.brand em` above — at badge scale. The header
   gains a release stage without gaining a style, which is the whole of the order.
   It rides INSIDE `.brand`, the one element on this page pinned to `direction:ltr`,
   and that is what keeps the mark on the name's trailing edge in `he` as well as `en`
   without a single directional rule of its own.
   Raised with `position:relative`, NOT `vertical-align:super`: a superscript grows the
   line box, and the mid rail's height is the header's height — the mark must not be
   able to move the chrome it is printed on. A relative offset paints high and occupies
   its original line box, so the header measures the same with it as without it.
   9px against the wordmark's 19px is what separates a QUALIFIER from a third word: set
   at the wordmark's own size it would read as "PROJECT MAGNETO BETA", which is a
   different product name rather than a release stage. */
.brand .beta{font-size:9px; font-weight:800; letter-spacing:.14em; position:relative; top:-6px;
             margin-inline-start:6px; background:var(--aurora);
             -webkit-background-clip:text; background-clip:text; color:transparent;}
/* v2: one notch more saturation + a soft halo. It is the page's only claim that the
   feed is alive, so it should read as lit, not as a grey label with a green dot. */
.livep{display:inline-flex; align-items:center; gap:6px; font-size:10px; font-weight:800; letter-spacing:.06em;
       color:var(--up); background:rgba(59,212,162,.16); border:1px solid rgba(59,212,162,.52);
       border-radius:999px; padding:5px 10px; white-space:nowrap;
       box-shadow:0 0 14px rgba(59,212,162,.13);}
.livep i{width:7px; height:7px; border-radius:50%; background:var(--up); flex:0 0 7px;
         box-shadow:0 0 8px rgba(59,212,162,.8); animation:blip 1.7s ease-in-out infinite;}
@keyframes blip{0%,100%{opacity:1; transform:scale(1);} 50%{opacity:.28; transform:scale(.65);}}
/* stale-feed pill — replaces the live pill while the stream is down */
.livep.stale{color:var(--warn); background:rgba(232,176,74,.14); border-color:rgba(232,176,74,.45);
             box-shadow:0 0 14px rgba(232,176,74,.10);}
.livep.stale i{background:var(--warn); box-shadow:0 0 8px rgba(232,176,74,.7);}
/* ── the market-status chip (2026-09-02, operator order) ───────────────────
   The start rail's chip, between the language toggle and the wordmark. Same visual
   family as `.livep`: same pill, same 10px/800 type, same 7px dot — the two answer
   neighbouring questions ("is the feed alive?" / "is the tape open?") and two header
   chips that disagree about their own shape read as two unrelated features.
   What it deliberately does NOT borrow is `.livep i`'s `blip` animation. This page
   sanctions exactly TWO infinite animations (the live dot and the market panel's
   live dot) and selftest.js pins that count EXACTLY — but the real reason is that a
   session state is not a heartbeat. It changes four times a day; a pulsing dot would
   claim otherwise.
   Colour is carried ONLY by the four `.ms-*` classes and never by an inline style,
   so a state cannot be repainted from JS into looking like another one. */
.mstat{display:inline-flex; align-items:center; gap:6px; font-size:10px; font-weight:800;
       letter-spacing:.06em; border-radius:999px; padding:5px 10px; white-space:nowrap;
       border:1px solid var(--line); background:var(--bg-surface); color:var(--text-tertiary);}
.mstat i{width:7px; height:7px; border-radius:50%; flex:0 0 7px;
         background:currentColor; box-shadow:0 0 8px currentColor;}
.ms-pre{color:var(--warn); background:rgba(232,176,74,.14); border-color:rgba(232,176,74,.45);}
.ms-rth{color:var(--up); background:rgba(59,212,162,.16); border-color:rgba(59,212,162,.52);}
.ms-after{color:var(--accent-2); background:var(--accent-bg); border-color:var(--accent-glow);}
/* the ONE muted state, muted on purpose: a closed tape is the ABSENCE of a session
   and must not compete with the three lit ones. The dot keeps its shape (so the chip
   does not visibly re-flow at 20:00 ET) and loses only its halo. */
.ms-shut{color:var(--text-tertiary); background:var(--bg-surface); border-color:var(--line);}
.ms-shut i{box-shadow:none; opacity:.68;}
.who{font-size:11.5px; color:var(--text-tertiary); direction:ltr; max-width:210px;
     overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.tier{font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; direction:ltr;
      color:var(--accent-2); background:var(--accent-bg); border:1px solid var(--accent-glow);
      border-radius:999px; padding:3px 9px;}
.lang{display:inline-flex; border:1px solid var(--line); border-radius:999px;
      overflow:hidden; background:var(--bg-surface);}
.lang button{font-family:var(--font-sans); font-size:12px; font-weight:700; color:var(--text-tertiary);
             background:transparent; border:0; padding:5px 12px; cursor:pointer; transition:all .15s;}
.lang button+button{border-inline-start:1px solid var(--line);}
.lang button:hover{color:var(--text-primary);}
.lang button.on{background:var(--accent-bg); color:var(--accent-2);}
.lo{font-family:var(--font-sans); font-size:12px; font-weight:600; color:var(--text-tertiary);
    background:var(--bg-surface); border:1px solid var(--line); border-radius:999px;
    padding:5px 12px; cursor:pointer; transition:all .15s;}
.lo:hover{color:var(--down); border-color:rgba(243,110,110,.4);}
.aur{height:2px; background:var(--aurora); opacity:.75;}

/* ── subscriber feedback (2026-09-18 · LIT 2026-09-23) ────────────────────
   The header entry point sits in the START rail beside the language toggle and the
   market chip. It shipped as a QUIET control; the operator's order of 2026-09-23 was
   the opposite — "shine and be extra visible, keeping a contrast and design that fits
   the system" — so it is now the AURORA RING: the wordmark's own paint (`--aurora`,
   already on `.brand em`, `.beta` and the `.aur` line) drawn as a 2px ring around an
   OPAQUE, dimly aurora-tinted surface, with a two-tone halo. Nothing else in the chrome wears the
   gradient as a ring, which is what makes it findable at a glance without becoming
   the solid call-to-action the send button and the sign-in button own.
   HOW THE RING IS DRAWN: two background layers — the fill clipped to padding-box, the
   gradient clipped to border-box — under a TRANSPARENT border. It is the one technique
   that keeps the 999px radius (border-image would square it). Consequence: a state
   must repaint the LAYERS; `border-color` paints nothing here.
   THE FILL MUST BE OPAQUE (color-mix on tokens, never an rgba wash): a translucent fill
   lets the ring's gradient bleed through and the pill turns into a solid rainbow — the
   first harness shot of this pass did exactly that, and white on the violet band was
   ~3.5:1. Opaque and dim inside, lit at the edge: the label sits at >8:1. The same ring, the
   same halo and the same label weight are worn by the filters handle (`.fbtn.fbtn-more`)
   — the two doors the operator asked to shine speak ONE lit vocabulary, never two.
   MOTION: hover lifts 1px and brightens the halo through a transition the
   reduced-motion block kills. No keyframe — the four-keyframe ceiling holds.
   Every offset is logical, so `he` and `en` need no second rule. */
.fbbtn{display:inline-flex; align-items:center; gap:7px; font-family:var(--font-sans);
       font-size:12.5px; font-weight:700; letter-spacing:.01em; color:var(--text-primary);
       border:2px solid transparent; border-radius:999px;
       padding:5px 14px; padding-inline-start:12px; cursor:pointer; white-space:nowrap;
       background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 24%,var(--bg-elevated)) 0%,color-mix(in srgb,var(--info) 24%,var(--bg-elevated)) 55%,color-mix(in srgb,var(--up) 22%,var(--bg-elevated)) 100%) padding-box,
                  var(--aurora) border-box;
       box-shadow:0 0 0 1px rgba(107,159,255,.14), 0 0 18px rgba(107,159,255,.44),
                  0 4px 20px rgba(155,140,255,.26), inset 0 1px 0 rgba(255,255,255,.08);
       transition:transform .15s ease, box-shadow .15s ease, filter .15s ease;}
.fbbtn:hover{transform:translateY(-1px); filter:brightness(1.08);
             box-shadow:0 0 0 1px rgba(107,159,255,.22), 0 0 26px rgba(107,159,255,.62),
                        0 6px 24px rgba(155,140,255,.34), inset 0 1px 0 rgba(255,255,255,.10);}
.fbbtn:active{transform:none; filter:brightness(.96);}
.fbbtn:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
/* the speech-bubble mark, drawn in CSS — no icon font, no third-party sprite, and
   nothing that can 404 into a blank square in the header. It takes the accent so the
   glyph reads lit beside the primary-white label. */
.fbbtn i{width:11px; height:9px; border:1.5px solid currentColor; border-radius:2px;
         position:relative; flex:0 0 auto; color:var(--accent-2);}
.fbbtn i::after{content:""; position:absolute; bottom:-4px; inset-inline-start:2px;
                border-inline-start:3px solid currentColor; border-top:3px solid transparent;
                border-bottom:3px solid transparent;}

.fbpage{padding:36px 20px 64px; display:flex; justify-content:center;}
.fbcard{width:100%; max-width:640px;}
.fbback{font-family:var(--font-sans); font-size:12px; font-weight:600;
        color:var(--text-tertiary); background:none; border:0; padding:0 0 18px;
        cursor:pointer;}
.fbback:hover{color:var(--accent-2);}
.fbtitle{font-family:var(--font-sans); font-size:26px; font-weight:800;
         color:var(--text-primary); margin:0 0 8px; line-height:1.25;}
.fbintro{font-family:var(--font-sans); font-size:14px; color:var(--text-secondary);
         margin:0 0 26px; line-height:1.7;}
.fbform{display:flex; flex-direction:column;}
.fblabel{font-family:var(--font-sans); font-size:12px; font-weight:700;
         color:var(--text-secondary); letter-spacing:.02em; margin-bottom:9px;}
.fbcats{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:22px;}
.fbcats button{font-family:var(--font-sans); font-size:12.5px; font-weight:600;
               color:var(--text-secondary); background:var(--bg-surface);
               border:1px solid var(--line); border-radius:999px; padding:7px 15px;
               cursor:pointer; transition:all .15s;}
.fbcats button:hover{color:var(--text-primary); border-color:var(--accent-glow);}
.fbcats button.on{color:var(--accent-2); background:var(--accent-bg);
                  border-color:var(--accent-glow);}
.fbcats button:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
.fbmsg{font-family:var(--font-sans); font-size:14px; line-height:1.7;
       color:var(--text-primary); background:var(--bg-surface);
       border:1px solid var(--line); border-radius:12px; padding:14px 15px;
       resize:vertical; min-height:150px; width:100%; box-sizing:border-box;}
.fbmsg::placeholder{color:var(--text-disabled);}
.fbmsg:focus{outline:none; border-color:var(--accent-glow);
             box-shadow:0 0 0 3px var(--accent-bg);}
.fbcount{font-family:var(--font-mono); font-size:11px; color:var(--text-disabled);
         margin-top:7px; text-align:end;}
.fbcontact{display:flex; align-items:center; gap:9px; margin-top:16px;
           font-family:var(--font-sans); font-size:13px; color:var(--text-secondary);
           cursor:pointer;}
.fbcontact input{width:15px; height:15px; accent-color:var(--accent); cursor:pointer;
                 flex:0 0 auto;}
.fberr{font-family:var(--font-sans); font-size:13px; font-weight:600; color:var(--down);
       background:rgba(243,110,110,.08); border:1px solid rgba(243,110,110,.3);
       border-radius:10px; padding:11px 14px; margin-top:16px; line-height:1.6;}
.fbsend{font-family:var(--font-sans); font-size:14px; font-weight:700;
        color:var(--bg-base); background:var(--accent); border:0; border-radius:10px;
        padding:13px 22px; margin-top:22px; cursor:pointer; align-self:flex-start;
        transition:all .15s;}
.fbsend:hover:not(:disabled){background:var(--accent-2);}
.fbsend:disabled{opacity:.55; cursor:default;}
.fbsend:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
.fbdone{border:1px solid rgba(59,212,162,.32); background:rgba(59,212,162,.07);
        border-radius:14px; padding:26px;}
.fbdone h2{font-family:var(--font-sans); font-size:17px; font-weight:800;
           color:var(--up); margin:0 0 9px;}
.fbdone p{font-family:var(--font-sans); font-size:13.5px; color:var(--text-secondary);
          margin:0 0 18px; line-height:1.7;}
.fbagain{font-family:var(--font-sans); font-size:13px; font-weight:600;
         color:var(--text-primary); background:var(--bg-surface);
         border:1px solid var(--line); border-radius:999px; padding:9px 17px;
         cursor:pointer;}
.fbagain:hover{border-color:var(--accent-glow); color:var(--accent-2);}

@media (max-width:560px){
  .fbpage{padding:24px 14px 48px;}
  .fbtitle{font-size:21px;}
  /* the send button goes full width where a thumb has to find it */
  .fbsend{align-self:stretch; text-align:center;}
}

/* ── market + sector pulse strip ──────────────────────────────────────── */
.pulsebar{background:var(--bg-deeper); border-bottom:1px solid var(--line);}
/* ONE row, TWO slots: the scrolling gauge+sector track, and the MARKET PULSE card in
   the trailing space the strip has always left empty. The card is a SIBLING of the
   track, never a child — that is what keeps the six tiles at exactly 120px AND at
   their own height, because .pulse inside the track is height:auto and a taller card
   therefore cannot stretch it. All spacing is logical, so RTL needs no second rule. */
/* one COLUMN: the gauge+sector track on its own full-width line, the MARKET PULSE
   band on its own full-width line beneath it. Nothing shares a row with the tiles,
   so nothing can sit over them — the symmetry order, 2026-08-28. */
.pulserow{max-width:1180px; margin:0 auto; display:flex; flex-direction:column; align-items:stretch;}
.pulsescroll{flex:1 1 auto; min-width:0; align-self:stretch; overflow-x:auto; overflow-y:hidden;
             scrollbar-width:thin; -webkit-overflow-scrolling:touch;}
.pulse{display:flex; align-items:stretch; gap:10px; padding:12px 20px; width:max-content; min-width:100%;}
.regime{display:flex; flex-direction:column; justify-content:center; gap:3px; white-space:nowrap;
        border-radius:10px; padding:8px 14px; border:1px solid; font-size:12.5px; font-weight:700;}
/* the sub-line takes the gauge's own colour at low opacity instead of the grey it
   used to be — the whole pill reads as ONE lit object, not a label with a note. */
.regime small{font-weight:600; font-size:10px; letter-spacing:.05em; color:currentColor; opacity:.68;}
/* ── gauge state colours (the LIFE pass) ──────────────────────────────────
   Each state is a real reading and is painted like one: saturated fill, a lit
   border and a soft outward glow. 🔴 NEUTRAL IS WARM AMBER, NEVER GREY. Grey on
   this page means exactly one thing — "no data yet" (.rg-pending) — and painting a
   real NEUTRAL reading in the same grey told the subscriber the market gauge was
   broken when it was working. That is the whole "too grey" order in one rule. */
.rg-down{color:var(--down); background:rgba(243,110,110,.17); border-color:rgba(243,110,110,.48);
         box-shadow:0 0 20px rgba(243,110,110,.13), inset 0 1px 0 rgba(255,255,255,.03);}
.rg-up{color:var(--up); background:rgba(59,212,162,.17); border-color:rgba(59,212,162,.50);
       box-shadow:0 0 22px rgba(59,212,162,.17), inset 0 1px 0 rgba(255,255,255,.04);}
.rg-flat{color:var(--warn); background:rgba(232,176,74,.16); border-color:rgba(232,176,74,.46);
         box-shadow:0 0 20px rgba(232,176,74,.13), inset 0 1px 0 rgba(255,255,255,.03);}
/* the ONE grey: no reading has arrived, and the strip says so in words too */
.rg-pending{color:var(--text-tertiary); background:rgba(157,169,194,.06); border-color:rgba(157,169,194,.20);}
/* SUB.PULSE.V1: a reading whose asof is older than PULSE_STALE_MS is DIMMED, never
   error-coloured. Old is not broken — the gauge's own relative clock already says how
   old, and painting it red would teach the subscriber to distrust a correct number. */
.regime.pstale{opacity:.6;}
/* the gauge's own breadth ratio, same 3px rhythm as a sector tile's bar. `currentColor`
   is load-bearing, not shorthand: the bar is the SAME reading as the label above it, so
   it must be the same colour by construction — including when NEUTRAL turns amber. */
.gbr{display:block; height:3px; border-radius:2px; background:rgba(157,169,194,.14);
     overflow:hidden; margin-top:1px;}
.gbr i{display:block; height:100%; border-radius:2px; background:currentColor; opacity:.92;}
.pdiv{flex:0 0 1px; width:1px; background:var(--line); margin:4px 5px;}
.stile{flex:0 0 120px; width:120px; background:var(--bg-elevated); border:1px solid var(--line);
       border-radius:10px; padding:8px 10px 9px;
       transition:border-color .18s ease, box-shadow .18s ease;}
/* direction-tinted borders (the LIFE pass). The tint comes from the CONTRACT's
   `direction`, which is why the class is stamped on the tile in sectorTile() and is
   never inferred here from the sign of the number inside it. */
.stile.up{border-color:rgba(59,212,162,.32); box-shadow:0 4px 16px rgba(59,212,162,.07);}
.stile.down{border-color:rgba(243,110,110,.32); box-shadow:0 4px 16px rgba(243,110,110,.07);}
.stile.flat{border-color:rgba(232,176,74,.22);}
.sname{font-size:10.5px; font-weight:600; color:var(--text-secondary); line-height:1.32; height:28px;
       overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;}
.srow{display:flex; align-items:center; gap:7px; margin-top:6px;}
.sval{font-size:13px; font-weight:700; letter-spacing:-.01em;}
.sval.up{color:var(--up);} .sval.down{color:var(--down);}
/* FLAT is a real reading, not a missing one: it gets the primary text colour, the
   neutral bar, and NO arrow. The direction always comes from the contract's
   `direction` field — never from the sign of avg_gain. */
.sval.flat{color:var(--text-primary);}
.sarr{font-size:8.5px; margin-inline-end:3px; opacity:.85;}
.sbr{flex:1 1 auto; height:3px; border-radius:2px; background:rgba(157,169,194,.14); overflow:hidden;}
.sbr i{display:block; height:100%; border-radius:2px;}
/* gradient fills: the bar gains depth toward its leading edge instead of reading as a
   flat block of colour. FLAT keeps a bar of its own — a 50% breadth is a reading. */
.sbr i.up{background:linear-gradient(90deg,rgba(59,212,162,.45),var(--up));}
.sbr i.down{background:linear-gradient(90deg,rgba(243,110,110,.45),var(--down));}
.sbr i.flat{background:linear-gradient(90deg,rgba(232,176,74,.32),rgba(232,176,74,.62));}
/* nowrap + ellipsis: the bottom line must never wrap and stretch the whole 120px tile
   row — a long sector's breadth line is clipped, and the tile's title carries it whole. */
.sbl{margin-top:5px; font-size:9.5px; letter-spacing:.03em; color:var(--text-tertiary);
     white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
/* quiet "coming online" state — the design is present, the data is not, and the page says so */
.stile.pending{opacity:.45;}
.stile.pending .sname{color:var(--text-disabled);}
.stile.pending .sval{color:var(--text-disabled);}
.stile.pending .sbr i{background:rgba(157,169,194,.30);}
.pnote{display:inline-flex; align-items:center; align-self:center; white-space:nowrap;
       border-radius:999px; padding:7px 13px; font-size:11.5px; font-weight:700;
       color:var(--text-tertiary); background:rgba(157,169,194,.07); border:1px dashed rgba(157,169,194,.30);}

/* ── MARKET PULSE band (its own full-width line under the sector track) ────
   Every segment is a MECHANICAL market-wide aggregate; there is no ticker, no
   price and no index level in this lane, so nothing here is ever drawn as a
   quote. The state colour follows the LIFE-pass rule the gauge set:
   ACCUMULATION deep green · DISTRIBUTION red · BALANCED WARM AMBER, never grey —
   grey on this page means exactly one thing, "no reading has arrived" (.pending). */
/* a full-width horizontal internals BAND under the sector track: every reading is a
   segment on one line (wrapping to two on narrow screens), evenly spaced — no card
   beside the tiles, nothing overlapped, symmetric by construction. */
.mpanel{flex:none; margin-block:0 12px; margin-inline:20px; min-width:0;
        background:var(--bg-elevated); border:1px solid var(--line); border-radius:10px;
        padding:8px 14px; display:flex; flex-direction:row; align-items:center;
        flex-wrap:wrap; gap:6px 18px; justify-content:space-between; line-height:1.3;
        transition:border-color .18s ease, box-shadow .18s ease;}
/* segment sizing on the band: labels/rows stay content-sized, the two kinds of bar
   flex to absorb the slack evenly from both ends of the line */
.mphd{flex:0 0 auto;}
.mpsplit{flex:0 0 auto;}
.mpbar{flex:1 1 150px; min-width:110px; max-width:260px;}
.mprow{flex:0 0 auto;}
.mprow.mpmini{flex:1 1 150px; min-width:130px; max-width:220px;}
.mpanel.tp-up{border-color:rgba(59,212,162,.32); box-shadow:0 4px 16px rgba(59,212,162,.07);}
.mpanel.tp-down{border-color:rgba(243,110,110,.32); box-shadow:0 4px 16px rgba(243,110,110,.07);}
.mpanel.tp-flat{border-color:rgba(232,176,74,.28); box-shadow:0 4px 16px rgba(232,176,74,.07);}
/* a reading older than MPANEL_STALE_MS is DIMMED and prints its own age in the
   header — never hidden, never error-coloured. Old is not broken. */
.mpanel.mpstale{opacity:.6;}
.mphd{display:flex; align-items:center; gap:6px; min-width:0;}
.mptl{font-size:9.5px; font-weight:800; letter-spacing:.10em; color:var(--text-secondary);
      white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.mprel{font-size:9px; font-weight:600; color:var(--text-tertiary); white-space:nowrap;}
.mptape{margin-inline-start:auto; font-size:8.5px; font-weight:800; letter-spacing:.06em;
        white-space:nowrap; border-radius:999px; padding:2px 7px; border:1px solid;}
.mptape.tp-up{color:var(--up); background:rgba(59,212,162,.16); border-color:rgba(59,212,162,.46);}
.mptape.tp-down{color:var(--down); background:rgba(243,110,110,.16); border-color:rgba(243,110,110,.46);}
.mptape.tp-flat{color:var(--warn); background:rgba(232,176,74,.16); border-color:rgba(232,176,74,.44);}
/* the BUY / SELL split. space-between mirrors itself in RTL, so there is no second
   rule for Hebrew; the figures themselves are dir=ltr because numbers do not flip. */
.mpsplit{display:flex; align-items:center; justify-content:space-between; gap:6px;
         font-size:9.5px; font-weight:700; white-space:nowrap; margin-top:1px;}
.mpsl.up{color:var(--up);} .mpsl.down{color:var(--down);}
.mparr{font-size:7.5px; opacity:.85; margin-inline-end:2px; margin-inline-start:2px;}
/* the net flow is the SAME reading as the tape chip, so it wears the tape's colour */
.mpnet{font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:9px; font-weight:700;}
.mpnet.tp-up{color:var(--up);} .mpnet.tp-down{color:var(--down);} .mpnet.tp-flat{color:var(--warn);}
/* two-tone: the track is the SELL side, the fill is the BUY side. One bar, one split. */
.mpbar{display:block; height:4px; border-radius:2px; overflow:hidden;
       background:linear-gradient(90deg,rgba(243,110,110,.34),rgba(243,110,110,.60));}
.mpbar i{display:block; height:100%; border-radius:2px;
         background:linear-gradient(90deg,rgba(59,212,162,.45),var(--up));}
.mpbar.sm{flex:1 1 auto; height:3px; min-width:22px;
          background:rgba(157,169,194,.14);}
.mpbar.sm i{background:linear-gradient(90deg,rgba(107,159,255,.38),var(--accent));}
.mprow{display:flex; align-items:center; gap:5px; min-width:0; font-size:9.5px; white-space:nowrap;}
.mpk{color:var(--text-tertiary); letter-spacing:.03em; overflow:hidden; text-overflow:ellipsis;}
.mpv{font-weight:700; color:var(--text-primary);}
.mpv.up{color:var(--up);} .mpv.down{color:var(--down);} .mpv.flat{color:var(--warn);}
.mpmini .mpv{margin-inline-start:auto;}
.mptag{font-size:8px; font-weight:800; letter-spacing:.05em; border-radius:999px;
       padding:1px 6px; border:1px solid; margin-inline-start:auto;}
.mptag.up{color:var(--up); background:rgba(59,212,162,.14); border-color:rgba(59,212,162,.40);}
.mptag.down{color:var(--down); background:rgba(243,110,110,.14); border-color:rgba(243,110,110,.40);}
.mptag.flat{color:var(--warn); background:rgba(232,176,74,.14); border-color:rgba(232,176,74,.38);}
/* the quiet "coming online" state — the ONE grey on this card */
.mpanel.pending{opacity:.5;}
.mpanel.pending .mpv{color:var(--text-disabled);}
.mpanel.pending .mpbar{background:rgba(157,169,194,.16);}
.mpnote{font-size:9px; font-weight:700; color:var(--text-tertiary); white-space:nowrap;
        overflow:hidden; text-overflow:ellipsis;}

/* ── stats strip ───────────────────────────────────────────────────────── */
/* one shared row: the stats cluster at inline-start and the search DOOR centred in the row's
   free space (user 2026-09-28 20:4x ET; its rules sit with the header's Search pill in §APPV2).
   The premium quartet left this row for the chip band (user 2026-09-28 18:5x ET).
   align-items:center centres the 12.5px stats text against the 33px chip rhythm; both
   items are flex-wrap safe in either dir. */
.statsrow{display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:13px 0 3px;
          min-height:33px;}
.stats{display:flex; align-items:center; gap:18px; flex-wrap:wrap;
       color:var(--text-tertiary); font-size:12.5px;}
.stats b{color:var(--text-primary); font-weight:700; margin-inline-end:5px; transition:color .25s ease;}
.stats b.bump{color:var(--up);}
.notice{margin-top:12px; display:flex; gap:10px; flex-wrap:wrap;}
.note{font-size:12px; font-weight:600; border-radius:8px; padding:7px 12px; border:1px solid; line-height:1.5;}
.note-delay{color:var(--warn); background:var(--warn-bg); border-color:rgba(232,176,74,.34);}
.note-err{color:var(--down); background:rgba(243,110,110,.10); border-color:rgba(243,110,110,.34);}

/* ── filters ──────────────────────────────────────────────────────────── */
.filters{display:flex; gap:8px; flex-wrap:wrap; padding:14px 0 14px; flex:1 1 560px; min-width:0;}
/* ── the CHIP BAND (user 2026-09-28 18:5x ET: "allign the market 'proffesor x' 'phoenix' etc with
   the main line … where all the filers are") — ONE wrapper, the chip row first and the locked
   premium quartet second. The quartet sits at the band's inline END (the left in `he`),
   TOP-ALIGNED with the first chip line: its own 14px top padding is the chip row's, so a pill's
   top is a chip's top. The chips take the room the quartet leaves and wrap under
   themselves; the quartet never wraps into them. The chip row's 560px basis is where the two stop
   sharing a line: narrower than that (below ~1150px), the quartet drops under the chips as its own
   line, still at the inline END; at ≤900px it centres (the tablet rule below). ── */
.filtersrow{display:flex; flex-wrap:wrap; align-items:flex-start; gap:8px 14px;}
.premium{display:flex; flex:0 0 auto; gap:7px; flex-wrap:wrap; align-items:center; margin-inline-start:auto;
         align-self:flex-start; padding-block:14px;}
/* the pill — the lit family of the Filters handle and the Analyst Opinion door (a 1px tinted edge, a
   token fill, a halo, primary text at 700), painted in the LIVE pill's light green so the four read
   as doors being announced, fully visible — still locked (the padlock + "Premium only"), so the
   press is a shake and nothing else. No keyframe; the global reduced-motion block kills the lift. */
.pbtn{display:inline-flex; align-items:center; gap:8px; font-family:var(--font-sans);
      font-size:13px; font-weight:700; letter-spacing:.01em; color:var(--text-primary); cursor:pointer; opacity:1;
      border:1px solid rgba(59,212,162,.50); border-radius:999px;
      padding:6px 14px; padding-inline-start:12px;
      background:color-mix(in srgb,var(--up) 14%,var(--bg-elevated));
      box-shadow:0 0 0 1px rgba(59,212,162,.12), 0 0 12px rgba(59,212,162,.22);
      transition:transform .15s ease, box-shadow .15s ease, filter .15s ease;}
.pbtn:hover{transform:translateY(-1px); filter:brightness(1.1);
            box-shadow:0 0 0 1px rgba(59,212,162,.20), 0 0 18px rgba(59,212,162,.38);}
.pbtn:active{transform:none; filter:brightness(.96);}
.pbtn:focus-visible{outline:2px solid var(--up); outline-offset:3px;}
.pbtn .plock{color:var(--up);}
/* CSS padlock — no icon font, no external asset */
.plock{position:relative; display:inline-block; width:9px; height:7px; border-radius:2px;
       background:currentColor; margin-top:4px; flex:0 0 9px;}
.plock::before{content:""; position:absolute; inset-inline-start:50%; bottom:6px; width:7px; height:6px;
               margin-inline-start:-3.5px; border:1.6px solid currentColor; border-bottom:0;
               border-radius:4px 4px 0 0;}
.pname{color:var(--text-primary); font-weight:700; white-space:nowrap;}
@keyframes shake{10%,90%{transform:translateX(-2px);} 20%,80%{transform:translateX(3px);}
                 30%,50%,70%{transform:translateX(-4px);} 40%,60%{transform:translateX(4px);}}
.pbtn.shake{animation:shake .52s cubic-bezier(.36,.07,.19,.97);}
.fbtn{font-family:var(--font-sans); font-size:13px; font-weight:600; color:var(--text-secondary);
      background:var(--bg-surface); border:1px solid var(--line); border-radius:999px;
      padding:7px 14px; cursor:pointer; transition:all .15s;}
.fbtn b{color:var(--text-tertiary); font-weight:600; margin-inline-start:5px;}
.fbtn:hover{border-color:var(--accent-glow); color:var(--text-primary);}
.fbtn.active{background:var(--accent-bg); border-color:var(--accent); color:var(--accent-2);}
.fbtn.active b{color:var(--accent);}
.fbtn.active[data-f="osint"]{background:var(--osint-bg); border-color:var(--osint); color:var(--osint);}
.fbtn.active[data-f="osint"] b{color:var(--osint);}
/* LIFE pass 2 (2026-09-23): an active family chip wears ITS family's colour — the same colour
   as the row badge, the accent bar and the row tint it switches on, so the chip row and the
   table agree about what "options" looks like. osint had this since v2; the other seven
   join it (levels spelt out even though it equals the default, so the set is complete).
   `all` and `today` are not families and keep the accent. */
.fbtn.active[data-f="momentum"]{background:rgba(59,212,162,.16); border-color:var(--up); color:var(--up);}
.fbtn.active[data-f="momentum"] b{color:var(--up);}
.fbtn.active[data-f="levels"]{background:var(--accent-bg); border-color:var(--accent); color:var(--accent-2);}
.fbtn.active[data-f="levels"] b{color:var(--accent);}
.fbtn.active[data-f="options"]{background:var(--info-bg); border-color:var(--info); color:var(--info);}
.fbtn.active[data-f="options"] b{color:var(--info);}
.fbtn.active[data-f="insider"]{background:var(--insider-bg); border-color:var(--insider); color:var(--insider);}
.fbtn.active[data-f="insider"] b{color:var(--insider);}
.fbtn.active[data-f="news"]{background:var(--news-bg); border-color:var(--news); color:var(--news);}
.fbtn.active[data-f="news"] b{color:var(--news);}
.fbtn.active[data-f="market"]{background:var(--market-bg); border-color:var(--market); color:var(--market);}
.fbtn.active[data-f="market"] b{color:var(--market);}
.fbtn.active[data-f="market_update"]{background:var(--brief-bg); border-color:var(--brief); color:var(--brief);}
.fbtn.active[data-f="market_update"] b{color:var(--brief);}
/* ── §ATTENTION · the family chip flickers until it is pressed (operator order 2026-09-24:
   "the OSINT tab flickers until it is pressed … when he comes back to the main page the
   flickering will be gone") ───────────────────────────────────────────────────────────
   Only a chip that is NOT active wears it (app.js: selecting the family is what clears it), so
   it never fights the active rules above. Each family names its own far colour: OSINT the
   critical row's strong red and its text (the row it points at is red), Market its family
   tint. The critical row's 2.4 s cadence. Reduced motion: the still far colour + the edge. */
.fbtn.attn{--attn-bg:var(--accent-bg); --attn-line:var(--accent);
           border-color:var(--attn-line); animation:chipflick 2.4s ease-in-out infinite alternate;}
.fbtn.attn[data-f="osint"]{--attn-bg:var(--crit-row-bg-strong); --attn-line:var(--crit-chip-bg); color:var(--crit-row-fg);}
.fbtn.attn[data-f="osint"] b{color:var(--crit-row-fg);}
.fbtn.attn[data-f="market"]{--attn-bg:rgba(143,163,200,.30); --attn-line:var(--market); color:var(--market);}
.fbtn.attn[data-f="market"] b{color:var(--market);}
@keyframes chipflick{from{background-color:var(--bg-surface);} to{background-color:var(--attn-bg);}}
@media (prefers-reduced-motion: reduce){
  .fbtn.attn{animation:none; background-color:var(--attn-bg);}
}

/* ── table ────────────────────────────────────────────────────────────── */
.tblbox{border:1px solid var(--line); border-radius:14px; overflow:hidden; background:var(--bg-surface);}
.scroll{overflow-x:auto;}
table{width:100%; border-collapse:collapse; font-size:13.5px; min-width:860px;}
thead th{position:sticky; top:0; background:var(--bg-elevated); color:var(--text-tertiary);
         font-size:11px; font-weight:700; letter-spacing:.06em; text-align:start;
         padding:11px 14px; border-bottom:1px solid var(--line); white-space:nowrap;}
tbody td{padding:12px 14px; border-bottom:1px solid rgba(107,159,255,.06); vertical-align:top;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background-color:var(--bg-hover);}   /* -color, never the shorthand: see the TINT note */

/* ── family accent (the LIFE pass) ────────────────────────────────────────
   Every row carries a 3px accent on its INLINE-START edge in its family's colour, so
   a scan down the table reads as families rather than as one grey list. --fam is set
   on the ROW from data-fam, and drawn by the first cell's ::before: a border on a
   <tr> under border-collapse is unreliable across browsers, while a positioned
   pseudo-element on the first cell is not, and inset-inline-start puts it on the
   correct edge in Hebrew without a second rule.
   ONE MAP, TWO SURFACES (LIFE pass 3, 2026-09-23): every line below names the alert
   TICKET as well as the row, because the ticket now wears its family too (the band,
   see `.tkwrap .tk[data-fam]`). One map means a colour can never drift between a row
   and the card it opens. The row selector stays second and unbroken on purpose — the
   harness pins it by that exact text. */
tbody tr{--fam:rgba(107,159,255,.22);}
/* ── family TINT (LIFE pass 2 — operator order 2026-09-23 16:3x ET: "put some more life and
   colours into the system… options are painted purple, so the options alert should be
   purple background as well, but much much lighter") ─────────────────────────────
   Every row's surface takes its family colour at 8% — a CAST, not a fill: the badge and
   the accent bar say the family out loud, the surface only agrees with them. It rides
   `background-image` (a flat two-stop gradient of one colour) and NEVER `background-color`,
   because that channel is already spoken for: :hover, the 60s fresh tint and the
   `glowfade` arrival all paint `background-color`, and an image layer sits ABOVE a colour
   layer, so all three still show through the cast instead of being wiped by it — which is
   also why those rules now say `background-color`, never the shorthand (`background:`
   resets the image layer, and the family would vanish under the pointer).
   `--fam-tint` is computed on the row from the row's OWN --fam, so the eight family rules
   above need no second line each. The unknown-family default is a translucent blue, which
   mixes down to ~1.5% — effectively no cast, on purpose. The empty row carries none. */
tbody tr{--fam-tint:color-mix(in srgb,var(--fam) 8%,transparent);
         background-image:linear-gradient(var(--fam-tint),var(--fam-tint));}
tbody tr.emptyrow{background-image:none;}
.tkwrap .tk[data-fam="momentum"],tbody tr[data-fam="momentum"]{--fam:var(--up);}
.tkwrap .tk[data-fam="levels"],tbody tr[data-fam="levels"]{--fam:var(--accent);}
.tkwrap .tk[data-fam="options"],tbody tr[data-fam="options"]{--fam:var(--info);}
.tkwrap .tk[data-fam="insider"],tbody tr[data-fam="insider"]{--fam:var(--insider);}
.tkwrap .tk[data-fam="news"],tbody tr[data-fam="news"]{--fam:var(--news);}
.tkwrap .tk[data-fam="osint"],tbody tr[data-fam="osint"]{--fam:var(--osint);}
.tkwrap .tk[data-fam="market"],tbody tr[data-fam="market"]{--fam:var(--market);}
.tkwrap .tk[data-fam="market_update"],tbody tr[data-fam="market_update"]{--fam:var(--brief);}
/* the floor rose 110 → 176px on 2026-09-10: the tile is a BOX now, and 176 − 28 of cell
   padding is the 148px box, whose inner width is the name's — see the tile block below */
.c-tk{white-space:nowrap; min-width:176px; position:relative;}
.c-tk::before{content:""; position:absolute; inset-block:0; inset-inline-start:0; width:3px;
              background:var(--fam); opacity:.62; border-radius:2px; transition:opacity .18s ease;}
tbody tr:hover .c-tk::before{opacity:1;}
.tk{font-weight:700; font-size:14px; color:var(--text-primary); display:inline-block;}
/* ── the ticker TILE — ONE BOX holding company, ticker and price ─────────────
   The box is now DRAWN ON PURPOSE by its own element (`div.tkbox`) instead of being
   inherited by accident from the ticket modal's bare `.tk` rule (see the note beside
   `.tkwrap .tk`). Same dark-panel language as the rest of the page, at a size a table
   cell can carry: 10px radius rather than the modal's 16, and 7px/8px of padding rather
   than a modal's 22px/24px — which is what those empty bands above and below the ticker
   have been all along. Now they hold the name and the price, which is what the operator
   drew on the screenshot.

   WIDTH — the box is a fixed 148px so the column reads as a stack of identical cards,
   never a ragged one. 148 = the cell's content box at its 176px floor; inside it,
   148 − 2 border − 16 padding leaves exactly the 130px the name may take, so the name's
   max-content contribution is exactly the floor the cell already declares and no name
   can widen the column. 130px is a MEASURED number: the worst specimen the operator
   named, "1-800-FLOWERS.COM, Inc.", carries an 18-character unbreakable token measuring
   ~118px at 11px in this font stack, so it clears by ~10% — enough that a substituted
   fallback font cannot force `overflow-wrap` to snap it mid-word.

   HEIGHT — the box grows for a two-line name and shrinks when there is none. There is
   no reserved empty band: a card with no resolved name is a box holding ticker + price.

   CENTRED, WHICH IS ALSO WHAT MAKES IT DIRECTION-BLIND — `text-align:center` reads the
   same in Hebrew and in English, so the RTL edge rules this block used to need are gone
   rather than accumulated. The spans keep dir="ltr" purely for BIDI (without it the
   trailing "." of "…, Inc." jumps to the wrong end of the string); centring is immune to
   the direction that attribute forces, which flushing never was.

   THE CLAMP — `display:block` is declared FIRST so an engine that does not know
   `-webkit-box` keeps a block and still stops at `max-height` (2 × the 14px line): a
   hard two-line cut rather than an ellipsised one, but never a third line and never a
   grown row. `title` carries the whole name in either case. */
.tkbox{display:block; max-width:148px; padding:7px 8px; text-align:center;
       background:var(--bg-surface); border:1px solid var(--line); border-radius:10px;}
.tkco{display:block; display:-webkit-box; -webkit-box-orient:vertical;
      -webkit-line-clamp:2; line-clamp:2; max-height:28px; overflow:hidden;
      max-width:130px; margin:0 auto 2px; font-size:11px; line-height:14px;
      color:var(--text-secondary); white-space:normal; overflow-wrap:anywhere;}
/* the price is the ONE thing on this page deliberately BRIGHTER than --text-primary
   (#EAEEF7): operator order 2026-09-10, "a bit little whiter then the ticker". */
.px{display:block; color:var(--px-bright); font-size:11.5px; margin-top:2px;}
/* §CLASS FACTS (2026-09-28) — the ticket's share-structure facts as ONE muted line in the
   tile, right after the name: smaller and dimmer than the name, plain text (never a chip).
   It may WRAP (the cell is nowrap), but only between facts — each fact holds together. */
.tkfx{display:block; max-width:130px; margin:0 auto 3px; font-size:10px; line-height:13px;
      color:var(--text-tertiary); white-space:normal;}
.tkfxi{white-space:nowrap;}
.tkfxs{color:var(--text-disabled);}
/* THE SOURCE BADGE ("Cerebro") — operator order 2026-09-16: "aligned in the middle, same as
   the stocks, and 10% bigger". It used to be an inline-block pill hugging the inline-start
   edge while every symbol-ful row rendered a centred 148px `.tkbox` beside it, so the one
   column read as two different layouts. It is now the SAME BOX: `display:block` at the same
   `max-width:148px` with `text-align:center`, so the word sits over exactly the footprint a
   ticker occupies. Font 11.5px -> 12.65px is the 10% that was asked for, to the decimal. */
.srcb{display:block; max-width:148px; text-align:center; box-sizing:border-box;
      font-size:12.65px; font-weight:700; color:var(--osint);
      background:var(--osint-bg); border:1px solid var(--osint-line); border-radius:6px;
      padding:2px 8px; white-space:nowrap;}
.srcb.mkt{color:var(--market); background:var(--market-bg); border-color:var(--market-line);}
.c-sig{white-space:nowrap;}
/* v2: one notch of saturation on every family chip — .16 fill / .5 border. The families
   are the page's colour system; at .09 they read as grey pills with tinted text. */
.chip{display:inline-block; font-size:11px; font-weight:700; border-radius:6px; padding:3px 9px;
      border:1px solid; margin-inline-end:8px;}
.chip-momentum{color:var(--up); border-color:rgba(59,212,162,.5); background:rgba(59,212,162,.16);}
.chip-levels{color:var(--accent-2); border-color:rgba(107,159,255,.5); background:rgba(107,159,255,.16);}
.chip-options{color:var(--info); border-color:rgba(155,140,255,.5); background:rgba(155,140,255,.16);}
.chip-insider{color:var(--insider); border-color:rgba(159,232,112,.5); background:rgba(159,232,112,.16);}
.chip-osint{color:var(--osint); border-color:rgba(79,195,232,.5); background:rgba(79,195,232,.16);}
.chip-news{color:var(--news); border-color:rgba(224,112,155,.5); background:rgba(224,112,155,.16);}
.chip-market{color:var(--market); border-color:rgba(143,163,200,.46); background:rgba(143,163,200,.16);}
.chip-market_update{color:var(--brief); border-color:rgba(94,168,242,.5); background:rgba(94,168,242,.16);}
.kind{color:var(--text-secondary); font-size:12px;}
/* §CLASS — the OSINT event class printed in the kind word's place ("Oil Supply Major
   Alert", operator order 2026-09-24). Descriptive TEXT, not a chip: the same 12px line as
   the kind word, one step brighter and heavier because it names the EVENT rather than the
   lane. On a CRITICAL row it takes the red row's text colour (`tbody tr.crit .kcls`, in the
   CRITICAL block below). Outside every width query, so the mobile card draws it the same. */
.kcls{color:var(--text-primary); font-weight:600;}
/* a cell with NO reading. An em dash, never a zero and never a greyed-out illustrative
   value — an unknown intensity is not a 1, and an unknown direction is not a watch. */
.ill{opacity:.6;}
.dash{color:var(--text-disabled); font-size:14px; font-weight:700; letter-spacing:.06em;}
th .ast{color:var(--warn);}

/* ── the two MECHANICAL columns (PULSE v2) ────────────────────────────────
   🔴 These are NOT the mockup's .dots / .dirpill, which ranked an alert by model
   conviction and a model long/short call. Both of those quantities are still barred
   (conviction is anti-calibrated 16/16 days; every MADRL voter was inverted on LONG
   over n=245,805) and neither class exists in this stylesheet — the selftest holds
   that line. What renders here is arithmetic on the alert itself: an intensity TIER
   from traded volume / float turnover / rvol, and the alert KIND stated as a word.

   Interest is a WRITTEN TIER, never a numeral (operator order, 2026-08-28 — it used to
   be three dots). A number invites the reader to treat it as a score, which is
   precisely what it is not; a word can say "how much stock changed hands" without
   implying a ranking against the next card.

   The column is TABULAR: table-layout is auto, so the column is already sized by the
   WIDEST word among the rows currently in the DOM — every cell in it matches. The
   floor below is what stops the column CHANGING width as rows arrive and leave: it is
   set for "CRITICAL INTEREST" (17 characters at 11.5px/800 plus the cell's 14px
   padding on each side), so a table that happens to hold no critical row is still the
   same width as one that does. */
.c-int{min-width:154px;}
.act{display:inline-block; font-size:11.5px; font-weight:700; letter-spacing:.02em;
     white-space:nowrap;}
/* tier 1 is DIM on purpose: "Low interest" is the least interesting thing the column can
   say, and it should not compete with the alert's own prose for attention. */
.act.a1{color:var(--text-tertiary); font-weight:600;}
.act.a2{color:var(--warn);}
/* tier 3 is the only place --hot appears — one hot accent per page. */
.act.a3{color:var(--hot);}
/* tier 4 — CRITICAL INTEREST, the loudest thing this page says about an alert, and the
   only all-caps English tier (ordered that way). Red, weight 800, and a SUBTLE glow.
   The glow is a text-shadow, NOT a keyframe: the page's animation ceiling is unchanged,
   and the reduced-motion block has nothing here to switch off because nothing moves. */
.act.a4{color:var(--crit); font-weight:800; text-shadow:0 0 9px rgba(255,77,77,.45);}
.dirc{display:inline-block; font-size:11px; font-weight:700; letter-spacing:.02em; white-space:nowrap;
      border-radius:6px; padding:3px 9px; border:1px solid;}
.dirc-bullish{color:var(--up); border-color:rgba(59,212,162,.5); background:rgba(59,212,162,.16);}
.dirc-bearish{color:var(--down); border-color:rgba(243,110,110,.5); background:rgba(243,110,110,.16);}
/* WATCH is an OUTLINE on purpose — it is the ABSENCE of a directional read, and a
   filled chip would make it look like a third call. */
.dirc-watch{color:var(--warn); border-color:rgba(232,176,74,.5); background:transparent;}
/* CRITICAL (2026-09-24) takes the WATCH chip's slot on a CRITICAL OSINT row, and is FILLED
   on purpose: the operator's words were "is not a watch". It is a SEVERITY, not a fourth
   direction — its own tokens, and the tooltip says "direction: Watch". */
.dirc-crit{color:var(--crit-chip-fg); border-color:var(--crit-chip-bg); background:var(--crit-chip-bg);
           font-weight:800; letter-spacing:.06em;}

/* ── sub.alert.v2 · the DIRECTION LEVEL, drawn as pips ────────────────────────
   THE CHIP WORD DOES NOT CHANGE WITH THE LEVEL, and neither does its colour. A
   level is not a louder call — it is a count of the independent measurements
   standing behind the SAME call — so it may not be allowed to read as intensity.
   The pips inherit `currentColor`, so a level can never recolour a chip into
   looking like a different direction, and the unlit ones stay visible at .28 so
   "one of three" reads as one of three rather than as a single dot.
   They are aria-hidden: the chip's aria-label already says "Bullish · Stated ·
   computed materiality" in words, and a screen reader must hear the basis, never
   "three dots". A `watch` chip never has them — renderableLevel refuses. */
.dirpips{display:inline-flex; gap:2px; margin-inline-start:6px; vertical-align:middle;}
.dirpips i{width:4px; height:4px; border-radius:50%; background:currentColor; opacity:.28;}
.dirpips i.lit{opacity:1;}
/* ⚠️ the lit-pip class is `lit` and NOT the obvious short word, and that is
   load-bearing: the interest column's "no dot markup survives" guard bans the
   retired dot selector in this file outright, and a NEW column must never weaken
   an OLD column's guard to make room for itself. */
/* ── §5.4.4 · the ×N repeat badge ─────────────────────────────────────────────
   PRESENTATION ONLY. Nothing was dropped and nothing was withheld — this row
   stands for N identical cards inside a 30-minute window, and the ticket lists
   every one of their times. Deliberately the quietest thing in its cell: it is a
   note about repetition, not a signal about the alert. */
.repb{display:inline-block; margin-inline-start:7px; font-size:9.5px; font-weight:800;
      letter-spacing:.03em; color:var(--text-tertiary); border:1px solid var(--line);
      border-radius:999px; padding:1px 6px; vertical-align:middle;}
/* the ticket's direction rows: the level+basis in words under the chip, then the
   card's own measured number. Both are DIMMER than the chip — they explain the
   claim, they are not a second one. */
.tkdb{display:block; margin-top:4px; font-size:10.5px; color:var(--text-tertiary);}
.tkds{display:block; margin-top:2px; font-size:11px; color:var(--text-secondary);}
.tkrep{display:block; margin-top:3px; font-size:10.5px; color:var(--text-tertiary);}
.c-why{color:var(--text-secondary); line-height:1.5; max-width:440px;}
.whyhd{display:block; color:var(--text-primary); font-weight:600; margin-bottom:3px;}
.whytx{display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;}
.trtag{display:inline-block; margin-top:5px; font-size:9.5px; font-weight:700; letter-spacing:.04em;
       color:var(--info); background:var(--info-bg); border:1px solid rgba(155,140,255,.34);
       border-radius:999px; padding:1px 8px;}
/* §NEWS SLOT (2026-09-28) — the empty-news-slot line, LAST in the WHY cell: muted and smaller
   than the headline, plain text — not a chip, no icon. It speaks for the feed, and wraps. */
.newsgap{display:block; margin-top:5px; font-size:11px; line-height:1.4; font-weight:500;
         color:var(--text-tertiary);}
/* §OPTIONS HOLD (2026-09-28, order 11) — "expires 2026-10-30 · 32 DTE" under the kind word of an options
   row that carries an expiry: muted, smaller than the kind, plain text (not a chip). The date is an ltr
   figure span, so it reads the same on the Hebrew page. */
.optexp{display:block; margin-top:3px; font-size:10.5px; font-weight:500; color:var(--text-tertiary);}
.c-tm{color:var(--text-tertiary); font-size:11.5px; white-space:nowrap; text-align:end;}
.rel{display:block; color:var(--text-disabled); font-size:10.5px; margin-top:3px;}
.nowb{display:inline-block; margin-inline-start:8px; font-size:9.5px; font-weight:800; letter-spacing:.06em;
      color:var(--up); background:rgba(59,212,162,.14); border:1px solid rgba(59,212,162,.4);
      border-radius:999px; padding:1px 7px; vertical-align:middle; transition:opacity .6s ease;}
.nowb.off{opacity:0;}
/* round 2 — ONE "now": while the green fresh chip is up, the age label beside it (which also reads "now") stands down */
.c-tm .nowb:not(.off) ~ .rel{display:none;}
.emptyrow td{text-align:center; color:var(--text-tertiary); font-size:12.5px; padding:34px 14px;}
.emptyrow:hover{background:transparent;}

/* ── the fresh window (60s) ───────────────────────────────────────────────
   A row that arrived in the last minute keeps a quiet LIVE-green tint and a hairline
   inset edge, and its family accent burns at full strength. Green rather than the
   family colour on purpose: the tint answers "is this new?", the accent answers
   "what kind is it?" — one channel per question, or the table starts arguing with
   itself. Written AFTER :hover so the state survives the pointer.
   NO keyframes: the fade-out is a transition, which costs the page no new animation
   and is switched off wholesale by the reduced-motion block below. */
tbody tr.fresh{background-color:rgba(59,212,162,.055); box-shadow:inset 0 0 0 1px rgba(59,212,162,.10);
               transition:background-color .9s ease, box-shadow .9s ease;}
tbody tr.fresh .c-tk::before{opacity:1; box-shadow:0 0 8px var(--fam);}
tbody tr.fresh:hover{background-color:rgba(59,212,162,.085);}
/* the last 900ms: the tint crossfades to nothing, then the sweeper drops the class */
tbody tr.fresh.out{background-color:transparent; box-shadow:inset 0 0 0 1px rgba(59,212,162,0);}
tbody tr.fresh.out .c-tk::before{box-shadow:none;}
/* reduced motion: SAME 60 seconds, same tint — it simply blinks out at the end
   instead of crossfading. The state is information; the crossfade is decoration. */
tbody tr.fresh.nofade{transition:none;}
tbody tr.fresh.nofade.out{background-color:transparent; box-shadow:none;}

/* arrival motion — inherited verbatim from the approved mockup */
@keyframes slidein{from{opacity:0; transform:translateY(-12px);} to{opacity:1; transform:none;}}
@keyframes glowfade{
  0%{background-color:rgba(107,159,255,.17); box-shadow:inset 0 0 0 1px rgba(107,159,255,.42);}
  70%{background-color:rgba(107,159,255,.07); box-shadow:inset 0 0 0 1px rgba(107,159,255,.18);}
  100%{background-color:rgba(107,159,255,0); box-shadow:inset 0 0 0 1px rgba(107,159,255,0);}
}
tbody tr.arrive{animation:slidein .42s cubic-bezier(.2,.8,.3,1), glowfade 2.5s ease-out;}

/* ── the CRITICAL OSINT row (operator order 2026-09-24) ─────────────────────
   "should be marked as Critical, flickering for 15 minutes and placed at first until that
   time ends… the background of such alert should be red. light red, but noticeable".
   Two classes, both set by the renderer from the alert and a clock: `crit` for the row's
   WHOLE life, `crit-live` inside its 15-minute window (pinned + flickering).
   🔴 THE DECISION (pinned in selftest §Y — REVISED in round 2, 2026-09-24). The red rides
   `background-color`, OPAQUE, and the 8% family cast STANDS DOWN on a critical row
   (`background-image:none`, in the same rule). Pass 1 kept the cast on `background-image`
   ABOVE a translucent red, and on the rendered page the cyan OSINT cast over the navy base
   turned the red plum (hue 304°) — not the "red. light red" that was ordered. The row does
   not lose its family: the accent bar (.c-tk::before; on a phone, the card's inline-start
   border) and the source badge still say it out loud, and the cast only ever agreed with
   them. Against the other states that paint `background-color`:
     · fresh / fresh.out / fresh.nofade.out — the red WINS. A critical row is red from its
       first paint to its last, never green and never faded to nothing; the fresh state
       keeps its accent burn (a box-shadow on the first cell), which is not a colour.
     · :hover — COMPOSED, not lost: the hover is the stronger red.
     · the arrival glow — on a LIVE row the flicker REPLACES it (both are `animation`, and
       the flicker is the louder, longer arrival). An expired critical row that arrives
       late (a delayed tier) plays the glow once and settles back to its red.
   The selectors are COMPOUNDS of .crit, so each outranks the state rule it answers by
   specificity — no !important anywhere. They sit outside every media query, so the
   mobile card layout (the row as a block) wears exactly the same surface.
   The flicker animates `background-color` ONLY — never opacity, never the text colour —
   so the text holds full opacity through the whole cycle.
   The interest word takes --crit-row-fg on this surface and drops its glow: the tier's
   --crit is 3.34:1 on the flicker's far end (below AA at 11.5px), and a red halo on a red
   row only blurs the glyph edge. The compound outranks `.act.a4` by specificity.
   The event CLASS label (§CLASS, "Oil Supply Major Alert") takes the same --crit-row-fg
   at 700 — the critical text colour, at the contrast the red surface allows (7.43 / 5.94:1
   on the two ends at 12px, where --crit itself would fall to 3.34:1). */
tbody tr.crit,
tbody tr.crit.fresh,
tbody tr.crit.fresh.out,
tbody tr.crit.fresh.nofade.out{background-color:var(--crit-row-bg); background-image:none; box-shadow:inset 0 0 0 1px var(--crit-row-line);}
tbody tr.crit:hover,
tbody tr.crit.fresh:hover{background-color:var(--crit-row-bg-strong);}
tbody tr.crit .act.a4{color:var(--crit-row-fg); text-shadow:none;}
tbody tr.crit .kcls{color:var(--crit-row-fg); font-weight:700;}
tbody tr.crit-live{animation:critflick 2.4s ease-in-out infinite alternate;}
@keyframes critflick{from{background-color:var(--crit-row-bg);} to{background-color:var(--crit-row-bg-strong);}}
/* reduced motion: no flicker at all — the row stays pinned and holds the STATIC light red */
@media (prefers-reduced-motion: reduce){
  tbody tr.crit-live{animation:none; background-color:var(--crit-row-bg);}
}
/* ── §FLIP · the market / sector regime flip flickers for 10 minutes (operator order
   2026-09-24: "the Market flip / sector flip will also flicker for 10 minutes") ────────
   The `background-color` channel — the one hover / fresh / glowfade already use; the family
   cast is the image layer above it and shows through — swings to the row's OWN family colour
   at 26% and back, at the critical row's cadence so the page has ONE rhythm. Not red, not
   pinned, no chip: a flip is "notice me", not "critical". LIVE-only (a flip has no whole-life
   state), and reduced motion gets the still tint beside the global kill. */
tbody tr.flip-live{animation:flipflick 2.4s ease-in-out infinite alternate;}
@keyframes flipflick{from{background-color:transparent;} to{background-color:color-mix(in srgb,var(--fam) 26%,transparent);}}
@media (prefers-reduced-motion: reduce){
  tbody tr.flip-live{animation:none; background-color:color-mix(in srgb,var(--fam) 14%,transparent);}
}
/* ── §13-F HOT · a news ticket whose latest tape raised share volume and the day's gain (user 2026-10-04).
   Pinned first and flickering while that rise is still the latest print, or until Stop updates. No clock.
   The frame is the fresh / crit inset shadow. The pulse REUSES flipflick (no new keyframe).
   Reduced motion: the global kill stops the pulse; the frame and the chip stay. */
tbody tr.lt-hot,
tbody tr.lt-hot.fresh,
tbody tr.lt-hot.fresh.out,
tbody tr.lt-hot.fresh.nofade.out{box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--warn) 72%,transparent);}
tbody tr.lt-hot{animation:flipflick 2.4s ease-in-out infinite alternate;}
.lthot .ltstop{font:inherit;font-weight:700;margin-inline-start:8px;padding:1px 6px;border-radius:4px;
  border:1px solid color-mix(in srgb,var(--warn) 70%,transparent);background:transparent;color:var(--warn);cursor:pointer;}
/* ruling 10-05 — the QUIET tier ("Updating · Stop updates") and the STOPPED card ("Updates stopped · Resume updates"):
   a muted pill, no pulse, no frame, no pin */
.ltquiet{display:flex; align-items:baseline; width:max-content; max-width:100%; box-sizing:border-box;
         margin:0 0 6px; padding:2px 9px; border-radius:999px; font-family:var(--font-sans); font-size:11px; line-height:16px;
         font-weight:700; white-space:nowrap; color:var(--text-secondary); border:1px solid var(--line);}
.ltquiet .ltstop,.ltquiet .ltresume{font:inherit;font-weight:700;margin-inline-start:8px;padding:1px 6px;border-radius:4px;
  border:1px solid var(--line);background:transparent;color:var(--text-primary);cursor:pointer;}
.ltquiet.lthalted .ltresume{color:var(--warn); border-color:color-mix(in srgb,var(--warn) 70%,transparent);}
/* the OPEN ticket of a HOT card: a pulse dot in its header + the 10-minute velocity
   — it REUSES the page's sanctioned live dot (.livep i, blip): no new infinite animation, recoloured amber as .livep.stale is */
.livep.lthotdot{color:var(--warn); background:var(--warn-bg); border-color:color-mix(in srgb,var(--warn) 55%,transparent);
                font-size:11px; letter-spacing:0; text-transform:none;}
.livep.lthotdot i{background:var(--warn); box-shadow:0 0 8px color-mix(in srgb,var(--warn) 70%,transparent);}

/* ── the alert ticket (the full card) ─────────────────────────────────────
   The row truncates — one line of headline, three of prose. This is where the
   subscriber reads the whole thing, in BOTH languages, with the meta grid of what
   the contract actually carries. Same dark-institutional panel as the sign-in gate,
   so the page has one modal language and not two. */
.tkwrap{position:fixed; inset:0; z-index:70; display:none; align-items:center; justify-content:center;
        padding:24px 20px; background:rgba(4,7,13,.72);}
.tkwrap.on{display:flex;}
/* 🔴 SCOPED 2026-09-10, AND THIS IS A BUG FIX, NOT TIDYING. This rule was a BARE `.tk`,
   and `.tk` is ALSO the feed row's ticker span — so every ticker in the table has been
   wearing this modal's chrome: a --bg-surface fill, a 16px radius, a 1px border, a
   `0 28px 70px` drop shadow, `width:100%`, `overflow-y:auto`, and `padding:22px 24px 24px`.
   That padding is the mystery "dark rounded box" with an empty band above and below the
   ticker that the operator has been annotating — a modal's padding, drawn 25 rows deep in
   a table. `.tkwrap .tk` keeps the panel and takes the row back. The tile draws its own
   box on purpose now (see .tkbox), at a size a table cell can carry. */
/* 🔴 WIDENED 2026-09-11, 720 → min(960px, 94vw), BY OPERATOR ORDER, and it is a bug
   fix rather than a preference. At 720px the sector ticket's category table could
   not seat its four columns beside a 60-character taxonomy key
   ("Spacecraft Manufacturing, Components & Enabling Technologies"), so the wrapper's
   overflow-x took over and the subscriber got a table that scrolled sideways inside a
   modal and clipped the very names the ticket exists to show. The room is the fix; the
   column plan below is what spends it. 94vw is the small-screen half of the same
   rule — a fixed 960 would overhang a phone, and .tkwrap's own 20px side padding is
   not enough on its own. EVERY ticket family shares this panel, so the alert card's
   prose simply gets a wider reading column out of the same change. */
.tkwrap .tk{position:relative; width:100%; max-width:min(960px, 94vw); max-height:86vh; overflow-y:auto;
    background:var(--bg-surface); border:1px solid var(--line); border-radius:16px;
    padding:22px 24px 24px; box-shadow:0 28px 70px rgba(0,0,0,.6);
    --fam:rgba(107,159,255,.22);}   /* the rows' faint default: an unknown family paints a whisper, never currentColor */
/* the close control sits in the panel's inline-END corner in BOTH directions */
.tkx{position:absolute; top:12px; inset-inline-end:12px; width:30px; height:30px; line-height:1;
     font-family:var(--font-sans); font-size:19px; font-weight:700; color:var(--text-tertiary);
     background:var(--bg-elevated); border:1px solid var(--line); border-radius:9px; cursor:pointer;
     transition:color .15s, border-color .15s;}
.tkx:hover{color:var(--text-primary); border-color:var(--accent-glow);}
/* ── the FAMILY BAND (LIFE pass 3 — the operator's go, 2026-09-23 17:3x ET) ────────
   The ticket carries its family exactly as the row it opened from does: `data-fam` on
   the panel, painted by the ONE family map above. Three touches, one channel:
   a 4px band along the top edge (the header's `.aur` idea in the family's colour — a
   background layer, so it holds still while the panel scrolls and is clipped by the
   16px radius), the same 8% cast the row wears, and the prose blocks' side rule + the
   close button's hover ring in the family colour. The panel's BORDER stays neutral on
   purpose: a coloured frame reads as a LEVEL, and level and family are two channels
   that must never blur. The brief keeps its gold frame and simply gains the band.
   `.tkwrap .tk` itself is untouched (the harness pins that there is exactly one). */
.tkwrap .tk[data-fam]{--fam-tint:color-mix(in srgb,var(--fam) 8%,transparent);
     background-image:linear-gradient(var(--fam),var(--fam)),linear-gradient(var(--fam-tint),var(--fam-tint));
     background-size:100% 4px,auto; background-repeat:no-repeat,repeat; background-position:top,0 0;}
.tkwrap .tk[data-fam] .tkl{border-inline-start-color:color-mix(in srgb,var(--fam) 60%,transparent);}
.tkwrap .tk[data-fam] .tkx:hover{border-color:var(--fam); color:var(--text-primary);}
/* ── the CRITICAL ticket (§CRITICAL review, 2026-09-24) ─────────────────────────────
   The row a subscriber taps is red; the card it opens must not say otherwise. The panel
   wears the row's two classes (app.js tkPanelClass) and the row's OWN tokens — no new colour:
     · `crit` (the card's whole life): the panel surface is the row's opaque --crit-row-bg
       and the 8% family cast STANDS DOWN — the row's round-2 decision, for the row's
       reason (a translucent red over the navy base and the cyan cast renders plum). The
       band stays the 4px top layer and turns the chip's red (--crit-chip-bg, through
       --crit-band). COMPOSED, never replaced: data-fam stays on the panel, so the prose
       rule, the close ring and the family chip in the grid still name the family —
       exactly as the accent bar still does on the red row. The frame stays neutral (a
       coloured frame reads as a level), and nothing here touches a non-critical card.
     · `crit-live` (inside the window only): the BAND alone flickers — `critband`, at the
       row's own cadence (2.4 s ease-in-out, alternate), between the chip's red and the
       row's hairline red. It animates ONE registered colour (@property --crit-band) that
       paints only the 4px band layer, so the surface and every glyph hold still. Reduced
       motion: no animation, the static chip-red band (its own rule, beside the global kill).
     · the interest word takes --crit-row-fg and drops its glow, as it does on the row:
       the tier's --crit is 4.18:1 on this surface, below AA at 11.5px.
     · the Severity slot may WRAP: the printed "Direction: Watch" drops under the chip
       instead of being cut by the grid cell's ellipsis (measured: the English line was
       clipped to "Direction: Wat" at 1280px) — a clipped direction is one the reader
       does not have. */
@property --crit-band{syntax:"<color>"; inherits:false; initial-value:transparent;}
.tkwrap .tk.crit[data-fam]{--crit-band:var(--crit-chip-bg); background-color:var(--crit-row-bg);
     background-image:linear-gradient(var(--crit-band),var(--crit-band));
     background-size:100% 4px; background-repeat:no-repeat; background-position:top;}
.tkwrap .tk.crit .act.a4{color:var(--crit-row-fg); text-shadow:none;}
.tkwrap .tk.crit .tkm[data-k="direction"] .tkmv{flex-wrap:wrap; row-gap:2px;}
/* ROUND 8 (2026-09-24): a HIGH card's ticket prints "Geopolitical risk N" beside the outline Watch chip — the same
   wrap, so the labelled number drops under the chip instead of being clipped to "Geopolitical ri" */
.tkwrap .tkm[data-k="direction"] .tkmv:has(.tkrisk){flex-wrap:wrap; row-gap:2px;}
/* ROUND 8 (2026-09-24, screenshot finding): the Signal Type fact carries the CLASS label
   ("Critical-Infrastructure Cyberattack" / "פריצת סייבר לגוף ממשלתי"), which is longer than
   the 196px cell — the single-line value clipped its FIRST letter in Hebrew and read as a
   different word. The cell wraps instead; the ellipsis rule stays for every other fact. */
.tkwrap .tkm[data-k="kind"]{align-items:flex-start;}
.tkwrap .tkm[data-k="kind"] .tkmv{white-space:normal; overflow:visible; text-overflow:clip; line-height:1.35;}
/* ORDER 12c (2026-09-28, the user on the AMC unusual-flow card: "the company name is cut") — the value is an
   inline-flex span, so no ellipsis ever drew: "AMC ENTERTAINMENT HOLDINGS, INC." was clipped at "AMC
   ENTERTAINMENT H" by the 196px cell. The company fact wraps exactly as the kind row does; app.js sets the
   full name as its title. */
.tkwrap .tkm[data-k="company_name"]{align-items:flex-start;}
.tkwrap .tkm[data-k="company_name"] .tkmv{white-space:normal; overflow:visible; text-overflow:clip; line-height:1.35;}
.tkwrap .tk.crit-live[data-fam]{animation:critband 2.4s ease-in-out infinite alternate;}
@keyframes critband{from{--crit-band:var(--crit-chip-bg);} to{--crit-band:var(--crit-row-line);}}
@media (prefers-reduced-motion: reduce){
  .tkwrap .tk.crit-live[data-fam]{animation:none;}
}
.tkhd{display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; padding-inline-end:38px;}
.tksym{font-size:19px; font-weight:800; letter-spacing:.02em; color:var(--text-primary);}
.tkcap{font-size:10.5px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
       color:var(--text-tertiary);}
/* the meta grid — only the fields the alert HAS. An absent field is absent, never a
   row of em dashes: a grid of dashes reads as broken data instead of as N/A. */
.tkmeta{display:grid; grid-template-columns:repeat(auto-fill,minmax(196px,1fr)); gap:9px 18px;
        margin-top:16px; padding:14px 0 15px; border-top:1px solid var(--line);
        border-bottom:1px solid var(--line);}
.tkmeta:empty{display:none;}
.tkm{display:flex; align-items:center; gap:9px; min-width:0;}
.tkml{flex:0 0 auto; font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
      color:var(--text-tertiary);}
.tkmv{display:inline-flex; align-items:center; gap:8px; min-width:0; font-size:13px;
      color:var(--text-primary); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.tkmv .rel{display:inline; margin:0; font-size:10.5px;}
/* D1 (10-05): the live PRICE NOW slot ("$0.44 +26%" + "at alert $0.35") wraps; text-overflow never applies to the
   children of an inline-flex box, so overflow:hidden only CLIPPED it on the desktop grid */
.tkwrap .tkm[data-k="price"] .tkmv{flex-wrap:wrap; row-gap:2px; white-space:normal; overflow:visible; text-overflow:clip;}
.tkmv .chip{margin-inline-end:0;}
/* one block per language, each with its own direction — a Hebrew card inside an
   English page still reads right-to-left, and vice versa. */
.tkbody{display:flex; flex-direction:column; gap:16px; margin-top:17px;}
.tkl{border-inline-start:2px solid var(--line); padding-inline-start:13px;}
.tklname{display:block; font-size:9.5px; font-weight:800; letter-spacing:.1em; text-transform:uppercase;
         color:var(--text-disabled); margin-bottom:6px;}
.tklh{font-size:14.5px; font-weight:700; color:var(--text-primary); line-height:1.5; margin-bottom:6px;}
/* 🔴 NO line clamp anywhere in here. The ticket exists BECAUSE the row truncates;
   clamping the prose again would leave the subscriber with no surface that shows the
   whole text. pre-wrap keeps the producer's own line breaks. */
.tklw{font-size:13px; color:var(--text-secondary); line-height:1.72;
      white-space:pre-wrap; overflow-wrap:anywhere;}
/* the full analysis (`why_full`) arrives paragraphs-long: each blank-line break is a
   real <p> with reading room, single newlines still drawn by the inherited pre-wrap.
   The PANEL (.tk, max-height:86vh, overflow-y:auto) is the scroll surface — a
   6,000-character card scrolls; it is never clamped and never clipped. */
.tklw p{margin:0 0 10px;}
.tklw p:last-child{margin-bottom:0;}
/* market_update — the premium brief ticket (8th family, 2026-09-02): a long-form
   editorial card gets an accent frame and a wider reading column. The body already
   renders why_full/he_why_full unclamped (.tklw pre-wrap, panel scrolls) — no clamp
   overrides needed, only the frame.
   🔴 ITS `max-width:820px` IS GONE (2026-09-11). It was written to make this family
   WIDER than the 720px base; once the base became min(960px, 94vw) the very same
   declaration started making the premium brief the NARROWEST ticket on the page —
   an override that had silently inverted its own purpose. The frame stays, the width
   comes from the shared panel, and the brief keeps the most room, as intended. */
.tk.card--brief{border:1px solid var(--brief, #5EA8F2); border-radius:10px;}
.tk.card--brief .tklw{line-height:1.6;}

/* ── pulse panels (2026-09-01) — sector / regime / market detail in the SAME modal ──
   The strip keeps its exact closed look: the affordance is cursor + the page's own
   global :focus-visible ring, never a layout change. Everything below renders inside
   .tk (the ticket panel), so the trap/Escape/backdrop chrome is inherited, not forked. */
.stile[role="button"],.regime[role="button"],.mpanel[role="button"]{cursor:pointer;}
.stile[role="button"]:hover,.regime[role="button"]:hover{border-color:var(--accent-glow);}
.ppup{color:var(--up);} .ppdn{color:var(--down);} .ppfl{color:var(--warn);}
.ppb{color:var(--up); font-weight:700;} .pps{color:var(--down); font-weight:700;}
.ppsep{color:var(--text-tertiary); margin-inline:3px;}
.ppsplit{font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:12px;}
.pparr{font-size:8px; margin-inline-end:3px; opacity:.85;}
.ppbig{font-size:15px; font-weight:800;}
.ppcap{margin-top:15px; font-size:9.5px; font-weight:800; letter-spacing:.1em;
       text-transform:uppercase; color:var(--text-tertiary);}
.pprule{margin-top:8px; font-size:12px; line-height:1.7; color:var(--text-secondary);
        border-inline-start:2px solid var(--line); padding-inline-start:13px;}
.ppmath{margin-top:4px; font-weight:700;}
.ppstale{margin-top:8px; font-size:11px; color:var(--warn);}
/* 🔴 THE SIDE-SCROLL IS GONE, AND NOT BY HIDING IT (2026-09-11). `.pptwrap` used to
   carry `overflow-x:auto`, which is machinery for a table that is too wide — it made
   the sector ticket's category table scroll sideways inside the modal and clip the
   taxonomy names. `table-layout:fixed` removes the CAUSE instead: a fixed table is
   sized by its container and its first row, never by its content, so it is physically
   incapable of asking for more width than it has been given, at ANY viewport, and
   nothing needs to scroll. A long name WRAPS (see .ppname) rather than being cut.
   The wrapper survives only as the margin it always was. */
.pptwrap{margin-top:8px;}
.ppt{width:100%; table-layout:fixed; border-collapse:collapse; font-size:12px;}
/* headers WRAP too — a nowrap header is exactly how a narrow column forces a wide
   table, and "BUYERS/SELLERS" is the widest string in this whole panel */
.ppt th{text-align:start; font-size:9.5px; font-weight:700; letter-spacing:.06em;
        text-transform:uppercase; color:var(--text-tertiary); padding:6px 10px;
        border-bottom:1px solid var(--line); white-space:normal;}
.ppt td{padding:7px 10px; border-bottom:1px solid var(--line); vertical-align:middle;}
.ppt tr:last-child td{border-bottom:none;}
/* a 60-character taxonomy key gets TWO LINES here rather than an ellipsis: the ticket
   is the surface that exists to show the whole name, so clipping it here would leave
   the subscriber with nowhere to read it. `overflow-wrap:anywhere` is for the
   pathological unbreakable token, not for normal prose. */
.ppt td.ppname{color:var(--text-primary); font-weight:600; white-space:normal;
               overflow-wrap:anywhere; line-height:1.4;}
.ppt td.ppnum{white-space:nowrap; font-variant-numeric:tabular-nums;}
/* ── the column plans. With table-layout:fixed the FIRST ROW decides the columns, so
      the percentages ride the headers. At the ticket's 912px of inner width the name
      column is ~419px — one line for a 60-character key, two on a narrow phone. ── */
.pptcat th:nth-child(1){width:46%;}
.pptcat th:nth-child(2){width:20%;}
.pptcat th:nth-child(3){width:16%;}
.pptcat th:nth-child(4){width:18%;}
.pptsec th:nth-child(1){width:46%;}
.pptsec th:nth-child(2){width:18%;}
.pptsec th:nth-child(3){width:18%;}
.pptsec th:nth-child(4){width:18%;}
.pptmem th:nth-child(1){width:40%;}
.pptmem th:nth-child(2){width:30%;}
.pptmem th:nth-child(3){width:30%;}
.ppadv{font-size:9px;}

/* ── the category drill-down (2026-09-11) — ONE category's constituent names ──
   A VIEW of the sector ticket, not a second modal: the sector's header stats stay
   above it, so the reading these prices are as-of never leaves the screen.
   DIRECTION: every rule here is logical (inline-start/end, text-align:start/end,
   grid/flex order), so the view mirrors itself in Hebrew with no [dir=rtl]
   exceptions — the lesson from the ticker tile, where the exceptions were deleted
   rather than stacked. The one thing deliberately CENTRED is nothing at all: this is
   a start-aligned reading list, and start-alignment is what flips correctly. */
.ppmhd{margin-top:15px;}
/* the back control: TEXT ONLY, no chevron. A back arrow is one of the few glyphs that
   has to be mirrored by hand between LTR and RTL, and a label that reads correctly in
   both directions costs nothing and cannot be drawn pointing the wrong way. It is a
   real <button>, so the ticket's existing Tab trap picks it up with no change. */
/* 🔴 ONE PILL RULE, TWO USES (2026-09-11). `.ppall` — the "all sector stocks"
   affordance that sits above the category table — is drawn in the SAME control
   language as the back control rather than in a new one: same radius, same border,
   same elevated fill, same hover. A second pill vocabulary on one panel is two
   things to keep in step and nothing gained. `.ppall` adds only what makes it a ROW
   rather than a button-sized pill: it spans the panel and pushes its count to the
   inline-END with `margin-inline-start:auto` (logical, so it flips in Hebrew). */
.ppback,.ppall{font:inherit; font-size:11px; font-weight:700; letter-spacing:.04em;
        color:var(--text-secondary); background:var(--bg-elevated); border:1px solid var(--line);
        border-radius:999px; padding:5px 13px; cursor:pointer;
        transition:color .15s ease, border-color .15s ease;}
.ppback:hover,.ppall:hover{color:var(--text-primary); border-color:var(--accent-glow);}
.ppall{display:flex; align-items:baseline; gap:10px; margin-top:15px; padding:9px 15px;}
.ppalll{color:var(--text-primary); font-weight:800; letter-spacing:.03em;}
.ppallc{margin-inline-start:auto; color:var(--text-tertiary); font-weight:700;
        font-variant-numeric:tabular-nums; white-space:nowrap;}
.ppmname{margin-top:11px; font-size:16px; font-weight:800; color:var(--text-primary);
         line-height:1.35; overflow-wrap:anywhere;}
/* count · updated <ET time> <relative> — the label the two figures below hang on */
.ppmsub{display:flex; align-items:baseline; flex-wrap:wrap; gap:6px; margin-top:5px;
        font-size:10.5px; font-weight:700; color:var(--text-tertiary);}
.ppmdot{color:var(--text-disabled);}
.ppmnote{margin-top:9px; font-size:11px; line-height:1.6; color:var(--text-tertiary);
         border-inline-start:2px solid var(--line); padding-inline-start:11px;}
/* the ticker is the prominent thing in its row — the price and the change are what it
   is being read WITH, not the other way round */
.ppmsym{font-size:14px; font-weight:800; letter-spacing:.02em; color:var(--text-primary);}
.ppt td.ppmsymc{white-space:nowrap;}
/* the row is the handle for all of this */
tbody tr[role="button"]{cursor:pointer;}
tbody tr[role="button"]:focus-visible{outline:2px solid var(--accent-2); outline-offset:-2px;}
/* the header strip under the title: dot + age + the two state chips */
.mpxhead{flex:1 0 100%; display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-top:11px;}
.mpxdot{width:7px; height:7px; border-radius:50%; flex:0 0 7px; background:var(--up);
        box-shadow:0 0 8px rgba(59,212,162,.8); animation:blip 1.7s ease-in-out infinite;}
/* a stale reading keeps its dot — it stops breathing and goes amber. Old is not broken. */
.mpxdot.mpxold{background:var(--warn); box-shadow:0 0 8px rgba(232,176,74,.7); animation:none;}
.mpxage{font-size:10.5px; font-weight:700; color:var(--text-tertiary); white-space:nowrap;}
.mpxrg{display:inline-flex; align-items:baseline; gap:5px;}
.mpxrgs{font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:10.5px; font-weight:700;}
.mpxrgs.up{color:var(--up);} .mpxrgs.down{color:var(--down);} .mpxrgs.flat{color:var(--warn);}

/* ── the synthesis sentence — one per language, each in its own direction ─── */
.mpxsyn{margin-top:14px; padding:13px 15px; border-radius:12px; border:1px solid var(--line);
        background:var(--bg-elevated);}
.mpxsynl{display:block; font-size:9.5px; font-weight:800; letter-spacing:.1em;
         text-transform:uppercase; color:var(--text-disabled); margin-bottom:5px;}
.mpxsynt{font-size:13.5px; line-height:1.65; color:var(--text-primary); font-weight:600;}
.mpxsyn > div + div{margin-top:11px; padding-top:11px; border-top:1px dashed var(--line);}

/* ── the explainer control ────────────────────────────────────────────────── */
.mpxhb{margin-top:12px; font:inherit; font-size:11px; font-weight:700; letter-spacing:.04em;
       color:var(--text-secondary); background:var(--bg-elevated); border:1px solid var(--line);
       border-radius:999px; padding:5px 13px; cursor:pointer;
       transition:color .15s ease, border-color .15s ease;}
.mpxhb:hover{color:var(--text-primary); border-color:var(--accent-glow);}
/* the hint line is present in the DOM at all times (so `title` and the tap row are
   the SAME text) and revealed by one class on the panel root. */
.mpxhint{display:none; margin-top:4px; font-size:11px; line-height:1.6; color:var(--text-tertiary);}
.mpx--hints .mpxhint{display:block;}
/* the panel owns its own container so nothing it sets can outlive it on the shared
   ticket body — see renderMarketDetailPanel(). */
.mpx{display:block;}

/* ── sections ─────────────────────────────────────────────────────────────── */
.mpxsec{margin-top:20px;}
.mpxcap{display:flex; align-items:center; gap:10px; font-size:9.5px; font-weight:800;
        letter-spacing:.1em; text-transform:uppercase; color:var(--text-tertiary);}
.mpxcap::after{content:""; flex:1 1 auto; height:1px; background:var(--line);}
.mpxmet{margin-top:13px;}
.mpxmet + .mpxmet{margin-top:14px;}
/* label row: name at inline-start, figure at inline-end. Logical properties only —
   RTL mirrors itself with no second rule. */
.mpxlab{display:flex; align-items:baseline; gap:10px; font-size:11.5px; color:var(--text-secondary);}
.mpxlabn{font-weight:700; letter-spacing:.03em;}
.mpxlabv{margin-inline-start:auto; display:inline-flex; align-items:baseline; gap:7px;
         font-family:var(--font-mono); font-variant-numeric:tabular-nums;
         font-size:13px; font-weight:700; color:var(--text-primary);
         border-radius:5px; padding:0 3px;
         transition:background-color .85s ease, color .85s ease;}
.mpxlabv.up{color:var(--up);} .mpxlabv.down{color:var(--down);} .mpxlabv.flat{color:var(--warn);}
.mpxsub{margin-top:5px; font-size:10.5px; color:var(--text-tertiary); line-height:1.6;}
/* 🔴 the value flash. A TRANSITION, never a keyframe rule: the node is appended
   already lit and the class is dropped one tick later, so the fade runs on removal
   without adding a fifth keyframe rule to the bundle (the suite pins the set at four
   in five places, and the at-rule name must not appear here even in a comment).
   Skipped outright under reduced motion — see mpxSetVal(). */
.mpxlabv.mpxflash{background-color:rgba(107,159,255,.26); color:var(--text-primary);
                  transition:none;}

/* ── bars. All pure CSS: a div with a width. No canvas, no library. ───────── */
.mpxbar{display:block; height:8px; border-radius:4px; overflow:hidden; margin-top:7px;
        background:rgba(157,169,194,.14);}
.mpxbar > i{display:block; height:100%; border-radius:4px; transition:width .55s cubic-bezier(.2,.8,.3,1);}
/* the buy/sell split: the TRACK is the sell side, the FILL is the buy side. One bar,
   one split — the same two-tone idiom the compact card uses. */
.mpxbar.mpxsplit{height:12px; border-radius:6px;
                 background:linear-gradient(90deg,rgba(243,110,110,.34),rgba(243,110,110,.62));}
.mpxbar.mpxsplit > i{background:linear-gradient(90deg,rgba(59,212,162,.5),var(--up));}
.mpxbar > i.mpxup{background:linear-gradient(90deg,rgba(59,212,162,.45),var(--up));}
.mpxbar > i.mpxdn{background:linear-gradient(90deg,rgba(243,110,110,.45),var(--down));}
.mpxbar > i.mpxnu{background:linear-gradient(90deg,rgba(107,159,255,.38),var(--accent));}

/* the 50% midline tick on a 0–100 progress bar. ::after on the TRACK, positioned with
   inset-inline-start so it lands on the visual midpoint in both directions. */
.mpxbar.mpxmid{position:relative; overflow:visible;}
.mpxbar.mpxmid > i{position:relative; z-index:0;}
/* the midline is at 50%, so physical vs logical is the same pixel in both
   directions — `left` is used because it needs no fallback anywhere. */
.mpxbar.mpxmid::after{content:""; position:absolute; top:-3px; bottom:-3px;
                      left:calc(50% - 1px); width:2px; z-index:1;
                      background:rgba(234,238,247,.42); border-radius:1px;}

/* the diverging net-flow bar. 🔴 dir=ltr is FORCED on the wrapper: the reader of a
   diverging chart must find "+" on the same side in both languages — this is a
   chart axis, not prose, exactly like every figure on the page being dir=ltr. */
.mpxdiv{display:flex; align-items:stretch; height:12px; margin-top:7px;}
.mpxdivh{flex:1 1 0; display:flex; min-width:0; background:rgba(157,169,194,.12);}
.mpxdivh.l{justify-content:flex-end; border-radius:6px 0 0 6px;}
.mpxdivh.r{justify-content:flex-start; border-radius:0 6px 6px 0;}
.mpxdivh > i{display:block; height:100%; transition:width .55s cubic-bezier(.2,.8,.3,1);}
.mpxdivh.l > i{background:linear-gradient(270deg,rgba(243,110,110,.45),var(--down)); border-radius:6px 0 0 6px;}
.mpxdivh.r > i{background:linear-gradient(90deg,rgba(59,212,162,.45),var(--up)); border-radius:0 6px 6px 0;}
.mpxdivt{flex:0 0 2px; background:rgba(234,238,247,.5);}
.mpxaxis{display:flex; justify-content:space-between; margin-top:4px;
         font-family:var(--font-mono); font-size:9px; color:var(--text-disabled);}

/* the banded gauge (TRIN, $-PCR): three coloured zones + a marker whose POSITION is
   the reading. Zones are painted with one gradient using hard stops, so the band
   edges land exactly on the two boundary constants. */
.mpxg{position:relative; height:10px; border-radius:5px; margin-top:7px; overflow:visible;}
/* the marker is positioned with PHYSICAL left because .mpxg is dir-locked to ltr —
   see mpxGauge(). Everything outside the charts uses logical properties. */
.mpxg > b{position:absolute; top:-4px; bottom:-4px; width:3px; border-radius:2px;
          background:var(--text-primary); box-shadow:0 0 0 2px var(--bg-surface);
          transition:left .55s cubic-bezier(.2,.8,.3,1);}
.mpxgt{display:flex; margin-top:4px; font-family:var(--font-mono); font-size:9px;
       color:var(--text-disabled);}
.mpxgt span{position:relative;}
.mpxgz{display:flex; gap:10px; margin-top:6px; font-size:10px; color:var(--text-tertiary);
       flex-wrap:wrap;}
.mpxgz i{font-style:normal; display:inline-flex; align-items:center; gap:4px;}
.mpxgz i::before{content:""; width:8px; height:8px; border-radius:2px; background:currentColor;
                 opacity:.65;}
.mpxgz i.z1{color:var(--up);} .mpxgz i.z2{color:var(--warn);} .mpxgz i.z3{color:var(--down);}
.mpxgz i.mpxon{color:var(--text-primary); font-weight:700;}
.mpxgz i.mpxon.z1{color:var(--up);} .mpxgz i.mpxon.z2{color:var(--warn);} .mpxgz i.mpxon.z3{color:var(--down);}

/* ── the clocks ───────────────────────────────────────────────────────────── */
.mpxclk{display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; margin-top:9px;
        font-size:11.5px; color:var(--text-secondary);}
.mpxclkn{font-weight:700; letter-spacing:.03em; flex:0 0 auto;}
.mpxclkt{margin-inline-start:auto; font-family:var(--font-mono); font-variant-numeric:tabular-nums;
         font-size:12px; color:var(--text-primary);}
.mpxclkr{font-size:10.5px; color:var(--text-tertiary);}
.mpxsc{font-size:8.5px; font-weight:800; letter-spacing:.05em; border-radius:999px;
       padding:1px 7px; border:1px solid; white-space:nowrap;}
/* THREE states, and only the middle one is red. "old because the session is closed"
   is a FACT about the calendar, not a fault, and painting it red teaches the
   subscriber to distrust a correct number. */
.mpxsc.ok{color:var(--up); background:rgba(59,212,162,.13); border-color:rgba(59,212,162,.38);}
.mpxsc.bad{color:var(--down); background:rgba(243,110,110,.13); border-color:rgba(243,110,110,.40);}
.mpxsc.shut{color:var(--text-tertiary); background:rgba(157,169,194,.10); border-color:rgba(157,169,194,.26);}

@media (max-width:620px){
  .mpxlab{flex-wrap:wrap;}
  .mpxlabv{margin-inline-start:auto;}
  .mpxclkt{margin-inline-start:0;}
}

/* ── legend + footer ──────────────────────────────────────────────────── */
.legend{margin-top:14px; font-size:12px; color:var(--text-tertiary); line-height:1.7;}
.legend .ast{color:var(--warn); font-weight:700;}
.foot{margin-top:26px; border-top:1px solid var(--line); padding-top:16px;
      color:var(--text-tertiary); font-size:11.5px; line-height:1.8;}

/* ── sign-in gate ─────────────────────────────────────────────────────── */
#relay-gate{position:fixed; inset:0; z-index:60; display:none; align-items:center; justify-content:center;
            padding:24px; background:radial-gradient(1200px 600px at 50% -10%,rgba(107,159,255,.08),transparent),
            var(--bg-base);}
#relay-gate.on{display:flex;}
.gate{width:100%; max-width:392px; background:var(--bg-surface); border:1px solid var(--line);
      border-radius:16px; padding:26px 24px 22px; box-shadow:0 24px 60px rgba(0,0,0,.55);}
.gate .gbrand{font-weight:800; letter-spacing:.14em;
              font-size:15px; direction:ltr; text-align:center; display:block;}
.gate .gbrand em{font-style:normal; background:var(--aurora); -webkit-background-clip:text;
                 background-clip:text; color:transparent;}
.gate .gsub{display:block; text-align:center; color:var(--text-tertiary); font-size:12px; margin-top:7px;}
.gate .glang{display:flex; justify-content:center; margin:16px 0 4px;}
.gfield{margin-top:14px;}
.gfield label{display:block; font-size:11.5px; font-weight:600; color:var(--text-secondary); margin-bottom:6px;}
.gfield input{width:100%; font-family:var(--font-sans); font-size:14px; color:var(--text-primary);
              background:var(--bg-deeper); border:1px solid var(--line); border-radius:9px;
              padding:10px 12px; direction:ltr; text-align:start;}
.gfield input:focus{border-color:var(--accent); outline:none; box-shadow:0 0 0 3px var(--accent-bg);}
.gbtn{width:100%; margin-top:18px; font-family:var(--font-sans); font-size:14px; font-weight:700;
      color:#08111F; background:var(--accent-2); border:0; border-radius:9px; padding:11px 14px;
      cursor:pointer; transition:filter .15s;}
.gbtn:hover{filter:brightness(1.08);}
.gbtn[disabled]{filter:grayscale(.6) brightness(.8); cursor:default;}
.gerr{min-height:18px; margin-top:11px; font-size:12px; color:var(--down); line-height:1.5; text-align:center;}
.gerr.info{color:var(--text-tertiary);}
.gnote{margin-top:14px; padding-top:13px; border-top:1px solid var(--line);
       font-size:11px; color:var(--text-tertiary); line-height:1.7; text-align:center;}

/* ── header stack + narrower rails (v3) ───────────────────────────────── */
@media (max-width:900px){
  /* the strip's two slots stop sharing a line: the sector track keeps its own
     horizontal scroll, and the MARKET PULSE card takes a full row beneath it.
     margin-inline (not -end) so the card is inset on BOTH sides in either dir. */
  /* the band already wraps by its own flex-wrap; narrow screens just tighten it */
  .mpanel{gap:5px 12px; padding:8px 10px; margin-inline:20px;}
  .top .wrap{grid-template-columns:1fr; row-gap:11px; justify-items:center;}
  .hz-start{order:2; justify-self:center;}
  .hz-mid{order:1; justify-self:center;}
  .hz-end{order:3; justify-self:center; justify-content:center;}
  .brand{font-size:17px;}
  /* stats first, the search door on its own full-width line beneath, then the chips
     and the premium quartet on its own centred line under them — the stack falls straight out of
     document order, no reordering needed */
  .statsrow{gap:11px;}
  .premium{margin-inline-start:0; width:100%; justify-content:center;}
  .filtersrow > .premium{padding-block:0 14px;}
  .statsrow > .srdoor{flex-basis:100%; max-width:none; margin-inline:0;}
}

/* ── mobile cards ─────────────────────────────────────────────────────── */
@media (max-width:720px){
  table{min-width:0;}
  thead{display:none;}
  /* the card layout makes the row itself a block, so the family accent moves onto the
     row's own inline-start border and the first cell's bar stands down — otherwise the
     accent would mark only the ticker line instead of the whole card. */
  tbody tr{display:block; padding:12px 14px; border-bottom:1px solid var(--line);
           border-inline-start:3px solid var(--fam); padding-inline-start:11px;}
  tbody td{display:block; padding:2px 0; border-bottom:none;}
  /* the tile IS a box now, and a box stacks its own three lines — there is no flex row
     for the card layout to build any more. The box simply spans the card, which gives
     the name far more width than the desktop column's 130px, so on a phone almost every
     name lands on ONE line. */
  .c-tk{display:block;}
  .c-tk::before{display:none;}
  .tkbox{max-width:none;}
  .tkco{max-width:none;}
  .tkfx{max-width:none;}   /* §CLASS FACTS — the line spans the card like the name above it */
  .srcb{max-width:none;}   /* matches .tkbox — the badge is the same box on narrow screens */
  /* no header row in the card layout, so the two un-certified cells name themselves.
     The desktop column's tabular min-width stands down here — there is no column to hold
     open, and a 132px floor on an inline-block would print a gap after the word. */
  .c-int,.c-dir{display:inline-block; margin-inline-end:14px; margin-top:4px; min-width:0;}
  .c-int::before,.c-dir::before{content:attr(data-label) " "; color:var(--text-tertiary);
                                font-size:10.5px; font-weight:600;}
  .c-why{max-width:none; margin-top:6px;}
  .c-tm{text-align:start; margin-top:6px;}
  .rel{display:inline; margin-inline-start:8px;}
  .who{max-width:150px;}
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation:none !important; transition:none !important;}
}

/* ============================================================================
   sub.alert.v3 — THE EXTREME TIER
   Colour by CLASS, never an inline style, exactly as the interest tiers are: a lane
   that could be recoloured from JS is a lane that could be made to look like the
   other one. No animation and no transition is added here — the motion ceiling
   (four keyframes, one infinite) is asserted in selftest.js and this section keeps it.
   ============================================================================ */
.xbadge{display:inline-block; margin-inline-start:7px; font-size:9.5px; font-weight:800;
        letter-spacing:.05em; border-radius:999px; padding:1px 8px; border:1px solid;
        vertical-align:middle; white-space:nowrap;}
.x-chase{color:var(--xchase); border-color:var(--xchase-line); background:var(--xchase-bg);}
.x-early{color:var(--xearly); border-color:var(--xearly-line); background:var(--xearly-bg);}
/* 🔴 L3 — the honest label leads the WHY cell, at full contrast. It is not a caption
   and not a footnote: it is the sentence that stops "already moving" from reading as
   "we caught this early". */
.xlabel{display:block; color:var(--text-primary); font-weight:700; font-size:11.5px;
        letter-spacing:.02em; line-height:1.45; margin-bottom:5px;}
/* 🔴 L2 — the printed stop. In the row it is one line; in the ticket the same builder
   adds the reason under it. Never a tooltip, on either surface. */
.xstop{display:inline-flex; align-items:baseline; flex-wrap:wrap; gap:7px; margin-top:6px;
       padding:3px 9px; border:1px solid var(--xstop-line); background:var(--xstop-bg);
       border-radius:8px; color:var(--xstop); font-size:11px; line-height:1.5;}
.xstopw{font-weight:800; letter-spacing:.05em; text-transform:uppercase; font-size:10px;}
.xstoppx{color:var(--text-primary);}
.xstopfrom{color:var(--text-tertiary); font-size:10px;}
.xstopwhy{flex:1 0 100%; color:var(--text-secondary); font-size:11.5px; line-height:1.55;
          margin-top:5px;}
/* the ticket block: its own cleared container between the head and the meta grid */
.tkxwrap:empty{display:none;}
.tkxbox{margin-top:14px; padding:13px 15px 14px; border-radius:12px; border:1px solid;
        background:var(--bg-elevated);}
.tkxbox.x-chase{border-color:var(--xchase-line);}
.tkxbox.x-early{border-color:var(--xearly-line);}
.tkxhead{display:flex; align-items:center; gap:9px; flex-wrap:wrap;}
.tkxhead .xbadge{margin-inline-start:0; font-size:10.5px; padding:2px 10px;}
.tkxlabel{margin-top:9px; color:var(--text-primary); font-weight:700; font-size:13.5px;
          line-height:1.5;}
.tkxbl{margin-top:12px; font-size:10.5px; font-weight:700; letter-spacing:.05em;
       text-transform:uppercase; color:var(--text-tertiary);}
.tkxlegs{margin:6px 0 0; padding-inline-start:18px; color:var(--text-secondary);
         font-size:12.5px; line-height:1.6;}
.tkxprob{display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; margin-top:12px;}
.tkxprobl{font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
          color:var(--text-tertiary);}
.tkxprobv{font-size:15px; font-weight:800; color:var(--text-primary);}
.tkxprobs{flex:1 0 100%; color:var(--text-tertiary); font-size:11px; line-height:1.5;}
/* 🔴 L1 — the cohort block is SEPARATED from the card body by a rule and captioned as
   a cohort. Dimmer than the card's own facts on purpose: it is true of 224 alerts, not
   of this one, and it must never read as the louder claim. */
.tkxco{margin-top:13px; padding-top:11px; border-top:1px dashed var(--line);}
.tkxcocap{font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
          color:var(--text-disabled); margin-bottom:6px;}
.tkxco p{margin:0 0 5px; color:var(--text-tertiary); font-size:11.5px; line-height:1.6;}
.tkxco p:last-child{margin-bottom:0;}
@media (max-width:720px){
  .tkxbox{padding:11px 12px 12px;}
  .xstop{width:100%;}
}

/* ── SOURCE LINKS inside a ticket's analysis (2026-09-20) ──────────────────────────────────
   Genuine publisher links are clickable and labelled by DOMAIN, so a paragraph reads
   "…ahead of the summit (scmp.com) and the yen slipped" instead of carrying a 120-character
   tracking URL mid-sentence. Our own Vertex grounding redirects are removed upstream by the
   redactor and, belt-and-braces, dropped by writeProse — they never get one of these. */
.tklw a.srclink {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  padding-bottom: 1px;
  word-break: break-word;
}
.tklw a.srclink:hover,
.tklw a.srclink:focus-visible { border-bottom-color: var(--accent); }
/* the page's one focus ring, not a second convention */
.tklw a.srclink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* ============================================================================
   THE ALERT FILTERS (2026-09-23 — docs/RELAY_ALERT_FILTERS_2026-09-23.md §3)

   One rhythm, no new colour, no new animation. Everything here is built from the
   tokens at :root and from the chip geometry the filter row already had (33px
   tall, 999px radius, --bg-surface on --line), so the panel reads as more of the
   page rather than as a control surface bolted onto it.

   TWO PRESENTATIONS, ONE ELEMENT. `.fpanel` is an inline band under the chips on
   a desktop — the table stays visible, which is the point: a subscriber tuning a
   filter is watching what it does. At ≤720px, where an inline band would push the
   feed off the screen, the SAME element becomes a bottom sheet. The switch is CSS
   alone: no JS breakpoint, no second render path, nothing to fall out of step.

   The panel is NOT a dialog and takes no focus trap. The page owns exactly one
   modal (the alert ticket) and one trap; a second would be two dismiss machines
   that eventually disagree. The panel sits in the document right after the chips
   that open it, so Tab walks into it, and Escape (bound on the panel and on its
   own button) closes it and hands focus back.
   ============================================================================ */

/* the handle. It shipped as "the same chip as its neighbours"; the operator's order of
   2026-09-23 — "shine and be extra visible" — makes it the row's ONE lit control, wearing
   the SAME aurora ring + halo as the header's feedback pill (`.fbbtn`): the two doors the
   operator asked to shine speak one lit vocabulary, never two.
   WHERE IT LIVES (moved 2026-09-23 14:2x ET at the operator's mark): it LEADS the
   applied-filter row (`.fstrip`) under the chips. It had been the last chip of the row
   pushed to the trailing edge by a margin-auto; on a PRO tier the ten family chips fill
   the row and the handle wrapped onto a lonely line at the far edge. Heading the row of
   the tokens it produces gives it one fixed spot whether or not a filter is on. No
   margin-auto any more — it sits at the row's leading edge in `he` and `en` alike.
   The funnel is a clip-path over a background, so the aurora goes straight in as paint.
   The ring is two background layers under a TRANSPARENT border (see `.fbbtn`), so
   `.active` and `.open` repaint the LAYERS — `border-color` paints nothing here — and
   every rule is written at `.fbtn.fbtn-more` specificity so the chip row's own
   `.fbtn.active` can no longer recolour the handle into a family chip. The 2px ring
   is paid for out of the padding (6px), so the chip stays on the row's 33px rhythm.
   The fill is OPAQUE for the reason `.fbbtn` records — a wash turns the ring into a blob.
   No keyframe; the four-keyframe ceiling holds; every offset is logical. */
.fbtn.fbtn-more{display:inline-flex; align-items:center; gap:8px; margin-inline-end:4px;
       font-weight:700; letter-spacing:.01em; color:var(--text-primary);
       border:2px solid transparent; padding:6px 16px; padding-inline-start:13px;
       background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 24%,var(--bg-elevated)) 0%,color-mix(in srgb,var(--info) 24%,var(--bg-elevated)) 55%,color-mix(in srgb,var(--up) 22%,var(--bg-elevated)) 100%) padding-box,
                  var(--aurora) border-box;
       box-shadow:0 0 0 1px rgba(107,159,255,.14), 0 0 18px rgba(107,159,255,.44),
                  0 4px 20px rgba(155,140,255,.26), inset 0 1px 0 rgba(255,255,255,.08);
       transition:transform .15s ease, box-shadow .15s ease, filter .15s ease;}
.fbtn.fbtn-more:hover{color:var(--text-primary); transform:translateY(-1px); filter:brightness(1.08);
       box-shadow:0 0 0 1px rgba(107,159,255,.22), 0 0 26px rgba(107,159,255,.62),
                  0 6px 24px rgba(155,140,255,.34), inset 0 1px 0 rgba(255,255,255,.10);}
.fbtn.fbtn-more:active{transform:none; filter:brightness(.96);}
.fbtn.fbtn-more:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
.flico{width:12px; height:10px; flex:0 0 12px; background:var(--aurora); opacity:1;
       clip-path:polygon(0 0,100% 0,62% 46%,62% 100%,38% 78%,38% 46%);}
/* facets on: the fill steps up one notch and the badge carries the count */
.fbtn.fbtn-more.active{color:var(--text-primary);
       background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 36%,var(--bg-elevated)) 0%,color-mix(in srgb,var(--info) 36%,var(--bg-elevated)) 55%,color-mix(in srgb,var(--up) 32%,var(--bg-elevated)) 100%) padding-box,
                  var(--aurora) border-box;}
/* open: pressed — the fill at its deepest, the halo pulled in */
.fbtn.fbtn-more.open{color:var(--text-primary);
       background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 46%,var(--bg-elevated)) 0%,color-mix(in srgb,var(--info) 46%,var(--bg-elevated)) 55%,color-mix(in srgb,var(--up) 40%,var(--bg-elevated)) 100%) padding-box,
                  var(--aurora) border-box;
       box-shadow:0 0 0 1px rgba(107,159,255,.18), 0 0 12px rgba(107,159,255,.26),
                  inset 0 2px 6px rgba(0,0,0,.28);}
/* the count. Written at the handle's own specificity because the chip row's `.fbtn b`
   and `.fbtn.active b` (0,2,1) outranked a bare `.flbadge` (0,1,0) and painted the digit
   accent-on-accent — the 2026-09-23 harness shot showed a blue disc with no number. */
.fbtn.fbtn-more .flbadge{display:inline-flex; align-items:center; justify-content:center; min-width:18px;
         height:18px; padding:0 5px; border-radius:999px; font-size:10.5px; font-weight:800;
         color:var(--bg-base); background:var(--text-primary); margin-inline-start:0;
         box-shadow:0 0 8px rgba(234,238,247,.35);}
/* the arrivals the filter is holding back. Warm, because it is a caveat about
   what the subscriber is NOT seeing — the same job the delay note's amber does. */
.flpill{display:inline-flex; align-items:center; margin-inline-start:7px; padding:1px 7px;
        border-radius:999px; font-size:10px; font-weight:800; letter-spacing:.02em;
        color:var(--warn); background:var(--warn-bg); border:1px solid rgba(232,176,74,.36);}

/* ── the applied-filter strip ─────────────────────────────────────────────── */
/* the applied-filter row — the handle's home since 2026-09-23 14:2x ET, so it is on
   screen whenever there are chips; the tokens and the reset come and go inside it. */
.fstrip{display:flex; flex-wrap:wrap; align-items:center; gap:7px; padding:0 0 14px;}
.ftok{display:inline-flex; align-items:center; gap:6px; max-width:100%;
      font-size:11.5px; font-weight:600; color:var(--text-secondary);
      background:var(--accent-bg); border:1px solid var(--accent-glow); border-radius:999px;
      padding:4px 6px 4px 11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ftokx,.fsymx{display:inline-flex; align-items:center; justify-content:center; flex:0 0 16px;
              width:16px; height:16px; padding:0; border:0; border-radius:50%; cursor:pointer;
              font-size:13px; line-height:1; color:var(--text-tertiary);
              background:rgba(107,159,255,.14); transition:color .15s, background .15s;}
.ftokx:hover,.fsymx:hover{color:var(--text-primary); background:var(--accent-glow);}
.ftokall{font-family:var(--font-sans); font-size:11.5px; font-weight:600; cursor:pointer;
         color:var(--text-tertiary); background:none; border:0; padding:4px 2px;
         text-decoration:underline; text-underline-offset:3px;}
.ftokall:hover{color:var(--accent-2);}

/* ── the panel ────────────────────────────────────────────────────────────── */
.fpanel{background:var(--bg-surface); border:1px solid var(--line); border-radius:14px;
        margin:0 0 14px; overflow:hidden;}
.flhead{display:flex; align-items:center; justify-content:space-between; gap:12px;
        padding:13px 16px; border-bottom:1px solid var(--line); background:var(--bg-elevated);}
.fltitle{font-size:13px; font-weight:800; letter-spacing:.03em; color:var(--text-primary);}
.flx{font-size:19px; line-height:1; color:var(--text-tertiary); background:none; border:0;
     cursor:pointer; padding:0 4px; transition:color .15s;}
.flx:hover{color:var(--text-primary);}
.flbody{padding:4px 16px 14px;}
.flsec{padding:12px 0; border-bottom:1px solid rgba(107,159,255,.07);}
.flsec:last-child{border-bottom:0;}
.flcap{font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
       color:var(--text-tertiary); margin-bottom:9px;}
.flgrp{margin-bottom:10px;}
.flgrp:last-child{margin-bottom:0;}
.flgrph{background:none; border:0; padding:0 0 6px; cursor:pointer;}
.flgrph .chip{opacity:.62; transition:opacity .15s;}
.flgrph:hover .chip,.flgrph.on .chip{opacity:1;}
.flrow{display:flex; flex-wrap:wrap; gap:7px;}
/* a segmented control is still made of the same chips — it simply has one answer */
.flseg{gap:6px;}
.flchip{font-family:var(--font-sans); font-size:11.5px; font-weight:600; cursor:pointer;
        color:var(--text-secondary); background:var(--bg-deeper);
        border:1px solid var(--line); border-radius:999px; padding:5px 11px;
        transition:border-color .15s, background .15s, color .15s;}
.flchip:hover{border-color:var(--accent-glow); color:var(--text-primary);}
.flchip.on{background:var(--accent-bg); border-color:var(--accent); color:var(--accent-2);}
.flchip b{font-weight:700; color:var(--text-disabled); margin-inline-start:6px;}
.flchip.on b{color:var(--accent);}
/* the two vocabularies keep their OWN colour on the control, so the panel and the
   column can never read as two different ladders. The interest tiers arrive
   wearing `act a1..a4` and are painted by those rules above — nothing is restated
   here, which is what keeps --hot and --crit declared exactly once each. The
   direction words need a compound selector: `.dirc-*` is a single class, `.flchip`
   is a single class written later, and the later one would otherwise win. */
.flchip.dirc-bullish{color:var(--up); border-color:rgba(59,212,162,.5);}
.flchip.dirc-bearish{color:var(--down); border-color:rgba(243,110,110,.5);}
.flchip.dirc-watch{color:var(--warn); border-color:rgba(232,176,74,.5);}
.flchip.dirc-bullish.on{background:rgba(59,212,162,.16);}
.flchip.dirc-bearish.on{background:rgba(243,110,110,.16);}
.flchip.dirc-watch.on{background:var(--warn-bg);}
.flchip.act.on{background:var(--accent-bg); border-color:var(--accent);}
/* the free-text and symbol inputs — the gate's field, at chip scale */
.flin{width:100%; max-width:340px; font-family:var(--font-sans); font-size:13px;
      color:var(--text-primary); background:var(--bg-deeper); border:1px solid var(--line);
      border-radius:9px; padding:8px 11px;}
.flin:focus{border-color:var(--accent); outline:none; box-shadow:0 0 0 3px var(--accent-bg);}
.flsymin{max-width:190px; text-transform:uppercase; direction:ltr; text-align:start;}
.flsyms{display:flex; flex-wrap:wrap; gap:6px; margin-bottom:8px;}
.flsyms:empty{display:none;}
.fsym{display:inline-flex; align-items:center; gap:5px; font-family:var(--font-mono);
      font-size:11.5px; font-weight:700; color:var(--text-primary);
      background:var(--accent-bg); border:1px solid var(--accent-glow); border-radius:7px;
      padding:3px 4px 3px 9px;}
.flhint{margin-top:7px; font-size:11px; line-height:1.6; color:var(--text-tertiary);}
.flfoot{display:flex; align-items:center; flex-wrap:wrap; gap:10px 14px;
        padding:11px 16px; border-top:1px solid var(--line); background:var(--bg-elevated);}
.flshow{font-size:12px; font-weight:700; color:var(--text-primary);}
.flreset{font-family:var(--font-sans); font-size:12px; font-weight:600; cursor:pointer;
         color:var(--text-secondary); background:var(--bg-surface);
         border:1px solid var(--line); border-radius:999px; padding:6px 13px;
         transition:border-color .15s, color .15s;}
.flreset:hover{border-color:var(--accent-glow); color:var(--text-primary);}
.flsync{margin-inline-start:auto; font-size:10.5px; color:var(--text-tertiary);}

/* ── the empty state, and the filtered stats line ─────────────────────────── */
.emptyhd{font-size:13.5px; font-weight:700; color:var(--text-primary); margin-bottom:6px;}
.emptysub{font-size:12px; line-height:1.7; color:var(--text-tertiary); margin-bottom:4px;}
.emptyrow .flreset{margin-top:10px;}
.stof{color:var(--text-tertiary); font-weight:600;}

/* ── ≤720px: the same panel, as a bottom sheet ────────────────────────────── */
@media (max-width:720px){
  .fpanel{position:fixed; inset-inline:0; bottom:0; z-index:40; margin:0;
          border-radius:16px 16px 0 0; border-inline:0; border-bottom:0;
          max-height:78vh; overflow-y:auto; -webkit-overflow-scrolling:touch;
          box-shadow:0 -18px 44px rgba(0,0,0,.55);}
  .flhead{position:sticky; top:0; z-index:1;}
  .flin{max-width:100%;}
  .flsymin{max-width:100%;}
  .flfoot{position:sticky; bottom:0;}
  .flsync{width:100%; margin-inline-start:0;}
}

/* ── §OPINION — DAILY ANALYST OPINION (2026-09-24) ───────────────────────────────
   The door sits right after the filters handle in `.fstrip` and belongs to the same
   family (a lit pill with a halo, primary text at 700) one notch quieter and in the
   editorial violet — NOT the aurora ring, which is reserved for the two doors (§31) — so
   the filters handle stays the loudest control on the row. The page reuses the feedback page's frame at an
   editorial measure: 17.5px body, 1.6 leading, ~72ch. Every offset is logical, so the
   page mirrors in `he` without one directional rule. No keyframe; tokens only. */
.opbtn{position:relative; display:inline-flex; align-items:center; gap:8px;
       font-family:var(--font-sans); font-size:13px; font-weight:700; letter-spacing:.01em;
       color:var(--text-primary); cursor:pointer; white-space:nowrap;
       border:1px solid rgba(155,140,255,.46); border-radius:999px; padding:6px 14px; padding-inline-start:12px;
       background:color-mix(in srgb,var(--info) 12%,var(--bg-elevated));
       box-shadow:0 0 0 1px rgba(155,140,255,.10), 0 0 12px rgba(155,140,255,.20);
       transition:transform .15s ease, box-shadow .15s ease, filter .15s ease;}
.opbtn:hover{transform:translateY(-1px); filter:brightness(1.1);
       box-shadow:0 0 0 1px rgba(155,140,255,.18), 0 0 18px rgba(155,140,255,.36);}
.opbtn:active{transform:none; filter:brightness(.96);}
.opbtn:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
/* a folded page: two ruled lines on a card */
.opico{width:11px; height:12px; flex:0 0 11px; border:1.5px solid var(--accent-2); border-radius:2px;
       background:linear-gradient(var(--accent-2),var(--accent-2)) center 3px/5px 1.5px no-repeat,
                  linear-gradient(var(--accent-2),var(--accent-2)) center 6.5px/5px 1.5px no-repeat;}
.opbtn .tag{display:inline-flex; align-items:center; padding:1px 7px; border-radius:999px;
       font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
       color:var(--info); background:var(--info-bg); border:1px solid rgba(155,140,255,.40);}
/* "new today" — a still dot on the handle's leading-top corner, no animation */
.opdot{position:absolute; top:-3px; inset-inline-end:-3px; width:9px; height:9px; border-radius:50%;
       background:var(--up); box-shadow:0 0 0 2px var(--bg-base), 0 0 8px rgba(59,212,162,.6);}

.oppage{padding:36px 20px 72px; display:flex; justify-content:center;}
.opcard{width:100%; max-width:72ch; font-family:var(--font-sans);}
.opback{display:inline-flex; align-items:center; gap:7px; font-family:var(--font-sans);
        font-size:12.5px; font-weight:600; color:var(--text-secondary); background:var(--bg-surface);
        border:1px solid var(--line); border-radius:999px; padding:5px 13px; margin:0 0 24px; cursor:pointer;}
/* the chevron is a TEXT node (U+2039, Bidi_Mirrored): the text renderer mirrors it in the
   RTL page, so it points to the inline start in en and he with no [dir] rule in this sheet */
.opback .opchev{font-size:17px; line-height:1; margin-top:-2px;}
.opback:hover{color:var(--accent-2); border-color:var(--accent-glow);}
.opback:focus-visible{outline:2px solid var(--accent); outline-offset:3px;}
.opkicker{font-size:11.5px; font-weight:800; letter-spacing:.14em; color:var(--info);
          margin:0 0 10px;}
.opmeta{display:flex; flex-wrap:wrap; align-items:center; gap:4px 9px; font-size:13px;
        color:var(--text-tertiary); margin:0 0 16px;}
.opsep{color:var(--text-disabled);}
.optitle{font-size:32px; font-weight:800; line-height:1.22; letter-spacing:-.01em;
         color:var(--text-primary); margin:0 0 14px; outline:none;}
.opdek{font-size:19px; line-height:1.55; color:var(--text-secondary); margin:0 0 30px;
       padding-bottom:26px; border-bottom:1px solid var(--line);}
.opbody{font-size:17.5px; line-height:1.6; color:var(--text-primary);}
.opbody h2{font-size:21px; font-weight:800; line-height:1.3; color:var(--text-primary);
           margin:34px 0 12px;}
.opbody h2:first-child{margin-top:0;}
.opbody p{margin:0 0 16px;}
.opbody .oplead{font-weight:700; color:var(--accent-2); margin:20px 0 10px;}
.opbody ul,.opbody ol{margin:0 0 18px; padding-inline-start:26px;}
.opbody li{margin:0 0 10px; padding-inline-start:4px;}
.opbody li::marker{color:var(--accent-2); font-weight:700;}
.opbasis{font-size:13.5px; line-height:1.6; font-style:italic; color:var(--text-tertiary);
         margin:30px 0 0; padding-top:18px; border-top:1px solid var(--line);}
/* RISK WARNING (user order 2026-09-24 19:05 ET, via the supervisor: "amplify the disclaimer,
   make it more harsh and much more visible and alerting"). The muted .opdisc footer is gone.
   Two surfaces, one danger palette (--down is the page's only red; --crit-* belongs to the
   critical severity rows and must not be borrowed): a STRIP directly under the dek, read
   before the first paragraph, and a full-width BLOCK at the end — 2px danger border plus a
   glyph + bold uppercase label, body in near-white, never italic. 19:1x ET addendum after the
   user saw the live footer ("way too grey, we need it much more visible"): the red family is
   the user's, declared once as the --risk-* tokens on :root (the sheet's no-raw-hex pin) and
   used nowhere else, so no theme change can grey it again. Logical offsets only (the §OPINION
   pin); the glyph is a text node. */
.opstrip{display:flex; align-items:center; gap:10px; font-size:14px; font-weight:700;
         line-height:1.45; color:var(--risk-strip-text); background:var(--risk-strip-bg);
         border:1.5px solid var(--risk-strip-line); border-inline-start:4px solid var(--risk);
         border-radius:8px; padding:10px 14px; margin:-6px 0 30px;}
.opstrip .opwarnglyph{color:var(--risk); font-size:18px; line-height:1;}
.opwarn{display:block; box-sizing:border-box; width:100%; margin:20px 0 0; padding:18px 20px;
        color:var(--risk-body); background:var(--risk-bg);
        border:2px solid var(--risk); box-shadow:inset 0 0 0 1px var(--risk-ring);
        border-radius:12px; font-style:normal;}
.opwarnhead{display:flex; align-items:center; gap:10px; margin:0 0 9px;}
.opwarnglyph{display:inline-block; flex:0 0 auto; font-size:20px; line-height:1; color:var(--risk);
             font-variant-emoji:text;}
.opwarnlabel{font-size:13px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
             color:var(--risk-label);}
.opwarnbody{margin:0; font-size:15px; line-height:1.6; font-weight:500; color:var(--risk-body);
            font-style:normal;}
.opempty{font-size:17px; line-height:1.6; color:var(--text-secondary); margin:8px 0 0;}
/* Hebrew has no capitals to space out and no true italic: the page's `lang` drives both */
.oppage:lang(he) .opkicker{letter-spacing:.02em;}
.oppage:lang(he) .opbasis{font-style:normal;}
.oppage:lang(he) .opwarnlabel{letter-spacing:.02em;}

@media (max-width:560px){
  .oppage{padding:22px 16px 56px;}
  .optitle{font-size:25px;}
  .opdek{font-size:17px; margin-bottom:24px; padding-bottom:20px;}
  .opbody{font-size:17px;}
  .opbody h2{font-size:19px; margin-top:28px;}
  .opbody ul,.opbody ol{padding-inline-start:22px;}
  .opstrip{font-size:13.5px; padding:9px 12px; margin:-4px 0 24px;}
  .opwarn{padding:16px 15px;}
  .opwarnbody{font-size:14.5px;}
}


/* ============================================================================
   §APPV2 — APP PLAN V2 (2026-09-28): the chip modes, the locked families, the language list,
   search + history, the opinion's previous days, the admin-only block. Tokens only (no raw hex),
   logical offsets only, no keyframe and no new animation. The phone's rules for these nodes live
   inside the last ≤720px block (§PHONE), beside the scan card they share the screen with.
   ============================================================================ */
/* the chip row's MODE switch — the sentence the chips complete ("Hide:" / "Show only:") */
.fbtn.fmode{display:inline-flex; align-items:center; gap:6px; color:var(--text-primary); font-weight:700;
            background:var(--bg-elevated); border-style:dashed;}
.fbtn.fmode .fmico{font-size:14px; line-height:1; color:var(--accent-2);}
.fbtn.fmode[data-mode="only"]{border-style:solid; border-color:var(--accent-glow);}
/* a HIDDEN family (Hide mode, ticked): struck through and dimmed — out of the view, one tap from back */
.fbtn.hid{color:var(--text-tertiary); background:var(--bg-deeper); border-style:dashed;
          text-decoration:line-through; text-decoration-thickness:1.5px;}
.fbtn.hid b{color:var(--text-disabled);}
.fbtn[aria-disabled="true"]{cursor:not-allowed;}
/* a LOCKED family's chip: the premium quartet's padlock, muted — information, never a filter */
.fbtn.flock{display:inline-flex; align-items:center; gap:7px; color:var(--text-tertiary);
            background:var(--bg-deeper); border-style:dashed;}
.fbtn.flock .plock{margin-top:3px;}
.fbtn.flock:hover{color:var(--text-secondary);}
/* the lock sheet — a state of the one modal, sized to its words */
.tkwrap .tk.tklock{max-width:min(460px, 94vw);}
.tklock .tkhd .tksym{display:inline-flex; align-items:center; gap:10px; font-family:var(--font-sans); font-size:19px;}
.lkbody{margin:0 0 10px; font-size:15.5px; line-height:1.6; color:var(--text-primary);}
.lknote{margin:0; font-size:13.5px; line-height:1.6; color:var(--text-secondary);}
/* BOTH (English + Hebrew on every card): the card's Hebrew under its English, right-to-left */
.whyhe{display:block; margin-top:7px; padding-top:7px; border-top:1px dashed var(--line); text-align:start;}
.whyhe .trtag{margin-top:4px;}
/* the language LIST in the account sheet: one row per choice, the chosen one checked */
.aclist{flex-direction:column; gap:8px;}
.aclist .acopt{display:flex; align-items:center; gap:10px; width:100%; min-height:48px; padding-block:0;
               padding-inline:14px; text-align:start; font-family:var(--font-sans); font-size:15px; font-weight:700;
               color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
               border-radius:12px; cursor:pointer;}
.aclist .acoptn{flex:0 0 auto;}
.aclist .acopts{flex:1 1 auto; min-width:0; font-size:12.5px; font-weight:500; color:var(--text-tertiary);}
.aclist .acck{flex:0 0 18px; width:18px; height:18px; margin-inline-start:auto; border-radius:50%;
              border:1.5px solid var(--line); box-sizing:border-box;}
.aclist .acopt.on{border-color:var(--accent); background:var(--accent-bg);}
.aclist .acopt.on .acck{border-color:var(--accent); background:radial-gradient(circle,var(--accent) 0 4px,transparent 4.5px);}
/* ADMIN ONLY — the relay strips it for every other role; the page draws it for an admin only */
.tkadm{margin-top:18px; padding:12px 14px; border:1px dashed var(--warn); border-radius:10px; background:var(--warn-bg);}
.tkadm .tklname{color:var(--warn);}
.tkadmr{display:flex; gap:10px; margin-top:6px; font-size:13px; line-height:1.5; color:var(--text-primary);}
.tkadmk{flex:0 0 auto; min-width:110px; font-size:12px; color:var(--text-tertiary);}
.tkadmv{min-width:0; overflow-wrap:anywhere;}
.tkadmmiss{color:var(--warn); font-weight:700;}
/* the SEARCH door: a pill leading the desktop header's end rail (the phone's is an icon in .ph) */
.srbtn{display:inline-flex; align-items:center; gap:8px; font-family:var(--font-sans); font-size:12.5px;
       font-weight:600; color:var(--text-secondary); background:var(--bg-surface); border:1px solid var(--line);
       border-radius:999px; padding-block:5px; padding-inline:11px 14px; cursor:pointer; transition:all .15s;}
.srbtn:hover{color:var(--text-primary); border-color:var(--accent-glow);}
/* the end rail must not wrap for a long e-mail or the wider Hebrew words: under 1400px the door is the
   glass alone (its accessible name and title still say "Search alerts and opinions") */
@media (max-width:1399px){
  .srbtn{padding-inline:9px;}
  .srbtn span{display:none;}
}
.srbtn:focus-visible,.phsr:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
/* the magnifier: a ring and a handle, no asset; the handle is placed by a translate from the ring's
   centre, so it points the same way on the Hebrew page (a search glass is not a direction) */
.srico{position:relative; display:inline-block; flex:0 0 auto; width:12px; height:12px; box-sizing:border-box;
       border:2px solid currentColor; border-radius:50%;}
.srico::after{content:""; position:absolute; inset:0; margin:auto; width:2px; height:6px; border-radius:1px;
              background:currentColor; transform:translate(5px,5px) rotate(-45deg);}
/* the stats-row DOOR (user 2026-09-28 20:4x ET: "the search tab so a user can search for a stock or a key
   word - place it where ive marked it"): a field in the header Search pill's family — the same height
   (30px, the pill with its word, as it stands from 1400px), the 1px line, the elevated fill, the accent
   focus ring, the same magnifier inside — centred in the row's free space. A door, not a second search
   (app.js §SEARCH): a click, a keystroke or Enter opens the search page, which draws everything (focus
   alone opens nothing — fix round 1, WCAG 3.2.1). Desktop and tablet only; the
   phone keeps its header icon and hides this (§PHONE). */
.srdoor{flex:1 1 300px; max-width:440px; min-width:0; margin-block:0; margin-inline:auto; display:flex;
        align-items:center; gap:8px; padding-inline:11px 14px; color:var(--text-tertiary);
        background:var(--bg-elevated); border:1px solid var(--line); border-radius:999px; cursor:text;
        transition:border-color .15s;}
.srdoor:hover{border-color:var(--accent-glow);}
.srdoor:focus-within{border-color:var(--accent); outline:2px solid var(--accent); outline-offset:2px;}
.srdoorin{flex:1 1 auto; min-width:0; height:28px; margin:0; padding:0; font-family:var(--font-sans); font-size:13px;
          color:var(--text-primary); background:transparent; border:0; outline:none;}
.srdoorin::placeholder{color:var(--text-tertiary); opacity:1;}
.srdoorin::-webkit-search-cancel-button{-webkit-appearance:none; appearance:none;}
/* the SEARCH page — the opinion page's frame, wide enough for the table */
.srpage{padding:28px 20px 72px; display:flex; justify-content:center; font-family:var(--font-sans);}
.srwrap{width:100%; max-width:1180px;}
.srhead{display:flex; align-items:center; gap:12px; margin-bottom:10px;}
.srhead .srback{margin:0; flex:0 0 auto;}
.srbox{flex:1 1 auto; display:flex; align-items:center; gap:10px; min-width:0; max-width:720px;
       padding-inline:14px 4px; color:var(--text-tertiary); background:var(--bg-surface);
       border:1px solid var(--line); border-radius:14px;}
.srbox:focus-within{border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-bg);}
.srin{flex:1 1 auto; min-width:0; height:46px; padding:0; font-family:var(--font-sans); font-size:16px;
      color:var(--text-primary); background:transparent; border:0; outline:none;}
.srin::placeholder{color:var(--text-tertiary);}
.srin::-webkit-search-cancel-button{-webkit-appearance:none; appearance:none;}
.srclr{flex:0 0 auto; width:38px; height:38px; font-size:20px; line-height:1; color:var(--text-tertiary);
       background:none; border:0; border-radius:10px; cursor:pointer;}
.srclr:hover{color:var(--text-primary); background:var(--bg-hover);}
.srlist{list-style:none; max-width:720px; margin:0 0 10px; padding:6px; background:var(--bg-elevated);
        border:1px solid var(--line); border-radius:14px;}
.sropt{display:flex; align-items:center; gap:12px; min-height:44px; padding-inline:12px; border-radius:10px; cursor:pointer;}
.sropt:hover,.sropt.on{background:var(--accent-bg);}
.sropt .srsym{flex:0 0 auto; min-width:64px; font-size:15px; font-weight:800; color:var(--text-primary);}
.sropt .srname{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px;
               color:var(--text-secondary);}
.srhint{margin:4px 2px 14px; font-size:13px; color:var(--text-tertiary);}
.srttl{display:flex; align-items:baseline; flex-wrap:wrap; gap:6px 12px; margin:18px 0 4px; font-size:21px;
       font-weight:800; line-height:1.3; color:var(--text-primary);}
.srttl .srsym{font-size:24px; letter-spacing:.02em;}
.srttl .srco{font-size:15px; font-weight:600; color:var(--text-secondary);}
.srsec{margin-top:18px;}
.srcap{margin:0 0 10px; font-size:11.5px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
       color:var(--text-tertiary);}
.srpage:lang(he) .srcap{letter-spacing:.02em;}
.srnote{display:flex; align-items:center; flex-wrap:wrap; gap:10px; margin:10px 2px; font-size:14px;
        color:var(--text-secondary);}
.srerr{color:var(--warn);}
.srretry,.srmore,.ohmore{font-family:var(--font-sans); font-size:13px; font-weight:700; color:var(--text-primary);
                 background:var(--bg-elevated); border:1px solid var(--line); border-radius:999px;
                 padding-block:6px; padding-inline:14px; cursor:pointer;}
.srmore{display:block; margin:12px auto 0;}
/* the opinions a search found, and the opinion page's PREVIOUS DAYS: one list design */
.srolist,.ohlist{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px;}
.srop,.ohbtn{display:flex; flex-direction:column; align-items:flex-start; gap:3px; width:100%; text-align:start;
             font-family:var(--font-sans); color:var(--text-primary); background:var(--bg-surface);
             border:1px solid var(--line); border-radius:12px; padding-block:11px; padding-inline:14px; cursor:pointer;}
.srop:hover,.ohbtn:hover{border-color:var(--accent-glow);}
.srop:focus-visible,.ohbtn:focus-visible,.srmore:focus-visible,.srretry:focus-visible,.ohmore:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
.srodate,.ohdate{font-size:11.5px; font-weight:700; letter-spacing:.04em; color:var(--info);}
.srotitle,.ohtitle{font-size:15px; font-weight:700; line-height:1.4;}
/* §OPHIST-TOP (user 2026-09-28: "I would prefer the Previous days to be on top, visible, 'inviting' users to
   watch it") — the page reads Back → the PREVIOUS DAYS rail → the article (whose RISK WARNING stays its last
   word), in ONE 72ch column: a grid track, so Back sits at the column's inline start. The rail is an
   accent-tinted panel, not a footer; each row is a door — an inline-start accent bar, the date line (+ the
   LATEST pill on the current piece offered back), the title, and a chevron at the inline END (a text node,
   U+203A, Bidi_Mirrored: no [dir] rule). The newest three show; "Show all N days" opens the rest. */
.oppage{display:grid; grid-template-columns:minmax(0,72ch); justify-content:center; align-content:start;
        font-family:var(--font-sans);}
.oppage > .opback{justify-self:start;}
.ophist{box-sizing:border-box; width:100%; max-width:72ch; margin:0 0 22px; padding-block:14px; padding-inline:16px;
        background:color-mix(in srgb,var(--accent) 6%,var(--bg-surface));
        border:1px solid color-mix(in srgb,var(--accent) 28%,var(--line)); border-radius:14px;
        font-family:var(--font-sans);}
.ohttl{margin:0 0 3px; font-size:13px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--info);}
.oppage:lang(he) .ohttl{letter-spacing:.02em;}
.ohsub{margin:0 0 12px; font-size:13.5px; line-height:1.45; color:var(--text-secondary);}
.ohbtn{display:grid; grid-template-columns:auto minmax(0,1fr) auto; grid-template-areas:"date pill chev" "title title chev";
       align-items:center; column-gap:8px; row-gap:3px; border-inline-start:3px solid var(--accent);}
.ohdate{grid-area:date;}
.ohlatest{grid-area:pill; justify-self:start; font-size:10.5px; font-weight:800; letter-spacing:.06em; line-height:1.5;
          text-transform:uppercase; color:var(--bg-deeper); background:var(--accent); border-radius:999px;
          padding-block:1px; padding-inline:7px;}
.oppage:lang(he) .ohlatest{letter-spacing:.02em;}
.ohtitle{grid-area:title;}
.ohchev{grid-area:chev; align-self:center; margin-inline-start:6px; font-size:22px; line-height:1; color:var(--accent-2);}
.ohbtn:hover,.ohbtn:focus-visible{border-color:var(--accent-glow); border-inline-start-color:var(--accent);
                                  background:color-mix(in srgb,var(--accent) 12%,var(--bg-surface));}
.ohmore{display:block; margin:12px auto 0;}
.ohnote{margin:0; font-size:13.5px; color:var(--text-tertiary);}
.opwait{font-size:17px; line-height:1.6; color:var(--text-secondary); margin:8px 0 0;}

/* ============================================================================
   §PREMIUM SCREENS (operator rulings 2026-10-18) — Smart Money (insider transactions: the daily-close line with
   its BUY / SALE bubbles, the stats panel, the sortable + filterable table) and Professor X (the ask-anything
   analyst), the two premium entries that open for a session whose /v1/me `features` names them; and the SOURCE
   LINE every card now carries. The house's own design language: the page tokens, the search page's frame, the
   opinion page's RISK WARNING block. Tokens only (no raw hex), logical offsets only, no keyframe and no motion;
   the phone's rules ride INSIDE the last ≤720px block (§PHONE).
   ============================================================================ */
/* the open premium door: the locked pill's own face, a chevron where the padlock was */
.pbtn.pbtn-on{padding-inline:14px 12px;}
.pmchev{font-size:17px; line-height:1; margin-top:-2px; color:var(--up);}
/* §SOURCE LINE — under the kind word: quiet, plain text, never a chip and never a link */
.srccls{display:block; margin-top:3px; font-size:10.5px; font-weight:600; letter-spacing:.01em; color:var(--text-tertiary);}
/* the two screens share the search page's frame */
.pmpage{padding:28px 20px 72px; display:flex; justify-content:center; font-family:var(--font-sans);}
.pmwrap{width:100%; max-width:1180px; min-width:0;}
.pxpage .pmwrap{max-width:820px;}
.pmhead{display:grid; grid-template-columns:auto minmax(0,1fr); column-gap:16px; align-items:start; margin:0 0 18px;}
.pmhead .pmback{grid-row:1 / span 3; margin:6px 0 0;}
.pmkick{margin:0; font-size:11.5px; font-weight:800; letter-spacing:.14em; color:var(--up);}
.pmttl{margin:2px 0 4px; font-size:28px; font-weight:800; line-height:1.2; letter-spacing:-.01em; color:var(--text-primary); outline:none;}
.pmsub{margin:0; max-width:72ch; font-size:14.5px; line-height:1.5; color:var(--text-secondary);}
.pmpage:lang(he) .pmkick{letter-spacing:.02em;}
.pmpage .srnote{margin:14px 2px;}
/* ── Smart Money ── */
.smbox{max-width:560px;}
.smlist{max-width:560px;}
.smhint{margin:8px 2px 0;}
.smh2{margin:22px 0 4px; font-size:19px; font-weight:800; line-height:1.3; color:var(--text-primary);}
.smlede{margin:0 0 4px; font-size:14px; line-height:1.5; color:var(--text-secondary);}
.smtkhd{display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px 16px; margin:20px 0 12px;}
.smtkttl{display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 12px; min-width:0; margin:0; font-size:21px; font-weight:800;
         color:var(--text-primary);}
.smtkttl .srsym{font-size:26px; letter-spacing:.02em;}
.smtkttl .srco{font-size:15px; font-weight:600; color:var(--text-secondary);}
.smranges{display:flex; flex-wrap:wrap; gap:6px; margin:0 0 14px;}
.smrange{min-width:46px; font-family:var(--font-sans); font-size:12.5px; font-weight:700; color:var(--text-secondary);
         background:var(--bg-surface); border:1px solid var(--line); border-radius:999px; padding-block:6px; padding-inline:12px; cursor:pointer;}
.smrange:hover{color:var(--text-primary); border-color:var(--accent-glow);}
.smrange.on{color:var(--accent-2); background:var(--accent-bg); border-color:var(--accent);}
.smrange:focus-visible,.smsort:focus-visible,.smtog:focus-visible,.smtkbtn:focus-visible,.pxask:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
.smgrid{display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:14px; align-items:stretch;}
.smcard{min-width:0; background:var(--bg-surface); border:1px solid var(--line); border-radius:14px; padding-block:14px; padding-inline:16px;}
.smcap{margin:0 0 8px;}
.smsvg{width:100%; min-width:0;}
.smsvgc{display:block; max-width:100%; height:auto; direction:ltr;}
.smgl{stroke:var(--line); stroke-width:1;}
.smtl{fill:var(--text-tertiary); font-family:var(--font-mono); font-size:10.5px;}
.smarea{fill:var(--accent-bg); stroke:none;}
.smline{fill:none; stroke:var(--accent); stroke-width:1.6; stroke-linejoin:round; stroke-linecap:round;}
.smb{stroke-width:1.3; cursor:pointer;}
.smb-buy{fill:color-mix(in srgb,var(--up) 50%,transparent); stroke:var(--up);}
.smb-sell{fill:color-mix(in srgb,var(--down) 50%,transparent); stroke:var(--down);}
.smb-neg{fill:color-mix(in srgb,var(--warn) 10%,transparent); stroke:var(--warn); stroke-dasharray:3 2;}
.smpick{min-height:18px; margin:6px 0 0; font-size:12.5px; line-height:1.45; color:var(--text-primary);}
.smleg{display:flex; flex-wrap:wrap; align-items:center; gap:6px 14px; margin:8px 0 0; font-size:12px; color:var(--text-secondary);}
.smlegi{display:inline-flex; align-items:center; gap:6px;}
.smleg i{display:inline-block; width:10px; height:10px; border-radius:50%;}
.smleg .lg-buy{background:var(--up);}
.smleg .lg-sell{background:var(--down);}
.smleg .lg-neg{border:1.5px dashed var(--warn);}
.smlegsz{color:var(--text-tertiary);}
.smdaily{margin:6px 0 0; font-size:11.5px; color:var(--text-tertiary);}
.smtiles{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px;}
.smtile{min-width:0; background:var(--bg-elevated); border:1px solid var(--line); border-radius:10px; padding-block:10px; padding-inline:12px;}
.smtile.wide{grid-column:1 / -1;}
.smtk{display:block; font-size:11px; font-weight:700; letter-spacing:.03em; line-height:1.3; color:var(--text-tertiary);}
.smtv{display:block; margin-top:4px; font-size:18px; font-weight:800; color:var(--text-primary); white-space:nowrap;}
.smtv.up{color:var(--up);}
.smtv.down{color:var(--down);}
.smtv.warn{color:var(--warn);}
.smasof{margin:10px 0 0; font-size:11.5px; color:var(--text-tertiary);}
/* the filters: one bar, every control labelled */
.smfltbtn{display:none;}
.smflt{display:flex; flex-wrap:wrap; align-items:flex-end; gap:10px 14px; margin:18px 0 6px; padding-block:12px; padding-inline:14px;
       background:var(--bg-surface); border:1px solid var(--line); border-radius:14px;}
.smfl{display:flex; flex-direction:column; gap:4px; min-width:0;}
.smflk{font-size:11px; font-weight:700; letter-spacing:.03em; color:var(--text-tertiary);}
.smsel,.smnum{height:34px; font-family:var(--font-sans); font-size:13px; color:var(--text-primary); background:var(--bg-elevated);
              border:1px solid var(--line); border-radius:8px; padding-inline:10px;}
.smnum{width:120px; font-family:var(--font-mono);}
.smsel:focus,.smnum:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-bg);}
.smseg{display:inline-flex; flex-wrap:wrap; gap:4px;}
.smtog{height:34px; font-family:var(--font-sans); font-size:12.5px; font-weight:700; color:var(--text-secondary); background:var(--bg-elevated);
       border:1px solid var(--line); border-radius:8px; padding-inline:11px; cursor:pointer;}
.smtog.on{color:var(--accent-2); background:var(--accent-bg); border-color:var(--accent);}
.smclr{height:34px; padding-block:0;}
.smcount{margin:6px 2px 8px; font-size:12.5px; color:var(--text-tertiary);}
/* the table: a <div role=table>, so no rule of the feed's table can reach it; it scrolls INSIDE its own box */
.smscroll{overflow-x:auto; background:var(--bg-surface); border:1px solid var(--line); border-radius:12px;}
.smtbl{display:table; width:100%; border-collapse:separate; border-spacing:0; font-size:13px;}
.smtr{display:table-row;}
.smth,.smtd{display:table-cell; vertical-align:middle; text-align:start; white-space:nowrap; border-bottom:1px solid var(--line);}
.smtd{padding-block:9px; padding-inline:8px; color:var(--text-primary);}
/* the desktop lets the three text columns wrap, so the table fits its box at 1280 (the phone keeps them on one line) */
.smtd.smc-name,.smtd.smc-title,.smtd.smc-security{white-space:normal; min-width:80px; line-height:1.35;}
.smth{padding:0; background:var(--bg-elevated);}
.smtr:last-child .smtd{border-bottom:0;}
.smtr:hover .smtd{background:var(--bg-elevated);}
/* the first column holds while the rest scroll */
.smth:first-child,.smtd:first-child{position:sticky; inset-inline-start:0; z-index:1; border-inline-end:1px solid var(--line);}
.smtd:first-child{background:var(--bg-surface);}
.smth:first-child{z-index:2;}
.smsort{display:flex; align-items:center; gap:5px; width:100%; min-height:36px; padding-inline:8px; font-family:var(--font-sans);
        font-size:11.5px; font-weight:700; letter-spacing:.03em; color:var(--text-tertiary); text-align:start; white-space:nowrap;
        background:none; border:0; cursor:pointer;}
.smsort:hover{color:var(--text-primary);}
.smth[aria-sort="ascending"] .smsort,.smth[aria-sort="descending"] .smsort{color:var(--text-primary);}
.smarr{font-size:9px; color:var(--accent-2);}
.smc-shares,.smc-price,.smc-value_usd,.smc-n_trans,.smc-mcap_usd{text-align:end;}
.smth.smc-shares .smsort,.smth.smc-price .smsort,.smth.smc-value_usd .smsort,.smth.smc-n_trans .smsort,.smth.smc-mcap_usd .smsort{justify-content:flex-end;}
.smc-rule_10b5_1,.smc-is_director,.smc-is_ten_pct{text-align:center;}
.smth.smc-rule_10b5_1 .smsort,.smth.smc-is_director .smsort,.smth.smc-is_ten_pct .smsort{justify-content:center;}
.smv{font-weight:600;}
.smup{color:var(--up);}
.smdn{color:var(--down);}
.smdash{color:var(--text-disabled);}
.smdate{color:var(--text-secondary);}
.smcode{display:inline-block; font-size:11px; font-weight:800; line-height:1.4; border:1px solid; border-radius:6px; padding-block:2px; padding-inline:8px;}
.smcd-buy{color:var(--up); border-color:color-mix(in srgb,var(--up) 50%,transparent); background:color-mix(in srgb,var(--up) 16%,transparent);}
.smcd-sell{color:var(--down); border-color:color-mix(in srgb,var(--down) 50%,transparent); background:color-mix(in srgb,var(--down) 16%,transparent);}
.smcd-grant{color:var(--text-secondary); border-color:var(--line); background:var(--bg-elevated);}
.smcd-other{color:var(--text-primary); border-color:var(--line); background:transparent;}
/* the negotiated issuance: the house label, in the warning colour, under the code */
.smnegtag{display:block; max-width:180px; margin-top:4px; font-size:10.5px; font-weight:600; line-height:1.35; white-space:normal; color:var(--warn);}
.smyes{font-weight:800; color:var(--up);}
.smno{color:var(--text-disabled);}
.smtkbtn{display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:1px; padding:0; font-family:var(--font-sans);
         text-align:start; color:var(--text-primary); background:none; border:0; cursor:pointer;}
.smtksym{font-size:14px; font-weight:800; color:var(--accent-2);}
.smtkco{max-width:140px; overflow:hidden; text-overflow:ellipsis; font-size:11px; color:var(--text-tertiary);}
.smtkbtn:hover .smtksym{text-decoration:underline;}
.smmore{display:block; margin:12px auto 0;}
/* ── Professor X ── */
.pxform{display:flex; flex-direction:column; gap:8px; background:var(--bg-surface); border:1px solid var(--line); border-radius:14px;
        padding-block:16px; padding-inline:16px;}
.pxlbl{font-size:12px; font-weight:700; letter-spacing:.03em; color:var(--text-tertiary);}
.pxq{width:100%; min-height:96px; resize:vertical; font-family:var(--font-sans); font-size:16px; line-height:1.5; color:var(--text-primary);
     background:var(--bg-elevated); border:1px solid var(--line); border-radius:10px; padding-block:10px; padding-inline:12px;}
.pxq:focus,.pxtk:focus{outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-bg);}
.pxq::placeholder,.pxtk::placeholder{color:var(--text-tertiary);}
.pxrow{display:flex; flex-wrap:wrap; align-items:flex-end; gap:10px 12px;}
.pxtkf{display:flex; flex-direction:column; gap:4px;}
.pxtk{width:160px; height:40px; font-family:var(--font-mono); font-size:15px; font-weight:700; text-transform:uppercase; color:var(--text-primary);
      background:var(--bg-elevated); border:1px solid var(--line); border-radius:10px; padding-inline:12px;}
.pxask{height:40px; margin-inline-start:auto; padding-inline:24px; font-family:var(--font-sans); font-size:14px; font-weight:800;
       color:var(--bg-deeper); background:var(--up); border:0; border-radius:999px; cursor:pointer;}
.pxask[aria-disabled="true"]{opacity:.55; cursor:progress;}
.pxnote{margin:0; font-size:13px; color:var(--warn);}
.pxout{margin-top:16px;}
.pxthink{display:flex; flex-direction:column; gap:6px; font-size:14.5px; line-height:1.5; color:var(--text-secondary);
         background:var(--bg-surface); border:1px dashed var(--accent-glow); border-radius:12px; padding-block:14px; padding-inline:16px;}
.pxthinkw{font-weight:700; color:var(--accent-2);}
.pxslow{color:var(--text-secondary);}
.pxthinkq{color:var(--text-primary);}
.pxans{background:var(--bg-surface); border:1px solid var(--line); border-radius:14px; padding-block:16px; padding-inline:18px;}
.pxcap{display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 10px; margin:0 0 8px;}
.pxcap .srcap{margin:0;}
.pxabout{font-size:12.5px; color:var(--text-secondary);}
.pxqecho{margin:0 0 12px; font-size:14px; font-weight:700; line-height:1.5; color:var(--text-secondary);}
.pxpara{margin:0 0 12px; font-size:16px; line-height:1.65; white-space:pre-line; color:var(--text-primary);}
.pxans .opwarn{margin-top:14px;}
.pxpage:lang(he) .opwarnlabel{letter-spacing:.02em;}
.pxhist{margin-top:26px;}
.pxhisthd{display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 4px;}
.pxhisthd .srcap{margin:0;}
.pxhistnote{margin:0 0 10px; font-size:12.5px; color:var(--text-tertiary);}

/* ============================================================================
   §WIDTH · §VIEW-AS (operator orders 2026-10-18 10:5x ET)
   WIDTH — the page-width toggle at the stats row's inline end on a plain page (a layout session carries the
   toolbar's twin, styled in §LAYOUT) and `body.wdfull`, this device's full width on a plain page: the header,
   the pulse strip and the feed drop their 1180px cap and keep their own gutters.
   VIEW AS — the admin's selector beside the role pill, the pill's "Viewing as" mark (amber, dashed: a state the
   admin must not forget), and the paused-editing notice. Tokens only, logical offsets only, no keyframe; the
   phone's rules ride inside the last ≤720px block.
   ============================================================================ */
.statsrow:has(> .wdbtn){position:relative;}
.wdbtn{position:absolute; top:13px; inset-inline-end:0; display:inline-flex; align-items:center; justify-content:center;
       width:30px; height:30px; padding:0; color:var(--text-secondary); background:var(--bg-surface);
       border:1px solid var(--line); border-radius:999px; cursor:pointer;}
.wdbtn:hover{color:var(--text-primary); border-color:var(--accent-glow);}
.wdbtn[aria-pressed="true"]{color:var(--accent-2); border-color:var(--accent); background:var(--accent-bg);}
.wdbtn:focus-visible,.vasel:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}
.wdbtn .lyl{display:none;}
/* the icon: two edges and a double arrow — out (to full width) or in (back to standard); drawn, no asset, and
   physical on purpose (direction:ltr), because "wider" points outwards in either language */
.wdi{position:relative; display:inline-block; flex:0 0 auto; width:16px; height:12px; direction:ltr;
     background:linear-gradient(currentColor,currentColor) 0 0/2px 100% no-repeat,
                linear-gradient(currentColor,currentColor) 100% 0/2px 100% no-repeat,
                linear-gradient(currentColor,currentColor) 50% 50%/8px 2px no-repeat;}
.wdi::before,.wdi::after{content:""; position:absolute; top:50%; width:4px; height:4px; margin-top:-3px;
                         border:solid currentColor; border-width:0 0 2px 2px;}
.wdi-out::before{inset-inline-start:3px; transform:rotate(45deg);}
.wdi-out::after{inset-inline-end:3px; transform:rotate(-135deg);}
.wdi-in::before{inset-inline-start:1px; transform:rotate(-135deg);}
.wdi-in::after{inset-inline-end:1px; transform:rotate(45deg);}
body.wdfull .page > .wrap,body.wdfull .top .wrap,body.wdfull .pulserow{max-width:none;}
.vagrp{display:contents;}
.hz-end.hzva .vagrp{display:flex; flex-basis:100%; order:1; justify-content:flex-end; align-items:center; gap:8px;}
.vabox{display:inline-flex; align-items:center; gap:5px; padding-block:2px; padding-inline:8px 3px; white-space:nowrap;
       background:var(--bg-surface); border:1px dashed color-mix(in srgb,var(--warn) 55%,transparent); border-radius:999px;}
.val{font-size:10px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--warn);}
.vasel{font-family:var(--font-sans); font-size:11.5px; font-weight:700; letter-spacing:.04em; color:var(--text-primary);
       background:var(--bg-elevated); border:1px solid var(--line); border-radius:999px;
       padding-block:2px; padding-inline:8px 4px; cursor:pointer; direction:ltr;}
.tier.tierva{direction:inherit; color:var(--warn); background:var(--warn-bg); border-style:dashed;
             border-color:color-mix(in srgb,var(--warn) 55%,transparent);}
.tiervm{font-size:8.5px; font-weight:700; letter-spacing:.06em; opacity:.85; margin-inline-end:5px;}
.note-va{color:var(--warn); background:var(--warn-bg); border-color:color-mix(in srgb,var(--warn) 34%,transparent);}

/* ============================================================================
   §PHONE — THE PHONE LAYER (2026-09-28 · docs/MOBILE_APP_SPEC_2026-09-28.md §1, §2, A–H)
   ≤720px, and ONLY there. Above it every rule in this block is either inside a max-width
   query or a display:none for a node only the phone draws, so the desktop at ≥721px renders
   exactly as it did. ONE renderer: the scan card below is buildRow's own row, cut. Tokens only
   (no raw hex), logical offsets only, no keyframe and no new animation — the one motion (the
   sheet settling back after a short drag) is a transition, which the reduced-motion block
   above switches off with every other.
   SAFE AREAS. The installed iOS app draws under the status bar (black-translucent) and over the
   home indicator. The insets are custom properties so a harness can simulate a notch by setting
   them; in a browser they are env(), and 0 where the screen has no inset.
   ============================================================================ */
:root{--safe-t:env(safe-area-inset-top,0px); --safe-b:env(safe-area-inset-bottom,0px); --nb-h:56px;}
.ph,.mkhead,.nb,.tkgrab,.tkfacts,.tkfoot,.tkpx{display:none;}
/* §BOOK-NAME (Build C) — the Book / All toggle, the name page's head and news line, and the
   symbol's door to it: phone-only nodes too (the desktop keeps the row as its one door) */
.bkseg,.nphd,.npgap,.tknm{display:none;}
/* the offline note: a caveat about how old the list is, in the delay note's amber */
.note-off{color:var(--warn); background:var(--warn-bg); border-color:color-mix(in srgb,var(--warn) 34%,transparent);}
/* the wordmark's Inter is the desktop's; the phone reads Heebo + JetBrains Mono only */
@media (min-width:721px){
  .brand{font-family:'Inter',var(--font-sans);}
  .gate .gbrand{font-family:'Inter',var(--font-sans);}
}
/* the ACCOUNT SHEET's content (a state of the one modal; it exists only while that sheet is up) */
.tkacct .tkhd .tksym{font-family:var(--font-sans); font-size:20px;}
.acsec{margin-top:18px;}
.accap{font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
       color:var(--text-tertiary); margin-bottom:8px;}
.acwho{display:flex; align-items:center; flex-wrap:wrap; gap:8px; font-size:14px; color:var(--text-primary);}
.acmail{overflow-wrap:anywhere;}
.aclang{display:flex; width:100%;}
.aclang button{flex:1 1 0; font-size:14px;}
.acacts{display:flex; flex-direction:column; gap:10px;}
.acbtn{width:100%; min-height:48px; font-family:var(--font-sans); font-size:15px; font-weight:700;
       color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
       border-radius:12px; cursor:pointer;}
.acbtn.acout{color:var(--down); border-color:color-mix(in srgb,var(--down) 40%,transparent);}
.acdisc{padding-top:14px; border-top:1px solid var(--line);}
.acdisct{margin:0; font-size:12.5px; line-height:1.7; color:var(--text-secondary);}

/* ============================================================================
   §LAYOUT — BUILD YOUR OWN VIEW (2026-10-15, operator order 09:2x ET)
   Contract: docs/APP_UI_BUILD_YOUR_OWN_VIEW_2026_10_15.md. EVERY rule in this block is scoped to html.lyv2,
   the class app.js sets only when the flag is on (GET /v1/me `layout_v2`, or ?layout=v2 on a loopback host) —
   with the flag off not one selector here matches, so production renders byte-for-byte as before.
   html.lyg     the GRID mode (any layout but Everything; never the phone's Market screen)
   html.lyfull  the layout's page width is the whole window
   html.lyedit  edit mode (handles, edges, the edit bar)
   html.lyfocus focus mode (the lists take the window)
   html.lyfs    the browser is in full screen
   Logical properties only; tokens only; no new keyframe (the page's motion ceiling is pinned).
   ============================================================================ */

/* ── icons, drawn (no font, no image) ── */
html.lyv2 .lyi{display:inline-block; flex:0 0 auto; position:relative; width:14px; height:14px;}
html.lyv2 .lyi-grid{background:linear-gradient(currentColor,currentColor) 0 0/6px 6px no-repeat,
                               linear-gradient(currentColor,currentColor) 100% 0/6px 6px no-repeat,
                               linear-gradient(currentColor,currentColor) 0 100%/6px 6px no-repeat,
                               linear-gradient(currentColor,currentColor) 100% 100%/6px 6px no-repeat;}
html.lyv2 .lyi-split{border:2px solid currentColor; border-radius:3px;
                     background:linear-gradient(currentColor,currentColor) 50% 0/2px 100% no-repeat;}
html.lyv2 .lyi-focus{border:2px solid currentColor; border-radius:3px;
                     background:linear-gradient(currentColor,currentColor) 50% 2px/6px 2px no-repeat,
                                linear-gradient(currentColor,currentColor) 50% 6px/6px 2px no-repeat;}
html.lyv2 .lyi-fs{background:linear-gradient(currentColor,currentColor) 0 0/5px 2px no-repeat,
                             linear-gradient(currentColor,currentColor) 0 0/2px 5px no-repeat,
                             linear-gradient(currentColor,currentColor) 100% 0/5px 2px no-repeat,
                             linear-gradient(currentColor,currentColor) 100% 0/2px 5px no-repeat,
                             linear-gradient(currentColor,currentColor) 0 100%/5px 2px no-repeat,
                             linear-gradient(currentColor,currentColor) 0 100%/2px 5px no-repeat,
                             linear-gradient(currentColor,currentColor) 100% 100%/5px 2px no-repeat,
                             linear-gradient(currentColor,currentColor) 100% 100%/2px 5px no-repeat;}
html.lyv2 .lyi-fsx{background:linear-gradient(currentColor,currentColor) 0 4px/6px 2px no-repeat,
                              linear-gradient(currentColor,currentColor) 4px 0/2px 6px no-repeat,
                              linear-gradient(currentColor,currentColor) 100% 4px/6px 2px no-repeat,
                              linear-gradient(currentColor,currentColor) calc(100% - 4px) 0/2px 6px no-repeat,
                              linear-gradient(currentColor,currentColor) 0 calc(100% - 4px)/6px 2px no-repeat,
                              linear-gradient(currentColor,currentColor) 4px 100%/2px 6px no-repeat,
                              linear-gradient(currentColor,currentColor) 100% calc(100% - 4px)/6px 2px no-repeat,
                              linear-gradient(currentColor,currentColor) calc(100% - 4px) 100%/2px 6px no-repeat;}
html.lyv2 .lyi-edit{width:14px; height:14px;
                    background:linear-gradient(currentColor,currentColor) 50% 50%/3px 13px no-repeat;
                    transform:rotate(45deg); border-radius:1px;}
html.lyv2 .lyi-grip{width:10px; height:16px; background-image:radial-gradient(circle,currentColor 1.3px,transparent 1.7px);
                    background-size:5px 5px; background-position:0 0;}
html.lyv2 .lyi-chev{width:8px; height:8px; border:solid currentColor; border-width:0 2px 2px 0;
                    transform:translateY(-2px) rotate(45deg);}
html.lyv2 .lycoll .lycl .lyi-chev{transform:translateY(2px) rotate(225deg);}
/* move up / down: an ARROW (a stem under the head), never the collapse chevron's shape */
html.lyv2 .lyi-up,html.lyv2 .lyi-down{width:12px; height:14px; background:linear-gradient(currentColor,currentColor) 50% 50%/2px 12px no-repeat;}
html.lyv2 .lyi-up::after,html.lyv2 .lyi-down::after{content:""; position:absolute; inset-inline-start:2px; width:6px; height:6px;
                                                    border:solid currentColor; border-width:0 2px 2px 0;}
html.lyv2 .lyi-up::after{top:1px; transform:rotate(225deg);}
html.lyv2 .lyi-down::after{bottom:1px; transform:rotate(45deg);}
html.lyv2 .lyi-tune{background:linear-gradient(currentColor,currentColor) 0 2px/100% 2px no-repeat,
                               linear-gradient(currentColor,currentColor) 0 6px/100% 2px no-repeat,
                               linear-gradient(currentColor,currentColor) 0 10px/100% 2px no-repeat,
                               linear-gradient(currentColor,currentColor) 3px 0/2px 5px no-repeat,
                               linear-gradient(currentColor,currentColor) 9px 4px/2px 5px no-repeat,
                               linear-gradient(currentColor,currentColor) 5px 8px/2px 5px no-repeat;}
html.lyv2 .lyi-mute{border:2px solid currentColor; border-radius:50%;
                    background:linear-gradient(45deg,transparent 44%,currentColor 44%,currentColor 58%,transparent 58%);}
html.lyv2 .lyx{display:block; font-size:20px; line-height:1;}

/* ── the toolbar: NATIVE — in the stats row's free space, absolutely placed, so not one pixel of the page moves ── */
html.lyv2 .statsrow{position:relative;}
html.lyv2 .lytb{display:flex; align-items:center; gap:6px; min-width:0;}
html.lyv2 .lytb.lytbn{position:absolute; top:13px; inset-inline-end:0; height:30px;}
html.lyv2 .lytb.lytbn .lytsp,html.lyv2 .lytb.lytbn .lytmu,html.lyv2 .lytb.lytbn .lyted{display:none;}
html.lyv2 .lytb.lytbn .lytfo .lyl,html.lyv2 .lytb.lytbn .lytfs .lyl{display:none;}
html.lyv2 .lytbb{display:inline-flex; align-items:center; gap:7px; height:30px; padding:0 12px;
                 font-family:var(--font-sans); font-size:12.5px; font-weight:700; letter-spacing:.01em;
                 color:var(--text-secondary); background:var(--bg-surface); border:1px solid var(--line);
                 border-radius:999px; cursor:pointer; white-space:nowrap;}
html.lyv2 .lytbb:hover{color:var(--text-primary); border-color:var(--accent-glow);}
html.lyv2 .lytbb[aria-pressed="true"]{color:var(--accent-2); border-color:var(--accent); background:var(--accent-bg);}
html.lyv2 .lytb.lytbn .lytfo,html.lyv2 .lytb.lytbn .lytfs{width:30px; padding:0; justify-content:center;}
/* §WIDTH (2026-10-18) — the width toggle beside full screen: an icon in the native bar, a labelled pill in the grid's */
html.lyv2 .lytb.lytbn .lytwd{width:30px; padding:0; justify-content:center;}
html.lyv2 .lytb.lytbn .lytwd .lyl{display:none;}
/* …and the bar is one button wider, so above 900px (where the search door shares the row) the row keeps the bar's
   footprint free: the door centres in the space before it instead of running under it */
@media (min-width:901px){
  html.lyv2 .statsrow:has(> .lytb.lytbn){padding-inline-end:216px;}
}
/* §VIEW-AS — Edit and Split while an admin views as a tier (editing paused; a press says why) */
html.lyv2 .lytbb[aria-disabled="true"]{opacity:.5; cursor:not-allowed;}
html.lyv2 .lytbb.lyresume{color:var(--accent-2); border-color:var(--accent);
                          box-shadow:0 0 0 1px var(--accent-bg), 0 0 10px var(--accent-glow);}
html.lyv2 .lytl .lyi-chev{width:6px; height:6px; margin-inline-start:1px;}
html.lyv2 .lytl .lyl{max-width:180px; overflow:hidden; text-overflow:ellipsis;}

/* ── GRID mode: the grid, its bar, the frames ── */
html.lyv2.lyg .pulsebar{display:none;}
html.lyv2.lyfull .page > .wrap{max-width:none; padding-inline:16px;}
/* §WIDTH (2026-10-18) — full width is the whole page's: the header and the pulse strip spread with the grid */
html.lyv2.lyfull .top .wrap{max-width:none; padding-inline:16px;}
html.lyv2.lyfull .pulserow{max-width:none;}
html.lyv2 .lypark{display:none;}
html.lyv2 .lygrid{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:16px; align-items:start;
                  padding:14px 0 18px;}
html.lyv2 .lybar{grid-column:1 / -1; display:flex; flex-direction:column; gap:10px; min-width:0;}
html.lyv2 .lybar .lytb{flex-wrap:wrap;}
html.lyv2 .lybar .lytl{margin-inline-end:auto; color:var(--text-primary);}
html.lyv2 .lyw{grid-column:span var(--ly-span,12); min-width:0; position:relative;}
html.lyv2 .lywh{display:none; align-items:center; gap:8px; min-width:0; min-height:36px; padding:0 2px 8px;}
html.lyv2 .lyw[data-k="list"]:not([data-w="feed"]) > .lywh,html.lyv2 .lyw.lycoll > .lywh,html.lyv2.lyedit .lywh{display:flex;}
html.lyv2 .lyw.lycoll > .lywb{display:none;}
html.lyv2 .lyw.lycoll > .lywh{padding:0 12px; border:1px solid var(--line); border-radius:12px; background:var(--bg-surface);}
html.lyv2 .lywt{margin:0; min-width:64px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
                font-size:12px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-secondary);}
html.lyv2 .lyun{flex:0 0 auto; min-width:20px; height:20px; padding:0 6px; border-radius:999px; font-size:11px;
                font-weight:800; line-height:20px; text-align:center; color:var(--bg-base); background:var(--accent-2);}
html.lyv2 .lyw[data-k="list"] > .lywh{flex-wrap:wrap; row-gap:6px;}
html.lyv2 .lywx{display:flex; flex-wrap:wrap; justify-content:flex-end; align-items:center; gap:6px; margin-inline-start:auto; min-width:0;}
html.lyv2 .lygrip,html.lyv2 .lymv,html.lyv2 .lygear,html.lyv2 .lyrm{display:none;}
html.lyv2 .lygrip,html.lyv2 .lymv,html.lyv2 .lycl,html.lyv2 .lygear,html.lyv2 .lyrm{
    flex:0 0 auto; align-items:center; justify-content:center; width:30px; height:30px; padding:0;
    color:var(--text-tertiary); background:none; border:1px solid transparent; border-radius:8px; cursor:pointer;}
html.lyv2 .lycl{display:inline-flex;}
html.lyv2 .lymv[aria-disabled="true"]{opacity:.3; cursor:default;}
html.lyv2 .lygrip:hover,html.lyv2 .lymv:hover,html.lyv2 .lycl:hover,html.lyv2 .lygear:hover,html.lyv2 .lyrm:hover{
    color:var(--text-primary); border-color:var(--line); background:var(--bg-elevated);}
html.lyv2.lyedit .lygrip{display:inline-flex; cursor:grab; touch-action:none;}
html.lyv2.lyedit .lygear,html.lyv2.lyedit .lyrm{display:inline-flex;}
html.lyv2.lyedit .lyw{outline:1px dashed var(--accent-glow); outline-offset:6px; border-radius:10px;}
html.lyv2.lyedit .lyw > .lywb{pointer-events:none; opacity:.82;}
html.lyv2.lyedit .lyw > .lywh{padding:6px 8px; margin-bottom:8px; border-radius:10px;
                              background:color-mix(in srgb,var(--accent) 7%,var(--bg-surface)); border:1px solid var(--line);}
html.lyv2 .lyw.lydrag{opacity:.55; outline:2px dashed var(--accent);}
html.lyv2.lydnd,html.lyv2.lydnd *{cursor:grabbing; user-select:none;}
html.lyv2.lydnd .lyw.lydrag{pointer-events:none;}
html.lyv2 .lyrz{display:none;}
html.lyv2.lyedit .lyrz{display:block; position:absolute; top:0; bottom:0; inset-inline-end:-14px; width:14px;
                       cursor:ew-resize; touch-action:none;}
html.lyv2.lyedit .lyrz::before{content:""; position:absolute; top:50%; inset-inline-start:5px; width:4px; height:44px;
                               margin-top:-22px; border-radius:2px; background:var(--accent-glow);}
html.lyv2.lyedit .lyrz:hover::before,html.lyv2 .lyw.lysizing .lyrz::before{background:var(--accent);}
html.lyv2 .lyrzb{display:none;}
html.lyv2 .lyw.lysizing .lyrzb{display:block; position:absolute; top:50%; inset-inline-end:16px; margin-top:-13px;
                               padding:3px 9px; border-radius:999px; font-size:12px; font-weight:800; white-space:nowrap;
                               color:var(--bg-base); background:var(--accent-2);}
html.lyv2 .lyw[data-h="s"] > .lywb{max-height:320px; overflow:auto;}
html.lyv2 .lyw[data-h="m"] > .lywb{max-height:520px; overflow:auto;}
html.lyv2 .lyw[data-h="l"] > .lywb{max-height:760px; overflow:auto;}
html.lyv2 .lyw[data-h="fill"]{position:sticky; top:12px;}
html.lyv2 .lyw[data-h="fill"] > .lywb{height:calc(100vh - 84px); overflow:auto;}
/* the moved nodes, in a frame: their strip-context margins stand down */
html.lyv2 .lyw .pulsescroll{border:1px solid var(--line); border-radius:14px; background:var(--bg-deeper);}
html.lyv2 .lyw .pulse{padding:12px;}
html.lyv2 .lyw .mpanel{margin:0;}
html.lyv2 .lyw .statsrow{padding:0;}
html.lyv2 .lyw .fstrip{padding:0;}
html.lyv2 .lyw .fpanel{margin:12px 0 0;}
html.lyv2 .lyw .filtersrow > .premium{padding-block:0;}
html.lyv2 .lyw[data-w="opinion"] .opbtn{width:100%; justify-content:center; min-height:44px;}
/* the list widgets: the feed's own box, and its scan-card cut when the widget is narrow (the block at the end) */
html.lyv2 .lyw[data-k="list"] > .lywb{container-type:inline-size; container-name:lyw;}
html.lyv2 .lyp:has(tbody:empty){display:none;}
html.lyv2 .lynote:empty{display:none;}
html.lyv2 .lyempty{margin:0; padding:22px 16px; text-align:center; font-size:13.5px; line-height:1.6;
                   color:var(--text-tertiary); border:1px dashed var(--line); border-radius:14px; background:var(--bg-surface);}
html.lyv2 .lyempty.lylock{color:var(--text-secondary);}
html.lyv2 .lyempty .plock{display:inline-block; margin-inline-end:8px; vertical-align:-2px;}
html.lyv2 .lymore{margin:8px 4px 0; font-size:12px; color:var(--text-tertiary);}
html.lyv2 .lymore:empty{display:none;}
html.lyv2 .lysel{height:30px; max-width:180px; padding:0 8px; font-family:var(--font-sans); font-size:12.5px; font-weight:600;
                 color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line); border-radius:8px;}
html.lyv2 .lyrd{display:inline-flex; align-items:center; height:30px; padding:0 10px; font-family:var(--font-sans);
                font-size:12px; font-weight:700; color:var(--text-tertiary); background:none; border:1px solid var(--line);
                border-radius:8px; cursor:pointer; white-space:nowrap;}
html.lyv2 .lyrd:hover{color:var(--text-primary);}
/* unread · pinned · the inbox's actions — decoration of buildRow's row, never a card of its own */
html.lyv2 tbody tr.lyunr td.c-tm .lyud{display:inline-block; width:8px; height:8px; margin-inline-end:7px; border-radius:50%;
                                        vertical-align:1px; background:var(--accent-2); box-shadow:0 0 6px var(--accent-glow);}
html.lyv2 .lypin{display:inline-block; margin-inline-start:6px; padding:1px 7px; border-radius:999px; font-family:var(--font-sans);
                 font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--warn);
                 background:var(--warn-bg);}
html.lyv2 .lyact{display:flex; flex-wrap:wrap; gap:6px; margin-top:9px;}
html.lyv2 .lyab{display:inline-flex; align-items:center; height:28px; padding:0 10px; font-family:var(--font-sans);
                font-size:11.5px; font-weight:700; color:var(--text-secondary); background:var(--bg-elevated);
                border:1px solid var(--line); border-radius:999px; cursor:pointer; white-space:nowrap;}
html.lyv2 .lyab:hover{color:var(--text-primary); border-color:var(--accent-glow);}
/* My Names' band */
html.lyv2 .lyns{display:flex; align-items:center; gap:6px; overflow-x:auto; overflow-y:hidden; padding:0 0 10px;
                scrollbar-width:none;}
html.lyv2 .lyns::-webkit-scrollbar{display:none;}
html.lyv2 .lync{flex:0 0 auto; display:inline-flex; align-items:center; gap:7px; height:32px; padding:0 12px;
                font-family:var(--font-sans); font-size:12.5px; font-weight:700; color:var(--text-primary);
                background:var(--bg-surface); border:1px solid var(--line); border-radius:999px; cursor:pointer; white-space:nowrap;}
html.lyv2 .lync.on{border-color:var(--accent); background:var(--accent-bg); color:var(--accent-2);}
html.lyv2 .lync.quiet{color:var(--text-tertiary);}
html.lyv2 .lyncs{font-weight:800; letter-spacing:.02em;}
html.lyv2 .lyncn{min-width:18px; height:18px; padding:0 5px; border-radius:999px; font-size:10.5px; line-height:18px;
                 text-align:center; color:var(--bg-base); background:var(--accent-2);}
html.lyv2 .lyadd{flex:0 0 auto; display:inline-flex; align-items:center; gap:0; margin:0; height:32px;
                 border:1px dashed var(--accent-glow); border-radius:999px; overflow:hidden;}
html.lyv2 .lyaddin{width:96px; height:100%; padding-inline:12px 4px; font-family:var(--font-mono); font-size:12.5px;
                   text-transform:uppercase; color:var(--text-primary); background:none; border:0; outline:0;}
html.lyv2 .lyaddin::placeholder{text-transform:none; font-family:var(--font-sans); color:var(--text-tertiary);}
html.lyv2 .lyaddgo{width:32px; height:100%; padding:0; font-size:17px; font-weight:700; color:var(--accent-2);
                   background:var(--accent-bg); border:0; cursor:pointer;}
html.lyv2 .lyadd2{height:40px; border-radius:10px; border-style:solid; width:100%;}
html.lyv2 .lyadd2 .lyaddin{flex:1 1 auto; width:auto;}
html.lyv2 .lyadd2 .lyrb{border-radius:0; height:100%; margin:0;}
/* the edit bar */
html.lyv2 .lyebar{display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding:10px 12px; border-radius:14px;
                  border:1px solid var(--accent-glow); background:color-mix(in srgb,var(--accent) 8%,var(--bg-surface));}
html.lyv2 .lyeh{font-size:11px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:var(--accent-2);}
html.lyv2 .lyname{height:32px; min-width:0; width:200px; padding:0 10px; font-family:var(--font-sans); font-size:13.5px;
                  font-weight:700; color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
                  border-radius:8px;}
html.lyv2 .lyeb,html.lyv2 .lyrb{display:inline-flex; align-items:center; justify-content:center; gap:6px; height:32px;
                                padding:0 12px; font-family:var(--font-sans); font-size:12.5px; font-weight:700;
                                color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
                                border-radius:8px; cursor:pointer; white-space:nowrap;}
html.lyv2 .lyeb:hover,html.lyv2 .lyrb:hover{border-color:var(--accent-glow);}
html.lyv2 .lyrbp{color:var(--bg-base); background:var(--accent-2); border-color:var(--accent-2);}
html.lyv2 .lyrbp[aria-disabled="true"]{color:var(--text-tertiary); background:var(--bg-elevated); border-color:var(--line); cursor:default;}
html.lyv2 .lyebr,html.lyv2 .lyrbr{color:var(--down);}
html.lyv2 .lyseg{display:inline-flex; flex-wrap:wrap; align-items:center; gap:4px;}
html.lyv2 .lysegl{font-size:11.5px; color:var(--text-tertiary); margin-inline-end:4px;}
html.lyv2 .lysb{height:30px; min-width:36px; padding:0 10px; font-family:var(--font-sans); font-size:12.5px; font-weight:700;
                color:var(--text-secondary); background:var(--bg-elevated); border:1px solid var(--line); border-radius:8px; cursor:pointer;}
html.lyv2 .lysb.on{color:var(--accent-2); border-color:var(--accent); background:var(--accent-bg);}
html.lyv2 .lyhint{flex:1 1 100%; margin:2px 0 0; font-size:12px; line-height:1.5; color:var(--text-tertiary);}

/* ── the side drawer ── */
html.lyv2 .lydr{display:none;}
html.lyv2 .lydr.on{display:flex; flex-direction:column; position:fixed; top:0; bottom:0; inset-inline-end:0; z-index:62;
                   width:min(392px,100vw); background:var(--bg-surface); border-inline-start:1px solid var(--line);
                   box-shadow:0 0 48px rgba(0,0,0,.5);}
html.lyv2 .lydrh{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:12px 14px 12px 18px;
                 padding-inline:18px 12px; border-bottom:1px solid var(--line); background:var(--bg-elevated);}
html.lyv2 .lydrt{margin:0; font-size:15px; font-weight:800; color:var(--text-primary);}
html.lyv2 .lydrx{display:inline-flex; align-items:center; justify-content:center; width:36px; height:36px; padding:0;
                 color:var(--text-secondary); background:none; border:1px solid var(--line); border-radius:10px; cursor:pointer;}
html.lyv2 .lydrb{flex:1 1 auto; overflow:auto; padding:4px 18px 24px; overscroll-behavior:contain;}
html.lyv2 .lyds{padding:14px 0 6px; border-bottom:1px solid rgba(107,159,255,.07);}
html.lyv2 .lyds:last-child{border-bottom:0;}
html.lyv2 .lydc{margin:0 0 10px; font-size:10.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase;
                color:var(--text-tertiary);}
html.lyv2 .lydp{margin:6px 0 10px; font-size:12.5px; line-height:1.55; color:var(--text-tertiary);}
html.lyv2 .lydp.lylock{color:var(--warn);}
html.lyv2 .lyrow{display:flex; align-items:center; gap:12px; padding:9px 0; border-bottom:1px solid rgba(107,159,255,.06);}
html.lyv2 .lyrow:last-child{border-bottom:0;}
html.lyv2 .lyrowt{flex:1 1 auto; min-width:0;}
html.lyv2 .lyrowt b{display:block; font-size:13.5px; color:var(--text-primary);}
html.lyv2 .lyrowt span{display:block; margin-top:2px; font-size:11.5px; line-height:1.45; color:var(--text-tertiary);}
html.lyv2 .lyrows{flex:1 1 auto; font-size:14px; color:var(--text-primary);}
html.lyv2 .lyalw{font-size:11.5px; font-weight:700; color:var(--text-tertiary); white-space:nowrap;}
html.lyv2 .lyki{flex:0 0 auto; width:28px; height:28px; border-radius:8px; border:1px solid var(--line); background:var(--bg-elevated);}
html.lyv2 .lyki-list{background:linear-gradient(var(--accent),var(--accent)) 6px 7px/14px 2px no-repeat,
                                linear-gradient(var(--accent),var(--accent)) 6px 12px/14px 2px no-repeat,
                                linear-gradient(var(--accent),var(--accent)) 6px 17px/10px 2px no-repeat,var(--bg-elevated);}
html.lyv2 .lyki-chrome{background:linear-gradient(var(--up),var(--up)) 6px 16px/3px 6px no-repeat,
                                  linear-gradient(var(--up),var(--up)) 11px 11px/3px 11px no-repeat,
                                  linear-gradient(var(--up),var(--up)) 16px 8px/3px 14px no-repeat,var(--bg-elevated);}
html.lyv2 .lyki-control{background:linear-gradient(var(--info),var(--info)) 5px 9px/16px 2px no-repeat,
                                   linear-gradient(var(--info),var(--info)) 5px 15px/16px 2px no-repeat,
                                   linear-gradient(var(--info),var(--info)) 9px 6px/2px 7px no-repeat,
                                   linear-gradient(var(--info),var(--info)) 15px 12px/2px 7px no-repeat,var(--bg-elevated);}
html.lyv2 .lyki-door{background:linear-gradient(var(--warn),var(--warn)) 8px 6px/10px 14px no-repeat,var(--bg-elevated);
                     box-shadow:inset 0 0 0 7px var(--bg-elevated);}
html.lyv2 .lyfld{display:block; margin:0 0 14px;}
html.lyv2 .lyfl{display:block; margin-bottom:6px; font-size:11.5px; font-weight:700; color:var(--text-secondary);}
html.lyv2 .lyin{width:100%; height:38px; padding:0 12px; font-family:var(--font-sans); font-size:14px; color:var(--text-primary);
                background:var(--bg-elevated); border:1px solid var(--line); border-radius:10px;}
html.lyv2 .lysel2{width:100%; max-width:none; height:38px; margin-bottom:6px;}
html.lyv2 .lychk{display:flex; align-items:center; gap:10px; min-height:36px; font-size:13px; color:var(--text-secondary); cursor:pointer;}
html.lyv2 .lychk input{width:18px; height:18px; accent-color:var(--accent);}
html.lyv2 .lyacts{display:flex; flex-wrap:wrap; gap:8px; margin-top:4px;}
html.lyv2 .lycards{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px;}
html.lyv2 .lycard{display:flex; flex-direction:column; gap:6px; min-width:0;}
html.lyv2 .lycard + .lycard{margin-top:0;}
html.lyv2 .lyds > .lycard{margin-bottom:10px;}
html.lyv2 .lycb{display:flex; flex-direction:column; gap:9px; width:100%; padding:10px; text-align:start;
                font-family:var(--font-sans); color:var(--text-primary); background:var(--bg-elevated);
                border:1px solid var(--line); border-radius:12px; cursor:pointer;}
html.lyv2 .lycb:hover{border-color:var(--accent-glow);}
html.lyv2 .lycard.on .lycb{border-color:var(--accent); box-shadow:0 0 0 1px var(--accent), 0 0 14px var(--accent-bg);}
html.lyv2 .lycbt b{display:block; font-size:13.5px; font-weight:800;}
html.lyv2 .lycbt span{display:block; margin-top:3px; font-size:11.5px; line-height:1.45; color:var(--text-tertiary);}
html.lyv2 .lyinuse{display:inline-block; margin-top:6px; font-style:normal; font-size:10px; font-weight:800; letter-spacing:.07em;
                   text-transform:uppercase; color:var(--accent-2);}
html.lyv2 .lycacts{display:flex; gap:6px;}
html.lyv2 .lymini{display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:2px; width:100%; padding:6px;
                  border-radius:8px; background:var(--bg-deeper); border:1px solid var(--line);}
html.lyv2 .lymb{grid-column:span var(--ly-span,12); height:5px; border-radius:2px; background:var(--text-disabled);}
html.lyv2 .lymb-chrome{background:color-mix(in srgb,var(--up) 45%,var(--bg-elevated));}
html.lyv2 .lymb-control{background:color-mix(in srgb,var(--info) 55%,var(--bg-elevated));}
html.lyv2 .lymb-door{background:color-mix(in srgb,var(--warn) 50%,var(--bg-elevated));}
html.lyv2 .lymb-list{height:20px; background:color-mix(in srgb,var(--accent) 40%,var(--bg-elevated));}
html.lyv2 .lyta{display:block; width:100%; min-height:150px; padding:10px 12px; margin:0 0 8px; resize:vertical;
                font-family:var(--font-mono); font-size:11.5px; line-height:1.5; color:var(--text-primary);
                background:var(--bg-deeper); border:1px solid var(--line); border-radius:10px;}
html.lyv2 .lyfilel{position:relative; overflow:hidden;}
html.lyv2 .lyfile{position:absolute; inset:0; opacity:0; cursor:pointer;}
html.lyv2 .lyst{color:var(--text-secondary);}
html.lyv2 .lykeys{display:grid; grid-template-columns:auto 1fr; gap:10px 14px; margin:4px 0 0; align-items:center;}
html.lyv2 .lykeys dt{margin:0;}
html.lyv2 .lykeys dd{margin:0; font-size:13px; color:var(--text-secondary);}
html.lyv2 .lykeys kbd{display:inline-block; min-width:28px; padding:3px 8px; text-align:center; font-family:var(--font-mono);
                      font-size:12px; font-weight:700; color:var(--text-primary); background:var(--bg-elevated);
                      border:1px solid var(--line); border-bottom-width:2px; border-radius:6px;}

/* ── the open card's star · the account sheet's Layout section ── */
html.lyv2 .lyfollow{display:inline-flex; align-items:center; gap:6px; align-self:center; height:30px; padding:0 12px;
                    font-family:var(--font-sans); font-size:12.5px; font-weight:700; color:var(--text-secondary);
                    background:var(--bg-elevated); border:1px solid var(--line); border-radius:999px; cursor:pointer;}
html.lyv2 .lyfollow:hover{color:var(--text-primary); border-color:var(--accent-glow);}
html.lyv2 .lyfollow.on{color:var(--warn); border-color:color-mix(in srgb,var(--warn) 55%,transparent); background:var(--warn-bg);}
html.lyv2 .lystar{font-size:14px; line-height:1;}
html.lyv2 .lyacacts{display:flex; flex-wrap:wrap; gap:8px; margin-top:10px;}

/* ── the onboarding card (no backdrop, never blocking) ── */
html.lyv2 .lyob{position:fixed; inset-inline-end:20px; bottom:20px; z-index:58; width:min(420px,calc(100vw - 32px));
                max-height:calc(100vh - 40px); overflow:auto; background:var(--bg-surface); border:1px solid var(--accent-glow);
                border-radius:16px; box-shadow:0 18px 60px rgba(0,0,0,.55), 0 0 0 1px var(--accent-bg);}
html.lyv2 .lyobh{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:14px 14px 0 18px;
                 padding-inline:18px 14px;}
html.lyv2 .lyobt{margin:0; font-size:15px; font-weight:800; background:var(--aurora); -webkit-background-clip:text;
                 background-clip:text; color:transparent;}
html.lyv2 .lyobs{display:flex; align-items:center; gap:6px; padding:8px 18px 0; font-size:11.5px; color:var(--text-tertiary);}
html.lyv2 .lyobs span{margin-inline-start:6px;}
html.lyv2 .lydot{width:18px; height:4px; border-radius:2px; background:var(--line);}
html.lyv2 .lydot.on{background:var(--accent-2);}
html.lyv2 .lydot.done{background:color-mix(in srgb,var(--accent) 45%,var(--bg-elevated));}
html.lyv2 .lyobb{padding:4px 18px 4px;}
html.lyv2 .lyobq{margin:12px 0 2px; font-size:17px; font-weight:800; color:var(--text-primary);}
html.lyv2 .lyopts{display:flex; flex-direction:column; gap:8px; margin-top:6px;}
html.lyv2 .lyopt{display:flex; align-items:center; min-height:44px; padding:0 14px; font-family:var(--font-sans); font-size:14px;
                 font-weight:700; color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
                 border-radius:12px; cursor:pointer; text-align:start;}
html.lyv2 .lyopt.on{border-color:var(--accent); background:var(--accent-bg);}
html.lyv2 .lycards2{margin-top:6px;}
html.lyv2 .lyobn{display:flex; flex-wrap:wrap; gap:8px; margin-top:8px;}
html.lyv2 .lyobw{margin-top:14px; color:var(--text-secondary);}
html.lyv2 .lyobf{display:flex; justify-content:flex-end; gap:8px; padding:10px 18px 2px;}

/* ── FOCUS mode: the header, the tiles and the strips go; the lists take the window ── */
html.lyv2.lyfocus .top,html.lyv2.lyfocus .pulsebar,html.lyv2.lyfocus .statsrow,
html.lyv2.lyfocus .filtersrow,html.lyv2.lyfocus .fstrip,html.lyv2.lyfocus .lybar{display:none;}
html.lyv2.lyfocus .lyw[data-k="chrome"],html.lyv2.lyfocus .lyw[data-k="control"],html.lyv2.lyfocus .lyw[data-k="door"]{display:none;}
html.lyv2.lyfocus .page > .wrap{max-width:none; padding-inline:16px;}
html.lyv2.lyfocus .page{padding-top:10px; padding-bottom:72px;}
html.lyv2 .lyfbar{display:none;}
html.lyv2.lyfocus .lyfbar{display:flex; position:fixed; bottom:18px; inset-inline-end:18px; z-index:50; gap:6px;}
html.lyv2 .lyfb{display:inline-flex; align-items:center; gap:8px; height:34px; padding:0 14px; font-family:var(--font-sans);
                font-size:12.5px; font-weight:700; color:var(--text-primary); background:color-mix(in srgb,var(--bg-elevated) 92%,transparent);
                border:1px solid var(--accent-glow); border-radius:999px; cursor:pointer; box-shadow:0 6px 24px rgba(0,0,0,.45);}
html.lyv2 .lyfb:not(.lyfbx){width:34px; padding:0; justify-content:center;}
html.lyv2 .lytabs{display:none;}

/* ── the phone (≤720px): one column; list widgets become tabs; ▲ ▼ instead of drag; focus keeps one pill ── */
@media screen and (max-width:720px){
  html.lyv2 .lygrid{grid-template-columns:minmax(0,1fr); gap:10px; padding:10px 0 12px;}
  html.lyv2 .lyw{grid-column:1 / -1;}
  html.lyv2 .lybar .lytb{gap:6px; flex-wrap:nowrap;}
  html.lyv2 .lybar .lytbb{height:44px; min-width:44px; padding:0 12px;}
  html.lyv2 .lybar .lytbb:not(.lytl) .lyl{display:none;}
  html.lyv2 .lybar .lytbb:not(.lytl){width:44px; padding:0; justify-content:center;}
  html.lyv2 .lybar .lytl{min-width:0; flex:1 1 auto; justify-content:flex-start;}
  html.lyv2 .lybar .lytl .lyl{max-width:none;}
  html.lyv2.lyg .lytabs.lyhas{display:flex; grid-column:1 / -1; gap:6px; overflow-x:auto; scrollbar-width:none;
                              margin-bottom:-2px;}
  html.lyv2 .lytabs::-webkit-scrollbar{display:none;}
  html.lyv2 .lytab{flex:0 0 auto; display:inline-flex; align-items:center; gap:7px; height:44px; padding:0 14px;
                   font-family:var(--font-sans); font-size:13.5px; font-weight:700; color:var(--text-tertiary);
                   background:var(--bg-surface); border:1px solid var(--line); border-radius:12px; cursor:pointer; white-space:nowrap;}
  html.lyv2 .lytab.on{color:var(--text-primary); border-color:var(--accent); background:var(--accent-bg);}
  html.lyv2.lyg .lyw.lytabbed:not(.lyon){display:none;}
  html.lyv2 .lyw.lytabbed > .lywh .lywt,html.lyv2 .lyw.lytabbed > .lywh .lyun{display:none;}
  html.lyv2.lyedit .lygrip,html.lyv2.lyedit .lyrz{display:none;}
  html.lyv2.lyedit .lymv{display:inline-flex;}
  /* edit on the phone: the title takes its own line, the five 44px controls the next one */
  html.lyv2.lyedit .lyw > .lywh{flex-wrap:wrap; row-gap:4px;}
  html.lyv2.lyedit .lyw > .lywh .lywt{flex:1 1 100%;}
  html.lyv2.lyedit .lyw > .lywh .lywx{display:none;}
  html.lyv2.lyedit .lyw > .lywh .lymv{margin-inline-start:0;}
  html.lyv2.lyedit .lyw > .lywh .lyup{margin-inline-start:auto;}
  html.lyv2 .lyebar .lyseg{display:none;}
  html.lyv2 .lygrip,html.lyv2 .lymv,html.lyv2 .lycl,html.lyv2 .lygear,html.lyv2 .lyrm{width:44px; height:44px;}
  html.lyv2 .lysel{height:44px;}
  html.lyv2 .lyrd{height:44px;}
  html.lyv2 .lync{height:44px;}
  html.lyv2 .lyadd{height:44px;}
  html.lyv2 .lyab{height:44px; padding:0 12px;}
  html.lyv2 .lyname{width:100%; height:44px;}
  html.lyv2 .lyeb,html.lyv2 .lyrb,html.lyv2 .lysb{height:44px;}
  html.lyv2 .lysb{min-width:44px;}
  html.lyv2 .lyfollow{height:44px;}
  html.lyv2 .lydr.on{top:auto; inset-inline:0; width:auto; max-height:80vh; bottom:calc(var(--nb-h) + var(--safe-b));
                     border-inline-start:0; border-top:1px solid var(--line); border-radius:18px 18px 0 0;}
  html.lyv2 .lydrx{width:44px; height:44px;}
  html.lyv2 .lycards{grid-template-columns:repeat(2,minmax(0,1fr));}
  html.lyv2 .lyob{inset-inline:8px; width:auto; bottom:calc(var(--nb-h) + var(--safe-b) + 8px);
                  max-height:calc(100vh - var(--nb-h) - var(--safe-b) - var(--safe-t) - 70px);}
  html.lyv2.lyfocus .ph,html.lyv2.lyfocus .bkseg,html.lyv2.lyfocus .nb,html.lyv2.lyfocus .filters{display:none;}
  html.lyv2.lyfocus .page{padding-top:var(--safe-t); padding-bottom:calc(var(--safe-b) + 76px);}
  html.lyv2.lyfocus .lyfbar{bottom:calc(var(--safe-b) + 14px); inset-inline-end:12px;}
  html.lyv2 .lyfb{height:44px;}
  html.lyv2 .lyfb:not(.lyfbx){width:44px;}
}
@media screen and (max-width:720px){
  /* the phone scrolls the page, not a widget: a list's height setting stands down there */
  html.lyv2 .lyw[data-k="list"] > .lywb{max-height:none; height:auto; overflow:visible;}
  html.lyv2 .lyw[data-h="fill"]{position:relative; top:auto;}
}

/* §LAYOUT — the NARROW LIST WIDGET is the phone's scan card (2026-10-15). A list widget's body is a size container
   (container-name lyw, grid mode only); under 880px of its OWN width it takes these rules — copied VERBATIM from the
   two phone blocks above (the mobile cards block and the phone layer's SCAN CARD / §STORY rules), each selector is prefixed with .lywb (the widget body) so it outranks the desktop rules at any
   position in the file — so a narrow widget draws the same cut of the same buildRow row the phone draws. Selftest §LY pins every rule here to its phone twin. */
@container lyw (max-width:879px){
  .lywb table { min-width:0; }
  .lywb thead { display:none; }
  .lywb tbody tr { display:block; padding:12px 14px; border-bottom:1px solid var(--line); border-inline-start:3px solid var(--fam); padding-inline-start:11px; }
  .lywb tbody td { display:block; padding:2px 0; border-bottom:none; }
  .lywb .c-tk { display:block; }
  .lywb .c-tk::before { display:none; }
  .lywb .tkbox { max-width:none; }
  .lywb .tkco { max-width:none; }
  .lywb .tkfx { max-width:none; }
  .lywb .srcb { max-width:none; }
  .lywb .c-int,.lywb .c-dir { display:inline-block; margin-inline-end:14px; margin-top:4px; min-width:0; }
  .lywb .c-int::before,.lywb .c-dir::before { content:attr(data-label) " "; color:var(--text-tertiary); font-size:10.5px; font-weight:600; }
  .lywb .c-why { max-width:none; margin-top:6px; }
  .lywb .c-tm { text-align:start; margin-top:6px; }
  .lywb .rel { display:inline; margin-inline-start:8px; }
  .lywb tbody tr { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:12px; align-items:start; padding-block:12px; padding-inline:11px 14px; }
  .lywb tbody tr.emptyrow { display:block; }
  .lywb tbody td { padding:0; }
  .lywb tbody td.c-tk { grid-column:1; grid-row:1; }
  .lywb tbody td.c-tm { grid-column:2; grid-row:1; margin:0; padding-top:3px; text-align:end; white-space:nowrap; }
  .lywb tbody td.c-why { grid-column:1 / -1; grid-row:2; margin-top:7px; }
  .lywb tbody td.c-sig { grid-column:1 / -1; grid-row:3; margin-top:7px; display:flex; align-items:center; gap:8px; min-width:0; white-space:nowrap; }
  .lywb tbody td.c-int,.lywb tbody td.c-dir { display:none; }
  .lywb tbody td.c-sig .chip { display:none; }
  .lywb tbody td.c-tm .tmet { display:none; }
  .lywb tbody td.c-why .whytx { display:none; }
  .lywb .tkbox { display:grid; grid-template-columns:auto minmax(0,1fr); align-items:baseline; column-gap:8px; padding:0; border:0; border-radius:0; background:none; text-align:start; }
  .lywb .tkbox > * { justify-self:start; max-width:100%; margin:0; }
  .lywb .tkbox .tk { grid-row:1; grid-column:1; font-size:18px; line-height:22px; font-weight:800; letter-spacing:.02em; }
  .lywb .tkbox .px { grid-row:1; grid-column:2; font-size:13px; line-height:22px; }
  .lywb .tkbox .tkco { grid-row:2; grid-column:1 / -1; display:block; margin-top:1px; font-size:13px; line-height:18px; max-height:none; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .lywb .tkbox .tkfx { grid-row:3; grid-column:1 / -1; margin-top:2px; font-size:14px; line-height:20px; color:var(--text-secondary); }
  .lywb .tkfx .tkfxi[data-k="deal_x"] .mono { font-size:18px; font-weight:800; color:var(--text-primary); }
  .lywb tbody td.c-why .whyhd { display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2; overflow:hidden; margin:0; font-size:14px; line-height:20px; }
  .lywb tbody td.c-why:has(.newsgap) .whyhd,.lywb tbody td.c-why:has(.newsgap) .trtag { display:none; }
  .lywb tbody td.c-why .newsgap { margin:0; font-size:13.5px; line-height:20px; }
  .lywb tbody td.c-why .trtag { margin-top:6px; }
  .lywb tbody td.c-sig .kind { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .lywb tbody td.c-sig .xbadge,.lywb tbody td.c-sig .repb { flex:0 0 auto; margin:0; }
  .lywb tbody td.c-sig .optexp { display:inline; flex:0 0 auto; margin:0; font-size:12px; }
  .lywb tbody td.c-tm .rel { display:inline; margin:0; font-size:11.5px; color:var(--text-tertiary); }
  .lywb tbody td.c-tm .nowb { margin-inline:0 6px; }
  .lywb tbody tr.crit-live { animation:none; background-color:var(--crit-row-bg); }
  .lywb .tkbox .tk { position:relative; }
  .lywb tbody td.c-why:has(.newsgap) .whyhe { display:none; }
  .lywb tbody td.c-why .ltstate { margin-top:6px; font-size:12.5px; line-height:18px; }
  .lywb tbody td.c-tm .ltupd { margin-top:4px; }
  .lywb tbody tr[data-lt="living"] td.c-why .whyhd { display:block; -webkit-line-clamp:unset; line-clamp:unset; overflow:visible; }
  .lywb .tkbox .ltpx { white-space:normal; }
  .lywb .tkbox .ltpub { display:inline-block; margin:0; font-size:11px; line-height:22px; }
  .lywb .tkbox:has(> .ltpx) { display:flex; flex-wrap:wrap; align-items:baseline; column-gap:6px; row-gap:0; }
  .lywb .tkbox:has(> .ltpx) > .tk { order:1; }
  .lywb .tkbox:has(> .ltpx) > .ltpx { display:contents; }
  .lywb .tkbox:has(> .ltpx) > .ltpx > * { order:2; white-space:nowrap; line-height:22px; }
  .lywb .tkbox:has(> .ltpx) > .tkco { order:3; flex:1 1 100%; min-width:0; }
  .lywb .tkbox:has(> .ltpx) > .tkfx { order:4; flex:1 1 100%; min-width:0; }
  .lywb .tkpct { margin-inline-start:6px; }
  .lywb .tkpub { margin-inline-start:8px; font-family:var(--font-sans); font-size:12px; font-weight:500; color:var(--text-secondary); }
  .lywb .tkpub .mono { font-weight:600; }
}

/* ============================================================================
   §STORY → THE LIVING TICKET (2026-09-30, docs/LIVING_TICKET_UPDATE_DESIGN_2026-09-30.md §1–§3, §8)
   The user's ruling: the cards stay exactly as they are; an update adds a SIGN beside the clock, moves the
   ticket to the top, and puts the merged record INSIDE the ticket. So there is no second card here — only the
   three new nodes the born card's row and its ticket gain, styled with the app's own tokens and, where one
   exists, the app's own class (.ststate / .stfig / .sttl / .sttr / .tkmeta / .tkm / .tklname). Every node is
   made ONLY while GET /v1/me says `stories: true` AND a story is held for the name; otherwise none of these
   selectors matches anything and the page paints exactly as it did. The 09-29 band and story card (rejected
   on sight) are gone with their rules.
   ============================================================================ */
/* the story atoms the ticket reuses */
.ststate{font-size:12.5px; line-height:1.5; color:var(--text-secondary);}
.ststate .mono{font-weight:700; color:var(--text-primary);}
.stfig{white-space:nowrap;}
.stsep{color:var(--text-disabled);}
/* NEVER TRUNCATE A FIGURE — a figure is ATOMIC (a clamp or an ellipsis hides it whole or not at all), a
   hyphenated word never breaks at its hyphen. The muted text is --text-secondary (the token the feed's own
   .kind uses): ≥ 4.5:1 on both surfaces, where --text-tertiary measured 3.85:1. */
.stfg{display:inline-block; white-space:nowrap; overflow-wrap:normal;}
.stnb{white-space:nowrap;}
.sttl{list-style:none; margin:2px 0 0; padding:6px 0 0; border-top:1px solid var(--line);
      display:flex; flex-direction:column; gap:3px;}
.sttr{display:flex; align-items:baseline; gap:8px; min-width:0; font-size:12px; line-height:1.4; color:var(--text-secondary);}
.sttm{flex:0 0 auto; font-size:11px; color:var(--text-secondary);}
.stlbl{min-width:0; overflow-wrap:break-word;}
.sttr.stlk{color:var(--text-secondary);}
.sttr .plock{flex:0 0 9px; align-self:center; margin-top:4px; color:var(--text-secondary);}
.stunk{color:var(--text-secondary); font-style:italic;}
/* 1 · THE SIGN — beside the clock, the only new element on the collapsed ticket, in three short lines so it
   never widens the clock's column. The info colour the translation tag wears: a note about the card. */
.ltupd{display:flex; flex-direction:column; align-items:center; width:max-content; max-width:100%;
       margin-top:6px; margin-inline-start:auto; padding:3px 8px; border-radius:8px;
       font-family:var(--font-sans); font-size:10px; line-height:14px; letter-spacing:.02em; white-space:nowrap;
       color:var(--info); background:var(--info-bg); border:1px solid rgba(155,140,255,.34);}
.ltupdw{font-weight:800; letter-spacing:.05em;}
.ltupdk{font-weight:700;}
.ltupdt{font-weight:500; opacity:.85;}
/* 2 · THE STATE LINE — one line under the why-line, in the story typography */
.ltstate{margin-top:5px;}
.ltstate .mono.ltup{color:var(--up);}
.ltstate .mono.ltdn{color:var(--down);}
.ltstage{font-size:11px; font-weight:600; color:var(--text-secondary); text-transform:lowercase; white-space:nowrap;}
/* ROUND 6 (MEDIUM-1 + LOW, rulings 10-06) — a line of UNITS (app.js ltUnitLine), at EVERY width: each unit opens with its
   own separator; .ltin starts one separator-width OUTSIDE the line's box and .ltln clips that strip, so the separator of a
   unit that begins a visual line is never painted — in either direction, with nothing measured (one layout per width).
   A unit longer than the line wraps inside itself on a hanging indent: its next line starts where its text starts. The
   tail ("· <stage>, <flow>") is one unit with one separator: it moves to the next line whole. */
.ltln{display:block; overflow:hidden; --lts:.8em;}
.ltln > .ltin{display:flex; flex-wrap:wrap; align-items:baseline; min-width:0; margin-inline-start:calc(-1 * var(--lts));}
.ltln .ltunit{flex:0 1 auto; min-width:0; padding-inline-start:var(--lts); text-indent:calc(-1 * var(--lts)); white-space:normal;}
.ltln .ltunit0{text-indent:0;}
.ltln .ltunit *{text-indent:0;}
.ltln .ltunit > .stsep,.ltln .ltpair > .stsep{display:inline-block; width:var(--lts); text-align:center; white-space:pre;}
.ltln .ltstage,.ltln .ltflow{white-space:nowrap;}
/* ROUND 7 (D3, ruling 10-06) — A SCOPE LABEL GOVERNS BOTH ITS UNITS: the shares and the dollars of one scope are ONE
   unbreakable piece (app.js ltPair) — "254.2M shares · $189M traded" wraps whole, never between its two figures, so the
   share count is never left on a line without the label that scopes it (390: the summary's width is 341 px). Its inner
   separator is drawn in the SAME box as a unit's (the rule above), so a one-line reading is unchanged. In the ledger the
   label that closes the pair ("since 09:50 ET (first tape print)") is one inline block: it moves to the next line WHOLE,
   under the pair it governs, instead of splitting after its first words — and still wraps inside itself, never clipped,
   should it ever be wider than the line. */
.ltln .ltpair{white-space:nowrap;}
.ltrg .ltgl{display:inline-block; max-width:100%;}
/* R1 — the newest news headline, ONE line under the why-line. width:0 + min-width:100% = it fills the cell
   but adds NO intrinsic width, so a long headline can never widen the Why column past the clock */
.ltlatest{display:block; width:0; min-width:100%; box-sizing:border-box; margin-top:4px; font-size:12px; line-height:17px;
          color:var(--text-secondary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.ltlatestk{font-weight:700; color:var(--text-primary);}
/* 3 · THE MERGED RECORD inside the expanded ticket, under the headline (18:11–18:12 ET: a story of updates, not a
   numbers grid — every update row in the card's NORMAL type size, not a grey footnote) */
.ltsum{margin:2px 0 4px; font-size:13.5px; color:var(--text-primary);}
.ltsuml{font-weight:700;}
/* THE LEDGER (ruling 10-05) — newest first; a two-column row grid: [time ET · age] [bold event + bold price + %,
   then the headline, then the since-alert shares / dollars / cap in grey] */
.ltledger{list-style:none; margin:0; padding:6px 0 0; display:flex; flex-direction:column;}
.ltrow{display:grid; grid-template-columns:minmax(72px,max-content) minmax(0,1fr); column-gap:14px; align-items:baseline;
       padding:8px 0; border-top:1px solid var(--line); font-size:13px; line-height:1.45; color:var(--text-primary);}
.ltrow:first-child{border-top:0; padding-top:2px;}
.ltrt{display:flex; flex-direction:column; font-size:12px; line-height:1.35; color:var(--text-secondary); white-space:nowrap;}
.ltrtm{font-weight:600; color:var(--text-primary);}
.ltrsep{display:none;}
.ltrrel{font-size:11px;}
/* round 3 — the live "Now" row already says Now: its age cell stands down while it reads "now" (data-relnow, kept by
   the page's one relative ticker), as the feed's time cell does beside the fresh chip; "2 min ago" shows again */
.ltunow .ltrrel[data-relnow="1"]{display:none;}
.ltrb{display:flex; flex-direction:column; gap:2px; min-width:0;}
.ltrh{display:block; overflow-wrap:anywhere;}
.ltrw{font-weight:800;}
/* round 2 — the live "Now" row at the head of the ledger (the current state; the event rows keep their as-of figures) */
.ltunow .ltrw{color:var(--accent);}
.ltrpx{font-weight:800;}
.ltrpct{font-family:var(--font-sans); font-weight:700;}
.ltrn{display:block; color:var(--text-primary); overflow-wrap:anywhere;}
.ltrg{display:block; font-size:12px; color:var(--text-secondary); overflow-wrap:anywhere;}
.ltbasis{margin-top:6px; font-size:12px; color:var(--text-secondary);}
.ltmerged{display:flex; flex-direction:column; gap:14px; margin:10px 0 14px;}
.ltblock .tklname{margin-bottom:4px;}
.ltmerged .tkmeta{margin-top:0; padding:10px 0 11px;}
.ltmerged .tkmv{display:block; white-space:normal; overflow:visible; line-height:1.45;}
.ltmerged .tkm{align-items:baseline;}
.ltmerged .ltnow{grid-template-columns:repeat(2,minmax(0,1fr));}
.ltmerged .ltlv{grid-template-columns:minmax(0,1fr);}
.ltv .mono{white-space:nowrap;}
.ltmerged .tkmv .mono{font-weight:700;}
.ltmerged .sttl{padding-top:8px; margin:0; gap:5px;}
.ltmerged .sttr[data-head="1"] .stlbl{color:var(--text-primary); font-weight:600;}
/* §13-D (2026-09-30 20:00 ET) — THE LIVE HEADER of a news ticket: the price now and its % since the alert in the
   price slot, the alert's price (the since-alert basis) small beside it. Figures stay ltr in Hebrew (ltr spans). */
.ltpx .ltpct{font-weight:700;}
.ltpct.ltup{color:var(--up);}
.ltpct.ltdn{color:var(--down);}
.ltpub{display:block; margin-top:1px; font-family:var(--font-sans); font-size:10px; line-height:13px; font-weight:500;
       color:var(--text-secondary); white-space:nowrap;}
.ltpub .mono{font-weight:600; color:var(--text-secondary);}
.tkm[data-k="price"] .ltpct{font-family:var(--font-sans); font-size:12px; font-weight:700; white-space:nowrap;}
.tkm[data-k="price"] .ltpct .mono{font-weight:700; color:inherit;}
/* the live grid rows WRAP their small basis word ("shares outstanding") under the figure — never an ellipsis */
.tkwrap .tkm[data-k^="lt_"]{align-items:flex-start;}
.tkwrap .tkm[data-k^="lt_"] .tkmv{flex-wrap:wrap; row-gap:0; white-space:normal; overflow:visible; text-overflow:clip; line-height:1.35;}
.tkwrap .tkm[data-k^="lt_"] .tkmv .rel{white-space:nowrap;}
/* ROUND 6 ruling (a): a since-figure measured from a late first tape print names that print in its label ("Volume since
   09:50 ET (first tape print)") — wider than a 1280 grid cell, where a label that never shrinks overprinted the next
   cell. These two labels WRAP inside their own cell; their one figure keeps its width. A label that fits is unchanged. */
.tkwrap .tkm[data-k="lt_vol"] .tkml,.tkwrap .tkm[data-k="lt_usd"] .tkml{flex:0 1 auto;}
.tkwrap .tkm[data-k="lt_vol"] .tkmv,.tkwrap .tkm[data-k="lt_usd"] .tkmv{flex:0 0 auto;}
/* §13-F — the update chip ("Update · +26% in 10 min · Stop updates"), at the head of the why cell; the row's pulse
   and frame are declared beside the FLIP flicker (before the phone layer), see "§13-F HOT" there */
.lthot{display:flex; align-items:baseline; width:max-content; max-width:100%; box-sizing:border-box;
       margin:0 0 6px; padding:2px 9px; border-radius:999px; font-family:var(--font-sans); font-size:11px; line-height:16px;
       font-weight:700; white-space:nowrap; color:var(--warn);
       background:var(--warn-bg); border:1px solid color-mix(in srgb,var(--warn) 55%,transparent);}
.lthotw{font-weight:800; letter-spacing:.08em;}
.lthot .stfg,.lthotk .mono{font-weight:800;}

@media (max-width:720px){
  /* ── fonts: Heebo + JetBrains Mono only ── */
  :root{--font-sans:'Heebo',-apple-system,system-ui,sans-serif;}

  /* ── the shell: the phone header stands in for the v3 header; the page ends above the bar ── */
  .top{display:none;}
  .page{padding-bottom:calc(var(--nb-h) + var(--safe-b) + 20px);}
  .wrap{padding-inline:12px;}

  /* the ONE-LINE sticky header: wordmark (→ account sheet) · live light · count · stamp */
  .ph{display:flex; align-items:center; gap:10px; position:sticky; top:0; z-index:30;
      min-height:calc(52px + var(--safe-t)); padding-top:var(--safe-t); padding-inline:8px 12px;
      background:var(--bg-deeper); border-bottom:1px solid var(--line);}
  .phbrand{flex:0 0 auto; display:inline-block; line-height:44px; padding:0 6px;
           font-family:var(--font-sans); font-weight:800; font-size:14px; letter-spacing:.12em;
           color:var(--text-primary); background:none; border:0; border-radius:10px; cursor:pointer;
           direction:ltr; white-space:nowrap;}
  .phbrand em{font-style:normal; background:var(--aurora); -webkit-background-clip:text;
              background-clip:text; color:transparent;}
  .phbrand .beta{font-size:8px; font-weight:800; letter-spacing:.12em; position:relative; top:-5px;
                 margin-inline-start:4px; background:var(--aurora); -webkit-background-clip:text;
                 background-clip:text; color:transparent;}
  .phmeta{display:flex; align-items:center; gap:7px; min-width:0; margin-inline-start:auto;
          white-space:nowrap; overflow:hidden;}
  .phled{flex:0 0 8px; width:8px; height:8px; border-radius:50%; background:var(--up);
         box-shadow:0 0 8px color-mix(in srgb,var(--up) 70%,transparent);}
  .phled.stale{background:var(--warn); box-shadow:0 0 8px color-mix(in srgb,var(--warn) 70%,transparent);}
  .phcount{font-size:13px; font-weight:700; color:var(--text-primary);}
  .phupd{min-width:0; overflow:hidden; text-overflow:ellipsis; font-size:11px; color:var(--text-tertiary);}

  /* the BOTTOM BAR: 56px + the home indicator's inset; a flex row, so it mirrors in Hebrew */
  .nb{display:flex; position:fixed; inset-inline:0; bottom:0; z-index:45;
      height:calc(var(--nb-h) + var(--safe-b)); padding-bottom:var(--safe-b);
      background:var(--bg-deeper); border-top:1px solid var(--line);}
  .nbb{position:relative; flex:1 1 0; height:var(--nb-h); display:flex; flex-direction:column;
       align-items:center; justify-content:center; gap:4px; padding:0;
       font-family:var(--font-sans); font-size:11px; font-weight:700; letter-spacing:.02em;
       color:var(--text-tertiary); background:none; border:0; cursor:pointer;}
  .nbb.on{color:var(--accent-2);}
  .nbb.on::before{content:""; position:absolute; top:0; inset-inline:30%; height:2px;
                  border-radius:0 0 2px 2px; background:var(--accent);}
  .nbi{display:block; width:20px; height:18px;}
  .nbi-now{background:linear-gradient(currentColor,currentColor) 0 2px/100% 2px no-repeat,
                      linear-gradient(currentColor,currentColor) 0 8px/100% 2px no-repeat,
                      linear-gradient(currentColor,currentColor) 0 14px/64% 2px no-repeat;}
  .nbi-market{background:linear-gradient(currentColor,currentColor) 1px 100%/4px 8px no-repeat,
                         linear-gradient(currentColor,currentColor) 8px 100%/4px 16px no-repeat,
                         linear-gradient(currentColor,currentColor) 15px 100%/4px 11px no-repeat;}
  .nbi-filter{background:currentColor; clip-path:polygon(0 0,100% 0,62% 46%,62% 100%,38% 78%,38% 46%);}
  .nbbadge{position:absolute; top:5px; inset-inline-start:calc(50% + 6px); min-width:16px; height:16px;
           padding:0 4px; border-radius:999px; font-size:10px; font-weight:800; line-height:16px;
           text-align:center; color:var(--bg-base); background:var(--accent-2);}

  /* ── TAP TARGETS ≥ 44px (spec B): every control on the phone, one rule; no hover-only door ── */
  button,input:not([type="checkbox"]),select,textarea,[role="button"]{min-height:44px;}
  button{min-width:44px;}
  .fbcontact{min-height:44px;}
  .ppt tr[role="button"] td{padding-block:14px;}
  /* the token ×: a 44px target around the same 16px mark, paid for by negative margins */
  .ftokx,.fsymx{min-width:44px; min-height:44px; padding:14px; margin-block:-14px; margin-inline:-8px -6px;
                background-clip:content-box;}

  /* ── the TWO SCREENS: one class on .page, nothing moves in the DOM. Now = the list;
     Market = the session chip, the pulse strip, the market pulse band, the premium set and
     the daily opinion. The header carries the count, so the stats line rests. ── */
  .statsrow .stats{display:none;}
  .srdoor{display:none;}
  .page.pv-now .pulsebar,.page.pv-now .statsrow{display:none;}
  .page.pv-now .fstrip .fbtn-more,.page.pv-now .fstrip .opbtn{display:none;}
  .page.pv-now .fstrip:not(:has(.ftok)){display:none;}
  .page.pv-market .filters,.page.pv-market .tblbox,.page.pv-market .legend{display:none;}
  .page.pv-market .fstrip > *{display:none;}
  .page.pv-market .fstrip{padding-top:4px;}
  .page.pv-market .fstrip > .opbtn{display:flex; width:100%; min-height:48px;}
  /* the PREMIUM QUARTET (user 2026-09-28 18:5x ET): it now rides the chip band, and the phone renders it as
     before — Now: the chips, no quartet · Market: the quartet centred on its own full-width line, where
     the stats row carried it (the Market column puts the band first), the
     now-empty stats row taken away so it leaves no gap · the name page: neither. Only the paint moved
     (light green); every pill keeps the 44px phone target (the tap-target rule above). */
  .page.pv-now .premium,.page.pv-name .premium{display:none;}
  .page.pv-market .statsrow{display:none;}
  .page.pv-market > .wrap{display:flex; flex-direction:column;}
  .page.pv-market .filtersrow{display:flex; order:-1;}
  .page.pv-market .premium{margin-inline-start:0; width:100%; justify-content:center; padding-block:10px 3px;}
  .mkhead{display:flex; align-items:center; padding:12px 12px 0;}
  .pulse{padding:12px;}
  .mpanel{margin-inline:12px;}
  /* (architect note, Build C) the Market screen's sideways scroller fades at BOTH edges instead
     of ending in a hard cut. The fade is the same at either edge, so the Hebrew page mirrors it
     with no rule of its own; it is 12px, the width of the content's own inline padding, so at rest
     the start-side fade lies over padding only. A mask: no colour, no animation. */
  .pulsescroll{-webkit-mask-image:linear-gradient(to right,transparent,black 12px,black calc(100% - 12px),transparent);
               mask-image:linear-gradient(to right,transparent,black 12px,black calc(100% - 12px),transparent);}
  /* the family chips: ONE line that scrolls inside itself — the page never scrolls sideways */
  .filters{flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden; scrollbar-width:none; gap:6px; padding:10px 0;}
  .filters::-webkit-scrollbar{display:none;}
  .filters .fbtn{flex:0 0 auto; white-space:nowrap;}
  /* the filter panel's sheet sits ON the bottom bar, so the Filter tab stays in reach */
  .fpanel{bottom:calc(var(--nb-h) + var(--safe-b));
          max-height:calc(100% - var(--nb-h) - var(--safe-b) - var(--safe-t) - 64px);}

  /* ── THE SCAN CARD (spec §2): the SAME row, cut. Symbol + price, company on one line, the
     class line, the headline in two lines (or the "No news card today" line in its slot), the
     relative time trailing, the family edge, the kind as plain text, the EXTREME tag. Hidden
     here and kept on the sheet: interest, direction, the family chip, the why body, the ET clock. ── */
  tbody tr{display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:12px; align-items:start;
           padding-block:12px; padding-inline:11px 14px;}
  tbody tr.emptyrow{display:block;}
  tbody td{padding:0;}
  tbody td.c-tk{grid-column:1; grid-row:1;}
  tbody td.c-tm{grid-column:2; grid-row:1; margin:0; padding-top:3px; text-align:end; white-space:nowrap;}
  tbody td.c-why{grid-column:1 / -1; grid-row:2; margin-top:7px;}
  tbody td.c-sig{grid-column:1 / -1; grid-row:3; margin-top:7px; display:flex; align-items:center;
                 gap:8px; min-width:0; white-space:nowrap;}
  tbody td.c-int,tbody td.c-dir{display:none;}
  tbody td.c-sig .chip{display:none;}
  tbody td.c-tm .tmet{display:none;}
  tbody td.c-why .whytx{display:none;}
  /* the tile flattens into three start-aligned lines: SYMBOL price / company / class line */
  .tkbox{display:grid; grid-template-columns:auto minmax(0,1fr); align-items:baseline; column-gap:8px;
         padding:0; border:0; border-radius:0; background:none; text-align:start;}
  .tkbox > *{justify-self:start; max-width:100%; margin:0;}
  .tkbox .tk{grid-row:1; grid-column:1; font-size:18px; line-height:22px; font-weight:800; letter-spacing:.02em;}
  .tkbox .px{grid-row:1; grid-column:2; font-size:13px; line-height:22px;}
  .tkbox .tkco{grid-row:2; grid-column:1 / -1; display:block; margin-top:1px; font-size:13px; line-height:18px;
               max-height:none; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .tkbox .tkfx{grid-row:3; grid-column:1 / -1; margin-top:2px; font-size:14px; line-height:20px;
               color:var(--text-secondary);}
  /* the deal MULTIPLE at the symbol's size — the one figure a subscriber scans the class for */
  .tkfx .tkfxi[data-k="deal_x"] .mono{font-size:18px; font-weight:800; color:var(--text-primary);}
  tbody td.c-why .whyhd{display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; line-clamp:2;
                        overflow:hidden; margin:0; font-size:14px; line-height:20px;}
  /* a moving name with no news card: the line takes the headline's slot (the headline, and the
     translation tag that spoke for it, stand down; both are on the sheet) */
  tbody td.c-why:has(.newsgap) .whyhd,tbody td.c-why:has(.newsgap) .trtag{display:none;}
  tbody td.c-why .newsgap{margin:0; font-size:13.5px; line-height:20px;}
  tbody td.c-why .trtag{margin-top:6px;}
  tbody td.c-sig .kind{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  tbody td.c-sig .xbadge,tbody td.c-sig .repb{flex:0 0 auto; margin:0;}
  /* §OPTIONS HOLD — on the scan card the expiry rides the kind's line and never shrinks (the kind ellipsises first) */
  tbody td.c-sig .optexp{display:inline; flex:0 0 auto; margin:0; font-size:12px;}
  tbody td.c-tm .rel{display:inline; margin:0; font-size:11.5px; color:var(--text-tertiary);}
  tbody td.c-tm .nowb{margin-inline:0 6px;}
  /* critical red is STATIC on the phone (spec §2): the surface the row wears its whole life */
  tbody tr.crit-live{animation:none; background-color:var(--crit-row-bg);}

  /* ── THE SHEET (spec §1 "Read"): the one modal as a full-height bottom sheet — a 20px strip of
     backdrop (tap it to close) under the status bar's inset, the handle, head → facts strip →
     tier → prose → grid, and a close in the thumb zone above the home indicator ── */
  html.relay-sheet,html.relay-sheet body{overflow:hidden;}
  .tkwrap{padding:0; align-items:flex-end;}
  /* (architect note, Build C) the 20px strip above the sheet is OPAQUE (at 94% the wordmark still
     ghosted through), so the sticky header does not peek out; it is still the backdrop, and a tap
     on it still closes the sheet */
  .tkwrap{background:var(--bg-deeper);}
  .tkwrap .tk{display:flex; flex-direction:column; width:100%; max-width:none;
              height:calc(100% - var(--safe-t) - 20px); max-height:none; padding:0 16px;
              border-radius:18px 18px 0 0; border-bottom:0; overscroll-behavior:contain;
              transition:transform .22s ease;}
  .tkwrap .tk > *{flex:0 0 auto;}
  .tkgrab{display:flex; order:0; position:sticky; top:0; z-index:2; align-items:center; justify-content:center;
          height:44px; margin-inline:-16px; background:inherit; touch-action:none; cursor:grab;}
  .tkgrab i{display:block; width:40px; height:5px; border-radius:3px; background:var(--text-disabled);}
  .tkwrap .tkx{order:0; position:sticky; top:0; inset-inline-end:auto; z-index:3; align-self:flex-end;
               width:44px; height:44px; margin-top:-44px; margin-inline-end:-6px; font-size:22px;
               border-radius:12px;}
  .tkhd{order:1; padding-inline-end:0;}
  .tkpx{display:inline; font-size:16px; font-weight:700; color:var(--px-bright);}
  .tkcap{display:none;}
  .tkfacts{order:2; display:flex; gap:8px; overflow-x:auto; overflow-y:hidden; margin:12px -16px 0;
           padding:0 16px 2px; scrollbar-width:none;}
  .tkfacts:empty{display:none;}
  .tkfacts::-webkit-scrollbar{display:none;}
  .tkfi{flex:0 0 auto; display:flex; flex-direction:column; gap:3px; min-width:84px; padding:8px 11px;
        border:1px solid var(--line); border-radius:10px; background:var(--bg-elevated);}
  .tkfil{font-size:10px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
         color:var(--text-tertiary); white-space:nowrap;}
  .tkfiv{font-size:15px; font-weight:700; color:var(--text-primary); white-space:nowrap;}
  .tkxwrap{order:3;}
  .tkbody{order:4; margin-top:16px;}
  .tkmeta{order:5; margin-top:18px; grid-template-columns:1fr;}
  /* the thumb-zone close: pushed to the sheet's foot when the content is short (the auto margin),
     held there while it scrolls (sticky); it wears the panel's own surface without its top band */
  .tkfoot{order:6; display:block; position:sticky; bottom:0; z-index:2; margin:auto -16px 0;
          padding:10px 16px calc(10px + var(--safe-b)); background:inherit; background-size:0 0,auto;
          border-top:1px solid var(--line);}
  .tkx2{display:block; width:100%; min-height:48px; font-family:var(--font-sans); font-size:15px;
        font-weight:700; color:var(--text-primary); background:var(--bg-elevated);
        border:1px solid var(--line); border-radius:12px; cursor:pointer;}

  /* ── §BOOK-NAME (Build C): Book | All under the header (the JS hides it while there is no
     book); the symbol's door, an empty button laid over the symbol with a 44px reach; and the
     name page — the list's own table through one symbol, its head above it, the news line
     under it, the list's chrome resting while it is up ── */
  /* 44px and no taller (the line is an inset shadow, not a border); the negative bottom margin
     lends the list the wrap's own top padding, so the Book view still shows three cards at 390×844
     — and the toggle sits ABOVE that padding (z-index) so the whole 44px stays tappable */
  .bkseg{display:flex; position:relative; z-index:1; margin:6px 12px -12px; border-radius:12px;
         box-shadow:inset 0 0 0 1px var(--line); background:var(--bg-deeper);}
  .bkb{flex:1 1 0; min-height:44px; padding:0 12px; font-family:var(--font-sans); font-size:14px;
       font-weight:700; color:var(--text-tertiary); background:none; border:0; border-radius:12px; cursor:pointer;}
  .bkb.on{color:var(--text-primary); background:var(--bg-elevated); box-shadow:inset 0 0 0 1px var(--line);}
  .page.pv-market .bkseg,.page.pv-name .bkseg{display:none;}
  .tkbox .tk{position:relative;}
  .tknm{display:block; position:absolute; inset-block:-11px; inset-inline:-8px; padding:0;
        background:none; border:0; border-radius:8px; cursor:pointer;}
  .page.pv-name .filters,.page.pv-name .fstrip,.page.pv-name .tknm{display:none;}
  .page.pv-name .nphd{display:flex; align-items:center; gap:12px; min-width:0; padding:10px 0;}
  .npback{flex:0 0 auto; display:inline-flex; align-items:center; gap:8px; padding-block:0;
          padding-inline:14px 16px; font-family:var(--font-sans); font-size:14px; font-weight:700;
          color:var(--text-primary); background:var(--bg-elevated); border:1px solid var(--line);
          border-radius:12px; cursor:pointer;}
  .npchev{font-style:normal; font-size:22px; line-height:1; margin-top:-3px;}
  .npttl{display:flex; align-items:baseline; gap:8px; min-width:0; margin:0; font-size:inherit; font-weight:inherit;}
  .npsym{flex:0 0 auto; font-size:20px; line-height:26px; font-weight:800; letter-spacing:.02em;
         color:var(--text-primary);}
  .npco{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px;
        color:var(--text-secondary);}
  .page.pv-name .npgap{display:block; margin:12px 2px 0; font-size:13.5px; line-height:20px;
                       color:var(--text-tertiary);}

  /* ── §APPV2 (app plan v2) on the phone ── */
  /* the search door at the header's inline end: 44px, the icon only. The one-line header pays for it
     out of its own air (gaps and the end padding), so the stamp still reads whole at 390px */
  .ph{gap:6px; padding-inline:6px 2px;}
  .phmeta{gap:5px;}
  .phsr{display:inline-flex; align-items:center; justify-content:center; flex:0 0 44px; width:44px; height:44px;
        padding:0; color:var(--text-primary); background:none; border:0; border-radius:12px; cursor:pointer;}
  .phsr .srico{width:15px; height:15px;}
  .phsr .srico::after{height:7px; transform:translate(6px,6px) rotate(-45deg);}
  /* the search page under the sticky header: Back and the box on one line, 16px text (no zoom) */
  .srpage{padding:12px 12px 24px;}
  .srhead{gap:8px;}
  .srbox{max-width:none; padding-inline:12px 0;}
  .srin{height:44px;}
  .srclr{width:44px; height:44px;}
  .srlist{max-width:none;}
  .srttl{font-size:18px; margin-top:12px;}
  .srttl .srsym{font-size:20px;}
  /* Both: when "No news card today" takes the headline's slot, the Hebrew block stands down with the
     English headline (it is on the sheet), so no empty divider is left behind */
  tbody td.c-why:has(.newsgap) .whyhe{display:none;}
  /* a history card is not a door to the feed's name page */
  .srpage .tknm{display:none;}
  /* nothing of the list's chrome stays over the search page */
  .page:has(.srpage.on) .bkseg{display:none;}
  /* the lock sheet rises from the bottom, sized to its words */
  .tkwrap .tk.tklock{height:auto; max-height:calc(100% - var(--safe-t) - 20px);}
  /* …over the list it speaks about: a small sheet leaves the page visible behind a dimmed backdrop
     (the full-height sheets keep the opaque strip) */
  .tkwrap:has(.tk.tklock){background:color-mix(in srgb,var(--bg-deeper) 72%,transparent);}
  /* §STORY (2026-09-30) — the LIVING TICKET on the phone (the desktop rules sit above this block).
     §6 q2: the FEED ROW's state line keeps the flow word only while the tail sits on its neighbour's line (ltFitLine reads
     the laid-out line and drops the word whole, never a stub); the units (.ltln, above) never paint a separator at the
     start of a line, whatever the fit decides.
     ROUND 6 (MEDIUM-1, ruling 10-06): the ticket's SUMMARY has ONE layout per width, by CSS alone — its tail (stage,
     flow) always takes a line of its own, so no live figure's width can flip it between two layouts; nothing measures
     it. */
  .ltsum.ltln .lttail{flex:1 1 100%;}
  tbody td.c-why .ltstate{margin-top:6px; font-size:12.5px; line-height:18px;}
  tbody td.c-tm .ltupd{margin-top:4px;}
  .ltmerged .tkmeta{grid-template-columns:1fr;}
  /* "the news are the headline — all of it": a living ticket's headline is never clamped on the phone */
  tbody tr[data-lt="living"] td.c-why .whyhd{display:block; -webkit-line-clamp:unset; line-clamp:unset; overflow:visible;}
  /* §13-D — on the phone the live price sits beside the symbol and the alert's price follows it on the same line
     (a whole unit: it wraps under the price rather than breaking) */
  .tkbox .ltpx{white-space:normal;}
  .tkbox .ltpub{display:inline-block; margin:0; font-size:11px; line-height:22px;}
  /* round 3 (R4) — when the slot does not fit beside the symbol ("$0.3196 −8.7% at alert $0.35" next to an UPDATED
     sign), "at alert $0.35" wraps to the LEFT EDGE of the tile, never under the price column (the grid's ~80 px
     indent). The live tile lays its line out as one wrapping row: symbol · price · % · at-alert, then the company and
     the class line each on a full line. Each piece stays whole (white-space:nowrap); the page direction orders them. */
  .tkbox:has(> .ltpx){display:flex; flex-wrap:wrap; align-items:baseline; column-gap:6px; row-gap:0;}
  .tkbox:has(> .ltpx) > .tk{order:1;}
  .tkbox:has(> .ltpx) > .ltpx{display:contents;}
  .tkbox:has(> .ltpx) > .ltpx > *{order:2; white-space:nowrap; line-height:22px;}
  .tkbox:has(> .ltpx) > .tkco{order:3; flex:1 1 100%; min-width:0;}
  .tkbox:has(> .ltpx) > .tkfx{order:4; flex:1 1 100%; min-width:0;}
  .tkpct{margin-inline-start:6px;}
  .tkpub{margin-inline-start:8px; font-family:var(--font-sans); font-size:12px; font-weight:500; color:var(--text-secondary);}
  .tkpub .mono{font-weight:600;}
  /* the live strip: three columns, labels may wrap — nothing scrolls sideways */
  .tkfacts.ltfx{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); overflow:visible;}
  .tkfacts.ltfx .tkfi{min-width:0;}
  .tkfacts.ltfx .tkfil{white-space:normal; line-height:12px;}
  .tkfacts.ltfx .tkfis{display:block; margin-top:2px; font-family:var(--font-sans); font-size:10px; line-height:12px;
                       font-weight:500; letter-spacing:0; text-transform:none; color:var(--text-secondary); white-space:normal;}
  /* ── §PREMIUM SCREENS on the phone (2026-10-18): under the sticky header, every control 44px (the block's own
     floor above), nothing scrolls sideways — the transactions table scrolls inside its own box with its first
     column held; the chart and the stats stack ── */
  .pmpage{padding:12px 12px 28px;}
  .pmhead{grid-template-columns:minmax(0,1fr); row-gap:2px; margin-bottom:12px;}
  .pmhead .pmback{grid-row:auto; justify-self:start; margin:0 0 8px;}
  .pmttl{font-size:23px;}
  .pmsub{font-size:13.5px;}
  .smbox,.smlist{max-width:none;}
  .smh2{margin-top:16px; font-size:17px;}
  .smlede{font-size:13.5px;}
  .smtkhd{margin:14px 0 10px;}
  .smtkttl .srsym{font-size:22px;}
  .smranges{flex-wrap:nowrap; gap:4px;}
  .smrange{flex:1 1 0; min-width:0; padding-inline:2px; font-size:12px; white-space:nowrap;}
  .pmpage:lang(he) .smranges{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:6px;}
  .smgrid{grid-template-columns:minmax(0,1fr); gap:10px;}
  .smcard{padding-block:12px; padding-inline:12px;}
  .smtv{font-size:16px;}
  .smfltbtn{display:inline-flex; align-items:center; margin:14px 0 0;}
  .smflt:not(.open){display:none;}
  .smflt{gap:8px 10px; margin-top:8px; padding-block:10px; padding-inline:10px;}
  .smsel,.smnum,.smtog,.smclr{height:44px;}
  .smsort{min-height:44px;}
  .smtd.smc-name,.smtd.smc-title,.smtd.smc-security{white-space:nowrap; min-width:0;}
  .smnum{width:110px;}
  .smtkco{max-width:120px;}
  .pxform{padding-block:12px; padding-inline:12px;}
  .pxtk,.pxask{height:44px;}
  .pxtk{width:130px;}
  .pxans{padding-block:14px; padding-inline:14px;}
  .pxpara{font-size:15.5px;}

  /* §WIDTH · §VIEW-AS (2026-10-18) — the phone is full width already: no width toggle; the view's pill in the header */
  .wdbtn{display:none;}
  html.lyv2 .lytb .lytwd{display:none;}
  .phva{flex:0 0 auto; white-space:nowrap;
        font-size:10.5px; font-weight:800; letter-spacing:.04em; line-height:18px; padding-inline:7px;
        color:var(--warn); background:var(--warn-bg); border:1px dashed color-mix(in srgb,var(--warn) 55%,transparent);
        border-radius:999px;}
}
