/*
 * flat.css — the flat-racing cinematic.
 *
 * Loaded after experience.css (the chrome shared with the jumps engine:
 * screen grid, parade, leaderboard, roll call, reveal) and only on the
 * flat page, so its rules refine and override that chrome for flat
 * races: the band pill and subtitle, the starting stalls, the race
 * screen's broadcast chrome (result card, lower-third, Winning Moment),
 * the podium, the intro typography, and the band hooks
 * .page-experience--sprint / --mile / --stayer.
 *
 * The .flat-photo-finish overlay is still in the markup but never shown
 * (the finish is its own sequence now); its base rules keep it hidden.
 */

/* ── Band pill in the intro kicker ──────────────────────────── */
.flat-band-pill {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border: 1px solid currentColor;
}
.flat-band-pill--sprint { color: #ff8a5c; background: rgba(255, 138, 92, 0.12); }
.flat-band-pill--mile   { color: #f5d76e; background: rgba(245, 215, 110, 0.12); }
.flat-band-pill--stayer { color: #7eb8e8; background: rgba(126, 184, 232, 0.12); }

.flat-band-subtitle {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(var(--text-rgb), 0.55);
  margin: -4px 0 18px;
  font-style: italic;
}
.page-experience--sprint .flat-band-subtitle { color: rgba(255, 138, 92, 0.75); }
.page-experience--mile   .flat-band-subtitle { color: rgba(245, 215, 110, 0.75); }
.page-experience--stayer .flat-band-subtitle { color: rgba(126, 184, 232, 0.75); }

/* ── Subtle daylight tint on the flat intro background ──────── */
.page-experience--flat #screen-intro::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 80% 60% at 50% 30%,
              rgba(126, 184, 232, 0.06), transparent 60%);
  z-index: -1;
}

/* ══════════════════════════════════════════════════════════════
   STALLS — gate graphic at race start
   ══════════════════════════════════════════════════════════════
   Two horizontal halves cover the upper + lower track strip; on
   gate-open they translate apart with a flash + "BANG" subtitle.
   The flat.js engine adds .is-opening at t=0 of the race phase
   and .is-hidden once the gates have left the viewport.        */

.flat-stalls {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 8;
  opacity: 1;
  transition: opacity 0.4s ease;
}
.flat-stalls.is-hidden { opacity: 0; pointer-events: none; }

.flat-stalls__top,
.flat-stalls__bottom {
  position: absolute;
  left: 0;
  right: 0;
  height: 50%;
  background: linear-gradient(180deg, #1c2a44 0%, #0f1828 100%);
  border-bottom: 4px solid var(--gold, var(--gold));
  box-shadow:
    inset 0 -2px 0 rgba(var(--gold-rgb), 0.25),
    0 12px 30px rgba(0, 0, 0, 0.6);
  background-image:
    repeating-linear-gradient(
      to right,
      rgba(var(--gold-rgb), 0.10) 0,
      rgba(var(--gold-rgb), 0.10) 2px,
      transparent 2px,
      transparent 56px
    ),
    linear-gradient(180deg, #1c2a44 0%, #0f1828 100%);
  transform: translateY(0);
  transition: transform 0.6s cubic-bezier(0.6, 0, 0.2, 1),
              opacity 0.4s ease 0.2s;
  will-change: transform;
}
.flat-stalls__top {
  top: 0;
  border-bottom: 4px solid var(--gold, var(--gold));
}
.flat-stalls__bottom {
  bottom: 0;
  border-top: 4px solid var(--gold, var(--gold));
  border-bottom: none;
  background-image:
    repeating-linear-gradient(
      to right,
      rgba(var(--gold-rgb), 0.10) 0,
      rgba(var(--gold-rgb), 0.10) 2px,
      transparent 2px,
      transparent 56px
    ),
    linear-gradient(0deg, #1c2a44 0%, #0f1828 100%);
}

.flat-stalls.is-opening .flat-stalls__top    { transform: translateY(-110%); }
.flat-stalls.is-opening .flat-stalls__bottom { transform: translateY(110%);  }

.flat-stalls__bang {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.5);
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(72px, 14vw, 180px);
  font-weight: 900;
  font-style: italic;
  letter-spacing: 0.08em;
  color: var(--gold-lt, var(--gold-lt));
  text-shadow:
    0 0 24px rgba(var(--gold-rgb), 0.85),
    0 0 60px rgba(var(--gold-rgb), 0.45);
  opacity: 0;
  pointer-events: none;
}
.flat-stalls.is-opening .flat-stalls__bang {
  animation: flatStallsBang 0.55s cubic-bezier(0.2, 1.4, 0.3, 1) 0.05s both;
}
@keyframes flatStallsBang {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  35%  { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
  85%  { opacity: 1; transform: translate(-50%, -50%) scale(1.0); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.0); }
}

/* ── The legacy photo-finish overlay ──────────────────────────
   Still in the markup (the production template has it too) but never
   shown: the finish is its own sequence now. */
.flat-photo-finish { display: none; }

/* ── Reduced motion: no stalls bang ── */
@media (prefers-reduced-motion: reduce) {
  .flat-stalls { display: none; }
}

/* ─────────────────────────────────────────────────────────────────
   Reveal-screen podium — three result rows below the winner trophy.
   Was previously bare inline text ("1 Thunder Call 7/2  2 Red Spells
   Danger 9/2 +.5"). Now a proper finish-line card stack.

   Layout per row:
   ┌─────────────────────────────────────────────────────────────┐
   │  🥇  1ST  ▓▓  Thunder Call                          7/2     │
   │  🥈  2ND  ▓▓  Red Spells Danger              ½L     9/2     │
   │  🥉  3RD  ▓▓  Fortification                 1¼L    11/1     │
   └─────────────────────────────────────────────────────────────┘
   ───────────────────────────────────────────────────────────── */
#revealPodium,
.reveal-podium {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 520px;
  margin: 16px auto 0;
}
.reveal-podium__row {
  display: grid;
  /* Six tracks — last two are FIXED minimums so the gap pill column
     reserves space even when empty, keeping the odds column aligned
     across all three rows regardless of whether a distance is shown. */
  grid-template-columns: 28px 40px 30px 1fr 56px 64px;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 16px 10px 12px;
  background: linear-gradient(180deg, rgba(20, 24, 36, 0.86), rgba(var(--ink-rgb), 0.86));
  border: 1px solid rgba(var(--gold-rgb), 0.22);
  border-radius: 10px;
  box-shadow: 0 4px 14px rgba(var(--ink-rgb), 0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  box-sizing: border-box;
}
.reveal-podium__row:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(var(--ink-rgb), 0.42);
}
.reveal-podium__medal {
  font-size: 22px;
  line-height: 1;
  text-align: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
.reveal-podium__pos {
  font-family: "DM Sans", "Inter", sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(var(--paper-rgb), 0.55);
}
.reveal-podium__silk {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 30px;
  /* renderSilkSvg() outputs a 28×32-viewBox SVG (matches the racecard
     atom). Drop-shadow lifts the jersey off the dark card. */
}
.reveal-podium__silk .silk-svg,
.reveal-podium__silk .silk-img {
  width: 100%;
  height: auto;
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}
.reveal-podium__silk .silk-img {
  border-radius: 3px;
}
.reveal-podium__name {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--paper);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.reveal-podium__gap {
  margin-left: 8px;
  font-family: "DM Sans", "Inter", sans-serif;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: rgba(var(--paper-rgb), 0.55);
  padding: 3px 8px;
  background: rgba(var(--paper-rgb), 0.05);
  border: 1px solid rgba(var(--paper-rgb), 0.10);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-width: 0;
  justify-self: stretch;
}
/* Empty placeholder pill on the winner row — keeps grid alignment. */
.reveal-podium__gap.is-empty {
  background: transparent;
  border-color: transparent;
  padding: 0;
}
.reveal-podium__odds {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 17px;
  font-weight: 800;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  min-width: 56px;
  text-align: right;
}

/* ── Medal-position tints ───────────────────────────────────── */
/* Gold winner — stronger border, gold glow, slightly larger row. */
.reveal-podium__row--1 {
  border-color: rgba(var(--gold-rgb), 0.55);
  background:
    radial-gradient(ellipse 80% 60% at 50% 0%, rgba(var(--gold-rgb), 0.12) 0%, transparent 70%),
    linear-gradient(180deg, rgba(28, 24, 14, 0.92), rgba(14, 12, 7, 0.92));
  box-shadow:
    0 1px 0 rgba(var(--gold-rgb), 0.18) inset,
    0 8px 22px rgba(var(--ink-rgb), 0.42),
    0 0 0 1px rgba(var(--gold-rgb), 0.10);
}
.reveal-podium__row--1 .reveal-podium__pos  { color: var(--gold); }
.reveal-podium__row--1 .reveal-podium__name { font-size: 20px; }
.reveal-podium__row--1 .reveal-podium__odds {
  color: var(--gold-lt);
  text-shadow: 0 0 12px rgba(var(--gold-rgb), 0.5);
}

/* Silver — cooler tint. */
.reveal-podium__row--2 {
  border-color: rgba(192, 192, 192, 0.32);
}
.reveal-podium__row--2 .reveal-podium__pos  { color: var(--rank-silver); }
.reveal-podium__row--2 .reveal-podium__odds { color: var(--rank-silver); }

/* Bronze — warmer copper tint. */
.reveal-podium__row--3 {
  border-color: rgba(205, 127, 50, 0.32);
}
.reveal-podium__row--3 .reveal-podium__pos  { color: var(--rank-bronze); }
.reveal-podium__row--3 .reveal-podium__odds { color: var(--rank-bronze); }

/* ── Mobile ────────────────────────────────────────────────── */
@media (max-width: 640px) {
  #revealPodium, .reveal-podium { max-width: 92vw; }
  .reveal-podium__row {
    grid-template-columns: 22px 34px 24px 1fr 44px 52px;
    gap: 8px;
    padding: 8px 12px 8px 10px;
  }
  .reveal-podium__medal { font-size: 18px; }
  .reveal-podium__pos   { font-size: 9px; }
  .reveal-podium__silk  { width: 22px; height: 26px; }
  .reveal-podium__name  { font-size: 15px; }
  .reveal-podium__row--1 .reveal-podium__name { font-size: 16px; }
  .reveal-podium__gap   { font-size: 10.5px; padding: 2px 6px; }
  .reveal-podium__odds  { font-size: 14px; }
}

/* ═══════════════════════════════════════════════════════════════
   CINEMATIC REPLAY V2 — broadcast chrome
   ═══════════════════════════════════════════════════════════════
   Everything below belongs to the redesigned race screen. The two
   elements are injected by js/flat.js at runtime rather than declared
   in the markup, so nothing here needs a change to the Django template
   (ARCHITECTURE.md §10, option 1).
   ─────────────────────────────────────────────────────────────── */

/* ── Broadcast identification ───────────────────────────────────
   Replaces the floating name chips that used to hang over every
   podium runner. One runner, named for ~2.6s, bottom-left, the way a
   director cuts to a name super. Opacity and x are owned by GSAP —
   no transition here, or the two fight each other. */
.bcast-id {
  position: absolute;
  left: clamp(16px, 3vw, 40px);
  bottom: clamp(96px, 14vh, 150px);
  z-index: 11;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 8px 10px;
  max-width: min(420px, 76vw);
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(var(--dark-rgb),0.94), rgba(var(--dark-rgb),0.72));
  border-left: 3px solid var(--gold, var(--gold));
  border-radius: 2px 6px 6px 2px;
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 28px rgba(0,0,0,0.45);
}

.bcast-id__silk {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  display: block;
}
.bcast-id__silk svg { width: 100%; height: 100%; display: block; }

.bcast-id__body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.bcast-id__name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(15px, 1.5vw, 19px);
  font-weight: 700;
  color: var(--paper);
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bcast-id__meta {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(var(--text-rgb),0.5);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bcast-id__tag {
  flex: 0 0 auto;
  margin-left: 6px;
  padding: 3px 8px;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.16em;
  color: var(--ink);
  background: var(--gold, var(--gold));
}

/* ── Result card ────────────────────────────────────────────────
   Shown after the pause that follows the line, not on it. DOM rather
   than canvas text so it stays sharp at any pixel ratio and reflows
   on a phone without a font-size lookup table. */
.race-result {
  position: absolute;
  left: 50%;
  /* High in the frame on purpose: the finish shot now has eight or nine
     horses running through the middle of it, and a card centred at 46%
     sat straight on top of them. */
  top: 27%;
  transform: translate(-50%, -50%);
  z-index: 12;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 34px 78px 40px;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  /* The fade has to finish inside the box, otherwise the corners are
     still ~50% opaque and the card reads as a rectangle sitting on the
     turf instead of a pool of shade under the headline. */
  background: radial-gradient(ellipse 62% 88% at 50% 50%,
              rgba(var(--dark-rgb),0.88) 0%, rgba(var(--dark-rgb),0.55) 48%,
              rgba(var(--dark-rgb),0) 82%);
}

.race-result__eyebrow {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--gold, var(--gold));
  padding: 5px 14px;
  border: 1px solid rgba(var(--gold-rgb),0.45);
  border-radius: 999px;
}

.race-result__name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(28px, 5vw, 58px);
  font-weight: 900;
  line-height: 1.05;
  color: var(--paper);
  text-shadow: 0 0 40px rgba(var(--gold-rgb),0.35), 0 4px 24px rgba(0,0,0,0.8);
}

.race-result__margin {
  font-family: 'Iowan Old Style', Charter, Georgia, serif;
  font-style: italic;
  font-size: clamp(14px, 1.8vw, 22px);
  color: rgba(var(--paper-rgb),0.72);
}

.race-result--photo .race-result__eyebrow {
  color: var(--paper);
  background: rgba(var(--gold-rgb),0.9);
  border-color: transparent;
}

/* ── Live Positions: motion is GSAP's job now ───────────────────
   V1 let a CSS transition chase a transform that JS rewrote every
   frame. V2 tweens each row only when its rank actually changes, so
   the CSS transition on transform has to go or the two compete and
   every move lands late. Opacity keeps its transition — nothing
   animates that from JS on a per-frame basis. */
.race-lb-row {
  transition: opacity 0.35s ease, background-color 0.35s ease;
}

/* A row that has just gained or lost places carries a direction class
   for ~0.65s. Restrained on purpose: a tinted edge, not a flash. */
.race-lb-row.is-climbing { background: linear-gradient(90deg, rgba(var(--gold-rgb),0.16), transparent 62%); }
.race-lb-row.is-falling  { background: linear-gradient(90deg, rgba(120,140,170,0.14), transparent 62%); }

/* ── Race screen phase states ───────────────────────────────────
   js/flat.js stamps data-race-phase on #screen-race as the director
   moves through Cruise → Build → Drive → Line. Used sparingly: the
   camera does the work, the chrome just gets out of the way. */
#screen-race[data-race-phase="drive"] .race-leaderboard,
#screen-race[data-race-phase="line"]  .race-leaderboard {
  opacity: 0.82;
}
#screen-race[data-race-phase="line"] .race-phase-strip {
  opacity: 0.35;
}
.race-leaderboard,
.race-phase-strip {
  transition: opacity 0.6s ease;
}

