/* =========================================================================
   MutRadar
   =========================================================================

   THE PAGE IS ONE SNAP, BROKEN DOWN.

   A hero that states the idea, then a field that stays pinned while you
   scroll through five beats of a single read: the huddle breaking, the
   personnel, their book, the call, the snap. The scroll position drives the
   camera, the markers, the tendency bars and the route. The copy scrolls
   over the top of it.

   The language around that story is flat and loud rather than dark and
   glassy: the brand colour is the GROUND, not an accent, the display type is
   enormous, and each section is one full-bleed field of colour. Restraint
   read as unfinished, so there is none here.

   PALETTE — four grounds, and nothing else
     yolk   #FFD400   telestrator yellow, used as a floor
     ink    #0B0F0C   near-black, the other floor
     bone   #F1EDE1   warm paper, the third floor
     pitch  #071309   the night field, only ever inside the 3D

   TYPE
     Archivo 900, width axis at 112  -- broadcast lower-third, set enormous
     Caveat 700                      -- the coach's hand, for the emphasis
     Geist 400/500/600               -- everything you actually read
   Deliberately not Inter, Helvetica, Arial or Roboto.
   ====================================================================== */

:root {
  --yolk:    #FFD400;
  --yolk-2:  #FFE873;
  --ink:     #0B0F0C;
  --ink-2:   #131A15;
  --bone:    #F1EDE1;
  --bone-2:  #E3DDCB;
  --pitch:   #071309;

  --live:    #FF3B30;
  --hair-d:  rgba(255, 255, 255, .13);
  --hair-l:  rgba(11, 15, 12, .16);

  --display: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --hand:    "Caveat", ui-serif, cursive;
  --font:    "Geist", ui-sans-serif, system-ui, sans-serif;

  --t1: 11px;
  --t2: 15px;
  --t3: clamp(16px, .5vw + 14px, 19px);
  --t4: clamp(21px, 1.4vw + 15px, 30px);
  --t5: clamp(34px, 3.8vw + 16px, 72px);

  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 36px; --s7: 56px;
  --s8: clamp(56px, 8vw, 104px);
  --s9: clamp(88px, 12vw, 168px);

  --wrap: 1280px;
  --gut: clamp(20px, 4vw, 48px);
  --ease: cubic-bezier(.32, .72, 0, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--ink);
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--ink);
  font: 400 var(--t2)/1.6 var(--font);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

/* Grain, flat. No mix-blend-mode: blending a fixed full-viewport layer over a
   page that carries a composited WebGL canvas is a documented way to lose the
   whole frame to white, and at three percent it was never worth the risk. */
