/* =========================================================
   KBAA — Korean North American Basketball Association
   Single stylesheet. Order: tokens → reset → base →
   layout → components → sections → pages → utilities.
   ========================================================= */

/* ---------- 1. Tokens ---------- */

:root {
  /* Brand — Korean flag red & blue on white */
  --red: #cd2e3a;
  --red-dark: #a71f2a;
  --red-soft: #fdeef0;
  /* Text that sits ON a red fill. Must flip with the red itself. */
  --on-red: #ffffff;
  --blue: #0a3a82;
  --blue-dark: #06285c;
  --blue-soft: #edf2fb;

  /* Red and blue both go muddy on navy. This is the accent for anything
     sitting on a dark surface — links, eyebrows, indexes, rules. */
  --accent-on-dark: #ff7f88;

  /* Neutrals */
  --navy: #061733;
  --navy-2: #0d244d;
  --ink: #101014;
  --ink-2: #4a4f5a;
  /* Tertiary labels. Must clear 4.5:1 on both --paper and --paper-2, since
     it carries table headers and form hints as well as decorative captions.
     5.21:1 on white, 4.80:1 on --paper-2. */
  --ink-3: #666d7a;
  --paper: #ffffff;
  --paper-2: #f5f6f8;
  --paper-3: #eceef2;
  --line: #e4e6eb;
  --line-strong: #cbd0da;

  /* Type */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  --font-display: "Archivo", "Inter", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --fs-display: clamp(2.75rem, 6.2vw, 5.25rem);
  --fs-h1: clamp(2.25rem, 4.8vw, 3.75rem);
  --fs-h2: clamp(1.75rem, 3.2vw, 2.75rem);
  --fs-h3: clamp(1.25rem, 1.8vw, 1.5rem);
  --fs-body: 1rem;
  --fs-sm: 0.875rem;
  --fs-xs: 0.75rem;

  /* Space */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;

  /* Structure */
  --container: 1200px;
  --gutter: 1.5rem;
  --radius: 4px;
  --radius-lg: 10px;
  --nav-h: 72px;

  --shadow-sm: 0 1px 2px rgba(6, 23, 51, 0.06);
  --shadow: 0 4px 24px rgba(6, 23, 51, 0.08);
  --shadow-lg: 0 18px 60px rgba(6, 23, 51, 0.16);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (min-width: 768px) {
  :root {
    --gutter: 2.5rem;
    --nav-h: 80px;
  }
}

/* ---------- 2. Reset ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
  color-scheme: light dark;
}

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

ul[class],
ol[class] {
  list-style: none;
  padding: 0;
}

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

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

button {
  background: none;
  border: 0;
  cursor: pointer;
}

table {
  border-collapse: collapse;
  width: 100%;
}

/* Reduced motion removes movement, not feedback. Colour, border and shadow
   transitions still run at their authored speed so hover, focus and pressed
   states keep reading as state changes; only travel is dropped. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-property: color, background-color, border-color, outline-color,
      box-shadow, opacity !important;
  }
  .btn:hover,
  .btn:active,
  a.card:hover,
  .team-card:hover,
  .division-card:hover,
  .gallery__item:hover img,
  .arrow-link:hover::after {
    transform: none !important;
  }
}

/* ---------- 3. Base ---------- */

body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-h1);
}
h2 {
  font-size: var(--fs-h2);
}
h3 {
  font-size: var(--fs-h3);
  letter-spacing: -0.02em;
  line-height: 1.25;
}

p {
  text-wrap: pretty;
}

a {
  color: var(--blue);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.18s var(--ease);
}

a:hover {
  color: var(--red);
}

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

::selection {
  background: var(--red);
  color: var(--on-red);
}

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: -100px;
  z-index: 200;
  background: var(--red);
  color: var(--on-red);
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  border-radius: var(--radius);
  transition: top 0.2s var(--ease);
}

.skip-link:focus {
  top: var(--s-4);
  color: var(--on-red);
}

/* ---------- 4. Layout ---------- */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--wide {
  max-width: 1440px;
}

.section {
  padding-block: var(--s-8);
}

@media (min-width: 768px) {
  .section {
    padding-block: var(--s-9);
  }
}

.section--tight {
  padding-block: var(--s-7);
}

.section--alt {
  background: var(--paper-2);
}

.section--dark {
  background: var(--navy);
  color: #fff;
}

.section--dark h1,
.section--dark h2,
.section--dark h3 {
  color: #fff;
}

.section--dark p {
  color: rgba(255, 255, 255, 0.78);
}

/* Inline links on navy. The default --blue lands at 1.3:1 here, which is
   invisible rather than merely low — these surfaces need the light accent
   and an underline, since colour alone can't carry the affordance. */
