/* Dunder Race — token system in the homes-site style (oklch, layered, light + dark),
   restyled as a paper company: paper white, manila, corporate blue, Dundie gold. */

@layer reset, tokens, base, components, utilities;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; }
  body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
  h1, h2, h3, p { margin: 0; }
  button, input, textarea, select { font: inherit; color: inherit; }
  button { cursor: pointer; }
  canvas { display: block; }
  img, svg { max-width: 100%; display: block; }
  table { border-collapse: collapse; }
  [hidden] { display: none !important; }
}

@layer tokens {
  :root {
    color-scheme: light dark;

    /* Hues */
    --hue-paper: 85;
    --hue-manila: 78;
    --hue-corp: 250;
    --hue-gold: 82;
    --hue-red: 25;
    --hue-green: 150;

    /* Light: a sheet of paper on a manila folder */
    --bg: oklch(98.5% 0.006 var(--hue-paper));
    --bg-2: oklch(95.5% 0.012 var(--hue-manila));
    --manila: oklch(90% 0.06 var(--hue-manila));
    --manila-2: oklch(84% 0.08 var(--hue-manila));
    --surface: oklch(100% 0 0);
    --surface-2: oklch(96.5% 0.008 var(--hue-paper));
    --ink: oklch(22% 0.02 var(--hue-corp));
    --ink-2: oklch(42% 0.025 var(--hue-corp));
    /* Secondary text tier: ranks, gaps, table headers, all around 12 px. 60% measured 3.9:1 and
       50% measures 5:1 against the HUD's translucent surface, which has the course showing through. */
    --ink-3: oklch(50% 0.02 var(--hue-corp));
    --line: oklch(86% 0.012 var(--hue-manila));
    --line-2: oklch(76% 0.02 var(--hue-manila));

    --accent: oklch(48% 0.16 var(--hue-corp));
    --accent-2: oklch(40% 0.15 var(--hue-corp));
    --accent-soft: oklch(93% 0.04 var(--hue-corp));
    --on-accent: oklch(99% 0 0);

    --gold: oklch(76% 0.15 var(--hue-gold));
    --gold-2: oklch(66% 0.15 var(--hue-gold));
    --gold-soft: oklch(94% 0.07 var(--hue-gold));
    --on-gold: oklch(25% 0.05 var(--hue-gold));

    --danger: oklch(55% 0.19 var(--hue-red));
    --danger-soft: oklch(94% 0.05 var(--hue-red));
    --ok: oklch(52% 0.14 var(--hue-green));
    --ok-soft: oklch(94% 0.05 var(--hue-green));
    --warn: oklch(72% 0.15 65);
    --warn-soft: oklch(95% 0.06 65);

    --sky-top: oklch(88% 0.05 235);
    --sky-bottom: oklch(96% 0.02 85);

    --shadow: 0 1px 2px oklch(20% 0.02 var(--hue-corp) / 0.08), 0 6px 20px oklch(20% 0.02 var(--hue-corp) / 0.10);
    --shadow-lg: 0 2px 4px oklch(20% 0.02 var(--hue-corp) / 0.10), 0 20px 50px oklch(20% 0.02 var(--hue-corp) / 0.18);
    --pill-shadow: 0 1px 0 oklch(0% 0 0 / 0.25);

    --font: "Helvetica Neue", Helvetica, Arial, "Liberation Sans", system-ui, sans-serif;
    --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    --font-display: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;

    --text-xs: 0.75rem;
    --text-sm: 0.875rem;
    --text-md: 1rem;
    --text-lg: 1.25rem;
    --text-xl: clamp(1.6rem, 1.2rem + 2vw, 2.5rem);
    --text-2xl: clamp(2.2rem, 1.5rem + 4vw, 4.5rem);

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-8: 3rem;

    --radius-sm: 4px;
    --radius: 8px;
    --radius-lg: 14px;
    --radius-pill: 999px;

    --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
    --dur: 180ms;
    --dur-slow: 400ms;

    /* The minimap's band at the top of the stage; the lobby keeps its card clear of it. */
    --hud-minimap-h: 22px;

    --z-canvas: 0;
    --z-masthead: 5;
    --z-layer: 10;
    --z-overlay: 20;
    --z-board: 30;
    --z-panel: 40;
  }

  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      --bg: oklch(18% 0.015 var(--hue-corp));
      --bg-2: oklch(22% 0.018 var(--hue-corp));
      --manila: oklch(32% 0.05 var(--hue-manila));
      --manila-2: oklch(38% 0.06 var(--hue-manila));
      --surface: oklch(24% 0.018 var(--hue-corp));
      --surface-2: oklch(28% 0.02 var(--hue-corp));
      --ink: oklch(95% 0.008 var(--hue-paper));
      --ink-2: oklch(78% 0.015 var(--hue-paper));
      --ink-3: oklch(68% 0.015 var(--hue-paper));
      --line: oklch(32% 0.02 var(--hue-corp));
      --line-2: oklch(42% 0.025 var(--hue-corp));

      --accent: oklch(72% 0.14 var(--hue-corp));
      --accent-2: oklch(80% 0.12 var(--hue-corp));
      --accent-soft: oklch(30% 0.06 var(--hue-corp));
      --on-accent: oklch(15% 0.03 var(--hue-corp));

      --gold: oklch(80% 0.15 var(--hue-gold));
      --gold-2: oklch(72% 0.15 var(--hue-gold));
      --gold-soft: oklch(32% 0.07 var(--hue-gold));
      --on-gold: oklch(18% 0.05 var(--hue-gold));

      --danger: oklch(70% 0.17 var(--hue-red));
      --danger-soft: oklch(30% 0.07 var(--hue-red));
      --ok: oklch(72% 0.14 var(--hue-green));
      --ok-soft: oklch(28% 0.06 var(--hue-green));
      --warn: oklch(78% 0.14 65);
      --warn-soft: oklch(32% 0.07 65);

      --sky-top: oklch(30% 0.06 250);
      --sky-bottom: oklch(45% 0.08 40);

      --shadow: 0 1px 2px oklch(0% 0 0 / 0.4), 0 6px 20px oklch(0% 0 0 / 0.4);
      --shadow-lg: 0 2px 4px oklch(0% 0 0 / 0.5), 0 20px 50px oklch(0% 0 0 / 0.6);
    }
  }

  :root[data-theme="dark"] {
    --bg: oklch(18% 0.015 var(--hue-corp));
    --bg-2: oklch(22% 0.018 var(--hue-corp));
    --manila: oklch(32% 0.05 var(--hue-manila));
    --manila-2: oklch(38% 0.06 var(--hue-manila));
    --surface: oklch(24% 0.018 var(--hue-corp));
    --surface-2: oklch(28% 0.02 var(--hue-corp));
    --ink: oklch(95% 0.008 var(--hue-paper));
    --ink-2: oklch(78% 0.015 var(--hue-paper));
    --ink-3: oklch(68% 0.015 var(--hue-paper));
    --line: oklch(32% 0.02 var(--hue-corp));
    --line-2: oklch(42% 0.025 var(--hue-corp));

    --accent: oklch(72% 0.14 var(--hue-corp));
    --accent-2: oklch(80% 0.12 var(--hue-corp));
    --accent-soft: oklch(30% 0.06 var(--hue-corp));
    --on-accent: oklch(15% 0.03 var(--hue-corp));

    --gold: oklch(80% 0.15 var(--hue-gold));
    --gold-2: oklch(72% 0.15 var(--hue-gold));
    --gold-soft: oklch(32% 0.07 var(--hue-gold));
    --on-gold: oklch(18% 0.05 var(--hue-gold));

    --danger: oklch(70% 0.17 var(--hue-red));
    --danger-soft: oklch(30% 0.07 var(--hue-red));
    --ok: oklch(72% 0.14 var(--hue-green));
    --ok-soft: oklch(28% 0.06 var(--hue-green));
    --warn: oklch(78% 0.14 65);
    --warn-soft: oklch(32% 0.07 65);

    --sky-top: oklch(30% 0.06 250);
    --sky-bottom: oklch(45% 0.08 40);

    --shadow: 0 1px 2px oklch(0% 0 0 / 0.4), 0 6px 20px oklch(0% 0 0 / 0.4);
    --shadow-lg: 0 2px 4px oklch(0% 0 0 / 0.5), 0 20px 50px oklch(0% 0 0 / 0.6);
  }
}

