/* Grudgeon site. Tokens and base styles are the game's own (apps/web/src/styles). */
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/big-shoulders-display-latin-ext-700-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/big-shoulders-display-latin-700-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 800;
  src: url(/assets/fonts/big-shoulders-display-latin-ext-800-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 800;
  src: url(/assets/fonts/big-shoulders-display-latin-800-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 900;
  src: url(/assets/fonts/big-shoulders-display-latin-ext-900-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-display: swap;
  font-weight: 900;
  src: url(/assets/fonts/big-shoulders-display-latin-900-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Atkinson Hyperlegible Next Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(/assets/fonts/atkinson-hyperlegible-next-latin-ext-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Atkinson Hyperlegible Next Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(/assets/fonts/atkinson-hyperlegible-next-latin-wght-normal.woff2) format('woff2-variations');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
/*
 * Grudgeon design tokens. See DESIGN.md.
 * One dark theme: the product is a fight night under one spotlight, by design.
 */
:root {
  color-scheme: dark;

  /* Surfaces */
  --bg: oklch(0.145 0 0);
  --bg-deep: oklch(0.11 0 0);
  --surface-1: oklch(0.195 0.006 40);
  --surface-2: oklch(0.24 0.008 40);
  --surface-3: oklch(0.29 0.01 40);
  --line: oklch(0.34 0.01 40);
  --line-strong: oklch(0.46 0.012 40);
  --scrim: oklch(0 0 0 / 0.62);
  /* The one light over the ring: warm, from above. Pages sit under it. */
  --spotlight: oklch(0.42 0.06 55 / 0.42);
  /* Top-edge catch light on raised plates and panels. */
  --catch: inset 0 1px 0 oklch(1 0 0 / 0.07);

  /* Text */
  --ink: oklch(0.965 0.004 80);
  --ink-muted: oklch(0.76 0.01 60);
  --ink-faint: oklch(0.64 0.01 60);

  /* Corners: the player is orange, the opponent is studio blue. */
  --corner: oklch(0.56 0.19 38);
  --corner-hover: oklch(0.6 0.19 38);
  --corner-ink: oklch(0.77 0.15 52);
  --corner-wash: oklch(0.56 0.19 38 / 0.14);
  --corner-deep: oklch(0.4 0.15 34);
  --corner-flood: oklch(0.56 0.19 38 / 0.3);
  --rival: oklch(0.5 0.13 240);
  --rival-hover: oklch(0.54 0.13 240);
  --rival-ink: oklch(0.78 0.11 230);
  --rival-wash: oklch(0.5 0.13 240 / 0.16);
  --rival-deep: oklch(0.36 0.1 244);
  --rival-flood: oklch(0.5 0.13 240 / 0.32);

  /* Semantic */
  --danger: oklch(0.66 0.2 25);
  --danger-wash: oklch(0.66 0.2 25 / 0.14);
  --success: oklch(0.78 0.16 150);
  --success-wash: oklch(0.78 0.16 150 / 0.12);
  --warn: oklch(0.84 0.15 85);
  --warn-wash: oklch(0.84 0.15 85 / 0.12);
  --poison: oklch(0.8 0.17 135);
  /* Enchant effects in the replay: Fire's ember and Frost's chill. Always paired with a word. */
  --burn: oklch(0.72 0.19 42);
  --chill: oklch(0.86 0.08 215);

  /* Rarity: always paired with the rarity name in text. */
  --r-common: oklch(0.78 0 0);
  --r-uncommon: oklch(0.78 0.17 145);
  --r-rare: oklch(0.74 0.14 250);
  --r-epic: oklch(0.72 0.18 305);
  --r-legendary: oklch(0.8 0.16 65);

  /* Class jerseys: low-chroma tints used by placeholder art and class chips only. */
  --c-goose: oklch(0.42 0.05 95);
  --c-badger: oklch(0.38 0.03 250);
  --c-raccoon: oklch(0.38 0.04 300);
  --c-frog: oklch(0.4 0.07 145);
  --c-pigeon: oklch(0.4 0.05 220);
  --c-crow: oklch(0.34 0.05 285);

  /* Type */
  --font-display: 'Big Shoulders Display', 'Arial Narrow', sans-serif;
  --font-body: 'Atkinson Hyperlegible Next Variable', 'Atkinson Hyperlegible Next', system-ui, sans-serif;
  --text-xs: 0.8125rem;
  --text-sm: 0.875rem;
  --text-md: 1rem;
  --text-lg: 1.1875rem;
  --text-xl: 1.4375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;
  --text-4xl: 3rem;
  /* Display-only steps: verdicts, fighter names on stage, page titles on wide screens. */
  --text-5xl: 3.75rem;
  --text-6xl: 4.75rem;
  /* Width of a 900 display capital in em, for fitting names: real names run 0.46 to 0.53 (wide Q, W, K, M). */
  --caps-advance: 0.56;

  /* Space (4px grid) */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.25rem;
  --s-6: 1.5rem;
  --s-8: 2rem;
  --s-10: 2.5rem;
  --s-12: 3rem;
  --s-16: 4rem;

  /* Shape */
  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 8px;
  --tap: 44px;
  --control: 48px;
  --control-xl: 64px;
  /* The broadcast cut: plates (tabs, tags, the VS cell) are parallelograms slanted by this much. */
  --slant: 10px;
  /* Depth of a pressable plate's bottom edge. */
  --edge: 4px;

  /* Layers */
  --z-sticky: 10;
  --z-nav: 20;
  --z-sheet-backdrop: 30;
  --z-sheet: 40;
  --z-toast: 50;

  /* Motion */
  --ease-out: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0);
  /* Impacts: verdict slams, stamps, the VS cut. Fast attack, long settle. */
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 240ms;
  --dur-impact: 420ms;

  /* Layout */
  --content-max: 46rem;
  /* Two-column screens on desktop (the fighter sheet); the top bar widens to match. */
  --content-wide: 76rem;
  --nav-h: 68px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-top: env(safe-area-inset-top, 0px);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0ms;
    --dur: 80ms;
    --dur-slow: 120ms;
    --dur-impact: 120ms;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-md);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
}

/* The one light over the ring. Fixed, so every page sits under it; the HUD bars stay dark. */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto;
  height: 75vh;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(55% 100% at 50% 0%, var(--spotlight), transparent 72%);
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

ul[role='list'],
ol[role='list'] {
  list-style: none;
  padding: 0;
}

h1,
h2,
h3 {
  text-wrap: balance;
  line-height: 1.1;
}

p {
  text-wrap: pretty;
}

img,
svg {
  display: block;
  max-width: 100%;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

a {
  color: var(--corner-ink);
  text-underline-offset: 0.18em;
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

::selection {
  background: var(--corner);
  color: white;
}

.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;
}

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -100px;
  z-index: var(--z-toast);
  padding: var(--s-3) var(--s-4);
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius);
  font-weight: 700;
}
.skip-link:focus {
  top: calc(var(--safe-top) + var(--s-2));
}

/* ---------------------------------------------------------------- type */

.display {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
}

.title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-4xl);
  letter-spacing: 0.01em;
  line-height: 0.95;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}