/* The final furlong dims the surrounding UI so the frame belongs to
   the race. */
#screen-race.is-final-furlong .race-commentary {
  background: linear-gradient(to top, rgba(var(--dark-rgb),0.99) 0%, rgba(var(--dark-rgb),0.55) 65%, transparent 100%);
}

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 768px) {
  /* On a phone the centred phase title and strip run straight into the
     Live Positions panel. Stack the race chrome down the left edge and
     leave the right-hand side to the leaderboard. */
  .race-phase-title {
    left: 10px;
    top: 10px;
    transform: none;
    text-align: left;
    max-width: calc(100vw - 170px);
  }
  .race-phase-strip {
    left: 10px;
    top: 54px;
    transform: none;
  }

  /* The Live Positions rows are 30px tall on a phone but the name plus
     the probability bar needs more than that, so the bar overflows into
     the row below and the whole panel reads as double-exposed. The bar
     is the least useful thing on a 375px screen — drop it and let the
     name and position have the row. */
  .race-lb-prob { display: none; }
  .race-lb-name-prob { justify-content: center; }

  .bcast-id {
    left: 10px;
    bottom: clamp(120px, 20vh, 190px);
    padding: 6px 10px 6px 8px;
    gap: 8px;
    max-width: calc(100vw - 20px);
  }
  .bcast-id__silk { width: 18px; height: 18px; }
  .bcast-id__tag  { font-size: 8px; letter-spacing: 0.12em; padding: 2px 6px; }
  .race-result    { padding: 16px 20px 20px; width: min(92vw, 520px); top: 24%; }
}