.section--dark a:not([class]),
.feature a:not([class]) {
  color: var(--accent-on-dark);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.section--dark a:not([class]):hover,
.feature a:not([class]):hover {
  color: #fff;
}

.rule {
  height: 1px;
  background: var(--line);
  border: 0;
  margin: 0;
}

/* ---------- 5. Type helpers ---------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: var(--s-4);
}

.eyebrow::before {
  content: "";
  width: 28px;
  height: 2px;
  background: var(--red);
}

.section--dark .eyebrow {
  color: var(--accent-on-dark);
}
.section--dark .eyebrow::before {
  background: var(--accent-on-dark);
}

.lede {
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
}

.body-copy p + p {
  margin-top: var(--s-4);
}

.body-copy {
  color: var(--ink-2);
  max-width: 68ch;
}

.section-head {
  margin-bottom: var(--s-7);
  max-width: 60ch;
}

.section-head p {
  margin-top: var(--s-4);
  color: var(--ink-2);
}

.section-head--row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
  max-width: none;
}

/* ---------- 6. Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8rem 1.5rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  border-radius: 999px;
  border: 1px solid transparent;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease),
    border-color 0.18s var(--ease), transform 0.18s var(--ease);
}

.btn:hover {
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn--primary {
  background: var(--red);
  color: var(--on-red);
}
.btn--primary:hover {
  background: var(--red-dark);
  color: var(--on-red);
}

.btn--blue {
  background: var(--blue);
  color: #fff;
}
.btn--blue:hover {
  background: var(--blue-dark);
  color: #fff;
}

.btn--outline {
  border-color: var(--line-strong);
  color: var(--ink);
  background: transparent;
}
.btn--outline:hover {
  border-color: var(--ink);
  color: var(--ink);
  background: var(--paper-2);
}

.btn--ghost-light {
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
}
.btn--ghost-light:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border-color: #fff;
}

.btn--lg {
  padding: 1rem 2rem;
  font-size: 1rem;
}

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 3px;
  border-bottom: 2px solid var(--red);
}

.arrow-link::after {
  content: "→";
  transition: transform 0.18s var(--ease);
}

.arrow-link:hover {
  color: var(--red);
}
.arrow-link:hover::after {
  transform: translateX(4px);
}

.section--dark .arrow-link {
  color: #fff;
  border-color: var(--accent-on-dark);
}
.section--dark .arrow-link:hover {
  color: var(--accent-on-dark);
}

/* ---------- 7. Site header / nav ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  height: var(--nav-h);
}

/* Wordmark */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--ink);
  flex-shrink: 0;
}

/* The KBAA logo, cropped to just the circular emblem.
   Source file is 219x226 with the "KBAA" wordmark baked in underneath; the
   emblem occupies a 144x144 square starting at (37, 7). We window to that
   square in CSS so the wordmark isn't repeated next to the text beside it.
   Adjust --mark-size to resize; the offsets scale with it. */
.brand__logo {
  --mark-size: 42px;
  --src-w: 219;
  --src-crop: 144;
  --src-x: 37;
  --src-y: 7;

  width: var(--mark-size);
  height: var(--mark-size);
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  position: relative;
  background: #fff;
}

.brand__logo img {
  position: absolute;
  max-width: none;
  width: calc(var(--mark-size) * var(--src-w) / var(--src-crop));
  height: auto;
  left: calc(var(--mark-size) * var(--src-x) / var(--src-crop) * -1);
  top: calc(var(--mark-size) * var(--src-y) / var(--src-crop) * -1);
}

@media (min-width: 768px) {
  .brand__logo {
    --mark-size: 46px;
  }
}

.brand__text {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.brand__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
}

.brand__sub {
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 3px;
}

/* Nav buttons */
.nav__menu {
  display: none;
  align-items: center;
  gap: 0.15rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav__link {
  display: inline-block;
  padding: 0.5rem 0.85rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  border-radius: 999px;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease);
}

.nav__link:hover {
  background: var(--paper-2);
  color: var(--ink);
}

.nav__link[aria-current="page"] {
  color: var(--red);
  background: var(--red-soft);
  font-weight: 600;
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}

.nav__cta {
  display: none;
}

/* Hamburger */
.nav__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  align-items: center;
  border-radius: var(--radius);
}

.nav__toggle span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--ink);
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}

.nav__toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav__toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.nav__toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Mobile panel */
.nav__panel {
  position: fixed;
  inset: var(--nav-h) 0 0 0;
  background: var(--paper);
  padding: var(--s-6) var(--gutter) var(--s-8);
  overflow-y: auto;
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 0.28s var(--ease), visibility 0.28s var(--ease);
  z-index: 99;
}

.nav__panel.is-open {
  transform: translateX(0);
  visibility: visible;
}

.nav__panel ul {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-6);
}

.nav__panel li + li {
  border-top: 1px solid var(--line);
}

/* Scoped to the list so the CTA button below keeps its own styling. */
.nav__panel ul a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 0.25rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}

.nav__panel ul a::after {
  content: "→";
  color: var(--ink-3);
  font-family: var(--font-sans);
  font-size: 1rem;
}

.nav__panel ul a[aria-current="page"] {
  color: var(--red);
}
.nav__panel ul a[aria-current="page"]::after {
  color: var(--red);
}

.nav__panel .btn {
  width: 100%;
}

body.nav-open {
  overflow: hidden;
}

@media (min-width: 1080px) {
  .nav__menu {
    display: flex;
  }
  .nav__toggle {
    display: none;
  }
  .nav__cta {
    display: inline-flex;
  }
  .nav__panel {
    display: none;
  }
}

/* ---------- 8. Hero ---------- */

/* Film hero. The reel covers the entire first screen and, on desktop, past it.

   It is a 9:16 phone clip in a landscape frame, so cover crops it. How much it
   crops is pure arithmetic: the visible slice of the clip's height is
   9H/16W, where H and W are the hero's. On a 1440x900 display a
   viewport-height hero showed 28% of the frame. Growing H is the only lever
   that does not also shrink the video, so the hero runs past the fold:

     H = 100svh (820px)  ->  32% of the frame
     H = 138svh (1130px) ->  44% of the frame

   That is the trade being made here. The copy is pinned to the top of the
   hero rather than centred in it, so the buttons stay above the fold and the
   extra height is spent entirely on footage. */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  align-items: center;
  min-height: calc(100svh - var(--nav-h));
  padding-block: var(--s-8);
  background: #071227;
  color: #fff;
}

