/* ============================================================================
   LMU Garage — "Broadcast" design system
   Live TV race-control / world-feed aesthetic: void/navy ground, motion-blur
   atmosphere, glassy translucent panels, crimson hot accent, kinetic condensed
   italic display type, and data-dense timing-tower tables.

   Canonical spec: docs/design-language.md
   Visual source of truth: docs/design-explorations/broadcast-pages.html

   Fonts are loaded via Google Fonts <link> in base.html.twig (Saira Condensed,
   Inter, IBM Plex Mono) — no @font-face here.

   IMPORTANT: this file restyles the app's EXISTING class names (see the class
   list in design-language.md §3). Do not rename classes here without also
   updating every template that relies on them.
   ============================================================================ */

:root {
  color-scheme: dark;

  /* -- foundations (design-language.md §1.1) -- */
  --void: #060B14;
  --navy: #0C1728;
  --navy-hi: #132038;
  --crimson: #E5123B;
  --crimson-hi: #FF3355;
  --cyan: #22C3FF;
  --warn: #FFC21A; /* warning/attention amber — sun-weather glyphs, foreign-round slot markers */
  --white: #FFFFFF;
  --text: #F2F5FA;
  --muted: #9DB0C4;
  --faint: #7E93A8;

  /* -- data-locked colors (§1.2) — semantic, never repurpose -- */
  --gt3: #35C46A;
  --gte: #F97316;
  --lmp2: #3F7FE0;
  --lmp3: #9A67EA;
  --hy: #E5484D;
  --hy-hi: #FF6E78;
  --bronze: #C07D43;
  --silver: #9AA6B2;
  --gold: #E0A83B;
  --plat: #46CFE0;
  --best: #C77DFF;

  /* -- glass surfaces (§1.1) -- */
  --glass-bg: rgba(16, 27, 46, 0.58);
  --glass-bg-hi: rgba(20, 32, 54, 0.72);
  --glass-border: rgba(255, 255, 255, 0.09);
  /* stronger outline for small outlined chips (tyre/nat/sched-time) — needs ≥3:1 non-text contrast */
  --chip-border: rgba(255, 255, 255, 0.4);
  --glass-blur: blur(18px) saturate(150%);
  /* secondary text over photo veils — --muted brightened to hold AA on the lighter veil stops */
  --photo-text: #D9E2EC;

  /* -- typography (§1.3) — three families, each with a job -- */
  --display: 'Saira Condensed', Oswald, 'Arial Narrow', sans-serif;
  --body: 'Inter', 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'JetBrains Mono', SFMono-Regular, Menlo, monospace;

  /* -- scale / spacing / shape (§1.4) -- */
  --radius: 10px;
  --wrap: 1240px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--void); }
html, body { overflow-x: hidden; } /* the page body never scrolls sideways — tables scroll inside .table-wrap */

/* ============================================================================
   ATMOSPHERE — signature motif #1 (design-language.md §2.1)
   Fixed, layered-gradient backdrop: radial glow + diagonal streaks + a skewed
   speed sweep. CSS only, no photography. The static base (radial glow +
   vertical gradient) lives on body's own background with
   background-attachment:fixed, pinned to the viewport; the two animated
   layers (streak drift, speed sweep) live on body::before/::after — so no
   extra wrapper element is needed in base.html.twig.
   ============================================================================ */
body {
  margin: 0;
  font-family: var(--body);
  color: var(--text);
  line-height: 1.5;
  min-height: 100vh;
  display: flex; flex-direction: column; /* main grows so the footer sits at the viewport bottom on short pages */
  position: relative;
  background-color: var(--void);
  background-image:
    radial-gradient(ellipse 1300px 700px at 14% -8%, rgba(229, 18, 59, 0.20), transparent 58%),
    radial-gradient(ellipse 1000px 620px at 104% 6%, rgba(34, 195, 255, 0.11), transparent 60%),
    radial-gradient(ellipse 900px 500px at 50% 115%, rgba(229, 18, 59, 0.10), transparent 62%),
    linear-gradient(180deg, #060B14 0%, #0C1728 42%, #0A1422 68%, #060B14 100%);
  background-repeat: no-repeat;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
h1, h2, h3 { font-family: var(--display); text-transform: uppercase; margin: 0; line-height: 1.05; letter-spacing: 0.01em; }

.muted { color: var(--muted); }
.tnum { font-variant-numeric: tabular-nums lining-nums; }

/* track/circuit name featured outside a table (e.g. the Current-round panel) —
   names are Inter, never condensed (§1.3) */
.track-name { font-family: var(--body); font-weight: 700; font-size: 1.15rem; color: var(--white); }

/* ±1 local-day superscript on time chips — one style everywhere it rides
   (sched-grid chips, rundown times). Floored at 12px (§1.4). */
.tz-dayhint {
  font-size: max(0.65em, 0.75rem); font-weight: 600; color: var(--cyan);
  vertical-align: super; margin-left: 0.12em; text-decoration: none;
}

/* generic glass surface, reused by panels/cards/tables/header */
.glass-surface,
.panel,
.race-card,
.hub-tile,
.table-wrap {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
}

/* ============================================================================
   APP SHELL / NAV — .site-header .nav .brand .nav-tabs (§3.1)
   ============================================================================ */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(6, 11, 20, 0.72);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.site-header::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: linear-gradient(90deg, var(--crimson), var(--cyan) 60%, transparent);
  opacity: 0.85;
}
.nav {
  max-width: var(--wrap); margin: 0 auto;
  display: flex; align-items: center; gap: clamp(0.9rem, 2.4vw, 1.8rem);
  padding: 0.85rem clamp(1.25rem, 4vw, 3rem);
  flex-wrap: wrap;
}
.brand {
  display: inline-flex; align-items: center; gap: 0.3em;
  font-family: var(--display); font-weight: 800; font-style: italic;
  transform: skewX(-6deg); transform-origin: left;
  text-transform: uppercase; letter-spacing: 0.02em; font-size: 1.3rem;
  color: var(--white); flex: none;
  min-height: 24px;
}
.brand span { color: var(--crimson-hi); }
.nav-tabs { display: flex; gap: clamp(0.9rem, 2.4vw, 1.6rem); margin-left: auto; flex-wrap: wrap; }
.nav-tabs a {
  display: inline-flex; align-items: center; min-height: 24px; padding: 0.3rem 0.1rem;
  font-family: var(--display); font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; font-size: 0.92rem; color: var(--muted);
  position: relative;
}
.nav-tabs a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: -2px; height: 2px;
  background: linear-gradient(90deg, var(--crimson), var(--crimson-hi));
  transition: right 0.22s ease;
}
.nav-tabs a:hover { color: var(--text); }
.nav-tabs a:hover::after { right: 0; }
.nav-tabs a.active { color: var(--white); }
.nav-tabs a.active::after { right: 0; }

main { flex: 1 0 auto; width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 1.7rem clamp(1.25rem, 4vw, 3rem) 4.5rem; position: relative; }

/* ============================================================================
   PAGE HEAD & TABS — .page-head, .tabs (§3.2)
   ============================================================================ */
.page-head { display: flex; flex-direction: column; gap: 0.5rem; margin: 0.3rem 0 1.7rem; }
.page-head h1 {
  font-family: var(--display); font-weight: 800; font-style: italic;
  text-transform: uppercase; color: var(--white);
  font-size: clamp(1.9rem, 4.4vw, 3rem); line-height: 1.02;
  transform: skewX(-4deg); transform-origin: left;
  text-shadow: 0 0 30px rgba(229, 18, 59, 0.28);
}
.page-head .sub { font-family: var(--body); color: var(--muted); font-size: 1rem; max-width: 56em; }

/* ============================================================================
   EVENT HERO — .ov-hero (.oh-crumb .oh-title .oh-sub .oh-chips)
   (docs/design-explorations/overview-pages.html §1, adopted 2026-07-18 WITHOUT
   the on-air status bug). Replaces .page-head + the chips row on detail pages:
   game photo behind the rc-banner veil, breadcrumb chip, identity chips in the
   lower third. No image synced → the bare glass surface carries it.
   ============================================================================ */
.ov-hero {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; min-height: 236px;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  margin: 0.3rem 0 1.1rem;
}
.ov-hero:not(:has(.bg)) { min-height: 180px; }
.ov-hero .bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; display: block; }
.ov-hero::before { /* veil weighted to the lower third — the adopted .rc-banner recipe, darkened for the taller hero */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 11, 20, 0.34) 0%, rgba(6, 11, 20, 0.56) 34%, rgba(6, 11, 20, 0.92) 100%),
    linear-gradient(305deg, rgba(229, 18, 59, 0.12), transparent 44%);
}
.ov-hero .motif { /* hazard-stripe wedge corner, as on hub tiles */
  position: absolute; top: 0; right: 0; width: 30px; height: 30px; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(45deg, var(--crimson) 0 6px, #0A1220 6px 12px);
  clip-path: polygon(100% 0, 100% 100%, 0 0); opacity: 0.9;
}
.oh-top { flex: 1; display: flex; flex-direction: column; gap: 0.55rem; padding: 0.95rem 1.4rem 1.1rem; }
.oh-crumb { /* glass chip: the veil is lightest up here — bare muted text can't guarantee AA over a bright sky */
  display: inline-flex; align-items: center; gap: 0.45em; align-self: flex-start; min-height: 24px;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  font-size: 0.8125rem; color: var(--text);
  background: rgba(6, 11, 20, 0.55); padding: 0.22em 0.6em; border-radius: 4px;
}
.oh-crumb:hover { color: var(--cyan); }
.oh-title {
  font-family: var(--display); font-weight: 800; font-style: italic; text-transform: uppercase;
  transform: skewX(-4deg); transform-origin: left;
  font-size: clamp(1.9rem, 4vw, 2.7rem); line-height: 1.02; margin: 0;
  color: var(--white); text-shadow: 0 1px 18px rgba(0, 0, 0, 0.75);
}
.oh-sub { font-family: var(--body); color: var(--photo-text); font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.02em; margin: 0; }
.oh-chips { margin-top: auto; padding-top: 0.6rem; }

.tabs {
  display: flex; gap: 0.2rem; flex-wrap: wrap;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1); margin: 0 0 1.7rem;
}
.tabs a {
  display: inline-flex; align-items: center; min-height: 24px;
  font-family: var(--display); font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; font-size: 0.92rem; color: var(--muted);
  padding: 0.6rem 0.9rem; margin-bottom: -1px; position: relative;
}
.tabs a:hover { color: var(--text); }
.tabs a.active { color: var(--white); }
.tabs a.active::after {
  content: ""; position: absolute; left: 0.15rem; right: 0.15rem; bottom: -1px; height: 3px;
  background: linear-gradient(90deg, var(--crimson), var(--crimson-hi));
  border-radius: 2px 2px 0 0;
}

