/* ── Fonts: self-hosted (#417) ───────────────────────────────────────────────
   This file used to open with @import url('https://fonts.googleapis.com/...') — which is why
   removing the <link> from login.html did NOT make the login path third-party-free, and my
   claim that it did was wrong. TC-08 only read the HTML and never looked here.

   Now all four faces ship from /assets/fonts. That kills a third-party request on every page
   (a privacy leak, and a render-blocking dependency on someone else's uptime), and an @import
   is the worst way to load a font besides: the browser cannot even discover it until this
   stylesheet has downloaded and parsed.

   All four are SIL Open Font License, which explicitly permits self-hosting. Each file is the
   VARIABLE font — one file covers every weight, which is why there are 4 files and not 12
   (Google serves the same bytes for :wght@400 and :wght@700; they were byte-identical).

   font-display: swap — text paints immediately in the fallback and re-renders when the face
   arrives. Never invisible, at the cost of a reflow.
   ------------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 800;               /* variable: the whole range from one file */
  font-display: swap;
  src: url('/assets/fonts/inter.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url('/assets/fonts/dmsans-var.woff2') format('woff2');
}
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/montserrat-var.woff2') format('woff2');
}
@font-face {
  font-family: 'Great Vibes';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/greatvibes.woff2') format('woff2');
}

* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  /* #234 shared chip metrics — EVERY badge/chip family on the runner card consumes
     these so heights align on a shared row (colour/border stay per-family). */
  --chip-h: 20px;
  /* #235 single source for page gutters — consumed by .page-main (+ 640px override). */
  /* #239 phase 1: ALL white overlays route through this base triplet, so a future
     light theme flips ONE knob (e.g. to 16,18,24) instead of hunting 39 literals. */
  --brand-vo-green: #3fe9ad;          /* the VectorOdds mark — a BRAND, so it is the same on */
  --brand-vo-green-2: #2fcf98;        /* every theme. Declared once here, not typed per page. */
  --brand-vo-purple: #4b3ff0;
  --brand-vo-purple-2: #6d5cff;
  /* #417 The exchange's back/lay convention: blue is BACK, pink is LAY, on every betting
     exchange there is. Like the rug colours, that is a fact about the domain — a theme that
     recoloured them would be lying to the user — so they are declared once and inherited by
     every palette rather than typed into the screener. */
  --exch-back: #1e88e5;
  --exch-back-rgb: 30, 136, 229;
  --exch-lay: #e53935;
  --exch-lay-rgb: 229, 57, 53;
  /* the modal scrim: it DIMS the page, so it is black on a light theme too */
  --scrim-rgb: 0, 0, 0;
  --video-mat: #000;                  /* letterbox behind <video> — black by convention, not by theme */
  --overlay-rgb: 255, 255, 255;
  --page-pad-x: 1rem;
  --page-pad-x-m: 0.55rem;
  --chip-fs: var(--fs-2xs);
  --chip-px: 0.4rem;
  --bg: #101218;
  --bg-card: #191c26;
  --bg-hover: #1f2330;
  --bg-input: #191c26;
  --border: #282d3e;
  --border-light: #333849;
  --bg-light: #3b4152;
  /* Page backdrop behind the content panels — kept separate from --bg-light so
     it can be tuned without affecting chips that use --bg-light. */
  --bg-page: var(--bg);
  --text: #e8e9ed;
  /* #133 grey text lightened site-wide for easier reading (was b0b3c0 / 9da1b8 / 767a94). */
  --text-mid: #c2c5d2;
  --text-muted: #b4b8cc;
  --text-dim: #9296b0;
  --accent: #7c6cf0;
  --accent-btn: #6a5ad4;  /* a11y (#168): accent shade for fills BEHIND WHITE TEXT — clears AA
                             (5.22:1). Plain --accent (#7c6cf0) is only 3.99:1 and stays for
                             text-less fills (bars, toggles, dots) + accent-coloured text. */
  /* #416 Text ON --accent-btn. White works here because the accent is a deep purple. A LIGHT
     accent (the mint CTA in the indigo trial) needs DARK text — every theme sets its own. */
  --on-accent: #ffffff;
  --accent-light: #b0a4ff;
  --win: #f5c542;
  --win-bg: rgba(245, 197, 66, 0.07);
  --ew: #2dd4bf;
  --ew-bg: rgba(45, 212, 191, 0.07);
  --avoid: #6b7280;
  --avoid-bg: rgba(107, 114, 128, 0.05);
  --danger: #f87171;
  --green: #34d399;
  /* Race-type colour coding — single source of truth, reused site-wide. */
  --type-horse: var(--accent);
  --type-grey: var(--green);
  --type-harness: var(--win);
  --radius: 10px;
  --header-h: 89px; /* two equal rows: top bar + next-to-jump (44px each + 1px divider) */
  --race-pills-h: 58px; /* #301 approx height of the sticky meet-nav pills row (mobile) — the hero stacks below it */
  --header-top-h: 44px;
  --gutter: 0px;
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  /* #417 --font-head lets a theme pair a DISPLAY face with its body face — the classic move
     #148 had no way to express, since one --font meant one voice. It defaults to --font, so
     every theme that does not set it looks exactly as it did: this is a new capability, not a
     restyle. Consumed by h1–h6/.text-h*/.section-title. */
  --font-head: var(--font);
  /* #148 One font throughout — --mono now aliases --font (was a separate monospace).
     Numbers keep column alignment via font-variant-numeric on .mono/[--mono] users.
     The ONLY exception is the Tulloch's Tips heading (Great Vibes, see .tt-title). */
  --mono: var(--font);
  /* #417 --font-code is the REAL monospace, and it is not a relapse of #148. --mono aliases
     --font, so it is a promise about NUMBER ALIGNMENT (kept via font-variant-numeric), not
     about fixed width. Log output and stack traces need actual fixed width — their columns
     are load-bearing — and admin-logs.html had to hardcode a stack because no token said
     "monospace" any more. One place to change it, and a theme can still swap it. */
  --font-code: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* #148 Consolidated type scale — 8 named steps (was ~42 ad-hoc rem sizes). Use the
     --fs-* tokens or the h1–h6 / .text-* classes; the ≤640px block below shifts the
     larger steps down for mobile. */
  --fs-h1: 1.5rem;
  --fs-h2: 1.25rem;
  --fs-h3: 1.05rem;
  --fs-h4: 0.9rem;
  --fs-body: 0.85rem;
  --fs-sm: 0.78rem;
  --fs-xs: 0.75rem;   /* a11y (#168): raised legibility floor ~12px — was 0.68rem/10.9px */
  --fs-2xs: 0.7rem;   /* a11y (#168): raised legibility floor ~11px — was 0.6rem/9.6px */
  /* #416 --x-rgb companions. CSS cannot do rgba(var(--win), .12) -- a hex var is not
     three numbers -- so a tint could never follow the theme and every one was hardcoded.
     Derived from this theme's own colours; --overlay-rgb already set the precedent. */
  --accent-rgb:       124, 108, 240;
  --win-rgb:          245, 197, 66;
  --ew-rgb:           45, 212, 191;
  --green-rgb:        52, 211, 153;
  --danger-rgb:       248, 113, 113;
  --text-rgb:         232, 233, 237;
  --avoid-rgb:        107, 114, 128;
  /* #416 Tulloch's Tips carries its own small palette: the card is a premium slab with its
     OWN ground and ink, deliberately not the page's. Every one of these used to be a literal
     (#3a2b8c, rgba(176,164,255)…) so the card looked identical in every theme. */
  --tulloch:      #b0a4ff;            /* the signature: border, glow, crest, accent bar */
  --tulloch-rgb:  176, 164, 255;
  --tulloch-g1:   #3a2b8c;            /* the slab gradient, light -> dark */
  --tulloch-g2:   #241b63;
  --tulloch-g3:   #171833;
  --tulloch-ink:  #e9e5ff;            /* text ON the slab (12.1:1 on g2) */
  --tulloch-well-rgb: 10, 10, 24;   /* the inset wells, a darkening of the slab itself */
  /* #417 chart lines — the bright set: drawn on the DARK ground */
  --chart-1: #3b82f6;  --chart-2: #f97316;  --chart-3: #22c55e;
  --chart-4: #a855f7;  --chart-5: #ef4444;  --chart-6: #14b8a6;
  --brand-betfair: #f59e0b;           /* Betfair's amber — a BRAND, kept recognisable */
  --chart-1-rgb: 59, 130, 246;        /* companion for tints of the info blue */
}

/* #250 responsible-gambling footer — every page, theme-var driven. */
/* #424 site footer — column-driven links + brand, above the compliance strip. */
.site-footer { display: grid; grid-template-columns: minmax(180px, 1fr) 2fr; gap: 1.5rem 2rem; padding: 2rem var(--page-pad-x) 1.5rem; margin-top: 2rem; border-top: 1px solid var(--border); color: var(--text-muted); font-size: var(--fs-xs); }
.sf-brand { display: flex; flex-direction: column; gap: 0.6rem; }
.sf-logo { border-radius: 7px; }
.sf-wordmark { font-weight: 700; color: var(--text-mid); letter-spacing: 0.01em; }
.sf-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1.25rem 1.5rem; }
.sf-heading { margin: 0 0 0.5rem; font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-mid); }
.sf-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.sf-links a { color: var(--text-muted); text-decoration: none; }
.sf-links a:hover { color: var(--text-mid); text-decoration: underline; }
.sf-social { display: flex; gap: 0.75rem; }
.sf-social a { color: var(--text-muted); }
.sf-social a:hover { color: var(--accent); }
@media (max-width: 640px) { .site-footer { grid-template-columns: 1fr; gap: 1.25rem; } }

.rg-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.5rem 0.9rem; padding: 0.8rem var(--page-pad-x) calc(0.8rem + env(safe-area-inset-bottom)); margin-top: 1.5rem; border-top: 1px solid var(--border); font-size: var(--fs-2xs); color: var(--text-muted); text-align: center; }
.rg-footer a { color: var(--text-mid); text-decoration: underline; }
.rg-18 { display: inline-flex; align-items: center; justify-content: center; min-width: 26px; height: 20px; padding: 0 4px; border: 1.5px solid var(--text-muted); border-radius: 50%; font-weight: 800; }
.rg-tagline { font-weight: 700; color: var(--text-mid); text-transform: uppercase; letter-spacing: 0.03em; }
@media (max-width: 640px) { .rg-footer { margin-bottom: 56px; } } /* clear the bottom tabs */

/* #257 Admin-host chrome — a simple, admin-only shell on the dedicated admin host.
   Distinct compact header + a flat admin nav; consumer chrome is not built (these rules
   are belt-and-braces in case a page ships its own copy). Scoped to :root.admin-host so
   normal hosts are untouched. */
:root.admin-host .site-header,
:root.admin-host .bottom-nav,
:root.admin-host .rg-footer,
:root.admin-host .ai-upgrade-strip { display: none !important; }
/* a distinct, businesslike admin bar (tinted from the accent, flatter than the consumer nav) */
:root.admin-host .top-nav {
  background: linear-gradient(180deg, #1a1436, #14112b);
  border-bottom: 2px solid var(--accent);
}
/* a small "ADMIN" tag next to the brand so the environment is unmistakable */
:root.admin-host .tn-brand::after {
  content: "ADMIN"; margin-left: 0.55rem; padding: 0.1rem 0.4rem;
  font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.12em;
  color: var(--accent-light); border: 1px solid var(--accent); border-radius: 4px;
  align-self: center;
}
/* the admin nav is flat + always visible (no consumer curation) */
:root.admin-host .app-shell { padding-top: 0.5rem; }

/* #271 (+ admin cleanup 2026-07-15) Admin chrome = the mobile-style STICKY TOP BAR with the
   VectorOdds brand at EVERY width. Originally these rules were mobile-only (the consumer
   header/bottom bar that open the drawer are hidden on admin pages); the desktop admin nav
   was the consumer left sidebar. Now the same top-bar strip applies on desktop too — one
   admin chrome everywhere. The desktop sidebar rules (body padding-left, hidden brand) are
   neutralised below at higher specificity, so consumer pages are untouched. */
:root.admin-host body { padding-top: 0; padding-left: 0; }
:root.admin-host .top-nav {
  position: sticky; top: 0; left: 0; right: 0; bottom: auto;
  width: 100%; height: auto; max-height: none;
  transform: none !important;            /* never parked off-screen */
  will-change: auto !important;          /* CRITICAL: transform/will-change make .top-nav the
                                            containing block for position:fixed descendants,
                                            trapping the dropdowns inside its overflow clip. */
  border-right: 0; border-bottom: 2px solid var(--accent);
  overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
  z-index: 300; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
:root.admin-host .tn-inner {
  flex-direction: row; align-items: center; height: auto;
  padding: 0.35rem 0.55rem; gap: 0.2rem; flex-wrap: nowrap;
  width: max-content; min-width: 100%;
}
/* the brand stays visible at every width (desktop consumer nav hides it in the sidebar) */
:root.admin-host .top-nav .tn-brand { display: flex; margin: 0 0.4rem 0 0.15rem; flex: 0 0 auto; white-space: nowrap; }
:root.admin-host .top-nav .tn-user-area { display: flex; flex: 0 0 auto; }
:root.admin-host .tn-menu { flex-direction: row; align-items: center; gap: 0.2rem; flex-wrap: nowrap; }
:root.admin-host .tn-dropdown { width: auto; flex: 0 0 auto; }
:root.admin-host .tn-link { width: auto; white-space: nowrap; padding: 0.4rem 0.7rem; }
:root.admin-host .tn-divider { display: none; }          /* dividers make no sense in a row strip */
:root.admin-host .app-shell { padding-top: 0.6rem; }
:root.admin-host .nav-scrim { display: none !important; } /* pinned open → never scrim */
/* Grouped sub-menus in the strip: the strip clips overflow (overflow-x:auto/overflow-y:
   hidden), so absolute menus would be cut off — fixed positioning escapes the clip (no
   transformed ancestor: the strip forces transform:none). auto offsets keep the menu under
   its trigger. */
:root.admin-host .tn-drop-menu { position: fixed; top: auto; left: auto; z-index: 400; max-height: 70vh; overflow-y: auto; }
:root.admin-host .tn-drop-header { display: flex; align-items: center; }

/* #260 18+ age gate (blocking modal) + the account "18+" section. Mobile-first. */
.age-gate-lead { font-size: var(--fs-body); line-height: 1.5; margin: 0 0 1rem; }
.age-gate-lead.age-gate-block { color: #ff9d9d; }
.age-gate-form { display: flex; flex-direction: column; gap: 0.5rem; }
.age-gate-form label { font-size: var(--fs-sm); color: var(--text-mid); }
.age-gate-form input[type="date"] {
  width: 100%; background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 0.55rem 0.65rem;
  font-size: var(--fs-body); margin-bottom: 0.35rem;
}
.age-gate-form input[type="date"]:focus { outline: none; border-color: var(--accent); }
.age-gate-err { color: #ff9d9d; font-size: var(--fs-sm); min-height: 1.1em; }
.age-gate-help { font-size: var(--fs-2xs); color: var(--text-muted); line-height: 1.5; margin: 0.9rem 0 0; }
.age-gate-help a { color: var(--text-mid); text-decoration: underline; }
.acct-age { display: flex; align-items: flex-start; gap: 0.6rem; }
.acct-age input[type="checkbox"] { margin-top: 0.2rem; width: 1.05rem; height: 1.05rem; flex: none; accent-color: var(--accent); }

/* #244 locked-field chip — same metrics as every other chip (#234). */
.locked-field { display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; gap: 0.2rem; border-radius: 5px; border: 1px dashed var(--border-light); color: var(--text-dim); text-decoration: none; font-weight: 700; }
.locked-field:hover { color: var(--accent-light); border-color: var(--accent); }

/* #243 segmented control (UI.segmented) — theme-var driven. */
/* #416 WAS: `inline-flex` + `overflow: hidden`, which silently CLIPPED any option past the
   container width -- the buttons rendered, sat outside the box, and could not be clicked. It
   held 3 short labels so nobody hit it; adding two longer ones (theme trials) made it
   unusable, and the failure is invisible (no scrollbar, no ellipsis -- the option is just gone).
   A row of unknown length must never be `overflow: hidden`.
   max-width + overflow-x keeps the joined-pill look and makes every option reachable at any
   width; overflow-y stays hidden so the children still clip to the radius. */
.ui-seg {
  display: inline-flex; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-card);
  max-width: 100%; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
}
.ui-seg-btn { white-space: nowrap; flex: none; }
.ui-seg-btn { border: 0; background: transparent; color: var(--text-mid); font: inherit; font-size: var(--fs-xs); font-weight: 700; padding: 0.35rem 0.85rem; cursor: pointer; }
.ui-seg-btn + .ui-seg-btn { border-left: 1px solid var(--border); }
.ui-seg-btn.seg-on { background: var(--accent-btn); color: var(--on-accent); }
.ui-seg-btn:not(.seg-on):hover { background: var(--bg-hover); }

/* ── #243 LIGHT THEME ──────────────────────────────────────────────────────────────
   Dark (the :root above) stays the default and is byte-identical without this block.
   theme-boot.js stamps <html data-theme>; Auto = OS preference. Every COLOUR var the
   dark root defines is overridden here (LM-01 test enforces full coverage) so nothing
   falls through as a dark value on a white page. Accent/status hues are re-tinted for
   AA on light backgrounds (the dark-mode neons fail on white). */
:root[data-theme="light"] {
  --overlay-rgb: 16, 18, 24;          /* the #239 knob: overlays become soft darks */
  --bg: #f2f3f7;
  --bg-card: #ffffff;
  --bg-hover: #eceef4;
  --bg-input: #ffffff;
  --border: #d7dae4;
  --border-light: #c6cad8;
  --bg-light: #e2e5ee;
  --bg-page: var(--bg);
  --text: #14161d;
  --text-mid: #3a3e4d;
  --text-muted: #565b70;
  --text-dim: #666b82;            /* 4.75:1 on --bg — AA */
  --accent: #5b4bd6;                  /* deepened for contrast on white (was #7c6cf0) */
  --accent-btn: #5343c8;              /* white-text fills stay ≥AA */
  --on-accent: #ffffff;               /* deep purple accent — white is 6.99:1 */
  --accent-light: #4938b8;            /* "light" accent is a TEXT colour → must darken */
  --win: #9a6d00;                     /* gold as readable text on white (chips keep tints) */
  --win-bg: rgba(154, 109, 0, 0.10);
  --ew: #0f766e;                      /* teal darkened for AA text */
  --ew-bg: rgba(15, 118, 110, 0.08);
  --avoid: #6b7280;
  --avoid-bg: rgba(107, 114, 128, 0.08);
  --danger: #d03838;
  --green: #0c7d54;                   /* success green darkened for AA text */
  --on-status: #ffffff;               /* text on solid win/ew/green fills (deep hues here) */
  /* --type-* alias accent/green/win and follow automatically. */
  /* #416 --x-rgb companions. CSS cannot do rgba(var(--win), .12) -- a hex var is not
     three numbers -- so a tint could never follow the theme and every one was hardcoded.
     Derived from this theme's own colours; --overlay-rgb already set the precedent. */
  --accent-rgb:       91, 75, 214;
  --win-rgb:          154, 109, 0;
  --ew-rgb:           15, 118, 110;
  --green-rgb:        12, 125, 84;
  --danger-rgb:       208, 56, 56;
  --text-rgb:         20, 22, 29;
  --avoid-rgb:        107, 114, 128;
  /* #416 Tulloch's Tips carries its own small palette: the card is a premium slab with its
     OWN ground and ink, deliberately not the page's. Every one of these used to be a literal
     (#3a2b8c, rgba(176,164,255)…) so the card looked identical in every theme. */
  --tulloch:      #b0a4ff;            /* the signature: border, glow, crest, accent bar */
  --tulloch-rgb:  176, 164, 255;
  --tulloch-g1:   #3a2b8c;            /* the slab gradient, light -> dark */
  --tulloch-g2:   #241b63;
  --tulloch-g3:   #171833;
  --tulloch-ink:  #e9e5ff;            /* text ON the slab (12.1:1 on g2) */
  --tulloch-well-rgb: 10, 10, 24;   /* the inset wells, a darkening of the slab itself */
  /* #417 chart lines — the deep set: the same six hues, taken darker so they read on a
     LIGHT ground. Bright #3b82f6 on white is a washed-out line, not a data series. */
  --chart-1: #2563eb;  --chart-2: #ea580c;  --chart-3: #16a34a;
  --chart-4: #9333ea;  --chart-5: #dc2626;  --chart-6: #0d9488;
  --brand-betfair: #b45309;           /* Betfair's amber, darkened to stay visible on white:
  --chart-1-rgb: 37, 99, 235;         /* companion for tints of the info blue */
                                         same hue, legible ground — the brand is still read */
}

/* ── TRIAL: mint/purple theme ────────────────────────────────────────────────
   An opt-in THIRD theme so the palette can be seen on the real site without
   touching dark or light. Switch it in Account -> Appearance, or:
       localStorage.theme = "mint"; location.reload()
   Delete this block and the "mint" case in theme-boot.js to bin the trial.

   The supplied palette was:
       mint #53e3ae · purple #5839fb · bg #f8f9fd · text #1a1638
       purple-light #e8e5ff · white #ffffff
   Its `body { display:flex; justify-content:center; align-items:center;
   min-height:100vh }` is DELIBERATELY not carried over — that centres a single
   card. This app has a fixed header (body has padding-top: var(--header-h)),
   bottom tabs and 23 fixed/sticky rules; centring the body collapses the shell.
   The palette is the idea; the demo's layout is not.

   Every text token below was MEASURED against both surfaces (#f8f9fd and the
   #ffffff card) and clears AA — the same discipline the light palette above
   applies. The two facts that shaped it:

     mint  #53e3ae on the bg  = 1.54:1  -> unusable as TEXT. It is a FILL, and
           only with DARK text on it (10.67:1); white on mint is 1.62:1.
     purple #5839fb           = 5.88:1  -> fine as text AND as a fill behind
           white text (6.19:1), so no darkened button shade is needed.

   Where the palette had no colour, the hue was preserved and the lightness
   dropped until it cleared AA (mint 158deg -> #147b55 at 5.00:1), rather than
   substituting an unrelated colour. */
:root[data-theme="mint"] {
  --overlay-rgb: 0, 0, 0;
  --bg: #f8f9fd;
  --bg-page: var(--bg);
  --bg-card: #ffffff;
  --bg-input: #ffffff;
  --bg-hover: #f0eeff;                /* purple-light, thinned to a hover wash */
  --bg-light: #dedbf5;
  --border: #e3e0f3;
  --border-light: #cfcbe8;
  --text: #1a1638;                    /* 16.4:1 */
  --text-mid: #3d3663;                /* 10.5:1 */
  --text-muted: #544c7a;              /*  7.4:1 */
  --text-dim: #6b6390;                /*  5.2:1 — the dimmest we may go and stay AA */
  --accent: #5839fb;                  /*  5.9:1 */
  --accent-btn: #5839fb;              /* white text on it = 6.2:1, so the raw brand purple works */
  --on-accent: #ffffff;               /* #416 white on the brand purple is 6.19:1 */
  --accent-light: #4326d6;            /* an "accent-light" is TEXT here, so it DARKENS (as light does) */
  --win: #5839fb;                     /* this palette has no gold; purple is the primary bet colour */
  --win-bg: rgba(88, 57, 251, 0.08);
  --ew: #147b55;                      /* mint at its hue, darkened to 5.0:1 for text */
  --ew-bg: rgba(83, 227, 174, 0.20);  /* ...while the CHIP keeps the real mint as a tint */
  --avoid: #6b7280;
  --avoid-bg: rgba(107, 114, 128, 0.08);
  --danger: #c2263c;                  /* no red in the palette; derived for AA (5.5:1) */
  --green: #147b55;                   /* positive = mint-as-text */
  --on-status: #1a1638;               /* text ON a mint/purple fill is DARK — white would be 1.6:1 */
  /* #416 --x-rgb companions. CSS cannot do rgba(var(--win), .12) -- a hex var is not
     three numbers -- so a tint could never follow the theme and every one was hardcoded.
     Derived from this theme's own colours; --overlay-rgb already set the precedent. */
  --accent-rgb:       88, 57, 251;
  --win-rgb:          88, 57, 251;
  --ew-rgb:           20, 123, 85;
  --green-rgb:        20, 123, 85;
  --danger-rgb:       194, 38, 60;
  --text-rgb:         26, 22, 56;
  --avoid-rgb:        107, 114, 128;
  /* #416 Tulloch's Tips carries its own small palette: the card is a premium slab with its
     OWN ground and ink, deliberately not the page's. Every one of these used to be a literal
     (#3a2b8c, rgba(176,164,255)…) so the card looked identical in every theme. */
  --tulloch:      #b0a4ff;            /* the signature: border, glow, crest, accent bar */
  --tulloch-rgb:  176, 164, 255;
  --tulloch-g1:   #3a2b8c;            /* the slab gradient, light -> dark */
  --tulloch-g2:   #241b63;
  --tulloch-g3:   #171833;
  --tulloch-ink:  #e9e5ff;            /* text ON the slab (12.1:1 on g2) */
  --tulloch-well-rgb: 10, 10, 24;   /* the inset wells, a darkening of the slab itself */
  /* #417 chart lines — the deep set: the same six hues, taken darker so they read on a
     LIGHT ground. Bright #3b82f6 on white is a washed-out line, not a data series. */
  --chart-1: #2563eb;  --chart-2: #ea580c;  --chart-3: #16a34a;
  --chart-4: #9333ea;  --chart-5: #dc2626;  --chart-6: #0d9488;
  --brand-betfair: #b45309;           /* Betfair's amber, darkened to stay visible on white:
  --chart-1-rgb: 37, 99, 235;         /* companion for tints of the info blue */
  /* #417 AC4 — the trial changes the TYPE as well as the colour. Avenir/Segoe is a rounder,
     softer grotesque than Inter: it suits the mint palette's lighter ground, and it proves
     the toggle reaches type. System stack only — no webfont, no network request. */
  --font: 'Avenir Next', Avenir, 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
                                         same hue, legible ground — the brand is still read */
}

/* ── TRIAL 2: indigo/mint — mapped from the DesignAcademy reference ──────────
   Account -> Appearance -> "Indigo (trial)", or localStorage.theme = "indigo".

   v3. The supplied reference settles what this palette actually IS: a WHITE ground with these
   five as ACCENTS on it. Not a dark theme. My first two attempts assumed the palette had to
   supply the surface. It does not -- and that assumption produced a dark theme nobody asked
   for, twice.

   The reference obeys the contrast maths exactly, whether it knew it or not:

       space-indigo  #3d315b  11.74:1 on white -> REAL TEXT. The wordmark, headings.
       dusk-blue     #444b6e   8.48:1          -> REAL TEXT. The structural second voice.
       tomato        #fe4a49   3.34:1          -> LARGE+BOLD only ("300+"), outlines, fills.
       rosy-taupe    #b09398   2.81:1          -> one huge display heading. Below even the 3:1
                                                  large-text floor: it is really a TINT.
       tropical-mint #53e3ae   1.62:1          -> NEVER text. The primary CTA FILL, and the
                                                  reference puts DARK text on it (10.75:1).

   That mint CTA is why --on-accent had to exist (#416). Every --accent-btn fill in this
   stylesheet hardcoded color:#fff, and .btn-primary hardcoded its BACKGROUND too -- so the main
   button was the same purple in every theme including both trials, and setting --accent-btn to
   the mint would have shipped white-on-mint at 1.62:1.

   Every text token measured against BOTH the page and the card; all clear AA. Where a supplied
   colour cannot be text it is used as the reference uses it -- a fill or a tint -- rather than
   darkened past recognition. */
:root[data-theme="indigo"] {
  --overlay-rgb: 0, 0, 0;
  --bg: #f7f6f9;                      /* a trace of indigo in the ground, so white cards lift */
  --bg-page: var(--bg);
  --bg-card: #ffffff;                 /* the reference is white cards on a near-white page */
  --bg-input: #f3f1f6;
  --bg-hover: #f0edf5;
  --bg-light: #e6e2ee;
  --border: #e2dfe9;
  --border-light: #cdc7d8;
  --text: #241d33;                    /* near-black, indigo-biased */
  --text-mid: #4b4165;
  --text-muted: #6a5f85;
  --text-dim: #766b8f;                /* white 4.92 - the AA floor on the harder surface */
  --accent: #3d315b;                  /* SPACE-INDIGO, RAW - 11.74:1. The reference uses it as
                                         real text (the wordmark), so it leads here too. */
  --accent-btn: #53e3ae;              /* TROPICAL-MINT, RAW - the primary CTA fill, exactly as
                                         the reference. Only possible because --on-accent now
                                         exists. */
  --on-accent: #1c1730;               /* DARK text on the mint button. The "Enroll Now" pairing. */
  --accent-light: #554778;
  --win: #3d315b;                     /* indigo - the primary voice */
  --win-bg: rgba(83, 227, 174, 0.22); /* on a MINT tint: the CTA colour doing chip duty */
  --ew: #444b6e;                      /* DUSK-BLUE, RAW - 8.48:1, the second voice */
  --ew-bg: rgba(68, 75, 110, 0.10);
  --avoid: #776b8a;                   /* white 4.94 */
  --avoid-bg: rgba(176, 147, 152, 0.16); /* ROSY-TAUPE as the muted tint - its real job */
  --danger: #d31f1e;                  /* TOMATO darkened 64->50% L. Raw #fe4a49 is 3.34:1, which
                                         is why the reference only uses it LARGE ("300+") or as
                                         an outline. Body text needs the darker one. */
  --green: #0c7e56;                   /* the mint darkened until it reads as text (mint itself
                                         is 1.62:1). The chip tints keep the true mint. */
  --on-status: #1c1730;               /* dark text on a mint / tomato / taupe fill */
  /* #416 --x-rgb companions. CSS cannot do rgba(var(--win), .12) -- a hex var is not
     three numbers -- so a tint could never follow the theme and every one was hardcoded.
     Derived from this theme's own colours; --overlay-rgb already set the precedent. */
  --accent-rgb:       61, 49, 91;
  --win-rgb:          61, 49, 91;
  --ew-rgb:           68, 75, 110;
  --green-rgb:        12, 126, 86;
  --danger-rgb:       211, 31, 30;
  --text-rgb:         36, 29, 51;
  --avoid-rgb:        119, 107, 138;
  /* #416 The user asked for rosy-taupe as Tulloch's main colour on this palette. The card
     keeps its character — a rich slab that lifts off the page — in the taupe hue (350) at the
     same lightness structure as the violet it replaces. Note the slab stays DARK even though
     this is a light theme: that contrast IS the card's job, and its own ink comes with it. */
  --tulloch:      #b09398;            /* rosy-taupe, raw — 4.86:1 on the slab */
  --tulloch-rgb:  176, 147, 152;
  --tulloch-g1:   #60393f;
  --tulloch-g2:   #3f272b;
  --tulloch-g3:   #24191b;
  --tulloch-ink:  #f1e4e7;            /* 11.1:1 on g2 */
  --tulloch-well-rgb: 20, 13, 14;   /* the taupe slab's own shadow, not the violet's blue-black */
  /* #417 chart lines — the deep set: the same six hues, taken darker so they read on a
     LIGHT ground. Bright #3b82f6 on white is a washed-out line, not a data series. */
  --chart-1: #2563eb;  --chart-2: #ea580c;  --chart-3: #16a34a;
  --chart-4: #9333ea;  --chart-5: #dc2626;  --chart-6: #0d9488;
  --brand-betfair: #b45309;           /* Betfair's amber, darkened to stay visible on white:
  --chart-1-rgb: 37, 99, 235;         /* companion for tints of the info blue */
  /* #417 The requested pairing: DM Sans for body, Montserrat for headings.
     They work together for the reason most sans/sans pairs do not: Montserrat is geometric with
     wide round bowls and real weight up top, DM Sans is a low-contrast grotesque with a tall
     x-height that stays quiet at 14px. Contrast in ROLE, agreement in shape — so a heading
     announces itself without the page looking like two websites.
     Both are self-hosted (see the @font-face block) — SIL OFL, one variable file each. The
     fallbacks are the nearest system geometrics, so a failed font load degrades in kind. */
  --font: 'DM Sans', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-head: 'Montserrat', 'Avenir Next', 'Segoe UI', system-ui, -apple-system, sans-serif;
                                         same hue, legible ground — the brand is still read */
}

/* ── Emerald & Gold — "Sportsbook & Racing Analytics" ────────────────────────
   A DARK theme (unlike the mint/indigo light trials): deep charcoal with a
   microscopic emerald warmth, mint-green primary accent, champagne-gold Win tier.
   Only the colour identity is overridden — charts, type and overlays inherit the
   base dark :root. Account -> Appearance -> "Emerald", or localStorage.theme = "emerald".
   Contrast: dark ink (#080b0d) on the mint accent = 11.8:1 (AAA); the same ink on
   the bright win/ew/green FILLS (--on-status) = 9.4:1 (gold) / 10.9:1 (mint) = AAA. */
:root[data-theme="emerald"] {
  --bg: #0b0f12;
  --bg-page: #0b0f12;
  --bg-card: #151c22;                 /* elevation 1: hero, table cards, tips */
  --bg-input: #151c22;
  --bg-hover: #1f2933;
  --bg-light: #242f37;
  --border: #242f37;
  --border-light: #1a222a;
  --on-accent: #080b0d;               /* dark ink on the mint accent — 11.8:1, AAA */
  --text: #ffffff;
  --text-mid: #c2c5d2;
  --text-dim: #8a99a5;
  --text-muted: #5a6872;
  --text-rgb: 255, 255, 255;
  --accent: #00e676;                  /* mint green — primary accent */
  --accent-btn: #00e676;
  --accent-light: #00ff84;
  --accent-rgb: 0, 230, 118;
  --avoid: #6b7280;
  --avoid-bg: rgba(107, 114, 128, 0.08);
  --avoid-rgb: 107, 114, 128;
  --danger: #ff5252;
  --danger-rgb: 255, 82, 82;
  --green: #00e676;
  --green-rgb: 0, 230, 118;
  --win: #d4af37;                     /* champagne gold — Top Picks / Win tier */
  --win-bg: rgba(212, 175, 55, 0.10);
  --win-rgb: 212, 175, 55;
  --ew: #2dd4bf;                      /* teal — Each-Way */
  --ew-bg: rgba(45, 212, 191, 0.10);
  --ew-rgb: 45, 212, 191;
  --on-status: #080b0d;               /* dark ink on the bright win/ew/green FILLS (white fails here) */
  /* Tulloch's Tips — sleek dark-slate slab with a gold signature (no violet). */
  --tulloch: #d4af37;
  --tulloch-rgb: 212, 175, 55;
  --tulloch-g1: #1a232a;
  --tulloch-g2: #151c22;
  --tulloch-g3: #0b0f12;
  --tulloch-ink: #ffffff;
  --tulloch-well-rgb: 6, 9, 11;
  /* Exchange + utility — functional semantics preserved. */
  --exch-back: #1e88e5;
  --exch-lay: #e53935;
  --exch-back-rgb: 30, 136, 229;
  --exch-lay-rgb: 229, 57, 53;
  --video-mat: #000000;
}

/* ── Editorial — premium LIGHT theme, "financial data journal" ───────────────
   A luxury print / top-tier data-journal aesthetic, NOT another app skin. The design
   is BORDER-FIRST: hairline silver-ink rules + negative space carry structure, with
   drop shadows removed entirely (panels sit flat on an off-white canvas). Green is
   heavily restricted to cure the monotonous-highlight look — deep FOREST INK
   (#0b2f1d) does all the interactive-text / nav / CTA work, and one clean MINT
   (#00a854) is reserved strictly for the "Live" hero eyebrow + win indicators, never
   general borders/fills. Headings are a serif display in midnight black; body copy is
   muted charcoal. A crisp corner HIERARCHY (10px structural / 2px tactical inner / 0px
   global frame) reads as a printed page married to modern device design. Account ->
   Appearance -> "Editorial", or localStorage.theme = "editorial". */
:root[data-theme="editorial"] {
  --overlay-rgb: 0, 0, 0;
  --bg: #f3f4f6; --bg-page: #f3f4f6;      /* cool platinum canvas — white cards POP off it */
  --bg-card: #ffffff;                     /* pure white for every data container/table/pill */
  --bg-input: #ffffff;
  --bg-hover: #eef1f5;                     /* the faint tint shift on interactive focus */
  --bg-light: #e9ebef;                     /* header/well fill, a touch darker than the cards */
  --border: #e5e7eb;                      /* crisp silver-gray hairline — the primary separator */
  --border-light: #eef0f3;
  --text: #111827;                        /* deep charcoal — high-priority data, headings (16.1:1) */
  --text-mid: #4b5563;                    /* legible slate — secondary labels/body/headers (7.6:1) */
  --text-dim: #6b7280;                    /* tertiary labels */
  --text-muted: #9ca3af;                  /* dimmest, large/secondary only */
  --text-rgb: 17, 24, 39;
  --accent: #065f46;                      /* commanding FOREST GREEN — links, nav, active states (6.5:1) */
  --accent-light: #065f46;                /* interactive text stays the deep forest on white */
  --accent-btn: #065f46;                  /* CTA fill + the selected Race pill */
  --accent-hover: #054e3a;                /* CTA/active hover — a shade deeper */
  --on-accent: #ffffff;                   /* white on forest green — 6.5:1, AA */
  --accent-rgb: 6, 95, 70;                /* forest tints for the rare fill/rule */
  --green-ink: #166534; --mint-bg: #f0fdf4; /* result banner: dark ink-green text on a subtle mint */
  --mint: #00a854; --mint-rgb: 0, 168, 84; /* RESTRICTED: the "Live" eyebrow + win only */
  --avoid: #6b7280; --avoid-bg: rgba(107, 114, 128, 0.08); --avoid-rgb: 107, 114, 128;
  --danger: #b3261e; --danger-rgb: 179, 38, 30;
  --green: #00a854; --green-rgb: 0, 168, 84; /* live/positive = the reserved mint */
  --win: #00a854;                         /* win indicator = mint */
  --win-bg: rgba(0, 168, 84, 0.10);
  --win-rgb: 0, 168, 84;
  --ew: #8a6d4a;                          /* each-way / secondary "Basic" = bronze, not green */
  --ew-bg: rgba(138, 109, 74, 0.12);
  --ew-rgb: 138, 109, 74;
  --on-status: #ffffff;
  /* Tulloch & elite scorecards — warm cream PAPER stock + a faint bronze hairline (no glow). */
  --tulloch: #b9a986; --tulloch-rgb: 185, 169, 134;
  --tulloch-g1: #fdfbf7; --tulloch-g2: #faf7f1; --tulloch-g3: #f5f0e7;
  --tulloch-ink: #111827; --tulloch-well-rgb: 240, 233, 220;
  --tulloch-border: #e6dfd3;              /* warm bronze hairline that signals exclusivity */
  /* charts — the deep set, taken dark so lines read on a LIGHT ground. */
  --chart-1: #1565c0; --chart-2: #c2410c; --chart-3: #15803d;
  --chart-4: #7e22ce; --chart-5: #b91c1c; --chart-6: #0f766e;
  --chart-1-rgb: 21, 101, 192; --brand-betfair: #b45309;
  --exch-back: #1565c0; --exch-lay: #b3261e; --exch-back-rgb: 21, 101, 192; --exch-lay-rgb: 179, 38, 30;
  --video-mat: #000000;
  /* Serif display for headings — the news-journal voice. */
  --font-head: 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
  /* Crisp corner HIERARCHY + a slightly tighter generic radius. NO elevation tokens —
     the layout is border-first, so cards stay flat. */
  --radius: 8px;
  --r-card: 10px;                         /* structural containers: modern but rigid */
  --r-inner: 2px;                         /* inner components: ultra-tactical, near-square */
}
/* BORDER-FIRST structural panels — hairline rule, crisp radius, ZERO shadow, flat on
   the canvas. Backgrounds are left alone so semantic tints (callouts, pred states) survive. */
:root[data-theme="editorial"] .landing-hero,
:root[data-theme="editorial"] .hiw-card,
:root[data-theme="editorial"] .sp-card,
:root[data-theme="editorial"] .tf-card,
:root[data-theme="editorial"] .bs-card,
:root[data-theme="editorial"] .notif-channel,
:root[data-theme="editorial"] .acct-panel,
:root[data-theme="editorial"] .pred-box,
:root[data-theme="editorial"] .mr-item,
:root[data-theme="editorial"] .value-card,
:root[data-theme="editorial"] .stat-card,
:root[data-theme="editorial"] .callout,
:root[data-theme="editorial"] .hero {
  border-radius: var(--r-card);
  border: 1px solid var(--border);
  box-shadow: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
/* The landing hero drops its tinted radial — structure comes from spacing, not gradient. */
:root[data-theme="editorial"] .landing-hero { background: var(--bg-card); }
/* Interactive focus: the hairline SNAPS to forest ink + a faint tint shift. No glow. */
:root[data-theme="editorial"] .hiw-card:hover,
:root[data-theme="editorial"] .sp-card:hover,
:root[data-theme="editorial"] .tf-card:hover,
:root[data-theme="editorial"] .bs-card:hover,
:root[data-theme="editorial"] .mr-item:hover,
:root[data-theme="editorial"] .value-card:hover {
  border-color: var(--accent);
  background: var(--bg-hover);
  box-shadow: none;
}
/* Inner components — ultra-tactical, near-square corners (0–2px). */
:root[data-theme="editorial"] .hero-cta,
:root[data-theme="editorial"] .status-badge,
:root[data-theme="editorial"] .btn-primary,
:root[data-theme="editorial"] .btn-secondary,
:root[data-theme="editorial"] .btn-outline,
:root[data-theme="editorial"] .btn-danger,
:root[data-theme="editorial"] .jh-chip,
:root[data-theme="editorial"] .rf-chip,
:root[data-theme="editorial"] .badge,
:root[data-theme="editorial"] .flow-badge,
:root[data-theme="editorial"] .horse-filter,
:root[data-theme="editorial"] .sb-field,
:root[data-theme="editorial"] .form-input,
:root[data-theme="editorial"] input,
:root[data-theme="editorial"] textarea,
:root[data-theme="editorial"] select {
  border-radius: var(--r-inner);
}
/* The CTA is FOREST INK (mint pulled off buttons); its hover deepens the ink — this also
   overrides the leftover indigo-purple :hover literal that would otherwise flash here. */
:root[data-theme="editorial"] .hero-cta { background: var(--accent-btn); color: var(--on-accent); }
:root[data-theme="editorial"] .hero-cta:hover { background: var(--accent-hover); }
/* The eyebrow is the ONE mint element — the "Live form intelligence" status marker. */
:root[data-theme="editorial"] .hero-eyebrow {
  color: var(--mint);
  background: rgba(var(--mint-rgb), 0.10);
  border-color: rgba(var(--mint-rgb), 0.35);
}
/* The secondary "Basic" model reads as BRONZE, not another green. */
:root[data-theme="editorial"] .flow-badge.flow-basic {
  background: color-mix(in srgb, var(--ew) 15%, transparent);
  color: var(--ew);
  border-color: color-mix(in srgb, var(--ew) 45%, transparent);
}
/* Tulloch & elite scorecards — cream paper, warm bronze hairline, flat (no glow), crisp radius. */
:root[data-theme="editorial"] .tulloch {
  border-radius: var(--r-card);
  border: 1px solid var(--tulloch-border);
  box-shadow: none;
}
/* Global frame — a flat, unrounded 0px canvas edge grounding the text-heavy sections. */
:root[data-theme="editorial"] .site-header { border-radius: 0; }

/* ── Editorial — Race Detail shell + injected data components ─────────────────
   The dense page. Legibility and grid alignment over decoration: the platinum
   canvas flows through the transparent section wrappers (.home-section-primary is
   margin-only), and pure white is applied only to the injected data cards/tables. */

/* Dynamic data matrices (#raceRoot): a premium financial LEDGER. Numeric/grid data in a
   true tabular mono at muted charcoal; rows separated by hairline rules + negative space,
   NOT zebra striping; row focus is a neutral cool-grey wash (no green bleed). */
:root[data-theme="editorial"] { --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; }
:root[data-theme="editorial"] .data-table { color: var(--text-mid); }
:root[data-theme="editorial"] .data-table tbody tr:hover { background: var(--bg-hover); }
/* Primary metric (top pick): a premium cream-paper block with a bronze hairline —
   flags it as strategic intelligence — with forest-ink accents, never a green fill.
   Kills the tinted/indigo gradient the base .top-pick paints. */
:root[data-theme="editorial"] .top-pick {
  background: var(--tulloch-g1);
  border: 1px solid var(--tulloch-border);
  border-radius: var(--r-card);
}
:root[data-theme="editorial"] .top-pick-name { color: var(--accent); }

/* Modal architecture (UI.modal — quaddies, media): dark-ink scrim, crisp hairline card,
   flat (no heavy shadow — the scrim carries the separation), unboxed midnight ✕. */
:root[data-theme="editorial"] .modal-overlay { background: rgba(var(--text-rgb), 0.6); }
:root[data-theme="editorial"] .modal-content {
  border-radius: var(--r-card);
  border: 1px solid var(--border);
  box-shadow: none;
}
:root[data-theme="editorial"] .modal-close { color: var(--text); }

/* Premium loading state (#loadingRace): no spinner — a subtle serif pulse, midnight fading
   to charcoal, centred in generous white space, building anticipation for the insight. */
@keyframes editorial-loading-pulse {
  0%, 100% { color: var(--text); opacity: 1; }
  50% { color: var(--text-mid); opacity: 0.55; }
}
:root[data-theme="editorial"] #loadingRace,
:root[data-theme="editorial"] .loading-msg {
  color: var(--text);
  font-family: var(--font-head);
  letter-spacing: 0.01em;
  animation: editorial-loading-pulse 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  :root[data-theme="editorial"] #loadingRace,
  :root[data-theme="editorial"] .loading-msg { animation: none; }
}

/* ── Editorial — Race Detail asymmetric 2-column grid ────────────────────────
   UI.racePage emits three wrappers under Editorial only: .race-hd (full-width race
   context), .race-main (65% field matrix) and .race-side (35% insights). Mobile-first:
   a single column with the INSIGHTS stacked ABOVE the dense field, so strategy reads
   before the scroll. At ≥1025px it becomes the 65/35 grid. Other themes never emit
   these wrappers, so this whole section is inert for them. */
:root[data-theme="editorial"] #raceRoot {
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 1380px;
  margin: 0 auto;
}
:root[data-theme="editorial"] .race-hd { order: 0; border-bottom: 1px solid var(--border); padding-bottom: 0.75rem; }
:root[data-theme="editorial"] .race-side { order: 1; display: flex; flex-direction: column; gap: 24px; min-width: 0; }
:root[data-theme="editorial"] .race-main {
  order: 2; min-width: 0;
  display: flex; flex-direction: column; gap: 0.75rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
}
/* The premium sidebar blocks (top pick, best bets) already carry the cream-paper treatment
   via their own rules; track bias and any other insight sits on a plain white hairline card. */
:root[data-theme="editorial"] .race-side .race-best-bets:not(:empty) {
  background: var(--tulloch-g1);
  border: 1px solid var(--tulloch-border);
  border-radius: var(--r-card);
  padding: 0.85rem 1rem;
}
/* Best-bets is desktop-hidden globally (shown elsewhere); in the Editorial sidebar it IS
   the strategy surface, so let a populated one show at the 2-column breakpoint. */
@media (min-width: 1025px) {
  :root[data-theme="editorial"] #raceRoot {
    display: grid;
    grid-template-columns: 65fr 35fr;
    column-gap: 32px;
    row-gap: 20px;
    align-items: start;
  }
  :root[data-theme="editorial"] .race-hd { grid-column: 1 / -1; }
  :root[data-theme="editorial"] .race-main { grid-column: 1; order: 0; }
  :root[data-theme="editorial"] .race-side { grid-column: 2; order: 0; }
  :root[data-theme="editorial"] .race-side .race-best-bets { display: block; }
}

/* ── Editorial — Race Detail contrast refinements ────────────────────────────
   Higher-contrast hierarchy: white data containers pop off the platinum canvas,
   and the components the brief calls out get their legibility fixed. */

/* A. Result banner — subtle mint field, dark ink-green placements (no neon-on-pale). */
:root[data-theme="editorial"] .resulted-banner {
  background: var(--mint-bg);
  border: 1px solid color-mix(in srgb, var(--green-ink) 30%, transparent);
}
:root[data-theme="editorial"] .rb-header,
:root[data-theme="editorial"] .rb-pos strong { color: var(--green-ink); }

/* B. Next-to-jump track pills + filter chips — pure white so they don't bleed into the
   header bar; muted text that darkens to full charcoal on hover. */
:root[data-theme="editorial"] .jh-race,
:root[data-theme="editorial"] .jh-chip {
  background: var(--bg-card);
  border-color: var(--border);
  color: var(--text-mid);
}
:root[data-theme="editorial"] .jh-race:hover,
:root[data-theme="editorial"] .jh-chip:hover { color: var(--text); border-color: var(--accent); }

/* D. Field-matrix rows — hairline separators, no zebra, generous 12px vertical padding;
   column headers in the legible slate. */
:root[data-theme="editorial"] .data-table th { color: var(--text-mid); }
:root[data-theme="editorial"] .data-table td,
:root[data-theme="editorial"] .data-table th { padding-top: 0.75rem; padding-bottom: 0.75rem; }

@media (max-width: 640px) {
  :root { --fs-h1: 1.35rem; --fs-h2: 1.15rem; --fs-h3: 1rem; --fs-sm: 0.76rem; --fs-xs: 0.72rem; --fs-2xs: 0.68rem; } /* a11y (#168): mobile floor ~11px, was 10.5/9.3px */
}
/* #148 standard heading classification + text-size utilities (all read the scale). */
/* #417 …and the heading FACE, from one rule. --font-head defaults to --font, so this changes
   nothing for a theme that does not set it — but a theme that wants a display face now has
   somewhere to put it. .tt-title (Great Vibes) sets its own family and still wins on
   specificity, so Tulloch's script is untouched. */
h1, h2, h3, h4, h5, h6,
.text-h1, .text-h2, .text-h3, .text-h4,
.section-title, .hero-title { font-family: var(--font-head); }
h1, .text-h1 { font-size: var(--fs-h1); }
h2, .text-h2 { font-size: var(--fs-h2); }
h3, .text-h3 { font-size: var(--fs-h3); }
h4, .text-h4 { font-size: var(--fs-h4); }
h5, h6 { font-size: var(--fs-body); }
.text-body { font-size: var(--fs-body); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.text-2xs { font-size: var(--fs-2xs); }
/* Keep tabular alignment for numeric/odds text now that mono = the body font. */
.mono, [class*="mono"], .odds-row, .to-val, .runner-num, .pal-var, .pal-hex { font-variant-numeric: tabular-nums; }

body {
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-h3);
  line-height: 1.55;
  padding-top: var(--header-h);
  min-height: 100vh;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

/* Main menu — an overlay drawer that slides in over the content from the left
   (default closed) at all sizes; the content never resizes. Opened by the header
   menu toggle; a scrim + any outside click closes it. */
.top-nav {
  position: fixed; top: var(--header-h); left: 0; bottom: 0;
  width: min(84vw, 300px);
  background: var(--bg-card); border-right: 1px solid var(--border);
  z-index: 250; overflow-y: auto; -webkit-overflow-scrolling: touch;
  transform: translateX(-100%);
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
body.nav-open .top-nav { transform: translateX(0); }
/* Dim scrim behind the open drawer (below the header so the toggle stays live). */
.nav-scrim {
  position: fixed; inset: var(--header-h) 0 0 0; z-index: 240;
  background: rgba(0, 0, 0, 0.45); opacity: 0; visibility: hidden; pointer-events: none;
  /* Fully removed from hit-testing when closed so it can never block page scroll;
     visibility flips to hidden only after the fade-out completes. */
  transition: opacity 0.42s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear 0.42s;
}
body.nav-open .nav-scrim { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity 0.42s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s; }

.tn-inner {
  max-width: none;
  margin: 0;
  height: 100%;
  flex-direction: column;
  align-items: stretch;
  gap: 0.35rem;
  display: flex;
  padding: 1rem 0.75rem;
}

.tn-brand {
  display: flex;
  align-items: center;
  margin: 0 0 0.6rem 0.25rem;
  opacity: 1;
  transition: opacity 0.15s;
}
.tn-brand:hover { opacity: 0.8; }
.tn-brand-live { display: flex; align-items: center; gap: 0.5rem; }
.tn-brand-img { height: 40px; width: auto; max-width: 120px; object-fit: contain; display: block; }
.tn-brand-word { font-size: var(--fs-h3); font-weight: 800; color: #33e0a1; letter-spacing: -0.3px; }

.tn-menu {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.1rem;
}
.tn-link { width: 100%; padding: 0.5rem 0.7rem; }
.tn-dropdown { position: relative; width: 100%; }
/* The in-nav hamburger is replaced by the header menu toggle. */
.tn-toggle { display: none !important; }
.tn-divider { height: 1px; background: var(--border); margin: 0.4rem 0.3rem; align-self: stretch; }

.tn-link {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-mid);
  padding: 0.4rem 0.75rem;
  border-radius: 6px;
  transition: all 0.12s;
}

.tn-link:hover { color: var(--text); background: var(--bg-hover); }
.tn-link.tn-active { color: var(--accent-light); background: rgba(var(--accent-rgb), 0.08); font-weight: 600; }

.tn-date {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-left: 0.2rem;
}

/* Navbar Dropdowns */

.tn-dropdown {
  position: relative;
}

.tn-drop-header {
  display: flex;
  align-items: center;
}

.tn-drop-link {
  border-radius: 6px 0 0 6px;
}
span.tn-drop-link[data-dropdown-label] { cursor: pointer; user-select: none; }
/* Hovering anywhere on a parent row highlights the whole row (label + caret),
   so dropdown parents behave like the plain top-level links. */
.tn-drop-header:hover .tn-drop-link,
.tn-drop-header:hover .tn-caret-btn { background: var(--bg-hover); color: var(--text); }

.tn-caret-btn {
  font-family: var(--font);
  font-size: var(--fs-2xs);
  color: var(--text-mid);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.4rem 0.45rem;
  border-radius: 0 6px 6px 0;
  transition: all 0.12s;
}

.tn-caret-btn:hover { color: var(--text); background: var(--bg-hover); }
.tn-caret-btn.tn-caret-active { color: var(--accent-light); background: rgba(var(--accent-rgb), 0.08); }

.tn-drop-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 200px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,0.3);
  z-index: 200;
  overflow: hidden;
}

.tn-drop-menu.tn-drop-open { display: block; }

.tn-drop-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  font-size: var(--fs-sm);
  color: var(--text-mid);
  border-top: 1px solid var(--border);
  transition: background 0.12s;
}