@media (min-width: 48rem) {
  .title {
    font-size: var(--text-5xl);
  }
}

/* Section heads carry the broadcast slash: one slanted corner-orange cut before the words. */
.section-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: uppercase;
}
.section-title::before {
  content: '';
  flex-shrink: 0;
  width: 0.5em;
  height: 0.78em;
  background: var(--corner);
  clip-path: polygon(45% 0, 100% 0, 55% 100%, 0 100%);
}

.muted {
  color: var(--ink-muted);
}

.small {
  font-size: var(--text-sm);
}

.num {
  font-variant-numeric: tabular-nums;
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: 0 var(--s-2);
  min-height: 1.5rem;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
}

.corner-tag {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/*
 * Plate: the broadcast cut. A slanted parallelogram for short labels that need
 * to read at a glance: corner tabs, level badges, VS, stamps, odds. Slant scales
 * with the text so small plates are not all edge.
 */
.plate {
  --cut: 0.42em;
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  padding: 0.2em calc(var(--cut) + 0.4em);
  clip-path: polygon(var(--cut) 0, 100% 0, calc(100% - var(--cut)) 100%, 0 100%);
  background: var(--plate-bg, var(--ink));
  color: var(--plate-ink, var(--bg));
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1.1;
  text-transform: uppercase;
  white-space: nowrap;
}
.plate-corner {
  --plate-bg: var(--corner);
  --plate-ink: white;
}
.plate-rival {
  --plate-bg: var(--rival);
  --plate-ink: white;
}
.plate-dark {
  --plate-bg: var(--bg-deep);
  --plate-ink: var(--ink);
}
.plate-gold {
  --plate-bg: var(--warn);
  --plate-ink: oklch(0.22 0.03 80);
}
.plate-danger {
  --plate-bg: var(--danger);
  --plate-ink: oklch(0.16 0.02 25);
}

/*
 * Stage: a lit panel for a fighter or a boss. A flood of the corner colour from
 * above and a halftone that fades out downwards, like a printed fight poster.
 */
.stage {
  --flood: var(--corner-flood);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    radial-gradient(110% 85% at 72% 0%, var(--flood), transparent 62%),
    var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
}
.stage::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(oklch(1 0 0 / 0.1) 1px, transparent 1.5px);
  background-size: 6px 6px;
  mask-image: linear-gradient(160deg, black, transparent 60%);
}
.stage-rival {
  --flood: var(--rival-flood);
}

/* ---------------------------------------------------------------- buttons */

/*
 * Buttons are pressable plates: a hard bottom edge in a darker shade of the
 * fill that the button sinks into when pressed. No blur, no glow.
 */
.btn {
  --btn-bg: var(--surface-2);
  --btn-bg-hover: var(--surface-3);
  --btn-ink: var(--ink);
  --btn-line: var(--line);
  --btn-edge: var(--bg-deep);
  --btn-depth: var(--edge);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--control);
  min-width: var(--tap);
  padding: 0 var(--s-5);
  border: 1px solid var(--btn-line);
  border-radius: var(--radius);
  background: var(--btn-bg);
  color: var(--btn-ink);
  box-shadow:
    var(--catch),
    0 var(--btn-depth) 0 var(--btn-edge);
  font-weight: 700;
  font-size: var(--text-md);
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  user-select: none;
  transition:
    background-color var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}
.btn:hover {
  background: var(--btn-bg-hover);
}
.btn:active {
  transform: translateY(calc(var(--btn-depth) - 1px));
  box-shadow:
    var(--catch),
    0 1px 0 var(--btn-edge);
}
.btn[disabled],
.btn[aria-disabled='true'] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow:
    var(--catch),
    0 var(--btn-depth) 0 var(--btn-edge);
}
/* Action plates: the fight buttons speak in the scoreboard face. */
.btn-primary,
.btn-rival {
  --btn-ink: white;
  --btn-line: transparent;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-lg);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  line-height: 1;
}
.btn-primary {
  --btn-bg: var(--corner);
  --btn-bg-hover: var(--corner-hover);
  --btn-edge: var(--corner-deep);
}
.btn-rival {
  --btn-bg: var(--rival);
  --btn-bg-hover: var(--rival-hover);
  --btn-edge: var(--rival-deep);
}
.btn-ghost {
  --btn-bg: transparent;
  --btn-bg-hover: var(--surface-2);
  --btn-ink: var(--corner-ink);
  --btn-line: transparent;
  --btn-depth: 0px;
  box-shadow: none;
  padding: 0 var(--s-3);
}
.btn-ghost:active {
  box-shadow: none;
}
.btn-danger {
  --btn-bg: transparent;
  --btn-bg-hover: var(--danger-wash);
  --btn-ink: var(--danger);
  --btn-line: var(--danger);
  --btn-depth: 0px;
}
.btn-block {
  width: 100%;
}
.btn-sm {
  --btn-depth: 3px;
  min-height: var(--tap);
  padding: 0 var(--s-3);
  font-size: var(--text-sm);
}
.btn-primary.btn-sm,
.btn-rival.btn-sm {
  font-size: var(--text-md);
}
/* The one big call to action on a screen. */
.btn-xl {
  --btn-depth: 6px;
  min-height: var(--control-xl);
  padding: 0 var(--s-6);
  font-size: var(--text-xl);
}
.btn-primary.btn-xl,
.btn-rival.btn-xl {
  font-size: 1.625rem;
}
.btn-icon {
  padding: 0;
  width: var(--tap);
  min-height: var(--tap);
}
.btn .spin {
  animation: spin 0.9s linear infinite;
}

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