/* Only widescreen viewports crop the clip badly enough to be worth the extra
   scroll. Narrow ones already cover by height and show it nearly whole.
   Scoped to --film so a future plain .hero on another page keeps the ordinary
   one-screen height. */
@media (min-width: 900px) {
  .hero--film {
    align-items: start;
    /* 40vw only bites past ~3100px wide, where the 1240px cap would crop the
       top off the end-card roundel. See the end-card note below. */
    min-height: max(min(138svh, 1240px), 40vw);
    padding-block-start: clamp(2rem, 11svh, 7.5rem);
    padding-block-end: var(--s-10, 5rem);
  }
}

.hero__reel-video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  /* The clip is a high-angle shot: clean court across the top, the matchup and
     the burned-in "2026 KBAA ALL-STAR KOREA TOUR" title together across the
     bottom. Biasing the crop upwards puts the empty floor behind the headline
     and drops both the players and the burned title into the lower half of the
     hero, so the footage's own title stops competing with the h1. */
  object-position: 50% 30%;
}

/* Showing the whole end card.

   The clip finishes on 1.6s of black with the KBAA roundel centred: measured
   off the decoded frame, the logo occupies 43%-57% of the frame's height and
   37%-63% of its width. At 50% 30% that landed low in the hero, and on screens
   1920px and wider it fell outside the crop entirely — the bottom of the
   roundel was simply not rendered.

   For a frame fraction `a`, the geometry is
       px from top of hero = (a - p) * (16/9) * W  +  p * H
   for object-position 50% p, hero W x H. Raising p lifts the roundel up into
   the viewport, which is what is wanted.

   Raising p far enough to centre the roundel would also drag the burned-in
   "2026 KBAA ALL-STAR KOREA TOUR" card — which sits at 43.6%-55.7%, almost the
   same band — across the buttons. So the footage is left alone entirely: the
   crop above holds for all 47.5 seconds of it, and only the black end card is
   re-framed.

   The clip hard-cuts to black between 47.50s (still action, 95% of the frame
   lit) and 47.55s, sampled every 50ms. `main.js` switches at 47.52s and, since
   that frame is black apart from the roundel, moving the crop on it cannot be
   seen. It also sets a timer for the exact moment rather than relying on
   timeupdate, which only fires about 4Hz and would leave the roundel low for a
   quarter second after the cut.

   The 40vw floor on min-height keeps H >= 0.388W so the top of the roundel
   cannot fall outside the crop on ultrawide, where the 1240px cap would
   otherwise bite.

   The framing is applied instantly rather than eased. It used to transition
   over 1.2s, which had a real failure: a hidden document freezes transitions,
   so a backgrounded tab came back still rendering the old crop, and
   `getComputedStyle` reported the pre-transition value throughout, which made
   the behaviour impossible to verify. On a black frame there is nothing to
   ease anyway. */
.hero__reel-video.is-endcard {
  object-position: 50% 55%;   /* fallback; main.js computes the exact value */
}

/* There is deliberately no scrim, wash or pool over this video. The hero
   background is the footage and nothing else, by request. What used to sit
   here was a `.hero__tint` layer holding alpha 0.83-0.85 behind the copy,
   which is what put the hero text at AA. Removing it is a real accessibility
   regression, measured and written up under "Contrast" in the root README —
   read that before deciding this is fine. The type keeps its own text-shadows,
   which help on mid-tone footage and are not enough on bright court.

   To restore it: re-add `<div class="hero__tint" aria-hidden="true"></div>`
   as the first child of `.hero--film` after the <video>, and give it
   `position:absolute; inset:0; z-index:-1; pointer-events:none` plus a
   radial-gradient `72% 480px at 24% 385px` running rgba(4,11,24,.86) 0%,
   .83 70%, .36 84%, transparent 100% above 900px, and a vertical
   linear-gradient .78 0%, .85 9%, .85 96%, .45 100% below it. */

.hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  align-items: center;
}

@media (min-width: 900px) {
  .hero__copy {
    max-width: 46rem;
  }
}

/* Type over the reel: plain letterforms, nothing drawn on or behind them.

   An earlier pass put a dark stroke on every glyph. It measured well and
   looked like subtitling — heavy, and wrong for this page. What is here now is
   ordinary type with a wide, low-opacity shadow, which at these radii reads as
   depth rather than as an effect: no visible edge, no halo, no panel.

   It is a legibility aid, not a fix. Over the bright frames of this clip the
   copy is still low contrast; see "Contrast" in the root README for the
   measurements and the options. */
.hero__title {
  font-size: var(--fs-display);
  letter-spacing: -0.045em;
  color: #fff;
  text-shadow: 0 2px 28px rgba(2, 8, 18, 0.55);
}

.hero__title em {
  font-style: normal;
  color: var(--accent-on-dark);
}

/* Full-strength white rather than the old 0.9 alpha. Identical on screen,
   slightly better against a bright frame, costs nothing. */
.hero__sub {
  margin-top: var(--s-5);
  font-size: 1.125rem;
  color: #fff;
  max-width: 42ch;
  text-shadow: 0 1px 20px rgba(2, 8, 18, 0.6);
}

.hero .eyebrow {
  color: var(--accent-on-dark);
}

.hero .eyebrow::before {
  background: var(--accent-on-dark);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

.hero__reel-cap {
  display: grid;
  gap: 0.15rem;
  margin: var(--s-8) 0 0;
  color: #fff;
  text-shadow: 0 1px 20px rgba(2, 8, 18, 0.65);
}

.hero__reel-kicker {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-on-dark);
}

/* The date and "Coming soon" read as one line, so they share one row: the date
   carries the weight, the status trails it in lighter type. A pill or a chip
   would be a filled shape behind words, which is the one thing this hero is
   not doing. */