/* ============================================================================
   SECTIONS — .section (used to group tiers/status buckets)
   ============================================================================ */
.section { margin: 2.7rem 0 2.2rem; }
/* section header = kinetic italic title with a crimson underline under the text (matches the
   active-tab / leaderboard-header motif) so each section clearly announces itself */
.section > h2 {
  display: inline-block;
  font-family: var(--display); font-weight: 800; font-style: italic;
  transform: skewX(-4deg); transform-origin: left; /* every display heading leans (§1.3) */
  text-transform: uppercase; letter-spacing: 0.04em;
  font-size: 1.42rem; color: var(--white);
  margin: 0 0 1.15rem; padding-bottom: 0.35rem;
  border-bottom: 3px solid var(--crimson);
}

/* ============================================================================
   BADGES & RATINGS — .badge.badge-class[data-class], .rating[data-rank] (§3.3)
   Rectangular, condensed uppercase, solid coded bg + near-black text. Never a
   dot, never round. Sized ≥14px since they carry font-weight 700 (no small-bold).
   ============================================================================ */
.badge {
  display: inline-flex; align-items: center; min-height: 24px;
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; font-size: 0.875rem; line-height: 1;
  padding: 0.3em 0.55em; border-radius: 4px; white-space: nowrap;
}
.badge-class { background: var(--gt3); color: #06120a; } /* GT3 default */
.badge-class[data-class="GTE"] { background: var(--gte); color: #180a00; }
.badge-class[data-class="LMP2"] { background: var(--lmp2); color: #000000; }
.badge-class[data-class="LMP3"] { background: var(--lmp3); color: #000000; }
.badge-class[data-class="HY"] { background: var(--hy); color: #1a0404; }
.badge-class[data-class="Overall"] { background: rgb(148, 163, 184); color: #0b0e13; }

.rating {
  display: inline-flex; align-items: stretch; overflow: hidden; min-height: 24px;
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; font-size: 0.875rem; line-height: 1;
  border-radius: 4px; white-space: nowrap;
}
.rating .k { display: inline-flex; align-items: center; background: #2a313c; color: var(--muted); padding: 0.32em 0.42em; }
.rating .v { display: inline-flex; align-items: center; color: #0b0e13; padding: 0.32em 0.46em; background: #3a424e; }
.rating[data-rank="Bronze"] .v { background: var(--bronze); }
.rating[data-rank="Silver"] .v { background: var(--silver); }
.rating[data-rank="Gold"] .v { background: var(--gold); }
.rating[data-rank="Platinum"] .v { background: var(--plat); }
.rating[data-rank=""] .v, .rating:not([data-rank]) .v { background: #3a424e; color: var(--text); }

.chips { display: inline-flex; gap: 0.35rem; flex-wrap: wrap; align-items: center; }

/* ============================================================================
   PILLS — .pill, .pill.live (§3.7)
   ============================================================================ */
.pill {
  display: inline-flex; align-items: center; gap: 0.4em; min-height: 24px;
  font-family: var(--display); font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; font-size: 0.875rem; color: var(--muted);
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--chip-border);
  padding: 0.4em 0.8em; border-radius: 999px; white-space: nowrap;
}
/* pills that ARE links carry the cyan action accent statically — an action never
   shares the neutral status-chip look (§3.7) */
a.pill { color: var(--cyan); border-color: rgba(34, 195, 255, 0.45); }
a.pill:hover { border-color: rgba(34, 195, 255, 0.75); background: rgba(34, 195, 255, 0.08); }
.pill.live {
  color: var(--text); background: rgba(53, 196, 106, 0.14); border-color: rgba(53, 196, 106, 0.55);
}
.pill.live::before {
  content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--gt3); box-shadow: 0 0 8px 1px rgba(53, 196, 106, 0.7);
  animation: pill-blink 1.6s ease-in-out infinite;
}
@keyframes pill-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

.natcode {
  font-family: var(--body); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.03em;
  color: var(--muted); background: rgba(255, 255, 255, 0.06); border: 1px solid var(--chip-border);
  padding: 0.18em 0.45em; border-radius: 3px; display: inline-block;
}
.flag { font-size: 1rem; line-height: 1; }

/* ============================================================================
   CARD GRIDS & RACE CARDS — .cards(.tri), .race-card, .tier-card, .rc-stats (§3.4)
   Cards carry the game-sourced hero/card photo (.bg <img>) full-bleed behind a dark
   Broadcast veil (see .bg / :has(.bg) rules below); image-less records fall back to
   the glass-over-atmosphere surface. (design-language §3.4/§5)
   ============================================================================ */
/* auto-fit min tuned so the plain card grid (special / championship lists) tops out at 3 columns
   on the 1240px wrap, then reflows to 2 / 1 on narrower screens */
.cards { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.cards.tri { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .cards.tri { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .cards.tri { grid-template-columns: 1fr; } }

.race-card {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: 0.85rem;
  padding: 1.4rem 1.4rem 1.3rem;
  text-decoration: none; color: var(--text);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.race-card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.6); }
.race-card:focus-visible { outline-offset: -3px; }

/* game-sourced hero/card photo (heroImage/cardImage) — shown full-bleed behind a
   dark Broadcast veil + subtle crimson wash so titles/stats stay legible. Cards with
   no image fall back to the glass-over-atmosphere surface. */
.race-card .bg, .hub-tile .bg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2;
}
.race-card:has(.bg) { min-height: 210px; }
.race-card:has(.bg)::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  /* shadow concentrated under the text: darkest top-left + down the left, plus a bottom
     boost for the stats row; the photo peeks through the open right side */
  background:
    linear-gradient(118deg, rgba(6,11,20,0.90) 0%, rgba(7,12,22,0.54) 46%, rgba(9,15,26,0.20) 100%),
    linear-gradient(to top, rgba(6,11,20,0.52) 0%, transparent 36%),
    linear-gradient(305deg, rgba(229,18,59,0.12), transparent 44%);
}
.race-card:has(.bg) .rc-title { text-shadow: 0 1px 16px rgba(0,0,0,0.7); }
.race-card:has(.bg) .rc-track { color: var(--photo-text); }

.race-card .rc-top { display: flex; flex-wrap: wrap; gap: 0.45rem; align-items: center; }
.race-card .rc-body { display: flex; flex-direction: column; gap: 0.5rem; flex: 1; }
.race-card .rc-title,
.rc-title {
  font-family: var(--display); font-weight: 700; font-style: italic;
  transform: skewX(-4deg); transform-origin: left;
  text-transform: uppercase; font-size: 1.28rem; color: var(--white); line-height: 1.08;
}
.race-card .rc-track { font-family: var(--body); color: var(--muted); font-size: 0.86rem; letter-spacing: 0.02em; }
.race-card .rc-meta { margin-top: 0.1rem; display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }

/* stretched card link — cards are <article>s: the title link's ::after covers the whole
   card as the click target while .rc-start .cta sits above it as a second, separate
   link (no nested <a>). Anchored by .race-card's position:relative. */
.race-card .rc-link::after { content: ""; position: absolute; inset: 0; z-index: 1; }

/* .rc-start — next-start block pinned to the card bottom: cyan pulse + eyebrow over a big
   skewed-italic clock, "Full schedule" CTA bottom-right. Chosen "start block" variant,
   docs/design-explorations/card-next-start-variants.html (2026-07-10). */
.rc-start {
  margin-top: auto; padding-top: 0.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 0.8rem 1rem; flex-wrap: wrap; text-transform: uppercase;
}
.rc-start .rs-when { display: flex; flex-direction: column; gap: 0.3rem; }
.rc-start .lab {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.1em;
  font-size: 0.75rem; color: var(--muted);
}
.rc-start .time {
  font-family: var(--display); font-weight: 800; font-style: italic;
  transform: skewX(-4deg); transform-origin: left;
  font-size: 1.45rem; line-height: 1.05; color: var(--white); letter-spacing: 0.01em;
}
.rc-start .cta { position: relative; z-index: 2; margin-left: auto; font-size: 0.8125rem; padding: 0.5em 0.9em; }

/* .rc-stats — reused generic label/value grid (race cards, panels) */
.rc-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 0.8rem 1rem; margin-top: 0.3rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08); padding-top: 0.85rem;
}
.rc-stats > div { display: flex; flex-direction: column; gap: 0.18rem; min-width: 0; }
.rc-stats .lab { font-family: var(--display); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.75rem; color: var(--muted); }
.rc-stats .val { font-family: var(--display); font-weight: 700; color: var(--text); font-size: 0.98rem; letter-spacing: 0.01em; overflow-wrap: anywhere; }

/* wedge/hazard-stripe corner motif clipped into the card corner — CSS only */
.race-card .motif {
  position: absolute; top: 0; right: 0; width: 30px; height: 30px; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(45deg, var(--crimson) 0 6px, #0A1220 6px 12px);
  clip-path: polygon(100% 0, 100% 100%, 0 0);
  opacity: 0.9;
}

/* Poster-banner cards — daily Next .tier-card ("poster twin",
   docs/design-explorations/next-card-banner-variants.html §1, adopted 2026-07-14) and the
   championships .champ-card ("clean ledger", champ-card-banner-variants.html §9, adopted
   2026-07-17). The photo sits in a full-opacity top banner mirroring the Schedule tab's
   .sched-poster: SR chip (plus class badges where the body carries none) up top, title +
   track line in the lower third. Bodies differ per card type below; other .race-card
   layouts are unaffected. */
.tier-card, .champ-card { padding: 0; gap: 0; }
.tier-card::before, .champ-card::before { content: none; } /* photo + veil live in the banner, not across the card */
:is(.tier-card, .champ-card) .rc-banner {
  /* positioned so the photo/veil fill it — but NOT overflow:hidden: the stretched
     rc-link::after below must escape it (the card's own overflow crops everything) */
  position: relative; isolation: isolate;
  display: flex; flex-direction: column;
  min-height: 132px; padding: 0.85rem 1.4rem 0.8rem;
}
:is(.tier-card, .champ-card) .rc-banner::before { /* veil weighted to the lower third, where the text sits */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 11, 20, 0.28) 0%, rgba(6, 11, 20, 0.52) 30%, rgba(6, 11, 20, 0.9) 100%),
    linear-gradient(305deg, rgba(229, 18, 59, 0.10), transparent 44%);
}
:is(.tier-card, .champ-card) .rc-banner .rating { align-self: flex-start; }
:is(.tier-card, .champ-card) .rc-banner .rc-track { font-size: 0.8rem; } /* matches .sched-poster .sp-track */
:is(.tier-card, .champ-card) .rc-foot {
  margin-top: auto; padding-top: 1rem;
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.35rem;
}
/* The whole card stays the click target: the banner is the title link's containing block,
   so the stretched ::after overshoots downward and the card's overflow:hidden crops it. */
:is(.tier-card, .champ-card) .rc-link::after { bottom: -100vh; }
:is(.tier-card, .champ-card) .rc-main {
  padding: 0.9rem 1.4rem 1.3rem; flex: 1;
  display: flex; flex-direction: column; gap: 0.55rem;
}

/* Championship "clean ledger" standings — position · class badge · name · points on hairline
   rows, P1 emphasized, a stronger rule where the next class group starts. Canonical .stand:
   shared by the championships-index cards and the champ detail Standings panel; the hub hero's
   .pod-band speaks the same ledger language with its own crew-line twist (§ podium band). The
   banner's track line announces the next round ("R4 · <track>") with the round number popped
   white. */
.champ-card .rc-track b { color: var(--white); font-weight: 700; font-size: 0.875rem; } /* popped round no. — 700 needs ≥14px (§1.4) */
.stand { display: flex; flex-direction: column; }
.stand .bl {
  font-family: var(--display); font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; font-size: 0.75rem; color: var(--muted); margin-bottom: 0.15rem;
}
.stand .row { display: flex; align-items: baseline; gap: 0.55rem; padding: 0.3rem 0.1rem; font-size: 0.875rem; }
.stand .row + .row { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.stand .row.grp { border-top-color: rgba(255, 255, 255, 0.12); } /* new class group starts */
.stand .pos { font-family: var(--display); font-weight: 600; color: var(--faint); min-width: 1.6em; }
.stand .badge { min-height: 18px; font-size: 0.75rem; font-weight: 600; align-self: center; }
.stand .name { color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stand .pts { margin-left: auto; font-family: var(--display); font-weight: 600; color: var(--muted); white-space: nowrap; flex-shrink: 0; }
.stand .row.p1 .pos { color: var(--text); }
.stand .row.p1 .name { font-weight: 700; color: var(--white); }
.stand .row.p1 .pts { color: var(--text); }
/* card leaderboard rows reuse the Time-to-beat .beat-row anatomy — one "class
   leader + lap" row style everywhere (badge · .name · .lap) */
.tier-card .rc-beat {
  margin-top: 0.2rem; padding-top: 0.6rem;
  border-top: 1px dashed rgba(255, 255, 255, 0.12);
  display: flex; flex-direction: column;
}
.tier-card .rc-beat .bl {
  font-family: var(--display); font-weight: 600; letter-spacing: 0.12em;
  text-transform: uppercase; font-size: 0.75rem; color: var(--muted); margin-bottom: 0.15rem;
}
.tier-card .rc-times { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.tier-card .rc-times time {
  font-family: var(--display); font-weight: 600; font-size: 0.8125rem; letter-spacing: 0.05em;
  color: var(--muted); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 4px;
  padding: 0.15em 0.5em; background: rgba(8, 14, 25, 0.5);
}
.tier-card .rc-times time.past {
  color: var(--faint);
  text-decoration: line-through; text-decoration-color: var(--crimson); text-decoration-thickness: 2px;
}

/* ============================================================================
   PANELS — .panel > h3 (§3.5)
   ============================================================================ */
.panel { padding: 1.4rem 1.4rem 1.5rem; }
.panel > h3 {
  font-family: var(--display); font-weight: 700; font-style: italic;
  transform: skewX(-4deg); transform-origin: left;
  text-transform: uppercase; font-size: 1.12rem; color: var(--white);
  margin: 0 0 1rem; padding-bottom: 0.65rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
/* muted suffix inside a panel heading ("· round 2 of 8") — 500 is the lightest loaded
   Saira weight; never set 400 (not loaded, silently substitutes) */
.panel > h3 .muted { font-weight: 500; }

.grid-2 { display: grid; grid-template-columns: 340px 1fr; gap: 1.1rem; align-items: start; }
.grid-2 > * { min-width: 0; }
@media (max-width: 860px) { .grid-2 { grid-template-columns: 1fr; } }

/* stacked panels sharing one grid column */
.stack { display: flex; flex-direction: column; gap: 1.1rem; }

/* panel-corner deep link into the full view (e.g. "Full board →") */
.board-link {
  font-family: var(--display); font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; font-size: 0.8125rem; color: var(--cyan);
}
.board-link:hover { text-decoration: underline; }
.panel .ph-link { float: right; }

/* ============================================================================
   TIME TO BEAT — .panel.beat, .beat-row, .beat-ghost
   (docs/design-explorations/overview-pages.html §2, adopted 2026-07-18)
   ============================================================================ */
.beat-row { display: flex; align-items: center; gap: 0.55rem; padding: 0.44rem 0.1rem; }
.beat-row + .beat-row { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.beat-row .badge { min-height: 18px; font-size: 0.75rem; font-weight: 600; }
.beat-row .name {
  font-family: var(--body); font-weight: 600; color: var(--white); font-size: 0.9rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.beat-row .lap { margin-left: auto; font-family: var(--font-mono); font-weight: 700; font-size: 0.88rem; color: var(--best); }
.beat-row .gap { font-family: var(--display); font-weight: 600; font-size: 0.8125rem; color: var(--muted); text-align: right; }
.beat-ghost {
  margin-top: 0.6rem; border: 1px dashed rgba(255, 255, 255, 0.16); border-radius: 6px;
  padding: 0.5rem 0.7rem;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; font-size: 0.75rem; color: var(--faint);
}

/* ============================================================================
   TIMETABLE, WEEKDAY SPINE — .panel.timetable, .spn-row, .spn-cell, .spn-none
   (docs/design-explorations/timetable-day-variants.html §2, adopted 2026-07-18)
   The weekday is a boxed cell on a fixed left rail — the eye runs down the card
   like a wall calendar. Today is the ONE solid cyan block on the page (keep it
   unique or it loses its meaning); raceless days keep a hatched cell with the
   weekday struck, so a Mon+Thu weekly shows its true shape.
   ============================================================================ */
.spn-row { display: grid; grid-template-columns: 56px 1fr; gap: 0.6rem; align-items: start; }
.spn-row + .spn-row { margin-top: 0.55rem; }
.spn-cell {
  display: flex; flex-direction: column; align-items: center; gap: 0.06rem; padding: 0.42rem 0.2rem;
  border: 1px solid var(--glass-border); border-radius: 6px; background: rgba(255, 255, 255, 0.03);
  font-family: var(--display); text-align: center;
}
.spn-cell b { font-weight: 800; font-size: 0.875rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text); line-height: 1.1; }
.spn-cell span { font-weight: 600; font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); line-height: 1.1; white-space: nowrap; }
.spn-row.today .spn-cell { background: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 16px -3px rgba(34, 195, 255, 0.75); }
.spn-row.today .spn-cell b, .spn-row.today .spn-cell span { color: #06121c; }
.spn-row.dark .spn-cell {
  border-color: rgba(255, 255, 255, 0.05);
  background: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.035) 0 5px, transparent 5px 10px);
}
.spn-row.dark .spn-cell b { color: var(--faint); text-decoration: line-through; text-decoration-thickness: 1.5px; }
.spn-none {
  align-self: center; padding-left: 0.2rem;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint);
}
.timetable .sched-grid { grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); }
.timetable .sched-grid time { font-size: 0.95rem; padding: 0.5rem 0.2rem; }
.tt-foot {
  margin-top: 0.9rem; display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; font-size: 0.75rem; color: var(--muted);
}

/* ============================================================================
   RESULTS LEDGER, DAY SPINE — .rspine, details.rsp-day, .rsp-sum, .rsp-head, .rsp-row
   (docs/design-explorations/results-list-variants.html §1, adopted 2026-07-25)
   The Results tab's instance list as a collapsible wall calendar: the timetable's
   .spn-cell weekday boxes on the left rail, one native <details> per UTC day.
   A 30-min daily rotation collapses from ~336 status rows to one summary line
   per day plus the day the viewer opens. Statuses are positional, never chips:
   started slots are ledger rows (live = crimson, the run-row convention),
   upcoming slots are dimmed rows labeled "upcoming", and the crimson "now" seam
   sits on today's boundary. Today keeps the ONE solid cyan block rule.
   ============================================================================ */
.rspine { display: flex; flex-direction: column; }
.rsp-day { border-top: 1px solid rgba(255, 255, 255, 0.06); }
.rsp-day:first-child { border-top: none; }
.rsp-sum {
  display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: 0.6rem; align-items: center;
  padding: 0.5rem 0.5rem 0.5rem 0; cursor: pointer; list-style: none; border-radius: 6px;
}
.rsp-sum::-webkit-details-marker { display: none; }
.rsp-sum:hover { background: rgba(34, 195, 255, 0.05); }
.rsp-sum:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; }
.rsp-day.today .spn-cell { background: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 16px -3px rgba(34, 195, 255, 0.75); }
.rsp-day.today .spn-cell b, .rsp-day.today .spn-cell span { color: #06121c; }
.rsp-day.future .spn-cell { border-style: dashed; background: none; }
.rsp-day.future .spn-cell b { color: var(--faint); }
.rsp-line { font-family: var(--body); font-size: 0.9rem; color: var(--muted); }
.rsp-line b { color: var(--white); font-weight: 600; }
.rsp-line .dim { color: var(--faint); }
.rsp-line .live-hint { color: var(--crimson-hi); font-weight: 600; }
.rsp-chev {
  font-family: var(--display); font-weight: 600; font-size: 0.8125rem; letter-spacing: 0.09em;
  color: var(--faint); transition: transform 0.15s ease;
}
.rsp-day[open] > .rsp-sum .rsp-chev { transform: rotate(90deg); }
.rsp-body { padding: 0 0 0.9rem calc(56px + 0.6rem); }
.rsp-row {
  display: grid; grid-template-columns: 3.9rem 3.2rem minmax(0, 1fr) auto; gap: 1rem;
  align-items: center; min-height: 40px; padding: 0.15rem 0.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.rsp-row:first-child { border-top: none; }
.rsp-row:hover { background: rgba(34, 195, 255, 0.05); }
.rsp-row > time, .rsp-row .rsp-t {
  font-family: var(--display); font-weight: 600; font-size: 1rem; letter-spacing: 0.05em; color: var(--text);
}
.rsp-e { font-family: var(--display); font-weight: 600; font-size: 1rem; text-align: right; color: var(--white); }
.rsp-note { font-size: 0.875rem; color: var(--faint); display: flex; align-items: center; gap: 0.6em; }
.rsp-row.none > time, .rsp-row.none .rsp-t {
  color: var(--faint); text-decoration: line-through;
  text-decoration-color: rgba(229, 18, 59, 0.55); text-decoration-thickness: 2px;
}
.rsp-row.none .rsp-e { color: var(--faint); font-weight: 500; }
.rsp-row.live {
  background: rgba(229, 18, 59, 0.08); box-shadow: inset 3px 0 0 var(--crimson);
  border-top-color: rgba(229, 18, 59, 0.3);
}
.rsp-row.live > time { color: var(--white); }
.rsp-row.up > time { color: var(--muted); }
.rsp-live {
  display: inline-flex; align-items: center; gap: 0.45em;
  font-family: var(--display); font-weight: 600; font-size: 0.8125rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--crimson-hi);
}
/* Column labels atop each opened day's raced rows — same grid as .rsp-row, so the
   labels sit exactly over their columns; the first data row's hairline doubles as
   the header's separator rule (only header-less future days keep a borderless first row). */
.rsp-head {
  display: grid; grid-template-columns: 3.9rem 3.2rem minmax(0, 1fr) auto; gap: 1rem;
  padding: 0.35rem 0.5rem 0.15rem;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted);
}
.rsp-head .r { text-align: right; }
/* winner cell: class badge per winner + driver name per site convention (body face, 700,
   white — §3.6); one line, ellipsized, so long winner lists never push the Results pill around */
.rsp-win { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rsp-win .name { font-family: var(--body); font-weight: 700; color: var(--white); }
.rsp-win a.name:focus-visible { outline-offset: -2px; } /* ring stays inside the clipped cell (§4) */
.rsp-win .badge-class { margin-right: 0.4em; }
.rsp-win .name + .badge-class { margin-left: 0.7em; } /* breathing room between class winners */
.rsp-now { display: flex; align-items: center; gap: 0.7rem; padding: 0.35rem 0.5rem; }
.rsp-now::before, .rsp-now::after { content: ""; height: 2px; flex: 1; background: linear-gradient(90deg, var(--crimson), rgba(229, 18, 59, 0.12)); }
.rsp-now::after { background: linear-gradient(90deg, rgba(229, 18, 59, 0.12), transparent); }
.rsp-now span {
  font-family: var(--display); font-weight: 600; font-size: 0.8125rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--crimson-hi);
}
.rsp-unsch { border-top: 1px solid rgba(255, 255, 255, 0.06); padding: 0.5rem 0 0.9rem calc(56px + 0.6rem); }
.rsp-unsch-lab {
  display: block; padding: 0.3rem 0.5rem;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint);
}
@media (max-width: 560px) {
  .rsp-body, .rsp-unsch { padding-left: 0; }
  .rsp-row, .rsp-head { gap: 0.6rem; }
  .rsp-note { flex-wrap: wrap; row-gap: 0.1em; } /* prose wraps under the Live label, never hides it */
}

/* ============================================================================
   SEASON STRIP — .season, .rd (.no .trk .win), .season-cap
   (docs/design-explorations/overview-pages.html §4, adopted 2026-07-18)
   The championship's rounds as a filmstrip: done rounds dim their CHROME, not
   their text (opacity over muted/faint would fall below AA); the live round
   pops and scrolls into view on load on narrow viewports.
   ============================================================================ */
.season { display: flex; gap: 0.55rem; overflow-x: auto; padding: 2px 2px 0.4rem; scrollbar-width: none; }
.season::-webkit-scrollbar { display: none; }
.season:focus-visible { outline-offset: -2px; } /* keyboard-scrollable (tabindex on the strip) */
.rd {
  flex: 1 1 0; min-width: 96px; display: flex; flex-direction: column; gap: 0.16rem;
  padding: 0.55rem 0.65rem; border: 1px solid var(--glass-border); border-radius: 6px; background: var(--glass-bg);
}
.rd .no {
  font-family: var(--display); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  font-size: 0.75rem; color: var(--muted); display: flex; align-items: center; gap: 0.45em;
}
.rd .trk { font-family: var(--body); font-weight: 600; font-size: 0.875rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rd .win { font-family: var(--display); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--faint); }
.rd.done { background: rgba(16, 27, 46, 0.32); border-color: rgba(255, 255, 255, 0.05); }
.rd.done .no { color: var(--faint); }
.rd.done .trk { color: var(--muted); font-weight: 500; }
.rd.done .no::after { content: "done"; letter-spacing: 0.12em; color: var(--faint); }
.rd.live { border-color: rgba(229, 18, 59, 0.55); background: linear-gradient(180deg, rgba(229, 18, 59, 0.14), var(--glass-bg) 75%); min-width: 150px; flex-grow: 1.6; }
.rd.live .no { color: var(--crimson-hi); }
.season-cap {
  margin: 0.5rem 0 1.1rem; font-family: var(--display); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.75rem; color: var(--muted);
}

/* ============================================================================
   SESSIONS / WEATHER — .sessions .ses (.n .d), .weather span (§3.5)
   ============================================================================ */
.sessions { display: flex; flex-direction: column; gap: 0.5rem; }
.sessions .ses {
  display: flex; align-items: center; gap: 0.8rem;
  padding: 0.55rem 0.75rem; background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 6px;
}
.sessions .ses .n {
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; font-size: 0.875rem; color: var(--text); min-width: 82px;
}
.sessions .ses .d {
  font-family: var(--display); font-weight: 700; color: var(--cyan); font-size: 0.9rem;
  margin-left: auto; text-align: right;
}
/* colorful weather (design-language §3.5): sun amber, cloud steel, rain blue.
   The wx-* class is added per-condition in the ui.weather macro — see _macros.html.twig. */
.weather { display: inline-flex; align-items: center; gap: 0.22rem; font-size: 0.98rem; color: var(--muted); flex: 1; justify-content: center; }
.weather span { line-height: 1; }
.weather .wx-sun { color: var(--warn); text-shadow: 0 0 8px rgba(255, 194, 26, 0.5); }
.weather .wx-cloud { color: #9FB6D4; }
.weather .wx-rain { color: #22C3FF; text-shadow: 0 0 8px rgba(34, 195, 255, 0.5); }

/* weekend server-settings tiles — .set-tiles .tile (design-explorations/
   weekend-card-variants.html §V2 "pit-wall tiles", adopted 2026-07-20).
   One glass tile per setting: stroke glyph + value + label, echoing the .ses
   rows above. Boolean tiles carry state — .on lights glyph+value cyan, .off
   dims them; the Yes/No value text always rides along (color never alone). */
.set-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 0.45rem; margin-top: 1rem; }
.set-tiles .tile {
  display: flex; align-items: center; gap: 0.55rem; padding: 0.5rem 0.6rem; min-width: 0;
  background: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 6px;
}
.set-tiles .tile svg { width: 20px; height: 20px; flex: none; stroke: var(--muted); }
.set-tiles .t-txt { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.set-tiles .t-val { font-family: var(--display); font-weight: 700; font-size: 0.95rem; color: var(--text); line-height: 1.1; letter-spacing: 0.02em; }
.set-tiles .t-lab {
  font-family: var(--display); font-weight: 500; letter-spacing: 0.07em; text-transform: uppercase;
  font-size: 0.75rem; color: var(--muted); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.set-tiles .tile.on { border-color: rgba(34, 195, 255, 0.35); }
.set-tiles .tile.on svg { stroke: var(--cyan); filter: drop-shadow(0 0 4px rgba(34, 195, 255, 0.5)); }
.set-tiles .tile.on .t-val { color: var(--cyan); }
.set-tiles .tile.off svg { stroke: var(--faint); opacity: 0.65; }
.set-tiles .tile.off .t-val { color: var(--faint); }

/* ============================================================================
   HUB BAND — .hub, .hub-tile(.ht-name, .ht-count) (§3.5)
   Slim section band above the footer ("race control deck" adoption 2026-08-04,
   docs/design-explorations/racing-today-filter-variants.html#deck): the 2×2
   tiles slimmed down to a four-across strip when the rundown went full width.
   Each tile keeps its game-sourced section photo (.bg) behind the house veil —
   synced imagery is real content (§3.4/§5); image-less tiles stay bare glass.
   ============================================================================ */
.hub {
  margin-top: 2.4rem; padding-top: 1.2rem; border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.7rem; position: relative;
}
.hub::before { /* band label riding the top rule */
  content: "Sections"; position: absolute; top: -0.62em; left: 0;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  background: var(--void); padding-right: 0.7em;
}
.hub-tile {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: 0.15rem; justify-content: flex-end;
  padding: 0.75rem 0.95rem; border-radius: 8px;
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.hub-tile:hover { transform: translateY(-2px); border-color: rgba(229, 18, 59, 0.4); }
.hub-tile:hover::before { transform: translate(2px, -2px); }
.hub-tile:focus-visible { outline-offset: -3px; }
/* photo tiles grow a little so the image reads; the veil is darkest under the
   left-aligned text and lets the photo peek out on the right (house recipe) */
.hub-tile:has(.bg) { min-height: 108px; }
.hub-tile:has(.bg)::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(118deg, rgba(6,11,20,0.90) 0%, rgba(7,12,22,0.54) 46%, rgba(9,15,26,0.20) 100%),
    linear-gradient(to top, rgba(6,11,20,0.52) 0%, transparent 36%),
    linear-gradient(305deg, rgba(229,18,59,0.12), transparent 44%);
}
.hub-tile:has(.bg) .ht-name { text-shadow: 0 1px 16px rgba(0,0,0,0.7); }
.hub-tile:has(.bg) .ht-count { color: var(--photo-text); }
.hub-tile .ht-name {
  font-family: var(--display); font-weight: 800; text-transform: uppercase; letter-spacing: 0.02em;
  font-size: 1rem; color: var(--white); padding-right: 1.4rem;
}
.hub-tile .ht-name::after { content: ""; display: block; width: 30px; height: 2px; background: var(--crimson); margin-top: 0.25rem; }
.hub-tile .ht-count { font-family: var(--body); color: var(--muted); font-size: 0.78rem; }

/* ============================================================================
   TABLES — .table-wrap, table.data (§3.6) — the acceptance test of the design
   ============================================================================ */
.table-wrap { overflow-x: auto; margin-bottom: 1rem; }
table.data { width: 100%; border-collapse: collapse; font-size: 0.92rem; }

table.data thead th {
  position: sticky; top: 0; z-index: 2;
  background: rgba(10, 17, 30, 0.92);
  font-family: var(--display); font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; font-size: 0.9375rem; color: var(--muted);
  padding: 0.75rem 0.9rem; text-align: left;
  border-bottom: 2px solid var(--crimson);
  white-space: nowrap;
}
table.data thead th.num, table.data td.num { text-align: right; }

table.data tbody td {
  padding: 0.62rem 0.9rem; font-size: 0.92rem; color: var(--text);
  border-bottom: 1px solid rgba(34, 195, 255, 0.14);
  white-space: nowrap; vertical-align: middle;
}
table.data tbody tr { transition: background 0.18s ease; }
table.data tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.018); }
table.data tbody tr:hover { background: rgba(34, 195, 255, 0.07); box-shadow: inset 0 0 0 1px rgba(34, 195, 255, 0.15); }

table.data .pos { font-family: var(--display); font-weight: 800; font-size: 1.05rem; color: var(--text); }
table.data .num { font-variant-numeric: tabular-nums lining-nums; }

/* driver / track / circuit names — Inter, bold, white. NOT condensed (§3.6, §1.3). */
table.data .driver { font-family: var(--body); min-width: 200px; white-space: normal; }
.driver-cell { display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.driver-cell .name,
table.data .name {
  font-family: var(--body); font-weight: 700; color: var(--white); font-size: 1rem;
}
a.name:hover, a.name:focus-visible { color: var(--cyan); text-decoration: underline; }

/* team / car cell */
table.data td.muted { color: var(--muted); font-family: var(--body); font-size: 0.92rem; }

/* lap & sector times — IBM Plex Mono. Sector cells get the `.time` hook added
   in _leaderboard.html.twig so they mono without affecting gap/other numerics. */
table.data .lap { font-family: var(--font-mono); font-weight: 600; letter-spacing: 0; font-size: 0.92rem; }
table.data .num.time { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0; font-size: 0.9rem; }
/* fastest-sector / personal-best highlight — apply `.best` alongside `.time` where that data exists */
table.data .num.time.best {
  color: var(--best); font-weight: 700; background: rgba(199, 125, 255, 0.1);
  text-shadow: 0 0 10px rgba(199, 125, 255, 0.45);
  box-shadow: inset 3px 0 0 var(--best);
}

table.data .gap { font-family: var(--display); font-weight: 600; font-size: 0.85rem; color: var(--muted); }
table.data .total { font-family: var(--display); font-weight: 800; color: var(--white); font-size: 1rem; }

/* leader / "you" row emphasis, ready for use wherever a template marks a row */
table.data tbody tr.leader { background: linear-gradient(90deg, rgba(229, 18, 59, 0.22), rgba(229, 18, 59, 0.05) 70%); box-shadow: inset 3px 0 0 var(--crimson-hi); }
table.data tbody tr.leader:hover { background: linear-gradient(90deg, rgba(229, 18, 59, 0.28), rgba(229, 18, 59, 0.08) 70%); }
table.data tbody tr.you-row { background: linear-gradient(90deg, rgba(34, 195, 255, 0.16), rgba(34, 195, 255, 0.03) 70%); box-shadow: inset 3px 0 0 var(--cyan); }

/* position-change glyph, ready for use wherever a template renders one */
.delta { font-family: var(--display); font-weight: 500; font-size: 0.8125rem; letter-spacing: 0.02em; margin-left: 0.35em; }
.delta-up { color: var(--gt3); }
.delta-down { color: var(--hy-hi); }
.delta-flat { color: var(--muted); }

/* ============================================================================
   SCHEDULE GRID — .sched-grid, time, time.past (§3.5)
   ============================================================================ */
.sched-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 0.4rem; }
.sched-grid time {
  font-family: var(--display); font-weight: 700; text-align: center;
  padding: 0.4rem 0.2rem; font-variant-numeric: tabular-nums;
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--chip-border); border-radius: 5px;
  font-size: 0.875rem; color: var(--text); display: block; position: relative;
}
.sched-grid time.past {
  color: var(--crimson-hi); text-decoration: line-through; opacity: 0.6;
  border-color: rgba(229, 18, 59, 0.3); background: rgba(229, 18, 59, 0.05);
}
/* timetable chip states (overview-pages.html §2): the next start pops cyan, a start still
   inside its race window reads live — each with a riding marker in the .tz-dayhint register */
.sched-grid time.next {
  color: var(--white); border-color: rgba(34, 195, 255, 0.65); background: rgba(34, 195, 255, 0.13);
  box-shadow: 0 0 12px -2px rgba(34, 195, 255, 0.5);
}
.sched-grid time.next::after {
  content: "next"; position: absolute; top: -8px; left: 50%; transform: translateX(-50%); white-space: nowrap;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--cyan); background: #0A1524; padding: 0 0.4em; border-radius: 2px;
}
.sched-grid time.live { color: var(--white); border-color: rgba(229, 18, 59, 0.55); background: rgba(229, 18, 59, 0.10); }
.sched-grid time.live::after {
  content: "on air"; position: absolute; top: -8px; left: 50%; transform: translateX(-50%); white-space: nowrap;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--crimson-hi); background: #0A1524; padding: 0 0.4em; border-radius: 2px;
}
/* Day-boundary hint (.tz-dayhint, top of file) on a grid slot whose local time falls
   on a different calendar day than UTC — poster-card grids only: weekday-spine
   timetables re-home such chips onto their local day row instead (_localtime.html.twig). */
