/* AWS Agentic Cup — one design system.
   Spec: docs/superpowers/specs/2026-07-29-landing-and-onboarding-design.md §2
   Rules: three accent colours max · no box-shadow · hairline borders only. */

/* ---------- tokens ---------- */
:root {
  --bg: #06080F;
  --page-gutter: 48px;
  --surface: #0E1119;
  /* One more rung on the surface ladder, for objects that sit ON a card —
     the league table and the award cards in WHAT YOU WIN. Elevation here is
     colour + hairline, never a heavier shadow. */
  --surface-2: #141824;
  --line: rgba(255, 255, 255, .08);
  --line-strong: rgba(255, 255, 255, .18);
  --ink: #F5F6F8;
  --ink-dim: #8A8F9C;
  /* Brand orange scale: keep the dark theme vivid without the old neon red. */
  --orange-100: #fff0df;
  --orange-600: #FD8D1D;
  --accent-100: var(--orange-100);
  --accent-600: var(--orange-600);
  --accent-hover: #d96608;
  --accent-soft: rgba(253, 141, 29, .14);
  --neon: var(--accent-600);
  --aws: var(--accent-600);
  --volt: #3D8BFF;

  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 40px;
  --space-5: 64px;
  --space-6: 96px;
  --section-y: 160px;
  --sitenav-height: 60px;

  /* Makes the UA paint checkboxes, autofill and scrollbars dark. Without it an
     unchecked checkbox is a solid white block — the brightest thing on the
     page after the CTA, and a second boldness centre. */
  color-scheme: dark;

  --radius: 20px;
  --radius-sm: 12px;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --dur: 520ms;
}

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

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

html { background: var(--bg); }

body {
  margin: 0;
  color: var(--ink);
  font: 400 17px/1.65 "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  overflow-x: hidden;
}

/* ---------- ambient glow ----------
   Flat black below the hero read as dead space. Three very low-opacity light
   pools drift behind everything so the page has depth without any element
   actually being decorated. Killed by the reduced-motion block. */
body::before {
  content: "";
  position: fixed;
  inset: -10%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(42% 30% at 16% 14%, rgba(61, 139, 255, .14), transparent 72%),
    radial-gradient(38% 28% at 88% 44%, rgba(253, 141, 29, .10), transparent 74%),
    radial-gradient(50% 34% at 46% 92%, rgba(61, 139, 255, .09), transparent 76%);
  animation: ambient-drift 28s ease-in-out infinite alternate;
}

@keyframes ambient-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-2%, -4%, 0) scale(1.12); }
}

/* height:auto is load-bearing — every img here carries width/height attributes
   (good for layout stability), and without this any CSS width change stretches
   the picture to the attribute height. */
img { max-width: 100%; height: auto; display: block; }

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

/* ---------- type ---------- */
/* Stepped down from 5.5rem: the hero now carries a description line under the
   headline, and at the old size the three uppercase lines ate the fold before
   the sentence that explains the season got a chance to be read. */
.display {
  font-size: clamp(2.3rem, 5.5vw, 4.75rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: .91;
  text-transform: uppercase;
  margin: 0;
  text-wrap: balance;
}

/* The setup line above the claim — sized relative to .display so the pair
   scales as one lockup through the clamp. */
.display__kick {
  display: block;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: clamp(1.3rem, 2.7vw, 3.5rem);
  font-weight: 400;
  letter-spacing: -.01em;
  line-height: 1.2;
  margin-bottom: .4em;
  text-transform: none;
}

.display__hot { color: var(--neon); }
.display__main,
.display__amount,
.display__prize { display: block; }
.display__amount { margin-top: .06em; }
.display__main {
  max-width: 23ch;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: clamp(1.5rem, 3.6vw, 4.1rem);
  line-height: 1.02;
  text-transform: none;
}
.display__prize {
  max-width: 32ch;
  margin-top: .5em;
  color: var(--ink);
  font-size: clamp(1.15rem, 1.9vw, 2rem);
  font-weight: 300;
  letter-spacing: -.015em;
  line-height: 1.2;
  text-transform: none;
}

h2 {
  font-size: clamp(1.9rem, 4.5vw, 3.4rem);
  font-weight: 700;
  letter-spacing: -.035em;
  line-height: 1.02;
  margin: 0 0 var(--space-3);
}

#how > .wrap > h2,
#faq > .wrap > h2,
#reward .win__head--solo h2,
#register .duo__intro h2 {
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
}

h3 {
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
  margin: 0 0 var(--space-1);
  color: var(--ink);
}

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 var(--space-2);
}

p {
  color: var(--ink-dim);
  margin: 0 0 var(--space-2);
}

.lede {
  font-size: clamp(1rem, 1.5vw, 1.2rem);
  color: var(--ink);
  max-width: 52ch;
}

/* ---------- layout ---------- */
.wrap {
  width: min(1200px, 100% - (2 * var(--page-gutter)));
  margin-inline: auto;
}

section { padding-block: var(--section-y); }

/* ---------- components ---------- */
.card {
  background: linear-gradient(145deg, rgba(255, 255, 255, .035), transparent 42%), var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-4);
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 48px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 180ms var(--ease), background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.btn:hover { border-color: rgba(255, 255, 255, .34); transform: translateY(-1px); }
.btn:active { transform: translateY(1px) scale(.98); }

.btn--primary {
  background: var(--neon);
  border-color: var(--neon);
  color: #0B0600;
}

.btn--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* aria-disabled is matched alongside :disabled throughout — the gate's confirm
   uses the attribute rather than the property so a keyboard user can still land
   on it and be told why it won't go yet. */
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .38;
  cursor: not-allowed;
}

/* A faded neon fill reads as "broken", not "not yet". Drop back to the ghost
   treatment while disabled so the fill arriving is the reward for finishing. */
.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  opacity: 1;
  background: transparent;
  border-color: var(--line);
  color: var(--ink-dim);
}

.btn--primary:disabled .btn__chip,
.btn--primary[aria-disabled="true"] .btn__chip { background: rgba(255, 255, 255, .06); }

.btn__chip {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .18);
  font-size: 13px;
  line-height: 1;
}

.btn--primary .btn__chip { background: rgba(0, 0, 0, .22); }

/* The outbound arrow is drawn, not typed: U+2197 renders as a colour emoji on
   some Android font stacks, which is not a thing you can style back down. */
.btn__chip svg { display: block; }

/* ---------- visually hidden ---------- */
/* For live-region text that must be announced but never seen. clip-path alone
   is not enough — a zero-size box drops out of some screen readers' buffers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- skip link ---------- */
.skip {
  position: absolute;
  left: -9999px;
  top: var(--space-2);
  z-index: 100;
  padding: 12px var(--space-3);
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  text-decoration: none;
}

.skip:focus { left: var(--space-3); }

/* ---------- hero ---------- */
/* The nav is sticky and sits in flow above this, so the negative top margin
   pulls the photo back up behind it — the bar floats over the image rather
   than sitting on a 72px black shelf above it. The matching padding keeps the
   copy clear of the bar. */
.hero {
  position: relative;
  margin-top: -72px;
  background-color: #000;
  display: flex;
  align-items: center;
  padding-block: calc(var(--space-6) + 72px) var(--space-5);
  overflow: hidden;
}

.hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right 70%;
  animation: kenburns 1.6s var(--ease) both;
  will-change: transform;
}

.hero__picture { display: contents; }

/* Desktop and tablet use a lateral scrim to protect the copy while retaining
   the full photo. The stronger vertical fade is reserved for phone crops. */
.hero__scrim {
  position: absolute;
  inset: 0;
  /* Deepened 2026-07-30 (Gwen: type was fighting the photo) — the left half
     where every line of copy sits goes darker; the right keeps the neon. */
  background:
    linear-gradient(to bottom,
      rgba(6, 8, 15, .66) 0%,
      rgba(6, 8, 15, 0) 26%),
    linear-gradient(to right,
      rgba(6, 8, 15, .84) 0%,
      rgba(6, 8, 15, .48) 44%,
      rgba(6, 8, 15, 0) 78%);
}

/* Very light grain — hides softness from upscaling the 1672px source. */
.hero__grain {
  position: absolute;
  inset: 0;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* No max-width here: it would fight .wrap's auto margins and shove the
   whole block into a narrow centred column. Cap the prose children instead. */
.hero__body {
  position: relative;
  width: min(90vw, 100% - 96px);
}

.hero__cup-logo {
  width: clamp(260px, 26vw, 400px);
  height: auto;
  margin: 0 0 var(--space-3);
}

.hero__title {
  max-width: 44ch;
  margin: var(--space-3) 0 0;
  font-size: clamp(1.1rem, 1.25vw, 1.3rem);
  font-weight: 700;
  letter-spacing: -.015em;
  line-height: 1.45;
}

.hero__subtitle {
  max-width: 44ch;
  margin: var(--space-2) 0 0;
  color: var(--orange-600);
  font-size: clamp(1rem, 1.15vw, 1.2rem);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.35;
}

/* Narrower than the global 52ch: beside a photographic hero a long measure
   loses its left edge against the scrim. */
.hero__lede {
  margin: calc(var(--space-3) + 4px) 0 0;
  max-width: 38ch;
  color: #8a8a9c;
  font-size: clamp(1rem, 1.25vw, 1.15rem);
  line-height: 1.55;
}

.hero__meta {
  font-size: 14px;
  margin-top: 10px;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: 28px;
}

.hero__cta .btn {
  min-height: 56px;
  padding-inline: var(--space-4);
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 24px;
}

/* The pitch paragraphs sit under the CTA: one size down from the lede and
   measure-bound, so they read as supporting copy without competing with the
   buttons above them. */
.hero__pitch {
  margin: var(--space-2) 0 0;
  max-width: 44ch;
  font-size: 15px;
  line-height: 1.55;
}
.hero__pitch p { margin: 0; }
.hero__pitch p + p { margin-top: var(--space-2); }

.hero__registration-note {
  margin: var(--space-2) 0 0;
  color: var(--ink-dim);
  font-size: 13px;
}

.hero__deadline {
  margin: var(--space-2) 0 0;
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .01em;
}
.hero__deadline strong { color: var(--ink); }

@keyframes kenburns {
  from { transform: scale(1.06); }
  to   { transform: scale(1); }
}

/* ---------- countdown ---------- */
/* The frame: dark glass so the clock stays readable over the photo. Docked
   bottom-right of the hero on desktop; in the flow below the CTAs on
   anything narrower. */
.countbox {
  width: fit-content;
  margin-top: var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: 1px solid rgba(253, 141, 29, .35);
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, rgba(253, 141, 29, .12), transparent 60%), rgba(6, 8, 15, .68);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.countbox__label { margin-bottom: var(--space-1); }

@media (min-width: 1100px) {
  .countbox {
    position: absolute;
    right: 0;
    bottom: 0;
    margin-top: 0;
  }
}

.countdown {
  display: flex;
  gap: var(--space-3);
}

.countdown__unit {
  display: grid;
  gap: 2px;
  min-width: 62px;
}

.countdown__num {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.countdown__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- urgency bar ---------- */
.urgency {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-block: 1px solid var(--line);
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink-dim);
}

.urgency--hot {
  color: var(--neon);
  border-color: rgba(253, 141, 29, .34);
  background: rgba(253, 141, 29, .06);
}

/* ---------- toast ---------- */
/* Centred by left+right inset rather than left:50%. With only left:50% the
   available width is 50vw, so on a phone the message wrapped to three lines
   inside a pill and landed on top of the CTA it was reporting about. */
.toast {
  position: fixed;
  left: var(--space-2);
  right: var(--space-2);
  bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  margin-inline: auto;
  width: max-content;
  max-width: min(420px, calc(100% - var(--space-4)));
  translate: 0 12px;
  z-index: 90;
  padding: 12px var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), translate var(--dur) var(--ease);
}

.toast.is-on {
  opacity: 1;
  translate: 0 0;
}

/* ---------- scroll reveal ---------- */
/* Gated behind .js: if the script fails to load, every section stays visible
   rather than being permanently invisible at opacity 0. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* ---------- two-column section (intro + panel) ---------- */
.duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  align-items: start;
}

.duo__intro { position: sticky; top: var(--space-5); }

.ticks {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}

.ticks li {
  position: relative;
  padding-left: 26px;
  color: var(--ink-dim);
  font-size: 15px;
}

/* Hairline tick, not an emoji — emoji bullets are the generic-AI tell. */
.ticks li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 8px;
  width: 10px;
  height: 5px;
  border-left: 1.5px solid var(--volt);
  border-bottom: 1.5px solid var(--volt);
  rotate: -45deg;
}

/* ---------- form ---------- */
.form { display: grid; gap: var(--space-3); }

/* Registration is the page's primary action: lift it onto a distinct slate
   panel so the fields read as a deliberate conversion surface, not another
   section of background. */
#register-form {
  background:
    radial-gradient(88% 80% at 108% -8%, rgba(80, 118, 192, .38), transparent 66%) padding-box,
    radial-gradient(80% 72% at -8% 108%, rgba(25, 58, 116, .28), transparent 64%) padding-box,
    linear-gradient(145deg, rgba(47, 61, 93, .82), rgba(18, 25, 44, .98) 52%, rgba(8, 12, 22, 1)) padding-box,
    linear-gradient(135deg, #FD8D1D 0%, #B7B7B7 48%, #626A78 100%) border-box;
  border: 2px solid transparent;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .15),
    inset 0 0 0 1px rgba(208, 224, 255, .08),
    0 24px 56px rgba(0, 0, 0, .34),
    0 0 46px rgba(253, 141, 29, .2),
    0 0 72px rgba(52, 105, 224, .12);
}

#register-form.form--light {
  background: #F5F6F8;
  border: 1px solid #D5DAE3;
  box-shadow: none;
  color: #0D1220;
}

#register-form.form--light .field label { color: #0D1220; }

#register-form.form--light .field input,
#register-form.form--light .field select {
  border-color: #C9CFDA;
  /* background-color, not the shorthand: the shorthand's ID specificity would
     reset the select chevron's no-repeat/position/size and tile it. */
  background-color: #FFFFFF;
  color: #0D1220;
}

#register-form.form--light .field input::placeholder { color: #6B7280; }
#register-form.form--light .field :is(input, select):hover { border-color: #9AA4B2; }
#register-form.form--light .check,
#register-form.form--light .check em,
#register-form.form--light .form__note { color: #5B6472; }
#register-form.form--light .formerror { color: #9C2F24; }
#register-form.form--light .check input { accent-color: #0D1220; }

#register-form.form--light .form__submit {
  width: fit-content;
  min-width: 0;
  min-height: 56px;
  justify-self: start;
  padding-inline: var(--space-4);
  font-size: 24px;
}

.field { display: grid; gap: 6px; }
/* The author display beats the UA's [hidden] rule — same fix as .done__entry. */
.field[hidden] { display: none; }

.field label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

#register-form .field label { color: var(--orange-600); }

.field input,
.field select {
  min-height: 52px;
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--ink);
  /* 16px floor — anything smaller makes iOS Safari zoom on focus.
     Longhands on purpose: `inherit` is not a legal family inside the `font`
     shorthand, so the whole declaration would be dropped and inputs would
     fall back to 13.3px Arial. */
  font-family: inherit;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  transition: border-color var(--dur) var(--ease);
}

/* Placeholders carry real guidance here, so they hold AA rather than fading
   to the decorative grey a placeholder usually gets. */
.field input::placeholder { color: rgba(138, 143, 156, .92); }

/* The country select swaps the UA arrow for a drawn chevron: the native one
   inherits the OS widget colour and can vanish on the dark field. */
.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238A8F9C' stroke-width='1.5'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 16px;
}

/* Until a country is picked the select shows its placeholder option, which
   should read like the inputs' placeholders, not like an answer. */
.field select:invalid { color: rgba(138, 143, 156, .92); }

#register-form.form--light .field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%230D1220' stroke-width='1.5'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
}

#register-form.form--light .field select:invalid { color: #6B7280; }
.field :is(input, select):hover { border-color: var(--line-strong); }
/* Only the mouse-focus ring goes; :focus-visible keeps its ring for keyboards,
   otherwise the focused field looks identical to a hovered one. */
.field :is(input, select):focus { border-color: var(--volt); }
.field :is(input, select):focus:not(:focus-visible) { outline: none; }

.field__hint {
  margin: 0;
  font-size: 13px;
  color: var(--ink-dim);
  min-height: 1.4em;
}

.field__error {
  margin: 0;
  color: #A83225;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
}

#register-form.form--light .field__error { color: #9C2F24; }

.check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 44px;
  padding-block: 4px;
  font-size: 15px;
  color: var(--ink-dim);
  cursor: pointer;
}

.check input {
  flex: none;
  width: 22px;
  height: 22px;
  margin: 2px 0 0;
  accent-color: #151b28;
  cursor: pointer;
}

.check em { font-style: normal; color: var(--ink-dim); }

/* The AWS opt-in carries a legally-required unsubscribe paragraph — quieter
   than the consent line itself, but still readable. */
.check small {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
}

.check a { color: inherit; text-decoration: underline; }

.formerror {
  margin: 0;
  padding: 8px 10px;
  border: 1px solid rgba(202, 70, 47, .38);
  border-radius: 6px;
  background: transparent;
  color: #A83225;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
}

/* The banner lives above the submit button, which on a phone can be a screen
   away from the field that is actually focused. This marks the offending field
   itself, so the signal is wherever the user's attention already is. Set by
   mountForm, cleared on input — never by :invalid, which would light up every
   required field before anyone had typed a character. */