/* ---------------------------------------------------------------- forms */

.field {
  display: grid;
  gap: var(--s-2);
}
.field label,
.field .label {
  font-weight: 700;
  font-size: var(--text-sm);
}
.input {
  width: 100%;
  min-height: var(--control);
  padding: 0 var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg-deep);
  box-shadow: inset 0 2px 0 oklch(0 0 0 / 0.35);
  color: var(--ink);
  font-size: var(--text-md);
  font-weight: 600;
  transition: border-color var(--dur) var(--ease-out);
}
.input::placeholder {
  color: var(--ink-faint);
}
.input:hover {
  border-color: var(--ink-faint);
}
.input:focus-visible {
  outline: 2px solid var(--corner-ink);
  outline-offset: 0;
  border-color: transparent;
}
.input[aria-invalid='true'] {
  border-color: var(--danger);
}
.field-help {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.field-error {
  font-size: var(--text-sm);
  color: var(--danger);
  font-weight: 600;
}

/* ---------------------------------------------------------------- surfaces */

.panel {
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
}

/*
 * Ruled list. One surface, rows split by hairlines: the default for any list
 * of things (modes, opponents, boons, attributes). Not a stack of cards.
 */
.group {
  display: grid;
  margin: 0;
  padding: 0;
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
  overflow: hidden;
}
.group > * + * {
  border-top: 1px solid var(--line);
}
.group-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 64px;
  padding: var(--s-3) var(--s-4);
  color: var(--ink);
  text-decoration: none;
}
/* Drop the button border without specificity, so the ruled list's hairline above still wins. */
:where(a.group-row, button.group-row) {
  border: 0;
}
a.group-row,
button.group-row {
  width: 100%;
  background: transparent;
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--dur) var(--ease-out);
}
a.group-row:hover,
button.group-row:hover:not(:disabled) {
  background: var(--surface-2);
}
.group-row:focus-visible {
  outline-offset: -2px;
}
.group-row-text {
  display: grid;
  flex: 1;
  min-width: 0;
}
.group-row-title {
  font-size: var(--text-md);
  font-weight: 700;
  line-height: 1.4;
}
.group-row-sub {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/*
 * Stat strip. Figures side by side, split by hairlines, like a scoreboard
 * line. Set --per-row on the strip; cells grow to fill the last row.
 */
.strip {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  margin: 0;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.strip > * {
  flex: 1 1 calc(100% / var(--per-row, 3) - 1px);
  min-width: 0;
  padding: var(--s-3) var(--s-4);
  background: var(--surface-1);
}
.strip dt,
.strip-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
}
/* Figures in the scoreboard face: condensed, heavy, tabular. */
.strip dd,
.strip-value {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
/* Label left, value right: a stat sheet rather than a row of numbers. */
.strip-rows > * {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
.strip-rows dt {
  font-size: var(--text-sm);
}

/* One choice in a ruled list of radios. The dot carries state, not colour alone. */
.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  min-height: var(--control);
  padding: var(--s-3) var(--s-4);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease-out);
}
.choice:hover {
  background: var(--surface-2);
}
.choice:has(input:checked) {
  background: var(--corner-wash);
}
.choice:has(:focus-visible) {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}
.radio {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  border: 2px solid var(--line-strong);
  border-radius: 50%;
  transition: border-color var(--dur) var(--ease-out);
}
.radio::after {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--corner-ink);
  transform: scale(0);
  transition: transform var(--dur-fast) var(--ease-out);
}
.choice:has(input:checked) .radio {
  border-color: var(--corner-ink);
}
.choice:has(input:checked) .radio::after {
  transform: scale(1);
}

.notice {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--radius);
  background: var(--warn-wash);
  color: var(--warn);
  font-weight: 600;
  font-size: var(--text-sm);
}

.lock-line {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2) var(--s-3);
}

.stack {
  display: grid;
  gap: var(--s-4);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}

.page {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--s-4) var(--s-4) var(--s-12);
  display: grid;
  gap: var(--s-6);
  align-content: start;
}

.page-head {
  display: grid;
  gap: var(--s-2);
  padding-top: var(--s-2);
}
.page-head p {
  color: var(--ink-muted);
  max-width: 60ch;
}

/* Rarity text colours */
.rarity-common {
  color: var(--r-common);
}
.rarity-uncommon {
  color: var(--r-uncommon);
}
.rarity-rare {
  color: var(--r-rare);
}
.rarity-epic {
  color: var(--r-epic);
}
.rarity-legendary {
  color: var(--r-legendary);
}

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

/*
 * Grudgeon site. Builds on the game's tokens.css and base.css (concatenated
 * before this file), so plates, buttons, stages and section heads are the
 * game's own. See DESIGN.md. The site is the fight-night poster for the game:
 * a split corner-versus-corner poster up top, a broadcast still, the roster,
 * the card, and one orange band for the promise.
 */

:root {
  --header-h: 3.75rem;
  --wrap: 72rem;
  --wrap-wide: 80rem;
  --gutter: max(var(--s-4), env(safe-area-inset-left, 0px));
  --band-y: clamp(3.5rem, 2.5rem + 4.5vw, 6.5rem);
  --seam: clamp(1.5rem, 5vw, 4.5rem);
  /* Mode colours from the game's Fight hub posters. */
  --mode-adventure: oklch(0.72 0.14 145);
  --mode-adventure-flood: oklch(0.5 0.12 145 / 0.3);
  --mode-dungeons: oklch(0.7 0.15 305);
  --mode-dungeons-flood: oklch(0.45 0.14 305 / 0.32);
}

html {
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}

main:focus {
  outline: none;
}

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap-wide {
  width: 100%;
  max-width: calc(var(--wrap-wide) + 2 * var(--gutter));
  margin-inline: auto;
}

.lede {
  max-width: 56ch;
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--ink-muted);
}