/* Round marker on championship timetable chips — "tower rule", §1 of
   round-marker-variants.html (adopted 2026-07-19): the marker rides inline after the
   digits behind a timing-tower hairline divider, so it reads as a column of the chip
   rather than a floating superscript. Only slots from a round other than the one on
   air carry it (.away — e.g. projected next-round times), in warning amber; the
   current round's chips stay plain. Rendered from data-round via ::before pushed
   after the digits with flex order (survives the localtime textContent rewrite;
   ::after is owned by the next/on-air labels). Every championship chip is tagged, so
   tagged grids widen their columns uniformly — the daily/special grids keep the
   plain 64px block chips. */
.sched-grid:has(time[data-round]) { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); }
.sched-grid time.away[data-round] { display: flex; align-items: baseline; justify-content: center; }
.sched-grid time.away[data-round]::before {
  content: attr(data-round); order: 1;
  font-family: var(--display); font-weight: 600; font-size: 12px; letter-spacing: 0.08em;
  line-height: 1; color: var(--warn);
  margin-left: 0.55em; padding-left: 0.55em; border-left: 1px solid rgba(255, 194, 26, 0.35);
}
.sched-grid time.past.away[data-round]::before { color: inherit; border-left-color: rgba(229, 18, 59, 0.3); }

/* Schedule-tab "race poster" cards (docs/design-explorations/schedule-tab-variants.html §3,
   adopted 2026-07-14): the photo banner carries all identity — SR chip + class badges in the
   top row (mirroring the special/weekly cards' .rc-top), series title and track line in the
   lower third — while the body below is nothing but the timetable, bucketed under per-day
   eyebrow rules. Today's eyebrow goes cyan (time accent). */