.field :is(input, select).is-bad,
.field :is(input, select).is-bad:hover {
  border-color: #CA4630;
  /* background-color, not the shorthand, or the error state re-tiles the
     select's chevron (same trap as the light-mode and mindcard rules). */
  background-color: rgba(202, 70, 47, .06);
}

.field :is(input, select).is-bad:focus {
  box-shadow: 0 0 0 3px rgba(202, 70, 47, .16);
}

.form__submit {
  justify-content: center;
  justify-self: stretch;
  width: 100%;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
}

.form__note {
  margin: 0;
  font-size: 13px;
  text-align: left;
}

/* The three documents the submit commits you to, one tap away from the
   button that does the committing. Text links, not buttons — they must not
   compete with the primary action they sit under. */
.form__legal {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 4px var(--space-3);
  font-size: 13px;
  color: var(--ink-dim);
}

.form__legal a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.form__legal a:hover { color: var(--ink); }
#register-form.form--light .form__legal { color: #5B6472; }
#register-form.form--light .form__legal a:hover { color: #0D1220; }

/* ---------- register modal ---------- */
.modal {
  width: min(520px, 100% - 32px);
  max-height: min(92svh, 860px);
  margin: auto;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  overflow: auto;
  overscroll-behavior: contain;
}

.modal--light {
  border-color: #D5DAE3;
  background: #F5F6F8;
  color: #0D1220;
}

/* Near-opaque, because the hero photo behind it is busy enough to make a
   half-lit form look like it is still loading. */
.modal::backdrop { background: rgba(6, 8, 15, .78); }

/* Tighter top and bottom than the sides: the form is 850px of fields, and the
   40px it saves is what keeps the submit and its note above the fold at 900. */
.modal__panel { position: relative; padding: var(--space-3) var(--space-4); }

.modal--light .modal__panel { background: #F5F6F8; }
.modal--light .modal__close { border-color: #C9CFDA; color: #5B6472; }
.modal--light #register-form.form--light {
  background: transparent;
  border: 0;
  box-shadow: none;
}

.modal__title { margin: 0 0 var(--space-3); font-size: clamp(1.6rem, 3vw, 2.2rem); }

.modal__close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: none;
  color: var(--ink-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.modal__close:hover { color: var(--ink); border-color: var(--line-strong); }

/* showModal() makes the background inert but does not stop it scrolling —
   without this the page slides around behind the open form. */
.is-modal-open { overflow: hidden; }

/* ---------- FAQ ---------- */
.faq {
  border-top: 1px solid var(--line);
  width: 100%;
}

.faq__item { border-bottom: 1px solid var(--line); }

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 64px;
  padding-block: var(--space-2);
  font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}

.faq__item summary::-webkit-details-marker { display: none; }

.faq__item summary::after {
  content: "+";
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 20px;
  font-weight: 400;
  color: var(--ink-dim);
  transition: rotate var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.faq__item[open] summary::after { content: "−"; border-color: var(--line-strong); }

.faq__item p {
  margin: 0;
  padding-bottom: var(--space-3);
  max-width: 62ch;
}

.faq__back { margin-top: var(--space-4); font-size: 15px; }

.faq__back a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--neon);
  text-decoration: none;
  font-weight: 600;
}

.faq__back a:hover { text-decoration: underline; }

/* ---------- standalone pages (gate / confirm / demo) ---------- */
/* Centred while the content fits; the smaller padding only bites on a short
   laptop viewport, where the disabled CTA and its reason must both stay above
   the fold (spec §5 — a greyed button with no visible reason is the failure). */
/* Not centred: when the content is taller than the viewport, centring pushes
   the primary action below the fold on every laptop and phone while the screen
   still looks complete, so nobody scrolls to find it. */
.pagewrap {
  min-height: 100svh;
  display: flex;
  align-items: flex-start;
  padding-block: var(--space-4) 0;
}

.pagetitle {
  font-size: clamp(1.9rem, 4.2vw, 3.2rem);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.05;
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}

.backlink {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-bottom: var(--space-3);
  padding-right: var(--space-2);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-dim);
  text-decoration: none;
}

.backlink:hover { color: var(--ink); }

.column { max-width: 720px; }

/* ---------- stepper (steps.html) ----------
   Two nodes, inline and left-aligned, sitting above the checklist. Compact on
   purpose: it is a status line, not the page's structure — the rows below are
   where the work happens, and a full-width rail would compete with them. */