mark.todo {
  padding: 0 0.25em;
  border-radius: 2px;
  background: var(--warn);
  color: oklch(0.2 0.03 80);
  font-weight: 700;
}

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg-deep);
  border-bottom: 1px solid var(--line);
  padding-top: var(--safe-top);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: var(--header-h);
}
.wordmark {
  display: inline-flex;
  min-height: var(--tap);
  align-items: center;
  text-decoration: none;
}
.wordmark .plate {
  font-size: var(--text-xl);
  font-weight: 900;
  letter-spacing: 0.05em;
}
.header-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.lang-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--s-3);
  border-radius: var(--radius);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 700;
  text-decoration: none;
  transition:
    color var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out);
}
.lang-link:hover {
  color: var(--ink);
  background: var(--surface-2);
}

/* ---------------------------------------------------------------- hero: the poster */

.hero {
  padding-bottom: calc(var(--band-y) * 0.5);
}

/*
 * Two corners on one poster, cut by a slanted seam. Each half is a 4:5
 * portrait under its corner's top rule; the halves share the seam line, with a
 * dark gap between them like a broadcast split.
 */
.poster {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  aspect-ratio: 8 / 5;
  background: var(--bg-deep);
}
@media (min-width: 48rem) {
  .poster {
    aspect-ratio: 16 / 8;
    margin-top: var(--s-6);
    border-radius: var(--radius-lg);
    border: 1px solid var(--line);
    width: calc(100% - 2 * var(--gutter));
  }
}
@media (min-width: 80rem) {
  .poster {
    aspect-ratio: 16 / 7;
  }
}
.poster-half {
  position: absolute;
  top: 0;
  bottom: 0;
  width: calc(50% + var(--seam) / 2);
  overflow: hidden;
}
.poster-corner {
  left: 0;
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--seam)) 100%, 0 100%);
  box-shadow: inset 0 4px 0 var(--corner);
  animation: poster-in-left 760ms var(--ease-expo) both;
}
.poster-rival {
  left: calc(50% - var(--seam) / 2 + 6px);
  right: 0;
  width: auto;
  clip-path: polygon(var(--seam) 0, 100% 0, 100% 100%, 0 100%);
  animation: poster-in-right 760ms var(--ease-expo) both;
}
.poster-art {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
}
.poster-corner .poster-art {
  object-position: 40% 18%;
}
.poster-rival .poster-art {
  object-position: 60% 18%;
}
/* The corner rule sits over the art, so it reads as part of the broadcast frame. */
.poster-corner::after,
.poster-rival::after {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: var(--corner);
}
.poster-rival::after {
  background: var(--rival-ink);
}

/* Lower-third name plates, one per corner, on a solid HUD panel. */
.poster-tag {
  position: absolute;
  bottom: clamp(var(--s-2), 2vw, var(--s-6));
  display: grid;
  justify-items: start;
  gap: 2px;
  max-width: calc(100% - var(--seam) - var(--s-4));
  padding: var(--s-2) var(--s-3) var(--s-2);
  background: var(--bg-deep);
  box-shadow: inset 0 3px 0 var(--corner);
  animation: tag-up 520ms var(--ease-expo) 420ms both;
}
.poster-corner .poster-tag {
  left: clamp(var(--s-2), 2vw, var(--s-6));
}
.poster-rival .poster-tag {
  right: clamp(var(--s-2), 2vw, var(--s-6));
  justify-items: end;
  text-align: right;
  box-shadow: inset 0 3px 0 var(--rival-ink);
}
.poster-tag .plate {
  font-size: var(--text-xs);
}
.poster-name {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--text-xl), 1rem + 2.6vw, var(--text-5xl));
  line-height: 0.92;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.poster-line {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
  white-space: nowrap;
}
.poster-vs {
  position: absolute;
  top: 42%;
  left: 50%;
  z-index: 1;
  font-size: clamp(var(--text-2xl), 1rem + 4vw, var(--text-6xl));
  font-weight: 900;
  translate: -50% -50%;
  animation: vs-stamp var(--dur-impact) var(--ease-expo) 360ms both;
}

@media (max-width: 30rem) {
  .poster-line {
    display: none;
  }
}