.hero__reel-dates {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.hero__reel-soon {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.78);
}

.hero__reel-link {
  justify-self: start;
  margin-top: 0.2rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.hero__reel-link:hover {
  color: var(--accent-on-dark);
}

/* Facts band. These three items used to sit inside the hero as a fourth
   text block, which pushed it past the point where a hero reads as one
   moment. They are their own strip directly under it now. */
.factband {
  border-block: 1px solid var(--line);
  background: var(--paper-2);
}

.factband dl {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-4);
  margin: 0;
  padding-block: var(--s-5);
}

@media (min-width: 640px) {
  .factband dl {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--s-6);
  }
}

.factband dt {
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}

.factband dd {
  margin: 0.3rem 0 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Page hero (inner pages) */
.page-hero {
  padding-block: var(--s-8) var(--s-7);
  border-bottom: 1px solid var(--line);
  background: var(--paper-2);
}

.page-hero h1 {
  max-width: 20ch;
}

.page-hero .lede {
  margin-top: var(--s-5);
}

/* Variant that carries an image beside the copy, for the pages that were
   running as walls of text. */
.page-hero--media .container {
  display: grid;
  gap: var(--s-6);
  align-items: center;
}

@media (min-width: 900px) {
  .page-hero--media .container {
    grid-template-columns: 1fr 0.85fr;
    gap: var(--s-8);
  }
}

.page-hero__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper-3);
}

.page-hero__media img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

/* ---------- 10. Cards ---------- */

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

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease),
    transform 0.2s var(--ease);
}

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

a.card:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
  transform: translateY(-3px);
}

.card p {
  color: var(--ink-2);
  font-size: 0.95rem;
}

/* Division cards (dark, like the reference's product cards) */
.division-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(250px, 1fr);
  gap: var(--s-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: var(--s-4);
  scrollbar-width: thin;
}

.division-strip > * {
  scroll-snap-align: start;
}

@media (min-width: 1080px) {
  .division-strip {
    grid-auto-flow: row;
    grid-template-columns: repeat(5, 1fr);
    overflow: visible;
  }
}

.division-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-7);
  min-height: 280px;
  padding: var(--s-5);
  border-radius: var(--radius-lg);
  background: linear-gradient(165deg, var(--navy-2) 0%, var(--navy) 100%);
  color: #fff;
  text-decoration: none;
  overflow: hidden;
  transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease);
}

.division-card::before {
  content: "";
  position: absolute;
  right: -40px;
  top: -40px;
  width: 140px;
  height: 140px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.12);
}

.division-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  color: #fff;
}

.division-card h3 {
  color: #fff;
  font-size: 1.35rem;
}

.division-card p {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.875rem;
  margin-top: var(--s-2);
}

.division-card__go {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: #fff;
}

/* Commitments: one lead cell carrying a photograph, one dark, one plain.
   Exactly three cells for three commitments, no filler tile. */
.commitments {
  display: grid;
  gap: var(--s-4);
}

@media (min-width: 900px) {
  .commitments {
    grid-template-columns: 1.55fr 1fr;
    align-items: stretch;
  }
  .commitment--lead {
    grid-row: 1 / span 2;
  }
}

.commitment {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper);
}

.commitment img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.commitment__body {
  padding: var(--s-6);
}

.commitment p {
  margin-top: var(--s-3);
  color: var(--ink-2);
  font-size: 0.95rem;
}

.commitment--lead {
  justify-content: flex-start;
}

.commitment--lead .commitment__body {
  margin-top: auto;
}

.commitment--dark {
  background: linear-gradient(165deg, var(--navy-2) 0%, var(--navy) 100%);
  border-color: transparent;
  color: #fff;
}

.commitment--dark h3 {
  color: #fff;
}

.commitment--dark p {
  color: rgba(255, 255, 255, 0.74);
}

/* ---------- 11. Feature / split sections ---------- */

.split {
  display: grid;
  gap: var(--s-6);
  align-items: center;
}

@media (min-width: 900px) {
  .split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-8);
  }
  .split--reverse > :first-child {
    order: 2;
  }
}

.split + .split {
  margin-top: var(--s-8);
}

.media {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper-3);
  display: grid;
  place-items: center;
}

.media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media--dark {
  background: linear-gradient(160deg, var(--navy-2), var(--navy));
  color: rgba(255, 255, 255, 0.5);
}

.media__caption {
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  padding: var(--s-4);
  color: var(--ink-3);
}

.media--dark .media__caption {
  color: rgba(255, 255, 255, 0.45);
}

.media-credit {
  margin-top: var(--s-3);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Wide feature banner */
.feature {
  display: grid;
  gap: var(--s-6);
  padding: var(--s-7);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--navy) 0%, #0d2a5c 100%);
  color: #fff;
  align-items: center;
  position: relative;
  overflow: hidden;
}

.feature::after {
  content: "";
  position: absolute;
  right: -80px;
  bottom: -120px;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(205, 46, 58, 0.35), transparent 65%);
}

@media (min-width: 900px) {
  .feature {
    grid-template-columns: 1.4fr auto;
    padding: var(--s-8);
  }
}

.feature h2 {
  color: #fff;
}

.feature p {
  color: rgba(255, 255, 255, 0.75);
  margin-top: var(--s-4);
  max-width: 52ch;
}

.feature__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  background: var(--red);
  color: var(--on-red);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: var(--s-4);
}

.feature__actions {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}