.stepper {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

.stepper__node {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* The rail lives in the gap before the node it arrives at, so it carries that
   node's state and lights up as progress lands. */
.stepper__node + .stepper__node::before {
  content: "";
  position: absolute;
  right: 100%;
  top: 50%;
  margin-right: 12px;
  width: 40px;
  height: 1px;
  background: var(--line-strong);
  transition: background var(--dur) var(--ease);
}

/* The sibling combinator must be repeated here, not dropped: the base rail rule
   above scores (0,2,1), so a bare `.stepper__node--done::before` at (0,1,1)
   loses to it and the rail stays grey in every state. */
.stepper__node + .stepper__node--done::before,
.stepper__node + .stepper__node--current::before { background: var(--volt); }

.stepper__dot {
  position: relative;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.stepper__label { font-size: 13px; font-weight: 600; color: var(--ink-dim); }

.stepper__node--current .stepper__dot { border-color: var(--neon); color: var(--neon); }
.stepper__node--current .stepper__label,
.stepper__node--done .stepper__label { color: var(--ink); }

/* Done — the numeral gives way to a tick drawn from two borders. */
.stepper__node--done .stepper__dot {
  border-color: var(--volt);
  color: transparent;
}

.stepper__node--done .stepper__dot::after {
  content: "";
  position: absolute;
  width: 10px;
  height: 5px;
  border-left: 2px solid var(--volt);
  border-bottom: 2px solid var(--volt);
  rotate: -45deg;
  translate: 0 -1px;
}

/* ---------- gate (steps.html) ----------
   Named .gate* / .gaterow* on purpose: the landing page already owns
   .steps / .steps__item for its "How it works" list.

   Re-laid 2026-07-31 (Gwen): statement on top at full width, the stepper
   under it, then the two steps side by side as cards — the previous
   "no cards" split read as a settings list, and the pair of cards is what
   says these are the only two things the page wants. */
.gate {
  max-width: 1040px;
  display: grid;
  grid-template-columns: 1fr;
  row-gap: var(--space-4);
}

.gate__back { grid-column: 1 / -1; margin-bottom: 0; }

/* One step up from .pagetitle with a tighter leading. The 超大字 ask,
   delivered on an existing scale rather than a new one. */
.gate__statement {
  margin: 0;
  max-width: 22ch;
  font-size: clamp(1.9rem, 4.5vw, 3.4rem);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: .98;
  text-wrap: balance;
}

.gate__panel { display: grid; align-content: start; }

.gate__empty { margin: 0 0 var(--space-3); font-size: 14px; }
.gate__empty a { color: var(--neon); font-weight: 600; text-decoration: none; }
.gate__empty a:hover { text-decoration: underline; }

.gatelist__cap { margin: 0 0 var(--space-2); }

/* The two steps, side by side. */
.gatelist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}

.gaterow {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  min-height: 176px;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.gaterow__num {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}

.gaterow__text { display: grid; gap: 2px; }

/* Pins the buttons to the card's foot however tall its neighbour runs. */
.gaterow__actions { margin-top: auto; }

.gaterow__label {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.3;
  color: var(--ink);
  transition: color var(--dur) var(--ease);
}

.gaterow__meta { margin: 0; font-size: 13px; }

/* A done row's only remaining affordance: its own name, quietly clickable, so
   a wrong self-report can still be put right by actually going and doing it. */
.gaterow__relink {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 4px;
  cursor: pointer;
}

.gaterow__relink:hover { color: var(--ink); }

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

.gaterow__fallback {
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: var(--ink-dim);
  font: inherit;
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.gaterow__fallback:hover { color: var(--ink); }

/* Done: the row keeps its name and loses its affordance. No button is a
   stronger "nothing to do here" than any amount of dimming — and it leaves
   exactly one row on the page still asking for something. */
.gaterow--done { border-color: rgba(61, 139, 255, .30); }
.gaterow--done .gaterow__label { color: var(--ink-dim); }
.gaterow--done .gaterow__meta,
.gaterow--done .gaterow__actions { display: none; }

/* 64px of air under the last hairline. That gap is what says "this is not a
   third step" — which is why no sentence has to. */
.gate__finish {
  margin-top: var(--space-5);
  display: grid;
  gap: var(--space-1);
  justify-items: start;
}

.gate__finish .btn { justify-content: space-between; min-width: 260px; }

.confirm-reason { margin: 0; font-size: 14px; }

.gate__warn { margin: var(--space-1) 0 0; font-size: 13px; color: var(--ink-dim); }

.is-ready { animation: pulse-once 620ms var(--ease) 1; }

@keyframes pulse-once {
  0%   { scale: 1; }
  45%  { scale: 1.035; }
  100% { scale: 1; }
}

/* ---------- confirmation ---------- */
.done__ctas { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

.done__entry {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: rgba(6, 8, 15, .58);
}

/* The author display:grid above beats the UA's [hidden] rule, so an empty
   entry rendered as a bare bordered box. Say hidden explicitly. */
.done__entry[hidden] { display: none; }

.done__entry div { min-width: 0; }
.done__entry dt {
  margin-bottom: 4px;
  color: var(--ink-dim);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.done__entry dd { margin: 0; overflow-wrap: anywhere; font-weight: 700; }

.done__sign {
  margin: var(--space-5) 0 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
  font-size: clamp(1.1rem, 2vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
  text-transform: uppercase;
}

/* ---------- confirmation (full-bleed) ---------- */
.done {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: var(--space-6);
  overflow: hidden;
}

.done__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 50%;
  animation: kenburns 2s var(--ease) both;
}

/* The source render leaves the left third almost empty — the scrim deepens it
   so the copy sits in real darkness instead of on top of a busy picture. */
.done__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right,
      rgba(6, 8, 15, .94) 0%,
      rgba(6, 8, 15, .74) 34%,
      rgba(6, 8, 15, .18) 62%,
      rgba(6, 8, 15, .34) 100%),
    linear-gradient(to bottom, rgba(6, 8, 15, .46), transparent 30%, rgba(6, 8, 15, .60));
}

.done__body {
  position: relative;
  max-width: 620px;
  margin-inline: 0;
  padding-inline: max(48px, calc((100vw - 1200px) / 2));
}

/* ---------- confirm flow (confirm.html) ----------
   Two states in one document: A "check your email" (quiet, blue progress,
   no primary) and B "you're in" (the orange CTA arriving IS the reward).
   The shell — backlink, stepper, Mind figure — persists; only copy and foot
   swap. Flat --bg on purpose: mind.png anchors this page now, and a
   transparent-bg character over the throne photo went muddy. Vegas survives
   in the sign-off line. Spec: agent-team/specs/confirm-flow-v2.md */
.confirm {
  --confirm-lime: #E1FF57;
  min-height: 100svh;
  display: grid;
  overflow-x: clip; /* the mobile figure bleeds off the right edge */
  background:
    radial-gradient(44% 38% at 14% 8%, rgba(225, 255, 87, .09), transparent 72%),
    radial-gradient(32% 28% at 88% 74%, rgba(253, 141, 29, .10), transparent 76%);
}

/* The foot row takes the leftover height so the copy stays top-aligned while
   the figure — spanning all three rows — can anchor to the page's foot. */
.confirm__body {
  display: grid;
  grid-template-columns: minmax(0, 620px) minmax(280px, 420px);
  grid-template-rows: auto auto 1fr;
  grid-template-areas:
    "head head"
    "swap figure"
    "foot figure";
  column-gap: var(--space-5);
  justify-content: space-between;
  padding-block: var(--space-4) var(--space-4);
  padding-inline: max(48px, calc((100vw - 1200px) / 2));
}

.confirm__head { grid-area: head; }
.confirm__swap { grid-area: swap; }
.confirm__foot { grid-area: foot; align-self: start; }

.confirm__head .stepper { margin-bottom: var(--space-4); }

/* A wrapped node's rail pokes left of the list into the page padding —
   clip the list box so wrapped rows drop their rails cleanly. */
.confirm .stepper { overflow: clip; }

.confirm .stepper__node + .stepper__node--done::before,
.confirm .stepper__node + .stepper__node--current::before { background: var(--confirm-lime); }

.confirm .stepper__node--done .stepper__dot,
.confirm .stepper__node--current .stepper__dot {
  border-color: var(--confirm-lime);
  color: var(--confirm-lime);
}

.confirm .stepper__node--done .stepper__dot { color: transparent; }
.confirm .stepper__node--done .stepper__dot::after {
  border-color: var(--confirm-lime);
}

.confirm .stepper__node--current .stepper__label,
.confirm .stepper__node--done .stepper__label { color: var(--confirm-lime); }

.confirm .eyebrow { color: var(--confirm-lime); }

.confirm .done__entry {
  border-color: rgba(253, 141, 29, .42);
  background: rgba(253, 141, 29, .05);
}

.confirm .done__entry dt { color: var(--orange-600); }
.confirm .done__sign {
  border-top-color: rgba(253, 141, 29, .40);
  color: var(--orange-600);
}

/* These are swap panels, not page sections — undo the global
   `section { padding-block: var(--section-y) }` rhythm. */
.confirm__state { padding-block: 0; }

/* State A keeps ALL accent off the page — blue progress only, so the orange
   CTA arriving with B stays the reward. Overrides the component's --neon
   current dot on this page alone. */
.confirm .stepper__node--current .stepper__dot {
  border-color: var(--confirm-lime);
  color: var(--confirm-lime);
}

/* State A is deliberately quiet — dim inks, blue progress; the only bright
   object is the address itself. */
.confirm__state--quiet .lede { color: var(--ink-dim); }

.confirm__email {
  color: var(--orange-600);
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* One framed note, not a card grid. */
.confirm__aside {
  max-width: 52ch;
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid rgba(253, 141, 29, .36);
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, rgba(253, 141, 29, .10), transparent 54%);
}

.confirm__asidelabel {
  margin: 0 0 var(--space-1);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--orange-600);
}

.confirm__asideline { margin: 0; font-size: 14px; }

/* State B folds the Mind CTA into this card — one AFC Virtual League Assistant Coach Mind section, not a
   card here and an orphan button in the foot. */
.confirm__aside-cta {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid rgba(253, 141, 29, .32);
}

.confirm__aside-cta .confirm__ctanote { margin-top: var(--space-1); }

/* The demo strip reads as labelled stage apparatus, never product surface —
   dashed is the one visual voice this site uses nowhere else. */
.demo-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  max-width: 620px;
  margin-top: var(--space-4);
  padding: var(--space-2) var(--space-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  transition: opacity 260ms var(--ease), translate 260ms var(--ease);
}

.demo-strip[hidden] { display: none; }

.demo-strip.is-leaving {
  opacity: 0;
  translate: 0 6px;
  pointer-events: none;
}

.demo-strip__tag {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.demo-strip__line {
  flex: 1 1 200px;
  min-width: 0;
  margin: 0;
  font-size: 14px;
}

/* The park state (no demo, no email backend yet): one dim link, nothing else. */
.confirm__reenter { margin: var(--space-4) 0 0; font-size: 14px; }

.confirm__reenter a {
  color: var(--ink-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.confirm__reenter a:hover { color: var(--ink); }

/* B's future lines: a hairline apart from the lede, never a tick list —
   ticks assert done, and these haven't happened. */
.confirm__next {
  max-width: 52ch;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid rgba(225, 255, 87, .34);
}

.confirm__next p { margin: 0 0 var(--space-1); }
.confirm__next p:last-child { margin-bottom: 0; }

.confirm__ctanote { margin: var(--space-2) 0 0; font-size: 14px; }

/* A→B choreography. A exits up and out… */
.confirm__state.is-leaving {
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 200ms var(--ease), transform 200ms var(--ease);
}

/* …and B's children land staggered — the [data-reveal] recipe's values,
   applied by confirm.js with 60ms delays. */
.confirm__stagger {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.confirm__stagger.is-in {
  opacity: 1;
  transform: none;
}

/* The figure is the shell's one constant: top-aligned with the copy column
   so image + Mind card read as one right-hand section, not a floor ornament. */
.confirm__figure {
  grid-area: figure;
  position: relative;
  align-self: start;
  justify-self: end;
  width: min(320px, 28vw);
}

.confirm__figure-img { position: relative; }

/* A restrained blue halo separates the Mind from the dark confirm shell while
   keeping the artwork itself untouched. */
.confirm__figure-img::before {
  content: "";
  position: absolute;
  inset: 12% 4% 10%;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 45%, rgba(73, 145, 255, .22), rgba(44, 105, 214, .10) 42%, transparent 74%);
  filter: blur(14px);
  pointer-events: none;
  z-index: 0;
}

/* A wide, short floor shadow so it stands rather than floats — no glow,
   no gradient blob. */
.confirm__figure-img::after {
  content: "";
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: -6px;
  height: 24px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, .5), transparent 78%);
  z-index: 0;
}

.confirm__mind {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: auto;
  animation: mind-float 7s var(--ease) infinite;
}

/* One bounce on confirmation — reuses the gate's pulse-once. The `scale`
   keyframe lives on the wrapper so it stacks with the img's own float. */
.confirm__figure--pop { animation: pulse-once 620ms var(--ease) 1; }

/* Tablet: still two columns, but the desktop's 48px gutters + 64px gap
   starve the copy column — tighten both and let the figure column size to
   the (smaller) figure so the copy keeps a readable measure. */
@media (max-width: 1023px) {
  .confirm__body {
    grid-template-columns: minmax(0, 620px) minmax(220px, 36vw);
    column-gap: var(--space-4);
    padding-inline: 24px;
  }

  .confirm__figure { width: min(260px, 32vw); }
}

/* Single column: backlink → stepper → copy → figure → controls → sign-off.
   The figure drops between copy and controls (its own grid row) and bleeds
   ~24px off the right viewport edge. */
@media (max-width: 700px) {
  .confirm__body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto 1fr;
    grid-template-areas: "head" "swap" "figure" "foot";
    column-gap: 0;
    padding-block: var(--space-3) var(--space-4);
    padding-inline: 16px;
  }

  /* The section goes full-width so the Mind card (and its state-B CTA) keeps
     the page measure; only the image itself stays small and bleeds right. */
  .confirm__figure {
    width: auto;
    justify-self: stretch;
    margin-top: var(--space-3);
  }

  .confirm__figure-img {
    width: 180px;
    margin-inline: auto;
  }

  .confirm__foot { margin-top: 0; }
  .demo-strip { margin-top: var(--space-3); }
}

@media (max-width: 560px) {
  .demo-strip .btn {
    width: 100%;
    justify-content: space-between;
  }
}

/* ---------- mind create (demo) ---------- */
.mindcard {
  display: grid;
  grid-template-columns: minmax(0, 0.6fr) minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
  margin-top: var(--space-4);
}

.mindcard__art {
  width: min(240px, 100%);
  justify-self: center;
  animation: mind-float 7s var(--ease) infinite;
}

.mindcard__form { margin: 0; }

.field select {
  min-height: 52px;
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  /* background-color, not the shorthand — the shorthand would re-reset the
     chevron's no-repeat/position/size from the earlier .field select rule
     and tile it across the control. */
  background-color: var(--bg);
  color: var(--ink);
  font: 400 16px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* ---------- Minds theme (the two stand-in pages) ----------
   hellominds.ai is a separate product, not a section of the Cup — you leave one
   site and land on another. The stand-ins have to say that in the first half
   second, so they swap the whole palette: light surfaces and a product blue
   where the Cup runs near-black and neon. Tokens carry almost all of it; the
   handful of rules below exist only because the base sheet hard-codes white for
   the dark UI. Set with data-theme on <html> so the page background changes too. */
:root[data-theme="minds"] {
  --bg: #F4F6FB;
  --surface: #FFFFFF;
  --line: rgba(16, 24, 40, .10);
  --line-strong: rgba(16, 24, 40, .20);
  --ink: #0D1220;
  --ink-dim: #5A6376;   /* 5.6:1 on --bg */
  --neon: #2563EB;      /* the primary fill; 5.2:1 against white text */
  --volt: #2563EB;      /* focus + field states, so one blue does both jobs */
  color-scheme: light;
}

/* One still wash instead of the Cup's three drifting pools: the same effect in
   light mode reads as a printing fault, and calm is the point over here. */
:root[data-theme="minds"] body::before {
  background: radial-gradient(58% 40% at 50% 0%, rgba(37, 99, 235, .10), transparent 70%);
  animation: none;
}

:root[data-theme="minds"] .btn:hover { border-color: rgba(16, 24, 40, .34); }

/* The Cup's neon carries near-black text; this blue needs white. */
:root[data-theme="minds"] .btn--primary { color: #FFFFFF; }

:root[data-theme="minds"] .btn--primary:hover {
  background: #1D4ED8;
  border-color: #1D4ED8;
}

:root[data-theme="minds"] .btn--primary .btn__chip { background: rgba(255, 255, 255, .22); }

/* Placeholders still carry real guidance, so they hold AA against the light
   field fill rather than inheriting the dark theme's grey. */
:root[data-theme="minds"] .field input::placeholder { color: #646D80; }

/* ---------- app shell (prematch) ---------- */
.appbar {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--line);
  background: rgba(6, 8, 15, .82);
  backdrop-filter: blur(12px);
}

.appbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 64px;
}

.appbar__brand {
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
  text-decoration: none;
}

.appbar__account {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 14px;
}

.appbar__team { font-weight: 600; color: var(--ink); }
.appbar__who { color: var(--ink-dim); }

.appbar__out {
  min-height: 44px;
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-dim);
  font: 600 13px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  cursor: pointer;
}

.appbar__out:hover { color: var(--ink); border-color: var(--line-strong); }

.app { padding-block: var(--space-5) var(--space-6); }

.app__row { padding-block: var(--space-5) 0; }

.app__h {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 var(--space-3);
}

.squadgrid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-2);
}

.squadgrid__slot {
  padding: var(--space-3);
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 4px;
}

.squadgrid__art { width: 100%; max-width: 120px; }

/* Two of the five have no render yet — a monogram tile is honest about that
   and still reads as a filled slot. */
.squadgrid__empty {
  display: grid;
  place-items: center;
  width: 100%;
  max-width: 120px;
  aspect-ratio: 1;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  font-size: 30px;
  font-weight: 800;
  color: var(--ink-dim);
}

.squadgrid__slot p { margin: 0; font-size: 13px; }

.playbook {
  width: 100%;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: 400 16px/1.6 system-ui, -apple-system, "Segoe UI", sans-serif;
  resize: vertical;
}

.playbook:focus { border-color: var(--volt); outline: none; }

.app__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.app__saved { font-size: 14px; color: var(--volt); }

.nextmatch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.nextmatch p { margin: 0; max-width: 54ch; }
.nextmatch p + h3 { margin-top: 2px; }

.column--narrow { max-width: 520px; }

/* One-time-code entry (login.html). The six digits are the object of the
   stage, so they get display weight; tabular figures keep them from
   shuffling as they're typed. */
.field--code input {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: .35em;
  font-variant-numeric: tabular-nums;
}

.field--code input::placeholder { letter-spacing: .35em; }

/* The strip inside the form card: the card already provides the surface,
   so the strip only keeps its dashed voice, not the page-level width. */
.demo-strip--form { max-width: none; margin-top: 0; }

/* ---------- demo-only notice ---------- */
.demonote {
  margin: 0 0 var(--space-4);
  padding: 10px var(--space-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  color: var(--ink-dim);
}

/* ---------- how it works (landing) ----------
   A 2×2 grid with the connectors drawn as one overlay in its gutters. The
   single-column version read as a flow but cost 4 full-width cards of height
   for four short steps; the grid is the shape Gwen asked for, and the wires
   are what keep it from reverting to "four unrelated cards". */
.howgrid {
  position: relative;
  margin-top: var(--space-5);
}

/* The gutters are the canvas. preserveAspectRatio="none" is deliberate here
   and safe: every leg is axis-aligned, so stretching distorts nothing that
   would show — and the arrowheads are drawn as separate short strokes whose
   own aspect distortion at these ratios is under a pixel. */
.howgrid__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
  overflow: visible;
}

.wire {
  fill: none;
  stroke: rgba(255, 255, 255, .34);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* One dash chased along each leg, on a shared 3.4s loop.

   Both the dasharray and --wire-len are set per element by mountHowWires from
   the path's own measured length. They cannot be authored here: the three legs
   differ by an order of magnitude (the gutter hops are ~28px, the wrap-around
   leg ~630px), and one shared dasharray makes the short hops render as a solid
   line that never appears to move.

   --wire-len has a fallback so a no-JS page still animates something sane
   rather than freezing at offset 0. */
.wire--lit {
  stroke: var(--neon);
  animation: wire-travel 3.4s linear infinite;
}

/* Staggered so the eye is walked 01 → 02 → 03 → 04. The long wrap leg gets the
   widest slot, and 03 → 04 fires only once it has landed. */
.wire--a { animation-delay: 0s; }
.wire--b { animation-delay: .45s; }
.wire--c { animation-delay: 2.1s; }

@keyframes wire-travel {
  0%   { stroke-dashoffset: var(--wire-len, 700); opacity: 0; }
  10%  { opacity: 1; }
  58%  { opacity: 1; }
  76%  { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

/* grid-auto-rows: 1fr makes both rows the same height, and each card stretches
   to its row — so all four are identical whatever their copy length. That only
   works because 02's cast is out of flow now; in flow it set the row height and
   the equalising just padded the other three with air. */
.how {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: var(--space-4);
}

/* The rules page presents the four steps as the same 2x2 composition as the
   landing page. Its legacy arrow elements are hidden so they do not occupy
   grid cells between the cards. */
#season .how {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

#season .how__arrow { display: none; }

/* The padding-top is the numeral's room: it is absolutely positioned, so
   nothing else reserves space for it and the copy would run underneath.
   Flex column so .how__stat can be pushed to the card's foot with margin-top:
   auto — that is what makes 01 and 03 agree on where their figure sits
   regardless of how their copy wraps. */
.how__item {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--space-6) + var(--space-3));
  display: flex;
  flex-direction: column;
}

.how__num {
  position: absolute;
  top: calc(var(--space-3) + 16px);
  left: var(--space-4);
  font-size: clamp(2.6rem, 4.2vw, 4.2rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}

.how__step {
  position: absolute;
  top: var(--space-3);
  left: var(--space-4);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.how__item h3 { font-size: clamp(1.5rem, 2.2vw, 1.9rem); }

.how__item--registration .how__num { font-size: clamp(2.2rem, 3.6vw, 3.6rem); }

.how__register-link {
  color: var(--neon);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.how__register-link:hover { color: var(--accent-100); }

/* The art is absolutely positioned and comes later in source order, so without
   this it paints over the copy — and on step 03 that copy is the sentence the
   whole section exists for. */
.how__item h3,
.how__item p { position: relative; z-index: 1; }

/* Step 01 reads as two beats — register, then meet your Mind — so it carries
   its own tiny numbered sequence instead of two undifferentiated paragraphs. */
.how__substeps {
  position: relative;
  z-index: 1;
  list-style: none;
  counter-reset: substep;
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  max-width: 38ch;
}

.how__substeps li {
  counter-increment: substep;
  position: relative;
  padding-left: 30px;
}

.how__substeps li::before {
  content: counter(substep);
  position: absolute;
  left: 0;
  top: 1px;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-dim);
  border: 1px solid var(--line-strong);
  border-radius: 50%;
}

.how__item p { margin: 0; max-width: 34ch; }

.how__item--hero p { padding-right: 92px; }

/* Step 04 is the payoff — the leaderboard and the plane. It gets the accent,
   and a light that travels its border: the one card in the set that should
   look like it is worth reaching. */
/* A conic gradient rotating behind the card, masked to the border's width by
   the two-layer padding-box/border-box trick — that is what confines a moving
   fill to a 1px frame without a second element or an SVG stroke. The card's own
   background paints over the middle, so only the rim shows.

   The rotation is carried by a registered custom property rather than by
   `transform` on a pseudo-element: rotating a box big enough to cover the card
   would overflow it and force a repaint of everything behind. */
@property --shine {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* .how__item--hero alone loses to `.card { background: var(--surface) }` — same
   specificity, and .card is declared later in the file. Doubling the class is
   the cheapest way to win it without reordering the stylesheet or reaching for
   !important. */
/* 2px, not 1: a travelling highlight on a hairline is invisible at any
   brightness — there is not enough rim to catch it. The base stops sit at .38
   so the whole frame reads as an accent border even at the dim phase of the
   loop, and the bright arc runs to full --aws so the pass is unmistakable. */
/* Brighter fill than the other three, so 04 reads as the payoff before anyone
   reaches its border: a warm wash from the bottom-right corner over a surface
   lifted above --surface. The two accent layers sit on padding-box so they stop
   at the border, leaving the conic gradient the rim to itself. */
.how__item--hero.how__item--hero {
  border: 2px solid transparent;
  background:
    radial-gradient(130% 110% at 100% 100%, rgba(255, 122, 48, .30), transparent 66%) padding-box,
    radial-gradient(90% 80% at 0% 0%, rgba(255, 153, 0, .10), transparent 62%) padding-box,
    linear-gradient(168deg, #1E1A22, #15141C) padding-box,
    conic-gradient(from var(--shine),
      rgba(253, 141, 29, .38) 0deg,
      rgba(255, 170, 110, 1) 26deg,
      var(--accent-100) 44deg,
      var(--aws) 62deg,
      rgba(253, 141, 29, .38) 108deg,
      rgba(253, 141, 29, .38) 360deg) border-box;
  animation: hero-shine 5.5s linear infinite;
}

@keyframes hero-shine {
  to { --shine: 360deg; }
}

.how__item--hero .how__num { color: var(--ink-dim); }

/* Lift the four primary step cards slightly above the page background while
   keeping the separate finale card as the stronger closing treatment. */
#how .how > .how__item {
  background: linear-gradient(145deg, rgba(255, 255, 255, .065), transparent 42%), #161B26;
}

/* Step 04 keeps its payoff artwork, but shares the same quiet card surface and
   hairline border as Steps 01–03. */
.how__item--hero.how__item--hero {
  border: 1px solid var(--line);
  background: linear-gradient(145deg, rgba(255, 255, 255, .035), transparent 42%), var(--surface);
  animation: none;
}

/* The journey lands in a separate, centred finale below the 2×2 grid. The
   flight lane is its own canvas so the plane can follow measured coordinates
   without disturbing the card grid or creating horizontal overflow. */
.howflight {
  position: relative;
  z-index: 3;
  width: 100%;
  height: 20px;
  margin-top: 0;
  pointer-events: none;
}

/* A 20px handoff cannot carry the former multi-bend flight route without
   distorting it. Use one crisp vertical connector anchored below step 04. */
.howflight::before {
  content: "";
  position: absolute;
  top: 0;
  left: 75%;
  width: 2px;
  height: 20px;
  background: var(--accent-600);
  border-radius: 999px;
  transform: translateX(-1px);
}

.howflight__route,
.howflight__plane { display: none; }

.howflight__route path {
  stroke: var(--accent-600);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 2 10;
  opacity: .72;
  vector-effect: non-scaling-stroke;
}

.howflight__plane {
  position: absolute;
  left: 0;
  top: 0;
  width: 44px;
  height: 44px;
  overflow: visible;
  color: var(--accent-600);
  opacity: 0;
  offset-position: 0 0;
  offset-rotate: auto;
  filter: drop-shadow(0 0 10px rgba(253, 141, 29, .35));
}

.howflight.is-active .howflight__plane {
  animation: how-flight 2.5s var(--ease) forwards;
}

@keyframes how-flight {
  0% { offset-distance: 0%; opacity: 0; }
  12% { opacity: 1; }
  100% { offset-distance: 100%; opacity: 1; }
}

.howfinale {
  display: flex;
  justify-content: center;
  width: 100%;
}

.howfinale .how__item {
  width: 100%;
}

.how__item--finale {
  border: 2px solid transparent;
  background:
    radial-gradient(130% 110% at 100% 100%, rgba(253, 141, 29, .34), transparent 66%) padding-box,
    radial-gradient(90% 80% at 0% 0%, rgba(253, 141, 29, .12), transparent 62%) padding-box,
    linear-gradient(168deg, #1E1A22, #15141C) padding-box,
    conic-gradient(from var(--shine),
      rgba(253, 141, 29, .42) 0deg,
      var(--accent-100) 44deg,
      var(--accent-600) 62deg,
      rgba(253, 141, 29, .42) 108deg,
      rgba(253, 141, 29, .42) 360deg) border-box;
  animation: hero-shine 5.5s linear infinite;
}

.how__item--finale .how__num { color: var(--accent-600); }

.how__item--finale .how__num { z-index: 1; }

.how__vegas {
  position: absolute;
  z-index: 0;
  inset: 0 0 0 auto;
  width: 58%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, .55) 30%, #000 72%);
          mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, .55) 30%, #000 72%);
}

.how__item--finale .how__stat {
  position: relative;
  z-index: 1;
}

.how__item--hero .how__art {
  position: absolute;
  right: -19%;
  bottom: -14%;
  width: 68%;
  opacity: 1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 36%);
          mask-image: linear-gradient(to right, transparent 0%, #000 36%);
}

.how__item--registration .how__art,
.how__art--train {
  position: absolute;
  right: -10%;
  bottom: -12%;
  width: 52%;
  opacity: 1;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 38%);
          mask-image: linear-gradient(to right, transparent 0%, #000 38%);
}

/* The cast is BACKGROUND on this card, not content: absolutely positioned in
   the top-right corner, behind the copy, faded back. In flow it dictated the
   row's height — grid rows size to their tallest cell, so three figures at the
   card's foot made row 1 nearly 600px and left card 01 with 300px of dead
   space. Out of flow it costs the layout nothing and the four cards can be
   equal height. */
.how__item--squad .squad__cast {
  position: absolute;
  top: var(--space-3);
  right: var(--space-2);
  z-index: 0;
  width: 42%;
  margin: 0;
  justify-content: flex-end;
  opacity: 1;
  pointer-events: none;
  /* Fades into the card at the bottom-left so the figures do not end in a hard
     edge across the copy that sits under them. */
  -webkit-mask-image: linear-gradient(200deg, #000 34%, rgba(0, 0, 0, 0) 82%);
          mask-image: linear-gradient(200deg, #000 34%, rgba(0, 0, 0, 0) 82%);
}

.how__item--squad .squad__cast img { width: 100%; }

/* Left, not centred — inside a card with left-aligned copy above them, centred
   chips read as a different component that wandered in. */
/* Sized to fit all five roles on ONE line inside a half-width card: the five
   names total ~40 characters, so at the global chip's 13px/9px-16px they wrapped
   "Striker" to a second row. nowrap on the list plus the tighter chip below is
   what holds the line — the five roles are one thought and a lone orphan chip
   underneath read as a sixth, different thing. */
.how__item--squad .chips {
  position: relative;
  z-index: 1;
  margin-top: var(--space-3);
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 5px;
}

.how__item--squad .chips li {
  padding: 6px 9px;
  font-size: 10.5px;
  letter-spacing: .04em;
  white-space: nowrap;
}

/* The cast now sits behind the top-right corner, so the heading and the first
   line keep clear of it. The chips below run full width — by then the art has
   faded out. */
.how__item--squad h3 { max-width: none; white-space: nowrap; }
.how__item--squad > p { max-width: 30ch; }

/* Sits directly under the copy, NOT pushed to the card's floor with auto: grid
   rows size to their tallest cell, so 02's cast makes row 1 tall and an
   auto-pushed figure left card 01 looking like an empty box with a caption at
   the bottom. Anchored to the text it annotates, the leftover height reads as
   the card breathing rather than as missing content. */
.how__stat {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding-top: var(--space-3);
  font-size: 15px;
  color: var(--ink-dim);
}

.how__stat b {
  font-size: clamp(1.4rem, 2.2vw, 1.9rem);
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* ---------- squad cast ---------- */
.squad__cast {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin-top: var(--space-5);
}

/* gap cannot be negative — the overlap comes from margins. */
.squad__cast img { width: clamp(150px, 22vw, 300px); }

.squad__cast img:nth-child(2) {
  width: clamp(180px, 26vw, 350px);
  z-index: 1;
  margin-inline: clamp(-40px, -3vw, -12px);
}

.chips {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1);
}

.chips li {
  padding: 9px var(--space-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- coach ----------
   Split from the chat demo 2026-07-30. This section is the claim and nothing
   else: the copy on the left with a real measure, the character on the right as
   decoration. It used to also carry the chat window, which meant the headline
   was squeezed into whatever column was left over after both. */
.coach {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(400px, .42fr);
  column-gap: var(--space-5);
  row-gap: var(--space-4);
  align-items: center;
}

.coach__figure {
  position: relative;
  margin: 0;
  display: grid;
  place-items: center;
}

/* The glow is what stops a cut-out from looking pasted on. */
.coach__figure::before {
  content: "";
  position: absolute;
  inset: -18% -10%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(61, 139, 255, .26), rgba(61, 139, 255, .07) 58%, transparent 78%);
  filter: blur(6px);
}

/* Decoration, not the subject — so it is sized to sit beside the chat window
   rather than to anchor the section. */
.coach__mind {
  position: relative;
  width: min(400px, 100%);
  height: auto;
  animation: mind-float 7s var(--ease) infinite;
}

@keyframes mind-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

.coach__intro h2 { max-width: 24ch; font-weight: 300; }
.coach__title-lead { font-weight: 300; }
.coach__intro h2 q {
  font-weight: 700;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
}
.coach__intro .lede { max-width: 56ch; }
.coach__points {
  display: grid;
  gap: 10px;
  max-width: 56ch;
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.coach__points li {
  position: relative;
  padding-left: 20px;
}
.coach__points li::before {
  content: "";
  position: absolute;
  top: .56em;
  left: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--neon);
  box-shadow: 0 0 0 4px rgba(253, 141, 29, .12);
}

/* One topic split across two grids, not two topics: the claim and its exhibit
   sit a single interval apart instead of two full section paddings. */
#coach { padding-block: var(--section-y); }
#chatdemo { padding-block: 0 var(--section-y); }

/* ---------- chat demo ----------
   Its own section now. Horizontal: the window on the left, the short label on
   the right — mirroring the coach section above (copy left, art right) so the
   pair zigzags instead of stacking two same-shaped rows. The caption stays
   first in the DOM so readers and screen readers get the claim before the
   exhibit; `order` does the visual swap. */
.chatdemo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .58fr);
  column-gap: var(--space-5);
  row-gap: var(--space-4);
  align-items: center;
}

.chatdemo__intro { order: 1; }

.chatdemo__intro h2 { margin-bottom: var(--space-2); max-width: 14ch; }
.chatdemo__intro p { margin: 0; max-width: 34ch; }

.coach__note {
  margin-top: var(--space-3);
  font-size: 14px;
  max-width: 46ch;
}

.coach__cta { margin-top: var(--space-2); }

/* The chat is a window, not a transcript: a titled bar, a threaded body and a
   composer. The three of them together are what make it read as another app —
   which is the section's actual claim, and the reason the address bar carries
   hellominds.ai. The card's own 40px padding is dropped so the bar and the
   composer can run to its edges. */
.chat {
  display: grid;
  gap: 0;
  padding: 0;
  overflow: hidden;
}

.chat__bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 12px var(--space-3);
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, .025);
}

.chat__ava {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: rgba(61, 139, 255, .14);
}

/* mind.png is a whole standing character, so object-fit on a near-square file
   puts a torso in the circle. Scaled and offset to land the head instead. */
.chat__ava img {
  width: 165%;
  max-width: none;
  margin: -5% 0 0 -32.5%;
}

.chat__id { display: grid; line-height: 1.3; }

.chat__name {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
}

.chat__host { font-size: 12px; color: var(--ink-dim); }

.chat__thread {
  list-style: none;
  margin: 0;
  padding: var(--space-3);
  display: grid;
  gap: var(--space-3);
}

.msg { display: grid; gap: 6px; justify-items: start; }
.msg--you { justify-items: end; }

.bubble {
  max-width: 88%;
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  font-size: 15px;
  line-height: 1.55;
}

.bubble p { margin: 0 0 var(--space-2); font-size: 15px; }
.bubble p:last-child { margin-bottom: 0; }

/* One squared corner on the speaker's side is the whole tail — a drawn tail
   would need a shadowed pseudo-element, which this system does not have. */
.msg--you .bubble {
  background: rgba(255, 255, 255, .05);
  border-bottom-right-radius: 4px;
}

.msg--mind .bubble {
  background: rgba(61, 139, 255, .08);
  border-color: rgba(61, 139, 255, .30);
  border-bottom-left-radius: 4px;
}

.chat__who {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.msg--mind .chat__who { color: var(--volt); }

/* A real link, not a dressed-up dead input: it runs through the site's
   placeholder handler and says "Not live yet." out loud. The Mind is a
   separate app — nothing typed here could ever reach it. */
.chat__composer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 56px;
  padding: 0 10px 0 var(--space-3);
  border-top: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink-dim);
  font-size: 15px;
  text-decoration: none;
  transition: color var(--dur) var(--ease);
}

.chat__composer:hover { color: var(--ink); }

.chat__send {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(61, 139, 255, .45);
  color: var(--volt);
  font-size: 15px;
  line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.chat__composer:hover .chat__send {
  background: var(--volt);
  border-color: var(--volt);
  color: #06080F;
}

/* The two bubbles land one after the other, so the exchange reads as a reply
   arriving rather than a block of text that was always sitting there. Gated
   behind .js for the same reason the reveals are: no script, no hiding. */
.js .chat .msg {
  opacity: 0;
  transform: translateY(10px);
}

.js .chat.is-in .msg {
  animation: msg-in 440ms var(--ease) 140ms forwards;
}

.js .chat.is-in .msg--mind { animation-delay: 640ms; }

@keyframes msg-in {
  to { opacity: 1; transform: none; }
}

/* The Copy button is deliberately visible: the whole point is that advice
   moves by hand from the Mind app into your squad. Hiding it would imply
   an integration that does not exist. */
.chat__snippet {
  display: grid;
  gap: 10px;
  margin-block: 10px;
  padding: 12px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--bg);
}

.chat__snippet code {
  font: 400 14px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--ink);
}

.copybtn {
  justify-self: start;
  min-height: 44px;
  padding: 0 var(--space-2);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: 600 13px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.copybtn:hover { border-color: var(--neon); color: var(--neon); }

/* ---------- dateline ----------
   What the "road to Vegas" section became when it merged into this one.

   Rebuilt 2026-07-30: the first version was a pair of hairlines with 6px dots,
   which Gwen read as "too subtle" — correct, it was annotation-weight on a
   section whose whole job is to be scanned. It is now an actual timeline: one
   continuous rail with nodes sitting ON it, the dates at display weight, and
   the segment you are currently in drawn in the accent. Same footprint, an
   order of magnitude more legible. */
.dateline {
  list-style: none;
  /* Air on both sides (Gwen, 2026-07-30): the rail was landing right off the
     headline's baseline and the route cards were crowding the labels. */
  margin: var(--space-5) 0 calc(var(--space-6) + var(--space-2));
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* The rail is drawn per stop as a border on the node's own row, so the line is
   continuous across a grid gap of zero. The last stop draws none of it: a
   timeline that runs past its final marker to the container's edge is drawing a
   future it has no dates for. */
.dateline__stop {
  position: relative;
  padding: var(--space-4) var(--space-3) 0 0;
  border-top: 2px solid var(--line-strong);
}

.dateline__stop:last-child { border-top-color: transparent; }

/* The node. 14px and filled, on the rail rather than beside it — the old 6px
   dot floating to the left of the text was the main reason the rail read as a
   hairline with some words under it. */
.dateline__stop::before {
  content: "";
  position: absolute;
  top: -8px;
  left: 0;
  width: 14px;
  height: 14px;
  border-radius: 999px
;
  border: 2px solid var(--bg);
  background: var(--ink-dim);
}

.dateline__when {
  display: block;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.dateline__what {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* The live stop owns its whole segment of the rail, not just its node: the
   accent running along the line is what says "this is the part you are in",
   which a coloured dot alone never managed. */
.dateline__stop--live {
  border-top-color: var(--neon);
}

.dateline__stop--live::before {
  background: var(--neon);
  box-shadow: 0 0 0 4px rgba(253, 141, 29, .18);
}

.dateline__stop--live .dateline__when { color: var(--neon); }
.dateline__stop--live .dateline__what { color: rgba(255, 138, 90, .9); }

/* The far end is lit but not pulsing — it is the destination, not the state. */
.dateline__stop--end::before { background: var(--neon); }
.dateline__stop--end .dateline__when { color: var(--neon); }

/* The live node breathes as a ring, not a scale: "on", never an alarm. */
.dateline__stop--live::after {
  content: "";
  position: absolute;
  top: -8px;
  left: 0;
  width: 14px;
  height: 14px;
  border-radius: 999px;
  border: 2px solid var(--neon);
  animation: dateline-live 2.4s var(--ease) infinite;
}

@keyframes dateline-live {
  0%       { transform: scale(1);   opacity: .85; }
  70%, 100%{ transform: scale(2.1); opacity: 0; }
}

/* ---------- what you win (landing) ---------- */
/* The arithmetic IS the layout: two routes on one row, a connector that merges
   them into 16, one boarding pass underneath. Built to be read in a single
   screen — a route is worthless if you have to scroll to find out they add up,
   so this section runs on one tight interval and gets a short-viewport block
   at the bottom of the stylesheet that tightens it further.

   Everything here is drawn: the league table, the award cards and the pass are
   artefacts from this competition's own world, and a flat raster of any of them
   would be soft on retina and stuck on one theme. No gold anywhere — that was
   the one note in the reference that read as a casino. */
/* Full section interval, not --space-5: this one section now carries what two
   used to, and the tighter padding was calibrated for a page where the road
   section sat immediately above it. */
#reward { padding-block: var(--section-y); }

/* Headline left, the sentence that explains the sum right. Stacked, the two
   cost 70px of the fold for no reading benefit. The headline takes the wider
   track — it is two authored lines now, not one. */
.win__head {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: var(--space-3) var(--space-5);
  align-items: end;
  margin-bottom: var(--space-4);
}

.win__head h2 { margin: 0; max-width: 18ch; }

/* One column when the lede is gone — a 2-track grid with an empty right cell
   left the headline in 55% of the width for no reason. */
.win__head--solo { display: block; }
.win__head--solo h2 { max-width: 26ch; }
.win__head .lede { margin: 0; }
.win__criteria {
  margin: 0 0 var(--space-3);
  font-size: clamp(1.25rem, 2vw, 1.6rem);
}

/* Asymmetric on purpose: the right column holds four content objects (the
   award cards) against the left's one texture — equal tracks would starve
   them. The merge rails' x-positions (60/860 in the 920 art) still land under
   each card at these tracks. */
.win {
  display: grid;
  grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  /* Row gap is zero so every connector in the flow spine — the merge rails,
     the drop, the coda rail — starts and ends ON a card border instead of
     hanging short of it. The bands are transparent, so the breathing room is
     drawn inside the SVGs, not by the grid. */
  gap: 0 var(--space-2);
}

/* ---- the two routes ----
   padding-bottom is the drawing's room, and it is what makes the overlap
   impossible rather than merely unlikely: the champions card's table is
   absolutely positioned and bottom-anchored, so if the copy ever wraps to an
   extra line the card grows and the artwork moves down with it. A fixed
   min-height alone would have let a longer sentence land on top of it.
   (The wildcard card opts out via --wild below — its award cards are in-flow
   content, so it has no floor to reserve.) */
.win__route {
  position: relative;
  overflow: hidden;
  min-height: 300px;
  padding-bottom: 130px;
  /* Flex column with the artwork pushed out of flow: the copy stacks from the
     top and `margin-top:auto` on nothing means the padding-bottom below is a
     true floor. Without this the card is a block box whose min-height does not
     react to the copy growing, and a three-line .win__say at a narrow width
     walked straight over the table. */
  display: flex;
  flex-direction: column;
}

.win__route.card {
  background: #F5F6F8;
  color: #0D1220;
}

#reward .win__route.card .win__n,
#reward .win__route.card h3,
#reward .win__route.card .win__say b { color: #0D1220; }

#reward .win__route.card .win__say em { color: #5B6472; }

#reward .win__route:not(.win__route--wild) {
  background: #161B26;
  color: var(--ink);
}

#reward .win__route:not(.win__route--wild) .win__say em { color: var(--ink-dim); }

#reward .win__route.card {
  background: #161B26;
  color: #F5F6F8;
}

#reward .win__route.card .win__n,
#reward .win__route.card h3,
#reward .win__route.card .win__say b { color: #F5F6F8; }

#reward .win__route.card .win__say em { color: #8A8A9C; }

/* The league route earns a warmer finish: a restrained gold glow gathers at
   the bottom of the proof card while the upper copy stays on the same dark
   reading surface. */
#reward .win__route:not(.win__route--wild).card {
  background:
    radial-gradient(90% 70% at 50% 100%, rgba(253, 141, 29, .25), transparent 72%),
    linear-gradient(180deg, #161B26 0%, #161B26 44%, #2A2119 100%);
}

#reward .win__route.card .awards__control {
  background: #0E1119;
  border-color: rgba(255, 255, 255, .18);
  color: #F5F6F8;
}

/* The standalone rules page uses the same two-route component as the landing
   page, so keep both route panels on the dark competition surface there too. */
#routes .win__route.card {
  background: #161B26;
  color: #F5F6F8;
}

#routes .win__route.card .win__n,
#routes .win__route.card h3,
#routes .win__route.card .win__say b { color: #F5F6F8; }

#routes .win__route.card .win__say em { color: #8A8A9C; }

/* The copy sits above the artwork no matter how it wraps. z-index alone is not
   enough — a positioned ancestor is required for it to apply at all. */
.win__route > *:not(.league-champions__art) {
  position: relative;
  z-index: 1;
  flex: none;
}

.win__n {
  margin: 0 0 var(--space-1);
  font-size: clamp(2.6rem, 4.4vw, 3.6rem);
  font-weight: 800;
  letter-spacing: -.04em;
  line-height: .9;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.win__route h3 {
  margin-bottom: var(--space-1);
  font-size: clamp(1.5rem, 2.2vw, 1.9rem);
}

/* A class, not `.win__route > p` — the big 10 and 6 are paragraphs too, and a
   child selector quietly outranked .win__n and shrank them to body size. */
/* The card's own surface, painted behind the sentence. The table is angled and
   bottom-anchored, so at a short viewport or a narrow column its top edge
   reaches the copy — and hairline table rows showing through a sentence reads
   as a rendering fault, not as depth. The bleed is the card's padding, so the
   panel meets both side walls rather than floating as a visible rectangle. */
.win__say {
  margin: 0 calc(var(--space-4) * -1);
  padding: 0 var(--space-4) var(--space-2);
  max-width: none;
  font-size: 15px;
  text-wrap: pretty;
}

/* The measure the max-width used to hold, moved inside so the negative margin
   above does not stretch the line length. */
.win__say > span,
.win__route h3 { max-width: 36ch; }

.win__say b { color: var(--ink); font-weight: 700; }
.win__say em { font-style: normal; color: rgba(138, 143, 156, .8); }

/* ---- the league table ----
   Angled and cropped by the card, because it is a screen you will be staring
   at in week 10, not a chart we drew for you. z-index 0 keeps it under the
   copy no matter how the copy wraps. */
/* Smaller and fainter than it was — Gwen: "the visual on 10 league and 6
   wildcard need smaller, more transparent, now is too messy". It was competing
   with the copy at full opacity and near-full card width; as a texture behind
   the sentence it does the same job (this is a screen you will be staring at in
   week 10) without asking to be read. */
/* left 30% / bottom -34px / opacity .5, retuned from 46% / -44px / .48: the
   card stretches to match the wildcard column now (~480px+ at 1440), so the
   table fills the lower portion instead of hugging the corner. Hard rule
   unchanged: it never touches .win__say. */
.league-champions__art {
  position: absolute;
  z-index: 0;
  left: 18%;
  width: 72%;
  /* Raised from -34px (Gwen, 2026-07-31): the table sits fully inside the
     card now and shows more of the league; the mask below still dissolves it
     before any hard edge shows. */
  bottom: -12%;
  height: auto;
  object-fit: cover;
  object-position: center;
  opacity: 1;
  transform: rotate(-3deg);
  transform-origin: 100% 100%;
  pointer-events: none;
  /* The table runs off the bottom of the card on purpose — a league is longer
     than the five rows we drew. The fade has to finish before the card's edge
     does, or the crop reads as a clipping bug instead of a continuation.
     Reaching zero at 62% rather than 88% is what makes that true: at 88% the
     last visible row still had most of its ink when the card's overflow cut
     it, so the tear landed mid-letterform and read as a rendering fault. The
     fade now finishes well above the card's edge, so the table dissolves
     instead of being sliced. */
  -webkit-mask-image: none;
          mask-image: none;
}

/* --volt is the site's "live" signal (it is the stepper's current step too),
   so the matchday bar borrows it rather than inventing a second green. */
.ltable__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 8px 12px;
  background: rgba(61, 139, 255, .16);
  border-bottom: 1px solid rgba(61, 139, 255, .32);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #C2D8FF;
}

.ltable__live { color: #EAF2FF; }

.ltable__rows { list-style: none; margin: 0; padding: 0; }

.ltable__row {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-dim);
}

.ltable__row:last-child { border-bottom: 0; }
.ltable__row i { font-style: normal; font-size: 11px; font-variant-numeric: tabular-nums; }
.ltable__row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ltable__row b { font-weight: 700; font-variant-numeric: tabular-nums; }

/* The one row that matters. Everything above it is the reason the accent means
   something down here. */
.ltable__row--top {
  background: rgba(255, 255, 255, .05);
  color: var(--ink);
}

.ltable__row--top b { color: var(--neon); }

/* ---- the four award cards ----
   Four real awards, four countable objects — four cards = four seats. An <a>
   block card: object-on-card elevation (surface-2, like .ltable), type-led,
   no icon, no image. Each links to its full-copy entry on rules.html#awards.
   The old six-card fan was texture; these are content, so no absolute
   positioning and no reserved floor. */

/* Doubled class: plain .win__route rules in the media queries below (150px
   stacked floor, short-viewport min-heights) are for the champions card's
   absolute artwork only — this card's height is its content. */
.win__route.win__route--wild {
  min-height: 0;
  padding-bottom: var(--space-4);
}

.awards__controls {
  position: relative;
  z-index: 4;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: var(--space-2);
  pointer-events: auto;
}

.awards__control {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink);
  font: 600 18px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.awards__control:hover { border-color: var(--neon); color: var(--neon); }
.awards__control:active { transform: translateY(1px); }
.awards__control:disabled { opacity: .36; cursor: not-allowed; }

.awards__viewport {
  /* The viewport still crops the next slide horizontally, but reserves enough
     room for the award card's hover lift so its foil border stays intact. */
  margin-top: calc(var(--space-2) - 6px);
  padding-top: 6px;
  overflow: hidden;
}

.awards {
  list-style: none;
  margin: 0;
  /* This element is the horizontal scroll container. Its own inset, not only
     the outer viewport's, must clear the card transform on hover. */
  padding: 8px 0 0;
  display: flex;
  gap: var(--space-2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.awards::-webkit-scrollbar { display: none; }

.awards > li {
  /* Two complete cards establish the set. A narrow third-card preview makes
     the carousel's remaining content obvious without stealing room from the
     award names. */
  flex: 0 0 44%;
  min-width: 220px;
  scroll-snap-align: start;
}

.award {
  position: relative;                       /* anchors the frame + sheen */
  overflow: hidden;
  display: block;
  height: 100%;
  min-height: 210px;
  padding: var(--space-3);
  /* Trading-card anatomy (Gwen, 2026-07-30): a collectible's frame, not a
     UI card's hairline. The border paints transparent so the holo gradient
     on the border-box layer shows through it — an iridescent rim running
     white → volt → neon, all existing accents, no new colours. The glass
     body stays on the padding-box layer underneath. */
  border: 2px solid transparent;
  border-radius: var(--radius-sm);          /* object-on-card scale, like .ltable */
  /* Three layers, top to bottom: the glass tint, a near-opaque plate that
     stops the rim gradient bleeding into the body (without it the holo fills
     the whole card), and the holo rim on the border-box. */
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .10),
      rgba(255, 255, 255, .03) 48%,
      rgba(255, 255, 255, .07)) padding-box,
    linear-gradient(rgba(20, 24, 36, .94), rgba(20, 24, 36, .94)) padding-box,
    linear-gradient(148deg,
      rgba(255, 255, 255, .35) 0%,
      rgba(61, 139, 255, .40) 30%,
      rgba(255, 90, 31, .45) 62%,
      rgba(255, 255, 255, .18) 100%) border-box;
  -webkit-backdrop-filter: blur(14px) saturate(1.15);
  backdrop-filter: blur(14px) saturate(1.15);
  text-decoration: none;
  transition: transform .35s var(--ease);
}

/* The inner window line — the frame-within-a-frame that makes it read as a
   collectible rather than a bordered box. */
.award::before {
  content: "";
  position: absolute;
  inset: 7px;
  border: 1px solid rgba(255, 255, 255, .10);
  border-radius: calc(var(--radius-sm) - 5px);
  pointer-events: none;
  transition: border-color .35s var(--ease);
}

/* The moving part of the glass: a specular band that sweeps once per hover.
   Sits above the background, below nothing — pointer-events off so the card
   stays one click target. */
.award::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg,
    transparent 32%,
    rgba(255, 255, 255, .13) 48%,
    rgba(255, 255, 255, .04) 55%,
    transparent 70%);
  transform: translateX(-130%);
  transition: transform .9s var(--ease);
  pointer-events: none;
}