.hero-body {
  display: grid;
  gap: var(--s-6);
  padding-top: clamp(var(--s-6), 4vw, var(--s-12));
}
@media (min-width: 60rem) {
  .hero-body {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--s-12);
  }
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(3.25rem, 2rem + 7vw, 6rem);
  line-height: 0.9;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  animation: title-wipe 680ms var(--ease-expo) 200ms both;
}
.hero-side {
  display: grid;
  gap: var(--s-5);
  animation: rise 560ms var(--ease-out) 380ms both;
}
.hero-lede {
  max-width: 54ch;
  font-size: var(--text-lg);
  line-height: 1.6;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-4);
}
.hero-note {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
}
.stores-soon {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

@keyframes poster-in-left {
  from {
    opacity: 0;
    transform: translateX(-8%);
  }
}
@keyframes poster-in-right {
  from {
    opacity: 0;
    transform: translateX(8%);
  }
}
@keyframes tag-up {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}
@keyframes vs-stamp {
  from {
    opacity: 0;
    transform: scale(1.8) rotate(-8deg);
  }
}
@keyframes title-wipe {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}

/* ---------------------------------------------------------------- bands */

.band {
  padding-block: var(--band-y);
}
.band + .band:not(.band-fair) {
  border-top: 1px solid var(--line);
}
.band-head {
  display: grid;
  gap: var(--s-4);
  margin-bottom: clamp(var(--s-8), 4vw, var(--s-12));
}
.band .section-title {
  font-size: clamp(var(--text-2xl), 1.1rem + 2.2vw, var(--text-4xl));
  font-weight: 900;
}
/* A long head wraps beside its slash instead of dropping the slash onto its own line. */
.band .section-title,
.prose h2.section-title {
  flex-wrap: nowrap;
  align-items: flex-start;
}
.band .section-title::before {
  margin-top: 0.08em;
}
.prose h2.section-title::before {
  margin-top: 0.22em;
}

/* Text one side, the picture the other. */
.split {
  display: grid;
  gap: clamp(var(--s-8), 5vw, var(--s-16));
}
.split-text {
  display: grid;
  gap: var(--s-5);
  align-content: start;
}
@media (min-width: 64rem) {
  .split {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
  }
  .split-text {
    position: sticky;
    top: calc(var(--header-h) + var(--s-8));
  }
  .split-reverse {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  }
  .split-reverse > .split-text {
    order: 2;
  }
}

/* ---------------------------------------------------------------- the broadcast still */

.broadcast {
  display: grid;
  gap: var(--s-3);
}
.scoreboard {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
  overflow: hidden;
}
.sb-corner {
  position: relative;
  container-type: inline-size;
  display: grid;
  align-content: start;
  gap: 3px;
  min-width: 0;
  padding: var(--s-4) var(--s-3) var(--s-3);
  background: linear-gradient(110deg, var(--corner-flood), transparent 70%);
  box-shadow: inset 0 4px 0 var(--corner);
}
.sb-rival {
  background: linear-gradient(250deg, var(--rival-flood), transparent 70%);
  box-shadow: inset 0 4px 0 var(--rival-ink);
  text-align: right;
}
.sb-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.sb-rival .sb-head {
  flex-direction: row-reverse;
}
.sb-face {
  width: 48px;
  height: 48px;
  border-radius: var(--radius);
  box-shadow: 0 0 0 2px var(--bg-deep);
}
.sb-head .plate {
  font-size: var(--text-xs);
}
.sb-name {
  margin-top: var(--s-2);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: min(var(--text-3xl), 18cqi);
  line-height: 0.92;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.sb-meta {
  margin-bottom: var(--s-1);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The game's segmented HP bar: a recessed slot, a lit fill, ten ticks. */
.hp-track {
  position: relative;
  height: 18px;
  border-radius: 3px;
  background: var(--bg-deep);
  box-shadow:
    inset 0 2px 0 oklch(0 0 0 / 0.4),
    0 0 0 1px var(--line);
  overflow: hidden;
}
.hp-track::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent calc(100% - 2px), oklch(0 0 0 / 0.5) 0) 0 0 / 10%
    100%;
}
.hp-fill {
  position: absolute;
  inset: 0;
  background: var(--corner);
  box-shadow: inset 0 3px 0 oklch(1 0 0 / 0.22);
  transform-origin: left center;
  /* Final HP after round 4 (FIGHT in src/pages/home.ts): Gary 105/160. */
  transform: scaleX(0.65625);
}
.sb-rival .hp-track {
  transform: scaleX(-1);
}
.sb-rival .hp-fill {
  background: var(--rival-ink);
  /* Kevin 0/120. */
  transform: scaleX(0);
}
.sb-hp {
  display: flex;
  align-items: baseline;
  gap: 2px;
  margin-top: var(--s-1);
}
.sb-rival .sb-hp {
  justify-content: flex-end;
}
.sb-hp-now {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-2xl);
  line-height: 1.05;
}
.sb-hp-max {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
}
.sb-mid {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 2px;
  min-width: 3.5rem;
  padding: var(--s-3) var(--s-2);
  background: var(--bg-deep);
  border-inline: 1px solid var(--line);
}
.sb-round-label {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.sb-round {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-4xl);
  line-height: 1;
}
.sb-out .sb-face {
  filter: grayscale(1) brightness(0.7);
}
.sb-out .sb-name,
.sb-out .hp-track {
  opacity: 0.55;
}
.ko-stamp {
  position: absolute;
  top: 70%;
  left: 46%;
  padding: 0.05em 0.3em 0;
  border: 4px solid var(--danger);
  border-radius: var(--radius);
  background: oklch(0.14 0.03 25 / 0.8);
  color: var(--danger);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--text-2xl), 18cqi, var(--text-4xl));
  line-height: 1;
  letter-spacing: 0.04em;
  pointer-events: none;
  transform: translate(-50%, -50%) rotate(-12deg);
}

/* The venue as a lower-third under the scoreboard, like the in-game venue strip. */
.sb-venue {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2);
  padding-right: var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
.sb-venue-art {
  width: 96px;
  height: auto;
  border-radius: var(--radius-sm);
}
.sb-venue .plate {
  font-size: var(--text-xs);
}
.sb-venue-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-lg);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* Commentary transcript: round numerals on the left, one line per event. */
.transcript {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
}
.tr-round {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr);
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4) var(--s-3) var(--s-3);
}
.tr-round + .tr-round {
  border-top: 1px solid var(--line);
}
.tr-marker {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-2xl);
  line-height: 1.1;
  color: var(--ink-faint);
  text-align: center;
}
.tr-lines {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.tr-line {
  line-height: 1.5;
}
.dmg {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.15em;
  letter-spacing: 0.02em;
}
.dmg-crit {
  color: var(--danger);
}
.tr-stun {
  color: var(--warn);
  font-weight: 600;
}
.tr-ko {
  font-weight: 700;
}

/* ---------------------------------------------------------------- how a grudge works */

/* The one numbered sequence on the page: it is a real sequence. */
.steps {
  display: grid;
  gap: var(--s-6);
  margin: var(--s-2) 0 0;
  padding: 0;
  list-style: none;
}
.step {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  gap: var(--s-3);
}
.step-num {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-6xl);
  line-height: 0.78;
  color: var(--corner-ink);
}
.step-title {
  margin-bottom: var(--s-2);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-xl);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.step p {
  max-width: 52ch;
  color: var(--ink-muted);
}