.tn-drop-item:first-child { border-top: none; }
.tn-drop-item:hover { background: var(--bg-hover); color: var(--text); }
.tn-drop-item-active { color: var(--accent-light); font-weight: 600; }
/* Group heading inside the admin dropdown (#50) */
.tn-drop-heading {
  padding: 0.5rem 0.75rem 0.25rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}
.tn-drop-heading:first-child { border-top: none; }

.tn-di-course {
  font-weight: 600;
  color: var(--text);
}

.tn-di-meta {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.tn-drop-loading, .tn-drop-empty {
  padding: 0.6rem 0.75rem;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}

/* Future dropdown: days -> expandable meets */
.tn-drop-menu-future { min-width: 240px; max-height: 72vh; overflow-y: auto; }
.tn-future-day { border-top: 1px solid var(--border); }
.tn-future-day:first-child { border-top: none; }
.tn-future-day-header {
  display: flex; align-items: stretch; gap: 0;
  width: 100%; color: var(--text); font-size: var(--fs-body); font-weight: 700;
}
.tn-fd-link {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  flex: 1 1 auto; min-width: 0; text-decoration: none; color: inherit;
  padding: 0.5rem 0.5rem 0.5rem 0.75rem;
}
.tn-fd-link:hover { background: var(--bg-hover); }
.tn-fd-caret-btn {
  flex: 0 0 auto; background: none; border: none; border-left: 1px solid var(--border);
  cursor: pointer; color: var(--text-dim); padding: 0.5rem 0.7rem;
}
.tn-fd-caret-btn:hover { background: var(--bg-hover); color: var(--text); }
.tn-fd-date { color: var(--text-dim); font-weight: 500; font-size: var(--fs-xs); }
.tn-fd-meta { font-size: var(--fs-xs); color: var(--text-dim); font-weight: 600; white-space: nowrap; }
.tn-fd-caret { display: inline-block; transition: transform 0.15s; }
.tn-future-day.tn-fd-open .tn-fd-caret { transform: rotate(180deg); }
.tn-future-meets { display: none; background: var(--bg); }
.tn-future-day.tn-fd-open .tn-future-meets { display: block; }
.tn-future-meets .tn-drop-item { padding-left: 1.1rem; }

.tn-user-area {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: 0.5rem;
  padding-left: 0.5rem;
  border-left: 1px solid var(--border);
}

.tn-username {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tn-logout-btn {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.25rem 0.55rem;
  cursor: pointer;
  transition: all 0.12s;
}
.tn-logout-btn:hover { color: var(--danger); border-color: var(--danger); }

.tn-toggle {
  display: none;
  flex-direction: column;
  gap: 4px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.4rem;
}

.tn-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--text-mid);
  border-radius: 1px;
  transition: all 0.2s;
}

@media (max-width: 640px) {
  body { font-size: 16px; }

  .tn-link {
    width: 100%;
    padding: 0.55rem 0.75rem;
    text-align: left;
  }

  .tn-dropdown { width: 100%; }

  .tn-drop-header { width: 100%; }
  .tn-drop-link { flex: 1; padding: 0.55rem 0.75rem; border-radius: 6px; }
  .tn-caret-btn { padding: 0.55rem 0.75rem; }

  .tn-drop-menu {
    position: static;
    box-shadow: none;
    border: none;
    border-radius: 0;
    background: var(--bg);
    margin: 0.15rem 0;
  }
}

/* Best bets in the main content — mobile only; the sticky right rail shows these
   on desktop, so hide the in-content copies there. (The loaders set an inline
   display, so override with !important.) */
.race-best-bets { margin: 1rem 0; }
.race-best-bets:empty { display: none; }
.race-best-bets .rbb-title { font-weight: 800; font-size: var(--fs-h4); margin-bottom: 0.5rem; }
@media (min-width: 900px) {
  .race-best-bets,
  #dayBestBetsSection,
  #bestBetsSection { display: none !important; }
}

/* Back link — "← Back to …" button (race pages → day schedule). */
.back-link {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: var(--fs-body); font-weight: 600; color: var(--text-mid);
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  padding: 0.4rem 0.7rem; text-decoration: none;
}
.back-link:hover { border-color: var(--accent); color: var(--text); }
.back-link-arrow { font-size: var(--fs-h3); line-height: 1; }

/* Menu collapse toggle — top-left button that slides the sidebar off-screen for
   more content room. Desktop-only (mobile uses the hamburger). */
.nav-toggle-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0; padding: 0;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
  color: var(--text-mid); cursor: pointer;
}
.nav-toggle-btn:hover { border-color: var(--accent); color: var(--text); }
.nav-toggle-btn svg { width: 18px; height: 18px; }

/* Desktop: left sidebar pinned to the page edge; the header spans full width; the
   page area (right of the rail) holds a centred content + sticky right-column shell. */
@media (min-width: 900px) {
  /* Scale all fonts on desktop: rem sizes are root-relative, so bumping the root
     font-size enlarges every rem-based font (and rem spacing) uniformly by 1.125x. */
  html { font-size: 112.5%; background: var(--bg-page); }
  /* Divided layout widths: main content (--content-w) + sticky right column
     (--side-w) sum to a fixed 1340px, so the right column can be widened by
     narrowing the main content by the same amount (combined width unchanged). */
  :root { --rail: 240px; --content-w: 980px; --side-w: 360px; }
  /* Content is full width — the menu drawer overlays it rather than pushing it. */
  body { margin-left: 0; max-width: none; background: var(--bg-page); padding-left: 0; padding-right: 0; }
  .app-shell { display: flex; justify-content: center; align-items: flex-start; gap: 0.9rem; padding: 1rem 0.9rem 0; }
  .app-content { flex: 1 1 auto; max-width: var(--content-w); min-width: 0; }
  /* Full-width template (admin): no rail, content spans the whole page width. */
  .app-shell-full .app-content { max-width: none; }
  .app-rail {
    display: block; flex: 0 1 var(--side-w); max-width: var(--side-w); min-width: 0;
    position: sticky; top: calc(var(--header-h) + 1rem); align-self: flex-start;
  }
  /* Desktop: the submenu slides OUT as a fixed panel at left:100% (below). Because
     .top-nav has transform/will-change it is the containing block for that fixed
     panel, so its overflow clips it — the #109 mobile-scroll fix (overflow-y:auto on
     the base rule) must NOT apply here or the submenu flashes out and is cut off,
     making every sub-page unreachable. On desktop the rail's own items are short and
     never overflow, so visible is safe (mobile keeps the base overflow-y:auto). */
  .top-nav { width: var(--rail); overflow: visible; }
  .tn-dropdown { width: 100%; }
  .tn-drop-header { width: 100%; }
  .tn-drop-link { flex: 1; }
  .tn-caret-btn { padding: 0.5rem 0.6rem; }
  /* On hover, the submenu slides OUT as a full-height panel pinned to the right
     edge of the sidebar (TAB-style), from below the header to the bottom of the
     viewport. It starts tucked behind the sidebar and slides right into view. */
  .tn-drop-menu {
    display: block; position: fixed; left: 100%; top: 0; bottom: 0;
    width: 260px; min-width: 0;
    background: var(--bg-card); border-right: 1px solid var(--border); border-radius: 0;
    box-shadow: 10px 0 30px rgba(0,0,0,0.45); margin: 0; padding: 0.6rem; z-index: 90;
    overflow-y: auto;
    opacity: 0; transform: translateX(-100%); pointer-events: none;
    will-change: transform, opacity;
    /* Slower, more organic slide: a gentle spring easing with a hint of overshoot
       so the panel eases out, drifts slightly past, then settles into place. The
       opacity fade trails the motion so it feels like it emerges, not snaps. */
    transition: opacity 0.4s ease-out, transform 0.6s cubic-bezier(0.34, 1.42, 0.5, 1);
  }
  .tn-drop-menu.tn-drop-open { opacity: 1; transform: translateX(0); pointer-events: auto; }
  .tn-user-area {
    flex-direction: column; align-items: stretch; gap: 0.4rem;
    margin: auto 0 0 0; padding: 0.75rem 0 0; border-left: none; border-top: 1px solid var(--border);
  }
  .tn-username { max-width: none; }
}