.award:hover::after { transform: translateX(-130%); }

/* The → is the persistent "this goes somewhere" affordance — visible before
   hover, never hover-only. */
.award__tag {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-1);
  margin: 0 0 var(--space-1);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.award__go { transition: transform .35s var(--ease), color .35s var(--ease); }

.award__name {
  margin: 0 0 6px;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.25;
  color: var(--ink);
}

.award__say {
  margin: 0;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ink-dim);
}

/* One card lights at a time — accent as feedback, not decoration. The border
   colour is the old fan front-card value: precedent, not a new colour. */
/* Lift + the inner window line brightens; the holo rim itself never changes,
   the way a card's foil doesn't — the light moves, not the print. */
.award:hover {
  transform: none;
}

.award:hover::before { border-color: rgba(255, 255, 255, .10); }

/* OneFootball's award keeps the same foil-card treatment, but trades the
   generic orange flash for the partner's vivid green. */
.award--onefootball {
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .10),
      rgba(255, 255, 255, .03) 48%,
      rgba(255, 255, 255, .07)) padding-box,
    linear-gradient(rgba(20, 24, 36, .18), rgba(20, 24, 36, .18)) padding-box,
    url("../assets/onefootball-award-background.png") center / cover no-repeat padding-box,
    linear-gradient(148deg,
      rgba(255, 255, 255, .35) 0%,
      rgba(61, 139, 255, .40) 30%,
      rgba(225, 255, 87, .58) 62%,
      rgba(255, 255, 255, .18) 100%) border-box;
}