.sched-poster {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--glass-bg); border: 1px solid var(--glass-border); border-radius: var(--radius);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.sched-poster:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.6); }
.sched-poster .sp-banner {
  /* positioned so the photo/veil fill it — but NOT overflow:hidden: the stretched
     rc-link::after below must escape it (the card's own overflow crops everything) */
  position: relative; isolation: isolate;
  min-height: 148px; padding: 0.85rem 1.1rem 0.8rem;
  display: flex; flex-direction: column;
}
/* Whole card is the click target: the banner is the title link's containing block, so the
   stretched ::after overshoots downward and the card's overflow:hidden crops it. */
.sched-poster .rc-link::after { content: ""; position: absolute; inset: 0; bottom: -100vh; z-index: 1; }
.sched-poster .sp-banner .bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.sched-poster .sp-banner::before { /* veil weighted to the lower third, where the text sits */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(6, 11, 20, 0.28) 0%, rgba(6, 11, 20, 0.52) 30%, rgba(6, 11, 20, 0.9) 100%),
    linear-gradient(305deg, rgba(229, 18, 59, 0.10), transparent 44%);
}
.sched-poster .sp-top { display: flex; flex-wrap: wrap; gap: 0.45rem; align-items: center; } /* matches .race-card .rc-top */
.sched-poster .sp-foot {
  margin-top: auto; padding-top: 1.2rem;
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.35rem;
}
.sched-poster .sp-foot .rc-title { font-size: 1.3rem; text-shadow: 0 1px 16px rgba(0, 0, 0, 0.75); }
.sched-poster .sp-track { font-family: var(--body); color: var(--photo-text); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.02em; }
.sched-poster .sp-body { flex: 1; padding: 0.95rem 1.1rem 1.15rem; display: flex; flex-direction: column; gap: 0.85rem; }
.sp-day { display: flex; flex-direction: column; gap: 0.45rem; }
.sp-day .sp-day-lab {
  display: flex; align-items: center; gap: 0.6rem;
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
}
.sp-day .sp-day-lab::after { content: ""; flex: 1; height: 1px; background: rgba(255, 255, 255, 0.09); }
.sp-day.today .sp-day-lab { color: var(--cyan); }
.sp-day .sched-grid { grid-template-columns: repeat(auto-fill, minmax(70px, 1fr)); }
.sp-day .sched-grid time { font-size: 0.95rem; padding: 0.5rem 0.2rem; }