/* A group chat, drawn as a chat: the one place on the page with its own visual world. */
.chat {
  display: grid;
  gap: var(--s-3);
  width: 100%;
  max-width: 28rem;
  margin: 0;
  padding: var(--s-4);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
@media (min-width: 64rem) {
  .chat {
    justify-self: center;
  }
}
.msg {
  justify-self: start;
  max-width: 88%;
  padding: var(--s-2) var(--s-3) var(--s-3);
  background: var(--surface-2);
  border-radius: 12px 12px 12px 4px;
}
.msg-reply {
  justify-self: end;
  background: var(--rival);
  border-radius: 12px 12px 4px 12px;
}
.msg-from {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--ink-muted);
}
.msg-reply .msg-from {
  color: oklch(0.92 0.03 235);
}
.msg-text {
  font-size: var(--text-lg);
}
.linkcard {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  margin-top: var(--s-2);
  background: var(--bg-deep);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.linkcard-art {
  width: 64px;
  height: 64px;
}
.linkcard-text {
  display: grid;
  align-content: center;
  padding: var(--s-1) var(--s-3);
  min-width: 0;
}
.linkcard-title {
  font-weight: 700;
  line-height: 1.3;
}
.linkcard-sub,
.linkcard-url {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.linkcard-url {
  color: var(--corner-ink);
}
.inbox-note {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  margin-top: var(--s-2);
  padding: var(--s-3);
  background: var(--surface-1);
  box-shadow: inset 0 3px 0 var(--corner);
  border-radius: 0 0 var(--radius) var(--radius);
  font-weight: 600;
}
.inbox-note .plate {
  font-size: var(--text-xs);
}

/* ---------------------------------------------------------------- roster */

/* Character select: square head crops in one ruled grid, no floating cards. */
.roster {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.fighter {
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--surface-1);
}
/* Wide screens: portrait left, sheet right, two fighters a row. */
@media (min-width: 52rem) {
  .fighter {
    grid-template-rows: none;
    grid-template-columns: clamp(9rem, 16vw, 13rem) minmax(0, 1fr);
  }
  .fighter-art {
    height: 100%;
    object-fit: cover;
  }
  .fighter-text {
    align-content: center;
    box-shadow: inset 3px 0 0 var(--bg-deep);
  }
}
.fighter-art {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}
.fighter-text {
  display: grid;
  align-content: start;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-4) var(--s-5);
  box-shadow: inset 0 3px 0 var(--bg-deep);
}
.fighter-name {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--text-xl), 1rem + 1.5vw, var(--text-3xl));
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.fighter-role {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--corner-ink);
}
.fighter-tagline {
  margin-top: var(--s-1);
  font-weight: 700;
}
.fighter-skill {
  display: grid;
  justify-items: start;
  gap: var(--s-1);
  margin-top: var(--s-2);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.fighter-skill .plate {
  max-width: 100%;
  font-size: var(--text-xs);
  /* Long skill names (Malédiction Brillante) wrap in narrow cells instead of clipping. */
  white-space: normal;
}

/* ---------------------------------------------------------------- tonight's card */

/* Mode posters, like the game's Fight hub: the Daily Pit headlines the card. */
.modes {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 44rem) {
  .modes {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .mode-pit {
    grid-column: 1 / -1;
  }
}
.mode {
  --mode: var(--corner);
  --mode-flood: var(--corner-flood);
  position: relative;
  isolation: isolate;
  display: grid;
  align-content: end;
  justify-items: start;
  gap: var(--s-2);
  min-height: 11rem;
  padding: var(--s-5);
  overflow: hidden;
  background:
    radial-gradient(110% 85% at 72% 0%, var(--mode-flood), transparent 62%), var(--surface-1);
  border: 1px solid var(--line);
  border-top: 4px solid var(--mode);
  border-radius: var(--radius-lg);
}
.mode::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(oklch(1 0 0 / 0.1) 1px, transparent 1.5px);
  background-size: 6px 6px;
  mask-image: linear-gradient(160deg, black, transparent 60%);
}
.mode-arena {
  --mode: var(--rival-ink);
  --mode-flood: var(--rival-flood);
}
.mode-adventure {
  --mode: var(--mode-adventure);
  --mode-flood: var(--mode-adventure-flood);
}
.mode-dungeons {
  --mode: var(--mode-dungeons);
  --mode-flood: var(--mode-dungeons-flood);
}
.mode-name {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-3xl);
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--mode);
}
.mode-pit {
  min-height: 15rem;
}
.mode-pit .mode-name {
  font-size: clamp(var(--text-4xl), 1.5rem + 3vw, var(--text-6xl));
  color: var(--ink);
}
.mode p {
  max-width: 52ch;
  color: var(--ink-muted);
}
.mode .plate {
  font-size: var(--text-sm);
}

.venues-head {
  display: grid;
  gap: var(--s-2);
  margin: clamp(var(--s-10), 5vw, var(--s-16)) 0 var(--s-5);
}
.venues-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-2xl);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.venues {
  display: grid;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
@media (min-width: 52rem) {
  .venues {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.venue {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3);
  background: var(--surface-1);
}
.venue-art {
  flex-shrink: 0;
  width: clamp(112px, 28vw, 160px);
  height: auto;
  border-radius: var(--radius);
}
.venue-text {
  display: grid;
  gap: var(--s-1);
  min-width: 0;
}
.venue-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-lg);
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.venue-blurb {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.venue-effect {
  justify-self: start;
  margin-top: var(--s-1);
  padding: 0 var(--s-2);
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  font-size: var(--text-xs);
  font-weight: 700;
  line-height: 1.6rem;
}

/* ---------------------------------------------------------------- the promise: one orange band */

.band-fair {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--corner);
  color: white;
}
.band-fair::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(oklch(0 0 0 / 0.14) 1.2px, transparent 1.7px);
  background-size: 7px 7px;
  mask-image: linear-gradient(200deg, black, transparent 55%);
}
.fair-inner {
  display: grid;
  gap: var(--s-8);
}
@media (min-width: 60rem) {
  .fair-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--s-16);
    align-items: start;
  }
}
.fair-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--text-4xl), 1.5rem + 4vw, var(--text-6xl));
  line-height: 0.92;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.fair-body {
  display: grid;
  gap: var(--s-5);
}
.fair-text {
  font-size: var(--text-xl);
  font-weight: 700;
  line-height: 1.4;
}
.fair-points {
  margin: 0;
  padding: 0;
  list-style: none;
}
.fair-points li {
  display: flex;
  gap: var(--s-3);
  padding-block: var(--s-3);
  border-top: 1px solid oklch(1 0 0 / 0.35);
  font-size: var(--text-lg);
}
/* The corner slash, inverted: dark on orange. */
.fair-points li::before {
  content: '';
  flex-shrink: 0;
  width: 0.55em;
  height: 0.85em;
  margin-top: 0.3em;
  background: var(--bg-deep);
  clip-path: polygon(45% 0, 100% 0, 55% 100%, 0 100%);
}