.award--onefootball .award__tag,
.award--onefootball .award__name { color: #0D1220; }

.award--onefootball .award__say { color: #26303B; }

.award--onefootball > :not(.award__mark) { position: relative; z-index: 1; }

.award__mark {
  position: absolute;
  right: -12px;
  bottom: -16px;
  width: 78px;
  height: auto;
  opacity: 1;
  pointer-events: none;
}

@media (min-width: 561px) {
  .award { min-height: 320px; }
}

/* Physical press. */
.award:active { transform: translateY(0); }

/* The global :focus-visible rule sets border-radius: 4px, which would visibly
   snap the card's corners on keyboard focus. */
.award:focus-visible { border-radius: var(--radius-sm); }

/* ---- the join ----
   Two routes in, one number out, one arrow down into the pass. The travelling
   light is this page's only looping animation; reduced-motion stops it dead. */
/* 168px, up from 108px — Gwen's "啲箭嘴可以再有多少少空間令到睇得清楚啲". At the
   old height the two inbound arrowheads and the outbound drop were fighting
   for the same 40px of vertical, and none of the three read as an arrow.
   place-items:start centres the pill horizontally but lets the top padding
   place it, so it lands on the SVG's y=90 rather than on the band's midpoint —
   the two are not the same once the art is capped at 920px. */
/* The band is capped to the art's own width and the art fills it, so the SVG
   and the pill share one coordinate space. Sizing them independently — a
   1200px band holding a 920px drawing — is what put the pill on top of the
   right-hand arrowhead: the two were centred on different boxes.
   The height comes from the aspect-ratio, so any width change keeps the
   drawing's proportions and the pill's offset stays a percentage of it. */
.merge {
  grid-column: 1 / -1;
  /* align-self:start is what lets aspect-ratio decide the height. As a grid
     item this stretches to its row by default, and a stretched box ignores
     aspect-ratio entirely — the band rendered 366px tall and the drawing
     letterboxed inside it. */
  align-self: start;
  position: relative;
  width: min(920px, 100%);
  margin-inline: auto;
  aspect-ratio: 920 / 168;
  /* The pill is placed absolutely rather than by padding: percentage padding
     resolves against WIDTH, so a 26% top padding on a 760px band was ~198px
     and inflated the box past its own aspect-ratio. top:45% is y≈76/168 —
     the rails' centre line — and the translate re-centres the pill on it. */
  display: block;
}

/* Wide enough that each rail starts roughly under its own card, so the glyph
   reads as "these two join" rather than as a bracket floating in the middle.
   preserveAspectRatio stays at the default: skewing it to full width would
   flatten the arrowhead into a smear. */
/* inset:0 would set height:100% as well as top/bottom, and with the default
   preserveAspectRatio="xMidYMid meet" a 920×168 viewBox in a box of a
   different ratio letterboxes the drawing — the arrowheads flatten into
   smears against the band's edges. Pin the top only and let the aspect-ratio
   carry the height, so the glyph is always drawn at its authored proportions. */
/* Fills its band exactly — the band already carries the 920/168 ratio, so the
   drawing is never letterboxed and the arrowheads never smear. */
.merge__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Brighter and thicker than --line-strong's 18% white. At the hairline weight
   the rails read as absent next to the orange arrowheads, so the connector
   looked like three floating chevrons with gaps between them rather than one
   continuous path — a reviewer read it as exactly that. The line has to be
   visible enough to be followed, while still losing to the pill. */
.merge__rail {
  fill: none;
  stroke: rgba(255, 255, 255, .34);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.merge__head {
  fill: none;
  stroke: var(--neon);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.merge__flow {
  fill: none;
  stroke: var(--neon);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 30 260;
  animation: merge-flow 3.2s cubic-bezier(.4, 0, .2, 1) infinite;
}

/* The offset is what makes the two inbound lights read as two separate
   journeys rather than one symmetric ornament. */
.merge__flow--b { animation-delay: .18s; }

/* Departs only after both inbound lights have landed on the pill, so the eye
   is handed downward to the pass instead of being asked to pick a direction.
   Shorter dash because the drop is a third of the rails' length. */
.merge__flow--c {
  animation-delay: 1.15s;
  stroke-dasharray: 16 120;
}

@keyframes merge-flow {
  0%   { stroke-dashoffset: 210; opacity: 0; }
  12%  { opacity: 1; }
  62%  { opacity: 1; }
  100% { stroke-dashoffset: -34; opacity: 0; }
}

/* Absolutely placed on the rails' centre line (y≈76 of the 168 viewBox), not
   flowed by the band's padding — percentage padding resolves against width and
   would break the band's aspect-ratio. */
.merge__sum {
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
  /* No transform: the taller band centres the pill correctly on its own, and
     it is the hinge of the whole flow now, so it earns the extra padding. */
  padding: 5px 20px;
  border: 1px solid rgba(253, 141, 29, .38);
  border-radius: 999px;
  background: rgba(6, 8, 15, .94);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* Kept deliberately under the badge's own height budget: at 2.1rem the pill
   grew tall enough to swallow the arrow underneath it. */
.merge__n {
  font-size: clamp(1.3rem, 2vw, 1.6rem);
  font-weight: 800;
  letter-spacing: -.03em;
  color: var(--neon);
  font-variant-numeric: tabular-nums;
}

/* ---- the boarding pass ----
   Real ticket anatomy: utility labels, a perforation with punched notches, a
   stub. A "prize card" would have been a box with a list in it. */
.pass {
  grid-column: 1 / -1;
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  column-gap: var(--space-5);
  border-color: rgba(253, 141, 29, .22);
  background:
    radial-gradient(120% 150% at 100% 0%, rgba(253, 141, 29, .10), transparent 58%),
    var(--surface);
}

.pass__main,
.pass__stub { position: relative; z-index: 1; }

.pass__route {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-1) 0 var(--space-3);
  font-size: clamp(2rem, 4.2vw, 3.2rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
}

.pass__to { color: var(--neon); }

/* The runway (Gwen, 2026-07-30): wider air between the ports, and the plane
   flies it on a loop — takes off from HOME's side, lands into LAS, fading at
   both ends so the return leg is never seen. The rotate is baked into every
   keyframe because transform is one property. */
.pass__plane {
  flex: none;
  width: .62em;
  height: .62em;
  margin-inline: .6em;
  color: var(--ink-dim);
  transform: rotate(90deg);
  animation: pass-fly 3s ease-in-out infinite;
}

@keyframes pass-fly {
  0%   { transform: translateX(-.65em) rotate(90deg); opacity: 0; }
  16%  { opacity: 1; }
  84%  { opacity: 1; }
  100% { transform: translateX(.65em) rotate(90deg); opacity: 0; }
}

.pass__specs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, auto));
  justify-content: start;
  column-gap: var(--space-4);
  row-gap: var(--space-2);
  margin: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}

.pass__specs dt {
  margin-bottom: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.pass__specs dd {
  margin: 0;
  font-size: clamp(.9rem, 1.2vw, 1.02rem);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--ink);
}

/* The perforation sits in the middle of the column gap, and the two notches
   are punched out of the card's own edges in --bg so the tear reads as
   physical rather than as a dashed border someone drew. */
.pass__stub::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-5) / 2);
  top: calc(-1 * var(--space-4));
  bottom: calc(-1 * var(--space-4));
  border-left: 1px dashed var(--line-strong);
}

.pass__stub::after {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-5) / 2 - 11px);
  top: calc(-1 * var(--space-4) - 2px);
  bottom: calc(-1 * var(--space-4) - 2px);
  width: 22px;
  pointer-events: none;
  background:
    radial-gradient(11px 11px at 11px 0, var(--bg) 98%, transparent 100%),
    radial-gradient(11px 11px at 11px 100%, var(--bg) 98%, transparent 100%);
  background-repeat: no-repeat;
}

.pass__covered {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  max-width: 32ch;
}

.pass__covered li {
  position: relative;
  width: fit-content;
  max-width: 100%;
  padding-left: var(--space-3);
  font-size: 16px;
  line-height: 1.45;
  color: var(--ink-dim);
}

/* Neutral dots, not accent ones: the accent in this section means "you won",
   and it is already spent on LAS and on the 16. */
.pass__covered li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--ink-dim);
}

.pass__covered b { display: block; color: var(--ink); font-size: 17px; font-weight: 700; }

/* Our own mascot, cropped by the ticket. Not a gold trophy — that was the
   casino tell in the reference. */
.pass__art {
  position: absolute;
  right: -18px;
  bottom: -22px;
  width: 152px;
  opacity: .42;
  pointer-events: none;
}

/* ---- the prize band ----
   Merged INTO the ticket (Gwen, 2026-07-31): pass and prize are one object,
   not a card plus a coda. A horizontal perforation under the pass body —
   the same tear language as the stub's vertical one, notches included — and
   below it the cash: coins, shimmer, and the one-team-only line. The flow
   spine now terminates at the pass itself. */
.pass__prize {
  grid-column: 1 / -1;
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  /* The band bleeds to the card's own edges (negative margins swallow the
     card padding) so the whole lower slab of the ticket reads as the gold
     zone, not a strip floating inside it. */
  margin: var(--space-4) calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
  min-height: 220px;
  padding: var(--space-3) var(--space-4);
  overflow: hidden;
  border-top: 1px dashed rgba(255, 153, 0, .38);
  background:
    radial-gradient(56% 130% at 50% 0%, rgba(255, 153, 0, .16), transparent 72%),
    linear-gradient(180deg, rgba(255, 153, 0, .04), rgba(255, 153, 0, .10));
}

/* The tear's punched notches, horizontal edition: a half-circle of page
   background bitten out of each side edge, centred on the dashed line. The
   card's overflow:hidden clips the outer halves. */
.pass__prize::before,
.pass__prize::after {
  content: "";
  position: absolute;
  top: -11px;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: var(--bg);
  pointer-events: none;
}

.pass__prize::before { left: -11px; }
.pass__prize::after  { right: -11px; }

.prize__copy {
  position: relative;
  z-index: 1;
  width: min(100%, 560px);
  text-align: center;
}