/* ============================================================================
   EMPTY STATE / BACK LINK — .empty, .back (§3.7)
   ============================================================================ */
.empty { color: var(--muted); font-style: normal; text-align: center; padding: 2.2rem 1.2rem; font-size: 0.94rem; }
.empty::before { content: "◌"; display: block; font-size: 1.5rem; color: var(--faint); margin-bottom: 0.5rem; }

.back {
  display: inline-flex; align-items: center; min-height: 24px;
  margin-top: 1.6rem; color: var(--muted);
  font-family: var(--display); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.875rem;
}
.back:hover { color: var(--cyan); }

/* ── Race results page — race-control feed + position deltas (2026-07-09 spec) ── */
.race-control { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.race-control li { display: flex; gap: 0.7rem; align-items: baseline; padding: 0.35rem 0.2rem; font-size: 0.88rem; }
.race-control li + li { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.race-control .rc-et { font-family: var(--display); font-weight: 600; color: var(--muted); min-width: 4.6em; }
.race-control .rc-kind { font-family: var(--display); font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; font-size: 0.75rem; color: var(--muted); min-width: 5.2em; }
.race-control .rc-penalty .rc-kind { color: var(--crimson-hi); }
.race-control .rc-desc { color: var(--text); }

/* ============================================================================
   FOOTER — .site-footer .footer-inner .footer-brand .footer-disclaimer
   ============================================================================ */
.site-footer { border-top: 1px solid rgba(255, 255, 255, 0.08); padding: 2.4rem 0 2.2rem; margin-top: 1rem; position: relative; }
.site-footer::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--crimson) 30%, var(--cyan) 65%, transparent); opacity: 0.7;
}
.footer-inner {
  max-width: var(--wrap); margin: 0 auto; padding: 0 clamp(1.25rem, 4vw, 3rem);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1.5rem; align-items: flex-end;
}
.footer-brand {
  font-family: var(--display); font-weight: 800; font-style: italic; transform: skewX(-6deg);
  display: inline-block; font-size: 1.15rem; color: var(--white); text-transform: uppercase;
}
.footer-brand span { color: var(--crimson-hi); }
.footer-tz { color: var(--text); font-size: 0.82rem; margin: 0; }
.footer-disclaimer { color: var(--muted); font-size: 0.82rem; max-width: 34em; line-height: 1.5; margin-top: 0.6rem; }

