    :root {
      --bg-base: #09090b; --bg-surface: #111113; --bg-elevated: #18181b;
      --bg-hover: #27272a; --bg-active: #3f3f46;
      --bg-card: #111113; --bg-detail: #18181b; --bg-page: #09090b;
      --bg-raised: #27272a; --bg-sidebar: #0e0e10;
      --border: rgba(255,255,255,0.1); --border-subtle: rgba(255,255,255,0.06);
      --border-default: rgba(255,255,255,0.1); --border-strong: rgba(255,255,255,0.16);
      --accent: #10b981; --accent-hover: #059669;
      --accent-muted: rgba(16,185,129,0.15); --accent-glow: #10b981;
      /* FIX 2026-07-23: the secondary/muted ramp cleared the 4.5:1 AA floor but
         still read as dim gray at a glance. Raised the whole muted end so the
         lowest rung sits ~7:1 and the top of the ramp ~11:1 on --bg-surface,
         keeping the ordering primary > secondary > muted > faint > dim. */
      --text-primary: #f4f4f5; --text-secondary: #d4d4d8; --text-muted: #c6c6cd; /* was #b4b4bc */
      --text-faint: #b0b0ba; /* was #8a8a94, 5.6:1 → 9.9:1 */
      --text-dim: #a3a3ad;   /* was #86868f, 5.2:1 → 7.5:1 (#71717a before that was a 3.9:1 AA fail) */
      --accent-blue: #10b981; --accent-blue-light: #34d399;
      --accent-green: #22c55e; --accent-green-bg: rgba(34,197,94,0.12);
      --accent-red: #f87171; --accent-red-bg: rgba(239,68,68,0.12); /* #ef4444 text was 4.49:1 on light rows — WCAG 1.4.3 nudge to red-400 (FIX 2026-07-18, ~6.8:1); bg tint unchanged */
      --accent-amber: #f59e0b; --accent-amber-bg: rgba(245,158,11,0.12);
      --ev-pos: #22c55e; --ev-neg: #f87171; /* lightened from #ef4444 for WCAG 1.4.3 AA (FIX 2026-07-18) */
      --shadow-card: 0 2px 8px rgba(0,0,0,0.4); --shadow-hover: 0 4px 16px rgba(0,0,0,0.5);
      --radius-sm: 6px; --radius-md: 8px; --radius-lg: 12px; --radius-pill: 999px;
      --transition-fast: 120ms ease-in-out; --transition-normal: 200ms ease;
      --font-mono: 'IBM Plex Mono','JetBrains Mono','SF Mono','Fira Code',monospace;
      --space-xs: 4px; --space-sm: 8px; --space-md: 12px; --space-lg: 16px; --space-xl: 24px;
      /* FIX 2026-07-23: type ramp was 15/13/11/9 — body copy at 13px and micro
         labels at 9px are well under any comfortable reading floor. Raised across
         the board, and every hardcoded px/rem font-size in the app was swept onto
         the same curve. 12px is now the smallest text any surface can render; a
         live /ui pass is the check (209 text nodes sat at 11px after the first
         pass — game times, book names, grade chips — so the floor moved again). */
      --text-lg: 18px; --text-base: 15px; --text-sm: 13px; --text-xs: 12px;
    }
    /* Light theme removed — dark mode only */
    html { scroll-behavior: smooth; }
    body { font-family: 'IBM Plex Sans',system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; margin:0; background:var(--bg-page); color:var(--text-secondary); font-size:var(--text-base); line-height:1.55; }
    :focus-visible { outline:2px solid var(--accent-blue); outline-offset:2px; }
    /* Top Nav */
    .top-nav { position:fixed; top:0; left:0; right:0; height:56px; padding-top:env(safe-area-inset-top); background:var(--bg-surface); border-bottom:1px solid var(--border-subtle); display:flex; align-items:center; padding-left:var(--space-xl); padding-right:var(--space-xl); padding-bottom:0; z-index:100; gap:var(--space-xl); }
    .top-nav-logo-wrap { display:flex; flex-direction:column; line-height:1; min-width:160px; flex-shrink:0; }
    .top-nav-logo { font-size:1.4rem; font-weight:300; color:var(--text-primary); white-space:nowrap; font-family:'IBM Plex Sans',sans-serif; letter-spacing:-0.02em; }
    .top-nav-logo .logo-pipe { font-weight:800; color:var(--accent); text-shadow:0 0 8px rgba(16,185,129,0.4); }
    .top-nav-logo .logo-bold { font-weight:700; }
    .top-nav-logo .logo-sigma { font-weight:700; font-size:0.75em; vertical-align:0.1em; color:var(--accent); text-shadow:0 0 14px rgba(16,185,129,0.5); }
    .top-nav-tagline { font-family:var(--font-mono); font-size:12px; letter-spacing:0.18em; color:var(--accent); text-transform:uppercase; margin-top:3px; animation:taglineGlow 3s ease-in-out infinite; }
    @keyframes taglineGlow { 0%,100%{opacity:0.6;text-shadow:none;} 50%{opacity:1;text-shadow:0 0 8px rgba(16,185,129,0.4);} }
    /* Prediction Markets tables */
    .pm-table { width:100%; border-collapse:collapse; font-size:var(--text-sm); }
    .pm-table th { font-size:var(--text-xs); color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.06em; font-weight:700; padding:8px 12px; text-align:left; border-bottom:1px solid var(--border-default); background:var(--bg-surface); }
    .pm-table td { padding:8px 12px; border-bottom:1px solid var(--border-subtle); color:var(--text-secondary); vertical-align:top; }
    .pm-table tr:hover td { background:var(--bg-hover); }
    .pm-table td:nth-child(n+3) { font-family:var(--font-mono); }
    .top-nav-tabs { display:flex; gap:var(--space-xs); margin-left:var(--space-xl);
      /* min-width:0 is the load-bearing bit: a flex item's default min-width is
         auto, i.e. its content, so this strip refused to shrink and shoved
         .top-nav-right (Sign In included) past the viewport edge with no way to
         scroll to it. Now the strip is the only thing that gives. */
      min-width:0; flex-shrink:1; overflow-x:auto; overscroll-behavior-x:contain;
      scrollbar-width:none; -ms-overflow-style:none; }
    /* A visible scrollbar inside a 56px nav would eat the tabs' underline. */
    .top-nav-tabs::-webkit-scrollbar { display:none; }
    .top-nav-tab { padding:var(--space-sm) var(--space-md); font-size:15px; font-weight:500; color:var(--text-muted); cursor:pointer; border-bottom:2px solid transparent; transition:color var(--transition-fast),border-color var(--transition-fast); line-height:52px; white-space:nowrap; flex-shrink:0; }
    .top-nav-tab:hover { color:var(--text-secondary); }
    .top-nav-tab.active { color:var(--accent); border-bottom-color:var(--accent); font-weight:600; }
    .top-nav-right { margin-left:auto; display:flex; align-items:center; gap:var(--space-sm); flex-shrink:0; }
    .top-nav-settings { position:relative; }
    .top-nav-pill { background:none; border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:6px 14px; color:var(--text-secondary); cursor:pointer; font-size:15px; font-weight:500; transition:all var(--transition-fast); font-family:'IBM Plex Sans',sans-serif; display:inline-flex; align-items:center; gap:6px; white-space:nowrap; }
    .top-nav-pill:hover { border-color:var(--accent); color:var(--text-primary); }
    .bankroll-pill { gap:2px; }
    .bankroll-pill .bankroll-label { color:var(--text-secondary); font-weight:600; font-size:var(--text-sm); text-transform:uppercase; letter-spacing:0.04em; }
    .bankroll-pill .bankroll-sep { color:var(--text-muted); font-family:var(--font-mono); font-weight:600; margin-left:6px; }
    .bankroll-pill .bankroll-input { background:none; border:none; color:var(--text-primary); font-family:var(--font-mono); font-size:15px; font-weight:600; width:60px; padding:0; outline:none; -moz-appearance:textfield; }
    .bankroll-pill .bankroll-input::-webkit-inner-spin-button,
    .bankroll-pill .bankroll-input::-webkit-outer-spin-button { -webkit-appearance:none; margin:0; }
    .bankroll-pill .bankroll-input:focus { color:var(--accent); }
    .bankroll-pill .bankroll-units { color:var(--text-muted); font-family:var(--font-mono); font-size:15px; font-weight:600; border-left:1px solid var(--border-default); padding-left:6px; margin-left:4px; }
    .top-nav-dropdown { position:absolute; top:calc(100% + 4px); right:0; width:260px; background:var(--bg-surface); border:1px solid var(--border-default); border-radius:var(--radius-md); padding:var(--space-md); display:none; box-shadow:0 8px 24px rgba(0,0,0,0.4); z-index:200; }
    .top-nav-dropdown.open { display:block; }
    .top-nav-dropdown label { font-size:var(--text-sm); color:var(--text-secondary); display:block; margin-bottom:var(--space-xs); }
    .top-nav-dropdown input[type="number"] { width:100%; box-sizing:border-box; background:var(--bg-elevated); border:1px solid var(--border-default); border-radius:var(--radius-sm); padding:var(--space-xs) var(--space-sm); color:var(--text-primary); font-size:var(--text-base); margin-bottom:var(--space-sm); }
    .top-nav-dropdown input:focus { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-muted); outline:none; }
    /* Hamburger (mobile only) + mobile menu sheet */
    .top-nav-hamburger { display:none; background:none; border:1px solid var(--border-strong); border-radius:var(--radius-sm); width:44px; height:44px; padding:11px 9px; cursor:pointer; flex-direction:column; justify-content:space-between; align-items:stretch; flex-shrink:0; }
    .top-nav-hamburger:hover { border-color:var(--accent); }
    .top-nav-hamburger:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
    .top-nav-hamburger span { display:block; height:2px; background:var(--text-secondary); border-radius:1px; }
    .top-nav-mobile-menu { display:none; left:auto; right:var(--space-md); top:calc(56px + env(safe-area-inset-top) + 4px); width:240px; }
    .top-nav-mobile-menu.open { display:flex; flex-direction:column; gap:6px; }
    .top-nav-mobile-menu .top-nav-pill { width:100%; justify-content:flex-start; min-height:44px; }
    /* Bottom nav (mobile chrome) */
    .bottom-nav { display:none; position:fixed; left:0; right:0; bottom:0; padding-bottom:env(safe-area-inset-bottom); background:var(--bg-surface); border-top:1px solid var(--border-subtle); z-index:100; }
    .bottom-nav-inner { display:flex; align-items:stretch; justify-content:space-around; height:64px; }
    .bottom-nav-item { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; flex:1 1 0; min-width:44px; min-height:44px; background:none; border:none; color:var(--text-muted); font-size:12px; font-weight:500; cursor:pointer; transition:color var(--transition-fast); padding:6px 4px; font-family:'IBM Plex Sans',sans-serif; }
    .bottom-nav-item:hover { color:var(--text-secondary); }
    .bottom-nav-item.active { color:var(--accent); }
    .bottom-nav-item:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
    .bottom-nav-item .bn-icon { font-size:20px; line-height:1; letter-spacing:-0.05em; display:inline-flex; align-items:center; justify-content:center; }
    .bottom-nav-item .bn-icon svg { width:22px; height:22px; display:block; }
    .bottom-nav-item .bn-label { letter-spacing:0.02em; }
    /* Medium-desktop (640-1399px): full desktop chrome but tightened so it fits
       narrower laptop widths (1280, 1366, 1440) without overflowing. Without this,
       7 tabs + bankroll-pill + Settings + Parlay + Sign-In overflows the viewport
       at ~1363px minimum natural width.

       FIX 2026-08-22: tightening alone never closed the gap. Measured on prod at
       a 1100px viewport the nav still wanted 1445px, so ~345px ran off the right
       edge -- and because nothing here scrolls horizontally, everything past the
       edge was simply unreachable. Sign In is the last child of .top-nav-right,
       so it was the first thing lost: at 1280px it sat at x=1375. The whole band
       from 640px (where the hamburger takes over) to ~1400px was a dead zone.
       The real fix is the min-width:0 on .top-nav-tabs above; this block now only
       does what its name says, buying space rather than pretending to fix
       overflow. */
    @media (min-width: 640px) and (max-width: 1399px) {
      .top-nav { gap: var(--space-md); padding-left: var(--space-md); padding-right: var(--space-md); }
      .top-nav-tabs { margin-left: var(--space-sm); gap: 0; }
      .top-nav-pill { padding: 6px 10px; }
      .bankroll-pill .bankroll-units { display: none; }
    }
    /* 640-1039px: below ~860px even a zero-width tab strip cannot absorb enough --
       the fixed chrome alone (logo 160 + Home 83 + right-hand controls ~519 +
       gaps) needs ~842px. The cutoff is 1039 rather than the ~860 the arithmetic
       suggests because stopping at the overflow point leaves the strip
       technically scrollable but useless: measured, a 900px viewport gave the
       tabs 27px while 899px gave them 257px, a cliff on either side of one
       pixel. 1039 keeps ~200px of tabs at the moment the full chrome returns.
       Recover the space from the three lowest-value pixels, never from Sign In:
         - the Home button, whose destination the logo already is (it carries
           role="link" and the same switchTab('premium') handler); it is hidden
           <=639px for this same reason.
         - the tagline and the oversized logo, per the <=639px rules.
         - the "Bankroll" word; the "$" and the input remain, and the 2026-05-17
           audit note above keeps the "$" precisely so the number is not read as
           a phone number. */
    @media (min-width: 640px) and (max-width: 1039px) {
      .top-nav-home { display: none; }
      .top-nav-tagline { display: none; }
      .top-nav-logo-wrap { min-width: auto; }
      .top-nav-logo { font-size: 1.05rem; }
      .bankroll-pill .bankroll-label { display: none; }
    }
    /* Mobile breakpoint (<640px): collapse tabs + Settings + Parlay into hamburger; show bottom nav */
    @media (max-width: 639px) {
      .top-nav { padding-left:var(--space-md); padding-right:var(--space-md); gap:var(--space-sm); }
      .top-nav-hamburger { display:flex; }
      .top-nav-tabs { display:none; }
      .top-nav-tagline { display:none; }
      .top-nav-logo-wrap { min-width:auto; }
      .top-nav-logo { font-size:1.05rem; }
      .top-nav-right { gap:var(--space-xs); margin-left:auto; }
      /* FIX 2026-07-12: collapse everything except the bankroll pill into the
         hamburger/bottom-nav on phones. The old selector targeted
         onclick*="openParlaySlip" — a handler that no longer exists (the
         Parlay Cart button now calls Slate.toggleCart) — so Parlay Cart,
         Builder and Sign In never hid and overflowed/collided with the
         hamburger at <=430px. Login stays reachable via the bottom-nav
         Account item. */
      .top-nav-right > *:not(.bankroll-pill) { display:none; }
      /* 2026-05-17 audit S2: keep '$' on mobile so "1000" doesn't read as a phone number. */
      .bankroll-pill .bankroll-label, .bankroll-pill .bankroll-units { display:none; }
      .top-nav-pill { min-height:44px; padding:8px 12px; }
      .top-nav-home { display:none; }   /* bottom-nav "Games" covers home on mobile */
      .bottom-nav { display:block; }
      .feedback-fab { display:none; }
      /* Touch targets (WCAG 2.5.5). A live 375px audit found these well under
         the 44px floor this very block already applies to .top-nav-pill — the
         2026-07-18 sweep set the standard but nothing enforced it, so controls
         outside its scope never got it. Measured: bankroll input 19px, tutorial
         skip 17px, role="link" logo/home wrapper 16px.
         .bankroll-input drives unit sizing + Kelly math, so a mis-tap there
         mis-sizes every stake the product recommends.
         NOT included: the inline "See how it works" link inside the sign-in
         sentence — WCAG exempts inline links in a text block.
         Pinned by tests/test_slate_touch_targets.py. */
      .bankroll-pill .bankroll-input { min-height:44px; }
      .tutorial-skip-link { min-height:44px; display:flex; align-items:center; justify-content:center; }
      .top-nav-logo-wrap { min-height:44px; justify-content:center; }
    }
    /* Layout */
    .app-layout { display:grid; grid-template-columns:180px 1fr; min-height:100vh; padding-top:56px; }
    /* Tutorial centered card */
    .tutorial-overlay { position:fixed; inset:0; z-index:10000; display:flex; align-items:center; justify-content:center; background:rgba(0,0,0,0.6); backdrop-filter:blur(4px); transition:opacity 0.3s ease; }
    .tutorial-overlay.hidden { display:none; }
    .tutorial-card { background:var(--bg-card); border:1px solid var(--border-default); border-top:3px solid var(--accent); border-radius:var(--radius-lg); width:min(560px, 90vw); box-shadow:0 24px 80px rgba(0,0,0,0.5); animation:modalFadeIn 0.3s ease; overflow:hidden; }
    .tutorial-card-header { display:flex; align-items:center; justify-content:space-between; padding:16px 20px; }
    .tutorial-card-logo { font-size:1.2rem; font-weight:300; color:var(--text-primary); }
    .tutorial-card-logo .pipe { font-weight:800; color:var(--accent); text-shadow:0 0 8px rgba(16,185,129,0.3); }
    .tutorial-card-logo .bold { font-weight:700; }
    .tutorial-card-logo .sigma { font-weight:700; font-size:0.7em; vertical-align:0.08em; color:var(--accent); text-shadow:0 0 8px rgba(16,185,129,0.3); }
    .tutorial-card-close { background:none; border:1px solid var(--border-default); color:var(--text-muted); width:44px; height:44px; border-radius:var(--radius-sm); cursor:pointer; font-size:16px; display:flex; align-items:center; justify-content:center; transition:all 0.15s; }
    .tutorial-card-close:hover { border-color:var(--accent); color:var(--accent); background:var(--accent-muted); }
    .tutorial-card-body { padding:0 20px 20px; text-align:center; }
    .tutorial-card-tagline { font-family:var(--font-mono); font-size:15px; letter-spacing:0.18em; text-transform:uppercase; color:var(--accent); margin-bottom:16px; text-align:center; }
    .tutorial-card-headline { font-size:1.3rem; font-weight:700; color:var(--text-primary); letter-spacing:-0.02em; margin-bottom:8px; }
    .tutorial-card-desc { font-size:var(--text-base); color:var(--text-muted); line-height:1.6; max-width:420px; margin:0 auto 24px; }
    /* gap 20px -> 12px (2026-08-01): the row lists all ten steps now, not the
       seven it used to show while the copy beside it claimed ten. */
    .tutorial-card-steps { display:flex; justify-content:center; gap:12px; margin-bottom:24px; flex-wrap:wrap; }
    .tutorial-card-step { display:flex; flex-direction:column; align-items:center; gap:4px; }
    .tutorial-card-step-num { width:28px; height:28px; border-radius:50%; background:var(--accent-muted); border:1px solid rgba(16,185,129,0.25); display:flex; align-items:center; justify-content:center; font-family:var(--font-mono); font-size:12px; font-weight:700; color:var(--accent); }
    .tutorial-card-step-label { font-size:12px; font-weight:600; color:var(--text-faint); text-transform:uppercase; letter-spacing:0.06em; }
    .tutorial-play-btn { display:inline-flex; align-items:center; gap:8px; padding:12px 32px; border-radius:var(--radius-sm); border:none; background:var(--accent); color:#0d1117; font-family:'IBM Plex Sans',sans-serif; font-size:15px; font-weight:700; cursor:pointer; transition:all 0.15s; letter-spacing:0.02em; min-height:44px; } /* dark text: #fff was 2.54:1 on the green — WCAG 1.4.3 fail (FIX 2026-07-18, now 7.5:1) */
    .tutorial-play-btn:hover { background:#0ea572; transform:translateY(-1px); box-shadow:0 4px 16px rgba(16,185,129,0.3); }
    .tutorial-play-btn svg { flex-shrink:0; }
    .tutorial-skip-link { display:block; margin-top:12px; font-size:var(--text-sm); color:var(--text-faint); cursor:pointer; text-decoration:underline; text-underline-offset:2px; transition:color 0.15s; }
    .tutorial-skip-link:hover { color:var(--text-secondary); }
    /* Tutorial fullscreen mode */
    .tutorial-fullscreen { position:fixed; inset:0; z-index:10001; background:#06080c; display:none; flex-direction:column; }
    .tutorial-fullscreen.active { display:flex; }
    .tutorial-fs-header { display:flex; align-items:center; justify-content:flex-end; padding:8px 16px; background:rgba(9,9,11,0.95); border-bottom:1px solid rgba(255,255,255,0.08); flex-shrink:0; }
    .tutorial-fs-close { background:none; border:1px solid rgba(255,255,255,0.12); color:var(--text-muted); width:36px; height:36px; border-radius:var(--radius-sm); cursor:pointer; font-size:20px; display:flex; align-items:center; justify-content:center; transition:all 0.15s; }
    .tutorial-fs-close:hover { border-color:var(--accent); color:var(--accent); background:var(--accent-muted); }
    .tutorial-fs-iframe { flex:1; width:100%; border:none; background:#06080c; }
    .sidebar { background:var(--bg-sidebar); border-right:1px solid var(--border-default); padding:12px 0; position:sticky; top:56px; height:calc(100vh - 56px); overflow-y:auto; display:flex; flex-direction:column; }
    .sidebar-section { padding:12px 12px 4px; }
    .sidebar-section-title { font-size:var(--text-sm); font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.1em; padding:0 8px; margin-bottom:4px; }
    .sidebar-nav-item { display:flex; align-items:center; padding:8px 12px; border-radius:var(--radius-sm); cursor:pointer; font-size:var(--text-base); font-weight:600; color:var(--text-primary); transition:background var(--transition-fast),color var(--transition-fast); border-left:3px solid transparent; margin:1px 0; gap:8px; }
    .sidebar-nav-icon { width:18px; text-align:center; font-size:1rem; line-height:1; flex-shrink:0; }
    .sidebar-count { margin-left:auto; }
    .sidebar-nav-item:hover { background:var(--accent-muted); color:var(--text-primary); }
    .sidebar-nav-item.active { background:var(--accent-muted); color:var(--accent-blue); font-weight:700; border-left-color:var(--accent-blue); }
    .sidebar-count { font-size:var(--text-base); font-weight:600; background:var(--bg-hover); color:var(--text-muted); padding:2px 7px; border-radius:var(--radius-pill); min-width:18px; text-align:center; }
    .sidebar-nav-item.active .sidebar-count { background:var(--accent-muted); color:var(--accent-blue); }
    /* Hierarchical category styles */
    .sidebar-category { border:none; padding:0; margin:0; }
    .sidebar-category > summary { display:flex; align-items:center; gap:6px; padding:6px 12px; font-size:var(--text-sm); font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.06em; cursor:pointer; list-style:none; user-select:none; }
    .sidebar-category > summary::-webkit-details-marker { display:none; }
    .sidebar-category > summary::before { content:'\25BE'; font-size:var(--text-sm); width:10px; text-align:center; transition:transform 0.15s ease; color:var(--text-faint); }
    .sidebar-category:not([open]) > summary::before { transform:rotate(-90deg); }
    .sidebar-category > summary:hover { color:var(--text-primary); }
    .sidebar-category > summary .cat-icon { font-size:var(--text-base); line-height:1; }
    .sidebar-league-list { padding:0 0 2px; }
    .sidebar-league-item { display:flex; align-items:center; padding:6px 12px 6px 28px; border-radius:var(--radius-sm); cursor:pointer; font-size:var(--text-base); font-weight:600; color:var(--text-primary); transition:background var(--transition-fast),color var(--transition-fast); border-left:3px solid transparent; margin:1px 0; gap:6px; }
    .sidebar-league-item:hover { background:var(--accent-muted); color:var(--text-primary); }
    .sidebar-league-item.active { background:var(--accent-muted); color:var(--accent-blue); font-weight:700; border-left-color:var(--accent-blue); }
    .sidebar-league-item .league-icon { flex-shrink:0; line-height:0; width:32px; display:flex; align-items:center; justify-content:center; }
    .sidebar-league-item .league-icon img { height:30px; width:auto; max-width:32px; object-fit:contain; display:block; }
    .sidebar-league-item .sidebar-count { margin-left:auto; }
    .sidebar-league-item.active .sidebar-count { background:var(--accent-muted); color:var(--accent-blue); }
    .sidebar-league-item.placeholder { opacity:0.5; }
    .sidebar-control { padding:4px 8px; }
    .sidebar-control label { display:block; font-size:var(--text-sm); font-weight:500; color:var(--text-muted); margin-bottom:2px; }
    .sidebar-control input[type="number"], .sidebar-control input[type="text"] { width:100%; box-sizing:border-box; background:var(--bg-page); border:1px solid var(--border-default); color:var(--text-primary); border-radius:var(--radius-sm); padding:5px 8px; font-size:var(--text-base); }
    .sidebar-control input:focus { border-color:var(--accent-blue); box-shadow:0 0 0 2px var(--accent-muted); outline:none; }
    .sidebar-control-row { display:flex; align-items:center; gap:6px; padding:4px 8px; }
    .sidebar-control-row label { font-size:var(--text-sm); color:var(--text-muted); font-weight:500; }
    .sidebar-control-row input[type="checkbox"] { accent-color:var(--accent-blue); }
    .sidebar-settings-collapse { border:none; padding:12px 12px 4px; margin:0; }
    .sidebar-settings-collapse > summary::-webkit-details-marker { display:none; }
    .sidebar-settings-collapse > summary { list-style:none; }
    .sidebar-settings-arrow { font-size:var(--text-sm); transition:transform 0.15s ease; display:inline-block; }
    .sidebar-settings-collapse:not([open]) .sidebar-settings-arrow { transform:rotate(-90deg); }
    .sidebar-advanced { padding:0 8px; margin-top:4px; }
    .sidebar-advanced summary { cursor:pointer; font-size:var(--text-sm); color:var(--text-muted); font-weight:500; padding:4px 0; }
    .sidebar-refresh { margin:12px 16px; background:var(--accent-blue); border:none; color:#0d1117; padding:8px 16px; border-radius:var(--radius-sm); cursor:pointer; font-size:var(--text-base); font-weight:600; text-transform:uppercase; letter-spacing:0.04em; transition:opacity var(--transition-normal); }
    .sidebar-refresh:hover { opacity:0.9; }
    .sidebar-footer { margin-top:auto; padding:0 16px 24px; display:flex; gap:8px; }
    .sidebar-footer a { font-size:var(--text-sm); color:#fff; text-decoration:none; font-weight:600; text-transform:uppercase; letter-spacing:0.04em; padding:6px 10px; border:none; border-radius:var(--radius-sm); background:var(--accent-blue); cursor:pointer; transition:opacity var(--transition-normal); flex:1; text-align:center; }
    .sidebar-footer a:hover { opacity:0.9; color:#fff; }
    .main-content { padding:20px 24px; min-width:0; width:100%; box-sizing:border-box; display:flex; flex-direction:column; height:calc(100vh - 56px); overflow:hidden; }
    /* Mobile (<640px): subtract bottom-nav height + safe-area-inset from main content */
    @media (max-width: 639px) {
      .main-content { height:calc(100vh - 56px - 64px - env(safe-area-inset-bottom)); }
    }
    .main-header { margin-bottom:20px; display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-shrink:0; }
    .main-header h1 { margin:0 0 8px; font-size:1.1rem; font-weight:700; color:var(--text-primary); letter-spacing:-0.02em; }
    .how-pill { display:inline-flex; align-items:center; gap:5px; padding:10px 16px; border-radius:999px; border:1px solid var(--border-default); background:var(--bg-surface); color:var(--text-primary); font-size:var(--text-base); font-weight:600; cursor:pointer; white-space:nowrap; transition:all 0.15s; letter-spacing:0.02em; min-height:44px; }
    .how-pill:hover { border-color:var(--accent); color:var(--accent); background:var(--accent-muted); }
    .status-line { font-size:var(--text-base); color:var(--text-muted); margin-bottom:12px; padding:8px 14px; background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-sm); display:flex; align-items:center; gap:8px; min-height:20px; }
    .status-line::before { content:''; display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--accent-green); flex-shrink:0; }
    .status-line:empty { display:none; }
    .status-line.loading::before { background:var(--accent-amber); animation:statusPulse 1.2s ease-in-out infinite; }
    @keyframes statusPulse { 0%,100%{opacity:1} 50%{opacity:0.3} }

    /* FIX 2026-08-07: the mobile header measured 228px and pushed Best Bets off
       the fold. Most of that was a SQUEEZE, not content. `.main-header` is a
       nowrap flex row; `.how-pill` is white-space:nowrap and so claims 220px of
       a 327px screen and refuses to shrink, leaving 117px for the whole text
       block. The one-sentence status line then wrapped to ~7 lines: measured
       181px at 117px wide vs 65px given full width.

       Stacking gives the status line the full width. Do NOT "fix" this by
       hiding or truncating the status text — it is unsqueezed, not removed.

       640px, not this file's usual 639px, deliberately: this trim exists to
       give the proof hero its fold, and must engage at exactly the same width
       as the hero reorder in slate.css. */
    @media (max-width: 640px) {
      .main-header { flex-direction: column; align-items: flex-start; }

      /* Bill 2026-08-07, with the consequence stated: this is the ONLY
         reachable openGlossary() trigger on a phone — the sidebar's "Reference"
         item has a display:none parent at this width and #mobile-menu is empty.
         Hiding it makes the glossary unreachable on mobile.

         Scoped to .main-header on purpose: a bare `.how-pill` rule would also
         kill the props view's separate "How Prop Predictions Work" pill. */
      .main-header .how-pill { display: none; }
    }
    /* Each view tab fills remaining height and scrolls internally */
    #view-premium, #view-pmdebug, #view-analytics { flex:1 1 0; min-height:0; overflow-y:auto; width:100%; box-sizing:border-box; }
    /* view-props uses an inner scroll container so the header row stays pinned */
    #view-props.view-props-flex { flex:1 1 0; min-height:0; overflow:hidden; width:100%; box-sizing:border-box; display:flex; }
    #view-analytics { padding:16px; }
    .game-cards-container { display:flex; flex-direction:column; gap:5px; max-width:none; }
    /* FIX 2026-08-06: the rule above outranks the UA `[hidden]{display:none}`,
       so Slate._toggleVisibility setting `.hidden = true` for the drilldown
       takeover changed the ATTRIBUTE and nothing else — measured live: hidden
       was true, computed display stayed `flex`, and all 15 cards were still
       4,625px tall on top of the takeover. A class selector beats a bare
       attribute selector; this one is 0-2-0 and wins without !important.
       Only mattered once the board moved ABOVE the slate. */
    .game-cards-container[hidden] { display:none; }
    /* 2026-08-05: the board is visible again. `#game-cards-container { display:
       none }` (2026-07-18) hid the legacy Game Board because it re-rendered the
       full slate a 2nd time (~35,500px) below Today's Slate. That loop is gone;
       renderGameCards() now emits the per-market odds box (.ob-card, styled at
       the foot of this file) for the visible sport only. */
    .date-header { display:block; font-size:var(--text-base); font-weight:700; color:var(--text-secondary); padding:16px 0 6px; border-bottom:1px solid var(--border-subtle); margin-bottom:4px; text-transform:uppercase; letter-spacing:0.06em; }
    .date-header:first-child { padding-top:0; }
    .game-card { background:var(--bg-card); border:1px solid var(--border-default); border-top:2px solid var(--accent-muted); border-radius:var(--radius-lg); box-shadow:var(--shadow-card); transition:box-shadow var(--transition-normal),border-color var(--transition-normal); overflow:hidden; }
    .game-card:hover { box-shadow:var(--shadow-hover); border-color:var(--border-strong); border-top-color:var(--accent); }
    .game-card-summary { cursor:pointer; user-select:none; }
    .game-header-bar { display:flex; align-items:center; justify-content:space-between; padding:6px 12px 1px; }
    .game-header-left { display:flex; align-items:center; gap:8px; font-size:var(--text-base); }
    .game-header-right { display:flex; align-items:center; gap:8px; }
    .game-time-label { color:var(--text-muted); font-weight:500; }
    .fallback-badge { display:inline-block; font-size:var(--text-base); padding:1px 5px; background:var(--accent-amber-bg); color:var(--accent-amber); border-radius:4px; font-weight:600; }
    .game-status-live { display:inline-flex; align-items:center; gap:5px; color:var(--ev-neg); font-weight:700; font-size:var(--text-base); text-transform:uppercase; letter-spacing:0.04em; }
    .game-status-live::before { content:''; display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--ev-neg); box-shadow:0 0 0 0 rgba(248,113,113,0.6); animation:livePulse 1.5s ease-in-out infinite; flex-shrink:0; }
    @keyframes livePulse { 0%{box-shadow:0 0 0 0 rgba(248,113,113,0.6)} 50%{box-shadow:0 0 0 6px rgba(248,113,113,0)} 100%{box-shadow:0 0 0 0 rgba(248,113,113,0)} }
    .game-status-final { display:inline-block; font-size:var(--text-base); font-weight:700; color:var(--text-faint); text-transform:uppercase; letter-spacing:0.04em; }
    .game-card-live { border-right:3px solid var(--ev-neg); }
    .game-card-final { opacity:0.7; }
    .game-card-bet { border-left:3px solid var(--accent-green); }
    .game-card-lock { border-left:3px solid #3b82f6; }
    .game-card-lean { border-left:3px solid var(--accent-amber); }
    .game-card.drawer-active { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent),var(--shadow-hover); }
    .game-rows { padding:0 12px 4px; }
    .game-row { display:grid; grid-template-columns:1fr repeat(3, 80px); column-gap:4px; align-items:center; }
    .team-cell { display:flex; align-items:center; gap:6px; padding:4px 4px; font-size:var(--text-base); color:var(--text-primary); }
    .odds-group { display:contents; }
    .team-cell .team-name { font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    .team-cell .team-score { font-weight:700; font-family:var(--font-mono); font-size:var(--text-lg); margin-left:8px; flex-shrink:0; }
    .game-card-live .team-score { color:var(--ev-neg); }
    .game-card-final .team-score { color:var(--text-faint); }
    .team-cell .team-at { font-size:var(--text-sm); color:var(--text-faint); margin:0 2px; }
    .odds-cell { display:flex; flex-direction:column; align-items:center; justify-content:center; padding:3px 4px; border:1px solid var(--border-default); border-radius:var(--radius-sm); min-height:28px; transition:background var(--transition-fast),border-color var(--transition-fast); }
    .odds-cell:hover { background:var(--bg-surface); border-color:var(--accent-blue-light); }
    .odds-cell.cell-bet { background:var(--accent-green-bg); border-color:var(--ev-pos); }
    .odds-cell.cell-lean { background:var(--accent-amber-bg); border-color:var(--accent-amber); }
    .odds-cell.cell-empty { border-color:transparent; min-height:0; }
    .odds-cell.cell-empty:hover { background:transparent; border-color:transparent; }
    .odds-val { font-size:var(--text-base); font-weight:600; color:var(--text-primary); line-height:1.3; font-family:var(--font-mono); }
    .odds-juice { font-size:var(--text-sm); font-weight:700; color:var(--text-muted); line-height:1.3; font-family:var(--font-mono); }
    .sizing-badge { display:inline-flex; align-items:center; gap:3px; padding:2px 8px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:700; text-transform:uppercase; letter-spacing:0.04em; }
    .sizing-badge-bet { background:var(--accent-green-bg); color:var(--accent-green); }
    .sizing-badge-lock { background:rgba(59,130,246,0.12); color:#3b82f6; }
    .sizing-badge-lean { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .sizing-badge-pass { background:var(--bg-surface); color:var(--text-faint); }
    .analysis-btn { font-size:var(--text-sm); color:var(--accent-blue); font-weight:600; display:inline-flex; align-items:center; gap:4px; padding:2px 10px; border:1px solid var(--accent-blue-light); border-radius:var(--radius-pill); transition:all 0.2s; cursor:pointer; }
    .analysis-btn:hover { background:var(--accent-muted); border-color:var(--accent-blue); }
    .card-col-headers { display:grid; grid-template-columns:1fr repeat(3, 80px); column-gap:4px; padding:0 0 2px; }
    .card-col-headers span { font-size:var(--text-sm); font-weight:700; color:var(--text-secondary); text-align:center; text-transform:uppercase; letter-spacing:0.06em; }
    .game-card-detail { display:none; padding:0 16px 16px; background:var(--bg-detail); border-top:1px solid var(--border-subtle); }
    .game-card.expanded .game-card-detail { display:block; animation:detailSlide 0.2s ease; }
    @keyframes detailSlide { from{opacity:0} to{opacity:1} }
    /* Game Board Row styles (new row-based board) */
    .gb-header { display:grid; grid-template-columns:70px 1fr repeat(3,90px) 110px; padding:var(--space-xs) var(--space-md); gap:var(--space-sm); border-bottom:1px solid var(--border-default); }
    .gb-header span { font-size:var(--text-xs); color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.08em; font-weight:700; text-align:center; }
    .gb-header span:first-child { text-align:left; }
    .gb-header span:last-child { text-align:right; }
    .gb-row { display:grid; grid-template-columns:70px 1fr repeat(3,90px) 110px; align-items:center; padding:var(--space-sm) var(--space-md); border-bottom:1px solid var(--border-subtle); cursor:pointer; transition:background var(--transition-fast); gap:var(--space-sm); }
    .gb-row:hover { background:var(--bg-hover); }
    .gb-row.pass-row { opacity:0.55; }
    .gb-row.active { background:var(--bg-elevated); border-left:2px solid var(--accent); }
    .gb-time { font-size:var(--text-sm); color:var(--text-muted); white-space:nowrap; }
    .gb-time .live-dot { display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--accent-red); margin-right:4px; animation:livePulse 1.5s ease-in-out infinite; }
    .gb-teams { font-size:var(--text-base); font-weight:600; color:var(--text-primary); line-height:1.4; }
    .gb-teams .away-line { color:var(--text-secondary); }
    .gb-teams .gb-score { color:var(--text-muted); font-family:var(--font-mono); margin-left:var(--space-xs); font-weight:700; }
    .gb-odds { text-align:center; padding:var(--space-xs) 2px; border-radius:var(--radius-sm); font-family:var(--font-mono); font-size:var(--text-base); font-weight:600; color:var(--text-secondary); background:var(--bg-elevated); cursor:pointer; transition:all var(--transition-fast); line-height:1.3; }
    .gb-odds:hover { background:var(--bg-hover); box-shadow:0 0 0 1px var(--accent); }
    .gb-odds.recommended { background:var(--accent-muted); color:var(--accent); }
    .gb-odds .odds-sub { font-size:var(--text-xs); color:var(--text-faint); font-weight:400; display:block; }
    .gb-sizing { display:flex; align-items:center; gap:var(--space-xs); justify-content:flex-end; flex-wrap:wrap; }
    .gb-sizing .sizing-pill { font-size:var(--text-xs); font-weight:700; padding:2px var(--space-sm); border-radius:var(--radius-sm); text-transform:uppercase; letter-spacing:0.04em; }
    .sizing-pill.bet { color:var(--ev-pos); background:var(--accent-green-bg); }
    .sizing-pill.lean { color:var(--accent-amber); background:var(--accent-amber-bg); }
    .sizing-pill.pass-pill { color:var(--text-faint); }
    .gb-ev { font-size:var(--text-sm); font-family:var(--font-mono); font-weight:600; }
    .detail-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:12px; }
    .detail-section { background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-md); padding:14px 16px; }
    .detail-section-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; padding-bottom:8px; border-bottom:1px solid var(--border-subtle); }
    .detail-section-title { font-size:var(--text-sm); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; }
    .original-pick-row { display:flex; align-items:center; gap:8px; padding:4px 0; font-size:var(--text-base); }
    .original-pick-row .op-label { color:var(--text-faint); font-weight:600; min-width:28px; text-transform:uppercase; font-size:var(--text-sm); }
    .original-pick-row .op-side { color:var(--text-primary); font-weight:600; flex:1; }
    .original-pick-row .op-prob { color:var(--text-secondary); font-family:var(--font-mono); font-size:var(--text-sm); }
    .original-pick-row .op-badge { display:inline-block; padding:1px 7px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:700; text-transform:uppercase; letter-spacing:0.04em; }
    .original-pick-row .op-badge-bet { background:var(--accent-green-bg); color:var(--accent-green); }
    .original-pick-row .op-badge-lock { background:rgba(59,130,246,0.12); color:#3b82f6; }
    .original-pick-row .op-badge-lean { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .original-pick-row .op-badge-pass { background:var(--bg-surface); color:var(--text-faint); }
    .detail-row { display:flex; justify-content:space-between; align-items:baseline; padding:3px 0; font-size:var(--text-base); }
    .detail-row .label { color:var(--text-muted); font-weight:500; }
    .detail-row .value { color:var(--text-primary); font-weight:600; font-family:var(--font-mono); }
    .source-row { display:flex; justify-content:space-between; align-items:baseline; padding:2px 0; font-size:var(--text-sm); }
    .source-row .label { color:var(--text-muted); }
    .source-row .value { color:var(--text-secondary); font-family:var(--font-mono); }
    .gauge-row { display:flex; align-items:center; gap:8px; margin-bottom:8px; }
    .gauge-label { font-size:var(--text-base); color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; min-width:80px; font-weight:500; }
    .gauge-track { flex:1; height:8px; background:var(--accent-muted); border-radius:4px; overflow:hidden; }
    .gauge-fill { height:100%; border-radius:4px; transition:width 0.3s ease; }
    .gauge-score { font-size:var(--text-base); font-weight:700; min-width:40px; text-align:right; font-family:var(--font-mono); }
    .gauge-grade { font-size:var(--text-sm); font-weight:600; min-width:70px; }
    .modal-backdrop { position:fixed; inset:0; background:rgba(0,0,0,0.4); z-index:9999; display:flex; align-items:center; justify-content:center; }
    .modal-backdrop.hidden { display:none; }
    .modal { background:var(--bg-card); color:var(--text-secondary); width:min(900px,92vw); max-height:85vh; overflow-y:auto; border-radius:var(--radius-lg); border:1px solid var(--border-default); border-top:3px solid var(--accent-blue); padding:14px 16px; box-shadow:0 20px 60px rgba(0,0,0,0.15); animation:modalFadeIn 0.25s ease; }
    @keyframes modalFadeIn { from{opacity:0;transform:translateY(12px) scale(0.98)} to{opacity:1;transform:translateY(0) scale(1)} }
    .modal h2 { margin:4px 0 10px; font-size:1.1rem; color:var(--text-primary); }
    .modal .row { display:grid; grid-template-columns:140px 1fr; gap:10px; padding:8px 0; border-bottom:1px solid var(--border-subtle); }
    .modal .k { color:var(--accent-blue); font-weight:600; font-size:var(--text-base); }
    .modal .v { color:var(--text-secondary); font-size:var(--text-base); }
    .modal-actions { display:flex; justify-content:flex-end; gap:10px; margin-top:10px; }
    .modal-header { display:flex; align-items:center; justify-content:space-between; padding:12px 16px; border-bottom:1px solid var(--border-strong); }
    .modal-header h2 { margin:0; font-size:var(--text-lg); }
    .close-btn { background:none; border:1px solid transparent; color:var(--text-faint); font-size:22px; font-weight:bold; cursor:pointer; line-height:1; padding:4px 8px; border-radius:var(--radius-sm); transition:background var(--transition-normal); }
    .close-btn:hover { color:var(--text-primary); background:var(--bg-hover); border-color:var(--border-default); }
    .modal-body { padding:16px 18px; }
    .modal-body h4 { margin-top:14px; margin-bottom:4px; font-size:var(--text-base); }
    .modal-body p { font-size:var(--text-base); line-height:1.45; margin:0 0 6px; }
    /* Reference Center */
    .ref-modal { background:var(--bg-card); color:var(--text-secondary); width:min(720px,94vw); max-height:88vh; display:flex; flex-direction:column; border-radius:var(--radius-lg); border:1px solid var(--border-default); border-top:3px solid var(--accent-blue); box-shadow:0 20px 60px rgba(0,0,0,0.15); animation:modalFadeIn 0.25s ease; overflow:hidden; }
    .ref-header { display:flex; align-items:center; justify-content:space-between; padding:14px 18px 10px; flex-shrink:0; }
    .ref-header h2 { margin:0; font-size:1rem; color:var(--text-primary); font-weight:700; }
    .ref-search-wrap { padding:0 18px 10px; flex-shrink:0; position:relative; }
    .ref-search-input { width:100%; padding:9px 14px 9px 36px; border:1px solid var(--border-default); border-radius:var(--radius-md); font-size:var(--text-base); background:var(--bg-page); color:var(--text-primary); outline:none; transition:border-color 0.2s; box-sizing:border-box; }
    .ref-search-input:focus { border-color:var(--accent-blue); box-shadow:0 0 0 3px var(--accent-muted); }
    .ref-search-icon { position:absolute; left:30px; top:50%; transform:translateY(-50%); color:var(--text-faint); font-size:var(--text-base); pointer-events:none; }
    .ref-search-count { position:absolute; right:30px; top:50%; transform:translateY(-50%); font-size:var(--text-xs); color:var(--text-faint); }
    .ref-pills { display:flex; gap:6px; padding:0 18px 12px; flex-shrink:0; flex-wrap:wrap; }
    .ref-pill { padding:4px 12px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:600; border:1px solid var(--border-default); background:var(--bg-surface); color:var(--text-muted); cursor:pointer; transition:all 0.15s; white-space:nowrap; }
    .ref-pill:hover { border-color:var(--accent-blue); color:var(--accent-blue); }
    .ref-pill.active { background:var(--accent-blue); color:#0d1117; border-color:var(--accent-blue); }
    .ref-body { flex:1; overflow-y:auto; padding:0 18px 14px; }
    .ref-cat-header { font-size:var(--text-sm); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; margin:16px 0 8px; padding-bottom:4px; border-bottom:1px solid var(--border-subtle); }
    .ref-cat-header:first-child { margin-top:4px; }
    .ref-term { padding:8px 12px; margin-bottom:6px; border-radius:var(--radius-sm); border:1px solid var(--border-subtle); background:var(--bg-page); transition:border-color 0.15s; }
    .ref-term:hover { border-color:var(--border-default); }
    .ref-term-name { font-weight:700; font-size:var(--text-base); color:var(--text-primary); }
    .ref-term-aka { font-size:var(--text-sm); color:var(--text-faint); margin-left:6px; font-weight:500; }
    .ref-term-def { font-size:var(--text-sm); color:var(--text-secondary); line-height:1.55; margin-top:3px; }
    .ref-term-sport { display:inline-block; font-size:var(--text-xs); padding:1px 6px; border-radius:var(--radius-pill); background:var(--accent-muted); color:var(--accent-blue); font-weight:600; margin-left:6px; }
    .ref-highlight { background:var(--accent-amber-bg); color:var(--accent-amber); border-radius:2px; padding:0 1px; }
    .ref-empty { text-align:center; padding:40px 20px; color:var(--text-faint); font-size:var(--text-base); }
    .ref-empty span { display:block; font-size:1.5rem; margin-bottom:8px; }
    .pill { border-radius:var(--radius-pill); padding:2px 8px; font-size:var(--text-base); font-weight:600; }
    .pill-gold { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .pill-silver { background:var(--bg-hover); color:var(--text-secondary); }
    .pill-bronze { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .pill-none { background:var(--bg-surface); color:var(--text-muted); }
    .badge { display:inline-block; font-size:var(--text-base); padding:2px 5px; border-radius:var(--radius-pill); border:1px solid var(--border-default); margin-left:4px; color:var(--text-muted); white-space:nowrap; }
    .badge-ok { border-color:var(--accent-green); color:var(--accent-green); }
    .badge-warn { border-color:var(--accent-amber); color:var(--accent-amber); }
    .badge-bad { border-color:var(--accent-red); color:var(--accent-red); }
    .badges { display:inline-flex; gap:6px; flex-wrap:wrap; align-items:center; }
    .margin-badge { display:inline-block; padding:2px 8px; border-radius:4px; font-size:var(--text-base); font-weight:700; }
    .margin-badge.positive { background:var(--accent-green-bg); color:var(--accent-green); }
    .margin-badge.negative { background:var(--accent-red-bg); color:var(--accent-red); }
    .margin-badge.neutral { background:var(--accent-amber-bg); color:var(--accent-amber); }
    table { width:100%; border-collapse:collapse; font-size:var(--text-base); table-layout:auto; }
    th,td { padding:8px 10px; border-bottom:1px solid var(--border-subtle); vertical-align:top; }
    th { text-align:left; background:var(--bg-surface); font-size:var(--text-base); font-weight:600; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; white-space:nowrap; }
    td { color:var(--text-secondary); }
    tbody tr:hover { background:var(--bg-hover); }
    .sub { font-size:var(--text-base); color:var(--text-muted); }
    .book-best { font-size:var(--text-base); color:var(--text-primary); font-weight:600; }
    .book-best-odds { color:var(--accent-blue); font-weight:700; }
    .book-others { font-size:var(--text-sm); color:var(--text-muted); margin-top:2px; line-height:1.4; }
    .book-others-odds { color:var(--text-muted); }
    .ev-pos { color:var(--accent-green); font-weight:600; }
    .ev-neg { color:var(--accent-amber); font-weight:500; }
    details { margin-top:4px; }
    details summary { cursor:pointer; font-size:var(--text-base); color:var(--accent-blue); }
    pre { font-size:var(--text-sm); background:var(--bg-page); border-radius:var(--radius-sm); padding:6px; border:1px solid var(--border-default); overflow-x:auto; white-space:pre-wrap; word-break:break-word; }
    .context-block { margin-top:8px; padding:8px 10px; border-radius:var(--radius-sm); background:var(--bg-page); border:1px solid var(--border-subtle); }
    .context-toggle { color:var(--text-muted); display:flex; align-items:center; gap:6px; padding:2px 0; }
    .context-toggle:hover { color:var(--text-primary); }
    .context-label { color:var(--text-secondary); font-weight:500; }
    .context-headline { font-weight:600; }
    .context-chevron { display:inline-block; transition:transform 0.25s ease; font-size:0.8em; color:var(--text-faint); }
    .context-toggle[data-open="true"] .context-chevron { transform:rotate(90deg); }
    .context-drawer { margin-top:6px; padding:6px 0 6px 10px; border-left:2px solid var(--border-default); animation:drawerSlide 0.2s ease; }
    @keyframes drawerSlide { from{opacity:0;transform:translateY(-4px)} to{opacity:1;transform:translateY(0)} }
    .q { display:inline-flex; align-items:center; justify-content:center; width:16px; height:16px; border-radius:var(--radius-pill); border:1px solid var(--border-default); color:var(--text-muted); font-size:12px; margin-left:6px; cursor:help; }
    .help-link { display:inline-block; margin-left:8px; color:var(--accent-blue); font-size:13px; cursor:help; text-decoration:underline; text-underline-offset:2px; }
    .tip { position:relative; display:inline-block; vertical-align:middle; }
    .tip:hover::after { content:attr(data-tip); position:absolute; left:0; top:22px; min-width:220px; max-width:360px; background:var(--bg-surface); border:1px solid var(--border-default); padding:10px; border-radius:var(--radius-md); color:var(--text-secondary); font-size:var(--text-base); line-height:1.25; z-index:50; box-shadow:0 10px 30px rgba(0,0,0,0.12); white-space:normal; }
    .pm-stack { margin-top:6px; }
    .pm-stack .row { display:grid; grid-template-columns:62px 1fr; gap:8px; margin:2px 0; align-items:baseline; }
    .pm-stack .k { color:var(--text-muted); font-size:var(--text-base); }
    .pm-stack .v { color:var(--text-secondary); font-size:var(--text-base); }
    .pm-vol-liq { font-size:var(--text-base); color:var(--text-secondary); margin-top:4px; }
    .muted { color:var(--text-muted); }
    .card { border-radius:var(--radius-lg); border:1px solid var(--border-default); padding:12px 14px; background:var(--bg-card); margin-bottom:12px; }
    .card h3 { margin:0 0 4px; font-size:var(--text-lg); color:var(--text-primary); }
    .card p { margin:6px 0; font-size:var(--text-base); color:var(--text-muted); line-height:1.35; }
    .tab-btn { background:var(--bg-page); border:1px solid var(--border-default); color:var(--text-secondary); padding:6px 16px; border-radius:var(--radius-sm); cursor:pointer; font-size:var(--text-base); font-weight:600; }
    .tab-btn:hover { background:var(--bg-hover); color:var(--text-primary); }
    .pill-btn { background:var(--bg-page); border:1px solid var(--border-default); color:var(--text-secondary); padding:4px 12px; border-radius:var(--radius-sm); cursor:pointer; font-size:var(--text-sm); font-weight:600; transition:background 0.15s,color 0.15s; }
    .pill-btn:hover { background:var(--bg-hover); color:var(--text-primary); }
    .pill-btn.active { background:var(--accent-muted); color:var(--accent); border-color:var(--accent); }
    .props-sport-pill { background:none; border:none; border-bottom:2px solid transparent; color:var(--text-muted); padding:var(--space-xs) var(--space-md); cursor:pointer; font-size:var(--text-base); font-weight:600; transition:color var(--transition-fast),border-color var(--transition-fast); }
    .props-sport-pill:hover { color:var(--text-secondary); }
    .props-sport-pill.active { color:var(--accent); border-bottom-color:var(--accent); }
    /* .hidden keeps !important deliberately: it is the global hide utility
       toggled by 15+ JS sites (modals, backdrops, overlays, view switching)
       and must beat any later display rule. Competing view containers use
       :not(.hidden) on their display rule instead of counter-!importants
       (FIX 2026-07-12, Batch 2 — ended the cc-view-container arms race). */
    .hidden { display:none !important; }
    /* FIX 2026-04-06: scoped flex layout for #view-props that only applies
       when the element is visible (2026-07-12: now via :not(.hidden);
       flex-direction moved here from an inline style on the element). */
    .view-props-flex:not(.hidden) { display:flex; flex-direction:column; }

    /* Inline Line Shopping */
    .game-card-row { display:flex; gap:12px; align-items:flex-start; }
    .game-card-row .game-card { flex:0 0 500px; }
    .ls-box { display:grid; grid-template-columns:1fr 1fr; gap:10px; flex:1; min-width:0; }
    .ls-expand-toggle {
      padding:8px 16px; font-size:var(--text-sm); font-weight:600;
      color:var(--accent-blue); cursor:pointer; user-select:none;
      border-top:1px solid var(--border-subtle);
    }
    .ls-expand-toggle:hover { background:var(--bg-hover); }
    .ls-card {
      background:var(--bg-surface); border:1px solid var(--border-default);
      border-radius:var(--radius-lg); box-shadow:var(--shadow-card); overflow:hidden;
    }
    .ls-header {
      padding:12px 16px; border-bottom:1px solid var(--border-subtle);
      font-size:var(--text-lg); font-weight:700; color:var(--text-primary);
      display:flex; align-items:center; justify-content:space-between;
      cursor:pointer; user-select:none;
    }
    .ls-header:hover { background:var(--bg-hover); }
    .ls-header .ls-chevron { transition:transform 0.2s; font-size:var(--text-sm); color:var(--text-faint); margin-right:6px; }
    .ls-card.ls-collapsed .ls-header { border-bottom:none; }
    .ls-card.ls-collapsed .ls-body { display:none; }
    .ls-best-badge {
      display:inline-flex; align-items:center; gap:5px;
      background:var(--accent-green-bg); border:1px solid var(--ev-pos); border-radius:6px;
      padding:4px 10px; font-size:var(--text-sm); font-weight:700; color:var(--ev-pos);
    }
    .ls-best-badge svg { flex-shrink:0; }
    .ls-best-grid {
      display:grid; grid-template-columns:repeat(3, 1fr); gap:1px;
      background:var(--border-subtle); border-bottom:1px solid var(--border-subtle);
    }
    /* 2026-05-17 audit S3 mobile: 3-column ML/SPREAD/O/U grid clipped at
       <640px. Stack vertically on phones — each cell takes full width. */
    @media (max-width: 640px) {
      .ls-best-grid { grid-template-columns: 1fr; }
      .ls-table-wrap { scrollbar-width: thin; }
      .ls-table th, .ls-table td { padding: 6px 4px; font-size: var(--text-sm); }
      .ls-table th:first-child, .ls-table td:first-child { padding-left: 6px; }
    }
    .ls-best-cell {
      background:var(--accent-green-bg); padding:10px 12px; text-align:center;
    }
    .ls-best-cell-label {
      font-size:var(--text-sm); font-weight:700; color:var(--text-muted);
      text-transform:uppercase; letter-spacing:0.06em; margin-bottom:4px;
    }
    .ls-best-cell-book {
      font-size:var(--text-base); font-weight:700; color:var(--accent-green);
    }
    .ls-best-cell-odds {
      font-size:var(--text-base); font-weight:800; color:var(--accent-green);
      font-family:var(--font-mono);
    }
    .ls-table-wrap { padding:0; overflow-x:auto; }
    .ls-table {
      width:100%; border-collapse:collapse;
      font-size:var(--text-base);
    }
    .ls-table th {
      padding:8px 6px; text-align:center; font-size:var(--text-sm); font-weight:700;
      color:var(--text-muted); text-transform:uppercase; letter-spacing:0.06em;
      background:var(--bg-surface); border-bottom:1px solid var(--border-subtle);
      white-space:nowrap;
    }
    .ls-table th:first-child { text-align:left; padding-left:12px; }
    .ls-table td {
      padding:6px 6px; text-align:center; font-family:var(--font-mono);
      font-weight:500; color:var(--text-secondary);
      border-bottom:1px solid var(--border-subtle);
    }
    .ls-table td:first-child {
      text-align:left; padding-left:12px;
      font-family:system-ui,sans-serif; font-weight:600; color:var(--text-primary);
      font-size:var(--text-sm); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
    }
    .ls-table tbody tr:hover { background:var(--bg-hover); }
    .ls-cell-best { background:var(--accent-green-bg); color:var(--ev-pos); font-weight:700; }
    .ls-cell-worst { color:var(--text-faint); opacity:0.6; }
    .ls-cell-missing { font-style:italic; color:var(--text-faint); opacity:0.5; }
    .ls-vig-low { color:var(--ev-pos); font-weight:600; }
    .ls-vig-high { color:var(--ev-neg); font-weight:600; }
    .ls-fair-prob { font-weight:700; color:var(--text-primary); }
    .ls-no-data {
      padding:32px 24px; text-align:center;
      color:var(--text-faint); font-size:var(--text-base);
    }
    .ls-legend {
      padding:8px 16px; border-top:1px solid var(--border-subtle);
      display:flex; flex-direction:column; gap:2px;
      font-size:var(--text-sm); color:var(--text-faint); line-height:1.4;
    }
    /* ============================================================
       GAME DASHBOARD — full-screen game view layout
       ============================================================ */
    .app-layout-gameview { display:grid; grid-template-columns:220px 280px 1fr; min-height:100vh; }
    .app-layout-gameview .main-content { display:none; }

    /* Game Strip — compact scrollable game list */
    .game-strip { background:var(--bg-base); border-right:1px solid var(--border-default); display:flex; flex-direction:column; height:100vh; position:sticky; top:0; overflow:hidden; }
    .game-strip-header { padding:2px 4px; border-bottom:1px solid var(--border-subtle); display:flex; align-items:center; justify-content:space-between; }
    .game-strip-header h2 { margin:0; font-size:1.1rem; font-weight:700; color:var(--text-primary); }
    .game-strip-header .strip-count { font-size:1.0rem; color:var(--text-muted); font-weight:600; }
    .league-logo { height:28px; }
    .game-strip-header .strip-league-logo .league-logo { height:80px; }
    .game-strip-list { flex:1; overflow-y:auto; padding:4px 0; }
    .game-strip-date { font-size:var(--text-sm); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.06em; padding:12px 14px 4px; }
    .game-strip-date:first-child { padding-top:8px; }
    .game-strip-item { padding:8px 14px; cursor:pointer; border-left:3px solid transparent; transition:background var(--transition-fast),border-color var(--transition-fast); border-bottom:1px solid var(--border-subtle); background:var(--bg-card); margin:0 6px 4px; border-radius:var(--radius-sm); border-bottom:none; }
    .game-strip-item:hover { background:var(--bg-hover); }
    .game-strip-item.active { background:var(--bg-raised); border-left-color:var(--accent-blue); box-shadow:inset 3px 0 8px var(--accent-muted); }
    .game-strip-item.strip-live { border-right:2px solid var(--ev-neg); }
    .game-strip-item.strip-final { opacity:0.55; }
    .strip-score-inline { font-weight:700; font-family:var(--font-mono); font-size:var(--text-base); margin-left:auto; padding-left:4px; min-width:16px; text-align:right; }
    .strip-live .strip-score-inline { color:var(--ev-neg); }
    .strip-final .strip-score-inline { color:var(--text-faint); }
    .strip-odds-abbr-scored { display:flex; align-items:center; }
    .strip-top-row { display:flex; align-items:center; justify-content:space-between; margin-bottom:2px; }
    .strip-top-time { font-size:var(--text-sm); font-weight:600; color:var(--text-secondary); }
    .strip-live .strip-top-time { color:var(--ev-neg); font-weight:700; display:inline-flex; align-items:center; gap:4px; }
    .strip-live .strip-top-time::before { content:''; display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--ev-neg); animation:livePulse 1.5s ease-in-out infinite; flex-shrink:0; }
    .strip-final .strip-top-time { color:var(--text-faint); }
    .game-strip-live { font-size:var(--text-sm); font-weight:700; color:var(--ev-neg); text-transform:uppercase; }
    .game-strip-badge { display:inline-flex; padding:1px 6px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:700; text-transform:uppercase; letter-spacing:0.03em; }
    .game-strip-badge-bet { background:var(--accent-green-bg); color:var(--accent-green); }
    .game-strip-badge-lock { background:rgba(59,130,246,0.12); color:#3b82f6; }
    .game-strip-badge-lean { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .game-strip-badge-pass { background:var(--bg-surface); color:var(--text-faint); }

    /* Props game cards */
    .props-game-card { background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-lg); overflow:hidden; }
    .props-game-header { display:flex; align-items:center; justify-content:space-between; padding:10px 16px; background:var(--bg-surface); border-bottom:1px solid var(--border-subtle); cursor:pointer; user-select:none; }
    .props-game-header:hover { background:var(--bg-hover); }
    .props-game-matchup { font-size:var(--text-base); font-weight:700; color:var(--text-primary); }
    .props-game-count { font-size:var(--text-sm); color:var(--text-muted); }
    .props-game-body { padding:0; }
    /* min-height 2026-08-12: every row carries an odds cell, and the odds cell
       is a control (app.js attaches toggleParlayLeg to it on unlocked rows).
       Its 44px target needs a 44px row or it spills ~3px into the neighbour
       above and below and two adjacent prices overlap — the same arithmetic
       recorded for the SGP checkbox below. Rows were 40.9px. */
    .props-player-row { display:grid; grid-template-columns:1fr 78px 76px 62px 76px 56px; gap:0; align-items:center; padding:6px 16px; min-height:44px; font-size:var(--text-base); border-bottom:1px solid var(--border-subtle); transition:background 0.12s; }
    .props-player-row:last-child { border-bottom:none; }
    .props-player-row:hover { background:rgba(255,255,255,0.02); }
    .props-player-name { font-weight:700; font-size:var(--text-base); color:var(--text-primary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    .props-player-factors { font-size:var(--text-base); color:var(--text-muted); margin-left:8px; }
    .props-line { font-family:var(--font-mono); font-weight:600; font-size:var(--text-base); color:var(--text-primary); text-align:right; }
    .props-odds-cell { text-align:right; font-family:var(--font-mono); font-size:var(--text-lg); color:var(--text-primary); position:relative; }
    /* FIX 2026-08-12 — WCAG 2.5.5. The price is a CONTROL: app.js:8214 gives
       every unlocked row's odds cell `onclick=... toggleParlayLeg(...)`, so a
       tap here commits a leg. Measured 76 x 27.9 at 390px in both normal and
       SGP mode, with adjacent odds cells 13px apart — a mis-tap adds the wrong
       player's leg, and nothing tells the user.

       ::after rather than sizing the cell, for the same reason as
       .props-sgp-checkbox: `.props-player-row` is `align-items:center`, so the
       cell does not stretch to the row, and growing the cell to 44px would
       push every row 40.9 -> 56px on a board that shows dozens at a time.
       A click on a pseudo-element is attributed to its originating element,
       so the inline onclick needs no change.

       Full cell width (76px, already over the minimum) and 44px tall, which
       exactly fills the row's new 44px min-height — so vertically adjacent
       targets touch without overlapping. Locked rows are unaffected: they set
       pointer-events:none below.
       Guarded by tests/test_props_row_mobile_scroll.py. */
    .props-odds-cell::after {
      content:''; position:absolute; left:0; right:0; top:50%;
      height:44px; transform:translateY(-50%);
    }
    /* Phase 9 (C2) 2026-04-08: line shopping badge */
    .props-shop-badge { display:inline-block; margin-left:6px; padding:1px 5px; border-radius:6px; background:rgba(59,130,246,0.10); color:var(--accent-blue, #3b82f6); font-family:var(--font-sans); font-size:var(--text-xs); font-weight:600; vertical-align:middle; cursor:help; white-space:nowrap; }
    .props-shop-badge:hover { background:rgba(59,130,246,0.18); }
    /* Phase 9 (B2) 2026-04-08: injury status badge */
    .props-injury-badge { display:inline-block; margin-right:6px; padding:1px 5px; border-radius:5px; font-family:var(--font-sans); font-size:var(--text-xs); font-weight:700; vertical-align:middle; cursor:help; }
    .props-injury-badge-quest { background:rgba(245,158,11,0.15); color:#f59e0b; border:1px solid rgba(245,158,11,0.30); }
    .props-injury-badge-doubt { background:rgba(239,68,68,0.15); color:#f87171; border:1px solid rgba(239,68,68,0.30); }
    /* Phase 9 (C3) 2026-04-08: live-lock pill and row state */
    .props-row-locked { opacity:0.68; }
    .props-row-locked .props-odds-cell { pointer-events:none; }
    .props-row-locked .props-shop-badge { display:none; }
    .props-lock-badge { display:inline-block; margin-left:6px; padding:1px 6px; border-radius:5px; font-family:var(--font-sans); font-size:var(--text-xs); font-weight:700; letter-spacing:0.03em; vertical-align:middle; }
    .props-lock-live { background:rgba(239,68,68,0.20); color:#f87171; border:1px solid rgba(239,68,68,0.35); }
    .props-lock-final { background:rgba(107,114,128,0.25); color:var(--text-faint); border:1px solid rgba(107,114,128,0.40); }
    .props-proj { text-align:right; font-family:var(--font-mono); color:var(--text-primary); font-size:var(--text-lg); }
    .props-ev { text-align:right; font-family:var(--font-mono); font-weight:700; font-size:var(--text-lg); }
    .props-sizing-cell { text-align:center; }
    .props-col-header { display:grid; grid-template-columns:1fr 78px 76px 62px 76px 56px; gap:0; padding:5px 16px; font-size:var(--text-sm); font-weight:700; color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.04em; border-bottom:1px solid var(--border-default); }
    .props-col-header > span { text-align:right; }
    .props-col-header > span:first-child { text-align:left; }
    .props-type-accordion { border-bottom:1px solid var(--border-subtle); }
    .props-type-accordion:last-child { border-bottom:none; }
    .props-type-toggle { display:flex; align-items:center; justify-content:space-between; padding:10px 16px; cursor:pointer; user-select:none; background:var(--bg-surface); transition:background 0.15s; }
    .props-type-toggle:hover { background:var(--bg-hover); }
    .props-type-toggle-label { font-size:1rem; font-weight:700; color:var(--text-primary); letter-spacing:0.02em; }
    .props-type-toggle-chevron { font-size:var(--text-base); color:var(--text-muted); transition:transform 0.2s; }
    .props-type-toggle.open .props-type-toggle-chevron { transform:rotate(90deg); }
    .props-type-body { }
    .props-team-accordion { border-bottom:1px solid var(--border-subtle); }
    .props-team-accordion:last-child { border-bottom:none; }
    .props-team-toggle { display:flex; align-items:center; justify-content:space-between; padding:7px 16px 7px 28px; cursor:pointer; user-select:none; background:var(--bg-card); transition:background 0.15s; }
    .props-team-toggle:hover { background:var(--bg-hover); }
    .props-team-toggle-label { font-size:var(--text-base); font-weight:600; color:var(--text-secondary); }
    .props-team-toggle-chevron { font-size:var(--text-sm); color:var(--text-muted); transition:transform 0.2s; }
    .props-team-toggle.open .props-team-toggle-chevron { transform:rotate(90deg); }

    /* ============================================================
       Props category navigation — Phase 1 restructure 2026-04-07
       Left rail on desktop, horizontal pills on mobile, matches
       DraftKings / FanDuel props taxonomy (Scoring / Batter / etc).
       ============================================================ */
    .props-main-layout { display:flex; gap:var(--space-md); align-items:flex-start; }
    .props-content { flex:1; min-width:0; display:flex; flex-direction:column; gap:var(--space-sm); }

    /* Left rail (desktop) */
    .props-category-rail { flex:0 0 180px; position:sticky; top:var(--space-md); background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-lg); overflow:hidden; }
    .props-category-rail-header { padding:10px 14px; font-size:var(--text-sm); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.06em; border-bottom:1px solid var(--border-subtle); background:var(--bg-surface); }
    .props-category-rail-list { display:flex; flex-direction:column; padding:4px 0; }
    .props-category-item { display:flex; align-items:center; justify-content:space-between; padding:9px 14px; cursor:pointer; border-left:3px solid transparent; color:var(--text-secondary); font-size:var(--text-base); font-weight:600; transition:background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); user-select:none; }
    .props-category-item:hover { background:var(--bg-hover); color:var(--text-primary); }
    .props-category-item.active { background:var(--bg-raised); color:var(--accent); border-left-color:var(--accent); }
    .props-category-item.is-empty { opacity:0.45; cursor:default; }
    .props-category-item.is-empty:hover { background:transparent; color:var(--text-secondary); }
    .props-category-item-count { font-size:var(--text-sm); color:var(--text-muted); font-weight:500; font-family:var(--font-mono); }
    .props-category-item.active .props-category-item-count { color:var(--accent); }

    /* Horizontal pills (mobile) */
    .props-category-pills { display:none; gap:6px; overflow-x:auto; padding:6px 0 8px; scrollbar-width:none; -ms-overflow-style:none; }
    .props-category-pills::-webkit-scrollbar { display:none; }
    .props-category-pill { flex:0 0 auto; padding:6px 14px; border:1px solid var(--border-default); border-radius:var(--radius-pill); background:var(--bg-surface); color:var(--text-secondary); font-size:var(--text-sm); font-weight:600; cursor:pointer; white-space:nowrap; transition:background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast); }
    .props-category-pill:hover { background:var(--bg-hover); color:var(--text-primary); }
    .props-category-pill.active { background:var(--accent); color:var(--bg-base); border-color:var(--accent); }
    .props-category-pill.is-empty { opacity:0.45; cursor:default; }
    .props-category-pill.is-empty:hover { background:var(--bg-surface); color:var(--text-secondary); }
    .props-category-pill-count { font-size:var(--text-xs); opacity:0.8; margin-left:4px; font-family:var(--font-mono); }

    /* Responsive breakpoint — flip rail to pills */
    @media (max-width: 768px) {
      /* FIX 2026-07-25: align-items:flex-start (line ~643) SURVIVED this
         direction flip. In a column flex the cross axis is horizontal, so
         flex-start stopped .props-content stretching and sized it to
         MAX-CONTENT — the sum of every category pill. Measured on prod at
         390px: .props-main-layout 295px but .props-content 911px, giving
         576px of horizontal PAGE scroll, and .props-category-pills'
         overflow-x:auto (line ~659) was inert, because a scroll container
         cannot scroll while its parent is sized to its own max-content.
         With stretch: overflow 576 -> 0, content 911 -> 310, and the pill
         strip's scrollWidth > clientWidth flips to TRUE (it finally
         scrolls). Guarded by tests/test_props_mobile_layout.py. */
      .props-main-layout { flex-direction:column; align-items:stretch; }
      .props-category-rail { display:none; }
      .props-category-pills { display:flex; }
    }


    /* ============================================================
       Phase 9 (B1) 2026-04-08: Same-Game Parlay (SGP) builder
       ============================================================ */
    .props-sgp-toggle { margin-left:auto; display:inline-flex; align-items:center; padding:6px 14px; border:1px solid var(--accent); border-radius:var(--radius-pill); background:transparent; color:var(--accent); font-size:var(--text-sm); font-weight:600; cursor:pointer; transition:background var(--transition-fast), color var(--transition-fast); }
    .props-sgp-toggle:hover { background:var(--accent); color:var(--bg-base); }

    /* Selection mode: each prop row gets a checkbox in the leftmost cell */
    /* Header takes the same 7-track template as the rows in SGP mode — see the
       FIX note at the colHeader in app.js. */
    .props-player-row.props-sgp-mode,
    .props-col-header.props-sgp-mode { grid-template-columns:44px 1fr 78px 76px 62px 76px 56px; }
    .props-sgp-checkbox { display:inline-flex; align-items:center; justify-content:center; width:20px; height:20px; border:1.5px solid var(--border-default); border-radius:4px; cursor:pointer; transition:background var(--transition-fast), border-color var(--transition-fast); color:transparent; position:relative; }
    .props-sgp-checkbox:hover { border-color:var(--accent); }
    .props-sgp-checkbox.checked { background:var(--accent); border-color:var(--accent); color:var(--bg-base); }
    /* FIX 2026-07-25 — WCAG 2.5.5 Target Size (44x44). The visible box stays
       20x20 by design; ::after carries the real pointer target. A click on a
       pseudo-element is attributed to its originating element, so the inline
       onclick in app.js needs no change.

       The two sizes that keep this target from OVERLAPPING a neighbour (an
       overlap would trade one 2.5.x problem for another): the SGP track went
       28px -> 44px so the target stays inside its own column, and the row
       gets min-height:44px so vertically adjacent checkboxes can't collide —
       rows were ~40px, i.e. 4px short, which is exactly how much a 44px
       target would have spilled into the row above and below.

       Applies at every width, not just phones: 2.5.5 covers mouse pointers
       too, and precision pointing is the exact thing this product must not
       assume. Guarded by tests/test_props_row_mobile_scroll.py. */
    .props-sgp-checkbox::after {
      content:''; position:absolute; left:50%; top:50%;
      width:44px; height:44px; transform:translate(-50%,-50%);
    }
    .props-player-row.props-sgp-mode { min-height:44px; }

    /* FIX 2026-07-25: the three LATENT props grids. `.props-col-header` and
       `.props-player-row` share `1fr 78px 76px 62px 76px 56px`, and
       `.props-player-row.props-sgp-mode` prepends a 44px checkbox column.
       The fixed tracks alone are 348px (392px in SGP mode) plus 32px of
       padding — inside a ~295px .props-content at a 390px viewport. Same bug
       class as the analytics grids and .slate-prop-row, but it renders ZERO
       rows out of NBA season, so it was invisible to the live sweep and would
       have bitten in ~Oct.

       Scroll rather than collapse to a card (Bill's analytics call, and the
       only option that survives this markup): `.props-col-header` is a real
       header whose spans align to the row tracks, and a player's extra lines
       render with an EMPTY name cell (app.js ~8651) so they read as a group.
       A card stack destroys both. Making the team body the scroller keeps
       header and rows in one aligned, swipeable table.

       Scoped to 639px to match .slate-row / .slate-prop-row. At 640-768px
       .props-content is ~600px+, which clears the 380px the desktop grid
       needs, so a wider scope would add a scrollbar to rows that already fit.

       THIS BLOCK MUST STAY BELOW the .props-sgp-mode rules above. A media
       query adds NO specificity, and `.props-player-row.props-sgp-mode` here
       ties the desktop rule at two classes — so whichever comes LAST wins.
       It originally sat ~30 lines higher and the desktop `44px 1fr ...` quietly
       beat it, leaving the phone SGP name track as a 1fr that resolved to the
       player name's max-content (97px for "Jayson Tatum") instead of the fixed
       120px. Guarded by tests/test_props_row_mobile_scroll.py, which asserts
       source ORDER — a declaration-level test cannot see the cascade. */
    @media (max-width: 639px) {
      .props-team-body { overflow-x:auto; -webkit-overflow-scrolling:touch; }
      /* Fixed first track, not 1fr: inside a scroller a 1fr name column would
         collapse to 0 and the row's max-content would then swing with the
         longest player name. 120px ellipsizes predictably (the cell already
         sets overflow:hidden + text-overflow) and pins the row at a known
         width, so the swipe is bounded. */
      .props-col-header,
      .props-player-row { grid-template-columns:120px 78px 76px 62px 76px 56px; }
      .props-player-row.props-sgp-mode,
      .props-col-header.props-sgp-mode { grid-template-columns:44px 120px 78px 76px 62px 76px 56px; }
      /* Without this the row BOX is only as wide as the 295px container while
         its tracks overflow, so the border, hover fill and locked-row tint
         stop mid-row once you scroll. min-width:100% keeps short rows full
         width. */
      .props-col-header,
      .props-player-row { width:max-content; min-width:100%; }
    }

    /* Floating slip panel — bottom-right of the props view */
    .props-sgp-panel { position:fixed; bottom:20px; right:20px; width:340px; max-height:70vh; overflow-y:auto; background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-lg); box-shadow:0 10px 30px rgba(0,0,0,0.4); z-index:50; display:flex; flex-direction:column; }
    .props-sgp-panel-header { display:flex; align-items:center; gap:8px; padding:12px 16px; background:var(--bg-surface); border-bottom:1px solid var(--border-subtle); }
    .props-sgp-panel-title { font-weight:700; color:var(--text-primary); font-size:var(--text-base); }
    .props-sgp-leg-count-wrap { font-size:var(--text-sm); color:var(--text-muted); font-family:var(--font-mono); }
    .props-sgp-panel-close { margin-left:auto; background:none; border:none; color:var(--text-muted); font-size:20px; cursor:pointer; line-height:1; padding:0 4px; }
    .props-sgp-panel-close:hover { color:var(--text-primary); }
    .props-sgp-legs { padding:8px 12px; flex:1; min-height:60px; }
    .props-sgp-empty { font-size:var(--text-sm); color:var(--text-muted); text-align:center; padding:16px 8px; line-height:1.4; }
    .props-sgp-leg { display:flex; align-items:center; gap:8px; padding:8px 10px; margin-bottom:6px; background:var(--bg-surface); border-radius:6px; font-size:var(--text-sm); }
    .props-sgp-leg-name { font-weight:700; color:var(--text-primary); flex-shrink:0; }
    .props-sgp-leg-detail { color:var(--text-muted); font-family:var(--font-mono); font-size:var(--text-xs); flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
    .props-sgp-leg-remove { background:none; border:none; color:var(--text-faint); font-size:18px; cursor:pointer; line-height:1; padding:0 4px; flex-shrink:0; }
    .props-sgp-leg-remove:hover { color:var(--ev-neg); }
    .props-sgp-actions { display:flex; gap:8px; padding:8px 12px; border-top:1px solid var(--border-subtle); }
    .props-sgp-btn { flex:1; padding:8px 14px; border:none; border-radius:6px; font-size:var(--text-sm); font-weight:600; cursor:pointer; transition:opacity var(--transition-fast); }
    .props-sgp-btn-primary { background:var(--accent); color:var(--bg-base); }
    .props-sgp-btn-primary:hover { opacity:0.9; }
    .props-sgp-btn-secondary { background:var(--bg-surface); color:var(--text-secondary); border:1px solid var(--border-default); }
    .props-sgp-btn-secondary:hover { color:var(--text-primary); }
    .props-sgp-status { padding:0 16px; font-size:var(--text-sm); color:var(--text-muted); min-height:18px; }
    .props-sgp-result { padding:0 16px 12px; }
    .props-sgp-result-row { display:flex; align-items:center; justify-content:space-between; padding:6px 0; font-size:var(--text-sm); border-top:1px solid var(--border-subtle); color:var(--text-secondary); }
    .props-sgp-result-row:first-child { border-top:none; padding-top:10px; }
    .props-sgp-result-val { font-family:var(--font-mono); font-weight:700; color:var(--text-primary); }
    .props-sgp-result-corr { color:var(--accent-green); font-style:italic; font-size:var(--text-xs); padding:2px 0; border-top:none; }
    /* Grade-gate note: shown when a leg is not model-recommended so the joint
       EV above is not read as a green light. */
    .props-sgp-result-note { display:block; color:var(--accent-amber,#e8a40f); font-size:var(--text-xs); line-height:1.35; padding:4px 0; border-top:none; }

    /* Game strip odds rows */
    .strip-odds { display:grid; grid-template-columns:58px 1fr 1fr 1fr; gap:2px; align-items:center; font-size:var(--text-sm); font-family:var(--font-mono); }
    .strip-odds-abbr { font-size:var(--text-base); font-weight:600; color:var(--text-primary); padding:1px 2px; font-family:system-ui,sans-serif; white-space:nowrap; overflow:hidden; line-height:1.3; }
    .strip-odds-cell { text-align:center; padding:1px 2px; border-radius:3px; color:var(--text-secondary); line-height:1.3; cursor:pointer; transition:box-shadow 0.15s; }
    .strip-odds-cell .strip-odds-val { font-weight:600; }
    .strip-odds-cell .strip-odds-juice { font-size:var(--text-xs); color:var(--text-muted); font-weight:400; }
    .strip-odds-cell.strip-cell-bet { background:rgba(52,211,153,0.12); }
    .strip-odds-cell.strip-cell-lean { background:rgba(251,191,36,0.12); }
    .strip-odds-cell.strip-cell-focused { box-shadow:0 0 0 1.5px var(--accent); border-radius:4px; }
    .strip-odds-cell:hover { box-shadow:0 0 0 1px var(--accent); border-radius:4px; }

    /* ── Parlay Slip ─────────────────────────────────── */
    .parlay-slip{position:fixed;bottom:20px;right:20px;z-index:9000;width:380px;max-height:80vh;border-radius:var(--radius-lg);border:1px solid var(--border-default);background:var(--bg-surface);box-shadow:0 8px 32px rgba(0,0,0,0.4);overflow:hidden;transition:all 0.3s ease;font-family:'IBM Plex Sans',system-ui;}
    .parlay-slip.collapsed .parlay-expanded{display:none;}
    .parlay-slip.expanded .parlay-collapsed-body{display:none;}
    .parlay-slip .parlay-header{background:linear-gradient(135deg,var(--accent),var(--accent-hover));padding:10px 14px;display:flex;justify-content:space-between;align-items:center;cursor:pointer;}
    .parlay-slip .parlay-header .parlay-title{display:flex;align-items:center;gap:8px;font-weight:700;font-size:var(--text-base);color:#fff;}
    .parlay-slip .parlay-header .parlay-badge{background:rgba(0,0,0,0.3);border-radius:var(--radius-pill);padding:2px 8px;font-size:var(--text-xs);color:#fff;}
    .parlay-slip .parlay-header .parlay-toggle{color:rgba(255,255,255,0.8);font-size:var(--text-xs);}
    .parlay-collapsed-body{padding:12px 14px;display:flex;justify-content:space-between;font-size:var(--text-base);}
    .parlay-collapsed-body .parlay-stat{text-align:center;}
    .parlay-collapsed-body .parlay-stat-label{color:var(--text-muted);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:0.04em;}
    .parlay-collapsed-body .parlay-stat-value{font-weight:700;font-size:var(--text-lg);font-family:var(--font-mono);color:var(--text-primary);}
    .parlay-collapsed-body .parlay-stat-value.pos{color:var(--ev-pos);}
    .parlay-collapsed-body .parlay-stat-value.neg{color:var(--ev-neg);}
    .parlay-expanded{max-height:60vh;overflow-y:auto;}
    /* FIX 2026-08-11: these are the SLIP's legs (app.js renderParlaySlip,
       always inside #parlay-slip.parlay-slip). They were unscoped, so they
       also hit the Slate CART's legs — a different component, in
       .parlay-rail, styled from slate.css:555 under the same class name.
       slate.css loads second and won every property both declared, but
       `display` was declared ONLY here, so this flex row silently laid out
       the cart and put .parlay-leg-meta under its corner button.
       Scoped to .parlay-slip, matching this file's own convention for the
       rest of the component (see .parlay-slip .parlay-header above).
       Guarded by tests/test_slate_touch_targets.py. */
    .parlay-slip .parlay-leg{padding:10px 14px;border-bottom:1px solid var(--border-subtle);display:flex;justify-content:space-between;align-items:start;}
    .parlay-slip .parlay-leg-info{flex:1;}
    .parlay-slip .parlay-leg-badges{display:flex;gap:4px;align-items:center;margin-bottom:4px;}
    .parlay-slip .parlay-leg-badges .sport-badge{background:var(--bg-hover);color:var(--text-muted);font-size:var(--text-xs);padding:2px 5px;border-radius:var(--radius-sm);text-transform:uppercase;}
    .parlay-slip .parlay-leg-badges .sizing-badge-mini{font-size:var(--text-xs);padding:2px 5px;border-radius:var(--radius-sm);font-weight:700;}
    .parlay-slip .parlay-leg-badges .sizing-badge-mini.bet{background:var(--accent-green-bg);color:var(--ev-pos);}
    .parlay-slip .parlay-leg-badges .sizing-badge-mini.lean{background:var(--accent-amber-bg);color:var(--accent-amber);}
    .parlay-slip .parlay-leg-badges .sizing-badge-mini.pass{background:var(--bg-hover);color:var(--text-faint);font-weight:600;}
    .parlay-slip .parlay-leg-badges .sizing-badge-mini.defer{background:rgba(255,80,80,0.1);color:var(--ev-neg);font-weight:600;}
    .parlay-slip .parlay-leg-desc{color:var(--text-primary);font-size:var(--text-base);font-weight:600;}
    .parlay-slip .parlay-leg-context{color:var(--text-muted);font-size:var(--text-sm);}
    .parlay-slip .parlay-leg-odds{text-align:right;margin-right:8px;}
    .parlay-slip .parlay-leg-odds-val{font-weight:700;font-size:var(--text-base);font-family:var(--font-mono);}
    .parlay-slip .parlay-leg-odds-prob{color:var(--text-muted);font-size:var(--text-xs);font-family:var(--font-mono);}
    .parlay-slip .parlay-leg-remove{color:var(--text-faint);font-size:var(--text-base);cursor:pointer;padding:2px 4px;transition:color var(--transition-fast);}
    .parlay-slip .parlay-leg-remove:hover{color:var(--accent-red);}
    .parlay-warning{padding:8px 14px;background:var(--accent-amber-bg);border-bottom:1px solid var(--border-subtle);display:flex;align-items:center;gap:6px;font-size:12px;color:var(--accent-amber);}
    .parlay-summary{padding:12px 14px;background:var(--bg-elevated);}
    .parlay-metrics{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:var(--space-sm);margin-bottom:12px;}
    .parlay-metric-label{color:var(--text-muted);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:0.04em;}
    .parlay-metric-value{font-weight:700;font-size:18px;font-family:var(--font-mono);color:var(--text-primary);}
    .parlay-stake-row{display:flex;gap:8px;align-items:center;}
    .parlay-stake-input{flex:1;background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:var(--radius-sm);padding:8px 10px 8px 24px;color:var(--text-primary);font-size:var(--text-base);font-weight:600;font-family:var(--font-mono);}
    .parlay-stake-box{background:var(--bg-elevated);border:1px solid var(--border-default);border-radius:var(--radius-sm);padding:8px 12px;text-align:center;}
    .parlay-actions{display:flex;justify-content:flex-end;padding:8px 14px;gap:8px;border-top:1px solid var(--border-subtle);}
    .parlay-actions button{background:none;border:1px solid var(--border-default);border-radius:var(--radius-sm);padding:4px 12px;color:var(--text-muted);font-size:var(--text-sm);cursor:pointer;transition:all var(--transition-fast);}
    .parlay-actions button:hover{border-color:var(--accent);color:var(--text-primary);}
    .odds-cell.parlay-selected{border:2px solid var(--ev-pos) !important;background:var(--accent-green-bg) !important;position:relative;}
    .odds-cell.parlay-selected::after{content:'✓';position:absolute;top:-6px;right:-6px;background:var(--ev-pos);color:#0d1117;border-radius:50%;width:14px;height:14px;font-size:12px;display:flex;align-items:center;justify-content:center;}
    .strip-odds-cell.parlay-selected{border:2px solid var(--ev-pos) !important;background:var(--accent-green-bg) !important;position:relative;}
    .strip-odds-cell.parlay-selected::after{content:'✓';position:absolute;top:-6px;right:-6px;background:var(--ev-pos);color:#0d1117;border-radius:50%;width:14px;height:14px;font-size:12px;display:flex;align-items:center;justify-content:center;}

    .strip-odds-head .strip-head-focused { color:var(--accent); }
    .gd-bet-row.gd-bet-row-focused { grid-template-columns:1fr; }
    .gd-bet-tabs { display:flex; align-items:center; gap:6px; margin-bottom:10px; }
    .gd-bet-tabs-label { font-size:var(--text-base); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; margin-right:4px; }
    .gd-bet-tab { padding:5px 14px; border-radius:var(--radius-pill); font-size:var(--text-base); font-weight:600; cursor:pointer; border:1.5px solid var(--border-strong); background:var(--bg-card); color:var(--text-secondary); transition:all 0.15s; }
    .gd-bet-tab:hover { border-color:var(--accent); color:var(--accent); }
    .gd-bet-tab.active { background:var(--accent); color:#0d1117; border-color:var(--accent); }
    .ls-col-focused { background:var(--accent-muted); }
    .ls-th-focused { color:var(--accent) !important; font-weight:700 !important; }
    .strip-odds-head { display:grid; grid-template-columns:58px 1fr 1fr 1fr; gap:2px; font-size:var(--text-sm); color:var(--text-secondary); text-transform:uppercase; letter-spacing:0.06em; font-weight:700; text-align:center; margin-top:2px; }
    .strip-fallback { font-size:var(--text-xs); padding:0 4px; background:var(--accent-amber-bg); color:var(--accent-amber); border-radius:3px; font-weight:600; margin-left:4px; }
    .strip-steam { font-size:var(--text-xs); padding:0 4px; background:rgba(248,113,113,0.15); color:var(--ev-neg); border-radius:3px; font-weight:700; margin-left:4px; cursor:pointer; animation:steamPulse 1.8s ease-in-out infinite; }
    @keyframes steamPulse { 0%,100%{box-shadow:0 0 4px rgba(248,113,113,0.4);} 50%{box-shadow:0 0 12px rgba(248,113,113,0.8), 0 0 20px rgba(248,113,113,0.3);} }
    .steam-books-tbl { width:100%; border-collapse:collapse; font-size:var(--text-base); margin:10px 0; }
    .steam-books-tbl th { text-align:left; padding:4px 8px; border-bottom:2px solid var(--border-default); color:var(--text-muted); font-weight:600; font-size:var(--text-sm); text-transform:uppercase; }
    .steam-books-tbl td { padding:4px 8px; border-bottom:1px solid var(--border-subtle); }
    .steam-books-tbl .shift-pos { color:var(--ev-neg); font-weight:700; }
    .steam-books-tbl .shift-neg { color:var(--ev-pos); font-weight:700; }
    .steam-interp { border:1.5px solid var(--accent-amber); background:var(--accent-amber-bg); border-radius:8px; padding:12px 16px; margin-top:12px; font-size:var(--text-base); line-height:1.5; color:var(--accent-amber); }
    .steam-interp-action { margin-top:8px; padding:8px 12px; border-radius:6px; background:var(--accent-muted); border:1px solid var(--border-default); color:var(--accent); font-size:var(--text-sm); font-weight:600; }

    /* Game Dashboard — main content area */
    .game-dashboard { display:flex; flex-direction:column; height:100vh; overflow:hidden; background:var(--bg-page); }

    /* Dashboard Header */
    .gd-header { display:flex; align-items:center; gap:16px; padding:12px 24px; background:var(--bg-card); border-bottom:1px solid var(--border-default); flex-shrink:0; min-height:56px; }
    .gd-header-teams { font-size:1rem; font-weight:700; color:var(--text-primary); white-space:nowrap; }
    .gd-header-time { font-size:var(--text-base); color:var(--text-muted); }
    .gd-header-live { font-size:var(--text-sm); font-weight:700; color:var(--ev-neg); text-transform:uppercase; display:inline-flex; align-items:center; gap:4px; }
    .gd-header-live::before { content:''; display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--ev-neg); animation:livePulse 1.5s ease-in-out infinite; }
    .gd-header-badges { display:flex; gap:8px; margin-left:auto; flex-shrink:0; flex-wrap:wrap; }
    .gd-conf-badge { display:inline-flex; align-items:center; gap:4px; padding:3px 10px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:700; text-transform:uppercase; letter-spacing:0.03em; }
    .gd-conf-high { background:var(--accent-green-bg); color:var(--ev-pos); }
    .gd-conf-mod { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .gd-conf-low { background:var(--accent-red-bg); color:var(--ev-neg); }
    .gd-sizing-pill { display:inline-flex; align-items:center; gap:4px; padding:4px 12px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:800; text-transform:uppercase; }
    .gd-sizing-bet { background:var(--accent-hover); color:#fff; }
    .gd-sizing-lock { background:#3b82f6; color:#fff; }
    .gd-sizing-lean { background:var(--accent-amber); color:#fff; }
    .gd-sizing-pass { background:var(--bg-hover); color:var(--text-muted); }

    /* Dashboard Body */
    .gd-body { flex:1; overflow-y:auto; overflow-x:hidden; padding:16px 20px; display:flex; flex-direction:column; gap:14px; }

    /* Top Row — 3 Bet Type Cards */
    .gd-bet-row { display:grid; grid-template-columns:repeat(3,1fr); gap:14px; flex-shrink:0; }
    .gd-bet-card { background:linear-gradient(135deg, var(--bg-card), var(--bg-surface)); border:1px solid var(--border-strong); border-radius:var(--radius-lg); padding:14px 16px; display:flex; flex-direction:column; gap:8px; box-shadow:var(--shadow-card); overflow:hidden; min-width:0; }
    .gd-bet-card-header { display:flex; align-items:center; justify-content:space-between; padding-bottom:6px; border-bottom:1px solid var(--border-subtle); }
    .gd-bet-card-type { font-size:var(--text-base); font-weight:700; color:var(--text-primary); text-transform:uppercase; letter-spacing:0.04em; }
    .gd-bet-card .sizing-badge-inline { padding:2px 8px; border-radius:var(--radius-pill); font-size:var(--text-sm); font-weight:700; text-transform:uppercase; }
    .gd-pick-line { font-size:var(--text-base); font-weight:700; color:var(--text-primary); }
    .gd-numbers { display:grid; grid-template-columns:1fr 1fr; gap:4px; }
    .gd-num-item { font-size:var(--text-base); }
    .gd-num-item .gd-num-label { color:var(--text-muted); font-weight:500; }
    .gd-num-item .gd-num-value { color:var(--text-primary); font-weight:600; font-family:var(--font-mono); }
    .gd-sources { border-top:1px solid var(--border-subtle); padding-top:6px; }
    .gd-source-row { display:flex; align-items:center; gap:6px; padding:2px 0; font-size:var(--text-base); }
    .gd-source-label { width:52px; color:var(--text-muted); font-weight:500; flex-shrink:0; }
    .gd-source-bar { flex:1; height:7px; background:var(--accent-muted); border-radius:3px; overflow:hidden; }
    .gd-source-bar-fill { height:100%; border-radius:3px; transition:width 0.3s ease; }
    .gd-source-val { width:48px; text-align:right; color:var(--text-secondary); font-family:var(--font-mono); font-weight:500; font-size:var(--text-base); }
    .gd-sizing-reason { padding:6px 10px; border-radius:6px; font-size:var(--text-base); color:var(--text-secondary); line-height:1.4; border-left:3px solid; }
    .gd-sizing-reason-bet { background:var(--accent-green-bg); border-color:var(--ev-pos); }
    .gd-sizing-reason-lock { background:rgba(59,130,246,0.08); border-color:#3b82f6; }
    .gd-sizing-reason-lean { background:var(--accent-amber-bg); border-color:var(--accent-amber); }
    .gd-sizing-reason-pass { background:var(--bg-surface); border-color:var(--text-muted); }
    .gd-best-book { font-size:var(--text-base); color:var(--accent-blue); font-weight:600; }

    /* Detail Panels — full-width vertical stack */
    .gd-detail-row { display:flex; flex-direction:column; gap:14px; overflow:visible; }
    .gd-detail-panel { background:var(--bg-card); border:1px solid var(--border-strong); border-radius:var(--radius-lg); box-shadow:var(--shadow-card); }
    .gd-detail-panel-header { padding:10px 14px; border-bottom:1px solid var(--border-subtle); font-size:var(--text-base); font-weight:700; color:var(--text-primary); text-transform:uppercase; letter-spacing:0.04em; display:flex; align-items:center; justify-content:space-between; }
    .gd-detail-panel-body { padding:12px 14px; font-size:var(--text-base); color:var(--text-secondary); line-height:1.5; overflow-wrap:break-word; word-break:break-word; }

    /* Signals panel styling */
    .gd-signal-item { padding:6px 0; border-bottom:1px solid var(--border-subtle); }
    .gd-signal-item:last-child { border-bottom:none; }
    .gd-signal-header { display:flex; align-items:center; gap:6px; }
    .gd-signal-name { font-weight:600; color:var(--text-primary); font-size:var(--text-sm); }
    .gd-signal-weight { color:var(--text-muted); font-size:var(--text-xs); }
    .gd-signal-favor { font-weight:600; font-size:var(--text-sm); margin-left:auto; }
    .gd-signal-drilldown { margin:4px 0 0 12px; padding:6px 0 4px 10px; border-left:2px solid var(--border-default); font-size:var(--text-sm); color:var(--text-secondary); }

    /* Books panel */
    .gd-books-best { display:grid; grid-template-columns:repeat(5,1fr); gap:1px; background:var(--border-subtle); border-radius:var(--radius-sm); overflow:hidden; margin-bottom:10px; }
    .gd-books-best-cell { background:var(--accent-green-bg); padding:8px 10px; text-align:center; }
    .gd-books-best-label { font-size:var(--text-xs); font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; }
    .gd-books-best-book { font-size:var(--text-sm); font-weight:700; color:var(--accent-green); }
    .gd-books-best-odds { font-size:var(--text-sm); font-weight:800; color:var(--accent-green); font-family:var(--font-mono); }

    /* Context panel */
    .gd-ctx-section { margin-bottom:10px; }
    .gd-ctx-label { font-size:var(--text-xs); font-weight:700; color:var(--accent-blue); text-transform:uppercase; letter-spacing:0.04em; margin-bottom:4px; }
    .gd-ctx-content { font-size:var(--text-sm); color:var(--text-secondary); line-height:1.5; }
    .gd-pm-row { display:flex; justify-content:space-between; padding:2px 0; font-size:var(--text-sm); }
    .gd-pm-label { color:var(--text-muted); }
    .gd-pm-value { color:var(--text-primary); font-weight:600; font-family:var(--font-mono); }

    /* AI panel extras */
    .gd-chalk { margin-top:8px; padding:8px 12px; background:var(--bg-surface); border-left:3px solid var(--text-dim); border-radius:6px; }
    .gd-chalk-label { font-size:var(--text-xs); font-weight:700; color:var(--text-dim); text-transform:uppercase; letter-spacing:0.04em; margin-bottom:6px; }
    .gd-chalk-row { padding:4px 0; }
    .gd-chalk-row + .gd-chalk-row { border-top:1px solid var(--border); margin-top:4px; padding-top:6px; }
    .gd-chalk-team { font-size:var(--text-lg); font-weight:700; color:var(--text-primary); }
    .gd-chalk-sources { font-size:var(--text-xs); color:var(--text-dim); margin-top:2px; }
    .gd-chalk-odds { font-size:var(--text-base); color:var(--text-secondary); margin-top:3px; }
    .gd-chalk-tag { display:inline-block; font-size:var(--text-xs); font-weight:600; padding:1px 6px; border-radius:9999px; margin-left:6px; vertical-align:middle; }
    .gd-chalk-tag--edge { background:var(--accent-green-bg); color:var(--ev-pos); }
    .gd-chalk-tag--low { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .gd-line-shop { margin-top:8px; padding:8px 12px; background:var(--accent-muted); border-left:3px solid var(--accent); border-radius:6px; }
    .gd-line-shop-label { font-size:var(--text-xs); font-weight:700; color:var(--accent); text-transform:uppercase; letter-spacing:0.04em; margin-bottom:2px; }
    .gd-line-shop-action { font-size:var(--text-base); color:var(--text-primary); line-height:1.4; }
    .gd-line-shop-fair { font-size:var(--text-sm); color:var(--text-muted); margin-top:3px; }
    .gd-clv-inline { display:inline-flex; gap:6px; align-items:center; font-size:var(--text-sm); color:var(--text-muted); }
    .gd-kelly-label { font-size:var(--text-sm); color:var(--text-muted); margin-top:3px; }
    .gd-ctx-delta { font-size:var(--text-sm); font-weight:600; margin-top:2px; }

    /* Empty state */
    .gd-empty { display:flex; align-items:center; justify-content:center; height:100%; color:var(--text-faint); font-size:var(--text-lg); }

    /* Fade transition for game switching */
    .gd-fade-enter { animation:gdFadeIn 0.15s ease; }
    @keyframes gdFadeIn { from{opacity:0;} to{opacity:1;} }

    /* Responsive: <1600px narrow strip */
    @media (max-width:1200px) {
      .app-layout-gameview { grid-template-columns:220px 240px 1fr; }
    }
    /* Tablet: collapse sidebar */
    @media (max-width:1024px) {
      .app-layout-gameview { grid-template-columns:0px 240px 1fr; }
      /* FIX 2026-07-12 (Batch 2): the sidebar used to display:none here with
         NO replacement — sport switching on phones/tablets depended entirely
         on the hamburger. It now becomes a horizontal sport-chip strip under
         the top nav (gameview keeps it hidden — that layout has its own
         strip). initSportTabs() force-opens the <details> categories at this
         width because closed-details content cannot be revealed by CSS. */
      .app-layout-gameview .sidebar { display:none; }
      .app-layout > .sidebar {
        position:static; width:auto; height:auto;
        /* min-width:0 is load-bearing: as a grid item the sidebar's default
           min-width:auto would size the track to the chip strip's min-content
           (~1300px of non-wrapping chips), blowing the mobile layout viewport
           out to ~1338px. Found live 2026-07-12. */
        min-width:0;
        padding:0; overflow:visible;
        border-right:none; border-bottom:1px solid var(--border-subtle);
      }
      .app-layout > .sidebar .sidebar-section { padding:0; }
      .app-layout > .sidebar .sidebar-section-title { display:none; }
      /* Footer utilities (Tutorial / Reference / Terms) stay hamburger-only */
      .app-layout > .sidebar > div:not(.sidebar-section) { display:none; }
      .app-layout > .sidebar #sport-tabs-container {
        display:flex; align-items:center; gap:6px;
        overflow-x:auto; -webkit-overflow-scrolling:touch;
        padding:8px 12px;
        scrollbar-width:none;
      }
      .app-layout > .sidebar #sport-tabs-container::-webkit-scrollbar { display:none; }
      .app-layout > .sidebar .sidebar-category { display:contents; }
      .app-layout > .sidebar .sidebar-category > summary { display:none; }
      /* FIX 2026-07-25: was display:contents, intending (with the same on
         .sidebar-category above) to flatten every league chip into ONE flex
         row. `<details>` has a UA shadow DOM and does NOT honour that
         flattening, so each CATEGORY stayed a single flex item with its
         leagues stacked VERTICALLY — making the strip as tall as the tallest
         category. Measured on prod at 390px, chips shared an x-slot per
         category: soccer dx=569 at dy 8/56/103/151/198/246 (6 leagues) =
         6 x 48px = 288 + padding = the 302px strip, i.e. 36% of the phone
         screen and almost all of it empty (align-items:center centred each
         shorter stack, hence the staggered look).
         An explicit horizontal row doesn't depend on that flattening:
         302px -> 66px, all 17 chips on one row, horizontal scroll intact.
         Do NOT revert to display:contents — it computes as "contents" with a
         0x0 rect, so it LOOKS applied while laying out as a block.
         Guarded by tests/test_mobile_chip_strip.py. */
      .app-layout > .sidebar .sidebar-league-list {
        display:flex; flex-direction:row; align-items:center; gap:6px;
      }
      .app-layout > .sidebar .sidebar-league-item {
        flex:0 0 auto; white-space:nowrap;
        padding:8px 14px; margin:0;
        min-height:44px;
        border:1px solid var(--border-default); border-left:1px solid var(--border-default);
        border-radius:var(--radius-pill);
      }
      .app-layout > .sidebar .sidebar-league-item.active {
        border-color:var(--accent); color:var(--accent);
        background:var(--accent-muted);
      }
      /* FIX 2026-07-12: sidebar hides at <=1024px but .app-layout kept its
         180px first track until <=639px, so across 640-1023px (iPad portrait,
         large phones landscape) main-content auto-placed into the dead 180px
         column and the whole Slate rendered in a ~180px ribbon. Collapse to a
         single column wherever the sidebar rail is gone (the chip strip spans
         the single column as a grid row). minmax(0,1fr), not bare 1fr — bare
         1fr's auto minimum lets wide row content (chip strip, tables) expand
         the track past the viewport. */
      .app-layout { grid-template-columns:minmax(0,1fr); }
    }
    /* Mobile: single column — strip on top, dashboard below */
    @media (max-width:768px) {
      .app-layout-gameview { display:flex; flex-direction:column; }
      .app-layout-gameview .sidebar { display:none; }
      .game-strip { height:auto; max-height:35vh; position:relative; border-right:none; border-bottom:1px solid var(--border-default); }
      .game-dashboard { height:auto; min-height:65vh; }
      .game-strip-item { padding:8px 10px; }
      .strip-odds-head span { font-size:var(--text-xs); }
      .gd-header { flex-direction:column; align-items:flex-start; gap:6px; }
      .gd-source-grid { grid-template-columns:1fr 1fr; }
    }

    /* ============================================================
       TUTORIAL MODAL
       ============================================================ */
    .tutorial-modal { width:min(720px,92vw); max-height:85vh; overflow-y:auto; border-top:3px solid var(--accent-blue); }
    .tutorial-header { display:flex; align-items:center; justify-content:space-between; padding:16px 20px 12px; border-bottom:1px solid var(--border-subtle); }
    .tutorial-header h2 { margin:0; font-size:1rem; color:var(--text-primary); font-weight:700; }
    .tutorial-counter { font-size:var(--text-sm); color:var(--text-muted); font-weight:500; }
    .tutorial-progress { display:flex; gap:6px; padding:12px 20px 0; justify-content:center; }
    .tutorial-pip { width:10px; height:10px; border-radius:50%; background:var(--border-default); transition:background 0.2s, transform 0.2s; cursor:pointer; }
    .tutorial-pip:hover { transform:scale(1.2); }
    .tutorial-pip.active { background:var(--accent-blue); transform:scale(1.15); }
    .tutorial-pip.completed { background:var(--accent-green); }
    .tutorial-step-content { padding:20px 24px 16px; animation:tutorialFade 0.25s ease; }
    @keyframes tutorialFade { from{opacity:0;transform:translateX(8px)} to{opacity:1;transform:translateX(0)} }
    @keyframes analyticsSpinner { to{transform:rotate(360deg)} }
    .analytics-loading{display:flex;align-items:center;gap:8px;color:var(--text-dim);font-size:var(--text-base);}
    .analytics-loading::before{content:'';width:14px;height:14px;border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:analyticsSpinner 0.6s linear infinite;}
    .tutorial-step-title { font-size:var(--text-base); font-weight:700; color:var(--text-primary); margin:0 0 4px; }
    .tutorial-step-phase { font-size:var(--text-sm); font-weight:600; text-transform:uppercase; letter-spacing:0.06em; color:var(--accent-blue); margin-bottom:12px; }
    .tutorial-visual { background:var(--bg-page); border:1px solid var(--border-subtle); border-radius:var(--radius-md); padding:16px; margin-bottom:14px; }
    .tutorial-text { font-size:var(--text-base); color:var(--text-secondary); line-height:1.6; }
    .tutorial-text p { margin:0 0 8px; }
    .tutorial-text strong { color:var(--text-primary); }
    .tutorial-audio { display:flex; align-items:center; gap:10px; }
    .tutorial-audio-btn { display:inline-flex; align-items:center; gap:6px; padding:6px 14px; border-radius:var(--radius-pill); border:1px solid var(--border-default); background:var(--bg-surface); color:var(--text-secondary); font-size:var(--text-sm); font-weight:600; cursor:pointer; transition:all 0.15s; }
    .tutorial-audio-btn:hover { background:var(--bg-hover); border-color:var(--accent-blue); color:var(--accent-blue); }
    .tutorial-audio-btn.playing { background:var(--accent-muted); border-color:var(--accent-blue); color:var(--accent-blue); }
    .tutorial-nav { display:flex; align-items:center; justify-content:space-between; padding:12px 20px; border-bottom:1px solid var(--border-subtle); }
    .tutorial-nav-btn { padding:8px 20px; border-radius:var(--radius-sm); font-size:var(--text-base); font-weight:600; cursor:pointer; transition:all 0.15s; border:1px solid var(--border-default); }
    .tutorial-nav-btn.primary { background:var(--accent-blue); color:#0d1117; border-color:var(--accent-blue); }
    .tutorial-nav-btn.primary:hover { opacity:0.9; }
    .tutorial-nav-btn.secondary { background:var(--bg-surface); color:var(--text-secondary); }
    .tutorial-nav-btn.secondary:hover { background:var(--bg-hover); }
    .tutorial-nav-btn:disabled { opacity:0.4; cursor:not-allowed; }
    .tutorial-skip { font-size:var(--text-sm); color:var(--text-muted); cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
    .tutorial-skip:hover { color:var(--text-primary); }
    /* Tutorial visual diagram annotations */
    .tv-card { background:var(--bg-card); border:1px solid var(--border-default); border-radius:var(--radius-md); overflow:hidden; font-size:var(--text-sm); }
    .tv-row { display:grid; grid-template-columns:1fr 60px 60px 60px; gap:4px; padding:4px 10px; align-items:center; }
    .tv-team { font-weight:600; color:var(--text-primary); }
    .tv-odds { text-align:center; padding:3px 4px; border:1px solid var(--border-default); border-radius:4px; font-family:var(--font-mono); font-size:var(--text-sm); }
    .tv-odds.tv-bet { background:var(--accent-green-bg); border-color:var(--ev-pos); }
    .tv-odds.tv-lean { background:var(--accent-amber-bg); border-color:var(--accent-amber); }
    .tv-header { display:grid; grid-template-columns:1fr 60px 60px 60px; gap:4px; padding:4px 10px; font-size:var(--text-xs); font-weight:700; color:var(--text-muted); text-transform:uppercase; text-align:center; }
    .tv-header span:first-child { text-align:left; }
    .tv-badge { display:inline-block; padding:2px 8px; border-radius:var(--radius-pill); font-size:var(--text-xs); font-weight:700; text-transform:uppercase; }
    .tv-badge-bet { background:var(--accent-green-bg); color:var(--accent-green); }
    .tv-badge-lock { background:rgba(59,130,246,0.12); color:#3b82f6; }
    .tv-badge-lean { background:var(--accent-amber-bg); color:var(--accent-amber); }
    .tv-badge-pass { background:var(--bg-surface); color:var(--text-faint); }
    .tv-annotation { display:flex; align-items:center; gap:6px; margin-top:8px; font-size:var(--text-xs); color:var(--text-muted); }
    .tv-annotation::before { content:''; display:inline-block; width:8px; height:8px; border-radius:50%; flex-shrink:0; }
    .tv-annotation.green::before { background:var(--accent-green-bg); border:1px solid var(--accent-green); }
    .tv-annotation.amber::before { background:var(--accent-amber-bg); border:1px solid var(--accent-amber); }
    .tv-annotation.blue::before { background:var(--accent-muted); border:1px solid var(--accent-blue); }
    .tv-source-bar { display:flex; gap:2px; height:8px; border-radius:4px; overflow:hidden; margin:4px 0; }
    .tv-source-bar > div { height:100%; border-radius:2px; }
    .tv-gauge-row { display:flex; align-items:center; gap:6px; margin:6px 0; }
    .tv-gauge-label { font-size:var(--text-sm); color:var(--text-muted); min-width:70px; font-weight:500; }
    .tv-gauge-track { flex:1; height:6px; background:var(--accent-muted); border-radius:3px; overflow:hidden; }
    .tv-gauge-fill { height:100%; border-radius:3px; }
    /* Analytics Dashboard Grid */
    .analytics-grid { display:flex; flex-direction:column; gap:var(--space-md); }
    .analytics-metrics { display:grid; grid-template-columns:repeat(4,1fr); gap:var(--space-sm); margin-bottom:var(--space-md); }
    .analytics-metric { background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-md); padding:var(--space-md); }
    .analytics-metric-value { font-size:24px; font-weight:700; font-family:var(--font-mono); color:var(--text-primary); }
    .analytics-metric-label { font-size:var(--text-xs); color:var(--text-muted); text-transform:uppercase; letter-spacing:0.04em; margin-top:var(--space-xs); }
    .analytics-metric-trend { font-size:var(--text-sm); font-family:var(--font-mono); margin-top:var(--space-xs); }
    .analytics-metric-trend.up { color:var(--ev-pos); }
    .analytics-metric-trend.down { color:var(--ev-neg); }
    .analytics-charts { display:grid; grid-template-columns:1fr 1fr; gap:var(--space-md); }
    .analytics-chart-card { background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-md); padding:var(--space-md); }
    /* card-info: shared style for the "?" info blurb on analytics/PM cards.
       Extracted 2026-07-12 from 20 identical inline style="" blocks in
       index.html. The inline style="display:none;" is intentionally kept on
       each element because toggleInfo() reads/writes info.style.display. */
    .card-info { color:var(--text-muted); font-size:var(--text-base); line-height:1.6; margin-bottom:12px; padding:10px 12px; background:var(--bg-elevated); border-radius:6px; }
    .analytics-chart-title { font-size:var(--text-sm); font-weight:600; color:var(--text-secondary); margin-bottom:var(--space-sm); display:flex; align-items:center; gap:8px; }
    .analytics-full-width { grid-column:1/-1; }
    .analytics-section-header { font-size:var(--text-base); font-weight:800; color:var(--accent); margin:var(--space-xl) 0 var(--space-md) 0; text-transform:uppercase; letter-spacing:0.04em; }
    .analytics-filter-bar { display:flex; gap:var(--space-sm); align-items:center; padding:var(--space-sm) 0; flex-wrap:wrap; }
    .analytics-filter-pill { font-size:var(--text-sm); padding:var(--space-xs) var(--space-md); border-radius:var(--radius-pill); border:1px solid var(--border-default); color:var(--text-muted); cursor:pointer; background:none; transition:all var(--transition-fast); }
    .analytics-filter-pill.active { background:var(--accent-muted); color:var(--accent); border-color:var(--accent); }
    .analytics-filter-pill:hover { border-color:var(--text-muted); color:var(--text-secondary); }

    /* FIX 2026-07-25: the Analytics tab pushed the PAGE sideways 467px at a
       390px viewport (scrollWidth 857 vs clientWidth 390).

       Root cause is grid blowout, not the tables on their own: a `1fr` track's
       automatic minimum is min-content, so every analytics grid sized itself to
       its widest descendant and spilled out of its parent —

         .analytics-metrics  repeat(4,1fr)  -> tracks 98/98/98/88 in a 310px row,
                                               last KPI card reached x=446
         .analytics-charts   1fr 1fr        -> e.g. 326px + 397px in a 310px row
         #analytics-daily-perf's inline split (app.js) 1fr 1fr
                                            -> 354px + 434px in a 284px card;
                                               the Signal Accuracy table started
                                               at x=423 and ran to x=857

       Stacking the grids is necessary but NOT sufficient: at one column the
       Signal Accuracy table's own min-content (434px) still exceeds the 284px
       card interior. So each wide table also gets its own scroll box —
       wide content scrolls in its own container, never the page body
       (same contract as .slate-ss-scroll and #analytics-props-history). */
    .analytics-tbl-scroll { overflow-x:auto; -webkit-overflow-scrolling:touch; }
    /* Two-up split inside an analytics card (was an inline style in app.js;
       promoted to a class so the phone breakpoint below can reach it). */
    .analytics-split-2 { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
    /* Six-up stat strip inside the Daily Performance card (also de-inlined). */
    .analytics-tiles-6 { display:grid; grid-template-columns:repeat(6,1fr); gap:8px; margin-bottom:16px; }

    @media (max-width: 639px) {
      .analytics-metrics { grid-template-columns:repeat(2,1fr); }
      .analytics-tiles-6 { grid-template-columns:repeat(2,1fr); }
      .analytics-charts { grid-template-columns:1fr; }
      .analytics-split-2 { grid-template-columns:1fr; }
      /* min-width:0 is the declaration that actually defeats the blowout — a
         single-column track still refuses to shrink below its item's
         min-content without it, so dropping this re-breaks the page. */
      .analytics-metrics > *,
      .analytics-tiles-6 > *,
      .analytics-charts > *,
      .analytics-split-2 > * { min-width:0; }
    }

    /* Detail Drawer — Slide-out panel */
    .detail-drawer-overlay { position:fixed; inset:0; background:rgba(0,0,0,0.3); z-index:50; opacity:0; pointer-events:none; transition:opacity var(--transition-normal); }
    .detail-drawer-overlay.open { opacity:1; pointer-events:auto; }
    /* FIX 2026-04-06: flex column with the scroll moved INSIDE #drawer-content
       so position:sticky on .drawer-bet-tabs-section actually works. Sticky was
       unreliable when the scroll container was the fixed+transformed
       .detail-drawer itself. */
    .detail-drawer { position:fixed; top:56px; right:0; bottom:0; width:420px; background:var(--bg-surface); border-left:1px solid var(--border-subtle); box-shadow:-8px 0 40px rgba(0,0,0,0.4); z-index:51; transform:translateX(100%); transition:transform 200ms ease-out; display:flex; flex-direction:column; overflow:hidden; }
    #drawer-content { flex:1 1 auto; overflow-y:auto; min-height:0; }
    .detail-drawer.open { transform:translateX(0); }
    .detail-drawer-close { position:absolute; top:var(--space-md); right:var(--space-md); background:none; border:none; color:var(--text-muted); font-size:18px; cursor:pointer; padding:var(--space-xs); border-radius:var(--radius-sm); z-index:1; min-width:44px; min-height:44px; display:inline-flex; align-items:center; justify-content:center; }
    .detail-drawer-close:hover { color:var(--text-primary); background:var(--bg-hover); }
    .drawer-header { padding:var(--space-lg); border-bottom:1px solid var(--border-subtle); }
    .drawer-header-teams { font-size:var(--text-lg); font-weight:700; color:var(--text-primary); }
    .drawer-header-meta { display:flex; align-items:center; gap:var(--space-sm); margin-top:var(--space-xs); flex-wrap:wrap; }
    .drawer-section { padding:var(--space-md) var(--space-lg); border-bottom:1px solid var(--border-subtle); }
    /* FIX 2026-04-06: pin the bet-type tab row (All / ML / Spread / O/U)
       at the top of #drawer-content so the user can switch bet types from
       anywhere while scrolling through Picks & Odds, AI Confidence, Books,
       Context, and Line Movement sections below. Background must be opaque
       so scrolling content passes underneath cleanly. The scroll container
       is #drawer-content (flex:1; overflow-y:auto) — sticky finds it as the
       nearest scrolling ancestor. */
    .drawer-bet-tabs-section { display:block; position:-webkit-sticky; position:sticky; top:0; background:var(--bg-surface); z-index:5; box-shadow:0 2px 8px rgba(0,0,0,0.4); }
    .drawer-section-label { font-size:var(--text-xs); color:var(--text-muted); text-transform:uppercase; letter-spacing:0.06em; margin-bottom:var(--space-sm); font-weight:700; }
    .drawer-odds-grid { display:grid; grid-template-columns:1fr 1fr 1fr; gap:var(--space-sm); }
    .drawer-odds-cell { background:var(--bg-elevated); border-radius:var(--radius-sm); padding:var(--space-sm); text-align:center; border:1px solid var(--border-subtle); }
    .drawer-odds-cell.best { border-color:var(--accent); background:var(--accent-muted); }
    .drawer-odds-val { font-size:var(--text-lg); font-weight:700; font-family:var(--font-mono); color:var(--text-primary); }
    .drawer-odds-label { font-size:var(--text-xs); color:var(--text-muted); margin-top:2px; }
    .drawer-odds-sub { font-size:var(--text-xs); color:var(--text-faint); font-family:var(--font-mono); }
    .drawer-signal-row { display:flex; justify-content:space-between; align-items:center; padding:var(--space-xs) 0; }
    .drawer-signal-name { font-size:var(--text-sm); color:var(--text-secondary); }
    .drawer-signal-value { font-size:var(--text-sm); font-family:var(--font-mono); font-weight:600; }
    .drawer-context-tags { display:flex; flex-wrap:wrap; gap:var(--space-xs); }
    .drawer-context-tag { font-size:var(--text-xs); padding:2px var(--space-sm); border-radius:var(--radius-pill); background:var(--bg-elevated); color:var(--text-secondary); border:1px solid var(--border-subtle); }
    .drawer-bet-tabs { display:flex; gap:2px; margin-bottom:var(--space-sm); }
    .drawer-bet-tab { padding:var(--space-xs) var(--space-md); font-size:var(--text-sm); font-weight:600; color:var(--text-muted); cursor:pointer; border-bottom:2px solid transparent; transition:all var(--transition-fast); }
    .drawer-bet-tab:hover { color:var(--text-secondary); }
    .drawer-bet-tab.active { color:var(--accent); border-bottom-color:var(--accent); }
    .drawer-gauge { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
    .drawer-gauge-label { font-size:var(--text-sm); color:var(--text-muted); min-width:70px; font-weight:500; }
    .drawer-gauge-track { flex:1; height:6px; background:var(--accent-muted); border-radius:3px; overflow:hidden; }
    .drawer-gauge-fill { height:100%; border-radius:3px; }
    .drawer-gauge-score { font-size:var(--text-sm); font-weight:700; min-width:32px; text-align:right; font-family:var(--font-mono); }
    .drawer-gauge-grade { font-size:var(--text-xs); font-weight:600; min-width:55px; }
    .drawer-books-row { display:grid; grid-template-columns:1fr auto auto auto; gap:var(--space-sm); align-items:center; padding:3px 0; font-size:var(--text-sm); border-bottom:1px solid var(--border-subtle); }
    .drawer-books-row:last-child { border-bottom:none; }
    .drawer-books-name { color:var(--text-secondary); font-weight:500; }
    .drawer-books-val { font-family:var(--font-mono); color:var(--text-primary); font-weight:600; text-align:center; min-width:45px; }
    .drawer-books-val.is-best { color:var(--accent); }
    .info-btn {
      width:17px; height:17px; border-radius:50%;
      border:1.5px solid var(--accent); background:var(--accent-muted);
      color:var(--accent); font-size:var(--text-sm); font-weight:700;
      cursor:pointer; display:inline-flex; align-items:center;
      justify-content:center; padding:0; transition:all 0.15s;
    }
    .info-btn:hover { background:var(--accent-muted); color:#fff; }
    /* Pick-history pager. Was inline padding+font-size in app.js, which no
       media query could override; promoted to a class so the phone
       breakpoint can reach it (same reason as .analytics-split-2).
       Colour and cursor stay inline — they depend on hasPrev/hasNext. */
    .pick-history-page-btn {
      padding:3px 10px; font-size:var(--text-sm);
      border-radius:4px; border:1px solid var(--border);
      background:var(--bg-card);
    }

    /* ----------------------------------------------------------------
       Bet Routing Teaser Pill (2026-04-09)
       ---------------------------------------------------------------- */
    .bet-routing-pill {
      display:inline-flex; align-items:center; gap:6px;
      margin-top:4px; padding:3px 10px;
      font-size:var(--text-xs); font-weight:600;
      color:var(--accent); background:var(--accent-muted);
      border:1px dashed var(--accent);
      border-radius:var(--radius-pill);
      cursor:pointer; transition:all 0.15s;
      user-select:none;
    }
    .bet-routing-pill:hover {
      background:var(--accent); color:#0d1117; border-style:solid;
    }
    .bet-routing-pill .pill-soon {
      font-size:12px; font-weight:700;
      padding:1px 5px; border-radius:var(--radius-pill);
      background:rgba(255,255,255,0.2);
      text-transform:uppercase; letter-spacing:0.05em;
    }
    .bet-routing-pill:hover .pill-soon {
      background:rgba(255,255,255,0.3);
    }

/* ── Auth Modal ── */
.auth-modal { max-width:400px; padding:24px 28px; }
.auth-modal-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }
.auth-modal-logo { font-size:18px; font-weight:600; color:var(--text-primary); }
.auth-title { font-size:1.1rem; font-weight:600; margin:8px 0 16px; color:var(--text-primary); }
.auth-form { display:flex; flex-direction:column; gap:6px; }
.auth-label { font-size:13px; font-weight:500; color:var(--text-muted); margin-top:4px; }
.auth-input {
  width:100%; padding:10px 12px;
  background:var(--bg-elevated); border:1px solid var(--border-default);
  border-radius:var(--radius-sm); color:var(--text-primary);
  font-size:15px; font-family:var(--font-sans);
}
.auth-input:focus { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-muted); outline:none; }
.auth-btn {
  margin-top:12px; padding:10px 16px;
  background:var(--accent); color:#0d1117; border:none;
  border-radius:var(--radius-sm); font-size:15px; font-weight:600;
  cursor:pointer; transition:background var(--transition-fast);
}
.auth-btn:hover { background:var(--accent-hover); }
.auth-btn:disabled { opacity:0.5; cursor:not-allowed; }
.auth-switch { text-align:center; margin-top:14px; font-size:14px; color:var(--text-muted); }
.auth-switch a { color:var(--accent); text-decoration:none; margin-left:4px; }
.auth-switch a:hover { text-decoration:underline; }
.auth-error {
  background:rgba(239,68,68,0.1); border:1px solid var(--accent-red);
  border-radius:var(--radius-sm); padding:8px 12px; margin-bottom:8px;
  color:var(--accent-red); font-size:14px;
}
/* Password rules, stated where they can actually be read. Muted like .auth-label
   rather than red like .auth-error: these are requirements up front, not a
   failure. 13px matches .auth-label; line-height because it wraps to two lines
   in the modal's width. */
.auth-help {
  margin:6px 0 0; font-size:13px; line-height:1.45;
  color:var(--text-muted);
}

/* ── User Pill + Menu ── */
.user-pill { position:relative; cursor:pointer; display:flex; align-items:center; gap:6px; }
.tier-badge {
  font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:0.05em;
  padding:2px 6px; border-radius:var(--radius-pill);
}
.tier-badge.free { background:var(--bg-hover); color:var(--text-muted); }
.tier-badge.pro { background:rgba(16,185,129,0.15); color:var(--accent); }
.tier-badge.enterprise { background:rgba(234,179,8,0.15); color:#eab308; }
.user-menu {
  display:none; position:absolute; top:calc(100% + 4px); right:0;
  min-width:140px; background:var(--bg-surface); border:1px solid var(--border-default);
  border-radius:var(--radius-md); box-shadow:0 8px 24px rgba(0,0,0,0.4); z-index:200;
}
.user-menu.open { display:block; }
.user-menu-item {
  padding:8px 14px; font-size:14px; color:var(--text-secondary); cursor:pointer;
}
.user-menu-item:hover { background:var(--bg-hover); color:var(--text-primary); }

/* ── Feedback FAB ── */
.feedback-fab {
  position:fixed; bottom:20px; left:20px; z-index:8000;
  width:44px; height:44px; border-radius:50%;
  /* FIX 2026-07-23: #fff on --accent was 2.54:1 — WCAG 1.4.3 AA fail. Same
     treatment the tutorial play button already uses: dark ink on the green (7.5:1). */
  background:var(--accent); color:#0d1117; border:none;
  font-size:20px; cursor:pointer; box-shadow:0 4px 16px rgba(0,0,0,0.4);
  transition:background var(--transition-fast), transform var(--transition-fast);
}
.feedback-fab:hover { background:var(--accent-hover); transform:scale(1.1); }

/* =========================================
   COMMAND CENTER (2026-04-15)
   ========================================= */

#view-commandcenter {
  color: var(--text-primary);
  font-family: 'IBM Plex Sans', sans-serif;
}
.cc-view-container {
  padding: 0;
  width: 100%;
  box-sizing: border-box;
  flex-direction: column;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
}
/* FIX 2026-07-12 (Batch 2): display lives in a :not(.hidden) rule so the
   .hidden utility hides this container without an !important arms race
   (was display:flex !important + .cc-view-container.hidden counter-rule). */
.cc-view-container:not(.hidden) {
  display: flex;
}

.cc-summary-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 6px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: 6px;
  margin-bottom: 8px;
  flex-shrink: 0;
}

.cc-summary-count {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}

.cc-summary-metrics {
  font-size: 14px;
  color: var(--text-muted);
  font-family: 'IBM Plex Mono', monospace;
}

.cc-refresh-btn {
  background: transparent;
  border: 1px solid var(--border-default);
  color: var(--text-muted);
  padding: 4px 10px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}
.cc-refresh-btn:hover { background: var(--bg-hover); color: var(--text-primary); }

.cc-filter-bar {
  background: var(--bg-base);
  padding: 6px 12px;
  border: 1px solid var(--border-default);
  border-radius: 6px;
  margin-bottom: 8px;
  z-index: 10;
  flex-shrink: 0;
}

.cc-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  padding: 2px 0;
}

.cc-filter-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-muted);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.cc-filter-label select,
.cc-filter-label input[type="number"],
.cc-filter-label input[type="text"] {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
  border-radius: 4px;
  padding: 4px 8px;
  font-size: 14px;
  font-family: inherit;
}

.cc-checkgroup {
  display: inline-flex;
  gap: 8px;
}
.cc-checkgroup label {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 13px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-primary);
  font-weight: 500;
  cursor: pointer;
}

.cc-table-wrap {
  overflow: auto;
  flex: 1 1 0;
  min-height: 0;
  border: 1px solid var(--border-default);
  border-radius: 6px;
  background: var(--bg-surface);
}

.cc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  font-family: 'IBM Plex Mono', monospace;
}

.cc-th {
  text-align: left;
  padding: 10px 12px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: 0.05em;
  border-bottom: 1px solid var(--border-default);
  cursor: pointer;
  user-select: none;
  background: var(--bg-base);
  position: sticky;
  top: 0;
  z-index: 5;
}
.cc-th:hover { color: var(--text-primary); }
.cc-th-active { color: var(--text-primary); }

.cc-row {
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--border-default);
  cursor: pointer;
  transition: background 0.1s ease;
}
.cc-row:hover { background: var(--bg-hover); }
.cc-row td { padding: 8px 12px; vertical-align: middle; }

.cc-row-bet  { border-left-color: var(--accent-green, #10b981); }
.cc-row-lock { border-left-color: #3b82f6; }
.cc-row-lean { border-left-color: var(--accent-amber, #f59e0b); }
.cc-row-noedge { border-left-color: var(--text-faint, #b0b0ba); }

.cc-tier-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
}
.cc-tier-bet  { background: rgba(16,185,129,0.15); color: #10b981; }
.cc-tier-lock { background: rgba(59,130,246,0.15); color: #3b82f6; }
.cc-tier-lean { background: rgba(245,158,11,0.15); color: #f59e0b; }
.cc-tier-noedge { background: var(--bg-base); color: var(--text-faint); }

.cc-ev-positive { color: var(--accent-green, #10b981); font-weight: 600; }
.cc-ev-negative { color: var(--text-muted); }
/* FIX 2026-07-16 same-hole check: phantom (>30pp) EV never renders green */
.cc-ev-suspect { color: var(--accent-amber, #f59e0b); font-weight: 600; }
.cc-row-started { opacity: 0.5; }
.cc-started-chip {
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--text-muted); border: 1px solid var(--border-color, #374151);
  border-radius: 3px; padding: 0 3px; margin-left: 4px; vertical-align: 1px;
}

/* Prob colored relative to breakeven — green = edge exists */
.cc-prob-strong { color: var(--accent-green, #10b981); font-weight: 600; }
.cc-prob-thin { color: var(--accent-amber, #f59e0b); }
.cc-prob-negative { color: var(--text-muted); }

.cc-grade-high   { color: var(--accent-green, #10b981); font-weight: 600; }
.cc-grade-mod    { color: var(--accent-amber, #f59e0b); }
.cc-grade-low    { color: var(--text-muted); }

.cc-empty {
  text-align: center;
  padding: 40px 12px;
  color: var(--text-faint);
  font-style: italic;
  font-family: 'IBM Plex Sans', sans-serif;
}

/* FIX 2026-07-22: the empty state now explains WHY the table is empty
   (see static/js/cc_empty_state.js). The headline is the verdict, the detail
   carries the counts, and the action is the escape hatch. Not italic — this
   is a statement of fact about the board, not a placeholder. */
.cc-empty-headline {
  font-style: normal;
  font-size: var(--text-base, 15px);
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.cc-empty-detail {
  font-style: normal;
  font-size: var(--text-sm, 13px);
  color: var(--text-muted);
  max-width: 62ch;
  margin: 0 auto;
  line-height: 1.5;
}

.cc-empty-action {
  font-style: normal;
  font-family: inherit;
  font-size: var(--text-sm, 13px);
  margin-top: 14px;
  /* 44px min touch target — enforced by tests/test_mobile_touch_targets.py.
     Assert the DECLARATION, not the rendered rect. */
  min-height: 44px;
  padding: 10px 18px;
  cursor: pointer;
  color: var(--text-primary);
  background: transparent;
  border: 1px solid var(--border-default, #333);
  border-radius: 6px;
}

.cc-empty-action:hover {
  border-color: var(--accent-green, #10b981);
  color: var(--accent-green, #10b981);
}

/* The escape hatch is the one control on an empty All Bets table, so a
   fat-finger miss there leaves the user with nothing to do but leave.
   Enumerated in tests/test_slate_touch_targets.py::GUARDED_CONTROLS — the
   sentinel only reads declarations inside a mobile media query. */
@media (max-width: 768px) {
  .cc-empty-action {
    min-height: 44px;
  }
}

.cc-detail-row td {
  padding: 16px 24px;
  background: var(--bg-base);
  border-left: 3px solid var(--accent-muted, #b0b0ba);
}

/* Sports custom dropdown */
.cc-sports-wrap { position: relative; }
.cc-sports-dropdown { position: relative; display: inline-block; }
.cc-sports-btn {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
  border-radius: 4px;
  padding: 4px 12px 4px 8px;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  min-width: 120px;
  text-align: left;
}
.cc-sports-btn:hover { border-color: var(--text-muted); }
.cc-sports-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 100;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: 6px;
  padding: 6px 0;
  margin-top: 4px;
  min-width: 160px;
  max-height: 300px;
  overflow-y: auto;
  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}
.cc-sports-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  font-size: 14px;
  color: var(--text-primary);
  cursor: pointer;
  font-weight: 500;
}
.cc-sports-item:hover { background: var(--bg-hover); }

@media (max-width: 768px) {
  .cc-filter-row { gap: 8px; }
  .cc-checkgroup { flex-wrap: wrap; }
  .cc-th, .cc-row td { padding: 6px 8px; font-size: 13px; }
}

/* FIX 2026-07-12 (Batch 2): phone collapse for the 12-col All Bets table.
   At 390px the full grid needed ~700-800px of two-finger horizontal scroll.
   Keep the 5 decision-driving columns — Matchup(3), Side/Line(5), Odds(7),
   EV(8), Tier(12) — and hide Time(1), Sport(2), Bet(4), Book(6), Prob(9),
   B/E(10), Grade(11). Everything hidden is still shown in the tap-to-expand
   detail row (renderCCRow order pins the indices; detail/empty rows use
   colspan and are excluded via :not([colspan])). */
@media (max-width: 639px) {
  .cc-table thead th:nth-child(1),
  .cc-table thead th:nth-child(2),
  .cc-table thead th:nth-child(4),
  .cc-table thead th:nth-child(6),
  .cc-table thead th:nth-child(9),
  .cc-table thead th:nth-child(10),
  .cc-table thead th:nth-child(11),
  .cc-table tbody td:nth-child(1):not([colspan]),
  .cc-table tbody td:nth-child(2):not([colspan]),
  .cc-table tbody td:nth-child(4):not([colspan]),
  .cc-table tbody td:nth-child(6):not([colspan]),
  .cc-table tbody td:nth-child(9):not([colspan]),
  .cc-table tbody td:nth-child(10):not([colspan]),
  .cc-table tbody td:nth-child(11):not([colspan]) {
    display: none;
  }
}

/* ============================================================
   Cricket (IPL) card elements — Phase 1 Task 16
   ============================================================ */

/* Pitch type badge */
.gd-cricket-pitch-badge {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  text-transform: capitalize;
  letter-spacing: 0.02em;
}
.gd-cricket-pitch-green   { background: rgba(16,185,129,0.18); color: #10b981; }
.gd-cricket-pitch-dusty   { background: rgba(217,119,6,0.18);  color: #d97706; }
.gd-cricket-pitch-flat    { background: rgba(59,130,246,0.18); color: #3b82f6; }
.gd-cricket-pitch-balanced{ background: rgba(107,114,128,0.18);color: var(--text-faint); }
.gd-cricket-pitch-unknown { background: rgba(107,114,128,0.12);color: var(--text-dim); }

/* DLS risk amber chip */
.gd-cricket-dls-chip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  font-weight: 600;
  color: #f59e0b;
  background: rgba(245,158,11,0.15);
  border: 1px solid rgba(245,158,11,0.3);
  border-radius: 4px;
  padding: 2px 6px;
  margin-left: 6px;
  vertical-align: middle;
}

/* ============================================================
   Tennis card elements — Phase 1 Task 13
   ============================================================ */

/* Surface badge */
.gd-tennis-surface-badge {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  text-transform: capitalize;
  letter-spacing: 0.02em;
}
/* Clay — terracotta */
.gd-tennis-surface-clay    { background: rgba(180,83,9,0.18);    color: #b45309; }
/* Hard court — blue */
.gd-tennis-surface-hard    { background: rgba(59,130,246,0.18);  color: #3b82f6; }
/* Grass — green */
.gd-tennis-surface-grass   { background: rgba(16,185,129,0.18);  color: #10b981; }
/* Indoor / carpet — purple */
.gd-tennis-surface-indoor  { background: rgba(139,92,246,0.18);  color: #8b5cf6; }
/* Unknown fallback */
.gd-tennis-surface-unknown { background: rgba(107,114,128,0.12); color: var(--text-dim); }

/* ==========================================================================
   UFC / MMA card badges — Phase 1 Task 13
   ========================================================================== */

/* Weight class badge — replaces "SPREAD" column in UFC cards */
.gd-ufc-weight-class {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  background: rgba(212, 175, 55, 0.15);
  color: #d4af37;
  border: 1px solid rgba(212, 175, 55, 0.30);
}

/* Title fight highlights the weight class in a brighter accent */
.gd-ufc-weight-class.title-fight {
  background: rgba(212, 175, 55, 0.28);
  border-color: rgba(212, 175, 55, 0.55);
}

/* Rounds O/U badge — replaces "O/U" column in UFC cards */
.gd-ufc-rounds {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: 600;
  background: rgba(99, 102, 241, 0.12);
  color: #818cf8;
  border: 1px solid rgba(99, 102, 241, 0.25);
  white-space: nowrap;
}

/* Cross-region book dispersion panel — Phase 2 Task 9 */
.gd-dispersion-panel {
  font-size: var(--text-sm);
}
.gd-dispersion-book-row {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 3px 0;
  border-bottom: 1px solid var(--border-default);
  font-size: var(--text-sm);
}
.gd-dispersion-book-row:last-child { border-bottom: none; }
.gd-dispersion-book-name {
  flex: 1;
  color: var(--text-secondary);
  font-weight: 500;
  min-width: 100px;
}
.gd-dispersion-book-prob {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  white-space: nowrap;
}
.gd-dispersion-outlier .gd-dispersion-book-name {
  color: #f59e0b;
}
.gd-dispersion-outlier {
  background: rgba(245,158,11,0.07);
  border-radius: 4px;
  padding-left: 4px;
  padding-right: 4px;
}

/* Synthetic totals — Phase 2 Task 8 */
.gd-synthetic-badge {
  display: inline-block;
  background: #7c3aed;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 4px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin-left: 8px;
  vertical-align: middle;
  cursor: help;
}
.gd-synthetic-row {
  background: rgba(124,58,237,0.06);
  border: 1px solid rgba(124,58,237,0.18);
  border-radius: 6px;
  padding: 10px 14px;
}

/* ── Mobile input zoom-prevention (iOS Safari zooms on focus when input <16px) ──
   Placed at end of file so it overrides every earlier input rule via source order.
   Targets each app input class explicitly to keep specificity equal-or-greater. */
@media (max-width: 639px) {
  .bankroll-pill .bankroll-input,
  .top-nav-dropdown input[type="number"],
  .sidebar-control input[type="number"],
  .sidebar-control input[type="text"],
  .ref-search-input,
  .auth-input,
  .cc-filter-label select,
  .cc-filter-label input[type="number"],
  .cc-filter-label input[type="text"],
  /* FIX 2026-08-11: the Analytics page-size select renders at --text-sm
     (13px) via .analytics-filter-pill and zoomed the viewport on focus.
     Qualified with `select` so it beats the .analytics-filter-pill rule
     (0,1,1 vs 0,1,0) — an unqualified .analytics-filter-pill here would tie
     and lose nothing, but would also restyle the pill BUTTONS, which are not
     focusable text controls and must keep their compact size. */
  select.analytics-filter-pill {
    font-size: 16px;
  }
}

/* WCAG 2.5.5 touch targets — 2026-08-11 picks-page sweep (All Bets,
   Analytics, Props). Measured at 390x844: every failure was HEIGHT, never
   width, because these controls were sized for a mouse. End of file so they
   win on source order. Guarded by tests/test_slate_touch_targets.py. */
@media (max-width: 639px) {
  /* Buttons and label rows: centre the existing content in a 44px box. */
  .cc-checkgroup label,
  .cc-sports-btn,
  .cc-refresh-btn,
  .analytics-filter-pill,
  .pick-history-page-btn,
  .props-sport-pill,
  .props-category-pill,
  .props-sgp-toggle {
    min-height: 44px;
    /* WCAG 2.5.5 is 44 in BOTH axes. Height was the common failure, but the
       short labels are narrow too: measured after the height fix,
       .cc-refresh-btn was 35 wide, the "ML" bet-type label 40.3, and the
       "All" clv/cal tabs 40.5. */
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Form controls get height only. `display:inline-flex` on a <select>
     fights the native control's own rendering, so it is not set here. */
  .cc-filter-label select,
  .cc-filter-label input[type="number"],
  .cc-filter-label input[type="text"] {
    min-height: 44px;
  }

  /* .info-btn is a 17x17 dot INLINE inside chart headings — 22 of them. A
     44px box would reflow every heading, so grow the TARGET, not the
     control: an absolutely-positioned ::after contributes no layout.
     17 + 2*14 = 45px. (accessibility-audit skill: expand the hit area with
     padding or a pseudo-element when the visual design needs to stay small.) */
  .info-btn { position: relative; }
  .info-btn::after {
    content: "";
    position: absolute;
    inset: -14px;
  }
}

/* ── Mobile game-card layout (<640px) ──
   Desktop: .game-card-row is a flex row with .game-card fixed at 500px + .ls-box (line-shopping)
   side-by-side. At mobile width the 500px overflows the 390px viewport; .main-content has
   overflow:hidden so the overflow is silently CLIPPED (right half of every card is cut off
   without horizontal scroll appearing). Fix: stack vertically and let .game-card fill width.
   Also collapse .ls-box's 2-col grid to single-column so the line-shopping cards are readable.
   Also: .sidebar is already display:none at <1024px (line ~837), but .app-layout's grid template
   still allocates 180px to the empty column — collapse the sidebar column at mobile so .main-content
   actually gets the full viewport width. */
@media (max-width: 639px) {
  .app-layout { grid-template-columns: 1fr; }
  .game-card-row { flex-direction: column; }
  .game-card-row .game-card { flex: 1 1 auto; width: 100%; max-width: 100%; }
  .ls-box { grid-template-columns: 1fr; }
}

/* ── 100vh → 100dvh upgrade (iOS Safari URL-bar-collapse fix) ──
   100vh on iOS includes the URL bar's space. When the bar collapses on scroll, content
   jumps. 100dvh (dynamic viewport height) tracks the actual visible area. Wrapped in
   @supports so older browsers fall through to the original 100vh rules unchanged. */
@supports (height: 100dvh) {
  .app-layout { min-height: 100dvh; }
  .sidebar { height: calc(100dvh - 56px); }
  .main-content { height: calc(100dvh - 56px); }
  .app-layout-gameview { min-height: 100dvh; }
  .game-strip { height: 100dvh; }
  .game-dashboard { height: 100dvh; }
  @media (max-width: 639px) {
    .main-content { height: calc(100dvh - 56px - 64px - env(safe-area-inset-bottom)); }
  }
}

/* ── Mobile detail drawer (<640px) ──
   Desktop: 420px-wide right-side drawer. At 390px viewport that overflows by 30px,
   AND the drawer's bottom:0 sits BEHIND the new bottom-nav (z-index 51 vs 100), so
   the bottom 64px of drawer content is hidden. Fix: full-width drawer at mobile,
   stop above the bottom-nav. Slide-from-right animation preserved. */
@media (max-width: 639px) {
  /* 65px = 64 (bottom-nav-inner) + 1 (bottom-nav border-top) */
  .detail-drawer { width: 100%; left: 0; right: 0; bottom: calc(65px + env(safe-area-inset-bottom)); border-left: none; }
}

/* ============================================================
   UI cleanup Batch 2 (2026-07-12) — component classes extracted
   from inline style="" scaffolding in index.html. Values are
   verbatim from the inline originals unless commented.
   ============================================================ */

/* Modal size modifiers (were per-modal inline max-width overrides) */
.modal--sm { max-width: 420px; }
.modal--md { max-width: 520px; }
.modal--lg { max-width: 720px; }
.modal--xl { max-width: 900px; }
/* Modal header row: title left, close button right */
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.modal-head h2 { margin: 0; font-size: 1.05rem; }

/* Prediction-markets (Polymarket / Kalshi) panels */
.pm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 1023px) { .pm-grid { grid-template-columns: 1fr; } }
.pm-panel { background: var(--bg-card); border: 1px solid var(--border-default); border-radius: var(--radius-lg); overflow: hidden; }
.pm-panel-head { padding: 16px; border-bottom: 1px solid var(--border-subtle); }
.pm-panel-head .status-line { margin-top: 8px; }
.pm-panel-title-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pm-panel-title-row h3 { margin: 0; font-size: var(--text-lg); color: var(--text-primary); font-weight: 700; }
.pm-panel-badge { font-size: var(--text-xs); padding: 2px 8px; border-radius: var(--radius-pill); font-weight: 600; }
.pm-panel-badge--crypto { background: var(--accent-muted); color: var(--accent); }
.pm-panel-badge--usd { background: var(--accent-green-bg); color: var(--ev-pos); }
.pm-panel-meta { font-size: var(--text-sm); color: var(--text-muted); }
.pm-panel-count { font-size: var(--text-sm); color: var(--text-faint); }
.pm-panel-push { margin-left: auto; }
.pm-panel-desc { margin: 0; font-size: var(--text-sm); color: var(--text-muted); line-height: 1.5; }
.pm-panel-scroll { overflow-x: auto; }

/* Bet-routing teaser modal internals.
   NOTE: --accent-blue-bg is not a defined token — the original inline style
   referenced it too, so the badge background has always resolved transparent.
   Kept verbatim to preserve behavior; candidate for a real token later. */
.feature-badge { display: inline-block; font-size: var(--text-xs); font-weight: 700; color: var(--accent-blue); background: var(--accent-blue-bg); border: 1px solid var(--accent-blue); padding: 2px 8px; border-radius: var(--radius-pill); text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 14px; }
.feature-copy { font-size: var(--text-base); color: var(--text-secondary); line-height: 1.5; margin: 0 0 14px; }
.feature-list { list-style: none; padding: 0; margin: 0 0 18px; font-size: var(--text-base); color: var(--text-secondary); }
.feature-list li { margin: 6px 0; display: flex; align-items: flex-start; gap: 8px; }
.feature-check { color: var(--accent); font-weight: 700; }
.br-label { display: block; font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
.br-input { width: 100%; padding: 9px 12px; font-size: var(--text-base); border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-input, var(--bg-card)); color: var(--text-primary); box-sizing: border-box; }
.br-submit { margin-top: 10px; width: 100%; padding: 10px 14px; font-size: var(--text-base); font-weight: 600; background: var(--accent-blue); color: white; border: none; border-radius: var(--radius-md); cursor: pointer; }
.br-status { margin-top: 8px; font-size: var(--text-sm); min-height: 18px; }
.br-footnote { font-size: var(--text-xs); color: var(--text-muted); margin: 14px 0 0; line-height: 1.4; }

/* Props Scanner header + scroll container (were inline on #view-props kids) */
.props-header { z-index: 20; background: var(--bg-base); padding: var(--space-sm) var(--space-lg); display: flex; align-items: center; gap: var(--space-lg); flex-wrap: wrap; border-bottom: 1px solid var(--border-subtle); flex-shrink: 0; }
.props-title { margin: 0; font-size: var(--text-lg); font-weight: 700; color: var(--text-primary); }
.props-sport-pills { display: flex; gap: 2px; }
.props-scroll { padding: var(--space-sm) var(--space-lg) var(--space-lg); flex: 1 1 0; min-height: 0; overflow-y: auto; }
.props-status-line { margin-bottom: var(--space-sm); color: var(--text-muted); font-size: var(--text-sm); }
.props-games { display: flex; flex-direction: column; gap: var(--space-sm); }

/* Steam modal chart box */
.steam-chart-box { height: 240px; position: relative; }

/* ===== Reduced motion — WCAG 2.3.3 / motion sensitivity (FIX 2026-07-18) =====
   Nothing respected the OS "reduce motion" setting, so the infinite loops
   (taglineGlow, livePulse on live games, steamPulse, spinners) ran non-stop for
   everyone. Neutralize CSS animations + transitions for users who opt out;
   unchanged for everyone else. Canonical reset (accessibility-audit skill). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Slate drilldown Context panel (2026-07-22) — injuries, weather, officials,
   fatigue, prediction markets. This data shipped to the browser for months
   with no screen rendering it: the display lived on the legacy Game Board,
   hidden 2026-07-18, and the parity check never listed context.
   See static/js/slate_context.js. */
.slate-ctx {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border-left: 3px solid var(--accent-blue, #3b82f6);
  border-radius: 6px;
}

/* Signal Stack — the complete weighted stack behind the consensus number.
   Sits above Edge math; mirrors the Context panel chrome but keeps its own
   green accent so "our signals" reads apart from "external context". */
.slate-sigstack {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border-left: 3px solid var(--slate-green, #22c55e);
  border-radius: 6px;
}

.slate-ss-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
/* FIX 2026-07-24: a global th nowrap kept team-name headers on one line, so
   the table's min-content width (442px) overflowed the 312px takeover body
   at 390px viewport and clipped the Weight column off-screen. Headers wrap;
   the scroll wrapper below is the safety net for extreme names. */
.slate-ss-scroll { overflow-x: auto; }
.slate-ss-table th {
  text-align: right;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-muted);
  padding: 3px 6px;
  border-bottom: 1px solid var(--border-subtle);
  white-space: normal;
  overflow-wrap: break-word;
}
.slate-ss-table th:first-child { text-align: left; }
.slate-ss-table td {
  padding: 3px 6px;
  text-align: right;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  border-bottom: 1px solid var(--border-subtle);
}
.slate-ss-table td:first-child {
  text-align: left;
  font-family: inherit;
}
.slate-ss-pick { font-weight: 700; color: var(--text-primary); }
.slate-ss-wt { color: var(--text-faint); }
.slate-ss-consensus td {
  font-weight: 700;
  color: var(--text-primary);
  border-top: 2px solid var(--border-default);
}

/* FIX 2026-07-24 (desktop review): unconstrained, the panel stretched to the
   full drilldown width — 1149px at a 1280 viewport — leaving ~280px of dead
   space between a signal's name and its number, and shoving the advanced
   rows' team/prob pair against the far right edge. Sharps scan DOWN a number
   column; a stretched data table is the classic mobile-styles-let-loose tell
   (OddsJam and Unabated both cap theirs). 720px also holds the explanation
   prose to a readable measure. No effect on mobile — the container is
   already narrower. */
.slate-ss-scroll,
.slate-ss-footnote,
.slate-ss-advanced,
.slate-ss-ai { max-width: 720px; }

.slate-ss-footnote {
  margin-top: 4px;
  font-size: var(--text-xs);
  color: var(--text-faint);
  line-height: 1.4;
}

.slate-ss-advanced, .slate-ss-ai { margin-top: 10px; }
.slate-ss-count {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-muted);
}

.slate-ss-sig {
  display: grid;
  grid-template-columns: 1fr auto 52px;
  gap: 4px 8px;
  padding: 3px 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
  align-items: baseline;
}
.slate-ss-sig--unavail { opacity: 0.55; }
.slate-ss-sig-name { color: var(--text-secondary); }
.slate-ss-sig-wt { color: var(--text-faint); font-size: var(--text-xs); }
.slate-ss-sig-favor { color: var(--text-primary); font-weight: 600; text-align: right; }
.slate-ss-sig-prob {
  color: var(--text-secondary);
  font-family: var(--font-mono);
  text-align: right;
}
.slate-ss-sig-explain {
  grid-column: 1 / -1;
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.4;
}

.slate-ctx-head {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--text-primary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 8px;
}

.slate-ctx-section { margin-bottom: 10px; }
.slate-ctx-section:last-child { margin-bottom: 0; }

.slate-ctx-label {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--accent-blue, #3b82f6);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}

/* The priced impact. Amber by default, red past 2pp — a 4pp injury swing is
   the single biggest thing on this panel and must not read as a footnote. */
.slate-ctx-impact {
  margin-left: 8px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--accent-amber, #f59e0b);
}
.slate-ctx-impact--severe { color: var(--ev-neg, #ef4444); }

.slate-ctx-line,
.slate-ctx-note {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}
.slate-ctx-note { color: var(--text-muted); font-style: italic; }

.slate-ctx-player {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: baseline;
  font-size: var(--text-sm);
  padding: 2px 0;
  color: var(--text-secondary);
}
.slate-ctx-player-name { font-weight: 600; color: var(--text-primary); }
.slate-ctx-player-team { color: var(--text-faint); font-size: var(--text-xs); }
.slate-ctx-status { font-weight: 600; color: var(--accent-amber, #f59e0b); }
.slate-ctx-status--out { color: var(--ev-neg, #ef4444); }

/* 50 rows is real evidence, but it cannot bury the edge math above it. */
.slate-ctx-details { margin-top: 6px; }
.slate-ctx-details summary {
  font-size: var(--text-sm);
  color: var(--text-muted);
  cursor: pointer;
  /* 44px touch target — enforced by tests/test_slate_touch_targets.py.
     Assert the CSS DECLARATION, not the rendered rect. */
  min-height: 44px;
  display: flex;
  align-items: center;
}
.slate-ctx-report { max-height: 220px; overflow-y: auto; margin-top: 4px; }

@media (max-width: 768px) {
  .slate-ctx-details summary { min-height: 44px; }
}

/* ── Mobile/tablet shell: ONE scroll region, not two (2026-07-25) ──
   `.app-layout` is a grid. At <=1024px it collapses to a single column
   (main.css:956), so `.sidebar` stops being a column BESIDE `.main-content`
   and becomes a ~302px sport-chip-strip ROW ABOVE it. But `.main-content`
   kept `height: calc(100dvh - 56px [- 64px])` — a formula written for the
   desktop case where it starts directly under the 56px top nav.

   Measured on prod at 390x844 before this fix:
     .main-content top = 358 (56 nav + 302 stacked strip), height = 724
     358 + 724 = 1082 = document.scrollHeight EXACTLY
     1082 - 844 = 238 = exactly what the window scrolled
   That outer scrollbar plus `#view-premium`'s own overflow-y:auto gave two
   nested scroll regions, and letterboxed the Slate drilldown into a 421px
   window on an 844px phone.

   Fix: below the grid-collapse breakpoint, stop deriving the pane height
   from the viewport and let the PAGE scroll. Range is <=1024px to match the
   grid collapse — scoping it to 639px would leave 640-1024px broken
   (verified 768x1024 pre-fix: window scrolled 302px AND pane scrolled
   2379px), the same trap main.css:948 documents them hitting before.

   Verified at 390px that no view container collapses once the pane height
   is released: premium 3894px, pmdebug 4373, analytics 6545, commandcenter
   398, props 383, cricket 217 — and zero nested scrollers remain in the
   shell (component-level table scrollers are intentional and untouched). */
@media (max-width: 1024px) {
  .main-content { height: auto; overflow: visible; }
  #view-premium, #view-pmdebug, #view-analytics,
  #view-commandcenter, #cricket-view, #ufc-view,
  #view-props.view-props-flex { flex: 0 1 auto; min-height: 0; overflow: visible; }
  .props-scroll { flex: 0 1 auto; min-height: 0; overflow-y: visible; }
  /* The top nav is position:fixed at 56px. With the page scrolling, a
     sticky child would otherwise pin UNDER it instead of below it. */
  #proof-sticky { top: 56px; }
}

/* `.bottom-nav` is position:fixed and display:block ONLY at <=639px
   (main.css:124). The page now scrolls beneath it, so reserve its height
   (64px inner + 1px border) plus the safe-area inset. */
@media (max-width: 639px) {
  .main-content { padding-bottom: calc(65px + env(safe-area-inset-bottom)); }
}

/* ============================================================
   GAMES BOARD — PER-MARKET ODDS BOX (2026-08-05)
   Markup: renderOddsBoxCard() in static/js/app.js.
   Nothing here may drop below 12px (tests/test_type_scale_floor.py), and
   anything carrying meaning uses --text-primary/--text-secondary rather than
   --text-faint — grey text was called out as hard to read.
   ============================================================ */
.ob-card { background:var(--bg-surface); border:1px solid var(--border); border-radius:var(--radius-lg); margin-bottom:10px; overflow:hidden; }
.ob-card-live { border-color:rgba(248,113,113,0.35); }
.ob-head { padding:10px 14px; border-bottom:1px solid var(--border); font-size:var(--text-base); font-weight:600; color:var(--text-primary); }
.ob-head .ob-at { color:var(--text-muted); font-weight:400; margin:0 2px; }
.ob-live-chip { font-family:var(--font-mono); font-size:var(--text-xs); font-weight:700; color:var(--ev-neg); text-transform:uppercase; letter-spacing:0.04em; margin-left:8px; }
.ob-locked { padding:14px; font-size:var(--text-sm); color:var(--text-primary); text-align:center; }

/* overflow-x is a floor, not the plan — the mobile block below makes the grid
   fit 375px outright, because an element that scrolls inside a container still
   reports a right edge past the viewport. */
.ob-box-wrap { overflow-x:auto; }
.ob-box { width:100%; border-collapse:collapse; }
.ob-box thead th { font-family:var(--font-mono); font-size:var(--text-xs); font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-secondary); padding:8px; text-align:center; }
.ob-box tr.ob-subhead th { font-family:var(--font-mono); font-size:var(--text-xs); font-weight:400; letter-spacing:0; text-transform:none; color:var(--text-muted); padding:0 8px 8px; border-bottom:1px solid var(--border); }
/* Each word wears the colour of the value it names — the only in-place
   explanation of what the green number is. Keep these in step with
   .ob-line/.ob-price/.ob-prob below or the legend starts lying. */
.ob-k-line, .ob-k-price { color:var(--text-primary); }
.ob-k-prob { color:var(--accent); font-weight:700; }
.ob-box td { padding:7px 8px; text-align:center; border-bottom:1px solid var(--border-subtle); }
.ob-box tbody tr:last-child td, .ob-box tbody tr:last-child .ob-team { border-bottom:none; }
.ob-team { text-align:left; padding:7px 8px 7px 14px; font-size:var(--text-base); font-weight:600; color:var(--text-primary); border-bottom:1px solid var(--border-subtle); }
.ob-cell { display:inline-flex; flex-direction:column; align-items:center; gap:1px; min-width:76px; padding:4px 8px; border:1px solid transparent; border-radius:var(--radius-sm); }
.ob-cell-pick { background:var(--accent-green-bg); border-color:var(--ev-pos); }
.ob-line { font-family:var(--font-mono); font-size:var(--text-base); font-weight:700; color:var(--text-primary); line-height:1.25; }
.ob-price { font-family:var(--font-mono); font-size:var(--text-xs); color:var(--text-primary); line-height:1.25; }
.ob-prob { font-family:var(--font-mono); font-size:var(--text-sm); font-weight:700; color:var(--accent); line-height:1.25; }

.ob-strip { padding:8px 14px; border-top:1px solid var(--border-subtle); font-size:var(--text-base); color:var(--text-primary); }
.ob-strip-k { font-family:var(--font-mono); font-size:var(--text-xs); font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-secondary); margin-right:8px; }
.ob-pct { font-family:var(--font-mono); font-weight:700; color:var(--accent); }
.ob-strip-bubble .ob-pct { color:var(--accent-amber); }
/* 'info' is the common case (an Over/Under play takes no side on the winner);
   only a genuine conflict earns amber. */
.ob-note { font-size:var(--text-sm); }
/* --text-secondary, not --text-muted: this note is meaning-carrying copy ("takes
   no side on the winner"), and the block header above requires the readable rung
   for anything carrying meaning. It is the COMMON case on MLB, so it must not be
   the least legible text on the card. */
.ob-note-info { color:var(--text-secondary); }
.ob-note-warn { color:var(--accent-amber); }

/* The card opens its own drilldown panel (2026-08-07). */
.ob-card[role="button"] { cursor:pointer; }
.ob-card[role="button"]:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* [hidden] must beat any display rule on this class — the same specificity
   trap that made #game-cards-container[hidden] inert on 2026-08-06. Verified
   2026-08-07: no other .ob-panel/.ob-card rule sets `display` at all, so
   nothing here is competing for it. */
.ob-panel[hidden] { display:none; }
.ob-panel { border-top:1px solid var(--border); padding:12px 14px; }

@media (max-width: 768px) {
  .ob-box { table-layout:fixed; }
  .ob-box thead th, .ob-box td { padding:6px 3px; }
  .ob-box thead th:first-child { width:29%; }
  .ob-head, .ob-strip, .ob-locked { padding-left:10px; padding-right:10px; }
  .ob-team { padding:6px 4px 6px 10px; font-size:var(--text-sm); white-space:normal; overflow-wrap:anywhere; }
  .ob-cell { min-width:0; width:100%; padding:4px 2px; }
  .ob-line, .ob-price, .ob-prob { max-width:100%; overflow:hidden; text-overflow:ellipsis; }
  /* FIX 2026-08-05: the GLOBAL `th { white-space:nowrap }` (main.css:401) also
     catches this sub-header, so "line · price · win prob" was held on one line
     and forced the table to 422px inside a 325px phone column — pushing the
     Over/Under column, MLB's only unsuppressed market, off-screen by default.
     Letting it wrap brings the table to 333px. Same global rule was already
     fixed once for team-name headers (see the note at main.css:1999). The
     sub-header is the only in-place explanation of what the green number
     means, so it wraps rather than being shortened or dropped. */
  .ob-box tr.ob-subhead th { white-space:normal; line-height:1.3; }
}

/* ============================================================
   GAMES BOARD — DRILLDOWN PANEL (2026-08-07)
   Markup: renderOddsBoxPanel() in static/js/app.js.
   Same floor as the odds box above: nothing may drop below 12px
   (tests/test_type_scale_floor.py).
   ============================================================ */
.ob-panel-stamp { font-family:var(--font-mono); font-size:12px; color:var(--text-secondary); margin-bottom:10px; }
.ob-panel-stamp.ob-stale { color:var(--accent-amber); }
.ob-provisional { color:var(--accent-amber); font-weight:600; }
.ob-panel-sec { margin-bottom:14px; }
.ob-panel-sec h4 { font-family:var(--font-mono); font-size:12px; letter-spacing:.08em; text-transform:uppercase; color:var(--text-secondary); margin:0 0 6px; }
.ob-sig-table { width:100%; border-collapse:collapse; font-size:13px; }
.ob-sig-table th { text-align:left; font-size:12px; color:var(--text-secondary); padding:3px 6px; }
.ob-sig-table td { padding:3px 6px; border-top:1px solid var(--border-subtle); color:var(--text-primary); vertical-align:top; }
.ob-sig-dark { opacity:.65; }
.ob-sig-dark .ob-sig-w { color:var(--accent-amber); font-weight:700; }
.ob-sig-w { font-family:var(--font-mono); white-space:nowrap; }
.ob-nominal { color:var(--text-secondary); font-size:12px; }
.ob-absorbed { color:var(--accent); font-size:12px; }
.ob-agree { color:var(--accent); }
.ob-disagree { color:var(--accent-amber); }
.ob-ou-comp { list-style:none; padding:0; margin:4px 0 0; display:flex; flex-wrap:wrap; gap:10px; font-size:13px; }
.ob-none { color:var(--text-secondary); font-size:13px; }

/* Verdict strip (2026-08-08) — markup: renderVerdictStrip() in app.js.
   Same 12px floor as everything else here (tests/test_type_scale_floor.py). */
.ob-verdict { display:flex; justify-content:space-between; align-items:center;
  gap:8px; flex-wrap:wrap; padding:7px 10px; border-top:1px solid var(--border);
  font-size:13px; color:var(--text-secondary); }
.ob-verdict-play { border-top-color:var(--accent); color:var(--text-primary); }
.ob-verdict-ev { color:var(--accent); font-weight:600; }
.ob-verdict-none { color:var(--text-secondary); }
.ob-verdict-go { font-size:12px; color:var(--text-secondary); white-space:nowrap; }
@media (max-width:768px) {
  .ob-sig-table { font-size:12px; }
  .ob-panel { padding:10px; }
}