/* Two-line site header (fixed, full width, above everything). Line 1 = logo +
   menu toggle + user; line 2 = the "next to jump" row. */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; height: var(--header-h);
  z-index: 300; background: var(--bg-card); border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column;
}
.sh-top {
  display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0;
  height: var(--header-top-h); padding: 0 0.9rem; border-bottom: 1px solid var(--border);
  background: #000; /* black top row; the next-to-jump row below is lighter */
}
.sh-logo { display: inline-flex; align-items: center; flex-shrink: 0; }
.sh-logo img { height: 28px; width: auto; max-width: 130px; object-fit: contain; display: block; }
.sh-logo-word { font-weight: 800; color: #33e0a1; font-size: var(--fs-h3); letter-spacing: -0.3px; }
.nav-toggle-labeled { width: auto; gap: 0.4rem; padding: 0 0.65rem; }
.ntb-label { font-size: var(--fs-body); font-weight: 600; }
.sh-user { margin-left: auto; display: flex; align-items: center; min-width: 0; }
.sh-user-name {
  font-size: var(--fs-body); font-weight: 600; color: var(--text);
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
  padding: 0.28rem 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40vw;
}

/* Betslip button relocated into the header top row (black bg) — was in the drawer. */
.sh-betslip {
  position: relative; display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0;
  background: transparent; border: 1px solid rgba(var(--overlay-rgb), 0.16); color: var(--text);
  border-radius: 8px; height: 34px; padding: 0 9px; cursor: pointer;
}
.sh-betslip:hover { background: rgba(var(--overlay-rgb), 0.09); }
.sh-betslip .bs-star { fill: currentColor; }
.sh-betslip .betslip-badge:empty { display: none; }
.sh-betslip .betslip-badge {
  position: absolute; top: -5px; right: -5px; background: var(--accent-btn); color: var(--on-accent);
  border-radius: 999px; font-size: var(--fs-2xs); font-weight: 700; min-width: 16px; height: 16px;
  padding: 0 4px; display: inline-flex; align-items: center; justify-content: center;
}

/* Top-right "My Account" mini-menu (replaces the username label). */
.sh-acct { position: relative; }
.sh-acct-btn {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 0.6rem;
  background: transparent; border: 1px solid rgba(var(--overlay-rgb), 0.16); border-radius: 8px;
  color: var(--text); font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer; white-space: nowrap;
}
.sh-acct-btn:hover { background: rgba(var(--overlay-rgb), 0.09); }
.sh-acct-ico { font-size: 1rem; line-height: 1; }
.sh-acct-caret { font-size: 0.7em; opacity: 0.75; }
.sh-acct-menu {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 200px; z-index: 300;
  display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; padding: 6px;
  box-shadow: 0 12px 32px -12px rgba(0,0,0,0.75);
}
.sh-acct-menu[hidden] { display: none; }
.sh-acct-item {
  display: block; text-align: left; padding: 0.5rem 0.6rem; border-radius: 6px;
  background: transparent; border: none; color: var(--text-mid); font: inherit; font-size: var(--fs-sm);
  text-decoration: none; white-space: nowrap; cursor: pointer;
}
.sh-acct-item:hover { background: var(--bg-hover); color: var(--text); }
.sh-acct-logout { color: var(--danger); }
.sh-acct-sep { height: 1px; background: var(--border); margin: 4px 2px; }
@media (max-width: 420px) { .sh-acct-lbl { display: none; } }

/* Search box in the header top row. */
.sh-search { flex: 1 1 auto; min-width: 0; max-width: 440px; margin: 0 0.5rem; }
.sh-search .sb-field { height: 34px; background: rgba(var(--overlay-rgb), 0.06); border-color: rgba(var(--overlay-rgb), 0.14); }
.sh-search .sb-input, .sh-search .sb-ico { color: var(--text); }
.sh-search .sb-input::placeholder { color: rgba(var(--text-rgb), 0.55); }

/* #183 — mobile search: the inline header search shares the top row with the logo,
   betslip and account controls, which is cramped ≤700px. Below that width the inline
   box is hidden and replaced with a search-icon toggle that opens a full-width overlay
   (fixed, below the top bar) hosting its own UI.searchBox instance. */
.sh-search-toggle {
  display: none; flex-shrink: 0; align-items: center; justify-content: center;
  width: 34px; height: 34px; background: transparent; border: 1px solid rgba(var(--overlay-rgb), 0.16);
  border-radius: 8px; color: var(--text); cursor: pointer; padding: 0;
}
.sh-search-toggle:hover { background: rgba(var(--overlay-rgb), 0.09); }
.sh-search-toggle svg { width: 16px; height: 16px; }
.sh-search-overlay {
  position: fixed; left: 0; right: 0; top: var(--header-top-h); z-index: 350;
  background: var(--bg-card); border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.75rem;
}
.sh-search-overlay[hidden] { display: none; }
.sh-search-overlay-mount { flex: 1; min-width: 0; }
.sh-search-overlay-mount .sb-results { position: fixed; left: 8px; right: 8px; top: calc(var(--header-top-h) + 58px); }
.sh-search-overlay-close {
  flex-shrink: 0; background: transparent; border: none; color: var(--text-mid);
  font-size: 1.6rem; line-height: 1; cursor: pointer; padding: 0 0.3rem;
}
@media (max-width: 700px) {
  .sh-search { display: none; }
  .sh-search-toggle { display: inline-flex; }
  /* Break the dropdown out to the viewport so results aren't squeezed into a narrow box. */
  .sh-search .sb-results { position: fixed; left: 8px; right: 8px; top: calc(var(--header-top-h) + 4px); }
}

/* Account page in "individual pages" mode (#—): the tab bar is hidden — each section is
   reached from the top-right My Account mini-menu and rendered on its own. */
.acct-solo .acct-nav { display: none; }
@media (max-width: 640px) {
  .ntb-label { display: none; }
  .nav-toggle-labeled { width: 34px; padding: 0; }
  .sh-logo img { height: 24px; }
}

/* The "next to jump" row now sits as the second line inside .site-header. */
.jump-header {
  position: static; z-index: auto; height: auto; flex: 1; min-height: 0;
  background: var(--bg-light); border-bottom: none;
  display: flex; align-items: center; gap: 0.75rem; padding: 0 0.9rem;
}
.jh-title { font-weight: 800; font-size: var(--fs-h4); color: var(--text); white-space: nowrap; flex-shrink: 0; }
.jh-filters { display: flex; align-items: center; gap: 0.3rem; flex-shrink: 0; }
.jh-chip {
  background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 0.28rem 0.5rem; font-size: var(--fs-body); line-height: 1; cursor: pointer;
  color: var(--text-mid); font-family: var(--font);
}
.jh-chip:hover { border-color: var(--border-light); }
.jh-chip.active { border-color: var(--accent); color: var(--accent-light); background: rgba(var(--accent-rgb), 0.12); }
.jh-chip.jh-soon { opacity: 0.4; cursor: default; }
.jh-opt { font-weight: 700; font-size: var(--fs-xs); }
.jh-sep { width: 1px; height: 20px; background: var(--border); margin: 0 0.15rem; flex-shrink: 0; }
.jh-races { display: flex; align-items: center; gap: 0.5rem; overflow-x: auto; flex: 1; height: 100%; }
.jh-races::-webkit-scrollbar { height: 5px; }
.jh-races::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 3px; }
.jh-race {
  display: flex; align-items: center; gap: 0.4rem;
  flex: 1 1 0; min-width: 0; box-sizing: border-box;
  background: var(--bg); border: 1px solid var(--border); border-radius: 7px;
  padding: 0.18rem 0.55rem; text-decoration: none; white-space: nowrap;
}
.jh-race:hover { border-color: var(--accent); }
.jh-race-grey { border-left: 3px solid var(--type-grey); }
.jh-race-horse { border-left: 3px solid var(--type-horse); }
.jh-race-harness { border-left: 3px solid var(--type-harness); }
.jh-r-ico { font-size: var(--fs-h3); line-height: 1; flex-shrink: 0; }
.jh-r-track { flex: 1; min-width: 0; font-size: var(--fs-xs); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jh-r-track b { color: var(--text-muted); font-weight: 700; }
.jh-r-time {
  flex-shrink: 0; font-size: var(--fs-h4); font-family: var(--mono); font-weight: 800;
  color: var(--accent-light); background: var(--bg-card); border-radius: 5px;
  padding: 0.1rem 0.38rem; line-height: 1.1;
}
.jh-r-time.jh-off { color: var(--text-dim); }
.jh-empty { color: var(--text-muted); font-size: var(--fs-body); }
/* Compact filter dropdown on the next-to-jump bar. */
.jh-filter-dd { position: relative; flex-shrink: 0; }
.jh-filter-btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.jh-fb-dots { display: inline-flex; gap: 3px; }
.jh-fb-caret { font-size: var(--fs-xs); opacity: 0.8; }
.jh-filter-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 320;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.45); padding: 0.4rem; min-width: 190px;
  display: flex; flex-direction: column; gap: 0.05rem;
}
.jh-filter-menu[hidden] { display: none; }
.jh-fm-row {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem;
  border-radius: 6px; font-size: var(--fs-body); color: var(--text); cursor: pointer; white-space: nowrap;
}
.jh-fm-row:hover { background: var(--bg-hover); }
.jh-fm-row input { accent-color: var(--accent); margin: 0; }
.jh-fm-disabled { opacity: 0.5; cursor: default; }
.jh-fm-disabled:hover { background: none; }
.jh-fm-soon { font-size: var(--fs-2xs); color: var(--text-dim); border: 1px solid var(--border); border-radius: 4px; padding: 0 0.25rem; margin-left: auto; }
.jh-fm-sep { height: 1px; background: var(--border); margin: 0.25rem 0.2rem; }
/* Mobile "next to jump": drop the label, tighten chips, and give race cards a
   fixed comfortable width so the row scrolls instead of squashing each card. */
@media (max-width: 640px) {
  .jump-header { gap: 0.4rem; padding: 0 0.5rem; }
  .jh-title { display: none; }
  .jh-filters { gap: 0.2rem; }
  .jh-chip { padding: 0.24rem 0.4rem; }
  .jh-sep { margin: 0 0.1rem; }
  .jh-race { flex: 0 0 auto; min-width: 138px; padding: 0.18rem 0.5rem; }
  .jh-r-track { font-size: var(--fs-xs); }
  .jh-r-time { font-size: var(--fs-h4); padding: 0.1rem 0.38rem; }
}

/* App shell: main content + a right-hand column. Base (mobile) = single column,
   rail hidden; desktop turns it into a centred two-column layout (see media query).
   NOTE: scoped to max-width:899px so these do NOT override the min-width:900px
   desktop rules above — media queries add no specificity, so an unscoped rule
   here would win by source order and hide the rail at all widths. */
/* Desktop default: the mobile Tulloch block is hidden (the rail shows Tulloch there).
   Declared BEFORE the media query so the query's override wins on mobile. */
.home-tulloch-mobile { display: none; }
@media (max-width: 899px) {
  .app-shell { display: block; }
  .app-rail { display: none; }
  /* On mobile the rail (with Tulloch's Tips + Best Bets) is hidden, so surface
     Tulloch's Tips in the main column in place of the how-it-works cards, and drop
     Best Bets from the page. */
  .home-tulloch-mobile { display: block; }
  .hiw-section { display: none; }
  #bestBetsSection { display: none !important; }
}
.app-rail-card {
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
  padding: 1rem 1.1rem; color: var(--text-muted); font-size: var(--fs-body);
}
.app-rail-card + .app-rail-card { margin-top: 0.75rem; }
.arc-title { font-weight: 800; color: var(--text); font-size: var(--fs-h4); margin-bottom: 0.4rem; }
.arc-body { line-height: 1.6; }
/* Collapsible rail card (e.g. the rolled-up "Live alerts" on the home rail). */
.arc-head { display: flex; align-items: center; gap: 0.5rem; width: 100%; background: none; border: none; cursor: pointer; color: inherit; font-family: inherit; padding: 0; }
.arc-chevron { color: var(--text-muted); transition: transform 0.15s; font-size: var(--fs-sm); }
.app-rail-card.collapsed .arc-chevron { transform: rotate(-90deg); }
.app-rail-card.collapsed .arc-body { display: none; }
.arc-count { margin-left: auto; font-size: var(--fs-xs); font-weight: 800; color: var(--accent-light); background: color-mix(in srgb, var(--accent) 16%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 999px; padding: 0.05rem 0.45rem; }
.arc-alerts .arc-body { margin-top: 0.7rem; }
.arc-more { display: inline-block; margin-top: 0.35rem; font-size: var(--fs-sm); font-weight: 700; color: var(--accent-light); text-decoration: none; }
.arc-more:hover { text-decoration: underline; }

/* Home "How it works" strip — three linked cards; collapses to one column on mobile. */
.hiw-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.85rem; }
.hiw-card { display: block; background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 1rem 1.1rem; text-decoration: none; color: var(--text); transition: border-color 0.15s, background 0.15s; }
.hiw-card:hover { border-color: var(--accent); background: var(--bg-hover); }
.hiw-head { display: flex; align-items: center; gap: 0.55rem; }
.hiw-ico { font-size: var(--fs-h2); flex: none; line-height: 1; }
.hiw-t { font-weight: 700; font-size: var(--fs-h3); }
.hiw-d { font-size: var(--fs-body); color: var(--text-mid); line-height: 1.5; margin-top: 0.5rem; }
.hiw-link { display: inline-block; margin-top: 0.5rem; font-size: var(--fs-body); font-weight: 700; color: var(--accent-light); }
@media (max-width: 560px) { .hiw-grid { grid-template-columns: 1fr; } }

/* Legacy header (hidden by nav.js) */
header { display: none; }

/* Loading / Empty / Error */

.loading-msg {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-muted);
  font-size: var(--fs-h4);
  display: none;
}

/* Archive filter controls (reuses the horse-page control styles) */
.archive-controls { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 1.1rem; align-items: center; }

/* Horses page */
.horse-controls { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 1.1rem; align-items: center; }
.horse-search-input {
  flex: 1 1 260px; min-width: 200px; padding: 0.6rem 0.8rem; font-size: var(--fs-h4);
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; color: var(--text);
}
.horse-search-input:focus, .horse-filter:focus { outline: none; border-color: var(--accent); }
.horse-filter {
  padding: 0.55rem 0.7rem; font-size: var(--fs-body); cursor: pointer;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; color: var(--text);
}
/* Render the native date picker + calendar popup in dark mode and make the
   calendar icon clearly visible on the dark theme. */
input[type="date"].horse-filter { color-scheme: dark; }
input[type="date"].horse-filter::-webkit-calendar-picker-indicator {
  filter: invert(0.65); cursor: pointer; opacity: 0.9;
}
.horse-check {
  display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--fs-body);
  color: var(--text-muted); background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 8px; padding: 0.5rem 0.7rem; cursor: pointer;
}
.horse-check input { accent-color: var(--accent); }
.horse-layout { display: grid; grid-template-columns: 280px 1fr; gap: 1.25rem; align-items: start; }

/* ── Race-type colour coding (library) ───────────────────────────────────────
   Reusable helpers so every surface shows race types consistently. Apply
   .rt-<code> to expose the type colour as --rt-c, then use --rt-c for borders,
   text, dots, fills. .rt-dot renders the standalone colour swatch. */
.rt-horse   { --rt-c: var(--type-horse); }
.rt-grey    { --rt-c: var(--type-grey); }
.rt-harness { --rt-c: var(--type-harness); }
.rt-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--rt-c, var(--text-dim)); flex-shrink: 0; vertical-align: middle; }
.rt-border-left { border-left: 3px solid var(--rt-c, var(--border)); }

/* Home "Today's meetings" matrix filters (AU / trials) beside the code tabs. */
.board-filters { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.1rem 0 0.85rem; }
/* Day page: race-type filter + AU/trials toggles on one row. */
.race-filter-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.25rem; margin-bottom: 1.1rem; }
.race-filter-row > #raceFilters { flex: 1 1 320px; }
.race-filter-row .race-filter-bar { margin-bottom: 0; }

/* Mobile: filter chips fill the row evenly (equal thirds) with compensated font
   sizing so the labels still fit; day-page filter row stacks vertically. */
@media (max-width: 640px) {
  .race-filter-bar { gap: 0.3rem; }
  .race-filter-bar .jh-chip { padding: 0.42rem 0.25rem; font-size: var(--fs-sm); }
  .rf-chip[data-type] { gap: 0.3rem; }
  .rf-chip[data-type]::before { width: 7px; height: 7px; }
  /* #202-followup: lay the toggles out as a neat 2-column grid so the switches line
     up in columns instead of trailing each label at a different offset. */
  .board-filters .toggle-stack, .race-filter-row #raceToggles .toggle-stack {
    display: grid; grid-template-columns: 1fr 1fr; align-items: center; margin-left: 0; gap: 0.5rem 1rem;
  }
  .board-filters .toggle-stack .toggle-label, .race-filter-row #raceToggles .toggle-stack .toggle-label {
    justify-content: space-between; width: 100%;
  }
  /* Stack the type filter over the toggles. Reset the 320px flex-basis — in a
     column it would apply to height and force a big gap. */
  .race-filter-row { flex-direction: column; align-items: stretch; gap: 0.5rem; }
  .race-filter-row > #raceFilters { flex: 0 0 auto; }
  .toggle-text { font-size: var(--fs-sm); }
}
@media (max-width: 380px) {
  .race-filter-bar .jh-chip { font-size: var(--fs-xs); padding: 0.42rem 0.15rem; }
}

/* Reusable race filter bar (UI.raceFilters) — chips reuse the .jh-chip look and
   share equal width, evenly dividing the full bar width. */
/* Chips dynamically size to the bar width — equal share of whatever the content
   width is, so the filter reads well on both mobile and desktop. */
.race-filter-bar { display: flex; flex-wrap: nowrap; align-items: stretch; gap: 0.4rem; margin-bottom: 1.1rem; }
.race-filter-bar .jh-chip { flex: 1 1 0; min-width: 0; overflow: hidden; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; text-align: center; white-space: nowrap; }
/* Labels truncate rather than force the bar to wrap or overflow — chips always
   shrink to fit a single row at any width. */
.race-filter-bar .rf-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Colour-code the type chips (no icons): a coloured dot + matching active fill. */
.rf-chip[data-type]::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--rt-c, var(--text-dim)); flex-shrink: 0; }
.rf-chip[data-type="horse"]   { --rt-c: var(--type-horse); }
.rf-chip[data-type="grey"]    { --rt-c: var(--type-grey); }
.rf-chip[data-type="harness"] { --rt-c: var(--type-harness); }
.rf-chip[data-type].active { border-color: var(--rt-c); color: var(--text); background: color-mix(in srgb, var(--rt-c) 16%, transparent); }

/* Flat, cross-code race list (UI-driven full day list). */
.all-races-list { display: flex; flex-direction: column; gap: 0.22rem; }
/* Grouped-by-track view: a track header above each track's rows. */
.arl-group { margin-bottom: 0.9rem; }
.arl-group-head {
  display: flex; align-items: center; gap: 0.4rem; padding: 0.3rem 0.2rem 0.4rem;
  font-weight: 800; font-size: var(--fs-h4); color: var(--text);
}
.arl-group-count { font-weight: 600; font-size: var(--fs-sm); color: var(--text-dim); }
.arl-group .arl-row { margin-bottom: 0.3rem; }

.arl-row {
  display: flex; align-items: center; gap: 0.55rem; padding: 0.32rem 0.7rem; font-size: var(--fs-body);
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 7px;
  text-decoration: none; color: var(--text);
}
.arl-row:hover { border-color: var(--accent); background: var(--bg-hover); }
.arl-row.arl-abn { opacity: 0.6; }
/* Colour-code the race type (no icons): each row expose its type colour as --rt-c
   and themes to it — left accent, subtle tinted background, and coloured time —
   so it's obvious which race type you're viewing. */
.arl-row.arl-horse   { --rt-c: var(--type-horse); }
.arl-row.arl-grey    { --rt-c: var(--type-grey); }
.arl-row.arl-harness { --rt-c: var(--type-harness); }
.arl-row.arl-horse, .arl-row.arl-grey, .arl-row.arl-harness {
  border-left: 4px solid var(--rt-c);
  background: color-mix(in srgb, var(--rt-c) 8%, var(--bg-card));
}
.arl-row.arl-horse:hover, .arl-row.arl-grey:hover, .arl-row.arl-harness:hover {
  border-color: var(--rt-c);
  background: color-mix(in srgb, var(--rt-c) 16%, var(--bg-card));
}
.arl-time { font-family: var(--mono); font-weight: 800; color: var(--rt-c, var(--accent-light)); flex-shrink: 0; width: 66px; font-size: var(--fs-xs); white-space: nowrap; }
.arl-num { font-weight: 800; color: var(--text-muted); flex-shrink: 0; width: 32px; }
.arl-track { font-weight: 700; flex-shrink: 0; min-width: 120px; }
/* Desktop: transparent wrapper so track/name/meta stay direct flex children. */
.arl-main { display: contents; }
.arl-name { flex: 1; min-width: 0; color: var(--text-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arl-meta { color: var(--text-dim); font-size: var(--fs-sm); flex-shrink: 0; white-space: nowrap; }
.arl-status { flex-shrink: 0; margin-left: auto; }
@media (max-width: 640px) {
  /* Stack track + race name on two lines so the race is identifiable, not just the
     track. Time stays left, status right. */
  .arl-main { display: flex; flex-direction: column; gap: 0.05rem; flex: 1 1 auto; min-width: 0; }
  .arl-main > span { flex: 0 0 auto; min-width: 0; }
  .arl-track { min-width: 0; font-size: var(--fs-sm); }
  .arl-name { display: block; font-size: var(--fs-sm); }
  .arl-meta { display: none; }
}

/* Race matrix (UI.raceMatrix) — meetings down the left, races across the top,
   tightly aligned by race number. Colour-coded by race type. Sticky venue col. */
.race-matrix {
  display: grid;
  /* Fixed race-column width so cells NEVER compress — the grid overflows and the
     container scrolls horizontally instead of cramming R#/time into 50px. The venue
     column is sticky (below) so it stays visible while the races scroll. */
  grid-template-columns: minmax(150px, 210px) repeat(var(--rm-cols, 1), 64px);
  gap: 4px; overflow-x: auto; background: var(--border); border: 1px solid var(--border);
  border-radius: 8px; font-size: var(--fs-sm);
  /* No visible scrollbar — pan by grab-dragging (mouse) or swiping (touch). */
  scrollbar-width: none; cursor: grab;
}
.race-matrix::-webkit-scrollbar { display: none; }
.race-matrix.rm-grabbing { cursor: grabbing; user-select: none; }
.race-matrix.rm-grabbing a { cursor: grabbing; }
.rm-corner, .rm-colhead { background: var(--bg); }
.rm-corner { position: sticky; left: 0; z-index: 3; } /* above the sticky venue */
.rm-colhead { text-align: center; font-weight: 800; color: var(--text-muted); padding: 0.35rem 0.2rem; }
.rm-venue {
  display: flex; align-items: center; gap: 0.4rem; padding: 0.7rem 0.55rem;
  background: var(--bg-card); border-left: 3px solid var(--rt-c, var(--border));
  text-decoration: none; color: var(--text); font-weight: 700;
  /* z-index 2: the sticky venue must paint ABOVE in-cell absolute content (the AI
     marker .rmc-ai sits at z-index 1) or badges bleed over the track name on scroll. */
  position: sticky; left: 0; z-index: 2;
  flex-wrap: wrap; row-gap: 0.3rem;
}
/* Forces the coverage tag onto its own line under the track name. */
.rm-vbreak { flex-basis: 100%; height: 0; margin: 0; }
/* Wrap the track name to up to two lines (then ellipsis) so it stays readable
   instead of being cut off — matters most in the narrow mobile venue column. */
.rm-venue-name { min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; }
a.rm-venue:hover { background: var(--bg-hover); }
.rm-cell {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  padding: 0.6rem 0.35rem; background: var(--bg-card);
  border-top: 2px solid var(--rt-c, transparent); text-decoration: none; color: var(--text);
}
a.rm-cell:hover { background: var(--bg-hover); }
.rm-cell.rm-empty { background: transparent; border-top-color: transparent; }
/* Races with an AI prediction: soft accent tint + an accent-coloured race number,
   reinforced by a labelled "AI" corner tag (#169) so the signal survives without colour. */
.rm-cell.rm-pred { background: color-mix(in srgb, var(--accent) 9%, var(--bg-card)); }
a.rm-cell.rm-pred:hover { background: color-mix(in srgb, var(--accent) 16%, var(--bg-card)); }
.rm-cell.rm-pred .rmc-num { color: var(--accent-light); }
/* #169 labelled "AI" corner tag on a predicted race cell — a shape+text marker that
   reads without relying on the tint (colour-blind safe), replacing the old colour-only dot. */
.rmc-ai {
  position: absolute; top: 2px; right: 2px; z-index: 1;
  font-size: 8px; font-weight: 800; letter-spacing: 0.04em; line-height: 1;
  padding: 2px 3px; border-radius: 3px;
  background: var(--accent-btn); color: var(--on-accent);
}
/* Count of AI-predicted races beside the track/venue name. */
.rm-venue-preds {
  flex-shrink: 0; margin-left: auto; font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.02em;
  color: var(--accent-light); background: color-mix(in srgb, var(--accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); border-radius: 5px; padding: 0.05rem 0.3rem;
}
/* #430 specials marker on a matrix cell — bottom-left so it never collides with .rmc-ai (top-right). */
.rmc-special {
  position: absolute; bottom: 2px; left: 2px; z-index: 1;
  font-size: 9px; font-weight: 800; line-height: 1; padding: 1px 3px; border-radius: 3px;
  background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent-light);
}
/* #430 race-page hero special pill. */
.hero-special { margin-top: 0.4rem; }
.special-badge {
  display: inline-flex; align-items: center; gap: 0.2rem;
  font-size: var(--fs-sm); font-weight: 700; text-decoration: none;
  color: var(--accent-light); background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 999px; padding: 0.12rem 0.55rem;
}
.special-badge:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.rmc-num { font-weight: 700; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1; }
.rmc-time { font-family: var(--mono); font-size: var(--fs-xs); color: var(--accent-light); line-height: 1.1; white-space: nowrap; }
.rm-cell.rm-resulted { opacity: 0.5; }
.rm-cell.rm-abn { opacity: 0.4; }
/* Uncoverable meeting (not in TAB, never settled) — dim the whole row, no tips. */
.rm-venue.rm-uncov, .rm-cell.rm-uncov { opacity: 0.45; }
.rm-venue-tag { flex-shrink: 0; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; border-radius: 5px; padding: 0.05rem 0.3rem; margin-left: 0.35rem; white-space: nowrap; }
.rm-tag-uncov { color: var(--text-dim); background: rgba(157,161,184,0.14); border: 1px solid var(--border); }
.rm-tag-delay { color: var(--win); background: rgba(var(--win-rgb), 0.12); border: 1px solid rgba(var(--win-rgb), 0.3); }
/* Race-page coverage badge (in the hero badge row) + identifier banner */
.hero-cov { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; border-radius: 999px; padding: 0.12rem 0.5rem; white-space: nowrap; }
.hero-cov-uncov { color: var(--text-dim); background: rgba(157,161,184,0.14); border: 1px solid var(--border); }
.hero-cov-delay { color: var(--win); background: rgba(var(--win-rgb), 0.12); border: 1px solid rgba(var(--win-rgb), 0.3); }
.race-cov-note { margin-top: 0.75rem; padding: 0.6rem 0.9rem; border-radius: 8px; font-size: var(--fs-body); line-height: 1.45; }
.race-cov-uncov { color: var(--text-mid); background: rgba(157,161,184,0.1); border: 1px solid var(--border); border-left: 3px solid var(--text-dim); }
.race-cov-delay { color: var(--win); background: rgba(var(--win-rgb), 0.08); border: 1px solid rgba(var(--win-rgb), 0.25); border-left: 3px solid var(--win); }
.rm-cell.rm-abn .rmc-time { text-decoration: line-through; }
.rm-cell.rm-live .rmc-time { color: var(--green); }
@media (max-width: 640px) {
  /* Roomier cells on mobile so the matrix isn't cramped — it scrolls
     horizontally (as intended) rather than squeezing every race into view. */
  .race-matrix {
    grid-template-columns: minmax(136px, 1.5fr) repeat(var(--rm-cols, 1), minmax(58px, 1fr));
    font-size: var(--fs-sm); -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
  }
  .rm-venue { padding: 0.7rem 0.55rem; scroll-snap-align: start; }
  .rm-cell { padding: 0.7rem 0.4rem; gap: 3px; }
  .rmc-num { font-size: var(--fs-xs); }
  .rmc-time { font-size: var(--fs-sm); }
}
/* Stats page tabs */
.stat-tabs {
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
}
.stat-tab {
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: var(--fs-body); font-weight: 600;
  padding: 0.55rem 0.9rem; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.stat-tab:hover { color: var(--text); }
.stat-tab.active { color: var(--accent-light); border-bottom-color: var(--accent); }

/* Sample prompt display */
.prompt-block { margin-top: 0.9rem; }
.prompt-label {
  font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--text-dim); margin-bottom: 0.35rem;
}
.prompt-pre {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  padding: 0.75rem 0.85rem; margin: 0; max-height: 60vh; overflow: auto;
  font-family: var(--mono); font-size: var(--fs-sm); line-height: 1.5; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
}
/* Code toggle for the Sample Prompt panel (Thoroughbred / Greyhound / Harness) */
.prompt-codes .pill {
  padding: 0.3rem 0.7rem; border-radius: 999px; cursor: pointer;
  background: var(--bg-card); border: 1px solid var(--border); color: var(--text-dim);
  font-size: var(--fs-sm); font-weight: 600;
}
.prompt-codes .pill:hover { color: var(--text); border-color: var(--accent-light); }
.prompt-codes .pill-on {
  background: rgba(var(--accent-rgb), 0.15); border-color: var(--accent-light); color: var(--text);
}

/* Backtest table */
.bt-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); margin-top: 0.5rem; }
.bt-table th, .bt-table td {
  padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--border); text-align: left;
}
.bt-table th { color: var(--text-dim); font-weight: 600; font-size: var(--fs-sm); }
.bt-table .bt-num { text-align: right; font-family: var(--mono); }
.bt-table tr.bt-best td { color: var(--accent-light); font-weight: 700; }

/* ── Component library: shared data table / buttons / badges (UI.*) ─────────── */
/* Horizontal-scroll wrapper so wide tables scroll instead of overflowing the
   page on mobile. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-wrap .data-table { min-width: 480px; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
.data-table th { text-align: left; color: var(--text-dim); font-weight: 600; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.03em; padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--border); }
.data-table td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tbody tr:hover { background: rgba(var(--accent-rgb), 0.05); }
.data-table .dt-num { text-align: right; font-family: var(--mono); }
.data-table .dt-muted { color: var(--text-muted); }
.data-table .dt-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }

/* a11y (#168): fill is #6a5ad4 so white text clears WCAG AA (5.22:1; var(--accent)
   #7c6cf0 was only 3.99:1). Shared 44px min hit-area on standalone buttons below. */
/* #416 .btn-primary was `background: #6a5ad4` — a LITERAL. The main button was the same purple
   in every theme, including both palette trials, which is a large part of why they read as
   "barely any change". It now follows the tokens like everything else.
   --on-accent (not #fff) because a light accent needs DARK text: white on the mint is 1.62:1. */
.btn-primary { background: var(--accent-btn); color: var(--on-accent); border: none; padding: 0.35rem 0.9rem; font-weight: 600; font-size: var(--fs-body); border-radius: 7px; cursor: pointer; transition: background 0.15s, filter 0.15s; }
.btn-primary:hover { filter: brightness(0.92); }
/* One accessible hit-area for the standalone button family (compact .btn-sm opts down). */
.btn-primary, .btn-secondary, .btn-outline, .btn-danger, .hero-cta {
  min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
}
.btn-sm { min-height: 34px; }
.btn-block { width: 100%; }

/* Segmented control (UI.segmented) — code tabs for consolidated sections (#164). */
.segmented { display: flex; gap: 4px; padding: 4px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.segmented::-webkit-scrollbar { display: none; }
.seg-btn {
  flex: 1 0 auto; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.4rem 0.9rem; border: none; border-radius: 7px; background: transparent; color: var(--text-muted);
  font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer; white-space: nowrap; transition: background 0.15s, color 0.15s;
}
.seg-btn:hover { color: var(--text); background: var(--bg-hover); }
/* Active tab is tinted in the RACE-TYPE colour + outlined, matching the All-Races filter
   chips (.rf-chip.active) so race-type selection looks like one system everywhere. */
.seg-btn.active { background: color-mix(in srgb, var(--rt-c, var(--accent)) 20%, transparent); color: var(--text); box-shadow: inset 0 0 0 1.5px var(--rt-c, var(--accent)); }
.seg-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--rt-c, currentColor); }
.bb-dot-horse { --rt-c: var(--type-horse); }
.bb-dot-grey { --rt-c: var(--type-grey); }
.bb-dot-harness { --rt-c: var(--type-harness); }
.bb-tabs { margin-bottom: 0.8rem; }