/* ============================================================================
   SUPPORT ROW — .support-row .support-inner .support-label .support-copy
   .bmc-btn (§3.14; the footer's first row,
   docs/design-explorations/footer-support-variants.html V4, adopted 2026-08-04 —
   replaced the standalone band above the footer from the same day)
   No band chrome: the row shares the footer's background, seam and side padding;
   a full-bleed hairline separates it from the brand row. The button is the
   official Buy Me a Coffee look rendered as our own static markup
   (partials/_support_button.html.twig) — never the vendor <script> embed.
   BMC brand yellow #FFDD00 is the one sanctioned hard-coded hex.
   ============================================================================ */
.bmc-btn {
  display: inline-flex; align-items: center; gap: 0.45em; flex: none;
  background: #FFDD00; color: #000;
  font-family: var(--body); font-weight: 600; font-size: 0.9375rem;
  height: 40px; padding: 0 16px; border-radius: 9px;
  text-decoration: none; white-space: nowrap;
  transition: filter 0.15s ease;
}
.bmc-btn:hover { filter: brightness(1.08); }
.bmc-btn svg { height: 24px; width: auto; flex: none; }
.bmc-btn-text { line-height: 1; }

.support-row { border-bottom: 1px solid rgba(255, 255, 255, 0.07); margin-bottom: 1.7rem; }
.support-inner {
  max-width: var(--wrap); margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 3rem) 1.5rem;
  display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap;
}
.support-label {
  display: inline-flex; align-items: center; gap: 0.6em; flex: none;
  font-family: var(--display); font-weight: 700; font-size: 0.875rem;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--white);
}
.support-glyph { color: var(--warn); flex: none; }
.support-copy { color: var(--muted); font-size: 0.875rem; margin: 0; flex: 1 1 24em; min-width: 16em; }
.support-inner .bmc-btn { margin-left: auto; }
@media (max-width: 640px) {
  .support-inner .bmc-btn { margin-left: 0; }
}

/* ============================================================================
   ACCESSIBILITY — focus, reduced motion (§4)
   ============================================================================ */
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 3px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .race-card:hover, .hub-tile:hover, .sched-poster:hover { transform: none; }
  .dot-cyan, .dot-live { animation: none; }
  .cta { transition: none; }
}

/* ============================================================================
   RESPONSIVE — reflow to ~380px without horizontal page scroll (§4)
   ============================================================================ */