.prize__side {
  position: absolute;
  z-index: 0;
  bottom: -56px;
  width: clamp(220px, 21vw, 360px);
  max-height: none;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

.prize__side--left {
  left: 0%;
  object-position: left bottom;
  display: block;
  width: 280px;
  bottom: -110px;
}

@media (min-width: 901px) {
  .prize__side--left { bottom: -82px; }
}

.prize__side--right {
  right: -70px;
  bottom: -70px;
  width: 400px;
  object-position: right bottom;
}

.prize__coins {
  width: 104px;
  flex: none;
  stroke: var(--aws);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The glints are the only filled shapes in the drawing; they twinkle in
   counter-phase so the coins feel lit, not animated. */
.prize__spark {
  fill: var(--aws);
  stroke: none;
  transform-box: fill-box;
  transform-origin: center;
  animation: prize-twinkle 2.4s ease-in-out infinite;
}

.prize__spark--b { animation-delay: 1.1s; }

@keyframes prize-twinkle {
  0%, 100% { opacity: .15; transform: scale(.8); }
  50%      { opacity: 1;   transform: scale(1); }
}

/* Gilded, not dimmed — inside the gold zone the utility grey read as a
   misprint. */
.prize__label { margin-bottom: var(--space-1); color: rgba(255, 190, 96, .85); }

.prize__n {
  margin: 0;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: clamp(2.6rem, 4.4vw, 3.8rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: .9;
  font-variant-numeric: tabular-nums;
  /* The shimmer: a gold gradient clipped to the digits, swept by animating
     its position. color stays as the no-clip fallback paint. */
  color: var(--aws);
  background: linear-gradient(105deg,
    #FFC24D 0%, #FF9900 30%, #FFEFC9 50%, #FF9900 70%, #FFC24D 100%);
  background-size: 240% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: prize-shine 3s linear infinite;
}

.prize__currency {
  color: var(--aws);
  font-size: .38em;
  font-weight: 600;
  letter-spacing: .1em;
  vertical-align: middle;
  -webkit-text-fill-color: var(--aws);
}

@keyframes prize-shine {
  to { background-position: -240% 0; }
}

.prize__say { margin: var(--space-1) 0 0; font-size: 14px; color: var(--ink-dim); }

/* ---- the awards in full (rules.html #awards) ----
   Read-mode section on a content page — plain cards at page level; the tags
   carry the cross-page thread back to the landing's award cards. */
.awardgrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}

.awardfull h3 { margin-bottom: var(--space-1); }

.awardfull p:not(.award__tag) { margin: 0; font-size: 15px; color: var(--ink-dim); }

/* The landing cards deep-link here; without this the sticky nav sits on the
   card's title on arrival. */
.awardfull { scroll-margin-top: 96px; }


/* ---------- partner band (under the hero) ----------
   A credit strip, not a section: it overrides the global section padding down
   to one interval, and it deliberately has no rule of its own — the urgency
   bar's top border underneath is the divider, and two hairlines 20px apart
   would read as a stack of toolbars. */
.partnerband {
  padding-block: var(--space-2);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .025), transparent);
  border-block: 1px solid var(--line);
}

.partnerband__inner {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-6);
}

/* Each group reads label-then-marks on one line: "Powered by · AWS" and
   "Partners · Minds · OneFootball", split by a hairline. */
.partnerband__group {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  /* Flush left, not centered: the AWS mark sits left inside its box
     (object-position), so a centered label above it reads as misaligned
     the moment the group wraps to two rows. */
  justify-content: flex-start;
  gap: var(--space-2) var(--space-4);
  min-width: 0;
}

.partnerband__label {
  margin: 0;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.partnerband__divider {
  width: 1px;
  align-self: stretch;
  background: var(--line);
}

.partnerband__logo {
  display: block;
  height: 48px;
  width: auto;
  max-width: 100%;
  min-width: 0;
  flex-shrink: 1;
  object-fit: contain;
  object-position: left center;
}
.partnerband__logo--aws { width: fit-content; height: 72px; }
.partnerband__logo--minds { width: fit-content; }
.partnerband__logo--onefootball { width: 150px; }
.partnerband__role {
  grid-row: 1;
  margin-bottom: 8px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- bring your friends ---------- */
.duo--tight { align-items: center; gap: var(--space-4); }

.together__art {
  width: min(320px, 100%);
  justify-self: center;
}

/* ---------- site nav ----------
   The site grew from one page to four, so a persistent bar is now the only
   thing that says the other three exist. Sticky rather than fixed: it leaves
   the hero's full height alone on load and only starts occluding once you
   have already decided to scroll. The backdrop blur is what keeps the
   wordmark legible over the Vegas photo without a solid band cutting the
   hero in half. */
.sitenav {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid transparent;
  background: transparent;
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

/* .is-stuck is set by the scroll observer once the page has moved past the
   nav's own height — before that the bar floats over the hero unlined. */
.sitenav.is-stuck {
  background: var(--bg);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}

/* Subpages have no photographic hero to float over, so they carry the solid
   treatment from the first pixel. */
.sitenav--solid {
  background: var(--bg);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}

.sitenav__inner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 60px;
  padding-block: 8px;
  container-type: inline-size;
}

@media (min-width: 901px) {
  .sitenav .wrap {
    width: min(90dvw, 100% - 96px);
  }
}

.sitenav__league {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}
.sitenav__league-mark { width: auto; height: 24px; display: block; }
.sitenav__league-label {
  color: var(--orange-600);
  font-size: 16px;
  font-weight: 900;
  letter-spacing: -0.05rem;
  line-height: 1;
  text-transform: none;
  white-space: nowrap;
}

.sitenav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--ink);
  margin-right: auto;
}

.sitenav__mark {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 9px;
  background: linear-gradient(140deg, var(--accent-600), var(--accent-100));
  display: grid;
  place-items: center;
}

.sitenav__mark svg { width: 20px; height: 20px; }

.sitenav__word {
  display: block;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -.01em;
  text-transform: uppercase;
  line-height: 1.1;
}

.sitenav__sub {
  display: block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.sitenav__links {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 20px;
  margin: 0;
  margin-left: auto;
  padding: 0;
}

.sitenav__links a {
  display: block;
  padding-block: 6px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: none;
  color: var(--ink-dim);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color 180ms var(--ease), border-color 180ms var(--ease);
}

.sitenav__links a:hover { color: var(--ink); }

.sitenav__kiro svg {
  width: 13px;
  height: 13px;
  margin-left: 2px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.5;
}

/* The current page is named twice — aria-current for assistive tech, the
   rule for everyone else. */
.sitenav__links a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--neon);
}

.sitenav__links a:focus-visible { outline-offset: 6px; }

.sitenav__cta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 0;
}

.sitenav__cta .btn {
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* A text button on purpose — a third pill in the bar would fight the real
   CTA. Matches the link row's voice instead. */
.sitenav__login {
  display: inline-flex;
  align-items: center;
  padding: 5px 10px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: none;
  color: var(--ink-dim);
  text-decoration: none;
  transition: color 180ms var(--ease);
}

.sitenav__kiro {
  padding: 0;
  border: 0;
  border-radius: 0;
}

.sitenav__login:hover { color: var(--ink); }

.sitenav__login:focus-visible { outline-offset: 6px; }

/* Smaller than the page's real buttons: a nav CTA that matches the hero's
   button competes with it on the one screen where they are both visible. */
.sitenav .btn {
  min-height: 34px;
  padding: 4px var(--space-2);
  gap: 2px;
  font-size: 16px;
  line-height: 1.1;
}

.sitenav .btn--primary { padding-inline: 12px; }

.sitenav__menu { display: none; }

/* ---------- AWS Kiro placeholder ---------- */
.kiro-page {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: var(--space-3);
  background:
    radial-gradient(44% 38% at 16% 12%, rgba(225, 255, 87, .12), transparent 72%),
    radial-gradient(34% 30% at 84% 78%, rgba(253, 141, 29, .12), transparent 74%);
}

.kiro-page__panel {
  width: min(680px, 100%);
  padding: clamp(32px, 6vw, 72px);
  border: 1px solid rgba(225, 255, 87, .34);
  border-radius: var(--radius);
  background: linear-gradient(145deg, rgba(225, 255, 87, .07), transparent 48%), var(--surface);
}

.kiro-page__back {
  display: inline-block;
  margin-bottom: var(--space-5);
  color: var(--ink-dim);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}

.kiro-page__back:hover { color: #E1FF57; }
.kiro-page .eyebrow { color: #E1FF57; }
.kiro-page h1 { margin-bottom: var(--space-2); }
.kiro-page__lede { max-width: 46ch; margin: 0 0 var(--space-4); color: var(--ink-dim); }

.kiro-page__tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: var(--space-4);
  padding: 7px 10px;
  border: 1px solid rgba(253, 141, 29, .4);
  border-radius: 999px;
  color: var(--orange-600);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.kiro-page__tag svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; }

@media (min-width: 901px) {
  .partnerband__inner {
    flex-wrap: nowrap;
    gap: var(--space-2) clamp(16px, 4vw, var(--space-6));
  }
  .partnerband__group {
    flex-wrap: nowrap;
    gap: var(--space-2) clamp(16px, 2.5vw, var(--space-4));
  }
  .partnerband__logo {
    flex: none;
    max-width: none;
  }
}

/* The compact label prevents the mobile header from wrapping at narrow widths;
   wider layouts retain the more explicit "Register now" CTA. */
@container (max-width: 350px) {
  .sitenav__register-now { display: none; }
}

/* The mobile bar keeps the brand and the CTA and drops the links into a
   scrollable rail underneath — a hamburger for four items is a tap and an
   animation spent to hide something that fits. */
.sitenav__rail { display: none; }

/* ---------- trust block ----------
   Sits beside the form, because "who is this and what happens to my email" is
   asked at the moment the field is focused, not in a footer. Statements, not
   badges — a lock icon on a dark page is decoration; the sentence is the
   assurance. Hairline-separated rows so it reads as fine print you can
   actually read, rather than a fourth card. */
.trust {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: var(--space-3) 0 0;
  border-top: 1px solid var(--line);
  display: grid;
  gap: var(--space-2);
}

.trust li {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-dim);
}

.trust b {
  display: block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--ink);
}

/* ---------- site footer ---------- */
.sitefoot {
  border-top: 1px solid var(--line);
  padding-block: var(--space-4);
}

.sitefoot__inner {
  display: flex;
  flex-wrap: wrap;
  /* Bottom-aligned, not centered: the left column is two lines tall (credit
     over the legal links), and centering left the right-hand nav floating
     between them. Anchoring both groups to the bottom puts every link on the
     same row, with the credit line riding above. */
  align-items: flex-end;
  gap: var(--space-3) var(--space-4);
  justify-content: space-between;
}

.sitefoot__note {
  margin: 0;
  font-size: 13px;
  color: var(--ink-dim);
}

/* Left column: the credit line with the two legal documents directly under
   it — ownership and its small print in one block, site navigation on the
   opposite edge. */
.sitefoot__left { display: grid; gap: 2px; }

.sitefoot__links {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
}

/* inline-flex + min-height, not padding alone: these are 12px caps, so the
   text box is ~15px tall and the link was a 15px tap target. The row's gap
   absorbs the extra height without moving the baseline. */
.sitefoot__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-dim);
  text-decoration: none;
}

.sitefoot__links a:hover { color: var(--ink); }

/* ---------- film ----------
   Sits directly under the hero: the fastest possible answer to "what does a
   match actually look like", before a word of rules. The frame is 16:9 and
   holds its own ratio so the placeholder and the real file swap without the
   page reflowing. */
.film__head {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.film__head h2 {
  margin: 0;
  font-family: "Arial Nova Condensed", "Arial Nova", "Bahnschrift", system-ui, -apple-system, "Segoe UI", sans-serif;
}
.film__note { margin: 0; font-size: 17px; max-width: 72ch; }
.film__description { margin: 0; font-size: 15px; max-width: 72ch; }
.film__description { color: var(--ink-dim); }

/* What the game actually is — four numbered beats reading left to right
   under the gallery, centred on the gallery's own axis. Numbers and
   hairlines only: no icons, no card chrome. */
.film__steps {
  list-style: none;
  counter-reset: filmstep;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-4);
  max-width: 1100px;
  margin: var(--space-4) auto 0;
  padding: 0;
  text-align: center;
}

.film__steps li {
  counter-increment: filmstep;
  display: grid;
  gap: var(--space-1);
  align-content: start;
  justify-items: center;
  padding-top: var(--space-2);
  border-top: 1px solid var(--line);
}

.film__steps li::before { display: none; }

.film__steps h3::before {
  content: "0" counter(filmstep);
  display: inline-block;
  margin-right: .7em;
  color: var(--neon);
  font-size: .72em;
  font-weight: 700;
  letter-spacing: .16em;
  vertical-align: .08em;
}

.film__steps h3 {
  margin: 0;
  font-size: clamp(19px, 1.1vw, 22px);
  font-weight: 700;
  letter-spacing: -.01em;
}

.film__steps p {
  margin: 0;
  font-size: clamp(15px, .8vw, 17px);
  line-height: 1.55;
  color: var(--ink-dim);
  max-width: 30ch;
}

.film__steps strong { color: var(--ink); font-weight: 600; }

@media (max-width: 1024px) {
  .film__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .film__steps p { width: 100%; max-width: none; }
}

@media (max-width: 600px) {
  #register-form.form--light {
    position: static;
    width: 100%;
    max-width: none;
    margin-inline: 0;
    transform: none;
    border-radius: var(--radius);
    border-inline: 1px solid #D5DAE3;
  }
}

@media (max-width: 560px) {
  .film__steps { grid-template-columns: minmax(0, 1fr); }
  .film__steps { text-align: left; }
  .film__steps li { justify-items: start; }
}

.film__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  background:
    radial-gradient(80% 70% at 50% 46%, rgba(61, 139, 255, .12), transparent 70%),
    var(--surface);
  display: grid;
  place-items: center;
}

/* Faint pitch markings, drawn in CSS — an empty rounded rectangle reads as a
   broken image, and a stock "video" glyph reads as a stock site. */
.film__pitch {
  position: absolute;
  inset: 6%;
  border: 1px solid rgba(255, 255, 255, .07);
  border-radius: 8px;
  pointer-events: none;
}

.film__pitch::before,
.film__pitch::after {
  content: "";
  position: absolute;
}

.film__pitch::before {
  inset: 0 50% 0 auto;
  border-right: 1px solid rgba(255, 255, 255, .07);
}

.film__pitch::after {
  top: 50%;
  left: 50%;
  width: 84px;
  height: 84px;
  margin: -42px 0 0 -42px;
  border: 1px solid rgba(255, 255, 255, .07);
  border-radius: 50%;
}

.film__cue {
  position: relative;
  text-align: center;
  padding: var(--space-3);
}

.film__play {
  width: 74px;
  height: 74px;
  margin: 0 auto var(--space-3);
  border-radius: 50%;
  border: 1px solid rgba(253, 141, 29, .38);
  background: rgba(253, 141, 29, .10);
  display: grid;
  place-items: center;
  color: var(--neon);
}

.film__play svg { width: 24px; height: 24px; margin-left: 3px; }