/* ---------------------------------------------------------------- final call */

.cta {
  display: grid;
  gap: var(--s-8);
  padding: clamp(var(--s-6), 4vw, var(--s-12));
}
@media (min-width: 56rem) {
  .cta {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
  }
}
.cta-text {
  display: grid;
  gap: var(--s-5);
  justify-items: start;
}
.cta-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(var(--text-4xl), 1.5rem + 4vw, var(--text-6xl));
  line-height: 0.92;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
/* A QR code only helps on a computer, so phones and touch screens never see it. */
.cta-qr {
  display: none;
  margin: 0;
  justify-items: center;
  gap: var(--s-3);
  text-align: center;
}
@media (min-width: 56rem) and (hover: hover) and (pointer: fine) {
  .cta-qr {
    display: grid;
  }
}
.qr {
  width: 176px;
  padding: var(--s-2);
  border-radius: var(--radius);
  background: white;
}
.qr svg {
  width: 100%;
  height: auto;
}
.cta-qr figcaption {
  max-width: 22ch;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/* ---------------------------------------------------------------- footer */

.site-footer {
  padding-block: var(--s-10) calc(var(--s-10) + var(--safe-bottom));
  background: var(--bg-deep);
  border-top: 1px solid var(--line);
}
.footer-inner {
  display: grid;
  gap: var(--s-6);
}
@media (min-width: 56rem) {
  .footer-inner {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
  }
  .footer-rights {
    grid-column: 1 / -1;
  }
}
.footer-brand {
  display: grid;
  justify-items: start;
  gap: var(--s-2);
}
.footer-line {
  max-width: 40ch;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-5);
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-links a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--ink-muted);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--dur) var(--ease-out);
}
.footer-links a:hover {
  color: var(--ink);
  text-decoration: underline;
}
.footer-links a[aria-current='page'] {
  color: var(--ink);
}
.footer-rights {
  font-size: var(--text-xs);
  color: var(--ink-faint);
}

/* ---------------------------------------------------------------- long-form pages */

.doc {
  padding-block: clamp(var(--s-8), 5vw, var(--s-16)) var(--band-y);
}
.doc-head {
  display: grid;
  gap: var(--s-3);
  max-width: 50rem;
  padding-bottom: clamp(var(--s-8), 4vw, var(--s-12));
  border-bottom: 1px solid var(--line);
}
.doc-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(2.25rem, 1.25rem + 4vw, var(--text-6xl));
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.doc-meta {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
}
.doc-intro {
  max-width: 62ch;
  margin-top: var(--s-2);
  font-size: var(--text-lg);
  line-height: 1.65;
}
.doc-grid {
  display: grid;
  gap: var(--s-8);
  padding-top: clamp(var(--s-8), 4vw, var(--s-12));
}
@media (min-width: 64rem) {
  .doc-grid {
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: var(--s-12);
  }
}
.toc {
  display: grid;
  gap: var(--s-2);
  align-content: start;
}
@media (min-width: 64rem) {
  .toc {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    max-height: calc(100dvh - var(--header-h) - var(--s-12));
    overflow-y: auto;
  }
}
/* On phones the contents fold to a short strip of links, so the text starts sooner. */
@media (max-width: 63.99rem) {
  .toc {
    padding: var(--s-3) var(--s-4);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
  }
  .toc-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--s-4);
  }
}
.toc-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.toc-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.toc-list a {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.3;
  text-decoration: none;
  transition: color var(--dur) var(--ease-out);
}
.toc-list a:hover {
  color: var(--ink);
  text-decoration: underline;
}

.prose {
  max-width: 70ch;
  font-size: 1.0625rem;
  line-height: 1.65;
}
.prose > section + section {
  margin-top: clamp(var(--s-10), 4vw, var(--s-12));
}
/* Section heads in the body face: these headings are often sentences, and sentences stay in sentence case. */
.prose h2.section-title {
  margin-bottom: var(--s-4);
  font-family: var(--font-body);
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.25;
  text-transform: none;
}
.prose h3 {
  margin: var(--s-6) 0 var(--s-2);
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.3;
}
.prose p + p,
.prose p + ul,
.prose ul + p,
.prose ol + p,
.prose p + ol {
  margin-top: var(--s-4);
}
.prose ul:not([role]) {
  display: grid;
  gap: var(--s-2);
  margin: var(--s-3) 0 0;
  padding-left: 1.25em;
}
.prose ul:not([role]) li::marker {
  color: var(--corner-ink);
}
.prose strong {
  font-weight: 700;
  color: var(--ink);
}

.summary-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--catch);
}
.summary-list li {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
}
.summary-list li + li {
  border-top: 1px solid var(--line);
}
.summary-list li::before {
  content: '';
  flex-shrink: 0;
  width: 0.5em;
  height: 0.8em;
  margin-top: 0.4em;
  background: var(--corner);
  clip-path: polygon(45% 0, 100% 0, 55% 100%, 0 100%);
}

/* The privacy inventory: one ruled row per kind of data, labels left on wide screens. */
.data-rows {
  margin: var(--s-6) 0 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--line);
}
.data-row {
  padding-block: var(--s-5);
  border-top: 1px solid var(--line);
}
.prose .data-title {
  margin: 0 0 var(--s-3);
}
.data-dl {
  display: grid;
  gap: var(--s-3);
  margin: 0;
}
.data-dl > div {
  display: grid;
  gap: 2px;
}
@media (min-width: 40rem) {
  .data-dl > div {
    grid-template-columns: 9.5rem minmax(0, 1fr);
    gap: var(--s-4);
  }
}
.data-dl dt {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--text-sm);
  letter-spacing: 0.05em;
  line-height: 1.9;
  text-transform: uppercase;
  color: var(--corner-ink);
}
.data-dl dd {
  margin: 0;
  color: var(--ink-muted);
}

.doc-steps {
  display: grid;
  gap: var(--s-3);
  margin: var(--s-4) 0 0;
  padding: 0;
  list-style: none;
}
.doc-steps li {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr);
  gap: var(--s-2);
  align-items: baseline;
}
.doc-step-num {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--corner-ink);
}

/* ---------------------------------------------------------------- 404 */