@media (max-width: 720px) {
  .hub { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 420px) {
  .hub { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .nav { gap: 0.7rem; }
  .nav-tabs { width: 100%; justify-content: space-between; gap: 0.6rem; }
}

/* ── Event-of-the-day podium band — clean ledger + accent spine (2026-07-19,
   docs/design-explorations/hero-podium-variants.html V2 + V3's spine, adopted) ──
   The champ-card .stand language on the hero band: hairline rows, no fills, P1 popped
   white. Team entries stack the full lineup on an indented crew line under the classified
   driver; solo/points rows stay one line, so both hero flavours share the markup. Each
   entry carries a 3px class-colored spine — P1 at full strength, the rest at the old
   fill-gradient alphas — the class code as a thread instead of the retired bar wash.
   Replaced the gradient .podium/.pod-band bars — the hub was their last user after the
   championships index went ledger on 2026-07-17. */
.pod-class { display: flex; flex-direction: column; }
.cls-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.cls-head .lab { font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); }
.pod-band .cls-head { margin-bottom: 0.45rem; }
.pod-band .pod-class { --spine: rgb(148, 163, 184); --spine-dim: rgba(148, 163, 184, 0.32); } /* Overall */
.pod-band .pod-class[data-class="GT3"] { --spine: var(--gt3); --spine-dim: rgba(53, 196, 106, 0.34); }
.pod-band .pod-class[data-class="GTE"] { --spine: var(--gte); --spine-dim: rgba(249, 115, 22, 0.36); }
.pod-band .pod-class[data-class="LMP2"] { --spine: var(--lmp2); --spine-dim: rgba(63, 127, 224, 0.38); }
.pod-band .pod-class[data-class="LMP3"] { --spine: var(--lmp3); --spine-dim: rgba(154, 103, 234, 0.36); }
.pod-band .pod-class[data-class="HY"] { --spine: var(--hy); --spine-dim: rgba(229, 72, 77, 0.36); }
.pod-band .entry { border-left: 3px solid var(--spine-dim); padding: 0.38rem 0.1rem 0.38rem 0.6rem; }
.pod-band .entry.p1 { border-left-color: var(--spine); }
.pod-band .entry + .entry { border-top: 1px solid rgba(255, 255, 255, 0.05); }
.pod-band .line { display: flex; align-items: baseline; gap: 0.55rem; font-size: 0.875rem; }
.pod-band .line .pos { font-family: var(--display); font-weight: 600; color: var(--faint); min-width: 1.6em; }
.pod-band .line .name { min-width: 0; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* linked names keep the ledger's look until hover — the band is a standings read, not a nav strip */
a.name { text-decoration: none; }
.pod-band .line a.name:hover { color: var(--cyan); text-decoration: underline; text-underline-offset: 2px; }
.pod-band .line .pts { margin-left: auto; font-family: var(--display); font-weight: 600; color: var(--muted); white-space: nowrap; flex-shrink: 0; }
.pod-band .crew { margin: 0.06rem 0 0 calc(1.6em + 0.55rem); font-size: 0.75rem; line-height: 1.3; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pod-band .entry.p1 .pos { color: var(--text); }
.pod-band .entry.p1 .name { font-weight: 700; color: var(--white); }
.pod-band .entry.p1 .pts { color: var(--text); }
.grid-forming { display: flex; flex-direction: column; gap: 0.45rem; background: rgba(8, 14, 25, 0.66); border: 1px dashed rgba(255, 255, 255, 0.16); border-radius: 8px; padding: 0.8rem 0.9rem; }
.grid-forming .gf-line { display: flex; align-items: center; gap: 0.55rem; font-family: var(--display); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.8125rem; color: var(--muted); }
.grid-forming .gf-sub { color: var(--faint); font-size: 0.82rem; }

.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dot-cyan { background: var(--cyan); box-shadow: 0 0 8px 1px rgba(34, 195, 255, 0.7); animation: dot-blink 2.2s ease-in-out infinite; }
@keyframes dot-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.28; } }

/* ── "Racing today" rundown (hub) — full-width race control deck ("race control
   deck", docs/design-explorations/racing-today-filter-variants.html#deck,
   adopted 2026-08-04; replaced the .hub-cols split of 2026-07-19 — the section
   tiles moved to the .hub band above the footer). The rundown always lists the
   30 soonest upcoming starts (no date horizon) plus the freshest started rows;
   the deck's facets are server-backed (rows re-fetched, never hidden in place).
   Row anatomy: start time with its status stacked beneath (the row's clock) ·
   SR gate as its own scannable column · title + kind/circuit line · class
   badges · labeled race length on the far edge behind a hairline rule. Times
   stay upright 800 — the board doesn't lean, the car does.
   Surface: "departure board" (racing-today-row-variants.html §1, adopted
   2026-08-07 — replaced the bordered card rows of 2026-08-04): no per-row
   plates, the day ruled into hairlines inside one glass panel (§2's tower
   surface, folded in on adoption); statuses are inset edge bars with a wash,
   and the crimson NOW seam divides started from upcoming (the results spine's
   positional grammar, §3.13). ── */
.run-head { display: flex; align-items: baseline; gap: 0.9rem; flex-wrap: wrap; margin-bottom: 0.65rem; }
.run-head h2 { font-family: var(--display); font-weight: 800; font-style: italic; text-transform: uppercase; letter-spacing: 0.04em; transform: skewX(-4deg); transform-origin: left; font-size: clamp(1.3rem, 2.6vw, 1.7rem); line-height: 1; margin: 0; color: var(--white); }
.run-head .rh-count { font-family: var(--display); font-weight: 600; font-size: 0.8125rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }

/* the deck — one glass command strip of facet groups above the rows */
.run-deck {
  display: flex; align-items: flex-end; gap: 1rem 1.4rem; flex-wrap: wrap;
  background: var(--glass-bg); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border); border-radius: var(--radius);
  padding: 0.85rem 1.1rem 0.95rem; margin-bottom: 0.9rem;
  position: relative; overflow: hidden;
}
.dk-group { display: flex; flex-direction: column; gap: 0.4rem; }
.dk-lab { font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.dk-chips { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.dk-read { margin-left: auto; display: flex; align-items: center; gap: 0.9rem; padding-bottom: 0.15rem; }

/* facet chip = a <label> around a visually-hidden checkbox: ghost outline until
   checked, then the site's own solid badge colors. State is never hue alone —
   the fill/text luminance flips and the checkbox semantics carry it for AT. */
.fchip {
  display: inline-flex; align-items: center; gap: 0.4em; min-height: 30px; cursor: pointer;
  font-family: var(--display); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  font-size: 0.8125rem; padding: 0.25em 0.7em; border-radius: 4px;
  border: 1px solid var(--chip-border); color: var(--muted);
  background: rgba(255, 255, 255, 0.04);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.fchip input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
.fchip:hover { color: var(--text); border-color: rgba(255, 255, 255, 0.65); }
.fchip:has(input:focus-visible) { outline: 2px solid var(--cyan); outline-offset: 3px; }
.fchip:has(input:checked) { background: var(--text); border-color: var(--text); color: #0b0e13; }
/* class chips: colored ghost → solid data-locked class color when checked (§1.2) */
.fc-hy { color: var(--hy-hi); border-color: rgba(229, 72, 77, 0.6); }
.fc-hy:hover { border-color: var(--hy); }
.fc-hy:has(input:checked) { background: var(--hy); border-color: var(--hy); color: #160404; }
.fc-lmp2 { color: #7FA9EC; border-color: rgba(63, 127, 224, 0.6); }
.fc-lmp2:hover { color: #9FBFF2; border-color: var(--lmp2); }
.fc-lmp2:has(input:checked) { background: var(--lmp2); border-color: var(--lmp2); color: #000000; }
.fc-lmp3 { color: #B78FF0; border-color: rgba(154, 103, 234, 0.6); }
.fc-lmp3:hover { color: #C7A6F5; border-color: var(--lmp3); }
.fc-lmp3:has(input:checked) { background: var(--lmp3); border-color: var(--lmp3); color: #000000; }
.fc-gt3 { color: var(--gt3); border-color: rgba(53, 196, 106, 0.55); }
.fc-gt3:hover { color: var(--gt3); border-color: var(--gt3); }
.fc-gt3:has(input:checked) { background: var(--gt3); border-color: var(--gt3); color: #06120a; }
.fc-gte { color: #FFA057; border-color: rgba(249, 115, 22, 0.6); }
.fc-gte:hover { border-color: var(--gte); }
.fc-gte:has(input:checked) { background: var(--gte); border-color: var(--gte); color: #180a00; }
/* SR chips: same grammar in the rating metals */
.fc-bronze { color: #D49A64; border-color: rgba(192, 125, 67, 0.6); }
.fc-bronze:hover { border-color: var(--bronze); }
.fc-bronze:has(input:checked) { background: var(--bronze); border-color: var(--bronze); color: #160b03; }
.fc-silver { color: var(--silver); border-color: rgba(154, 166, 178, 0.6); }
.fc-silver:hover { border-color: var(--silver); }
.fc-silver:has(input:checked) { background: var(--silver); border-color: var(--silver); color: #0b0e13; }
.fc-gold { color: var(--gold); border-color: rgba(224, 168, 59, 0.6); }
.fc-gold:hover { border-color: var(--gold); }
.fc-gold:has(input:checked) { background: var(--gold); border-color: var(--gold); color: #171001; }

.fsel {
  font-family: var(--display); font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
  font-size: 0.8125rem; color: var(--text); background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--chip-border); border-radius: 4px; min-height: 30px; padding: 0.25em 0.5em;
  max-width: 15em;
}
.fsel option { background: var(--navy); color: var(--text); text-transform: none; }
.fapply, .freset {
  font-family: var(--display); font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  font-size: 0.8125rem; color: var(--cyan); background: none; border: none; padding: 0.25em 0; cursor: pointer;
}
.fapply:hover, .freset:hover { text-decoration: underline; }

.run {
  display: flex; flex-direction: column;
  background: var(--glass-bg); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border); border-radius: var(--radius); overflow: hidden;
}
/* filtered-empty: the dashed .run-empty box keeps its bare surface — no panel behind a panel */
.run:not(:has(.run-row)) { background: none; backdrop-filter: none; border: none; border-radius: 0; overflow: visible; }
.run-row {
  display: grid; grid-template-columns: 8.6em auto minmax(0, 1fr) auto auto; align-items: center; gap: 1rem;
  padding: 0.8rem 1.1rem; border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--text); transition: background 0.15s ease;
}
.run .run-row:last-child { border-bottom: none; }
.run-row:hover { background: rgba(34, 195, 255, 0.055); }
.run-row:focus-visible { outline-offset: -3px; } /* ring stays inside the clipped panel (§4) */
.run-row .rr-when { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.run-row .rr-time { font-family: var(--display); font-weight: 800; font-size: 1.45rem; letter-spacing: 0.04em; line-height: 1; color: var(--white); }
.run-row .rr-main { min-width: 0; }
.run-row .rr-name { display: block; font-weight: 600; font-size: 0.95rem; color: var(--white); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.run-row .rr-event-type { font-size: 0.78rem; font-weight: normal; color: var(--faint); letter-spacing: 0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.run-row .rr-track { display: block; font-size: 0.78rem; color: var(--faint); letter-spacing: 0.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 0.1rem; }
.run-row .rr-track .rr-eod { font-family: var(--display); font-weight: 600; letter-spacing: 0.06em; color: var(--crimson-hi); }
.run-row .rr-sr .rating { min-height: 18px; font-size: 0.75rem; font-weight: 600; }
.run-row .rr-meta { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; }
.run-row .rr-meta .badge { min-height: 18px; font-size: 0.75rem; font-weight: 600; }
.run-row .rr-len {
  display: flex; flex-direction: column; align-items: flex-end; gap: 0.12rem; text-align: right;
  border-left: 1px solid rgba(255, 255, 255, 0.09); padding-left: 1rem; min-width: 6.2em;
}
.run-row .rr-len .lab { font-family: var(--display); font-weight: 500; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint); }
.run-row .rr-len .val { font-family: var(--display); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text); white-space: nowrap; }
.run-row .rr-status { font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); display: inline-flex; align-items: center; gap: 0.4em; }
.run-row .rr-status [data-countdown] { white-space: nowrap; } /* "Starts in: H:MM:SS" stays on one line */
.run-row .rr-status .dot { width: 7px; height: 7px; }
.run-row.finished .rr-time { color: var(--faint); text-decoration: line-through; text-decoration-color: var(--crimson); text-decoration-thickness: 2px; }
.run-row.finished .rr-name { color: var(--muted); }
.run-row.finished .rr-len .val { color: var(--muted); }
.run-row.live { box-shadow: inset 3px 0 0 var(--crimson); background: linear-gradient(90deg, rgba(229, 18, 59, 0.13), transparent 62%); }
.run-row.live:hover { background: linear-gradient(90deg, rgba(229, 18, 59, 0.19), transparent 62%); }
.run-row.live .rr-status { color: var(--crimson-hi); }
.run-row.next { box-shadow: inset 3px 0 0 var(--cyan); background: linear-gradient(90deg, rgba(34, 195, 255, 0.11), transparent 62%); }
.run-row.next:hover { background: linear-gradient(90deg, rgba(34, 195, 255, 0.17), transparent 62%); }
.run-row.next .rr-status { color: var(--cyan); }
/* the NOW seam — positional state (§3.13's grammar): rendered between the last
   started row and the first upcoming one; decorative for AT (statuses are text) */
.run-seam { display: flex; align-items: center; gap: 0.55em; padding: 0.28rem 1.1rem; }
.run-seam .lab { font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--crimson-hi); }
.run-seam::after { content: ""; flex: 1; height: 2px; background: linear-gradient(90deg, var(--crimson), rgba(229, 18, 59, 0.12)); }
.run-empty {
  text-align: center; color: var(--muted); padding: 2rem 1.2rem; margin: 0; font-size: 0.94rem;
  border: 1px dashed rgba(255, 255, 255, 0.16); border-radius: 8px;
}
.run-empty .freset { margin-left: 0.6em; }
@media (max-width: 860px) {
  /* rows re-wrap: time + status, then title, with SR + badges + length folding onto a trailing line */
  .run-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem 0.9rem; }
  .run-row .rr-when { order: 1; }
  .run-row .rr-main { order: 2; flex: 1 1 12em; }
  .run-row .rr-sr { order: 3; }
  .run-row .rr-meta { order: 4; justify-content: flex-start; }
  .run-row .rr-len { order: 5; flex-direction: row; align-items: baseline; gap: 0.45em; margin-left: auto; border-left: none; padding-left: 0; min-width: 0; }
  .dk-read { margin-left: 0; }
}
.dot-live { background: var(--crimson-hi); box-shadow: 0 0 8px 1px rgba(255, 51, 85, 0.7); animation: dot-blink 2.2s ease-in-out infinite; }

/* ── Event-of-the-day hero (hub) — poster hero ("the mix",
   docs/design-explorations/homepage-variants-2.html#mix, adopted 2026-07-19) ──
   Poster-scale: the game art fills the section behind a bottom-weighted veil, the
   title carries the page (it IS the h1 on hero days), the CTA row holds the
   "Starts in:" countdown, the event's start slots sit as a glassy panel on the
   right, and the podium ledger band closes the lower third. The gantry lamps
   retired with this layout — the eyebrow + countdown say "race day" on their own. */
.hero {
  position: relative; overflow: hidden; border-radius: var(--radius); border: 1px solid var(--glass-border);
  isolation: isolate; margin-bottom: 1.4rem;
  display: flex; flex-direction: column; justify-content: flex-end;
}
.hero:has(.hero-img) { min-height: clamp(430px, 44vw, 560px); }
.hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(8deg, rgba(6, 11, 20, 0.97) 20%, rgba(6, 11, 20, 0.44) 62%, rgba(6, 11, 20, 0.62) 100%); }
.hero .motif { /* hazard-stripe wedge corner, as on hub tiles / .ov-hero */
  position: absolute; top: 0; right: 0; width: 30px; height: 30px; z-index: 0; pointer-events: none;
  background: repeating-linear-gradient(45deg, var(--crimson) 0 6px, #0A1220 6px 12px);
  clip-path: polygon(100% 0, 100% 100%, 0 0); opacity: 0.9;
}
.hero-top { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1.4rem; align-items: end; padding: clamp(1.2rem, 3vw, 2.2rem); padding-top: clamp(2.2rem, 6vw, 4rem); }
@media (max-width: 900px) { .hero-top { grid-template-columns: 1fr; align-items: start; } }
.hero-eyebrow { font-family: var(--display); font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--crimson-hi); font-size: 0.875rem; margin: 0 0 0.2rem; text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8); }
.hero-title { font-family: var(--display); font-weight: 900; font-style: italic; text-transform: uppercase; transform: skewX(-6deg); transform-origin: left; font-size: clamp(2.2rem, 5.6vw, 3.9rem); line-height: 0.96; margin: 0 0 0.5rem; color: var(--white); text-shadow: 0 3px 30px rgba(0, 0, 0, 0.85); }
.hero-sub { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; color: var(--photo-text); font-size: 0.9rem; margin: 0; }
.hero-sub > span:not(.chips,.rating) { text-shadow: 0 1px 12px rgba(0, 0, 0, 0.7); }
.hero-row { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; margin-top: 1rem; }
.hero-cd { display: inline-flex; align-items: center; gap: 0.5em; font-family: var(--display); font-weight: 700; font-size: 1rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--white); text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8); }
.hero-cd [data-countdown] { color: var(--cyan); }
.cta { display: inline-flex; align-items: center; gap: 0.5em; font-family: var(--display); font-weight: 700; font-size: 0.95rem; letter-spacing: 0.08em; text-transform: uppercase; padding: 0.55em 1.1em; border-radius: 6px; border: 1px solid var(--crimson); color: var(--white); background: rgba(229, 18, 59, 0.16); transition: background 0.15s ease; }
.cta:hover { background: rgba(229, 18, 59, 0.3); }
.sched { display: flex; flex-direction: column; gap: 0.15rem; align-self: end; min-width: 264px; background: rgba(8, 14, 25, 0.55); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 8px; padding: 0.7rem 0.75rem; backdrop-filter: blur(8px); }
@media (max-width: 900px) { .sched { align-self: start; max-width: 340px; } }
.sched .sh { font-family: var(--display); font-weight: 600; font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--faint); margin-bottom: 0.3rem; }
.slot { display: flex; align-items: center; gap: 0.7rem; font-family: var(--display); font-weight: 600; font-size: 0.95rem; letter-spacing: 0.05em; padding: 0.32rem 0.55rem; border-radius: 4px; color: var(--text); }
.slot .t { min-width: 6.4em; }
.slot .s { font-size: 0.8125rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); }
.slot.past { color: var(--faint); }
.slot.past .t { text-decoration: line-through; text-decoration-color: var(--crimson); text-decoration-thickness: 2px; }
.slot.next { background: rgba(34, 195, 255, 0.14); }
.slot.next .s { color: var(--cyan); }
.pod-band { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(0.8rem, 2.4vw, 1.8rem); padding: 0.95rem clamp(1.2rem, 3vw, 2.2rem) 1.15rem; background: rgba(6, 11, 20, 0.62); backdrop-filter: var(--glass-blur); border-top: 1px solid rgba(255, 255, 255, 0.12); }
@media (max-width: 900px) { .pod-band { grid-template-columns: 1fr; } }
.pod-band .pod-class { gap: 0; }
.pod-band.one { grid-template-columns: minmax(260px, 440px); }

/* ============================================================================
   LEGAL / PROSE PAGES — .legal (privacy policy) + .footer-links
   ============================================================================ */
.legal { max-width: 46em; display: grid; gap: 1.1rem; }
.legal .panel p,
.legal .panel li { font-family: var(--body); font-size: 0.95rem; line-height: 1.65; color: var(--text); }
.legal .panel p { margin: 0 0 0.85rem; }
.legal .panel > :last-child { margin-bottom: 0; }
.legal .panel ul { margin: 0 0 0.85rem; padding-left: 1.2rem; }
.legal .panel li { margin-bottom: 0.4rem; }
.legal a { color: var(--cyan); text-decoration: underline; text-underline-offset: 2px; }
.legal a:hover { color: var(--white); }
.legal .panel .updated { color: var(--faint); font-size: 0.82rem; }
/* "The short version" (always the first panel) is subtly lifted: cyan-tinted border +
   raised glass. The heading still carries the meaning — color is never alone. */
.legal > .panel:first-child {
  background: var(--glass-bg-hi);
  border-color: rgba(34, 195, 255, 0.26);
}
.footer-links { font-size: 0.82rem; margin: 0.6rem 0 0; }
.footer-links a { color: var(--cyan); display: inline-flex; align-items: center; min-height: 24px; }
.footer-links a:hover { color: var(--white); text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================================
   LAP-BY-LAP DIALOG — clickable classification rows + <dialog> (§3.15)
   Adopted from docs/design-explorations/lap-dialog-variants.html:
   §1 "Timing tower" table with the §2 lap-time chart on top, 2026-08-06.
   Content arrives from the race_laps fragment (_lap_dialog_content.html.twig);
   the shell + row wiring live in _lap_dialog.html.twig.
   ========================================================================= */
/* The row opens the dialog on click; the driver name inside stays a link to the driver page.
   The row is deliberately not a button — the chevron .lapbtn is the real control, so keyboard
   and screen-reader users get the dialog without nesting a link inside a button. */
table.data tr.rowlink { cursor: pointer; }
table.data td.chev { text-align: right; width: 34px; padding-left: 0; }
.lapbtn {
  width: 26px; height: 26px; padding: 0; line-height: 1;
  border: 1px solid transparent; border-radius: 6px; background: transparent;
  color: var(--faint); font-size: 1.05rem; cursor: pointer;
}
table.data tr.rowlink:hover .lapbtn { color: var(--cyan); }
.lapbtn:hover { color: var(--cyan); border-color: rgba(34, 195, 255, 0.35); background: rgba(34, 195, 255, 0.08); }
.lapbtn:focus-visible { outline: 2px solid var(--cyan); outline-offset: -2px; color: var(--cyan); }

dialog.lapdlg {
  width: min(960px, calc(100vw - 32px));
  max-height: min(88vh, 900px);
  padding: 0; margin: auto;
  border: 1px solid var(--glass-border); border-radius: var(--radius);
  color: var(--text);
  /* near-opaque: the dialog floats over a timing table, glass would ghost rows through */
  background: linear-gradient(180deg, rgba(19, 32, 56, 0.97), rgba(10, 18, 33, 0.97));
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
  /* only .lapdlg-body ever scrolls — the dialog itself must not grow a second scrollbar */
  overflow: hidden;
}
/* The dialog is the flex container, so the body is bounded by its real content box. Scoped to
   [open] so the UA's display:none still hides it when closed. (Handing .lapdlg-in a
   `max-height: inherit` instead made it 2px taller than the space inside the border — with
   border-box the dialog's max-height includes its 1px borders — and that overflow was enough
   to give the dialog its own tiny scrollbar.) */
dialog.lapdlg[open] { display: flex; flex-direction: column; }
dialog.lapdlg::backdrop { background: rgba(4, 8, 16, 0.62); backdrop-filter: blur(2px); }
.lapdlg-in { display: flex; flex-direction: column; min-height: 0; }

.lapdlg-head {
  display: flex; align-items: flex-end; gap: 18px;
  padding: 18px 22px 13px; border-bottom: 2px solid var(--crimson);
}
.lapdlg-head .lead { flex: 1; min-width: 0; }
.lapdlg-eyebrow {
  font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--crimson-hi);
}
/* heading register — same treatment as the driver page's own h1 */
.lapdlg-title {
  font-family: var(--display); font-style: italic; font-weight: 800;
  text-transform: uppercase; font-size: 1.6rem; line-height: 1.05; letter-spacing: 0.01em;
  margin: 0; color: var(--white);
}
.lapdlg-title a { color: inherit; text-decoration: none; }
.lapdlg-title a:hover { color: var(--cyan); text-decoration: underline; text-underline-offset: 3px; }
.lapdlg-sub { color: var(--muted); font-size: 0.875rem; margin: 2px 0 0; }
.lapdlg-close {
  flex: none; width: 34px; height: 34px; align-self: flex-start;
  border: 1px solid var(--glass-border); border-radius: 8px; background: transparent;
  color: var(--muted); font-size: 1rem; cursor: pointer;
}
.lapdlg-close:hover { color: var(--white); border-color: var(--crimson); background: rgba(229, 18, 59, 0.12); }

.lapdlg-kpis {
  display: flex; gap: 24px; flex-wrap: wrap;
  padding: 11px 22px; border-bottom: 1px solid var(--glass-border);
}
.lapdlg-kpis .kpi i {
  display: block; font-style: normal; font-family: var(--display); font-weight: 600;
  font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}
.lapdlg-kpis .kpi b { font-size: 1.0625rem; font-weight: 600; }
.lapdlg-kpis .kpi .lap { font-family: var(--font-mono); }
.lapdlg-kpis .kpi .bestink { color: var(--best); }

.lapdlg-body { overflow: auto; min-height: 0; }
.lapdlg-body .table-wrap { border-radius: 0; }
.lapdlg-table { min-width: 720px; font-size: 0.875rem; }
.lapdlg-table td.ln { font-family: var(--display); font-weight: 600; letter-spacing: 0.06em; color: var(--muted); }
.lapdlg-table td.laptot { color: var(--white); }
.lapdlg-table td.wear { color: var(--muted); font-size: 0.8125rem; }
.lapdlg-table td.pitcell { width: 52px; }
.lapdlg-table tbody tr.isbest { background: rgba(199, 125, 255, 0.07); }
.lapdlg-table tbody tr.isbest td:first-child { box-shadow: inset 3px 0 0 var(--best); }
.pitchip {
  display: inline-block; font-family: var(--display); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--warn);
  border: 1px solid rgba(255, 194, 26, 0.45); border-radius: 3px; padding: 0 6px;
}

/* the lap-time chart — cyan series, amber pit marker, purple best-lap callout */
svg.lapchart { display: block; width: 100%; height: auto; padding: 12px 10px 0; }
svg.lapchart .grid { stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
svg.lapchart .tick { fill: var(--faint); font-family: var(--display); font-size: 12px; letter-spacing: 0.06em; }
svg.lapchart .series { fill: none; stroke: var(--cyan); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* bridge = a lap whose time was never recorded (invalidated): the driver kept circulating, so
   the trace continues, dashed and dimmed to read as "no data here" — never a fabricated point.
   Dimmed cyan still clears 3:1 on the dialog surface. The .lapdlg-note caption names it, so the
   dash pattern is never the sole carrier. */
svg.lapchart .series.bridge { stroke-dasharray: 5 4; opacity: 0.7; }
svg.lapchart .pointdot { fill: var(--cyan); }
/* the pit band — a soft amber wash over the laps a stop kept off the trace (§3.15). It marks an
   absence of data, so it recedes: no border, and the amber PIT label carries the meaning. */
svg.lapchart .pitband { fill: rgba(255, 194, 26, 0.09); }
svg.lapchart .pitlab { fill: var(--warn); font-family: var(--display); font-weight: 600; font-size: 12px; letter-spacing: 0.1em; }
/* halo so the two in-plot labels stay readable wherever the trace runs behind them */
svg.lapchart .pitlab { paint-order: stroke; stroke: #0B1526; stroke-width: 3px; stroke-linejoin: round; }
/* the fastest lap is marked, not annotated — its time rides in an SVG <title> for hover */
svg.lapchart .bestdot { fill: var(--best); stroke: #0a1221; stroke-width: 2; }
/* explanatory prose, not a label — Inter per §1.3, never condensed caps */
.lapdlg-note { font-family: var(--body); font-size: 0.8125rem; color: var(--muted); margin: 0; padding: 2px 22px 12px; }

@media (max-width: 640px) {
  .lapdlg-kpis { gap: 14px; }
  .lapdlg-title { font-size: 1.3rem; }
}

/* ============================================================================
   CLICKABLE ROWS — [data-row-href] + .row-go (§3.16)
   The whole row navigates; the .row-go link stays the real control for keyboard
   and screen readers, and is what no-JS users click. Behaviour lives in
   partials/_rowlink.html.twig (one delegated listener, wired into base).
   ========================================================================= */
[data-row-href] { cursor: pointer; }
table.data tbody tr[data-row-href]:hover { background: rgba(34, 195, 255, 0.07); }

/* the end-of-row action: a labelled chevron, not a pill — the row itself is now the
   button, so the control should read as a destination marker rather than compete with it */
.row-go {
  display: inline-flex; align-items: center; gap: 0.3em;
  min-height: 24px; padding: 0 2px;
  font-family: var(--display); font-weight: 600; font-size: 0.8125rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--cyan); text-decoration: none; white-space: nowrap;
}
.row-go span { font-size: 1.15em; line-height: 1; color: var(--faint); }
.row-go:hover { color: var(--white); }
.row-go:hover span, [data-row-href]:hover .row-go span { color: var(--cyan); }
.row-go:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; border-radius: 3px; }