@media (max-width: 480px) {
  /* On a phone the lower-third and the commentary line are competing
     for the same band of screen. The tag is the first thing to go. */
  .bcast-id__tag { display: none; }
}

/* ── Reduced motion ─────────────────────────────────────────────
   The engine already routes prefers-reduced-motion straight to the
   static reveal and zeroes camera shake, parallax foreground and dust
   at source. These rules cover the DOM chrome so that anything that
   does render holds still. */
@media (prefers-reduced-motion: reduce) {
  .bcast-id,
  .race-result,
  .race-leaderboard,
  .race-phase-strip,
  .race-lb-row {
    transition: none !important;
    backdrop-filter: none;
  }
  .race-lb-row.is-climbing,
  .race-lb-row.is-falling { background: none; }
}

/* The race screen has to be transparent so the parallax backdrop drawn
   on #particleCanvas (which sits below it in the stacking order) shows
   through. In V1 the whole world was painted onto #raceCanvas over an
   opaque screen, so the second canvas was invisible and effectively
   dead weight; V2 gives it the sky and the far planes. */
#screen-race { background: transparent; }

/* ── Intro runner chips carry silks ──────────────────────────────
   The chip is now a cap plus a name rather than a text pill, so the
   intro reads as a racecard and the viewer meets the colours before
   the race rather than during it. */