@layer base {
  html {
    font-family: var(--font);
    font-size: 16px;
    line-height: 1.4;
    color: var(--ink);
    background: var(--bg);
    height: 100%;
  }

  body {
    height: 100%;
    min-height: 100dvh;
    overflow: hidden;
    background: var(--bg);
    color: var(--ink);
  }

  body.gallery-page {
    overflow: auto;
    padding: var(--space-5);
  }

  a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
  a:hover { color: var(--accent-2); }

  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
    }
  }
}

@layer components {
  /* Stage: the canvas fills the viewport; every root is layered over it. */
  .stage {
    position: relative;
    width: 100vw;
    width: 100dvw;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    background: linear-gradient(var(--sky-top), var(--sky-bottom));
  }

  .course {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: var(--z-canvas);
  }

  .layer {
    position: absolute;
    inset: 0;
    z-index: var(--z-layer);
    pointer-events: none;
  }
  .layer > * { pointer-events: auto; }

  .overlay { z-index: var(--z-overlay); }

  .masthead {
    position: absolute;
    top: var(--space-4);
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-masthead);
    text-align: center;
    max-width: min(90vw, 44rem);
    padding: var(--space-3) var(--space-5);
    background: color-mix(in oklch, var(--surface) 88%, transparent);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    pointer-events: none;
  }
  .wordmark {
    font-family: var(--font-display);
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-size: var(--text-xs);
    color: var(--accent);
  }
  .wordmark-sub {
    display: block;
    font-weight: 500;
    letter-spacing: 0.12em;
    color: var(--ink-3);
    font-size: 0.65rem;
  }
  .title {
    font-family: var(--font-display);
    font-weight: 900;
    font-size: var(--text-xl);
    letter-spacing: -0.02em;
    line-height: 1.05;
    margin-top: var(--space-1);
  }
  .race-name {
    font-size: var(--text-xs);
    color: var(--ink-2);
    margin-top: var(--space-1);
    text-wrap: balance;
  }
  body[data-state="racing"] .masthead,
  body[data-state="finished"] .masthead { display: none; }
  /* Scheduled: the start line runs up the middle of the stage, so the masthead and the countdown
     card stack down the left instead of sitting on top of the field. */
  body[data-state="lobby"] .masthead {
    top: calc(var(--space-3) * 2 + 1.6rem);
    left: var(--space-3);
    transform: none;
    text-align: left;
    max-width: min(46vw, 22rem);
    padding: var(--space-3) var(--space-4);
  }
  body[data-state="lobby"] .title { font-size: var(--text-lg); }
  /* The countdown card underneath carries the full race name; once is enough. */
  body[data-state="lobby"] .race-name { display: none; }

  .stage-footer {
    position: absolute;
    right: var(--space-4);
    bottom: var(--space-3);
    z-index: var(--z-overlay);
  }

  /* Draft board: full-screen sheet over the stage */
  .draftboard {
    z-index: var(--z-board);
    pointer-events: auto;
    overflow: auto;
    background: var(--bg-2);
  }

  /* Commissioner: a manila folder that slides over whatever is showing */
  .commissioner {
    z-index: var(--z-panel);
    pointer-events: auto;
    left: auto;
    width: min(100%, 34rem);
    background: var(--manila);
    border-left: 1px solid var(--manila-2);
    box-shadow: var(--shadow-lg);
    overflow: auto;
    padding: var(--space-5);
  }

  .button {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0.55em 1.1em;
    border-radius: var(--radius);
    border: 1px solid transparent;
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
    transition: background var(--dur) var(--ease), transform var(--dur) var(--ease);
  }
  .button:hover { background: var(--accent-2); }
  .button:active { transform: translateY(1px); }
  .button:disabled { opacity: 0.5; cursor: not-allowed; }
  .button.secondary { background: var(--surface); color: var(--ink); border-color: var(--line-2); }
  .button.secondary:hover { background: var(--surface-2); }
  .button.gold { background: var(--gold); color: var(--on-gold); }
  .button.gold:hover { background: var(--gold-2); }
  .button.danger { background: var(--danger); color: var(--on-accent); }

  .link-button {
    background: none;
    border: 0;
    padding: var(--space-1) var(--space-2);
    color: var(--ink-3);
    font-size: var(--text-sm);
    text-decoration: underline;
    text-underline-offset: 2px;
  }
  .link-button:hover { color: var(--accent); }

  .card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow);
    padding: var(--space-4) var(--space-5);
  }

  .pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.2em 0.7em;
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: 600;
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--ink-2);
  }
  .pill.ok { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
  .pill.warn { background: var(--warn-soft); color: var(--on-gold); border-color: transparent; }
  .pill.danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
  .pill.gold { background: var(--gold-soft); color: var(--on-gold); border-color: transparent; }

  .input, textarea.input {
    width: 100%;
    padding: 0.55em 0.75em;
    border-radius: var(--radius);
    border: 1px solid var(--line-2);
    background: var(--surface);
    color: var(--ink);
  }
  .input:focus-visible { outline-offset: 0; border-color: var(--accent); }

  .noscript {
    position: fixed;
    inset: auto 0 0 0;
    padding: var(--space-4);
    background: var(--danger-soft);
    color: var(--danger);
    text-align: center;
  }

  .gallery { color: var(--ink-2); }
}

