:root {
  /* theme-lock 2026-08-30 (operator: peach renders lightness-INVERTED in
     Firefox - measured: every var is our own palette with L flipped and hue
     kept, which no engine does and no extension-free browser produces).
     The peach block already declared its scheme; the DARK theme declared
     nothing, so the page never advertised that it HAS a dark mode. That
     declaration is the standards-based signal a dark-mode extension - and the
     browser's own auto-dark - reads before forcing one on. The vendor
     <meta name="darkreader-lock"> in the page shells is the belt to this
     one's braces. It also closes the real side effect of the omission: native
     scrollbars, form controls and spinners were painted LIGHT on the dark
     theme, because the UA had nothing telling it otherwise. */
  color-scheme: dark;
  /* hm-ring-contrast 2026-09-05 (moved here by ROOT .924): the two inks a
     marked heatmap tile picks between for its ring, chosen per tile against
     the venue colour underneath. Tokens, so the card carries no literal. */
  --hm-ring-light: #ffffff;
  --hm-ring-dark: #0b1220;
  --bg: #0b1020;
  --panel: #141b33;
  --panel-2: #1c2547;
  --text: #e6ebff;
  /* peach-news-ink .849: one step STRONGER than --text, for text that must
     read as the primary ink of a dense list. Defined in every theme per the
     graphical tenet (a value that lives in only one theme block is invisible
     to the others). On dark, stronger = brighter. */
  --text-strong: #f4f7ff;
  --muted: #8a96c4;
  /* text-soft 2026-07-10 (operator): a higher-contrast "muted" for secondary
     card text (mkt-card label/note/ctx) that washed out against --panel — sits
     between --muted and --text so the hierarchy vs the big value figures holds.
     Every theme MUST redefine it (graphical tenet). */
  --text-soft: #b6c0e8;
  --accent: #2dd4bf;
  /* LMTLS 2026-06-10: Limitless brand lime, sampled from static/market-logos/limitless.png */
  --limitless-yellow: #C3FF00;
  --limitless-black:  #0a0a0a;
  --kalshi: #60a5fa;
  --sxbet: #ec4899;
  --limitless: #f97316;
  --whale: #f472b6;
  --mint: #6ee7b7;         /* Build .282: mint green for the "...to KNOW" tagline clause */
  /* cal-green 2026-08-22 (operator: "turn the FLIGHT CALENDAR dots to green
     hues instead of yellow"). ALIASED to --mint rather than given its own hex:
     --mint is already redefined in the peach block (#059669, legible on cream),
     so the theme twin comes free and can never drift out of sync. Named
     separately so the calendar can diverge from the tagline later without
     touching either. Verified in a browser that a var()-valued custom property
     DOES resolve through getComputedStyle - the calendar reads this from JS,
     and an unresolved "var(--mint)" would reach the SVG fill as a garbage
     string and paint nothing. */
  --mt-cal-coin: var(--mint);
  --jackpot: #fbbf24;
  --danger: #ef4444;
  --success: #4ade80;
  /* parlay-ink 2026-09-07 (operator: "in parlays and combos name the data for
     IMPLIED and MULTIPLYER bolder and paint IMPLIED deep blue and MULTIPLYER
     deep green"). TOKENS, not two literals in the templates: both parlay
     surfaces render on BOTH themes, and "deep" inverts between them — a deep
     navy/forest that reads on peach cream is invisible on the dark card, so
     the dark theme takes the deepest tone that still passes AA there.
     MEASURED IN CHROMIUM (getComputedStyle, on the assembled real cascade),
     against the background each surface ACTUALLY paints — which is not the
     same one twice: the dashboard's parlay TABLE paints var(--panel) itself,
     while the standalone board's rows sit on the bare .etand-card.

         surface / theme        bg        implied       multiplier
         dash  dark   (table)   #141b33   #60a5fa 6.69  #22c55e 7.47
         dash  peach  (table)   #FFE3D6   #1e40af 7.15  #166534 5.84
         board dark   (card)    #1e293b   #60a5fa 5.75  #22c55e 6.42
         board peach  (card)    #fffaf2   #1e40af 8.39  #166534 6.86

     Worst case 5.75:1 — every cell clears AA for normal text. The browser
     re-measures all eight, per theme, in
     tests/sanity/test_parlay_implied_mult_ink.py, so a later background
     change cannot quietly drop one below the line. */
  --parlay-implied-ink: #60a5fa;
  --parlay-mult-ink:    #22c55e;
  --border: #2a3566;
  --chip-ink: #0b1020;   /* P3 2026-06-12: dark ink for text on BRIGHT brand-color chips (teal/pink/amber). Theme-agnostic — chip backgrounds are bright in BOTH dark + peach, so peach inherits this (no override needed), same precedent as --source-tint. */
  /* Phase C: board palette — et-gold is new; others alias existing vars */
  --et-gold: #D4AF37;
  /* hm-podium .934 (operator: three square gold / silver / bronze buttons beside
     the minimised heatmap for the 24h money podium). Dark values here; peach
     rebinds all three, because the light metallics measure 1.26:1 on the peach
     panel. Within each theme the three are >= 45 apart in RGB so the ranks never
     read as one hue, and each is >= 4.5:1 on its own panel (measured in the
     patch that added them; re-measured by test_hm_podium.py). */
  --medal-1: #facc15;
  --medal-2: #cbd5e1;
  --medal-3: #e2954f;
  /* P4 2026-06-14: venue brand sub-system — colors that recur 10+ times in the file,
     elevated to vars so theme toggles + future re-skinning are single-edit. */
  --platform-manifold-brand: #a78bfa;
  --platform-polyus-brand:   #38bdf8;
  /* P4 2026-06-14: long-tail tokens — promoted from 3-7x-repeated bespoke hex. */
  --white:        #ffffff;   /* pure white for high-contrast text on dark/brand chips */
  --bg-deeper:    #0c1a3a;   /* deeper navy used in radial gradients + overlays */
  --accent-deep:  #0d9488;   /* teal-600, darker accent for dense ink contexts */
  --source-tint: rgba(0,0,0,0.22);   /* Build .284: subtle dark backing behind Marketplace Activity source cells; theme-agnostic black-alpha (reads on dark + peach). Build .286: deepened 0.10 -> 0.22 for stronger venue-name contrast. */
  --live-bg: rgba(239, 68, 68, 0.18);  /* Build .287: theme-agnostic red-alpha backing for the 🔴 LIVE in-play badge (sx.bet); composites over dark + peach. */
  --chip-halo: rgba(0,0,0,0.9);
  --mbn-bg: rgba(13,19,40,0.96);  /* mtabs 2026-07-04: mobile bottom-nav backdrop (navy-alpha; peach rebinds to cream-alpha) */  /* Build .288: dark text-halo so colorful Marketplace venue names pop against their same-hue colorful chip background. Theme-agnostic (a dark outline reads on dark + peach). */

  /* ── P4 2026-06-14: design tokens (the polish layer's foundation) ──────── */
  /* TYPE — 6-step tabular-grid scale (aligned to a 6px rhythm) */
  --t-micro:   11px;
  --t-body:    13px;
  --t-meta:    16px;
  --t-h:       20px;
  --t-section: 28px;
  --t-hero:    44px;

  /* RADIUS — canonical 3-step scale (collapses 20 ad-hoc values to 3) */
  --r-chip:    3px;
  --r-card:    8px;
  --r-pill:    999px;

  /* ELEVATION — three tiers, theme-var driven */
  --e-1: 0 1px 0 var(--border);
  --e-2: 0 1px 0 var(--border), 0 0 0 1px var(--border) inset;
  --e-3: 0 0 18px color-mix(in srgb, var(--jackpot) 28%, transparent);

  /* MOTION — semantic durations (not decorative timings) */
  --m-tick:    1s linear;
  --m-flash:   600ms ease-out;
  --m-flip:    260ms ease-in-out;
  --m-tab:     120ms ease;

  /* TYPE FACES — self-hosted (Task 2 adds the @font-face declarations) */
  --f-led:  "DSEG7 Classic", ui-monospace, Menlo, monospace;
  --f-num:  "IBM Plex Mono Condensed", ui-monospace, monospace;
  --f-text: "Inter Tight", -apple-system, "Segoe UI", Roboto, sans-serif;

  /* SEMANTIC PALETTE — meaning, not color (decoupled from brand vars) */
  --c-money:  var(--jackpot);   /* AMBER — $ amounts, arb edge, payouts, liquidity */
  --c-time:   var(--accent);    /* TEAL  — countdowns, live status, going-live */
  --c-wallet: var(--whale);     /* PINK  — whales, smart money, hall-of-fame */

  /* sizing 2026-08-10 — Risk Console band colors */
  --sizing-under: var(--accent);
  --sizing-near: var(--jackpot);
  --sizing-over: var(--danger);
}

/* P4 2026-06-14: self-hosted webfonts (the --f-* tokens point here) */
@font-face {
  font-family: "Inter Tight";
  src: url("/static/fonts/InterTight-Variable.woff2") format("woff2-variations");
  font-weight: 400 800;
  font-display: swap;
  font-style: normal;
}
@font-face {
  font-family: "IBM Plex Mono Condensed";
  src: url("/static/fonts/IBMPlexMonoCondensed-Regular.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  font-style: normal;
  font-stretch: condensed;
}

/* P4 2026-06-14: type utility classes — apply at element level via templates.
   tabular-nums everywhere so numeric content doesn't jitter on update. */
.is-text {
  font-family: var(--f-text);
  font-feature-settings: "tnum";
}
.is-num {
  font-family: var(--f-num);
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
}
.is-led {
  font-family: var(--f-led);
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
}

/* P4 2026-06-14: semantic palette utility classes (decoupled from brand vars).
   Use these on chips/numbers when you want the SIGNAL color, not the brand color. */
.c-money  { color: var(--c-money); }
.c-time   { color: var(--c-time); }
.c-wallet { color: var(--c-wallet); }
.bg-money  { background-color: color-mix(in srgb, var(--c-money) 14%, transparent); }
.bg-time   { background-color: color-mix(in srgb, var(--c-time)  14%, transparent); }
.bg-wallet { background-color: color-mix(in srgb, var(--c-wallet) 14%, transparent); }

/* P4 2026-06-14: utility-class attachments for selectors with many render sites */
.arb-cd-timer,
.rs-ttr {
  font-family: var(--f-led);
  font-feature-settings: "tnum";
  letter-spacing: 0.03em;
}
.sig-amt,
.sig-score,
.cv-spread,
.se-edge,
.mkt-oi-val,
.mkt-vol-sub,
.jp-amount,
.tk-amount,
.evt-jp-date,
.ut-type-chip {
  font-family: var(--f-num);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.plat-name,
.plat-sub,
.smh-h,
.ct-live-title,
.smh-tab,
.ct-tab,
.lq-tab {
  font-family: var(--f-text);
}
* { box-sizing: border-box; }

/* ────────────────────────────────────────────────────────────────────
   Build v.03 .31 build 159 (2026-05-23): GLOBAL HARD RULE — NO
   HORIZONTAL SCROLL BAR EVER, on any viewport, any page, any layout.
   This is non-negotiable.  When ANY content tries to exceed the
   viewport width, it must wrap, shrink, or be clipped — never push
   the body wider than 100vw.

   Belt + suspenders:
     - overflow-x: clip on <html> AND <body> (clip is stricter than
       hidden — it disables scrolling entirely, no programmatic
       scrollLeft either)
     - max-width: 100vw to prevent any child's intrinsic size from
       widening the body
     - Fallback to overflow-x: hidden on older browsers that don't
       support `clip` (still ~99%+ now, but defensive)

   If you're adding a new component and a horizontal scrollbar
   appears, the BUG is in the component, not in this rule.  Common
   culprits: <pre> with long lines, <table> with non-wrappable cells,
   inline-block rows that can't shrink, fixed-width grids.  Apply
   `min-width: 0` to flex/grid children and `overflow-wrap: anywhere`
   to text containers as needed.
   ──────────────────────────────────────────────────────────────── */
html, body {
  overflow-x: clip;
  max-width: 100vw;
}
@supports not (overflow-x: clip) {
  html, body { overflow-x: hidden; }
}

body {
  margin: 0;
  font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { margin: 0; font-size: 20px; letter-spacing: 0.02em; }
.brand-accent { color: var(--accent); font-weight: 700; }
.brand {
  /* brand-tagline .508: column — the row wrapper alone sets the width (the
     .507 flex-wrap version leaked one phantom 14px column-gap into the
     intrinsic width: 358 vs the row's 344, measured live). */
  display: flex; flex-direction: column; row-gap: 1px;
  flex-shrink: 0; text-decoration: none; color: inherit;
}
/* brand-nudge 2026-07-19 (operator): the EventTracker block sits a little
   closer to the PodComet logo (gap 14 → 6px) so the wordmark stops clashing
   with the search bar to its right. */
/* hdr-brand-tagline 2026-07-20 (operator: "EventTracker logo + text is STILL
   obscured by the search box and slogan box — move it a bit further left,
   closer to the PodComet logo + text"). brand-nudge took the gap 14->6px; this
   closes it to 2px and pulls the block a further 8px, so the wordmark's right
   edge clears the centre zone by ~12px more than before. */
.brand-row { display: flex; align-items: center; gap: 2px; }
/* hdr-align .588 (operator, repeated: "EventTracker logo and text STILL haven't
   moved left"). MEASURED not guessed: the PodComet logo <img> has a 380-wide
   viewBox but its ink ("Comet" + the AI·FEDERATED DATA sub-line) ends at
   viewBox x=271 (getBBox in-browser) = 133px into its 186px box → ~53px of
   built-in trailing whitespace. So the ET block sat ~47px from the visible
   wordmark even with the boxes overlapping; -8px read as nothing. -45px puts
   the stripes ~10px past "Comet"'s last letter. Overlapping the img box is
   safe (transparent padding); at the 62px-logo breakpoint the whitespace
   scales UP (~75px) so the gap only widens — never collides. Tagline start is
   handled separately (.585: it lives in .meta, left edge = Peachy chip). */
.brand-etblock { margin-left: -45px; }
/* brand-tagline-span 2026-07-11: the bars+wordmark sub-column — the tagline
   stretches to THIS block, i.e. exactly the stripes→wordmark span. */
.brand-etblock { display: flex; flex-direction: column; row-gap: 1px; min-width: 0; }
.brand-etrow { display: flex; align-items: center; gap: 14px; }
/* brand-tagline 2026-07-11 (operator, rev 2 — brand-tagline-span): strapline
   spans the 3-BARS → the wordmark's final "r" (comet logo excluded); it
   stretches to .brand-etblock, whose width is the stripes+wordmark row.
   text-align-last justifies the words across that span (left-align fallback). */
.brand-tagline {
  align-self: stretch;
  /* brand-tagline-fit .510: width:0 excludes the tagline from .brand-etblock's
     intrinsic width (safe here — column container, no wrapped-row gap quirk),
     so the bars+wordmark row ALONE sizes the block; min-width:100% stretches
     the tagline back to that span. Font calibrated to fill it: the string
     measures 1877px per 100px of font → 7.5px ≈ 141px of the 145px span,
     text-align-last closes the remainder. 10.5px overshot the wordmark by
     59px (measured live on .509). */
  width: 0; min-width: 100%;
  font-size: 7.5px; font-weight: 600; letter-spacing: 0.02em;
  text-transform: uppercase; white-space: nowrap;
  color: var(--muted);
  text-align-last: justify;
}
.brand:hover { text-decoration: none; }
.brand-logo { display: block; height: 44px; width: auto; }

/* Build .69 (item #1): 0.8×0.8cm decorative box mirroring the three
   primary ticker labels. Uses the exact same backgrounds as
   .tl-events / .tl-whales / .tl-jackpot, so the visual identity
   stays in sync if those CSS vars ever change. Sits on its own
   --bg parent so the alpha-blend renders the same dark-teal /
   pink / dark-brown the user sees on the ticker row.

   Stripe widths: 87% / 100% / 74% — middle is 15% wider than top,
   bottom is 15% narrower than top, per the spec. */
.brand-decoration {
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  width: 0.8cm;
  height: 0.8cm;
  padding: 1px 0;
  background: var(--bg);
  border-radius: var(--r-chip);
  gap: 1px;
  flex-shrink: 0;
}
.brand-stripe {
  display: block;
  height: calc(33.33% - 1px);
  border-radius: var(--r-chip);
}
.brand-stripe-events {
  width: 87%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 55%, transparent), color-mix(in srgb, var(--kalshi) 45%, transparent));
}
.brand-stripe-whales {
  width: 100%;
  background: var(--whale);
}
.brand-stripe-jackpot {
  width: 74%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--jackpot) 55%, transparent), color-mix(in srgb, var(--jackpot) 30%, transparent));
}

.brand-product { display: flex; flex-direction: column; gap: 2px; line-height: 1.15; }
.brand-product-name {
  font-size: 16px; font-weight: 700; color: var(--text);
  letter-spacing: 0.01em;
}
.brand-et-name { color: var(--whale); }
.beta-tag {
  display: inline-block; font-size: 10px; font-weight: 700; color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent); padding: 1px 6px; border-radius: var(--r-chip);
  letter-spacing: 0.08em; vertical-align: middle; margin-left: 4px;
}
.tagline { font-size: 11px; color: var(--whale); font-style: italic; letter-spacing: 0.02em; }
h2 { font-size: 16px; color: var(--muted); margin: 24px 20px 12px; text-transform: uppercase; letter-spacing: 0.1em; }
h3 { font-size: 18px; color: var(--white); margin: 0 0 12px; font-weight: 800; letter-spacing: 0.02em; }
h3 .plat-name { font-size: 18px; font-weight: 900; letter-spacing: 0.04em; text-transform: uppercase; }
h3 .plat-sub { font-size: 14px; color: var(--white); font-weight: 700; }
/* h3 platform tinting */
.dv-chart h3 .plat-name { color: var(--accent); }
.visitor-card h3 .plat-name { color: var(--jackpot); }
h4.section-title { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin: 18px 0 8px; }
.evt-chart-wrap { position: relative; height: 180px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card); padding: 8px; }
.evt-chart-empty { font-size: 11px; color: var(--muted); padding: 8px 0; font-style: italic; }

/* Legacy top-strip styles kept only because some older selectors may still
   reference them; the actual element no longer renders post-Phase-1 reorder. */
.top-strip { display: none; }
.ticker-strip { display: none; }
.ticker-row { display: none; }
/* Jackpot top-10 card sitting in the right half of the top strip */
.jackpot-top10-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 10px 14px; max-height: none; overflow-y: visible;
  border-top: 3px solid var(--jackpot);
}
.jackpot-top10-card .platform { margin-bottom: 8px; padding-bottom: 6px; }
.jackpot-list { list-style: none; margin: 0; padding: 0; counter-reset: jp; }
.jackpot-list .jp-row { counter-increment: jp; border-bottom: 1px solid var(--border); }
.jackpot-list .jp-row:last-child { border-bottom: none; }
.jackpot-list .jp-row-link {
  display: grid; grid-template-columns: 22px 36px 1fr auto; gap: 8px; align-items: baseline;
  padding: 5px 4px; color: var(--text); font-size: 12px;
}
.jackpot-list .jp-row-link::before {
  content: counter(jp);
  font-family: monospace; font-size: 10px; color: var(--muted); text-align: right;
}
.jackpot-list .jp-row-link .sig-plat { font-size: 9px; padding: 2px 4px; align-self: center; }
.jackpot-list .jp-row-link:hover { background: var(--panel-2); text-decoration: none; }
.jackpot-list .jp-row-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jackpot-list .jp-row-amount { font-family: monospace; font-size: 11px; color: var(--jackpot); font-weight: 700; }
.plat-name.jackpot-name { color: var(--jackpot); }
.ticker-label {
  font-size: 10px; letter-spacing: 0.12em; font-weight: 700; flex-shrink: 0;
  padding: 2px 6px; border-radius: var(--r-chip);
}
.ticker-poly .ticker-label { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
.ticker-kalshi .ticker-label { background: color-mix(in srgb, var(--kalshi) 15%, transparent); color: var(--kalshi); }
.ticker-manifold .ticker-label { background: color-mix(in srgb, var(--platform-manifold-brand) 15%, transparent); color: var(--platform-manifold-brand); }
.ticker-sxbet .ticker-label { background: rgba(236,72,153,0.15); color: var(--sxbet); }
.ticker-limitless .ticker-label { background: rgba(249,115,22,0.15); color: var(--limitless); }
/* Legacy .ticker-item rule removed (was: flex:1; min-width:0; overflow:hidden).
   That style was for the original per-platform top-strip ticker rows where
   each row had a single .ticker-item child meant to fill remaining space.
   Phase 1's reorder removed top-strip, but this rule was still inherited
   by the marquee .ticker-item items inside .ticker-track. Combined with
   flex layout on .ticker-track, it forced every marquee item to shrink to
   1/N of the track width and clipped longer fields like titles. */
.ticker-link {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  color: var(--text); text-decoration: none; min-width: 0;
}
.ticker-link:hover .ticker-title { color: var(--accent); }
.ticker-title {
  font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0;
}
.ticker-vol { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.ticker-placeholder { font-size: 11px; color: var(--muted); font-style: italic; }

@media (max-width: 800px) {
  .ticker-strip { grid-template-columns: 1fr; }
}

/* Viewer pill — sticks to the bottom-right corner of the WEB PAGE (not the
   viewport). Body is the offset parent, so absolute positioning anchors it
   to the page bottom-right and it scrolls away with the page. */
body { position: relative; }
.viewer-pill {
  position: absolute; right: 16px; bottom: 16px; z-index: 5;
  background: rgba(13,19,40,0.92);
  border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: 6px 12px; font-size: 11px; color: var(--text);
  display: flex; align-items: center; gap: 6px;
  box-shadow: 0 6px 24px rgba(0,0,0,0.35); cursor: pointer;
}
.viewer-pill:hover { border-color: var(--accent); }
.vw-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 70%, transparent); animation: vwPulse 1.8s infinite; }
@keyframes vwPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
.vw-total { font-weight: 700; font-size: 13px; color: var(--accent); }
.vw-all-unique { font-weight: 700; font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
.vw-sep { color: var(--muted); opacity: 0.5; }
.vw-label { color: var(--muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; }
.vw-flag { font-size: 11px; } /* .313: reduced for compact widget */
.vw-cc { color: var(--muted); width: 20px; font-variant-numeric: tabular-nums; font-size: 10px; }
.vw-n { margin-left: auto; font-variant-numeric: tabular-nums; font-size: 10px; }
.vw-list { list-style: none; margin: 0; padding: 0; }
.vw-list li { display: flex; align-items: center; gap: 6px; padding: 2px 0; border-top: 1px solid rgba(255,255,255,0.04); font-size: 12px; }

/* Visitor globe card (bottom of page — replaces jackpot) */
.visitor-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 14px 16px;
}
/* ─── Visitor card (bottom of page) ───
   Layout: globe on left, stats panel on right.
   Stats panel = 3-stat row (online / all-time unique / all-time visits)
   on top, country list spanning full width on row 2. */
.visitor-body {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 18px; align-items: stretch;
}
.vw-globe-bottom {
  width: 200px; height: 200px; margin: 0 auto;
  border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 50% 50%, var(--bg-deeper) 0%, var(--bg) 100%);
  display: flex; align-items: center; justify-content: center;
}
.vw-globe-bottom canvas { display: block; margin: auto; }

.vw-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto auto;
  gap: 12px;
  min-width: 0;        /* let the country list shrink instead of overflowing right */
}
.vw-stat {
  background: var(--panel-2); border-radius: var(--r-card); padding: 12px 10px;
  text-align: center; min-width: 0;
}
.vw-stat-num {
  font-family: monospace; font-size: 22px; font-weight: 800;
  color: var(--accent); line-height: 1.1;
}
.vw-stat-lbl {
  font-size: 10px; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.08em; margin-top: 4px;
}
/* admin-users-list 2026-08-20: the Registered-users stat is a link now -
   keep the tile look, add only the affordance (vars only). */
.vw-stat-link { display: block; color: inherit; text-decoration: none; cursor: pointer; }
.vw-stat-link:hover { outline: 1px solid var(--accent); outline-offset: -1px; }

/* Build .300: sub-line under a stat label (e.g. "Since June 2026" under
   returning visitors) — smaller + dimmer + sentence-case so it reads as a
   footnote, not a second label. */
.vw-stat-sub {
  font-size: 8px; color: var(--muted); opacity: 0.8;
  letter-spacing: 0.03em; margin-top: 2px;
}
.vw-list.vw-list-bottom {
  grid-column: 1 / -1;        /* span all 3 stat columns on row 2 */
  list-style: none; margin: 0; padding: 8px 0 0;
  border-top: 1px solid var(--border);
  max-height: 140px; overflow-y: auto;
  font-size: 11px;
  /* Reset older standalone styling that used to draw a left border */
  border-left: none; padding-left: 0;
}
.vw-list.vw-list-bottom li {
  display: flex; justify-content: space-between; align-items: center;
  padding: 3px 4px;
}
@media (max-width: 800px) {
  .visitor-body { grid-template-columns: 1fr; }
  .vw-stats { grid-template-columns: repeat(3, 1fr); }
}
.vw-modal { max-width: 720px; width: 90vw; }
.vw-globe-big { width: 100%; height: 400px; border-radius: var(--r-card); overflow: hidden; background: radial-gradient(circle at 50% 50%, var(--bg-deeper) 0%, var(--bg) 100%); margin: 12px 0; }
.vw-list-big { max-height: 180px; }

/* ─── Header ─── */
header {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 16px;
  padding: 14px 20px; border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, #101735, var(--bg));
}
.meta { color: var(--muted); font-size: 12px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.alive-toggle {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-card);
  cursor: pointer; font-size: 11px; color: var(--text); user-select: none;
}
.alive-toggle:hover { border-color: var(--accent); }

/* .403 (f): signed-in user indicator in the header (online dot + name → portfolio,
   gear → account). Only rendered for authenticated users. */
.hdr-user {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--r-card);
  font-size: 11px; max-width: 180px;
}
.hdr-user-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: var(--success);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 60%, transparent);
  animation: hdrUserPulse 2.4s ease-out infinite;
}
@keyframes hdrUserPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 55%, transparent); }
  70%  { box-shadow: 0 0 0 5px color-mix(in srgb, var(--success) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 0%, transparent); }
}
.hdr-user-name {
  color: var(--text); font-weight: 700; text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.hdr-user-name:hover { color: var(--accent); }
.hdr-user-gear { color: var(--muted); text-decoration: none; flex: 0 0 auto; }
.hdr-user-gear:hover { color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .hdr-user-dot { animation: none; } }

/* ── Right-side header cluster + Trackster mascot ───────────────────────────
   .header-right groups the Telegram CTA + the three controls so they sit close
   together (no space-between gap), and lets the mascot anchor the far corner. */
.header-right {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 14px; flex-wrap: wrap; margin-left: auto;
}
/* hdr-brand-tagline 2026-07-20, re-homed .585: the tagline is now the last
   child of .meta and wraps onto its own full-width row WITHIN .meta, so its
   left edge is .meta's content-left = the Peachy chip's left edge (operator:
   "begin on the left where the Peachy icon starts"). Plain left-align — no
   more edge-to-edge justify, which belonged to the full-header-right span.
   Theme-var colour; no literals. */
.hdr-tagline { flex: 1 0 100%; width: 100%; margin-top: 0; text-align: left;
  color: var(--muted); font-size: 10.5px; letter-spacing: .01em; white-space: normal; }
@media (max-width: 900px) { .hdr-tagline { display: none; } }
/* Trackster waves in the top-right corner, above the right end of the tickers.
   The arm-wave is a Lottie animation (damped-sine swing about the shoulder),
   rendered by lottie-web into each .header-mascot container. */
.header-mascot {
  flex: 0 0 auto; width: 112px; height: auto; align-self: flex-end;
  aspect-ratio: 640 / 916;       /* divs have no intrinsic size — size like the old <img> */
  margin: -4px -2px -16px 4px;   /* lift a touch + let the feet sit on the ticker */
  position: relative; z-index: 6; pointer-events: none; user-select: none;
}
.header-mascot svg { display: block; width: 100%; height: 100%; }
/* Trackster wears shades on DARK (default) and goes bare-faced on peachy/day. */
.header-mascot--day { display: none; }
:root[data-theme="peach"] .header-mascot--dark { display: none; }
:root[data-theme="peach"] .header-mascot--day { display: block; }
.alive-toggle input { accent-color: var(--accent); }
.alive-toggle:has(input:checked) { background: color-mix(in srgb, var(--accent) 15%, transparent); border-color: var(--accent); color: var(--accent); }

/* Build v0.35 20260523.173 (2026-05-23): donation widget — replaces
   the "Last updated:" timestamp in the top-right meta strip.  The
   button uses a warm gold-pink gradient so it pops against the cool
   header background without screaming for attention. */
.donate-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--r-card);
  font-size: 12px; font-weight: 700; color: var(--bg);
  background: linear-gradient(135deg, var(--jackpot) 0%, var(--whale) 100%);
  border: 1px solid color-mix(in srgb, var(--jackpot) 50%, transparent);
  cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  transition: transform 120ms ease, box-shadow 120ms ease;
  text-decoration: none;
}
.donate-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 3px 8px color-mix(in srgb, var(--jackpot) 35%, transparent);
}
.donate-btn .donate-icon {
  width: 16px; height: 16px; display: block; border-radius: var(--r-chip);
}
.donate-btn-disabled {
  background: var(--panel-2);
  color: var(--muted);
  border-color: var(--border);
  cursor: not-allowed; opacity: 0.55;
}
.donate-btn-disabled:hover { transform: none; box-shadow: none; }

/* Donation modal */
.donate-modal {
  max-width: 540px;
}
.donate-title-icon {
  width: 22px; height: 22px; vertical-align: -4px;
  margin-right: 6px; border-radius: var(--r-chip);
}
.donate-intro {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
  margin: 4px 0 16px 0;
}
.donate-wallet-block {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 12px 14px;
  margin-bottom: 16px;
}
.donate-wallet-lbl {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 6px;
}
.donate-wallet-row {
  display: flex; align-items: center; gap: 8px;
}
.donate-wallet-addr {
  flex: 1;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  color: var(--text);
  padding: 6px 8px;
  border-radius: var(--r-chip);
  word-break: break-all;
  user-select: all;
}
.donate-copy-btn {
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: var(--r-chip);
  cursor: pointer;
  white-space: nowrap;
}
.donate-copy-btn:hover {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
}
.donate-wallet-hint {
  font-size: 11px;
  color: var(--muted);
  margin-top: 6px;
  font-style: italic;
}
.donate-form {
  display: flex; flex-direction: column; gap: 12px;
}
.donate-row {
  display: flex; flex-direction: column; gap: 4px;
}
.donate-row-2col {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: 12px;
}
.donate-col {
  display: flex; flex-direction: column; gap: 4px;
}
.donate-label {
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
}
.donate-opt {
  font-weight: 400; opacity: 0.7;
}
.donate-input {
  font-size: 13px;
  padding: 7px 10px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-chip);
  color: var(--text);
  font-family: inherit;
}
.donate-input:focus {
  outline: none;
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.donate-input-mono {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
}
.donate-textarea {
  resize: vertical;
  min-height: 60px;
  font-family: inherit;
}
.donate-actions {
  display: flex; align-items: center; gap: 12px;
  margin-top: 4px;
}
.donate-submit {
  padding: 8px 18px;
  font-size: 13px;
  font-weight: 700;
  color: var(--bg);
  background: linear-gradient(135deg, var(--jackpot) 0%, var(--whale) 100%);
  border: 1px solid color-mix(in srgb, var(--jackpot) 50%, transparent);
  border-radius: var(--r-card);
  cursor: pointer;
}
.donate-submit:hover { filter: brightness(1.08); }
.donate-status {
  font-size: 12px;
  color: var(--muted);
}
.donate-status-pending { color: var(--muted); }
.donate-status-ok      { color: var(--success); }
.donate-status-err     { color: var(--danger); }

/* Build v0.4 (operator 2026-06-07): Contact-us modal. Inherits most styling
   from .donate-form / .donate-modal / .donate-input; only the contact-
   specific extras live here. Theme vars only → auto-themes for peach. */
.contact-modal { max-width: 480px; }
.contact-intro { font-size: 13px; color: var(--muted); margin: 4px 0 12px; line-height: 1.5; }
.contact-to-row { gap: 6px; }
.contact-to-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--r-card);
  font-family: monospace; font-size: 13px;
  color: var(--text);
  width: fit-content;
}
.contact-to-icon { color: var(--accent); font-size: 14px; line-height: 1; }
.contact-to-addr { font-weight: 600; }
.contact-textarea {
  resize: vertical; min-height: 100px;
  font-family: inherit; line-height: 1.5;
}
/* Honeypot — visually hidden but still focusable to screen readers; bots
   parsing the DOM see a normal input and fill it. We DO NOT use
   display:none (some bots skip those); off-screen + tabindex=-1 is the
   classic pattern. */
.contact-honeypot {
  position: absolute !important;
  left: -10000px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}
/* "Cancel" button styled lighter than the primary "Send" CTA */
.donate-submit-cancel {
  background: transparent !important;
  color: var(--muted) !important;
  border: 1px solid var(--border) !important;
}
.donate-submit-cancel:hover {
  color: var(--text) !important;
  border-color: var(--text) !important;
}
/* Footer "Contact us →" button: looks like a link, behaves like a button. */
.footer-contact-btn {
  background: transparent; border: none; padding: 0;
  color: var(--accent); cursor: pointer;
  font: inherit; text-decoration: underline;
  text-underline-offset: 2px;
}
.footer-contact-btn:hover { color: var(--text); }
.donate-fineprint {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
  line-height: 1.5;
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
}
@media (max-width: 540px) {
  .donate-row-2col { grid-template-columns: 1fr; }
}

/* Build .94: Telegram subscribe CTA in the header.  Vibrant Telegram-
   blue → emerald-green gradient (cheerful palette, distinct from the
   site's teal/blue accent so it visibly stands out).  Paper-plane
   icon with a subtle "fly" animation on hover.  Sits between the
   search box and the meta block. */
/* P0 2026-06-08: admin-gated ET& Subscribe CTA. Amber (--jackpot) = premium/"yours".
   All theme vars -> auto-themes for peach. Hidden for non-admins via .admin-only. */
.subscribe-now-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r-card);
  font-size: 13px; font-weight: 700; text-decoration: none; white-space: nowrap;
  color: var(--bg, var(--bg));
  background: var(--jackpot);
  border: 1px solid var(--jackpot);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--jackpot) 40%, transparent);
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.subscribe-now-btn:hover { filter: brightness(1.08); }
.subscribe-now-btn:active { filter: brightness(0.94); }

/* .449: the .tg-subscribe-btn element was REMOVED from the free header
   (Telegram alerting became ET&-only). The rules below are inert and kept
   only to avoid churn; safe to delete in a cleanup pass. */
.tg-subscribe-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: linear-gradient(135deg, #229ED9 0%, #34D399 100%);
  color: var(--white);
  text-decoration: none;
  border-radius: var(--r-card);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  box-shadow:
    0 2px 12px rgba(34, 158, 217, 0.40),
    0 0 0 0 rgba(52, 211, 153, 0);
  transition: transform 0.18s ease, box-shadow 0.25s ease;
  border: none;
  cursor: pointer;
  white-space: nowrap;
  /* Subtle idle pulse so the button has life even without hover. */
  animation: tg-btn-pulse 3.2s ease-in-out infinite;
}
.tg-subscribe-btn:hover {
  transform: translateY(-1px) scale(1.04);
  box-shadow:
    0 4px 20px rgba(34, 158, 217, 0.60),
    0 0 0 4px rgba(52, 211, 153, 0.22);
  animation: none;   /* Halt the pulse so hover takes over cleanly. */
}
.tg-subscribe-btn:active {
  transform: translateY(0) scale(0.98);
}
.tg-subscribe-btn .tg-icon {
  font-size: 15px;
  display: inline-block;
  transform: rotate(-20deg);
  transition: transform 0.3s ease;
}
.tg-subscribe-btn:hover .tg-icon {
  animation: tg-fly 0.55s ease-in-out;
}
@keyframes tg-fly {
  0%   { transform: rotate(-20deg) translate(0, 0); }
  40%  { transform: rotate(-35deg) translate(3px, -3px); }
  100% { transform: rotate(-20deg) translate(0, 0); }
}
@keyframes tg-btn-pulse {
  0%, 100% {
    box-shadow:
      0 2px 12px rgba(34, 158, 217, 0.40),
      0 0 0 0 rgba(52, 211, 153, 0);
  }
  50% {
    box-shadow:
      0 3px 16px rgba(34, 158, 217, 0.55),
      0 0 0 6px rgba(52, 211, 153, 0.12);
  }
}
/* Mobile: shrink padding + text size so it still fits in the header
   when stacked.  On narrowest breakpoint it sits inline with the
   search box (flex-wraps). */
@media (max-width: 900px) {
  .tg-subscribe-btn {
    padding: 7px 12px;
    font-size: 11px;
  }
  .tg-subscribe-btn .tg-icon { font-size: 13px; }
}
@media (max-width: 700px) {
  .tg-subscribe-btn {
    order: 13;        /* sit at the very end after search + meta on mobile */
    margin-left: auto;
  }
}
.hidden-note { color: var(--muted); font-size: 10px; font-weight: normal; text-transform: none; letter-spacing: 0; }
.ts { color: var(--text); font-family: monospace; }
.collect-btn {
  background: var(--accent); color: var(--bg); border: none; padding: 6px 14px;
  border-radius: var(--r-chip); font-weight: 600; font-size: 12px; cursor: pointer;
  letter-spacing: 0.05em; text-transform: uppercase;
}
.collect-btn:hover:not(:disabled) { background: #5eead4; }
.collect-btn:disabled { opacity: 0.6; cursor: wait; }
.collect-status { font-family: monospace; font-size: 11px; }
.collect-status.ok { color: var(--accent); }
.collect-status.err { color: var(--danger); }

/* Build .54: hero subtitle now lives INSIDE the header flex row,
   spanning the middle column between the brand block (left) and the
   search/meta block (right). Gradient text fill preserved. The old
   .hero-subtitle / .hero-subtitle-text full-width band classes are
   gone — replaced by a single .hero-subtitle-inline. */
.hero-subtitle-inline {
  margin: 0;
  max-width: 100%;
  text-align: center;
  /* Build .281: ONE line — scales down on narrow viewports so it never
     wraps (until the <=600px rule lets it wrap to avoid clipping). */
  font-size: clamp(11px, 1.1vw, 14px);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.25;
  /* Build .228: solid var(--whale) pink to match the EventTracker brand name. */
  color: var(--whale);
  /* Build .246: thin gold outline to frame the tagline */
  border: 1px solid color-mix(in srgb, var(--jackpot) 45%, transparent);
  border-radius: var(--r-card);
  padding: 4px 12px;
  white-space: nowrap;   /* Build .281: single line */
  word-break: keep-all;
}
/* Build .282: second tagline clause ("come to EventTracker to KNOW") in mint green. */
.hero-know { color: var(--mint); }
/* Build .256: legal disclaimer — small all-caps line inside the gold border */
.hero-disclaimer {
  display: block;
  width: 100%;
  font-size: 8px;
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
  line-height: 1.3;
  text-align: center;
  opacity: 0.75;
}
@media (max-width: 900px) {
  .hero-subtitle-inline { font-size: 16px; }
}
@media (max-width: 600px) {
  /* On small phones let the one-line tagline wrap rather than clip, and
     give the stack full width so the search box isn't cramped. */
  .hero-subtitle-inline { font-size: 14px; margin: 0; white-space: normal; }
  .hero-inner { width: 100%; }
}

/* Build .281: hero tagline + search + disclaimer stacked as their own
   centered, full-width row in the (wrapping) header.  .hero-stack claims a
   100%-basis row below the brand/controls row (order:5); .hero-inner is
   sized to the one-line tagline (width:fit-content) so the search box
   stretches to exactly the tagline's width, with the disclaimer beneath. */
.hero-stack {
  /* Build .282: inline in the header row -- sits between the brand
     (...BETA) and the Telegram CTA.  Drops to its own full-width row at
     <=1000px (media rule below) where there isn't room inline. */
  display: flex;
  flex: 0 1 auto;
  justify-content: center;
  min-width: 0;
}
.hero-inner {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: fit-content;       /* = the one-line tagline's width */
  max-width: 100%;
  gap: 6px;
  margin: 0;
}
.hero-inner .hero-subtitle-inline { align-self: center; }
.hero-inner .search-box {
  position: relative;
  flex: 0 0 auto;           /* auto height in the column (override 0 1 260px) */
  order: 0;                 /* override the <=1000/<=768 search-box reorders */
  width: 100%;              /* stretch to the inner width = tagline width */
  max-width: 100%;
  margin: 0;                /* override margin-left:auto */
}
/* Build .282: at <=1000px the hero drops to its own full-width row below
   the brand/controls row -- there, push the Telegram CTA + meta right
   (brand stays left).  On desktop the hero is inline, so space-between
   distributes brand | hero | CTA | meta with the hero between them. */
@media (max-width: 1000px) {
  .hero-stack { flex-basis: 100%; order: 5; }
  /* .header-right already has margin-left:auto (base) — keeps the CTA cluster
     + mascot pinned right when the hero drops to its own full-width row. */
}

/* mob-hdr 2026-07-06 (operator): compress the mobile pre-ticker header "by A
   LOT" — it stacked brand → mascot → controls → hero to ~400px (~half the
   initial viewport). Now a 2-col grid: brand row on top, hero + controls in
   the LEFT column, Trackster owning the RIGHT column — everything above the
   tickers ends no lower than Trackster's shadow (his feet keep their -16px
   overlap onto the ticker). ~400px → ~215px. Desktop (>768px) untouched. */
@media (max-width: 768px) {
  header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 112px;   /* left column | mascot */
    gap: 4px 10px;
    align-items: start;
    padding: 8px 12px 0;   /* no bottom pad — the mascot's feet sit on the ticker */
  }
  .brand { grid-column: 1 / -1; grid-row: 1; }
  /* Break the CTA cluster apart so its children place individually. */
  .header-right { display: contents; }
  .header-mascot {
    grid-column: 2; grid-row: 2 / span 3;   /* .457: +1 left row for the login pill; Trackster's shadow stays lowest */
    align-self: end; justify-self: end;
  }
  .hero-stack {
    grid-column: 1; grid-row: 2;
    order: 0; flex-basis: auto;           /* undo the ≤1000px full-row drop */
    justify-content: stretch; min-width: 0;
  }
  .hero-inner { width: 100%; gap: 4px; }
  .hero-subtitle-inline { font-size: 11px; padding: 3px 8px; white-space: normal; }
  .hero-inner .search-box input { font-size: 12px; padding: 5px 9px; }
  /* .449: the Telegram CTA left the free header (ET&-only feature now) —
     one whole row gone; meta rises to row 3 and the mascot spans 2 rows.
     Pre-ticker header shrinks again (~235px → ~200px). */
  header .meta { grid-column: 1; grid-row: 3; }
  /* admin-only CTA (display:none for the public) — admins get a 4th left row */
  /* .457: admin .etand-header-btn retired; the PUBLIC login pill takes the
     bottom-left row (no room right of the mascot at phone width). */
  .etand-login-btn { grid-column: 1; grid-row: 4; justify-self: start; font-size: 10px; }
}

/* etand-login 2026-07-06 (.457): the public ET& login pill (+~150px) tips the
   desktop flex header into a 2nd row in a mid-width band (~1100-1279px, where
   the header is otherwise one row). Pin the hero-stack flex-basis small + let
   the tagline wrap, so the flex line-break reserves room for the pill on one
   row. Live-measured: 1200px 276->169 with this. Above ~1500px + below ~1024px
   the header already fits/wraps at baseline, so the band is scoped. */
@media (min-width: 1001px) and (max-width: 1499px) {
  .hero-stack { flex: 1 1 200px; min-width: 0; }
  .hero-subtitle-inline { white-space: normal; }
}


/* Build .309: wide-desktop banner — three zones with EQUAL side blocks.
   LEFT (.brand) and RIGHT (.header-right: Telegram + Peachy + Donate +
   Trackster) are forced to the SAME column width (--hdr-side) via grid, so
   "their total width equals" by construction.  The brand's logo + EventTracker
   text are enlarged to fill the left column; the CENTER (.hero-stack: slogan +
   search + disclaimer) takes the whole middle and its contents scale up to fit.
   Only applies where there's room (>=1500px); below that the base flexbox header
   + the <=1000px stack handle the responsive fallback unchanged. */
@media (min-width: 1500px) {
  header {
    --hdr-side: 540px;             /* == the right cluster's natural width */
    display: grid;
    grid-template-columns: var(--hdr-side) minmax(0, 1fr) var(--hdr-side);
    align-items: center;
    gap: 24px;
  }
  /* LEFT — enlarge the PodComet logo + EventTracker text (~1.35x) to fill it */
  .brand-row, .brand-etrow { gap: 16px; }  /* brand-tagline .508/.rev2: both rows share the gap */
  .brand-tagline { font-size: 10px; }  /* brand-tagline-fit .510: the 22px wordmark row spans ~194px */
  .brand-logo { height: 62px; }
  .brand-decoration { width: 1.0cm; height: 1.0cm; }
  .brand-product-name { font-size: 22px; }

  /* RIGHT — pin the cluster to the right edge of its equal column */
  .header-right { justify-content: flex-end; margin-left: 0; }

  /* CENTER — slogan + search + disclaimer, as large as fits the middle zone */
  .hero-stack { justify-content: center; }
  .hero-inner { width: 100%; max-width: 100%; gap: 8px; }
  .hero-inner .hero-subtitle-inline {
    font-size: clamp(15px, 1.25vw, 21px);
    white-space: normal;           /* wrap rather than clip if the zone narrows */
    padding: 6px 16px;
    width: 100%;
  }
  .hero-inner .search-box input { font-size: 14px; padding: 8px 12px; }
  .hero-disclaimer { font-size: 11px; }
}

/* ─── Search ─── */
.search-box { position: relative; flex: 0 1 260px; margin-left: auto; }
.search-box input {
  width: 100%; padding: 5px 10px; background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--r-card); color: var(--text); font-size: 12px; outline: none;
  text-align: center;   /* Build .282: center-align the placeholder + typed query */
}
.search-box input:focus { border-color: var(--accent); }
.search-results {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 4px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  display: none; max-height: 60vh; overflow-y: auto; z-index: 50;  /* Build .288: taller (was 320px) now the 5-item cap is lifted; stays scrollable + viewport-bounded */
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.search-results.open { display: block; }
.sr-item {
  display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: center;
  padding: 8px 12px; border-bottom: 1px solid var(--border); cursor: pointer; color: var(--text);
}
.sr-item:last-child { border-bottom: none; }
.sr-item:hover { background: var(--panel-2); text-decoration: none; }
/* search-keys 2026-08-30: the KEYBOARD-highlighted row. Same background as
   :hover so the two states never disagree about what "current" looks like,
   plus an accent rail because a keyboard user gets no pointer to confirm
   where they are. Vars only - it themes with peach for free. */
.sr-item.is-kb { background: var(--panel-2); box-shadow: inset 2px 0 0 var(--accent); }
.sr-plat {
  font-size: 9px; font-weight: 700; padding: 2px 6px; border-radius: var(--r-chip);
  letter-spacing: 0.1em; font-family: monospace;
}
/* search-disambiguation 2026-07-11 (operator): cross-venue disambiguation card
   in the search dropdown — accent-tinted so it reads as "same event, N venues". */
.sr-xv { border-left: 3px solid var(--accent); }
.sr-xv-tag { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.sr-xv-venues { font-size: 10px; color: var(--muted); font-weight: 400; }
.sr-poly { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
.sr-kalshi { background: color-mix(in srgb, var(--kalshi) 20%, transparent); color: var(--kalshi); }
.sr-title { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sr-vol { font-family: monospace; font-size: 11px; color: var(--muted); }
.sr-empty { padding: 16px; text-align: center; color: var(--muted); font-size: 12px; }
/* Build (2026-06-05): wallet results (hash / username / AKA) + group headers in
   the search dropdown. Wallet rows reuse .sr-item; these add the group label,
   the 👤 tag, and the AKA text. All theme vars. */
.sr-group-label {
  padding: 5px 12px 3px; font-size: 9px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted); background: var(--panel-2);
}
.sr-wallet-tag { background: transparent; padding: 0; font-size: 14px; }
.sr-aka { color: var(--muted); font-weight: 400; font-size: 11px; }

/* ─── Signals row: Anomaly + Top Wallets + Smart-Money (under top strip) ─── */
.signals-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  padding: 8px 20px;
}
@media (max-width: 1200px) {
  .signals-row { grid-template-columns: 1fr 1fr; }
  .wallets-card,
  .marketplace-card { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .signals-row { grid-template-columns: 1fr; }
  .wallets-card,
  .marketplace-card { grid-column: auto; }
}

/* Build .66: 3×2 grid layout for the signals row.
   Layout map (desktop):
     ┌──────────────┬─────────────────┬──────────────┐
     │ Anomaly      │ Marketplace     │ Top-10       │
     │ Watch        │ Activity        │ Movers       │
     │ (.row 1)     │ (.row 1 + 2)    │ (.row 1)     │
     ├──────────────┤                 ├──────────────┤
     │ Smart-Money  │                 │ Reserved     │
     │ Feed         │                 │              │
     │ (.row 2)     │                 │ (.row 2)     │
     └──────────────┴─────────────────┴──────────────┘ */
.signals-row-3x2 {
  /* P1a 2026-06-08: board + marketplace lifted to the departures-band; the 4
     survivors (smartmoney, latest-analysis, movers, liq) auto-tile into a 2×2
     (no explicit grid-column/grid-row → no holes). */
  /* P3 2026-06-12: modular auto-flow — cards tile/reflow with no holes; a card
     hidden by NO-EMPTY-BOXES simply drops out. */
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  grid-auto-rows: auto;
  align-items: stretch;
}
/* Make sure the inner placeholder body grows to fill the card so the
   "Wiring up in .67" / "Reserved" text sits centered vertically. */
.signals-row-3x2 .signals-card { display: flex; flex-direction: column; }
.signals-row-3x2 .placeholder-body { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }

/* P3 2026-06-12: secondary-grid card chips (resolving / cross-venue / sharp-edge / model-edge) */
.rs-ttr { font-variant-numeric: tabular-nums; font-weight: 700; }
.rs-ttr-red { color: var(--danger); } .rs-ttr-amber { color: var(--jackpot); }
.rs-ttr-green { color: var(--success); } .rs-ttr-gray { color: var(--muted); }
.rs-leader { color: var(--muted); }
.cv-venues { color: var(--muted); font-variant-numeric: tabular-nums; }
/* fairprice-cv 2026-07-12 (operator design B): Fair Price chip on the
   Cross-Venue card. Static (free) by default; .cv-fair-live is the ET&
   client-side upgrade (live value + pulse). Colors via vars only. */
.cv-fair {
  font-family: monospace; font-size: 10px; font-weight: 700;
  color: var(--accent); border: 1px solid var(--accent);
  border-radius: var(--r-chip); padding: 0 4px;
  white-space: nowrap; flex-shrink: 0;
}
.cv-fair-live { animation: cv-fair-pulse 2.4s ease-in-out infinite; }
@keyframes cv-fair-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
.cv-spread { font-variant-numeric: tabular-nums; font-weight: 700; }
.cv-spread-green { color: var(--success); } .cv-spread-amber { color: var(--jackpot); } .cv-spread-muted { color: var(--muted); }
.se-edge { font-weight: 700; font-variant-numeric: tabular-nums; }
.se-buy { color: var(--success); } .se-fade { color: var(--danger); }
.se-prices { color: var(--muted); font-variant-numeric: tabular-nums; }
.me-dir.me-underpriced { color: var(--success); } .me-dir.me-overpriced { color: var(--danger); }
.me-band { font-weight: 700; }
.me-score { font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }   /* 2026-06-13: raw 0-100 ETScore chip, colour by .me-band-*. 2026-06-14: nowrap so "ET 34.2" never breaks. */
.me-band-strong { color: var(--success); } .me-band-moderate { color: var(--jackpot); } .me-band-weak { color: var(--muted); }
.me-ettau { color: var(--accent); font-variant-numeric: tabular-nums; }
.resolving-card { border-top: 3px solid var(--whale); }
.crossvenue-card { border-top: 3px solid var(--jackpot); }
.sharpedge-card { border-top: 3px solid var(--accent); }
.modeledge-card { border-top: 3px solid var(--accent); }
/* P1a 2026-06-08: board-card + marketplace-card lifted to the departures-band.
   The 4 survivors (smartmoney, latest-analysis, movers, liq) AUTO-PLACE into the
   2-col grid above — no explicit grid-column/grid-row, so hiding/removing a card
   never leaves a hole (honors NO EMPTY BOXES). Dissolves further in P2/P3. */

/* Two-column fallback (build .82: Movers + Topics now side-by-side on the
   bottom row, mirroring Anomaly + Smart-Money above).
   Build v0.35 20260523.190: Smart-Money ↔ Anomaly swap also applies
   here — Smart-Money on left (col 1), Anomaly on right (col 2). */
@media (max-width: 1200px) {
  .signals-row-3x2 {
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: auto;
  }
  /* P1a 2026-06-08: survivors auto-place (board + marketplace now in the band). */
}
/* Mobile single-column: everything stacks.
   Build v0.35 20260523.190: explicit `order` on the swapped cards so
   the mobile stack also shows Smart-Money above Anomaly (without
   touching the HTML source order). */
@media (max-width: 900px) {
  .signals-row-3x2 { grid-template-columns: 1fr; grid-template-rows: none; }
  /* Build v0.35 20260525.222: board-card in place of anomaly-card */
  .signals-row-3x2 .board-card,
  .signals-row-3x2 .smartmoney-card,
  .signals-row-3x2 .marketplace-card,
  .signals-row-3x2 .latest-analysis-card,
  .signals-row-3x2 .movers-card,
  .signals-row-3x2 .liq-card { grid-column: auto; grid-row: auto; }
  /* board-card first in source order so it appears at top of mobile stack */
  .signals-row-3x2 .smartmoney-card  { order: -1; }
}

/* Build v0.35 20260525.222: movers-card top/bottom split.
   Top half = 🚀 Top-10 Movers.  Bottom half = ⚠ Anomalies. */
.movers-card { border-top: 3px solid var(--accent); display: flex; flex-direction: column; overflow: hidden; }
.movers-top-half {
  flex: 1 1 50%;
  overflow-y: auto;
  overflow-x: hidden;
  padding-bottom: 6px;
  min-height: 0;
}
.movers-bottom-half {
  flex: 1 1 50%;
  border-top: 2px solid var(--danger);
  padding-top: 6px;
  overflow-y: auto;
  min-height: 0;
}
.movers-bottom-half h3 { margin: 0 0 4px; padding: 0 10px; font-size: 12px; }

/* Build v0.35 20260525.222: board-card — Federated Board in the
   ex-anomaly slot (col 1, row 2 of the 3×2 signals grid). */
/* P1a 2026-06-08: Departures-Board center band, two tracks since markets-hub
   (2026-08-20): column 1 = the cross-venue card, then the free Market Alerts;
   column 2 = .hm-board-stack (heatmap, Hot-200, Advanced Event Info).
   events-band-dead-placement-rules: the 2.2fr split used to be keyed on
   :not(:has(.marketplace-card)), always true once that card left the band, so it
   sits on this rule now and the three-track value it overrode is gone.
   All theme vars → auto-peach. */
.departures-band {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.2fr);
  gap: 12px; padding: 8px 20px; align-items: start;
}

/* P4 2026-06-14: signature decorative anchor — amber Solari frame.
   The center band is the ONLY element on the page that gets this treatment. */
.departures-band {
  position: relative;
  border: 1px solid color-mix(in srgb, var(--c-money) 35%, transparent);
  border-radius: var(--r-card);
  box-shadow: var(--e-3);
}
.departures-band::before,
.departures-band::after,
.departures-band > .departures-band-corner-tr,
.departures-band > .departures-band-corner-bl {
  content: "";
  position: absolute;
  width: 12px;
  height: 12px;
  border: 2px solid var(--c-money);
  pointer-events: none;
}
.departures-band::before                       { top: -1px;    left: -1px;   border-right: 0;  border-bottom: 0; }
.departures-band::after                        { bottom: -1px; right: -1px;  border-left: 0;   border-top: 0;    }
.departures-band > .departures-band-corner-tr  { top: -1px;    right: -1px;  border-left: 0;   border-bottom: 0; }
.departures-band > .departures-band-corner-bl  { bottom: -1px; left: -1px;   border-right: 0;  border-top: 0;    }

/* board-fit 2026-09-04 (operator: "get rid of unused real estate at the bottom
   of the HOT-200 box"). Was align-self:stretch, which sized this card to the
   LEFT FLANK rather than to its own rows - see the board-card-list note below
   for the two defects that produced. */
.departures-band .board-card { align-self: start; display: flex; flex-direction: column; }
.departures-band > .signals-card { min-width: 0; }
.departures-band .crossvenue-card { grid-column: 1; grid-row: 1; align-self: start; min-width: 0; }   /* 2026-06-15: Cross-Venue holds the left-flank top slot (was control-tower alerts, now the strip under the tickers) */
/* hm-stack 2026-09-05 (operator: "pull the hot 200 list box up until it is right
   under the mini-heatmap box"). ⚠⚠ GRID ROWS ARE SHARED ACROSS COLUMNS, which
   is where the gap came from: .919 placed the map at col2/row1 and the board at
   col2/row2, so row 1 took the height of the TALLER cell in it - the cross-venue
   card in column 1 - and the board began below that. Browser-measured at
   1440x900 with a 560px cross-venue card against the 236px map: 324px of empty
   column, 0px after. The two boxes now share ONE cell spanning both rows and
   stack inside it, so the board sits exactly one row-gap under the map whatever
   column 1 does. They remain SIBLINGS - the map is still its own box. */
.departures-band .hm-board-stack { grid-column: 2; grid-row: 1 / -1; display: flex;
                                   flex-direction: column; gap: 12px; min-width: 0;
                                   align-self: start; }
.departures-band .hm-mini            { align-self: start; min-width: 0; margin-top: 0; }   /* alerts-etand 2026-09-05: the map is its own top box; margin-top is the in-board spacing it no longer needs. No grid placement: it and Hot-200 are flex items inside the stack (events-band-dead-placement-rules) */
/* events-alerts-placement-2 (operator 2026-09-13): column 1 = the cross-venue card,
   then the free Market Alerts DIRECTLY under it; the lq-box (ADVANCED EVENT INFO)
   moved into column 2's stack under Hot-200, so it has no grid placement of its own.
   The alerts block is a DIRECT band child with only its column pinned: auto-placement
   puts it in row 2 under the card, or in row 1 when no card rendered.
   ⚠ Row 2 is 1fr ON PURPOSE. The column-2 stack spans both rows; with two auto rows
   its height is shared out over both and column 1's second box lands far below the
   first - measured at .942 1440x900: 530.8px between the cross-venue card and the
   lq-box that sat there. An item crossing a flexible track is left out of auto-row
   sizing, so row 1 is exactly the card's height. Keyed on BOTH boxes: an explicit
   row 2 with nothing in it would still keep its 12px gutter (NO EMPTY BOXES). */
.departures-band > .sa-block { grid-column: 1; }
.departures-band:has(.crossvenue-card):has(> .sa-block:not([hidden])) { grid-template-rows: auto 1fr; }
/* Left flank empty (no cross-venue card, no visible alerts) -> the column-2 stack
   takes the whole band, no hole. Was keyed on the lq-box, which left column 1
   above; its board/marketplace reflow targeted a card that left the band at
   markets-hub 2026-08-20. */
.departures-band:not(:has(.crossvenue-card)):not(:has(> .sa-block:not([hidden]))) { grid-template-columns: minmax(0, 1fr); }
.departures-band:not(:has(.crossvenue-card)):not(:has(> .sa-block:not([hidden]))) .hm-board-stack { grid-column: 1; }
/* P1a 2026-06-08: in the band the board list sizes to its visible segment
   (~20 rows) — the legacy `flex: 1 1 0` collapsed to ~0 here because the band
   (align-items:start) gives no fixed cell height for the flex-basis to fill. */
/* board-fit 2026-09-04: was flex:1 1 0, which grew this list to whatever height
   the card had been stretched to.
   ⚠ TWO defects, one rule. When this was written the card spanned BOTH grid
   rows beside the left flank, so a flank TALLER than the rows need left dead
   space under the last row (what the operator reported), and a flank SHORTER
   made overflow:hidden CLIP the tail with no scroll path. Browser-measured at
   1440x900 with 25 rows: 303px of empty box in the first case, 456px clipped
   and only 9 of 25 rows painted in the second. Sizing to content closes both.
   Since hm-stack (.919) and events-alerts-placement-2 (.944) the card is the
   middle box of .hm-board-stack (heatmap, Hot-200, Advanced Event Info), the
   one column-2 cell spanning both rows; content sizing still keeps it from
   stretching to, or being clipped by, the other column's height.
   The trade is deliberate: the board no longer matches the flank's height
   exactly, so the two columns can end at different points - an honest edge
   beats an empty box or a silently truncated list. */
.departures-band .board-card-list { flex: 0 0 auto; overflow: hidden; }
@media (max-width: 900px) {
  /* .427: the :has() desktop rules above (0-2-0 / 0-3-0) OUT-RANK the plain
     .departures-band selectors this block originally used — media queries add
     no specificity — so the band silently STOPPED stacking the day the lq-box
     rules landed (2026-06-14): board/marketplace kept grid-row:1/-1 inside a
     1-column grid → the grid manufactured implicit side columns → the crushed
     "sliver board" phone bug (operator 2026-07-01). Mirror every :has()
     variant at equal specificity; this block is later in source, so it wins —
     no !important needed. */
  /* .941: the markets-hub 2-track rule (0-2-0) was never mirrored here, so a
     band with no lq-box kept two tracks on a phone and the column-2 stack -
     now also home to Market Alerts - rendered 84px wide (measured 375x900).
     events-band-dead-placement-rules: that split now sits on the plain
     .departures-band rule, which the first selector below mirrors. */
  .departures-band,
  .departures-band:has(.crossvenue-card):has(> .sa-block:not([hidden])),
  .departures-band:not(:has(.crossvenue-card)):not(:has(> .sa-block:not([hidden]))) {
    grid-template-columns: 1fr; grid-template-rows: none;
  }
  .departures-band .board-card,
  .departures-band .crossvenue-card,
  .departures-band > .sa-block,
  /* hm-stack 2026-09-05: ⚠⚠ THE WRAPPER MUST RESET TOO. Browser-measured at
     375x812 before adding it: the stack stayed pinned to grid-column 2 and
     rendered 95px wide - the .427 'sliver board' bug exactly, which .919's
     own entry names as the reason this list swaps dead selectors for live
     ones. Its flex column is what actually stacks the two boxes on a phone. */
  .departures-band .hm-board-stack,
  .departures-band .hm-mini,
  .departures-band:not(:has(.crossvenue-card)):not(:has(> .sa-block:not([hidden]))) .hm-board-stack {
    grid-column: auto; grid-row: auto;
  }
  /* Stacked band cells are auto-height, so the board list's flex:1 1 0 basis
     collapses to ~0 rows (the P1a trap again — see the note above). Fixed-size
     it and give it its own scroll instead. */
  .departures-band .board-card-list { flex: 0 0 auto; max-height: 62vh; overflow-y: auto; }
}

/* ── CTWR 2026-06-10: Control-Tower alert rail ───────────────────────────── */
.control-tower-card { display: flex; flex-direction: column; }
.ct-head { margin: 0; padding: 8px 10px 6px; font-size: 13px; font-weight: 700; }
/* 2026-06-13: alert box tabs (Live Alerts | Closing Soon) */
.ct-tabs { display: flex; gap: 6px; padding: 7px 8px 5px; flex-wrap: wrap; }
.ct-tab { font: inherit; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; }
.ct-tab.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent); }
.ct-panel { display: none; }
.ct-panel.is-active { display: block; }
.ct-ttr-red { color: var(--danger); } .ct-ttr-amber { color: var(--jackpot); }
.ct-ttr-green { color: var(--success); } .ct-ttr-gray { color: var(--muted); }
.ct-list { list-style: none; margin: 0; padding: 0 6px 6px; overflow: hidden; }
.ct-alert {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 4px; font-size: 11px; cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.ct-alert:last-child { border-bottom: 0; }
.ct-alert:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.ct-alert-arb        { background: color-mix(in srgb, var(--accent)  6%, transparent); }
.ct-alert-underdog   { background: color-mix(in srgb, var(--jackpot) 8%, transparent); }
.ct-alert-going_live { background: color-mix(in srgb, var(--accent)  5%, transparent); }
.ct-alert-resolving  { background: color-mix(in srgb, var(--danger)  6%, transparent); }
.ct-alert-surge      { background: color-mix(in srgb, var(--success) 7%, transparent); }
.ct-alert-new_liquid { background: color-mix(in srgb, var(--whale)   6%, transparent); }
.ct-ico { flex-shrink: 0; font-size: 12px; }
.ct-plat-logos { display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; }   /* P3 2026-06-13: venue-logo cluster (1 for single-venue alerts, all venues for arb) */
.ct-plat-logo { flex-shrink: 0; width: 12px; height: 12px; border-radius: var(--r-chip); object-fit: contain; }   /* P3 2026-06-13: platform logo beside the type icon */
.ct-title { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ct-metric { flex-shrink: 0; color: var(--muted); font-variant-numeric: tabular-nums; }
.ct-alert .dep-status { flex-shrink: 0; }

/* 2026-06-15 (operator): LIVE ALERTS landscape boxes — the wrap-grid strip under
   the tickers. Reuses .ct-alert + .ct-alert-{type} (shared tint + mascot hook),
   but lays each alert out as a landscape card colored by TYPE (left stripe +
   label color). Wraps to multiple rows; never a horizontal scrollbar. */
.ct-strip-section { margin: 10px 20px 6px; }
.ct-strip-head { margin-bottom: 6px; }
/* .417: 16 alert boxes in an 8-col × 2-row grid (was 12 flex-wrapped). Equal
   columns + equal row heights; collapses to 4-col then 2-col so no h-scroll. */
.ct-boxes { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); grid-auto-rows: 1fr; gap: 8px; }
@media (max-width: 1200px) { .ct-boxes { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 600px)  { .ct-boxes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ct-box {
  min-width: 0;
  box-sizing: border-box;
  display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-left-width: 4px;
  border-radius: var(--r-card);
  cursor: pointer; overflow: hidden;
  transition: border-color var(--m-tab), background-color var(--m-tab);
}
.ct-box:hover { border-color: var(--accent); }
.ct-box-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.ct-box-type { font-size: 10px; font-weight: 800; letter-spacing: 0.06em; white-space: nowrap; }
.ct-box-title {
  font-size: 12px; line-height: 1.3; color: var(--text); white-space: normal;
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.ct-box-metric { font-size: 13px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
/* .403 (g)+(h): compact detail lines on the LIVE ALERTS boxes — arb BUY/SELL
   legs and the underdog signal breakdown. Small, wrap, theme-aware colors. */
.ct-box-legs, .ct-box-ud {
  display: flex; flex-wrap: wrap; gap: 2px 8px; margin-top: 1px;
  font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.ct-leg-buy  { color: var(--success); }
.ct-leg-sell { color: var(--danger); }
.ct-ud-dog   { color: var(--success); }
.ct-ud-lead  { color: var(--muted); }
.ct-ud-mult  { color: var(--jackpot); }
.ct-ud-new   { color: var(--jackpot); font-weight: 800; }
.ct-ud-fresh { color: var(--success); }
/* Per-type left-stripe + label color (bg tint inherited from .ct-alert-{type}). */
.ct-box.ct-alert-arb        { border-left-color: var(--accent); }
.ct-box.ct-alert-arb        .ct-box-type { color: var(--accent); }
.ct-box.ct-alert-underdog   { border-left-color: var(--jackpot); }
.ct-box.ct-alert-underdog   .ct-box-type { color: var(--jackpot); }
.ct-box.ct-alert-going_live { border-left-color: var(--accent); }
.ct-box.ct-alert-going_live .ct-box-type { color: var(--accent); }
.ct-box.ct-alert-resolving  { border-left-color: var(--danger); }
.ct-box.ct-alert-resolving  .ct-box-type { color: var(--danger); }
.ct-box.ct-alert-surge      { border-left-color: var(--success); }
.ct-box.ct-alert-surge      .ct-box-type { color: var(--success); }
.ct-box.ct-alert-new_liquid { border-left-color: var(--whale); }
.ct-box.ct-alert-new_liquid .ct-box-type { color: var(--whale); }
/* CTWR 2026-06-11: "LIVE ALERTS" rail title — blinking red on Trackster's-paw
   rhythm (the paw Lottie is 120 frames @ 60fps = exactly 2.0s/loop). */
.ct-live-title {
  color: var(--danger); font-weight: 800; letter-spacing: 0.04em;
  animation: ct-live-blink 2s ease-in-out infinite;
}
@keyframes ct-live-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.28; } }
@media (prefers-reduced-motion: reduce) { .ct-live-title { animation: none; } }

/* ── SMH 2026-06-11: Sharp Money Hub (tabbed) ────────────────────────────── */
.sharp-hub { margin: 10px 20px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card); padding: 8px 10px 10px; }
.smh-tabs { display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
/* 2026-06-13 (#9): Liquidity / Model-Edge box — tabbed (Most Liquid | Top by ETScore).
   2026-06-14: relocated INSIDE the departures-band as a 2nd row in the left flank;
   the band's gap:12px owns spacing, so no margin here. */
.lq-tabs { display: flex; gap: 6px; margin-bottom: 6px; flex-wrap: wrap; }
.lq-tab { font: inherit; font-size: 12px; font-weight: 700; padding: 5px 12px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; }
.lq-tab.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent); }
.lq-panel { display: none; }
.lq-panel.is-active { display: block; }
/* 2026-06-20 (operator): cross-venue card tabs — Matched / Disambiguation, 30 events total.
   Mirrors .lq-tabs/.lq-tab/.lq-panel exactly so the visual treatment matches the lq-box below. */
.cv-tabs { display: flex; gap: 6px; margin-bottom: 6px; flex-wrap: wrap; }
.cv-tab { font: inherit; font-size: 12px; font-weight: 700; padding: 5px 12px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; }
.cv-tab.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent); }
.cv-panel { display: none; }
.cv-panel.is-active { display: block; }
/* .410 (etscore-option-display): per-row sub-line naming the scored option +
   price + $vol, stacked UNDER the title so row width is unchanged (the 2026-06-16
   inline attempt crushed the title; this stacks). .411: 3 sub-tabs paginate
   1-10 / 11-20 / 21-30 so all 30 ranked entries are reachable. All theme-vars. */
.lq-box .sig-title-stack { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; gap: 1px; }
.lq-box .me-pick { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lq-box .me-pick-pct { margin-left: 5px; font-variant-numeric: tabular-nums; color: var(--text); }
.lq-box .me-pick-vol { margin-left: 5px; font-variant-numeric: tabular-nums; opacity: 0.8; }
.lq-box .lq-subtabs { display: flex; gap: 5px; padding-top: 2px; margin-bottom: 5px; flex-wrap: wrap; }
.lq-box .lq-subtab { font: inherit; font-size: 10.5px; font-weight: 600; padding: 2px 8px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; font-variant-numeric: tabular-nums; }
.lq-box .lq-subtab.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent); }
.ets-subpanel { display: none; }
.ets-subpanel.is-active { display: block; }
/* hot-movers-tab 2026-07-16: the movers 1h/24h sub-panels — same show/hide
   contract as .ets-subpanel (the ETScore sub-tabs the movers pane now mirrors). */
.mv-subpanel { display: none; }
.mv-subpanel.is-active { display: block; }
.lq-list { list-style: none; margin: 0; padding: 0; }
/* 2026-06-14: force each lq-box row to a single line — ellipsis on the title, never
   wrap the meta — so the box stays compact and predictable in height. Written for the
   narrow left flank (~24% width) the box then lived in; since .944 it closes the
   column-2 stack under Hot-200, and one line per row still keeps it compact. */
.lq-box .sig-row { padding: 4px 8px; font-size: 12px; }
.lq-box .sig-row .sig-link { display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; min-width: 0; }
.lq-box .sig-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lq-box .sig-meta { flex: 0 0 auto; display: inline-flex; gap: 4px; align-items: center; white-space: nowrap; }
.smh-tab { font: inherit; font-size: 12px; font-weight: 700; padding: 5px 12px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; }
.smh-tab.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent); }
.smh-panel { display: none; }
.smh-panel.is-active { display: block; }
/* .414 (operator): Hot-Events lists STACK full-width (was a 2-up grid that
   capped each title to ~half the hub width → ellipsis). Single column gives each
   row the full hub width, so far more event-title text fits before truncating.
   Trade-off: the tab is taller (the two lists stack instead of sitting side by
   side) — accepted for the wider text. */
.smh-halves { display: grid; grid-template-columns: 1fr; gap: 14px; }
.smh-h { margin: 0 0 4px; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.smh-h-sub { font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--muted); opacity: 0.75; font-size: 10px; }   /* 2026-06-13 */
.smh-date { flex-shrink: 0; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }   /* 2026-06-13: HoF bet date */
.smh-list { list-style: none; margin: 0; padding: 0; }
/* .417: per-column header row (title + 1–10/11–20 subtabs) + paging. The
   .smh-paged ol holds up to 20 rows; CSS shows only the active page's 10. */
.smh-h-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 4px; }
.smh-h-row .smh-h { margin: 0; }
.smh-subtabs { display: inline-flex; gap: 4px; flex: 0 0 auto; }
.smh-subtab { font-size: 10px; font-weight: 700; color: var(--muted); background: transparent; border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; line-height: 1.4; cursor: pointer; transition: border-color var(--m-tab), color var(--m-tab), background-color var(--m-tab); }
.smh-subtab:hover { color: var(--text); border-color: var(--accent); }
.smh-subtab.is-active { color: var(--text); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* hot-wallets-100 .471: generic 10-page pager (was a 2-page hide-pair).
   Hide every row, show only the active page's ten. */
.smh-paged > .smh-row { display: none; }
.smh-paged[data-page="0"] > .smh-row[data-pg="0"] { display: flex; }
.smh-paged[data-page="1"] > .smh-row[data-pg="1"] { display: flex; }
.smh-paged[data-page="2"] > .smh-row[data-pg="2"] { display: flex; }
.smh-paged[data-page="3"] > .smh-row[data-pg="3"] { display: flex; }
.smh-paged[data-page="4"] > .smh-row[data-pg="4"] { display: flex; }
.smh-paged[data-page="5"] > .smh-row[data-pg="5"] { display: flex; }
.smh-paged[data-page="6"] > .smh-row[data-pg="6"] { display: flex; }
.smh-paged[data-page="7"] > .smh-row[data-pg="7"] { display: flex; }
.smh-paged[data-page="8"] > .smh-row[data-pg="8"] { display: flex; }
.smh-paged[data-page="9"] > .smh-row[data-pg="9"] { display: flex; }
.smh-row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; font-size: 12px; cursor: pointer; border-bottom: 1px solid var(--border); }
.smh-row:last-child { border-bottom: 0; }
.smh-row:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.smh-title, .smh-evt { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.smh-name { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.smh-delta { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.smh-delta.up { color: var(--success); } .smh-delta.down { color: var(--danger); }
.smh-usd { flex-shrink: 0; color: var(--text-soft, var(--muted)); font-variant-numeric: tabular-nums; }  /* nh-fix 2026-07-10: --muted taupe washed out on the peach panel (the "$63,258" column) */
/* .412 Top-Mover context (venue · option · liquidity · settlement) → .415
   (operator): now INLINE on a SINGLE line with the title (was stacked below it),
   so the content stretches across the now-full-width row and the table is more
   compact (1 line per row, not 2). Title grows + ellipsizes; the context cluster
   + the delta sit at the right. Muted + tabular; never wraps or h-scrolls. */
.smh-mv-row { align-items: center; }
.smh-mv-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: row; align-items: center; gap: 10px; }
.smh-mv-main .smh-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.smh-mv-ctx { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; flex-wrap: nowrap; overflow: hidden; font-size: 11px; color: var(--muted); white-space: nowrap; }
.smh-mv-logo { flex-shrink: 0; border-radius: 2px; }
.smh-mv-opt { overflow: hidden; text-overflow: ellipsis; max-width: 16ch; }
.smh-mv-liq, .smh-mv-close { flex-shrink: 0; font-variant-numeric: tabular-nums; }
/* Hall of Fame — 2 columns, COLUMN-MAJOR (hof-cols 2026-07-20, operator:
   "1/2/3 down the left, 4/5/6 down the right — not the 1,2/3,4 zigzag").
   CSS multi-columns flow down-then-across natively (the wds-list precedent);
   the grid version auto-placed row-major. Sorting still just reorders the DOM
   rows — the columns re-flow in the new order. */
.smh-hof-grid { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 18px; }
.smh-hof-row { break-inside: avoid; }
/* hof-100 2026-07-27: the 1-50 / 51-100 range pager — only the active range's
   rows render (the 2-col column-major flow re-flows per range). */
.smh-hof-grid > .smh-hof-row { display: none; }
.smh-hof-grid[data-hofpage="0"] > .smh-hof-row[data-hofpg="0"] { display: flex; }
.smh-hof-grid[data-hofpage="1"] > .smh-hof-row[data-hofpg="1"] { display: flex; }
.smh-hof-row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; font-size: 12px; cursor: pointer; border-bottom: 1px solid var(--border); }
.smh-hof-row:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.smh-rank { flex-shrink: 0; width: 22px; text-align: right; color: var(--muted); font-weight: 700; font-variant-numeric: tabular-nums; }
/* .413: Hall of Fame sort header — two clickable labels ($ amount / date) that
   reuse .pc-sort-th (asc/desc arrows + active highlight come from that rule). */
.smh-hof-head { display: flex; gap: 14px; align-items: center; margin: 0 0 6px 4px; }
.smh-hof-sort { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
@media (max-width: 760px) { .smh-halves { grid-template-columns: 1fr; } .smh-hof-grid { columns: 1; } }

/* ww-top-lists 2026-08-16 (operator): the two-box row at the top of the default
   Hot Wallets view — whale alerts (left, built separately) + this box's two
   lists (top trades 24h, top wallets this calendar month).

   AUTO-FIT, NOT `1fr 1fr`. Only one box exists until the alerts box lands, and
   a hard two-column rule would hold open an empty left cell — precisely the NO
   EMPTY BOXES rule. auto-fit gives a full-width single box today and two
   columns the instant a sibling appears, with no CSS change and no flag.

   Colours are palette vars only (GRAPHICAL TENET). The two stacked lists take
   the dominant vertical order — teal on top, amber below; `:first-child` rather
   than a fixed class so the ordering still holds when the 24h list is empty on
   a quiet day and the month list becomes the top one. */
.ww-top-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px; margin: 0 0 14px;
}
/* wallets-toprow 2026-08-20 (operator): the two top-10 lists sit SIDE BY
   SIDE in one full-width box ABOVE the Hot-Wallets table (the .822/.826
   sidebar layout is deleted above - the panel reverts to block flow and
   .ww-top-row, the panel's FIRST child, renders on top). auto-fit keeps
   NO-EMPTY-BOXES: one list alone takes the full width; the pending
   whale-alerts box still lands as a SIBLING box in .ww-top-row's own
   auto-fit row, unaffected. <=760px stacks via the existing media rule. */
.ww-top-box {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 12px 18px; min-width: 0;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px;
}
.ww-top-sec { min-width: 0; }
/* NO VERTICAL SCROLLBAR INSIDE SIGNAL CARDS: ten rows are server-capped, so the
   list is sized to fit and clips rather than scrolls. */
.ww-top-list { list-style: none; margin: 0; padding: 0; overflow: hidden; }
.ww-top-item {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 3px 4px; font-size: 12px; cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.ww-top-item:last-child { border-bottom: 0; }
.ww-top-item:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
/* NO HORIZONTAL SCROLLBAR: the two text cells are the only growable ones and
   both carry min-width:0 + ellipsis, so a long event title or an un-shortened
   wallet hash truncates instead of widening the row. */
.ww-top-name {
  flex: 0 1 auto; max-width: 42%; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600; color: var(--text);
}
.ww-top-evt {
  flex: 1 1 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--muted); font-size: 11px;
}
.ww-top-usd {
  flex-shrink: 0; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.ww-top-sec:nth-child(2) .ww-top-usd { color: var(--jackpot); }
@media (max-width: 760px) { .ww-top-row, .ww-top-box { grid-template-columns: 1fr; } }


/* Split-flap board: shared 6-col grid for the header + rows. The compound
   `.board-card-row.dep-row` (0-2-0) beats the legacy `.board-card-row` layout. */
.dep-head,
.board-card-row.dep-row {
  display: grid;
  /* dep-venue-logo 2026-07-20 (operator: "only show venue logo, not name, and
     widen the space allocated to event title"): VENUE 84px -> 44px now that the
     cell renders the 14px logo alone. The 40px is reclaimed by EVENT, which is
     the minmax(0,1fr) column — it absorbs the slack automatically. */
  /* board-bell-clip 2026-08-18: the EVENT track's min was 0, so on a NARROW
     DESKTOP card (measured 0px at both 1280 and 1366) the column collapsed to
     zero and .dep-cell's overflow:hidden CLIPPED the row's follow-event bell
     out of existence - still in the DOM with a real getBoundingClientRect, but
     unpainted and NOT hit-testable, so every click fell through to the row's
     own openEventById. Measured on live .819 at 1366x768: 25 of 25 rendered
     chips clipped (worst overflowed its cell by 67px), 0 clickable. This is
     the SAME collapse the max-width:700px block already re-flows for phones
     ("titles were invisible") - the 701-1430px band was simply never covered.
     The floor also restores the event TITLE, invisible in that band for the
     same reason. No horizontal scrollbar at 1280/1366/1440/1920. */
  /* hot200-slim 2026-09-04: the board gives up 10% of its width, and the
     EVENT track is the 1fr — it would absorb the whole loss and show LESS
     title, which the ask forbids. So width is handed back from the two
     places that can spare it: the gap, and the one column already declared
     squeezable (minmax(0,...)). The 86/44/62/58 tracks are NOT touched —
     the comment above records a measured clipping bug (25 of 25 chips
     clipped at 1366) that those floors exist to prevent.
     ⚠ This offsets roughly half the loss, not all of it. At 1440 the EVENT
     track goes ~454px -> ~402px rather than ~362px. */
  grid-template-columns: 86px minmax(96px,1fr) 44px 62px minmax(0,120px) 58px;
  gap: 6px; align-items: center;
}
.dep-head { list-style:none; margin:0; padding:4px 10px 6px; font-size:9px; font-weight:700;
  letter-spacing:.08em; color:var(--muted); text-transform:uppercase; border-bottom:1px solid var(--border); }
.board-card-row.dep-row { padding:5px 10px; border-bottom:1px solid color-mix(in srgb,var(--border) 55%,transparent); }
.board-card-row.dep-row:hover { background: var(--panel-2); }
.dep-cell { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; font-size:12px; }
.dep-event { font-weight:600; color:var(--text); display:flex; align-items:center; gap:4px; }
.dep-event-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.dep-ic { flex-shrink:0; font-size:11px; text-decoration:none; }
.dep-venue { display:flex; align-items:center; gap:4px; color:var(--muted); font-size:10px; }
.dep-venue-name { font-family:monospace; letter-spacing:.03em; }
/* dep-venue-logo 2026-07-20 (operator): board ROWS show the venue LOGO only.
   Scoped to .board-card-row so the sortable column HEADER keeps its label —
   it is the sort control, and a wordless header would be unusable. Venues
   with no logo file fall back to the short name so the cell is never blank
   (NO-EMPTY-BOX). */
.board-card-row .dep-venue-name { display: none; }
.board-card-row .dep-venue:not(:has(.dep-venue-logo)) .dep-venue-name { display: inline; }
.dep-venue-logo { flex-shrink: 0; }
.dep-closes { font-family:monospace; font-size:11px; color:var(--muted); text-align:right; }
.dep-leader-lbl { color:var(--text); } .dep-leader-pct { color:var(--accent); }
.dep-delta { text-align:right; font-family:monospace; font-size:11px; }
.dep-delta-up { color:var(--success,var(--success)); } .dep-delta-dn { color:var(--danger); }
.dep-na { color:var(--muted); }

/* STATUS split-flap chip — amber --jackpot board glow (the iconic flap). */
.dep-status {
  font-family:monospace; font-weight:700; font-size:10px; letter-spacing:.03em;
  padding:2px 5px; border-radius: var(--r-chip); text-align:center; white-space:nowrap;
  background: color-mix(in srgb, var(--jackpot) 16%, transparent);
  color: var(--jackpot); border:1px solid color-mix(in srgb, var(--jackpot) 32%, transparent);
}
/* CTWR 2026-06-10: sentence-case status relabel + Hot */
.dep-status-closing-soon { background:color-mix(in srgb,var(--danger) 18%,transparent); color:var(--danger); border-color:color-mix(in srgb,var(--danger) 36%,transparent); }
.dep-status-going-live   { background:color-mix(in srgb,var(--accent) 16%,transparent); color:var(--accent); border-color:color-mix(in srgb,var(--accent) 32%,transparent); }
.dep-status-closed       { background:color-mix(in srgb,var(--muted) 14%,transparent); color:var(--muted); border-color:color-mix(in srgb,var(--muted) 28%,transparent); }
.dep-status-hot          { background:color-mix(in srgb,var(--whale) 18%,transparent); color:var(--whale); border-color:color-mix(in srgb,var(--whale) 36%,transparent); }
/* Operator 2026-06-16: chip/label legibility. The status chips rendered as
   same-hue text on a same-hue faint tint (Live=amber/amber, Going live=teal/teal,
   Closing soon=red/red, Hot=…), washed out on the cream theme.
   (a) Bold is theme-agnostic — option title was 400; bump the label set to 700. */
.dep-status-live,
.dep-status-going-live,
.dep-status-closing-soon,
.dep-status-closed,
.dep-status-hot,
.dep-leader-lbl,
.dep-leader-pct          { font-weight: 700; }
/* (b) Re-ink to high-contrast text ONLY on the light/peach theme — the
   wash-out is a bright-on-cream problem. Dark mode already pops (bright text on
   dark), so leave it alone (operator 2026-06-16: "no need to make fonts darker
   on dark mode"). var(--text) on peach = espresso #3b2f25 = the "black" wanted. */
:root[data-theme="peach"] .dep-status-live,
:root[data-theme="peach"] .dep-status-going-live,
:root[data-theme="peach"] .dep-status-closing-soon,
:root[data-theme="peach"] .dep-status-closed,
:root[data-theme="peach"] .dep-status-hot,
:root[data-theme="peach"] .me-score,
:root[data-theme="peach"] .me-band-strong,
:root[data-theme="peach"] .me-band-moderate,
:root[data-theme="peach"] .me-band-weak,
:root[data-theme="peach"] .dep-leader-pct { color: var(--text); }
.dep-flap-char { display:inline-block; min-width:.55ch; }
.dep-flip-anim { animation: dep-flip .26s ease-in-out; }
@keyframes dep-flip { 0%{transform:rotateX(0);} 49%{transform:rotateX(-90deg);opacity:.35;} 51%{transform:rotateX(90deg);} 100%{transform:rotateX(0);opacity:1;} }
@media (prefers-reduced-motion: reduce) { .dep-flip-anim { animation:none; } }

/* P4 2026-06-14: data-changed flash (pcFlashWatcher) */
.is-flashing-up,
.is-flashing-down,
.is-flashing-amber {
  transition: background-color var(--m-flash);
}
.is-flashing-up    { background-color: color-mix(in srgb, var(--success) 22%, transparent); }
.is-flashing-down  { background-color: color-mix(in srgb, var(--danger)  22%, transparent); }
.is-flashing-amber { background-color: color-mix(in srgb, var(--c-money) 22%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .is-flashing-up,
  .is-flashing-down,
  .is-flashing-amber { background-color: transparent; transition: none; }
}

.board-card { border-top: 3px solid var(--accent); display: flex; flex-direction: column; overflow: hidden; }
.board-card-name { color: var(--accent); }
/* Build .263: tighten h3 + sub on board card to claw back vertical
   space for the 20 visible rows. */
.board-card h3 { margin: 0 0 2px; font-size: 12px; }
.board-card h3 .plat-sub { font-size: 10px; }

/* Build .263: tighten tabs / filter / rows so all 20 segment rows fit
   inside the card with NO scrollbar.  Total budget for the card is
   roughly the same as .liq-card (~320-360px in the row-2 signals grid).
   Header overhead: h3 ~20px + tabs ~22px + filter ~32-50px = ~75-92px.
   Remaining ~228-285px for 20 rows → must keep rows ≤ 14px each. */

/* Segment tab bar (1–20 / 21–40 / 41–60) */
.board-tab-bar {
  display: flex; gap: 3px; flex-shrink: 0;
  padding: 1px 0 3px;        /* was 2px 0 6px */
}
.btb-btn {
  flex: 1; min-width: 0; padding: 2px 0;   /* was 4px 0 · board-200 2026-07-28: min-width:0 lets 8 flex tabs shrink to fit, no h-scroll */
  border: 1px solid var(--border);
  border-radius: var(--r-chip); background: var(--panel); color: var(--muted);
  font-size: 9px;            /* was 11px→10px→9: 8 tabs incl 3-digit 101–125 labels (board-200) */
  font-weight: 800; font-family: monospace; cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
  line-height: 1.3;
  white-space: nowrap;       /* btb-oneline .655 (operator): a seg label NEVER wraps */
}
.btb-btn:hover { background: var(--panel-2); color: var(--text); }
.btb-btn.btb-active {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: var(--accent); color: var(--accent);
}

/* board-filter-seg 2026-07-05: seg tab whose 25-row window is empty under the
   active platform filter — visibly inert (no blank page is reachable). */
.btb-btn.btb-off { opacity: 0.35; pointer-events: none; }

/* Platform filter bar */
.board-filter-bar {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;                  /* was 4px */
  padding: 2px 0 4px;        /* was 4px 0 6px */
}
.bfb-btn {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 6px;          /* was 2px 7px */
  border-radius: var(--r-card);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  font-size: 9px;            /* was 10px */
  font-weight: 600;
  cursor: pointer;
  line-height: 1.3;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.bfb-btn:hover { background: var(--panel-2); color: var(--text); }
.bfb-btn.bfb-active {
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  border-color: var(--accent);
  color: var(--accent);
}
.bfb-btn img { width: 10px !important; height: 10px !important; }

/* Build .263: list now CLIPS — no scrollbar.  Tightening below keeps
   20 visible segment rows inside the available height. */
.board-card-list {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow: hidden;          /* was overflow-y: auto */
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Section dividers — JS hides these (display:none) so styling is moot,
   but keep the rules minimal in case the JS is ever rolled back. */
.board-card-divider {
  list-style: none;
  padding: 2px 6px 1px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Compact event rows — target ~13-14px per row */
.board-card-row {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 6px;            /* was 3px 6px — saves 6px per row × 20 = 120px */
  border-radius: var(--r-chip);
  cursor: pointer;
  min-width: 0;
  line-height: 1.3;
}
.board-card-row:hover { background: var(--panel-2); }
.board-card-row-urgent { border-left: 2px solid var(--danger); padding-left: 4px; }
.bc-rank {
  flex-shrink: 0;
  width: 16px;               /* was 18px */
  text-align: right;
  font-size: 9px;            /* was 10px */
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.bc-logo {
  flex-shrink: 0;
  width: 14px;               /* was 16px */
  display: flex;
  align-items: center;
  justify-content: center;
}
.bc-logo img { width: 12px !important; height: 12px !important; }
.bc-icons {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 1px;
  font-size: 10px;           /* was 11px */
  min-width: 12px;           /* was 14px */
}
.bc-icon { line-height: 1; }
.bc-icon-news { text-decoration: none; }
.bc-title {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;           /* was 12px */
  color: var(--text);
}
.bc-chips {
  flex-shrink: 0;
  display: flex;
  gap: 2px;
  align-items: center;
}
.bc-chip {
  font-size: 9px;            /* was 10px */
  padding: 0 3px;            /* was 1px 4px */
  border-radius: var(--r-chip);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  line-height: 1.4;
}
.bc-chip-vol    { color: var(--success); }
.bc-chip-ttr-red    { color: var(--danger); font-weight: 700; }
.bc-chip-ttr-yellow { color: var(--jackpot); }
.bc-chip-ttr-gray   { color: var(--muted); }
/* Recurring-market cadence chips (2026-06): fast -> slow color gradient. */
.bc-chip-recur            { font-weight: 700; }
.bc-chip-recur-intraday   { color: var(--sxbet); }          /* pink  - fastest */
.bc-chip-recur-hourly     { color: var(--success); }   /* green */
.bc-chip-recur-daily      { color: #3b82f6; }          /* blue */
.bc-chip-recur-weekly     { color: #a855f7; }          /* purple */
.bc-chip-recur-monthly    { color: var(--jackpot); }   /* amber */
.bc-chip-recur-quarterly  { color: var(--accent); }          /* teal */
.bc-chip-recur-annual     { color: var(--muted); }     /* gray  - slowest */
.bc-chip-ai {
  color: var(--accent);
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.bc-chip-ai-logo {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  vertical-align: middle;
  flex-shrink: 0;
}

/* board-panels-section: slim section below the signals-row (reclaim panels) */
.board-panels-section {
  max-width: var(--content-max, 1600px);
  margin: 0 auto;
  padding: 0 16px 16px;
  width: 100%;
  box-sizing: border-box;
}

/* Coming-soon placeholder cards (Top-10 Movers / Reserved). */
.reserved-card { border-top: 3px solid var(--muted); opacity: 0.85; }
/* Build .74: PredictHQ feed in the bottom-right slot. Overrides the
   muted .reserved-card look since this is real data now, not a "coming
   soon" placeholder. Top border swapped to a globe-blue. */
.reserved-card.predicthq-card { opacity: 1; border-top: 3px solid var(--platform-polyus-brand); }
.predicthq-name { font-weight: 800; color: var(--platform-polyus-brand); }

.phq-list { list-style: none; padding: 0; margin: 0; }
.phq-row { padding: 6px 0; border-bottom: 1px solid var(--border); }
.phq-row:last-child { border-bottom: none; }
.phq-link {
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-decoration: none;
}
.phq-title {
  font-size: 12px;
  line-height: 1.3;
  font-weight: 600;
  color: var(--text);
  word-break: break-word;
}
.phq-cat {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--platform-polyus-brand) 15%, transparent);
  color: var(--platform-polyus-brand);
  align-self: flex-start;
}
.phq-cat-concerts        { background: color-mix(in srgb, var(--whale) 18%, transparent); color: var(--whale); }
.phq-cat-sports          { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.phq-cat-conferences     { background: color-mix(in srgb, var(--platform-manifold-brand) 18%, transparent); color: var(--platform-manifold-brand); }
.phq-cat-expos           { background: color-mix(in srgb, var(--platform-manifold-brand) 18%, transparent); color: var(--platform-manifold-brand); }
.phq-cat-festivals       { background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot); }
.phq-cat-performing_arts { background: color-mix(in srgb, var(--whale) 18%, transparent); color: var(--whale); }
.phq-cat-politics        { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.phq-cat-community       { background: color-mix(in srgb, var(--kalshi) 18%, transparent); color: var(--kalshi); }
.phq-cat-academic        { background: color-mix(in srgb, var(--platform-manifold-brand) 18%, transparent); color: var(--platform-manifold-brand); }

/* Build v0.35 20260524.199: boost emoji nested INSIDE the .phq-cat chip.
   Was previously a separate flex-item / grid cell which broke the
   wide-grid 4-column layout (added a 5th cell with no rule).  Now sits
   as a tight prefix inside the green sports / red politics pill,
   consuming zero extra horizontal cells.  Emoji needs a slight
   nudge — kept proportional to chip text (9-11px), vertically aligned,
   tight right-margin separator. */
.phq-cat .phq-boost {
  display: inline-block;
  font-size: 11px;          /* slightly larger than 9px chip text for emoji legibility */
  line-height: 1;
  vertical-align: -1px;     /* nudge baseline down so emoji aligns with chip caps */
  margin-right: 3px;
  /* Don't inherit uppercase from .phq-cat — meaningless for emoji */
  text-transform: none;
  /* Don't inherit letter-spacing — emoji has its own metric */
  letter-spacing: 0;
}
.phq-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 10px;
  color: var(--muted);
}
.phq-when { font-family: monospace; }
.phq-country {
  font-family: monospace;
  background: rgba(138, 150, 196, 0.12);
  padding: 0 4px;
  border-radius: var(--r-chip);
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
/* Build .77.2: real flag images from flagcdn.com (Unicode regional
   indicators rendered as plain ASCII on Windows, looking like a duplicate
   country code). Base `.flag-img` is the small (16px wide) variant used in
   meta lines, tooltips, and the viewer list. */
.flag-img {
  width: 16px;
  height: auto;
  vertical-align: middle;
  border-radius: var(--r-chip);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
  display: inline-block;
}
.flag-na {
  font-size: 12px;
  line-height: 1;
}
/* Flag riding to the left of the PHQ event title — a touch bigger than the
   inline-meta variant so it visually anchors the row. */
.phq-title-flag {
  display: inline-block;
  margin-right: 6px;
  vertical-align: middle;
}
.phq-title-flag .flag-img {
  width: 18px;
}
/* Larger flag used in the PHQ modal's Country row. */
.phq-flag-lg {
  display: inline-block;
  margin-right: 5px;
  vertical-align: middle;
}
.phq-flag-lg .flag-img {
  width: 22px;
}
/* Legacy class names kept for the visitor mini-list + globe tooltip — they
   used to wrap a Unicode glyph; with .flag-img now an <img>, this wrapper
   just needs to align the image. */
.phq-flag,
.vw-flag {
  display: inline-block;
  vertical-align: middle;
}
.phq-rank {
  font-family: monospace;
  font-weight: 600;
  padding: 0 5px;
  border-radius: var(--r-chip);
}
.phq-rank-hi  { color: var(--success); background: color-mix(in srgb, var(--success) 10%, transparent); }
.phq-rank-mid { color: var(--text); background: color-mix(in srgb, var(--platform-manifold-brand) 10%, transparent); }
.phq-rank-lo  { color: var(--muted); background: rgba(138, 150, 196, 0.10); }
/* Build .96.1: dual-rank display in the card row.  Global chip sits
   immediately before local; small gap; subtle border on global to
   distinguish from local (which carries the primary signal). */
.phq-rank-global + .phq-rank-local { margin-left: 4px; }
.phq-rank-global {
  border: 1px dashed rgba(148, 163, 184, 0.40);
  opacity: 0.85;
}
.phq-rank-local {
  border: 1px solid transparent;
  font-weight: 700;   /* primary signal — bolder than global */
}
.phq-attendance, .phq-spend {
  font-family: monospace;
  cursor: help;
}
.phq-footnote {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  cursor: help;
}
/* Build .75: PHQ filter tabs + sort controls + clickable rows + modal. */
.phq-controls {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}
.phq-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.phq-tab {
  font-family: inherit;
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: var(--r-chip);
  border: 1px solid var(--border);
  background: rgba(255,255,255,0.03);
  color: var(--muted);
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.phq-tab:hover {
  color: var(--text);
  background: rgba(255,255,255,0.06);
}
.phq-tab-active {
  background: color-mix(in srgb, var(--platform-polyus-brand) 18%, transparent);
  border-color: var(--platform-polyus-brand);
  color: var(--platform-polyus-brand);
}
.phq-sort-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--muted);
}
.phq-sort-lbl { font-family: monospace; }
.phq-sort-select {
  font-family: inherit;
  font-size: 10px;
  padding: 2px 6px;
  background: rgba(255,255,255,0.03);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--r-chip);
  cursor: pointer;
}
.phq-sort-select:focus { outline: 1px solid var(--platform-polyus-brand); }
.phq-row-clickable { cursor: pointer; transition: background 0.12s; }
.phq-row-clickable:hover {
  background: color-mix(in srgb, var(--platform-polyus-brand) 6%, transparent);
}
.phq-empty-row {
  padding: 18px 6px;
  text-align: center;
  color: var(--muted);
  font-style: italic;
}

/* ─── Build v0.35 20260525.208: Most Liquid USD Markets widget ─────────
   Replaces the Trending Topics tile in the 3×2 signals row's col 3 /
   row 2 slot.  Topics promoted to a 4th top-of-page ticker in the same
   build (see .tt-* styles further down).
   Layout grammar is a strict extension of .signals-list / .sig-row, so
   the only widget-specific styles are: card accent color, rank chip,
   leader-price chip, and a wider title column to accommodate the rank
   prefix without crowding the chips. */
.liq-card {
  border-top: 3px solid var(--platform-polyus-brand);   /* sky blue — "liquidity" accent */
  /* Build .243: flex-column so the list scrolls inside the fixed card height */
  display: flex; flex-direction: column; overflow: hidden;
  padding-bottom: 0;
}
.liq-name { color: var(--platform-polyus-brand); font-weight: 800; }
.liq-sub { color: var(--muted); font-size: 10px; font-weight: 500; }
/* Build .252: no scrollbar (overflow hidden) + flex rows so logo + chip
   + title + chips all stay on one line.  Item count capped at 15 on the
   server side so nothing is silently clipped. */
.liq-list {
  list-style: none; margin: 0; padding: 0;
  overflow: hidden;          /* no scrollbar — ever */
  flex: 1 1 0; min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;                  /* Build .259: match .la-news-list gap */
}
/* Build .259: structure + fonts mirror Latest News (.la-news-*).
   ALL liq-* rules use 2-class specificity (.liq-list X) so the .sig-row
   / .sig-link rules defined ~770 lines later in this file can't win the
   cascade tie. */
.liq-list .liq-row {
  cursor: pointer;
  border-bottom: none;       /* defeat .sig-row { border-bottom: 1px } */
  list-style: none;
  margin: 0; padding: 0;
}
.liq-list .liq-link {
  display: flex;             /* defeat .sig-link { display: grid } */
  flex-direction: row;
  align-items: baseline;     /* mirror .la-news-link */
  gap: 6px;                  /* mirror .la-news-link */
  grid-template-columns: none;
  padding: 4px 8px;          /* mirror .la-news-link */
  text-decoration: none;
  color: var(--text);
  border-left: 2px solid transparent;
  border-radius: var(--r-chip);
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
  font-size: 12px;
  min-height: 0;
}
.liq-list .liq-link:hover {
  background: color-mix(in srgb, var(--platform-polyus-brand) 7%, transparent);
  border-left-color: var(--platform-polyus-brand);
  text-decoration: none;
}
/* Meta block on the LEFT — logo + plat chip + rank + amount + leader */
.liq-list .liq-meta {
  flex-shrink: 0;
  display: flex;
  gap: 5px;
  align-items: center;
  font-size: 10.5px;         /* mirror .la-news-meta */
  color: var(--muted);
  justify-self: auto;        /* defeat .sig-meta { justify-self: end } */
  flex-wrap: nowrap;
  max-width: none;
}
.liq-list .liq-meta .plat-chip-logo {
  width: 12px; height: 12px; flex-shrink: 0;
}
.liq-list .liq-meta .sig-plat {
  padding: 1px 6px;
  font-size: 10px;           /* mirror .la-news-prov */
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  flex-shrink: 0;
}
.liq-list .liq-rank {
  flex-shrink: 0;
  color: var(--platform-polyus-brand);
  font-family: monospace; font-weight: 700;
  font-size: 10px;
  min-width: 18px;
  text-align: right;
}
.liq-list .liq-meta .sig-tag {
  padding: 1px 5px;
  font-size: 10px;
  line-height: 1.4;
  border-radius: var(--r-chip);
}
.liq-list .liq-meta .sig-tag.sig-amt {
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success);
  font-weight: 700;
}
.liq-list .sig-tag.liq-leader {
  background: color-mix(in srgb, var(--platform-polyus-brand) 14%, transparent);
  color: var(--platform-polyus-brand);
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  vertical-align: middle;
}
/* Title flex-fills to the right — mirror .la-news-title */
.liq-list .liq-title {
  flex: 1 1 0;
  min-width: 0;
  font-size: 12px;
  line-height: 1.3;
  font-weight: 500;          /* mirror .la-news-title (was 600) */
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Topic modal — full-list view of every event under a topic */
.topic-modal {
  max-width: 760px;
  width: min(760px, 96vw);
}
.topic-modal-head {
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
  padding-bottom: 10px;
}
.topic-modal-title {
  font-size: 22px; font-weight: 800; color: var(--jackpot);
  letter-spacing: 0.01em;
}
.topic-modal-sub {
  font-size: 12px; color: var(--muted); margin-top: 3px;
  font-family: monospace;
}
.topic-modal-body {
  display: flex; flex-direction: column; gap: 14px;
  max-height: calc(85vh - 100px);
  overflow-y: auto;
  padding-right: 4px;
}
.topic-plat-block {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 8px 10px;
}
.topic-plat-head {
  display: flex; align-items: center; gap: 8px;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 5px; margin-bottom: 5px;
}
.topic-plat-name {
  font-weight: 700; font-size: 13px; color: var(--text);
}
.topic-plat-count {
  font-family: monospace; font-size: 10px; color: var(--muted);
  margin-left: auto;
}
.topic-evt-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column;
}
.topic-evt { border-bottom: 1px dashed rgba(255,255,255,0.04); }
.topic-evt:last-child { border-bottom: none; }
.topic-evt-link {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px; align-items: center;
  padding: 5px 0;
  color: var(--text); text-decoration: none;
  font-size: 12px;
}
.topic-evt-link:hover { color: var(--jackpot); }
.topic-evt-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topic-evt-vol {
  font-family: monospace; font-weight: 600;
  color: var(--muted); white-space: nowrap;
}
@media (max-width: 700px) {
  .topic-modal { width: 96vw; }
  .topic-modal-title { font-size: 18px; }
  .topic-modal-body { max-height: calc(100vh - 140px); }
}

/* ─── Build .80: page-wide PHQ section ──────────────────────────────────
   The "Top Real-World Events" card lives in its own row between the
   platform Top-20 grid and the Visitors row.  Wider canvas → two-column
   row layout (title block | meta block) so the list reads more like a
   compact table than a stacked column. */
.phq-section { padding: 0 20px 12px; }
.predicthq-card-wide {
  border-top: 3px solid var(--platform-polyus-brand);
}
.predicthq-card-wide .phq-controls {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.predicthq-card-wide .phq-tabs { flex: 1 1 auto; }
.predicthq-card-wide .phq-sort-row { flex: 0 0 auto; }

/* Wide list — two-column grid on desktop, falls back to stacked on narrow
   viewports. JS still emits the same DOM (li.phq-row > a.phq-link with
   .phq-title + .phq-meta) so we just restyle here. */
.phq-list-wide {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 24px;
}
@media (max-width: 1100px) {
  .phq-list-wide { grid-template-columns: 1fr; }
}
/* Build .82: row padding tightened 8px → 4px and title font 13 → 12 so
   doubling the visible event count (10 → 20) keeps the total card height
   close to the prior dimensions.  Each row drops from ~34px → ~22px tall. */
.phq-list-wide > .phq-row {
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
}
/* Build .80.2: row grid is [flag] [cat] [title 1fr] [meta auto].  The
   flag sits as the LEFTMOST cell so it lines up flush against each
   column's left edge across both data columns. */
.phq-list-wide .phq-link {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 2px 8px;
}
.phq-list-wide .phq-row-flag { grid-column: 1; }
.phq-list-wide .phq-cat   { grid-column: 2; }
.phq-list-wide .phq-title { grid-column: 3; }
.phq-list-wide .phq-meta  { grid-column: 4; }
.phq-list-wide .phq-title {
  font-size: 12px;
  line-height: 1.25;
  /* Single-line clipping — preserves the row-count vs height tradeoff:
     long titles ellipsize instead of forcing the row to expand. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.phq-list-wide .phq-cat {
  font-size: 9px;
  padding: 0 5px;
}
.phq-list-wide .phq-meta {
  justify-content: flex-end;
  font-size: 10px;
  white-space: nowrap;
  flex-wrap: nowrap;
  gap: 4px;
}
.phq-list-wide .phq-meta .phq-rank {
  font-size: 10px;
  padding: 0 4px;
}
.phq-list-wide .phq-meta .phq-poly-btn {
  font-size: 9px;
  padding: 1px 5px;
}
.phq-list-wide .phq-row-flag {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-width: 22px;
}
.phq-list-wide .phq-row-flag .flag-img {
  width: 18px;
}

/* PredictHQ detail modal */
.phq-modal {
  max-width: 720px;
  width: min(720px, 96vw);
}
.phq-modal-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.phq-modal-cat {
  font-size: 11px;
}
.phq-modal-title {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
  margin: 0;
  flex: 1 1 auto;
  line-height: 1.25;
}
.phq-state-badge {
  font-family: monospace;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  background: rgba(255,255,255,0.06);
  color: var(--muted);
  letter-spacing: 0.05em;
}
.phq-state-active     { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.phq-state-cancelled,
.phq-state-deleted    { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.phq-state-rescheduled,
.phq-state-postponed  { background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot); }
.phq-modal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
.phq-modal-stat {
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 10px 12px;
}
.phq-modal-stat-lbl {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 4px;
}
.phq-modal-stat-num {
  font-family: monospace;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  line-height: 1;
}
.phq-modal-stat-of {
  font-size: 12px;
  color: var(--muted);
  font-weight: 500;
}
.phq-modal-stat-sub {
  font-size: 10px;
  color: var(--muted);
  margin-top: 4px;
}
.phq-modal-details {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  margin-bottom: 12px;
}
.phq-modal-details th {
  text-align: left;
  vertical-align: top;
  padding: 6px 12px 6px 0;
  color: var(--muted);
  font-weight: 600;
  width: 130px;
  white-space: nowrap;
}
.phq-modal-details td {
  padding: 6px 0;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}
.phq-modal-details tr:last-child td { border-bottom: none; }
.phq-modal-details td a { color: var(--platform-polyus-brand); text-decoration: none; }
.phq-modal-details td a:hover { text-decoration: underline; }
.phq-tz {
  font-family: monospace;
  font-size: 10px;
  color: var(--muted);
  margin-left: 8px;
  padding: 0 4px;
  background: rgba(255,255,255,0.04);
  border-radius: var(--r-chip);
}
.phq-modal-labels { line-height: 1.8; }
.phq-lbl {
  display: inline-block;
  font-family: monospace;
  font-size: 10px;
  padding: 2px 6px;
  margin-right: 3px;
  background: color-mix(in srgb, var(--platform-manifold-brand) 10%, transparent);
  color: var(--platform-manifold-brand);
  border-radius: var(--r-chip);
  cursor: help;
}
.phq-modal-foot {
  font-size: 10px;
  color: var(--muted);
  text-align: center;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-style: italic;
}
.phq-modal-srclbl { cursor: help; }
/* Build .78: prominent "Search on Polymarket" CTA in the PHQ modal.
   Polymarket-branded gradient (their teal-green) so the off-platform
   destination reads visually. Sits between the related-markets list
   and the data-source footer. */
.phq-modal-cta {
  margin: 14px 0 4px;
  text-align: center;
}
.phq-modal-poly-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  background: linear-gradient(135deg, var(--accent), #0ea5e9);
  color: #061325;
  font-weight: 700;
  font-size: 13px;
  text-decoration: none;
  border-radius: var(--r-card);
  box-shadow: 0 2px 8px rgba(20, 184, 166, 0.25);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.phq-modal-poly-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(20, 184, 166, 0.4);
}
.phq-modal-poly-icon { font-size: 14px; }
.phq-modal-poly-sub {
  font-size: 10px;
  font-weight: 500;
  color: rgba(6, 19, 37, 0.65);
  margin-left: 4px;
}
/* Compact row-level Polymarket button on the PHQ event list. */
.phq-poly-btn {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  color: var(--accent);
  background: rgba(20, 184, 166, 0.08);
  border: 1px solid rgba(20, 184, 166, 0.25);
  border-radius: var(--r-chip);
  text-decoration: none;
  margin-left: auto;
}
.phq-poly-btn:hover {
  background: rgba(20, 184, 166, 0.18);
  color: var(--accent);
}
/* Build v.03 .31 build 161 (2026-05-23): Kalshi-themed sibling to
   the Polymarket search button — same shape, blue/sapphire accent
   that matches Kalshi's brand colour (was --kalshi: var(--kalshi)). */
.phq-poly-btn.phq-kalshi-btn {
  color: var(--kalshi);
  background: color-mix(in srgb, var(--kalshi) 8%, transparent);
  border-color: color-mix(in srgb, var(--kalshi) 25%, transparent);
  margin-left: 4px;  /* override the auto margin from the first button */
}
.phq-poly-btn.phq-kalshi-btn:hover {
  background: color-mix(in srgb, var(--kalshi) 18%, transparent);
  color: var(--kalshi);
}
.phq-modal-poly-btn.phq-modal-kalshi-btn {
  background: linear-gradient(135deg, #3b82f6, var(--kalshi));
  box-shadow: 0 2px 8px color-mix(in srgb, var(--kalshi) 25%, transparent);
  margin-left: 10px;
}

/* Build v0.35 20260524.200: Manifold deep-search button — third
   venue after Polymarket + Kalshi.  Manifold's brand color is amber
   (var(--jackpot) ≈ their orange-yellow). Uses same chip pattern as
   .phq-kalshi-btn for the row chip, same gradient pattern as
   .phq-modal-kalshi-btn for the modal CTA. */
.phq-poly-btn.phq-manifold-btn {
  color: var(--jackpot);
  background: rgba(245, 158, 11, 0.08);
  border-color: rgba(245, 158, 11, 0.25);
  margin-left: 4px;
}
.phq-poly-btn.phq-manifold-btn:hover {
  background: rgba(245, 158, 11, 0.18);
  color: var(--jackpot);
}
.phq-modal-poly-btn.phq-modal-manifold-btn {
  background: linear-gradient(135deg, #d97706, var(--jackpot));
  box-shadow: 0 2px 8px rgba(245, 158, 11, 0.25);
  margin-left: 10px;
}
.phq-modal-poly-btn.phq-modal-kalshi-btn:hover {
  box-shadow: 0 4px 12px color-mix(in srgb, var(--kalshi) 40%, transparent);
}
/* Build .78: MetaForecast probability-history sparkline. Uses the same
   evt-chart-wrap base height; adds spacing above to separate from the
   volume chart. */
.mf-hist-wrap {
  margin-top: 8px;
}
.mf-hist-sub {
  font-size: 11px;
  font-weight: 400;
  color: var(--muted);
  margin-left: 6px;
}
@media (max-width: 600px) {
  .phq-modal-title { font-size: 16px; }
  .phq-modal-stat-num { font-size: 18px; }
  .phq-modal-details th { width: 90px; font-size: 11px; }
}

/* Build .76: PHQ economic-impact banner (top of PHQ card) */
.phq-impact-banner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
  padding: 8px 10px;
  margin-bottom: 8px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--platform-polyus-brand) 6%, transparent), rgba(34, 211, 238, 0.04));
  border: 1px solid color-mix(in srgb, var(--platform-polyus-brand) 18%, transparent);
  border-radius: var(--r-card);
  font-family: monospace;
}
.phq-impact-stat { display: flex; flex-direction: column; }
.phq-impact-num {
  font-size: 16px;
  font-weight: 700;
  color: var(--platform-polyus-brand);
  line-height: 1.1;
}
.phq-impact-major { color: var(--success); }
.phq-impact-of { font-size: 11px; color: var(--muted); font-weight: 500; margin-left: 2px; }
.phq-impact-lbl {
  font-size: 9px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 2px;
}
.phq-impact-top {
  grid-column: 1 / -1;
  padding-top: 6px;
  border-top: 1px dashed color-mix(in srgb, var(--platform-polyus-brand) 18%, transparent);
  font-family: inherit;
  cursor: help;
}
.phq-impact-toplink {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  margin: 2px 0;
}
.phq-impact-toplink:hover { color: var(--platform-polyus-brand); text-decoration: underline; }
.phq-impact-topspend {
  font-family: monospace;
  font-size: 10px;
  color: var(--platform-polyus-brand);
}

/* Build .76: PHQ modal — related prediction markets section */
.phq-modal-matches {
  margin: 8px 0 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
}
.phq-matches-loading {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
  text-align: center;
}
.phq-matches-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 4px;
}
.phq-matches-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.phq-matches-sub { font-size: 10px; color: var(--muted); font-family: monospace; }
.phq-matches-list { list-style: none; padding: 0; margin: 0; }
.phq-match-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
}
.phq-match-row:last-child { border-bottom: none; }
.phq-match-plat {
  font-family: monospace;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  flex-shrink: 0;
}
.phq-match-title { flex: 1 1 auto; color: var(--text); }
.phq-match-title a { color: var(--text); text-decoration: none; }
.phq-match-title a:hover { color: var(--platform-polyus-brand); text-decoration: underline; }
.phq-match-conf {
  font-family: monospace;
  font-size: 10px;
  color: var(--muted);
  background: rgba(255,255,255,0.04);
  padding: 1px 5px;
  border-radius: var(--r-chip);
  cursor: help;
  flex-shrink: 0;
}

/* Build .76: globe legend overlay */
.vw-globe-wrap { position: relative; }
.vw-globe-legend {
  position: absolute;
  bottom: 6px;
  left: 6px;
  display: flex;
  gap: 12px;
  font-size: 9px;
  color: var(--muted);
  background: rgba(15, 23, 42, 0.6);
  padding: 4px 8px;
  border-radius: var(--r-chip);
  pointer-events: none;
  font-family: monospace;
}
.vw-leg-item { display: inline-flex; align-items: center; gap: 4px; }
.vw-leg-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.vw-leg-dot-visitor { background: var(--jackpot); }
.vw-leg-dot-phq { background: var(--accent); }
.vw-leg-hint { color: rgba(148, 163, 184, 0.7); font-style: italic; }

/* Build .76: in-event-modal "Real-world event" badge (PHQ cross-match) */
.modal-phq-match {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 6px 10px;
  background: rgba(34, 211, 238, 0.06);
  border: 1px solid rgba(34, 211, 238, 0.2);
  border-radius: var(--r-chip);
  font-size: 11px;
}
.modal-phq-icon { font-size: 13px; line-height: 1; }
.modal-phq-lbl {
  font-family: monospace;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--accent);
  letter-spacing: 0.05em;
}
.modal-phq-link {
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
}
.modal-phq-link:hover { color: var(--accent); text-decoration: underline; }
.modal-phq-meta {
  font-family: monospace;
  font-size: 10px;
  color: var(--muted);
}
.modal-phq-more {
  color: var(--accent);
  font-weight: 600;
}
.movers-card .movers-name,
.reserved-card .reserved-name { font-weight: 800; }
.placeholder-body {
  padding: 18px 6px 10px;
  text-align: center;
  color: var(--muted);
}
.placeholder-icon {
  font-size: 28px;
  margin-bottom: 8px;
  opacity: 0.85;
}
.placeholder-title {
  font-weight: 700;
  color: var(--text);
  font-size: 13px;
  margin-bottom: 6px;
  letter-spacing: 0.02em;
}
.placeholder-sub {
  font-size: 11px;
  line-height: 1.5;
  max-width: 340px;
  margin: 0 auto;
  color: var(--muted);
}
.placeholder-sub em { color: var(--text); font-style: italic; }
.movers-placeholder .placeholder-icon { color: var(--accent); }

/* Build .67: Top-10 Movers populated rows. Reuses the signals-list /
   sig-row chrome from Smart-Money so platform pills + click-into-event
   modal behavior is consistent across the four list cards. */
/* Build .251: switch movers rows from grid (3-col) to flex so the logo
   added in build .230 doesn't overflow the grid and push the meta chips
   to a second row.  Logo → chip → title (flex:1) → meta (nowrap, right). */
.movers-list .mv-row .sig-link {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 5px;
}
.movers-list .mv-title {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  line-height: 1.35;
}
.movers-list .mv-bet-chip {
  color: var(--muted);
  font-weight: 500;
  font-size: 11px;
}
.movers-list .mv-meta {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: nowrap;
}
.movers-list .mv-pct-pair {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: monospace;
  font-size: 11px;
  color: var(--muted);
}
.movers-list .mv-pct-pair .mv-prior { opacity: 0.7; }
.movers-list .mv-pct-pair .mv-current { color: var(--text); font-weight: 600; }
.movers-list .mv-arrow { font-size: 10px; }
.movers-list .mv-delta {
  font-family: monospace;
  font-weight: 700;
  font-size: 11px;
  padding: 1px 4px;
  border-radius: var(--r-chip);
  white-space: nowrap;
}
.movers-list .mv-up   { color: var(--success); }
.movers-list .mv-down { color: var(--danger); }
.movers-list .mv-delta.mv-up   { background: color-mix(in srgb, var(--success) 10%, transparent); }
.movers-list .mv-delta.mv-down { background: rgba(248, 113, 113, 0.10); }
/* Build .77: 1h delta chip — smaller than the 24h chip so it reads as
   "supplementary context" rather than competing with the headline number.
   Inline label ("24h" / "1h") on each chip so the two are unambiguous. */
.movers-list .mv-delta-lbl {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-right: 4px;
  opacity: 0.85;
}
.movers-list .mv-delta-1h {
  font-size: 10px;
  padding: 1px 5px;
}
.movers-list .mv-delta.mv-flat {
  color: var(--muted);
  background: rgba(138, 150, 196, 0.08);
}
.mv-footnote {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 10px;
  text-align: center;
  cursor: help;
}
.signals-card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 10px 14px;
  /* Natural height — show all rows without an internal scrollbar.
     The page itself scrolls if the panel grows tall. */
}
/* .anomaly-card standalone removed in build .222 — content moved into
   .movers-bottom-half; .anomaly-card-split/.anomaly-top-half classes also
   removed from HTML; retaining .anomaly-bottom-half for sx.bet traders. */
.smartmoney-card { border-top: 3px solid var(--jackpot); }
.signals-card h3 { margin-bottom: 6px; }
.anomaly-bottom-half {
  flex: 0 0 auto;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  margin-top: 6px;
}
.anomaly-bottom-half .sxlb-heading {
  margin: 0 0 6px 0;
  font-size: 12px;
}
.anomaly-bottom-half .sxlb-heading .sxlb-name { color: var(--platform-manifold-brand); font-weight: 800; }
.anomaly-bottom-half .sxlb-heading .plat-sub  { font-size: 10px; color: var(--muted); }
.sxlb-grid-compact {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sxlb-grid-compact .sxlb-row {
  display: grid;
  grid-template-columns: 28px 110px 1fr 1fr;
  align-items: center;
  gap: 8px;
  padding: 3px 8px;
  background: var(--panel-2);
  border-radius: var(--r-chip);
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.sxlb-grid-compact .sxlb-row:hover { background: rgba(192,132,252,0.10); }
.sxlb-grid-compact .sxlb-rank { font-family: monospace; font-size: 11px; font-weight: 800; color: var(--platform-manifold-brand); text-align: center; }
.sxlb-grid-compact .sxlb-wallet { font-family: monospace; font-size: 11px; color: var(--text); }
.sxlb-grid-compact .sxlb-stat { display: flex; flex-direction: column; align-items: flex-end; font-family: monospace; font-size: 11px; font-weight: 700; }
.sxlb-grid-compact .sxlb-stat-lbl { font-size: 8px; font-weight: 400; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0; }
.plat-name.anomaly-name { color: var(--danger); }
.plat-name.smartmoney-name { color: var(--jackpot); }
.signals-list { list-style: none; margin: 0; padding: 0; }
.sig-row { border-bottom: 1px solid var(--border); }
.sig-row:last-child { border-bottom: none; }
.sig-link {
  display: grid; grid-template-columns: 38px 1fr auto; gap: 8px; align-items: center;
  padding: 5px 4px; color: var(--text); font-size: 12px;
}
.sig-link:hover { background: var(--panel-2); text-decoration: none; }
.sig-plat {
  font-size: 9px; font-weight: 800; padding: 2px 5px; border-radius: var(--r-chip);
  letter-spacing: 0.08em; font-family: monospace; text-align: center;
}
.sig-poly .sig-plat { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.sig-kalshi .sig-plat { background: color-mix(in srgb, var(--kalshi) 18%, transparent); color: var(--kalshi); }
.sig-manifold .sig-plat { background: color-mix(in srgb, var(--platform-manifold-brand) 18%, transparent); color: var(--platform-manifold-brand); }
.sig-sxbet .sig-plat { background: rgba(236,72,153,0.18); color: var(--sxbet); }
.sig-limitless .sig-plat { background: rgba(249,115,22,0.18); color: var(--limitless); }
/* Build .32 / .34: Probable + Myriad — both PMXT-sourced, both deserve
   their own platform color so cross-venue groups + tickers stay readable. */
.sig-probable .sig-plat,
.sig-plat.sig-probable { background: rgba(34,197,94,0.18); color: var(--success); }   /* emerald */
.sig-myriad   .sig-plat,
.sig-plat.sig-myriad   { background: color-mix(in srgb, var(--whale) 18%, transparent); color: #f9a8d4; } /* rose */
.sig-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600;
}
.sig-meta { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; justify-self: end; }
.sig-tag {
  background: var(--panel-2); color: var(--muted);
  padding: 1px 6px; border-radius: var(--r-chip); font-family: monospace; font-size: 10px;
  font-weight: 600; white-space: nowrap;
}
.sig-tag.sig-amt { background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot); }
.sig-tag.sig-topbet { background: color-mix(in srgb, var(--whale) 15%, transparent); color: var(--whale); }
.sig-fresh { color: var(--success); font-weight: 800; }
.sig-score {
  background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger);
  padding: 1px 6px; border-radius: var(--r-chip); font-family: monospace; font-size: 10px; font-weight: 700;
}

/* Bettor stance chips (FOR / AGAINST) — clarifies what the whale is
   actually wagering when the side+outcome combo (BUY YES vs SELL NO) is
   ambiguous to non-trader readers. */
.whale-stance {
  display: inline-block; margin-left: 6px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.08em;
  padding: 2px 7px; border-radius: var(--r-chip); text-transform: uppercase;
  vertical-align: middle;
}
.whale-stance-for     { background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success); }
.whale-stance-against { background: color-mix(in srgb, var(--danger) 20%, transparent);  color: var(--danger); }

/* ─── Cross-Platform Arbitrage panel (PolyRouter) ─── */
/* Build v0.31 build 101 (compaction): saves ~25-30px per arb-card by
   tightening padding/gaps/fonts. Visual hierarchy preserved (big bps
   number still dominates; secondary chips smaller). */
.arb-section {
  padding: 4px 20px 8px;
}
.arb-heading {
  margin: 0 0 5px;
  font-size: 12px;
  font-weight: 600;
}
.plat-name.arb-name {
  color: var(--limitless);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
}
.arb-grid {
  display: grid;
  /* Build v.03 .31 build 160 (2026-05-23): re-styled to mirror the
     Hot Underdog card visual identity (per user request "Arb boxes
     should look like hot underdog boxes").  Same 260px minmax + 8px
     gap as .hud-grid; identical layout grammar inside each card. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 6px;
  /* Build .249: stretch so all cards in a row grow to the tallest card's
     height — prevents the "jagged bottom edge" when title lengths differ */
  align-items: stretch;
}
.arb-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 3px solid var(--limitless);
  border-radius: var(--r-chip);
  /* Build .239: redesigned layout — flex-column (title + body row).
     Old grid (auto / 1fr) replaced by flex children with their own padding. */
  padding: 0;
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Full-width title header — always reserves exactly 2 lines of space
   so every card has an identical-height title band regardless of whether
   the title wraps. Build .249: min-height = 2 × line-height + padding. */
.arb-title {
  padding: 5px 8px 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text);
  border-bottom: 1px solid rgba(249, 115, 22, 0.18);
  background: rgba(249, 115, 22, 0.05);
  line-height: 1.3;
  /* Reserve 2 full lines: 2 × (11px × 1.3) + 5px top + 4px bottom ≈ 38px */
  min-height: calc(2 * 1.3em + 9px);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  min-width: 0;
}
.arb-stale-inline { color: var(--danger); font-size: 10px; }
/* Two-column body — flex:1 fills whatever height remains after the
   title band, so cards that are stretched by align-items:stretch fill
   evenly rather than leaving a gap at the bottom. */
.arb-body {
  /* Build .292: single-column stack (was a row split into a flexible left
     column + a fixed 105px right column).  In a 260px grid card the left
     column was only ~150px, so .arb-plat-info (the platform name chip) got
     squeezed to nothing by the price/stance/countdown — the platforms "didn't
     present".  Stacking gives every row the full card width, so platforms
     show, and all fields read as ONE compact card. */
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 0;
}
.arb-left {
  flex: 1 1 auto;
  min-width: 0;
  overflow: visible;         /* Build .292: full-width single column — no clipping */
  padding: 5px 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.arb-right {
  /* Build .292: was a fixed 105px right column; now a full-width horizontal
     meta strip BELOW the platforms (fees / net / vig / persists + liquidity),
     wrapping as needed. */
  flex: 0 0 auto;
  min-width: 0;
  overflow: visible;
  border-left: none;
  border-top: 1px solid rgba(249, 115, 22, 0.15);
  padding: 4px 8px 5px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
/* Spread + net numbers block in left column */
.arb-spread-nums {
  display: flex;
  align-items: baseline;
  gap: 5px;
  flex-wrap: wrap;
}
/* Liquidity box in right column */
.arb-liq {
  /* Build .292: inline in the bottom meta strip (was a centered box pinned to
     the bottom of the old fixed right column via margin-top:auto). */
  margin-top: 0;
  padding: 2px 7px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-radius: var(--r-chip);
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 5px;
}
.arb-liq-icon { font-size: 12px; line-height: 1; }
.arb-liq-amt  { font-family: monospace; font-size: 13px; font-weight: 800; color: var(--accent); line-height: 1.1; }
.arb-liq-label { font-size: 7px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.arb-card:hover {
  border-color: var(--limitless);
}
/* Build v.03 .31 build 160: arb-spread is the LEFT BADGE — directly
   mirrors .hud-mult.  Display only the spread % (no bps, no label —
   .hud-mult shows just "×3.5" + "vol multiplier"; we show "13%" +
   "spread"). */
.arb-spread {
  grid-row: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  background: rgba(249, 115, 22, 0.12);
  border-radius: var(--r-chip);
  padding: 3px 5px;
  min-width: 56px;
}
.arb-spread-bps {
  /* Hidden — replaced visually by .arb-spread-pct below.  Keeping the
     class in the template for any tooling that scrapes bps values. */
  display: none;
}
.arb-spread-pct {
  font-family: monospace;
  font-size: 13px;
  font-weight: 800;
  color: var(--limitless);
  line-height: 1;
}
.arb-spread-label {
  font-size: 8px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 1px;
  text-align: center;
}
/* Build .232/.238: net spread % + countdown timers.
   Timers moved to right column (grid-column:2) in build .238 so the
   left badge stays compact — just the two big numbers + label. */
.arb-spread { min-width: 60px; }
.arb-spread-net {
  font-family: monospace;
  font-size: 13px; font-weight: 800; letter-spacing: 0.01em;
  color: var(--limitless);
  margin-top: 0;
  text-align: center; white-space: nowrap; line-height: 1;
}
.arb-spread-net-strong { color: var(--success); }
.arb-spread-net-zero   { color: var(--danger); }
.arb-countdowns {
  grid-column: 2;
  display: flex; flex-direction: row; flex-wrap: wrap; gap: 6px;
  align-items: center; margin: 0;
}
/* Build .242: arb-plat-info wraps all left content so arb-cd-row
   never gets squeezed off screen. arb-cd-plat removed (redundant). */
.arb-plat-info {
  flex: 1 1 0; min-width: 0; overflow: hidden;
  display: flex; align-items: center; gap: 4px;
}
.arb-cd-row {
  display: flex; flex-direction: row; align-items: center; gap: 3px;
  flex-shrink: 0; flex: 0 0 auto;
}
.arb-cd-timer {
  font-family: 'Courier New', Courier, monospace;
  font-size: 12px; font-weight: 700;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: var(--r-chip);
  padding: 1px 4px;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
/* Build .250: flash red when ≤ 30 min remain on an arb. */
@keyframes arb-urgent-flash {
  0%, 100% { color: var(--danger); background: color-mix(in srgb, var(--danger) 20%, transparent); border-color: color-mix(in srgb, var(--danger) 55%, transparent); }
  50%       { color: #ff8080; background: color-mix(in srgb, var(--danger) 4%, transparent); border-color: color-mix(in srgb, var(--danger) 18%, transparent); }
}
.arb-cd-timer-urgent {
  animation: arb-urgent-flash 1s ease-in-out infinite;
}
/* Operator 2026-06-15: tiered "ending in" countdown emphasis. Toggled by
   _tickCountdowns() on arb-card timers, departures-board close cells, and
   center-band closing metrics alike.
     < 7 days   → bolder
     < 24 hours → + distinguishable background
     < 30 min   → + blink (.arb-cd-timer-urgent, above) */
.arb-cd-timer-week {
  font-weight: 800;
  color: var(--text);
}
.arb-cd-timer-day {
  font-weight: 800;
  color: var(--text);
  /* Operator 2026-06-16: 22% wash was too faint to read as "highlighted" on the
     small right-aligned CLOSES cell — bumped to 40% + a 70% border so a <24h
     clock clearly pops as a chip (verified on the live board). */
  background: color-mix(in srgb, var(--accent) 40%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 70%, transparent);
  border-radius: var(--r-chip, 4px);
  padding: 0 5px;
}
/* Colorful buy/sell arrows on platform rows */
.arb-stance-buy  { color: var(--success) !important; font-weight: 800; }
.arb-stance-sell { color: var(--danger) !important; font-weight: 800; }
.arb-event-title {
  /* Build v.03 .31 build 160: mirror .hud-event-title exactly. */
  grid-column: 2;
  font-size: 11px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.25;
  margin: 1px 0;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Build v.03 .31 build 172: clickable event-title link inside arb-card.
   Removed in build v0.35 20260523.173 — title is now plain text, the
   whole card click opens the disambiguation modal instead.  Style
   kept for any stragglers but the template no longer emits it. */
.arb-event-title-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

/* Build v0.35 20260523.173: arb-card platform CHIP link — explicit
   external arrow + visual cue that this is the only thing in the row
   that escapes the arb-card's outer disambiguation handler. */
.arb-plat-chip-link {
  text-decoration: none;
  cursor: pointer;
  position: relative;
  transition: filter 120ms ease;
}
.arb-plat-chip-link:hover {
  filter: brightness(1.18);
  text-decoration: none;
}

/* Disambiguation modal: platform name in the cross-platform table
   is now a clickable per-venue event-card link. */
.arb-modal-plat-link {
  text-decoration: none;
  cursor: pointer;
  transition: filter 120ms ease, box-shadow 120ms ease;
}
.arb-modal-plat-link:hover {
  filter: brightness(1.20);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent);
}
/* VWAP "True Global Odds" chip on each arb-card. Sits in column 2 of
   the arb-card grid (the arb-spread block in col 1 already spans every
   row), between the event title and the per-platform price rows. */
.arb-vwap {
  grid-column: 2;
  display: flex; align-items: center; gap: 5px;
  margin: 1px 0;
  padding: 2px 6px;
  background: color-mix(in srgb, var(--kalshi) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--kalshi) 20%, transparent);
  border-radius: var(--r-chip);
  font-size: 10px;
  min-width: 0;
}
.arb-vwap-icon {
  font-size: 11px; line-height: 1; flex: 0 0 auto;
  width: 14px; text-align: center;
}
.arb-vwap-converged { color: var(--success); }
.arb-vwap-divergent { color: var(--jackpot); }
.arb-vwap-label {
  text-transform: uppercase; letter-spacing: 0.05em;
  font-size: 9px; color: var(--muted);
}
.arb-vwap-pct {
  font-family: monospace; font-weight: 700;
  color: var(--text); font-size: 11px;
}
.arb-vwap-meta {
  font-size: 9px; color: var(--muted);
  margin-left: auto;
  font-family: monospace;
}

/* VWAP block in the cross-venue group modal */
.eg-vwap {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 12px 0; padding: 12px 14px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--kalshi) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--kalshi) 30%, transparent);
}
.eg-vwap-converged { border-left: 4px solid var(--success); }
.eg-vwap-divergent { border-left: 4px solid var(--jackpot); }
.eg-vwap-icon {
  font-size: 22px; line-height: 1; flex: 0 0 auto;
}
.eg-vwap-converged .eg-vwap-icon { color: var(--success); }
.eg-vwap-divergent .eg-vwap-icon { color: var(--jackpot); }
.eg-vwap-body { flex: 1; min-width: 0; }
.eg-vwap-headline {
  font-size: 14px; color: var(--text);
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.eg-vwap-headline strong { font-family: monospace; font-size: 18px; color: var(--kalshi); }
.eg-vwap-confidence {
  font-size: 10px; padding: 1px 6px; border-radius: var(--r-chip);
  text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;
}
.eg-vwap-conf-high   { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--success); }
.eg-vwap-conf-medium { background: color-mix(in srgb, var(--kalshi) 15%, transparent); color: var(--kalshi); }
.eg-vwap-conf-low    { background: rgba(148,163,184,0.15); color: var(--muted); }
.eg-vwap-sub {
  font-size: 11px; color: var(--muted); margin-top: 4px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.eg-vwap-tag {
  font-size: 10px; padding: 1px 6px; border-radius: var(--r-chip);
  text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;
}
.eg-vwap-tag-good { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--success); }
.eg-vwap-tag-warn { background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot); }

/* Build v.03 .31 build 160: arb-platforms now mirrors .hud-options —
   a flex-column of single-line rows, one per venue.  Cheapest YES
   (BUY side) gets a green-tinted row; most expensive (SELL side)
   gets a red tint; middle venues stay neutral.  Same compact
   flex-row pattern as .hud-option. */
.arb-platforms {
  grid-column: unset;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
}
.arb-plat-row {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 2px 4px;
  border-radius: var(--r-chip);
  font-size: 10px;
  min-width: 0;
  overflow: hidden;
  text-decoration: none;
  color: var(--text);
  background: rgba(148, 163, 184, 0.05);
  border: 1px solid rgba(148, 163, 184, 0.15);
}
.arb-plat-row:hover {
  text-decoration: none;
  background: rgba(148, 163, 184, 0.10);
}
/* Cheapest YES → BUY side; tint green. */
.arb-plat-row.arb-buy-side {
  background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.30);
}
.arb-plat-row.arb-buy-side:hover {
  background: rgba(34, 197, 94, 0.14);
}
/* Most-expensive YES → SELL side; tint red. */
.arb-plat-row.arb-sell-side {
  background: color-mix(in srgb, var(--danger) 7%, transparent);
  border-color: color-mix(in srgb, var(--danger) 28%, transparent);
}
.arb-plat-row.arb-sell-side:hover {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}
.arb-plat-row .sig-plat {
  flex: 0 0 auto;
  font-size: 9px;
}
.arb-plat-price {
  flex: 0 0 auto;            /* Build .265: never shrink — always visible */
  font-family: monospace;
  font-weight: 700;
  font-size: 11px;
  color: var(--text);
  flex: 0 0 auto;
}
.arb-plat-vol {
  flex: 1 1 0;
  min-width: 0;
  color: var(--muted);
  font-family: monospace;
  font-size: 9px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
}
.arb-plat-spread {
  flex: 0 0 auto;
  font-family: monospace;
  color: var(--muted);
  font-size: 9px;
}
.arb-plat-stance {
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.arb-plat-row.arb-buy-side  .arb-plat-stance { color: var(--success, var(--success)); }
.arb-plat-row.arb-sell-side .arb-plat-stance { color: var(--danger,  var(--danger)); }
.arb-plat-row:hover {
  text-decoration: none;
  color: var(--limitless);
}
.arb-plat-price {
  font-weight: 700;
  color: var(--accent);
}
/* .arb-plat-vol moved to a single definition above (build 159) —
   left-aligned now so volume reads next to price instead of being
   shoved to the right edge. */

/* Modal additions for the arb side-by-side view */
.arb-table .arb-yes-price {
  font-family: monospace;
  font-size: 14px;
  font-weight: 800;
  color: var(--accent);
}
.arb-stance {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-chip);
  font-family: monospace;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
}
.arb-stance.arb-buy  { background: rgba(34, 197, 94, 0.20); color: var(--success); }
.arb-stance.arb-sell { background: color-mix(in srgb, var(--danger) 20%, transparent); color: var(--danger); }
.arb-table .arb-vol { font-family: monospace; color: var(--muted); }
.arb-table .arb-link a { color: var(--accent); text-decoration: none; }
.arb-disclaimer {
  margin-top: 14px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--jackpot) 10%, transparent);
  border-left: 3px solid var(--jackpot);
  border-radius: var(--r-chip);
  font-size: 11px;
  color: var(--muted);
  line-height: 1.5;
}

/* Tier 1 arb enrichments (build .45): arb-size chip, stale flags,
   closed/paused platform chips, per-platform spread chip, modal
   columns for depth / spread / delta_1h. */
.arb-size {
  grid-column: unset;
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin: 0;
  min-width: 0;
  flex-wrap: wrap;
  /* Build .246: brighter band-tinted halo around the max-size row */
  padding: 3px 6px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--success) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
}
.arb-size[data-band="green"]  { background: color-mix(in srgb, var(--success) 15%, transparent); border-color: color-mix(in srgb, var(--success) 40%, transparent); }
.arb-size[data-band="amber"]  { background: color-mix(in srgb, var(--jackpot) 15%, transparent); border-color: color-mix(in srgb, var(--jackpot) 40%, transparent); }
.arb-size[data-band="red"]    { background: color-mix(in srgb, var(--danger) 15%, transparent); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.arb-size[data-band="unknown"] { background: rgba(148, 163, 184, 0.08); border-color: rgba(148, 163, 184, 0.22); }
.arb-size-icon {
  font-family: monospace;
  font-size: 11px;
  font-weight: 800;   /* Build .284: bolder tilde (was 400/normal — looked thin next to the 800-weight max-size amount) */
  color: var(--muted);
}
.arb-size-amt {
  font-family: monospace;
  font-size: 18px;
  font-weight: 800;
  color: var(--success);
}
.arb-size-label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 9px;
  color: var(--muted);
}
.arb-size-val { font-weight: 700; }

/* Build v0.35 20260525.223: color-grade the arb-size chip based on the
   `size_band` projection from self_arb_opportunities (green ≥ $1k,
   amber $100-1k, red < $100, unknown when depth is 0/missing). Gives
   the operator an at-a-glance "is this arb actually fillable?" answer
   per BI research 2026-05-25.  Color overrides the default green so
   amber/red unambiguously signal "small" / "paper" arbs. */
.arb-size[data-band="green"]  .arb-size-amt { color: var(--success); }
.arb-size[data-band="amber"]  .arb-size-amt { color: var(--jackpot); }
.arb-size[data-band="red"]    .arb-size-amt { color: var(--danger); }
.arb-size[data-band="unknown"] .arb-size-amt { color: var(--muted, var(--muted)); }

/* Per-side breakdown subtext: compact "Buy $4.5k · Sell $200" line
   under the headline max-size chip.  Color-cues mirror the existing
   .arb-buy-side / .arb-sell-side scheme on platform rows so the user
   reads them as the same buy/sell visual language. */
.arb-size-breakdown {
  display: inline-flex;
  align-items: baseline;
  max-width: 100%;           /* Build .256: never overflow arb-left column */
  overflow: hidden;
  text-overflow: ellipsis;
  gap: 4px;
  font-family: monospace;
  font-size: 10px;
  margin-left: 6px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.arb-size-leg-sep { color: var(--muted, var(--muted)); }
.arb-size-buy  { color: var(--success, var(--success)); }
.arb-size-sell { color: var(--danger,  var(--danger)); }
/* On amber / red headline, soften the per-side coloration so the
   warning state dominates the visual hierarchy. */
.arb-size[data-band="red"]   .arb-size-buy,
.arb-size[data-band="red"]   .arb-size-sell,
.arb-size[data-band="amber"] .arb-size-buy,
.arb-size[data-band="amber"] .arb-size-sell { opacity: 0.75; }

.arb-card-stale {
  background: rgba(148, 163, 184, 0.04);
  border-left-color: var(--muted);
  opacity: 0.82;
}
.arb-card-stale:hover { border-color: var(--muted); }

.arb-stale-flag {
  grid-column: 2;
  margin: 2px 0 0 0;
  padding: 2px 8px;
  background: color-mix(in srgb, var(--jackpot) 12%, transparent);
  border-left: 2px solid var(--jackpot);
  border-radius: var(--r-chip);
  font-size: 10px;
  color: var(--jackpot);
  font-weight: 600;
  width: fit-content;
  letter-spacing: 0.03em;
}

/* ──────────────────────────────────────────────────────────────
   Hot Underdogs section (build v.03 .99.4; recolored .99.13)
   Mirrors the arb-card grid layout but in Kelly green (var(--success)) to
   distinguish from the orange arb cards. Green signals "opportunity /
   smart-money inflow" rather than the original crimson "alert/heat".
   Same 60s refresh cadence; different signal class (per-platform
   smart-money vs cross-platform arbs).
   ────────────────────────────────────────────────────────────── */
/* Build v0.31 build 101 (compaction): mirrors the arb-card compaction
   pass — saves ~25-30px per hud-card. Same hierarchy preserved (large
   green multiplier dominates; secondary chips smaller). */
.hud-section {
  padding: 4px 20px 8px;
}
.hud-heading {
  margin: 0 0 5px;
  font-size: 12px;
  font-weight: 600;
}
.plat-name.hud-name {
  color: var(--success);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
}
.hud-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 8px;
}
.hud-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 3px solid var(--success);
  border-radius: var(--r-chip);
  padding: 0;
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
  /* Build .239: flex-column — header + body + options + meta + progress */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.hud-card:hover {
  border-color: var(--success);
}
/* Header row: mult (left) + new money (right) */
.hud-header {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 5px 8px 4px;
  border-bottom: 1px solid rgba(22, 163, 74, 0.15);
  background: rgba(22, 163, 74, 0.05);
}
.hud-mult {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: none;
  border-radius: 0;
  padding: 0;
  min-width: unset;
  grid-row: unset;
}
.hud-mult-x {
  font-family: monospace;
  font-size: 18px;
  font-weight: 800;
  color: var(--success);
  line-height: 1;
}
.hud-mult-label {
  font-size: 8px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 1px;
  text-align: left;
}
.hud-inc {
  grid-column: unset;
  flex: 1;
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 4px;
  margin: 0;
  min-width: 0;
}
.hud-inc-amt {
  font-family: monospace;
  font-size: 13px;
  font-weight: 800;
  color: var(--success);
}
.hud-inc-label {
  font-size: 9px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
/* Build .239: body row = content (left) + liq box (right) */
.hud-body {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 0;
  padding: 5px 8px 4px;
  min-width: 0;
}
.hud-content {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.hud-liq {
  flex: 0 0 80px;
  border-left: 1px solid rgba(22, 163, 74, 0.15);
  margin-left: 8px;
  padding: 4px 6px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-radius: var(--r-chip);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1px;
}
.hud-liq-icon  { font-size: 12px; line-height: 1; }
.hud-liq-amt   { font-family: monospace; font-size: 13px; font-weight: 800; color: var(--accent); line-height: 1.1; }
.hud-liq-label { font-size: 7px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.hud-platform-chip {
  grid-column: unset;
  margin: 0;
  min-width: 0;
  overflow: hidden;
  font-size: 10px;
}
.hud-event-title {
  grid-column: unset;
  font-size: 11px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.25;
  margin: 1px 0;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Build v.03 .31 build 172: clickable event-title link inside hud-card.
   Symmetric with .arb-event-title-link — see comment there. */
.hud-event-title-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  border-bottom: 1px dotted color-mix(in srgb, var(--kalshi) 0%, transparent);
  transition: border-bottom-color 120ms ease, color 120ms ease;
}
.hud-event-title-link:hover,
.hud-event-title-link:focus {
  color: var(--kalshi);
  border-bottom-color: color-mix(in srgb, var(--kalshi) 60%, transparent);
  outline: none;
}
.hud-options {
  grid-column: unset;
  padding: 0 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 2px 0 1px 0;
}
.hud-option {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  font-size: 10px;
  min-width: 0;
  overflow: hidden;
}
.hud-underdog {
  background: rgba(22, 163, 74, 0.08);
  border: 1px solid rgba(22, 163, 74, 0.30);
}
.hud-leader {
  background: rgba(148, 163, 184, 0.05);
  border: 1px solid rgba(148, 163, 184, 0.15);
}
.hud-option-marker {
  font-size: 11px;
  line-height: 1;
  flex: 0 0 auto;
  width: 12px;
  text-align: center;
}
.hud-underdog .hud-option-marker { color: var(--success); }
.hud-leader   .hud-option-marker { color: var(--muted); }
.hud-option-label {
  /* flex-basis 0 (not auto) + min-width 0 so this child can shrink below
     its content width and the ellipsis clip kicks in. flex:1 1 auto was
     the cause of the overflow — auto basis = "don't shrink below content". */
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  /* Build v0.35 20260523.193: bolder betting-option title per user
     request — the underdog/leader candidate name is the focal point
     of the Hot Underdog card, so weight it heavier than the meta
     chips and price stamp. */
  font-weight: 700;
}
.hud-option-pct {
  font-family: monospace;
  font-weight: 700;
  font-size: 11px;
  color: var(--text);
  margin-left: auto;
}
.hud-meta {
  grid-column: unset;
  padding: 3px 8px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: 2px;
  min-width: 0;
}
.hud-meta-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;                  /* Build .266: +1px to balance the larger text */
  padding: 2px 6px;          /* Build .266: was 1px 5px */
  border-radius: var(--r-chip);
  /* Build .267: brighter "Before" chip — opacity 0.06 → 0.18 (3×) on bg,
     0.18 → 0.50 on border so the value reads as a proper highlighted chip
     rather than a barely-tinted span. */
  background: rgba(148, 163, 184, 0.18);
  border: 1px solid rgba(148, 163, 184, 0.50);
  font-size: 11px;
}
.hud-meta-chip.hud-meta-now {
  /* Build .267: brighter "Now" chip — opacity 0.06 → 0.20 on bg, 0.20 →
     0.55 on border.  Stronger kelly-green so the "Now" value reads as
     fresh/positive without needing the user to squint. */
  background: rgba(22, 163, 74, 0.20);
  border-color: rgba(22, 163, 74, 0.55);
}
/* Build .267: brighter inner text colors on both chips so the value
   pops against the brighter background. */
.hud-meta-chip .hud-meta-label { color: var(--text); }         /* slate-300, was --muted */
.hud-meta-chip .hud-meta-val   { color: #f1f5f9; }         /* slate-100, was --text */
.hud-meta-chip.hud-meta-now .hud-meta-label { color: #86efac; }   /* green-300 */
.hud-meta-chip.hud-meta-now .hud-meta-val   { color: #bbf7d0; }   /* green-200 */

/* Build v.03 .99.6: flag emojis next to country ISO codes.
   Slightly larger than the iso2 text and vertically nudged to align
   with the all-caps letters. Used inside .country-chip and inside
   .hud-meta-chip wherever a country is rendered. */
.flag-glyph {
  font-size: 1.1em;
  line-height: 1;
  vertical-align: -0.05em;
  /* Don't apply text-decoration / color filters from parent link. */
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji",
               "Twemoji Mozilla", system-ui, sans-serif;
}
.hud-meta-label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 10px;           /* Build .266: was 8px (+25% to keep label/val ratio readable) */
  color: var(--muted);
}
.hud-meta-val {
  font-family: monospace;
  font-weight: 700;
  font-size: 11px;           /* Build .266: was 9px (+22%) */
  color: var(--text);
}
/* Build .239: progress bar — underdog% | bar | leader% */
.hud-progress {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px 6px;
}
.hud-prog-ud, .hud-prog-lead {
  font-family: monospace;
  font-size: 11px;
  font-weight: 700;
  flex: 0 0 auto;
}
.hud-prog-ud   { color: var(--success); }
.hud-prog-lead { color: var(--muted); }
.hud-prog-bar  {
  flex: 1;
  height: 4px;
  background: rgba(148, 163, 184, 0.20);
  border-radius: var(--r-chip);
  overflow: hidden;
}
.hud-prog-fill {
  height: 100%;
  background: var(--success);
  border-radius: var(--r-chip);
  max-width: 100%;
}

.arb-plat-closed {
  opacity: 0.55;
  text-decoration: line-through;
}
.arb-plat-status {
  display: inline-block;
  padding: 0 5px;
  font-size: 9px;
  font-weight: 700;
  border-radius: var(--r-chip);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
  margin-left: 4px;
}
.arb-plat-closed-chip {
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  color: var(--danger);
}
.arb-plat-paused-chip {
  background: color-mix(in srgb, var(--jackpot) 18%, transparent);
  color: var(--jackpot);
}

.arb-plat-spread {
  font-size: 9px;
  color: var(--muted);
  font-family: monospace;
  margin-left: 4px;
}

/* Modal table extra columns */
.arb-depth, .arb-spread-cell, .arb-delta {
  font-family: monospace;
  font-size: 12px;
  color: var(--text);
}
.arb-depth { text-align: right; }
.arb-depth-est {
  color: var(--muted);
  font-size: 10px;
  margin-left: 2px;
  font-weight: 400;
}
/* narrow-depth .636 (operator: shared with the free UI): the fillable-at-quote
   secondary figure beside the wide depth. Muted + smaller; vars only. */
.arb-depth-narrow {
  color: var(--muted);
  font-size: 0.86em;
  font-weight: 400;
  white-space: nowrap;
}
.arb-spread-cell { text-align: right; color: var(--muted); }
.arb-delta { text-align: right; }
.arb-delta-up   { color: var(--success); }
.arb-delta-down { color: var(--danger);  }
.arb-delta-flat { color: var(--muted); }

.arb-row-stale {
  opacity: 0.6;
  text-decoration: line-through;
}
.arb-row-stale .arb-stance { opacity: 0.75; }

/* Tier 2 meta-strip (build .46): fees / net spread / implied vig /
   persistence_hours. Lives at the bottom of the arb-card and at the
   top of the arb modal (between the headline and the table). */
.arb-meta {
  grid-column: unset;
  display: flex;
  flex-direction: row;       /* Build .292: horizontal chip strip (was a vertical column) */
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 0;
  min-width: 0;
}
/* In the right column, each chip is a row: label left, val right */
.arb-right .arb-meta-chip {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.arb-meta-modal {
  margin: 8px 0 4px;
}
.arb-meta-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  padding: 1px 5px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-chip);
  font-family: monospace;
  font-size: 9px;
  color: var(--text);
  cursor: help;
}
.arb-meta-label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 8px;
  color: var(--muted);
}
.arb-meta-val { font-weight: 700; }

.arb-meta-fee     { border-color: rgba(148,163,184,0.30); }
.arb-meta-net     { border-color: color-mix(in srgb, var(--kalshi) 30%, transparent); }
.arb-meta-net-zero {
  opacity: 0.65;
  background: rgba(148,163,184,0.10);
}
.arb-meta-net-zero .arb-meta-val { color: var(--muted); }
.arb-meta-net-strong {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.arb-meta-net-strong .arb-meta-val { color: var(--success); }

.arb-meta-vig     { border-color: color-mix(in srgb, var(--jackpot) 30%, transparent); }
.arb-meta-vig .arb-meta-val { color: var(--jackpot); }
.arb-meta-vig-arb {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
}
.arb-meta-vig-arb .arb-meta-val { color: var(--success); }

.arb-meta-persist { border-color: color-mix(in srgb, var(--kalshi) 30%, transparent); }
.arb-meta-persist .arb-meta-val { color: var(--kalshi); }

.arb-meta-size { border-color: color-mix(in srgb, var(--accent) 30%, transparent); }
.arb-meta-size .arb-meta-val { color: var(--success); }

/* Modal table extra columns (build .46) */
.arb-fee-cell {
  font-family: monospace;
  font-size: 12px;
  text-align: right;
  color: var(--muted);
}
.arb-fee-cell .arb-fee-none { color: var(--success); font-weight: 700; }

@media (max-width: 600px) {
  .arb-grid { grid-template-columns: 1fr; }
}

/* Public wallet page (/wallet/<addr>) — long-form leaderboard profile */
.wallet-page-main { padding: 16px 20px 80px; max-width: 1200px; margin: 0 auto; }
.wallet-not-found { text-align: center; padding: 60px 20px; color: var(--muted); }
.wallet-not-found h1 { color: var(--text); margin-bottom: 8px; }
/* 2026-07-02 (operator): de-Orca the wallet-hero top. The prior treatment
   (soft rounded pills + rounded panel-2 stat boxes w/ teal mono numerals on
   dark navy) read like OrcaLayer's wallet profile. Re-anchored in OUR locked
   design language instead — the DEPARTURES BOARD (CLAUDE.md design tenet):
   brand three-stripe band (title-gradient DNA), split-flap uppercase name,
   ticket-stub badges, Solari flip-tiles w/ amber digits. CSS vars only. */
.wallet-hero {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 0 0 var(--r-card) var(--r-card);   /* squared top — the stripe band butts the edge */
  padding: 26px 24px 22px; margin-bottom: 20px;
  position: relative; overflow: hidden;
}
.wallet-hero::before {   /* EventTracker signature stripes: teal / pink / amber */
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: linear-gradient(180deg,
    var(--accent) 0 33.4%, var(--whale) 33.4% 66.7%, var(--jackpot) 66.7% 100%);
}
.wallet-hero-name {
  font-size: 26px; font-weight: 800; margin: 0 0 4px;
  text-transform: uppercase; letter-spacing: 0.07em;   /* departure boards are uppercase */
}
.wallet-hero-name .wallet-aka { text-transform: none; letter-spacing: 0.02em; }  /* pseudonym pill stays literal */
.wallet-hero-addr { font-family: monospace; font-size: 12px; color: var(--muted); margin-bottom: 16px; }
.wallet-hero-addr code { font-size: 11px; word-break: break-all; }
.wallet-hero-empty { font-size: 13px; color: var(--muted); padding: 12px 0; }

/* Build v0.4 (operator 2026-06-07): ET& wallet-follow ⭐ button + the
   /me/follows management table. Theme vars only — auto-themes for peach.
   Button lives inline in the wallet-hero-addr row; toggles between ☆/★. */
/* Build v0.4 Phase 1.5 (operator 2026-06-07): site-wide follow-nickname overlay.
   When the authenticated client (window.applyFollowNicknames) finds a wallet-link
   for a followed wallet, it adds class `wallet-link-followed` + injects a ★ chip
   + the user's PRIVATE nickname. CSS theme vars only — auto-themes for peach.
   Privacy invariant: server never emits these classes; only the client overlays
   them after auth. */
.wallet-link-followed { color: var(--accent); font-weight: 600; }
.wallet-link-followed:hover { color: var(--accent); text-decoration: underline; }
.wallet-link-star {
  display: inline-block;
  margin-right: 3px;
  color: var(--jackpot, var(--accent));
  font-size: 0.9em;
  vertical-align: -1px;
}
.wallet-link-nick { font-style: italic; }

.wallet-follow-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  background: transparent; color: var(--muted);
  border: 1px solid var(--border); border-radius: var(--r-chip);
  font-size: 11px; font-family: inherit; cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.wallet-follow-btn:hover { color: var(--accent); border-color: var(--accent); }
.wallet-follow-btn.wallet-follow-on {
  color: var(--accent); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.wallet-follow-btn.wallet-follow-on:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.wallet-follow-icon { font-size: 14px; line-height: 1; }

/* /me/follows management table */
.follows-table { font-size: 13px; }
.follows-table thead tr { border-bottom: 1px solid var(--border); color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.follows-table tbody tr { border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent); }
.follows-table tbody tr:last-child { border-bottom: none; }
.follow-target-link { color: var(--text); text-decoration: none; }
.follow-target-link:hover .follow-target-code,
.follow-target-link:hover .follow-target-aka { color: var(--accent); }
.follow-target-code { font-size: 12px; }
/* ww-aka 2026-07-08: resolved wallet name / AKA in the follows list (proportional,
   not the mono hash). */
.follow-target-aka { font-size: 13px; font-weight: 600; }
.follow-type-chip { display: inline-block; margin-left: 6px; padding: 1px 6px; font-size: 9px; border-radius: var(--r-chip); background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); font-weight: 700; letter-spacing: 0.05em; }
.follow-edit-nick { margin-left: 6px; background: transparent; border: none; color: var(--muted); cursor: pointer; font-size: 12px; padding: 0 2px; }
.follow-edit-nick:hover { color: var(--accent); }
.follow-mode-sel { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-chip); padding: 2px 4px; font-size: 12px; font-family: inherit; }
.follow-unfollow { background: transparent; color: var(--danger, #f43f5e); border: 1px solid color-mix(in srgb, var(--danger, #f43f5e) 40%, transparent); border-radius: var(--r-chip); padding: 3px 9px; font-size: 11px; font-family: inherit; cursor: pointer; transition: background 0.12s, border-color 0.12s; }
.follow-unfollow:hover { background: color-mix(in srgb, var(--danger, #f43f5e) 14%, transparent); border-color: var(--danger, #f43f5e); }
.wallet-hero-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
/* 2026-07-02 de-Orca: badges are TICKET STUBS (square corners, dashed edge,
   solid semantic-colored left stub-bar) — not the soft rounded emoji pills
   every trader-profile site ships. Variant rules recolor the stub bar. */
.wallet-badge {
  display: inline-block; padding: 4px 10px; border-radius: 2px;
  background: color-mix(in srgb, var(--panel-2) 82%, transparent); color: var(--text);
  border: 1px dashed color-mix(in srgb, var(--muted) 40%, transparent);
  border-left: 3px solid var(--accent);
  font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
}
.wallet-badge-roi.roi-strong { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); border-left-color: var(--success); }
.wallet-badge-roi.roi-good   { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); border-left-color: var(--success); }
.wallet-badge-roi.roi-mid    { color: var(--muted); border-left-color: color-mix(in srgb, var(--muted) 60%, transparent); }
.wallet-badge-roi.roi-bad    { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); border-left-color: var(--danger); }
.wallet-badge-elite {
  background: color-mix(in srgb, var(--jackpot) 14%, transparent);
  color: var(--jackpot); border-left: 3px solid var(--jackpot);
  font-size: 12px; font-weight: 800;
}
.wallet-hero-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px;
}
/* 2026-07-02 de-Orca: stat boxes are SPLIT-FLAP TILES (Solari departures
   board): near-square corners, two-tone flap halves w/ a seam at 50%, and
   AMBER flip-digit numerals (--jackpot) — vs the rounded card + mint numeral
   grammar OrcaLayer uses. The seam is a ::after so it never touches markup. */
.wh-stat {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--panel-2) 94%, white) 0 50%,
    color-mix(in srgb, var(--panel-2) 90%, black) 50% 100%);
  border: 1px solid var(--border); border-radius: 3px;
  padding: 14px; text-align: center; position: relative; overflow: hidden;
}
.wh-stat::after {   /* the flap seam */
  content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
}
.wh-stat-num {
  font-family: monospace; font-size: 22px; font-weight: 800;
  color: var(--jackpot);   /* Solari flip-digit amber */
  text-shadow: 0 0 10px color-mix(in srgb, var(--jackpot) 30%, transparent);
}
/* Build v0.35 20260525.217 (item 1): green/red tint for the Net P&L
   tile in the wallet hero — pulls the PnL sign into the big-bold box
   so visitors don't need to read the small "+" sign to read the trend. */
.wh-stat-num.wh-stat-pos { color: var(--success); }
.wh-stat-num.wh-stat-neg { color: var(--danger); }
.wh-stat-lbl { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }
@media (max-width: 700px) { .wallet-hero-stats { grid-template-columns: repeat(2, 1fr); } }
/* Build v0.4 20260530.283: activity-first hero — 5 columns (was 4) for
   Total bets / Total events / Avg per bet / Avg per event / sparkline.
   The sparkline tile sets `color: var(--accent)` so the inline SVG's
   stroke="currentColor" inherits the accent without a hardcoded hex. */
.wallet-hero-activity { grid-template-columns: repeat(5, 1fr); }
.wh-stat-spark { color: var(--accent); display: flex; flex-direction: column; justify-content: center; }
.wh-spark-wrap { width: 100%; height: 30px; display: flex; align-items: center; justify-content: center; }
.wh-spark-svg { width: 100%; height: 100%; overflow: visible; }
.wh-spark-empty { font-family: monospace; font-size: 18px; font-weight: 800; color: var(--muted); }
@media (max-width: 700px) { .wallet-hero-activity { grid-template-columns: repeat(2, 1fr); } }
/* Build .283: prominent open-positions row under the hero boxes (full page) */
.wallet-openpos-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--r-card);
  padding: 12px 14px; margin: 14px 0 0 0; font-size: 13px;
}

.wallet-platforms { margin-bottom: 18px; }
.wp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; padding: 0 20px; }
.wp-card { background: var(--panel-2); border-radius: var(--r-card); padding: 12px; }
.wp-plat { display: inline-block; margin-bottom: 6px; }
.wp-trades { font-size: 12px; color: var(--muted); }
.wp-vol { font-family: monospace; font-size: 14px; color: var(--accent); margin-top: 2px; }

/* PMXT positions block on /wallet/<addr> pages (added May 13). Live
   open-position data fetched per wallet from pmxt.Polymarket().fetch_positions().*/
.wallet-pmxt { padding: 0 20px; margin-bottom: 24px; }
.wallet-pmxt .section-sub { font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 8px; }
.pmxt-summary {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  margin-bottom: 14px;
}
.pmxt-stat {
  background: var(--panel-2); border-radius: var(--r-card); padding: 10px 14px;
  border-top: 2px solid var(--platform-manifold-brand);
}
.pmxt-stat-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin-bottom: 4px;
}
.pmxt-stat-val { font-family: monospace; font-size: 18px; font-weight: 600; }
.pmxt-pnl-pos { color: var(--success); }
.pmxt-pnl-neg { color: var(--danger); }
.pmxt-plat-header {
  font-size: 13px; margin: 12px 0 6px 0;
  display: flex; align-items: center; gap: 10px;
}
.pmxt-plat-count { color: var(--muted); font-size: 11px; font-weight: 400; }
.pmxt-pos-table {
  width: 100%; border-collapse: collapse; font-size: 12px;
  background: var(--panel-2); border-radius: var(--r-card); overflow: hidden;
}
.pmxt-pos-table th {
  text-align: left; padding: 6px 10px; color: var(--muted);
  font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border);
}
.pmxt-pos-table td { padding: 7px 10px; border-bottom: 1px solid color-mix(in srgb, var(--platform-manifold-brand) 8%, transparent); }
.pmxt-pos-table tr:last-child td { border-bottom: none; }
.pmxt-num { font-family: monospace; text-align: right; }
.pmxt-more { font-size: 11px; color: var(--muted); margin-top: 6px; padding-left: 10px; }
/* Build .68: Market + Bet columns added to the PMXT open-positions table. */
.pmxt-mkt {
  font-size: 13px;
  max-width: 360px;
  cursor: help;
}
.pmxt-mkt a { color: var(--text); text-decoration: none; }
.pmxt-mkt a:hover { color: var(--accent); text-decoration: underline; }
.pmxt-bet {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}
@media (max-width: 700px) {
  .pmxt-summary { grid-template-columns: 1fr; }
  .pmxt-mkt { max-width: 180px; font-size: 11px; }
}

/* Build v0.4 20260526.229: sx.bet L3 surfacing.

   Two pieces:
     1. The "↔ Also on sx.bet" cross-match chip in the wallet hero
        badges row.  Fires when this Polymarket EOA is also active
        as an sx.bet maker (per the L3 archive's wallet_index).
        Cyan-purple tint differentiates it from green ROI badges.
     2. The "🎯 sx.bet Open Orders" panel just above the recent-trades
        section.  Reuses .pmxt-pos-table for layout consistency
        with the PMXT open-positions block — purpose is similar
        (forward-looking exposure), and one shared visual vocab
        keeps the page legible. */
.wallet-badge-cross-match {
  /* 2026-07-02 de-Orca: keep the ticket-stub grammar (dashed edge + solid
     left stub-bar) — the cyan is the cross-venue semantic color. */
  background: color-mix(in srgb, var(--platform-manifold-brand) 14%, transparent);
  color: var(--text);
  border: 1px dashed color-mix(in srgb, var(--muted) 40%, transparent);
  border-left: 3px solid var(--platform-manifold-brand);
}
.wallet-badge-bot {
  /* sxbet-forensics v3: honest "automated market-maker" label — amber (the
     dominant-palette caution hue) in the same ticket-stub grammar. */
  background: color-mix(in srgb, var(--jackpot) 15%, transparent);
  color: var(--text);
  border: 1px dashed color-mix(in srgb, var(--muted) 40%, transparent);
  border-left: 3px solid var(--jackpot);
  text-transform: none;   /* the reason string reads as prose, not a shout */
}

/* Build v0.4 20260526.230: per-source logo emblems sitting beside the
   text platform-chips throughout tickers, cards, and event rows.  The
   existing .sig-plat coloured badge stays (color affordance + fallback
   when a venue has no PNG yet) — the logo just makes the brand
   immediately scannable.  Sized to align with the smaller ticker
   chips; on rows that use larger 14-16 px logos elsewhere (top-20
   list, board panels) the existing .mkt-logo / .board-panel-logo
   rules keep those bigger. */
.plat-chip-logo {
  width: 14px;
  height: 14px;
  vertical-align: middle;
  margin-right: 4px;
  border-radius: var(--r-chip);
  flex-shrink: 0;
}
/* Build .252: Manifold logo is dark indigo — almost invisible on our dark
   background.  Boost brightness universally wherever it appears. */
img[src*="manifold"] { filter: brightness(3) saturate(0.9); }

/* Gemini Titan logo: black ring-mark cleaned to transparent (white tile +
   clipped right-edge glyph removed).  Invert so the black mark renders white
   on the dark theme; the peach twin (below) restores it to dark on light. */
img[src*="gemini_titan"] { filter: invert(1); }

/* smarkets-logo (.410, 2026-06-20): the global `img[src*="smarkets"]` scale
   override (.407 1.4× → .409 2.52×) was REMOVED. ROOT CAUSE it caused: an
   attribute selector (specificity 0,1,1) outranks `.mkt-logo` (0,1,0, which
   sets its own scale(1.2)) and `.dep-venue-logo`/`.plat-chip-logo` (14px), so
   Smarkets rendered 2.52× in EVERY context — ~35px inline (too big) and ~40px
   in the compact Marketplace row, overflowing the cell + clipping to an
   unrecognizable slice ("disappeared" when data IS present). Fix = no override:
   Smarkets follows the SAME per-context sizing as every other venue logo.
   ⛔ NEVER re-add a global smarkets scale — if the mark reads small, fix the
   ASSET (de-pad the PNG), not a transform that fights the per-context rules. */

/* smarkets-circle 2026-06-21 (operator): the smarkets.png asset is a dark-circle
   logo that reads ~50% smaller than peers in two specific surfaces. Bump it +50%
   in ONLY those two contexts, Smarkets-scoped — NOT a global transform (that was
   the .340-era footgun that clipped the compact rows). Specificity wins cleanly:
   `.mkt-logo[src*=smarkets]` (0,2,0) > base `.mkt-logo` (0,1,0); the scoped
   modal-header rule (0,3,0) > base `.plat-chip-logo` (0,1,0). Transform keeps the
   layout box fixed (rows don't grow); only the visible dark circle enlarges. The
   compact board/ticker `.plat-chip-logo` rows are deliberately UNTOUCHED. */
.mkt-logo[src*="smarkets"] { transform: scale(1.8); }                      /* marketplace icon: 1.2 base × 1.5 */
.modal-platform .plat-chip-logo[src*="smarkets"] { transform: scale(1.5); } /* event-modal icon: +50% */

.wallet-sxbet-orders { padding: 0 20px; margin-bottom: 24px; }
.wallet-sxbet-orders .section-sub {
  font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 8px;
}
.sxbet-orders-wrap { overflow-x: auto; }
.sxbet-orders-table th:first-child,
.sxbet-orders-table td:first-child { padding-left: 12px; }
/* Subtle cyan top-stripe so the section reads as sx.bet at a glance,
   echoing the cross-match chip palette. */
.sxbet-orders-table {
  border-top: 2px solid rgba(34,211,238,0.45);
}
.sxbet-exp {
  font-size: 11px; color: var(--muted);
  white-space: nowrap;
}

.wallet-trades-wrap { padding: 0 20px; overflow-x: auto; }
.wallet-page .back-link {
  font-size: 12px; color: var(--muted); text-decoration: none;
}
.wallet-page .back-link:hover { color: var(--accent); }

/* Elite-wallet styling on the leaderboard panel */
.sig-row-elite { background: linear-gradient(90deg, rgba(34,197,94,0.06), transparent); }
.elite-star { margin-left: 4px; font-size: 12px; }

/* Admin link + footer Collect Now (Phase 4 + admin gating) */
.admin-link {
  font-size: 11px; color: var(--muted); text-decoration: none;
  margin-left: 8px; opacity: 0.5; cursor: pointer;
}
.admin-link:hover { opacity: 1; color: var(--accent); }

/* Visitor counter / globe / flags — ADMIN-ONLY (operator 2026-06-06).
   Hidden for everyone by default; revealed only when admin mode is on
   (body.admin-on, set from localStorage['podcomet-admin'] by _initAdmin /
   promptAdmin in index.html).  Visit TRACKING (/api/track) is untouched —
   only the on-page display is gated, so the counts the admin sees stay
   accurate. */
body:not(.admin-on) .admin-only { display: none !important; }

.collect-btn-footer {
  font-size: 11px; padding: 3px 10px; margin-left: 4px;
  vertical-align: middle;
}

/* Build .260: .rp-section-title + .rp-table cell rules removed —
   Risers + Coldest now use the .movers-merged-card / .mvm-* namespace. */

/* Rank-change arrows on Top-20 rows. Sit at the row's far left; the
   row's existing left padding/numbering stays in place. */
.t20-arrow {
  display: inline-block; width: 14px; text-align: center;
  margin-right: 4px; font-family: monospace;
  font-size: 11px; line-height: 1;
  vertical-align: middle;
}
.t20-arrow-up   { color: var(--success); }
.t20-arrow-down { color: var(--danger);  }
.t20-arrow-same { color: var(--jackpot); opacity: 0.8; }
.t20-arrow-new  { color: var(--platform-manifold-brand); }

/* Section headings (subtle hr above each major below-the-fold section) */
.section-heading {
  font-size: 13px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
  margin: 18px 20px 8px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

/* Wallet track-record badges (in smart-money rows + top-wallets card) */
.track-badge {
  font-family: monospace; font-size: 10px; font-weight: 700;
  padding: 1px 5px; border-radius: var(--r-chip);
}
.track-badge.tr-good { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.track-badge.tr-bad  { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.track-badge.tr-mid  { background: var(--panel-2); color: var(--muted); }

/* Marketplace activity table (replaces Whale Leaderboard in signals row) */
.marketplace-card { border-top: 3px solid var(--kalshi); }
.plat-name.marketplace-name { color: var(--kalshi); }

/* Build v0.35 20260523.193 (2026-05-23): Latest Analysis card.
   Purple top-stripe (var(--platform-manifold-brand)) distinguishes editorial/insight content
   from the data-pull cards (Anomaly amber, Smart-Money pink,
   Marketplace blue, Movers/Topics accent).  Placeholder body is
   centered with a muted icon + heading so the reserved slot reads
   intentionally-empty rather than broken. */
.latest-analysis-card { border-top: 3px solid var(--platform-manifold-brand); }
.plat-name.latest-analysis-name { color: var(--platform-manifold-brand); }
.latest-analysis-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 28px 16px;
  gap: 6px;
  color: var(--muted);
  min-height: 120px;
}
.la-placeholder-icon { font-size: 28px; line-height: 1; opacity: 0.7; }
.la-placeholder-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.02em;
}
.la-placeholder-text {
  font-size: 11px;
  line-height: 1.45;
  max-width: 36ch;
  color: var(--muted);
}

/* Build v0.35 20260524 (2026-05-24): Latest News list inside the
   .latest-analysis-card.  Each item is a single link wrapping the
   headline + provider badge + source + relative age.  Provider
   badge colors mirror the modal "Related news" badges so the visual
   language stays consistent across page surfaces (Guardian blue,
   NewsData amber, Currents emerald, HN orange, GDELT slate). */
/* Build v0.35 20260525.222: compact inline layout — provider badge + age
   on the same line as the headline (was two-block column layout). */
.la-news-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;   /* was 4px */
}
/* latest-news 2026-07-28 (operator): the Latest News tabs (Headlines + Landscape)
   are ONE WIDE COLUMN so full item titles fit before the single-line ellipsis
   (.la-news-title clamps to one line — a wider row shows more characters). Still
   overrides .la-news-list's flex; same 1-class specificity, declared later wins. */
.smh-news-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  align-content: start;
}
@media (max-width: 600px) {
  .smh-news-list { grid-template-columns: 1fr; }
}
.la-news-item { margin: 0; padding: 0; }
.la-news-link {
  display: flex;
  flex-direction: row;       /* was column */
  align-items: baseline;
  gap: 6px;
  padding: 4px 8px;          /* was 7px 8px */
  border-radius: var(--r-chip);
  text-decoration: none;
  color: var(--text);
  border-left: 2px solid transparent;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.la-news-link:hover {
  background: color-mix(in srgb, var(--platform-manifold-brand) 6%, transparent);
  border-left-color: var(--platform-manifold-brand);
}
.la-news-title {
  flex: 1 1 0;
  min-width: 0;
  font-size: 12px;
  line-height: 1.3;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;       /* single-line clamp in row layout */
}
/* peach-news-ink .849 (operator: "make headline text shade for LATEST NEWS and
   LANDSCAPE tabs darker for peach UI theme"). Both tabs render the SAME
   `.la-news-title` (Elections uses `.elec-title`, so it is untouched), and the
   title carries no colour of its own — it inherits `.la-news-link`'s
   `var(--text)`, which on peach is the espresso #3b2f25 against a pale-salmon
   panel. Scoped to the peach theme so dark/light are byte-identical. */
:root[data-theme="peach"] .la-news-title {
  color: var(--text-strong);
}
:root[data-theme="peach"] .la-news-link:hover .la-news-title {
  color: var(--text-strong);   /* hover must not walk it back to --text */
}

.la-news-meta {
  flex-shrink: 0;
  display: flex;
  gap: 4px;
  align-items: center;
  font-size: 10.5px;
  color: var(--muted);
}
/* pm-landscape 2026-07-10: venue logo(s) inline before a 🌐 Landscape headline,
   showing which marketplace(s) the story is about. */
.la-news-venue-logo {
  width: 14px; height: 14px;
  border-radius: 3px;
  vertical-align: -2px;
  margin-right: 3px;
}
.la-news-prov {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--r-chip);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  background: var(--panel-2);
  color: var(--muted);
}
.la-news-prov-badge-guardian   { background: rgba(93, 168, 255, 0.18); color: #5da8ff; }
.la-news-prov-badge-newsdata   { background: rgba(245, 158, 11, 0.18); color: var(--jackpot); }
.la-news-prov-badge-currents   { background: rgba(16, 185, 129, 0.18); color: var(--success); }
.la-news-prov-badge-hackernews { background: rgba(255, 102, 0, 0.20);  color: #ff6600; }
.la-news-prov-badge-gdelt      { background: rgba(148, 163, 184, 0.18); color: var(--muted); }
.la-news-source {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  max-width: 18ch;
}
.la-news-age {
  margin-left: 0;   /* was auto (only needed in column layout) */
  font-variant-numeric: tabular-nums;
  opacity: 0.85;
}
/* Build v.03 .31 build 169 (2026-05-23): explicit top-anchor for the
   Marketplace Activity card.  It spans 2 grid rows in the 3×2 signals
   grid, so the card height is tall; without an explicit justify-content
   the flex children (h3 + 7-day chart + table) could end up visually
   floating relative to neighbouring cards.  Force top alignment so the
   list sits at the top of its box regardless of total card height. */
.signals-row-3x2 .marketplace-card {
  justify-content: flex-start;
  align-content:   flex-start;
}
.marketplace-card .mkt-table {
  /* Ensures any margin-collapse doesn't push the table downward.
     Build v.03 .31 build 172: dropped `margin-bottom: auto` — the chart
     now lives BELOW the table (build 169 layout had chart above, table
     below).  With table-first, the chart fills any remaining flex
     space naturally and pushing the table to the top is unnecessary. */
  margin-top: 4px;
  margin-bottom: 8px;
}
/* Build v.03 .31 build 172: kill any leading whitespace above the h3.
   `signals-card` already pads internally; we want the title flush. */
.marketplace-card > h3 {
  margin-top: 0;
}

/* Build v.03 .31 build 171 (2026-05-23): platform-logo PNGs next to
   venue names.  Three sizes — 16px in the Marketplace Activity table,
   20px in the top-10 hero tile headers, 14px in the top-20 tab nav.
   Use vertical-align: middle so they line up with the text baseline
   nicely.  `object-fit: contain` defends against logos that aren't
   perfectly square. */
/* mkt-status-light 2026-06-25: Marketplace Activity status dot — the .422
   snap-presence health light upgraded in place to ledger-driven states.
   green = online (data this cycle); red = offline (absent + seen before —
   sticky until it returns); amber = relay (Fly-routed venue, London proxy
   down); no dot = never-seen / PMXT-only. Colors alias --success/--danger/
   --jackpot so they auto-theme (peach redefines all three). Offline/relay
   rows dim their volume cell. */
.mkt-status {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  margin-right: 6px; vertical-align: middle; flex: 0 0 auto;
}
.mkt-status-online  { background: var(--success); box-shadow: 0 0 4px color-mix(in srgb, var(--success) 70%, transparent); }
.mkt-status-offline { background: var(--danger); opacity: 0.85; }
.mkt-status-relay   { background: var(--jackpot); opacity: 0.85; }
.mkt-row-offline td.mkt-vol { opacity: 0.55; }
.mkt-logo {
  display: inline-block;
  vertical-align: -3px;
  margin-right: 6px;
  width: 16px;            /* layout box stays 16×16 — row height unchanged */
  height: 16px;
  /* 2026-06-14: +20% visual size via transform (layout unchanged → rows DON'T grow). */
  transform: scale(1.2);
  transform-origin: center;
  object-fit: contain;
  border-radius: var(--r-chip);
  /* Subtle ring so light logos don't disappear against the dark panel */
  background: rgba(255,255,255,0.04);
}
.plat-logo {
  display: inline-block;
  vertical-align: -4px;
  margin-right: 6px;
  width: 20px;
  height: 20px;
  object-fit: contain;
  border-radius: var(--r-chip);
  background: rgba(255,255,255,0.04);
}
.t20-tab-logo {
  display: inline-block;
  vertical-align: -2px;
  margin-right: 4px;
  width: 14px;
  height: 14px;
  object-fit: contain;
  border-radius: var(--r-chip);
  background: rgba(255,255,255,0.04);
}
/* Slightly compact spacing on the top-20 tab buttons so the logo +
   text don't visually overflow on narrow viewports. */
.top-events-tabs button { gap: 0; }
/* Build .57 — visible "as of HH:MM UTC" freshness chip in the card header. */
.mkt-asof {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  font-family: monospace;
  font-size: 10px;
  color: var(--muted);
  background: var(--panel-2);
  border-radius: var(--r-card);
  cursor: help;
  vertical-align: 1px;
  letter-spacing: 0.02em;
}
.mkt-table {
  width: 100%; border-collapse: collapse;
  font-size: 12px; line-height: 1.4;
}
.mkt-table th {
  text-align: left; padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  color: var(--muted); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.05em; font-size: 10px;
}
.mkt-table td {
  padding: 7px 8px; border-bottom: 1px solid color-mix(in srgb, var(--kalshi) 8%, transparent);
  vertical-align: middle;
}
.mkt-table tr:last-child td { border-bottom: none; }
.mkt-table .mkt-rank   { text-align: center; color: var(--muted); font-family: monospace; width: 28px; }
.mkt-table .mkt-vol    { font-family: monospace; font-weight: 600; text-align: right; }
/* mkt-30d 2026-09-07 (operator: "you can narrow the distance between the first
   two columns to achieve that"). The Marketplace↔24h-volume gutter was the
   widest in the row — 8px of padding on each side of it — and this takes 12 of
   those 16px back. It is half of what the 6th Δ column costs; the other half is
   on .mkt-delta below.
   ⚠ MEASURED ON THE PRODUCTION ROW SET, not on a tidy fixture. The first pass
   measured a harness whose Rothera/ProphetX/UDX/ForecastEx rows had no EOD chip,
   which made the Marketplace column 166px instead of production's 240px and the
   whole question 74px easier than it really is. Against the archived
   2026-09-07 02:01 capture (29 rows, chips and all), in the 556px card a 1360px
   viewport gives: .933 as shipped 523px, .933 + this column 574px (the column
   costs 51), this trim alone 562 (still over), the Δ trim alone 554 (inside by
   2px, which is luck not margin), both trims 542. */
.mkt-table .mkt-name { padding-right: 2px; }
.mkt-table .mkt-vol  { padding-left: 2px; }
.mkt-table .mkt-vol-sub { color: var(--muted); font-weight: 400; font-size: 10px; display: block; }
/* 2026-06-14: delta cols auto-size to content (no min-width) — rank column was
   removed to free space; cells now shrink to actual numeric width within the
   323px right-flank card. Worst-case "+1,234.5%" measures ~70px @ 11px mono. */
/* mkt-30d 2026-09-07: 4px → 2px a side, the second half of what the new column
   costs (numbers in the .mkt-name comment above). The first two columns could
   not pay for it alone — the column is 51px wide and that gutter only had 12 to
   give — so five right-aligned nowrap numeric columns give up 2px a side each.
   That is 20px more, the table lands at 542 inside a 556px card, and the 1360
   verdict matches .933 exactly; every wider viewport already fitted. */
.mkt-table .mkt-delta  { font-family: monospace; text-align: right; font-size: 11px; white-space: nowrap; padding-left: 2px; padding-right: 2px; }
.mkt-table .mkt-events { font-family: monospace; text-align: right; color: var(--muted); width: 60px; }
.mkt-table .mkt-source { font-size: 10px; color: var(--muted); width: 90px; }
.mkt-table .mkt-source-pmxt { color: var(--platform-manifold-brand); }   /* PMXT rows in purple */
.mkt-table .mkt-na     { color: var(--muted); opacity: 0.5; }
.mkt-table .mkt-row-pmxt td.mkt-name .sig-plat { opacity: 0.85; }
/* .363 (2026-06-10): OI-based presentation (Opinion) — venue open interest
   shown instead of wash-prone volume.  Small "OI" chip distinguishes the
   figure from the volume numbers in sibling rows.  Colors via vars only
   (graphical tenet). */
.mkt-table .mkt-oi-val  { color: var(--text); }
.mkt-table .mkt-oi-chip {
  display: inline-block;
  margin-left: 5px;
  padding: 0 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  line-height: 1.6;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-chip);
  vertical-align: 1px;
  opacity: 0.9;
}
/* 2026-06-16: EOD-venue cadence chip (e.g. Rothera) — muted, informational.
   CSS vars only (graphical tenet). */
.mkt-table .mkt-eod-chip {
  display: inline-block;
  margin-left: 5px;
  padding: 0 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  line-height: 1.6;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--r-chip);
  vertical-align: 1px;
  white-space: nowrap;
  cursor: help;
}

/* pariflow-mktrow 2026-07-09: relay/aggregator chip (Pariflow re-serves other
   venues' markets). Same footprint as the EOD chip; teal accent border marks it
   as a source-type tag rather than a status. All colors via CSS vars (tenet). */
.mkt-table .mkt-relay-chip {
  display: inline-block;
  margin-left: 5px;
  padding: 0 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  line-height: 1.6;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-chip);
  vertical-align: 1px;
  white-space: nowrap;
  cursor: help;
  opacity: 0.85;
}

/* oddsapi-activity 2026-06-25: EOD activity presentation (ProphetX/Novig via The Odds API) */
.mkt-eod-markets { font-variant-numeric: tabular-nums; }
.mkt-eod-moves { color: var(--muted); }
/* novig-parlay-flow rev 2: the venue-wide EOD parlay line is a SENTENCE, not a
   stat chip. It must WRAP at every width — never clip, and never be clamped
   with text-overflow:ellipsis, which is precisely how the 320px truncation
   defect was re-introduced the second time. Left-aligned so the wrapped lines
   read as prose inside an otherwise right-aligned numeric cell. */
.mkt-parlay-eod {
  color: var(--muted);
  white-space: normal;
  overflow-wrap: anywhere;
  text-overflow: clip;
  overflow: visible;
  text-align: left;
  line-height: 1.35;
  max-width: 100%;
}

/* .364 (2026-06-10): Marketplace sort toggle — Activity ↔ Open Interest.
   Small segmented control above the table.  All colors via vars per the
   graphical tenet.  Hidden entirely when no row has OI data (handled
   server-side: {% if _any_oi %}). */
.mkt-sort-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 4px 0 8px;
  font-size: 11px;
  color: var(--muted);
}
.mkt-sort-label {
  font-size: 10.5px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.mkt-sort-btn {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: var(--r-card);
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.mkt-sort-btn:hover { color: var(--text); border-color: var(--muted); }
.mkt-sort-btn-active,
.mkt-sort-btn-active:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--panel);
}
/* When sorting by OI, deemphasize rows without an OI source so the
   meaningful subset reads first.  Volume mode = no special treatment. */
.mkt-table[data-sort-mode="oi"] .mkt-row-no-oi {
  opacity: 0.55;
}
.mkt-table[data-sort-mode="oi"] .mkt-row-no-oi:hover {
  opacity: 0.85;
}
/* Operator 2026-06-16 (.402): bold follows the SELECTED metric. Operator
   2026-06-17 (.403): go further — swap the full visual HIERARCHY so OI view is
   the mirror of Activity view. Activity view already shows the volume headline
   big + the OI sub-line small/muted; in OI view, shrink+mute the volume
   headline and PROMOTE the OI figure to headline size/weight/color. The OI
   figure is either the `.mkt-oi-sub` sub-line (most venues) or the
   `.mkt-oi-val` headline (OI-native venues like Opinion). `.mkt-oi-sub`
   (not generic `.mkt-vol-sub`) so the mana USD-equiv sub stays muted. */
.mkt-table[data-sort-mode="oi"] .mkt-vol     { font-weight: 400; font-size: 10px; color: var(--muted); }
.mkt-table[data-sort-mode="oi"] .mkt-oi-sub  { display: block; font-size: 13px; font-weight: 700; color: var(--text); }
.mkt-table[data-sort-mode="oi"] .mkt-oi-val  { font-size: 13px; font-weight: 700; color: var(--text); }

/* .375 (2026-06-11): Generic header-driven list-sort affordance.
   Applies to the Federated Board (.dep-head) and the Anomaly list
   (.anom-head).  All colors via vars per the graphical tenet. */
.pc-sort-th {
  cursor: pointer;
  user-select: none;
  transition: color var(--m-tab);
  position: relative;
}
.pc-sort-th:hover { color: var(--text); }
.pc-sort-th[data-sort-dir="asc"]::after  { content: " ↑"; color: var(--accent); }
.pc-sort-th[data-sort-dir="desc"]::after { content: " ↓"; color: var(--accent); }
.pc-sort-th.pc-sort-active { color: var(--accent); font-weight: 700; }

/* Anomaly header strip — same column widths as the rendered rows so
   labels visually align with the data underneath.  The rows themselves
   keep their existing free-form `.sig-meta` layout; only the header is
   new.  Grid uses minmax so the title column flexes. */
.anom-head {
  display: grid;
  grid-template-columns: 70px minmax(0, 1fr) 70px;
  gap: 6px;
  align-items: center;
  padding: 4px 8px 6px;
  margin: 4px 0 2px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.7px;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.anom-cell.anom-score { text-align: right; }
/* Build .272 (2026-05-29): venue name + logo in the Marketplace Activity
   table link to the platform's homepage.  Inherit color + drop the default
   underline so the row renders identically to before; hover underlines the
   name badge as a click affordance.  display:inline keeps the existing logo
   vertical-align + margin layout untouched. */
.mkt-name-link { color: inherit; text-decoration: none; cursor: pointer; }
/* mkt-widen .886 (operator, with screenshot): "I want all venue logos to
   appear in line with the venue name and notes". At narrow column widths the
   name cell WRAPPED - status dot on one line, logo+name beneath, EOD/relay
   chips wherever they fell. One row = one line: the cell refuses to wrap and
   the link lays out dot/logo/name as a single centered inline-flex line.
   Phones are unaffected - their <=700px block scrolls the card sideways BY
   DESIGN (.861), which is exactly what nowrap needs. */
.mkt-table td.mkt-name { white-space: nowrap; }
.mkt-table td.mkt-name .mkt-name-link { display: inline-flex; align-items: center; gap: 2px; vertical-align: middle; }
/* .886: the status dot is a SIBLING of the link; both must sit on the line's
   middle or the dot rides ~5px low against the logo/name (measured). */
.mkt-table td.mkt-name .mkt-logo { flex: 0 0 auto; }
.mkt-eod-chip, .mkt-relay-chip { white-space: nowrap; }
.mkt-name-link:hover .sig-plat { text-decoration: underline; }
.mkt-name-link:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; border-radius: var(--r-chip); }
/* arb-gate 2026-07-10 (operator): the LOCKED arb alert shell served to
   non-subscribers on the cached homepage ("AVAILABLE FOR ET& SUBSCRIBERS"). */
.ct-alert.ct-arb-locked .ct-arb-locked-msg { font-weight: 700; letter-spacing: 0.04em; }
.ct-alert.ct-arb-locked { cursor: pointer; }

/* mkt-card 2026-07-09 (operator): the Marketplace Card modal — venue link +
   7-day volume (total + daily sparkline) + OI, opened from a venue name in the
   Marketplace Activity table.  Rendered inside the generic #modal-body shell.
   Colors via vars only; the sparkline bar color is set inline in JS from the
   same per-venue hue the 7-day stacked chart already uses. */
/* Narrow the shared event-modal shell for the compact Marketplace Card (the
   modifier class is added on open + removed in closeModal).  Without it the
   card floats in the ~820px event-modal box.  High specificity so it wins over
   the base .modal width. */
/* marketplace-weekly 2026-07-24: widened 460px -> 560px so the added weekly
   running series (vol/OI bars + M/D labels since Jun 15) fits on one line; still
   well under the ~820px event-modal box, and max-width:90vw keeps it responsive
   (no horizontal scroll). */
#modal-overlay .modal.modal-mkt-card { width: 560px; max-width: 90vw; }
.mkt-card { display: flex; flex-direction: column; gap: 14px; width: 100%; min-width: 0; }
.mkt-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mkt-card-head img { width: 22px; height: 22px; border-radius: 5px; flex-shrink: 0; }
.mkt-card-name { font-size: 18px; font-weight: 700; color: var(--text); }

/* card-brand-lockup 2026-08-04 (operator): EventTracker mini-logo + wordmark
   in the top-left of every pop-up surface (event / wallet / disambiguation /
   marketplace / full profile).  font-size:1em -> matches the adjacent title;
   glyph = the teal/pink/gold title-stripe brand identity, all via brand vars. */
.et-brand-lockup{ display:inline-flex; align-items:center; gap:.34em; font-size:1em; font-weight:600; line-height:1; color:var(--accent); white-space:nowrap; text-transform:none; letter-spacing:.01em; vertical-align:-0.06em; margin-right:.5em; padding-right:.5em; border-right:1px solid var(--border); }
.et-brand-glyph{ display:inline-block; flex:0 0 auto; width:.7em; height:.8em; border-radius:1px; background:linear-gradient(var(--accent) 0 26%, transparent 26% 37%, var(--whale) 37% 63%, transparent 63% 74%, var(--jackpot) 74% 100%); }
.mkt-card-head .et-brand-lockup{ font-size:18px; }
/* mkt-name-native 2026-07-16: the card name is a native-site link — wraps
   logo+name; mirrors .mkt-card-head's flex/gap so geometry is unchanged. */
.mkt-card-name-a { display: inline-flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.mkt-card-name-a:hover .mkt-card-name { color: var(--accent); text-decoration: underline; }
.mkt-card-link { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--accent); text-decoration: none; white-space: nowrap; }
.mkt-card-link:hover { text-decoration: underline; }
.mkt-card-block { display: flex; flex-direction: column; gap: 4px; }
.mkt-card-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-soft); }  /* text-soft 2026-07-10 */
.mkt-card-big { font-size: 22px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.mkt-card-note { font-size: 12px; color: var(--text-soft); }  /* text-soft 2026-07-10 */
.mkt-card-spark { display: flex; align-items: flex-end; gap: 3px; height: 38px; margin-top: 2px; }
.mkt-card-bar { flex: 1 1 0; min-width: 0; border-radius: 2px 2px 0 0; opacity: 0.85; }
.mkt-card-bar:hover { opacity: 1; }
/* mkt-chart-dates 2026-07-10 (operator): M/D date labels under the 7-day bars.
   Mirrors .mkt-card-spark geometry (gap:3px, each child flex:1 1 0) so each label
   sits exactly under its bar. text-soft for readability; nowrap+overflow-hidden+
   min-width:0 honor the no-horizontal-scroll rule. */
.mkt-card-days { display: flex; gap: 3px; margin-top: 4px; }
.mkt-card-daylbl { flex: 1 1 0; min-width: 0; text-align: center; font-size: 9px; color: var(--text-soft, var(--muted)); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; }
.mkt-card-ctx { font-size: 11px; color: var(--text-soft); border-top: 1px solid var(--border); padding-top: 8px; }  /* text-soft 2026-07-10 */

/* Build .284: subtle dark hue behind each Marketplace Activity source cell so the
   per-platform colored name + logo read with more contrast (esp. on the peachy-cream
   default).  var(--source-tint) is a theme-agnostic black-alpha overlay. */
.mkt-table td.mkt-name { background: var(--source-tint); }
/* Build .286: stronger contrast for the Marketplace Activity venue-name chips
   (operator request).  A 1px outline in the chip's OWN colour (currentColor =
   the per-venue brand var) turns each name into a crisp, defined pill, and a
   small font bump aids legibility.  currentColor keeps it tenet-compliant (no
   hard-coded hue) and theme-adaptive; scoped to .mkt-table so the compact
   ticker / arb-card / liquidity .sig-plat chips elsewhere are untouched. */
.mkt-table td.mkt-name .sig-plat {
  font-size: 10px;
  border: 1px solid currentColor;
  /* Build .288: dark halo around the brand-coloured name so it contrasts hard
     against its same-hue brand-tint background (operator request — the prior
     border + tint weren't enough on their own). */
  text-shadow: 0 1px 2px var(--chip-halo), 0 0 2px var(--chip-halo);
}
/* Build .285: click-to-sort column headers on generic .sortable tables. */
table.sortable th.th-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
table.sortable th.th-sortable:hover { color: var(--accent); }
table.sortable th.sorted-asc::after  { content: " \25B2"; font-size: 0.72em; color: var(--accent); }
table.sortable th.sorted-desc::after { content: " \25BC"; font-size: 0.72em; color: var(--accent); }
.mkt-table .delta-up   { color: var(--success); }
.mkt-table .delta-down { color: var(--danger); }
.mkt-table .delta-flat { color: var(--muted); }
/* Build .274 (2026-05-29): forecaster venues (Foretold / FantasySCOTUS) have no
   real trading volume, so their delta columns show consensus drift (mean absolute
   move of the leading option's probability, in percentage points) instead of a
   volume Δ%, and their volume cell shows a forecast-count confidence chip rather
   than a misleading "$" figure.  Consensus drift is always a non-negative
   magnitude (signed moves cancel under averaging) so it gets the neutral accent
   color, not the up/down green/red of volume momentum. */
.mkt-table .mkt-consensus { color: var(--accent); font-variant-numeric: tabular-nums; }
.mkt-table .mkt-consensus .mkt-pp { font-size: 0.82em; opacity: 0.7; margin-left: 1px; }
.mkt-table .mkt-conf-chip {
  display: inline-flex; align-items: center; gap: 3px;
  /* Build .284: was color:#cbd5e1 (hardcoded slate-300) — invisible on the
     peachy-cream default.  var(--text) makes it readable in both themes;
     weight bumped 600->800 per "barely visible / bolder". */
  font-size: 11px; font-weight: 800; color: var(--text); white-space: nowrap;
}
.mkt-table .mkt-conf-chip .mkt-conf-unit {
  font-size: 9px; font-weight: 700; opacity: 0.85; text-transform: uppercase;
}
.mkt-footnote {
  margin-top: 8px; padding: 6px 0 0 0;
  font-size: 10px; color: var(--muted); line-height: 1.5;
  border-top: 1px dashed var(--border);
}

/* 7-day stacked-bar chart at the top of the marketplace card */
.mkt-7d-wrap {
  margin: 4px 0 10px 0;
  padding: 6px 0 0 0;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 10px;
}
.mkt-7d-title {
  font-size: 11px; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.mkt-7d-chart-box {
  position: relative;
  height: 180px;     /* fixed so Chart.js can compute layout */
  width: 100%;
}

/* marketplace-weekly 2026-07-24: running weekly chart (Volume/OI toggle) under the
   7-day chart. Toggle mirrors .mkt-sort-bar. Kept compact (130px box) so the card
   still fits its departures-band cell without an internal scrollbar. var() only. */
.mkt-weekly-wrap { margin-top: 8px; border-top: 1px solid var(--border); padding-top: 6px; }
.mkt-weekly-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.mkt-weekly-title { font-size: 11px; color: var(--muted); }
.mkt-weekly-toggle { display: inline-flex; gap: 2px; }
.mkt-wk-btn, .mkt-7d-btn { font-size: 10px; padding: 2px 7px; border: 1px solid var(--border); background: transparent; color: var(--muted); cursor: pointer; border-radius: 4px; }
.mkt-wk-btn-active, .mkt-7d-btn-active { background: var(--accent); color: var(--panel); border-color: var(--accent); }
/* chart-legends 2026-07-26: the 7d chart's own toggle (.mkt-7d-btn — a
   separate class so pcWeeklyMetric's .mkt-wk-btn sweep can't clobber its
   active state); the title drops its bottom margin inside the flex head. */
.mkt-weekly-head .mkt-7d-title { margin-bottom: 0; }
.mkt-weekly-chart-box { position: relative; height: 130px; width: 100%; }
/* mkt-legend-html 2026-08-10 (operator: legends were truncated): the chart
   legends now live OUTSIDE the fixed-height canvas boxes, so they wrap to as
   many rows as the venue roster needs and can never be clipped. */
.mkt-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; margin: 6px 0 2px;
  align-items: center; }
.mkt-legend-item { display: inline-flex; align-items: center; gap: 5px;
  background: none; border: none; padding: 1px 2px; cursor: pointer;
  color: var(--muted); font-size: 11px; line-height: 1.4; }
.mkt-legend-item:hover, .mkt-legend-item:focus-visible { color: var(--text); }
.mkt-legend-item.is-off { opacity: 0.45; text-decoration: line-through; }
.mkt-legend-sw { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
/* board-stats 2026-07-26 (operator): the 7d + weekly charts live at the bottom
   of the Federated Board card now — side-by-side when the center column is
   wide (auto-fit), stacked below ~640px, with ~2x taller chart boxes than the
   old marketplace strips (maintainAspectRatio:false → the canvases fill the
   box). min-width:0 on the grid children per the no-scrollbar rule. */
.board-stats-band { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 8px;
  /* mobile-pass .641: min(290px,100%) — the raw 290px floor overflowed the
     band's ~255px slot at phone width (charts clipped ~35px, live-measured). */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 4px 18px; }
.board-stats-band .mkt-7d-wrap, .board-stats-band .mkt-weekly-wrap { min-width: 0; }
.board-stats-band .mkt-7d-wrap { border-bottom: 0; padding-bottom: 0; margin: 0; }
.board-stats-band .mkt-weekly-wrap { border-top: 0; margin-top: 0; padding-top: 0; }
.board-stats-band .mkt-7d-chart-box, .board-stats-band .mkt-weekly-chart-box { height: 250px; }
.board-stats-band .mkt-7d-title, .board-stats-band .mkt-weekly-title { font-size: 12px; }

/* Top-wallets card (kept for legacy / future re-enable; not in homepage today) */
.wallets-card { border-top: 3px solid var(--success); }
.plat-name.wallets-name { color: var(--success); }
.wallets-list .wallet-link {
  grid-template-columns: 24px 1fr auto;
}
.wallet-rank { font-family: monospace; font-size: 11px; color: var(--muted); text-align: right; }
.wallet-name { font-family: monospace; font-size: 11px; color: var(--text); font-weight: 700; }

/* ─── Hero: Globe + Top-10 trio in a 2x2 squareish grid ─── */
.chart-box {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card); padding: 14px;
  min-height: 280px; display: flex; flex-direction: column;
}
.chart-box canvas { flex: 1; min-height: 280px; max-height: 380px; }
.whale-chart-box { margin-top: 16px; min-height: 260px; }

.globe-box {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card); padding: 14px;
  display: flex; flex-direction: column; position: relative;
}
#globe { flex: 1; min-height: 0; background: radial-gradient(circle at 50% 50%, var(--bg-deeper) 0%, var(--bg) 100%); border-radius: var(--r-card); }

/* 2x2 grid: each cell roughly square. grid-auto-rows: 1fr keeps both rows equal,
   and aspect-ratio on cells nudges them toward squareness while still scaling. */
.hero-2x2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(280px, 32vh));
  gap: 12px; padding: 12px 20px;
}
.hero-2x2 > * { min-height: 0; min-width: 0; overflow: hidden; box-sizing: border-box; }
@media (max-width: 900px) {
  .hero-2x2 { grid-template-columns: 1fr; grid-template-rows: auto; }
}

/* ─── 2x2 Top-10 corners + globe in the center ───
   4 top-10 cards in a strict 2x2 grid; the globe is rendered as a
   centered floating overlay, with explicit grid placement so Firefox
   doesn't reserve a grid cell for it. */
.hero-2x2-center {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(300px, 36vh));
  gap: 14px; padding: 14px 20px;
}
.hero-2x2-center > .t10-card {
  min-height: 0; min-width: 0; overflow-y: auto; box-sizing: border-box;
}

/* Globe overlay: lay it across the entire 2x2 grid via grid-area then
   center-self in both dimensions. This guarantees the globe's center
   sits at the geometric center of the 4-cell grid regardless of section
   padding, scrollbar widths, or asymmetric card content heights. */
.globe-hero-center {
  grid-column: 1 / -1;
  grid-row:    1 / -1;
  align-self:   center;     /* vertical centering inside the 2x2 grid */
  justify-self: center;     /* horizontal centering — the cross-corner */
  width:  clamp(260px, 24vw, 340px);   /* a bit larger so the disc clearly
                                          spans across all 4 inner corners */
  height: clamp(260px, 24vw, 340px);
  z-index: 5;
  pointer-events: auto;
  /* Solid disc with a dark border ring so the overlap with each card's
     inner corner is unmistakable. The radial-gradient still gives a soft
     halo at the very edge for visual blending. */
  background:
    radial-gradient(circle at 50% 50%,
      rgba(20,27,51,1.0) 0%,
      rgba(20,27,51,1.0) 78%,
      rgba(20,27,51,0.6) 92%,
      rgba(11,16,32,0)   100%);
  border: 2px solid color-mix(in srgb, var(--kalshi) 55%, transparent);
  border-radius: 50%;
  padding: 14px;
  display: flex; flex-direction: column;
  box-shadow: 0 0 60px color-mix(in srgb, var(--kalshi) 30%, transparent),
              inset 0 0 24px color-mix(in srgb, var(--accent) 10%, transparent);
  position: relative;       /* not absolute — we want flex-center positioning */
}
.globe-hero-center #globe {
  flex: 1; min-height: 0; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, var(--bg-deeper) 0%, var(--bg) 100%);
}
.globe-hero-center .globe-pause-btn {
  position: absolute; top: 8px; right: 50%; transform: translateX(50%);
  background: rgba(13,19,40,0.9); border: 1px solid var(--border);
  color: var(--muted); font-size: 11px; padding: 2px 6px; line-height: 14px;
  border-radius: var(--r-chip); z-index: 6; cursor: pointer;
}
.globe-hero-center .globe-pause-btn:hover { color: var(--accent); border-color: var(--accent); }

/* Smooth, symmetric inner-corner reserve for all 4 cards so the floating
   globe (anchored exactly at the 2x2 cross-corner intersection) doesn't
   cover row content. Each card keeps its inner corner clear with a
   diagonally-oriented padding pad and right-justifies text on right cards. */
@media (min-width: 901px) {
  /* Reserve a quadrant-of-globe of empty space at each card's inner corner.
     We use a single CSS custom property to keep all four sides synchronized. */
  .hero-2x2-center { --globe-reserve: clamp(95px, 11vw, 140px); }

  /* Top row cards: reserve space at the bottom-inside corner so the
     floating globe doesn't cover row content. Left-cards (Polymarket TL,
     Manifold BL) reserve space on the RIGHT; right-cards (Kalshi TR,
     Limitless BR) reserve space on the LEFT but content stays
     LEFT-ALIGNED — i.e. the rows now begin at the center of the right-
     cards instead of being flush against the right edge.
     This replaces an earlier attempt that right-justified the right-cards
     and reversed the grid; the user found that hard to read. */
  .hero-2x2-center > .t10-card:nth-child(1) { padding-right: var(--globe-reserve); padding-bottom: 18px; }
  .hero-2x2-center > .t10-card:nth-child(2) { padding-left:  var(--globe-reserve); padding-bottom: 18px; }
  .hero-2x2-center > .t10-card:nth-child(3) { padding-right: var(--globe-reserve); padding-top:    18px; }
  .hero-2x2-center > .t10-card:nth-child(4) { padding-left:  var(--globe-reserve); padding-top:    18px; }

  /* Anchor the globe EXACTLY at the cross-point of the 2x2 grid.
     Math: cross-point in the grid = (50%, 50%) of the .hero-2x2-center
     content box (taking the gap into account, since the grid uses gap not
     padding). Globe diameter = 2 × var(--globe-reserve) so each cell's
     reserved corner is exactly tangent to the globe. */
  .globe-hero-center {
    width:  calc(var(--globe-reserve) * 2);
    height: calc(var(--globe-reserve) * 2);
  }
}

/* Medium viewports — slightly smaller globe + reserve. */
@media (max-width: 1200px) and (min-width: 901px) {
  .hero-2x2-center { --globe-reserve: 88px; }
}

/* ─── Hero 4×3 (Option B, build .89.1) ─────────────────────────────────
   Unified 12-cell grid with 9-11 platforms + 1-3 vacant slots.  Order
   left→right, top→bottom:
     Row 1: poly · kalshi · manifold · limitless
     Row 2: metaforecast · myriad · betfair · predictit
     Row 3: opinion · sxbet (dev) · globe · (vacant)
   Vacant slot doubles as the floating-globe pane so we don't lose
   the world-map context. Tile content is identical to the old 3×2.
   .hero-3x2 retained as an alias so older templates still render. */
.hero-3x2,
.hero-4x3 {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* Three rows now; min-height trimmed slightly (340→300px) to keep the
     hero from dominating above-the-fold on a single-row aspect ratio. */
  grid-template-rows: repeat(3, minmax(300px, 36vh));
  gap: 14px;
  /* Build v.03 .31 build 104: padding-bottom trimmed 14→2 so the
     Featured Whale Bets section sits flush against the top-10 grid
     (removes the dead vertical space the user flagged). */
  padding: 14px 20px 2px;
}
.hero-3x2 > .t10-card,
.hero-4x3 > .t10-card,
.hero-3x2 > .hero-vacant-slot,
.hero-4x3 > .hero-vacant-slot {
  /* Build .54: dropped `overflow-y: auto` from t10-card so movers
     rows are visible at a glance — no internal scroll bars in the
     top-10 boxes. Vacant-slot keeps overflow:auto for the globe. */
  min-height: 0; min-width: 0; box-sizing: border-box;
}
.hero-3x2 > .hero-vacant-slot,
.hero-4x3 > .hero-vacant-slot {
  overflow-y: auto;
}
.hero-vacant-slot {
  display: flex; align-items: stretch; justify-content: center;
  background: rgba(13,19,40,0.30);
  border: 1px dashed color-mix(in srgb, var(--kalshi) 25%, transparent);
  border-radius: var(--r-card);
  padding: 10px;
}
.hero-vacant-slot .globe-hero-vacant {
  flex: 1; min-width: 0;
  background: radial-gradient(circle at 50% 50%, var(--bg-deeper) 0%, var(--bg) 100%);
  border: 1px solid color-mix(in srgb, var(--kalshi) 40%, transparent);
  border-radius: var(--r-card);
  padding: 10px;
  position: relative;
  display: flex; flex-direction: column;
}
.hero-vacant-slot .globe-hero-vacant #globe {
  flex: 1; min-height: 0; border-radius: var(--r-card);
}
.hero-vacant-slot .globe-pause-btn {
  position: absolute; top: 6px; right: 6px;
  background: rgba(13,19,40,0.9); border: 1px solid var(--border);
  color: var(--muted); font-size: 11px; padding: 2px 6px; line-height: 14px;
  border-radius: var(--r-chip); cursor: pointer;
}
.hero-vacant-slot .globe-pause-btn:hover { color: var(--accent); border-color: var(--accent); }
.hero-vacant-placeholder {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--muted); text-align: center; font-size: 13px;
}
.hero-vacant-placeholder .hv-icon {
  font-size: 36px; opacity: 0.5; line-height: 1; margin-bottom: 8px;
}
.hero-vacant-placeholder .hv-text { max-width: 220px; line-height: 1.5; }

@media (max-width: 1400px) {
  .hero-3x2,
  .hero-4x3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1100px) {
  .hero-3x2,
  .hero-4x3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .hero-3x2,
  .hero-4x3 {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
  .hero-vacant-slot { min-height: 240px; }
}

/* ─── Build .85.1: independent Betfair box under the leftmost column ─────
   3-column grid with the same column widths + horizontal padding as
   .hero-3x2 above, but only the first cell holds a tile.  Visually
   anchors Betfair under the Polymarket / Limitless column of the hero
   grid while keeping it as its own row (per user request: "independent
   box", not a 7-tile grid expansion). */
.hero-betfair-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* Same row sizing rule as the hero-3x2 so the Betfair tile matches
     the hero tile heights exactly when sitting directly below them. */
  grid-template-rows: minmax(340px, 44vh);
  gap: 14px;
  padding: 0 20px 14px;   /* no top-padding — sits flush under hero-3x2 */
}
.hero-betfair-row > .t10-card {
  grid-column: 1;
  grid-row: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  box-sizing: border-box;
}
@media (max-width: 1100px) {
  .hero-betfair-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .hero-betfair-row {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    padding: 0 12px 12px;
  }
}

/* MetaForecast platform colour & badges */
.t10-metaforecast { border-top: 3px solid var(--platform-manifold-brand); }
.t20-metaforecast { border-top: 3px solid var(--platform-manifold-brand); }
.sig-metaforecast .sig-plat,
.sig-plat.sig-metaforecast { background: color-mix(in srgb, var(--platform-manifold-brand) 18%, transparent); color: var(--platform-manifold-brand); }
.plat-aggr-pill {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  font-size: 10px; font-weight: 600; color: var(--platform-manifold-brand);
  background: color-mix(in srgb, var(--platform-manifold-brand) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--platform-manifold-brand) 30%, transparent); border-radius: var(--r-chip);
  letter-spacing: 0.04em;
}

/* Top-20 row 3×2 (5 platforms + 1 vacant slot).
   Specificity bump via .top-events.top-events-3x2 — otherwise the legacy
   .top-events base rule below (defined LATER in this file with the same
   single-class specificity) wins by source order and we render 4 columns
   instead of 3 on wide screens. The doubled class is intentional. */
.top-events.top-events-3x2 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 1100px) {
  .top-events.top-events-3x2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .top-events.top-events-3x2 { grid-template-columns: 1fr; }
}
.t20-vacant {
  border: 1px dashed color-mix(in srgb, var(--kalshi) 30%, transparent) !important;
  background: rgba(13,19,40,0.20);
  display: flex; flex-direction: column;
}
.t20-vacant-body {
  padding: 24px 16px; text-align: center;
  color: var(--muted); line-height: 1.6;
}
.t20-vacant-body .t20-vacant-sub { font-size: 12px; opacity: 0.7; }

/* When HIDE_UPPER_GLOBE=1: drop all the inner-corner padding so the
   four top-10 cards use the full grid cells without any reserved space. */
.hero-no-globe > .t10-card:nth-child(n) {
  padding-left: 12px !important;
  padding-right: 12px !important;
  padding-top: 12px !important;
  padding-bottom: 12px !important;
}

@media (max-width: 900px) {
  .hero-2x2-center { grid-template-columns: 1fr; grid-template-rows: auto; }
  .globe-hero-center {
    /* Mobile: globe drops out of overlay mode and becomes a normal
       block in flow under the 4 stacked cards. */
    grid-column: auto;
    grid-row: auto;
    align-self: stretch;
    justify-self: stretch;
    width: 100%; height: 280px; border-radius: var(--r-card);
    margin: 0; padding: 12px;
  }
  .globe-hero-center .globe-pause-btn { position: absolute; top: 12px; right: 16px; transform: none; }
}
.globe-hero { padding: 12px; }
.globe-hero h3 { margin-bottom: 6px; display: flex; align-items: center; gap: 8px; }
.globe-pause-btn {
  background: transparent; color: var(--muted); border: 1px solid var(--border);
  border-radius: var(--r-chip); padding: 0 6px; font-size: 11px; line-height: 18px; cursor: pointer;
}
.globe-pause-btn:hover { color: var(--accent); border-color: var(--accent); }
.fade-in { animation: fwFade 0.35s ease-in; }
@keyframes fwFade { from { opacity: 0.3; } to { opacity: 1; } }

/* Build .54: dropped max-height + overflow-y so the t10-card never
   shows internal scroll bars — the parent hero-3x2 grid row gives it
   enough headroom for 10 rows. */
.t10-card { padding: 10px 12px; }
.t10-card .platform { margin-bottom: 6px; padding-bottom: 4px; }
.t10-bet { color: var(--muted); font-weight: 500; font-size: 11px; }
.closed-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px;
  background: var(--danger); color: #fff;
  border-radius: var(--r-chip); font-weight: 800;
  font-family: monospace; font-size: 11px; margin-right: 6px;
  vertical-align: middle; line-height: 1;
}
/* Resolved/closed event rows get a STRONG tinted background + diagonal-stripe
   pattern so they're obviously distinct from live events when "Open Events
   Only" is OFF. Also reduce opacity slightly to push them visually back. */
.t10-row-closed,
.t20-row-closed {
  background:
    repeating-linear-gradient(135deg,
      color-mix(in srgb, var(--danger) 18%, transparent) 0,
      color-mix(in srgb, var(--danger) 18%, transparent) 4px,
      color-mix(in srgb, var(--danger) 6%, transparent) 4px,
      color-mix(in srgb, var(--danger) 6%, transparent) 10px);
  border-left: 4px solid var(--danger);
  position: relative;
}
.t10-row-closed::after,
.t20-row-closed::after {
  content: 'CLOSED';
  position: absolute; top: 4px; right: 8px;
  font-size: 9px; font-weight: 800; letter-spacing: 0.1em;
  color: var(--danger); background: color-mix(in srgb, var(--danger) 18%, transparent);
  padding: 1px 5px; border-radius: var(--r-chip);
  pointer-events: none;
}
.t10-row-closed a,
.t20-row-closed .t20-title { color: #fca5a5; }
.t10-row-closed:hover { background: color-mix(in srgb, var(--danger) 20%, transparent); }
.t20-bet-amt { color: var(--accent); font-weight: 600; font-size: 10px; margin-left: 3px; }
.t10-poly { border-top: 3px solid var(--accent); }
.t10-kalshi { border-top: 3px solid var(--kalshi); }
.t10-manifold { border-top: 3px solid var(--platform-manifold-brand); }
.t10-sxbet { border-top: 3px solid var(--sxbet); }
.t10-limitless { border-top: 3px solid var(--limitless); }
.top10-list { list-style: none; margin: 0; padding: 0; counter-reset: t10; }
.t10-row {
  counter-increment: t10;
  border-bottom: 1px solid var(--border);
}
.t10-row:last-child { border-bottom: none; }
.t10-row a {
  display: grid; grid-template-columns: 20px 1fr auto; gap: 6px; align-items: baseline;
  padding: 3px 4px; color: var(--text); font-size: 12px; line-height: 1.25;
}
.t10-row a:hover { background: var(--panel-2); text-decoration: none; }
.t10-row a::before {
  content: counter(t10);
  font-family: monospace; font-size: 10px; color: var(--muted); text-align: right;
}
.t10-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t10-vol { font-family: monospace; font-size: 11px; color: var(--accent); font-weight: 600; }
.t10-manifold .t10-vol { color: #c4b5fd; }
.t10-kalshi .t10-vol { color: var(--kalshi); }
.globe-legend {
  display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px;
  font-size: 10px; color: var(--muted); justify-content: center;
}
.globe-legend .leg { display: flex; align-items: center; gap: 4px; }
.globe-legend .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

/* ─── Ticker ─── */
.ticker-section {
  display: flex; align-items: center; background: var(--panel); border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border); overflow: hidden;
}
.ticker-label {
  background: var(--whale); color: var(--bg); font-weight: 800; padding: 10px 16px;
  font-size: 13px; letter-spacing: 0.16em; white-space: nowrap; align-self: stretch;
  display: flex; align-items: center;
}
.ticker-wrap { flex: 1; overflow: hidden; position: relative; padding: 8px 0; }
.ticker-track {
  display: flex; gap: 32px; white-space: nowrap;
  animation: scroll-left 44s linear infinite;   /* P3 2026-06-12: +17% faster (53->44s) */
  padding-left: 20px;
}
.ticker-track:hover { animation-play-state: paused; }
@keyframes scroll-left {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}
.ticker-item {
  display: inline-flex; align-items: center; gap: 8px; color: var(--text);
  font-size: 13px; padding: 4px 12px; border-left: 2px solid var(--whale);
  flex-shrink: 0;     /* don't let the flex parent (.ticker-track) shrink items */
  min-width: 0;       /* but DO allow truncation INSIDE via child overflow rules */
  overflow: visible;  /* the parent .ticker-wrap clips; items stay full-content-sized */
}
.ticker-item:hover { text-decoration: none; color: var(--whale); }
/* P3 2026-06-12: unified-ticker per-type chip */
.ut-type-chip {
  flex-shrink: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9px; font-weight: 800; letter-spacing: 0.06em;
  padding: 1px 5px; border-radius: var(--r-chip); color: var(--chip-ink);   /* P3: dark ink legible on bright chips in BOTH themes (was var(--bg) — illegible on peach) */
}
.ut-chip-event   { background: var(--accent); }
.ut-chip-whale   { background: var(--whale); }
.ut-chip-jackpot { background: var(--jackpot); }
.ut-item { border-left-color: var(--border); }   /* type chip carries the colour, not the border */
.tk-amount { font-weight: 700; color: var(--whale); font-family: monospace; }
.tk-side { padding: 2px 6px; border-radius: var(--r-chip); font-size: 10px; font-weight: 600; }
.tk-q { color: var(--muted); max-width: 280px; overflow: hidden; text-overflow: ellipsis; }
.tk-evt { color: var(--text); font-style: italic; max-width: 240px; overflow: hidden; text-overflow: ellipsis; font-size: 12px; }
.tk-odds { color: var(--jackpot); font-family: monospace; font-size: 11px; }
.tk-by   { color: var(--muted); font-size: 11px; opacity: 0.85; white-space: nowrap; }
.tk-user { color: var(--text); font-family: monospace; font-size: 11px; max-width: 120px; display: inline-block; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
/* Build .48: when tk-user is wrapped in an <a class="wallet-link">,
   make it visually obvious that the wallet name itself is clickable
   (separate target from the parent event-link). */
a.tk-user.wallet-link {
  color: var(--accent);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--m-tab);
}
a.tk-user.wallet-link:hover {
  color: var(--success);
  text-decoration: underline;
}
.ticker-empty { padding: 8px 20px; color: var(--muted); font-style: italic; }

/* ─── Top 20 Events ─── */
/* Build .87.4: second pass — push compression further.  Per-row height
   ~30px → ~22px (font sizes shrunk another step, padding tightened,
   margin-bottoms zeroed where safe, mini-bar slimmed to 3px). */
.top-events {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; padding: 6px 20px;
}
.top-events > .card { min-width: 0; }
@media (max-width: 1400px) { .top-events { grid-template-columns: repeat(2, 1fr); } }
.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-chip); padding: 6px 8px;
  /* Build .79: removed 900px cap — cards grow naturally with content.
     No internal scrollbar; the page scrolls instead. */
  max-height: none; overflow-y: visible;
}
.card.poly { border-top: 3px solid var(--accent); }
.card.kalshi { border-top: 3px solid var(--kalshi); }
.card.manifold { border-top: 3px solid var(--platform-manifold-brand); }
.card.sxbet { border-top: 3px solid var(--sxbet); }
.card.limitless { border-top: 3px solid var(--limitless); }
/* Build .85: Betfair brand color is yellow/black; we use Betfair yellow
   (var(--jackpot) — pulled from their brand pages) for the accent. */
.t10-betfair, .card.betfair { border-top: 3px solid var(--jackpot); }
.t10-betfair .plat-name, .card.betfair .plat-name { color: var(--jackpot); }
.sig-betfair, .sig-plat.sig-betfair { background: rgba(255, 184, 12, 0.18); color: var(--jackpot); }
/* Build .89.1: PredictIt (red — patriotic palette, US political venue)
   and Opinion (violet — distinct from Manifold's lighter violet) accents. */
.t10-predictit, .card.predictit { border-top: 3px solid #dc2626; }
.t10-predictit .plat-name, .card.predictit .plat-name { color: #dc2626; }
.sig-predictit, .sig-plat.sig-predictit { background: rgba(220, 38, 38, 0.18); color: var(--danger); }
.t10-opinion, .card.opinion { border-top: 3px solid #7c3aed; }
.t10-opinion .plat-name, .card.opinion .plat-name { color: #7c3aed; }
.sig-opinion, .sig-plat.sig-opinion { background: rgba(124, 58, 237, 0.18); color: var(--platform-manifold-brand); }
/* Build .89.2: ProphetX (cyan — distinct from Polymarket's teal) and
   Novig (orange — distinct from Limitless's orange-red).  Both surface
   the PolyRouter origin via the .plat-ph-pill class. */
.t10-prophetx, .card.prophetx { border-top: 3px solid #06b6d4; }
.t10-prophetx .plat-name, .card.prophetx .plat-name { color: #06b6d4; }
.sig-prophetx, .sig-plat.sig-prophetx { background: rgba(6, 182, 212, 0.18); color: var(--accent); }
.t10-novig, .card.novig { border-top: 3px solid #ea580c; }
.t10-novig .plat-name, .card.novig .plat-name { color: #ea580c; }
.sig-novig, .sig-plat.sig-novig { background: rgba(234, 88, 12, 0.18); color: #fb923c; }
/* Build v.03 .31 build 163 (2026-05-23): predict.fun palette —
   lime-green (var(--success)) matches their site's accent.  BNB-chain
   prediction market + Polymarket conditionId-paired arb opportunities. */
.t10-predict_fun, .card.predict_fun { border-top: 3px solid var(--success); }
.t10-predict_fun .plat-name, .card.predict_fun .plat-name { color: var(--success); }
.sig-predict_fun, .sig-plat.sig-predict_fun { background: rgba(132, 204, 22, 0.18); color: #a3e635; }
/* Build .91 (Option B): FantasySCOTUS (deep court-robe red — `#7c2d12`)
   and Foretold (calm forecaster teal — `var(--accent-deep)`).  Both partitioned
   out of MetaForecast (was `var(--platform-manifold-brand)` violet), so we get two clearly
   distinct tile identities replacing the misleading-aggregator one. */
.t10-fantasyscotus, .card.fantasyscotus { border-top: 3px solid #7c2d12; }
.t10-fantasyscotus .plat-name, .card.fantasyscotus .plat-name { color: #c2410c; }
.sig-fantasyscotus, .sig-plat.sig-fantasyscotus { background: rgba(124, 45, 18, 0.22); color: #fb923c; }
.t10-foretold, .card.foretold { border-top: 3px solid var(--accent-deep); }
.t10-foretold .plat-name, .card.foretold .plat-name { color: var(--accent); }
.sig-foretold, .sig-plat.sig-foretold { background: rgba(13, 148, 136, 0.18); color: var(--accent); }
/* "via Prediction Hunt" / "via PolyRouter" provenance pill — surfaces
   on tiles whose data originates from a federated aggregator API. */
.plat-ph-pill {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  font-size: 10px; font-weight: 600; color: var(--muted);
  background: rgba(148, 163, 184, 0.10);
  border: 1px solid rgba(148, 163, 184, 0.30); border-radius: var(--r-chip);
  letter-spacing: 0.04em;
}
.platform {
  font-size: 12px; color: var(--white);
  letter-spacing: 0.02em; margin-bottom: 3px; padding-bottom: 3px; border-bottom: 1px solid var(--border);
  font-weight: 800;
}
.plat-name {
  font-weight: 900; font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em;
}
.plat-sub {
  font-size: 10px; color: var(--white); text-transform: none; letter-spacing: 0; font-weight: 600;
}
/* Build .311 (operator 2026-06-01): strip descriptive subtitles from cards/boxes.
   Keep ONLY attribution notes ("powered by …" / "via …"), which are tagged
   .plat-credit.  Hides the descriptive .plat-sub lines + the four board-panel
   subs + the Smart-Wallets formula subheading.  Visual-only — the markup is
   retained so a subtitle can be restored by dropping the rule / adding .plat-credit. */
.plat-sub:not(.plat-credit),
.board-panel-sub,
.sw-subheading { display: none; }
/* Build (operator 2026-06-05): also hide the remaining attribution subtitle
   (.plat-credit) when its box is EMPTY — a card with no content rows shouldn't
   dangle a "powered by …" line. Keyed per box on its server-rendered content-
   row class via :has(); a harmless no-op (subtitle just stays, as before) on a
   browser without :has(). PHQ is JS-rendered + ~never empty → omitted to avoid
   a load-time flicker. */
.arb-section:not(:has(.arb-card)) .plat-credit,
.latest-analysis-card:not(:has(.la-news-list)) .plat-credit { display: none; }
/* crossvenue-rename 2026-08-06 (operator): keep the Multi-Marketplace Events
   card's tagline VISIBLE — a deliberate, card-scoped exception to the
   title-only .plat-sub:not(.plat-credit) hide rule above. */
.crossvenue-card .plat-sub.cv-tagline { display: inline; color: var(--muted); }
/* Platform-tinted names */
.t10-poly .plat-name, .card.poly .plat-name { color: var(--accent); }
.t10-kalshi .plat-name, .card.kalshi .plat-name { color: var(--kalshi); }
.t10-manifold .plat-name, .card.manifold .plat-name { color: var(--platform-manifold-brand); }
.t10-sxbet .plat-name, .card.sxbet .plat-name { color: var(--sxbet); }
.t10-limitless .plat-name, .card.limitless .plat-name { color: var(--limitless); }
.top20-list { list-style: none; margin: 0; padding: 0; counter-reset: t20; }
/* Build .96.6: single-line Top-20 rows.  Counter + arrows + icons +
   title + meta + delta chips all on ONE textual row per event.
   Title truncates with ellipsis when too long; meta stays right-
   aligned and never shrinks.  Mini-bar removed entirely (option
   breakdown still available in the modal).  Per-row height
   ~22px → ~15-16px = ~30% additional vertical compression on top
   of the .87.4 reduction. */
.t20-row {
  counter-increment: t20;
  display: flex;
  align-items: baseline;
  gap: 4px;
  padding: 2px 6px 2px 18px;
  border-bottom: 1px solid var(--border);
  position: relative;
  min-width: 0;
  overflow: hidden;
}
.t20-row:last-child { border-bottom: none; }
.t20-row::before {
  content: counter(t20); position: absolute; left: 0; top: 2px;
  font-family: monospace; color: var(--muted); font-size: 9px; width: 16px; text-align: right;
}
.t20-title {
  /* Build .96.10: switched anchor from `inline-block` to `inline-flex`
     so its children (news/flame/closed icons, title-text span, bet-amt,
     chips) lay out as flex items.  The title-text span is the ONLY
     flexible child (`flex: 1 1 0`); icons + chips stay at content
     width and never get clipped by the ellipsis. */
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  /* Build .96.7: font 11→13px (~2pt larger per user request) — title
     is the primary content of each row, deserves a readable size. */
  font-size: 13px; font-weight: 600; color: var(--text);
  line-height: 1.4;
  /* Build .96.9 → v.03: title floor raised 100px → 180px to claim the
     real estate freed up by the retired mini-bar + the tightened meta
     max-width (40% → 25%).  Most card widths are 380-600px so 180px
     guarantees a long substring of every title shows even on the
     narrowest cards. */
  flex: 1 1 180px;
  min-width: 180px;
  overflow: hidden;
  white-space: nowrap;
}
/* Build .96.10: dedicated wrapper for the title TEXT — gets the
   text-overflow ellipsis treatment so it shrinks gracefully while
   the surrounding icons + chips stay at full size. */
.t20-title-text {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Bet-amt / new-badge / country-chip — fixed-size, never shrink.
   On very tight rows the row's `overflow: hidden` clips them. */
.t20-bet-amt, .new-badge, .country-chip { flex-shrink: 0; }
.t20-title:hover { color: var(--accent); text-decoration: none; }
.t20-meta {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 11px; color: var(--muted); font-family: monospace;
  line-height: 1.4;
  /* Build v.03: meta capped at 25% of row width (was 40%) — title
     reclaims that space.  Mini-bar is also gone in this build.  Meta
     gets ellipsis so it stays graceful even when squeezed.  */
  flex-shrink: 1;
  margin-left: auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 25%;
}
/* Build .96.6: mini-bar removed for max compression.  Per-option
   breakdown still rendered in the event modal — Top-20 rows are now
   pure list-of-titles with right-aligned volume metadata. */
.mini-bar { display: none; }
/* Group pill — let it shrink alongside the title when row is tight.
   Build .96.7: capped at 35% of row width too so pill + meta together
   can never eat more than ~80% of the row → title always has space.
   Build .96.9: tightened 35% → 28% so title is guaranteed ≥32% on
   non-Manifold rows where pill is present. */
.t20-group-pill {
  flex-shrink: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; max-width: 28%;
}
.new-badge {
  display: inline-block; font-size: 9px; font-weight: 800;
  background: var(--success); color: var(--bg);
  padding: 1px 5px; border-radius: var(--r-chip); margin: 0 6px 0 0;
  letter-spacing: 0.12em; vertical-align: middle;
  animation: newPulse 2.4s ease-in-out infinite;
  box-shadow: 0 0 0 0 rgba(34,197,94,0.7);
}
@keyframes newPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34,197,94,0.65); }
  50%      { box-shadow: 0 0 0 4px rgba(34,197,94,0); }
}
.country-chip {
  display: inline-block; font-size: 9px; font-weight: 700; background: var(--panel-2);
  color: var(--muted); padding: 1px 5px; border-radius: var(--r-chip); margin-left: 4px;
  font-family: monospace; vertical-align: middle;
}

/* Build v.03 (May 21): mini-bar permanently retired from Top-20 rows
   per user request — title text takes that horizontal space instead.
   Per-option breakdown still rendered in the event modal when the user
   clicks a row.  The earlier `display: none` rule at line ~2725 was
   being overridden by this block; consolidating to a single hide
   rule below removes that bug. */
.mini-bar, .mini-seg { display: none !important; }

/* ─── Whale + Jackpot ─── */
/* Build .87: dramatic compression of the Featured Whale Bets section.
   Per-row height drops ~50% (font sizes -20-30%, padding -40-50%, label
   strip slimmed, gap between cards tightened) so the 2×2 grid takes
   roughly half the vertical real estate it used to. */
.whale-section { padding: 0 20px; }
.whale-cards { display: grid; grid-template-columns: 2fr 1fr; gap: 8px; margin-top: 4px; }
.whale-cards-2x2 {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 4px;
}
/* Build v.03 .31 build 104: tighten the "Featured Whale Bets" heading
   so it sits closer to both the top-10 grid above and the 2x2 cards
   below.  Only overrides .section-heading WITHIN .whale-section — other
   sections (Top 20 etc.) keep their default 18/8 margins. */
.whale-section .section-heading {
  margin: 4px 20px 4px;
  padding-bottom: 4px;
}
.whale-section .whale-cards-2x2 { margin-top: 2px; }
.wc-latest .fw-label { background: var(--accent); color: var(--bg); }
.manifold-whale.wc-biggest .fw-label { background: var(--platform-manifold-brand); color: var(--bg); }
.manifold-whale.wc-latest .fw-label { background: #c4b5fd; color: var(--bg); }
.manifold-whale .fw-amount { color: var(--platform-manifold-brand); }

.featured-whale {
  background: linear-gradient(90deg, #1a0b2e 0%, var(--panel) 100%);
  border: 1px solid var(--border); border-radius: var(--r-card);
  display: flex; align-items: center; gap: 8px; padding: 0;
}
.fw-label {
  background: var(--whale); color: var(--bg); font-weight: 700; padding: 6px 6px;
  font-size: 9px; letter-spacing: 0.10em; white-space: nowrap; align-self: stretch;
  display: flex; align-items: center; border-radius: 6px 0 0 6px;
  writing-mode: vertical-rl; transform: rotate(180deg);  /* vertical label strip — saves horizontal width */
  text-align: center;
}
.fw-body { flex: 1; padding: 4px 8px; display: grid; grid-template-columns: auto 1fr; gap: 1px 10px; align-items: center; }
.fw-amount { grid-row: span 4; font-family: monospace; font-size: 20px; font-weight: 700; color: var(--whale); line-height: 1.1; }
.fw-bet { font-size: 11px; line-height: 1.3; }
.fw-event { font-size: 10px; color: var(--muted); line-height: 1.2; }
.fw-event a { color: var(--text); }
.fw-meta { font-size: 9px; color: var(--muted); font-family: monospace; line-height: 1.2; }
.fw-empty { padding: 8px; color: var(--muted); font-style: italic; font-size: 11px; }

/* Multi-item LATEST whale card */
.fw-multi-card { align-items: stretch; }
.fw-multi-card .fw-label { border-radius: 6px 0 0 6px; }
.fw-multi-list {
  flex: 1; list-style: none; margin: 0; padding: 3px 6px;
  display: flex; flex-direction: column; gap: 1px;
  max-height: none; overflow-y: visible;
}
.wc-biggest-list .fw-multi-list { max-height: none; }
.fw-multi-empty { color: var(--muted); font-style: italic; padding: 6px; font-size: 10px; }
.fw-mi { border-bottom: 1px dashed rgba(255,255,255,0.05); }
.fw-mi:last-child { border-bottom: none; }
.fw-mi-link {
  display: grid; gap: 1px 6px; padding: 2px 3px;
  grid-template-columns: auto auto 1fr auto;
  grid-template-areas: "amt side q odds" "evt evt evt evt" "meta meta meta meta";
  color: var(--text); font-size: 10px; line-height: 1.2;
}
.fw-mi-link:hover { background: var(--panel-2); text-decoration: none; }
.fw-mi-amt { grid-area: amt; font-family: monospace; font-weight: 700; color: var(--whale); white-space: nowrap; font-size: 11px; }
.manifold-whale .fw-mi-amt { color: var(--platform-manifold-brand); }
.fw-mi-side { grid-area: side; padding: 0 4px; border-radius: var(--r-chip); font-size: 8px; font-weight: 700; align-self: center; line-height: 1.4; }
.fw-mi-q { grid-area: q; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; font-size: 10px; }
.fw-mi-evt { grid-area: evt; color: var(--muted); font-size: 9px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fw-mi-meta { grid-area: meta; color: var(--muted); font-family: monospace; font-size: 8px; }
.fw-mi-link .odds-chip { grid-area: odds; align-self: center; margin-left: 0; font-size: 9px; padding: 0 4px; }
.whale-side { margin-right: 6px; padding: 2px 6px; border-radius: var(--r-chip); font-size: 11px; font-weight: 600; }
.side-buy { background: #064e3b; color: #6ee7b7; }
.side-sell { background: #7f1d1d; color: #fca5a5; }
.whale-user { color: var(--accent); }
/* Build .74.2: "AKA <pseudonym>" — small subscript next to primary name.
   Used when Polymarket trade payload has both `name` (user-chosen) and
   `pseudonym` (auto-generated). Subtle so it doesn't compete with the
   real handle but legible enough to convey identity ambiguity. */
.fw-aka {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 5px;
  font-size: 9px;
  font-weight: 500;
  color: var(--muted);
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: var(--r-chip);
  letter-spacing: 0.02em;
  vertical-align: middle;
}
.wm-aka {
  display: inline-block;
  margin-left: 10px;
  padding: 2px 7px;
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: var(--r-chip);
  letter-spacing: 0.02em;
  vertical-align: middle;
  text-transform: none;
}

.jackpot-card {
  background: linear-gradient(90deg, #3a2a0a 0%, var(--panel) 100%);
  border: 1px solid var(--border); border-radius: var(--r-card);
  display: flex; align-items: center; gap: 12px; padding: 0;
}
.jp-label {
  background: var(--jackpot); color: var(--bg); font-weight: 800; padding: 18px 12px;
  font-size: 12px; letter-spacing: 0.14em; white-space: nowrap; align-self: stretch;
  display: flex; align-items: center; writing-mode: vertical-rl; text-orientation: mixed;
  border-radius: 8px 0 0 8px;
}
.jp-body { flex: 1; padding: 12px 14px; }
.jp-amount { font-family: monospace; font-size: 24px; font-weight: 700; color: var(--jackpot); }
.jp-bet { font-size: 13px; margin-top: 4px; }
.jp-event { font-size: 12px; color: var(--muted); margin-top: 4px; }
.jp-event a { color: var(--text); }
.jp-meta { font-size: 10px; color: var(--muted); font-family: monospace; margin-top: 6px; line-height: 1.4; }
.jp-empty { padding: 14px; color: var(--muted); font-style: italic; font-size: 12px; }

.odds-chip {
  display: inline-block; background: var(--panel-2); color: var(--jackpot);
  padding: 1px 6px; border-radius: var(--r-chip); font-family: monospace; font-size: 11px;
  font-weight: 600; margin-left: 4px;
}

/* Outcome chip — names the side that the displayed YES price refers to
   in event-modal market rows. Shown only when the outcome name is
   informative (e.g. 'TheMongolz', 'Max Verstappen'), hidden when it's
   just 'Yes' to avoid redundancy with the column header. */
.outcome-chip {
  display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  padding: 1px 6px; border-radius: var(--r-chip);
  font-size: 11px; font-weight: 500;
  margin-left: 4px; vertical-align: baseline;
}

/* Build v0.4 (operator 2026-06-07): per-option price-history sparkline inside
   the event-modal option rows. Inline SVG; color teal/red by direction; all
   theme vars (auto-themes for peach via existing --accent / --danger). */
.opt-spark {
  display: inline-block; vertical-align: middle;
  margin-left: 6px; opacity: 0.85;
}
.opt-spark-up { color: var(--accent); }
.opt-spark-dn { color: var(--danger); }

/* ─── Build .260: Risers + Coldest merged into ONE horizontal box ──────
   Single card with 2-column inner grid (mirrors PHQ pattern).
   Old .rp-* / .risers-plungers / .rp-grid / .rp-col / .rp-head / .rp-table
   rules removed below — replaced by .movers-merged-* + .mvm-* namespace
   to avoid the .sig-row / .sig-link specificity collisions we hit in
   .258 with the liq-card.  .pct-up / .pct-down semantic colors kept. */
.movers-merged-section { padding: 16px 20px 0; }
.movers-merged-card {
  border-top: 3px solid var(--success);   /* green = "movers" accent */
  padding: 12px 16px 14px;
}
.movers-merged-card h3 { margin: 0 0 10px; }
.movers-merged-name { color: var(--success); font-weight: 800; }

.movers-merged-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* P0 2026-06-08: risers-only after Coldest comment-out */
  gap: 8px 28px;
}
.movers-col-head {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  margin: 0 0 6px; padding-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.movers-col-head-risers  { color: var(--success); }
.movers-col-head-coldest { color: var(--kalshi); }

.movers-flat-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.mvm-row {
  cursor: pointer;
  list-style: none;
}
.mvm-row:hover { background: color-mix(in srgb, var(--success) 5%, transparent); }
.mvm-link {
  display: flex; flex-direction: row; align-items: baseline;
  gap: 6px; padding: 4px 8px;
  text-decoration: none; color: var(--text);
  border-left: 2px solid transparent; border-radius: var(--r-chip);
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
  font-size: 12px;
}
.mvm-link:hover {
  text-decoration: none;
  border-left-color: var(--success);
  background: color-mix(in srgb, var(--success) 6%, transparent);
}
.mvm-meta {
  flex-shrink: 0; display: flex; align-items: center; gap: 4px;
  font-size: 10px; color: var(--muted);
}
.mvm-meta .plat-chip-logo { width: 12px; height: 12px; flex-shrink: 0; }
.mvm-meta .sig-plat {
  padding: 1px 5px; font-size: 9px; font-weight: 600;
  letter-spacing: 0.04em; flex-shrink: 0;
}
.mvm-title {
  flex: 1 1 0; min-width: 0;
  font-size: 12px; line-height: 1.3; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mvm-delta {
  flex-shrink: 0;
  font-family: monospace; font-weight: 700; font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.mvm-empty {
  list-style: none; padding: 8px 6px;
  color: var(--muted); font-size: 11px; font-style: italic;
}

/* ─── Jackpot + Daily Volume row ─── */
.jackpot-volume-row { padding: 16px 20px; }
.jv-grid { display: grid; grid-template-columns: 1fr 2fr; gap: 16px; align-items: stretch; }
.jp-card-block { min-height: 180px; }
.dv-chart { min-height: 180px; }

/* ─── Manifold Top 20 row tweaks ─── */
/* Build .96.6: override the prior grid layout — Manifold rows now use
   the same single-line flex layout as every other Top-20 platform.
   Profile image inline as a small (14px) flex child, counter
   absolutely-positioned (same as default rows), title + meta inline. */
.t20-row-manifold {
  display: flex;
  align-items: baseline;
  gap: 4px;
  padding: 2px 6px 2px 18px;
  position: relative;
  grid-template-columns: none;
}
.t20-row-manifold::before {
  position: absolute; left: 0; top: 2px;
  display: inline;
  grid-column: auto; grid-row: auto;
  font-family: monospace; color: var(--muted); font-size: 9px;
  width: 16px; text-align: right;
}
.t20-row-manifold .t20-icon {
  grid-column: auto; grid-row: auto;
}
.t20-row-manifold .t20-title,
.t20-row-manifold .t20-meta {
  grid-column: auto; grid-row: auto;
  padding-left: 0;
}
.t20-icon {
  /* Build .96.6: image shrunk 20→14 to match inline-flex baseline
     height with the other icons.  Was 20×20 spanning 2 grid rows. */
  width: 14px; height: 14px; object-fit: cover; border-radius: var(--r-chip);
  flex-shrink: 0;
  grid-row: auto;
}
.t20-bet-inline { color: var(--text); font-family: -apple-system, "Segoe UI", Roboto, sans-serif; }
/* Build .260: .rp-col / .rp-head / .rp-table / .plungers-table rules
   removed (replaced by .movers-merged-* + .mvm-* above).  Semantic
   delta-percent colors kept — referenced by .mvm-delta. */
.pct-up { color: var(--success); }
.pct-down { color: var(--danger); }

/* ─── Daily volume ─── */
.daily-volume { padding: 0 20px 20px; }
.daily-volume .chart-box { min-height: 280px; }

/* ─── Coldest events ─── */
.coldest-events { padding: 0 20px 20px; }
.coldest-events h2 { color: var(--danger); }
.coldest-events .rank { color: var(--muted); font-family: monospace; width: 24px; }

/* ─── Status badges / bet indicators ─── */
.status-badge {
  display: inline-block; font-size: 9px; font-weight: 700; padding: 1px 5px; border-radius: var(--r-chip);
  letter-spacing: 0.08em; margin-left: 6px; font-family: monospace;
}
.status-payable { background: color-mix(in srgb, var(--success) 20%, transparent); color: var(--success); }
.status-eliminated { background: color-mix(in srgb, var(--danger) 20%, transparent); color: var(--danger); }

/* ─── CLOB-derived chips (live mid, spread, price delta) ─── */
.delta-chip {
  display: inline-block; font-size: 10px; font-weight: 700; padding: 1px 5px; border-radius: var(--r-chip);
  font-family: monospace; margin-left: 4px; vertical-align: middle;
}
.delta-up { background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success); }
.delta-down { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }

/* ─── Foretold aggregate + resolution chips (Build v.03 .31 build 103) ─── */
/* Forecaster venue has no $ volume; we display Foretold's
   `previousAggregate` (community consensus) + `outcome` (resolution)
   in the t20-meta slot instead. */
.ft-agg {
  display: inline-block;
  font-size: 10px; font-weight: 600; color: var(--text);
  font-family: monospace; padding: 1px 5px; border-radius: var(--r-chip);
  background: rgba(148,163,184,0.12);
}
.ft-out {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  font-family: monospace; padding: 1px 5px; border-radius: var(--r-chip);
  color: var(--muted); background: rgba(148,163,184,0.14);
}
.ft-out.ft-out-yes {
  color: var(--success); background: color-mix(in srgb, var(--success) 16%, transparent);
}
.ft-out.ft-out-no {
  color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, transparent);
}

/* ─── Wallet comprehensive stats panel (Build v.03 .31 build 126) ─── */
.wallet-stats-panel {
  padding: 0 20px; margin: 18px 0 24px;
}
/* wallet-stats-tabs 2026-07-10: WHALE / ALL scope switcher. All colors via
   CSS vars (graphical tenet). */
.wsp-tabs {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 0 0 14px; padding-bottom: 8px;
  border-bottom: 1px solid var(--border, #1f2530);
}
.wsp-tab {
  appearance: none; cursor: pointer;
  background: transparent; color: var(--muted, #8b95a6);
  border: 1px solid var(--border, #1f2530); border-radius: var(--r-chip, 8px);
  padding: 5px 13px; font-size: 13px; font-weight: 700; letter-spacing: 0.2px;
  transition: color .15s, border-color .15s, background .15s;
}
.wsp-tab:hover { color: var(--text, #e6eaf0); border-color: var(--accent, #2dd4bf); }
.wsp-tab.is-active {
  color: var(--accent, #2dd4bf); border-color: var(--accent, #2dd4bf);
  background: color-mix(in srgb, var(--accent, #2dd4bf) 12%, transparent);
}
.wsp-tab-sub { font-size: 11px; color: var(--muted, #8b95a6); margin-left: 4px; }
.wsp-pane { display: none; }
.wsp-pane.is-active { display: block; }
/* async ALL-pane loading state */
.wsp-loading { padding: 8px 0 4px; }
.wsp-shimmer {
  height: 74px; margin-bottom: 12px; border-radius: 10px;
  background: linear-gradient(90deg,
    var(--card, #11151c) 25%,
    color-mix(in srgb, var(--border, #1f2530) 60%, var(--card, #11151c)) 50%,
    var(--card, #11151c) 75%);
  background-size: 200% 100%;
  animation: wsp-shimmer 1.3s ease-in-out infinite;
}
.wsp-shimmer-wide { height: 96px; }
@keyframes wsp-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
.wsp-loading-txt, .wsp-empty {
  font-size: 12px; color: var(--muted, #8b95a6); text-align: center; margin: 6px 0 0;
}
.wsp-empty { padding: 22px 12px; }
.ws-row { display: grid; gap: 12px; margin-bottom: 12px; }
.ws-row-2col { grid-template-columns: 1fr 1fr; }
.ws-row-3col { grid-template-columns: 1fr 1fr 1fr; }
.ws-row-1col { grid-template-columns: 1fr; }
.ws-block {
  background: var(--card, #11151c);
  border: 1px solid var(--border, #1f2530);
  border-radius: var(--r-card);
  padding: 12px 14px;
}
.ws-block.ws-settled { border-left: 3px solid var(--kalshi); }
.ws-block.ws-open    { border-left: 3px solid var(--accent); }
.ws-block.ws-streaks { border-left: 3px solid var(--jackpot); }
.ws-block.ws-activity { border-left: 3px solid var(--platform-manifold-brand); }
.ws-block.ws-recent   { border-left: 3px solid var(--whale); }
.ws-block.ws-sizing   { border-left: 3px solid var(--muted); }
.ws-hdr {
  font-size: 13px; font-weight: 700; color: #e6e8ee;
  margin-bottom: 10px;
}
.ws-hdr-sub {
  font-size: 11px; font-weight: 500;
  color: var(--muted, var(--muted)); font-style: italic;
  margin-left: 6px;
}
.ws-figures {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.ws-fig { text-align: center; padding: 4px; }
.ws-fig-num {
  font-size: 20px; font-weight: 800; font-family: monospace;
  color: #e6e8ee; line-height: 1.2;
}
.ws-fig-num.ws-fig-date { font-size: 14px; }
.ws-fig-lbl {
  font-size: 10px; color: var(--muted, var(--muted));
  text-transform: uppercase; letter-spacing: 0.04em;
  margin-top: 2px;
}
.ws-pos { color: var(--success, var(--success)); }
.ws-neg { color: var(--danger, var(--danger)); }
.ws-sub {
  margin-top: 8px;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.ws-chip {
  display: inline-block; padding: 2px 8px;
  background: rgba(148,163,184,0.10);
  border-radius: var(--r-card); font-size: 11px;
  color: var(--text); font-family: monospace;
}
.ws-chip.ws-chip-pos {
  background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success, var(--success));
}
.ws-chip.ws-chip-neg {
  background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger, var(--danger));
}
.ws-empty {
  font-size: 12px; color: var(--muted, var(--muted));
  font-style: italic; padding: 8px 0;
}
@media (max-width: 1000px) {
  .ws-row-3col { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .ws-row-2col, .ws-row-3col { grid-template-columns: 1fr; }
}
.ws-row { display: grid; gap: 12px; margin-bottom: 12px; }
.ws-row-2col { grid-template-columns: 1fr 1fr; }
.ws-row-3col { grid-template-columns: 1fr 1fr 1fr; }
.ws-row-1col { grid-template-columns: 1fr; }
.ws-block {
  background: var(--card, #11151c);
  border: 1px solid var(--border, #1f2530);
  border-radius: var(--r-card);
  padding: 12px 14px;
}
.ws-block.ws-settled { border-left: 3px solid var(--kalshi); }
.ws-block.ws-open    { border-left: 3px solid var(--accent); }
.ws-block.ws-streaks { border-left: 3px solid var(--jackpot); }
.ws-block.ws-activity { border-left: 3px solid var(--platform-manifold-brand); }
.ws-block.ws-recent   { border-left: 3px solid var(--whale); }
.ws-block.ws-sizing   { border-left: 3px solid var(--muted); }
.ws-hdr {
  font-size: 13px; font-weight: 700; color: #e6e8ee;
  margin-bottom: 10px;
}
.ws-hdr-sub {
  font-size: 11px; font-weight: 500;
  color: var(--muted, var(--muted)); font-style: italic;
  margin-left: 6px;
}
.ws-figures {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.ws-fig { text-align: center; padding: 4px; }
.ws-fig-num {
  font-size: 20px; font-weight: 800; font-family: monospace;
  color: #e6e8ee; line-height: 1.2;
}
.ws-fig-num.ws-fig-date { font-size: 14px; }
.ws-fig-lbl {
  font-size: 10px; color: var(--muted, var(--muted));
  text-transform: uppercase; letter-spacing: 0.04em;
  margin-top: 2px;
}
.ws-pos { color: var(--success, var(--success)); }
.ws-neg { color: var(--danger, var(--danger)); }
.ws-sub {
  margin-top: 8px;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.ws-chip {
  display: inline-block; padding: 2px 8px;
  background: rgba(148,163,184,0.10);
  border-radius: var(--r-card); font-size: 11px;
  color: var(--text); font-family: monospace;
}
.ws-chip.ws-chip-pos {
  background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success, var(--success));
}
.ws-chip.ws-chip-neg {
  background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger, var(--danger));
}
.ws-empty {
  font-size: 12px; color: var(--muted, var(--muted));
  font-style: italic; padding: 8px 0;
}
@media (max-width: 1000px) {
  .ws-row-3col { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .ws-row-2col, .ws-row-3col { grid-template-columns: 1fr; }
}

/* ─── Wallet Smart Score (Build v.03 .31 build 108) ─── */
/* Composite 0-10 quality metric: ROI × win-rate × log(trades) × log(|PnL|)
   × recency. Section + per-row card for the "Smartest Wallets" leaderboard,
   plus inline chips for the Smart-Money Feed. */
.smartest-wallets-section { padding: 0 20px; margin-bottom: 18px; }
.smartest-wallets-section .section-heading {
  margin: 4px 0 6px; padding-bottom: 4px;
}
.smartest-wallets-card {
  background: var(--card, #11151c);
  border: 1px solid var(--border, #1f2530);
  border-radius: var(--r-card);
  padding: 10px 14px;
}
.sw-subheading {
  font-size: 11px; color: var(--muted, var(--muted));
  margin-bottom: 6px; font-style: italic;
  cursor: help;
}
.sw-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.sw-row {
  display: grid;
  grid-template-columns: 28px 60px minmax(140px, 1fr) auto auto auto auto;
  gap: 8px;
  align-items: center;
  padding: 4px 6px;
  border-radius: var(--r-chip);
  font-size: 12px;
  font-family: monospace;
}
.sw-row:hover { background: color-mix(in srgb, var(--kalshi) 6%, transparent); }
.sw-row.sw-elite { border-left: 3px solid var(--jackpot); }
.sw-row.sw-strong { border-left: 3px solid var(--success); }
.sw-row.sw-mid { border-left: 3px solid var(--kalshi); }
.sw-row.sw-weak { border-left: 3px solid var(--muted); }
.sw-rank {
  color: var(--muted, var(--muted)); font-weight: 700; text-align: right;
}
.sw-score-chip {
  display: inline-block; font-weight: 800; padding: 2px 7px;
  border-radius: var(--r-chip); font-family: monospace;
  text-align: center;
}
.sw-score-chip.sw-score-sw-elite {
  background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot);
  box-shadow: 0 0 6px color-mix(in srgb, var(--jackpot) 25%, transparent);
}
.sw-score-chip.sw-score-sw-strong { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.sw-score-chip.sw-score-sw-mid { background: color-mix(in srgb, var(--kalshi) 16%, transparent); color: var(--kalshi); }
.sw-score-chip.sw-score-sw-weak { background: rgba(100,116,139,0.18); color: var(--muted); }
.sw-wallet {
  color: #e6e8ee; text-decoration: none; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sw-wallet:hover { color: var(--kalshi); text-decoration: underline; }
.sw-stat {
  display: inline-flex; gap: 3px; align-items: baseline;
  padding: 1px 6px; border-radius: var(--r-chip);
  background: rgba(148,163,184,0.08);
  white-space: nowrap;
}
.sw-stat-lbl { color: var(--muted, var(--muted)); font-size: 10px; font-weight: 500; }
.sw-pos { color: var(--success, var(--success)); }
.sw-neg { color: var(--danger, var(--danger)); }

/* Inline Smart-Score chip used in Smart-Money Feed rows */
.smart-score-chip {
  display: inline-flex; align-items: center;
  font-weight: 800; padding: 1px 6px; border-radius: var(--r-chip);
  font-family: monospace; font-size: 10px;
  margin-right: 3px;
}
.smart-score-chip.ss-elite {
  background: color-mix(in srgb, var(--jackpot) 18%, transparent); color: var(--jackpot);
}
.smart-score-chip.ss-strong { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success); }
.smart-score-chip.ss-mid { background: color-mix(in srgb, var(--kalshi) 16%, transparent); color: var(--kalshi); }
.smart-score-chip.ss-weak { background: rgba(100,116,139,0.18); color: var(--muted); }

@media (max-width: 900px) {
  .sw-row {
    grid-template-columns: 24px 56px 1fr auto;
    grid-template-rows: auto auto;
    gap: 4px 6px;
  }
  .sw-row > .sw-roi { grid-column: 1 / -1; grid-row: 2; justify-self: start; }
  .sw-row > .sw-win,
  .sw-row > .sw-trades,
  .sw-row > .sw-pnl { grid-row: 2; }
}

/* ─── Foretold rich data panel (Build v.03 .31 build 110) ─── */
/* Per-event modal rendering of Foretold's full "Aggregate and resolution"
   view — markdown question description, channel + creator badges,
   expected/actual resolution timestamps, CDF percentiles. */
.ft-rich-block {
  margin: 12px 0 16px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--kalshi) 4%, transparent);
  border-left: 3px solid var(--kalshi);
  border-radius: var(--r-card);
}
.ft-rich-sub {
  font-size: 11px; font-weight: 500; color: var(--muted, var(--muted));
  margin-left: 8px; font-style: italic;
}
.ft-meta-strip {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-bottom: 12px; font-size: 11px;
}
.ft-chip {
  display: inline-block; padding: 2px 8px;
  background: rgba(148,163,184,0.12); color: var(--text);
  border-radius: var(--r-card); font-family: monospace;
  white-space: nowrap;
}
.ft-state-badge {
  display: inline-block; padding: 2px 8px;
  font-weight: 700; border-radius: var(--r-card);
  font-family: monospace; font-size: 11px;
}
.ft-state-badge.ft-state-judged {
  background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success, var(--success));
}
.ft-state-badge.ft-state-open {
  background: color-mix(in srgb, var(--kalshi) 18%, transparent); color: var(--kalshi);
}
.ft-state-badge.ft-state-closed {
  background: color-mix(in srgb, var(--jackpot) 16%, transparent); color: var(--jackpot);
}
.ft-ar-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.ft-ar-col {
  padding: 10px 12px; border-radius: var(--r-chip);
  background: rgba(11,16,32,0.6);
}
.ft-ar-col.ft-ar-empty { opacity: 0.6; }
.ft-ar-col.ft-ar-out-resolved {
  background: color-mix(in srgb, var(--success) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 18%, transparent);
}
.ft-ar-hdr {
  font-size: 11px; font-weight: 700; color: var(--muted, var(--muted));
  text-transform: uppercase; letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.ft-ar-sub {
  font-size: 10px; font-weight: 500; text-transform: none;
  letter-spacing: 0; color: var(--muted, var(--muted));
  font-style: italic;
}
.ft-ar-value {
  font-size: 22px; font-weight: 800; font-family: monospace;
  color: #e6e8ee; margin-bottom: 6px;
}
.ft-ar-col.ft-ar-out-resolved .ft-ar-value { color: var(--success, var(--success)); }
.ft-ar-meta {
  font-size: 11px; color: var(--muted, var(--muted));
  font-family: monospace; margin-top: 2px;
}
.ft-ar-meta .ft-k {
  color: var(--muted); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.04em;
  margin-right: 4px;
}
.ft-pctl {
  font-size: 11px; color: var(--text); font-family: monospace;
  margin-bottom: 4px;
}
.ft-ar-desc {
  font-size: 11px; color: var(--text); line-height: 1.4;
  margin-top: 8px; padding-top: 6px;
  border-top: 1px solid rgba(148,163,184,0.15);
}
.ft-desc-details {
  margin-top: 10px; padding: 8px 10px;
  background: rgba(11,16,32,0.5);
  border-radius: var(--r-chip);
}
.ft-desc-details summary {
  cursor: pointer; font-size: 12px; font-weight: 600;
  color: var(--muted, var(--muted));
}
.ft-desc-details[open] summary { margin-bottom: 8px; }
.ft-desc-sub { font-weight: 500; font-style: italic; }
.ft-desc-body {
  font-size: 12px; color: var(--text);
  white-space: pre-wrap; line-height: 1.5;
  font-family: inherit;
}
@media (max-width: 700px) {
  .ft-ar-grid { grid-template-columns: 1fr; }
}

/* ─── FantasySCOTUS Yes/No odds chips (Build v.03 .31 build 106) ─── */
/* SCOTUS-affirm questions are always binary; show both side odds since
   leader-only hides how close the vote split is. */
.fs-yes {
  display: inline-block;
  font-size: 10px; font-weight: 700; color: var(--success);
  font-family: monospace; padding: 1px 5px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--success) 16%, transparent);
}
.fs-no {
  display: inline-block;
  font-size: 10px; font-weight: 700; color: var(--danger);
  font-family: monospace; padding: 1px 5px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--danger) 16%, transparent);
}

/* ─── Top-20 rank-change indicators (prominent, leftmost on each row) ─── */
.t20-row { position: relative; }
.t20-row::after {
  content: ''; display: inline-block;
  position: absolute; left: 4px; top: 11px;
  width: 14px; height: 14px;
  font-size: 14px; line-height: 1; font-weight: 800;
  text-align: center;
}
.t20-row.t20-rc-up::after   { content: '▲'; color: var(--success);
  text-shadow: 0 0 4px color-mix(in srgb, var(--success) 60%, transparent); }
.t20-row.t20-rc-down::after { content: '▼'; color: var(--danger);
  text-shadow: 0 0 4px color-mix(in srgb, var(--danger) 60%, transparent); }
.t20-row.t20-rc-same::after { content: '●'; color: var(--jackpot);
  font-size: 10px; top: 14px; }
.t20-row.t20-rc-new::after  { content: '★'; color: var(--success);
  font-size: 13px; top: 12px;
  text-shadow: 0 0 6px rgba(34,197,94,0.7); }
/* Slightly indent every t20-row to make space for the arrow icon */
.t20-row { padding-left: 24px; }

/* ─── 🔥 Flame badge (big bets / 2x volume movers) ─── */
.flame-badge {
  display: inline-block;
  font-size: 18px; line-height: 1;     /* was 13px — bumped per UX request */
  margin-right: 5px;
  filter: drop-shadow(0 0 4px rgba(251,113,133,0.85));
  animation: flameFlicker 1.6s ease-in-out infinite;
  vertical-align: middle;
}
@keyframes flameFlicker {
  0%, 100% { filter: drop-shadow(0 0 4px rgba(251,113,133,0.85)); }
  50%      { filter: drop-shadow(0 0 9px color-mix(in srgb, var(--jackpot) 100%, transparent)); }
}

/* Row background brightening when an event has a 🔥 flame (big leader
   bet or 24h-volume doubling). Applied via .t10-row-flame / .t20-row-flame
   classes set server-side in the template — keeps lookups simple and
   works in every browser (no :has() dependency). */
.t10-row.t10-row-flame,
.t20-row.t20-row-flame {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--jackpot) 13%, transparent) 0%,
    rgba(251, 113, 133, 0.09) 50%,
    color-mix(in srgb, var(--jackpot) 5%, transparent) 100%
  );
  border-left: 2px solid rgba(251, 113, 133, 0.55);
  box-shadow: inset 0 0 18px rgba(251, 113, 133, 0.05);
}
.t10-row.t10-row-flame:hover,
.t20-row.t20-row-flame:hover {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--jackpot) 20%, transparent) 0%,
    rgba(251, 113, 133, 0.14) 50%,
    color-mix(in srgb, var(--jackpot) 9%, transparent) 100%
  );
}
.delta-flat { background: var(--panel-2); color: var(--muted); }
.delta-na { color: var(--muted); font-family: monospace; font-size: 11px; }
.spread-chip {
  display: inline-block; font-size: 10px; padding: 1px 5px; border-radius: var(--r-chip);
  font-family: monospace; margin-left: 4px; vertical-align: middle;
  background: var(--panel-2); color: var(--muted);
}
.opt-spread, .opt-delta { font-family: monospace; font-size: 11px; white-space: nowrap; }

/* ─── Tables (legacy) ─── */
table { width: 100%; border-collapse: collapse; background: var(--panel); border-radius: var(--r-card); overflow: hidden; }
.empty { padding: 20px; color: var(--muted); font-style: italic; text-align: center; }
code { background: var(--panel-2); padding: 2px 6px; border-radius: var(--r-chip); font-family: monospace; }

/* ─── Footer ─── */
footer {
  display: flex; justify-content: space-between; align-items: center;
  color: var(--muted); font-size: 11px; padding: 14px 20px;
  border-top: 1px solid var(--border);
}
.data-credit { color: var(--muted); letter-spacing: 0.03em; line-height: 1.55; text-align: left; }
.data-credit strong { color: var(--text); font-weight: 700; margin-right: 4px; }
.data-credit-link { color: inherit; text-decoration: underline; text-decoration-style: dotted; text-decoration-color: var(--border); }
.data-credit-link:hover { color: var(--accent); text-decoration-color: var(--accent); }
/* .424: the public-footer Terms link was muted (`.data-credit-link` inherits
   var(--muted) + a faint dotted border-color underline) → it read as prose, not a
   link (operator-reported "not visible"). `.footer-terms-link` makes it unmistakable;
   `.footer-legal-line` gives it its own row. Theme-safe — CSS vars only. */
.footer-legal-line { margin-top: 6px; }
.footer-terms-link { color: var(--accent); font-weight: 600; text-decoration: underline; text-decoration-style: solid; text-decoration-color: var(--accent); }
.footer-terms-link:hover { color: var(--accent); text-decoration-thickness: 2px; }
.data-credit-sep { display: inline-block; margin: 0 8px; color: rgba(148, 163, 184, 0.45); }
/* Build .94.1: each footer credit category renders as its own
   left-aligned block-level line (instead of the prior inline single-
   paragraph with `·` separators). Four lines total:
     1. Prediction markets: ...
     2. News sources:       ...
     3. Aggregators & APIs: ...
     4. <version> · <contact>
   Small vertical gap between lines for breathing room. */
.data-credit-line {
  display: block;
  text-align: left;
  margin-bottom: 4px;
}
.data-credit-line:last-child { margin-bottom: 0; }
/* .413 (operator): embolden the ownership line + a slightly brighter panel
   background so it reads as the primary footer statement. Theme-vars only —
   color-mix lifts the base panel a touch toward the text color (works on both
   dark + peach). The <strong> inside stays full-strength via --text. */
.data-credit-ownership {
  font-weight: 700;
  background: color-mix(in srgb, var(--panel-2) 78%, var(--text) 8%);
  padding: 7px 10px;
  border-radius: 5px;
}
.data-credit-ownership strong { color: var(--text); }
/* Responsible-use / independence disclaimer (footer, signed off 2026-06-06).
   Self-sufficient (own color + strong-color) so it works inside index.html's
   .data-credit AND as a standalone child of wallet.html's <footer>. Vars only
   (no hardcoded colors); overflow-wrap honors the no-horizontal-scrollbar rule. */
.data-credit-responsible {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  max-width: 880px;
  overflow-wrap: anywhere;
  color: var(--muted);
}
.data-credit-responsible strong { color: var(--text); }
/* Build v0.4 20260526.230: header line ("Powered by:") sits as a small
   section anchor above the three credit lines.  Slightly larger + a
   bit of bottom margin so the eye reads it as a heading rather than
   another data line. */
.data-credit-header {
  font-size: 14px;
  margin-bottom: 6px;
  color: var(--text);
  letter-spacing: 0.02em;
}
.data-credit-header strong { font-weight: 800; }
/* The fourth line (version + contact) sits visually a touch lower-key
   than the source-credit lines — same muted family but a bit smaller. */
.data-credit-meta {
  margin-top: 6px;
  font-size: 11px;
}
.data-credit-meta .version-tag,
.data-credit-meta .footer-contact {
  display: inline;
  margin-top: 0;
}
/* footer-social 2026-07-11 (operator): LinkedIn / X / Telegram account links.
   Monochrome muted glyphs that brighten to the accent on hover — theme-safe
   (no brand literals; the graphical tenet). */
.footer-social { display: flex; justify-content: center; align-items: center; gap: 18px; padding: 8px 0 2px; }
.fsoc-link { color: var(--muted); display: inline-flex; transition: color 0.15s ease; }
.fsoc-link:hover { color: var(--accent); }
.fsoc-icon { display: block; }

.version-tag {
  display: inline-block; margin-top: 4px;
  font-size: 10px; color: var(--muted); opacity: 0.6;
  font-family: monospace; letter-spacing: 0.05em;
}
.footer-meta { font-family: monospace; }

/* Build .315: consolidated footer stripe under the PredictHQ box.  It's a
   <footer>, so it inherits the base footer flex/padding/border-top; we override
   to a top-aligned two-zone band: Powered-by credits (left) across from the
   visitor globe + stats + flag tabs (bottom-right).  Wraps on narrow screens. */
.footer-stripe { align-items: flex-start; gap: 28px; flex-wrap: wrap; }
.fs-credits { flex: 1 1 320px; min-width: 0; }
.fs-credits .data-credit-header { font-size: 13px; margin-bottom: 4px; }
.fs-credits .data-credit-line { margin-bottom: 3px; }
.fs-credits .data-credit-meta { margin-top: 5px; }
.fs-visitors { flex: 1 1 430px; min-width: 0; }
/* Re-flow the visitor cluster: globe + stats on top, tabs, then the full
   20-flag grid spanning the width (all 20 visible per tab — no scroll). */
.fs-visitors .visitor-body-flat {
  display: grid;
  grid-template-columns: 76px auto;
  grid-template-areas:
    "globe stats"
    "tabs  tabs"
    "flags flags";
  gap: 5px 12px;
  align-items: center;
}
.fs-visitors .vw-globe-wrap { grid-area: globe; }
.fs-visitors .vw-globe-flat { width: 76px; height: 76px; }
.fs-visitors .vw-stats-flat { grid-area: stats; }
.fs-visitors .vw-flag-tabs { grid-area: tabs; border-left: none; padding: 2px 0 0; }
.fs-visitors .vw-list-flat {
  grid-area: flags; border-left: none; padding: 3px 0 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 0 12px; max-height: none; overflow: visible; font-size: 10px;
}
@media (max-width: 760px) {
  .fs-visitors .visitor-body-flat { grid-template-columns: 64px auto; }
}
.footer-contact {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.02em;
}
.footer-contact a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px dotted var(--border);
}
.footer-contact a:hover {
  border-bottom-color: var(--accent);
}
@media (max-width: 700px) {
  /* Build .94.1: keep `.data-credit-line` left-aligned on mobile even
     when the parent footer stacks vertically.  User explicitly asked
     for left-aligned attribution lines. */
  footer { flex-direction: column; gap: 6px; text-align: left; align-items: flex-start; }
  .data-credit { width: 100%; }
}

/* Flat visitor card at the bottom of the page (Phase 4 UX:
   single horizontal rectangle with globe on the left, stats grid in the
   middle, country list on the right — no nested 2-col layout). */
/* Build .313 (2026-06-02): compact visitor widget — minimal real-estate. */
.visitor-row { padding: 4px 20px; }
.visitor-card-flat {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 6px 10px; min-height: 0;
}
.visitor-card-flat h3 { margin: 0 0 4px; font-size: 11px; }
.visitor-body-flat {
  display: grid;
  grid-template-columns: 72px minmax(140px, 260px) 1fr;
  gap: 10px; align-items: center; min-height: 0;
}
.vw-globe-flat {
  width: 72px; height: 72px;
  margin: 0; flex-shrink: 0;
}
.visitor-card .vw-stats-flat {
  /* .282: 2x2 grid; .313: tighter gap */
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px;
  align-items: stretch;
}
.visitor-card .vw-stat { padding: 2px 4px; }
.visitor-card .vw-stat-num { font-size: 13px; }
.visitor-card .vw-stat-lbl { font-size: 9px; }
.visitor-card .vw-stat-sub { font-size: 8px; }
.vw-list-flat {
  list-style: none; margin: 0; padding: 3px 8px;
  border-left: 1px solid var(--border);
  max-height: 90px; overflow-y: auto;
  font-size: 10px;
}
.vw-list-flat li {
  display: flex; justify-content: space-between; align-items: center;
  padding: 1px 0;
}
/* Build .313: tab bar — compact. */
.vw-flag-tabs {
  display: flex; flex-wrap: wrap; gap: 3px;
  padding: 2px 8px 0;
  border-left: 1px solid var(--border);
}
.vw-flag-tab {
  background: transparent; color: var(--muted);
  border: 1px solid var(--border); border-radius: var(--r-chip);
  font-size: 9px; font-variant-numeric: tabular-nums;
  padding: 0 4px; cursor: pointer; line-height: 1.5;
}
.vw-flag-tab:hover { color: var(--fg); border-color: var(--muted); }
.vw-flag-tab.active {
  color: var(--fg); border-color: var(--accent, var(--accent));
  background: rgba(34,211,238,0.08);
}
@media (max-width: 900px) {
  .visitor-body-flat {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .vw-globe-flat { margin: 0 auto; }
  .vw-list-flat { border-left: none; border-top: 1px solid var(--border); padding-top: 6px; }
}

/* sx.bet geo-block pill + empty state */
.plat-blocked-pill {
  display: inline-block; vertical-align: middle;
  margin-left: 8px; padding: 2px 7px; border-radius: var(--r-card);
  font-size: 9px; font-weight: 700; letter-spacing: 0.06em;
  background: rgba(251,113,133,0.18); color: #fda4af;
  border: 1px solid rgba(251,113,133,0.35);
}
.empty-blocked {
  background: rgba(251,113,133,0.08);
  border: 1px dashed rgba(251,113,133,0.4);
  border-radius: var(--r-card);
  padding: 14px 16px; line-height: 1.55;
  color: var(--muted); font-size: 12px;
  margin: 8px 0;
}
.empty-blocked strong { color: var(--text); display: block; margin-bottom: 4px; }

/* ─── News-link icon (Phase 6) ────────────────────────────────────────────
   Pure visual indicator that a high-confidence news article exists for this
   event — NOT a clickable link. The article URL itself opens via the event
   card (.evt-news-card below) so the row click flow stays consistent: title
   → event modal → read the article from there. Earlier versions wrapped the
   icon in an <a>, but nested anchors inside the .t10-title link broke the
   title click. */
.news-icon, .news-icon-flag {
  display: inline-block; vertical-align: middle;
  margin-right: 5px; padding: 0 2px;
  font-size: 12px; line-height: 1;
  opacity: 0.7;
  pointer-events: none;   /* truly non-interactive — clicks pass through to .t10-title */
}

/* ─── Event modal: news block ─────────────────────────────────────────────
   Sits between the modal head and the meta-card; readers scan past the
   event title and immediately see "Related news" with the actual article
   link they can open. */
.evt-news-card {
  display: flex; gap: 12px; align-items: flex-start;
  margin: 12px 0; padding: 12px 14px;
  background: color-mix(in srgb, var(--kalshi) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--kalshi) 25%, transparent);
  border-radius: var(--r-card);
}
.evt-news-card .evt-news-icon {
  font-size: 22px; line-height: 1.1; flex: 0 0 auto;
}
.evt-news-card .evt-news-body { flex: 1; min-width: 0; }
.evt-news-card .evt-news-label {
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 4px;
}
.evt-news-card .evt-news-link {
  color: var(--accent); font-weight: 600;
  text-decoration: none; word-break: break-word;
}
.evt-news-card .evt-news-link:hover { text-decoration: underline; }
.evt-news-card .evt-news-meta {
  font-size: 11px; color: var(--muted); margin-top: 4px;
  font-family: monospace;
}

/* Source-provider chip on the primary 'Related news' line — labels
   whether the article came from Guardian (primary) or GDELT (fallback). */
.evt-news-provider {
  display: inline-block; margin-left: 6px;
  padding: 1px 6px; border-radius: var(--r-chip);
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.04em;
}
.evt-news-provider-guardian {
  background: rgba(0, 87, 156, 0.20); color: #5da8ff;
  border: 1px solid rgba(0, 87, 156, 0.40);
}
.evt-news-provider-gdelt {
  background: rgba(148, 163, 184, 0.15); color: var(--muted);
  border: 1px solid rgba(148, 163, 184, 0.30);
}
/* Build .87.1: NewsData.io fallback badge — amber to match the
   integration's brand without colliding with Guardian's blue. */
.evt-news-provider-newsdata {
  background: rgba(245, 158, 11, 0.18); color: var(--jackpot);
  border: 1px solid rgba(245, 158, 11, 0.40);
}
/* Build .90: Currents API third-source badge — emerald green to keep
   the three primary providers visually distinct (Guardian blue,
   NewsData amber, Currents green). */
.evt-news-provider-currents {
  background: rgba(16, 185, 129, 0.18); color: var(--success);
  border: 1px solid rgba(16, 185, 129, 0.40);
}
/* Build .90.1: HackerNews fourth-source badge — HN signature orange
   (#ff6600) so the brand association is immediate.  Caps it at the
   same border-weight as the other three sources so all four primary
   badges read visually similar. */
.evt-news-provider-hackernews {
  background: rgba(255, 102, 0, 0.18); color: #ff6600;
  border: 1px solid rgba(255, 102, 0, 0.40);
}

/* GDELT-augmented 'More coverage' list inside the event modal. Only
   rendered when the primary news icon is present. Sits below the
   primary article link, never on the main UI. */
.evt-news-extras {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed color-mix(in srgb, var(--kalshi) 20%, transparent);
}
.evt-news-extras-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin-bottom: 4px;
}
/* Build .58 (item #3): loading-skeleton styling so the "Loading…" text
   has a visible container instead of looking like a dangling sentence
   above the dashed divider. */
.evt-news-extras-loading .evt-news-extras-skel {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
  padding: 3px 0;
  opacity: 0.7;
  animation: extrasPulse 1.6s ease-in-out infinite;
}
@keyframes extrasPulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 0.85; }
}
.evt-news-extras-list {
  list-style: none; margin: 0; padding: 0;
}
.evt-news-extras-list li {
  font-size: 12px; line-height: 1.4; padding: 3px 0;
  display: flex; gap: 10px; align-items: baseline;
}
.evt-news-extras-list a {
  color: var(--text); text-decoration: none;
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.evt-news-extras-list a:hover { color: var(--accent); text-decoration: underline; }
.evt-news-extras-src {
  font-size: 10px; color: var(--muted); font-family: monospace;
  flex: 0 0 auto;
}
/* Build .77: per-row source badge so users can distinguish GDELT (live)
   from NewsData.io (cached, 4h-budget) articles. */
.nx-src-badge {
  display: inline-block;
  font-family: monospace;
  font-size: 8px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: var(--r-chip);
  letter-spacing: 0.04em;
  flex: 0 0 auto;
  cursor: help;
}
.nx-src-gd { background: color-mix(in srgb, var(--platform-manifold-brand) 15%, transparent); color: var(--platform-manifold-brand); }
.nx-src-nd { background: rgba(34, 211, 238, 0.15);  color: var(--accent); }

/* ─── Wallet link styling ─── */
.wallet-link {
  color: var(--accent); text-decoration: none; cursor: pointer;
  border-bottom: 1px dotted color-mix(in srgb, var(--accent) 40%, transparent);
}
.wallet-link:hover { color: var(--text); border-bottom-color: var(--text); text-decoration: none; }

/* Jackpot row winner line */
.jp-row-winner {
  display: flex; gap: 6px; align-items: baseline; padding: 2px 4px 6px 30px;
  font-size: 11px; color: var(--muted); flex-wrap: wrap;
}
.jp-row-winner .wallet-link { font-weight: 700; }
.jp-winner-amt { color: var(--success); font-family: monospace; font-weight: 700; }
.jp-winner-sub { color: var(--muted); font-family: monospace; }

/* ─── Wallet modal ─── */
.wallet-modal { max-width: 880px; }
.wm-head { margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.wm-name { font-size: 22px; font-weight: 800; color: var(--text); }
.wm-addr { font-size: 11px; color: var(--muted); margin-top: 2px; }
.wm-addr code { font-size: 11px; }

/* Build .65 (item #4): permalink to full /wallet/<addr> page in modal
   header, and PMXT open-positions summary band below the header. */
.wm-full-link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}
.wm-full-link:hover { text-decoration: underline; }

.wm-pmxt-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
  padding: 8px 12px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: var(--r-card);
  font-size: 12px;
  color: var(--text);
  cursor: help;
}
.wm-pmxt-summary .wm-pmxt-label {
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.03em;
}
.wm-pmxt-summary .wm-pmxt-stat {
  color: var(--muted);
  font-size: 12px;
}
.wm-pmxt-summary .wm-pmxt-stat strong {
  color: var(--text);
  font-weight: 700;
  margin-right: 4px;
}
.wm-pmxt-summary .wm-pmxt-more {
  margin-left: auto;
  color: var(--accent);
  text-decoration: none;
  font-size: 11px;
}
.wm-pmxt-summary .wm-pmxt-more:hover { text-decoration: underline; }
@media (max-width: 768px) {
  .wm-pmxt-summary { font-size: 10px; gap: 8px; padding: 6px 10px; }
  .wm-pmxt-summary .wm-pmxt-more { margin-left: 0; }
}

/* Build .65.2: empty-state band when the wallet was clicked from a live
   trade but has no whale-size history in our records (sub-$2k bettors,
   newly-active wallets, etc.). Replaces the misleading "wallet not
   found" error from earlier builds. */
.wm-no-records {
  margin-bottom: 14px;
  padding: 12px 14px;
  background: color-mix(in srgb, var(--kalshi) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--kalshi) 18%, transparent);
  border-radius: var(--r-card);
  color: var(--text);
  font-size: 13px;
  line-height: 1.45;
  cursor: help;
}
.wm-no-records .wm-no-rec-icon {
  font-size: 14px;
  margin-right: 6px;
}
.wm-no-records .wm-no-rec-sub {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: 11px;
}

/* Build .48 / v0.2 — activity badges next to the wallet name.
   🌊 splash    → ≥ 1 single USD bet ≥ $3,000
   🎆 firework  → > 12 trades across all venues */
.wm-badges {
  display: inline-flex;
  gap: 6px;
  margin-left: 10px;
  vertical-align: 1px;
}
.wm-badge {
  display: inline-block;
  font-size: 18px;
  line-height: 1;
  cursor: help;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--kalshi) 45%, transparent));
}
.wm-badge-splash   { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--kalshi) 55%, transparent)); }
.wm-badge-firework { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--jackpot) 55%, transparent)); }

/* Build .48 — never-blank event cell in the All-bets table. */
.wm-evt-fallback {
  font-family: monospace;
  font-size: 11px;
  color: var(--muted);
  background: var(--panel-2);
  padding: 1px 5px;
  border-radius: var(--r-chip);
  cursor: help;
}
.wm-stats {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 14px;
}
.wm-stat {
  background: var(--panel-2); border-radius: var(--r-card); padding: 10px; text-align: center;
}
.wm-stat-num { font-family: monospace; font-size: 18px; font-weight: 800; color: var(--accent); }
.wm-stat-num.tr-good { color: var(--success); }
.wm-stat-num.tr-bad { color: var(--danger); }
.wm-stat-lbl { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }
/* Build v0.35 20260523.175 (2026-05-23): per-row status icons that
   used to live inside the .t20-title anchor (news, flame, closed-x)
   are now hoisted to be siblings of the row — placed BEFORE the
   evt-group-pill multi-marketplace indicator.  This class normalises
   their vertical alignment + slight right-margin so they don't
   collide with whatever follows. */
.t20-row-icon {
  display: inline-block;
  vertical-align: middle;
  margin-right: 2px;
  line-height: 1;
  flex-shrink: 0;
}

/* Build v0.35 20260523.173: live-stats placeholder visual while
   loadWalletHistory fetches.  The dashes pulse to signal it's loading
   (vs the build-126 dead-dashes that looked broken). */
.wm-stats-pending .wm-stat-num {
  color: var(--muted);
  animation: wm-pending-pulse 1.4s ease-in-out infinite;
}
@keyframes wm-pending-pulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 0.9; }
}
.wm-stat-plats {
  /* When the "platforms" stat shows a list like "POLY KALSHI MANIFOLD"
     we need a smaller font so it doesn't overflow the box. */
  font-size: 11px;
  letter-spacing: 0.03em;
  word-spacing: 4px;
  line-height: 1.25;
}
.wm-stats-source-note {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
  margin: -4px 0 14px 0;
  text-align: center;
}
.wm-plats { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 14px; font-size: 11px; }
.wm-plat { background: var(--panel-2); padding: 4px 8px; border-radius: var(--r-chip); }

/* ── Build v0.4 20260530.283: activity-first wallet card ──────────────
   Replaces the 5 resolved-P&L hero boxes (Win rate / ROI / Net P&L /
   Staked / Resolved bets — empty for most wallets) with always-populated
   activity metrics, a prominent open-positions row, and a resolved
   track-record row that shows only when the data exists.  All colors via
   CSS vars per the graphical tenet. */
/* Sparkline tile (avg bet/event over time). The tile sets `color` so the
   inline SVG stroke="currentColor" picks up the accent — no hardcoded hex. */
.wm-stat-spark { color: var(--accent); display: flex; flex-direction: column; justify-content: center; }
.wm-spark-wrap { width: 100%; height: 30px; display: flex; align-items: center; justify-content: center; }
.wm-spark-svg { width: 100%; height: 100%; overflow: visible; }
.wm-spark-empty { font-family: monospace; font-size: 18px; font-weight: 800; color: var(--muted); }

/* Prominent open-positions row — same visual weight as the boxes, directly
   under them.  Shared inner classes (.wm-openpos-*) styled here are reused
   by the full-page .wallet-openpos-row. */
.wm-openpos-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--r-card);
  padding: 12px 14px; margin-bottom: 14px; font-size: 13px;
}
.wm-openpos-label { font-weight: 700; color: var(--text); }
.wm-openpos-stat { color: var(--muted); }
.wm-openpos-stat strong { color: var(--accent); font-family: monospace; font-size: 15px; }
.wm-openpos-stat .tr-good { color: var(--success); font-family: monospace; font-weight: 700; }
.wm-openpos-stat .tr-bad { color: var(--danger); font-family: monospace; font-weight: 700; }
.wm-openpos-more { margin-left: auto; color: var(--accent); text-decoration: none; font-size: 12px; }
.wm-openpos-more:hover { text-decoration: underline; }
.wm-openpos-plats { display: inline-flex; flex-wrap: wrap; gap: 8px; }
.wm-openpos-plats .wm-plat { font-size: 11px; }

/* Secondary resolved track-record row — only renders when the wallet has
   resolved P&L (most don't). Lighter weight than the open-positions row. */
.wm-track-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 14px; font-size: 12px; }
.wm-track-lbl { color: var(--muted); font-weight: 600; }
.wm-track-chip { background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-chip); padding: 3px 8px; font-family: monospace; color: var(--text); }
.wm-track-chip.tr-good { color: var(--success); }
.wm-track-chip.tr-bad { color: var(--danger); }
.wm-trades { width: 100%; font-size: 11px; }
.wm-trades th, .wm-trades td {
  padding: 5px 8px; border-bottom: 1px solid var(--border);
  text-align: left; vertical-align: top;
}
.wm-trades th {
  background: var(--panel-2); color: var(--muted); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.wm-trades .wm-ts, .wm-trades .wm-odds, .wm-trades .wm-amt { font-family: monospace; white-space: nowrap; }
.wm-trades .wm-amt { font-weight: 700; color: var(--whale); }
.wm-trades .wm-event a { color: var(--text); }
.wm-trades .wm-event a:hover { color: var(--accent); }
.wm-trades .wm-status { white-space: nowrap; font-family: monospace; font-size: 10px; }
.trade-won  { color: var(--success); font-weight: 700; }
/* win-amounts 2026-08-12 (operator): an ESTIMATED win amount, visually distinct
   from a confirmed one so the two are never read as the same class of number.
   Muted + italic; colours from existing vars only (graphical tenet). */
.trade-won-est { color: var(--muted); font-style: italic; font-weight: 500; }
.trade-lost { color: var(--danger);  font-weight: 700; }
.trade-open { color: var(--muted); font-style: italic; }
@media (max-width: 700px) {
  .wm-stats { grid-template-columns: repeat(2, 1fr); }
}

/* Build .43: wallet full-history block */
.wm-history-wrap { margin-top: 18px; }
.wm-history-sub {
  color: var(--muted); font-weight: normal; font-size: 11px;
  text-transform: none; letter-spacing: 0; margin-left: 6px;
}
.wm-history-slot { min-height: 40px; }
.wm-history-loading, .wm-history-err {
  padding: 12px; text-align: center; color: var(--muted);
  font-size: 12px; font-style: italic;
}
.wm-history-err { color: var(--danger); font-style: normal; }
.wm-history-meta {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  font-size: 10px; margin-bottom: 8px; color: var(--muted);
}
.wm-history-count {
  font-family: monospace; padding: 3px 8px; background: var(--panel-2);
  border-radius: var(--r-chip); font-weight: 700;
}
.wm-hp-chip {
  font-family: monospace; padding: 3px 6px; border-radius: var(--r-chip);
  font-size: 10px;
}
.wm-history-cached {
  padding: 2px 6px; border-radius: var(--r-chip); background: var(--panel-2);
  font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em;
}
.wm-load-full-wrap { margin-top: 10px; text-align: center; }
.wm-load-full {
  background: var(--accent); color: var(--bg); border: none;
  padding: 8px 16px; border-radius: var(--r-chip); font-weight: 700;
  cursor: pointer; font-size: 12px;
}
.wm-load-full:hover { filter: brightness(1.1); }
.wm-history-note { color: var(--muted); font-size: 10px; font-style: italic; }
.wm-history-table { margin-top: 0; }

/* P3 2026-06-12: anomaly link-strip + modal */
/* 2026-06-14: red-tinted bg behind the LATEST MARKET ANOMALIES strip
   (operator request — flag the alarm surface more loudly). */
.anomaly-link-strip {
  margin: 6px 20px 2px;
  padding: 6px 12px;
  text-align: center;
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  border-radius: var(--r-card);
}
.anomaly-link-strip a { color: var(--text); font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-decoration: none; }
.anomaly-link-strip a:hover { color: var(--danger); }
.anomaly-link-strip .anomaly-count { color: var(--danger); }
.anomaly-link-strip .anomaly-arrow { color: var(--danger); }
.anomaly-modal .anomaly-modal-list { max-height: 60vh; overflow-y: auto; }   /* modals MAY scroll */

/* ─── Cross-venue event group modal ─── */
.event-group-modal { max-width: 760px; }
.eg-head { margin-bottom: 14px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.eg-tag {
  display: inline-block; font-size: 10px; font-weight: 800;
  padding: 2px 8px; border-radius: var(--r-chip); color: var(--bg);
  letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 6px;
}
.eg-similarity { font-size: 11px; color: var(--muted); font-family: monospace; }
/* fairprice-cv 2026-07-12 (operator design B): the LIVE Fair Price strip in
   the cross-venue modal — the de-vigged sibling of .eg-vwap directly above
   it (ET&-only; rendered iff /api/etand/fairprice returned data). */
.eg-fair {
  display: flex; align-items: flex-start; gap: 12px;
  margin: 12px 0; padding: 12px 14px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.eg-fair-icon { font-size: 18px; line-height: 1; }
.eg-fair-body { flex: 1 1 0; min-width: 0; }
.eg-fair-headline { font-size: 13px; color: var(--text); }
.eg-fair-val { font-size: 18px; color: var(--accent); font-variant-numeric: tabular-nums; }
.eg-fair-tag {
  font-size: 9px; font-weight: 700; letter-spacing: 0.05em;
  color: var(--accent); border: 1px solid var(--accent);
  border-radius: var(--r-chip); padding: 0 4px; margin-left: 6px;
  vertical-align: 2px; white-space: nowrap;
}
.eg-fair-live .eg-fair-tag { animation: cv-fair-pulse 2.4s ease-in-out infinite; }
.eg-fair-sub {
  font-size: 11px; color: var(--muted); margin-top: 4px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.eg-fair-v {
  font-family: monospace; font-variant-numeric: tabular-nums;
  border: 1px solid var(--border); border-radius: var(--r-chip);
  padding: 0 4px; white-space: nowrap;
}
.eg-fair-v-live { border-color: var(--accent); color: var(--accent); }
.eg-table { width: 100%; font-size: 12px; }
.eg-table th, .eg-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); text-align: left; }
.eg-table th { background: var(--panel-2); color: var(--muted); font-size: 10px; text-transform: uppercase; }
.eg-row .eg-title a { color: var(--text); font-weight: 600; }
.eg-row .eg-title a:hover { color: var(--accent); }
.eg-row .eg-vol { font-family: monospace; white-space: nowrap; }
.eg-empty { color: var(--muted); font-style: italic; font-size: 11px; }
.eg-top { font-size: 11px; }

/* ── Arb modal top-half UX refresh (build v0.4 20260526.240) ─────────────
   Operator UX request: the modal's top-half (Spread line, VWAP row, and
   the 5-chip metric strip) was reading as a stack of tightly-packed
   tiny bars sitting under a hard horizontal divider.  Rework: drop the
   divider, kill the per-chip borders/backgrounds, promote font sizes
   to confident "lead summary" prominence, and lay the metric chips out
   as an even auto-fit grid spanning the modal's top-half real estate.

   All rules scoped to `.event-group-modal` so the homepage arb-card
   styling (where the same chip classes appear at compact size) stays
   untouched. */

/* Drop the eg-head bottom border that was acting as a horizontal bar
   between the top-half metric display and the per-venue table. */
.event-group-modal .eg-head {
  border-bottom: none;
  padding-bottom: 16px;
  margin-bottom: 18px;
}

/* "Spread: 1971 bps (19.71%) — gross of fees..." was tiny 11px mono
   muted; promote to lead-paragraph size with bps still mono-weighted
   for scannability. */
.event-group-modal .eg-similarity {
  font-size: 15px;
  font-family: inherit;
  color: var(--text);
  line-height: 1.45;
  margin: 10px 0 4px;
}
.event-group-modal .eg-similarity strong {
  font-family: monospace;
  font-size: 18px;
  color: var(--accent);
}
.event-group-modal .eg-similarity em {
  font-style: italic;
  color: var(--muted);
  font-size: 13px;
}

/* VWAP row in the modal — strip the boxed background+border so it
   doesn't read as another bar; promote the 47.6% % to hero size. */
.event-group-modal .arb-vwap.arb-vwap-modal {
  background: transparent;
  border: none;
  padding: 12px 0;
  margin: 0;
  font-size: 16px;
  gap: 12px;
  flex-wrap: wrap;
}
.event-group-modal .arb-vwap-modal .arb-vwap-icon {
  font-size: 22px;
  width: 24px;
}
.event-group-modal .arb-vwap-modal .arb-vwap-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.event-group-modal .arb-vwap-modal .arb-vwap-pct {
  font-size: 22px;
  font-weight: 800;
  color: var(--accent);
}
.event-group-modal .arb-vwap-modal .arb-vwap-meta {
  font-size: 13px;
  color: var(--muted);
  font-family: inherit;
}

/* Metric strip in the modal (Fees / Net spread / Vig / Persists / Max
   size).  Was a cramped row of bordered chips; convert to an evenly
   spaced auto-fit grid where each cell stacks LABEL (small caps) on
   top of VALUE (large bold mono), no individual chip border. */
.event-group-modal .arb-meta.arb-meta-modal {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 18px 24px;
  margin: 18px 0 6px;
  padding: 14px 0 4px;
  border-top: none;
}
.event-group-modal .arb-meta-modal .arb-meta-chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: transparent;
  border: none;
  padding: 0;
  border-radius: 0;
  font-family: inherit;
  font-size: 18px;
  gap: 4px;
}
.event-group-modal .arb-meta-modal .arb-meta-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.event-group-modal .arb-meta-modal .arb-meta-val {
  font-size: 20px;
  font-weight: 800;
  font-family: monospace;
  color: var(--text);
}
/* Restore color affordances on per-chip variants — without backgrounds
   we lean on the value color alone. */
.event-group-modal .arb-meta-modal .arb-meta-net-strong .arb-meta-val {
  color: var(--success);
}
.event-group-modal .arb-meta-modal .arb-meta-vig-arb .arb-meta-val {
  color: var(--success);
}
.event-group-modal .arb-meta-modal .arb-meta-net-zero .arb-meta-val {
  color: var(--muted);
}

/* Cross-venue group color palette (used as background tint on grouped event titles) */
:root {
  --evt-grp-0: #fbbf24;
  --evt-grp-1: #60a5fa;
  --evt-grp-2: #f472b6;
  --evt-grp-3: #a78bfa;
  --evt-grp-4: #4ade80;
  --evt-grp-5: #fb7185;
}
.evt-group-badge {
  display: inline-block; vertical-align: middle; margin-right: 6px;
  width: 8px; height: 8px; border-radius: 50%;
  cursor: pointer;
}
.evt-group-0 .evt-group-badge { background: var(--evt-grp-0); }
.evt-group-1 .evt-group-badge { background: var(--evt-grp-1); }
.evt-group-2 .evt-group-badge { background: var(--evt-grp-2); }
.evt-group-3 .evt-group-badge { background: var(--evt-grp-3); }
.evt-group-4 .evt-group-badge { background: var(--evt-grp-4); }
.evt-group-5 .evt-group-badge { background: var(--evt-grp-5); }

/* Cross-venue pill: explicit "↔ N" badge that's hard to miss. */
.evt-group-pill {
  display: inline-flex; align-items: center; vertical-align: middle;
  margin-right: 6px; padding: 1px 6px; border-radius: var(--r-card);
  font-family: monospace; font-size: 10px; font-weight: 800;
  color: var(--bg); cursor: pointer; border: 1px solid transparent;
  white-space: nowrap; line-height: 1.4;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
}
.evt-group-pill:hover { transform: scale(1.05); }
.evt-group-pill.evt-group-0 { background: var(--evt-grp-0); }
.evt-group-pill.evt-group-1 { background: var(--evt-grp-1); }
.evt-group-pill.evt-group-2 { background: var(--evt-grp-2); }
.evt-group-pill.evt-group-3 { background: var(--evt-grp-3); }
.evt-group-pill.evt-group-4 { background: var(--evt-grp-4); }
.evt-group-pill.evt-group-5 { background: var(--evt-grp-5); }
.evt-group-link { cursor: pointer; }
.evt-group-link:hover { text-decoration: underline; }
/* Subtle background tint on grouped rows.
   Build v0.35 20260523.181 (2026-05-23): removed the top-10 colored
   inset-shadow "pipes" per user request — the .evt-group-pill chip
   already conveys group membership; the 3px row marker was visually
   redundant with the pill and read as clutter.  Top-20 still gets
   the bar because top-20 rows are denser + the pill is smaller, so
   the row-level marker remains useful at-a-glance for scanning. */
.t20-row.evt-group-0 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-0); }
.t20-row.evt-group-1 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-1); }
.t20-row.evt-group-2 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-2); }
.t20-row.evt-group-3 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-3); }
.t20-row.evt-group-4 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-4); }
.t20-row.evt-group-5 .t20-title { box-shadow: inset 3px 0 0 var(--evt-grp-5); }

/* ─── Modal ─── */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(5, 8, 20, 0.85);
  display: none; align-items: flex-start; justify-content: center;
  padding: 40px 20px 20px; z-index: 100; overflow-y: auto;
}
.modal-overlay.open { display: flex; }
/* Build .318: the tag/topic card opens FROM WITHIN an open event modal (both are
   .modal-overlay at z-index 100), so it must stack ABOVE the event modal — give
   it a higher z-index so the tag card always pops up in FRONT, not behind. */
/* topic-front .683 (operator: hashtag cards "obscured by both the frozen top
   pane and tickers and the pop up card already open — open it in FRONT"):
   200 sat UNDER the frozen band (z 418-420) — the .651 bug class. Promoted
   tier: above the band AND above whatever card it opened from. */
#topic-overlay { z-index: 1010; }
.modal {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-card);
  width: 100%; max-width: 820px; padding: 24px 28px 20px; position: relative;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.modal-close {
  position: absolute; top: 10px; right: 14px; background: none; border: none;
  color: var(--muted); font-size: 26px; cursor: pointer; line-height: 1;
}
.modal-close:hover { color: var(--text); }
/* modal-back 2026-08-08 (operator): the "previous card" control. Mirrors
   .modal-close but sits in the opposite corner, and only renders when a
   card was opened FROM another card (the JS toggles [hidden]). */
.modal-back { position: absolute; top: 10px; left: 14px; background: none;
  border: 1px solid var(--border); border-radius: var(--r-chip, 6px);
  color: var(--muted); font-size: 12px; font-weight: 600; line-height: 1;
  padding: 4px 9px; cursor: pointer; z-index: 2; }
.modal-back:hover, .modal-back:focus-visible { color: var(--accent); border-color: var(--accent); }
.modal-back[hidden] { display: none; }
.modal-platform { color: var(--accent); font-size: 11px; text-transform: uppercase; letter-spacing: 0.15em; margin-bottom: 6px; }
.modal h3 { font-size: 18px; color: var(--text); margin: 0 0 8px; text-transform: none; letter-spacing: normal; }
.modal-meta { color: var(--muted); font-size: 12px; margin-bottom: 16px; }
.modal-meta strong { color: var(--text); font-family: monospace; }
/* Build .57 (item #10) — "—" placeholder when bettor count isn't exposed */
.modal-meta .bettors-na {
  color: var(--muted);
  font-family: monospace;
  cursor: help;
}
/* Build .60 — estimated per-outcome volume (event total × outcome
   price) for PMXT / MetaForecast events where per-outcome volume
   isn't exposed by the venue. ~ prefix + muted color signal estimate. */
.opt-vol-est {
  color: var(--muted);
  font-style: italic;
  cursor: help;
}
.opt-vol-na,
.opt-pct-na {
  color: var(--muted);
  cursor: help;
}

/* Build .58 (NEW item) — SETTLED banner for resolved events. Sits
   between modal-head and the news block, prominent so visitors don't
   miss that this event is no longer live. Gold/jackpot palette to
   match the existing jackpot ticker. */
.evt-settled {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  margin: 0 0 14px 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--jackpot) 18%, transparent) 0%, color-mix(in srgb, var(--jackpot) 6%, transparent) 100%);
  border-left: 4px solid var(--jackpot);
  border-radius: var(--r-chip);
  font-size: 12px;
  color: var(--text);
}
.evt-settled-badge {
  display: inline-block;
  padding: 2px 8px;
  font-family: monospace;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  background: var(--jackpot);
  color: var(--bg);
  border-radius: var(--r-chip);
  flex: 0 0 auto;
}
.evt-settled-body { flex: 1 1 auto; }
.evt-settled-body strong { color: var(--jackpot); font-weight: 700; }
.evt-settled-outcome {
  font-family: monospace;
  font-size: 10px;
  color: var(--muted);
  background: rgba(255,255,255,0.05);
  padding: 1px 5px;
  border-radius: var(--r-chip);
  margin-left: 2px;
}
/* 2026-06-13 (#5): closed-event JACKPOT-style hero block (replaces the small SETTLED banner) */
.evt-settled-hero {
  margin: 0 0 16px 0; padding: 14px 18px; border-radius: var(--r-card);
  border: 1px solid color-mix(in srgb, var(--jackpot) 40%, transparent);
  background: linear-gradient(135deg,
              color-mix(in srgb, var(--jackpot) 18%, transparent) 0%,
              color-mix(in srgb, var(--jackpot) 6%, transparent) 100%);
  color: var(--text);
}
.evt-jp-headline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.evt-jp-badge {
  display: inline-block; padding: 3px 10px; border-radius: var(--r-chip);
  background: var(--jackpot); color: var(--chip-ink, var(--bg));
  font-family: monospace; font-size: 11px; font-weight: 800; letter-spacing: 0.08em;
}
.evt-jp-date { font-size: 11px; color: var(--muted); }
.evt-jp-won { font-size: 14px; margin: 4px 0 10px; }
.evt-jp-winner-label { color: var(--jackpot); font-size: 18px; font-weight: 800; }
.evt-jp-winner-outcome { color: var(--muted); font-family: monospace; font-size: 11px; margin-left: 4px; }
.evt-jp-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.evt-jp-payout { display: inline-flex; align-items: baseline; gap: 6px; }
.evt-jp-payout-amt { color: var(--success); font-weight: 800; font-size: 16px; font-variant-numeric: tabular-nums; }
.evt-jp-payout-lbl { color: var(--muted); font-size: 11px; }
.evt-jp-winners-count { color: var(--accent); font-size: 11px; font-weight: 700; }
/* Winning row highlight in the frozen final betting board */
.opts-table tr.opt-row-winner {
  background: color-mix(in srgb, var(--jackpot) 14%, transparent);
  border-left: 3px solid var(--jackpot);
}
.opts-table tr.opt-row-winner td.opt-label { font-weight: 700; }
.opt-winner-mark { margin-right: 5px; }
.evt-frozen-note { color: var(--jackpot); font-style: italic; }
.modal-loading, .modal-error { padding: 30px; text-align: center; color: var(--muted); }
.modal-error { color: var(--danger); }

/* Build .350 (2026-06-07): "Ticket details" modal block — surfaces extra
 * Polymarket + Kalshi metadata that normalize_* previously dropped. Tier A
 * chips inline + Tier B in a collapsible <details>. Colors strictly via CSS
 * vars per the graphical tenet (no raw hex). */
.ticket-details {
  margin: 12px 0 14px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  border-left: 3px solid var(--accent);
}
.td-tier-a {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-bottom: 0;
}
.td-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--r-card);
  font-size: 11px;
  font-weight: 500;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  white-space: nowrap;
  line-height: 1.5;
}
.td-chip a {
  color: inherit;
  text-decoration: none;
}
.td-chip a:hover { text-decoration: underline; }
.td-chip-comments    { border-color: var(--whale); color: var(--whale); }
.td-chip-competitive { border-color: var(--accent); color: var(--accent); }
.td-chip-vol         { border-color: var(--accent); color: var(--accent); }
.td-chip-res         { border-color: var(--accent); color: var(--accent); }
.td-chip-suspended   { border-color: var(--danger); color: var(--danger); }
.td-chip-exp         { border-color: var(--jackpot); color: var(--jackpot); }
.td-chip-series      { border-color: var(--muted); }
.td-chip-broker      { border-color: var(--whale); color: var(--whale); }
.td-rules {
  display: block;
  width: 100%;
  margin: 4px 0;
  padding: 6px 10px;
  font-size: 12px;
  line-height: 1.45;
  background: var(--panel);
  border-radius: var(--r-chip);
  border-left: 2px solid var(--jackpot);
  color: var(--text);
}
.td-rules strong { color: var(--jackpot); margin-right: 4px; }
.td-rules-icon { margin-right: 4px; }
.td-rules-body { color: var(--text); }
.td-rules-details { width: 100%; margin: 4px 0; }
.td-rules-details summary {
  list-style: none;
  cursor: pointer;
  margin: 0;
  padding: 6px 10px;
  font-size: 12px;
  line-height: 1.45;
  background: var(--panel);
  border-radius: var(--r-chip);
  border-left: 2px solid var(--jackpot);
  color: var(--text);
}
.td-rules-details summary::-webkit-details-marker { display: none; }
.td-rules-details[open] summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.td-rules-full {
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1.5;
  background: var(--panel);
  border-left: 2px solid var(--jackpot);
  border-top: 1px solid var(--border);
  border-radius: 0 0 4px 4px;
  color: var(--text);
  white-space: pre-wrap;
}
.td-context {
  margin: 8px 0 4px;
  padding: 6px 10px;
  font-size: 12px;
  line-height: 1.5;
  font-style: italic;
  color: var(--muted);
  border-left: 2px solid var(--whale);
  background: var(--panel);
  border-radius: var(--r-chip);
}
.td-tier-b {
  margin-top: 10px;
  font-size: 12px;
}
.td-tier-b > summary {
  list-style: none;
  cursor: pointer;
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 4px 0;
  user-select: none;
}
.td-tier-b > summary::-webkit-details-marker { display: none; }
.td-tier-b-icon {
  display: inline-block;
  transition: transform 0.2s ease;
  margin-right: 6px;
}
.td-tier-b[open] .td-tier-b-icon { transform: rotate(90deg); }
.td-tier-b-count {
  color: var(--muted);
  font-weight: 400;
  font-size: 10px;
  text-transform: none;
  letter-spacing: 0;
  margin-left: 4px;
}
.td-defs {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 4px 12px;
  margin: 8px 0 0;
  padding: 8px 10px 10px;
  background: var(--panel);
  border-top: 1px solid var(--border);
  border-radius: 0 0 4px 4px;
}
.td-defs dt {
  color: var(--muted);
  font-size: 11px;
  text-align: right;
  align-self: center;
}
.td-defs dd {
  color: var(--text);
  font-size: 11.5px;
  margin: 0;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.td-defs dd code {
  background: var(--panel);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: var(--r-chip);
  font-size: 10.5px;
  color: var(--accent);
}
.td-defs dd a {
  color: var(--accent);
  text-decoration: none;
}
.td-defs dd a:hover { text-decoration: underline; }
.td-size {
  color: var(--muted);
  font-size: 10px;
  font-style: italic;
  margin-left: 4px;
}
@media (max-width: 600px) {
  .td-defs { grid-template-columns: 1fr; }
  .td-defs dt { text-align: left; padding-top: 4px; }
}

/* Build .247: shimmer skeleton loader for the wallet modal so the card
   frame appears instantly while the two network fetches run in parallel. */
@keyframes wm-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}
.wm-skeleton {
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 14px;
}
.wm-skel-bar {
  border-radius: var(--r-chip);
  background: linear-gradient(
    90deg,
    var(--panel-2) 25%,
    rgba(255,255,255,0.055) 50%,
    var(--panel-2) 75%
  );
  background-size: 200% 100%;
  animation: wm-shimmer 1.5s ease-in-out infinite;
}
.wm-skel-head { display: flex; flex-direction: column; gap: 7px; }
.wm-skel-name { height: 20px; width: 38%; }
.wm-skel-addr { height: 12px; width: 68%; }
.wm-skel-stats-row {
  display: flex; gap: 8px;
}
.wm-skel-stat-box {
  flex: 1; height: 52px; border-radius: var(--r-card);
  background: linear-gradient(
    90deg,
    var(--panel-2) 25%,
    rgba(255,255,255,0.055) 50%,
    var(--panel-2) 75%
  );
  background-size: 200% 100%;
  animation: wm-shimmer 1.5s ease-in-out infinite;
}
.wm-skel-hdr  { height: 13px; width: 55%; }
.wm-skel-rows { display: flex; flex-direction: column; gap: 7px; }
.wm-skel-row  { height: 26px; border-radius: var(--r-chip);
  background: linear-gradient(
    90deg,
    var(--panel-2) 25%,
    rgba(255,255,255,0.055) 50%,
    var(--panel-2) 75%
  );
  background-size: 200% 100%;
  animation: wm-shimmer 1.5s ease-in-out infinite;
}

.meta-card {
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 12px; margin-bottom: 14px;
}
/* P3 2026-06-13: "Event details" disclosure title — .meta-card is now a <details>
   hidden (closed) by default; the grid layout moved to .meta-card-inner. */
.meta-card-summary {
  cursor: pointer; font-weight: 700; font-size: 13px; color: var(--text);
  letter-spacing: 0.01em; user-select: none;
}
.meta-card-summary:hover { color: var(--accent); }
.meta-card[open] .meta-card-summary { margin-bottom: 10px; }
.meta-card-inner { display: none; }   /* hidden until the <details> is opened — gate display on [open] so author CSS doesn't override the UA "closed-details hide" */
.meta-card[open] .meta-card-inner { display: grid; grid-template-columns: auto 1fr; gap: 12px; }
.meta-card[open] .meta-card-inner:has(.meta-img) { grid-template-columns: 80px 1fr; }
.meta-img {
  width: 80px; height: 80px; max-width: 80px; max-height: 80px;
  object-fit: cover; border-radius: var(--r-chip); flex-shrink: 0;
}
.meta-fields { display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px 16px; font-size: 11px; }
.meta-fields > div { display: flex; gap: 6px; align-items: baseline; }
.mf-k { color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; font-size: 10px; }
.mf-v { color: var(--text); font-family: monospace; }
.mf-tags { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.tag-chip {
  display: inline-block; background: var(--panel); color: var(--muted);
  padding: 2px 6px; border-radius: var(--r-chip); font-size: 10px; border: 1px solid var(--border);
}
/* Build .306: clickable tag chips in the event-modal head — each opens a
   topic-style card of sibling events sharing that tag (window.openTag). */
.ev-tags { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; margin: 6px 0 2px; }
.tag-chip-link { cursor: pointer; transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease; }
.tag-chip-link:hover { color: var(--accent); border-color: var(--accent); background: var(--panel-2); }
.meta-desc { grid-column: 1 / -1; color: var(--muted); font-size: 12px; line-height: 1.5; max-height: 180px; overflow-y: auto; }

/* .409 (predict-on-cta 2026-06-20): prominent "Predict on PLATFORM →" CTA that
   replaces the low-emphasis inline link inside .modal-meta. Filled accent button,
   theme-var compliant (no hardcoded colors). Sits on its own line in modal-head. */
.predict-on-btn {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 8px 0 0; padding: 8px 14px;
  background: var(--accent); color: var(--bg);
  border: 1px solid var(--accent); border-radius: var(--r-chip, 3px);
  font-weight: 700; font-size: 13px; text-decoration: none;
  transition: background-color var(--m-tab, 0.15s),
              border-color var(--m-tab, 0.15s),
              color var(--m-tab, 0.15s),
              transform var(--m-tab, 0.15s);
}
.predict-on-btn:hover { background: var(--accent-deep, var(--accent)); border-color: var(--accent-deep, var(--accent)); }
.predict-on-btn:active { transform: translateY(1px); }

/* .409 (xv-modal-link 2026-06-20): outline-pill jump-link in event modals that
   closes the venue-specific modal and opens the cross-venue comparison modal
   for the same real-world event. Secondary to .predict-on-btn (the primary CTA).
   All theme-vars; works on both peach and dark themes. */
.modal-xv-link {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 6px 0 0 8px; padding: 6px 12px;
  background: transparent; color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-chip, 3px);
  font-weight: 600; font-size: 12px; cursor: pointer;
  transition: background-color var(--m-tab, 0.15s),
              border-color var(--m-tab, 0.15s),
              color var(--m-tab, 0.15s);
}
.modal-xv-link:hover, .modal-xv-link:focus { background: var(--panel-2); color: var(--accent); border-color: var(--accent); outline: none; }

/* 2026-06-19: Resolution & Rules modal section — collapsible, default closed. All theme-vars (no hardcoded colors). */
.reso-section { grid-column: 1 / -1; margin-top: 8px; border: 1px solid var(--border); border-radius: 8px; }
.reso-summary { cursor: pointer; padding: 8px 10px; font-size: 12px; font-weight: 600; color: var(--text); list-style: none; user-select: none; }
.reso-summary::-webkit-details-marker { display: none; }
.reso-summary::before { content: "\25B8\00a0"; color: var(--muted); }
.reso-section[open] > .reso-summary::before { content: "\25BE\00a0"; }
.reso-content { padding: 0 10px 10px; }
.reso-body { color: var(--muted); font-size: 12px; line-height: 1.5; max-height: 260px; overflow-y: auto; overflow-wrap: anywhere; }
.reso-sources { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.reso-k { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.reso-src { font-size: 11px; padding: 2px 7px; border-radius: 999px; border: 1px solid var(--border); color: var(--text); overflow-wrap: anywhere; }

/* 2026-06-20: Cross-venue Resolution & Rules (Part 2) — stacked collapsible
   per-venue blocks in the event-group modal. Reuses .reso-body/.reso-src/.reso-k.
   All theme-vars; single-line ellipsized previews so it never h-scrolls. */
.reso-xv { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
.reso-xv-head { font-size: 12px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.reso-xv-stack { display: flex; flex-direction: column; gap: 6px; }
.reso-venue { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; min-width: 0; }
.reso-venue-sum { cursor: pointer; padding: 7px 10px; display: flex; align-items: center; gap: 8px; list-style: none; user-select: none; min-width: 0; }
.reso-venue-sum::-webkit-details-marker { display: none; }
.reso-venue-sum::before { content: "\25B8"; color: var(--muted); flex-shrink: 0; font-size: 10px; }
.reso-venue[open] > .reso-venue-sum::before { content: "\25BE"; }
.reso-venue-snip { color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 0; }
.reso-venue-body { padding: 0 10px 10px 28px; }
.reso-venue-empty { padding: 7px 10px; display: flex; align-items: center; gap: 8px; opacity: 0.6; }
.reso-venue-empty .reso-venue-snip { font-style: italic; }

/* .409 (2026-06-20): arb-card "rules differ" warning chip (resolution-divergence
   gate, borderline tier). Amber caution, theme-vars only, single-line. */
.arb-reso-warn { display: inline-block; margin-left: 6px; font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 999px; border: 1px solid var(--jackpot); color: var(--jackpot); white-space: nowrap; vertical-align: middle; }

/* Build v0.4 (operator 2026-06-07): rich market metadata scraped from the
   venue's own page (Myriad today — Resolution Criteria / Resolution Details /
   Yes/No Criteria / Market Dates / Cancellation Conditions). Collapsible
   sections via <details>/<summary>; first section open by default. All theme
   vars → auto-themes for peach, no twin needed. */
.meta-rich { grid-column: 1 / -1; margin-top: 8px; }
.meta-rich-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.meta-rich-label { font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.meta-rich-source { font-size: 10px; color: var(--muted); opacity: 0.7; font-style: italic; }
.meta-rich-section {
  border: 1px solid var(--border); border-radius: var(--r-card);
  background: color-mix(in srgb, var(--panel) 60%, transparent);
  margin-bottom: 4px;
}
.meta-rich-section[open] { background: color-mix(in srgb, var(--panel) 95%, transparent); }
.meta-rich-title {
  cursor: pointer; user-select: none;
  padding: 6px 10px; font-size: 12px; font-weight: 700;
  color: var(--text); list-style: none; outline: none;
}
.meta-rich-title::-webkit-details-marker { display: none; }
.meta-rich-title::before {
  content: '▸'; display: inline-block; margin-right: 6px;
  font-size: 9px; color: var(--muted); transition: transform 0.15s;
}
.meta-rich-section[open] .meta-rich-title::before { transform: rotate(90deg); }
.meta-rich-title:hover { color: var(--accent); }
.meta-rich-body {
  padding: 0 10px 8px 22px;
  font-size: 12px; line-height: 1.55; color: var(--text);
  white-space: pre-line; overflow-wrap: anywhere;
  max-height: 280px; overflow-y: auto;
}
.meta-rich-body strong { color: var(--accent); font-weight: 700; }

/* Build v0.4 20260604.329 (P3): Odds-API "sharp consensus" card in the event
   modal — cross-book de-vig fair line + Polymarket-implied-vs-sharp edge on
   Polymarket sport fixtures. All colors via CSS vars + color-mix per the
   graphical tenet (teal --accent = neutral/"poly cheap", --danger = "poly
   rich"). No horizontal scroll: flex-wrap + min-width:0 on text children. */
.fairodds-card {
  margin: 10px 0; padding: 10px 12px;
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--r-card); background: var(--panel);
}
.fo-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; flex-wrap: wrap; margin-bottom: 6px;
}
.fo-title { color: var(--accent); font-weight: 700; font-size: 13px; letter-spacing: 0.02em; }
.fo-meta { color: var(--muted); font-size: 11px; }
.fo-edge {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 8px; border-radius: var(--r-card); margin-bottom: 6px; font-size: 12px; min-width: 0;
}
.fo-edge-cheap { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.fo-edge-rich  { background: color-mix(in srgb, var(--danger) 14%, transparent); }
.fo-edge-opt { font-weight: 700; color: var(--text); min-width: 0; overflow-wrap: anywhere; }
.fo-edge-nums { color: var(--muted); font-variant-numeric: tabular-nums; }
.fo-edge-mag { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.fo-edge-cheap .fo-edge-dir { color: var(--accent); font-weight: 700; }
.fo-edge-rich  .fo-edge-dir { color: var(--danger); font-weight: 700; }

/* Build v0.4: ⚡ Sharp Edge section — features the Odds-API sportsbook de-vig
   consensus as a ranked dashboard feed (Polymarket implied vs sharp). All
   color via CSS vars (graphical tenet → auto-themes for peach); reuses
   --accent (poly-cheap / BUY) + --danger (poly-rich / FADE) edge semantics
   from the modal's .fo-edge. No horizontal scroll; grid grows to fit (no
   in-card vertical scrollbar). */
.sharp-edge-section { max-width: 1200px; margin: 28px auto 0; padding: 0 16px; }
.sharp-edge-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.sharp-edge-title { font-size: 20px; font-weight: 800; color: var(--text); margin: 0; letter-spacing: 0.2px; }
.sharp-edge-credit { font-size: 11px; color: var(--muted); }
.sharp-edge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(290px, 100%), 1fr)); gap: 10px; }
.sharp-edge-card {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  padding: 10px 12px; border-radius: var(--r-card); cursor: pointer;
  background: var(--panel); border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.sharp-edge-card:hover { background: var(--panel-2); }
.sharp-edge-card.se-cheap { border-left-color: var(--accent); }
.sharp-edge-card.se-rich  { border-left-color: var(--danger); }
.sharp-edge-card.se-cheap:hover { border-color: var(--accent); }
.sharp-edge-card.se-rich:hover  { border-color: var(--danger); }
.se-lead { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; min-width: 54px; }
.se-edge-mag { font-size: 19px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.se-dir { font-size: 9px; font-weight: 800; letter-spacing: 0.6px; margin-top: 1px; }
.se-cheap .se-edge-mag, .se-cheap .se-dir { color: var(--accent); }
.se-rich  .se-edge-mag, .se-rich  .se-dir { color: var(--danger); }
.se-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.se-option { font-weight: 700; color: var(--text); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.se-matchup { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.se-meta { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: 10px; color: var(--muted); margin-top: 1px; }
.se-prices { font-variant-numeric: tabular-nums; }
.se-fair { color: var(--text); font-weight: 600; }
.se-arrow { color: var(--muted); }
.se-chip { font-variant-numeric: tabular-nums; white-space: nowrap; }
.se-sharpe { color: var(--text); }
@media (max-width: 560px) { .sharp-edge-grid { grid-template-columns: 1fr; } }
.fo-sides { display: flex; gap: 10px; flex-wrap: wrap; }
.fo-side {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 2px 8px; border: 1px solid var(--border); border-radius: var(--r-pill);
}
.fo-side-nm { color: var(--text); font-size: 12px; overflow-wrap: anywhere; }
.fo-side-p { color: var(--accent); font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
.fo-foot { color: var(--muted); font-size: 10px; margin-top: 6px; text-align: right; }
/* Phase 4 (structure-aware contract-type): payoff-structure chip in the modal
   head. touch = amber (the decision-relevant exception, prominent); terminal =
   muted (the default). CSS vars only — graphical tenet. */
.struct-chip.phq-dens-high { color: var(--success); border-color: var(--success); }
.struct-chip.phq-dens-med  { color: var(--jackpot); border-color: var(--jackpot); }
.struct-chip {
  display: inline-block; margin-left: 8px; padding: 1px 7px;
  border-radius: var(--r-pill); border: 1px solid var(--border);
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  vertical-align: middle; cursor: help;
}
.struct-terminal { color: var(--muted); border-color: var(--border); background: transparent; }
/* Stage-2b: EOD-cadence chip in the event modal head (e.g. Rothera). Muted —
   it's an honesty marker (daily, not live), same palette as the terminal chip. */
.struct-eod { color: var(--muted); border-color: var(--border); background: transparent; }
/* pariflow-fill 2026-08-04: Pariflow re-serve events whose per-option stats are
   relayed from the underlying Polymarket market (theme var, no literal). */
.struct-relay { color: var(--accent); border-color: var(--accent); background: transparent; }
.struct-touch {
  color: var(--jackpot); border-color: var(--jackpot);
  background: color-mix(in srgb, var(--jackpot) 13%, transparent);
}
/* Phase 6 (devig caveat): path-dependence warning on the sharp-consensus card
   for touch contracts — a no-vig fair price is indicative only when the barrier
   pays on ANY crossing. */
.fo-caveat {
  color: var(--jackpot); font-size: 10px; margin-top: 6px;
  padding: 4px 6px; border-radius: 6px; border: 1px solid var(--jackpot);
  background: color-mix(in srgb, var(--jackpot) 10%, transparent);
  cursor: help; overflow-wrap: anywhere;
}
/* Build 2026-06-13: Polymarket per-event Top Holders card — reuses the
   .fairodds-card frame; compact ranked rows. CSS vars only; ellipsis on the
   name so long pseudonyms never force a horizontal scrollbar. */
.topholders-card .th-list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.th-row { display: flex; align-items: center; gap: 8px; font-size: 12px; min-width: 0; }
.th-rank { color: var(--muted); font-variant-numeric: tabular-nums; flex-shrink: 0; width: 22px; }
.th-name { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent); text-decoration: none; }
.th-name:hover { text-decoration: underline; }
.th-usd { flex-shrink: 0; font-weight: 600; color: var(--whale); font-variant-numeric: tabular-nums; }
.th-sh { flex-shrink: 0; color: var(--muted); font-variant-numeric: tabular-nums; font-size: 11px; }

/* Build v0.4 20260530.285: canonical-buys toggle on the event-modal bets
   tables.  The button swaps each row's Side+Odds textContent between native
   ("BUY Landaluce 0.37") and the trade_unifier canonical fold ("AGAINST
   Cerundolo 0.63").  All colors via CSS vars per the graphical tenet. */
.bets-canon-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--panel-2); color: var(--accent);
  border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 4px 10px; font-size: 11px; cursor: pointer; margin: 2px 0 8px 0;
}
.bets-canon-toggle:hover { border-color: var(--accent); }
.bets-wrap.bets-canonical .bets-canon-toggle {
  background: var(--accent); color: var(--panel); border-color: var(--accent);
}
.opts-table, .trades-table, .winners-table { width: 100%; margin-bottom: 10px; }
/* 2026-06-15 (operator): "show more" expanders on the event-modal options + bets
   tables. Rows beyond the top 10 (bets) / the eliminated options carry
   .pc-row-extra — hidden until the table gets .pc-show-all (toggled by the
   .pc-more-btn that follows the table). Modals MAY scroll, so an expanded list
   is fine. */
.opts-table:not(.pc-show-all) .pc-row-extra,
.trades-table:not(.pc-show-all) .pc-row-extra { display: none; }
.pc-more-btn {
  display: inline-block; margin: 0 0 12px;
  padding: 3px 11px; font-size: 11px; font-weight: 700;
  color: var(--accent); background: transparent;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  cursor: pointer; transition: color var(--m-tab), border-color var(--m-tab);
}
.pc-more-btn:hover { color: var(--text); border-color: var(--accent); }
.opts-table th, .trades-table th, .winners-table th {
  background: var(--panel-2); color: var(--muted); font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 8px 10px; text-align: left;
}
.opts-table td, .trades-table td, .winners-table td {
  padding: 8px 10px; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: top;
}
.opts-table .rank { width: 28px; color: var(--muted); font-family: monospace; }
.opts-table .opt-label { font-weight: 600; word-break: break-word; overflow-wrap: anywhere; }
.opt-sidecar-note { color: var(--muted); font-size: 11px; margin: -4px 0 10px; }   /* option-sidecar: "Showing N of M · collected X ago" */
/* options C+E Phase 4 (OPTION_COLUMNS): only tables the payload marks carry
   .opts-cols, so OPTION_COLUMNS=0 renders exactly as before. The label wraps
   inside a bounded column; each figure's basis rides on its own line. */
.opts-table.opts-cols .opt-label { min-width: 9em; max-width: 26em; }
.opts-table.opts-cols .opt-basis { display: block; font-size: 10px; color: var(--muted); }
/* options C+E Phase 5 (OPTION_TABS): the bet-type tabs. A strip exists only
   over a table whose rows the server stamped (data-bucket), so OPTION_TABS=0
   renders exactly as before; a tab FILTERS the one table. Selected = filled,
   never colour alone; the focus ring is its own. */
.opt-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.opt-tab {
  padding: 3px 11px; font-size: 11px; font-weight: 700;
  color: var(--accent); background: transparent;
  border: 1px solid var(--border); border-radius: var(--r-pill); cursor: pointer;
}
.opt-tab:hover { color: var(--text); border-color: var(--accent); }
.opt-tab[aria-selected="true"] { background: var(--accent); color: var(--panel); border-color: var(--accent); }
.opt-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.opt-tab-n { font-weight: 400; }
.opts-table[data-opt-tab="straight"] > tbody > tr:not([data-bucket="straight"]),
.opts-table[data-opt-tab="spread"] > tbody > tr:not([data-bucket="spread"]),
.opts-table[data-opt-tab="total"] > tbody > tr:not([data-bucket="total"]),
.opts-table[data-opt-tab="props"] > tbody > tr:not([data-bucket="props"]) { display: none; }
@media (max-width: 768px) { .opt-tab { min-height: 36px; } }   /* a tab is a tap target */
/* rothera-ohl 2026-07-12: EOD day-range chip on an option row (Rothera). */
.opt-range { display: inline-block; font-size: 10px; font-family: monospace; color: var(--muted); border: 1px solid var(--border); border-radius: 4px; padding: 0 4px; margin-left: 4px; vertical-align: 1px; white-space: nowrap; }
.opts-table .opt-vol, .opts-table .opt-odds { font-family: monospace; white-space: nowrap; }
.opts-table .opt-odds { color: var(--jackpot); font-weight: 600; }
.opts-table .opt-pct { width: 200px; }
.bar-wrap { display: flex; align-items: center; gap: 8px; }
.bar-wrap .bar { height: 10px; background: var(--accent); border-radius: var(--r-chip); min-width: 2px; max-width: 140px; }
.bar-wrap span { font-family: monospace; font-size: 12px; color: var(--text); }
.trades-table .trade-side { font-size: 11px; }
.trades-table .trade-user { font-family: monospace; font-size: 11px; color: var(--muted); }
.trades-table .trade-ts { font-family: monospace; font-size: 11px; color: var(--muted); }
/* Build .64 (item #3): Polymarket trades table now shows which sub-market
   each bet was on for multi-market events. The Bet-option column wraps at
   narrow widths but stays single-line on desktop. */
.trades-table .trade-mkt {
  font-size: 12px;
  font-weight: 500;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Build .64 (item C): biggest-winners table for settled Polymarket
   events. Replaces the bets table on resolved jackpots. */
.winners-table .win-profit {
  font-family: monospace;
  font-weight: 700;
  color: var(--success);
  white-space: nowrap;
}
.winners-table .win-mkt {
  font-size: 12px;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.winners-table .win-user {
  font-family: monospace;
  font-size: 11px;
  color: var(--text);
}
.winners-table .win-buy,
.winners-table .win-trades {
  font-family: monospace;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
}
.winners-note {
  display: inline-block;
  margin-left: 6px;
  color: var(--muted);
  cursor: help;
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

/* ─── Responsive ─── */
@media (max-width: 1200px) {
  .top10-trio { grid-template-columns: 1fr 1fr; }
  .jv-grid { grid-template-columns: 1fr; }
}
@media (max-width: 1000px) {
  .top-events { grid-template-columns: 1fr 1fr; }
  .top10-trio { grid-template-columns: 1fr; }
  .movers-merged-grid { grid-template-columns: 1fr; }   /* Build .260 */
  .whale-cards, .whale-cards-2x2 { grid-template-columns: 1fr; }
  header { flex-wrap: wrap; }
  .search-box { order: 10; flex-basis: 100%; max-width: none; margin-left: 0; }
  .globe-hero { min-height: 360px; }
  #globe { min-height: 320px; }
}

/* ─── Mobile platform tabs (Top-20 list selector) ─── */
.top-events-tabs { display: none; }                /* hidden by default; shown on mobile */
.top-events-tabs button {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 8px 14px; font-size: 12px; font-weight: 700;
  cursor: pointer; white-space: nowrap; flex-shrink: 0;
}
.top-events-tabs button.active { background: var(--accent); color: var(--bg); border-color: var(--accent); }
.top-events-tabs button[data-target="kalshi"].active   { background: var(--kalshi); border-color: var(--kalshi); }
.top-events-tabs button[data-target="manifold"].active { background: var(--platform-manifold-brand); border-color: var(--platform-manifold-brand); }
.top-events-tabs button[data-target="sxbet"].active    { background: var(--sxbet); border-color: var(--sxbet); }
.top-events-tabs button[data-target="limitless"].active { background: var(--limitless); border-color: var(--limitless); color: var(--bg); }

/* ─── Tablet (≤ 900px) ─── */
@media (max-width: 900px) {
  .top-events { grid-template-columns: 1fr; }
}

/* ─── Mobile (≤ 768px) ─────────────────────────────────────────────── */
@media (max-width: 768px) {
  /* Header compaction */
  header { padding: 10px 12px; gap: 8px; }
  h1 { font-size: 18px; letter-spacing: 0.01em; }
  .beta-tag { font-size: 9px; padding: 1px 4px; margin-left: 2px; }
  .tagline { font-size: 10px; }
  .meta { font-size: 11px; gap: 8px; flex-wrap: wrap; width: 100%; order: 12; padding-top: 4px; border-top: 1px solid var(--border); }
  /* mascot is decorative — drop it on phones; let the CTA cluster span full width */
  .header-right { width: 100%; margin-left: 0; justify-content: flex-start; gap: 8px; }
  .header-mascot { display: none; }
  .ts { font-size: 10px; }
  .alive-toggle { font-size: 11px; padding: 4px 8px; border-radius: var(--r-card); }
  .collect-btn { font-size: 11px; padding: 6px 10px; }
  .collect-status { width: 100%; font-size: 10px; }
  .search-box { flex-basis: 100%; order: 11; max-width: none; margin: 0; }
  .search-box input { font-size: 14px; padding: 8px 10px; }

  /* Top strip — stack ticker + jackpot */
  .top-strip { grid-template-columns: 1fr; padding: 8px 12px; gap: 8px; }
  .ticker-strip { gap: 4px; }
  .ticker-row { padding: 5px 8px; gap: 6px; }
  .ticker-label { font-size: 9px; padding: 2px 5px; letter-spacing: 0.08em; }
  .ticker-title { font-size: 11px; }
  .ticker-vol { font-size: 10px; }
  .jackpot-top10-card { padding: 8px 12px; max-height: none; }
  .jackpot-list .jp-row-link { padding: 5px 4px; font-size: 11px; gap: 6px; }
  .jackpot-list .jp-row-amount { font-size: 11px; }
  .jp-row-winner { font-size: 10px; padding: 1px 4px 4px 26px; gap: 4px; }

  /* Signals row — stack vertically */
  .signals-row { grid-template-columns: 1fr; padding: 8px 12px; gap: 8px; }
  .signals-card { padding: 8px 12px; }
  .signals-card h3 { font-size: 14px; margin-bottom: 4px; }
  h3 .plat-name { font-size: 14px; }
  h3 .plat-sub { font-size: 11px; }
  .sig-link { grid-template-columns: 38px 1fr; gap: 6px; padding: 7px 4px; font-size: 11px; min-height: 40px; align-items: center; }
  .sig-meta { grid-column: 1 / -1; justify-self: start; margin-top: 2px; gap: 3px; }
  .sig-tag { font-size: 9px; padding: 1px 4px; }
  .wallets-list .wallet-link { grid-template-columns: 24px 1fr; }
  .wallets-list .sig-meta { grid-column: 2; }

  /* Hero — single column, smaller globe */
  .hero-2x2-center {
    padding: 8px 12px; gap: 8px;
    grid-template-columns: 1fr; grid-template-rows: auto;
  }
  .hero-2x2-center .t10-card { padding: 10px 12px; max-height: none; }
  .hero-2x2-center .t10-card:nth-child(n) { padding-left: 12px; padding-right: 12px; }
  .globe-hero-center {
    position: static; transform: none;
    width: 100%; height: 280px; border-radius: var(--r-card);
    margin: 0; box-shadow: none;
  }
  .globe-hero-center h3 { position: static; transform: none; background: transparent; border: none; padding: 0 0 6px; font-size: 13px; }
  .globe-hero-center .globe-legend { position: static; transform: none; margin-top: 6px; }
  .globe-legend { font-size: 9px; gap: 6px; }
  .platform { font-size: 14px; padding-bottom: 6px; margin-bottom: 8px; }
  .plat-name { font-size: 15px; letter-spacing: 0.04em; }
  .plat-sub { font-size: 11px; }
  .t10-row a { padding: 6px 4px; font-size: 12px; min-height: 36px; }
  .t10-name { font-size: 12px; }
  .t10-vol { font-size: 11px; }

  /* LATEST WHALES marquee — stack label above the scrolling track on mobile so
     items don't get squeezed against the fixed-width LATEST WHALES label. */
  .ticker-section { flex-direction: column; align-items: stretch; }
  .ticker-section .ticker-label {
    padding: 6px 12px; font-size: 10px; letter-spacing: 0.12em;
    text-align: center; align-self: stretch; justify-content: center;
  }
  .ticker-wrap { padding: 4px 0; }
  .ticker-track { gap: 20px; padding-left: 12px; }
  .ticker-item { font-size: 11px; padding: 2px 6px; gap: 4px; }
  .tk-amount { font-size: 11px; }
  .tk-side { font-size: 9px; padding: 1px 4px; }
  .tk-q { max-width: 160px; font-size: 11px; }
  .tk-evt { display: none; }   /* event-title chip removed on mobile to save horizontal space */
  .tk-odds { font-size: 10px; }
  .tk-by   { display: none; }  /* wallet/user trimmed on mobile */

  /* Top-20 platform tabs become visible on mobile */
  .top-events-tabs {
    display: flex; gap: 6px; padding: 8px 12px 4px; overflow-x: auto;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .top-events-tabs::-webkit-scrollbar { display: none; }
  .top-events { grid-template-columns: 1fr; padding: 4px 12px 12px; gap: 8px; }
  .top-events .card { display: none; max-height: none; }
  .top-events[data-active="poly"]     .card.poly     { display: block; }
  .top-events[data-active="kalshi"]   .card.kalshi   { display: block; }
  .top-events[data-active="metaforecast"] .card.metaforecast { display: block; }
  .top-events[data-active="myriad"]   .card.myriad   { display: block; }
  .top-events[data-active="betfair"]  .card.betfair  { display: block; }
  .top-events[data-active="manifold"] .card.manifold { display: block; }
  .top-events[data-active="sxbet"]    .card.sxbet    { display: block; }
  .top-events[data-active="limitless"] .card.limitless { display: block; }
  .t20-row { padding: 7px 0 7px 28px; }
  .t20-row::before { left: 0; top: 8px; font-size: 10px; }
  .t20-title { font-size: 12px; line-height: 1.3; }
  .t20-meta { font-size: 10px; line-height: 1.3; }

  /* Whale cards — stack with horizontal label on top */
  /* Build .87: mobile breakpoint scaled down to match the new
     dramatically-compressed desktop sizes. */
  .whale-cards-2x2 { gap: 4px; }
  .featured-whale { flex-direction: column; align-items: stretch; padding: 0; }
  .fw-label {
    writing-mode: horizontal-tb; transform: none;
    padding: 4px 10px;
    border-radius: 6px 6px 0 0; text-align: center; font-size: 9px;
    align-self: stretch; justify-content: center;
  }
  .fw-body { padding: 5px 8px; grid-template-columns: 1fr; gap: 3px; }
  .fw-amount { grid-row: auto; font-size: 18px; text-align: center; padding: 2px 0; line-height: 1.1; }
  .fw-bet { font-size: 11px; line-height: 1.3; }
  .fw-event, .fw-meta { font-size: 10px; }
  .fw-multi-card .fw-label { border-radius: 6px 6px 0 0; }
  .fw-multi-list { padding: 4px 6px; gap: 2px; }
  .fw-mi-link {
    grid-template-columns: auto auto 1fr;
    grid-template-areas:
      "amt side q"
      "evt evt evt"
      "meta meta meta";
    font-size: 10px; gap: 1px 5px; padding: 3px 3px; min-height: 0;
  }
  .fw-mi-link .odds-chip { display: none; }
  .fw-mi-amt { font-size: 11px; }

  /* Whale chart */
  .whale-chart-box { min-height: 220px; padding: 10px 12px; }
  .whale-chart-box canvas { min-height: 200px; max-height: 240px; }
  .whale-chart-box h3 { font-size: 14px; margin-bottom: 6px; }
  .whale-section { padding: 0 12px; }

  /* Build .260: Risers + Coldest merged box (mobile) */
  .movers-merged-section { padding: 8px 12px 0; }
  .movers-merged-card { padding: 10px 12px 12px; }
  .movers-col-head { font-size: 10px; margin-bottom: 4px; }
  .mvm-link { padding: 3px 6px; font-size: 11px; }
  .mvm-title { font-size: 11px; }
  .mvm-delta { font-size: 10px; }

  /* Visitor card + Daily volume */
  .jackpot-volume-row { padding: 8px 12px; }
  .jv-grid { grid-template-columns: 1fr; gap: 8px; }
  .visitor-card { padding: 12px; }
  .visitor-body { grid-template-columns: 1fr; gap: 8px; }
  .vw-globe-bottom { width: 180px; height: 180px; }
  .vw-stats { grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .vw-stat-num { font-size: 16px; }
  .vw-stat-lbl { font-size: 9px; }
  .vw-list-bottom { grid-column: 1 / -1; border-left: none; padding-left: 0; border-top: 1px solid var(--border); padding-top: 8px; max-height: 160px; }
  .dv-chart { min-height: 200px; padding: 10px 12px; }
  .dv-chart canvas { min-height: 180px; max-height: 220px; }

  /* Modals — full width, scrollable */
  .modal-overlay { padding: 8px; padding-top: 24px; align-items: flex-start; }
  .modal { padding: 18px 14px 14px; max-width: 100%; max-height: calc(100vh - 40px); overflow-y: auto; border-radius: var(--r-card); }
  .modal h3 { font-size: 16px; }
  .modal-close { font-size: 28px; top: 6px; right: 10px; padding: 0 4px; }
  .modal-platform { font-size: 10px; }
  .modal-meta { font-size: 11px; }
  .meta-card { padding: 10px; }
  .meta-card[open] .meta-card-inner { grid-template-columns: 1fr; gap: 8px; }
  .meta-card[open] .meta-card-inner:has(.meta-img) { grid-template-columns: 60px 1fr; }
  .meta-img { width: 60px; height: 60px; max-width: 60px; max-height: 60px; }
  .meta-fields { font-size: 10px; gap: 3px 12px; }
  .meta-desc { font-size: 11px; max-height: 100px; }
  .opts-table, .trades-table, .wm-trades { font-size: 10px; }
  .opts-table th, .opts-table td,
  .trades-table th, .trades-table td,
  .wm-trades th, .wm-trades td { padding: 5px 6px; }
  .opts-table .opt-pct { width: 90px; }
  .bar-wrap .bar { max-width: 60px; }

  /* Wallet modal */
  .wm-stats { grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .wm-stat { padding: 8px 4px; }
  .wm-stat-num { font-size: 14px; }
  .wm-stat-lbl { font-size: 9px; }
  .wm-trades th:nth-child(1), .wm-trades td:nth-child(1) { display: none; }  /* hide UTC col on phone */
  .wm-name { font-size: 16px; }

  /* Cross-venue group modal */
  .eg-table th, .eg-table td { padding: 6px 5px; font-size: 11px; }
  .eg-table th:nth-child(1), .eg-table td:nth-child(1) { width: 38px; }

  /* Footer */
  footer { padding: 10px 12px; font-size: 10px; flex-direction: column; gap: 6px; text-align: center; }
  .footer-meta { font-family: monospace; }

  /* Viewer pill */
  .viewer-pill { right: 8px; bottom: 8px; padding: 4px 8px; font-size: 10px; }
  .vw-total, .vw-all-unique { font-size: 11px; }
  .vw-label { font-size: 9px; }
}

/* ─── New Phase 1 tickers (Latest Events, Jackpot) ───────────────────── */

/* Both new tickers reuse .ticker-section / .ticker-track / .ticker-item but
   with their own label colors and item structure. The marquee animation is
   already defined; we just style the contents. */

/* Build v0.35 20260523.189 (2026-05-23): reverted to SOLID aqua per
   user request.
   Build v0.35 20260523.191 (2026-05-23): darker shade of aqua —
   switched from var(--accent) var(--accent) (Tailwind teal-400) to
   var(--accent-deep) (Tailwind teal-600).  Two steps darker.  Text flipped
   from var(--bg) (dark) to #f0fdfa (very light teal-tinted white)
   so contrast stays WCAG-AA clean (~7:1) on the darker background;
   dark text on var(--accent-deep) would have been borderline. */
.ticker-label.tl-events {
  background: var(--accent-deep);
  color: #f0fdfa;
  border-right: 1px solid rgba(13, 148, 136, 0.55);
}
.ticker-label.tl-jackpot {
  background: linear-gradient(180deg, color-mix(in srgb, var(--jackpot) 22%, transparent), color-mix(in srgb, var(--jackpot) 10%, transparent));
  color: var(--jackpot);
  border-right: 1px solid color-mix(in srgb, var(--jackpot) 30%, transparent);
}
.ticker-label.tl-whales {
  /* Inherits the existing default look; specific class kept for symmetry. */
}

/* Latest events items: platform badge + (NEW chip) + title + 24h volume. */
.le-item {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 12px; color: var(--text);
  border-right: 1px solid var(--border);
  white-space: nowrap;
}
.le-item:hover { background: var(--panel-2); text-decoration: none; }
.le-plat { font-size: 9px; padding: 1px 5px; }
.le-new {
  font-size: 11px; padding: 0 4px; line-height: 1;
  background: color-mix(in srgb, var(--success) 18%, transparent); color: var(--success);
  border-radius: var(--r-chip); font-weight: 700;
}
.le-title { font-size: 12px; font-weight: 500; max-width: 380px; overflow: hidden; text-overflow: ellipsis; }
.le-vol { font-family: monospace; font-size: 11px; color: var(--muted); font-weight: 600; }

/* Build v0.35 20260525.208: Trending Topics ticker (4th top-of-page
   ticker, promoted from a signals-row tile).  No .ticker-label per
   spec — visually distinguished by an amber border-top + tighter
   padding so the title-less section reads as "topics" without copy.
   Reuses .ticker-section / .ticker-track / scroll-left grammar above. */
.topics-ticker-section {
  border-top: 1px solid rgba(245, 158, 11, 0.30);
  border-bottom: 1px solid rgba(245, 158, 11, 0.20);
  background: linear-gradient(180deg,
              rgba(245, 158, 11, 0.05),
              rgba(245, 158, 11, 0.02));
}
.topics-ticker-section .ticker-wrap { padding: 4px 0; }
.topics-ticker-section .ticker-track { gap: 22px; }
.tt-item {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 3px 10px; color: var(--text);
  border-right: 1px solid var(--border);
  white-space: nowrap;
  cursor: pointer;
}
.tt-item:hover { background: rgba(245, 158, 11, 0.08); text-decoration: none; }
.tt-topic {
  font-weight: 800; color: var(--jackpot); font-size: 12px;
  letter-spacing: 0.02em;
}
.tt-vol {
  font-family: monospace; font-size: 11px; font-weight: 700;
  color: var(--jackpot);
  background: color-mix(in srgb, var(--jackpot) 12%, transparent);
  padding: 1px 6px; border-radius: var(--r-chip);
}
.tt-evt {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; color: var(--muted);
  max-width: 360px;
}
.tt-evt .sig-plat { font-size: 8px; padding: 1px 4px; flex: 0 0 auto; }
.tt-evt-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}

/* .403 (b): PEACHY-theme legibility for the Trending Topics ("hot topic")
   ticker. The amber var(--jackpot) chips + muted title wash out on the cream
   background — re-ink the topic/volume chips to deep purple and the event
   title to near-black. Dark theme unchanged. */
:root[data-theme="peach"] .tt-topic { color: #5b1a8a; }
:root[data-theme="peach"] .tt-vol {
  color: #5b1a8a;
  background: color-mix(in srgb, #5b1a8a 12%, transparent);
}
:root[data-theme="peach"] .tt-evt,
:root[data-theme="peach"] .tt-evt-title { color: #15110d; }

/* Jackpot ticker items: platform + payout + title + winner inline. */
.jp-item {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 14px; color: var(--text);
  border-right: 1px solid var(--border);
  white-space: nowrap;
}
.jp-item:hover { background: var(--panel-2); text-decoration: none; }
.jp-amount {
  font-family: monospace; font-size: 13px; font-weight: 800;
  color: var(--jackpot);
}
.jp-title-ticker { font-size: 12px; max-width: 380px; overflow: hidden; text-overflow: ellipsis; }
.jp-evt-sub { color: var(--muted); font-size: 11px; font-style: italic; }
.jp-winning-bet {
  display: inline-block; padding: 1px 7px; border-radius: var(--r-chip);
  font-family: monospace; font-size: 11px; font-weight: 800;
  letter-spacing: 0.04em;
}
.jp-winner-yes   { background: color-mix(in srgb, var(--success) 22%, transparent); color: var(--success); }
.jp-winner-no    { background: color-mix(in srgb, var(--danger) 20%, transparent);  color: var(--danger); }
.jp-winner-other { background: color-mix(in srgb, var(--kalshi) 20%, transparent); color: var(--kalshi); }
.jp-winner-ticker {
  font-size: 11px; color: var(--muted);
  background: color-mix(in srgb, var(--jackpot) 10%, transparent); padding: 1px 8px; border-radius: var(--r-card);
}
.jp-winner-ticker .wallet-link { color: var(--jackpot); border-bottom-color: color-mix(in srgb, var(--jackpot) 40%, transparent); }

/* Latest whales — add space after platform badge so it's clearly the source. */
.latest-whales-section .ticker-item .sig-plat {
  margin-right: 4px; font-size: 9px;
}

/* Build v.03 .31 build 172 (2026-05-23): Latest Whales is the section
   visitors track most actively (real-time signal of live activity), so
   it gets a slightly brighter background tint and tighter row geometry
   than the surrounding ticker sections (Latest Events, Jackpots).
   Scoped to .latest-whales-section only — no spillover to other
   tickers. */
.latest-whales-section {
  /* Tiny step up from var(--panel) — whale-blue tint so it reads as
     the "heartbeat" of the dashboard without losing the dark palette. */
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--accent) 7%, transparent),
              color-mix(in srgb, var(--kalshi) 5%, transparent));
  border-top-color:    color-mix(in srgb, var(--accent) 30%, transparent);
  border-bottom-color: color-mix(in srgb, var(--kalshi) 20%, transparent);
}
.latest-whales-section .ticker-wrap {
  /* Was 8px top + bottom — knock back to 4px so the band is visibly
     more compact than its neighbours. */
  padding: 4px 0;
}
.latest-whales-section .ticker-track {
  /* Tighter gap between whale items (was 32px) so more fit on screen. */
  gap: 22px;
}
.latest-whales-section .ticker-item {
  /* Compact whale row: smaller base font, tighter padding + gap. */
  font-size: 12px;
  padding: 2px 8px;
  gap: 6px;
}
.latest-whales-section .ticker-item .tk-amount { font-size: 12px; }
.latest-whales-section .ticker-item .tk-side   { font-size: 9px;  padding: 1px 5px; }
.latest-whales-section .ticker-item .tk-q      { font-size: 11px; max-width: 220px; }
.latest-whales-section .ticker-item .tk-evt    { font-size: 11px; max-width: 200px; }
.latest-whales-section .ticker-item .tk-odds   { font-size: 10px; }
.latest-whales-section .ticker-item .tk-by     { font-size: 10px; }
.latest-whales-section .ticker-item .tk-user   { font-size: 10px; max-width: 100px; }
/* Build v0.35 20260523.189 (2026-05-23): reverted the build-172
   gradient back to the inherited solid PINK (var(--whale) =
   var(--whale)) per user request.  The build-172 aqua-blue gradient was
   added to harmonize with the brightened section background but
   broke the original color identity ("LATEST WHALES = pink chip").
   Now the label uses the default .ticker-label background (solid
   pink) while the section itself keeps its subtle brighter tint.
   Padding + font-size kept slightly compacted from build-172 so
   the chip still reads as the more-recent compact treatment. */
.latest-whales-section .ticker-label.tl-whales {
  padding: 6px 14px;
  font-size: 12px;
}

/* Build .49 SX.BET SETTLEMENTS ticker CSS removed in build .54 —
   ticker section deprecated; big sx.bet settlements now fold into the
   Jackpot ticker via the collector recent_jackpots merge. */

/* Build .49 — SX.BET TRADER LEADERBOARD. Single-section card; one row
   per trader, click row to open wallet modal.
   Build .54 — compact variant (.sxbet-leaderboard-compact): smaller
   padding, 4-column grid (rank · wallet · PnL · ROI), tighter rows so
   the section earns its real estate. */
.sxbet-leaderboard-section {
  margin: 20px 16px;
  padding: 18px 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 4px solid var(--platform-manifold-brand);
  border-radius: var(--r-card);
}
.sxbet-leaderboard-section.sxbet-leaderboard-compact {
  padding: 10px 14px;
  margin: 14px 16px;
}
.sxlb-heading {
  margin: 0 0 14px 0;
  font-size: 16px;
  color: var(--text);
}
.sxbet-leaderboard-compact .sxlb-heading {
  margin: 0 0 8px 0;
  font-size: 13px;
}
.sxlb-heading .sxlb-name { color: var(--platform-manifold-brand); font-weight: 800; }
.sxlb-heading .plat-sub  { color: var(--muted); font-size: 12px; font-weight: 400; }
.sxbet-leaderboard-compact .sxlb-heading .plat-sub { font-size: 10px; }
.sxlb-grid {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sxbet-leaderboard-compact .sxlb-grid { gap: 2px; }
.sxlb-row {
  display: grid;
  grid-template-columns: 36px 130px 1fr 1fr;
  align-items: center;
  gap: 12px;
  padding: 6px 10px;
  background: var(--panel-2);
  border-radius: var(--r-chip);
  text-decoration: none;
  color: var(--text);
  cursor: pointer;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.sxbet-leaderboard-compact .sxlb-row {
  padding: 3px 8px;
  grid-template-columns: 28px 110px 1fr 1fr;
  gap: 8px;
}
.sxlb-row:hover { background: rgba(192,132,252,0.10); }
.sxlb-rank {
  font-family: monospace; font-size: 13px; font-weight: 800;
  color: var(--platform-manifold-brand); text-align: center;
}
.sxbet-leaderboard-compact .sxlb-rank { font-size: 11px; }
.sxlb-wallet {
  font-family: monospace; font-size: 12px; color: var(--text);
}
.sxbet-leaderboard-compact .sxlb-wallet { font-size: 11px; }
.sxlb-stat {
  display: flex; flex-direction: column; align-items: flex-end;
  font-family: monospace; font-size: 13px; font-weight: 700;
}
.sxbet-leaderboard-compact .sxlb-stat { font-size: 11px; }
.sxlb-stat-lbl {
  font-size: 9px; font-weight: 400; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.05em; margin-top: 1px;
}
.sxbet-leaderboard-compact .sxlb-stat-lbl { font-size: 8px; margin-top: 0; }
.sxlb-pnl-pos { color: var(--success); }
.sxlb-pnl-neg { color: var(--danger); }
.sxlb-staked  { color: var(--muted); }
.sxlb-trades  { color: var(--text); }
.sxlb-roi { color: var(--muted); }

@media (max-width: 700px) {
  .sxlb-row { grid-template-columns: 30px 100px 1fr 1fr; }
}

/* ─── Top-20 cross-venue button — bolder/larger so it can't be missed ─── */
.t20-group-pill {
  /* Build .87.4: pill compressed to match the slimmer rows around it. */
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 9px; font-weight: 700; padding: 1px 6px;
  border-radius: var(--r-card); margin-bottom: 1px;
  text-decoration: none; cursor: pointer;
  white-space: nowrap;
}
.t20-group-pill:hover { filter: brightness(1.15); text-decoration: none; }
.t20-group-pill-bold {
  /* Beefier visual treatment so the indicator reads from across the page. */
  font-size: 10px; font-weight: 800; padding: 1px 7px;
  border-width: 2px !important;
  letter-spacing: 0.02em;
  box-shadow: 0 0 0 0 currentColor;
  animation: t20gpPulse 3s ease-in-out infinite;
}
.t20-gp-icon  { font-size: 11px; line-height: 1; }
.t20-gp-label { font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.9; }
.t20-gp-plats { font-weight: 700; letter-spacing: 0.01em; opacity: 1; }
@keyframes t20gpPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,255,0.0); }
  50%      { box-shadow: 0 0 0 4px rgba(255,255,255,0.10); }
}
.t20-group-pill.evt-group-0 { background: color-mix(in srgb, var(--jackpot) 20%, transparent); color: var(--evt-grp-0); border: 1px solid color-mix(in srgb, var(--jackpot) 40%, transparent); }
.t20-group-pill.evt-group-1 { background: color-mix(in srgb, var(--kalshi) 20%, transparent); color: var(--evt-grp-1); border: 1px solid color-mix(in srgb, var(--kalshi) 40%, transparent); }
.t20-group-pill.evt-group-2 { background: color-mix(in srgb, var(--whale) 20%, transparent); color: var(--evt-grp-2); border: 1px solid color-mix(in srgb, var(--whale) 40%, transparent); }
.t20-group-pill.evt-group-3 { background: color-mix(in srgb, var(--platform-manifold-brand) 20%, transparent); color: var(--evt-grp-3); border: 1px solid color-mix(in srgb, var(--platform-manifold-brand) 40%, transparent); }
.t20-group-pill.evt-group-4 { background: color-mix(in srgb, var(--success) 20%, transparent);  color: var(--evt-grp-4); border: 1px solid color-mix(in srgb, var(--success) 40%, transparent); }
.t20-group-pill.evt-group-5 { background: rgba(251,113,133,0.20); color: var(--evt-grp-5); border: 1px solid rgba(251,113,133,0.4); }

/* ─── Mobile bottom nav (visible on ≤768px only) ──────────────────────── */
.mtab-strip { display: none; } /* mobile-pagenav 2026-08-21: <=768px only */
.mobile-bottom-nav {
  display: none; /* shown only on mobile */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 100;
  background: var(--mbn-bg); /* mtabs 2026-07-04: literal → var so peach retints the nav */
  border-top: 1px solid var(--border);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  padding: 6px 0 max(6px, env(safe-area-inset-bottom));
}
/* mobile-pagenav 2026-08-21: 5 VISIBLE cells - 4 pages + ONE of the two
   auth items (pc-auth-sub/anon, the other display:none'd), so auto-flow
   columns beat a fixed repeat() that would hold the hidden item's track. */
.mbn-list {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0; /* mtabs 2026-07-04: 5 true tabs (.442 pre-shipped the 4→5 grid) */
  list-style: none; margin: 0; padding: 0;
}
.mbn-item a {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 6px 4px; color: var(--muted); text-decoration: none;
  font-size: 10px; font-weight: 700; letter-spacing: 0.02em; /* mtabs 2026-07-04: tighter — 5 labels must fit */
  text-transform: uppercase;
}
.mbn-item a:hover, .mbn-item a:focus { color: var(--text); text-decoration: none; }
.mbn-item a.is-active { color: var(--accent); }  /* mtabs 2026-07-04 */

/* blog-tab 2026-09-02: the public /blog list + post pages. Vars only (graphical
   tenet); the list is FLEX rows (never a fixed grid); long-form body typography
   with tables scrolling inside their own box (no page-level horizontal scrollbar). */
.blog-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; max-width: 860px; }
.blog-entry-link { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); text-decoration: none; min-width: 0; }
.blog-entry-link:hover { border-color: var(--accent); text-decoration: none; }
.blog-entry-top { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.blog-kind { font-weight: 700; }
.blog-kind-newsletter { color: var(--accent); }
.blog-kind-post { color: var(--whale); }
.blog-title { font-size: 17px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.blog-summary { color: var(--muted); font-size: 13px; line-height: 1.5; }
.blog-author { color: var(--muted); font-size: 12px; }
.blog-post { max-width: 760px; }
.blog-back { display: inline-block; margin-bottom: 10px; font-size: 12px; color: var(--accent); text-decoration: none; }
.blog-post-meta { display: flex; gap: 10px; flex-wrap: wrap; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.blog-post-title { margin: 6px 0 14px; font-size: 1.6rem; line-height: 1.25; overflow-wrap: anywhere; }
.blog-post-body { font-size: 15px; line-height: 1.65; }
.blog-post-body p { margin: 0 0 1em; }
.blog-post-body img { max-width: 100%; height: auto; display: block; margin: 12px auto; border-radius: 6px; }
.blog-post-body p > em:only-child { display: block; text-align: center; color: var(--muted); font-size: 13px; margin-top: -6px; }
.blog-post-body table { display: block; overflow-x: auto; border-collapse: collapse; margin: 12px 0 16px; font-size: 13px; }
.blog-post-body th, .blog-post-body td { padding: 6px 10px; border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
.blog-post-body th { color: var(--muted); font-weight: 600; }
.blog-post-tail { margin: 22px 0 0; font-size: 13px; }

.mbn-icon { font-size: 18px; line-height: 1; }
.mbn-label { display: block; }

@media (max-width: 768px) {
  .mobile-bottom-nav { display: block; }
  /* mobile-pagenav 2026-08-21: the on-page section strip (/events only). */
  .mtab-strip { display: flex; gap: 6px; padding: 6px 10px; overflow-x: auto;
    -webkit-overflow-scrolling: touch; }
  .mtab-pill { flex: 0 0 auto; font-size: 11px; font-weight: 700;
    padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px;
    color: var(--muted); text-decoration: none; background: var(--panel); }
  .mtab-pill.is-active { color: var(--accent); border-color: var(--accent); }
  /* Reserve room at the bottom of the page so the fixed nav doesn't overlap
     the visitor pill or the footer's last line.
     ⚠ .893 review: SCOPED to the pages that actually carry the nav. This was
     bare `body`, and it only looked harmless because the old unscoped
     `body { padding-bottom: calc(--mbn-h + --tape-h + 10px) }` further down
     overrode it everywhere. mobile-usability scoped THAT rule to
     .pc-shell/.wallet-page, which uncovered this one — leaving 60px of dead
     space at ≤768 on /privacy, /terms and /admin/*, none of which render a
     bottom bar (verified: .mobile-bottom-nav ships only via _pc_shell). */
  body.pc-shell, body.wallet-page { padding-bottom: 60px; }
  .viewer-pill { bottom: 64px; }                  /* sit above the bottom nav */
  /* mtabs 2026-07-04: true tabs — hide every tagged pane not matching the active tab.
     events-mkt-tab-cleanup: one line per .mtab-strip pill. The retired hot and mkt
     tabs lost their lines - body[data-mtab] is set only by index.html's default
     (board) and literal mtabGo() calls, all pill names (test_events_mkt_tab_cleanup). */
  body[data-mtab="board"]  [data-mtab]:not([data-mtab~="board"]),
  body[data-mtab="alerts"] [data-mtab]:not([data-mtab~="alerts"]),
  body[data-mtab="cv"]     [data-mtab]:not([data-mtab~="cv"]) { display: none !important; }
  /* Band chrome must not render as an empty box when its only child for the
     active tab is absent server-side (the crossvenue card is Jinja-guarded). */
  body[data-mtab="cv"]  .departures-band:not(:has(.crossvenue-card)) { display: none !important; }
}

/* ─── Phone-narrow (≤ 480px) ──────────────────────────────────────────── */
@media (max-width: 480px) {
  .mbn-label { font-size: 9px; }                  /* mtabs 2026-07-04: 5 labels on phone-narrow */
  h1 { font-size: 16px; }
  .platform { font-size: 13px; }
  .plat-name { font-size: 14px; }
  .plat-sub { font-size: 10px; }
  .t10-name { white-space: normal; }              /* allow wrapping on tiny screens */
  .t10-row a { grid-template-columns: 18px 1fr auto; gap: 5px; }
  .t10-bet { display: none; }                     /* hide top-bet inline label, save space */
  .vw-stats { grid-template-columns: 1fr; }
  .wm-stats { grid-template-columns: repeat(2, 1fr); }
  .visitor-card h3 .plat-sub { display: none; }
}

/* ────────────────────────────────────────────────────────────────
   Build .61 additions
   ──────────────────────────────────────────────────────────────── */

/* Item #6: refresh-frequency note above the 3x2 top-20 grid. Stretches
   across the full section width (grid-column: 1 / -1) so it sits as a
   header band rather than inside one of the platform cards. */
.top20-meta-note {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin-bottom: 4px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  border-radius: var(--r-card);
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}
.top20-meta-note .t20-mn-icon {
  flex-shrink: 0;
  color: var(--accent);
  font-size: 13px;
  line-height: 1;
}
@media (max-width: 768px) {
  .top20-meta-note { font-size: 10px; padding: 6px 10px; gap: 6px; }
}

/* Item #9: bet-title prefix on the "Global probability YES" headline
   inside the cross-venue group modal. Subtle muted style so the % stays
   the visual anchor, but the user sees which question is being priced. */
.eg-vwap-evt-title {
  color: var(--muted);
  font-weight: 500;
  font-style: italic;
  margin-right: 2px;
}

/* Item #11: whale icon next to the LATEST WHALES ticker title.
   Inline SVG so we don't add another asset request.

   Build .61 follow-up: sized up from 14→18px and recolored to a light
   sky-blue (var(--platform-polyus-brand)) at full opacity for stronger contrast against the
   yellow/orange ticker background. The icon uses vertical-align: middle
   and stays within the label's natural padding (10px top/bottom +
   13px font), so the LATEST WHALES box dimensions don't change — all
   ticker title boxes stay visually the same size as before. */
.ticker-label.tl-whales .tl-whale-icon {
  display: inline-block;
  width: 18px;
  height: 18px;
  margin-right: 6px;
  vertical-align: middle;
  fill: var(--platform-polyus-brand);
  opacity: 1;
}
@media (max-width: 768px) {
  .ticker-label.tl-whales .tl-whale-icon { width: 13px; height: 13px; margin-right: 4px; }
}

/* -----------------------------------------------------------------
   Build v.03 .31 build 147 (2026-05-22): "Keep an Eye On:" section
   inside the event modal. Highlights up to 3 sub-markets outside the
   top-10 by volume that have climbed ≥10% in the last 24h. Each row
   gets a 🥇/🥈/🥉 medal; the section title carries a 🪬 Hamsa icon.

   Visual goals:
   - Distinct from the dense .opts-table above (lighter, accent-tinted)
   - Compact — three rows, single line each, no second-table grammar
   - The medal icon is THE visual anchor; everything else is meta info
   - Hamsa icon (🪬) is slightly oversized to act as the section glyph
   - Gold/silver/bronze accents subtly tint the row background
     ---------------------------------------------------------------- */
.kao-section {
  margin: 18px 0 10px;
  padding: 10px 14px 12px;
  background: rgba(250, 204, 21, 0.04);    /* faint gold wash */
  border-left: 3px solid rgba(250, 204, 21, 0.6);
  border-radius: var(--r-card);
}
.kao-title {
  /* Override section-title's muted color — this section is meant
     to draw the eye (literally — hence the Hamsa). */
  color: var(--text, #e2e8f0) !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  font-size: 13px !important;
  margin: 0 0 8px !important;
  display: flex;
  align-items: center;
  gap: 6px;
}
.kao-icon {
  font-size: 18px;
  line-height: 1;
  display: inline-block;
  vertical-align: middle;
}
.kao-sub {
  font-size: 11px;
  font-weight: 400;
  color: var(--muted, var(--muted));
  font-style: italic;
  margin-left: 4px;
}
.kao-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kao-row {
  display: grid;
  /* medal · label · vol · odds · delta */
  grid-template-columns: 28px 1fr auto auto auto;
  align-items: center;
  gap: 12px;
  padding: 6px 8px;
  border-radius: var(--r-chip);
  background: rgba(255,255,255,0.02);
  font-size: 13px;
  line-height: 1.3;
  transition: background 120ms ease;
}
.kao-row:hover {
  background: rgba(255,255,255,0.05);
}
/* Per-medal subtle row tinting — keeps the gold/silver/bronze hierarchy
   readable at a glance without overwhelming the modal's existing palette. */
.kao-medal-1 { border-left: 2px solid #facc15; padding-left: 6px; }
.kao-medal-2 { border-left: 2px solid #cbd5e1; padding-left: 6px; }
.kao-medal-3 { border-left: 2px solid #cd7f32; padding-left: 6px; }
.kao-medal {
  font-size: 18px;
  line-height: 1;
  text-align: center;
  /* The emoji renders best with a tiny baseline nudge */
  transform: translateY(-1px);
}
.kao-label {
  font-weight: 500;
  color: var(--text, #e2e8f0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.kao-vol {
  color: var(--muted, var(--muted));
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
.kao-odds {
  color: var(--text, #e2e8f0);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  min-width: 36px;
  text-align: right;
}
.kao-delta {
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  min-width: 50px;
  text-align: right;
}
/* Mobile: drop the volume column to keep the row on a single line */
@media (max-width: 600px) {
  .kao-row {
    grid-template-columns: 24px 1fr auto auto;
    gap: 8px;
    padding: 5px 6px;
  }
  .kao-vol { display: none; }
  .kao-sub { display: none; }
  .kao-icon { font-size: 16px; }
  .kao-medal { font-size: 16px; }
}

/* -----------------------------------------------------------------
   Build v.03 .31 build 149 (2026-05-22): arb-card submarket name.
   Surfaced ONLY for multi-outcome arbs ("Presidential Election Winner
   2028 → Vance") where the per-sub-market matcher (build 149)
   identified the same candidate across venues.  Visually nests under
   the event title — an indented arrow + candidate name in the
   accent color.
   ---------------------------------------------------------------- */
/* Build v.03 .31 build 152: submarket label inlined into event title
   instead of its own row.  Keeps the candidate name visible without
   adding vertical bloat to multi-outcome cards. */
.arb-submarket-inline {
  color: var(--accent, var(--accent));
  font-weight: 700;
  white-space: nowrap;
}
.arb-submarket-name {
  color: var(--accent, var(--accent));
  /* Build v0.35 20260523.193: bolder betting-option title per user
     request — the candidate name ("Vance", "Spurs") is the *thing
     you'd bet on*, so it deserves more visual weight than the
     surrounding event title. */
  font-weight: 800;
}

/* -----------------------------------------------------------------
   Build v.03 .31 build 151 (2026-05-23): ET& subscriber-tier preview
   — live WS arb-stream indicator.  Sits in the arb-section heading;
   colors:
     - gray (off)       → WS_STREAM_ENABLED=0 on the Space
     - amber (warm)     → connecting / reconnecting
     - green (on)       → connected, ticks flowing
     - red (error)      → fatal client-side error (EventSource unsupported)
   ---------------------------------------------------------------- */
.arb-live-indicator {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: var(--r-card);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
  cursor: help;
}
.arb-live-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.arb-live-label { line-height: 1; }
.arb-live-ticks {
  font-weight: 500;
  font-size: 9px;
  opacity: 0.7;
  margin-left: 2px;
  font-variant-numeric: tabular-nums;
}
.arb-live-off {
  color: var(--muted);
  background: rgba(100, 116, 139, 0.1);
}
.arb-live-warm {
  color: var(--jackpot);
  background: rgba(245, 158, 11, 0.1);
}
.arb-live-on {
  color: var(--success);
  background: rgba(34, 197, 94, 0.12);
}
.arb-live-error {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.arb-live-pulse {
  animation: arb-live-pulse 0.4s ease-out;
}
/* Operator 2026-06-16: when un-commented in templates/index.html, the
   Polymarket Top Traders leaderboard renders at 25% width instead of full —
   single-platform data lists shouldn't dominate the layout. */
#section-poly-top-traders {
  max-width: 25%;
}
@keyframes arb-live-pulse {
  0%   { transform: scale(1);   box-shadow: 0 0 0 0   rgba(34,197,94,0.7); }
  50%  { transform: scale(1.6); box-shadow: 0 0 0 6px rgba(34,197,94,0);   }
  100% { transform: scale(1);   box-shadow: 0 0 0 0   rgba(34,197,94,0);   }
}

/* Build v.03 .31 build 159: wallet hero — "AKA <pseudonym>" pill
   beside the primary name, and a muted treatment for the "Anonymous
   wallet" fallback when no name has been resolved. */
.wallet-aka {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  background: color-mix(in srgb, var(--kalshi) 12%, transparent);
  color: var(--kalshi);
  border: 1px solid color-mix(in srgb, var(--kalshi) 30%, transparent);
  border-radius: var(--r-card);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  vertical-align: middle;
}
.wallet-hero-name-anon {
  color: var(--muted, #8a96c4);
  font-style: italic;
  font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════
   Federated Event Board — Phase C (build v0.35 20260525.216)
   Active when ENABLE_FEDERATED_BOARD=1.  Replaces hero-4x3 + section-
   top20.  Color ordering: teal (top) → pink (middle) → amber (bottom)
   for vertical hierarchy; gold for the catalyst panel.
   ═════════════════════════════════════════════════════════════════ */

/* ── Section shell ── */
/* .board-section renamed to .board-panels-section in build .222 (panels only now) */
.board-panels-section,
.board-section { margin: 0 0 28px; }

.board-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
  padding: 14px 0 10px;
  border-bottom: 2px solid var(--accent);   /* teal — topmost element */
}
.board-heading {
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  margin: 0;
}
.board-heading-sub {
  font-size: 12px;
  color: var(--muted);
}
.board-meta-note {
  font-size: 11px;
  color: var(--muted);
  padding: 6px 0 10px;
}

/* ── Main board table ── */
.board-table {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.board-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: var(--panel);
  border-radius: var(--r-chip);
  min-width: 0;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.board-row:hover { background: var(--panel-2); }
.board-row-urgent { border-left: 3px solid var(--danger); }

.board-rank {
  flex: 0 0 22px;
  font-size: 11px;
  color: var(--muted);
  text-align: right;
}
.board-plat-logo {
  flex: 0 0 18px;
  display: flex;
  align-items: center;
}
.board-title-cell {
  flex: 1 1 0;
  min-width: 0;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.board-chips {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 4px;
}
.board-chip {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 5px;
  border-radius: var(--r-chip);
  background: rgba(255,255,255,0.06);
  white-space: nowrap;
  text-decoration: none;
  color: var(--text);
}
/* BoardScore tier colours */
.bsc-chip { min-width: 26px; text-align: center; }
.bsc-high { background: color-mix(in srgb, var(--accent) 18%, transparent);  color: var(--accent); }
.bsc-mid  { background: color-mix(in srgb, var(--jackpot) 18%, transparent);  color: var(--jackpot); }
.bsc-low  { color: var(--muted); }
/* Per-chip colour semantics */
.board-chip-vol  { color: var(--success);  background: color-mix(in srgb, var(--success) 10%, transparent); }
.board-chip-liq  { color: var(--accent);   background: color-mix(in srgb, var(--accent) 10%, transparent); }
.board-chip-vig  { color: var(--muted); }
.board-chip-ttr-red    { color: var(--danger);  background: color-mix(in srgb, var(--danger) 15%, transparent); }
.board-chip-ttr-yellow { color: var(--jackpot); background: color-mix(in srgb, var(--jackpot) 12%, transparent); }
.board-chip-ttr-gray   { color: var(--muted);   background: rgba(138,150,196,0.10); }
.board-chip-news:hover { opacity: 0.8; }
.board-chip-cross { color: var(--accent);  background: color-mix(in srgb, var(--accent) 12%, transparent); }
.board-chip-smart { color: var(--whale);   background: color-mix(in srgb, var(--whale) 12%, transparent); }
.board-row-empty  { color: var(--muted); font-style: italic; padding: 12px 0; }

/* ── Three reclaim panels ── */
.board-panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));  /* Build .287: auto-fit so the 4th (sx.bet Makers) panel lays out cleanly */
  gap: 16px;
  margin-top: 24px;
}
@media (max-width: 900px) {
  .board-panels { grid-template-columns: 1fr; }
}
.board-panel {
  background: var(--panel);
  border-radius: var(--r-card);
  overflow: hidden;
  min-width: 0;
}

/* P4 2026-06-14: late override — these selectors have per-rule font:/font-family declarations
   at L1098 / L1141 / L1154 / L4697 that beat the utility-attachment block at L114.
   Placed here (above peach, after all rule declarations) so source-order wins. */
.smh-tab,
.ct-tab,
.lq-tab {
  font-family: var(--f-text);
}
.ut-type-chip {
  font-family: var(--f-num);
}

/* ════════════════════════════════════════════════════════════════════
   PEACHY-CREAM THEME — opt-in skin (build .276, 2026-05-29)
   --------------------------------------------------------------------
   Activates ONLY when <html data-theme="peach"> is present (set by the
   bootstrap <script> in index.html from ?theme=peach or a persisted
   localStorage choice).  With no attribute the default DARK theme renders
   byte-for-byte unchanged — every rule below is ADDITIVE and scoped to
   :root[data-theme="peach"], so it can never touch the default UI.

   Logo / source-brand colors are RETAINED: --kalshi --sxbet --limitless
   --whale --jackpot --et-gold and every per-venue logo image are NOT
   overridden.  Only neutral surfaces + the ET accent change; semantic
   red/green are darkened just enough to stay legible on cream.

   Pass 1 = the locked palette + the handful of hardcoded dark/white
   literals that would otherwise read wrong on cream (the 3D globes are
   deliberately left dark).  The long tail of decorative dark gradients
   is refined on the live walk-through.  Promoting peach to default later
   = flip one line in the bootstrap script.
   ════════════════════════════════════════════════════════════════════ */
:root[data-theme="peach"] {
  --bg:      #e0e4c8;   /* the locked "between" hue (cream x greenback) */
  --panel:   #FFE3D6;   /* nh-fix 2026-07-10 (operator round 2: "still a bit too saturated"): #FFA07A → #FFD5C0 → #FFE3D6 — brighter + desaturated pale salmon (≈L0.79) */
  --panel-2: #fbf0df;
  --medal-1: #756400;   /* hm-podium .934: 5.12:1 on the peach panel (light gold was 1.26) */
  --medal-2: #4a5561;   /* 6.23:1 */
  --medal-3: #8f3a1a;   /* 6.4:1; kept >= 45 RGB from --medal-1, which #8a4a18 was not (40) */
  --text:    #3b2f25;   /* espresso */
  --text-strong: #1c1610;   /* peach-news-ink .849: darker espresso — headline
                               ink on the pale-salmon panel (matches the tone
                               .tt-evt-title already uses on this theme) */
  --muted:   #9c8a76;   /* taupe */
  --text-soft: #6a5744;  /* text-soft 2026-07-10: darker taupe-brown — readable on the pale-salmon panel, still softer than espresso --text */
  --accent:  #0d9488;   /* teal-600 — legible as links/accents on cream */
  /* LMTLS 2026-06-10: Limitless brand lime is theme-independent — same values under peach */
  --limitless-yellow: #C3FF00;
  --limitless-black:  #0a0a0a;
  --border:  #ecdcc5;   /* soft sand */
  --success: #15803d;   /* darkened for cream legibility (meaning kept) */
  --danger:  #b91c1c;
  --mint:    #059669;   /* Build .282: darker mint green, legible on cream */
  /* parlay-ink 2026-09-07: the peach twins. Here "deep" is literal — a light
     theme takes the DARK end of each ramp (blue-800 / green-800); on the dark
     theme the same tones measure 1.4-2.1:1 and are invisible, which is why
     these are tokens and not one literal. Measured 5.84-8.39 across the two
     peach backgrounds (see the dark block's table). #1e40af is the ink peach
     already uses for .etand-notice, so the blue is not a new house colour. */
  --parlay-implied-ink: #1e40af;
  --parlay-mult-ink:    #166534;
  /* RETAINED (logos/brand): --kalshi --sxbet --limitless --whale --jackpot --et-gold */
  /* P4 2026-06-14: brand colours unchanged under peach (logos are theme-independent) */
  --platform-manifold-brand: #a78bfa;
  --platform-polyus-brand:   #38bdf8;
  /* P4 2026-06-14: long-tail tokens — peach rebinds the ones that DO have a cream-skin variant.
     --white stays #ffffff (theme-agnostic chip ink). --bg-deeper stays (radial gradients
     are theme-incidental in peach). --accent-deep rebinds to peach's accent for legibility. */
  --accent-deep:  #0a7570;

  /* P4 2026-06-14: only the LED-glow elevation differs under peach (subtler) */
  --e-3: 0 0 14px color-mix(in srgb, var(--jackpot) 22%, transparent);
  --mbn-bg: rgba(224,228,200,0.96);  /* mtabs 2026-07-04: cream-alpha nav backdrop (matches peach --bg #e0e4c8) */

  /* sizing 2026-08-10 — Risk Console band colors */
  --sizing-under: var(--accent);
  --sizing-near: var(--jackpot);
  --sizing-over: var(--danger);

  color-scheme: light;
}

/* White-on-dark text that would vanish on cream → espresso */
:root[data-theme="peach"] h3,
:root[data-theme="peach"] h3 .plat-sub,
:root[data-theme="peach"] .platform,
:root[data-theme="peach"] .plat-sub { color: var(--text); }

/* Hardcoded dark chrome backgrounds → warm cream (globes left dark on purpose) */
:root[data-theme="peach"] header { background: linear-gradient(180deg, #fbf0df, #f1e6d0); }
:root[data-theme="peach"] .featured-whale { background: linear-gradient(90deg, #fdf3ea 0%, #fbf0df 100%); }
:root[data-theme="peach"] .jackpot-card  { background: linear-gradient(90deg, #fdf4e2 0%, #fbf0df 100%); }

/* Dark text on the (now darker) teal accent label → white for contrast */
:root[data-theme="peach"] .wc-latest .fw-label { color: #fff; }

/* Low-alpha WHITE separators/overlays disappear on cream → low-alpha BLACK */
:root[data-theme="peach"] .fw-mi { border-bottom-color: rgba(0,0,0,0.08); }
:root[data-theme="peach"] .fw-aka,
:root[data-theme="peach"] .wm-aka { background: rgba(0,0,0,0.04); border-color: rgba(0,0,0,0.10); }

/* Long-tail (.277): event-modal arb boxes hardcode a dark navy bg (var(--bg))
   that reads as a black slab on cream → warm panel.  Chart/globe tooltips
   (.dv-tooltip/.globe-tooltip/.evt-tooltip) are intentionally LEFT dark —
   like the 3D globes, a dark tooltip floating over cream reads as deliberate. */
:root[data-theme="peach"] .modal-arb-line,
:root[data-theme="peach"] .modal-arb-section-title { background: var(--panel-2); }

/* Build .290: Creamy (peach) fixes for the Marketplace Activity card.
   (1) The .288 dark --chip-halo shadow sat behind the (mostly dark espresso)
   name text and smudged it into an illegible blob — drop the shadow on peach.
   Also force ALL names to var(--text): the theme remapped most venues to
   espresso but missed a few (Betfair amber, Myriad pink) that stayed light
   brand colours at ~1.3:1 contrast on the cream cell; pinning every name to
   the dark text colour makes them uniformly legible (the logos still carry
   venue colour).  Dark mode is untouched — names stay colourful there.
   (2) Manifold's global brightness(3) logo filter brightens its dark-indigo
   logo for DARK backgrounds — on cream it washes to invisible.  Disable it on
   peach so the dark-indigo logo shows against the light cell. */
:root[data-theme="peach"] .mkt-table td.mkt-name .sig-plat { text-shadow: none; color: var(--text); }
/* .885 review-fix: .eg-variant wears var(--jackpot), which peach RETAINS as
   a brand token (amber #fbbf24) — on peach's #FFE3D6 panel that computes
   ~1.4:1, invisible. Deep amber ink for peach only; dark theme unchanged. */
:root[data-theme="peach"] .eg-variant { color: var(--text); }
:root[data-theme="peach"] img[src*="manifold"] { filter: none; }
:root[data-theme="peach"] img[src*="gemini_titan"] { filter: none; }
/* Hyperliquid: white wave-mark on transparent (navy tile knocked out) — shows
   fine on the dark board with no filter, but invisible on cream, so invert it
   to dark for peach only. */
:root[data-theme="peach"] img[src*="hyperliquid"] { filter: invert(1); }

/* ── Theme toggle button (lives in header .meta) ─────────────────────────
   Styled entirely with the theme vars, so it renders correctly in BOTH
   themes with no peach-specific rule.  JS: pcToggleTheme() in the <head>
   bootstrap of index.html / wallet.html. */
.theme-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: var(--r-card);
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--text); font: inherit; font-size: 11px; line-height: 1;
  cursor: pointer; user-select: none; white-space: nowrap;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle .tt-ico { font-size: 13px; line-height: 1; }
/* Palette: pink (middle) → amber (bottom) → gold (catalyst) */
.board-panel--resolving { border-top: 3px solid var(--whale); }
.board-panel--cross     { border-top: 3px solid var(--jackpot); }
.board-panel--catalyst  { border-top: 3px solid var(--et-gold); }

.board-panel-title {
  font-size: 13px;
  font-weight: 700;
  margin: 0;
  padding: 10px 12px 8px;
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
}
.board-panel--resolving .board-panel-title { color: var(--whale); }
.board-panel--cross     .board-panel-title { color: var(--jackpot); }
.board-panel--catalyst  .board-panel-title { color: var(--et-gold); }

/* ── Build .287: sx.bet live-score + maker-leaderboard surfacing ─────────── */
/* Latest Events ticker 🔴 LIVE badge (sxbet in-play rows only). */
.le-live {
  flex: 0 0 auto;
  font-size: 9px; font-weight: 800; letter-spacing: 0.03em;
  padding: 1px 5px; border-radius: var(--r-chip);
  background: var(--live-bg); color: var(--danger);
  white-space: nowrap;
}
.le-live-ft { background: var(--source-tint); color: var(--muted); }
/* Build .320: Kalshi broker-distribution chip (📲 Brokers) — the retail-
   facing subset (available_on_brokers). Amber = "attention/info" per the
   dominant palette; vars only (theme-agnostic), no hard-coded color. */
.le-broker {
  flex: 0 0 auto;
  font-size: 9px; font-weight: 700; letter-spacing: 0.02em;
  padding: 1px 5px; border-radius: var(--r-chip);
  background: var(--source-tint); color: var(--jackpot);
  white-space: nowrap;
}
/* Event-modal in-play score banner. */
.ev-live-score {
  display: flex; align-items: center; gap: 10px;
  margin: 8px 0 4px; padding: 6px 12px;
  background: var(--live-bg); border: 1px solid var(--danger); border-radius: var(--r-card);
}
.ev-live-score.ev-live-final { background: var(--source-tint); border-color: var(--border); }
.ev-live-badge { font-size: 12px; font-weight: 800; letter-spacing: 0.05em; color: var(--danger); white-space: nowrap; }
.ev-live-final .ev-live-badge { color: var(--muted); }
.ev-live-nums { font-size: 22px; font-weight: 800; font-family: monospace; color: var(--text); }
.ev-live-dash { margin: 0 4px; color: var(--muted); }
.ev-live-period { font-size: 12px; color: var(--muted); }
/* sx.bet Market-Makers reclaim panel — teal accent (top of the dominant palette). */
.board-panel--makers    { border-top: 3px solid var(--accent); }
.board-panel--makers    .board-panel-title { color: var(--accent); }
.board-panel-maker-addr { font-family: monospace; }

.board-panel-sub {
  font-size: 10px;
  font-weight: 400;
  color: var(--muted);
}
.board-panel-list {
  list-style: none;
  margin: 0;
  padding: 0 0 8px;
}
.board-panel-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  font-size: 12px;
  min-width: 0;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.board-panel-row:hover { background: var(--panel-2); }
.board-panel-logo { flex: 0 0 14px; }
.board-panel-title-cell {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.board-panel-ttr {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 4px;
  border-radius: var(--r-chip);
  white-space: nowrap;
}
.board-panel-ttr-red    { background: color-mix(in srgb, var(--danger) 15%, transparent);  color: var(--danger); }
.board-panel-ttr-yellow { background: color-mix(in srgb, var(--jackpot) 12%, transparent); color: var(--jackpot); }
.board-panel-ttr-gray   { background: rgba(138,150,196,0.12); color: var(--muted); }
.board-panel-odds   { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--text); }
.board-panel-badge  { flex: 0 0 auto; font-size: 10px; padding: 1px 4px; background: color-mix(in srgb, var(--accent) 12%, transparent);  color: var(--accent);   border-radius: var(--r-chip); white-space: nowrap; }
.board-panel-spread { flex: 0 0 auto; font-size: 10px; font-weight: 700; color: var(--jackpot); }
.board-panel-vol    { flex: 0 0 auto; font-size: 10px; color: var(--success); }
.board-panel-news-link { flex: 0 0 auto; text-decoration: none; font-size: 12px; color: var(--accent); }
.board-panel-empty  { color: var(--muted); font-style: italic; padding: 10px 12px; }

/* Build v0.35 20260525.216: arb explainer modal styles.
   Pairs with the "How do these work? →" button in the Cross-Platform
   Arbitrage section heading + the #arb-help-overlay modal. */
.arb-help-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: 12px;
  padding: 3px 11px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 12px;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.arb-help-btn:hover,
.arb-help-btn:focus-visible {
  color: var(--text);
  border-color: var(--accent);
  background: rgba(34, 197, 94, 0.08);
  outline: none;
}

.arb-help-modal {
  max-width: 640px;
}
.arb-help-modal-body { line-height: 1.6; color: var(--text); }
.arb-help-modal-body h3 {
  margin: 0 0 0.5rem 0;
  font-size: 18px;
  color: var(--text);
}
.arb-help-modal-body h4 {
  margin: 1.5rem 0 0.5rem;
  font-size: 14px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.arb-help-modal-body .arb-help-lead {
  font-size: 14.5px;
  color: var(--text);
  margin: 0.25rem 0 0.5rem;
}
.arb-help-modal-body ol {
  margin: 0.25rem 0;
  padding-left: 1.5rem;
}
.arb-help-modal-body ol li {
  margin-bottom: 0.75rem;
  font-size: 13.5px;
  color: var(--text);
}
.arb-help-modal-body ol li strong {
  color: var(--text);
  font-weight: 700;
}
.arb-help-modal-body .arb-help-disclaimer {
  margin-top: 1.5rem;
  padding: 0.875rem 1rem;
  background: rgba(245, 158, 11, 0.07);
  border-left: 3px solid var(--jackpot);
  border-radius: var(--r-chip);
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.55;
}
.arb-help-modal-body .arb-help-disclaimer strong { color: var(--jackpot); }

@media (max-width: 540px) {
  .arb-help-btn { margin-left: 8px; padding: 3px 9px; font-size: 11px; }
  .arb-help-modal-body h3 { font-size: 16px; }
  .arb-help-modal-body .arb-help-lead { font-size: 13.5px; }
  .arb-help-modal-body ol li { font-size: 12.5px; }
}

/* ── Build .255 — Resolved Trade Receipt Card ──────────────────────────── */
.re-card {
  display: flex; flex-direction: column; gap: 18px;
  padding: 20px 24px; max-width: 560px; margin: 0 auto;
}

/* Header: platform row + title */
.re-header { display: flex; flex-direction: column; gap: 8px; }
.re-plat-row {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
}
.re-badge {
  font-size: 10px; padding: 2px 7px; border-radius: var(--r-card);
  background: color-mix(in srgb, var(--jackpot) 12%, transparent); border: 1px solid color-mix(in srgb, var(--jackpot) 32%, transparent);
  color: var(--jackpot); font-weight: 600; letter-spacing: 0.02em;
}
.re-title {
  font-size: 17px; font-weight: 700; line-height: 1.35;
  color: var(--text);
}
.re-sub { font-size: 12px; color: var(--muted); line-height: 1.4; }

/* Outcome banner */
.re-outcome {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-radius: var(--r-card); font-weight: 700;
}
.re-outcome-won {
  background: color-mix(in srgb, var(--success) 11%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 28%, transparent);
}
.re-outcome-lost {
  background: color-mix(in srgb, var(--danger) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 26%, transparent);
}
.re-outcome-icon { font-size: 20px; line-height: 1; }
.re-outcome-won  .re-outcome-icon { color: var(--success); }
.re-outcome-lost .re-outcome-icon { color: var(--danger); }
.re-outcome-text { font-size: 17px; letter-spacing: 0.06em; }
.re-outcome-won  .re-outcome-text { color: var(--success); }
.re-outcome-lost .re-outcome-text { color: var(--danger); }
.re-outcome-pnl {
  margin-left: auto; font-size: 22px;
  font-weight: 800; font-variant-numeric: tabular-nums;
}
.re-outcome-won  .re-outcome-pnl { color: var(--success); }
.re-outcome-lost .re-outcome-pnl { color: var(--danger); }

/* Detail rows */
.re-details {
  display: flex; flex-direction: column; gap: 8px;
  border-top: 1px solid var(--border); padding-top: 14px;
}
.re-detail-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 13px; gap: 12px;
}
.re-detail-label { color: var(--muted); flex-shrink: 0; }
.re-detail-value { font-weight: 600; color: var(--text); text-align: right; }
.re-pnl-pos { color: var(--success); }
.re-pnl-neg { color: var(--danger); }
.re-detail-ts { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 400; }

/* Footer: external link + archive note */
.re-footer {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  border-top: 1px solid var(--border); padding-top: 12px;
}
.re-ext-link {
  color: var(--accent); text-decoration: none; font-weight: 600;
  font-size: 12px; padding: 4px 10px;
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent); border-radius: var(--r-chip);
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.re-ext-link:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.re-footer-note {
  color: var(--muted); font-size: 10px; font-style: italic;
  margin-left: auto;
}

/* ── LMTLS 2026-06-10: Limitless "Create a market" chip ───────────────────── */
/* PHQ buttons reuse .phq-poly-btn / .phq-modal-poly-btn base; these override color */
.phq-limitless-btn,
.phq-modal-limitless-btn {
  background: var(--limitless-yellow);
  color: var(--limitless-black);
  border-color: var(--limitless-black);
  font-weight: 700;
}
.phq-limitless-btn:hover,
.phq-modal-limitless-btn:hover { filter: brightness(0.92); }

/* compact ➕ chip on the single-line Latest News rows */
.la-news-limitless-chip {
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-left: 6px;
  background: var(--limitless-yellow); color: var(--limitless-black);
  border-radius: var(--r-chip); font-weight: 700; font-size: 12px; line-height: 1;
  text-decoration: none;
}
.la-news-limitless-chip:hover { filter: brightness(0.92); }

/* the news <li> becomes a flex row so the chip sits beside the link without
   triggering a horizontal scrollbar or a vertical scrollbar in the signals card */
.la-news-item { display: flex; align-items: center; }
.la-news-item .la-news-link { flex: 1 1 auto; min-width: 0; }

/* Build 2026-06-15: non-arb cross-venue disambiguation rows in the Cross-Venue
   card. Single line, no horizontal scroll; logos + venue count on the right.
   Colors via vars only (graphical tenet). */
.crossvenue-disambig-row { display: flex; align-items: center; gap: 6px; min-width: 0; cursor: pointer; }
.crossvenue-disambig-row .sig-title { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* .403 (d): cross-venue BOARD rows reuse the generic .sig-link grid
   (38px 1fr auto) but supply no logo cell, so the title was squeezed into the
   38px logo column — rendering "off" vs the flex disambig rows below. Flex the
   board row's sig-link so title + meta lay out consistently with the rest. */
/* 2026-06-20 (.409): also zero the inherited .sig-link padding (5px 4px desktop /
   7px 4px mobile) and the mobile min-height: 40px — the disambig <li> below has
   neither, so without these resets the first (arb) row sits 4px right + 5–12px
   down + 6–20px taller than the rest. */
.crossvenue-list .sig-link { display: flex; align-items: center; gap: 6px; min-width: 0; padding: 0; min-height: 0; }
.crossvenue-list .sig-link .sig-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crossvenue-list .sig-link .sig-meta { flex: 0 0 auto; justify-self: auto; }
.crossvenue-disambig-row .cv-disambig-meta { flex-shrink: 0; display: flex; align-items: center; gap: 3px; flex-wrap: nowrap; }
.crossvenue-disambig-row .cv-plat-txt { font-size: 10px; color: var(--muted); }
.crossvenue-disambig-row .cv-venues { font-size: 10px; color: var(--muted); margin-left: 2px; }

/* ── ET& LIVE Futuur order-book depth panel (2026-06-20) ──────────────────────
   On the Futuur event modal for ET& subscribers (server-gated; dark by default).
   All colors via CSS vars (graphical tenet): bid = --accent (teal), ask = --danger. */
.ff-depth-card { margin: 10px 0; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--panel); }
.ff-depth-head { display: flex; align-items: center; gap: 8px; min-width: 0;
  font-weight: 700; font-size: 14px; color: var(--text); margin-bottom: 8px; }
.ff-depth-etand { font-size: 10px; font-weight: 800; letter-spacing: .04em;
  padding: 1px 6px; border-radius: 999px; color: var(--bg); background: var(--accent); flex: 0 0 auto; }
.ff-depth-sub { font-size: 12px; font-weight: 500; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ff-d-summary { display: flex; flex-wrap: wrap; gap: 6px 16px;
  padding-bottom: 8px; margin-bottom: 8px; border-bottom: 1px solid var(--border); }
.ff-d-summary > div { display: flex; flex-direction: column; }
.ff-d-k { font-size: 10px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ff-d-v { font-size: 15px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.ff-d-vbid { color: var(--accent); }
.ff-d-vask { color: var(--danger); }
.ff-d-ladders { display: flex; gap: 10px; }
.ff-d-ladders > .ff-d-table { flex: 1 1 0; min-width: 0; }
.ff-d-table { width: 100%; border-collapse: collapse; font-size: 11px; }
.ff-d-table th { text-align: left; font-size: 9px; text-transform: uppercase;
  letter-spacing: .03em; color: var(--muted); padding: 2px 4px; font-weight: 600; }
.ff-d-row > td { padding: 1px 4px; font-variant-numeric: tabular-nums; }
.ff-d-px { color: var(--text); font-weight: 600; }
.ff-d-sz { color: var(--muted); }
.ff-d-cum { position: relative; min-width: 0; }
.ff-d-bar { position: absolute; left: 0; top: 1px; bottom: 1px; border-radius: 2px; z-index: 0; }
.ff-d-bid .ff-d-bar { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.ff-d-ask .ff-d-bar { background: color-mix(in srgb, var(--danger) 22%, transparent); }
.ff-d-cumv { position: relative; z-index: 1; color: var(--text); }
.ff-d-empty { color: var(--muted); text-align: center; padding: 6px; }
.ff-d-foot { margin-top: 8px; font-size: 10px; color: var(--muted); }
@media (max-width: 520px) { .ff-d-ladders { flex-direction: column; } }

/* ── wallet-chips 2026-06-20: ET& wallet-discovery chips + upsell modal +
   similar-results panel. Theme-vars ONLY (dark + peach auto-follow). ───── */

/* chips (spelled-out + inline) */
.pc-chip-bar { display: inline-flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.pc-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; background: transparent; color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  border-radius: var(--r-chip); font-size: 11px; font-family: inherit;
  cursor: pointer; line-height: 1.2; white-space: nowrap;
  transition: color var(--m-tab), background-color var(--m-tab), border-color var(--m-tab);
}
.pc-chip:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.pc-chip.pc-follow-on { color: var(--jackpot, var(--accent)); border-color: color-mix(in srgb, var(--jackpot, var(--accent)) 55%, var(--border)); }
.pc-etand-pill {
  font-size: 9px; font-weight: 700; letter-spacing: .02em;
  padding: 0 4px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent);
}
/* chip-target 2026-09-06 (operator: "larger and clearer for clicking, more
   engaging, within the limits of staying inline").

   1. BIGGER GLYPH, SAME BOX. font-size 13 -> 16px with the horizontal padding
      cut 5 -> 3px. Rendered (Chromium): star 22.8 -> 21.3px, magnifier
      29.9 -> 30px, unfollow x 20.9 -> 19px wide - no wider than before.
   2. ⚠ ROOT r936, MEASURED: THE HIT AREA GROWS VERTICALLY, NEVER SIDEWAYS.
      The first cut used `inset: -8px -6px`, and rendered that (a) pushed every
      .ww-tb-row and anomalies .sig-row 5px past its right edge (8px while
      hovered), (b) gave the right 4px of each chip to the NEXT chip - the group
      gap is 2px and the later sibling paints on top - and (c) covered the
      board's news link and event title beside the bell. Every inline context
      sits a chip 2-8px from another control, so sideways growth always lands
      on one. It grows UP 6px only: that is exactly the dead space above a line-1
      chip (row padding 2 + list gap 1 + border 1 + the previous row's padding 2),
      while the line BELOW starts at the chip's bottom edge - -3px there already
      covered the title link at 450px. 18px box -> 24px target (MEASURED, zero
      steals: the /wallets aside lists 268-450px, anomalies 320-450px). In the board's overflow:hidden
      .dep-cell it is clipped to the cell - no gain there, and no harm.
   3. Affordance: a resting border so it reads as a control, a hover fill, and
      a real focus ring. ⚠ No transform on hover: scale() is scrollable
      overflow, and the rightmost chip is flush with its row's edge.
   `line-height: 1` pins the box to the glyph. */
.pc-chip-inline {
  position: relative;
  padding: 0 3px; font-size: 16px; line-height: 1;
  border-color: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--accent);
  background: transparent; vertical-align: -2px; min-width: 0;
}
/* the click target, not a visual: taller, never wider (see 2 above) - and
   ⚠ ONLY WHERE MEASURED CLEAN. Global, the same 6px reached into the row ABOVE
   in every list whose rows are themselves click targets (li.wallet-link:
   24h/month top lists, hall of fame, biggest wagers) - a tap meant to open one
   wallet would follow the next. Add a context here only after measuring it. */
.ww-tb-row .pc-chip-inline::after,
.anomalies-card .pc-chip-inline::after { content: ""; position: absolute; inset: -6px 0 0; }
.pc-chip-inline:hover {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
/* ⚠ ROOT r936, MEASURED: the ring is drawn INSIDE the box. At offset +2px the
   board's overflow:hidden .dep-cell (exactly chip-tall) clipped its top and
   bottom - a pixel diff showed side bars only; -2px paints the whole ring
   in every list. */
.pc-chip-inline:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* ON must survive the bell no longer changing shape: colour ALONE is not a
   state signal, so the followed chip also fills. */
.pc-chip-inline.pc-follow-on {
  color: var(--jackpot, var(--accent));
  border-color: color-mix(in srgb, var(--jackpot, var(--accent)) 50%, transparent);
  background: color-mix(in srgb, var(--jackpot, var(--accent)) 16%, transparent);
}

/* upsell interstitial */
.pc-upsell-overlay {
  /* upsell-front 2026-07-10 (operator): the ET& sign-up popup was z:1000 while
     content modals climb _frontOverlay's counter from 1010 — so ANY open modal
     covered it. 99990 beats every realistic modal z (the counter would need
     ~9,000 opens/session to catch up) and stays under .pc-toast (100000), so
     toasts still top everything. Also lifts the shared-class subscriber
     popovers (follow-config / Connect-Telegram) above the modals they open from. */
  position: fixed; inset: 0; z-index: 99990; display: flex;
  align-items: center; justify-content: center; padding: 16px;
  background: color-mix(in srgb, var(--bg, #000) 72%, transparent);
}
.pc-upsell-modal {
  position: relative; max-width: 380px; width: 100%;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-card, 12px);
  padding: 22px 20px 20px; box-shadow: var(--elev-2, 0 8px 30px rgba(0,0,0,.4));
  text-align: center;
}
.pc-upsell-x {
  position: absolute; top: 8px; right: 10px; background: none; border: 0;
  color: var(--muted); font-size: 20px; line-height: 1; cursor: pointer;
}
.pc-upsell-pill {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 2px 9px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent);
  margin-bottom: 10px;
}
.pc-upsell-head { font-size: 16px; font-weight: 600; margin-bottom: 6px; }
.pc-upsell-sub { font-size: 13px; color: var(--muted); margin-bottom: 14px; }
.pc-upsell-f100 {
  font-size: 12px; color: var(--jackpot, var(--accent));
  margin-bottom: 14px; padding: 8px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--jackpot, var(--accent)) 10%, transparent);
}
.pc-upsell-f100 a { color: inherit; text-decoration: underline; }
.pc-upsell-cta {
  display: block; width: 100%; padding: 10px; box-sizing: border-box;
  background: var(--accent); color: var(--bg, #001); border-radius: var(--r-chip);
  font-weight: 700; font-size: 14px; text-decoration: none; margin-bottom: 8px;
}
.pc-upsell-cta:hover { filter: brightness(1.06); }
.pc-upsell-sec {
  display: inline-block; background: none; border: 0; color: var(--muted);
  font-size: 12px; cursor: pointer; text-decoration: none;
}
.pc-upsell-sec:hover { color: var(--text); }

/* similar-results panel */
.pc-similar-overlay {
  position: fixed; inset: 0; z-index: 1000; display: flex;
  align-items: center; justify-content: center; padding: 16px;
  background: color-mix(in srgb, var(--bg, #000) 72%, transparent);
}
.pc-similar-modal {
  position: relative; max-width: 560px; width: 100%; max-height: 82vh;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-card, 12px);
  box-shadow: var(--elev-2, 0 8px 30px rgba(0,0,0,.4)); padding: 18px;
}
.pc-similar-x { position: absolute; top: 8px; right: 10px; background: none; border: 0; color: var(--muted); font-size: 20px; cursor: pointer; }
.pc-similar-head { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.pc-similar-head code { font-size: 13px; color: var(--accent); }
.pc-similar-summary { font-size: 12px; color: var(--muted); margin-bottom: 10px; }
.pc-similar-bulk { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; margin-bottom: 8px; }
.pc-sim-followsel {
  background: var(--accent); color: var(--bg, #001); border: 0;
  border-radius: var(--r-chip); padding: 5px 10px; font-weight: 600; font-size: 12px; cursor: pointer;
}
.pc-sim-followsel:disabled { opacity: .5; cursor: default; }
.pc-similar-body { overflow-y: auto; min-height: 0; }
.pc-sim-spin, .pc-sim-empty { font-size: 13px; color: var(--muted); padding: 18px 4px; text-align: center; }
.psim-row {
  display: flex; align-items: center; gap: 8px; padding: 6px 2px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  font-size: 12px; min-width: 0;
}
.psim-check { flex: 0 0 auto; }
.psim-addr { flex: 0 0 auto; color: var(--accent); text-decoration: none; font-family: var(--mono, monospace); }
.psim-addr:hover { text-decoration: underline; }
.psim-score { flex: 0 0 auto; font-weight: 700; font-family: var(--mono, monospace); }
.psim-dots { flex: 0 0 auto; display: inline-flex; gap: 2px; }
.psim-dot { width: 7px; height: 7px; border-radius: 50%; background: color-mix(in srgb, var(--muted) 40%, transparent); }
.psim-dot.on { background: var(--accent); }
.psim-stat { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.psim-lowconf { flex: 0 0 auto; color: var(--danger, #f87171); font-size: 11px; }
.psim-following { flex: 0 0 auto; color: var(--jackpot, var(--accent)); font-size: 11px; }

/* toast */
.pc-toast {
  position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 12px);
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--r-chip); padding: 9px 16px; font-size: 13px;
  /* sim-aka 2026-07-08: toasts must never be occluded. The .254 overlay manager
     assigns modals a climbing inline z-index (now based at 1000 so it clears the
     chip overlays) — after enough opens it would pass a fixed 1100, so pin the
     toast effectively always-on-top. */
  z-index: 100000;
  opacity: 0; transition: opacity .25s, transform .25s; box-shadow: var(--elev-2, 0 8px 30px rgba(0,0,0,.4));
}
.pc-toast.pc-toast-in { opacity: 1; transform: translate(-50%, 0); }
.wm-chip-bar { margin-top: 8px; } /* wallet-chips 2026-06-20 */
.pc-inline-chips { display: inline-flex; gap: 2px; flex: 0 0 auto; margin-left: 4px; } /* wallet-chips 2026-06-20 */
.smh-row .pc-inline-chips, .sw-row .pc-inline-chips { vertical-align: middle; }

/* ettau 2026-07-02: ETτ (TeeKee) — Highest-Conviction card + group-modal
   headline. Presentation only; band classes are server-assigned via the GATED
   /api/etand/ettau (the public page carries no thresholds, no scores). */
.ettau-badge { font-size: 10px; font-weight: 800; color: var(--accent); border: 1px solid var(--accent); border-radius: var(--r-pill); padding: 1px 6px; vertical-align: middle; margin-left: 6px; }
.ettau-locked-msg { color: var(--muted); font-size: 12px; padding: 10px 12px; }
.ettau-locked-msg a { color: var(--accent); font-weight: 700; }
.ettau-row { display: flex; align-items: center; gap: 8px; }
.ettau-chip { font-weight: 800; font-variant-numeric: tabular-nums; border-radius: var(--r-chip); padding: 1px 8px; flex: 0 0 auto; }
.ettau-chip-strong   { color: var(--success); border: 1px solid var(--success); }
.ettau-chip-moderate { color: var(--jackpot); border: 1px solid var(--jackpot); }
.ettau-chip-weak     { color: var(--muted); border: 1px solid var(--border); }
.ettau-meta { flex: 0 0 auto; color: var(--muted); font-size: 11px; white-space: nowrap; }
.eg-ettau { margin: 6px 0 8px; font-size: 13px; }
.eg-ettau-strong   { color: var(--success); }
.eg-ettau-moderate { color: var(--jackpot); }
.eg-ettau-weak     { color: var(--muted); }
.eg-ettau-locked   { color: var(--muted); }
.eg-ettau-locked a { color: var(--accent); font-weight: 700; }

/* etand-alerts-p2 2026-06-21: per-option alert checkbox + event chip */
.pc-evt-chip { color: var(--jackpot, var(--accent)); }
.opt-bell { accent-color: var(--accent); cursor: pointer; margin-right: 4px; vertical-align: -1px; }
.wm-evt-follow { margin: 8px 0; }
.dep-event .pc-evt-chip { flex-shrink: 0; } /* .427-adapt: board bell lives INSIDE the flex dep-event cell */


/* ── .427 MOBILE PASS (operator 2026-07-01: "boxes stack upon each other and
   the tabs seem obsolete") — phone-width fixes, geometry only, all theme-safe.
   KEEP THIS BLOCK LAST IN THE FILE: it overrides same-specificity base rules
   purely by source order (no !important anywhere). ──────────────────────── */
@media (max-width: 700px) {
  /* Tab strips: flex-wrap turned them into stacked banner-buttons on phones
     (the "obsolete tabs" look). One row, swipeable; pills keep their tab
     affordance. Sub-tab strips (.lq-subtabs/.smh-subtabs) already fit. */
  .lq-tabs, .cv-tabs, .smh-tabs {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .lq-tabs::-webkit-scrollbar, .cv-tabs::-webkit-scrollbar, .smh-tabs::-webkit-scrollbar { display: none; }
  .lq-tab, .cv-tab, .smh-tab { white-space: nowrap; flex: 0 0 auto; }

  /* Federated Board rows: the shared 6-col template's FIXED columns
     (86+84+62+58px + five 8px gaps) ≈ a phone's full width, so the fr/minmax
     EVENT + LEADER columns compute to 0px — titles were invisible. Re-flow
     each row to two lines: title full-width on top, then
     status | venue | leader | closes | Δ. The dep-head column captions no
     longer line up with anything (and are the tap-sort affordance — sort is
     desktop-only for now), so hide them; the 2-line rows self-describe. */
  .dep-head { display: none; }
  .board-card-row.dep-row {
    grid-template-columns: auto auto minmax(0, 1fr) auto auto;
    grid-template-rows: auto auto;
    row-gap: 2px;
  }
  .board-card-row.dep-row .dep-event  { grid-column: 1 / -1; grid-row: 1; }
  .board-card-row.dep-row .dep-status { grid-column: 1; grid-row: 2; }
  .board-card-row.dep-row .dep-venue  { grid-column: 2; grid-row: 2; }
  .board-card-row.dep-row .dep-leader { grid-column: 3; grid-row: 2; }
  .board-card-row.dep-row .dep-closes { grid-column: 4; grid-row: 2; }
  .board-card-row.dep-row .dep-delta  { grid-column: 5; grid-row: 2; }

  /* Marketplace Activity: keep EVERY column (no data hidden — display tenet);
     the card scrolls horizontally instead of clipping the Δ columns. */
  .marketplace-card { overflow-x: auto; }
  .mkt-table { min-width: 540px; }

  /* Sharp-hub movers: the .415 single-line inline context overflows
     off-screen at phone width — context returns to its own line UNDER the
     title on phones only (desktop keeps the .415 compact inline form). */
  .smh-mv-main { flex-direction: column; align-items: flex-start; gap: 2px; }
  .smh-mv-ctx { max-width: 100%; }

  /* Header: ~500px of mascot + chrome before any content at 390px wide.
     Shrink the mascot and tighten paddings; everything else keeps its place. */
  .header-mascot { width: 64px; }
  header { padding: 10px 12px; gap: 8px; }

  /* .441 mobile tab redesign (operator: "the general UI on mobile still
     displays the old tabs"): the .427 pass made the strips one-row swipeable
     but the buttons kept their desktop tab look and nothing signalled
     off-screen tabs. Phones now render COMPACT PILL CHIPS (the ET& dashboard
     treatment) with an accent-filled active state + a right-edge fade that
     says "more tabs this way"; the control-tower strip joins the one-row
     swipe set (missed in .427). Theme vars only → dark + peach. Order-wins:
     these rules must stay inside this LAST media block. */
  .ct-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
             -webkit-overflow-scrolling: touch; }
  .ct-tabs::-webkit-scrollbar { display: none; }
  .ct-tab { white-space: nowrap; flex: 0 0 auto; }
  .lq-tabs, .cv-tabs, .smh-tabs, .ct-tabs, .smh-subtabs {
    -webkit-mask-image: linear-gradient(90deg, #000 92%, transparent 99.5%);
    mask-image: linear-gradient(90deg, #000 92%, transparent 99.5%);
    scroll-snap-type: x proximity; scroll-padding-left: 4px;
  }
  .lq-tab, .cv-tab, .smh-tab, .ct-tab, .smh-subtab {
    font-size: 11px; padding: 4px 11px; border-radius: 999px;
    border: 1px solid var(--border); background: transparent;
    color: var(--muted); scroll-snap-align: start;
  }
  .lq-tab.is-active, .cv-tab.is-active, .smh-tab.is-active,
  .ct-tab.is-active, .smh-subtab.is-active {
    background: var(--accent); border-color: var(--accent);
    color: var(--chip-ink); font-weight: 800;
  }
}

/* fx-deepen 2026-07-04 (B2): ForecastEx modal "Tape (EOD)" block + carry line.
   Dark until FORECASTEX_ENABLED — ships with the venue. All colors via CSS
   vars (graphical tenet). Flex rows, single-line, label ellipsizes (no-h-scroll
   rule); details collapses to a one-line summary when closed. */
.fx-tape-details { margin: 10px 0; font-size: 12px; }
.fx-tape-details > summary { cursor: pointer; color: var(--muted); font-weight: 600; }
.fx-tape-details[open] > summary { color: var(--text); }
.fx-tape-asof { font-size: 10px; font-weight: 500; color: var(--muted); }
.fx-carry-line { color: var(--muted); font-size: 11px; margin: 5px 0 4px; }
.fx-carry-line b { color: var(--accent); }
.fx-tape-row { display: flex; flex-wrap: nowrap; align-items: baseline; gap: 8px;
  min-width: 0; padding: 2px 0; border-bottom: 1px solid var(--border);
  font-family: monospace; font-size: 11px; }
.fx-tape-row:last-child { border-bottom: none; }
.fx-tape-label { flex: 1 1 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.fx-tape-vwap { color: var(--accent); flex-shrink: 0; }
.fx-tape-path, .fx-tape-n, .fx-tape-large { color: var(--muted); flex-shrink: 0; }

/* rothera-trade-tape P2 2026-08-03: Rothera per-contract Tape (EOD) block +
   per-option VWAP chip. Mirrors .fx-tape-* / .opt-range (theme vars only,
   no color literals; flex + min-width:0 + ellipsis so it never overflows). */
.rothera-tape-details { margin: 10px 0; font-size: 12px; }
.rothera-tape-details > summary { cursor: pointer; color: var(--muted); font-weight: 600; }
.rothera-tape-details[open] > summary { color: var(--text); }
.rothera-tape-asof { font-size: 10px; font-weight: 500; color: var(--muted); }
.rothera-tape-row { display: flex; flex-wrap: nowrap; align-items: baseline; gap: 8px;
  min-width: 0; padding: 2px 0; border-bottom: 1px solid var(--border);
  font-family: monospace; font-size: 11px; }
.rothera-tape-row:last-child { border-bottom: none; }
.rothera-tape-label { flex: 1 1 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.rothera-tape-vwap { color: var(--accent); flex-shrink: 0; }
.rothera-tape-n, .rothera-tape-large { color: var(--muted); flex-shrink: 0; }
.opt-vwap { display: inline-block; font-size: 10px; font-family: monospace;
  color: var(--accent); border: 1px solid var(--border); border-radius: 4px;
  padding: 0 4px; margin-left: 4px; vertical-align: 1px; white-space: nowrap; }

/* .463 (operator, GENERAL RULE): an unpopulated range-tab is never presented.
   pcHideEmptyTabs() (index.html) marks any tab button whose paired panel has
   no rows; server-side slice conditions handle initial render and this class
   is the general net (JS-populated or emptied-later panels included). */
.tab-unpopulated { display: none !important; }

/* ── frozen-panes 2026-07-18 (operator): app-shell — frozen top (brand + the
   two tickers) + collapsible left sidenav on BOTH UIs. Theme-vars only.
   position:sticky works here BECAUSE html/body use overflow-x:clip (clip does
   not create a scroll container; the @supports hidden fallback degrades to a
   normal scrolling header on legacy engines — acceptable). ──────────────── */
:root { --shell-side-w: 200px; --shell-rail-w: 52px; --shell-shadow: rgba(0,0,0,.35); }
body.pc-shell { padding-left: var(--shell-side-w); transition: padding-left .18s ease; }
body.pc-shell.pc-rail { padding-left: var(--shell-rail-w); }
/* frozen top (free UI): the real header + both tickers stick, stacked. */
/* shell-v3 2026-07-18 (operator): the frozen band spans the FULL width — the
   pane now starts UNDER the tickers (the spreadsheet frozen-pane corner), so
   the band cancels the body's sidenav padding with a negative margin. */
body.pc-shell > header { position: sticky; top: 0; z-index: 420; background: var(--bg);
  margin-left: calc(-1 * var(--shell-side-w)); transition: margin-left .18s ease; }
body.pc-shell.pc-rail > header { margin-left: calc(-1 * var(--shell-rail-w)); }
body.pc-shell .unified-ticker-section:not(.pc-shell-ticker) {
  position: sticky; top: var(--shell-h-hdr, 0px); z-index: 419; background: var(--bg);
  margin-left: calc(-1 * var(--shell-side-w)); transition: margin-left .18s ease; }
body.pc-shell .topics-ticker-section:not(.pc-shell-ticker) {
  position: sticky; top: calc(var(--shell-h-hdr, 0px) + var(--shell-h-t1, 0px));
  z-index: 418; background: var(--bg);
  margin-left: calc(-1 * var(--shell-side-w)); transition: margin-left .18s ease; }
body.pc-shell.pc-rail .unified-ticker-section:not(.pc-shell-ticker),
body.pc-shell.pc-rail .topics-ticker-section:not(.pc-shell-ticker) {
  margin-left: calc(-1 * var(--shell-rail-w)); }
/* condensed: while scrolled, the tall header internals hide — the brand row
   (+ right-side controls) and the tickers are what remain permanent. */
/* shell-v4 2026-07-19 (operator reminder): the frozen top = the WHOLE head
   block — everything from the top until the bottom of the tickers, ALWAYS.
   The condensed-on-scroll hiding of .hero-stack/.meta is retired; the
   pc-scrolled class still toggles (harmless) and measure() keeps offsets true.
   .544: retired on DESKTOP only — below 900px the condensation returns (see the
   shell-mobile-condense rule in the max-width:900px block; operator decision). */
/* frozen top (ET& pages): the partial's brand strip + light ticker strips. */
.pc-shell-top { position: sticky; top: 0; z-index: 420; background: var(--bg);
  border-bottom: 1px solid var(--border);
  /* shell-v3: full-bleed on ET& pages — cancel the pane column AND the
     .etand-page frame padding (2.5rem top / 1.5rem sides). */
  /* shell-audit .543: the shell's body padding REPLACES the .etand-page
     frame's left padding (it doesn't add to it), so cancel ONLY the pane
     column — the old extra -1.5rem term overshot and clipped the strip's
     left edge 24px off-screen. Top/right still cancel the frame. */
  /* mobile-pass .861: the frame-cancel is now the frame owner's OWN vars
     (see body.etand-page below). Hardcoded -2.5rem/-1.5rem drifted from
     the frame twice: .641 shrank the frame below 700px and the cancel
     never followed (12px off-screen on every ET& phone view), and
     /home + /events have no frame at all (24px off-screen; the brand
     mascot was clipped 10px at 375px, measured live). Pages without the
     frame get 0 via the var defaults. */
  margin: calc(-1 * var(--pc-frame-y, 0rem)) calc(-1 * var(--pc-frame-x, 0rem))
          1.25rem calc(-1 * var(--shell-side-w));
  transition: margin-left .18s ease; }
body.pc-rail .pc-shell-top { margin-left: calc(-1 * var(--shell-rail-w)); }
/* mobile-pass .861: THESE VALUES MUST EQUAL .etand-page's padding (both
   defined in etand/_base.html; the <=700px pair from its .641 block).
   test_mobile_pass_861 parses both files and asserts the equality. */
body.etand-page { --pc-frame-y: 2.5rem; --pc-frame-x: 1.5rem; }
@media (max-width: 700px) {
  body.etand-page { --pc-frame-y: 1.25rem; --pc-frame-x: 0.75rem; }
}
.pc-shell-brand { display: flex; align-items: baseline; gap: 10px; padding: 8px 14px 4px; }
.pc-shell-brand-a { color: var(--text); text-decoration: none; font-weight: 800; font-size: 17px; letter-spacing: 0.02em; }
.pc-shell-brand-a:hover { color: var(--accent); }
.pc-shell-brand-sub { color: var(--muted); font-size: 11px; }
/* markets-hub 2026-08-20 (operator item 3): /markets two-column layout - charts
   left, Marketplace Activity + 7d/weekly right. Single column under 1100px
   (the aside drops BELOW; no h-scroll - both columns minmax(0,...)). */
/* mkt-widen .886 (operator: "move the boxes to the left of MARKETPLACE
   ACTIVITY farther to the left, widen the MARKETPLACE ACTIVITY list and get
   rid of its scroll bar"). Three levers, all measured in a real-macro
   harness before shipping:
     - max-width 1460 -> 1600: on wide screens the whole grid gains 140px and
       its LEFT EDGE moves 70px left (the "boxes farther left" half).
     - the split flips from 1.4fr/1fr (58/42) to 1.05fr/1fr above 1360px:
       the Marketplace Activity column measured 602 -> 773px at 1720px
       viewport, 587 -> 687px at 1440.
     - 1100-1360px gets an even 50/50 split - that band is where the column
       was tightest and where the horizontal scrollbar appeared, and the
       scrollbar IS the overflow: give the column the width and the bar goes
       (the <=700px .mkt-table min-width stays - phones scroll BY DESIGN,
       .861 mobile-pass). */
.mtx-grid { max-width: 1920px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 1100px) {
  .mtx-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
}
@media (min-width: 1360px) {
  /* .886 rev 2 (operator, with screenshot): "A LOT of real estate to the
     left ... the right side boxes should be wider" - cap 1920 consumes the
     idle margins on wide screens, and the bias flips to the RIGHT column
     (the left holds fixed-width content that gains nothing from width). */
  .mtx-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
}
.mtx-left { min-width: 0; }
.mtx-right { min-width: 0; }
.mtx-right .marketplace-card { margin-top: 14px; }
.mtx-right .board-stats-band.mtx-stats { display: flex; flex-direction: column; gap: 14px; margin-top: 14px; }
.mtx-right .mkt-7d-wrap, .mtx-right .mkt-weekly-wrap {
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; min-width: 0;
}
.pc-shell-ticker .pc-shell-tk-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }

/* venue-unnamed 2026-08-26: the title slot is carrying a NOTE about the venue,
   not a market name. Muted + italic so it reads as metadata at a glance and is
   never mistaken for an event. Vars only - it follows every theme. */
.pc-shell-tk-title.tk-title-unnamed { color: var(--muted); font-style: italic; }
.pc-shell-tk-tag { color: var(--accent); font-weight: 700; }
/* the sidenav — full-height fixed rail/pane, above the frozen top. */
/* shell-v3 2026-07-18 (operator): the pane's options sit UNDER the two-ticker
   line — top tracks the measured frozen-band height (--shell-top-h, set by the
   partial's measure()); z drops below the band since they no longer overlap. */
.pc-sidenav { position: fixed; left: 0; top: var(--shell-top-h, 0px); bottom: 0;
  width: var(--shell-side-w);
  z-index: 415; background: var(--panel); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px; padding: 8px 6px;
  transition: width .18s ease, top .15s ease; overflow: hidden; }
body.pc-rail .pc-sidenav { width: var(--shell-rail-w); }
.pc-sidenav-collapse { font: inherit; background: transparent; color: var(--muted);
  border: 1px solid var(--border); border-radius: var(--r-card, 8px); cursor: pointer;
  padding: 4px 0; margin-bottom: 8px; width: 100%; }
.pc-sidenav-collapse:hover { color: var(--accent); border-color: var(--accent); }
.pc-sidenav-item { display: flex; align-items: center; gap: 9px; padding: 8px 9px;
  border-radius: var(--r-card, 8px); color: var(--text); text-decoration: none;
  /* etand-polish 2026-07-18 (operator): larger General / ET& labels; the
     font/background/border resets let the Sign-up <button> variant match. */
  font-size: 1rem; font-weight: 700; white-space: nowrap; min-width: 0;
  font-family: inherit; background: transparent; border: 0; cursor: pointer;
  text-align: left; width: 100%; }
.pc-sidenav-item:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.pc-sidenav-item.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent); }
.pc-sidenav-ico { flex-shrink: 0; width: 20px; text-align: center; }
/* etand-polish 2026-07-18 (operator: "put a background behind the popup"):
   .pc-followcfg-modal — the shared popup PANEL (follow-config thresholds, the
   Sign-up window) had NO css rules at all: a transparent box floating on the
   dim (the wds modal styled itself separately, masking the gap). Theme-var
   panel; peach follows. */
.pc-followcfg-modal { background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-card, 12px); padding: 16px 18px; width: 100%;
  max-width: 430px; max-height: 85vh; overflow: auto; position: relative;
  box-shadow: 0 18px 60px var(--shell-shadow, rgba(0,0,0,.35)); }
/* the Sign up / Sign in window's content */
.pc-shell-signup-head { font-size: 1.15rem; font-weight: 800; margin-bottom: 6px; color: var(--text); }
.pc-shell-signup-sub { color: var(--muted); font-size: 0.85rem; margin: 0 0 14px; }
.pc-shell-signup-cta { display: block; text-align: center; padding: 9px 12px; border-radius: 999px;
  background: var(--accent); color: var(--bg); font-weight: 800; text-decoration: none; margin-bottom: 10px; }
.pc-shell-signup-cta:hover { background: var(--jackpot); }
.pc-shell-signup-alt { display: block; text-align: center; color: var(--accent); font-size: 0.85rem; text-decoration: none; }
.pc-shell-signup-alt:hover { text-decoration: underline; }
/* etand-polish: Trackster in the ET& strip — in-flow at the brand row's right
   end (never obscures / never obscured); the .etand-header originals hide. */
.pc-shell-mascot { margin-left: auto; align-self: center; }
/* .546 (operator): the adopted .etand-header (relocated into the strip by the
   partial boot) drops its page-flow spacing — it is now a band row between the
   brand row and the tickers. Higher specificity beats the legacy literals. */
.pc-shell-top .etand-header { margin: 0; padding: 2px 14px 6px; border-bottom: 0; }
.etand-header .etand-mascot { display: none !important; }
body.pc-rail .pc-sidenav-lbl { display: none; }
/* shell-v3 2026-07-18 (operator): Trackster moves from the header's right side
   to the TOP-LEFT corner (the frozen-pane A1 cell). Absolute inside the sticky
   header overrides both breakpoints' flex/grid placements; the brand shifts
   right to clear him. Feet still dangle (the existing charm), now corner-side. */
/* etand-polish 2026-07-18 (operator): Trackster's box = the LIVE FEED pink
   label's width (measured into --shell-mascot-w) by the header's height
   (--shell-h-hdr) — from the top of the band down to that pink label. The
   inner SVG letterboxes (xMidYMid meet) so he scales, never distorts. */
/* shell-audit .543: desktop-only — below 900px the mob-hdr grid keeps its
   own mascot placement anyway, and the LIVE FEED label measures full-row
   there (--shell-mascot-w would hit ~375px and shove the brand off-screen). */
@media (min-width: 901px) {
body.pc-shell .header-mascot { position: absolute; left: 0; top: 0;
  width: var(--shell-mascot-w, 84px); height: var(--shell-h-hdr, 64px);
  aspect-ratio: auto; margin: 0; align-self: unset; justify-self: unset; z-index: 7; }
body.pc-shell .brand { margin-left: calc(var(--shell-mascot-w, 84px) + 10px); }
}
/* narrow viewports: the shell reserves only the rail; an expanded pane
   OVERLAYS content instead of pushing it. */
@media (max-width: 900px) {
  body.pc-shell, body.pc-shell.pc-rail { padding-left: var(--shell-rail-w); }
  body.pc-shell:not(.pc-rail) .pc-sidenav { box-shadow: 8px 0 24px var(--shell-shadow); }
  /* shell-audit .543: below 900px the body reserves ONLY the rail (an expanded
     pane OVERLAYS) — so the frozen band must always cancel just the rail. The
     class-keyed -200px variant shifted the whole band 148px off-screen the
     moment the pane was expanded on a phone. */
  body.pc-shell > header,
  body.pc-shell .unified-ticker-section:not(.pc-shell-ticker),
  body.pc-shell .topics-ticker-section:not(.pc-shell-ticker) {
    margin-left: calc(-1 * var(--shell-rail-w)); }
  body.pc-shell .pc-shell-top { margin-left: calc(-1 * var(--shell-rail-w)); }
  /* shell-mobile-condense .544 (operator picked option 2 of the .543 audit):
     on phones the full-head freeze ate ~40-49%% of the viewport — below 900px
     the tall header middle (.hero-stack/.meta) scrolls away past 40px while
     the brand row + both tickers stay frozen (the .538 behavior, phone-scoped).
     Desktop keeps the shell-v4 full-head freeze. The boot JS already toggles
     pc-scrolled + re-measures (plus the .543 ResizeObserver), so the tickers'
     sticky offsets and the sidenav top track the shrunk band automatically. */
  body.pc-shell.pc-scrolled .hero-stack,
  body.pc-shell.pc-scrolled .meta { display: none; }
}

/* .466 (operator): the event-modal Follow chip lives in the TOP banner now
   (was the last element of the card). Right-aligned on the platform row;
   compacted so the 'ET& + bell + label' button reads as a banner action. */
.modal-platform { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.modal-platform .wm-evt-follow-top { margin-left: auto; }
.modal-platform .wm-evt-follow-top .pc-evt-chip { padding: 3px 9px; font-size: 11px; }

/* ── wds-legend .467 (operator): "Where do I start?" ──────────────────────────
   Trigger pill sits inside the header .meta row (zero banner growth, live-
   measured at 375/1200/1280 before shipping); the panel is a fixed overlay on
   the site modal shell. Operator color spec: labels bold KELLY GREEN, ET&
   bold SHOCKING PINK/FUCHSIA, SUBSCRIBERS ONLY bold GOLD + gold descriptions.
   Peach theme lowers each hue for contrast on the cream background. */
.wds-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border, #334155); background: transparent;
  color: var(--muted, #94a3b8); font: inherit; font-size: 11.5px;
  font-weight: 700; cursor: pointer; white-space: nowrap;
  transition: color 0.12s, border-color 0.12s;
}
.wds-btn:hover { color: var(--text, #e2e8f0); border-color: var(--accent, #2dd4bf); }
@media (max-width: 768px) {
  .wds-btn { font-size: 10px; padding: 3px 8px; gap: 3px; }
}
.wds-modal {
  /* wds-wide 2026-07-08 (operator): enlarged so the 15 items fit scroll-free
     (2-column list ≥900px below); overflow stays auto purely as a short-
     viewport/phone safety — 15 items cannot physically fit a 375×667 screen. */
  max-width: 1120px; width: calc(100vw - 32px); max-height: 92vh; overflow-y: auto;
  /* explicit OPAQUE panel — the shared shell reads transparent over the busy
     homepage (the ".465 transparent windows" complaint class); solid bg +
     border keep the legend legible wherever it opens. */
  background: var(--panel, #141b33);  /* panel-bright 2026-07-10: match the modal family */
  border: 1px solid var(--border, #334155);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
}
[data-theme="peach"] .wds-modal {
  background: var(--panel, #FFE3D6);  /* panel-bright 2026-07-10; fallback synced to the .492 round-2 shade */
  border-color: #e8d9c4;
  box-shadow: 0 18px 60px rgba(90, 60, 20, 0.25);
}
.wds-sub { margin: 0 0 10px; font-size: 12px; color: var(--muted, #94a3b8); }
/* .468 (operator revision): descriptions after the dash = BLACK (true black on
   the peach/cream panel the operator reads; the dark panel is near-black so
   literal black would vanish — dark uses the theme's strong text color, same
   intent); SUBSCRIBERS ONLY = bold RED; wider gaps between items. */
.wds-list { margin: 0; padding-left: 1.35rem; font-size: 12.5px; line-height: 1.7; color: var(--text, #e2e8f0); }
.wds-list li { margin-bottom: 15px; }
.wds-label { font-weight: 800; color: #4cbb17; letter-spacing: 0.02em; }   /* kelly green */
.wds-etand { font-weight: 800; color: #ff1aa8; }                           /* shocking pink / fuchsia */
.wds-subonly { font-weight: 800; color: #ff3b30; }                         /* RED */
.wds-desc  { font-weight: 400; }                                           /* description: list text color */
.wds-tag   { white-space: nowrap; }
[data-theme="peach"] .wds-list { color: #111111; }                         /* BLACK on the cream panel */
[data-theme="peach"] .wds-label { color: #2f7d0f; }
[data-theme="peach"] .wds-etand { color: #d6088f; }
[data-theme="peach"] .wds-subonly { color: #c62828; }

/* ── hot-wallets-100 .471: wallet-context sub-line + last-5 W/L dots ───────── */
.smh-row-2ln { align-items: flex-start; }
.smh-row-2ln .smh-mv-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.smh-wctx { display: flex; align-items: center; gap: 7px; font-size: 10px; color: var(--muted); flex-wrap: wrap; }
.smh-wctx-logo { border-radius: 2px; flex-shrink: 0; }
.smh-wctx-plat { text-transform: uppercase; font-weight: 700; font-size: 9px; }
.smh-wctx-item { white-space: nowrap; }
.smh-l5 { display: inline-flex; gap: 2px; align-items: center; }
.smh-l5 i { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
.smh-l5-w { background: var(--success, #22c55e); }
.smh-l5-l { background: var(--danger, #f43f5e); }
/* 10 numeric pager buttons must fit a half column */
.smh-subtabs-10 .smh-subtab { padding: 1px 5px; font-size: 9.5px; min-width: 17px; }

/* ww-table 2026-07-08 (operator): Wallets & Whales TABLE layout — column-title
   header row + grid-aligned cells + content-fit card width. The SAME column
   template drives .smh-th and .smh-tbl-row, so titles align with data by
   construction. Includes the .471 sub-line styles (wctx logo / last-5 dots /
   10-page subtabs) this sheet predates, so the block is self-contained. */
.sharp-hub { width: fit-content; max-width: 100%; margin-inline: auto; }
/* ww-news-row 2026-07-10 (operator): WALLETS & WHALES pinned LEFT at content width
   + a standalone LATEST NEWS / ELECTIONS box filling the space to its right. The
   row-scoped rule (.ww-news-row > .sharp-hub) out-specifies the margin-inline:auto
   above, so W&W left-aligns inside the flex row. flex-wrap + min-width:0 preserve
   the no-horizontal-scrollbar rule; ≤768px stacks (news below W&W). */
.ww-news-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; margin: 10px 20px; }
/* whale-alerts 2026-08-17: rows only. The BOX chrome is .ww-top-box (the .808
   package) - re-declaring it here would fork the two cells' styling the first
   time either changed. The row is FLEX, never a fixed-column grid: a missing
   chip or an anonymous venue leaves a cell out, and a grid would push a sibling
   into the wrong column (the .230 lesson). min-width:0 + ellipsis on the title
   are what hold the no-horizontal-scrollbar rule. The is-new tint is a
   color-mix over --accent, so the peach theme follows and no literal appears. */
.ww-al-row { display: flex; flex-wrap: nowrap; align-items: baseline; gap: 8px; }
.ww-al-row.is-new { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.ww-al-amt { flex: 0 0 auto; font-weight: 700; color: var(--whale); font-variant-numeric: tabular-nums; }
.ww-al-plat, .ww-al-ts { flex: 0 0 auto; color: var(--muted); }
.ww-al-who { flex: 0 0 auto; }
.ww-al-ev { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ww-news-row > .sharp-hub { margin: 0; flex: 0 1 auto; }
/* wallets-top-bets 2026-08-17 (operator, spec §4.1): /wallets = Wallets & Whales
   LEFT-ALIGNED with the biggest-bets column filling the space to its right.
   Same mechanism as .ww-news-row above - the row-scoped rule out-specifies
   `.sharp-hub { margin-inline: auto }`, so dropping the centring reclaims both
   263px gutters instead of just one. flex-wrap + min-width:0 keep the
   no-horizontal-scrollbar rule; below ~1100px there is no room for two columns
   and the panel stacks UNDER the box (its flex-basis forces the wrap). */
.ww-topbets-row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 16px; margin: 10px 20px; }
/* ww-lists-sidebar 2026-08-18 (operator: "make the WALLETS tab top-10 lists
   narrower so that they fit TO THE RIGHT of the HOT WALLETS box"): the box was
   content-sized at 847px inside a 1185px row, leaving ~338px of DEAD SPACE to
   its right while the lists sat full-width ABOVE the table. Growing the box
   into that space is what makes room for the sidebar - without it the panel is
   826px, exactly what the table already wants, and the lists can only stack. */
.ww-topbets-row > .sharp-hub { margin: 0; flex: 1 1 auto; }
.ww-topbets-col {
  margin: 0; flex: 1 1 420px; min-width: 0; align-self: stretch;
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-card); padding: 8px 10px 10px; overflow: hidden;
}
/* topbets-split 2026-08-29: the column carries TWO stacked halves. Each half
   is its own titled box; the divider only appears when the second half exists,
   so a single-half column shows no orphan rule (NO-EMPTY-BOXES). */
/* ⚠ container-type 2026-09-07 (ts-inline, below): the HALF is the query
   container for its own rows. It has to be the half and not the column,
   because the two halves get different tails and only one of them forks.
   MEASURED, no layout cost: the aside is `flex: 1 1 420px; min-width: 0`, so
   its width comes from the flex basis and not from the halves' intrinsic
   contribution — asideW is byte-identical at 268 / 322 / 450 / 1145 with and
   without this line. */
.ww-tb-half { display: flex; flex-direction: column; min-height: 0;
              container-type: inline-size; }
/* ⚠ DIVIDER 2026-09-07 (operator: "let's even them to match"). `.932` made
   the row separators darker and thereby INVERTED this panel's hierarchy - the
   rules WITHIN each list outranked the divider BETWEEN the two lists, which both
   `.932` verifiers flagged independently. Same expression as the rows, so the two
   read as equals rather than one shouting over the other.
   ⚠ Two-step for the same reason as the rows: a lone color-mix() border is a
   SINGLE declaration, so a renderer without support drops it and the two lists
   would run together with NO divider at all.
   ⚠ The COLUMN'S OUTER BORDER is deliberately left at var(--border): every
   card on the page shares that frame, so darkening this one would fix a
   panel-level inconsistency by creating a page-level one. */
.ww-tb-half + .ww-tb-half { margin-top: 10px; padding-top: 8px;
                            border-top: 1px solid var(--border);
                            border-top: 1px solid
                              color-mix(in srgb, var(--border) 80%, var(--text)); }
.ww-tb-list { display: flex; flex-direction: column; gap: 1px; }
/* ⚠ SEPARATOR 2026-09-07 (operator: "for bot cumulative and biggest trade,
   make the lines between entries a bit more visible / dark"). BOTH halves.

   `var(--border)` alone is a PANEL-EDGE tone, not a row rule, and on peach —
   THE DEFAULT THEME — it measured 1.103:1 against the panel it sits on: a
   luminance gap of 0.08, i.e. functionally no line at all. Mixing a quarter of
   the theme's own ink into it keeps one declaration honest on both themes,
   because --text is dark on peach and light on dark, so the SAME expression
   darkens one and lightens the other. A per-theme pair of literals would be
   two things to keep true and would break the var()-only house rule.

   MEASURED against the panel each row actually sits on (getComputedStyle on
   the rendered row, contrast per WCAG 2 relative luminance):
       peach (default)   1.103:1  ->  1.566:1   (luminance gap 0.080 -> 0.311)
       dark              1.458:1  ->  2.525:1   (luminance gap 0.028 -> 0.094)
   Deliberately NOT stronger. 65% lands peach at 2.105 and dark at 3.761, which
   reads as a ruled table rather than a list; the operator asked for "a bit".
   Both halves share this rule on purpose — the ask named both lists. */
.ww-tb-row { display: flex; align-items: baseline; gap: 8px; padding: 2px 0;
             font-size: 12px;
             /* ⚠ ROOT .932: TWO-STEP, AND THE FIRST STEP IS LOAD-BEARING.
                A lone color-mix() border is a SINGLE declaration: a renderer that
                does not support color-mix drops the whole thing as invalid and the
                row loses its separator ENTIRELY - worse than the faint line the
                operator asked to strengthen. Declaring the plain token first means
                the fallback is what survives, and the darker mix simply overrides
                it where supported. Flagged by both .932 verifiers. */
             border-bottom: 1px solid var(--border);
             border-bottom: 1px solid color-mix(in srgb, var(--border) 80%, var(--text)); }
.ww-tb-amt { flex: 0 0 auto; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
/* ⚠⚠ ROOT .924, MEASURED ON THE STACKED BUILD. This cell held an 11-char
   hex until `wallet-name` (same build) made it a real, UNCAPPED name, while
   `wallet-chips` (same build) sized the row against the hex. On the aside's
   own documented 322px, a 35-character AKA takes 188px and drives
   .ww-tb-ev - THE EVENT TITLE - to exactly 0px: the row still shows an
   amount, a name and a time, so nothing looks broken, and the one thing the
   reader came for is gone. Neither package could see this alone.
   Capped at 8.5em (~102px here, a shade above the hex fallback's 65px) with
   the cell's own ellipsis, so a long name is shortened and the title keeps a
   readable share. The full name stays reachable: it is the link text's title
   attribute and the wallet card is one click away. */
/* ⚠ ROOT 2026-09-07, MEASURED: `flex: 0 1 auto` was a LATENT WRAP CLIFF once
   the row wraps (below). Flex breaks lines on each item's HYPOTHETICAL main
   size - the content size, i.e. the full 8.5em - and only shrinks afterwards,
   so `shrink: 1` never got a chance: at 268px with a FOLLOWED cumulative row
   (61.7 amount + 102 name + 75.6 three chips + 16 gaps = 255.3 > 246 content)
   the chip group wrapped onto a line of its own and the row went to three
   lines. Basis 0 + grow 1 makes the hypothetical size 0, so line 1 always
   holds all three items and the name then GROWS into whatever is left, still
   capped at 8.5em and still ellipsised. */
.ww-tb-who { flex: 1 1 0; min-width: 0; max-width: 8.5em;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
             color: var(--muted); }
.ww-tb-ev  { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ww-tb-ts  { flex: 0 0 auto; color: var(--muted); font-variant-numeric: tabular-nums; }

/* wallet-chips 2026-09-06, RELAID OUT 2026-09-07 (operator: "follow and
   similar buttons for wallets under 'biggest trades' and 'biggest cumulative'
   lists on WALLETS page only appear while hovering on that wallet. Please move
   the text in a way that those buttons are visible").

   ⚠⚠ WHY THE OLD DESIGN HID THEM, AND WHY THAT IS NOT THE FIX ANY MORE.
   .924 measured that a chip pair costs 67px on a row whose ONLY flexible cell
   is the event title, on an aside this sheet's own comment records at 322px:
   the title fell from 91px to 24px - at DESKTOP width. So the chips went out
   of flow (position:absolute, opacity:0, hover/focus-revealed) and the title
   kept its width. The operator has now rejected that trade, and "move the
   text" is the instruction for how to pay for it.

   ⚠ SO THE TEXT MOVES - THE TITLE'S BUDGET IS NOT CUT. The row wraps into two
   lines instead of being squeezed into one:

       line 1   $920,000   MegaWhaleTrader...            ☆ ✕ 🔍
       line 2   Will the Fed cut rates by 50bp bef...    Sep 01 14:10

   The title no longer shares a line with the amount, the name OR the chips, so
   it goes from 55px to ~226px at 322px - FOUR TIMES WIDER than under the
   design that was hiding the buttons to protect it. The chips get permanent,
   reserved space of their own and overlay nothing, at any width, in any state.

   MEASURED, aside pinned to its documented 322px, both lists (min across the
   10 rows of each, worst case = the longest wallet name):
       biggest trades       title  55.4px -> 226.3px    name 102px (unchanged)
       biggest cumulative   title  69.8px -> 247.9px    name 102px (unchanged)
   and at 375px, full width: title 26px (the old touch fallback) -> 259.9px.
   No row, aside or document overflow at either width.

   ⚠ THE BREAK IS A ZERO-HEIGHT FLEX ITEM, NOT NEW MARKUP. ::after with
   flex-basis:100% cannot fit beside line 1, so it wraps and everything
   `order`ed after it starts on line 2. .ww-tb-opt still rides INSIDE
   .ww-tb-ev, sharing its one ellipsis budget.
   row-gap:0 because the row's `gap: 8px` shorthand would otherwise pay a
   vertical gap TWICE (line 1 -> break -> line 2).

   ⚠ ROOT 2026-09-07, WCAG 2.4.3 (Level A) — ONLY THREE `order`s, DELIBERATELY.
   The first cut ordered all five cells 1..6 and left the chips LAST in the
   markup, which read as a free win ("DOM order untouched, screen readers still
   hear amount -> name -> title -> time"). It was not free: `order` moves the
   EYE and not the TAB SEQUENCE, so tab order became
   [name, event-link, follow, similar] against a visual
   [name, follow, similar, event-link] — a keyboard user tabbing 20 rows went
   line-1-left -> line-2 -> back UP to line-1-right, every row. That mismatch
   was created here; it did not exist at 0aee6d6. Fixed at the source: the
   chips MOVED in templates/index.html to sit right after .ww-tb-who, so
   .ww-tb-amt, .ww-tb-who and .pc-inline-chips need no `order` at all — they
   are already in visual order at the default 0, and DOM order IS visual order.
   Only the break and the two cells that must follow it are ordered.
   ⚠ Do not "tidy" this by re-adding order:1/2/3; that silently re-breaks focus
   order, and test_TAB_ORDER_matches_the_VISUAL_ORDER will fail if you do.

   ⚠ KNOWING ACCEPT, NOT AN OVERSIGHT — the two-line shape applies at EVERY
   width, including the one where the aside stops being a sidebar. When
   .ww-topbets-row wraps (~1225px viewport) this column goes full width
   (~1145px) and every row is still two lines, with the title alone on line 2
   and ~1000px of empty space on line 1. Verified against 20 production-shaped
   rows: the column's content height goes 566px -> 905px there. At that width
   the chips would be visible on ONE line too, so the second line is not buying
   anything the operator asked for. It is accepted anyway because the
   alternative is a container query (`.ww-topbets-col { container-type:
   inline-size }` + `@container (min-width: 700px) { .ww-tb-row::after {
   display: none } }`) — i.e. a second layout, forked on width, of exactly the
   kind this package just DELETED (@media (hover: none)). One layout that is
   slightly loose when wide beats two layouts that must both stay true.
   Revisit only if the operator complains about density on the stacked view.

   ⚠ ONE LAYOUT FOR EVERY POINTER. The old @media (hover: none) fork existed
   because hover was the only way in, and it bought the touch title back by
   capping the name to 5.5em. In flow at rest there is nothing to fork: mouse,
   touch and keyboard all get the same visible chips, and the touch name cap
   is no longer needed either. That block, the followed-row padding
   reservation, the hover/focus reveal, the opaque panel background and the
   opacity transition are DELETED rather than re-tuned - they were all
   scaffolding for hiding the chips.

   ⚠ A FOLLOWED ROW SHOWS ALL THREE CHIPS AT REST. pcPaintFollowChips does not
   light one chip - it also INJECTS an unfollow "✕" - and .924 had to hide
   those two actions because the group sat absolutely positioned on top of
   .ww-tb-ts (trade time / realized PnL). Nothing is positioned over anything
   now, so state and both actions are simply visible; elementFromPoint at the
   timestamp's centre returns the timestamp, followed or not. */
.ww-tb-row { flex-wrap: wrap; row-gap: 0; }
/* margin-left:auto right-aligns the group, so the chips form one steady action
   column above the timestamp instead of ending wherever each name happens to. */
.ww-tb-row .pc-inline-chips { margin-left: auto; }
.ww-tb-row::after { content: ""; order: 4; flex-basis: 100%; height: 0; }
.ww-tb-ev { order: 5; }
.ww-tb-ts { order: 6; }

/* ts-inline 2026-09-07 (operator: "in biggest trades ... the date should be
   inline with the follow and similar wallets icons. The date text ... could
   move a bit to the left without sacrificing important real estate", then
   "update: CUMULATIVE is fine, the issue is with BIGGEST tRADE").

   ⚠ THE TRADES HALF ONLY, AND THAT IS THE WHOLE POINT. Both halves share
   .ww-tb-row, but .ww-tb-ts holds DIFFERENT DATA in each: the trades half
   prints b.ts_str, a full "%Y-%m-%d %H:%M" datetime (16 chars, MEASURED at
   93.1px), while the cumulative half prints a short signed PnL number
   (~50px, title "Realized PnL across settled trades"). That 43px is exactly
   why the operator sees a problem on one list and not the other, so the fork
   is `:not(.ww-tb-half-vol)` and the cumulative tail is not touched at all.

   ⚠ WHY A CONTAINER QUERY - PHYSICS, NOT TASTE, AND ALL FOUR FIGURES MEASURED.
   Line 1 already carries the amount, the name and the chip group. Adding the
   date costs 93.1 + one 8px gap. The line's INFLEXIBLE content is
   amount + chips + date + 3 gaps, because .ww-tb-who is `flex: 1 1 0` and so
   contributes nothing to the wrap decision (the .931 note above). On a FOLLOWED
   row the painter injects a third chip and that sum is 263.3px:

       aside 268 -> 246px of line   263.3 does NOT fit -> the row goes to
                                    THREE lines (rowH 39 -> 55, measured)
       aside 322 -> 300px of line   fits, but the name is squeezed 102 -> 36.7
       aside 450 -> 428px of line   fits with the name at its 8.5em cap

   So an unconditional `order` re-breaks the .931 wrap cliff at the narrow end
   and eats the wallet name at the middle - "sacrificing important real estate"
   is the one thing the operator ruled out. The query fires only where line 1
   holds the date AND a readable name: 263.3 + ~77 = 340px of COLUMN width.
   MEASURED at the boundary (followed, widest row): 339px keeps today's shape,
   340px flips, and the row is 39px on both sides of it - it never grows a
   line. Below the boundary the shipped .931 layout stands unchanged, so this
   is an enhancement, not a second layout to keep true: a renderer without
   @container support gets .931 and nothing looks broken.
   Production widths: the aside is ~450px beside the table and ~1145px once
   .ww-topbets-row wraps, both above the boundary; a 375px phone (aside ~335px)
   is below it and keeps the two-line shape, which is the right answer there.

   ⚠ WCAG 2.4.3 IS SAFE HERE and that is not luck: .ww-tb-ts is a SPAN with no
   tabindex, so moving it changes the eye and not the tab sequence. The three
   focusables (name, follow, similar - plus the injected unfollow) keep both
   their DOM order and their visual order, which is why this needs no markup
   move like the one the chips needed. Verified rendered at all four widths.

   ⚠ elementFromPoint AT THE DATE'S CENTRE still returns the date, followed or
   not (the .924 regression). Nothing is positioned; the date is simply the
   last flex item on the line, after the chips. */
@container (min-width: 340px) {
  /* order 0 = the default group, so the date takes its DOM position: after the
     chips, which is the reading order the operator wrote out. `margin-right`
     is the "a bit to the left" - the date's right edge sits 6px inside the
     panel's content edge instead of flush against it. */
  .ww-tb-half:not(.ww-tb-half-vol) .ww-tb-ts { order: 0; margin-right: 6px; }
  /* ⚠ THE ANONYMOUS ROW. Kalshi's tape has no taker identity, so that row
     renders no chip group - and the chip group is what carries the
     `margin-left: auto` that right-aligns the tail. Without this the date on
     an anonymous row lands right after the name (MEASURED: 166px left of every
     other row's date at 450px) and the date column goes ragged. The auto
     margin moves to the date itself exactly when there is no group to hold
     it, so both shapes end at the same 6px inset. */
  .ww-tb-half:not(.ww-tb-half-vol)
    .ww-tb-row:not(:has(.pc-inline-chips)) .ww-tb-ts { margin-left: auto; }
}
/* wallets-options 2026-09-02: the backed option, inline after the title. Not a
   flex sibling — it lives INSIDE .ww-tb-ev so the pair shares one ellipsis and
   a long option can never widen the row (no horizontal scrollbar, ever). */
.ww-tb-opt { margin-left: 5px; color: var(--accent); opacity: 0.85; }
/* wallets-tab 2026-08-12 (operator): the row is now Sharp Edge · Highest
   Conviction · Latest News (Wallets & Whales moved to /wallets). flex-wrap is
   already set on the row, so the three wrap instead of overflowing; min-width:0
   is what stops a long title forcing the forbidden horizontal scrollbar. */
.ww-news-row > .signals-card { margin: 0; flex: 1 1 300px; min-width: 0; align-self: stretch; }
.ww-news-row > .news-hub {
  margin: 0; flex: 1 1 360px; min-width: 0; max-width: 760px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-card); padding: 8px 10px 10px;
  /* nh-fix 2026-07-10: (a) stretch — the box height locks to the row (W&W is
     the tall sibling), so toggling Headlines↔Elections no longer resizes the
     box; (b) overflow guard — nothing escapes the rounded border. */
  align-self: stretch;
  overflow: hidden;
}
/* nh-fix 2026-07-10: grid items default min-width:auto — a long unbroken
   headline forced the 2-col news grid wider than the box ("text not retained
   within the box limits"). min-width:0 lets each cell shrink; the title's
   own ellipsis then does its job. */
.smh-news-list > .la-news-item { min-width: 0; }
.news-hub h3 { margin: 0 0 6px; }
@media (max-width: 768px) {
  .ww-news-row { flex-direction: column; margin: 10px; gap: 10px; }
  .ww-news-row > .sharp-hub, .ww-news-row > .news-hub,
  .ww-news-row > .signals-card { width: 100%; max-width: 100%; }
}
@media (max-width: 768px) { .sharp-hub { width: 100%; } }  /* the mobile hot-tab pane fills its column */
.smh-th, .smh-tbl-row {
  display: grid;
  /* name capped (not 1fr) so the hub's max-content is finite — that's what
     lets .sharp-hub{width:fit-content} actually shrink below page width on
     wide monitors (the operator's "width of the data" ask). */
  /* hot-wallets-cols 2026-07-27 (operator): 9 cols — the Resolved column
     split into Resolved(count 44px) + Total(staked-$ 76px); W/L widened
     56→80px (the full `12/5 (70%)` reading, .smh-td ellipsis-clips it
     otherwise) and STREAK squeezed 78→56px in trade. Both header + data
     rows follow this one template, so they stay aligned. Width grows a
     little; the fit-content hub absorbs it — no horizontal scroll. */
  grid-template-columns: minmax(84px, 240px) 82px 44px 76px 58px 80px 56px 84px 34px;
  gap: 8px; align-items: center;
}
.smh-th {
  list-style: none; padding: 2px 4px 4px;
  font-size: 9px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--border);
}
.smh-th .smh-th-usd, .smh-tbl-row .smh-usd { justify-self: end; }
.smh-td { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
.smh-td.is-num { font-variant-numeric: tabular-nums; }
.smh-col-venue { display: inline-flex; align-items: center; }
.smh-col-l5 { display: inline-flex; align-items: center; gap: 4px; }
/* ww-winloss 2026-07-11 (operator): all-time W/L column (wins green / losses
   red) + the followed-lists inline chips. Streak chips reuse .smh-streak-w/-l. */
.smh-col-wl { font-variant-numeric: tabular-nums; }
/* hot-wallets-cols 2026-07-27: the split-out resolved-staked Total cell. */
.smh-col-total { font-variant-numeric: tabular-nums; }
.smh-wl-w { color: var(--success); font-weight: 700; }
.smh-wl-l { color: var(--danger); font-weight: 700; }
.fw-wl { font-variant-numeric: tabular-nums; font-size: 11px; margin-left: 6px; white-space: nowrap; }
/* wl-unknown 2026-07-20: the "·N?" undetermined-outcome count on W/L chips. */
.fw-wl-unk { color: var(--muted); font-style: normal; font-weight: 600; }
.fw-streak { font-size: 10.5px; margin-left: 5px; white-space: nowrap; }
.smh-streak-w { color: var(--success); font-weight: 800; }
.smh-streak-l { color: var(--danger);  font-weight: 800; }
.smh-na { color: var(--muted); opacity: 0.6; }
/* pager show/hide for GRID rows — mirrors the .471 flex pager (which re-asserts
   display:flex on the visible page and would otherwise flatten the grid); these
   sit later in the sheet, so the tie-break keeps table rows grid. */
.smh-paged > .smh-tbl-row { display: none; }
.smh-paged[data-page="0"] > .smh-tbl-row[data-pg="0"],
.smh-paged[data-page="1"] > .smh-tbl-row[data-pg="1"],
.smh-paged[data-page="2"] > .smh-tbl-row[data-pg="2"],
.smh-paged[data-page="3"] > .smh-tbl-row[data-pg="3"],
.smh-paged[data-page="4"] > .smh-tbl-row[data-pg="4"],
.smh-paged[data-page="5"] > .smh-tbl-row[data-pg="5"],
.smh-paged[data-page="6"] > .smh-tbl-row[data-pg="6"],
.smh-paged[data-page="7"] > .smh-tbl-row[data-pg="7"],
.smh-paged[data-page="8"] > .smh-tbl-row[data-pg="8"],
.smh-paged[data-page="9"] > .smh-tbl-row[data-pg="9"] { display: grid; }
/* (.471 sub-line styles already live in this sheet — the WIP block's duplicate tail dropped on import) */

@media (min-width: 900px) {
  /* wds-wide 2026-07-08: two columns halve the height — the legend fits without scrolling */
  .wds-modal .wds-list { columns: 2; column-gap: 28px; }
  .wds-modal .wds-list li { break-inside: avoid; }
}

/* elections-cal 2026-07-08: 🗳 Elections sub-tab inside the Latest News panel */
.news-subtabs { margin: 0 0 5px; }
.news-subtab { font-size: 10.5px; padding: 1px 9px; }
.elec-list { list-style: none; margin: 0; padding: 0; overflow: hidden; }
.elec-row { display: flex; align-items: center; gap: 7px; flex-wrap: nowrap;
  padding: 2.5px 2px; font-size: 11.5px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 45%, transparent); }
.elec-row:last-of-type { border-bottom: 0; }
.elec-date { flex: 0 0 66px; white-space: nowrap; color: var(--accent); font-weight: 700; }  /* nh-fix2 2026-07-10: 48px wrapped "~ Aug 30" onto two lines — widened to fit the longest label (measured 65px) + nowrap keeps every date one-line */
.elec-flag { flex: 0 0 auto; }
/* elec-region-flag 2026-07-11 (operator): the flag now sits beside the country
   name in .elec-region on desktop — hide the redundant LEADING flag there. On
   mobile (≤700px) .elec-region is hidden, so the leading flag stays the country
   indicator (unchanged). One flag per breakpoint, never two. */
.elec-region-flag { margin-right: 4px; }
/* elec-flag-img 2026-07-11: flagcdn <img> instead of emoji (Windows renders
   regional-indicator emoji as letters). Sized down for the compact 11.5px row;
   the .flag-img base is 16px. */
.elec-flag-img { width: 13px; border-radius: 2px; }
@media (min-width: 701px) { .elec-flag { display: none; } }
.elec-title { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text); }
.elec-region { flex: 0 0 auto; max-width: 112px; overflow: hidden; text-overflow: ellipsis;  /* elec-region-flag 2026-07-11: +16px for the leading flag glyph */
  white-space: nowrap; color: var(--muted); font-size: 10.5px; }
.elec-type { flex: 0 0 auto; color: var(--muted); font-size: 9.5px;
  text-transform: uppercase; letter-spacing: .04em;
  border: 1px solid var(--border); border-radius: 3px; padding: 0 4px; }
.elec-credit { color: var(--muted); font-size: 9.5px; padding: 3px 2px 0; list-style: none; }
/* The lists carry explicit display rules (.la-news-list flex / .smh-news-list
   grid) which BEAT the UA [hidden]{display:none} — force the toggle to win.
   nh-fix 2026-07-10: rescoped .smh-panel[data-smh-panel="news"] → .news-hub —
   the news panel became its own box (ww-news-row .491) and the old scope no
   longer matched ANY markup, so the headlines grid stayed visible under the
   Elections list (the "elections obscured" bug). */
.news-hub [data-news-panel][hidden] { display: none !important; }
@media (max-width: 700px) {
  .elec-region { display: none; }   /* flag emoji already conveys country at phone width */
}

/* ── mobile-pass .641 (operator: "make sure we have a mobile-optimized version
   of the updated UI") — phone rules for the recent additions. House pattern:
   a wide grid/table scrolls INSIDE its own container (the page body never
   h-scrolls); ≤768px matches the .smh stacked layout's breakpoint (the
   ≤700px block would leave a 701-768px clip sliver — audit-verified). ── */
@media (max-width: 768px) {
  /* hot-wallets-cols .637 made the W&W lists a 9-track ~662px grid; no
     mobile rule existed → everything right of Resolved was CLIPPED
     unreachable at phone width (live-measured 598px tracks in ~333px).
     The lists now scroll inside their own halves, headers in lockstep. */
  .smh-half { min-width: 0; }
  .smh-half > .smh-list { overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; }
  .smh-half > .smh-list::-webkit-scrollbar { display: none; }
  .smh-th, .smh-tbl-row { width: max-content; min-width: 100%; }
  /* hof-100 .633: up to 10 numeric pager pills on a no-wrap strip. */
  .smh-h-row { flex-wrap: wrap; row-gap: 4px; }
}

/* ── frozen-panes .642 (operator, 3 asks): (1) the frozen TOP pane at phone
   width was ~320px at rest / ~230px condensed (~40% of a 375×812 screen) —
   thin it to ⅓–½; (2) the two LIVE-FEED tracker strips move to a frozen
   BOTTOM pane (stacked above the mobile tab bar); (3) every rail icon gets
   a small label without widening the 52px rail.
   Free homepage only: the ticker selectors carry :not(.pc-shell-ticker) and
   the bottom tab bar exists only on index.html. ≤768px = the bar's own
   breakpoint (769-900px has no bottom bar → tickers stay sticky on top).
   Companion JS: _pc_shell.html measure() zeroes the tickers out of
   --shell-top-h at ≤768px so the rail top / ET& sticky offsets stay true. */
@media (max-width: 768px) {
  /* --mbn-h mirrors .mobile-bottom-nav's intrinsic box (1px border + 6px pad
     + 6px link pad + 18px icon + 2px gap + ~13px label + 6px link pad +
     max(6px, safe-area) pad) — the first var for a height that was only ever
     the hardcoded 60/64px literals at 8567-8568. --tape-h = both strips. */
  :root { --mbn-h: calc(51px + max(6px, env(safe-area-inset-bottom, 0px)));
          --tape-h: 56px; }

  /* (2) trackers → fixed bottom pane: LIVE FEED strip over topics strip,
     both riding on the tab bar. top:auto cancels the sticky offsets; the
     900px-block rail negative margin would shift a left/right-pinned box. */
  body.pc-shell .unified-ticker-section:not(.pc-shell-ticker) {
    position: fixed; left: 0; right: 0; top: auto;
    bottom: calc(var(--mbn-h) + 26px); z-index: 100; margin-left: 0;
    flex-direction: row; align-items: center; height: 30px;
  }
  body.pc-shell .topics-ticker-section:not(.pc-shell-ticker) {
    position: fixed; left: 0; right: 0; top: auto;
    bottom: var(--mbn-h); z-index: 100; margin-left: 0;
    flex-direction: row; align-items: center; height: 26px;
  }
  /* .643: the collapsed-rail variant (body.pc-rail, one class MORE specific
     than the rules above) re-applies margin-left:-52px globally — it dragged
     the fixed strips 52px off-screen left (the LIVE FEED label was half
     hidden, live-measured left:-52). Match its specificity to cancel it. */
  body.pc-shell.pc-rail .unified-ticker-section:not(.pc-shell-ticker),
  body.pc-shell.pc-rail .topics-ticker-section:not(.pc-shell-ticker) {
    margin-left: 0; }
  /* slim strip innards (the 8103 block stacked the label ABOVE the track —
     inline-left again so each strip is one thin line) */
  .unified-ticker-section:not(.pc-shell-ticker) .ticker-label {
    padding: 3px 8px; font-size: 9px; text-align: left; flex-shrink: 0; }
  .unified-ticker-section:not(.pc-shell-ticker) .ticker-wrap,
  .topics-ticker-section:not(.pc-shell-ticker) .ticker-wrap { padding: 2px 0; }
  /* page + chrome clear the taller bottom stack (was body 60px / pill 64px) */
  /* mobile-usability 2026-08-31: the reserve matches what the page ACTUALLY
     shows. Every shell page has the tab bar; only a page whose ticker strips
     are NOT adopted into the top band (i.e. /events) has the fixed bottom
     tape - :has() keys on the same :not(.pc-shell-ticker) the tape rules use,
     so the two can never disagree. wallet-page gets the bar this package. */
  body.pc-shell, body.wallet-page { padding-bottom: calc(var(--mbn-h) + 10px); }
  body.pc-shell:has(.unified-ticker-section:not(.pc-shell-ticker)) {
    padding-bottom: calc(var(--mbn-h) + var(--tape-h) + 10px); }
  .viewer-pill { bottom: calc(var(--mbn-h) + var(--tape-h) + 12px); }
  /* the rail (z 415, bottom:0) painted OVER the tab bar's leftmost 52px —
     it obscured the 🏆Board tab. End it above the whole bottom stack. */
  .pc-sidenav { bottom: calc(var(--mbn-h) + var(--tape-h)); }

  /* (1) thin top header. Pre-scroll ~234px → ~135px (42% of the old 320px
     frozen top); condensed (pc-scrolled hides hero+meta) ~144px → ~65px. */
  body.pc-shell > header { grid-template-columns: minmax(0, 1fr) auto;
    gap: 2px 8px; padding: 6px 10px 4px; }
  .brand-logo { height: 30px; }
  /* hdr-align .588's -45px overlap is calibrated to the 44px logo's empty
     right area (ink ends 133px into the 186px box). At 30px the box scales
     to ~127px, ink to ~91px → ~31px of air. Keep the ratio, not the px. */
  .brand-etblock { margin-left: -31px; }
  .brand-decoration { width: 22px; height: 22px; }
  .brand-product-name { font-size: 13px; }
  .hero-inner { gap: 3px; }
  .hero-subtitle-inline { font-size: 9px; padding: 2px 6px; }
  .hero-inner .search-box input { font-size: 11px; padding: 3px 8px; }
  .hero-disclaimer { font-size: 7px; margin-top: 1px; }
  header .meta { grid-row: 3; grid-column: 1; gap: 8px;
    border-top: none; padding-top: 0; }
  /* .643: the meta column is only ~183px beside the login pill — Peachy
     (72px) + "Where do I start?" (114px) wrapped to TWO lines (meta 49px,
     live-measured). One size down each fits them on one ~22px line. */
  header .theme-toggle { padding: 2px 6px; font-size: 9px; }
  header .wds-btn { font-size: 9px; padding: 2px 6px; }
  /* login pill rides beside the meta row (the mascot's 112px column is
     display:none at 8047 — its reserved track shrinks to auto).
     .644: the pill now shares Trackster's column — his feet landed ON the
     CTA's right end (live screenshot); paint the pill over the feet. */
  .etand-login-btn { grid-row: 3; grid-column: 2; justify-self: end;
    align-self: center; font-size: 9px; padding: 0.25rem 0.6rem;
    position: relative; z-index: 8; }

  /* (3) rail labels: the .pc-sidenav-lbl spans already exist in the markup —
     collapsed mode just display:none'd them (9856). Icon on top, 7px label
     under, everything inside the unchanged 52px rail. */
  body.pc-rail .pc-sidenav-item { flex-direction: column; gap: 2px;
    padding: 5px 2px; }
  body.pc-rail .pc-sidenav-ico { width: auto; }
  body.pc-rail .pc-sidenav-lbl { display: block; font-size: 7px;
    line-height: 1.2; font-weight: 700; text-align: center;
    white-space: normal; overflow-wrap: break-word; max-width: 100%; }
}

/* ── mkt-board-events .649 (operator): the venue's current Federated Board
   events at the bottom of the Marketplace Card. Global (the card renders at
   every width); the list scrolls inside the card past ~7 rows — the modal
   itself never grows unbounded. ── */
/* mkt-card-deepen 2026-08-21 (operator): the card's toggleable 7-day line
   chart + the four per-venue lists. Vars only; the lists scroll INSIDE their
   own box so the modal never grows unbounded (the .649 discipline). */
.mkt-card-7dtog { float: right; display: inline-flex; gap: 4px; }
.mkt-card-7dbtn { background: none; border: 1px solid var(--border); color: var(--muted);
  font-family: monospace; font-size: 9px; letter-spacing: 1px; padding: 1px 6px; cursor: pointer;
  border-radius: var(--r-chip, 4px); }
.mkt-card-7dbtn.is-on { color: var(--accent); border-color: var(--accent); }
.mkt-card-7dbtn[disabled] { opacity: .4; cursor: not-allowed; }
.mkt-card-7dsvg { width: 100%; height: 64px; display: block; margin-top: 4px; overflow: visible; }
.mkt-card-sub { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); }
.mkt-card-lilist { display: flex; flex-direction: column; gap: 1px; max-height: 190px;
  overflow-y: auto; -webkit-overflow-scrolling: touch; }
.mkt-card-li { display: flex; align-items: baseline; gap: 8px; padding: 2px 0; min-width: 0;
  font-size: 11px; border-bottom: 1px solid var(--border); }
.mkt-card-li:last-child { border-bottom: 0; }
.mkt-card-li-a { flex: 0 0 auto; font-weight: 700; color: var(--whale);
  font-variant-numeric: tabular-nums; }
.mkt-card-li-w { flex: 0 0 auto; color: var(--accent); text-decoration: none; max-width: 38%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mkt-card-li-t { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text); text-decoration: none; }
.mkt-card-li-t:hover, .mkt-card-li-w:hover { text-decoration: underline; }
.mkt-card-li-m { flex: 0 0 auto; color: var(--muted); font-variant-numeric: tabular-nums; }

.mkt-card-evlist { max-height: 236px; overflow-y: auto; margin-top: 4px;
  display: flex; flex-direction: column; gap: 2px;
  -webkit-overflow-scrolling: touch; }
.mkt-card-ev { display: flex; justify-content: space-between; gap: 10px;
  align-items: baseline; padding: 4px 6px; border-radius: var(--r-chip);
  background: var(--panel-2); text-decoration: none; color: var(--text);
  font-size: 11.5px; min-width: 0; }
a.mkt-card-ev:hover { background: color-mix(in srgb, var(--accent) 12%, transparent);
  text-decoration: none; }
.mkt-card-ev-t { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; min-width: 0; }
.mkt-card-ev-m { flex-shrink: 0; color: var(--muted); font-size: 10.5px;
  white-space: nowrap; }

/* ── xv-card-front .651 (operator: "cross-venue event disambiguation cards are
   being obscured by the frozen pane and tickers — push it to front"): the
   #event-group-overlay (also the arb card's shell) rode the shared
   .modal-overlay z 100, UNDER the frozen band (header 420 / tickers 419-418).
   Static floor above the band; _frontOverlay's inline z (1010+) still wins
   when modals interleave. Every opener of this overlay is covered. ── */
#event-group-overlay { z-index: 1000; }

/* contact-front 2026-08-21 (operator: "push the pop up box …?contact=1 to the
   front, otherwise it won't function"). #contact-overlay never set a z-index of
   its own, so it inherited `.modal-overlay`'s base **100** - the LOWEST of any
   overlay on the page. It therefore lost to every one of them: fronted content
   modals (_frontOverlay's counter starts at 1010 and climbs), #event-group
   (1000), #topic (1010), and - the one that actually bit - .pc-upsell-overlay
   at 99990, the ET& interstitial that shows on exactly the pages the
   `?contact=1` deep link exists to serve.

   Reproduced in a browser against this stylesheet: with the upsell open,
   elementFromPoint over the contact form's own input returned the UPSELL, not
   the input - the form rendered fully and was completely unclickable, which is
   precisely "it won't function". At 99995 the same probe returns the input.

   99995 follows .pc-upsell-overlay's own documented band: above the upsell so a
   user who opens Contact FROM an ET& page can actually type, and still below
   .pc-toast (100000) so toasts are never occluded. A fixed value, not a
   _frontOverlay() call - the climbing counter tops out around 1010+ and would
   never clear 99990. */
#contact-overlay { z-index: 99995; }

/* ── btb-oneline .655 (operator: "reduce the [1-25] etc. icon fonts so that
   they are all one-line, even for [XXX-XXX]") — at phone width a seg tab is
   ~28px wide; 9px MONOSPACE "101–125" is ~38px → it wrapped to two lines.
   ≤768px: 6.5px with proportional digits (monospace glyphs are too wide at
   any legible size: 7 chars × 0.6em vs 0.52em) + a whisker of negative
   tracking → XXX–XXX ≈ 22px, one line down to 360px-wide phones. Desktop
   keeps the 9px monospace departures look. Padding grows 2→3px so the tap
   target doesn't shrink with the font. ── */
@media (max-width: 768px) {
  .btb-btn { font-size: 6.5px; letter-spacing: -0.2px; font-family: inherit;
    padding: 3px 0; }
}

/* ── card-theme-toggle .661 (operator: "I still don't see the peachy / dark
   toggle in wallet / event / disambiguation / marketplace cards") — every
   card shell (#modal-overlay incl. the marketplace card, #wallet-overlay,
   #event-group-overlay, #event-whales-overlay, #topic-overlay) now carries
   the same .theme-toggle button beside its × close. The theme bootstrap's
   ui() syncs any .theme-toggle at load + on every flip, so the labels stay
   correct. Positioned clear of the 26px close glyph. ── */
.modal-theme-toggle { position: absolute; top: 12px; right: 48px; z-index: 3; }

/* ── etand-embed .662 (operator: ET& cards pop up IN-PAGE, never a new tab).
   Embed dress: with html.pc-embed (?embed=1) every body child except the five
   card overlays is hidden — the iframe shows ONLY the card. The parent-side
   .etand-embed-overlay sits at the promoted-modal tier (1010) so the ET&
   sticky strip (z 420) can never paint over it — the .651 bug class. ── */
html.pc-embed body > *:not(#modal-overlay):not(#wallet-overlay):not(#event-whales-overlay):not(#event-group-overlay):not(#topic-overlay) { display: none !important; }
html.pc-embed body { padding: 0 !important; }
html.pc-embed .modal-overlay { padding: 10px; background: rgba(5, 8, 20, 0.45); }
.etand-embed-overlay { z-index: 1010; }
.etand-embed-overlay .modal { padding: 0; overflow: hidden; max-width: 920px;
  width: min(96vw, 920px); height: min(90vh, 960px); }
.etand-embed-overlay iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ── card-chrome .675 (operator: "fix the peach / dark toggle being on top
   of the other links on MARKETPLACE and EVENT cards") — the .661 toggle is
   absolutely positioned in the card's top-right, but .modal content began
   at padding-top 24px (18px mobile) while the ×+toggle strip runs to
   ~38px: the toggle overlapped the first content row's right side (the
   marketplace card's venue link, the event card's header links). Reserve a
   REAL chrome strip on every card shell — content starts below the strip.
   The ET& embed host stays padding:0 (its chrome lives inside the frame,
   which gets this same strip from these rules). ── */
.modal { padding-top: 48px; }
.etand-embed-overlay .modal { padding-top: 0; }
@media (max-width: 768px) {
  .modal { padding-top: 42px; }
  .modal-theme-toggle { top: 8px; right: 44px; }
  .etand-embed-overlay .modal { padding-top: 0; }
}

/* most-liquid-view 2026-08-07 (operator): the "See all 100" card footer + the
   dedicated Most-Liquid modal (top-100 open markets by depth). The 💧 card
   stays a 15-row teaser (never scrolls — ABSOLUTE UX RULE); the MODAL list
   scrolls vertically inside itself. Colors strictly via CSS vars (graphical
   tenet), so both the dark + peach themes follow. No horizontal scroll. */
.lq-more-row { border-bottom: none; padding: 4px 8px 2px; }
.lq-more-btn {
  font: inherit; font-size: 11px; font-weight: 700; cursor: pointer;
  background: none; border: none; padding: 3px 6px; border-radius: var(--r-chip);
  color: var(--accent); letter-spacing: 0.02em;
  display: inline-flex; align-items: center; gap: 4px; min-width: 0;
}
.lq-more-btn:hover { background: var(--panel-2); text-decoration: underline; }
.lq-more-arrow { font-weight: 700; }

.most-liquid-modal { max-width: 760px; width: min(760px, 96vw); }
.ml-head { border-bottom: 1px solid var(--border); margin-bottom: 10px; padding-bottom: 9px; }
.ml-title-lead { font-size: 20px; font-weight: 800; color: var(--jackpot); letter-spacing: 0.01em; }
.ml-sub { font-size: 12px; color: var(--muted); margin-top: 3px; font-family: monospace; }

/* the list scrolls vertically INSIDE the modal (never the signal card) */
.ml-list {
  list-style: none; margin: 0; padding: 0 4px 0 0;
  max-height: calc(85vh - 150px); overflow-y: auto; overflow-x: hidden;
}
.ml-row { border-bottom: 1px solid var(--border); }
.ml-row:last-child { border-bottom: none; }
.ml-row-link {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 8px;
  min-width: 0; padding: 7px 4px; text-decoration: none; color: var(--text); font-size: 13px;
}
.ml-row-link:hover { background: var(--panel-2); text-decoration: none; }
.ml-venue { flex: 0 0 auto; }
.ml-title { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-liq {
  flex: 0 0 auto; white-space: nowrap;
  font-family: monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--accent);
}
@media (max-width: 700px) {
  .most-liquid-modal { width: 96vw; }
  .ml-title-lead { font-size: 17px; }
  .ml-list { max-height: calc(100vh - 170px); }
}

/* sizing 2026-08-10 — Risk Console */
.risk-console { display: flex; flex-direction: column; gap: 6px; }
.risk-row {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 4px;
  border: 1px solid var(--border); background: var(--panel);
}
.risk-label {
  flex: 1 1 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.risk-chip {
  flex-shrink: 0; flex-wrap: nowrap;
  font-family: ui-monospace, monospace; font-size: 11px;
  color: var(--muted);
}
.risk-row[data-band="under"] { border-left: 3px solid var(--sizing-under); }
.risk-row[data-band="near"]  { border-left: 3px solid var(--sizing-near); }
.risk-row[data-band="over"]  { border-left: 3px solid var(--sizing-over); }
.risk-note { color: var(--muted); font-size: 11px; margin-top: 6px; }

/* sizing 2026-08-10 — event-modal strip */
.sizing-strip {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  padding: 6px 8px; margin-top: 6px;
  border: 1px solid var(--border); border-radius: 4px; background: var(--panel);
}
.sizing-headline {
  font-size: 18px; font-weight: 700; color: var(--accent);
  font-family: ui-monospace, monospace;
}
.sizing-bound { color: var(--muted); font-size: 11px; }
.sizing-refuse { color: var(--muted); font-size: 12px; }

/* two-phase-modal .817: the phase-1 (snapshot) paint of the event modal.
   Replaced wholesale by phase 2 a moment later, so this is intentionally a
   plain, quiet layout — it must read as "loading in progress", never as a
   finished card the user might act on.
   GRAPHICAL TENET: every colour is a var(). No literals. */
.ev-fast { padding: 2px 0; }
.ev-fast h3 { margin: 0 0 6px 0; font-size: 16px; color: var(--text); }
.ev-fast-meta { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.ev-fast-tbl { width: 100%; border-collapse: collapse; }
.ev-fast-tbl td { padding: 3px 6px; font-size: 12px; color: var(--text);
                  border-bottom: 1px solid var(--border); }
.ev-fast-tbl td:first-child { overflow: hidden; text-overflow: ellipsis;
                              white-space: nowrap; max-width: 0; width: 100%; }
.ev-fast-px { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
              color: var(--accent); }
/* The age line is load-bearing, not decoration: it is what stops a soft price
   from reading as a live one. Muted, but never hidden. */
.ev-fast-age { margin-top: 8px; font-size: 11px; color: var(--muted); opacity: .85; }

/* ── mobile-pass .861: tables that clipped unreachably at 375px ──────────────
   html/body are overflow-x:clip, so a table wider than the viewport does not
   scroll - its right columns simply do not exist for the visitor. Every wide
   table gets the sxbet-orders-wrap treatment: scroll INSIDE the container.
   .ew-table additionally had ZERO css anywhere (UA-default 16px serifless
   sprawl inside a modal); it now matches its .wm-trades siblings. */
.ew-table-wrap { overflow-x: auto; }
.arb-table-wrap { overflow-x: auto; }
.mkt-table-wrap { overflow-x: auto; }

/* mkt-slice-pie 2026-08-30: the per-day / per-week breakdown modal. Colours are
   the venues' own brand values (inline, from the same data the bars use); every
   value here is a var so the peach theme comes free. */
.mkt-bar-clickable { cursor: pointer; }
.mkt-pie-wrap { padding: 2px 2px 6px; }
.mkt-pie-head { font-family: monospace; font-size: 11px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--muted); }
.mkt-pie-total { font-family: monospace; font-size: 22px; color: var(--text); margin: 2px 0 10px; }
.mkt-pie-sub { font-size: 11px; color: var(--muted); letter-spacing: 0; }
/* an EXPLICIT height: Chart.js sizes to the parent, and a modal that is
   display:none until opened gives a zero-height box otherwise. */
.mkt-pie-box { height: 260px; margin-bottom: 12px; }
.mkt-pie-tbl { width: 100%; border-collapse: collapse; font-size: 12px; }
.mkt-pie-tbl th { text-align: left; font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--muted); font-weight: 500;
  padding: 4px 6px; border-bottom: 1px solid var(--border); }
.mkt-pie-tbl td { padding: 5px 6px; border-bottom: 1px solid var(--border); }
.mkt-pie-tbl tr:last-child td { border-bottom: none; }
.mkt-pie-tbl .mkp-v, .mkt-pie-tbl .mkp-p { text-align: right; font-family: monospace;
  white-space: nowrap; }
.mkt-pie-tbl .mkp-p { color: var(--muted); }
.mkp-sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px;
  margin-right: 7px; vertical-align: -1px; }
.mkp-link { color: var(--text); text-decoration: none; }
.mkp-link:hover { color: var(--accent); text-decoration: none; }
.mkt-pie-back { display: inline-block; margin-bottom: 10px; background: none;
  border: 1px solid var(--border); border-radius: 4px; color: var(--muted);
  font-family: monospace; font-size: 11px; padding: 3px 10px; cursor: pointer; }
.mkt-pie-back:hover { color: var(--accent); border-color: var(--accent); }
.ew-table { width: 100%; font-size: 11px; border-collapse: collapse; }
.ew-table th, .ew-table td { padding: 6px 8px; text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--border); }
.ew-table th { color: var(--muted); font-weight: 600; }
@media (max-width: 768px) {
  .ew-table { font-size: 10px; }
  .ew-table th, .ew-table td { padding: 5px 6px; }
  /* UTC column off on phones - the wm-trades precedent (its col 1; ours is 5) */
  .ew-table th:nth-child(5), .ew-table td:nth-child(5) { display: none; }
}

/* pc-pager 2026-08-29 (operator: "< > arrow buttons") — the shared arrow
   control. Every colour is a var (graphical tenet); the control is inline so
   it sits in a heading row without changing its height. */
.pc-pg { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px;
         vertical-align: middle; }
.pc-pg-btn {
  appearance: none; cursor: pointer; line-height: 1;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 4px;
  padding: 0 5px; font-size: 12px; min-width: 18px; height: 18px;
}
.pc-pg-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
/* Disabled at the ends rather than hidden — a control that disappears makes the
   heading row reflow on every click. */
.pc-pg-btn:disabled { opacity: .38; cursor: default; }
.pc-pg-ind { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums;
             min-width: 24px; text-align: center; }
.pc-pg-host { display: inline-flex; align-items: center; }

/* weather-tab 2026-08-29: the 🌦 Weather sub-tab. Every colour a var; severity
   reuses the existing semantic danger/jackpot tokens rather than new literals. */
.wx-list { display: flex; flex-direction: column; gap: 1px; }
.wx-head { display: flex; flex-direction: column; gap: 2px; padding: 4px 0 6px;
           border-bottom: 1px solid var(--border); }
.wx-h-t { font-weight: 700; color: var(--text); font-size: 12px; }
.wx-h-s { font-size: 10px; color: var(--muted); }
.wx-sub { margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--border);
          font-size: 10px; color: var(--muted); text-transform: uppercase;
          letter-spacing: .04em; }
.wx-row { display: flex; align-items: baseline; gap: 8px; padding: 2px 0;
          font-size: 12px; border-bottom: 1px solid var(--border); }
.wx-sev { flex: 0 0 auto; font-size: 10px; font-weight: 700; padding: 0 4px;
          border-radius: 3px; border: 1px solid var(--border); color: var(--muted); }
.wx-sev-extreme { color: var(--danger); border-color: var(--danger); }
.wx-sev-severe  { color: var(--jackpot); border-color: var(--jackpot); }
.wx-auth { flex: 0 0 auto; font-size: 10px; font-weight: 700; color: var(--accent); }
.wx-ev { flex: 0 0 auto; font-weight: 600; color: var(--text); }
.wx-area { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis;
           white-space: nowrap; color: var(--muted); }

/* wx-live-markets 2026-09-05 (operator: real markets + venue + a link to the
   card). The alert rows put the long text in .wx-area; a MARKET row puts it in
   .wx-ev, so the flex roles swap for .wx-mkt only. Without this the title sits
   in a `flex: 0 0 auto` cell and pushes the row wide -- the horizontal-scroll
   rule is absolute, and a long market title is exactly what would break it. */
.wx-mkt .wx-ev { flex: 1 1 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.wx-mkt .wx-area { flex: 0 0 auto; font-size: 10px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
.wx-venue { display: inline-flex; align-items: center; gap: 3px;
  color: var(--muted); }
.wx-venue-logo { display: block; border-radius: 2px; }
.wx-mkt-link { color: inherit; text-decoration: none; }
.wx-mkt-link:hover, .wx-mkt-link:focus-visible { color: var(--accent);
  text-decoration: underline; }
.wx-sub-n { font-weight: 400; font-size: 10px; color: var(--muted);
  margin-left: 6px; }

/* xv-fixture 2026-08-30: the cross-venue disambiguation chip. A fixture group
   can hold a full-game line beside a first-five-innings / spread / total line
   on the SAME game; this names the difference so the rows never read as
   interchangeable. Colours are variables per the graphical tenet. */
.eg-variant {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--panel);
  color: var(--jackpot);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
  vertical-align: middle;
}

/* ── mobile-usability 2026-08-31: phone ergonomics for the recently-shipped UI
   (operator: "run a sanity test on mobile UI … package the fixes").
   Sources: a 375×812 live audit. Vars only; every rule is ≤768-scoped so
   desktop is untouched. Three families:
   (1) INPUT ZOOM — any input under 16px makes iOS Safari zoom the whole page
       on focus (and 11px search text was near-illegible anyway).
   (2) TAP TARGETS — measured: pie Back 20px tall, pie rows 27px, modal ×
       24×28, board segment tabs 16×29 at SIX-POINT-FIVE px font.
   (3) The event-modal options table overflowed through the MODAL's own
       overflow-x, so dragging it panned the entire modal sideways — it gets
       its own scroll container (.opts-scroll, wrapper added in index.html). */
@media (max-width: 768px) {
  /* .893 review: this was OUTSIDE the media query, contradicting the block
     header above. `overflow-x:auto` with visible overflow-y computes
     overflow-y:auto, making each wrapper a BFC — so .opts-table's 10px
     margin-bottom stopped collapsing with the next .section-title's 18px
     margin-top and DESKTOP gained 10px between every table and the heading
     under it (measured 18px → 28px at 1280). The sideways-pan this fixes is
     a phone defect; scope the fix to phones. */
  .opts-scroll { overflow-x: auto; }
  /* (1) inputs ≥ 16px — search, the auto-fired free-account popup, donate/
     contact. The search input override outranks the 10527 11px rule by order. */
  .hero-inner .search-box input { font-size: 16px; padding: 6px 10px; }
  .pc-upsell-overlay input { font-size: 16px; }
  .donate-input { font-size: 16px; }

  /* The dropdown spans its parent .search-box, and the mobile header grid
     leaves that column ~199px of a 375px screen (measured) — titles
     truncated to ~10 characters. Fixed-position it to the viewport instead,
     anchored under the measured frozen band (--shell-top-h, set by
     _pc_shell.html measure(); the header is sticky, so the box is always AT
     that height while the dropdown is open). Height stops above the fixed
     bottom tape + tab bar. */
  .hero-inner .search-results {
    position: fixed; left: 8px; right: 8px;
    top: calc(var(--shell-top-h, 132px) + 4px);
    max-height: calc(100vh - var(--shell-top-h, 132px)
                     - var(--tape-h, 56px) - var(--mbn-h, 57px) - 20px);
  }
  .sr-item { padding: 12px; }                    /* rows 34px → ~42px */

  /* (2) tap targets. The pie flow's Back button is the ONLY route back from
     the Marketplace Card to the breakdown it came from. */
  .mkt-pie-back { font-size: 13px; padding: 9px 16px; }
  .mkt-pie-tbl td { padding: 11px 6px; }
  .modal-close { min-width: 40px; min-height: 40px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    top: 2px; right: 4px; }
  /* board segment tabs were 6.5px/16×29 — the only pagination for 200 rows.
     9px + wrap: the eight fit two rows if they must, never overflow.
     ⚠ .893 review: THE WRAP HALF WAS NEVER WIRED, so 9px alone OVERFLOWED —
     .board-tab-bar is `display:flex` with the default nowrap, and .btb-btn is
     `flex:1` (basis 0) + `white-space:nowrap` + visible overflow, so the four
     three-digit labels (101–125 … 176–200) spilled across their neighbours'
     borders. Measured at 375px: bar scrollWidth 266 vs 257 client, worst
     label 11px past its box. Wrapping needs BOTH halves — `flex-wrap` on the
     bar AND a content-based basis on the buttons, because a flex-basis of 0
     never wraps, it just shrinks below the text. Re-measured with both:
     overflow 0, two rows, full labels. */
  .board-tab-bar { flex-wrap: wrap; }
  .btb-btn { font-size: 9px; letter-spacing: 0; padding: 5px 2px;
             flex: 1 0 auto; }
  .bfb-btn { font-size: 10px; padding: 3px 8px; }
  /* marketplace-card + weekly chart metric toggles (~13-18px tall). */
  .mkt-card-7dbtn { font-size: 11px; padding: 5px 10px; }
  .mkt-wk-btn, .mkt-7d-btn { font-size: 11px; padding: 5px 10px; }
}

.modal-xv-vol { cursor: help; }

/* just-resolved 2026-09-02: settled-outcome chip on the Advanced Event Info lead
   tab. Vars only (graphical tenet): YES rides --accent, NO rides --danger, any
   other label (an option name, MKT %, CANCELLED) stays muted. */
.lq-box .jr-outcome { font-weight: 700; }
.lq-box .jr-outcome.jr-yes { color: var(--accent); }
.lq-box .jr-outcome.jr-no { color: var(--danger); }
.lq-box .jr-outcome.jr-other { color: var(--muted); }

/* anomalies-resurrect 2026-09-02: the Market Anomalies card in the free Alerts row.
   Score chip graded like the ET& list (>=60 strong / >=40 moderate / else weak),
   vars only (graphical tenet). The follow chip sits after the link in the flex row;
   min-width:0 + ellipsis on the title hold the no-horizontal-scrollbar rule. */
.anomalies-card .sig-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.anomalies-card .sig-row > .sig-link { flex: 1 1 0; min-width: 0; }
.anomalies-card .sig-row > .pc-evt-chip { flex: 0 0 auto; }
.anomalies-card .sig-score { font-weight: 700; font-variant-numeric: tabular-nums; }
.anomalies-card .anom-score-high { color: var(--danger); }
.anomalies-card .anom-score-mid { color: var(--jackpot); }
.anomalies-card .anom-score-low { color: var(--muted); }
.anomalies-card .anom-more { text-align: right; padding: 4px 6px 0; font-size: 11px; }
.anomalies-card .anom-more a { color: var(--accent); text-decoration: none; }

/* anomalies-oneline 2026-09-04 (operator: "make sure all events on the ANOMALIES
   table are presented by one line of data"). The meta chips and the venue name
   are unshrinkable; only the title may give way, and it already ellipsises.
   ⚠ Flex, not grid: the platform logo is conditional ({% if _al %}), so rows
   have 3 or 4 children and any fixed track list would mis-column the ones
   without a logo. The injected follow/unfollow chips stay their own size. */
.anomalies-card .sig-link { display: flex; flex-wrap: nowrap; gap: 6px; align-items: baseline; }
.anomalies-card .sig-title { flex: 1 1 auto; min-width: 0; }
.anomalies-card .sig-meta { flex: 0 0 auto; flex-wrap: nowrap; white-space: nowrap; }
.anomalies-card .sig-row > .pc-event-chip,
.anomalies-card .sig-row > .pc-unfollow-chip { flex: 0 0 auto; }

/* anom-facts 2026-09-05 (operator: "on market anomalies list add the market's
   total volume, % change last hour, leading option and its volume and odds, and
   the name of the 'heaviest' wallet on that event (linking to its wallet card
   pop up)"). Four chips on the SAME line - anomalies-oneline above still holds:
   chips are unshrinkable, only the title gives way (the leader label is capped
   so one long option name cannot eat the row). The wallet chip is an <a> of its
   own, a SIBLING of .sig-link (an anchor cannot nest in an anchor), so it sits
   in the row's flex line beside the follow chip; the modal list gets the same
   row flex so its wallet chip stays on the line too. Colours via vars. */
.anom-fact { font-weight: 600; }
.anom-fact.anom-up { color: var(--success); }
.anom-fact.anom-down { color: var(--danger); }
.anom-fact.anom-lead { display: inline-flex; gap: 3px; align-items: baseline; }
.anom-lead-lbl { max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.anom-whale { color: var(--whale); background: color-mix(in srgb, var(--whale) 15%, transparent); text-decoration: none; }
.anom-whale:hover { text-decoration: underline; }
.anomalies-card .sig-row > .anom-whale { flex: 0 0 auto; }
.anomaly-modal-list .sig-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.anomaly-modal-list .sig-row > .sig-link { flex: 1 1 0; min-width: 0; }
.anomaly-modal-list .sig-row > .anom-whale { flex: 0 0 auto; }
/* ⚠ MEASURED AT 375px (Playwright, real render): the card is 288px wide and a row 263px.
   With the chips the rows overflowed by 81-91px and the title collapsed to 0px; without
   them the title had 61-72px and nothing overflowed. One line cannot hold four facts on a
   phone, and the one-line rule is the operator's - so below the mobile-tabs breakpoint the
   chips (wallet chip included) step aside and the row renders exactly as before. The facts
   stay in the row tooltip and on the ET& card, whose sub-line wraps by design. */
@media (max-width: 768px) {
  /* .sig-row scoping is for SPECIFICITY, not scope: .anom-fact.anom-lead sets display:inline-flex
     with two classes, and a one-class .anom-fact rule would lose to it - measured: the lead
     chip alone stayed visible at 375px and still overflowed the row by 41px. */
  .sig-row .anom-fact { display: none; }
}

/* ═══ markets heatmap ════════════════════════════════════════════════════════
   hm-events 2026-09-04: MOVED here from templates/market_trends.html, where it
   was inline. The map now lives on /events (index.html) as a minimised box under
   the federated board plus a full-size popup; keeping the rules in the shared
   sheet means one copy and either page can host it.

   Venue hue is DATA (it arrives from _MKT_VENUE_META via the API, as an inline
   custom property); every colour the chrome owns is a var(). */
.hm-card { margin-top: 1rem; }
.hm-meta { font-size: 0.72rem; color: var(--muted); margin: 0.15rem 0 0.6rem; }
.hm-host { width: 100%; position: relative; }
.hm-svg { width: 100%; height: auto; display: block; }
.hm-blk-label { font-size: 10px; font-weight: 700; fill: var(--text); }
.hm-blk-sub { font-size: 8.5px; fill: var(--muted); }
/* ⚠ hm-peach 2026-09-04 (operator: "switch to white text in PEACHY UI view of
   hover-over tooltips in the HEATMAP chart — current dark text colour doesn't
   display"). The cause was NOT a missing peach rule: `--card-bg` is not defined
   in ANY theme, so that fallback always resolved to its hard-coded near-black
   while `color` resolved to the theme's own --text. On peach that is
   espresso text on a near-black box — invisible. Both now ride --panel/--text,
   which every theme defines, so peach and dark each resolve as a pair and no
   theme-scoped override is needed. */
.hm-tip { position: absolute; pointer-events: none; z-index: 6; max-width: 300px;
          background: var(--panel); color: var(--text);
          border: 1px solid var(--border); border-radius: 5px;
          padding: 6px 9px; font-size: 11.5px; opacity: 0; transition: opacity .1s; }
.hm-shutout { display: flex; flex-wrap: wrap; gap: 0.3rem 0.9rem; margin-top: 0.4rem;
              font-size: 0.7rem; color: var(--muted); align-items: center; }
.hm-shutout i { width: 9px; height: 9px; border-radius: 2px; display: inline-block;
                margin-right: 4px; vertical-align: middle; }
.hm-legend { display: flex; flex-wrap: wrap; gap: 0.3rem 0.9rem; margin-top: 0.5rem;
             font-size: 0.7rem; color: var(--muted); }
/* the pip rim was the same undefined-token literal; --panel keeps the rim the
   colour of the surface the tile sits on, in every theme */
.hm-pip { stroke: var(--panel); stroke-width: .4; pointer-events: none; }
.hm-legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block;
               margin-right: 4px; vertical-align: middle; }
.hm-note { font-size: 0.7rem; color: var(--muted); margin-top: 0.45rem;
           border-left: 2px solid var(--border); padding-left: 0.5rem; }
/* hm-equal 2026-09-05: the tile-size switch. Sits above the venue chips and
   borrows their metrics so the two control rows read as one group. */
/* hm-by-marketplace 2026-09-06: the row WRAPS. Two chips plus the label already
   fill a 375px phone, and the page's global overflow-x guard CLIPS rather than
   scrolls - a third chip on one line would be silently cut off and the mode
   would be unreachable on a phone. Wrapping is the fix that cannot be
   out-measured: a flex line never exceeds the container. */
.hm-size { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin: 0.35rem 0 0.1rem; }
.hm-size-l { font-size: 0.68rem; letter-spacing: .06em; text-transform: uppercase;
             color: var(--muted); margin-right: 0.15rem; }
.hm-sbtn { font: inherit; font-size: 0.72rem; padding: 0.12rem 0.5rem; cursor: pointer;
           border: 1px solid var(--border); border-radius: 999px;
           background: transparent; color: var(--muted); }
.hm-sbtn:hover { color: var(--text); border-color: var(--accent); }
.hm-sbtn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent);
                                color: var(--bg); font-weight: 600; }
.hm-venues { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.25rem 0 0.55rem; }
.hm-vbtn { display: inline-flex; align-items: center; gap: 0.35rem; font: inherit;
           font-size: 0.7rem; color: var(--muted); background: var(--panel);
           border: 1px solid var(--border); border-left: 3px solid var(--hm-c, var(--border));
           border-radius: 4px; padding: 2px 8px 2px 6px; min-height: 26px; cursor: pointer;
           line-height: 1.1; }
.hm-vbtn b { font-weight: 600; color: var(--text); opacity: .8; }
.hm-vbtn:hover { color: var(--text); border-color: var(--accent); }
.hm-vbtn[aria-pressed="true"] { color: var(--text); border-color: var(--accent);
                                box-shadow: inset 0 0 0 1px var(--accent); }
.hm-vbtn img, .hm-vbtn i { width: 14px; height: 14px; flex: 0 0 auto; }
.hm-vbtn img { object-fit: contain; opacity: .9; }
.hm-vbtn i { display: inline-block; border-radius: 2px; background: var(--hm-c, var(--border)); }
/* the title on a tile: a halo in the panel colour keeps it legible on any
   venue hue, on either theme, without a per-venue contrast table */
.hm-tile-t { fill: var(--text); font-weight: 600; pointer-events: none;
             paint-order: stroke; stroke: var(--panel); stroke-width: 2.4px;
             stroke-linejoin: round; }
/* hm-money 2026-09-04: the market's own volume, same halo treatment, one weight
   quieter than the title. Only ships for venues whose metric is resolvable —
   see markets_heatmap_unified_model. */
.hm-tile-v { fill: var(--text); opacity: .82; font-weight: 500; pointer-events: none;
             paint-order: stroke; stroke: var(--panel); stroke-width: 2.2px;
             stroke-linejoin: round; }
/* hm-multi-mark 2026-09-06: the M on a tile whose click opens the
   cross-marketplace card. Same halo as the title so it reads on every venue
   hue in either theme, and no colour of its own - the reason it is a LETTER
   and not a coloured dot is that 22 venue fills already own the palette. */
.hm-tile-m { fill: var(--text); font-weight: 700; pointer-events: none;
             paint-order: stroke; stroke: var(--panel); stroke-width: 2.4px;
             stroke-linejoin: round; }
/* hm-by-marketplace 2026-09-06: the marketplace block and its header. The frame
   is a hairline in the surface colour - the same rim the share pips use - so a
   block reads as a group without adding a 23rd colour to the map. Both are
   pointer-events:none: they paint over the tiles and must not eat their
   clicks. */
.hm-blk { fill: none; stroke: var(--panel); stroke-width: 1.2px; pointer-events: none; }
.hm-blk-t { fill: var(--text); font-weight: 700; letter-spacing: .01em;
            pointer-events: none; paint-order: stroke; stroke: var(--panel);
            stroke-width: 2.6px; stroke-linejoin: round; }
/* hm-live 2026-09-04: a market that arrived in the latest collect batch.
   ⚠ Under reduced-motion the blink is REPLACED, not dropped — the tile keeps a
   ring, so the information survives for a reader who cannot take animation. */
/* hm-denominations 2026-09-04 (operator: "items [added in the latest data
   refresh] should keep blinking until they are replaced, in a pulsating
   manner"). THE LOGIC ALREADY DID THIS AND IS UNCHANGED: aggregator._hm_mark_new
   keys "new" on the COLLECT BATCH, a batch with no arrivals keeps the previous
   set marked, and the animation was already infinite. It is live - 10 of 987
   tiles carried "n": 1 when this was measured on prod, 2026-09-04 15:56Z.
   WHAT FAILED WAS LEGIBILITY. A dip to .3 opacity reads as a HOLE punched in a
   field of solid colour blocks rather than as attention, and on the THUMBNAIL
   (a 1000x300 viewBox squeezed into a strip) a ~12px tile fading and returning
   is easy to miss entirely. The pulse now also breathes an accent RING, which
   is size-independent - a border on a big tile, near enough the whole tile on a
   small one - and the opacity floor rises so the tile never reads as missing.
   `vector-effect` holds the ring at a constant device width, so it stays
   visible on the thumbnail without over-spilling in the popup, where tiles
   carry only a 0.7-unit gutter. */
/* hm-ring-contrast 2026-09-05 (operator: "the rectangle should all blink, not
   just a ring"). The old frames faded the STROKE toward nothing (stroke-opacity
   1 -> .12, width 2px -> .5px) while the fill only dipped to .5 -- so what
   pulsed was the outline, and the tile itself barely moved. Now `opacity` on the
   whole element carries the pulse, which fades fill AND stroke together: the
   RECTANGLE blinks. Colour-independent by construction, so it reads on every
   venue palette; the contrast-flipped stroke stays constant for definition at
   the ~6-20px sizes most tiles actually render at.
   ⚠ This opacity OVERRIDES the rect's own `opacity` presentation attribute
   (.78/.95) for the duration -- deliberate: a marked tile should reach full
   strength at the peak of each cycle. */
/* hm-shimmer 2026-09-07 (operator: "not a perpetual strobe (sorry for
   miswording it) but a soft visual indicator that is not too intrusive" -
   "a little shimmer every five seconds").
   The 1.3s / opacity-.28 cycle was a STROBE: ~46 tiles pulsing hard, twice a
   second, forever. This is one soft breath per 5s instead - flat for ~4.1s,
   a gentle dip to .6 over ~0.45s, back. Same signal, a fraction of the
   agitation, and it still reads at the ~6-20px most tiles render at because
   the whole rectangle moves rather than a 2px edge. */
@keyframes hm-blink {
  0%, 82%, 100% { opacity: 1; }
  91%           { opacity: .6; }
}
/* hm-ring-contrast 2026-09-05: the ring colour is now set PER TILE as a
   presentation attribute (see ringInk() in the heatmap script) so it contrasts
   with the venue colour underneath it. A fixed `stroke: var(--accent)` here
   measured 1.15:1 on poly_us and 1.01:1 on kalshi -- invisible, which is why a
   correctly-marked tile read as "not blinking". ⚠ DO NOT REINSTATE `stroke` in
   these rules: a CSS stroke out-ranks the presentation attribute and would put
   the fixed teal straight back. */
/* ⚠ ROOT .924: the two ring inks are DECLARED AT THE TOP OF THIS SHEET, with
   every other token - see --hm-ring-light / --hm-ring-dark on :root. They were
   declared here, near the end, and FOUR "every colour a var()" audits slice
   from their own marker to EOF (test_heatmap_unified, test_markets_heatmap,
   test_most_liquid_view, test_two_phase_modal_client) - so a hex declared after
   any of those markers reads as a literal inside THEIR section. Two of the four
   only surfaced once all nine packages were stacked. */
.hm-svg .hm-new { animation: hm-blink 5s ease-in-out infinite;
                  stroke-width: 2px;
                  vector-effect: non-scaling-stroke; }
/* ⚠⚠ DELIBERATE OVERRIDE OF A USER ACCESSIBILITY PREFERENCE - operator
   decision, 2026-09-07, taken with the trade-off stated. `.911` honoured
   prefers-reduced-motion by dropping the animation and keeping the ring; the
   operator reports that reads as "a static ring" and asked for the indicator
   to show for everyone. It now does.
   The mitigation is the whole point and must not be undone: what runs under
   reduce is NOT the old strobe. One 5s cycle, ~4.1s of it perfectly still,
   dipping only to .6 - far inside what the old 1.3s/.28 cycle asked of anyone
   sensitive to motion. ⚠ If this keyframe is ever made faster or deeper,
   restore `animation: none` HERE at the same time; the two travel together.
   The ring stays at full strength either way. */
@media (prefers-reduced-motion: reduce) {
  .hm-svg .hm-new { stroke-width: 2px;
                    stroke-opacity: 1; vector-effect: non-scaling-stroke; }
}
/* hm-click 2026-09-04: a tile is a link to its event card */
.hm-svg a { cursor: pointer; }
.hm-svg a:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rv-archived .hm-svg { outline: 1px dashed var(--border); outline-offset: 2px; }
@media (max-width: 768px) {
  /* mobile-usability floor: a filter chip is a tap target */
  .hm-vbtn { min-height: 36px; padding: 4px 10px 4px 8px; }
}

/* ─── the minimised box under the federated board, and its popup ─────────── */
.hm-mini { margin-top: 0.55rem; }
.hm-mini-btn { display: block; width: 100%; padding: 0; background: var(--panel);
               border: 1px solid var(--border); border-radius: 6px; cursor: pointer;
               overflow: hidden; text-align: left; font: inherit; }
.hm-mini-btn:hover, .hm-mini-btn:focus-visible { border-color: var(--accent); }
.hm-mini-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* hm-minihead 2026-09-04 (operator: "instead of 'who owns each market' insert a
   centered larger box title: Top 1,000 open event HEATMAP. And under that CLICK
   TO ENLARGE"). The head was a baseline ROW with the meta pushed to the far
   edge; it is now a centred COLUMN — title, then the affordance, then the meta.
   ⚠ .hm-mini-head b sets the title size, so the title rule has to out-specify
   it (b.hm-mini-title) rather than sit next to it and lose. */
.hm-mini-head { display: flex; flex-direction: column; align-items: center;
                justify-content: center; text-align: center; gap: 0.12rem;
                padding: 0.5rem 0.55rem 0.35rem; font-size: 0.68rem;
                color: var(--muted); }
.hm-mini-head b { color: var(--text); font-weight: 600; font-size: 0.76rem; }
.hm-mini-head b.hm-mini-title { font-size: 1.02rem; letter-spacing: 0.01em;
                                line-height: 1.2; }
.hm-mini-cta { font-weight: 700; font-size: 0.66rem; letter-spacing: 0.08em;
               text-transform: uppercase; color: var(--accent); }
.hm-mini .hm-svg { max-height: 168px; }
/* hm-podium .934 (operator: "In the currently empty real estate to the right of
   the minimized HEATMAP, add three square buttons, gold silver and bronze,
   displaying the open markets that have gone up the most $ in the past 24h").
   The map and the podium share ONE row: the map keeps every pixel it had minus
   the podium's fixed column, and the three squares stack beside it. Squares are
   a fixed 72px, not aspect-ratio games inside a column flex whose cross size is
   auto - three of them plus gaps (232px) match the map's head + 168px svg.
   ⚠ Every colour a var(): the medal tokens sit at the top of this file and
   peach rebinds them. Two-step backgrounds per the .932 lesson - a lone
   color-mix() is one declaration a non-supporting renderer drops whole. */
.hm-mini-row { display: flex; gap: 12px; align-items: flex-start; min-width: 0; }
.hm-mini-row .hm-mini { flex: 1 1 0; min-width: 0; margin-top: 0; }
.hm-podium { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.hm-pod { display: flex; flex-direction: column; align-items: center;
          justify-content: center; gap: 1px; width: 72px; height: 72px;
          padding: 0; cursor: pointer; font: inherit; color: var(--text);
          border: 1px solid var(--border); border-radius: 6px;
          background: var(--panel); overflow: hidden; }
.hm-pod-1 { border-color: var(--medal-1);
            background: color-mix(in srgb, var(--medal-1) 14%, var(--panel)); }
.hm-pod-2 { border-color: var(--medal-2);
            background: color-mix(in srgb, var(--medal-2) 14%, var(--panel)); }
.hm-pod-3 { border-color: var(--medal-3);
            background: color-mix(in srgb, var(--medal-3) 14%, var(--panel)); }
.hm-pod:hover, .hm-pod:focus-visible { border-width: 2px; }
.hm-pod:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.hm-pod-medal { font-size: 18px; line-height: 1; }
.hm-pod-amt { font-family: monospace; font-weight: 700; font-size: 11px;
              line-height: 1.1; letter-spacing: -0.01em; }
.hm-pod-venue { font-size: 7.5px; letter-spacing: 0.08em; text-transform: uppercase;
                color: var(--muted); line-height: 1; max-width: 66px;
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 900px) {
  /* the band stacks on a phone; the podium goes UNDER the map as a row of three */
  .hm-mini-row { flex-direction: column; }
  .hm-podium { flex-direction: row; justify-content: center; }
}
/* the scrim matches .modal-overlay's, the shade this app already uses */
/* hm-front 2026-09-04 (operator: "make the pop-up enlarged heatmap window a real
   full pop up window — it is currently being obscured by various banners").
   ⚠ z-index 60 sat UNDER the frozen shell chrome: .pc-shell-top and
   body.pc-shell > header are 420, the ticker strips 419/418 and .pc-sidenav
   415. This page already answered the same complaint for #event-group-overlay
   (contact-front / xv-front): a STATIC FLOOR above the band, with
   _frontOverlay's climbing inline z still winning when overlays interleave.
   The climb is load-bearing here — a tile click opens an event card, which
   fronts itself and must land ABOVE this popup, not behind it. */
.hm-modal { position: fixed; inset: 0; z-index: 1000; background: rgba(5, 8, 20, 0.85);
            display: flex; align-items: flex-start; justify-content: center;
            padding: 2vh 2vw; overflow: auto; }
.hm-modal[hidden] { display: none; }
.hm-modal-box { background: var(--panel); border: 1px solid var(--border);
                border-radius: 8px; width: min(1060px, 96vw); padding: 0.85rem 1rem 1rem;
                position: relative; }
.hm-modal-box h2 { margin: 0 0 0.15rem; font-size: 1rem; }
.hm-modal-close { position: absolute; top: 0.3rem; right: 0.5rem; background: none;
                  border: 0; color: var(--muted); font-size: 1.5rem; line-height: 1;
                  cursor: pointer; padding: 0 0.25rem; }
.hm-modal-close:hover, .hm-modal-close:focus-visible { color: var(--text); }
/* hm-share 2026-09-04: the popup's attribution + share row. Every colour is a
   var per the graphical tenet, so both themes follow. The bar reserves room on
   the right for .hm-modal-close, which is absolutely positioned over this
   corner (top 0.3rem / right 0.5rem) and would otherwise sit on the button. */
.hm-brandbar { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
               padding-right: 2rem; margin: 0 0 0.4rem; }
.hm-powered { display: inline-flex; align-items: center; gap: 0.35rem;
              font-size: 0.7rem; color: var(--muted); letter-spacing: 0.02em; }
.hm-powered b { color: var(--accent); font-weight: 700; }
.hm-powered-logo { display: block; width: 18px; height: 18px; border-radius: 4px; }
.hm-share { margin-left: auto; display: inline-flex; align-items: center; gap: 0.3rem;
            font-size: 0.72rem; font-weight: 600; font-family: inherit;
            color: var(--muted); background: none; border: 1px solid var(--border);
            border-radius: var(--r-chip); padding: 0.2rem 0.55rem; cursor: pointer; }
.hm-share:hover, .hm-share:focus-visible { color: var(--accent); border-color: var(--accent); }
.hm-share.is-done { color: var(--success); border-color: var(--success); }
/* the copy result reaches a screen reader without taking any layout */
.hm-sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
         clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* hot200-slim 2026-09-04 (operator: "cut 10% of the hot 200 board width, without
   cutting out any text or figures and without causing a horizontal scroll bar" +
   "widen the CROSS_VENUE box and advanced event info box to fill the space").
   ONE edit does both: the band is a two-track grid, so the width the board gives
   up is the width the left flank receives - then cross-venue on row 1 and the
   lq-box / ADVANCED EVENT INFO on row 2; since .944 row 2 is the free Market
   Alerts, and ADVANCED EVENT INFO sits in the board's own column under Hot-200.
   2.2fr → 1.62fr moves the board 68.75% → 61.8%
   and the flank 31.25% → 38.2%.
   ⚠ Gated at 1150px. Below that the board's row tracks (86+44+62+58px + gaps)
   no longer fit a narrower column and would force the horizontal scrollbar the
   ask forbids; there the shipped 2.2fr still stands. Below 900px the band is
   already single-column and neither ratio applies. */
@media (min-width: 1150px) {
  .departures-band {   /* was keyed on :not(:has(.marketplace-card)), always true (events-band-dead-placement-rules) */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.62fr);
  }
}

/* board-fold 2026-09-04 (operator: "fold the top-200 federated board so that it
   only displays up until the fifth event from the top and is collapseable").
   ⚠ NOT optional polish: .departures-band .board-card is align-self:stretch and
   spans both rows when the lq-box is present, and .board-card-list is flex:1 1 0
   — so a 5-row list inside a flank-height card leaves ~540px of empty card.
   That is a NO-EMPTY-BOXES violation, so the fold has to release the stretch. */
.board-fold-bar { display: flex; justify-content: center; padding: 0.35rem 0 0.1rem; }


/* mt-card-range 2026-09-07: the inline (chart-card) variant of the scrub
   pair. Two ordinary range inputs side by side rather than an overlaid
   dual-thumb: overlaying needs absolute positioning plus pointer-events
   juggling, whose classic failure is a top handle that cannot be grabbed.
   Two tracks are keyboard-operable and need no such machinery.
   min-width:0 on the inputs is the no-horizontal-scrollbar rule - a flex
   child with intrinsic width is exactly what pushes a card past 100vw. */
/* mt-card-range-2 port (.936): the base scrubber, moved here from the /markets
   page style because the marketplace card's date window now renders on /events
   too. Same rules, one place. */
.mt-scrub { display: flex; align-items: center; gap: 10px; margin: 2px 0 10px;
            font-family: monospace; font-size: 11px; color: var(--muted); }
.mt-scrub input[type=range] { flex: 1; min-width: 0; accent-color: var(--accent); }
.mt-scrub-date { color: var(--accent); min-width: 84px; text-align: right; }
.mt-scrub.mt-scrub-inline { display: inline-flex; align-items: center; gap: 6px;
                   margin-left: 10px; min-width: 0; flex-wrap: wrap; }
.mt-scrub.mt-scrub-inline input[type=range] { flex: 1 1 90px; min-width: 0; max-width: 150px;
                                     accent-color: var(--accent); }
.mt-scrub.mt-scrub-inline .mt-scrub-date { color: var(--accent); font-variant-numeric: tabular-nums; }
.mt-scrub.mt-scrub-inline[hidden] { display: none; }