.intro-runner-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.intro-runner-chip__silk {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  display: block;
}
.intro-runner-chip__silk svg { width: 100%; height: 100%; display: block; }
.intro-runner-chip__name { display: block; }

@media (max-width: 640px) {
  .intro-runner-chip__silk { width: 12px; height: 12px; }
}

/* ── Reveal confetti ─────────────────────────────────────────────
   Built from DOM nodes by spawnRevealConfetti() in flat.js, because the
   reveal screen sits above both canvases. pointer-events off so it can
   never swallow a click on the action buttons underneath it. */
.reveal-confetti {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 3;
}
.reveal-confetti i {
  position: absolute;
  top: 0;
  display: block;
  border-radius: 1px;
  will-change: transform, opacity;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-confetti { display: none; }
}

/* ── The Winning Moment ──────────────────────────────────────────
   Card and behaviour follow the V16.1 delivery (saturday_cinematic_v2):
   a dark, gold-edged card at the top of the hero shot, eyebrow in DM
   Sans, the winner's name in Playfair Display 900 capitals, then
   WINNER · odds · margin. Built by showWinnerMomentCard() in flat.js;
   opacity and position are GSAP's. */
.win-moment {
  position: absolute;
  left: 50%;
  top: 7%;
  transform: translateX(-50%);
  z-index: 12;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: min(520px, 72vw);
  padding: 16px 22px 18px;
  opacity: 0;
  pointer-events: none;
  text-align: center;
  background: rgba(7,10,15,.84);
  border: 1.4px solid var(--gold, var(--gold));
  border-radius: 10px;
  box-shadow: 0 18px 50px rgba(0,0,0,.45);
}
.win-moment__eyebrow {
  font-family: 'DM Sans', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  white-space: pre;
  color: var(--gold, var(--gold));
}
.win-moment__name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 40px;
  font-weight: 900;
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--paper);
  text-shadow: 0 2px 18px rgba(0,0,0,.5);
}
.win-moment__meta {
  font-family: 'DM Sans', sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  white-space: pre;
  color: rgba(var(--paper-rgb),.72);
}
@media (max-width: 650px) {
  .win-moment { width: 88vw; padding: 13px 14px 14px; }
  .win-moment__name { font-size: 30px; }
  .win-moment__eyebrow, .win-moment__meta { font-size: 10px; white-space: normal; }
}