.film__cue p {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* A selected full-size frame paired with compact dot pagination. Each image
   choice remains a real button, while the selected state carries the cue. */
.gallery {
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.gallery__main {
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-2);
}

.gallery__main img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.gallery__thumbnails {
  display: flex;
  justify-content: center;
  gap: 10px;
  padding: var(--space-2) 0 0;
}

.gallery__thumbnail {
  flex: 0 0 10px;
  width: 10px;
  height: 10px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .42);
  border-radius: 999px;
  background: rgba(255, 255, 255, .24);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.gallery__thumbnail img {
  display: none;
}

.gallery__thumbnail:hover,
.gallery__thumbnail:focus-visible { background: rgba(255, 255, 255, .62); }
.gallery__thumbnail.is-active {
  border-color: var(--neon);
  background: var(--neon);
}
.gallery__thumbnail:active { transform: translateY(1px); }

/* Desktop gallery: reserve a fixed rail for the unchanged thumbnails, then
   let the preview frame scale into the remaining visible viewport. The frame
   itself owns the 16:9 ratio, so the image is never stretched or cropped. */
@media (min-width: 901px) {
  .gallery {
    --gallery-rail-h: 83px;
    --gallery-gap: 12px;
    --gallery-viewport-offset: 96px;
    display: grid;
    grid-template-rows: minmax(0, 1fr) var(--gallery-rail-h);
    gap: var(--gallery-gap);
    justify-items: start;
    height: min(675px, calc(100dvh - var(--sitenav-height) - var(--gallery-viewport-offset)));
  }

  .gallery__main {
    min-height: 0;
    width: auto;
    max-width: 100%;
    height: 100%;
    aspect-ratio: 16 / 9;
    justify-self: center;
    margin-inline: auto;
  }

  .gallery__main img {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  .gallery__thumbnails {
    width: 100%;
    justify-content: center;
    padding-top: 0;
  }
}

/* Wide canvases have room for the full gallery story at its native ratio.
   Restore the preview to the gallery's full width and centre the fixed-size
   thumbnail choices within the matching rail. */
@media (min-width: 1441px) {
  .gallery {
    grid-template-rows: auto auto;
    height: auto;
  }

  .gallery__main {
    width: 100%;
    max-width: none;
    height: auto;
    aspect-ratio: 16 / 9;
  }

  .gallery__thumbnails {
    width: 100%;
    justify-content: center;
  }
}

@media (max-width: 640px) {
  .gallery__thumbnails {
    display: flex;
    justify-content: center;
    gap: 10px;
    padding-top: var(--space-1);
  }
  .gallery__thumbnail { flex: 0 0 10px; }
}

/* ---------- vertical flow arrow (rules.html) ----------
   A connector for a SINGLE-COLUMN step list: it sits as its own item between
   two cards and points straight down. The landing page uses .howgrid__wires
   instead, because in a 2×2 grid there is no "between" for an element to
   occupy — a card's next neighbour is sideways on one row and below on the
   other. Both carry the same 34% white rail and the same travelling light, so
   the two pages read as one system. */
.how__arrow {
  display: grid;
  place-items: center;
  color: rgba(255, 255, 255, .34);
  pointer-events: none;
}

/* Fixed width, not 100%: the svg is the only child of a full-width grid cell,
   so a percentage width scales it to the column and the "arrow" renders 1,100px
   tall. The viewBox is 24×64 — the glyph is authored at that size and stays
   there. */
.how__arrow svg { width: 24px; height: 64px; overflow: visible; }

.how__arrow .flowline {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

/* The travelling light: one short dash chased along the same path. The
   dasharray is the dash then a gap longer than the path, so exactly one
   segment is ever visible. */
.how__arrow .flowdash {
  fill: none;
  stroke: var(--neon);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 26 300;
  animation: flow-travel 2.6s linear infinite;
}

@keyframes flow-travel {
  from { stroke-dashoffset: 326; }
  to   { stroke-dashoffset: 0; }
}

/* Stagger, so the four arrows read as one current moving down the page
   rather than four independent blinks. */
.how__arrow:nth-of-type(2) .flowdash { animation-delay: .45s; }
.how__arrow:nth-of-type(3) .flowdash { animation-delay: .9s; }

/* ---------- subpage header ----------
   The two demo pages have no photographic hero to open on, so they open on
   type instead: eyebrow, a display headline, one sentence. Same rhythm as a
   landing section, without pretending to be one. */
.pagehead { padding-block: var(--space-6) var(--space-5); }

.pagehead h1 {
  font-size: clamp(2.2rem, 6vw, 4.4rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: .96;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
  max-width: 16ch;
}

/* The second word takes the accent so the headline has a hinge rather than
   being one uniform block of shouting. */
.pagehead h1 em { font-style: normal; color: var(--neon); }

.pagehead h1.pagehead__sentence { text-transform: none; }

.pagehead .lede { margin: 0; }

/* Sections after the head do not need the full 160px — the head already spent
   the opening interval. */
.pagesection { padding-block: var(--space-6); }

/* ---------- scoring table (rules) ----------
   A real table, because this is real tabular data — points against outcomes.
   A grid of cards would have been the generic move and would have lost the
   column alignment that makes the numbers comparable at a glance. */
.scoretable {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--space-4);
}

.scoretable caption { text-align: left; }

.scoretable th,
.scoretable td {
  padding: var(--space-3) var(--space-2);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: baseline;
}

.scoretable thead th {
  padding-block: var(--space-2);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-bottom-color: var(--line-strong);
}

.scoretable tbody th {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  width: 34%;
}

.scoretable td:last-child { color: var(--ink-dim); font-size: 15px; }

/* The points column is the reason the table exists — tabular figures so the
   plus signs and digits stack, and the accent so the eye can read the column
   without reading the rows. */
.scoretable__pts {
  width: 18%;
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--neon);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Bonuses are a different kind of point — earned by how you play rather than
   by the result — so they read in the secondary accent. */
.scoretable tr[data-kind="bonus"] .scoretable__pts { color: var(--aws); }

/* ---------- leaderboard (demo) ---------- */
/* The table sheds its two least-load-bearing columns on a phone, but a long
   team name can still push it wide. This scrolls the table rather than the
   page — a body that scrolls sideways is the single worst mobile bug, and it
   is always caused by something exactly like this. */
.tablewrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.lb__filters {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0 0 var(--space-4);
  padding: 0;
}

.lb__filters button {
  min-height: 40px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-dim);
  font: 600 13px/1 system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 180ms var(--ease), color 180ms var(--ease);
}

.lb__filters button:hover { border-color: var(--line-strong); color: var(--ink); }

.lb__filters button[aria-pressed="true"] {
  background: var(--neon);
  border-color: var(--neon);
  color: #06080F;
}

.lb {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.lb caption { text-align: left; }

.lb th,
.lb td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--line);
  text-align: left;
}

.lb thead th {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-bottom-color: var(--line-strong);
}

.lb tbody tr:hover { background: rgba(255, 255, 255, .03); }

.lb__rank {
  width: 56px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink-dim);
}

/* A quiet amber podium: the intensity drops from first to third, while the
   rest of the table stays neutral and easy to scan. */
.lb tbody tr:nth-child(1) { background: linear-gradient(90deg, rgba(245, 158, 11, .14), transparent 65%); }
.lb tbody tr:nth-child(2) { background: linear-gradient(90deg, rgba(251, 169, 76, .09), transparent 60%); }
.lb tbody tr:nth-child(3) { background: linear-gradient(90deg, rgba(245, 158, 11, .045), transparent 55%); }

.lb tbody tr:nth-child(1) .lb__rank {
  color: #F59E0B;
  font-size: 17px;
  text-shadow: 0 0 12px rgba(245, 158, 11, .5);
  box-shadow: inset 3px 0 #F59E0B;
}

.lb tbody tr:nth-child(2) .lb__rank { color: #FBA94C; }
.lb tbody tr:nth-child(3) .lb__rank { color: rgba(251, 169, 76, .72); }
.lb tbody tr:nth-child(1) .lb__pts { color: #F59E0B; }
.lb tbody tr:nth-child(2) .lb__pts { color: #FBA94C; }
.lb tbody tr:nth-child(3) .lb__pts { color: rgba(251, 169, 76, .86); }
.lb tbody tr:nth-child(1) .lb__team { font-weight: 700; }
.lb tbody tr:nth-child(1) .lb__team::before { content: "★"; margin-right: 7px; color: #F59E0B; font-size: 12px; vertical-align: 1px; }

.lb__team { font-weight: 600; color: var(--ink); }

.lb__team span {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-dim);
}

/* nowrap is load-bearing: "8–1–0" broke after the first en dash and the column
   rendered two lines tall, which made every row a different height. */
.lb__num {
  width: 78px;
  color: var(--ink-dim);
  font-size: 15px;
  white-space: nowrap;
}

.lb__pts {
  width: 76px;
  text-align: right;
  font-size: clamp(1.05rem, 1.8vw, 1.3rem);
  font-weight: 800;
  color: var(--ink);
}

/* Form: five results, most recent last. Amber carries wins; draws are neutral
   and losses deliberately recede instead of introducing competing colours. */
.form5 { display: flex; gap: 4px; }

.form5 i {
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 6px;
  font-style: normal;
  font-size: 11px;
  font-weight: 700;
  border: 1px solid var(--line-strong);
  color: var(--ink-dim);
}

.form5 i[data-r="W"] { background: rgba(245, 158, 11, .18); border-color: rgba(245, 158, 11, .62); color: #FBA94C; }
.form5 i[data-r="D"] { background: #4B5563; border-color: #4B5563; color: #9CA3AF; }
.form5 i[data-r="L"] { background: rgba(254, 129, 129, .12); border-color: rgba(254, 129, 129, .48); color: #FE8181; }

.lb__note { margin-top: var(--space-3); font-size: 13px; }

/* The demo pages state what they are — a pitch deck that quietly implies live
   data is a promise the backend has not made yet. */
.demoflag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: var(--space-3);
  padding: 6px var(--space-2);
  border: 1px solid rgba(255, 153, 0, .4);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--aws);
}

/* ---------- responsive ---------- */
/* The rails' own min(920px, 100%) handles the narrowing; only the band's
   height and the rail's gutters need a trim before the layout restructures. */
@media (max-width: 1100px) {
  /* No .merge height here: the band carries aspect-ratio 920/168 and shrinks
     with its own width, so a fixed height would only break the ratio. */
  .dateline { gap: var(--space-2); }
}

@media (max-width: 1024px) {
  :root {
    --section-y: 88px;
    --page-gutter: 24px;
  }
  .wrap { width: calc(100% - (2 * var(--page-gutter))); }
  .hero__body { width: calc(100% - (2 * var(--page-gutter))); }


  .duo { grid-template-columns: 1fr; gap: var(--space-4); }
  .duo__intro { position: static; }

  /* One column, so the wire overlay is describing a layout that no longer
     exists — its legs would cross the cards instead of running between them.
     Stacked, the vertical order already says "then". */
  .how { grid-template-columns: 1fr; gap: var(--space-3); }
  .howgrid__wires { display: none; }
  .howflight {
    height: 20px;
    margin-top: var(--space-2);
  }
  .howflight__route { display: none; }
  .howflight__plane {
    left: 50%;
    top: 0;
    offset-path: none !important;
    transform: translateX(-50%) rotate(42deg);
    opacity: 1;
  }
  .howflight.is-active .howflight__plane { animation: none; }
  #how .howflight::before { display: none; }
  .howfinale .how__item { width: 100%; }
  .how__vegas { width: 72%; opacity: 1; }
  .how__item--hero p { padding-right: 0; max-width: 34ch; }
  .how__item--hero .how__art { width: 62%; right: -18%; bottom: -11%; }
  .how__item--squad .chips { justify-content: flex-start; }

  /* One row is a desktop-only promise. In a full-width stacked card the five
     names need ~430px of chip and there is ~340px of card, so nowrap does not
     compress them — it pushes "Striker" past the edge where the card's
     overflow:hidden eats it. Wrapping is the honest result at this width. */
  .how__item--squad .chips { flex-wrap: wrap; }

  /* Stacked, the character follows the copy it decorates. */
  .coach,
  .chatdemo {
    grid-template-columns: 1fr;
    row-gap: var(--space-4);
  }

  .coach__intro h2,
  .coach__intro .lede,
  .chatdemo__intro h2,
  .chatdemo__intro p { max-width: none; }

  /* Stacked, the caption goes back above the window. */
  .chatdemo__intro { order: 0; }

  .coach__mind { width: min(210px, 52%); }
  /* Horizontal bleed here widened the layout enough for Chrome to zoom out. */
  .coach__figure::before { inset: -14% 0; }
  /* Two-up, not four: the two-word labels wrap at this width and the row goes
     ragged. Reading order stays left-to-right, top-to-bottom. */
  .dateline {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--space-3);
    margin-bottom: var(--space-5);
  }

  .how__item--enter { grid-template-columns: 1fr; align-items: start; }

  .partnerband__inner {
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: var(--space-2) var(--space-4);
  }
  .partnerband__group { gap: var(--space-2) var(--space-3); }
  /* Groups wrap to their own rows here — a stretched hairline between
     stacked rows reads as a glitch, so it goes. */
  .partnerband__divider { display: none; }

  .win__head { grid-template-columns: 1fr; align-items: start; }
  .win__head h2 { max-width: none; }
  /* Stacked, the SVG connectors are replaced by the ::before line, so the
     grid gets its row breathing back. */
  .win { grid-template-columns: 1fr; gap: var(--space-2); }
  .win__route { padding-bottom: 100px; }
  .league-champions__art { bottom: -16%; }

  /* Stacked, there is nothing to merge — the two routes are already one
     column. The wide converging glyph would be drawing a join that the layout
     no longer makes, so it goes and a plain line-and-chevron takes over. */
  /* Raised from 76px so the vertical hand-off keeps the extra room the desktop
     band got. The travelling light is deliberately NOT ported to the
     pseudo-element: stacked, the layout already reads top-to-bottom and one
     static chevron says everything the animation would. */
  /* Stacked, the wide converging drawing is hidden and the pseudo-element
     line takes over — so the band drops the art's aspect-ratio and goes back
     to a plain fixed height. */
  /* The pill stays absolutely placed; only its offset changes, because the
     stacked band is a plain line-and-chevron rather than the 920/168 drawing.
     top:38% keeps it clear of the chevron at the band's foot. */
  .merge { height: 104px; aspect-ratio: auto; width: 100%; }
  .merge__sum { top: 38%; }
  .merge__art { display: none; }

  .merge::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 12px;
    border-left: 1px solid var(--line-strong);
  }

  .merge::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 6px;
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--neon);
    border-bottom: 2px solid var(--neon);
    transform: translateX(-50%) rotate(45deg);
  }

  /* One column, so the tear runs across the ticket instead of down it. The
     punched notches only make sense on a vertical perforation — a horizontal
     one would need them on the side walls, which the card's radius eats. */
  .pass { grid-template-columns: 1fr; row-gap: var(--space-3); }
  .pass__stub { padding-top: var(--space-3); border-top: 1px dashed var(--line-strong); }
  .pass__stub::before,
  .pass__stub::after { display: none; }
  .pass__specs { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-3); }
  .pass__covered { max-width: none; padding-right: 0; }
  .pass__art { width: 116px; opacity: .42; }

  .together__art { width: min(240px, 70%); }
  .coach__art { width: 150px; }

  /* The bar keeps the primary registration action visible; the full link set
     moves into a native details menu so it remains reachable on small screens
     without squeezing the brand or wrapping the CTA. */
  .sitenav__inner { min-height: 62px; gap: var(--space-2); padding-block: 8px; }
  .sitenav__league { gap: 4px; }
  .sitenav__league-mark { height: 24px; }
  .sitenav__league-label {
    width: 7ch;
    white-space: normal;
    text-align: center;
    font-size: 14px;
    font-weight: 700;
    line-height: .9;
  }
  .sitenav__links { display: none; }
  .sitenav__sub { display: none; }
  .sitenav__cta {
    order: 1;
    gap: 0;
    margin-left: auto;
  }
  .sitenav__cta :is(.sitenav__login, .sitenav__kiro) { display: none; }

  .sitenav__menu {
    position: relative;
    z-index: 2;
    display: block;
    order: 2;
  }

  .sitenav__menu summary {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: 34px;
    justify-content: center;
    width: 34px;
    padding: 4px;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    color: var(--ink-dim);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .08em;
    list-style: none;
    cursor: pointer;
  }

  .sitenav__menu summary::-webkit-details-marker { display: none; }
  .sitenav__menu summary span { display: none; }
  .sitenav__menu summary i,
  .sitenav__menu summary i::before,
  .sitenav__menu summary i::after {
    display: block;
    width: 13px;
    height: 1px;
    background: currentColor;
  }
  .sitenav__menu summary i { position: relative; }
  .sitenav__menu summary i::before,
  .sitenav__menu summary i::after { content: ""; position: absolute; left: 0; }
  .sitenav__menu summary i::before { top: -4px; }
  .sitenav__menu summary i::after { top: 4px; }
  .sitenav__menu[open] summary { color: var(--ink); border-color: var(--orange-600); }

  .sitenav__menu-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: min(320px, calc(100vw - 32px));
    display: grid;
    gap: 2px;
    padding: var(--space-1);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
  }

  .sitenav__menu-panel a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 42px;
    padding: 0 var(--space-2);
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: .03em;
    text-decoration: none;
  }
  .sitenav__menu-panel a:hover { background: rgba(253, 141, 29, .10); color: var(--orange-600); }
  .sitenav__menu-panel svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; }

  /* The mask is the "more exists" affordance. Without it the only hint that
     the rail scrolls is the last item being sliced mid-word, which reads as a
     layout bug rather than an invitation — and a scrollbar is hidden here
     because a visible one on a 40px strip is uglier than the problem. A fade
     costs no space and no extra element. */
  .sitenav__rail {
    display: block;
    border-top: 1px solid var(--line);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, #000 84%, rgba(0, 0, 0, .15) 100%);
            mask-image: linear-gradient(to right, #000 84%, rgba(0, 0, 0, .15) 100%);
  }

  .sitenav__rail::-webkit-scrollbar { display: none; }

  .sitenav__rail ul {
    list-style: none;
    display: flex;
    gap: var(--space-3);
    margin: 0;
    /* Trailing padding so the last item can scroll clear of the fade rather
       than ending underneath it. */
    padding: 0 var(--space-4) 0 max(16px, env(safe-area-inset-left));
    white-space: nowrap;
  }

  /* 44px of height, from the flex box rather than from padding, so the caps
     stay optically centred on the strip. */
  .sitenav__rail a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink-dim);
    text-decoration: none;
    border-bottom: 2px solid transparent;
  }

  .sitenav__rail a[aria-current="page"] {
    color: var(--ink);
    border-bottom-color: var(--neon);
  }

  .film__play { width: 58px; height: 58px; }

  /* The bar is 62px and the rail is 45px (44px links + its top hairline), so
     the hero's offset has to grow with it or the eyebrow lands under the
     links. Measured against the rendered bar, not guessed. */
  .hero { margin-top: -107px; padding-top: calc(var(--space-5) + 107px); }

  .film__head { display: block; }
  .film__note { margin-top: var(--space-2); }
}

@media (max-width: 700px) {
  /* Route one only: its table is absolutely positioned, and in the stacked
     full-width card it needs to start further left to fill the frame. */
  .league-champions__art { left: 6%; width: 100%; }
}

/* Tablet widths keep the four milestone labels on one horizontal rail. */
@media (min-width: 561px) and (max-width: 900px) {
  /* Keep the supporting hero copy at the same quiet body treatment used on
     phones, rather than letting it compete with the larger tablet headline. */
  .hero__lede {
    color: #8a8a9c;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.55;
  }

  /* On tablet the champions card stays wide enough for its copy to occupy the
     left side, so shift the leaderboard artwork to the opposite edge. */
  .league-champions__art {
    left: auto;
    right: -10%;
    width: 360px;
    height: auto;
    max-width: none;
    object-fit: contain;
    transform: none;
  }

  .win__say { max-width: 42ch; }

  .dateline {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: 0;
    row-gap: 0;
  }

  .dateline__stop { padding-right: var(--space-2); }
  .dateline__when { font-size: clamp(1rem, 2.8vw, 1.35rem); }
  .dateline__what { font-size: 11px; letter-spacing: .02em; }

  .prize__side--right {
    right: -70px;
    bottom: -30px;
    width: 300px;
  }
}

@media (max-width: 560px) {
  .sitenav__league-mark { height: 26px; }

  .league-champions__art {
    left: 20%;
    width: 240px;
  }
}