/* ---------- 12. Stats ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 768px) {
  .stats {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat {
  background: var(--paper);
  padding: var(--s-6) var(--s-5);
  text-align: center;
}

.stat__value {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 4vw, 3.25rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--blue);
}

.stat:nth-child(even) .stat__value {
  color: var(--red);
}

.stat__label {
  margin-top: var(--s-3);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}

/* ---------- 13. Tables ---------- */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
}

/* The table is wider than a phone, so the wrapper is a focusable scroll
   region — without tabindex there is no keyboard route to the last two
   columns, because nothing inside it can take focus. */
.table-wrap:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 3px;
}

.table-empty td {
  padding: var(--s-7) var(--s-5);
  text-align: center;
  color: var(--ink-2);
}

.table-empty strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--ink);
  margin-bottom: var(--s-2);
}

.table-empty button {
  margin-top: var(--s-4);
}

.data-table {
  min-width: 620px;
  font-size: 0.9375rem;
}

.data-table caption {
  text-align: left;
  padding: var(--s-4) var(--s-5);
  font-size: var(--fs-sm);
  color: var(--ink-3);
  border-bottom: 1px solid var(--line);
}

.data-table th,
.data-table td {
  padding: 0.85rem 1.25rem;
  text-align: left;
  border-bottom: 1px solid var(--line);
}

.data-table thead th {
  position: sticky;
  top: 0;
  background: var(--paper-2);
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 700;
  white-space: nowrap;
}

.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr:hover {
  background: var(--blue-soft);
}

.data-table .year {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.data-table .champ {
  font-weight: 600;
  color: var(--ink);
}

.data-table tr.is-hidden {
  display: none;
}

.data-table tr.is-void td {
  color: var(--ink-3);
  font-style: italic;
}

.pill {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  background: var(--red-soft);
  color: var(--red-dark);
  white-space: nowrap;
}

.pill--blue {
  background: var(--blue-soft);
  color: var(--blue);
}

/* --ink-3 on --paper-3 lands at 4.48:1, just under AA. The pills are small
   and bold, so this steps up to the secondary ink rather than lightening
   the chip. */
.pill--muted {
  background: var(--paper-3);
  color: var(--ink-2);
}

/* Filter bar */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-5);
}

.filters__search {
  flex: 1 1 240px;
  min-width: 200px;
}

.chip {
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-2);
  background: var(--paper);
  transition: all 0.16s var(--ease);
}

.chip:hover {
  border-color: var(--ink-3);
  color: var(--ink);
}

.chip[aria-pressed="true"] {
  background: var(--red);
  border-color: var(--red);
  color: var(--on-red);
}

.result-count {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  margin-left: auto;
}

/* Leaderboard */
.leaderboard {
  display: grid;
  gap: var(--s-3);
}

.leaderboard li {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
}

/* Keyed to rank, not row position — Los Angeles and Orange County are tied
   at seven titles, and position-based accents were telling the reader they
   finished first and second. */
.leaderboard li[data-rank="1"] {
  border-left: 4px solid var(--red);
}
.leaderboard li[data-rank="3"] {
  border-left: 4px solid var(--blue);
}
.leaderboard li[data-rank="5"] {
  border-left: 4px solid var(--line-strong);
}

.leaderboard__rank {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink-3);
}

.leaderboard__city {
  font-weight: 600;
}

.leaderboard__count {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
}

/* ---------- 14. Forms ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.field label {
  font-size: var(--fs-sm);
  font-weight: 600;
}

.field .hint {
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

.input,
.textarea,
.select {
  width: 100%;
  padding: 0.8rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--paper);
  font-size: 0.9375rem;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--ink-3);
}

.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(10, 58, 130, 0.14);
}

.input[aria-invalid="true"],
.textarea[aria-invalid="true"] {
  border-color: var(--red);
  box-shadow: 0 0 0 3px rgba(205, 46, 58, 0.12);
}

.textarea {
  min-height: 150px;
  resize: vertical;
}

.error-msg {
  font-size: var(--fs-xs);
  color: var(--red-dark);
  font-weight: 600;
  min-height: 1rem;
}

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

@media (min-width: 640px) {
  .form-grid--2 {
    grid-template-columns: repeat(2, 1fr);
  }
  .form-grid .span-2 {
    grid-column: 1 / -1;
  }
}

.form-status {
  margin-top: var(--s-4);
  padding: var(--s-4);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  background: var(--blue-soft);
  color: var(--blue-dark);
  display: none;
}

.form-status.is-visible {
  display: block;
}

/* Newsletter band (reference's newsletter block) */
.newsletter {
  display: grid;
  gap: var(--s-6);
  align-items: center;
}

@media (min-width: 900px) {
  .newsletter {
    grid-template-columns: 1fr 1.1fr;
    gap: var(--s-8);
  }
}

.newsletter__form {
  display: grid;
  gap: var(--s-3);
}

@media (min-width: 640px) {
  .newsletter__form {
    grid-template-columns: 1fr 1fr auto;
    align-items: start;
  }
  /* Each field stacks label → input → error. The button has no label above
     it, so it drops by exactly one label line to land on the input row. */
  .newsletter__form > .btn {
    margin-top: calc(var(--fs-sm) * 1.65 + var(--s-2));
  }
}

.newsletter__form .form-status {
  grid-column: 1 / -1;
  margin-top: 0;
}

/* ---------- 15. Gallery ---------- */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--s-4);
}

.gallery__item {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: linear-gradient(160deg, var(--navy-2), var(--navy));
  aspect-ratio: 4 / 3;
  cursor: zoom-in;
  color: #fff;
  text-align: left;
}

.gallery__item--tall {
  aspect-ratio: 3 / 4;
}

.gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--ease);
}

.gallery__item:hover img {
  transform: scale(1.04);
}