/* The race chrome steps out of the hero shot. */
#screen-race .race-leaderboard,
#screen-race .race-phase-strip,
#screen-race .race-phase-title,
#screen-race .race-skip-wrap { transition: opacity .4s ease; }
#screen-race.is-winning-moment .race-leaderboard,
#screen-race.is-winning-moment .race-phase-strip,
#screen-race.is-winning-moment .race-phase-title,
#screen-race.is-winning-moment .race-skip-wrap,
#screen-race.is-winning-moment .bcast-id {
  opacity: 0 !important;
  pointer-events: none;
}

/* ── Intro typography ───────────────────────────────────────────
   The first page's type, matched to the V16.1 delivery: a smaller,
   balanced title with the lighter italic "The Virtual", a tighter
   coral kicker, the band subtitle in Playfair Display italic, and
   smaller, more tracked meta, chips, button and caption. Type only —
   the layout is ours. Scoped to #screen-intro so nothing else moves. */
.page-experience--flat #screen-intro .intro-kicker {
  font-size: 9px;
  letter-spacing: .34em;
  color: #db654f;
}
.page-experience--flat #screen-intro .flat-band-pill { font-size: 9px; }
.page-experience--flat #screen-intro .intro-title {
  font-size: clamp(42px, 5.75vw, 82px);
  line-height: .94;
  max-width: 1160px;
  text-wrap: balance;
}
.page-experience--flat #screen-intro .intro-title__line1 {
  font-size: .52em;
  line-height: 1;
  margin-bottom: 6px;
  color: rgba(var(--text-rgb),.92);
}
.page-experience--flat #screen-intro .intro-title__line2 {
  filter: drop-shadow(0 0 26px rgba(var(--gold-rgb),.22));
}
.page-experience--flat #screen-intro .intro-meta {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .1em;
  color: var(--text);
}
.page-experience--flat #screen-intro .intro-meta__sep { color: rgba(var(--text-rgb),.38); }
.page-experience--flat #screen-intro .flat-band-subtitle {
  color: rgba(var(--text-rgb),.58) !important;
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(12px, 1vw, 15px);
  font-weight: 700;
  letter-spacing: .02em;
}
.page-experience--flat #screen-intro .intro-runner-chip { font-size: 10px; }
.page-experience--flat #screen-intro .intro-btn {
  font-size: 12px;
  letter-spacing: .19em;
}
/* The caption under the button carries an inline style in the markup. */
.page-experience--flat #screen-intro #flatStartBtn + p {
  font-size: 9px !important;
  letter-spacing: .1em !important;
  color: rgba(var(--text-rgb),.26) !important;
}
@media (max-height: 820px) and (min-width: 769px) {
  .page-experience--flat #screen-intro .intro-title { font-size: clamp(38px, 5vw, 70px); }
}
@media (max-width: 768px) {
  .page-experience--flat #screen-intro .intro-title { font-size: clamp(38px, 12vw, 58px); }
  .page-experience--flat #screen-intro .intro-title__line1 { font-size: .48em; }
}