.not-found {
  display: grid;
  justify-items: start;
  gap: var(--s-4);
  padding-block: var(--band-y);
}

/* ---------------------------------------------------------------- scroll-driven playback */

/*
 * Where the browser supports scroll-driven animations, the broadcast still
 * plays back as you read: the scoreboard pins under the header, and each HP
 * change, round number and the KO stamp fire as their commentary line passes
 * the middle of the screen (tr-s<n> is the n-th line of the fight, tr-r<n> the
 * n-th round). Everywhere else, and with reduced motion, the still shows the
 * final state above.
 *
 * Each step is its own animation on its own line's timeline. The first step
 * of a value fills both ways; later steps fill forwards only, so before their
 * line arrives they do nothing and the earlier step shows through.
 *
 * Lines: 4 Gary hits (Kevin 120 → 102), 5 Kevin hits (Gary 160 → 146),
 * 6 Kevin crits (Gary → 105), 7 Gary hits (Kevin → 75), 8 Gary crits
 * (Kevin → 0), 9 KO. Keep in step with FIGHT and the transcript in copy.ts.
 */
@property --hp {
  syntax: '<integer>';
  inherits: true;
  initial-value: 0;
}
@property --round {
  syntax: '<integer>';
  inherits: true;
  initial-value: 4;
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .broadcast {
      --step: cover 34% cover 44%;
      timeline-scope: --s4, --s5, --s6, --s7, --s8, --s9, --r2, --r3, --r4;
    }
    .scoreboard {
      position: sticky;
      top: calc(var(--header-h) + var(--s-2));
      z-index: 1;
    }
    .tr-s4 {
      view-timeline: --s4 block;
    }
    .tr-s5 {
      view-timeline: --s5 block;
    }
    .tr-s6 {
      view-timeline: --s6 block;
    }
    .tr-s7 {
      view-timeline: --s7 block;
    }
    .tr-s8 {
      view-timeline: --s8 block;
    }
    .tr-s9 {
      view-timeline: --s9 block;
    }
    .tr-r2 {
      view-timeline: --r2 block;
    }
    .tr-r3 {
      view-timeline: --r3 block;
    }
    .tr-r4 {
      view-timeline: --r4 block;
    }

    .sb-corner .hp-fill {
      animation:
        hp-c1 linear both,
        hp-c2 linear forwards;
      animation-timeline: --s5, --s6;
      animation-range: var(--step);
    }
    .sb-rival .hp-fill {
      animation:
        hp-r1 linear both,
        hp-r2 linear forwards,
        hp-r3 linear forwards;
      animation-timeline: --s4, --s7, --s8;
      animation-range: var(--step);
    }
    .sb-hp-now {
      font-size: 0;
    }
    .sb-hp-now::before {
      counter-reset: hp var(--hp);
      content: counter(hp);
      font-size: var(--text-2xl);
    }
    .sb-corner .sb-hp-now {
      animation:
        hpn-c1 linear both,
        hpn-c2 linear forwards;
      animation-timeline: --s5, --s6;
      animation-range: var(--step);
    }
    .sb-rival .sb-hp-now {
      animation:
        hpn-r1 linear both,
        hpn-r2 linear forwards,
        hpn-r3 linear forwards;
      animation-timeline: --s4, --s7, --s8;
      animation-range: var(--step);
    }
    .sb-round {
      font-size: 0;
      animation:
        round-2 linear both,
        round-3 linear forwards,
        round-4 linear forwards;
      animation-timeline: --r2, --r3, --r4;
      animation-range: cover 30% cover 34%;
    }
    .sb-round::before {
      counter-reset: round var(--round);
      content: counter(round);
      font-size: var(--text-4xl);
    }
    .ko-stamp,
    .sb-out .sb-face,
    .sb-out .sb-name {
      animation-timeline: --s9;
      animation-range: var(--step);
      animation-fill-mode: both;
      animation-timing-function: var(--ease-expo);
    }
    .ko-stamp {
      animation-name: ko-land;
    }
    .sb-out .sb-face {
      animation-name: face-out;
    }
    .sb-out .sb-name {
      animation-name: name-out;
    }
    .tr-line {
      animation: line-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 100%;
    }
  }
}

@keyframes hp-c1 {
  from {
    transform: scaleX(1);
  }
  to {
    transform: scaleX(0.9125);
  }
}
@keyframes hp-c2 {
  from {
    transform: scaleX(0.9125);
  }
  to {
    transform: scaleX(0.65625);
  }
}
@keyframes hp-r1 {
  from {
    transform: scaleX(1);
  }
  to {
    transform: scaleX(0.85);
  }
}
@keyframes hp-r2 {
  from {
    transform: scaleX(0.85);
  }
  to {
    transform: scaleX(0.625);
  }
}
@keyframes hp-r3 {
  from {
    transform: scaleX(0.625);
  }
  to {
    transform: scaleX(0);
  }
}
@keyframes hpn-c1 {
  from {
    --hp: 160;
  }
  to {
    --hp: 146;
  }
}
@keyframes hpn-c2 {
  from {
    --hp: 146;
  }
  to {
    --hp: 105;
  }
}
@keyframes hpn-r1 {
  from {
    --hp: 120;
  }
  to {
    --hp: 102;
  }
}
@keyframes hpn-r2 {
  from {
    --hp: 102;
  }
  to {
    --hp: 75;
  }
}
@keyframes hpn-r3 {
  from {
    --hp: 75;
  }
  to {
    --hp: 0;
  }
}
@keyframes round-2 {
  from {
    --round: 1;
  }
  to {
    --round: 2;
  }
}
@keyframes round-3 {
  from {
    --round: 2;
  }
  to {
    --round: 3;
  }
}
@keyframes round-4 {
  from {
    --round: 3;
  }
  to {
    --round: 4;
  }
}
@keyframes ko-land {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(-12deg) scale(1.8);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) rotate(-12deg) scale(1);
  }
}
@keyframes face-out {
  from {
    filter: none;
  }
  to {
    filter: grayscale(1) brightness(0.7);
  }
}
@keyframes name-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0.55;
  }
}
@keyframes line-in {
  from {
    opacity: 0.2;
    transform: translateY(10px);
  }
}