/* Universal search box (UI.searchBox) — top nav + search page, one consistent look. */
.searchbox { position: relative; }
.sb-field { display: flex; align-items: center; gap: 6px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 8px; padding: 0 10px; height: 38px; }
.sb-field:focus-within { border-color: var(--accent); }
.sb-ico { width: 16px; height: 16px; color: var(--text-dim); flex-shrink: 0; }
.sb-input { flex: 1; min-width: 0; background: transparent; border: none; outline: none; color: var(--text); font: inherit; font-size: var(--fs-sm); }
.sb-input::placeholder { color: var(--text-dim); }
.sb-input::-webkit-search-cancel-button { -webkit-appearance: none; }
.sb-results {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 400;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; padding: 4px;
  box-shadow: 0 14px 36px -12px rgba(0,0,0,0.78); max-height: 62vh; overflow-y: auto;
}
.sb-results[hidden] { display: none; }
.sb-item { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 9px; padding: 8px; border-radius: 7px; text-decoration: none; color: var(--text); }
.sb-item:hover, .sb-item.active { background: var(--bg-hover); }
.sb-type { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; padding: 2px 7px; border-radius: 5px; white-space: nowrap; min-width: 62px; text-align: center; }
.sb-type-rt { background: color-mix(in srgb, var(--rt-c) 20%, transparent); color: var(--rt-c); }
.sb-type-plain { background: var(--bg-light); color: var(--text-muted); }
.sb-label { font-weight: 600; font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-sub { font-size: var(--fs-2xs); color: var(--text-dim); white-space: nowrap; }
.searchbox-compact .sb-field { height: 34px; }
@media (max-width: 560px) { .sb-item .sb-sub { display: none; } }

/* #171 Desktop persistent top-nav — the primary MENU items as a horizontal bar in the
   header top row, ≥900px only. Mobile keeps the drawer + bottom bar (below). The header
   hamburger stays on desktop for the full menu / betslip / account. */
.sh-nav { display: none; }
@media (min-width: 1100px) {
  .sh-nav { display: flex; align-items: center; gap: 1px; flex: 1 1 auto; min-width: 0; margin: 0 0.35rem; }
  .sh-nav .dn-item { position: relative; flex-shrink: 0; }
  .sh-nav .dn-link { display: inline-flex; align-items: center; gap: 3px; height: 34px; padding: 0 0.42rem; border-radius: 7px; color: #cfd2df; font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; text-decoration: none; cursor: pointer; }
  .sh-nav a.dn-link:hover, .sh-nav .dn-has-sub:hover > .dn-link, .sh-nav .dn-has-sub:focus-within > .dn-link { background: rgba(var(--overlay-rgb), 0.09); color: #fff; }
  .sh-nav .dn-item.active > .dn-link, .sh-nav a.dn-item.active { color: var(--accent-light); }
  .sh-nav .dn-caret { font-size: 0.65em; opacity: 0.7; }
  .sh-nav .dn-sub { display: none; position: absolute; top: 100%; left: 0; margin-top: 3px; min-width: 190px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; padding: 6px; box-shadow: 0 10px 30px -12px rgba(0,0,0,0.7); z-index: 260; }
  .sh-nav .dn-has-sub:hover > .dn-sub, .sh-nav .dn-has-sub:focus-within > .dn-sub { display: block; }
  .sh-nav .dn-sub-item { display: block; padding: 0.4rem 0.6rem; border-radius: 6px; color: var(--text-mid); font-size: var(--fs-sm); text-decoration: none; white-space: nowrap; }
  .sh-nav .dn-sub-item:hover { background: var(--bg-hover); color: var(--text); }
  .sh-nav .dn-heading { padding: 0.35rem 0.6rem 0.15rem; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim); }
  /* The persistent nav carries wayfinding now — trim the hamburger to an icon. */
  .site-header .ntb-label { display: none; }
}

/* #167 Mobile bottom tab bar — core tasks, thumb-reachable. Desktop keeps the drawer. */
.bottom-nav { display: none; }
@media (max-width: 1099px) {
  .bottom-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 200;
    background: var(--bg-card); border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .bn-tab {
    flex: 1; min-height: 54px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    padding: 6px 2px; color: var(--text-dim); text-decoration: none; font-size: var(--fs-2xs); font-weight: 600;
  }
  .bn-tab .bn-lbl { white-space: nowrap; } /* 5 tabs (#186): keep "Predictions" on one line */
  .bn-tab .bn-ico { line-height: 0; }
  .bn-tab .bn-ico svg { width: 23px; height: 23px; display: block; }
  .bn-tab.active { color: var(--accent-light); }
  .bn-tab:active { background: var(--bg-hover); }
  /* Keep page content clear of the fixed bar. */
  body { padding-bottom: calc(54px + env(safe-area-inset-bottom, 0px)); }
}

/* ── Sportsbet-style LEFT sidebar nav ─────────────────────────────────────────
   ≥1100px: the menu drawer is PINNED open as a fixed left sidebar and the page
   content is shifted right to sit beside it (no scrim / toggle). Below 1100px it
   stays a slide-out drawer opened by the bottom-bar ☰. (Placed after the --rail /
   body-padding rules so this wins for wide viewports.) */
@media (min-width: 1100px) {
  .top-nav { transform: translateX(0); box-shadow: none; }
  body { padding-left: var(--rail); }
  .nav-scrim { display: none; }
  /* The header already carries the logo + My Account, so drop the sidebar's copies. */
  .top-nav .tn-brand, .top-nav .tn-user-area { display: none; }
}
.btn-ico { display: inline-flex; align-items: center; line-height: 0; }
/* Link-buttons (UI.button with href) render as <a> — kill the underline, keep the box. */
a.btn-primary, a.btn-secondary, a.btn-outline, a.btn-danger { text-decoration: none; }
.btn-danger { background: transparent; color: var(--danger); border: 1px solid rgba(239, 83, 80, 0.4); padding: 0.3rem 0.75rem; font-weight: 600; font-size: var(--fs-sm); border-radius: 7px; cursor: pointer; }
.btn-danger:hover { background: rgba(239, 83, 80, 0.1); }
.btn-sm { font-size: var(--fs-sm) !important; padding: 0.25rem 0.6rem !important; }

.role-badge { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; padding: 0.12rem 0.5rem; border-radius: 4px; background: var(--bg); border: 1px solid var(--border); color: var(--text-mid); }
.role-badge.role-admin { background: rgba(var(--accent-rgb), 0.16); color: var(--accent-light); border-color: rgba(var(--accent-rgb), 0.4); }
.role-badge.role-analyst { background: rgba(var(--ew-rgb), 0.14); color: var(--ew); border-color: rgba(var(--ew-rgb), 0.4); }
.role-badge.role-viewer, .role-badge.role-user { background: var(--bg); color: var(--text-muted); }
.status-pill { font-size: var(--fs-sm); font-weight: 600; }
.status-pill.status-active { color: var(--ew); }
.status-pill.status-inactive { color: var(--text-dim); }

.horse-results { display: flex; flex-direction: column; gap: 0.3rem; max-height: 70vh; overflow-y: auto; }
.horse-result {
  display: flex; flex-direction: column; gap: 0.15rem; text-align: left; cursor: pointer;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem 0.7rem; color: inherit;
}
.horse-result:hover { border-color: var(--accent); }
.horse-result.active { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.1); }
.hr-name { font-weight: 600; font-size: var(--fs-h4); }
.hr-stats { color: var(--text-muted); font-size: var(--fs-sm); }
.horse-profile { min-height: 100px; }
.hp-head h2 { margin: 0 0 0.3rem; }
.hp-bio { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin-bottom: 0.4rem; font-size: var(--fs-body); }
.hp-bio-item { color: var(--text); }
.hp-bio-k { color: var(--text-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.03em; margin-right: 0.2rem; }
.hp-summary { color: var(--text-muted); font-size: var(--fs-body); margin-bottom: 0.5rem; }
.hp-section { margin: 1.1rem 0 0.5rem; font-size: var(--fs-h4); }
.hp-results { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
.hp-results th { text-align: left; color: var(--text-muted); font-weight: 600; padding: 0.3rem 0.5rem; border-bottom: 1px solid var(--border); }
.hp-results td { padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--border); }
.fin-win { color: var(--ew); font-weight: 700; }
.fin-place { color: var(--accent-light); font-weight: 600; }
.fin-other { color: var(--text-dim); }
.tip-hit { color: var(--ew); font-weight: 700; }
.tip-miss { color: #ef5350; }
.tip-pending { color: var(--text-dim); }
.hp-racelink { color: var(--accent-light); text-decoration: none; }
.hp-racelink:hover { text-decoration: underline; }
.hp-tipcount { font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); margin-left: 0.4rem; }
.runner-horse-link { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--text-dim); }
.runner-horse-link:hover { color: var(--accent-light); border-bottom-color: var(--accent); }
.note-add { display: flex; gap: 0.5rem; margin-bottom: 0.6rem; }
.note-add textarea { flex: 1; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; color: var(--text); padding: 0.5rem; resize: vertical; font: inherit; }
.note-add button {
  align-self: flex-start;
  background: var(--accent-btn); color: var(--on-accent); border: none;
  padding: 0.5rem 1.1rem; font-weight: 600; font-size: var(--fs-body);
  border-radius: 8px; cursor: pointer; transition: background 0.15s; white-space: nowrap;
}
.note-add button:hover { background: #5a4ac4; }
.note-add button:disabled { background: var(--border); color: var(--text-dim); cursor: not-allowed; }
.notes-list { display: flex; flex-direction: column; gap: 0.5rem; }
.note-item { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 0.55rem 0.7rem; }
.note-text { font-size: var(--fs-h4); white-space: pre-wrap; }
.note-meta { color: var(--text-muted); font-size: var(--fs-xs); margin-top: 0.3rem; }
.note-del { background: none; border: none; color: #ef5350; cursor: pointer; font-size: var(--fs-xs); margin-left: 0.4rem; }
@media (max-width: 720px) {
  .horse-layout { grid-template-columns: 1fr; }
  /* Single column on mobile: let the results list flow with the page instead of
     scrolling inside a capped box (which made the page feel unscrollable). */
  .horse-results { max-height: none; overflow: visible; }
}

/* Home page sections — match the standard .home-section rhythm used elsewhere */
.landing-section { margin-bottom: 1rem; }

/* Best Bets of the Day */
#bestBetsSection { margin-bottom: 1rem; }
.bb-subtitle { color: var(--text-muted); font-size: var(--fs-sm); }
.bb-bettype {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em;
  border-radius: 4px; padding: 0.08rem 0.32rem;
}
.bb-bt-win { background: rgba(var(--accent-rgb), 0.16); color: var(--accent-light); border: 1px solid rgba(var(--accent-rgb), 0.35); }
.bb-bt-ew  { background: rgba(var(--win-rgb), 0.16); color: var(--win); border: 1px solid rgba(var(--win-rgb), 0.35); }

/* Two rows (Win / Each-way), each with compact cards 4 across */
.bb-rows { display: flex; flex-direction: column; gap: 0.7rem; }
.bb-row-label {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 0.25rem;
}
.best-bets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.6rem; }
.bb-card {
  display: flex; flex-direction: column; gap: 0.22rem;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 0.6rem 0.7rem; text-decoration: none; color: inherit;
  transition: border-color 0.15s, background 0.15s;
}
.bb-card:hover { border-color: var(--accent); background: var(--bg-hover); }
.bb-top { display: flex; align-items: center; gap: 0.35rem; }
.bb-top .bb-prob { margin-left: auto; }
/* #93 low-confidence flag on a best bet */
.bb-lowconf { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--win); border: 1px solid var(--win); border-radius: 999px; padding: 0.05rem 0.4rem; margin-left: 0.4rem; white-space: nowrap; }
.bb-rank {
  width: 18px; height: 18px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(var(--accent-rgb), 0.15); color: var(--accent-light); font-weight: 700; font-size: var(--fs-xs);
}
.bb-tag {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em;
  background: rgba(var(--ew-rgb), 0.16); color: var(--ew);
  border: 1px solid rgba(var(--ew-rgb), 0.35); border-radius: 4px; padding: 0.05rem 0.3rem;
}
.bb-prob { font-family: var(--mono); font-weight: 800; font-size: var(--fs-h3); color: var(--text); line-height: 1; }
.bb-horse { font-weight: 700; font-size: var(--fs-h4); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bb-race { color: var(--text-muted); font-size: var(--fs-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bb-status {
  margin-top: 0.2rem; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em;
  text-align: center; border-radius: 4px; padding: 0.08rem 0.25rem;
}
.bb-status-win   { background: rgba(var(--ew-rgb), 0.16); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.4); }
.bb-status-place { background: rgba(var(--accent-rgb), 0.16); color: var(--accent-light); border: 1px solid rgba(var(--accent-rgb), 0.35); }
.bb-status-miss  { background: rgba(239,83,80,0.14); color: #ef5350; border: 1px solid rgba(239,83,80,0.3); }
.bb-status-awaiting, .bb-status-upcoming { background: rgba(var(--overlay-rgb), 0.05); color: var(--text-dim); border: 1px solid var(--border); }
/* Dim resulted cards slightly so upcoming tips stand out */
.bb-card.bb-win, .bb-card.bb-place, .bb-card.bb-miss { opacity: 0.85; }
@media (max-width: 760px) { .best-bets { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .best-bets { grid-template-columns: 1fr; } }

/* Compact best bets (day page): tight single-line clickable rows */
.bbc-rows { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem 1.25rem; }
.bbc-group .bb-row-label { margin-bottom: 0.35rem; }
.bbc-list { display: flex; flex-direction: column; gap: 0.3rem; }
.bbc-row {
  display: grid; grid-template-columns: 34px 1fr auto auto; align-items: center;
  gap: 0.5rem; padding: 0.4rem 0.55rem; border: 1px solid var(--border);
  border-radius: 7px; background: var(--bg-card); text-decoration: none; color: var(--text);
}
.bbc-row:hover { border-color: var(--accent); background: var(--bg-hover); }
.bbc-bt { grid-column: 1; grid-row: 1 / span 2; align-self: center; font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.03em; text-align: center; padding: 0.12rem 0; border-radius: 4px; }
.bbc-horse { font-weight: 700; font-size: var(--fs-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bbc-race { grid-column: 2; font-size: var(--fs-xs); color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bbc-prob { grid-column: 3; grid-row: 1 / span 2; align-self: center; font-weight: 800; font-size: var(--fs-h4); color: var(--accent-light); }
.bbc-status { grid-column: 4; grid-row: 1 / span 2; align-self: center; font-size: var(--fs-2xs); font-weight: 700; padding: 0.12rem 0.4rem; border-radius: 4px; white-space: nowrap; }
.bbc-row.bb-win, .bbc-row.bb-place, .bbc-row.bb-miss { opacity: 0.85; }
@media (max-width: 760px) { .bbc-rows { grid-template-columns: 1fr; } }

/* Race page loading animation (spinner + shimmer skeleton) */
.race-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  padding: 2.5rem 1rem 1.5rem;
  color: var(--text-muted);
  font-size: var(--fs-h4);
}
.race-loading .loader {
  width: 38px; height: 38px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
.skeleton-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.skeleton-card {
  height: 62px;
  border-radius: 10px;
  background: var(--bg-card);
  position: relative;
  overflow: hidden;
}
.skeleton-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(var(--overlay-rgb), 0.06) 50%, transparent 100%);
  transform: translateX(-100%);
  animation: shimmer 1.4s ease-in-out infinite;
}
@keyframes shimmer { 100% { transform: translateX(100%); } }

/* #301 Skeleton placeholders (reuse the shimmer) — reserve async sections' height, no CLS. */
.skel { position: relative; overflow: hidden; background: var(--bg-card); border-radius: 8px; display: inline-block; }
.skel::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent 0%, rgba(var(--overlay-rgb), 0.06) 50%, transparent 100%); transform: translateX(-100%); animation: shimmer 1.4s ease-in-out infinite; }
.skel-pills { display: flex; gap: 0.4rem; overflow: hidden; }
.skel-pills .skel-pill { width: 46px; height: 46px; border-radius: 10px; flex: 0 0 auto; }
.skel-hero { display: flex; flex-direction: column; gap: 0.6rem; min-height: 110px; padding: 0.3rem 0; }
.skel-hero .skel-line { height: 16px; border-radius: 6px; display: block; width: 100%; }
.skel-hero .skel-line-lg { height: 24px; width: 62%; }
.skel-hero-grid { display: flex; gap: 0.9rem; }
.skel-hero-grid .skel-cell { width: 64px; height: 34px; border-radius: 8px; }
.skel-tip { display: flex; flex-direction: column; gap: 0.5rem; min-height: 96px; padding: 0.6rem; }
.skel-tip .skel-line { height: 16px; border-radius: 6px; display: block; width: 100%; }
.skel-tip .skel-line-lg { height: 26px; width: 55%; }
.skel-tip .skel-line-sm { height: 12px; width: 28%; }

/* #301 Race-page condensed sticky header — the compact one-line core details, hidden until
   the hero condenses on scroll (mobile). Toggled on the #raceHero container. */
.hero-condensed { display: none; gap: 0.5rem; flex-wrap: wrap; align-items: center; font-weight: 700; font-size: var(--fs-sm); }
#raceHero.condensed .hero-condensed { display: flex; }
#raceHero.condensed .hero-top,
#raceHero.condensed .hero-name,
#raceHero.condensed .race-info-grid,
#raceHero.condensed .hero-tags,
#raceHero.condensed .race-cov-note { display: none; }

/* #301 / #341: pin the race-nav pills + race-details card under the site header while
   scrolling; the hero condenses (above) once scrolled past. #301 shipped this for mobile;
   #341 extends it to DESKTOP too (the header height --header-h is the same sticky anchor on
   both — the right rail already sticks at that offset), so desktop gets the same pinned
   race navigation + minimised hero card. */
.meet-nav-row { position: sticky; top: var(--header-h); z-index: 30; background: var(--bg); padding: 0.35rem 0 0.25rem; }
#raceHero { position: sticky; top: calc(var(--header-h) + var(--race-pills-h, 58px)); z-index: 29; background: var(--bg); border-bottom: 1px solid var(--border); }
#raceHero.condensed { padding: 0.3rem 0.1rem; }
#raceHero.condensed .race-hero { padding-top: 0.15rem; padding-bottom: 0.15rem; }

.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-muted);
  font-size: var(--fs-h4);
}

.error-msg {
  display: none;
  max-width: 1380px;
  margin: 1rem auto;
  padding: 0.75rem 1rem;
  background: rgba(var(--danger-rgb), 0.08);
  border: 1px solid rgba(var(--danger-rgb), 0.2);
  border-radius: var(--radius);
  color: var(--danger);
  font-size: var(--fs-body);
}

/* Page Layout with Sidebar */

.page-layout {
  display: flex;
  max-width: 1380px;
  margin: 0 auto;
  min-height: calc(100vh - 80px);
}

.nav-sidebar {
  width: 190px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  padding: 0.75rem 0;
  position: sticky;
  top: 64px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
}

.ns-section {
  padding: 0.25rem 0 0.6rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.4rem;
}

.ns-section:last-child { border-bottom: none; }

.ns-heading {
  font-size: var(--fs-2xs);
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0.25rem 0.75rem 0.35rem;
}

.ns-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.4rem 0.75rem;
  font-size: var(--fs-sm);
  color: var(--text-mid);
  transition: background 0.12s;
  border-left: 3px solid transparent;
}

.ns-link:hover { background: var(--bg-hover); color: var(--text); }
.ns-link.active { background: var(--bg-hover); border-left-color: var(--accent); color: var(--text); font-weight: 600; }

.ns-count {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  background: var(--bg);
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
}

.ns-accuracy {
  padding: 0.25rem 0.75rem;
}

.ns-acc-loading, .ns-acc-empty {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.acc-stat {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.2rem 0;
}

.acc-label {
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.acc-value {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text-mid);
}

.acc-value.acc-good { color: var(--green); }
.acc-value.acc-low { color: var(--text-muted); }

.acc-divider {
  height: 1px;
  background: var(--border);
  margin: 0.3rem 0;
}

.page-main {
  flex: 1;
  min-width: 0;
  padding: 0.75rem var(--page-pad-x) 2rem;
}

/* Landing Page */

.landing {
  max-width: 1380px;
  margin: 0 auto;
  padding: 0 1rem 2rem;
}

.landing-hero {
  text-align: center;
  padding: 2.5rem 1.5rem 2rem;
  background:
    radial-gradient(120% 140% at 50% -20%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 60%),
    var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 16px;
  margin-bottom: 1rem;
}
/* #166 slim hero for the task-first (logged-in) home — a compact brand strip above
   the picks, not a full marketing splash. */
.landing-hero-slim { padding: 1.4rem 1.5rem 1.5rem; }
.landing-hero-slim h2 { font-size: var(--fs-h2); margin-bottom: 0.9rem; }
.landing-hero-slim .hero-eyebrow { margin-bottom: 0.7rem; }
.hero-eyebrow {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: var(--fs-xs); font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--accent-light); background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 999px; padding: 0.2rem 0.7rem; margin-bottom: 0.9rem;
}

.landing-hero h2 {
  font-size: var(--fs-h1);
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--text);
  margin-bottom: 0.4rem;
}

.landing-hero p {
  font-size: var(--fs-h4);
  color: var(--text-muted);
  max-width: 560px;
  margin: 0 auto;
  line-height: 1.5;
}

.hero-stats {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.75rem;
  font-size: var(--fs-sm);
}

.hs-item { color: var(--text-mid); }
.hs-item.hs-good { color: var(--green); font-weight: 600; }
.hs-dot { color: var(--text-dim); }

/* International (non-Australian) race treatment — used site-wide */
.intl-badge {
  display: inline-block;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em;
  background: rgba(var(--ew-rgb), 0.16); color: var(--ew);
  border: 1px solid rgba(var(--ew-rgb), 0.4); border-radius: 4px;
  padding: 0.05rem 0.3rem; white-space: nowrap; vertical-align: middle;
}
.intl { border-left: 3px solid var(--ew); }
/* Trial / jump-out badge — same shape as the intl badge, amber to stand apart. */
.trial-badge {
  display: inline-block;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.03em;
  background: rgba(var(--win-rgb), 0.16); color: var(--win);
  border: 1px solid rgba(var(--win-rgb), 0.4); border-radius: 4px;
  padding: 0.05rem 0.3rem; white-space: nowrap; vertical-align: middle;
}

/* Hero benefit chips */
.hero-benefits {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
}
.hb-chip {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-mid);
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
}

/* Hero CTA row — primary + ghost secondary. */
.hero-ctas { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.25rem; }
.hero-cta-ghost { background: transparent; color: var(--accent-light); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
.hero-cta-ghost:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* Landing — mobile space savers: hide the hero benefit chips, show only the
   scorecard rings (no per-type breakdown/header), and show only the how-it-works
   headings (icon + title), hiding their descriptions. */
@media (max-width: 640px) {
  .hero-benefits { display: none; }
  .perf-card .ps-head, .perf-card .ps-types { display: none; }
  .perf-card .ps-gauges { padding-top: 0; }
  .hiw-card .hiw-d, .hiw-card .hiw-link { display: none; }
}

/* Hero call-to-action */
.hero-cta {
  display: inline-block;
  margin-top: 1.1rem;
  background: var(--accent-btn);
  color: var(--on-accent);
  font-weight: 700;
  font-size: var(--fs-h4);
  padding: 0.6rem 1.3rem;
  border-radius: 9px;
  text-decoration: none;
  transition: background 0.15s, transform 0.1s;
}
.hero-cta:hover { background: #5a4ac4; }
.hero-cta:active { transform: translateY(1px); }

/* Next-to-jump strip */
.next-races {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.6rem;
}
.nr-card {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.6rem 0.75rem;
  text-decoration: none;
  transition: border-color 0.12s, background 0.12s;
}
.nr-card:hover { border-color: var(--accent); background: var(--bg-hover); }
.nr-countdown {
  font-family: var(--mono);
  font-size: var(--fs-h3);
  font-weight: 800;
  color: var(--accent-light);
}
.nr-course { font-size: var(--fs-body); font-weight: 600; color: var(--text); }
.nr-rno { color: var(--text-muted); font-weight: 600; }
.nr-time { font-size: var(--fs-xs); color: var(--text-dim); display: flex; align-items: center; gap: 0.35rem; }
.nr-ai {
  background: rgba(var(--accent-rgb), 0.18); color: var(--accent-light);
  font-weight: 700; font-size: var(--fs-2xs); padding: 0.05rem 0.3rem; border-radius: 4px;
}
.nr-code { margin-right: 0.15rem; }
.nr-card.nr-grey { border-left: 3px solid var(--green); }
.nr-card.nr-horse { border-left: 3px solid var(--accent); }

/* Code tabs + today's meetings board (home) */
.code-tabs { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.9rem; border-bottom: 1px solid var(--border); }
.code-tab {
  background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
  padding: 0.5rem 0.9rem; font-family: var(--font); font-size: var(--fs-h4); font-weight: 700;
  color: var(--text-dim); cursor: pointer;
}
.code-tab:hover { color: var(--text); }
.code-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.code-tab-soon { opacity: 0.5; cursor: default; }
.board-region { margin-bottom: 1.1rem; }
.board-region-h { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-dim); margin-bottom: 0.5rem; }
.board-region-n { color: var(--text-muted); }
.board-meet { display: grid; grid-template-columns: 150px 1fr; gap: 0.6rem; align-items: center; padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
.board-meet-name { font-size: var(--fs-h4); font-weight: 700; color: var(--text); text-decoration: none; display: flex; align-items: center; gap: 0.35rem; }
.board-meet-name:hover { color: var(--accent-light); }
.board-pills { display: flex; flex-wrap: wrap; gap: 0.35rem; }
/* Uncoverable race/meeting (not in TAB, never settled) — dimmed, no tips possible. */
.arl-row.arl-uncov { opacity: 0.5; }
.status-badge.sb-uncov { background: rgba(157,161,184,0.14); color: var(--text-dim); border: 1px solid var(--border); }
.status-badge.sb-delay { background: rgba(var(--win-rgb), 0.12); color: var(--win); border: 1px solid rgba(var(--win-rgb), 0.3); }
/* Uncoverable meeting (not in TAB) — dimmed, results can't be recorded, no tips. */
.board-meet-uncov { opacity: 0.5; }
.board-meet-uncov .board-meet-name { color: var(--text-muted); font-weight: 600; }
.uncov-tag { font-size: var(--fs-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim); border: 1px solid var(--border); border-radius: 999px; padding: 0.05rem 0.45rem; white-space: nowrap; }
@media (max-width: 640px) { .board-meet { grid-template-columns: 1fr; gap: 0.3rem; } }

/* Week Matrix */

.week-matrix {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.wm-day {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.wm-day-today {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.wm-day-today .wm-day-header {
  background: rgba(var(--accent-rgb), 0.12);
  border-bottom-color: rgba(var(--accent-rgb), 0.25);
}

.wm-day-today .wm-day-label {
  color: var(--accent-light);
}

.wm-day-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  background: rgba(var(--accent-rgb), 0.04);
  border-bottom: 1px solid var(--border);
}

.wm-day-label {
  font-size: var(--fs-body);
  font-weight: 700;
  color: var(--text);
}

.wm-day-date {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.wm-meets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0.5rem 0.75rem;
}

.wm-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: border-color 0.12s, background 0.12s;
}

.wm-chip:hover { border-color: var(--accent); background: var(--bg-hover); }
.wm-chip.wm-abn { opacity: 0.4; }
.wm-chip.wm-done { border-left: 2px solid var(--green); }

.wm-course {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

.wm-info {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.wm-badges {
  display: flex;
  gap: 0.2rem;
}

.wm-loading, .wm-empty {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  padding: 0.2rem 0;
}

/* Landing Cards */

.landing-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.6rem;
  margin-top: 1.25rem;
}

.lc-card {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.85rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color 0.12s, background 0.12s;
}

.lc-card:hover { border-color: var(--accent); background: var(--bg-hover); }

.lc-icon { font-size: var(--fs-h1); }

.lc-text {
  display: flex;
  flex-direction: column;
}

.lc-text strong { font-size: var(--fs-body); color: var(--text); }
.lc-text span { font-size: var(--fs-xs); color: var(--text-dim); }

/* Homepage Layout */

.home-section {
  margin-bottom: 1rem;
}

.home-section-primary {
  margin-bottom: 1.25rem;
}

.section-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.toggle-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  font-size: var(--fs-sm);
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
}
.toggle-label input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 2.2rem;
  height: 1.2rem;
  background: var(--border);
  border-radius: 1rem;
  position: relative;
  cursor: pointer;
  transition: background 0.2s;
  flex-shrink: 0;
}
.toggle-label input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  width: 0.9rem;
  height: 0.9rem;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s;
}
.toggle-label input[type="checkbox"]:checked {
  background: var(--accent);
}
.toggle-label input[type="checkbox"]:checked::after {
  transform: translateX(1rem);
}

.section-title {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
}

.section-date {
  font-size: var(--fs-sm);
  color: var(--text-dim);
}

/* Prominent day/date heading on the race-day page */
.day-heading { display: flex; flex-direction: column; gap: 0.1rem; }
.day-page-head { margin: 0.25rem 0 1rem; }
.day-heading .day-title { font-size: var(--fs-h1); font-weight: 800; line-height: 1.1; }
.day-heading .day-date { font-size: var(--fs-h3); font-weight: 600; color: var(--text); }
@media (max-width: 760px) {
  .day-heading .day-title { font-size: var(--fs-h2); }
  .day-heading .day-date { font-size: var(--fs-h4); }
}

/* Toggle switch */
.toggle-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  user-select: none;
}
/* #389 "Top pick" price filter — align its font/size with the race toggles (--fs-sm),
   not the larger default .jh-chip body size, so the filter row reads as one control set. */
.rt-userfilters { align-items: center; }
.rt-price-group { display: inline-flex; align-items: center; gap: 0.3rem; flex-wrap: wrap; font-size: var(--fs-sm); }
.rt-price-group .rf-label { font-size: var(--fs-sm); }
.rt-price-group .rf-chip { font-size: var(--fs-sm); padding: 0.2rem 0.45rem; }
/* Stacked toggles: sit underneath each other, flush to the right of the header,
   with the switch to the right of its label text for a neat aligned column. */
.toggle-stack {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem 1.1rem;
  margin-left: auto;
}
.toggle-stack .toggle-track { order: 1; }
.toggle-label input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.toggle-track {
  position: relative;
  width: 32px;
  height: 18px;
  background: var(--border);
  border-radius: 9px;
  transition: background 0.2s;
  flex-shrink: 0;
}
.toggle-label input:checked + .toggle-track {
  background: var(--accent);
}
.toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s;
}
.toggle-label input:checked + .toggle-track .toggle-thumb {
  transform: translateX(14px);
}
.toggle-text {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}

.empty-state-sm {
  font-size: var(--fs-body);
  color: var(--text-dim);
  padding: 0.6rem 0;
}

/* Status badges (shared) */

.status-badge {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  padding: 0.08rem 0.35rem;
  border-radius: 3px;
  letter-spacing: 0.3px;
}

.sb-abn { color: var(--danger); background: rgba(var(--danger-rgb), 0.1); }
.sb-delayed { color: #f59e0b; background: rgba(245,158,11,0.12); }
.sb-abn-partial { color: var(--win); background: rgba(var(--win-rgb), 0.1); }
.sb-result { color: var(--green); background: rgba(var(--green-rgb), 0.1); }
.sb-started { color: var(--win); background: rgba(var(--win-rgb), 0.1); }
.sb-pred { color: var(--accent-light); background: rgba(var(--accent-rgb), 0.1); }

/* Compact meet row (yesterday/tomorrow) */

.meets-compact {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

/* Upcoming / Next to Jump */

.upcoming-row {
  display: grid;
  /* minmax(0,1fr) lets the three tracks shrink below their content's intrinsic
     width so the cards resize dynamically to fit the cell (the nowrap detail line
     ellipsises) instead of overflowing it. Stacks to one column at the mobile
     breakpoint below. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.75rem;
}

.upcoming-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  transition: background 0.12s, border-color 0.12s;
  text-decoration: none;
}

.upcoming-card:hover { background: var(--bg-hover); border-color: var(--accent); }

.upcoming-card.upcoming-imminent { border-color: var(--win); }

.uc-countdown {
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--accent-light);
  min-width: 44px;
  text-align: center;
  flex-shrink: 0;
}

.uc-countdown.uc-imminent { color: var(--win); }

.uc-body { flex: 1; min-width: 0; }

.uc-course {
  font-size: var(--fs-h4);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.uc-detail {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin-top: 0.15rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.uc-badges { flex-shrink: 0; }

.upcoming-empty {
  color: var(--text-muted);
  font-size: var(--fs-body);
  padding: 0.5rem 0;
}

@media (max-width: 640px) {
  .upcoming-row { grid-template-columns: 1fr; }
}

.compact-meet {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: var(--bg-card);
  transition: background 0.12s;
}

.compact-meet:hover { background: var(--bg-hover); }
.compact-meet.cm-abandoned { opacity: 0.4; }

.cm-course {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text);
}

.cm-info {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-right: auto;
}

/* Full meet group (today) */

.meet-group {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 0.6rem;
}

.meet-group.mg-abandoned { opacity: 0.45; }

.mg-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.85rem;
  background: rgba(var(--accent-rgb), 0.04);
  border-bottom: 1px solid var(--border);
  transition: background 0.12s;
}

.mg-header:hover { background: rgba(var(--accent-rgb), 0.08); }

.mg-title { display: flex; align-items: baseline; gap: 0.5rem; }

.mg-course {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
}

.mg-meta {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.mg-badges {
  display: flex;
  gap: 0.3rem;
}

.mg-races {
  display: flex;
  flex-direction: column;
}

.race-nav-pill {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.8rem 1rem;
  border-top: 1px solid var(--border);
  transition: background 0.12s;
}

.race-nav-pill:first-child { border-top: none; }
.race-nav-pill:hover { background: var(--bg-hover); }
.race-nav-pill.rnp-abn { opacity: 0.4; }
.race-nav-pill.rnp-resulted { border-left: 2px solid var(--green); }

.rnp-num {
  font-family: var(--mono);
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--accent-light);
  min-width: 36px;
}

.rnp-time {
  font-family: var(--mono);
  font-size: var(--fs-body);
  color: var(--text-dim);
  min-width: 68px;
}

.rnp-name {
  font-size: var(--fs-h4);
  color: var(--text);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rnp-meta {
  font-size: var(--fs-body);
  color: var(--text-dim);
  white-space: nowrap;
}

.rnp-status {
  display: flex;
  gap: 0.25rem;
  min-width: 32px;
  justify-content: flex-end;
}

/* Archive link card */

.archive-link-card {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color 0.15s, background 0.15s;
}

.archive-link-card:hover { border-color: var(--accent); background: var(--bg-hover); }

.alc-icon { font-size: var(--fs-h2); }

.alc-text {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.alc-text strong { font-size: var(--fs-h4); color: var(--text); }
.alc-text span { font-size: var(--fs-xs); color: var(--text-dim); }
.alc-arrow { font-size: var(--fs-h3); color: var(--text-dim); }

/* Race Page Layout */

.race-layout {
  display: flex;
  max-width: 1380px; /* match the greyhound/harness page width (.page-main) so all three align */
  margin: 0 auto;
  min-height: calc(100vh - 80px);
}

.sidebar {
  width: 200px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  padding: 0.75rem 0;
  overflow-y: auto;
  position: sticky;
  top: 64px;
  max-height: calc(100vh - 48px);
}

.sidebar-heading {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0.25rem 0.75rem 0.5rem;
}

.sidebar-meets {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sidebar-meet {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  transition: background 0.12s;
  border-left: 3px solid transparent;
}

.sidebar-meet:hover { background: var(--bg-hover); }
.sidebar-meet.active { background: var(--bg-hover); border-left-color: var(--accent); }

.sm-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sm-info {
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  white-space: nowrap;
}

.sm-abandoned {
  font-size: var(--fs-2xs);
  font-weight: 700;
  color: var(--danger);
  background: rgba(var(--danger-rgb), 0.1);
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
}

/* Quaddie Section */

.quaddie-section {
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
  padding-top: 0.25rem;
}

.qd-leg {
  margin-bottom: 0.5rem;
}

.qd-leg-header {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--accent-light);
  padding: 0.2rem 0.75rem;
}

.qd-picks {
  display: flex;
  flex-direction: column;
}

.qd-pick {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.2rem 0.75rem;
  font-size: var(--fs-xs);
  border-left: 2px solid transparent;
}

.qd-pick.qd-win { border-left-color: var(--win); }
.qd-pick.qd-ew { border-left-color: var(--ew); }
.qd-pick.qd-top { font-weight: 700; }

.qd-pick-num {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--accent-light);
  min-width: 18px;
}

.qd-pick-name {
  color: var(--text);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.qd-pick-conf {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  flex-shrink: 0;
  margin-left: auto;
  margin-right: 0.3rem;
}

.qd-pick-score {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  flex-shrink: 0;
}

/* Meet Nav Row */

.meet-nav-row {
  display: flex;
  align-items: center;
  max-width: 1380px;
  margin: 0 auto 0.8rem;
  gap: 0.5rem;
}

.meet-nav-row .meet-nav { flex: 1; }

.quaddie-btn {
  flex-shrink: 0;
  background: rgba(var(--accent-rgb), 0.1);
  color: var(--accent-light);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
  padding: 0.35rem 0.75rem;
  border-radius: 6px;
  font-size: var(--fs-sm);
  font-weight: 700;
  font-family: var(--font);
  cursor: pointer;
  transition: all 0.12s;
  margin-right: 0.75rem;
}

.quaddie-btn:hover { background: rgba(var(--accent-rgb), 0.2); border-color: var(--accent); }

/* Modal */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  padding: 1rem;
}

.modal-content {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 100%;
  max-width: 380px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
}

.modal-header h3 {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
}

.modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: var(--fs-h1);
  cursor: pointer;
  padding: 0 0.25rem;
  line-height: 1;
  transition: color 0.12s;
}

.modal-close:hover { color: var(--text); }

.modal-body {
  padding: 0.5rem 0.75rem 0.75rem;
}

.race-main {
  flex: 1;
  min-width: 0;
}

/* Abandoned Banner */

.abandoned-banner {
  max-width: 1380px;
  margin: 0.75rem auto;
  padding: 0.6rem 1rem;
  background: rgba(var(--danger-rgb), 0.1);
  border: 1px solid rgba(var(--danger-rgb), 0.25);
  border-radius: var(--radius);
  color: var(--danger);
  font-weight: 700;
  font-size: var(--fs-h4);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.resulted-banner {
  max-width: 1380px;
  margin: 0.75rem auto;
  padding: 0.75rem 1rem;
  background: linear-gradient(rgba(var(--green-rgb), 0.1), rgba(var(--green-rgb), 0.1)), var(--bg);
  border: 1px solid rgba(var(--green-rgb), 0.2);
  border-radius: var(--radius);
  text-align: center;
}

.rb-header {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--green);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 0.35rem;
}

.rb-positions {
  font-size: var(--fs-h4);
  color: var(--text);
  line-height: 1.6;
}

.rb-pos strong { color: var(--win); }

/* Meet Nav (race page) */

.meet-nav {
  max-width: 1380px;
  margin: 0 auto;
  padding: 0.5rem 0.75rem;
  display: flex;
  gap: 0.25rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.meet-nav::-webkit-scrollbar { display: none; }
.meet-nav:empty { display: none; }

.meet-nav-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.05rem;
  padding: 0.3rem 0.4rem;
  border-radius: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  /* Fixed width so every pill is identical across races AND race types — the time
     string (mono, up to "12:29pm") no longer drives per-pill width. */
  width: 3.6rem;
  box-sizing: border-box;
  flex-shrink: 0;
  transition: all 0.12s;
}
.meet-nav-pill .mnp-time { max-width: 100%; overflow: hidden; }

.meet-nav-pill:hover { border-color: var(--accent); background: var(--bg-hover); }
.meet-nav-pill.active { background: var(--accent-btn); border-color: var(--accent-btn); }
.meet-nav-pill.active .mnp-num { color: #fff; }
.meet-nav-pill.active .mnp-time { color: rgba(var(--overlay-rgb), 0.65); }
.meet-nav-pill.mnp-abn { opacity: 0.4; }

.mnp-num {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--accent-light);
}

.mnp-time {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-dim);
}

.mnp-indicators {
  display: flex;
  gap: 2px;
}

.mnp-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

.dot-abn { background: var(--danger); }
.dot-result { background: var(--green); }
.dot-started { background: var(--win); }
.dot-pred { background: var(--accent-light); }

/* Race Hero */

.race-hero {
  max-width: 1380px;
  margin: 0.75rem auto;
  padding: 1.1rem 1.25rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.hero-top {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.25rem;
  flex-wrap: wrap;
}

.hero-course {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--accent-light);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* Race-type pill in the hero header (dot + label), colour-coded per race type. */
.hero-type {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--type-color, var(--accent)) 14%, transparent);
  color: var(--type-color, var(--accent-light));
}
.hero-type.rt-horse   { --type-color: var(--type-horse, var(--accent)); }
.hero-type.rt-grey    { --type-color: var(--type-grey, var(--green)); }
.hero-type.rt-harness { --type-color: var(--type-harness, var(--win)); }