/* ══════════════════════════════════════════════════════════════
   THE FINISH — the winner's poster
   Replaces the trophy. The winner is still on the race canvas
   behind this screen (HERO.poster), so the screen itself is a
   transparent overlay: a masthead, an empty left column the horse
   shows through, an editorial column, and the podium along the
   bottom. Nothing here paints an opaque background, or the horse
   it is built around would be hidden by it.
   ══════════════════════════════════════════════════════════════ */
#screen-reveal {
  background: none;
  padding: 0;
  justify-content: stretch;
}

.winner-poster {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(14px, 2.2vh, 26px) clamp(18px, 4vw, 64px) clamp(12px, 2vh, 22px);
  box-sizing: border-box;
  pointer-events: none;   /* the buttons switch it back on */
}

.winner-poster__masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(var(--text-rgb), 0.5);
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.18);
  padding-bottom: 10px;
}

.winner-poster__brand { display: inline-flex; align-items: center; gap: 10px; }

.winner-poster__mark {
  display: inline-grid;
  place-items: center;
  width: 22px; height: 22px;
  border: 1px solid rgba(var(--gold-rgb), 0.5);
  border-radius: 50%;
  color: var(--gold);
  font-size: 9px;
  letter-spacing: 0.04em;
}

.winner-poster__finish { color: var(--gold); }

/* The horse owns the left; the story owns the right. */
.winner-poster__main {
  display: grid;
  grid-template-columns: 1fr minmax(320px, 42%);
  align-items: center;
  gap: clamp(16px, 3vw, 48px);
  min-height: 0;
  overflow: hidden;
}

.winner-poster__visual { min-height: 0; }

.winner-poster__story {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(6px, 0.9vh, 12px);
}

.winner-poster__story .reveal-kicker {
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0;
}

.winner-poster__rule {
  width: 74px; height: 2px;
  background: linear-gradient(90deg, var(--gold), rgba(var(--gold-rgb), 0));
}

.winner-poster__story .reveal-horse-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 900;
  font-size: clamp(34px, 5.4vw, 78px);
  line-height: 0.98;
  letter-spacing: -0.015em;
  color: var(--paper);
  margin: 0;
  text-shadow: 0 6px 40px rgba(0, 0, 0, 0.55);
}

.winner-poster__winnerline {
  display: flex;
  align-items: center;
  gap: 12px;
}