/* Logos and emblems: show the whole mark instead of cropping to fill. */
.gallery__item--contain img {
  object-fit: contain;
  padding: 14%;
  background: #fff;
}

.gallery__ph {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 0.35rem;
  text-align: center;
  padding: var(--s-4);
}

.gallery__ph span {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Reels we do not host. The still that used to fill these tiles belonged to
   another account, so the tile carries the caption and credit and Instagram
   serves the video itself. */
.gallery__item--linkonly .gallery__ph {
  place-content: start center;
  padding-top: 28%;
}

.gallery__item--linkonly .gallery__ph span {
  font-size: 1.15rem;
  opacity: 0.9;
}

.gallery__ph small {
  font-size: var(--fs-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.gallery__cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 2.5rem 1rem 0.9rem;
  background: linear-gradient(transparent, rgba(3, 12, 28, 0.88));
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* Reel tiles. The still is the poster frame; the badge says the tile opens a
   video rather than a photo. Nothing from Instagram loads until it is clicked
   (see initLightbox), so the grid stays fast and free of third-party requests. */
.gallery__item--reel::after {
  content: "";
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(3, 12, 28, 0.62)
    /* play triangle, drawn as a clipped square so there is no extra markup */;
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.35);
  transition: background-color 0.18s var(--ease), transform 0.18s var(--ease);
}

.gallery__item--reel::before {
  content: "";
  position: absolute;
  top: calc(var(--s-3) + 11px);
  right: calc(var(--s-3) + 12px);
  z-index: 1;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent #fff;
  transition: transform 0.18s var(--ease);
}

.gallery__item--reel:hover::after {
  background: var(--red);
  transform: scale(1.08);
}

/* Instagram's embed renders its own chrome at a fixed minimum width, so the
   viewer gives it a plain centred column rather than the photo frame. */
.lightbox__embed {
  position: relative;
  width: min(100%, 420px);
  margin-inline: auto;
  display: grid;
  place-items: center;
}

/* Instagram hard-codes min-width:326px inline, which overflows a 375px
   viewport once the lightbox padding is taken off. */
.lightbox__embed .instagram-media {
  margin: 0 auto !important;
  min-width: 0 !important;
  width: 100% !important;
}

/* embed.js writes `position:absolute` inline while it processes, which drops
   the iframe out of flow and sizes it against the fixed lightbox instead of
   this column. It also has no intrinsic height until Instagram resizes it by
   postMessage, so it needs a floor to sit on. */
.lightbox__embed iframe.instagram-media {
  position: relative !important;
  width: 100% !important;
  min-height: min(68vh, 560px);
  border-radius: var(--radius-lg);
  background: #fff;
}

/* Self-hosted reel. Sized like the photo viewer so switching between a photo
   tile and a video tile with the arrow keys does not jump the layout. */
.lightbox__video {
  display: block;
  height: min(72vh, 820px);
  width: auto;
  max-width: 100%;
  margin-inline: auto;
  border-radius: var(--radius-lg);
  background: #000;
}

.lightbox__loading {
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.7);
}

.lightbox__out {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: #fff;
}

/* Source account for reposted images. */
.gallery__credit {
  display: block;
  margin-top: 0.15rem;
  font-style: normal;
  font-weight: 500;
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.62);
}

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(3, 10, 24, 0.94);
  display: none;
  place-items: center;
  padding: var(--s-6);
}

.lightbox.is-open {
  display: grid;
}

.lightbox__stage {
  max-width: 1000px;
  width: 100%;
  text-align: center;
  color: #fff;
}

/* The frame takes the shape of whatever is in it. A fixed 16:10 box cropped
   every portrait image and upscaled 360px stills to 1000px wide; letting the
   image size itself means each photo is shown whole, at its own ratio, and
   never past its native resolution. */
.lightbox__frame {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 0;
}

/* Sized by height so portrait and landscape share a baseline, then reined in
   by max-width so a wide photo can't run past the stage. 72vh keeps a 640px
   still inside ~110% of native — the ceiling before these go soft. */
.lightbox__frame img {
  height: min(72vh, 820px);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--navy-2), #030d1f);
}

.lightbox__frame .lightbox__ph {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--navy-2), #030d1f);
}

.lightbox__ph {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4vw, 2.5rem);
  color: rgba(255, 255, 255, 0.5);
}

.lightbox__cap {
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.75);
}

.lightbox__btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.25rem;
  display: grid;
  place-items: center;
  transition: background 0.16s var(--ease);
}

.lightbox__btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

.lightbox__btn--prev {
  left: var(--s-4);
}
.lightbox__btn--next {
  right: var(--s-4);
}

.lightbox__close {
  position: absolute;
  top: var(--s-4);
  right: var(--s-4);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.25rem;
  display: grid;
  place-items: center;
}

.lightbox__close:hover {
  background: var(--red);
}

/* ---------- 16. News ---------- */

.news-list {
  display: grid;
  gap: var(--s-5);
}

.news-item {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.news-item:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
}

/* Capped on small screens so it stays a thumbnail rather than becoming a
   full-width lead image above every headline. */
.news-item__thumb {
  width: 100%;
  max-width: 200px;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--paper-3);
}

@media (min-width: 768px) {
  .news-item {
    grid-template-columns: 170px minmax(0, 1fr);
    gap: var(--s-4) var(--s-6);
    align-items: start;
  }
  /* Thumb and meta stack in the narrow left column; the copy spans both rows
     on the right. Items without a thumb collapse to a single left row. */
  .news-item__thumb,
  .news-item__meta {
    grid-column: 1;
  }
  .news-item > div:last-child {
    grid-column: 2;
    grid-row: 1 / -1;
  }
  .news-item__thumb {
    aspect-ratio: 4 / 3;
  }
}