@layer utilities {
  .sr-only {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0);
    white-space: nowrap; border: 0;
  }
  .mono { font-family: var(--font-mono); }
  .muted { color: var(--ink-3); }
  .gold-text { color: var(--gold-2); }
  .stack > * + * { margin-top: var(--space-3); }
  .row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
}

/* ui */

@layer components {
  /* ---------- shared bits: runner accents, history list ---------- */
  .roster-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; }
  .roster-chip {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: 0.2em 0.7em 0.2em 0.25em;
    border-radius: var(--radius-pill);
    background: var(--surface);
    border: 1px solid var(--line);
    font-size: var(--text-sm);
    max-width: 100%;
  }
  .roster-swatch {
    display: inline-grid; place-items: center;
    width: 1.6em; height: 1.6em; border-radius: 50%;
    background: var(--accent-runner, var(--accent));
    color: #fff; font-weight: 700; font-size: 0.8em;
    text-shadow: var(--pill-shadow);
    flex: none;
  }
  .roster-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .roster-team { font-size: var(--text-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .history-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
  .history-title { font-size: var(--text-md); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-2); }
  /* The confirm row is wider than the plain button, so the wrapper hangs to the right of the title
     on a phone as well and the list below never shifts. */
  .history-clear-wrap { margin-left: auto; text-align: right; }
  .history-clear { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; font-size: var(--text-sm); }
  .history-clear-ask { font-weight: 600; }
  .history-clear .button { padding: 0.35em 0.8em; font-size: var(--text-sm); }
  .history-clear-note { margin-top: var(--space-1); font-size: var(--text-xs); color: var(--danger); max-width: 28rem; }
  .history-list { list-style: none; margin: var(--space-3) 0 0; padding: 0; }
  .history-item { padding: var(--space-2) 0; border-top: 1px solid var(--line); display: grid; gap: var(--space-1); }
  .history-item:first-child { border-top: 0; }
  .history-line { font-weight: 600; }
  .history-seed { font-size: var(--text-xs); }
  .history-picks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); font-size: var(--text-xs); color: var(--ink-2); }
  .history-picks b { color: var(--accent); }

  /* ---------- lobby ---------- */
  .lobby {
    display: flex; flex-direction: column; align-items: center; gap: var(--space-4);
    padding: clamp(9rem, 26vh, 13rem) var(--space-4) var(--space-8);
    overflow-y: auto;
  }
  .lobby-card { width: min(92vw, 42rem); text-align: center; transition: opacity var(--dur) var(--ease) 400ms; }
  body[data-state="lobby"] .lobby {
    align-items: flex-start;
    justify-content: flex-start;
    padding: calc(var(--space-3) * 2 + 1.6rem + 11.5rem) var(--space-3) var(--space-6);
  }
  body[data-state="lobby"] .lobby-card { width: min(46vw, 22rem); text-align: left; }
  /* The HUD leaderboard already names everyone at this width, so the card drops the chip list
     rather than printing the roster twice over the runners it duplicates. */
  @media (min-width: 1200px) {
    body[data-state="lobby"] .lobby-roster-title,
    body[data-state="lobby"] .lobby-card .roster-chips { display: none; }
  }
  /* The 3·2·1 numeral lands dead centre of the stage, on top of the card. Give it those three
     seconds alone; the delay coming back covers the 100 ms gap between numerals so it can't flicker. */
  body[data-state="lobby"]:has(.hud-countdown:not([hidden])) .lobby-card { opacity: 0; transition-delay: 0s; }
  .lobby-kicker { font-size: var(--text-xs); letter-spacing: 0.18em; text-transform: uppercase; font-weight: 800; color: var(--accent); }
  .lobby-countdown {
    font-family: var(--font-display); font-weight: 900; font-size: var(--text-xl);
    letter-spacing: -0.02em; line-height: 1.1; margin-top: var(--space-1);
    font-variant-numeric: tabular-nums;
  }
  /* Leading with a date instead of a countdown: two or three times the characters, same box. */
  .lobby-countdown.far { font-size: var(--text-lg); }
  .lobby-countdown-sub { font-size: var(--text-sm); font-variant-numeric: tabular-nums; margin-top: var(--space-1); }
  .lobby-syncing { margin-top: var(--space-2); }
  .lobby-race-name { font-size: var(--text-xs); color: var(--ink-3); margin-top: var(--space-2); text-wrap: balance; }
  .lobby-roster-title { margin-top: var(--space-4); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-2); font-weight: 700; }
  .lobby-card .roster-chips { margin-top: var(--space-2); }
  .lobby-waiting { font-size: var(--text-lg); font-weight: 600; color: var(--ink-2); }
  .lobby-history { width: min(92vw, 42rem); text-align: left; }

  /* ---------- HUD ---------- */
  /* Sized as a container so the leaderboard can derive its row height from the viewport height. */
  .hud { position: absolute; inset: 0; pointer-events: none; font-size: var(--text-sm); container-type: size; }
  .hud > * { pointer-events: none; }
  .hud-top-left { position: absolute; top: var(--space-3); left: var(--space-3); display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; max-width: 40vw; }
  .hud-syncing { box-shadow: var(--shadow); }
  .hud-clock {
    display: inline-block; padding: 0.25em 0.6em; border-radius: var(--radius);
    background: color-mix(in oklch, var(--surface) 88%, transparent); border: 1px solid var(--line);
    font-weight: 700; font-variant-numeric: tabular-nums; box-shadow: var(--shadow);
  }
  .hud-mute {
    pointer-events: auto;
    padding: 0.25em 0.7em; border-radius: var(--radius-pill);
    background: color-mix(in oklch, var(--surface) 88%, transparent); border: 1px solid var(--line);
    color: var(--ink-2); font-size: var(--text-xs); font-weight: 600;
  }
  .hud-mute[aria-pressed="true"] { background: var(--warn-soft); color: var(--on-gold); }

  .hud-minimap {
    position: absolute; top: var(--space-3); left: 50%; transform: translateX(-50%);
    width: min(44vw, 380px); height: var(--hud-minimap-h);
    padding: 0; border-radius: var(--radius-pill);
    background: color-mix(in oklch, var(--surface) 82%, transparent);
    border: 1px solid var(--line); box-shadow: var(--shadow);
  }

  /* The board must list every runner (up to 20) without scrolling on every viewport, so rows shrink
     to share the space the board is allowed: overlay.js sets --hud-rows, the media queries set
     --hud-board-max, and --hud-board-chrome is the title plus paddings. Scrolling is only a fallback. */
  .hud-board {
    --hud-rows: 10;
    --hud-board-max: calc(100cqh - 7rem);
    --hud-board-chrome: 2.4rem;
    --hud-row-h: clamp(0.85rem, calc((var(--hud-board-max) - var(--hud-board-chrome)) / var(--hud-rows)), 1.65rem);
    position: absolute; top: var(--space-3); right: var(--space-3);
    width: 15rem; max-height: var(--hud-board-max); overflow: hidden auto; pointer-events: auto;
    padding: var(--space-2) var(--space-2) var(--space-1);
    border-radius: var(--radius-lg);
    background: color-mix(in oklch, var(--surface) 90%, transparent);
    border: 1px solid var(--line); box-shadow: var(--shadow);
  }
  .hud-board-title { font-size: var(--text-xs); line-height: 1.5; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); padding: 0 var(--space-1) var(--space-1); }
  .hud-board-list { list-style: none; margin: 0; padding: 0; position: relative; }
  .hud-row {
    display: grid; grid-template-columns: 1.4em 0.7em 1fr auto auto; align-items: center; gap: 0.35em;
    height: var(--hud-row-h); padding: 0 var(--space-1); border-radius: var(--radius-sm);
    font-size: min(1em, calc(var(--hud-row-h) * 0.78)); line-height: 1; will-change: transform;
    /* Opaque, always: a row sliding through a swap has to hide the row it crosses outright,
       and a background only the movers had made the resting rows read as a banding glitch. */
    background: var(--surface);
  }
  .hud-row.is-leader { background: var(--gold-soft); }
  .hud-row.is-moving { box-shadow: 0 2px 6px oklch(0% 0 0 / 0.22); }
  .hud-row-rank { color: var(--ink-3); font-weight: 700; text-align: right; font-size: 0.85em; }
  .hud-row-swatch { width: 0.7em; height: 0.7em; border-radius: 50%; background: var(--accent-runner); box-shadow: 0 0 0 1px oklch(0% 0 0 / 0.15) inset; }
  .hud-row-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hud-row-item { width: min(18px, calc(var(--hud-row-h) - 2px)); height: min(18px, calc(var(--hud-row-h) - 2px)); }
  .hud-row-gap { font-size: 0.85em; color: var(--ink-3); font-variant-numeric: tabular-nums; min-width: 3em; text-align: right; }

  .hud-ticker {
    position: absolute; left: 50%; bottom: var(--space-4); transform: translateX(-50%);
    display: inline-flex; align-items: center; gap: var(--space-2);
    width: max-content; max-width: min(92vw, 44rem);
    padding: 0.45em 0.9em 0.45em 0.45em; border-radius: var(--radius-pill);
    background: color-mix(in oklch, var(--ink) 90%, transparent); color: var(--bg);
    box-shadow: var(--shadow-lg); font-size: var(--text-md);
  }
  .hud-ticker.is-in { animation: hud-rise var(--dur-slow) var(--ease); }
  .hud-ticker-badge {
    display: inline-grid; place-items: center; width: 1.8em; height: 1.8em; border-radius: 50%;
    background: var(--gold); color: var(--on-gold); font-weight: 900; font-size: 0.85em; flex: none;
  }
  .hud-ticker[data-who="toby"] .hud-ticker-badge { background: var(--accent-soft); color: var(--accent); }
  .hud-ticker-who { font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.75em; color: var(--gold); flex: none; }
  .hud-ticker[data-who="toby"] .hud-ticker-who { color: var(--accent-2); }
  .hud-ticker-text { overflow: hidden; text-overflow: ellipsis; }

  .hud-banner {
    position: absolute; left: 50%; top: 30%; transform: translate(-50%, -50%);
    padding: 0.2em 0.8em; border-radius: var(--radius);
    font-family: var(--font-display); font-weight: 900; font-size: var(--text-2xl); letter-spacing: 0.02em; line-height: 1;
    background: var(--gold); color: var(--on-gold); box-shadow: var(--shadow-lg);
    width: max-content; max-width: 94vw; text-align: center; text-wrap: balance;
  }
  .hud-banner[data-kind="alert"] { background: var(--danger); color: var(--on-accent); }
  .hud-banner[data-kind="info"] { background: var(--accent); color: var(--on-accent); }
  .hud-banner.is-in { animation: hud-pop var(--dur-slow) var(--ease); }

  .hud-countdown {
    position: absolute; left: 50%; top: 45%; transform: translate(-50%, -50%);
    font-family: var(--font-display); font-weight: 900; font-size: clamp(5rem, 24vmin, 14rem); line-height: 1;
    color: var(--surface); -webkit-text-stroke: 0.04em var(--ink); paint-order: stroke fill;
    text-shadow: 0 6px 0 oklch(0% 0 0 / 0.2);
    width: max-content;
  }
  .hud-countdown[data-go="true"] { color: var(--gold); }
  /* In the lobby the field is the middle of the stage and the card it would have covered has just
     faded out, so the numeral counts down over the empty left column instead of over the runners. */
  @media (min-width: 1200px) {
    body[data-state="lobby"] .hud-countdown { left: 14rem; }
  }
  .hud-countdown.is-pop { animation: hud-count var(--dur-slow) var(--ease); }

  @keyframes hud-pop { from { transform: translate(-50%, -50%) scale(0.6); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } }
  @keyframes hud-count { from { transform: translate(-50%, -50%) scale(1.6); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } }
  @keyframes hud-rise { from { transform: translate(-50%, 12px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }

  /* ---------- draft board ---------- */
  .board { max-width: 64rem; margin: 0 auto; padding: var(--space-4) var(--space-4) var(--space-8); display: grid; gap: var(--space-4); }
  .board-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
  .board-kicker { font-size: var(--text-xs); letter-spacing: 0.18em; text-transform: uppercase; font-weight: 800; color: var(--gold-2); }
  .board-title { font-family: var(--font-display); font-weight: 900; font-size: var(--text-xl); letter-spacing: -0.02em; line-height: 1.05; }
  .board-verify-wrap { position: relative; }
  .board-verify { cursor: pointer; }
  .board-verify[data-state="checking"] { color: var(--ink-3); }
  .board-verify-tip {
    position: absolute; right: 0; top: calc(100% + var(--space-2)); z-index: 1;
    width: min(20rem, 80vw); padding: var(--space-3); font-size: var(--text-xs); color: var(--ink-2);
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-lg);
  }

  .board-stage {
    position: relative; overflow: hidden;
    padding: var(--space-6) var(--space-4) 0;
    border-radius: var(--radius-lg);
    background:
      radial-gradient(ellipse at 50% 110%, oklch(70% 0.15 var(--hue-gold) / 0.35), transparent 60%),
      linear-gradient(oklch(30% 0.09 var(--hue-red)), oklch(22% 0.07 var(--hue-red)));
    border: 1px solid oklch(20% 0.05 var(--hue-red));
    box-shadow: var(--shadow-lg);
    color: oklch(98% 0 0);
  }
  /* A size container so the pieces can fall the height of the stage: a percentage translateY would
     resolve against the 12 px piece and never leave the top edge. */
  .confetti { position: absolute; inset: 0; pointer-events: none; container-type: size; }
  .confetti i {
    position: absolute; top: -12px; left: var(--x); width: 8px; height: 12px; border-radius: 2px;
    opacity: 0.9; animation: confetti-fall var(--dur) linear var(--delay) infinite;
  }
  /* Held invisible until the fall has carried the piece clear of the stage edge, so nothing ever
     shows as a half-rectangle glued to the top of the frame. */
  @keyframes confetti-fall {
    0% { transform: translateY(0) rotate(0deg); opacity: 0; }
    8% { opacity: 0; }
    16% { opacity: 0.95; }
    100% { transform: translateY(calc(100cqh + 24px)) rotate(var(--spin)); opacity: 0; }
  }
  .podium { position: relative; display: flex; align-items: flex-end; justify-content: center; gap: var(--space-3); }
  .podium-spot { display: flex; flex-direction: column; align-items: center; width: min(30%, 14rem); text-align: center; }
  .podium-avatar { width: 124px; height: 124px; filter: drop-shadow(0 4px 6px oklch(0% 0 0 / 0.35)); }
  .podium-name { font-weight: 800; font-size: var(--text-md); margin-top: var(--space-1); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .podium-team { font-size: var(--text-xs); color: oklch(85% 0.02 var(--hue-gold)); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .podium-team.muted { color: oklch(85% 0.02 var(--hue-gold)); }
  .podium-block {
    margin-top: var(--space-2); width: 100%; min-height: var(--podium-h);
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 0.1em;
    padding-top: var(--space-2);
    border-radius: var(--radius) var(--radius) 0 0;
    background: linear-gradient(oklch(82% 0.15 var(--hue-gold)), oklch(66% 0.15 var(--hue-gold)));
    color: var(--on-gold); border-top: 3px solid var(--accent-runner);
  }
  .podium-spot[data-place="2"] .podium-block, .podium-spot[data-place="3"] .podium-block { background: linear-gradient(oklch(88% 0.03 var(--hue-manila)), oklch(74% 0.05 var(--hue-manila))); }
  .podium-place { font-weight: 900; font-size: var(--text-lg); line-height: 1; }
  .podium-award { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; padding: 0 var(--space-2); text-wrap: balance; }

  .board-sheet { display: grid; gap: var(--space-3); }
  .board-actions { justify-content: flex-start; }
  .board-actions .button .pill { margin-left: var(--space-1); }
  .button.is-copied { background: var(--ok); }
  .board-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .board-table { width: 100%; font-size: var(--text-sm); }
  .board-table th { text-align: left; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-3); padding: var(--space-2) var(--space-2); border-bottom: 2px solid var(--line-2); white-space: nowrap; }
  .board-table td { padding: var(--space-2); border-bottom: 1px solid var(--line); vertical-align: middle; }
  .board-table th.num, .board-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
  .board-table tbody tr:first-child td { background: var(--gold-soft); font-weight: 700; }
  .board-pick { font-weight: 900; font-size: var(--text-md); color: var(--accent); width: 2.5em; }
  .board-manager { font-weight: 600; white-space: nowrap; }
  .board-swatch { display: inline-block; width: 0.7em; height: 0.7em; border-radius: 50%; background: var(--accent-runner); margin-right: 0.5em; vertical-align: 0; }
  .board-team { color: var(--ink-2); max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .board-table.is-snake .snake-col { background: var(--accent-soft); }
  .board-seed { font-size: var(--text-xs); }

  /* ---------- watch gate ---------- */
  /* Same layer as the board, so the finished state is always one full-screen sheet. */
  .gate { min-height: 100%; display: grid; place-items: center; padding: var(--space-5) var(--space-4); }
  .gate-card { width: min(34rem, 100%); display: grid; gap: var(--space-3); text-align: center; justify-items: center; }
  .gate-title { font-size: var(--text-lg); }
  .gate-body { color: var(--ink-2); max-width: 28rem; }
  .gate-bar { width: min(20rem, 100%); height: 6px; border-radius: var(--radius-pill); background: var(--line); overflow: hidden; }
  .gate-bar i { display: block; height: 100%; background: var(--gold); }
  .gate-actions { justify-content: center; }
  .gate-runners { font-size: var(--text-xs); color: var(--ink-3); }

  /* ---------- commissioner panel ---------- */
  .cmsr-head { justify-content: space-between; margin-bottom: var(--space-3); }
  .cmsr-title { font-size: var(--text-lg); font-weight: 900; letter-spacing: 0.02em; }
  .cmsr-close { font-size: 1.6rem; line-height: 1; text-decoration: none; padding: 0 var(--space-2); }
  .cmsr-label { display: block; font-size: var(--text-xs); font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
  .cmsr-section { padding: var(--space-3); background: color-mix(in oklch, var(--surface) 55%, transparent); border-radius: var(--radius); border: 1px solid var(--manila-2); }
  .cmsr-textarea { resize: vertical; min-height: 7rem; font-family: var(--font-mono); font-size: var(--text-sm); }
  .cmsr-hint, .cmsr-count { font-size: var(--text-xs); }
  .cmsr-roster { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
  .cmsr-row {
    display: grid; grid-template-columns: var(--preview-px, 56px) 1fr auto auto; align-items: center; gap: var(--space-2);
    padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
    background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--accent-runner); border-radius: var(--radius-sm);
  }
  .cmsr-preview { width: var(--preview-px, 56px); height: var(--preview-px, 56px); }
  .cmsr-row-text { display: grid; min-width: 0; }
  .cmsr-row-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cmsr-row-team { font-size: var(--text-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cmsr-models { display: inline-flex; border: 1px solid var(--line-2); border-radius: var(--radius-pill); overflow: hidden; background: var(--surface-2); }
  .cmsr-model { border: 0; background: transparent; padding: 0.2em 0.6em; font-size: var(--text-xs); font-weight: 600; color: var(--ink-2); min-width: 2.4em; }
  .cmsr-model + .cmsr-model { border-left: 1px solid var(--line); }
  .cmsr-model[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }
  .cmsr-remove { font-size: 1.2rem; text-decoration: none; padding: 0 var(--space-1); }
  .cmsr-options { display: grid; gap: var(--space-3); }
  .cmsr-radios { border: 0; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
  .cmsr-radios legend { padding: 0; margin-bottom: var(--space-1); }
  .cmsr-radio { display: inline-flex; align-items: center; gap: 0.35em; padding: 0.25em 0.7em; border-radius: var(--radius-pill); background: var(--surface); border: 1px solid var(--line); font-size: var(--text-sm); }
  .cmsr-radio:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }
  .cmsr-startat-row { display: grid; gap: var(--space-1); }
  /* Safari renders datetime-local at its intrinsic width, which overflows a 390 px panel. */
  .cmsr-startat { width: 100%; max-width: 16rem; }
  .cmsr-start-note { font-size: var(--text-xs); }
  .cmsr-seed-notice { font-size: var(--text-xs); padding: var(--space-2) var(--space-3); border-left: 3px solid var(--gold); background: var(--gold-soft); color: var(--on-gold); border-radius: var(--radius-sm); }
  .cmsr-validation { font-size: var(--text-sm); color: var(--danger); }
  .cmsr-error { font-size: var(--text-sm); color: var(--danger); background: var(--danger-soft); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); }
  .cmsr-status { font-weight: 600; color: var(--accent); display: flex; align-items: center; gap: var(--space-2); }
  .cmsr-status::before { content: ""; width: 1em; height: 1em; border-radius: 50%; border: 2px solid var(--accent); border-right-color: transparent; animation: cmsr-spin 0.8s linear infinite; }
  @keyframes cmsr-spin { to { transform: rotate(360deg); } }
  .cmsr-note { padding: var(--space-3); background: var(--surface); border-radius: var(--radius); border: 1px solid var(--line); }
  .cmsr-actions { justify-content: space-between; }

  /* ---------- responsive ---------- */
  /* Narrower than this the centred lobby card reaches under the leaderboard. The card already lists
     every manager with their accent, so the board sits the lobby out rather than covering it. */
  @media (max-width: 1199px) {
    body[data-state="lobby"] .hud-board { display: none; }
  }

  @media (max-width: 640px) {
    .hud { font-size: var(--text-xs); }
    .hud-minimap { width: min(40vw, 240px); left: auto; right: var(--space-3); transform: none; top: var(--space-3); }
    .hud-board { top: calc(var(--space-3) + 30px); right: var(--space-3); width: 11.5rem; --hud-board-max: calc(100cqh - 9rem); }
    .hud-row { grid-template-columns: 1.2em 0.6em 1fr auto auto; gap: 0.25em; }
    .hud-row-gap { min-width: 2.6em; }
    .hud-ticker { font-size: var(--text-sm); bottom: var(--space-3); max-width: 96vw; }
    .hud-banner { font-size: clamp(1.4rem, 8vw, 2.4rem); }
    .lobby { padding-top: clamp(14.5rem, 30vh, 17rem); }
    /* The card is only 46vw here, and a date is a lot more characters than "1:30". */
    .lobby-countdown.far { font-size: var(--text-md); }
    .board { padding: var(--space-3) var(--space-2) var(--space-6); }
    .board-stage { padding: var(--space-4) var(--space-2) 0; }
    .podium { gap: var(--space-2); }
    .podium-avatar { width: 92px; height: 92px; }
    .podium-name { font-size: var(--text-sm); }
    .podium-award { font-size: 0.6rem; padding: 0 var(--space-1); }
    .podium-block { padding-bottom: var(--space-2); }
    .board-table { font-size: var(--text-xs); }
    .board-table th, .board-table td { padding: var(--space-1) var(--space-2); }
    .commissioner { padding: var(--space-4) var(--space-3); }
    .cmsr-model { padding: 0.2em 0.45em; }
  }

  /* Phone in portrait: the leaderboard owns the top-right, so banners and the countdown drop to the lower half. */
  @media (max-width: 640px) and (orientation: portrait) {
    .hud-banner { top: 62%; }
    .hud-countdown { top: 60%; }
    .hud-board { --hud-board-max: 50cqh; }
  }

  /* Phone in landscape: barely 400 px tall, so the HUD and lobby go compact. */
  @media (max-height: 480px) {
    .hud { font-size: var(--text-xs); }
    .hud-board { width: 11rem; --hud-board-max: calc(100cqh - 4.5rem); --hud-board-chrome: 2.1rem; }
    .hud-board-title { padding-bottom: 0; }
    .hud-ticker { bottom: var(--space-2); font-size: var(--text-sm); }
    .hud-countdown { font-size: clamp(4rem, 40vh, 8rem); }
    /* Only room for one thing at the top of a 390 px-tall stage, and it is the minimap. */
    .lobby { padding-top: calc(var(--space-3) * 2 + var(--hud-minimap-h)); justify-content: flex-start; }
    .lobby-card { padding: var(--space-3) var(--space-4); }
    .lobby-countdown { font-size: var(--text-lg); }
    .lobby-countdown.far { font-size: var(--text-md); }
    .lobby-race-name { display: none; }
    .lobby-roster-title { margin-top: var(--space-2); }
    .board-stage { padding-top: var(--space-3); }
    .podium-avatar { width: 76px; height: 76px; }
    .commissioner { padding: var(--space-3); }
  }
}

/* app */

@layer components {
  /* Which layer is on screen is a function of the state machine in app.js, not of what mounted. */
  body[data-state="booting"] .lobby,
  body[data-state="racing"] .lobby,
  body[data-state="finished"] .lobby { display: none; }

  body[data-state="booting"] .overlay,
  body[data-state="waiting"] .overlay,
  body[data-state="finished"]:not([data-replay="1"]) .overlay { display: none; }

  body[data-state="racing"] .stage-footer,
  body[data-replay="1"] .stage-footer { display: none; }

  /* Over the board too: someone arriving at a finished lottery still has to be able to sign in
     as commissioner, and the board's own button only shows once they have. */
  body[data-state="finished"] .stage-footer { z-index: calc(var(--z-board) + 1); }

  body[data-replay="1"] .masthead { display: none; }

  /* Under the clock and mute button, clear of the commentary ticker at the bottom. */
  .tap-sound {
    position: absolute;
    left: var(--space-3);
    top: calc(var(--space-3) + 2.4rem);
    z-index: var(--z-overlay);
    background: var(--surface);
    box-shadow: var(--shadow);
  }
  body[data-state="finished"]:not([data-replay="1"]) .tap-sound { display: none; }

  .debug {
    position: absolute;
    left: var(--space-3);
    bottom: var(--space-3);
    z-index: var(--z-panel);
    margin: 0;
    padding: var(--space-2) var(--space-3);
    max-width: min(90vw, 28rem);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: 1.5;
    white-space: pre-wrap;
    color: var(--ink);
    background: color-mix(in oklch, var(--surface) 85%, transparent);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    pointer-events: none;
  }
}