.hero-divider { color: var(--text-dim); font-size: var(--fs-sm); }

.hero-state { font-size: var(--fs-sm); color: var(--text-muted); }
.hero-race-num { font-size: var(--fs-sm); color: var(--text-muted); }
.hero-date { font-size: var(--fs-sm); color: var(--text-muted); }

.hero-status {
  font-size: var(--fs-xs);
  color: var(--green);
  background: rgba(var(--green-rgb), 0.1);
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  margin-left: auto;
}

.hero-name {
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--text);
  margin-bottom: 0.5rem;
}

.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.hero-chip {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.2rem 0.55rem;
  font-size: var(--fs-sm);
  color: var(--text-mid);
}

.chip-time { color: var(--accent-light); border-color: rgba(var(--accent-rgb), 0.25); }

/* Labelled race-info grid */
.race-info-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin: 0.6rem 0 0.2rem;
}
.ri-item { display: flex; flex-direction: column; gap: 0.1rem; }
.ri-label {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.ri-val { font-size: var(--fs-h4); font-weight: 600; color: var(--text); }
/* Track value renders as a coloured pill via the going-* classes */
.ri-val.going-good, .ri-val.going-soft, .ri-val.going-heavy, .ri-val.going-synth {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 5px;
  font-size: var(--fs-body);
  width: fit-content;
}

/* Track condition (going) colour coding */
.chip-going { font-weight: 600; }
.going-good  { color: #4caf7d; border-color: rgba(76,175,125,0.4);  background: rgba(76,175,125,0.08); }
.going-soft  { color: #e0a23c; border-color: rgba(224,162,60,0.4);  background: rgba(224,162,60,0.08); }
.going-heavy { color: #e57373; border-color: rgba(229,115,115,0.4); background: rgba(229,115,115,0.08); }
.going-synth { color: var(--ew); border-color: rgba(var(--ew-rgb), 0.4);  background: rgba(var(--ew-rgb), 0.08); }

/* (Removed dead .hero-bias — superseded by the .track-bias callout, now UI.trackBias.) */
/* Greyhounds page (meetings reuse the horse .meet-group layout) */
.gh-back { display: inline-block; font-size: var(--fs-body); color: var(--accent-light, #a78bfa); text-decoration: none; margin-bottom: 0.6rem; }
.gh-back:hover { text-decoration: underline; }
/* Greyhound race hero reuses the horse .race-hero / .hero-* / .race-info-grid styles. */
.gh-weights { font-size: var(--fs-xs); color: var(--text-dim, #64748b); margin-top: 0.35rem; }
.gh-ai-tag { font-size: var(--fs-2xs); font-weight: 800; padding: 0.1rem 0.35rem; border-radius: 4px; vertical-align: middle;
  background: rgba(var(--ew-rgb), 0.16); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.45); }
/* Greyhound race result reuses the horse .results-card / .rc-* styles. */
.gh-scratched { margin-top: 0.8rem; font-size: var(--fs-sm); color: var(--text-muted); }
.ws-code-heading { font-size: var(--fs-h3); font-weight: 800; margin: 1.5rem 0 0.4rem;
  padding-bottom: 0.4rem; border-bottom: 1px solid var(--border, rgba(var(--overlay-rgb), 0.1)); }
.ws-code-heading:first-child { margin-top: 0; }

/* Shell-level watch/listen row (UI.racePage) sits directly under the hero for every
   race type. Collapses fully when the race has no replay/call yet. */
.race-watch-row { margin: 0.5rem 0 0.25rem; }
.race-watch-row:empty { display: none; margin: 0; }
.race-watch-row .watch-links { margin: 0; }
.watch-links { display: flex; gap: 0.5rem; margin: 0.5rem 0 0.25rem; flex-wrap: wrap; }
.watch-link {
  display: inline-flex; align-items: center; gap: 0.3rem; font-size: var(--fs-sm); font-weight: 700;
  padding: 0.3rem 0.7rem; border-radius: 6px; text-decoration: none;
  background: rgba(var(--ew-rgb), 0.14); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.4);
}
.watch-link:hover { background: rgba(var(--ew-rgb), 0.22); }
.watch-link.watch-audio { background: rgba(148,163,184,0.14); color: #94a3b8; border-color: rgba(148,163,184,0.4); }
button.watch-link { cursor: pointer; font: inherit; }
.modal-content.replay-modal { max-width: 880px; width: 92vw; }
.modal-content.replay-modal .modal-body { padding-top: 0.5rem; }

/* UI.modal (#187) — shared content dialog. Size variants + a body-scroll-lock while
   open, a soft fade-in, and a bottom-sheet layout on phones. Reuses .modal-*. */
body.modal-open { overflow: hidden; }
.ui-modal { animation: ui-modal-fade 0.15s ease; }
.ui-modal-content { display: flex; flex-direction: column; max-height: 88vh; }
.ui-modal-content .modal-body { overflow-y: auto; }
.ui-modal-sm { max-width: 380px; }
.ui-modal-md { max-width: 560px; }
.ui-modal-lg { max-width: 820px; }
@keyframes ui-modal-fade { from { opacity: 0; } to { opacity: 1; } }
@media (max-width: 640px) {
  /* Bottom-sheet: dock to the bottom edge, full width, rounded top, slide up. */
  .ui-modal { align-items: flex-end; padding: 0; }
  .ui-modal .ui-modal-content { width: 100%; max-width: none; max-height: 85vh; border-radius: 14px 14px 0 0; animation: ui-modal-slide 0.2s ease; }
}
@keyframes ui-modal-slide { from { transform: translateY(100%); } to { transform: translateY(0); } }

/* Track bias as its own section below the prediction (same width as the rest). */
.track-bias {
  max-width: 1380px;
  margin: 0.75rem auto;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.6rem 0.75rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
}
.hb-tag {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--accent-light);
  background: rgba(var(--accent-rgb), 0.12);
  padding: 0.18rem 0.4rem;
  border-radius: 4px;
  flex-shrink: 0;
  margin-top: 0.1rem;
}
.hb-body { font-size: var(--fs-sm); color: var(--text-mid); line-height: 1.5; flex: 1 1 auto; min-width: 0; }
/* Subject words (Pace, Winning barriers, In-form today, the barrier verdict) bold + white. */
.hb-body strong { color: var(--text); font-weight: 700; }
.hb-line strong { text-transform: capitalize; }
.hb-dim { color: var(--text-dim); }
/* Consistent line sizing across the main line and the sub-lines. */
.hb-sub { font-size: var(--fs-sm); color: var(--text-mid); margin-top: 0.2rem; }

.hero-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.4rem;
}

.hero-tag {
  font-size: var(--fs-xs);
  color: var(--accent-light);
  background: rgba(var(--accent-rgb), 0.08);
  border-radius: 4px;
  padding: 0.1rem 0.4rem;
}

.prize-section {
  margin-top: 0.6rem;
  padding: 0.5rem 0.65rem;
  background: rgba(var(--win-rgb), 0.04);
  border: 1px solid rgba(var(--win-rgb), 0.12);
  border-radius: 8px;
}

.prize-total { font-weight: 700; font-size: var(--fs-body); color: var(--win); }

.prize-breakdown {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.25rem;
}

.prize-item { font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-muted); }
.prize-pos { color: var(--text-dim); margin-right: 0.1rem; }

/* Scratching Alert */

/* The scratchings alert renders a shared .alert-card (ac-scratching) inside this
   mount, so the container is just a wrapper — the card provides all the styling. */
.scratching-alert { margin: 0.6rem 0; }


/* Draw the eye to the main predict button when a scratching invalidated the
   stored prediction, so "regenerate" is obvious wherever the user looks. */
#predictBtn.needs-regen {
  background: var(--danger);
  animation: regenPulse 1.6s ease-in-out infinite;
}

#predictBtn.needs-regen:hover { background: var(--danger); filter: brightness(1.1); }

@keyframes regenPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 55%, transparent); }
  50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--danger) 0%, transparent); }
}

/* Race Actions */

.race-actions {
  max-width: 1380px;
  margin: 0.75rem auto;
  padding: 0 1rem;
  display: flex;
  gap: 0.6rem;
  align-items: center;
}

.race-actions select {
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.45rem 0.65rem;
  border-radius: 8px;
  font-size: var(--fs-body);
  font-family: var(--font);
}

.race-actions select:focus { outline: none; border-color: var(--accent); }

#predictBtn {
  background: var(--accent-btn);
  color: var(--on-accent);
  border: none;
  padding: 0.5rem 1.2rem;
  font-weight: 600;
  font-size: var(--fs-body);
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  transition: background 0.15s;
}

#predictBtn:hover { background: #5a4ac4; }
#predictBtn:disabled { background: var(--border); cursor: not-allowed; color: var(--text-dim); }

.btn-outline {
  background: transparent;
  color: var(--accent-light);
  border: 1px solid var(--border);
  padding: 0.5rem 1rem;
  font-weight: 600;
  font-size: var(--fs-body);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.btn-outline:hover { border-color: var(--accent); color: var(--accent); }
.btn-outline:disabled { color: var(--text-dim); cursor: not-allowed; }

.rd-bar-track {
  width: 100%;
  height: 6px;
  background: var(--bg);
  border-radius: 3px;
  overflow: hidden;
}
.rd-bar-fill {
  width: 0%;
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.4s ease;
}
.rd-bar-error { background: var(--danger, #e57373) !important; }
.rd-status {
  margin-top: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}

#recalcBtn {
  background: transparent;
  color: var(--accent-light);
  border: 1px solid var(--border);
  padding: 0.5rem 1rem;
  font-weight: 600;
  font-size: var(--fs-body);
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  transition: all 0.15s;
}

#recalcBtn:hover { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.08); }
#recalcBtn:disabled { opacity: 0.4; cursor: not-allowed; }

.spinner {
  display: none;
  width: 14px; height: 14px;
  border: 2px solid rgba(var(--overlay-rgb), 0.25);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.5s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* Top Pick Banner */

.top-pick {
  display: none;
  max-width: 1380px;
  margin: 1rem auto;
  padding: 1rem 1.25rem;
  background: linear-gradient(135deg, rgba(var(--accent-rgb), 0.16), rgba(176,164,255,0.07)), var(--bg);
  border: 1px solid rgba(var(--accent-rgb), 0.2);
  border-radius: var(--radius);
  text-align: center;
}

.top-pick-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--accent-light);
  margin-bottom: 0.2rem;
}

/* Flow badge — which prediction path produced the tip (AI vs basic blend). */
.flow-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: 0.5px;
  padding: 0.08rem 0.4rem;
  border-radius: 999px;
  margin-left: 0.4rem;
  vertical-align: middle;
}
.flow-badge.flow-ai { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent-light); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
.flow-badge.flow-basic { background: color-mix(in srgb, var(--green) 16%, transparent); color: var(--green); border: 1px solid color-mix(in srgb, var(--green) 45%, transparent); }

.top-pick-name { font-size: var(--fs-h1); font-weight: 700; color: var(--win); }
.top-pick-ew { color: var(--ew); font-size: var(--fs-body); margin-top: 0.25rem; }
/* #270 saddlecloth number chip before the pick name (AI + basic tips) */
.tp-num { display: inline-flex; align-items: center; justify-content: center; min-width: 1.5em; height: 1.5em; padding: 0 0.3em;
  font-size: 0.62em; font-weight: 800; color: var(--text); background: var(--bg); border: 1px solid var(--border);
  border-radius: 5px; vertical-align: middle; font-variant-numeric: tabular-nums; }
.top-pick-summary { color: var(--text-mid); font-size: var(--fs-body); margin-top: 0.2rem; }
/* #272 odds-shift sparkline (open→race-time fixed-win price). Green = steamed (shortened),
   red = drifted, muted = flat. Odds axis inverted so a steaming line rises. */