.news-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
}

.news-item__date {
  font-size: var(--fs-sm);
  color: var(--ink-3);
  font-weight: 600;
}

.news-item h3 {
  margin-bottom: var(--s-3);
}

.news-item p {
  color: var(--ink-2);
  margin-bottom: var(--s-4);
}

/* ---------- 17. Teams / people ---------- */

.team-card {
  position: relative;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}

.team-card:hover {
  border-color: var(--line-strong);
  transform: translateY(-3px);
  box-shadow: var(--shadow);
}

.team-card__city {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.team-card__region {
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
  margin-top: 0.15rem;
}

.team-card__stats {
  display: flex;
  gap: var(--s-5);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}

.team-card__stats div {
  display: flex;
  flex-direction: column;
}

.team-card__stats b {
  font-family: var(--font-display);
  font-size: 1.35rem;
  line-height: 1;
  color: var(--blue);
}

.team-card--champ b {
  color: var(--red);
}

.team-card__stats span {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-top: 0.3rem;
}

/* One grid for all seventeen cities. The region headings are full-width rows
   inside it, so the page reads as a single directory instead of the same
   three-column card block repeated three times. */
.city-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--s-4);
}

.city-grid__region {
  grid-column: 1 / -1;
  font-size: var(--fs-h3);
  margin-top: var(--s-5);
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}

.city-grid__region:first-child {
  margin-top: 0;
}

/* Cities that have won carry the accent; the rest stay quiet. */
.city-grid .team-card--champ {
  background: var(--paper-2);
  border-color: var(--line-strong);
}

/* Squad portraits. All eight are near-square lineup shots, so they sit on a
   shared 4:3 crop biased upward to keep faces and jerseys in frame. */
.squad-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--s-4);
}

.squad {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper);
}

.squad img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 38%;
}

.squad figcaption {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: var(--s-3) var(--s-4);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
}

/* The squad that won. Marked with a badge rather than a coloured edge, so it
   reads as information instead of decoration. */
.squad--champ {
  border-color: var(--line-strong);
  background: var(--paper-2);
}

.squad__badge {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--red);
  color: var(--on-red);
  white-space: nowrap;
}

.person {
  display: flex;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
}

.person__avatar {
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  background: var(--blue-soft);
  color: var(--blue);
}

.person:nth-child(3n + 1) .person__avatar {
  background: var(--red-soft);
  color: var(--red-dark);
}

.person__name {
  font-weight: 600;
  line-height: 1.3;
}

.person__role {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.person__city {
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-top: 0.15rem;
}

/* Staff, not board. The twelve officers below are volunteers elected to the
   board; an intern sitting inside that grid would read as one of them, so this
   is its own full-width row above it, separated by a rule. Same .person
   component so it still belongs to the page. */
.staff-row {
  margin-bottom: var(--s-6);
  padding-bottom: var(--s-6);
  border-bottom: 1px solid var(--line);
}

.staff-row__label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-4);
}

.person--staff {
  flex-wrap: wrap;
  row-gap: var(--s-4);
}

/* Pushes the button to the trailing edge on a wide card, and lets it drop
   below the name on a narrow one rather than squeezing the role text. */
.person__cta {
  margin-left: auto;
  flex-shrink: 0;
}

@media (max-width: 599px) {
  .person__cta {
    margin-left: 0;
    width: 100%;
    text-align: center;
  }
}

/* ---------- 17b. Staff bio page ---------- */

.bio {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}

@media (min-width: 900px) {
  .bio {
    grid-template-columns: 320px 1fr;
    gap: var(--s-8);
  }
}

/* Sits below the bio text, in the wide column rather than the 320px contact
   rail. It is an action shot with five players in it, not a headshot — at rail
   width it rendered 270px across and nothing in it was legible.

   The source is 800x791, near square. 4:3 crops it to 76% of its height,
   centred, which keeps the subject's head (31% down) and his shoes (88%) both
   inside the frame; anything wider starts cutting his feet off. */
.bio__portrait {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 50%;
  border-radius: var(--radius-lg);
  margin-top: var(--s-6);
  background: var(--paper-3);
}

.bio__contact {
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper-2);
}

.bio__contact-title {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.contact-list {
  display: grid;
  gap: var(--s-4);
  margin: var(--s-4) 0 0;
}

.contact-list dt {
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.contact-list dd {
  margin: 0.15rem 0 0;
  font-size: 1.0625rem;
  font-weight: 600;
}

/* Long addresses must not push the card wider than its column. */
.contact-list dd a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  overflow-wrap: anywhere;
}

.contact-list dd a:hover {
  color: var(--red);
}

/* ---------- 18. Division detail (tournament page) ---------- */

.division-detail {
  display: grid;
  gap: var(--s-5);
  padding-block: var(--s-7);
  border-top: 1px solid var(--line);
  scroll-margin-top: calc(var(--nav-h) + 2rem);
}

@media (min-width: 900px) {
  .division-detail {
    grid-template-columns: 200px 1fr 220px;
    gap: var(--s-7);
    align-items: start;
  }
}

.division-detail h3 {
  font-size: 1.6rem;
  margin-bottom: var(--s-3);
}

.division-detail blockquote {
  margin: 0;
  color: var(--ink-2);
  font-size: 1.0625rem;
}

.division-detail dl {
  display: grid;
  gap: var(--s-3);
  font-size: var(--fs-sm);
}

.division-detail dt {
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 700;
}

.division-detail dd {
  margin: 0.15rem 0 0;
  font-weight: 500;
}

/* Steps */
.steps {
  counter-reset: step;
  display: grid;
  gap: var(--s-5);
}

@media (min-width: 768px) {
  .steps {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  }
}

.steps li {
  counter-increment: step;
  position: relative;
  padding-top: var(--s-5);
  border-top: 2px solid var(--line);
}

.steps li::before {
  content: "0" counter(step);
  position: absolute;
  top: -0.85rem;
  left: 0;
  background: var(--paper);
  padding-right: 0.6rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--red);
  letter-spacing: 0.08em;
}