.winner-poster__badge {
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--gold);
  border-radius: 999px;
  padding: 5px 12px;
}

.winner-poster__winnerline .reveal-horse-odds {
  font-family: 'Playfair Display', Georgia, serif;
  font-weight: 700;
  font-size: clamp(20px, 2.4vw, 34px);
  color: var(--gold);
}

/* The silk belongs to the podium row, where all three are shown together
   and it means something. In the story column it was a second identity
   for the same horse — and .reveal-silk--jersey sizes it for a trophy
   plinth, which blew the column past its grid row and pushed the margin
   and the verdict down onto the podium. Kept in the DOM: the engine
   writes the winner's silk into it either way. */
.winner-poster__winnerline .reveal-horse-silk { display: none; }

/* .reveal-horse-odds ships at opacity 0 (experience.css) because the
   trophy's timeline faded it up by id. The poster fades the whole line
   instead, so the odds must start visible within it. */
.winner-poster__winnerline .reveal-horse-odds { opacity: 1; }

.winner-poster__margin {
  font-family: 'Playfair Display', Georgia, serif;
  font-style: italic;
  font-size: clamp(15px, 1.7vw, 22px);
  color: rgba(var(--text-rgb), 0.9);
}

.winner-poster__race {
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(var(--text-rgb), 0.52);
}

.winner-poster__connections {
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 12px;
  color: rgba(var(--text-rgb), 0.86);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
}
.winner-poster__connections span {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--gold);
  margin-right: 4px;
}
.winner-poster__connections b { color: rgba(var(--gold-rgb), 0.5); font-weight: 400; }

/* The podium runs along the foot of the poster. */
.winner-poster__lower {
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: auto;
}

.winner-poster__podium-label {
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(var(--text-rgb), 0.42);
}

.winner-poster .reveal-verdict-box { pointer-events: auto; }
.winner-poster .reveal-actions { pointer-events: auto; }

@media (max-width: 900px) {
  /* No room for two columns: the horse sits above the story, which is
     why the hero keeps its centred x on a narrow viewport. */
  .winner-poster__main { grid-template-columns: 1fr; align-items: end; }
  .winner-poster__visual { display: none; }
  .winner-poster__story { align-items: center; text-align: center; }
  .winner-poster__rule { align-self: center; }
}

/* The poster's own surface: above the ambient backdrop, below the screens,
   and never in the way of a click. Created by the engine, so it is not in
   the markup — see ensurePosterCanvas(). */
#posterCanvas {
  position: fixed;
  top: calc(var(--nav-h, 60px) + var(--banner-h, 0px));
  left: 0; right: 0; bottom: 0;
  z-index: 6;
  pointer-events: none;
}

/* The winner is drawn on #posterCanvas in full daylight — the same
   racecourse the race was run on. A poster wants a plate, not a
   photograph, so the screen lays a scrim over it: darkest under the
   story column on the right, so the type reads, and lightest over the
   horse on the left, so he does not. */
#screen-reveal::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(var(--dark-rgb), 0.30) 0%,
      rgba(var(--dark-rgb), 0.42) 34%,
      rgba(var(--dark-rgb), 0.86) 62%,
      rgba(var(--dark-rgb), 0.94) 100%),
    linear-gradient(180deg,
      rgba(var(--dark-rgb), 0.72) 0%,
      rgba(var(--dark-rgb), 0.10) 32%,
      rgba(var(--dark-rgb), 0.55) 78%,
      rgba(var(--dark-rgb), 0.95) 100%);
}

/* The story inherits margins from the centred layout the trophy used.
   In a column with its own gap they read as holes. */
.winner-poster__story > * { margin: 0; }

.winner-poster__story {
  justify-content: center;
  max-height: 100%;
}

/* The podium bar earns a plate of its own: it sits over the turf, and
   the horse runs behind it. */
.winner-poster__lower {
  background: linear-gradient(180deg,
    rgba(var(--dark-rgb), 0) 0%,
    rgba(var(--dark-rgb), 0.82) 26%,
    rgba(var(--dark-rgb), 0.96) 100%);
  padding-top: 18px;
  margin: 0 calc(clamp(18px, 4vw, 64px) * -1) calc(clamp(12px, 2vh, 22px) * -1);
  padding-left: clamp(18px, 4vw, 64px);
  padding-right: clamp(18px, 4vw, 64px);
  padding-bottom: clamp(12px, 2vh, 22px);
}