.spark { vertical-align: middle; overflow: visible; }
.spark.spark-in { color: var(--green); }
.spark.spark-out { color: var(--danger, #ef4444); }
.spark.spark-flat { color: var(--text-muted); }
.spark .spark-cur { fill: currentColor; }
.spark .spark-open { fill: var(--text-muted); }
.odds-spark { display: inline-flex; align-items: center; gap: 0.3rem; }
.odds-spark .os-move { font-size: var(--fs-2xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.odds-spark.os-in .os-move { color: var(--green); }
.odds-spark.os-out .os-move { color: var(--danger, #ef4444); }
.odds-spark .os-text { font-size: var(--fs-2xs); color: var(--text-muted); }
/* #273 muted "no price history captured yet" placeholder (poller often off) — subtle so it
   never competes with the prediction; it just fills the gap where a sparkline can't yet show. */
.odds-spark.os-empty { color: var(--text-dim); font-size: var(--fs-xs); opacity: 0.65; }

/* #277 per-runner "Odds movement" accordion — a fuller price chart + open/now/low/high labels,
   or a muted "no data yet" message. Mobile-first: the SVG scales to the card width. */
.odds-chart { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.2rem 0.1rem; }
.odds-chart-svg { width: 100%; }
.odds-chart-svg .spark { width: 100%; height: auto; max-height: 80px; display: block; }
.odds-chart.os-in .spark { color: var(--green); }
.odds-chart.os-out .spark { color: var(--danger, #ef4444); }
/* #295 dual fixed-vs-Betfair overlay: fixed = solid accent, Betfair = dashed teal. */
.odds-chart-svg .odds-dual { width: 100%; height: auto; max-height: 80px; display: block; }
.odds-dual .ocl-fixed, .odds-dual .ocl-fixed-dot { color: var(--accent, #7c6cff); }
.odds-dual .ocl-bf, .odds-dual .ocl-bf-dot { color: var(--teal, var(--ew)); }
.odds-chart-legend { display: flex; gap: 0.9rem; font-size: var(--fs-2xs); }
.odds-chart-legend .ocl-key { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.odds-chart-legend .ocl-key::before { content: ""; width: 14px; height: 0; border-top-width: 2px; border-top-style: solid; }
.odds-chart-legend .ocl-key-fixed::before { border-top-color: var(--accent, #7c6cff); }
.odds-chart-legend .ocl-key-bf::before { border-top-color: var(--teal, var(--ew)); border-top-style: dashed; }
/* #319 per-source legend: an inline colour swatch instead of the ::before line rule */
.odds-chart-legend .ocl-key .ocl-swatch { display: inline-block; width: 12px; height: 2px; border-radius: 1px; }
.odds-chart-legend .ocl-key:has(.ocl-swatch)::before { display: none; }
.odds-chart-legend { flex-wrap: wrap; row-gap: 0.25rem; }
.odds-chart-bf-labels { opacity: 0.9; }
.odds-chart-labels { display: flex; flex-wrap: wrap; gap: 0.4rem 0.9rem; }
.odds-chart-labels .occ { display: flex; flex-direction: column; line-height: 1.2; }
.odds-chart-labels .occ-lab { font-size: var(--fs-2xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.odds-chart-labels .occ-val { font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; }
.odds-chart.os-in .occ-move .occ-val { color: var(--green); }
.odds-chart.os-out .occ-move .occ-val { color: var(--danger, #ef4444); }
.odds-chart-empty { display: flex; flex-direction: column; gap: 0.15rem; color: var(--text-dim); font-size: var(--fs-sm); padding: 0.35rem 0.1rem; }
.odds-chart-empty .oce-sub { font-size: var(--fs-2xs); color: var(--text-muted); }
/* #296 single captured price (no movement yet) — show the price, not a "no data" message. */
.odds-chart-single { gap: 0.25rem; }
.odds-chart-single .oce-sub { font-size: var(--fs-2xs); color: var(--text-muted); }

.top-pick-timestamp {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 0.4rem;
}

/* Runner Rows */

.runners-container {
  max-width: 1380px;
  margin: 0 auto;
  padding: 0.5rem 0 2rem; /* no side padding — cards align with the other 1380px sections */
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* #133 runner card is a vertical stack: compact row + full-width accordion below. */
.runner-row {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.4rem 0.35rem;   /* #133/#140 tighter edge padding to reclaim horizontal space */
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.runner-compact {
  display: grid;
  /* #310 dropped the standalone rank column — the model rank was a bare, unlabelled number
     that competed with the saddlecloth number; it now shows once as the labelled "VO #n" chip. */
  grid-template-columns: 70px 1fr 190px;
  gap: 0.4rem;
  align-items: start;
}
/* #133 barrier inline next to the runner name */
.runner-barrier { color: var(--text-muted); font-weight: 600; font-size: 0.85em; }
/* #134 always-visible main info (jockey/trainer/weight/gear/going per code).
   #141 One inline label:value pattern at ALL widths (was a desktop grid) — same
   compact flow as mobile, so the card reads identically everywhere. */
.runner-main-info { display: flex; flex-direction: column; gap: 0.05rem; margin-top: 0.25rem; }
.runner-main-info .info-cell { display: flex; flex-direction: row; align-items: baseline; gap: 0.3rem; background: none; border: none; border-radius: 0; padding: 0; }
.runner-main-info .info-label { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); }
.runner-main-info .info-value { font-size: var(--fs-sm); color: var(--text-mid); }
/* #133 per-runner pace bar (back → lead) */
.pace-bar { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.25rem; }
.pace-bar-label { font-size: var(--fs-xs); font-weight: 600; color: var(--text-muted); white-space: nowrap; min-width: 72px; }
.pace-bar-end { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); }
.pace-bar-track { position: relative; flex: 1; height: 6px; border-radius: 3px; background: linear-gradient(90deg, rgba(148,163,184,0.18), rgba(var(--ew-rgb), 0.28)); }
.pace-bar-fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: 3px; background: linear-gradient(90deg, rgba(var(--ew-rgb), 0.35), var(--accent)); }
.pace-bar-dot { position: absolute; top: 50%; width: 8px; height: 8px; border-radius: 50%; background: var(--accent-light); border: 1px solid var(--bg); transform: translate(-50%, -50%); }
/* #141 TAB signal chips (fast-form lean / tcdw / price move) in the pace-flags row */
.tab-chip { display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; gap: 0.2rem; font-weight: 700; border-radius: 5px; border: 1px solid var(--border); background: var(--bg-card); color: var(--text-mid); text-transform: uppercase; letter-spacing: 0.02em; white-space: nowrap; }
.tab-chip.tc-lead { color: var(--accent-light); border-color: var(--accent); background: rgba(var(--accent-rgb), 0.12); }
.tab-chip.tc-top { color: var(--win); border-color: var(--win); background: var(--win-bg); }
.tab-chip.tc-tcdw { font-family: var(--mono); color: var(--ew); border-color: var(--ew); background: var(--ew-bg); }
.tab-chip.tc-firm { color: var(--green); border-color: var(--green); }
.tab-chip.tc-drift { color: var(--text-muted); }
/* #135 win% / place% prediction boxes (styled like the mobile guide) */
.pred-boxes { display: flex; gap: 0.4rem; }
.pred-box { display: flex; flex-direction: column; align-items: center; min-width: 52px; padding: 0.3rem 0.5rem; border-radius: 8px; background: var(--bg-card); border: 1px solid var(--border); }
.pred-box .pb-lab { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); }
.pred-box .pb-val { font-size: var(--fs-h3); font-weight: 700; color: var(--text); }
/* #135 inline rank shown on mobile only (desktop uses the rank column) */
/* #137 TAB Win + Place odds stacked (replaces the Fair/TAB lines) */
.tab-odds { display: flex; flex-direction: column; gap: 0.1rem; align-items: flex-end; }
.tab-odds-row { display: flex; gap: 0.4rem; align-items: baseline; }
.tab-odds .to-lab { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); min-width: 30px; }
.tab-odds .to-val { font-size: var(--fs-h4); font-weight: 700; color: var(--text); font-family: var(--mono); }
/* #137 speed / drift / value flags in a full-width row below the pace bar */
.runner-paceflags { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin-top: 0.25rem; } /* #249 one centred line — chips must NOT set their own margin-top */
.runner-paceflags:empty { display: none; }
/* #133 always-visible actions row: bordered betslip section + follow button */
.runner-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.runner-betslip-section { border: 1px solid var(--border); border-radius: 8px; padding: 0.25rem 0.4rem; background: var(--bg-card); display: inline-flex; align-items: center; }
.runner-betslip-section:empty { display: none; }
/* #133/#139 one full-width "More" accordion — the summary is a clear button, and the
   OPEN state gets a filled background + accent border so it's obvious it's expanded and
   how to close it (tap the highlighted header again). */
.ui-accordion { margin-top: 0.35rem; }
.ui-accordion-sum { cursor: pointer; list-style: none; padding: 0.45rem 0.7rem; font-size: var(--fs-sm); font-weight: 700; color: var(--text-mid); user-select: none; display: flex; align-items: center; gap: 0.4rem; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; }
.ui-accordion-sum::-webkit-details-marker { display: none; }
.ui-accordion-sum::before { content: "▸"; font-size: var(--fs-xs); transition: transform 0.15s; }
.ui-accordion[open] > .ui-accordion-sum::before { transform: rotate(90deg); }
.ui-accordion-sum:hover { color: var(--text); border-color: var(--accent); }
.ui-accordion[open] { background: var(--bg-card); border: 1px solid var(--accent); border-radius: 10px; padding: 0.3rem; }
.ui-accordion[open] > .ui-accordion-sum { background: var(--bg-hover); border-color: var(--accent); color: var(--text); margin-bottom: 0.3rem; }
.ui-accordion[open] > .ui-accordion-sum::after { content: "tap to close"; margin-left: auto; font-size: var(--fs-2xs); font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.03em; }
.ui-accordion-body { padding: 0.25rem 0.4rem 0.4rem; }

.runner-row.sel-win { border-left: 3px solid var(--win); background: linear-gradient(var(--win-bg), var(--win-bg)), var(--bg); }
.runner-row.sel-ew { border-left: 3px solid var(--ew); background: linear-gradient(var(--ew-bg), var(--ew-bg)), var(--bg); }
.runner-row.sel-avoid { border-left: 3px solid var(--avoid); background: linear-gradient(var(--avoid-bg), var(--avoid-bg)), var(--bg); }
/* Scratched runner card — greyed out but still legible, struck-through name.
   Shared across all race types via UI.scratchedCard / UI.scratchedSection. */
.runner-row.scratched {
  opacity: 0.7;
  filter: grayscale(1);
  background: color-mix(in srgb, var(--text-dim) 8%, transparent);
}
.runner-row.scratched .runner-horse {
  text-decoration: line-through;
  color: var(--text-dim);
}
.runner-row.scratched .runner-connections { color: var(--text-dim); }

.scratched-header {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0.75rem 0 0.2rem;
  border-top: 1px solid var(--border);
  margin-top: 0.4rem;
}

.runner-num-silk {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}

.runner-num {
  font-family: var(--mono);
  font-size: var(--fs-h1);
  line-height: 1;
  font-weight: 800;
  color: var(--accent-light);
  text-align: center;
  background: rgba(var(--accent-rgb), 0.12);
  border-radius: 7px;
  padding: 0.25rem 0 0.3rem;
  min-width: 2.4rem;
}
/* #310 tiny "NO" caption inside the saddlecloth box so it unmistakably reads as the runner
   number (the one that matters), not one of the other numbers on the card. */
.runner-num-lab {
  display: block;
  font-family: var(--font, inherit);
  font-size: 0.55rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  color: var(--text-dim);
  margin-bottom: 0.15rem;
}

.silk-img {
  width: 62px;
  height: auto;
  border-radius: 8px;
  box-sizing: border-box;
  padding: 3px;   /* #141 tighter padding on a white plate so the silk reads clearly */
  margin: 0.25rem 0.35rem;   /* #141 outside gap so neighbouring text doesn't touch the plate */
  background: #fff;
  border: 1px solid var(--border, rgba(var(--overlay-rgb), 0.1));
  object-fit: contain;
}

.runner-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.runner-horse-line {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.runner-horse { font-weight: 700; font-size: var(--fs-h4); color: var(--text); }

.runner-form {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent-light);
  letter-spacing: 1px;
  background: rgba(var(--accent-rgb), 0.06);
  padding: 0.05rem 0.35rem;
  border-radius: 3px;
}

.data-flag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--chip-h);
  height: var(--chip-h); /* #234 aligned */
  font-size: var(--fs-2xs);
  font-weight: 700;
  border-radius: 3px;
  margin-left: 0.25rem;
  cursor: help;
  vertical-align: middle;
}
.flag-enrich  { background: rgba(var(--ew-rgb), 0.16);  color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.35); }
.flag-profile { background: rgba(var(--win-rgb), 0.16);  color: var(--win); border: 1px solid rgba(var(--win-rgb), 0.35); }
.flag-debut   { width: auto; padding: 0 0.3rem; background: rgba(var(--accent-rgb), 0.16); color: var(--accent-light); border: 1px solid rgba(var(--accent-rgb), 0.35); }

.runner-connections {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.65rem;
}

.runner-silks {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 0.2rem;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conn-item strong { color: var(--text-mid); font-weight: 600; }
.claim { color: var(--ew); font-size: var(--fs-xs); }

.runner-info-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.info-cell {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0.15rem 0.45rem;
  display: flex;
  gap: 0.3rem;
  align-items: baseline;
}

.info-label {
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.info-value {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-mid);
}

.runner-breeding-line {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.runner-breeding-line span { color: var(--text-muted); }

.runner-owner {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  line-height: 1.3;
}

.runner-last-raced {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.runner-stats-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.stat-cell {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0.15rem 0.45rem;
  display: flex;
  gap: 0.3rem;
  align-items: baseline;
}

.stat-label {
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.stat-value {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.runner-comment {
  font-size: var(--fs-sm);
  color: var(--ew);
  font-style: italic;
  line-height: 1.35;
}

/* Racing.com enrichment block */
.enrichment-data {
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.rc-comment {
  font-size: var(--fs-sm);
  color: var(--text-mid);
  font-style: italic;
  line-height: 1.4;
}
.rc-gear {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.fais-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.fais-tag {
  font-size: var(--fs-xs);
  padding: 0.1rem 0.4rem;
  border-radius: 3px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.fais-pos {
  background: rgba(100, 200, 120, 0.15);
  color: #6dc87a;
  border: 1px solid rgba(100, 200, 120, 0.25);
}
.fais-neg {
  background: rgba(220, 100, 100, 0.12);
  color: #dc8080;
  border: 1px solid rgba(220, 100, 100, 0.2);
}
.rc-stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.rc-stat-item {
  display: inline-flex;
  gap: 0.25rem;
  align-items: center;
}
.rc-label {
  color: var(--text-dim);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.rc-time-fast { color: #4caf50; font-weight: 600; }
.rc-time-slow { color: #e57373; }
.rc-pips {
  font-size: var(--fs-2xs);
  letter-spacing: 0.05em;
  color: var(--accent);
}

/* Run history table */
.run-history {
  margin-top: 0.6rem;
}
.rh-title {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  margin-bottom: 0.3rem;
}
.rh-scroll {
  overflow-x: auto;
}
.rh-table {
  border-collapse: collapse;
  font-size: var(--fs-xs);
  color: var(--text-muted);
  white-space: nowrap;
  width: 100%;
}
.rh-table th {
  color: var(--text-dim);
  font-weight: 600;
  text-transform: uppercase;
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
  padding: 0.15rem 0.4rem 0.25rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}
.rh-table td {
  padding: 0.2rem 0.4rem;
  border-bottom: 1px solid rgba(var(--overlay-rgb), 0.04);
}
.rh-table .rh-finish {
  font-weight: 700;
  color: var(--text-mid);
}

/* #417 The icon set that replaced the emoji.
   Sized in `em` and coloured by `currentColor`, so an icon matches whatever text it sits
   beside and recolours with its container — which is the entire point: the emoji it replaced
   could do neither. `vertical-align: -0.14em` sits it on the text's optical centre rather
   than its baseline, where an SVG otherwise rides high. */
.vo-ico {
  width: 1.05em;
  height: 1.05em;
  vertical-align: -0.14em;
  flex: none;
}
/* Inside a chip/badge the glyph reads better a touch smaller than its label. */
.badge .vo-ico, .ac-badge .vo-ico, .flow-badge .vo-ico { width: 0.95em; height: 0.95em; }

.runner-reason {
  font-size: var(--fs-sm);
  color: var(--win);
  font-style: italic;
}

/* #404 Entry vs jump — the price we called it at, next to the price it went off at.
   Mobile-first: a wrapping flex row, so at ≤640px the legs stack onto a second line rather
   than forcing the (already dense, per #279/#301) card to scroll sideways. */
.entry-jump {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin-top: 4px;
  font-size: var(--fs-xs);
}
.entry-jump-leg { display: inline-flex; align-items: baseline; gap: 4px; }
.entry-jump-lab { color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em; }
.entry-jump-val { font-weight: 600; font-variant-numeric: tabular-nums; }
.entry-jump-at { color: var(--text-dim); }
/* Both directions are styled with the same weight and prominence — deliberately. A CLV
   display that shouts the wins and mumbles the losses is an ad, not a track record. */
.clv-delta { font-weight: 600; font-variant-numeric: tabular-nums; }
.clv-up { color: var(--win); }
.clv-down { color: var(--danger); }

/* Right column: odds + prediction */

.runner-right {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: flex-end;
}

.odds-section {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-align: right;
}

.odds-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.4rem;
  align-items: baseline;
  font-family: var(--mono);
  font-size: var(--fs-xs);
}

.bookie-name {
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.2px;
}

.odds-win { font-weight: 700; color: var(--win); }
.odds-place { color: var(--text-muted); }

.sp-row {
  font-family: var(--mono);
  font-size: var(--fs-h4);
  font-weight: 600;
  color: var(--text-dim);
  margin-top: 0.1rem;
}
.bf-row {
  font-family: var(--mono);
  font-size: var(--fs-h4);
  font-weight: 700;
  color: #f5a623;
  margin-top: 0.1rem;
}
.bf-place { color: #d08a1e; font-weight: 600; margin-left: 0.25rem; }
.tote-px { color: var(--text-dim); font-weight: 500; margin-left: 0.25rem; }
/* Tote-to-Fixed Friction Index flags */
.friction-badge {
  display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; font-weight: 800; letter-spacing: 0.02em; border-radius: 5px; cursor: help;
}
.friction-badge.fr-overlay { background: rgba(var(--ew-rgb), 0.16); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.45); }
.friction-badge.fr-trap    { background: rgba(239,83,80,0.16); color: #ef5350; border: 1px solid rgba(239,83,80,0.45); }
.drift-flag {
  display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; font-weight: 800; letter-spacing: 0.02em; border-radius: 5px; cursor: help;
  background: rgba(245,158,11,0.16); color: #f59e0b; border: 1px solid rgba(245,158,11,0.45);
}
.place-value-flag {
  display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; font-weight: 800; letter-spacing: 0.02em; border-radius: 5px; cursor: help;
  background: rgba(var(--green-rgb), 0.16); color: var(--green); border: 1px solid rgba(var(--green-rgb), 0.45);
}
.early-speed-chip {
  display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; font-weight: 700; letter-spacing: 0.02em; border-radius: 5px; cursor: help;
  background: rgba(148,163,184,0.14); color: #94a3b8; border: 1px solid rgba(148,163,184,0.35);
}
.delayed-tag {
  font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.03em; padding: 0.08rem 0.35rem;
  border-radius: 4px; cursor: help; vertical-align: middle;
  background: rgba(245,158,11,0.16); color: #f59e0b; border: 1px solid rgba(245,158,11,0.45);
}
.rerank-note {
  max-width: 1380px; margin: 0.5rem auto 0.9rem; padding: 0.6rem 0.8rem; border-radius: 8px;
  background: rgba(96,165,250,0.10); border: 1px solid rgba(96,165,250,0.4);
  font-size: var(--fs-body); line-height: 1.4;
}
.rerank-note .rr-icon { font-weight: 800; margin-right: 0.3rem; }
.rerank-note .rr-move { margin-top: 0.25rem; font-size: var(--fs-h4); }
.rerank-note .rr-from { color: var(--muted, #94a3b8); }
.rerank-note .rr-to { color: #60a5fa; }
.rerank-note .rr-why { margin-top: 0.2rem; color: var(--muted, #94a3b8); font-size: var(--fs-sm); }
.rerank-note.rerank-scr { background: rgba(245,158,11,0.10); border-color: rgba(245,158,11,0.45); }
.rerank-note.rerank-scr .rr-to { color: #f59e0b; }
.was-top {
  display: inline-block; margin-left: 0.35rem; font-size: var(--fs-2xs); font-weight: 800;
  letter-spacing: 0.02em; padding: 0.1rem 0.35rem; border-radius: 4px; cursor: help;
  background: rgba(148,163,184,0.18); color: #94a3b8; border: 1px solid rgba(148,163,184,0.4);
}
.reranked-dot {
  display: inline-block; margin-left: 0.3rem; font-size: var(--fs-2xs); font-weight: 800;
  letter-spacing: 0.03em; padding: 0.08rem 0.3rem; border-radius: 4px; cursor: help;
  background: rgba(96,165,250,0.14); color: #60a5fa; border: 1px solid rgba(96,165,250,0.4);
}

/* Race-level value opportunity alert */
.race-alert {
  max-width: 1380px; margin: 0 auto 1rem; padding: 0.75rem 1rem; border-radius: 10px;
  background: rgba(var(--ew-rgb), 0.10); border: 1px solid rgba(var(--ew-rgb), 0.45);
}
.race-alert .ra-head { font-weight: 800; color: var(--ew); font-size: var(--fs-h4); margin-bottom: 0.35rem; }
.race-alert .ra-sub { font-weight: 500; color: var(--text-dim); font-size: var(--fs-xs); letter-spacing: 0.02em; }
.race-alert .ra-item { font-size: var(--fs-body); color: var(--text); padding: 0.15rem 0; }
.race-alert .ra-vs { color: var(--text-dim); font-size: var(--fs-sm); }
.race-alert .ra-ratio { color: var(--ew); font-weight: 800; margin-left: 0.25rem; }
.race-alert .ra-tag { font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.02em; padding: 0.1rem 0.35rem; border-radius: 4px; margin-right: 0.35rem; white-space: nowrap; }
.race-alert .rt-value   { background: rgba(var(--win-rgb), 0.16); color: var(--win); border: 1px solid rgba(var(--win-rgb), 0.45); }
.race-alert .rt-overlay { background: rgba(var(--ew-rgb), 0.16); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.45); }

/* Alerts page */
.alert-card {
  display: block; text-decoration: none; color: var(--text);
  border: 1px solid var(--border); border-radius: 10px; padding: 0.7rem 0.9rem;
  margin-bottom: 0.6rem; background: var(--bg-card);
}
.alert-card:hover { border-color: var(--accent); background: var(--bg-hover); }
.alert-card.ac-value   { border-left: 3px solid var(--win); }
.alert-card.ac-overlay { border-left: 3px solid var(--ew); }
.alert-card.ac-trap    { border-left: 3px solid #ef5350; }
.alert-card.ac-rerank  { border-left: 3px solid #60a5fa; }
.alert-card.ac-placevalue { border-left: 3px solid var(--green); }
.ac-badge.ab-placevalue { background: rgba(var(--green-rgb), 0.16); color: var(--green); border: 1px solid rgba(var(--green-rgb), 0.45); }
/* Prediction updated (e.g. the basic flow refreshed from live data) — old → new pick + reason. */
.alert-card.ac-update { border-left: 3px solid var(--accent); }
.ac-badge.ab-update { background: rgba(var(--accent-rgb), 0.16); color: var(--accent-light); border: 1px solid rgba(var(--accent-rgb), 0.45); }
/* Scratching — top-priority, critical red with a slightly heavier accent. */
.alert-card.ac-scratching { border-left: 4px solid var(--danger); background: color-mix(in srgb, var(--danger) 6%, var(--bg)); }
.ac-badge.ab-scratching { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 50%, transparent); }
/* Blackbook — a followed runner is racing (amber ⭐), same card language as the rest. */
.alert-card.ac-blackbook { border-left: 3px solid #fbbf24; }
.ac-badge.ab-blackbook { background: rgba(251,191,36,0.16); color: #fbbf24; border: 1px solid rgba(251,191,36,0.45); }
/* Guide / key page */
.guide-intro { color: var(--text); line-height: 1.6; margin: 0 0 0.5rem; }
.guide-foot { color: var(--muted, #94a3b8); font-size: var(--fs-body); line-height: 1.6; margin-top: 1.5rem; }
.guide-h {
  font-size: var(--fs-h3); font-weight: 800; margin: 1.6rem 0 0.7rem; padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border, rgba(var(--overlay-rgb), 0.1));
}
.guide-list { display: grid; gap: 0.6rem; }
.guide-item {
  display: grid; grid-template-columns: 190px 1fr; gap: 0.9rem; align-items: start;
  padding: 0.6rem 0.7rem; border: 1px solid var(--border, rgba(var(--overlay-rgb), 0.08));
  border-radius: 8px; background: var(--bg-card, rgba(var(--overlay-rgb), 0.02));
}
.guide-badge { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; }
.guide-text { line-height: 1.5; font-size: var(--fs-h4); }
.guide-text strong:first-child { display: block; margin-bottom: 0.15rem; }
.guide-sub { margin: 0.4rem 0 0.4rem; padding-left: 1.1rem; display: grid; gap: 0.25rem; }
.guide-sub li { line-height: 1.45; }
.guide-sub li strong { color: var(--accent-light, #a78bfa); }
.guide-field {
  font-family: var(--mono, monospace); font-size: var(--fs-sm); font-weight: 700;
  padding: 0.12rem 0.45rem; border-radius: 5px; white-space: nowrap;
  background: rgba(var(--accent-rgb), 0.14); color: var(--accent-light, #a78bfa);
  border: 1px solid rgba(var(--accent-rgb), 0.35);
}
@media (max-width: 640px) {
  .guide-item { grid-template-columns: 1fr; gap: 0.4rem; }
}
/* Collapsible alert groups */
.alert-group { margin-bottom: 1rem; }
.alert-group-header {
  display: flex; align-items: center; gap: 0.5rem; width: 100%;
  background: var(--bg-hover, rgba(var(--overlay-rgb), 0.04)); border: 1px solid var(--border, rgba(var(--overlay-rgb), 0.1));
  border-radius: 8px; padding: 0.55rem 0.8rem; cursor: pointer; color: inherit;
  font: inherit; text-align: left;
}
.alert-group-header:hover { border-color: var(--accent); }
.alert-group .agh-chevron { transition: transform 0.15s ease; font-size: var(--fs-xs); opacity: 0.8; }
.alert-group.collapsed .agh-chevron { transform: rotate(-90deg); }
.alert-group .agh-label { font-weight: 800; }
.alert-group .agh-count {
  background: rgba(var(--overlay-rgb), 0.1); border-radius: 999px; padding: 0.05rem 0.5rem;
  font-size: var(--fs-xs); font-weight: 800;
}
.alert-group .agh-hint { color: var(--muted, #94a3b8); font-size: var(--fs-xs); margin-left: auto; }
.alert-group-body { display: grid; gap: 0.5rem; margin-top: 0.5rem; }
.alert-group.collapsed .alert-group-body { display: none; }
.ac-badge.ab-value { background: rgba(var(--win-rgb), 0.16); color: var(--win); border: 1px solid rgba(var(--win-rgb), 0.45); }
.ac-badge.ab-rerank { background: rgba(96,165,250,0.16); color: #60a5fa; border: 1px solid rgba(96,165,250,0.45); }
.ac-from { color: var(--muted, #94a3b8); }
.alert-card .ac-line { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.5rem; }
/* Width-flexible: cards fill their container, so they reflow gracefully in the
   narrow sticky rail as well as at full page width. */
.alert-card { min-width: 0; }
.alert-card .ac-horse, .alert-card .ac-detail { overflow-wrap: anywhere; }
.ac-badge { font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.02em; padding: 0.12rem 0.4rem; border-radius: 5px; white-space: nowrap; }
.ac-badge.ab-overlay { background: rgba(var(--ew-rgb), 0.16); color: var(--ew); border: 1px solid rgba(var(--ew-rgb), 0.45); }
.ac-badge.ab-trap    { background: rgba(239,83,80,0.16); color: #ef5350; border: 1px solid rgba(239,83,80,0.45); }
.ac-horse { font-weight: 700; font-size: var(--fs-h4); }
.ac-detail { font-size: var(--fs-body); margin-top: 0.2rem; }
.ac-detail .ac-vs { color: var(--text-dim); font-size: var(--fs-sm); }
.alert-card .ac-race { font-size: var(--fs-sm); color: var(--text-dim); margin-top: 0.15rem; }
.fair-row {
  font-family: var(--mono);
  font-size: var(--fs-h4);
  font-weight: 600;
  color: var(--accent-light);
  margin-top: 0.1rem;
}
.fair-row.fair-value { color: var(--ew); font-weight: 700; }
.value-tag {
  font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.03em;
  background: rgba(var(--ew-rgb), 0.16); color: var(--ew);
  border: 1px solid rgba(var(--ew-rgb), 0.4); border-radius: 4px;
  padding: 0.05rem 0.3rem; margin-left: 0.25rem; vertical-align: middle;
}

.runner-sort-bar {
  display: flex; align-items: center; gap: 0.5rem;
  margin: 0.25rem 0 0.6rem;
}
.runner-sort-bar .rs-label { font-size: var(--fs-sm); color: var(--text-muted); font-weight: 600; }
.runner-sort-select {
  background: var(--bg-card); border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; padding: 0.4rem 0.6rem; font-size: var(--fs-body); cursor: pointer;
}
.runner-sort-select:focus { outline: none; border-color: var(--accent); }

.prediction-section {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.2rem;
  padding-top: 0.4rem;
  border-top: 1px solid var(--border);
}

.badge {
  display: inline-flex; align-items: center; height: var(--chip-h); box-sizing: border-box; /* #234 aligned */
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0 0.5rem;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.badge.sel-win { background: var(--win); color: var(--on-status, var(--bg-card)); }
.badge.sel-ew { background: var(--ew); color: var(--on-status, var(--bg-card)); }
.badge.sel-place { background: var(--green); color: var(--on-status, var(--bg-card)); }
.badge.sel-avoid { background: var(--avoid); color: var(--text); }
.badge.sel-scratched { background: var(--danger); color: #fff; }
.badge.badge-neutral { background: rgba(157,161,184,0.14); color: var(--text-muted); border: 1px solid var(--border); }
/* #286 "Top rated" — the VO Speed top tier, surfaced as a clear gold badge on the runner card,
   shown left-aligned just above the Add-to-Betslip actions. */
.badge.badge-toprated { background: linear-gradient(180deg, rgba(255,196,61,0.22), rgba(255,196,61,0.12)); color: #ffcf5c; border: 1px solid rgba(255,196,61,0.5); font-weight: 700; }
.runner-above-actions { display: flex; justify-content: flex-start; margin: 0.35rem 0 0.15rem; }

.runner-score-num {
  font-family: var(--mono);
  font-size: var(--fs-h1);
  font-weight: 700;
  color: var(--text);
}

.score-max {
  font-size: inherit;
  color: inherit;
  font-weight: inherit;
  margin-left: 0.2rem;
}

.runner-place-prob {
  font-family: var(--mono);
  font-size: var(--fs-h1);
  font-weight: 700;
  color: var(--text);
  margin-top: 0.15rem;
}

.runner-pfai-rank {
  margin-top: 0.3rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--accent-light);
  background: rgba(var(--accent-rgb), 0.12);
  border-radius: 6px;
  padding: 0.15rem 0.4rem;
  display: inline-block;
}
.runner-pfai-rank strong { font-size: var(--fs-body); font-weight: 800; }
/* #304/#305 Runner-card odds sources — a price BUTTON that opens the comparison modal */
.odds-src-btn { display: inline-flex; align-items: center; gap: 0.35rem; margin-top: 0.35rem; padding: 0.2rem 0.55rem;
  border: 0.5px solid var(--border-strong, var(--border)); border-radius: 8px; background: transparent; color: var(--text);
  cursor: pointer; font: inherit; }
.odds-src-btn:hover { background: rgba(var(--overlay-rgb), 0.06); border-color: var(--accent-light); }
.odds-src-btn .osb-price { font-size: var(--fs-body); font-weight: 800; font-variant-numeric: tabular-nums; }
.odds-src-btn .osb-count { font-size: var(--fs-2xs); color: var(--text-muted); background: rgba(var(--overlay-rgb), 0.08); border-radius: 999px; padding: 0.05rem 0.4rem; }
.odds-src-btn .osb-caret { font-style: normal; color: var(--text-muted); font-size: 0.9em; }
/* #306 the MAIN odds block doubles as the compare-sources trigger — a light box border + caret
   signal it's tappable. Keeps the right-aligned Win/Place layout. */
.tab-odds.odds-btn { position: relative; flex-direction: row; align-items: center; gap: 0.5rem;
  padding: 0.25rem 0.5rem; border: 0.5px solid var(--border-strong, var(--border)); border-radius: 8px;
  background: transparent; cursor: pointer; transition: border-color 0.12s, background 0.12s; }
.tab-odds.odds-btn > .tab-odds-row { flex-direction: column; align-items: flex-end; gap: 0; }
.tab-odds.odds-btn:hover, .tab-odds.odds-btn:focus-visible { background: rgba(var(--overlay-rgb), 0.06); border-color: var(--accent-light); outline: none; }
.tab-odds.odds-btn:focus-visible { box-shadow: 0 0 0 2px var(--accent-light); }
.tab-odds.odds-btn .odds-btn-caret { color: var(--text-muted); font-size: 0.95em; line-height: 1; }
.odds-sources-modal .os-asof { font-size: var(--fs-2xs); color: var(--text-muted); margin-top: 0.7rem; line-height: 1.35; }
.os-value { font-size: var(--fs-2xs); font-weight: 700; padding: 0.1rem 0.4rem; border-radius: 999px; background: rgba(74,222,128,0.16); color: var(--green); margin-left: 0.35rem; }
/* modal body (rendered inside the shared responsive UI.modal) */
.odds-sources-modal .os-rows { display: flex; flex-direction: column; gap: 0.15rem; }
.odds-sources-modal .os-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.4rem; border-radius: 8px; }
.odds-sources-modal .os-row.os-best { background: rgba(74,222,128,0.10); }
.odds-sources-modal .os-w { font-weight: 800; font-variant-numeric: tabular-nums; min-width: 3.4rem; }
.odds-sources-modal .os-p { color: var(--text-muted); font-size: var(--fs-xs); flex: 1; }
.odds-sources-modal .os-bet { font-size: var(--fs-xs); font-weight: 700; padding: 0.25rem 0.7rem; border-radius: 6px; background: var(--accent, #7c6cff); color: #fff; text-decoration: none; display: inline-flex; align-items: center; gap: 0.2rem; }
.odds-sources-modal .os-ext { font-style: normal; }
.odds-sources-modal .os-modal-value { font-size: var(--fs-sm); color: var(--green); margin-bottom: 0.5rem; }
/* #331 best-price hero — line-shopping headline */
.odds-sources-modal .os-hero { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.6rem; margin-bottom: 0.5rem; border-radius: 10px; background: rgba(var(--overlay-rgb), 0.06); }
.odds-sources-modal .os-hero-lab { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-dim); }
.odds-sources-modal .os-hero-price { font-size: var(--fs-h3); font-weight: 800; font-variant-numeric: tabular-nums; }
.odds-sources-modal .os-hero-src { margin-left: auto; }
.odds-sources-modal .os-rg { font-size: var(--fs-2xs); color: var(--text-dim); margin-top: 0.7rem; text-align: center; }
.bk-badge { font-size: var(--fs-2xs); font-weight: 700; padding: 0.1rem 0.45rem; border-radius: 999px; white-space: nowrap; }
.bk-badge.bk-accent { background: rgba(96,165,250,0.16); color: #60a5fa; }
.bk-badge.bk-danger { background: rgba(239,68,68,0.16); color: var(--danger); }
.bk-badge.bk-success { background: rgba(74,222,128,0.16); color: #4ade80; }
.bk-badge.bk-warning { background: rgba(245,158,11,0.16); color: #f59e0b; }
.bk-badge.bk-neutral { background: rgba(148,163,184,0.16); color: var(--text-muted); }
.runner-pfai-rank.vo-rank-prov { color: var(--text-muted); background: rgba(148,163,184,0.12); } /* #297 provisional (pre-prediction) */
.runner-pfai-rank .vo-rank-prov-mark { font-size: var(--fs-2xs); opacity: 0.7; margin-left: 0.15rem; text-transform: uppercase; }
/* #298 Predicted finishing order panel */
.predicted-order .po-podium { display: flex; flex-direction: column; gap: 0.3rem; }
.predicted-order .po-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.35rem 0.5rem; border-radius: 8px; background: rgba(var(--overlay-rgb), 0.03); }
.predicted-order .po-1 { background: rgba(var(--accent-rgb), 0.14); }
.predicted-order .po-pos { font-weight: 800; min-width: 2.2rem; color: var(--accent-light); }
.predicted-order .po-num { font-size: var(--fs-xs); font-weight: 800; background: rgba(0,0,0,0.35); color: #fff; border-radius: 5px; padding: 0.05rem 0.35rem; }
.predicted-order .po-name { font-weight: 700; flex: 1; }
.predicted-order .po-pcts { display: flex; gap: 0.6rem; font-variant-numeric: tabular-nums; }
.predicted-order .po-pct { font-size: var(--fs-sm); color: var(--text-muted); }
.predicted-order .po-note { font-size: var(--fs-2xs); color: var(--text-dim); margin: 0.4rem 0 0.6rem; }
.predicted-order .po-sub { font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 0.3rem; }
.predicted-order /* #419 the podium demotion flag + the stated history empty — tokens only (TC-07) */
.po-flag { font-size: var(--fs-2xs); font-weight: 800; letter-spacing: 0.04em; color: var(--avoid);
  border: 1px solid rgba(var(--avoid-rgb), 0.5); background: var(--avoid-bg); border-radius: 4px;
  padding: 0 0.3rem; margin-left: 0.4rem; flex-shrink: 0; cursor: help; }
.rs-empty { color: var(--text-muted); font-size: var(--fs-sm); padding: 0.5rem 0; font-style: italic; }

.po-value-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0.5rem; flex-wrap: wrap; }
.predicted-order .po-vs { font-size: var(--fs-xs); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.predicted-order .po-empty, .po-prompt { font-size: var(--fs-sm); color: var(--text-dim); padding: 0.4rem 0.1rem; }
.po-prompt { padding: 0.6rem 0.75rem; background: rgba(var(--overlay-rgb), 0.03); border-radius: 8px; margin: 0.5rem 0; }

.confidence-tag {
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.conf-high { color: var(--green); }
.conf-medium { color: var(--win); }
.conf-low { color: var(--danger); }

.score-bar-wrap {
  width: 100%;
  background: var(--bg);
  border-radius: 3px;
  height: 3px;
  overflow: hidden;
}

.score-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  width: 0;
  transition: width 0.7s ease-out;
}

.score-breakdown {
  display: flex;
  flex-wrap: wrap;
  gap: 0.1rem 0.35rem;
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-dim);
}

/* Results Section */

.results-section {
  max-width: 1380px;
  margin: 1rem auto;
  padding: 0 1rem;
}

#checkResultsBtn {
  background: transparent;
  color: var(--ew);
  border: 1px solid rgba(var(--ew-rgb), 0.3);
  padding: 0.45rem 1rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: var(--fs-body);
  font-weight: 600;
  font-family: var(--font);
  transition: all 0.15s;
}

#checkResultsBtn:hover { border-color: var(--ew); background: rgba(var(--ew-rgb), 0.06); }
#checkResultsBtn:disabled { opacity: 0.4; cursor: not-allowed; }

.results-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  margin-top: 0.6rem;
}

.rc-header {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 0.5rem;
}

.rc-pending {
  color: var(--text-muted);
  font-size: var(--fs-body);
}

.rc-positions {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin-bottom: 0.65rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--border);
}

.rc-pos {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.rc-pos-num {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text-dim);
  min-width: 32px;
}

.rc-pos-horse {
  font-weight: 600;
  font-size: var(--fs-h4);
  color: var(--text);
}

.rc-pos-margin {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.rc-score-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.3rem;
}

.rc-label {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  min-width: 80px;
}

.rc-value {
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--text);
}

.rc-badge {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.rc-correct { background: var(--green); color: var(--on-status, var(--bg-card)); }
.rc-placed { background: var(--ew); color: var(--on-status, var(--bg-card)); }
.rc-miss { background: var(--danger); color: #fff; }

.rc-accuracy {
  margin-top: 0.65rem;
  padding-top: 0.65rem;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.rc-acc-label {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  width: 100%;
  margin-bottom: 0.1rem;
}

.rc-acc-stat {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-mid);
  background: var(--bg);
  border: 1px solid var(--border);
  padding: 0.15rem 0.45rem;
  border-radius: 5px;
}

/* Stream Panel */

.stream-panel {
  display: none;
  max-width: 1380px;
  margin: 0.75rem auto;
  padding: 0 1rem;
}

.stream-panel pre {
  background: var(--bg);
  padding: 0.75rem;
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--ew);
  white-space: pre-wrap;
  max-height: 350px;
  overflow-y: auto;
}

#streamBtn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--accent-light);
  padding: 0.35rem 0.85rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: var(--fs-sm);
  margin-bottom: 0.6rem;
}

#streamBtn:hover { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.08); }

/* Usage Footer */

.usage-footer {
  display: none;
  max-width: 1380px;
  margin: 0.75rem auto 2rem;
  padding: 0.4rem 1rem;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  text-align: center;
  border-top: 1px solid var(--border);
}

/* ── Staking Panel ─────────────────────────────────────────────────────────── */

.staking-panel {
  max-width: 1380px;
  margin: 1.5rem auto;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
}

.staking-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1rem;
}

.staking-title {
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--text);
  margin: 0;
}

.staking-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  font-size: var(--fs-body);
  color: var(--text-dim);
}

.staking-controls input,
.staking-controls select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  padding: 0.25rem 0.5rem;
  font-size: var(--fs-body);
}

/* Secondary = a NEUTRAL surface button, clearly subordinate to the accent-filled
   primary (they used to be identical). Hierarchy: primary (accent) > secondary
   (neutral) > outline (ghost) > danger. */
.btn-secondary {
  background: var(--bg-light);
  color: var(--text);
  border: 1px solid var(--border-light);
  padding: 0.35rem 0.9rem;
  font-weight: 600;
  font-size: var(--fs-body);
  border-radius: 7px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.btn-secondary:hover { background: #464d61; border-color: var(--accent); color: #fff; }
.btn-secondary:active { background: #2f3546; }

/* Universal disabled — clearly non-interactive across every button variant (was only
   defined for a few). Greyed + not-allowed, with hover feedback suppressed. */
.btn-primary:disabled, .btn-secondary:disabled, .btn-outline:disabled, .btn-danger:disabled, .hero-cta:disabled,
.btn-primary[disabled], .btn-secondary[disabled], .btn-outline[disabled], .btn-danger[disabled] {
  opacity: 0.45; cursor: not-allowed; box-shadow: none; filter: grayscale(0.3);
}
.btn-primary:disabled:hover, .hero-cta:disabled:hover { background: var(--accent-btn); }
.btn-secondary:disabled:hover { background: var(--bg-light); border-color: var(--border-light); color: var(--text); }
.btn-outline:disabled:hover { background: transparent; border-color: var(--border); color: var(--accent-light); }
.btn-danger:disabled:hover { background: transparent; }

.staking-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.staking-table th {
  text-align: left;
  padding: 0.4rem 0.6rem;
  color: var(--text-dim);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.staking-table td {
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--border-light, rgba(var(--overlay-rgb), 0.05));
  color: var(--text);
}

.staking-table tr:last-child td { border-bottom: none; }

.st-name { font-weight: 600; }
.st-toppick { color: var(--accent); }
.st-dim { color: var(--text-dim); }
.st-odds { font-weight: 500; }
.tp-badge {
  font-size: var(--fs-xs);
  font-weight: 700;
  background: var(--accent-btn);
  color: var(--on-accent);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  vertical-align: middle;
  margin-left: 0.3rem;
}

.edge-pos { color: #4caf7d; font-weight: 600; }
.edge-neg { color: var(--text-dim); }

.st-stake { font-family: var(--mono); font-size: var(--fs-body); }

.bet-btn {
  font-size: var(--fs-xs);
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  margin-left: 0.4rem;
}
.bet-btn:hover { background: var(--accent-btn); color: var(--on-accent); }
.bet-tracked { border-color: #4caf7d; color: #4caf7d; }

.odds-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  flex-wrap: wrap;
}
.odds-input {
  width: 56px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  padding: 0.2rem 0.35rem;
  font-size: var(--fs-body);
  font-family: var(--mono);
}
.odds-edge { flex-basis: 100%; font-size: var(--fs-xs); margin-top: 0.1rem; }

.stake-cell {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  flex-wrap: wrap;
}
.stake-dollar { color: var(--text-dim); font-size: var(--fs-body); }
.stake-input {
  width: 56px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  padding: 0.2rem 0.35rem;
  font-size: var(--fs-body);
  font-family: var(--mono);
}
.stake-suggest {
  flex-basis: 100%;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 0.1rem;
}
.stake-diff {
  font-size: var(--fs-xs);
  color: #e0a23c;
  font-family: var(--mono);
  margin-left: 0.25rem;
}

.staking-note {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin: 0.75rem 0 0;
}

.cal-banner {
  font-size: var(--fs-sm);
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
  margin-bottom: 0.75rem;
  border: 1px solid transparent;
}
.cal-good    { background: rgba(76,175,125,0.1);  border-color: rgba(76,175,125,0.3);  color: #4caf7d; }
.cal-weak    { background: rgba(229,115,115,0.1); border-color: rgba(229,115,115,0.3); color: #e57373; }
.cal-neutral { background: rgba(var(--overlay-rgb), 0.04); border-color: var(--border); color: var(--text-dim); }

.prob-raw { color: var(--text-dim); font-size: var(--fs-sm); }
.prob-cal { color: var(--text); font-weight: 600; }
.cal-method { display: block; margin-top: 0.3rem; font-size: var(--fs-xs); color: var(--text-dim); }

.staking-loading, .staking-empty, .staking-err {
  padding: 1rem;
  color: var(--text-dim);
  font-size: var(--fs-body);
}
.staking-err { color: #e57373; }

/* ── Staking panel — mobile (stacked cards) ──────────────────────────────────
   The 6-column editable table is unusable on a phone, so below 760px each
   runner becomes a card: thead is hidden and every cell becomes a labelled
   row (label left via data-label, value/input right). */
@media (max-width: 760px) {
  .staking-panel { padding: 1rem; margin: 1rem auto; }

  /* Controls: each on its own full-width line with the field pushed right. */
  .staking-controls { flex-direction: column; align-items: stretch; gap: 0.5rem; width: 100%; }
  .staking-controls label {
    display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; width: 100%;
  }
  .staking-controls input,
  .staking-controls select { flex: 0 0 auto; min-width: 0; }
  .staking-controls #bankrollInput { width: 110px !important; }
  .staking-controls select { max-width: 60%; }
  #calcStakingBtn { width: 100%; padding: 0.55rem; }

  .staking-table thead { display: none; }
  .staking-table, .staking-table tbody, .staking-table tr, .staking-table td { display: block; width: 100%; }
  .staking-table tr {
    border: 1px solid var(--border); border-radius: 9px; padding: 0.3rem 0.7rem;
    margin-bottom: 0.7rem; background: var(--bg);
  }
  .staking-table td {
    display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
    padding: 0.45rem 0; border-bottom: 1px solid var(--border-light, rgba(var(--overlay-rgb), 0.06));
  }
  .staking-table tr td:last-child { border-bottom: none; }
  /* Label from data-label sits on the left of each row. */
  .staking-table td::before {
    content: attr(data-label); color: var(--text-dim); font-size: var(--fs-sm);
    font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; flex: 0 0 auto;
  }
  /* Horse name = card title: full-width, larger, no label. */
  .staking-table td.st-name {
    justify-content: flex-start; font-size: var(--fs-h3); padding-top: 0.55rem;
    border-bottom: 1px solid var(--border);
  }
  .staking-table td.st-name::before { content: none; }

  /* Bigger tap targets for the editable fields on the right. */
  .odds-cell, .stake-cell { justify-content: flex-end; flex-wrap: wrap; }
  .odds-input, .stake-input { width: 72px; padding: 0.4rem 0.45rem; font-size: var(--fs-h4); }
  .bet-btn { padding: 0.4rem 0.8rem; font-size: var(--fs-sm); margin-left: 0.5rem; }
  .odds-edge, .stake-suggest { flex-basis: 100%; text-align: right; }
}

/* ── P&L Tracker ───────────────────────────────────────────────────────────── */

.pnl-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.pnl-table th {
  text-align: left;
  padding: 0.35rem 0.6rem;
  color: var(--text-dim);
  font-weight: 500;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.pnl-table td {
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--border-light, rgba(var(--overlay-rgb), 0.05));
  color: var(--text);
}

.pnl-table tr:last-child td { border-bottom: none; }
.pnl-table tr:hover td { background: rgba(var(--overlay-rgb), 0.02); }

.pnl-horse { font-weight: 600; }
.pnl-mono  { font-family: var(--mono); font-weight: 600; }

.pnl-pos     { color: #4caf7d; }
.pnl-neg     { color: #e57373; }
.pnl-pending { color: var(--text-dim); }

.sc-bad { color: #e57373; }

/* Admin sub-navigation */
.admin-subnav {
  display: flex;
  gap: 0.4rem;
  margin: 0 0 1.5rem;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  align-items: center;
}
/* Group heading in the grouped admin sub-nav (#50) */
.admin-subnav-group {
  padding: 0 0.5rem 0 0.9rem;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.admin-subnav-group:first-child { padding-left: 0; }
.admin-subnav a {
  padding: 0.55rem 1rem;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text-dim);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.admin-subnav a:hover { color: var(--text); }
.admin-subnav a.active { color: var(--accent); border-bottom-color: var(--accent); }

/* Accuracy-over-time chart */
.acc-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 0.5rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
}
.acc-key { display: inline-flex; align-items: center; gap: 0.35rem; }
.ak-line { display: inline-block; width: 16px; height: 3px; border-radius: 2px; }
.ak-win     { background: var(--accent); }
.ak-place   { background: var(--ew); }
.ak-rollwin { background: var(--win); }

/* Bankroll page */
.bankroll-setup {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
}
.bankroll-field { display: flex; flex-direction: column; gap: 0.3rem; font-size: var(--fs-sm); color: var(--text-dim); }
.bankroll-input-wrap { font-size: var(--fs-h3); color: var(--text); font-weight: 600; }
.bankroll-input-wrap input {
  width: 120px; background: var(--bg); border: 1px solid var(--border);
  border-radius: 6px; color: var(--text); padding: 0.35rem 0.5rem; font-size: var(--fs-h3); font-weight: 600;
}
.bankroll-current { margin-left: auto; text-align: right; }
.bankroll-current-row { display: flex; align-items: baseline; gap: 0.6rem; justify-content: flex-end; }
.bc-label { font-size: var(--fs-sm); color: var(--text-dim); }
.bc-value { font-size: var(--fs-h1); font-weight: 700; font-family: var(--mono); }
.bankroll-current-sub { font-size: var(--fs-xs); color: var(--text-dim); margin-top: 0.2rem; }

/* Responsive */

/* Stats Page */

.stat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.5rem;
}

.stat-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem;
  text-align: center;
}

.sc-value {
  font-family: var(--mono);
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--text);
}

.sc-value.sc-good { color: var(--green); }

.sc-label {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 0.2rem;
}

.sc-sub {
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  margin-top: 0.15rem;
  opacity: 0.7;
}

/* Top-pick outcome breakdown bar */
.outcome-bar {
  display: flex; height: 26px; width: 100%;
  border-radius: 7px; overflow: hidden; margin-top: 0.5rem;
  background: var(--bg-card); border: 1px solid var(--border);
}
.outcome-bar .ob-seg {
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-xs); font-weight: 700; color: #0b0d14; white-space: nowrap;
}
.ob-won { background: #2e9e5b; }
.ob-placed { background: #d8a01f; }
.ob-unplaced { background: #5a3138; color: #e8c4c4; }
.outcome-legend {
  display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 0.5rem;
  font-size: var(--fs-sm); color: var(--text-muted);
}
.outcome-legend .ob-key {
  display: inline-block; width: 0.8rem; height: 0.8rem; border-radius: 3px;
  vertical-align: middle; margin-right: 0.3rem;
}

.factor-bars {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-top: 0.5rem;
}

.factor-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.fr-label {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  min-width: 60px;
  text-transform: capitalize;
}

.fr-bar-wrap {
  flex: 1;
  height: 6px;
  background: var(--bg);
  border-radius: 3px;
  overflow: hidden;
}

.fr-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
}

.fr-value {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-mid);
  min-width: 28px;
  text-align: right;
}

.weight-grid {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.weight-item {
  display: grid;
  grid-template-columns: 110px 1fr 42px auto;
  align-items: center;
  gap: 0.5rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
}

.wi-delta {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 700;
  white-space: nowrap;
  padding: 0.08rem 0.4rem;
  border-radius: 999px;
  cursor: help;
}
.wi-delta .wd-arrow { opacity: 0.6; margin: 0 0.1rem; }
.wi-delta.wd-up   { color: var(--green); background: rgba(var(--green-rgb), 0.12); }
.wi-delta.wd-down { color: var(--danger); background: rgba(var(--danger-rgb), 0.12); }

.stat-updated {
  font-size: var(--fs-sm);
  color: var(--text-muted, #94a3b8);
  margin: 0.1rem 0 0.7rem;
}

.wi-label {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  text-transform: capitalize;
}

.wi-value {
  font-family: var(--mono);
  font-size: var(--fs-body);
  font-weight: 700;
  color: var(--text-mid);
}

.wi-value.wi-high { color: var(--green); }
.wi-value.wi-low { color: var(--danger); }

.wi-bar-wrap {
  height: 5px;
  background: var(--bg-hover);
  border-radius: 3px;
  overflow: hidden;
}
.wi-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 3px;
  transition: width 0.4s ease;
}

.section-explainer {
  font-size: var(--fs-body);
  color: var(--text-mid);
  line-height: 1.7;
  margin-bottom: 0.75rem;
  margin-top: 0.25rem;
  padding: 0.75rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}
/* A lead-in heading on its own line is OPT-IN via .se-lead (add it to a strong that is
   genuinely a mini-heading). Previously any strong:first-child blocked — which misfired on
   copy that merely opened with an inline bold word (CSS :first-child ignores the leading
   text node), forcing an unwanted line break mid-sentence. */
.section-explainer > strong.se-lead {
  display: block;
  color: var(--text);
  font-weight: 600;
  font-size: var(--fs-body);
  margin-bottom: 0.35rem;
}
.section-explainer strong {
  display: inline;
  color: var(--text);
  font-weight: 600;
}

/* Predictions Page */

.pred-group {
  margin-bottom: 1.5rem;
}

.pred-meet {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 0.6rem;
}

.pm-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.85rem;
  background: rgba(var(--accent-rgb), 0.04);
  border-bottom: 1px solid var(--border);
}

.pm-course {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
}

.pm-date {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.pm-count {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-left: auto;
}

.pred-meet .pred-list {
  gap: 0;
}

.pred-meet .pred-card {
  border: none;
  border-radius: 0;
  border-top: 1px solid var(--border);
  background: transparent;
}

.pred-meet .pred-card:first-child { border-top: none; }
.pred-meet .pred-card:hover { background: var(--bg-hover); }

.pc-race-name {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pred-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.pred-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.7rem 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  transition: border-color 0.12s, background 0.12s;
}

.pred-card:hover { border-color: var(--accent); background: var(--bg-hover); }
.pred-card.pred-scratched { border-left: 3px solid var(--danger); }

/* At-a-glance prediction outcome */
.pred-card.pred-won { border-left: 3px solid #2e9e5b; }
.pred-card.pred-place { border-left: 3px solid #c9971f; }
.pred-card.pred-miss { border-left: 3px solid #c0392b; }

.pc-outcome {
  margin-left: auto;
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  white-space: nowrap;
  letter-spacing: 0.3px;
}
.po-win { background: rgba(46, 158, 91, 0.18); color: #46c884; }
.po-place { background: rgba(201, 151, 31, 0.18); color: #e0b34a; }
.po-miss { background: rgba(192, 57, 43, 0.16); color: #e07a6f; }
.po-pending { background: var(--bg-hover); color: var(--text-dim); }

.pc-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.pc-course {
  font-weight: 700;
  font-size: var(--fs-body);
  color: var(--text);
}

.pc-race {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--accent-light);
}

.pc-time {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-left: auto;
}

.pc-name {
  font-size: var(--fs-sm);
  color: var(--text-mid);
}

.pc-pick {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.15rem;
}

.pc-pick-label {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.pc-pick-value {
  font-weight: 700;
  font-size: var(--fs-body);
  color: var(--win);
}

.pc-ew {
  font-size: var(--fs-xs);
  color: var(--ew);
  margin-left: 0.5rem;
}

.pc-summary {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  font-style: italic;
}

.pc-meta {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

/* Archive View */

.archive-view {
  max-width: 1380px;
  margin: 0 auto;
  padding: 0.75rem 1rem 2rem;
}

.archive-section {
  margin-bottom: 1.5rem;
}

.archive-heading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 0.45rem 0;
  border: none;
  border-bottom: 1px solid var(--border);
  background: none;
  cursor: pointer;
  margin-bottom: 0.5rem;
  text-align: left;
}
.archive-heading:hover { color: var(--text); }
.ah-caret { transition: transform 0.15s; font-size: var(--fs-xs); color: var(--accent-light); }
.archive-section.collapsed .ah-caret { transform: rotate(-90deg); }
.ah-label { flex: 1; }
.ah-count { font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--text-dim); }
.archive-section.collapsed .archive-section-body { display: none; }

/* Inner cards mirror the predictions page (.pred-meet / .pm-header / .pred-card). */
.archive-day {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 0.6rem;
  overflow: hidden;
}

.archive-day-header {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
  padding: 0.55rem 0.85rem;
  background: rgba(var(--accent-rgb), 0.04);
  border-bottom: 1px solid var(--border);
}

.archive-meets {
  display: flex;
  flex-direction: column;
}

.archive-meet-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
  border-top: 1px solid var(--border);
  transition: background 0.12s;
}

.archive-meet-link:first-child { border-top: none; }
.archive-meet-link:hover { background: var(--bg-hover); }

.aml-course {
  font-size: var(--fs-h4);
  font-weight: 700;
  color: var(--text);
}

.aml-info {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.aml-pred {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  color: var(--accent-light);
  background: rgba(var(--accent-rgb), 0.1);
  padding: 0.08rem 0.35rem;
  border-radius: 3px;
  margin-left: auto;
}

@media (max-width: 800px) {
  .sidebar { display: none; }
  .race-layout { display: block; }
  .nav-sidebar { display: none; }
  .page-layout { display: block; }
}

@media (max-width: 640px) {
  body { font-size: 14px; }

  header { padding: 1rem 0.75rem; }
  header h1 { font-size: var(--fs-h2); }

  .page-main { padding: 0.5rem var(--page-pad-x-m) 1.5rem; } /* #235 wider usable card area */
  .landing { padding: 0 0.85rem 1.5rem; }
  .landing-hero { padding: 1.25rem 0 1rem; }
  .landing-hero h2 { font-size: var(--fs-h3); }
  .landing-cards { grid-template-columns: 1fr; }
  .wm-meets { gap: 0.25rem; }

  .race-nav-pill { flex-wrap: wrap; gap: 0.3rem; }
  .rnp-meta { display: none; }

  .meet-nav { padding: 0.4rem 0.5rem; }

  .race-hero { padding: 1rem 0.75rem 0.4rem; }
  .hero-name { font-size: var(--fs-h3); }

  .race-actions { padding: 0 0.75rem; flex-wrap: wrap; }

  .top-pick { margin: 0.75rem 0.5rem; padding: 0.85rem; }
  .top-pick-name { font-size: var(--fs-h2); }

  .runners-container { padding: 0.4rem 0.5rem 1.5rem; }

  /* #135 mobile card (guided by the design mock): silk | compact info | win/place %
     boxes in ONE row, then the pace bar + actions full-width below. Rank goes inline. */
  .runner-row { padding: 0.45rem 0.3rem; gap: 0.35rem; }
  .runner-compact {
    grid-template-columns: 50px 1fr auto; /* #141 wide enough for the silk plate + its outside gap (no overlap into the name) */
    gap: 0.4rem;
    align-items: start;
  }
  /* #235 trim double padding inside the runner-card expander on phones */
  .stat-grid { padding: 0.55rem 0.6rem; gap: 0.5rem 0.6rem; }
  .rc-comments { padding: 0.55rem 0.6rem; }
  /* #135/#141 main info: one label:value line per row at all widths (base rule);
     mobile only trims the value size + top gap a touch. */
  .runner-main-info { margin-top: 0.15rem; }
  .runner-main-info .info-value { font-size: var(--fs-sm); }
  .runner-form { font-size: var(--fs-xs); }
  .pace-bar-label { min-width: 62px; }

  /* Tight, left-aligned silk + number so the name/connections get the width back */
  .runner-num-silk { align-items: stretch; gap: 0.2rem; }
  .silk-img { width: 42px; padding: 2px; margin: 0.25rem 0.2rem; }
  .runner-num {
    font-size: var(--fs-h3); min-width: 0; width: 100%; padding: 0.2rem 0;
  }

  /* Tables: smaller text + tighter cells so they wrap to width instead of overflowing */
  .bt-table { font-size: var(--fs-sm); }
  .bt-table th, .bt-table td { padding: 0.4rem 0.45rem; }

  /* Tab bars wrap / shrink so 4–5 tabs fit a phone width */
  .admin-subnav { flex-wrap: wrap; }
  .admin-subnav a { padding: 0.5rem 0.7rem; font-size: var(--fs-sm); }
  .stat-tab { padding: 0.5rem 0.6rem; font-size: var(--fs-sm); }
  .stat-cards { grid-template-columns: repeat(2, 1fr); }

  /* #135 win/place % boxes stay in the right column (not a full-width second row) */
  .runner-right {
    grid-column: auto;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.3rem;
    border-top: none;
    padding-top: 0;
    margin-top: 0;
  }
  .runner-right .odds-section { font-size: var(--fs-xs); text-align: right; color: var(--text-muted); }

  .prediction-section {
    align-items: flex-end;   /* #140 keep win / confidence / win% / place% right-aligned on mobile */
    border-top: none;
    padding-top: 0;
  }

  .runner-info-grid, .runner-stats-grid { gap: 0.2rem; }
  .runner-breeding-line { display: none; }
  .runner-owner { display: none; }
}

@media (max-width: 380px) {
  .race-actions select { font-size: var(--fs-sm); padding: 0.4rem 0.5rem; }
  #predictBtn, #recalcBtn { font-size: var(--fs-sm); padding: 0.45rem 0.85rem; }
  .hero-meta { gap: 0.25rem; }
  .hero-chip { font-size: var(--fs-xs); padding: 0.15rem 0.4rem; }
}

/* ── Performance scorecard (UI.performanceScorecard) ─────────────────────────
   High-level, graphical, responsive summary of tip performance (win + each-way).
   Rings scale via SVG viewBox; the gauge row and type grid wrap on small screens. */
.perf-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px;
  padding: 1.25rem 1.35rem; max-width: 100%;
}
.perf-card .ps-head { margin-bottom: 0.5rem; }
.perf-card .ps-title { font-size: var(--fs-h3); font-weight: 700; }
.perf-card .ps-sub { font-size: var(--fs-body); color: var(--text-muted); margin-top: 0.15rem; display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.ps-trend { font-weight: 700; }
.ps-trend.up { color: var(--ew); } .ps-trend.down { color: var(--danger); }

.ps-gauges { display: flex; flex-wrap: wrap; gap: 1rem 1.5rem; justify-content: center; padding: 0.75rem 0 0.25rem; }
.ps-gauge { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; flex: 1 1 120px; min-width: 96px; max-width: 160px; }
.ps-ring { width: 100%; height: auto; max-width: 150px; }
.ps-ring .ps-track { fill: none; stroke: var(--border); stroke-width: 12; }
.ps-ring .ps-arc { fill: none; stroke-width: 12; stroke-linecap: round; transform: rotate(-90deg); transform-origin: 60px 60px; transition: stroke-dashoffset 0.9s cubic-bezier(0.4,0,0.2,1); }
.ps-ring .ps-val { fill: var(--text); font-size: 30px; font-weight: 800; text-anchor: middle; dominant-baseline: central; }
.ps-ring .ps-pct { font-size: 15px; font-weight: 700; fill: var(--text-muted); }
.ps-glabel { font-size: var(--fs-sm); color: var(--text-mid); font-weight: 600; text-align: center; }

.ps-types { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.6rem 1rem; margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--border); }
.ps-type-head { display: flex; justify-content: space-between; font-size: var(--fs-body); font-weight: 600; margin-bottom: 0.35rem; }
.ps-type-n { color: var(--text-muted); font-weight: 500; }
.ps-tb { display: flex; align-items: center; gap: 0.4rem; font-size: var(--fs-xs); margin-bottom: 0.2rem; }
.ps-tb-k { color: var(--text-muted); width: 26px; flex: none; }
.ps-tb-track { flex: 1; height: 6px; background: rgba(var(--overlay-rgb), 0.06); border-radius: 4px; overflow: hidden; }
.ps-tb-fill { height: 100%; border-radius: 4px; transition: width 0.9s cubic-bezier(0.4,0,0.2,1); }
.ps-tb-fill.win { background: var(--win); } .ps-tb-fill.plc { background: var(--accent-light); } .ps-tb-fill.ew { background: var(--ew); }
.ps-tb-v { width: 34px; flex: none; text-align: right; color: var(--text-mid); font-variant-numeric: tabular-nums; }

/* ── Tulloch's Tips — modern "elite pick" card (ties into the dark theme) ─────── */
.tulloch {
  position: relative;
  border-radius: var(--radius);
  padding: 0.8rem 1rem 0.85rem;
  color: var(--tulloch-ink);
  /* Bold, premium background — a deep violet gradient with an accent glow so the
     card leaps off the dark page while staying in the purple accent family. */
  background:
    radial-gradient(120% 130% at 100% 0%, rgba(var(--tulloch-rgb), 0.28), rgba(var(--tulloch-rgb), 0) 55%),
    linear-gradient(150deg, var(--tulloch-g1) 0%, var(--tulloch-g2) 42%, var(--tulloch-g3) 100%);
  border: 1px solid rgba(var(--tulloch-rgb), 0.45);
  box-shadow: 0 10px 34px rgba(var(--tulloch-rgb), 0.28), 0 1px 0 rgba(var(--overlay-rgb), 0.08) inset;
  overflow: hidden;
}
/* signature gradient accent bar along the top edge */
.tulloch::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, var(--tulloch), var(--ew) 70%, var(--win));
}
.tt-head { display: flex; align-items: center; gap: 0.55rem; }
.tt-crest {
  color: var(--tulloch-ink); font-size: 2.2rem; line-height: 0.8;
  filter: drop-shadow(0 0 12px rgba(var(--tulloch-rgb), 0.6));
}
.tulloch--body .tt-crest { font-size: 2.1rem; }
.tt-title {
  font-family: 'Great Vibes', 'Snell Roundhand', 'Segoe Script', cursive;
  /* #354 the cursive has tall swashes + a 'p' descender ("Tulloch's Tips"); line-height:1
     clipped them. Give it room + a hair of padding so it renders in full. */
  font-weight: 400; letter-spacing: 0.01em; font-size: 1.9rem; line-height: 1.32;
  padding-bottom: 0.06em; color: var(--tulloch-ink); text-shadow: 0 1px 10px rgba(var(--tulloch-rgb), 0.4);
}
.tt-sub {
  font-size: var(--fs-sm); color: rgba(var(--text-rgb), 0.72); margin: 0.05rem 0 0.5rem;
  padding-bottom: 0.45rem; border-bottom: 1px solid rgba(var(--overlay-rgb), 0.14);
}
.tt-list { display: flex; flex-direction: column; gap: 0.4rem; }
.tt-pick {
  display: grid; grid-template-columns: auto minmax(0,1fr) auto; align-items: center;
  gap: 0.7rem; text-decoration: none; color: inherit;
  padding: 0.45rem 0.55rem; border-radius: 8px;
  border: 1px solid rgba(var(--overlay-rgb), 0.1); background: rgba(var(--tulloch-well-rgb), 0.32);
  transition: background 0.12s, border-color 0.12s, transform 0.12s;
}
.tt-pick:hover { background: rgba(var(--tulloch-well-rgb), 0.5); border-color: var(--tulloch); transform: translateY(-1px); }
.tt-conv {
  text-align: center; flex: none; min-width: 42px;
  border-right: 1px solid rgba(var(--overlay-rgb), 0.14); padding-right: 0.6rem;
}
.tt-conv-n {
  display: block; font-weight: 800; font-size: var(--fs-h2); color: var(--tulloch-ink);
  line-height: 1; font-variant-numeric: tabular-nums; text-shadow: 0 0 12px rgba(var(--tulloch-rgb), 0.45);
}
.tt-conv-l { display: block; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.14em; color: rgba(var(--text-rgb), 0.55); margin-top: 0.15rem; }
.tt-main { min-width: 0; }
/* #354 the runner name must fit — WRAP to two lines instead of truncating with an ellipsis,
   and size it down so it fits the compact card. */
.tt-horse {
  font-weight: 700; font-size: var(--fs-body); color: var(--tulloch-ink); line-height: 1.2;
  overflow-wrap: anywhere; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.tt-meta { font-size: var(--fs-xs); color: rgba(var(--text-rgb), 0.66); margin-top: 0.1rem; }
.tt-odds { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tt-flags { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.3rem; }
.tt-flag {
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.01em;
  color: var(--tulloch-ink); background: rgba(var(--overlay-rgb), 0.12);
  border: 1px solid rgba(var(--tulloch-rgb), 0.4); border-radius: 999px; padding: 0.05rem 0.4rem;
}
.tt-status { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; flex: none; text-align: right; }
.tt-empty { font-size: var(--fs-body); color: rgba(var(--text-rgb), 0.72); padding: 0.4rem 0; }
/* Track record — one compact row: a small caption + win/place cells side by side (#258) */
.tt-record {
  margin-top: 0.55rem; padding-top: 0.5rem; border-top: 1px solid rgba(var(--overlay-rgb), 0.14);
}
.tt-rec-h { display: block; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.12em; color: rgba(var(--text-rgb), 0.55); margin-bottom: 0.3rem; }
.tt-rec-cells { display: flex; gap: 0.9rem; }
.tt-rec-cell { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.05rem; }
.tt-rec-cell + .tt-rec-cell { padding-left: 0.9rem; border-left: 1px solid rgba(var(--overlay-rgb), 0.12); }
.tt-rec-k { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.1em; color: rgba(var(--text-rgb), 0.6); }
.tt-rec-v { font-size: var(--fs-body); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.tt-rec-roi { font-size: var(--fs-xs); font-weight: 700; }
.tt-rec-cell.pos .tt-rec-v { color: var(--green); } .tt-rec-cell.neg .tt-rec-v { color: var(--danger); }
.tt-rec-sub { font-size: var(--fs-2xs); color: rgba(var(--text-rgb), 0.55); }
.tt-more {
  display: inline-block; margin-top: 0.55rem; font-size: var(--fs-sm); font-weight: 700;
  color: var(--tulloch-ink); text-decoration: none; letter-spacing: 0.01em;
}
.tt-more:hover { color: var(--tulloch-ink); text-decoration: underline; }
/* Body variant: larger, two-up grid of picks when there's room */
/* #354 On desktop the card had no max-width, so on a wide page (tulloch.html / Models tab)
   the premium gradient card stretched edge-to-edge and the auto-fit pick grid spread each
   row's runner/status far apart. Contain + centre the card, cap the grid at two up, and
   align rows to the top so uneven picks line up. */
/* #354 compact body variant: contained + centred, smaller header + tighter pick grid. */
.tulloch--body { padding: 0.85rem 1rem 0.95rem; max-width: 720px; margin-inline: auto; }
.tulloch--body .tt-title { font-size: 2.1rem; }
.tulloch--body .tt-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  align-items: start; gap: 0.5rem;
}
/* smaller pick cards in the body grid — trim the padding + conviction block */
.tulloch--body .tt-pick { padding: 0.4rem 0.5rem; gap: 0.55rem; }
.tulloch--body .tt-conv { min-width: 36px; padding-right: 0.45rem; }
.tulloch--body .tt-conv-n { font-size: var(--fs-body); }
.tulloch--body .tt-horse { font-size: var(--fs-sm); }
/* #354 halve the badges so the runner name gets the width — smaller status frees the pick
   row's third column; tiny flags + scope badge take almost no space. */
.tulloch--body .tt-status { font-size: 0.55rem; letter-spacing: 0.02em; }
.tulloch--body .tt-flags { gap: 0.2rem; margin-top: 0.25rem; }
.tulloch--body .tt-flag { font-size: 0.55rem; padding: 0.02rem 0.3rem; letter-spacing: 0; }
.tulloch--body .tt-scope { font-size: 0.55rem; padding: 0.02rem 0.32rem; } /* smaller "Horses only" badge */
/* one lone tip shouldn't become a full-width bar — keep it to a card's width, left-aligned */
.tulloch--body .tt-list:has(> .tt-pick:only-child) { grid-template-columns: minmax(260px, 380px); justify-content: start; }
@media (max-width: 640px) { .tulloch--body .tt-list, .tulloch--body .tt-list:has(> .tt-pick:only-child) { grid-template-columns: 1fr; } }

/* Tulloch's Tips — admin config sliders */
.tt-cfg { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.2rem; margin-top: 0.6rem; }
.tt-cfg-group { border: 1px solid var(--border); border-radius: 8px; padding: 0.8rem 0.9rem; }
.tt-cfg-title { font-weight: 700; font-size: var(--fs-body); margin-bottom: 0.6rem; color: var(--text); }
.tt-cfg-row { display: grid; grid-template-columns: 9.5rem 1fr 2.4rem; align-items: center; gap: 0.5rem; margin-bottom: 0.55rem; }
.tt-cfg-k { font-size: var(--fs-body); color: var(--text); }
.tt-cfg-v { font-size: var(--fs-body); font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; color: var(--accent-light); }
.tt-cfg-hint { grid-column: 1 / -1; font-size: var(--fs-xs); color: var(--text-muted); margin-top: -0.15rem; }
.tt-cfg-row input[type=range] { width: 100%; accent-color: var(--accent); }

/* Model profit/loss card */
.pl-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0.75rem; margin-top: 0.25rem; }
.pl-row { border: 1px solid var(--border); border-radius: 10px; padding: 0.7rem 0.85rem; background: rgba(var(--overlay-rgb), 0.02); }
.pl-row-head { display: flex; justify-content: space-between; align-items: center; font-size: var(--fs-h4); font-weight: 700; margin-bottom: 0.55rem; }
.pl-row-n { color: var(--text-muted); font-weight: 500; font-size: var(--fs-sm); }
.pl-figs { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.pl-fig { background: rgba(var(--overlay-rgb), 0.03); border-radius: 8px; padding: 0.5rem 0.6rem; }
.pl-fig-k { font-size: var(--fs-xs); color: var(--text-muted); margin-bottom: 0.15rem; }
.pl-fig-v { font-size: var(--fs-h3); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.pl-fig-roi { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; margin-top: 0.1rem; }
.pl-fig-v.pos, .pl-fig-roi.pos, .pl-overall.pos strong { color: var(--green); }
.pl-fig-v.neg, .pl-fig-roi.neg, .pl-overall.neg strong { color: var(--danger); }
.pl-overall { margin-top: 0.85rem; padding-top: 0.75rem; border-top: 1px solid var(--border); font-size: var(--fs-h4); }
.pl-note { margin-top: 0.6rem; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.5; }

@media (max-width: 480px) {
  .perf-card { padding: 1rem; }
  .ps-gauges { gap: 0.75rem; }
  .ps-gauge { flex-basis: 90px; min-width: 84px; }
  .ps-ring .ps-val { font-size: 26px; }
  /* Weight bars: shrink the label so the bar keeps room on a phone. */
  .weight-item { grid-template-columns: 78px 1fr auto auto; gap: 0.35rem; padding: 0.4rem 0.5rem; }
  .pl-note { font-size: var(--fs-xs); }
}
  
/* Betslip Button */  
.betslip-btn { background: none; border: none; cursor: pointer; padding: 4px; color: #a0aec0; transition: all 0.2s ease; display: inline-flex; align-items: center; justify-content: center; }  
.betslip-btn:hover { color: #e2e8f0; transform: scale(1.1); }  
.betslip-btn.active { color: #fbbf24; }  
.betslip-btn.active .star-icon { fill: #fbbf24; }  
.star-icon { width: 18px; height: 18px; } 

/* ── Account / betslip components (#64/#65) ─────────────────────────────────
   Single-source classes for the My Account page + betslip rows, using theme
   variables (replacing the hardcoded-hex inline styles). account.js should
   adopt these when the #20 fix lands. Mobile: rows stack at 640px. */
/* Account / settings layout (#113/#142) — reusable page layout (UI.accountLayout):
   a horizontal tab bar across the top with full-width panels below (the same tab
   convention as the component showcase), so the content gets the whole page width
   instead of losing a fixed left rail. Same nav structure at every width. */
.acct-layout { display: block; }
/* Desktop: tabs wrap, no scroll (overflow-x:auto would force overflow-y:auto and
   show a stray vertical scrollbar). Mobile below switches to a horizontal scroll. */
.acct-nav { display: flex; flex-flow: row wrap; gap: 0.2rem; margin-bottom: 1.25rem; border-bottom: 1px solid var(--border); }
.acct-nav-link { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 1rem; color: var(--text-muted); text-decoration: none; font-size: var(--fs-h4); font-weight: 600; white-space: nowrap; border: none; border-bottom: 2px solid transparent; border-radius: 6px 6px 0 0; margin-bottom: -1px; transition: background .15s, color .15s, border-color .15s; }
.acct-nav-link:hover { background: var(--bg-hover, rgba(var(--overlay-rgb), 0.04)); color: var(--text, #fff); }
.acct-nav-link.active { color: var(--green); border-bottom-color: var(--green); background: transparent; }
.acct-nav-ico { font-size: var(--fs-h3); line-height: 1; }
.acct-main { min-width: 0; }
.acct-panel { padding: 1.5rem; background: var(--bg-card); border-radius: 8px; border: 1px solid var(--border); }
.acct-panel[hidden] { display: none; }
@media (max-width: 720px) {
  .acct-nav { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; margin-bottom: 1rem; -webkit-overflow-scrolling: touch; }
  .acct-nav-link { padding: 0.5rem 0.75rem; font-size: var(--fs-h4); }
  .acct-panel { padding: 1.1rem; }
}
.betslip-item { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem; background: var(--bg-hover); border-radius: 6px; border: 1px solid var(--border); margin-bottom: 0.5rem; }
.betslip-item .bs-details { display: flex; align-items: center; gap: 0.75rem; color: var(--text, #fff); text-decoration: none; flex: 1; min-width: 0; }
.betslip-item .bs-course { font-weight: 500; }
.betslip-item .bs-time { font-size: var(--fs-body); color: var(--text-muted); }
.btn-remove-betslip { background: transparent; border: 1px solid var(--danger, #ef4444); color: var(--danger, #ef4444); border-radius: 4px; padding: 0.4rem 0.75rem; cursor: pointer; margin-left: 1rem; min-height: 40px; }
.bs-section-label { margin-top: 1.5rem; margin-bottom: 0.75rem; font-size: var(--fs-h4); font-weight: bold; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; }
/* Touch target: the star is 18px visual but needs a ~40px hit area on mobile. */
.betslip-btn { min-width: 32px; min-height: 32px; }
@media (max-width: 640px) {
  .betslip-item { flex-wrap: wrap; gap: 0.5rem; }
  .btn-remove-betslip { margin-left: 0; width: 100%; }
  .betslip-btn { min-width: 40px; min-height: 40px; }
}

/* Segmented betslip control (#73 AC) */
/* The Win/E-W/Place pills ARE component-library badges (.badge.sel-* / .badge-neutral).
   The control is just a flex row; .bs-seg-btn is a button reset + tap target that
   defers ALL appearance to the badge classes. */
.betslip-runner-control {
  display: inline-flex;
  gap: 0.3rem;
  margin: 4px 0;
}
.bs-seg-btn {
  border: none;
  cursor: pointer;
  padding: 4px 9px;          /* a touch larger than a static badge, for tapability */
  min-height: 26px;
  transition: filter 0.15s ease;
}
.bs-seg-btn.badge-neutral:hover { color: var(--text); border-color: var(--text-dim); }
.bs-seg-btn.sel-win:hover, .bs-seg-btn.sel-ew:hover, .bs-seg-btn.sel-place:hover { filter: brightness(1.1); }


/* ── Virtual Betslip v2 (#74 rich cards + #75 sort/group) ──────────────────── */
.bs-loading { color: var(--text-muted); padding: 1rem 0; }
.bs-controls { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; margin-bottom: 1rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
.bs-ctl-group { display: inline-flex; align-items: center; gap: 0.4rem; }
.bs-ctl-lbl { font-size: var(--fs-sm); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
.bs-ctl-btn { background: var(--bg-hover); border: 1px solid var(--border); color: var(--text-muted); border-radius: 4px; padding: 0.3rem 0.6rem; font-size: var(--fs-sm); cursor: pointer; min-height: 32px; }
.bs-ctl-btn.active { background: var(--accent-btn); color: var(--on-accent); border-color: var(--accent-btn); }
.bs-ctl-toggle { font-size: var(--fs-body); color: var(--text-muted); cursor: pointer; gap: 0.3rem; }
.bs-group-head { margin: 1.25rem 0 0.6rem; font-size: var(--fs-body); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; display: flex; align-items: center; gap: 0.5rem; }
.bs-card { background: var(--bg-hover); border: 1px solid var(--border); border-left: 3px solid var(--border); border-radius: 6px; margin-bottom: 0.6rem; overflow: hidden; }
.bs-card-horse { border-left-color: var(--type-horse); }
.bs-card-greyhound { border-left-color: var(--type-grey); }
.bs-card-harness { border-left-color: var(--type-harness); }
.bs-card-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; background: rgba(0,0,0,0.15); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.bs-race-link { display: inline-flex; align-items: center; gap: 0.5rem; text-decoration: none; color: var(--text, #fff); min-width: 0; }
.bs-track { font-weight: 600; font-size: var(--fs-h4); }
/* Share button (#49) — copy / native-share affordance. */
.share-btn { display: inline-flex; align-items: center; gap: 0.35rem; background: var(--bg-hover, rgba(var(--overlay-rgb), 0.05)); border: 1px solid var(--border); color: var(--text, #e8e8e8); border-radius: 999px; padding: 0.35rem 0.8rem; font-size: var(--fs-body); cursor: pointer; }
.share-btn:hover { border-color: var(--green); color: var(--green); }
/* Top bar: back-link on the left, share button on the right (in line), on every race type. */
.race-topbar { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; }
.race-topbar .share-btn { padding: 0.28rem 0.7rem; font-size: var(--fs-sm); }
/* Blackbook card links (#blackbook-links): bound-runner name -> profile, and a
   "racing today" link -> the race page. */
.bb-name-link { font-weight: 600; color: var(--text, #fff); text-decoration: none; }
.bb-name-link:hover { text-decoration: underline; color: var(--green); }
.bb-race-link { display: inline-block; margin-top: 0.3rem; font-size: var(--fs-body); color: var(--green); text-decoration: none; }
.bb-race-link:hover { text-decoration: underline; }
.bs-jump { font-size: var(--fs-body); color: var(--text-muted); white-space: nowrap; }
.bs-r-time { font-weight: 700; color: var(--accent); }
.bs-card-body { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.6rem 0.75rem; }
/* Betslip runner rows now render via the shared UI.runnerCard (see account.js),
   so the old bespoke silk/number/row styles were removed. Only the connection
   label bits remain betslip-specific (used in the runnerCard `connections` slot). */
.bs-conn { white-space: nowrap; }
.bs-lbl { color: var(--text-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.4px; }

/* ── Bottom-sheet drawer (#99) ──────────────────────────────────────────────── */
.drawer-overlay { position: fixed; inset: 0; z-index: 500; background: rgba(0,0,0,0.5);
  display: flex; align-items: flex-end; justify-content: center; opacity: 0; transition: opacity 0.2s ease; }
.drawer-overlay.drawer-open { opacity: 1; }
.drawer-panel { width: 100%; max-width: 640px; max-height: 88vh; background: var(--bg, var(--bg-hover));
  border: 1px solid var(--border); border-bottom: 0; border-radius: 14px 14px 0 0;
  display: flex; flex-direction: column; transform: translateY(100%); transition: transform 0.25s ease; }
.drawer-overlay.drawer-open .drawer-panel { transform: translateY(0); }
.drawer-head { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--bg, var(--bg-hover)); border-radius: 14px 14px 0 0; }
.drawer-title { margin: 0; font-size: var(--fs-h4); }
.drawer-close { background: var(--bg-hover); border: 1px solid var(--border); color: var(--text);
  border-radius: 6px; padding: 0.4rem 0.7rem; cursor: pointer; min-height: 38px; font-weight: 600; }
.drawer-body { padding: 0.75rem 1rem 1.25rem; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.bs-drawer-chips { margin-bottom: 0.75rem; }
.stake-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.3rem; }
.stake-chip { cursor: pointer; padding: 6px 12px; min-height: 34px; }
/* Betslip drawer bet placement + P/L (#102) */
.bs-pnl-line { font-size: var(--fs-body); color: var(--text-muted); margin: 0 0 0.6rem; }
.bs-draw-item { margin-bottom: 0.5rem; }
.bs-place-row { display: flex; justify-content: flex-end; margin-top: -4px; }
.bs-place { min-height: 32px; }
.bs-place.bs-placed { color: var(--pos, var(--green)); border-color: var(--pos, var(--green)); }
.tn-betslip { position: relative; display: inline-flex; align-items: center; gap: 4px; background: transparent;
  border: 1px solid var(--border); color: var(--text); border-radius: 6px; padding: 6px 8px; cursor: pointer; margin-left: auto; }
.tn-betslip .bs-star { fill: currentColor; }
.tn-betslip .betslip-badge:empty { display: none; }
.tn-betslip .betslip-badge { background: var(--accent); color: #fff; border-radius: 999px;
  font-size: var(--fs-xs); font-weight: 700; min-width: 16px; height: 16px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; }

/* ── Feedback form (#98) ────────────────────────────────────────────────────── */
.fb-return { margin-bottom: 0.75rem; }
.fb-form { display: flex; flex-direction: column; gap: 0.9rem; margin-top: 0.5rem; }
.fb-field { display: flex; flex-direction: column; gap: 0.35rem; }
.fb-lbl { font-size: var(--fs-body); font-weight: 600; color: var(--text); }
.fb-opt { color: var(--text-muted); font-weight: 400; }
.fb-input { width: 100%; box-sizing: border-box; background: var(--bg-hover); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; padding: 0.6rem 0.7rem; font-size: var(--fs-h4); font-family: inherit; }
.fb-textarea { resize: vertical; min-height: 110px; line-height: 1.45; }
.fb-input:focus { outline: none; border-color: var(--accent); }
.fb-actions { display: flex; }
.fb-actions .btn-primary { width: 100%; min-height: 46px; }
.fb-status { margin-top: 0.9rem; }
/* Blackbook runner search typeahead (#107) */
.bb-typeahead { position: absolute; left: 0; right: 0; top: 100%; z-index: 20; margin-top: 2px;
  background: var(--bg, var(--bg-hover)); border: 1px solid var(--border); border-radius: 6px; max-height: 240px; overflow-y: auto; }
.bb-ta-row { padding: 0.5rem 0.7rem; cursor: pointer; font-size: var(--fs-h4); border-bottom: 1px solid var(--border); }
.bb-ta-row:last-child { border-bottom: 0; }
.bb-ta-row:hover { background: var(--bg-hover); }

/* Toast (#110) — transient bottom-right popups, stacked, fade in/out. */
.ui-toast-host { position: fixed; right: 16px; bottom: 16px; z-index: 600; display: flex; flex-direction: column; gap: 10px; max-width: 340px; pointer-events: none; }
.ui-toast { pointer-events: auto; display: flex; align-items: flex-start; gap: 8px; background: var(--bg, var(--bg-hover));
  border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 10px;
  padding: 0.7rem 0.8rem; box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  opacity: 0; transform: translateY(10px); transition: opacity 0.25s ease, transform 0.25s ease; }
.ui-toast.show { opacity: 1; transform: translateY(0); }
.ui-toast-body { flex: 1; min-width: 0; }
.ui-toast-title { font-weight: 700; font-size: var(--fs-h4); color: var(--text, #fff); }
.ui-toast-msg { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
.ui-toast-cta { display: inline-block; margin-top: 7px; font-size: var(--fs-sm); font-weight: 600; color: var(--accent-light, #a78bfa);
  border: 1px solid var(--border); border-radius: 6px; padding: 4px 10px; text-decoration: none; }
.ui-toast-cta:hover { border-color: var(--accent); }
.ui-toast-x { background: transparent; border: 0; color: var(--text-muted); font-size: var(--fs-h3); line-height: 1; cursor: pointer; padding: 0 2px; }
@media (max-width: 640px) { .ui-toast-host { left: 12px; right: 12px; max-width: none; bottom: 12px; } }

/* Notification channel rows (#110) */
.notif-channel { border: 1px solid var(--border); border-radius: 8px; padding: 0.75rem 0.9rem; margin: 0.75rem 0; background: var(--bg-hover); }
.notif-channel-head { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.5rem; }
.notif-channel-name { font-weight: 600; color: var(--text); }
.notif-row { display: flex; align-items: center; gap: 0.5rem; font-size: var(--fs-h4); color: var(--text); margin: 0.4rem 0; }
.notif-soon { opacity: 0.55; }
.notif-soon .notif-channel-head { margin-bottom: 0; }
/* Keep the submit + status in view when the mobile keyboard opens on small screens. */
@media (max-width: 640px) { .fb-form { scroll-margin-bottom: 40vh; } .fb-textarea { min-height: 90px; } }
.btn-remove-betslip { align-self: center; }
@media (max-width: 640px) {
  .bs-card-body { flex-wrap: wrap; }
  .bs-runner { flex-basis: calc(100% - 46px); }
  .btn-remove-betslip { width: 100%; margin-top: 0.4rem; }
  .bs-runner-meta { gap: 0.3rem 0.7rem; }
}

/* ── "Add to betslip" affordance on the per-runner control (#87) ───────────── */
.betslip-add-wrap { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 5px; }
.betslip-add-label { display: inline-flex; align-items: center; gap: 0.25rem; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted); white-space: nowrap; }
.betslip-add-label .bs-star { fill: none; stroke: var(--text-muted); stroke-width: 1.6; }
.betslip-add-wrap.on-slip .betslip-add-label { color: var(--win, #fbbf24); }
.betslip-add-wrap.on-slip .bs-star { fill: var(--win, #fbbf24); stroke: var(--win, #fbbf24); }
@media (max-width: 640px) { .betslip-add-wrap { flex-wrap: wrap; } }

/* ── Betslip page v2 (#89): race-grouped cards, runner rows, dated archive ──── */
.bs-race-runners { display: flex; flex-direction: column; }
.bs-runner-row { display: flex; align-items: flex-start; gap: 0.75rem; padding: 0.6rem 0.75rem; border-top: 1px solid var(--border); }
.bs-runner-row:first-child { border-top: none; }
.bs-archive { margin-top: 1.5rem; }
.bs-archive-head { color: var(--text-dim); }
.bs-archive-date { border: 1px solid var(--border); border-radius: 6px; margin-bottom: 0.5rem; background: var(--bg-card); overflow: hidden; }
.bs-archive-date > summary { cursor: pointer; padding: 0.6rem 0.8rem; display: flex; align-items: center; gap: 0.5rem; font-weight: 600; list-style: none; user-select: none; }
.bs-archive-date > summary::-webkit-details-marker { display: none; }
.bs-archive-date > summary::before { content: "▸"; color: var(--text-muted); transition: transform 0.15s ease; }
.bs-archive-date[open] > summary::before { transform: rotate(90deg); }
.bs-archive-date-lbl { flex: 1; }
.bs-archive-date .bs-card { margin: 0 0.6rem 0.6rem; }
.bs-controls { margin-bottom: 1rem; }
@media (max-width: 640px) { .bs-runner-row { flex-wrap: wrap; } .bs-runner-row .btn-remove-betslip { width: 100%; margin-top: 0.4rem; } }

/* Follow (blackbook) control on runner cards (#108) */
.follow-control { display: inline-flex; align-items: center; gap: 4px; background: transparent; border: 1px solid var(--border);
  color: var(--text-muted); border-radius: 6px; padding: 3px 8px; font-size: var(--fs-xs); cursor: pointer; margin-left: 6px; }
.follow-control:hover { border-color: var(--accent); color: var(--text); }
.follow-control .bs-star { fill: currentColor; }
.follow-control.fc-on { color: #fbbf24; border-color: #fbbf24; }

/* Shared admin tab bar — the underline tabs used by the Models/flows page AND the
   A/B test page, so admin tabs are one component (reuse, not per-page copies). */
.md-wrap { width: 100%; }
.md-tabs { display: flex; gap: 0.3rem; margin: 0.8rem 0 1.2rem; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.md-tab { background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-weight: 700; font-size: var(--fs-h4); padding: 0.55rem 1rem; cursor: pointer; font-family: inherit; }
.md-tab:hover { color: var(--text); }
.md-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.md-actions { margin-left: auto; display: flex; gap: 0.5rem; align-items: center; }
/* Shared form input (was duplicated inline on admin pages). */
.form-input { background: var(--bg); border: 1px solid var(--border); color: var(--text); padding: 0.45rem 0.6rem; border-radius: 8px; font-size: var(--fs-body); }
.form-input:focus { outline: none; border-color: var(--accent); }

/* Per-code Best Bets section tags (#36). */
.bb-code-tag { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; vertical-align: middle; margin-left: 0.4rem; padding: 1px 6px; border-radius: 999px; background: rgba(var(--accent-rgb), 0.15); color: var(--accent-light); }
.bb-code-tag.bb-code-grey { background: rgba(var(--ew-rgb), 0.15); color: var(--ew); }
.bb-code-tag.bb-code-harness { background: rgba(224,162,60,0.15); color: #e0a23c; }

/* Projected speed / pace map (#56). */
/* #137 pace map now lives inside a collapsed accordion (one row per runner, each
   with the SAME pace-bar chart as the runner cards). The accordion supplies the
   frame, so the inner .pace-map has no border/background of its own. */
.pace-map { margin: 0; padding: 0.15rem 0.1rem; }
.pace-map .pm-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.4rem; }
.pace-map .pm-src { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 0 4px; }
.pace-map .pm-axis-hint { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); }
.pace-map .pm-rows { display: flex; flex-direction: column; gap: 0.3rem; }
/* One horse per row: number + short name, then its pace bar filling the width. */
.pace-map .pm-row { display: grid; grid-template-columns: 96px 1fr; gap: 0.5rem; align-items: center; }
.pace-map .pm-runner { display: inline-flex; align-items: baseline; gap: 0.35rem; min-width: 0; }
.pace-map .pm-num { font-family: var(--mono); font-weight: 700; font-size: var(--fs-sm); color: var(--accent-light); }
.pace-map .pm-name { font-size: var(--fs-xs); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pace-map .pm-bar { min-width: 0; }
.pace-map .pm-bar .pace-bar { margin-top: 0; }
@media (max-width: 640px) { .pace-map .pm-row { grid-template-columns: 78px 1fr; } .pace-map .pm-bar .pace-bar-label { min-width: 58px; } }

/* #136 expanded-accordion content: runner comments, dark stat grid, recent starts. */
.rc-comments { background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 0.7rem 0.85rem; margin: 0.4rem 0 0.6rem; }
.rc-comments-title { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); font-weight: 700; margin-bottom: 0.3rem; }
.rc-comments-body { font-size: var(--fs-body); color: var(--text-mid); line-height: 1.5; }
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem 0.8rem; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 0.8rem 0.9rem; margin-bottom: 0.6rem; }
.stat-grid .sg-cell { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.stat-grid .sg-lab { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-dim); }
.stat-grid .sg-val { font-size: var(--fs-h4); font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.recent-starts .rs-title { font-size: var(--fs-xs); font-weight: 700; color: var(--text); margin: 0.4rem 0 0.15rem; }
.recent-starts .rs-days { font-size: var(--fs-xs); color: var(--text-muted); margin-bottom: 0.4rem; }
.recent-starts .ui-accordion { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 0.35rem; }
.recent-starts .ui-accordion-sum { padding: 0.45rem 0.6rem; font-size: var(--fs-sm); color: var(--text-mid); }
.recent-starts .ui-accordion .stat-grid { margin: 0 0.5rem 0.5rem; padding: 0.6rem; }
.recent-starts .ui-accordion[open] > .ui-accordion-sum::after { content: none; } /* #139 keep nested run rows clean */
/* #222 recent-start summary: finish/field badge leads, then the race line */
.recent-starts .ui-accordion-sum { display: flex; align-items: baseline; gap: 0.5rem; }
.rs-fin { font-family: var(--mono); font-weight: 800; font-size: var(--fs-sm); min-width: 2.4em; flex: none; }
.rs-fin .rs-of { font-weight: 600; font-size: 0.82em; opacity: 0.7; }
.rs-line { color: var(--text-mid); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-starts .rs-nodetail { padding: 0.5rem 0.6rem; font-size: var(--fs-xs); color: var(--text-dim); }
@media (max-width: 640px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }

/* Sectional-time ranks on the runner card (#57). */
.rc-sectionals { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.35rem; }
.rc-sectionals .rc-src { font-size: var(--fs-2xs); background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 0 3px; color: var(--text-dim); margin-left: 2px; }
.sectional-chips { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.sectional-chip { display: inline-flex; align-items: baseline; gap: 3px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px; font-size: var(--fs-xs); }
.sectional-chip .sc-lab { color: var(--text-muted); }
.sectional-chip .sc-rank { font-family: var(--mono); font-weight: 700; color: var(--accent-light); }
/* #218 interpreted closing-speed read — fast finisher (green) vs closed-hard-when-beaten (amber) */
.sectional-read { display: inline-flex; align-items: center; height: var(--chip-h); font-size: var(--chip-fs); padding: 0 var(--chip-px); box-sizing: border-box; gap: 0.3rem; font-weight: 700; border-radius: 6px; border: 1px solid transparent; }
.sectional-read.sr-fast { color: var(--green); background: rgba(var(--green-rgb), 0.12); border-color: rgba(var(--green-rgb), 0.3); }
.sectional-read.sr-badtrip { color: var(--win); background: rgba(var(--win-rgb), 0.12); border-color: rgba(var(--win-rgb), 0.3); }

/* #261 VO Speed tier badge — our blended speed rating (abstracted; sectional ranks never shown). */
/* #268 the VO Speed rating tier is now folded onto the VO Speed figure as a green suffix
   ("105 · Top-rated"); the old standalone .speed-badge is retired. */
.vo-speed-tier { color: var(--green); font-weight: 600; }

/* Value Scanner (#52) — filter chips + min-edge control row. */
.value-controls { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin: 0.4rem 0 1rem; }
.value-chips { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.val-chip { cursor: pointer; }
.value-minedge { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--fs-body); color: var(--text-muted); }

/* Today digest (#63) — light layout helpers around the shared UI components. */
.digest-code-group { margin: 0.6rem 0 1rem; }
.digest-code-head { display: flex; align-items: center; gap: 0.4rem; font-weight: 700; font-size: var(--fs-h4); margin-bottom: 0.35rem; color: var(--text); }
.digest-pl-bycode { margin-top: 0.75rem; font-size: var(--fs-body); color: var(--text-mid); }
/* #149 watch-replay link on runner-profile result rows */
.hp-replay { display: inline-block; margin-left: 0.4rem; padding: 0; background: none; border: none; cursor: pointer; font-family: inherit; font-size: var(--fs-xs); font-weight: 700; color: var(--ew); white-space: nowrap; }
.hp-replay:hover { text-decoration: underline; }

/* #151 AI paywall — slim "on Free plan" upgrade strip (fixed to the bottom). */
.ai-upgrade-strip { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; gap: 0.75rem; padding: 0.5rem 1rem;
  background: var(--card, #1b2233); border-top: 1px solid var(--border, #2c3446);
  color: var(--text, #e8edf6); font-size: var(--fs-sm); box-shadow: 0 -2px 10px rgba(0,0,0,0.25); }
.ai-upgrade-strip a { color: var(--ew, #f5c451); font-weight: 700; text-decoration: none; }
.ai-upgrade-strip a:hover { text-decoration: underline; }
.ai-upgrade-strip button { background: none; border: none; color: var(--text-dim, #9aa5b8);
  font-size: 1.1rem; line-height: 1; cursor: pointer; padding: 0 0.25rem; }

/* #200 Compact betslip rows (⭐ modal / drawer): one legible line per selection with
   race context (Track · R# · time) + live/snapshot odds. Mobile-first; scales up fine. */
.bs-rows { display: flex; flex-direction: column; gap: 0.5rem; }
.bs-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.65rem;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg-card); }
/* Whole-row click-through to the race (mobile + desktop). */
a.bs-row-link { text-decoration: none; color: inherit; cursor: pointer;
  transition: border-color 0.12s, background 0.12s; }
a.bs-row-link:hover, a.bs-row-link:focus-visible { border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.08); outline: none; }
.bs-row-chev { flex: 0 0 auto; margin-left: 0.1rem; font-size: 1.15rem; line-height: 1;
  color: var(--text-dim); font-weight: 400; }
.bs-row-num { flex: 0 0 auto; min-width: 1.6rem; height: 1.6rem; display: flex; align-items: center;
  justify-content: center; font-weight: 700; font-size: 0.85rem; border-radius: 6px;
  background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
.bs-row-silk { flex: 0 0 auto; width: 22px; height: 22px; object-fit: contain; border-radius: 4px; }
.bs-row-main { flex: 1 1 auto; min-width: 0; }
.bs-row-name { display: flex; align-items: center; gap: 0.4rem; font-weight: 600; font-size: 0.92rem;
  color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bs-row-name .badge { flex: 0 0 auto; }
.bs-row-ctx { margin-top: 0.15rem; font-size: 0.78rem; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bs-row-odds { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end;
  gap: 0.1rem; text-align: right; }
.bs-od { display: inline-flex; align-items: baseline; gap: 0.3rem; font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: 0.9rem; color: var(--text); }
.bs-od-place { font-weight: 600; font-size: 0.8rem; color: var(--text-muted); }
.bs-od-lab { font-weight: 600; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-dim); }
.bs-od-live { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--accent-light); border: 1px solid var(--accent); border-radius: 4px;
  padding: 0 0.2rem; margin-left: 0.15rem; }

/* #202 "Hide run races" toggle in the race-page nav row — compact, doesn't shrink,
   sits to the right of the scrollable pill strip (reuses the shared switch markup). */
.meet-nav-toggle { flex: 0 0 auto; display: inline-flex; align-items: center; }
.meet-nav-toggle:empty { display: none; }
.meet-nav-toggle .toggle-label { gap: 0.4rem; }
.toggle-sm .toggle-text { font-size: 0.78rem; color: var(--text-dim); white-space: nowrap; }
@media (max-width: 640px) { .toggle-sm .toggle-text { font-size: 0.72rem; } }

/* #203 redo 2: "Today's form" — ONE compact row per race type, AI + Basic as inline
   micro-bars (win% + a 4px fill) in the same row. ~150px tall on mobile; details in
   tooltips instead of extra rows. */
.tf-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 14px;
  padding: 0.7rem 0.9rem 0.6rem; max-width: 1380px; margin: 0 auto; }
.tf-head { margin-bottom: 0.4rem; }
.tf-title { font-weight: 700; font-size: 0.95rem; color: var(--text); }
.tf-sub { font-size: 0.72rem; color: var(--text-dim); }
.tf-rows { display: flex; flex-direction: column; }
.tf-row { display: grid; grid-template-columns: minmax(66px, 90px) 1fr 1fr 2.2em;
  gap: 0.6rem; align-items: center; padding: 0.28rem 0; }
.tf-row + .tf-row { border-top: 1px solid rgba(var(--overlay-rgb), 0.05); }
.tf-row-head { padding: 0 0 0.1rem; }
.tf-ch { font-size: 0.64rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.tf-row-overall { font-weight: 700; }
.tf-row-overall .tf-cv { font-size: 0.95rem; }
.tf-rlabel { display: flex; align-items: center; gap: 0.35rem; font-size: 0.8rem; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tf-cell { display: flex; align-items: center; gap: 0.45rem; min-width: 0; }
.tf-cell-empty { color: var(--text-dim); font-size: 0.8rem; }
.tf-cv { font-size: 0.86rem; font-weight: 800; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.tf-cv-ai { color: var(--accent-light); }
.tf-cv-basic { color: var(--win); }
.tf-mtrack { flex: 1 1 auto; height: 4px; border-radius: 3px; background: rgba(var(--overlay-rgb), 0.08); overflow: hidden; }
.tf-mfill { display: block; height: 100%; border-radius: 3px; transition: width 0.5s cubic-bezier(0.2,0.7,0.2,1); }
.tf-mfill-ai { background: linear-gradient(90deg, var(--accent), var(--accent-light)); }
.tf-mfill-basic { background: linear-gradient(90deg, var(--win), #ffe08a); }
.tf-rn { font-size: 0.68rem; color: var(--text-dim); text-align: right; font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .tf-mfill { transition: none; } }

/* #60 small-sample de-emphasis in stat tables — a low-n strike isn't signal. */
.dt-dim { color: var(--text-dim); font-weight: 500; }
/* Signed value cells in data tables (e.g. ROI, P/L) — reuse the semantic colour vars. */
.dt-pos { color: var(--green); font-weight: 600; }
.dt-neg { color: var(--danger); font-weight: 600; }

/* ═══ Coverage matrix (#262 UI.coverageMatrix) — "which source has which data" grid ═══ */
.coverage-matrix .cov-rowlabel { font-weight: 600; white-space: nowrap; position: sticky; left: 0; background: var(--bg-card); }
.coverage-matrix .cov-cell { text-align: center; }
.cov-status { font-size: 1.05rem; cursor: help; }
.cov-full { color: var(--green); }
.cov-partial { color: var(--win); }
.cov-none { color: var(--text-dim); opacity: 0.6; }
.cov-legend { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.5rem; font-size: var(--fs-xs); color: var(--text-dim); }
.cov-legend .cov-status { font-size: 0.9rem; cursor: default; }
.cov-hint { opacity: 0.8; }

/* #332 Race speed map — projected run-style lanes */

/* #335 Closing-speed sprint bar */
.closing-speed-bar { display: inline-flex; align-items: flex-end; gap: 3px; height: 22px; vertical-align: middle; }
.closing-speed-bar .csb-seg { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; }
.closing-speed-bar .csb-track { width: 7px; height: 16px; display: flex; align-items: flex-end; background: rgba(var(--overlay-rgb),0.08); border-radius: 2px; overflow: hidden; }
.closing-speed-bar .csb-fill { width: 100%; border-radius: 2px 2px 0 0; }
.closing-speed-bar .csb-lab { font-size: 0.5rem; color: var(--text-dim); line-height: 1; }

/* #336 Market-aware stance tag (honest framing) */
.mkt-stance { font-size: var(--fs-2xs); font-weight: 700; padding: 0.1rem 0.4rem; border-radius: 999px; white-space: nowrap; }
.mkt-stance.ms-value { color: var(--green,#22c55e); background: rgba(34,197,94,0.14); }
.mkt-stance.ms-inline { color: var(--text-muted); background: rgba(var(--overlay-rgb),0.08); }
.mkt-stance.ms-under { color: var(--text-dim); background: rgba(var(--overlay-rgb),0.06); }

/* #334 Value board — dedicated cross-race overlay list */
.vb-controls { display: flex; flex-direction: column; gap: .5rem; margin: .25rem 0 1rem; }
.vb-ctrl-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.vb-table td.vb-race a { font-weight: 600; }
.vb-table .vb-off { display: block; font-size: .8em; color: var(--text-muted); }
.vb-table td.vb-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.vb-table td.vb-edge { text-align: right; white-space: nowrap; }
.vb-table td.vb-runner { min-width: 9rem; }
@media (max-width: 640px) {
  .vb-table td.vb-race a { font-size: .92em; }
  .vb-table .vb-off { font-size: .72em; }
}

/* #333 My betting (CLV journal) */
.mb-h3 { font-size: 1rem; margin: 1.25rem 0 .5rem; }
.mb-h3-sub { font-weight: 400; font-size: .8em; color: var(--text-muted); }
.mb-chart-wrap { margin: 1rem 0 .5rem; }
.mb-table td.mb-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mb-table .mb-when { display: block; font-size: .78em; color: var(--text-muted); }
.mb-table td.mb-runner { min-width: 9rem; }
.mb-pos { color: var(--green, #22c55e); font-weight: 600; }
.mb-neg { color: var(--red, #ef4444); font-weight: 600; }

/* #337 My runners feed */
.mr-feed { display: flex; flex-direction: column; gap: .5rem; }
.mr-item { display: flex; align-items: center; gap: .75rem; padding: .6rem .75rem; border: 1px solid var(--border, rgba(var(--overlay-rgb),0.12)); border-radius: 10px; text-decoration: none; color: inherit; background: var(--card-bg, rgba(var(--overlay-rgb),0.03)); }
.mr-item:hover { border-color: var(--accent, #6ea8fe); }
.mr-item .mr-when { min-width: 3.5rem; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.mr-item.mr-now .mr-when { color: var(--green, #22c55e); }
.mr-item.mr-soon .mr-when { color: var(--amber, var(--win)); }
.mr-item.mr-later .mr-when { color: var(--text-muted); }
.mr-main { display: flex; flex-direction: column; gap: .1rem; flex: 1; min-width: 0; }
.mr-runner { font-size: .98em; }
.mr-race { font-size: .82em; color: var(--text-muted); }
.mr-assess { font-size: .8em; color: var(--text-dim); }
.mr-following { margin-top: 1.25rem; }
.mr-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.mr-chip { font-size: .85em; padding: .2rem .5rem; border-radius: 999px; background: rgba(var(--overlay-rgb),0.08); }
.mr-chip-type { font-size: .8em; color: var(--text-muted); text-transform: capitalize; }

/* #309 Live going "as at" stamp on the race card Track cell */
.going-asof { font-size: .72em; color: var(--text-muted); font-weight: 400; white-space: nowrap; }
#goingDriftNote:not(:empty) { margin-top: .6rem; }

/* #315 Exotics — "good strike" flag (≥55%) + no sample-size count in the cell */
.ex-good { color: var(--green, #22c55e); font-weight: 700; }
td.ex-good-cell { color: var(--green, #22c55e); }
/* #384(a) exotics budget bar */
.ex-budget { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.8rem; margin: 0 0 0.6rem; font-size: var(--fs-xs); color: var(--text-muted); }
.ex-budget label { display: inline-flex; align-items: baseline; gap: 0.35rem; font-weight: 600; color: var(--text-mid); }
.ex-budget .ex-cur { color: var(--text-muted); }
.ex-budget-input { width: 5rem; padding: 0.25rem 0.4rem; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-2, var(--surface)); color: var(--text); font: inherit; }
.ex-budget-note { flex: 1 1 12rem; }

/* #375 An each-way is ONE bet with TWO legs (#365), each closing against its own market — so a
   journal row can carry two lines per price cell, tagged W/P. Win and Place bets have a single
   leg and render as one line, so the tag is omitted rather than shown blank. */
.mb-leg { white-space: nowrap; }
.mb-leg + .mb-leg { margin-top: 0.15rem; }
.mb-leg-tag {
  display: inline-block; min-width: 1.1em; margin-right: 0.3em;
  font-size: 0.7em; font-weight: 600; opacity: 0.6; text-align: left;
}


/* ── Auth pages (#417) ───────────────────────────────────────────────────────
   login / register / forgot / reset used to be four standalone pages: no styles.css, no
   theme-boot, ~83 colour literals and an inline <style> block each. They were permanently
   dark whatever the toggle said — the FIRST screen a user ever sees ignored their theme.
   And because they never loaded this file, the mandatory 18+ footer they all render
   (.rg-footer/.rg-18/.rg-tagline, defined above) fell back to unstyled text.

   One block, four pages. Every colour is a token, so the auth screens follow the palette
   like everything else.
   ------------------------------------------------------------------------- */
.auth-body {
  /* the accent/green wash that gives the login its depth — as tints of the palette, so it
     re-tones per theme instead of staying a purple haze over a mint page */
  background:
    radial-gradient(120% 90% at 15% -10%, rgba(var(--accent-rgb), 0.22), transparent 55%),
    radial-gradient(120% 90% at 100% 110%, rgba(var(--green-rgb), 0.12), transparent 50%),
    var(--bg);
  color: var(--text);
  font-family: var(--font);
  min-height: 100vh; min-height: 100dvh;
  /* column so the (static) 18+ footer stacks BELOW the card, not beside it — the body is a
     flex parent and the footer is its second child, which read as a row before. */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 1.25rem;
}
.auth-box {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 1.75rem 1.5rem 1.5rem;
  width: 100%; max-width: 380px;
  margin: auto;                       /* centre the card in the free space above the footer */
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.auth-box.auth-wide { max-width: 460px; }
/* signature accent bar */
.auth-box::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, var(--green), var(--accent));
}
.auth-body .rg-footer { margin-top: auto; flex-shrink: 0; width: 100%; border-top: none; }
.auth-box h1 { font-size: 1.15rem; text-align: center; margin-bottom: 1.35rem; font-weight: 700; }
.auth-box label { display: block; font-size: 0.78rem; color: var(--text-muted); margin-bottom: 0.3rem; font-weight: 500; }
.auth-box input {
  width: 100%;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.7rem 0.8rem;
  border-radius: 10px;
  font-size: 1rem;                    /* 16px: anything smaller makes iOS zoom on focus */
  font-family: var(--font);
  margin-bottom: 1rem;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.auth-box input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.22); }
.auth-btn {
  width: 100%;
  background: var(--accent-btn); color: var(--on-accent);
  border: none; padding: 0.75rem; border-radius: 10px;
  font-size: 0.95rem; font-weight: 700; font-family: var(--font);
  cursor: pointer; transition: filter 0.12s, transform 0.06s;
}
.auth-btn:hover { filter: brightness(1.08); }
.auth-btn:active { transform: translateY(1px); }
.auth-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.auth-error { color: var(--danger); font-size: 0.82rem; text-align: center; margin-top: 0.85rem; display: none; }
.auth-ok { color: var(--green); }
.auth-hint { color: var(--text-muted); font-size: 0.78rem; line-height: 1.5; margin-bottom: 1rem; }
.auth-link { color: var(--text-muted); font-size: 0.8rem; text-decoration: none; }
.auth-link:hover { color: var(--text-mid); }
.auth-foot { text-align: center; margin-top: 0.7rem; }
/* #307 self-registration CTA: an "or" divider + a full-width secondary (outline) button so
   the register path is an obvious mechanism, distinct from the primary Sign In. */
.reg-or { display: flex; align-items: center; gap: 0.75rem; margin: 1.25rem 0 0.9rem; }
.reg-or::before, .reg-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.reg-or span { color: var(--text-dim); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; }
.reg-btn {
  display: block; width: 100%; text-align: center; text-decoration: none;
  padding: 0.7rem; border-radius: 10px; font-size: 0.9rem; font-weight: 700;
  color: var(--green); background: transparent; border: 1px solid rgba(var(--green-rgb), 0.5);
  transition: background 0.12s, border-color 0.12s;
}
.reg-btn:hover { background: rgba(var(--green-rgb), 0.08); border-color: var(--green); }
.auth-note { font-size: 0.82rem; line-height: 1.5; padding: 0.6rem 0.7rem; border-radius: 8px; margin-top: 0.85rem; }
.auth-note.ok { color: var(--green); background: rgba(var(--green-rgb), 0.1); border: 1px solid rgba(var(--green-rgb), 0.35); }
.auth-note.err { color: var(--danger); background: rgba(var(--danger-rgb), 0.1); border: 1px solid rgba(var(--danger-rgb), 0.35); }
@media (min-width: 480px) { .auth-box { padding: 2.25rem 2rem 1.85rem; } }

/* register.html's extras — in the shared block, not a one-off on the page (#417).
   row2 is mobile-first: one column, two only when there is room for two. */
.auth-row2 { display: grid; grid-template-columns: 1fr; gap: 0 0.75rem; }
@media (min-width: 480px) { .auth-row2 { grid-template-columns: 1fr 1fr; } }
.auth-decl { display: flex; gap: 0.55rem; align-items: flex-start; margin: 0 0 1rem; }
.auth-decl input { width: 1.05rem; height: 1.05rem; margin-top: 0.15rem; accent-color: var(--accent); }
.auth-decl span { font-size: 0.8rem; color: var(--text-muted); line-height: 1.45; }
.auth-done { display: none; text-align: center; }
.auth-done .auth-big { font-size: 2rem; margin-bottom: 0.6rem; }
.auth-backlink { text-align: center; margin-top: 1rem; font-size: 0.8rem; }
.auth-backlink a { color: var(--accent); font-weight: 600; }