.section--alt .steps li::before {
  background: var(--paper-2);
}

.steps h3 {
  font-size: 1.1rem;
  margin-bottom: var(--s-2);
}

.steps p {
  color: var(--ink-2);
  font-size: 0.9375rem;
}

/* ---------- 19. Footer ---------- */

.site-footer {
  background: var(--navy);
  color: rgba(255, 255, 255, 0.72);
  padding-block: var(--s-8) var(--s-5);
  font-size: 0.9375rem;
}

.footer__grid {
  display: grid;
  gap: var(--s-7);
}

@media (min-width: 768px) {
  .footer__grid {
    grid-template-columns: 1.6fr 1fr 1fr;
    gap: var(--s-8);
  }
}

.site-footer .brand {
  color: #fff;
}

.site-footer .brand__sub {
  color: rgba(255, 255, 255, 0.5);
}

.footer__blurb {
  margin-top: var(--s-4);
  max-width: 42ch;
  color: rgba(255, 255, 255, 0.65);
}

.footer__title {
  font-size: var(--fs-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #fff;
  font-weight: 700;
  margin-bottom: var(--s-4);
}

.footer__links {
  display: grid;
  gap: 0.6rem;
}

.footer__links a {
  color: rgba(255, 255, 255, 0.72);
  text-decoration: none;
}

.footer__links a:hover {
  color: #fff;
  text-decoration: underline;
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  justify-content: space-between;
  align-items: center;
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.5);
}

.footer__flag {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

.footer__flag i {
  width: 20px;
  height: 3px;
  border-radius: 2px;
  display: block;
}

.footer__flag i:nth-child(1) {
  background: var(--red);
}
.footer__flag i:nth-child(2) {
  background: #fff;
}
.footer__flag i:nth-child(3) {
  background: var(--blue);
}

/* ---------- 20. Utilities & motion ---------- */

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.stack > * + * {
  margin-top: var(--s-4);
}
.stack-lg > * + * {
  margin-top: var(--s-6);
}

.mt-5 {
  margin-top: var(--s-5);
}
.mt-6 {
  margin-top: var(--s-6);
}
.mt-7 {
  margin-top: var(--s-7);
}

.text-center {
  text-align: center;
}

/* Prose held to a readable measure when it is not inside .body-copy. */
.measure-prose {
  max-width: 68ch;
}

/* Centred measure — replaces the inline margin-inline/max-width pairs. */
.measure-center {
  margin-inline: auto;
  max-width: 52ch;
}

.note {
  padding: var(--s-4) var(--s-5);
  border-left: 3px solid var(--blue);
  background: var(--blue-soft);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--fs-sm);
  color: var(--blue-dark);
}

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
  }
}

@media print {
  .site-header,
  .site-footer,
  .filters,
  .nav__panel {
    display: none !important;
  }
}

/* ---------- 1b. Dark mode ----------
   Every surface is redefined at the token level, so components don't need
   per-rule overrides. The flag red and blue stay recognisable: red lifts
   slightly to clear 4.5:1 on a dark ground, blue lifts a lot, because the
   brand blue is far too dark to read as an accent here.

   The navy panels are the one thing that can't simply invert. On a white page
   they read as "the dark surface"; on a dark page they'd vanish. They become
   a lighter, bluer slate so they stay a distinct plane, which keeps the page
   on one theme rather than flipping mid-scroll. */
@media (prefers-color-scheme: dark) {
  :root {
    --red: #ff6b74;
    --red-dark: #ff8f96;
    --red-soft: #3a1418;
    --on-red: #2a0a0d;
    --blue: #7aa7ee;
    --blue-dark: #a9c6f5;
    --blue-soft: #16233d;

    --navy: #16203a;
    --navy-2: #1e2c4d;

    --ink: #eef0f4;
    --ink-2: #b6bcc9;
    --ink-3: #949bab;

    --paper: #0d1117;
    --paper-2: #141a22;
    --paper-3: #1c232d;

    --line: #262d38;
    --line-strong: #3a4350;

    --accent-on-dark: #ff8f96;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow: 0 4px 24px rgba(0, 0, 0, 0.55);
    --shadow-lg: 0 18px 60px rgba(0, 0, 0, 0.7);
  }

  /* Surfaces that hard-code white in light mode. */
  .site-header {
    background: rgba(13, 17, 23, 0.9);
  }

  .brand__logo,
  .gallery__item--contain img {
    background: #e9ecf1;
  }

  .stat,
  .card,
  .news-item,
  .team-card,
  .person,
  .chip,
  .table-wrap,
  .input,
  .textarea,
  .select,
  .commitment {
    background: var(--paper-2);
  }

  .data-table thead th {
    background: var(--paper-3);
  }

  .stats {
    background: var(--line);
  }

  .steps li::before {
    background: var(--paper);
  }

  .section--alt .steps li::before {
    background: var(--paper-2);
  }

  /* The lightened panels no longer need white text forced over them, but the
     type inside them is still light-on-dark, so it stays as authored. */
  .site-footer {
    background: var(--paper-2);
    border-top: 1px solid var(--line);
  }

  .footer__flag i:nth-child(2) {
    background: #e9ecf1;
  }
}