@media (max-width: 560px) {
  #season .how { grid-template-columns: 1fr; }

  /* Four full-width shallow cards read as a scannable list; a 2-up at ~150px
     per cell puts the 13px copy at 4–5 broken lines. */
  .awards > li { flex-basis: 84%; min-width: 0; }
  .award  { padding: var(--space-2); min-height: 174px; }
  .awardgrid { grid-template-columns: 1fr; }

  /* The rows need no rule: .gaterow already wraps, so a pill that no longer
     fits beside its label drops to its own line by itself. Measured: 390px
     keeps the row on one line (81px tall), 320px wraps it (143px). Both still
     land the confirm and its reason above the fold. */
  .gate__finish .btn { min-width: 0; width: 100%; }
  .done__ctas .btn { width: 100%; justify-content: space-between; }
  .done__entry { grid-template-columns: 1fr; }

  /* A bottom sheet, not a floating box: on a phone the form is the screen,
     and anchoring it to the bottom keeps the first fields nearest the thumb.

     The inset pair is load-bearing. A <dialog> in the top layer is positioned
     against the viewport, and `width: 100%` alone resolved against a
     containing block that kept the base rule's `min(520px, 100% - 32px)`
     inline size — the sheet came out 350px wide, pinned left, with a dead
     40px strip of scrim down the right. Pinning left and right instead of
     setting a width makes the sheet exactly as wide as the screen, whatever
     the base rule said. */
  .modal {
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    max-height: 92svh;
    margin: auto 0 0;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: 0;
  }

  .modal__panel { padding: var(--space-3); }
  .modal--light #modal-formslot { margin-inline: calc(-1 * var(--space-3)); }

  /* Pull the crop right so the LAS VEGAS neon — the prize hook — stays in frame
     alongside the front-runners, instead of being cropped off. */

  .hero__scrim {
    background:
      linear-gradient(to bottom,
        rgba(6, 8, 15, .6) 0%,
        rgba(6, 8, 15, 0) 26%),
      linear-gradient(to right,
        rgba(6, 8, 15, .78) 0%,
        rgba(6, 8, 15, .34) 56%,
        rgba(6, 8, 15, 0) 100%);
  }

  .countdown { gap: var(--space-2); }
  .countdown__unit { min-width: 54px; }

  /* A VERTICAL timeline, not four stacked horizontal ones. The desktop rail is
     a top border, which on a stacked layout draws a line sideways across each
     row and leaves the node floating above its own label — the rail has to
     rotate with the layout, so it becomes a left border instead. */
  .dateline {
    grid-template-columns: 1fr;
    gap: 0;
    margin-bottom: var(--space-5);
  }

  .dateline__stop {
    border-top: 0;
    border-left: 2px solid var(--line-strong);
    padding: 0 0 var(--space-4) var(--space-3);
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
  }

  /* The node moves to the left rail and centres on the date's own baseline. */
  .dateline__stop::before {
    top: 4px;
    left: -8px;
  }

  .dateline__stop--live { border-left-color: var(--neon); }

  .dateline__stop--live::after {
    top: 4px;
    left: -8px;
  }

  /* The last stop keeps its node but drops its rail, so the line ends at the
     final marker rather than trailing into the section below. */
  .dateline__stop:last-child {
    border-left-color: transparent;
    padding-bottom: 0;
  }

  .dateline__when { flex: none; min-width: 92px; font-size: 1.15rem; }
  .dateline__what { margin-top: 0; }

  /* At 390 the brand, a two-word CTA and the AWS lockup do not all fit on one
     line without the wordmark wrapping. The CTA loses its verb — the rail
     below already carries "Register" in full, and a button this size beside a
     logo reads as the primary action whatever it says. */
  .sitenav__word { font-size: 14px; }
  .sitenav__mark { width: 30px; height: 30px; }
  /* The "why it matters" column is the first thing to go — the outcome and its
     points are the table's actual content, and three columns of 12px type on a
     390px screen is unreadable in every one of them. */
  .scoretable td:last-child { display: none; }
  .scoretable tbody th { width: auto; font-size: 15px; }
  .scoretable th,
  .scoretable td { padding: var(--space-2) var(--space-1); }

  /* Same call on the leaderboard: played/form go, rank + team + points stay.
     Those three are what a table position means. */
  .lb__num,
  .lb__form { display: none; }
  .lb th,
  .lb td { padding: var(--space-2) var(--space-1); }
  .lb__rank { width: 38px; }

  /* clamp()'s 150px floor is wider than a third of a phone screen, so the cast
     overflowed and Chrome zoomed the whole page out to fit. Size by viewport. */
  .squad__cast img { width: 30vw; }
  .squad__cast img:nth-child(2) { width: 34vw; margin-inline: -10px; }
  .chips { justify-content: flex-start; }
  .how__item { padding-right: var(--space-5); }

  /* A phone-width bubble capped at 88% wastes the only column there is. */
  .chat__thread { padding: var(--space-2); gap: var(--space-2); }
  .bubble { max-width: 94%; }
}

/* Compact phone cards reserve a smaller header area and reuse the upper-right
   faded-art treatment from Step 02 for the other illustrated steps. */
@media (max-width: 640px) {
  .hero__img {
    object-fit: contain;
    object-position: center top;
    filter: brightness(.66);
  }

  .hero__scrim {
    background: linear-gradient(to bottom,
      rgba(6, 8, 15, 0) 0%,
      rgba(6, 8, 15, 0) 20%,
      rgba(6, 8, 15, 1) 100%);
  }

  .hero__body {
    margin-inline: auto;
    text-align: center;
  }

  .display__main,
  .display__prize,
  .hero__lede,
  .hero__pitch,
  .hero__deadline {
    margin-inline: auto;
    max-width: none;
  }

  .hero__cta { justify-content: center; }

  /* Phone cards need denser insets: the form remains comfortably tappable,
     while the reward flow shows more of each step without changing tablet or
     desktop proportions. */
  #register-form,
  #reward .card { padding: var(--space-3); }

  /* The prize slab deliberately bleeds through the boarding-pass inset. Keep
     that edge-to-edge relationship after the pass receives the smaller phone
     padding above. */
  #reward .pass__prize {
    margin: var(--space-3) calc(-1 * var(--space-3)) calc(-1 * var(--space-3));
    padding: var(--space-2) var(--space-3);
    min-height: 190px;
  }

  #reward .prize__copy {
    width: min(68%, 360px);
  }

  #reward .prize__side {
    display: none;
    width: 38%;
    opacity: .88;
    bottom: -18%;
  }

  #reward .prize__side--left {
    left: -4%;
  }

  #reward .prize__side--right {
    right: -12%;
    bottom: -25%;
  }

  .hero__cup-logo {
    display: block;
    width: min(190px, 60vw);
    margin: 0 auto var(--space-2);
  }

  .hero__lede {
    color: #8a8a9c;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.55;
  }

  .partnerband__inner {
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
  }

  .partnerband__group {
    flex: 1 1 0;
    align-items: flex-start;
    align-content: flex-start;
    gap: var(--space-2);
  }

  .partnerband__logo {
    flex: none;
    max-width: none;
    height: auto;
  }

  .partnerband__logo--aws { width: 60px; }
  .partnerband__logo--minds { width: 82px; }
  .partnerband__logo--onefootball { width: 132px; }

  .partnerband__inner {
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
  }

  .partnerband__group {
    flex: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: var(--space-1);
  }

  .how { grid-auto-rows: auto; }
  .how__item { padding: 88px var(--space-3) var(--space-3); }
  .how__step { top: var(--space-2); left: var(--space-3); }
  .how__num { top: 36px; left: var(--space-3); }

  .how__item .how__stat {
    position: relative;
    z-index: 1;
  }

  .how__item--registration .how__art,
  .how__art--train,
  .how__item--hero .how__art {
    top: var(--space-2);
    right: -8%;
    bottom: auto;
    width: 46%;
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 42%, rgba(0, 0, 0, 0) 100%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 42%, rgba(0, 0, 0, 0) 100%);
  }

  .how__art--train { top: -8%; }

  .how__item--finale .how__vegas {
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: .34;
    -webkit-mask-image: none;
            mask-image: none;
  }

  .how__item--finale > p { color: rgba(255, 255, 255, .88); }
}

/* ---------- gate: narrow phones ----------
   The two step cards stack once side-by-side would squeeze the buttons. The
   old title-left/checklist-right split is gone (Gwen, 2026-07-31): the
   statement now always sits on top at full width. */
@media (max-width: 639px) {
  .gatelist { grid-template-columns: 1fr; }
  .gaterow { min-height: 0; }
}

@media (max-width: 640px) {
  .partnerband__inner {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-2);
  }

  .partnerband__group {
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: var(--space-1);
  }

  .partnerband__group:nth-of-type(3) { flex-grow: 1.35; }

  .partnerband__divider { display: block; }
}

/* ---------- short viewports ----------
   The gate must fit without scrolling: if the disabled Confirm scrolls out of
   view its reason goes with it, and the page reads as a silently greyed button
   — the exact failure spec §5 calls out. The layout now buys this by fitting
   rather than by a sticky bar, so only the truly short viewports need trimming.
   If a target size ever overflows, drop the statement one size step; do not
   reinstate sticky — that was a symptom. */
@media (min-width: 901px) {
  .how__item--registration .how__art {
    top: -6%;
    right: -8%;
    bottom: auto;
    width: 48%;
  }
}

@media (max-height: 620px) {
  .pagewrap { padding-block: var(--space-3); }
  .gate { row-gap: var(--space-3); }
  .gate__back { margin-bottom: var(--space-2); }
  .stepper { margin-bottom: var(--space-2); }
  .gaterow { min-height: 0; }
  .gate__finish { margin-top: var(--space-3); }
}

/* The section is taller than a viewport by design now that the calendar lives
   inside it — Gwen asked for it to scroll. What must still land together in
   one screen is routes + merge + pass: that trio is the argument, and losing
   the pass off the bottom is what breaks it. Head and dateline are allowed to
   scroll off above. Only on the desktop layout: below 900px the section is one
   column and the promise no longer depends on seeing both routes at once. */
/* Desktop only: the champions card stretches to the wildcard column's height
   (~480px+ at 1440), and at its authored size the table hugged the corner of
   the taller frame. Scaled from the bottom-right origin it grows up-left into
   the card's empty middle; below 901px the stacked card keeps the untouched
   base size. */
@media (min-width: 901px) {
  .league-champions__art { transform: rotate(-3deg) scale(1.08); }
}

@media (min-width: 901px) and (max-height: 900px) {
  #reward { padding-block: var(--space-5); }
  .win__head { margin-bottom: var(--space-3); }
  .dateline { margin-bottom: var(--space-5); }
  /* The old 280/118 pair was tuned for a one-line .win__say. The copy is two
     lines now, and 118px of reserved room let the table's top edge climb onto
     the second line — the exact overlap the padding exists to prevent. */
  .win__route { min-height: 292px; padding-bottom: 132px; }
  .win__say { font-size: 14px; }
  /* The band scales by its own aspect-ratio; capping the width is how it
     gets shorter without the drawing distorting. */
  .merge { width: min(760px, 100%); }
  .league-champions__art { bottom: -16%; }
  .pass__route { margin-bottom: var(--space-2); }
  .pass__covered { gap: 10px; }
}

/* Second tier — a 13" laptop at default scaling is a ~760px viewport, and the
   pass fell off the bottom there. Measured, not guessed. */
@media (min-width: 901px) and (max-height: 810px) {
  #reward { padding-block: var(--space-4); }
  .win__head h2 { font-size: clamp(1.7rem, 3.4vw, 2.5rem); }
  .win__head { margin-bottom: var(--space-2); }
  .dateline { margin-bottom: var(--space-4); padding-block: var(--space-2); }
  .win__n { font-size: clamp(2.2rem, 3.6vw, 3rem); }
  .win__route { min-height: 268px; padding-bottom: 118px; }
  .league-champions__art { bottom: -16%; }
  .merge { width: min(660px, 100%); }
  .merge__head { stroke-width: 3; }
  .pass { padding: var(--space-3); }
  .pass__route { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
  .pass__specs { padding-top: var(--space-2); }
  .pass__covered { gap: 8px; }
}

/* Landscape phones (844×390 and friends). Measured, not guessed: at the ≤620
   values the reason line landed 38px below the fold here. */
@media (max-height: 460px) {
  .pagewrap { padding-block: var(--space-2); }
  .gate__back { margin-bottom: var(--space-1); }
  .stepper { margin-bottom: var(--space-1); }
  .gatelist__cap { margin-bottom: var(--space-1); }
  .gaterow { padding-block: 10px; }
  .gate__finish { margin-top: var(--space-2); }
}

/* ---------- motion safety ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }

  /* Must match .js [data-reveal]'s specificity (0-2-0) — a media query adds
     none, so a bare [data-reveal] rule here loses and the content stays
     invisible for exactly the users who asked for less motion. */
  .js [data-reveal] {
    opacity: 1;
    transform: none;
  }

  /* The global rule above zeroes animation *duration*, never delay — without
     this the bubbles sit invisible for 640ms for exactly the people who asked
     for less motion. */
  /* The connector's travelling light is a loop, so zeroing its duration leaves
     a 26px orange stub frozen on the rail. Take the stroke off entirely and
     the merge reads as plain rails into the arrow — which is all it ever
     needed to say. */
  .merge__flow { display: none; }

  /* Same reasoning as .merge__flow: a looped dash with its duration zeroed
     freezes as an orange stub partway along the rail. The static line and its
     arrowhead already say "next" without it. */
  /* Looped dashes freeze mid-path when only their duration is zeroed, leaving
     an orange stub stranded on the wire. Remove the travelling stroke entirely
     and the static rails plus their arrowheads state the flow with no
     movement — which is all it ever needed to say. .flowdash is the vertical
     connector on rules.html; .wire--lit is the landing page's grid overlay. */
  .how__arrow .flowdash,
  .wire--lit { display: none; }

  .howflight__plane {
    animation: none !important;
    opacity: 1;
    offset-distance: 100%;
  }

  /* The global rule zeroes duration, which would freeze the conic gradient at
     whatever angle it happened to reach. Stop the rotation and paint a plain
     accent rim instead — step 04 stays the emphasised card without moving. */
  /* Doubled to match the specificity of the rule it is overriding. The brighter
     fill stays — only the rotating rim is replaced by a static accent border,
     because emphasis is not motion. */
  .how__item--hero.how__item--hero {
    animation: none;
    border: 2px solid rgba(255, 138, 74, .58);
    background:
      radial-gradient(130% 110% at 100% 100%, rgba(255, 122, 48, .30), transparent 66%) padding-box,
      radial-gradient(90% 80% at 0% 0%, rgba(255, 153, 0, .10), transparent 62%) padding-box,
      linear-gradient(168deg, #1E1A22, #15141C) padding-box;
  }

  /* The expanding ring is a separate element, so zeroing its duration would
     freeze it mid-scale as a stray circle around the node. Remove it: the
     filled accent node and its accent rail segment already say "live". */
  .dateline__stop--live::after { display: none; }

  /* Colour/border still change on hover (state feedback), nothing translates.
     The sheen sweep is pure motion, so it goes entirely. */
  .award,
  .award__go { transition: none; }
  .award::after { display: none; }

  /* The prize keeps its gold — colour is not motion — but the shimmer sweep
     and the coin glints hold still. */
  .prize__n { animation: none; background-position: 50% 0; }
  .prize__spark { animation: none; opacity: .7; }

  /* The plane parks mid-runway; the wider spacing stays. */
  .pass__plane { animation: none; }

  .js .chat .msg {
    opacity: 1;
    transform: none;
    animation-delay: 0s !important;
  }
}

/* ---------- legal pages (official-rules / terms / privacy) ----------
   Long-form document prose. One measure, quiet type, real tables — these
   pages are for reading and citing, not for selling, so no cards, no
   reveals, no accent theatrics beyond links. */
.legal { max-width: 76ch; padding-bottom: var(--space-6); }

.legal h2 {
  font-size: 1.3rem;
  letter-spacing: -.01em;
  margin: var(--space-5) 0 var(--space-2);
}

.legal h3 {
  font-size: 1.02rem;
  margin: var(--space-4) 0 var(--space-2);
}

.legal p,
.legal li {
  color: var(--ink-dim);
  font-size: .98rem;
  line-height: 1.7;
}

.legal p { margin: 0 0 1em; }
.legal b, .legal strong { color: var(--ink); font-weight: 600; }

.legal a {
  color: var(--accent-600);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.legal a:hover { color: var(--accent-hover); }

.legal ol, .legal ul { margin: 0 0 1em; padding-left: 1.5em; }
.legal li { margin-bottom: .45em; }
.legal li > ol, .legal li > ul { margin-top: .45em; }

/* Documents cite their own clause numbers (1.4.1, §6.2) — the numbering is
   part of the text, so lists that carry it are unstyled and the numbers live
   in the copy itself. */
.legal ol[data-plain], .legal ul[data-plain] { list-style: none; padding-left: 0; }

.legal__updated {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 var(--space-4);
}

/* Wide tables scroll in their own frame; the page never scrolls sideways. */
.legal .tablewrap { overflow-x: auto; margin: var(--space-3) 0 var(--space-4); }

.legal table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: .9rem;
}

.legal th, .legal td {
  border: 1px solid var(--line);
  padding: var(--space-1) var(--space-2);
  text-align: left;
  vertical-align: top;
  color: var(--ink-dim);
  line-height: 1.55;
}

.legal thead th {
  color: var(--ink);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  border-bottom-color: var(--line-strong);
}