.grain {
  position: fixed; inset: 0; z-index: 6; pointer-events: none; opacity: .03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1, h2, h3 {
  margin: 0; font-family: var(--display); font-weight: 900;
  font-variation-settings: "wdth" 112;
  line-height: .92; letter-spacing: -.045em;
  overflow-wrap: normal;              /* a heading is never broken mid-word */
}
h1 em, h2 em, h3 em, .hand {
  font-family: var(--hand); font-weight: 700; font-style: normal;
  letter-spacing: -.01em; font-variation-settings: normal;
  /* the hand sits smaller on the metrics but reads larger, so it is scaled up
     and nudged back onto the baseline of the grotesque beside it */
  font-size: 1.24em; line-height: .78; display: inline-block;
  transform: translateY(.06em) rotate(-1.6deg);
}
p { margin: 0; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
ol, ul { margin: 0; padding: 0; list-style: none; }

.wrap {
  width: 100%; max-width: var(--wrap); margin-inline: auto;
  padding-inline: max(var(--gut), env(safe-area-inset-left));
}
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }

.skip {
  position: absolute; top: 0; left: 0; z-index: 90;
  width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
  white-space: nowrap; background: var(--ink); color: var(--yolk);
  padding: 12px 18px; font-weight: 700; border-radius: 0 0 14px 0;
}
.skip:focus { width: auto; height: auto; overflow: visible; clip-path: none; }

#top-sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 40px; }

/* ============================================================== bands ===
   Each section is one full-bleed field of colour. */
.band-ink  { background: var(--ink);  color: var(--bone); }
.band-bone { background: var(--bone); color: var(--ink); }
.band-yolk { background: var(--yolk); color: var(--ink); }
.band-ink h1, .band-ink h2, .band-ink h3 { color: var(--bone); }
.band-ink em { color: var(--yolk); }
.band-bone h1, .band-bone h2, .band-bone h3,
.band-yolk h1, .band-yolk h2, .band-yolk h3 { color: var(--ink); }

/* ================================================================ nav ===
   A floating outlined pill. Over the yellow hero it is ink on nothing; the
   moment it leaves, it takes a dark glass ground so it stays readable over
   the field. */
.nav {
  position: fixed; inset: 14px 0 auto; z-index: 40;
  display: flex; justify-content: center;
  padding-inline: max(var(--gut), env(safe-area-inset-left));
  pointer-events: none;
}
.nav-pill {
  pointer-events: auto;
  width: 100%; max-width: var(--wrap); height: 58px;
  display: flex; align-items: center; gap: var(--s5);
  padding: 0 7px 0 var(--s5); border-radius: 999px;
  border: 1px solid transparent; background: transparent;
  transition: background .5s var(--ease), border-color .5s var(--ease),
              color .5s var(--ease), backdrop-filter .5s var(--ease);
}
.nav.stuck .nav-pill {
  background: rgba(11, 15, 12, .82); border-color: var(--hair-d);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}
.brand { display: flex; align-items: center; gap: 10px; flex: none; min-height: 44px; }
.brand-mark { width: 30px; height: 30px; flex: none; border-radius: 6px; }
.brand-word {
  font-family: var(--display); font-weight: 900; font-size: 20px;
  font-variation-settings: "wdth" 112; letter-spacing: -.04em; line-height: 1;
  color: var(--ink);
}
.nav.stuck .brand-word { color: var(--bone); }
.nav-links { display: flex; gap: 6px; margin-inline: auto; }
.nav-links a {
  font-size: 10px; font-weight: 700; letter-spacing: .14em; white-space: nowrap;
  padding: 9px 15px; border-radius: 999px; border: 1px solid var(--hair-l);
  color: var(--ink); transition: background .3s var(--ease), color .3s var(--ease),
                                 border-color .3s var(--ease);
}
.nav-links a:hover { background: var(--ink); color: var(--yolk); border-color: var(--ink); }
.nav.stuck .nav-links a { color: var(--bone); border-color: var(--hair-d); }
.nav.stuck .nav-links a:hover { background: var(--yolk); color: var(--ink); border-color: var(--yolk); }

/* ============================================================= button === */
.btn {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  padding: 0 7px 0 22px; min-height: 46px; border-radius: 999px;
  border: 1.5px solid transparent;
  font: 700 var(--t2)/1 var(--font); letter-spacing: -.01em;
  cursor: pointer; white-space: nowrap;
  transition: transform .4s var(--ease), background .4s var(--ease),
              border-color .4s var(--ease), color .4s var(--ease);
}
.btn > span:first-child { padding-block: 2px; }
.btn .ico {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: 999px;
  background: rgba(255, 255, 255, .18);
  transition: transform .4s var(--ease);
}
.btn:hover .ico { transform: translate(2px, -2px) scale(1.06); }
.btn:active { transform: scale(.975); }

.btn-ink { background: var(--ink); color: var(--bone); }
.btn-ink .ico { background: rgba(255, 255, 255, .14); }
.btn-ink:hover { background: #000; }
.btn-yolk { background: var(--yolk); color: var(--ink); }
.btn-yolk .ico { background: rgba(11, 15, 12, .16); }
.btn-yolk:hover { background: var(--yolk-2); }
.btn-outline {
  padding-inline: 22px; color: currentColor; border-color: currentColor;
}
.btn-outline:hover { background: var(--ink); color: var(--yolk); border-color: var(--ink); }
.band-ink .btn-outline:hover { background: var(--bone); color: var(--ink); border-color: var(--bone); }

.btn-sm { min-height: 40px; font-size: 12px; padding-left: 18px; letter-spacing: .06em; }
.btn-sm .ico { width: 26px; height: 26px; }
.btn-lg { min-height: 56px; font-size: var(--t3); padding-left: 28px; }
.btn-lg .ico { width: 36px; height: 36px; }
.btn-outline.btn-lg { padding-inline: 28px; }

:where(a, button, summary):focus-visible {
  outline: 2px solid currentColor; outline-offset: 4px; border-radius: 999px;
}

/* ============================================== hamburger and menu ====== */
.burger {
  display: none; position: relative; flex: none; width: 44px; height: 44px;
  padding: 0; border: 1px solid var(--hair-l); border-radius: 999px;
  background: transparent; cursor: pointer;
}
.nav.stuck .burger { border-color: var(--hair-d); }
.burger span {
  position: absolute; left: 50%; top: 50%; margin-left: -9px;
  width: 18px; height: 1.5px; border-radius: 2px; background: var(--ink);
  transition: transform .5s var(--ease), background .4s var(--ease);
}
.nav.stuck .burger span { background: var(--bone); }
.burger span:first-child { transform: translateY(-3.5px); }
.burger span:last-child  { transform: translateY(3.5px); }
.burger[aria-expanded="true"] span:first-child { transform: rotate(45deg); }
.burger[aria-expanded="true"] span:last-child  { transform: rotate(-45deg); }

.menu {
  position: fixed; inset: 0; z-index: 39; background: var(--yolk);
  opacity: 0; transition: opacity .45s var(--ease);
}
.menu.open { opacity: 1; }
.menu-inner {
  height: 100%; display: flex; flex-direction: column; justify-content: center;
  gap: var(--s3); padding: 0 var(--gut);
}
.menu-inner a:not(.btn) {
  font-family: var(--display); font-weight: 900; font-variation-settings: "wdth" 112;
  font-size: clamp(32px, 10vw, 54px); letter-spacing: -.05em; color: var(--ink);
  overflow: hidden; padding-block: 4px;
}
.menu-inner a span, .menu-inner .btn {
  display: inline-flex; transform: translateY(110%); opacity: 0;
  transition: transform .7s var(--ease), opacity .5s var(--ease);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.menu-inner .btn { transform: translateY(30px); }
.menu.open .menu-inner a span, .menu.open .menu-inner .btn { transform: none; opacity: 1; }
.menu-cta { align-self: flex-start; margin-top: var(--s5); }
body.locked { overflow: hidden; }

/* =============================================================== hero ===
   The brand colour is the floor. */
.hero {
  position: relative; background: var(--yolk); color: var(--ink);
  min-height: 100svh; display: flex; align-items: center;
  padding: calc(58px + var(--s8)) 0 var(--s8); overflow: hidden;
}
.hero-inner { position: relative; z-index: 2; }
.hero h1 {
  font-size: clamp(38px, 10.6vw, 146px);
  line-height: .86; letter-spacing: -.055em;
}
.kinetic .ln { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
.kinetic .ln > span { display: block; }
.js .kinetic .ln > span {
  transform: translateY(108%);
  animation: titleUp 1s var(--ease) forwards;
  animation-delay: calc(.1s + var(--i) * .12s);
}
@keyframes titleUp { to { transform: none; } }

.hero-sub {
  margin-top: var(--s6); max-width: 44ch;
  font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  line-height: 1.7;
}
.hero-cta { display: flex; gap: var(--s3); margin-top: var(--s6); flex-wrap: wrap; }

.scroll-cue {
  display: inline-flex; align-items: center; gap: 4px; margin-top: var(--s8);
  font-size: 10px; font-weight: 700; letter-spacing: .22em;
  opacity: .55;
}
.scroll-cue i {
  width: 1px; height: 26px; background: currentColor; display: block;
  transform-origin: top; animation: cue 1.9s var(--ease) infinite;
}
@keyframes cue { 0%,100% { transform: scaleY(.35) } 50% { transform: scaleY(1) } }

/* rotated micro-labels pinned to the edges, the way a scorebug frames a shot */
.edge {
  position: absolute; top: 50%; z-index: 2;
  font-size: 10px; font-weight: 700; letter-spacing: .22em; white-space: nowrap;
  opacity: .5;
}
.edge-l { left: 0; transform: rotate(-90deg) translateX(-50%); transform-origin: left center; margin-left: 18px; }
.edge-r { right: 0; transform: rotate(90deg) translateX(50%); transform-origin: right center; margin-right: 18px; }

/* chalk, the way a coach actually marks up a board */
.doodle { position: absolute; color: var(--ink); opacity: .16; z-index: 1; }
.d1 { width: 46px; top: 18%;  right: 12%; transform: rotate(12deg); }
.d2 { width: 88px; bottom: 22%; right: 24%; transform: rotate(-6deg); }
.d3 { width: 62px; top: 26%;  right: 30%; transform: rotate(-14deg); }

/* ============================================================== story ===
   The field is pinned for the whole section; the beats scroll over it. */
.story { position: relative; background: var(--pitch); color: var(--bone); }
.stage {
  position: sticky; top: 0; height: 100svh; overflow: hidden; z-index: 0;
  background: var(--pitch);
}
.gl { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0;
      transition: opacity 1s var(--ease); }
html.gl .gl { opacity: 1; }
html.gl .stadium { opacity: 0; transition: opacity .8s var(--ease); }

/* copy sits right; the scrim keeps it readable whatever the camera is doing */
.stage::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background:
    linear-gradient(265deg, rgba(7,19,9,.9) 0%, rgba(7,19,9,.42) 30%, transparent 56%),
    linear-gradient(0deg, rgba(7,19,9,.72), transparent 30%);
}

.beats { position: relative; z-index: 2; margin-top: -100svh; }
.beat {
  min-height: 100svh; display: grid; align-items: center; justify-items: end;
  padding-inline: max(var(--gut), env(safe-area-inset-left));
}
.beat-card { max-width: 30rem; }
.beat-card h2 { font-size: clamp(34px, 4.4vw, 62px); color: var(--bone); }
.beat-card em { color: var(--yolk); }
.beat-card p {
  margin-top: var(--s5); font-size: var(--t3); line-height: 1.6;
  color: rgba(241, 237, 225, .68);
}
.beat-card .btn { margin-top: var(--s6); }

/* --- the broadcast furniture over the field ---------------------------- */
.hud { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.hud .bar { position: absolute; top: 0; left: 0; right: 0; height: 3px;
            background: rgba(255,255,255,.08); }
.hud .bar i { display: block; height: 100%; width: var(--p, 0%); background: var(--yolk); }
.onair {
  position: absolute; top: calc(58px + var(--s5)); left: var(--gut);
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--live); color: #fff; border-radius: 999px;
  padding: 5px 11px; font: 700 10px/1 var(--font); letter-spacing: .14em;
}
.onair i { width: 5px; height: 5px; border-radius: 50%; background: #fff;
           animation: blink 1.5s steps(1) infinite; }
@keyframes blink { 0%,60% { opacity: 1 } 61%,100% { opacity: .25 } }

.chapter {
  position: absolute; top: calc(58px + var(--s5) + 5px); left: calc(var(--gut) + 74px);
  font-size: 10px; font-weight: 700; letter-spacing: .22em; color: rgba(241,237,225,.5);
}
/* The personnel readout, as the broadcast shows it: one dark pill, hairline
   rules between the groups. It is the offence's own grouping, so it stays up
   from the moment the formation is set. */
.pers {
  display: flex; align-items: stretch; width: max-content; margin-top: 14px;
  background: rgba(6, 10, 7, .9); border: 1px solid var(--hair-d);
  border-radius: 10px; overflow: hidden;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.pers span {
  padding: 9px 14px; font-size: 15px; font-weight: 700; color: var(--bone);
  letter-spacing: .01em; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* A real pipe, not a border. A hairline rule vanishes the moment the
   stylesheet is stale or blocked, and the cells then run together as
   "3 WR1 TE1 RB"; a character cannot do that. */
.pers i {
  display: flex; align-items: center; font-style: normal;
  font-size: 15px; font-weight: 400; color: rgba(241, 237, 225, .38);
}
/* an author `display: flex` outranks the browser's own [hidden] rule, so a
   hidden pill would otherwise stay on screen as an empty black tab */
.pers[hidden] { display: none; }

.stat { position: absolute; left: var(--gut); bottom: var(--s7); }
.stat-n {
  display: block; font-family: var(--display); font-weight: 900;
  font-variation-settings: "wdth" 112; letter-spacing: -.06em; line-height: .82;
  font-size: clamp(64px, 11vw, 168px); color: var(--bone);
}
.stat-u {
  display: block; margin-top: var(--s3);
  font-size: 10px; font-weight: 700; letter-spacing: .22em; color: var(--yolk);
}

/* ---- the CSS field: what shows if the 3D never arrives ---------------- */
.stadium { position: absolute; inset: 0; overflow: hidden; }
.crowd {
  position: absolute; left: -10%; right: -10%; top: 0; height: 46%;
  background:
    radial-gradient(circle at 20% 30%, rgba(255,214,150,.10) 0 1.5px, transparent 2px),
    radial-gradient(circle at 62% 64%, rgba(190,220,255,.09) 0 1.5px, transparent 2px);
  background-size: 34px 30px, 46px 38px;
  filter: blur(1.4px);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 34%, #000 72%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 34%, #000 72%, transparent);
}
.rigs { position: absolute; inset: 0; }
.rigs i {
  position: absolute; left: var(--x); top: 6%;
  width: 3px; height: 3px; border-radius: 50%; background: #FFF6DC;
  box-shadow: 0 0 14px 5px rgba(255,246,220,.5), 0 0 60px 22px rgba(255,240,200,.17);
  transform: scale(var(--s));
}
.rigs i::after {
  content: ""; position: absolute; left: 50%; top: 2px;
  --shaft: clamp(130px, 17vw, 260px);
  width: var(--shaft); height: 60vh; margin-left: calc(var(--shaft) / -2);
  background: linear-gradient(to bottom, rgba(255,246,220,.085), transparent 78%);
  clip-path: polygon(46% 0, 54% 0, 100% 100%, 0 100%);
  filter: blur(14px);
}
.haze {
  position: absolute; left: -10%; right: -10%; top: 22%; height: 34%;
  background: linear-gradient(180deg, transparent, rgba(150,220,180,.09) 55%, transparent);
  filter: blur(26px);
}
.bloom {
  position: absolute; left: 50%; top: 18%; width: 140%; aspect-ratio: 2 / 1;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(120,235,175,.2), rgba(28,124,72,.09) 45%, transparent 72%);
  filter: blur(20px);
}
.pitch3d { position: absolute; inset: 0; perspective: 1100px; perspective-origin: 50% 26%; }
.plane {
  position: absolute; left: -30%; right: -30%; top: 34%; bottom: -46%;
  transform-origin: 50% 0%; transform: rotateX(var(--tilt, 66deg));
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 5%, #000 90%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 5%, #000 90%, transparent 100%);
}
/* Yard lines run ACROSS your view, not along it. They were vertical, which is
   what made the whole field read sideways: from behind the offense you see the
   yard lines stack away from you and the two sidelines converge. */
.turf {
  position: absolute; inset: 0;
  background:
    /* yard lines, every five */
    repeating-linear-gradient(0deg, transparent 0 92px, rgba(223,243,230,.20) 92px 95px),
    /* mown bands, parallel to them */
    repeating-linear-gradient(0deg, rgba(28,124,72,.20) 0 92px, rgba(28,124,72,.09) 92px 184px),
    linear-gradient(0deg, rgba(22,96,58,.62), rgba(8,28,17,.22));
}
/* sidelines and the two hash columns: the marks that tell you where you are */
/* The plane runs from -30% to 130% of the stage, so a percentage measured
   inside it lands at stage = -30 + f x 160. These put the sidelines just
   outside the widest receiver instead of somewhere off the screen. */
.marks { position: absolute; left: 24%; right: 24%; top: 0; bottom: 0; }
.marks::before, .marks::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 4px;
  background: rgba(223, 243, 230, .5);
}
.marks::before { left: 0; }
.marks::after  { right: 0; }
.marks {
  background:
    repeating-linear-gradient(0deg, transparent 0 74px, rgba(223,243,230,.22) 74px 80px)
      33% 0 / 3px 100% no-repeat,
    repeating-linear-gradient(0deg, transparent 0 74px, rgba(223,243,230,.22) 74px 80px)
      67% 0 / 3px 100% no-repeat;
}
/* the hashes are two dashed columns a third of the way in from each sideline */
.hashes { position: absolute; inset: 0; pointer-events: none; }
/* Sized so the diagram fits by WIDTH rather than height -- at the old ratio
   preserveAspectRatio was letterboxing it into the middle third. */
.tele-zone { position: absolute; left: 26%; right: 26%; top: 6%; height: 86%; }
.chalk { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
/* --- the play, as a coach draws it -------------------------------------
   Two sides in two colours, because the first thing you read on a board is
   who is who: the offense in chalk, the defense in a cold steel blue, the
   call in telestrator yellow, and everything the quarterback still has to
   hold in a dimmer white. */
.chalk path, .chalk circle { vector-effect: non-scaling-stroke; }
.los    { stroke: #DFF3E6; stroke-width: 2.5; opacity: .45; }
.sticks { stroke: #FFD400; stroke-width: 2;   opacity: .2; stroke-dasharray: 3 18; }
.o      { stroke: #FFFFFF; stroke-width: 3;   opacity: .95; }
.x      { stroke: #8FB4D8; stroke-width: 3.4; opacity: .95; }
.cover  { stroke: #8FB4D8; stroke-width: 2.4; opacity: .55; stroke-dasharray: 10 12; }
.block  { stroke: #FFFFFF; stroke-width: 2.6; opacity: .45; }
.alt    { stroke: #DFF3E6; stroke-width: 2.8; opacity: .5; }
.route, .head { stroke: #FFD400; stroke-width: 5.5;
                filter: drop-shadow(0 0 9px rgba(255,212,0,.5)); }
.ring   { stroke: #FFD400; stroke-width: 4.5;
          filter: drop-shadow(0 0 9px rgba(255,212,0,.45)); }
/* the throw. Solid rather than dotted, because the same stroke-dasharray
   that would make it dotted is what draws it. */
.ball   { stroke: #FFD400; stroke-width: 3.4; opacity: .9;
          filter: drop-shadow(0 0 8px rgba(255,212,0,.45)); }
.catch  { stroke: #FFD400; stroke-width: 4; }
.ghost path { stroke: #DFF3E6; stroke-width: 3.2; }
.ghost { opacity: 0; }

/* the shell, shaded the way a coordinator fills it in */
/* The shell, in Madden's own colour language: a zone's colour tells you what
   it is responsible for before you have read anything else. Deep is violet,
   the hook/curl band is cyan, the flats are green. Solid translucent fills
   with a lit edge rather than dashed outlines, because that is how the
   overlay actually looks on screen. */
.zone { stroke-width: 2.4; }
.z-deep {
  fill: rgba(139, 108, 245, .17); stroke: rgba(160, 134, 255, .72);
  filter: drop-shadow(0 0 12px rgba(139, 108, 245, .35));
}
.z-hook {
  fill: rgba(47, 184, 230, .16); stroke: rgba(86, 208, 246, .7);
  filter: drop-shadow(0 0 12px rgba(47, 184, 230, .32));
}
.z-flat {
  fill: rgba(57, 217, 138, .15); stroke: rgba(94, 232, 163, .68);
  filter: drop-shadow(0 0 12px rgba(57, 217, 138, .3));
}
/* the corners' drop, in the colour of the zone they are dropping into */
.cover { stroke: rgba(160, 134, 255, .6); }
/* they bring it: hot colour, so a blitz never reads as coverage */
.blitz, .tip { stroke: #FF4D2E; stroke-width: 5;
               filter: drop-shadow(0 0 10px rgba(255,77,46,.6)); }

/* Nothing is visible until the scroll puts it there. The one-shot fallback
   below covers browsers with no scroll timeline, and with no scripting at all
   the whole diagram is simply already drawn. */
.js .chalk .o, .js .chalk .x, .js .chalk .cover,
.js .chalk .block, .js .chalk .los, .js .chalk .sticks,
.js .chalk .head, .js .chalk .catch, .js .chalk .zone,
.js .chalk .tip { opacity: 0; }
.js .chalk .route, .js .chalk .alt, .js .chalk .ring,
.js .chalk .ball, .js .chalk .blitz { stroke-dasharray: 1400; stroke-dashoffset: 1400; }

/* Fallback for browsers with no scroll timeline: the diagram draws once when
   it arrives. Scoped behind .noscrolltl, which radar.js sets ONLY when the
   timeline is genuinely unavailable -- an earlier version tried to cancel
   this with a later rule instead, lost the specificity fight, and the whole
   play appeared at once on the very first beat. */
.noscrolltl .plane.on .chalk .o, .noscrolltl .plane.on .chalk .x,
.noscrolltl .plane.on .chalk .cover, .noscrolltl .plane.on .chalk .block,
.noscrolltl .plane.on .chalk .los, .noscrolltl .plane.on .chalk .sticks,
.noscrolltl .plane.on .chalk .head, .noscrolltl .plane.on .chalk .catch,
.noscrolltl .plane.on .chalk .zone, .noscrolltl .plane.on .chalk .tip {
  animation: pop .7s var(--ease-out) forwards;
}
.noscrolltl .plane.on .chalk .route, .noscrolltl .plane.on .chalk .alt,
.noscrolltl .plane.on .chalk .ring, .noscrolltl .plane.on .chalk .ball,
.noscrolltl .plane.on .chalk .blitz {
  animation: draw 1.4s var(--ease-out) .3s forwards;
}
.noscrolltl .plane.on .chalk .ghost { animation: flash 3s var(--ease-out) forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes pop { from { opacity: 0 } to { opacity: 1 } }
@keyframes flash { 0% { opacity: 0 } 22% { opacity: .5 } 68% { opacity: .5 } 100% { opacity: 0 } }

/* ============================================================ sections == */
section { position: relative; }
.band-ink, .band-bone, .band-yolk { padding: var(--s9) 0; }
h2 { font-size: var(--t5); }

/* --- the reader --------------------------------------------------------- */
.marked {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .95fr);
  gap: var(--s8); align-items: start; margin-top: var(--s8);
}
.note {
  padding: var(--s6) 0; border-bottom: 1px solid var(--hair-d);
  display: grid; grid-template-columns: 54px minmax(0, 1fr); gap: var(--s4); align-items: start;
}
.note:first-child { border-top: 1px solid var(--hair-d); }
.note .ring {
  width: 38px; height: 38px; border: 1.5px solid var(--yolk);
  display: grid; place-items: center; color: var(--yolk);
  font-weight: 700; font-size: var(--t1); font-family: var(--font);
  border-radius: 60% 55% 62% 58% / 55% 60% 56% 62%;
  filter: none;
}
.note h3 { font-size: var(--t4); margin-bottom: 8px; letter-spacing: -.03em; }
.note p { color: rgba(241,237,225,.6); font-size: var(--t2); }

.book .shell { border-radius: 26px; padding: 6px; background: rgba(255,255,255,.05);
               border: 1px solid var(--hair-d); }
.book .core { border-radius: 20px; background: rgba(255,255,255,.03); padding: var(--s5) var(--s6) var(--s6); }
.pb { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
      padding-bottom: var(--s4); margin-bottom: var(--s5); border-bottom: 1px solid var(--hair-d); }
.pb-k { font-size: 9px; font-weight: 700; letter-spacing: .2em; color: rgba(241,237,225,.42); }
.pb-v { font-family: var(--display); font-weight: 900; font-variation-settings: "wdth" 108;
        font-size: var(--t3); letter-spacing: -.03em; color: var(--yolk); }
.pb-n { margin-left: auto; font-size: var(--t1); color: rgba(241,237,225,.42); }

.chips { display: flex; gap: 6px; margin-bottom: var(--s5); flex-wrap: wrap; }
.chips button {
  flex: 1 1 auto; min-height: 40px; padding: 0 var(--s4); border-radius: 999px; cursor: pointer;
  border: 1px solid var(--hair-d); background: transparent;
  font: 600 13px/1 var(--font); color: rgba(241,237,225,.6); white-space: nowrap;
  transition: color .35s var(--ease), background .35s var(--ease), border-color .35s var(--ease);
}
.chips button:hover { color: var(--bone); border-color: rgba(255,255,255,.3); }
.chips button[aria-selected="true"] {
  color: var(--ink); font-weight: 700; background: var(--yolk); border-color: var(--yolk);
}
.book-head { display: flex; justify-content: space-between; gap: var(--s4);
  font-family: var(--display); font-size: 10px; font-weight: 800;
  font-variation-settings: "wdth" 112; letter-spacing: .16em; color: rgba(241,237,225,.5);
  padding-bottom: var(--s4); border-bottom: 1px solid var(--hair-d); }
.book .row { display: grid; grid-template-columns: minmax(0,1fr) 84px 52px; gap: var(--s4);
  align-items: center; padding: var(--s5) 0; border-bottom: 1px solid var(--hair-d); }
.rows .row:last-child { border-bottom: 0; }
.book .play { font-size: var(--t2); font-weight: 600; color: rgba(241,237,225,.8); min-width: 0; }
.book .row:first-of-type .play { color: var(--bone); font-weight: 700; }
.book .bar { height: 5px; border-radius: 999px; background: rgba(255,255,255,.1); overflow: hidden; }
.book .bar i { display: block; height: 100%; width: var(--w); border-radius: 999px; background: var(--yolk); }
.js .book .bar i { width: 0; }
.js .book.lit .bar i { width: var(--w); transition: width 1s var(--ease) .15s; }
.book .pct { text-align: right; font-family: var(--display); font-weight: 900;
             font-variation-settings: "wdth" 108; font-size: var(--t3); color: var(--bone); }
.book .row:first-of-type .pct { color: var(--yolk); }
.book-foot { padding-top: var(--s4); margin-top: var(--s4); font-size: var(--t1);
             color: rgba(241,237,225,.42); border-top: 1px solid var(--hair-d); }

/* --- who ---------------------------------------------------------------- */
.rosters { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--s4); margin-top: var(--s8); }
.roster { min-width: 0; }
.roster.wide { grid-row: span 2; }
.roster .shell { height: 100%; border-radius: 26px; padding: 6px;
                 background: rgba(11,15,12,.06); border: 1px solid var(--hair-l); }
.roster .core { height: 100%; border-radius: 20px; background: rgba(255,255,255,.34);
                padding: var(--s7) var(--s6); transition: transform .5s var(--ease); }
.roster.wide .core { display: flex; flex-direction: column; justify-content: space-between; gap: var(--s7); }
.roster h3 { font-size: var(--t4); margin-bottom: var(--s4); }
.roster.wide h3 { font-size: clamp(30px, 2.6vw + 12px, 52px); }
.roster p { color: rgba(11,15,12,.66); max-width: 44ch; }
.roster .status { display: inline-flex; align-items: center; gap: 9px; font-size: var(--t1);
  letter-spacing: .16em; text-transform: uppercase; font-weight: 700; }
.roster .status i { width: 7px; height: 7px; border-radius: 50%; background: #17803D;
                    animation: blink 2.4s steps(1) infinite; }
.roster.soon .shell { background: transparent; border-style: dashed; }
.roster.soon .core { background: transparent; }
.roster.soon h3, .roster.soon p { color: rgba(11,15,12,.5); }
.roster .when { display: inline-block; margin-top: var(--s5);
  font: 700 10px/1 var(--font); letter-spacing: .16em; color: var(--ink);
  border: 1px solid var(--ink); border-radius: 999px; padding: 8px 12px; }
@media (hover: hover) { .roster:hover .core { transform: translateY(-6px); } }

/* --- faq ---------------------------------------------------------------- */
.faq-wrap { display: grid; grid-template-columns: minmax(0, 30ch) minmax(0, 1fr);
            gap: var(--s8); align-items: start; }
.qs { border-top: 1px solid var(--hair-l); }
.qs details { border-bottom: 1px solid var(--hair-l); }
.qs summary { list-style: none; cursor: pointer; padding: var(--s5) 48px var(--s5) 0;
  font-size: var(--t3); font-weight: 600; position: relative; transition: color .35s var(--ease); }
.qs summary::-webkit-details-marker { display: none; }
.qs summary::after { content: ""; position: absolute; right: 0; top: 50%;
  width: 30px; height: 30px; margin-top: -15px; border-radius: 999px;
  border: 1px solid var(--hair-l); transition: background .35s var(--ease); }
.qs summary::before { content: ""; position: absolute; right: 10px; top: 50%; z-index: 1;
  width: 9px; height: 9px; margin-top: -6px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transform-origin: 60% 60%; transition: transform .45s var(--ease); }
.qs details[open] summary::before { transform: rotate(-135deg); }
.qs details[open] summary::after { background: var(--yolk); border-color: var(--yolk); }
.qs summary:hover { color: rgba(11,15,12,.6); }
.qs details > div { padding: 0 var(--s7) var(--s6) 0; }
.qs details p { color: rgba(11,15,12,.66); max-width: 64ch; }
.qs details p + p { margin-top: var(--s4); }
.qs details strong { font-weight: 700; }
.qs .steps { margin: var(--s4) 0; display: grid; gap: 10px; }
.qs .steps li { color: rgba(11,15,12,.66); font-size: var(--t2); padding-left: var(--s4);
                border-left: 2px solid var(--yolk); }
.qs .steps b { font-weight: 700; color: var(--ink); }

/* --- close -------------------------------------------------------------- */
.close { text-align: center; }
.close h2 { font-size: clamp(38px, 8vw, 128px); margin-bottom: var(--s5); }
.close p { color: rgba(241,237,225,.6); font-size: var(--t3); max-width: 46ch; margin: 0 auto var(--s7); }
.close .btn { justify-content: center; }

/* ============================================================== footer == */
.footer { background: var(--ink); color: var(--bone);
          border-top: 1px solid var(--hair-d); padding: var(--s7) 0 calc(var(--s7) + env(safe-area-inset-bottom)); }
.footer-inner { display: flex; justify-content: space-between; gap: var(--s5); flex-wrap: wrap; align-items: center; }
.footer .brand-word { font-size: 17px; color: var(--bone); }
.footer a:not(.brand) { color: rgba(241,237,225,.45); font-size: var(--t2);
  display: inline-flex; align-items: center; min-height: 44px; transition: color .3s var(--ease); }
.footer a:not(.brand):hover { color: var(--yolk); }
.footer nav { display: flex; gap: var(--s6); flex-wrap: wrap; }

/* ============================================================== motion == */
.js .reveal, .js .tilt3d { opacity: 0; transform: translateY(48px); }
.js .reveal.lit, .js .tilt3d.lit {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease), transform .9s var(--ease);
}

/* the big number knocks when it changes, so a new value reads as a change */
@keyframes statIn { from { opacity: 0; transform: translateY(14px) } to { opacity: 1; transform: none } }
.js .stat-n { animation: statIn .45s var(--ease-out) both; }

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* =================================================================
       THE STORY, SCRUBBED BY THE SCROLL POSITION

       `contain` on a subject taller than the viewport spans exactly the
       sticky duration -- from the story's top meeting the top of the screen
       to its bottom meeting the bottom -- so every range below is a real
       fraction of the pinned section, not a guess.

       Every one of these animates transform, opacity or stroke-dashoffset
       only, and runs off the main thread. There is no scroll handler on this
       page; a listener fires far more often than the screen refreshes and
       forces a layout read each time.
       ================================================================= */
    .story { view-timeline-name: --story; }

    .hud .bar i {
      width: 100%; transform-origin: left; transform: scaleX(0);
      animation: prog both linear;
      animation-timeline: --story; animation-range: contain 0% contain 100%;
    }
    @keyframes prog { to { transform: scaleX(1); } }

    /* THE CAMERA. It starts as a sky cam -- almost square on to the turf, so
       the play art reads like a page out of a playbook -- and comes down and
       in until you are standing on the field for the snap. One transform, on
       one element, so nothing compounds and the framing stays predictable. */
    .plane {
      animation: camera both linear;
      animation-timeline: --story; animation-range: contain 0% contain 100%;
    }
    @keyframes camera {
      /* Tilting the plane makes the near half rush toward the lens, so the
         apparent width grows on its own. The scale therefore comes DOWN as
         the angle goes up -- otherwise the play is wider than the screen by
         the third beat and the routes get drawn off the edges. */
      0%   { transform: rotateX(15deg) translateY(-30%) scale(.94); }
      25%  { transform: rotateX(24deg) translateY(-29%) scale(.92); }
      50%  { transform: rotateX(34deg) translateY(-28%) scale(.88); }
      75%  { transform: rotateX(46deg) translateY(-26%) scale(.82); }
      100% { transform: rotateX(57deg) translateY(-24%) scale(.76); }
    }

    /* the floodlights come up as you arrive */
    .bloom, .rigs {
      animation: lights both linear;
      animation-timeline: --story; animation-range: contain 0% contain 22%;
    }
    @keyframes lights { from { opacity: .25 } to { opacity: 1 } }

    /* the personnel light up, then the circle, then the route, then the arrow.
       These take over from the one-shot draw that runs on browsers without a
       scroll timeline, so the whole read is in your hands rather than on a
       timer you cannot rewind. */
    /* ---------------------------------------------------------------
       THE STORYBOARD. One phase class per moment of the breakdown, each
       pinned to a slice of the pinned section, so the play is drawn by your
       thumb rather than on a timer you cannot rewind.

         0-20%   the offense sets
        20-40%   the defense aligns and shows two deep
        40-58%   their three most-run concepts, flashed in turn
        58-80%   the call: the man ringed, his route, then everything else
        80-100%  the ball
       --------------------------------------------------------------- */
    .js .chalk .ph-a, .js .chalk .ph-b, .js .chalk .ph-c, .js .chalk .ph-d,
    .js .chalk .ph-e, .js .chalk .ph-e2, .js .chalk .ph-f, .js .chalk .ph-f2,
    .js .chalk .zn-deep, .js .chalk .zn-under, .js .chalk .zn-drop,
    .js .chalk .ph-j2, .js .chalk .ph-m, .js .chalk .bz-3 {
      animation: popIn both linear; animation-timeline: --story;
    }
    @keyframes popIn { from { opacity: 0 } to { opacity: var(--o, 1) } }

    .js .chalk .ph-i, .js .chalk .ph-j, .js .chalk .ph-k,
    .js .chalk .ph-k2, .js .chalk .ph-l,
    .js .chalk .bz-1, .js .chalk .bz-2 {
      animation: draw both linear; animation-timeline: --story;
    }

    .js .chalk .ph-a  { animation-range: contain 1%  contain 6%;  --o: .45; }
    .js .chalk .ph-b  { animation-range: contain 4%  contain 11%; --o: .95; }
    .js .chalk .ph-c  { animation-range: contain 9%  contain 16%; --o: .95; }
    .js .chalk .ph-d  { animation-range: contain 13% contain 20%; --o: .95; }

    .js .chalk .ph-e  { animation-range: contain 21% contain 26%; --o: .95; }
    .js .chalk .ph-e2 { animation-range: contain 24% contain 29%; --o: .95; }
    .js .chalk .ph-f  { animation-range: contain 27% contain 31%; --o: .95; }
    .js .chalk .ph-f2 { animation-range: contain 29% contain 33%; --o: .95; }

    /* the shell fills in behind them: deep first, then underneath */
    .js .chalk .zn-deep  { animation-range: contain 30% contain 35%; --o: 1; }
    .js .chalk .zn-under { animation-range: contain 32% contain 37%; --o: 1; }
    .js .chalk .zn-drop  { animation-range: contain 34% contain 38%; --o: .55; }

    /* their book: three concepts, each one flashing up and clearing */
    .js .chalk .ghost { animation: flash both linear; animation-timeline: --story; }
    .js .chalk .gh-1  { animation-range: contain 41% contain 48%; }
    .js .chalk .gh-2  { animation-range: contain 47% contain 54%; }
    .js .chalk .gh-3  { animation-range: contain 53% contain 60%; }

    .js .chalk .ph-i  { animation-range: contain 58% contain 65%; }
    .js .chalk .ph-j  { animation-range: contain 62% contain 74%; }
    .js .chalk .ph-j2 { animation-range: contain 73% contain 77%; --o: 1; }
    .js .chalk .ph-k  { animation-range: contain 66% contain 78%; }
    .js .chalk .ph-k2 { animation-range: contain 69% contain 80%; }

    /* and then they bring it */
    .js .chalk .bz-1  { animation-range: contain 81% contain 89%; }
    .js .chalk .bz-2  { animation-range: contain 84% contain 91%; }
    .js .chalk .bz-3  { animation-range: contain 88% contain 92%; --o: 1; }

    .js .chalk .ph-l  { animation-range: contain 87% contain 96%; }
    .js .chalk .ph-m  { animation-range: contain 95% contain 99%; --o: 1; }

    /* Each beat's copy arrives as it centres and leaves as it goes, so nothing
       is ever half-read under the nav. */
    .js .beat-card {
      animation: cardIn both linear;
      animation-timeline: view(); animation-range: cover 10% cover 90%;
    }
    @keyframes cardIn {
      0%   { opacity: 0; transform: translateY(44px); }
      20%  { opacity: 1; transform: none; }
      74%  { opacity: 1; transform: none; }
      100% { opacity: 0; transform: translateY(-44px); }
    }

    .js .reveal, .js .tilt3d { opacity: 1; }
    .js .reveal, .js .tilt3d {
      animation: rise both linear;
      animation-timeline: view(); animation-range: entry 4% cover 26%;
    }
    @keyframes rise {
      from { opacity: 0; transform: translateY(48px); }
      to   { opacity: 1; transform: none; }
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .01ms !important; transition-delay: 0ms !important;
  }
  .js .reveal, .js .tilt3d { opacity: 1; transform: none; }
  /* The play is not animated at all here -- it is simply the finished
     diagram, at the opacities it was designed with. */
  .js .chalk .o      { opacity: .95; }
  .js .chalk .x      { opacity: .95; }
  .js .chalk .cover  { opacity: .55; }
  .js .chalk .block  { opacity: .45; }
  .js .chalk .los    { opacity: .45; }
  .js .chalk .sticks { opacity: .2; }
  .js .chalk .head, .js .chalk .catch { opacity: 1; }
  .js .chalk .route, .js .chalk .alt,
  .js .chalk .ring,  .js .chalk .ball { stroke-dashoffset: 0; }
  .js .chalk .zone { opacity: 1; }
  .js .chalk .tip  { opacity: 1; }
  .js .chalk .blitz { stroke-dashoffset: 0; }
  .js .chalk .ghost { opacity: 0; }   /* a flash has no still frame */
  .js .book .bar i { width: var(--w); }
  .js .kinetic .ln > span { transform: none; animation: none; }
  .js .stat-n { animation: none; }
  .scroll-cue i { animation: none; }
}

/* ========================================================== responsive ==
     1080  the reader stacks its columns tighter
      900  every two-column grid becomes one; beat copy goes full width
      720  nav collapses to the pill and a hamburger
      560  buttons full width, edge labels away
   ====================================================================== */

@media (max-width: 1080px) {
  .faq-wrap { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .marked { gap: var(--s7); }
}

/* ---------------------------------------------------------------------
   MOBILE STORY LAYOUT

   On a narrow screen the copy cannot sit over the middle of the field: it
   lands right on top of the play, and a scrim heavy enough to keep the text
   readable buries the thing you came to watch.

   So the screen is banded instead of layered. The HUD takes the top, the
   play owns the middle and is left completely clear, and the copy is pinned
   to the bottom over a gradient that only exists where the words are.
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
  .marked { grid-template-columns: minmax(0, 1fr); }
  .rosters { grid-template-columns: minmax(0, 1fr); }
  .roster.wide { grid-row: auto; }

  /* the number moves up under the chapter, where there is room for it */
  .stat { top: calc(58px + var(--s7)); bottom: auto; }
  .pers span { padding: 7px 11px; font-size: 13px; }
  .stat-n { font-size: clamp(40px, 13vw, 76px); }   /* clear of the play below it */
  .stat-u { margin-top: var(--s2); }

  /* the field lifts into the middle band */
  .plane { top: 20%; }
  .tele-zone { left: 20%; right: 20%; top: 6%; height: 86%; }
  .marks { left: 18%; right: 18%; }

  /* dark at the top for the HUD, clear across the play, dark again for the
     copy -- rather than one sheet of black over everything */
  .stage::after {
    background: linear-gradient(180deg,
      rgba(7,19,9,.82) 0%, rgba(7,19,9,.34) 15%,
      rgba(7,19,9,.06) 30%, rgba(7,19,9,.10) 50%,
      rgba(7,19,9,.84) 60%, rgba(7,19,9,.97) 100%);
  }

  /* Sticky, not just bottom-aligned. Bottom-aligned copy still travels the
     full height of the screen on its way past, which drags it straight
     across the play; sticky holds it in the bottom band for as long as its
     beat is the one being read. */
  .beat { align-items: end; justify-items: start; padding-bottom: 6vh; }
  .beat-card {
    max-width: 34rem; position: sticky; bottom: 6vh;
    background: linear-gradient(180deg, transparent, rgba(7,19,9,.55) 22%);
    padding-top: var(--s5);
  }
  .beat-card h2 { font-size: clamp(30px, 7.6vw, 44px); }
  .beat-card p { margin-top: var(--s4); font-size: var(--t2); }
  .beat-card .btn { margin-top: var(--s5); }
}

@media (max-width: 900px) {
  .nav-links { display: none; }
  .nav-cta { display: none; }
  .burger { display: block; }
}

@media (max-width: 720px) {
  .nav-pill { justify-content: space-between; padding-right: 7px; }
  .book .core { padding: var(--s6) var(--s5); }
  .roster .core { padding: var(--s6) var(--s5); }
  .note { grid-template-columns: 44px minmax(0, 1fr); padding: var(--s5) 0; }
  .qs details > div { padding-right: 0; }
  .qs summary { padding-right: 42px; }
  .chapter { left: calc(var(--gut) + 70px); }
}

@media (max-width: 560px) {
  .edge { display: none; }
  .hero { padding-top: calc(58px + var(--s6)); padding-bottom: var(--s7); }
  .hero-sub { margin-top: var(--s5); }
  .hero-cta { margin-top: var(--s5); }
  .scroll-cue { display: none; }
  .doodle { opacity: .1; }
  .hero-cta { flex-direction: column; align-items: stretch; }
  .hero-cta .btn, .close .btn { width: 100%; justify-content: space-between; }
  .close .btn { max-width: 360px; margin-inline: auto; }
  .book .row { grid-template-columns: minmax(0,1fr) 56px 46px; gap: var(--s3); }
  .chips button { flex: 1 1 100%; }
  .footer-inner { flex-direction: column; align-items: flex-start; gap: var(--s3); }
  .stat-u { letter-spacing: .16em; }
}

@media (max-height: 560px) and (orientation: landscape) {
  .hero { min-height: 0; padding: calc(58px + var(--s6)) 0 var(--s7); }
  .hero h1 { font-size: clamp(34px, 7vw, 64px); }
  .scroll-cue { display: none; }
  .beat { min-height: 100svh; }
}
