/* ==========================================================================
   jaylenmcclain.com, design system
   A sketchbook at night. Graphite ground, paper type, one chalk line.
   ========================================================================== */

/* Fonts are self-hosted (latin subset, woff2), so the first paint doesn't wait
   on a third-party stylesheet. font-display: swap shows the fallback stack
   for a moment on a slow first visit rather than blank text. */
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/big-shoulders-display-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Big Shoulders Display';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/big-shoulders-display-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/newsreader-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/newsreader-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Color */
  --ink:      #0E0F12;              /* graphite black, the page ground */
  --paper:    #E8E3D9;              /* sketchbook paper, primary text on dark */
  --muted:    #9AA0A8;              /* pencil gray, secondary text */
  --rule:     rgba(232,227,217,0.14); /* hairlines and borders */
  --leather:  #16181D;              /* deep graphite, full-bleed accent blocks, fills only */
  --chalk:    #F4F6F8;              /* the drawn line */
  --scarlet:  #C8102E;              /* accent, rare */
  --scarlet-text: #E84A5F;          /* scarlet lifted for small text on dark grounds (5.1:1 on ink) */
  --muted-on-paper: #5B5F66;        /* pencil gray, darkened to read on paper (5.0:1) */
  --placeholder:    #565B62;        /* form placeholder on paper */
  --ink-hover:      #2A2C31;        /* solid button hover on paper */
  --gold:     #C9A24B;              /* second accent, rarer still: championship plaque, not team color */

  /* Type */
  --display:  'Big Shoulders Display', 'Arial Narrow', sans-serif;
  --body:     'Newsreader', Georgia, serif;
  --mono:     'JetBrains Mono', ui-monospace, monospace;

  /* Space, 8px base */
  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 40px;
  --s5: 64px; --s6: 96px; --s7: 144px; --s8: 200px;

  /* Structure */
  --maxw: 1240px;
  --gutter: 24px;
  --radius: 0;                      /* square is the decision, hold it */
  --ease: cubic-bezier(.2,.7,.2,1);

  /* Derived, light-section inversion */
  --ink-on-paper: var(--ink);
}

/* ==========================================================================
   Reset
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
img, picture, svg, video { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }
/* Links inside running text need a cue besides color (WCAG 1.4.1). Plain
   links only: buttons, cards and nav carry their own styling. */
p > a:not([class]) { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Sticky footer: on the shorter inner pages, content can end well
     above the viewport's bottom edge. Without this, the gap below the
     footer was just body's own --ink showing through -- invisible.
     Once .field-backdrop sits fixed behind everything, that same gap
     would show a floating patch of field with nothing anchoring it.
     Stretching body to the viewport and growing #main into any leftover
     space keeps the footer's opaque ground pinned to the true bottom. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
#main { flex: 1 0 auto; }

@media (min-width: 820px) {
  body { font-size: 1.125rem; }
}

/* ==========================================================================
   Type scale
   ========================================================================== */

.t-display {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(3.2rem, 9vw, 8rem);
  letter-spacing: -0.02em;
  line-height: 0.92;
  text-transform: uppercase;
}

.t-h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.4rem, 6vw, 4.5rem);
  letter-spacing: -0.015em;
  line-height: 0.96;
  text-transform: uppercase;
}

.t-section {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  letter-spacing: -0.01em;
  line-height: 1.05;
  text-transform: uppercase;
}

.t-stat {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(2.4rem, 5vw, 4rem);
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* No orphans -- never a lone word on a text block's last line, at any
   screen size. Browsers with text-wrap do it natively (and headings get
   evenly balanced lines); site.js's noOrphans() covers the rest by joining
   each block's last two words with a no-break space. */
p, li, figcaption, blockquote, label, .door__desc { text-wrap: pretty; }
h1, h2, h3, h4 { text-wrap: balance; }

.t-lead {
  font-family: var(--body);
  font-weight: 400;
  font-size: clamp(1.15rem, 2vw, 1.4rem);
  line-height: 1.5;
}
/* The italic line under a section heading ("An Afternoon of Purpose…"). */
.t-subhead { font-style: italic; }

.t-small {
  font-family: var(--body);
  font-size: 0.9rem;
  line-height: 1.55;
}

.t-label {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
}

.t-muted { color: var(--muted); }
.t-scarlet { color: var(--scarlet); }

/* Light (paper) sections invert */
.on-paper {
  background: var(--paper);
  color: var(--ink);
}
.on-paper .t-muted { color: var(--muted-on-paper); }
.on-paper .rule { background: rgba(14,15,18,0.14); }

/* Leather block: translucent over the field backdrop, opaque once it's the
   only ground under the hero-static fallback (no backdrop active yet). */
.on-leather {
  background: rgba(22,24,29,0.86);
  color: var(--paper);
  border-block: 1px solid rgba(201,162,75,0.35);
}

/* ==========================================================================
   Field backdrop: the empty-field still that takes over once the hero
   scrolls out of view, fixed behind the sections that follow it, until
   the footer covers it with an opaque ground of its own. Home page only.
   ========================================================================== */

.field-backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 900ms var(--ease);
}
body.field-active .field-backdrop { opacity: 1; }
.field-backdrop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.field-backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(14,15,18,0.4) 0%,
    rgba(14,15,18,0.6) 45%,
    rgba(14,15,18,0.88) 100%);
}
@media (prefers-reduced-motion: reduce) {
  .field-backdrop { transition: none; }
}

/* ==========================================================================
   Environment layer: grain + vignette, fixed behind everything
   ========================================================================== */

.env-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 78% 8%, rgba(244,246,248,0.05), transparent 55%),
    radial-gradient(140% 100% at 50% 100%, rgba(0,0,0,0.55), transparent 60%);
}
.env-layer::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
}

/* ==========================================================================
   Layout
   ========================================================================== */

.wrap {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  position: relative;
  z-index: 1;
}

.bleed { position: relative; z-index: 1; }

section, .section {
  padding-block: var(--s5);
  position: relative;
  z-index: 1;
}
@media (min-width: 1024px) {
  section, .section { padding-block: var(--s7); }
}

.split {
  display: grid;
  gap: var(--s4);
}
/* Flipped splits read in the same order on every screen: the text block
   (last in the markup) first, then the image or stats. */
.split.flip > :first-child { order: 2; }
.split.flip > :last-child { order: 1; }
/* Media on the left on wide screens only: text stays first in the markup,
   so phones (and screen readers) still get the heading before the photos. */
@media (min-width: 820px) {
  .split--media-left > :last-child { order: -1; }
}
@media (min-width: 820px) {
  /* A page can set its own ratio with style="--split: 45fr 55fr" -- a
     variable, not an inline grid-template-columns, so phones still stack. */
  .split { grid-template-columns: var(--split, 62fr 38fr); gap: var(--s5); align-items: start; }
  .split.flip { grid-template-columns: var(--split, 38fr 62fr); }

}

/* ==========================================================================
   Photo slots: blank placeholders standing in for real photos, everywhere
   the layout has a spot for one. Plain gray, nothing fancier, so they
   never get mistaken for finished content.
   ========================================================================== */

.photo-slot {
  background: #24262b;
  border: 1px solid var(--rule);
  display: block;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 160px;
  gap: var(--s2);
}
/* .photo-slot carries aspect-ratio: 4 / 5 for its standalone use (the
   single-photo slots elsewhere on the site). Inside this grid, the
   grid area itself sets both dimensions, but grid's automatic min-size
   still factors an item's aspect-ratio in, and can inflate the row
   track past grid-auto-rows to match it. Two classes beats .photo-slot
   on specificity, so this neutralizes the ratio and the auto-minimum
   for cells actually placed by the grid. */
.photo-slot.gallery-grid__item {
  aspect-ratio: auto;
  min-width: 0;
  min-height: 0;
}
.gallery-grid__item--a { grid-column: span 2; grid-row: span 2; }
.gallery-grid__item--b { grid-column: span 2; grid-row: span 2; }
.gallery-grid__item--d { grid-column: span 1; grid-row: span 1; }
.gallery-grid__item--e { grid-column: span 1; grid-row: span 1; }
.gallery-grid__item--f { grid-column: span 1; grid-row: span 1; } /* phones: side by side, like d/e above */
.gallery-grid__item--g { grid-column: span 1; grid-row: span 1; }

@media (min-width: 720px) {
  .gallery-grid { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 220px; gap: var(--s3); }
  .gallery-grid__item--a { grid-column: 1 / 3; grid-row: 1 / 3; }
  .gallery-grid__item--b { grid-column: 3 / 5; grid-row: 1 / 3; }
  .gallery-grid__item--d { grid-column: 1 / 2; grid-row: 3 / 4; }
  .gallery-grid__item--e { grid-column: 2 / 3; grid-row: 3 / 4; }
  .gallery-grid__item--f { grid-column: 3 / 4; grid-row: 3 / 4; }
  .gallery-grid__item--g { grid-column: 4 / 5; grid-row: 3 / 4; }
}

/* ==========================================================================
   Gala gallery: a collage of real photography (Legends Among Us Luncheon),
   sitting beside a blurb in a .split. Same asymmetric-grid idea as
   .gallery-grid, sized for a narrower column. Photos read desaturated,
   like everything else on the graphite ground, and come into color on
   hover/focus, the one place the site lets a photograph win.
   ========================================================================== */

.gala-gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 150px;
  gap: var(--s2);
}
.gala-gallery__item--a { grid-column: span 2; grid-row: span 2; }
.gala-gallery__item--b { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--c { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--d { grid-column: span 2; grid-row: span 1; }
.gala-gallery__item--e { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--f { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--g { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--h { grid-column: span 1; grid-row: span 1; }
.gala-gallery__item--i { grid-column: span 2; grid-row: span 1; }
/* Phones: the g/h award pair is dropped to keep the column from running long. */
@media (max-width: 499px) {
  .gala-gallery__item--g, .gala-gallery__item--h { display: none; }
}

@media (min-width: 500px) {
  .gala-gallery { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 130px; }
  .gala-gallery__item--a { grid-column: 1 / 3; grid-row: 1 / 3; }
  .gala-gallery__item--b { grid-column: 3 / 5; grid-row: 1 / 2; }
  .gala-gallery__item--c { grid-column: 3 / 4; grid-row: 2 / 3; }
  .gala-gallery__item--d { grid-column: 4 / 5; grid-row: 2 / 3; }
  .gala-gallery__item--e { grid-column: 1 / 2; grid-row: 3 / 4; }
  .gala-gallery__item--f { grid-column: 2 / 3; grid-row: 3 / 4; }
  .gala-gallery__item--g { grid-column: 3 / 5; grid-row: 3 / 4; }
  .gala-gallery__item--h { grid-column: 1 / 3; grid-row: 4 / 5; }
  .gala-gallery__item--i { grid-column: 3 / 5; grid-row: 4 / 5; }
}

/* Event gallery: same collage treatment as .gala-gallery, sized for eight
   photos (Youth Football Camp, Mid-Ohio Market) instead of nine -- tiles
   with a tall portrait slot (c) and a full-width closing strip (h). */
.event-gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 150px;
  gap: var(--s2);
}
.event-gallery__item--a { grid-column: span 2; grid-row: span 2; }
.event-gallery__item--b { grid-column: span 2; grid-row: span 1; }
.event-gallery__item--c { grid-column: span 1; grid-row: span 2; }
.event-gallery__item--d { grid-column: span 1; grid-row: span 1; }
.event-gallery__item--e { grid-column: span 1; grid-row: span 1; }
.event-gallery__item--f { grid-column: span 1; grid-row: span 1; }
.event-gallery__item--g { grid-column: span 1; grid-row: span 1; }
.event-gallery__item--h { grid-column: span 2; grid-row: span 1; }

@media (min-width: 500px) {
  .event-gallery {
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 130px;
    grid-template-areas:
      "a a b b"
      "a a c d"
      "e f c g"
      "h h h h"
      "h h h h";
  }
  .event-gallery__item--a { grid-area: a; }
  .event-gallery__item--b { grid-area: b; }
  .event-gallery__item--c { grid-area: c; }
  .event-gallery__item--d { grid-area: d; }
  .event-gallery__item--e { grid-area: e; }
  .event-gallery__item--f { grid-area: f; }
  .event-gallery__item--g { grid-area: g; }
  .event-gallery__item--h { grid-area: h; }
}

.gala-gallery__item,
.event-gallery__item {
  position: relative;
  overflow: hidden;
  background: #24262b;
  border: 1px solid var(--rule);
}
.gala-gallery__item img,
.event-gallery__item img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(70%) contrast(1.02);
  transform: scale(1.001); /* establishes a transform layer so the hover scale doesn't jump */
  transition: filter 420ms var(--ease), transform 420ms var(--ease);
}
.gala-gallery__item:hover img,
.gala-gallery__item:focus-within img,
.event-gallery__item:hover img,
.event-gallery__item:focus-within img {
  filter: grayscale(0%) contrast(1.02);
  transform: scale(1.05);
}
@media (prefers-reduced-motion: reduce) {
  .gala-gallery__item img,
  .event-gallery__item img { transition: filter 420ms var(--ease); }
  .gala-gallery__item:hover img,
  .gala-gallery__item:focus-within img,
  .event-gallery__item:hover img,
  .event-gallery__item:focus-within img { transform: none; }
}
/* On paper grounds the dark placeholder/hairline would nearly vanish;
   swap to the ink-tinted equivalents used elsewhere on .on-paper. */
.on-paper .gala-gallery__item,
.on-paper .event-gallery__item {
  background: rgba(14,15,18,0.06);
  border-color: rgba(14,15,18,0.14);
}

/* ==========================================================================
   Instagram stack: real, live embeds (embed.js swaps each blockquote for
   an iframe -- Instagram's own card, captioned, liked, clickable through
   to the post, not a screenshot) held in a hand-fanned deck. Three hand-set
   transforms, one per card by position, rest and hover both -- three is a
   fixed, known count, nothing a formula would buy here (a fourth post
   exists but Instagram's own embed API won't serve age-restricted posts,
   even signed out on the real site, so it's not one of the three). At
   rest they're nearly stacked; on hover they spread wide enough to read
   each card almost whole, which is why this needs real room, not a
   sidebar.
   ========================================================================== */

.ig-stack {
  position: relative;
  min-height: 640px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ig-stack__card {
  position: absolute;
  transition: transform 560ms var(--ease);
  transform-origin: center center;
  filter: drop-shadow(0 16px 32px rgba(5,5,10,0.55));
}
.ig-stack__card iframe,
.ig-stack__card .instagram-media {
  width: 336px !important;
  max-width: 336px !important;
  min-width: 300px !important;
}

/* An Instagram post whose embed kept failing (cms.js): a plain link to it,
   the size of a post card, instead of a blank box. */
.ig-fallback {
  display: grid;
  place-items: center;
  width: 100%;
  max-width: 336px;
  min-height: 420px;
  padding: var(--s3);
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: #16181d;
  color: var(--paper);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
}
.ig-stack__card .ig-fallback { width: 336px; }
.ig-fallback:hover,
.ig-fallback:focus-visible { border-color: var(--paper); }
.ig-stack__card:nth-child(1) { transform: translate(-12px, 7px) rotate(-4deg); z-index: 10; }
.ig-stack__card:nth-child(2) { transform: translate(0, 0) rotate(0deg); z-index: 12; }
.ig-stack__card:nth-child(3) { transform: translate(12px, -7px) rotate(4deg); z-index: 11; }

/* Reserve room for each Instagram / X embed while its script loads, so the
   page doesn't jump as they arrive. Every embed renders taller than this,
   so it never adds space once loaded. */
[data-social] > * { min-height: 480px; }

/* Fan-out only where there's a real hover and the room for it; on touch
   screens a tap would otherwise "stick" the fan open and throw the outer
   cards off the edge of the screen. */
@media (hover: hover) and (min-width: 1024px) {
  .ig-stack:hover .ig-stack__card:nth-child(1) { transform: translate(-230px, -14px) scale(0.8) rotate(-8deg); z-index: 20; }
  .ig-stack:hover .ig-stack__card:nth-child(2) { transform: translate(0, -32px) rotate(0deg); z-index: 22; }
  .ig-stack:hover .ig-stack__card:nth-child(3) { transform: translate(230px, -14px) scale(0.8) rotate(8deg); z-index: 20; }
}
/* Middle stays frontmost by default (z-index 22 beats the outer two's 20)
   whenever the cursor is over the stack but not settled on one card. The
   moment it settles on a specific card, that card jumps above everything
   -- !important so it wins regardless of which nth-child z-index above
   it's competing with. */
.ig-stack__card:hover { z-index: 30 !important; }

@media (prefers-reduced-motion: reduce) {
  .ig-stack__card { transition: none; }
}
/* Phones/tablets: the same stack, still (no fan), under the heading.
   Tall enough for the tallest embed; on narrow phones the whole stack is
   scaled down so the tilted cards stay inside the screen. */
@media (max-width: 1023px) {
  .ig-stack { min-height: 800px; margin-top: var(--s3); }
}
@media (max-width: 480px) {
  .ig-stack { min-height: 690px; }
  .ig-stack__card { scale: 0.86; }
}

.grid-2 {
  display: grid;
  gap: var(--s3);
}
@media (min-width: 640px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   Nav
   ========================================================================== */

/* The wrapping <header> exists for semantics only. Boxed, it would be
   exactly as tall as .nav — its own height — leaving position:sticky
   nowhere to run: a sticky element can only stay pinned while its
   containing block is still on screen. display:contents drops the
   header from the box tree so .nav's containing block becomes <body>
   (which spans the whole page), giving the stick its full runway. */
header { display: contents; }

/* Sticky, not fixed: the nav lives in normal flow right after the hero
   (same spot the achievement ticker used to sit), so it is simply off
   screen, below the hero, until the visitor scrolls to it — nothing
   hides or compensates for it. Once its flow position would carry it
   above the viewport top, it pins there for the rest of the page. */
.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s2) var(--gutter);
  background: rgba(14,15,18,0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
  opacity: 0;
  transform: translateY(-8px);
  animation: nav-in 500ms var(--ease) 80ms forwards;
}
@media (prefers-reduced-motion: reduce) {
  .nav { opacity: 1; transform: none; animation: none; }
}
@keyframes nav-in {
  to { opacity: 1; transform: translateY(0); }
}

.nav__mark {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.nav__mark b { color: var(--scarlet); font-weight: 600; }
.nav__mark-icon {
  width: 28px;
  height: 28px;
  flex: none;
}

.nav__links {
  display: none;
  gap: var(--s4);
}
@media (min-width: 1040px) {
  .nav__links { display: flex; }
}

/* Spacing and type match the old achievement ticker's items exactly:
   this bar took its place, so it reads as the same rhythm. */
.nav__link {
  position: relative;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
  padding-block: var(--s1);
}
.nav__link:hover, .nav__link:focus-visible { color: var(--paper); }
.nav__link svg {
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 6px;
  overflow: visible;
}
/* The page you're on reads gold, the way the lead achievement item did. */
.nav__link[aria-current="page"] { color: var(--gold); }
.nav__link path {
  fill: none;
  stroke: var(--scarlet);
  stroke-width: 1.5;
  stroke-linecap: round;
}

.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper);
  min-height: 44px;
  padding-inline: var(--s1);
}
@media (min-width: 1040px) {
  .nav__toggle { display: none; }
}

.nav__sheet {
  position: fixed;
  inset: 0;
  z-index: 39;
  background: var(--ink);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s3);
  padding: var(--s6) var(--s4);
  transform: translateY(-100%);
  /* Closed, the sheet is only slid off-screen, so it also needs
     visibility: hidden to drop out of the Tab order and the screen
     reader's reading order. The visibility change waits until the
     slide-up finishes (360ms delay) so closing still animates. */
  visibility: hidden;
  transition: transform 360ms var(--ease), visibility 0s linear 360ms;
}
.nav__sheet[data-open="true"] {
  transform: translateY(0);
  visibility: visible;
  transition: transform 360ms var(--ease), visibility 0s;
}
.nav__sheet .nav__link {
  font-family: var(--display);
  font-size: clamp(1.6rem, 8vw, 2.4rem);
  text-transform: uppercase;
  color: var(--paper);
  letter-spacing: -0.01em;
}
.nav__sheet .nav__link { padding-block: 10px; } /* 44px+ tap target */
.nav__sheet .nav__link[aria-current="page"] { color: var(--gold); }

/* ==========================================================================
   Buttons + text links
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 28px;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border: 1px solid var(--rule);
  transition: transform 260ms var(--ease), background 260ms var(--ease), border-color 260ms var(--ease), color 260ms var(--ease);
}
.btn:hover, .btn:focus-visible { transform: translateY(-2px); }

.btn--solid {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
}
.btn--solid:hover, .btn--solid:focus-visible { background: var(--chalk); }

.btn--ghost {
  color: var(--paper);
  border-color: var(--rule);
}
.btn--ghost:hover, .btn--ghost:focus-visible { border-color: var(--paper); }

.btn--leather {
  background: transparent;
  color: var(--gold);
  border-color: rgba(201,162,75,0.5);
}
.btn--leather:hover, .btn--leather:focus-visible {
  background: var(--gold);
  color: var(--ink);
  border-color: var(--gold);
}

.btn--gold {
  background: var(--gold);
  color: var(--ink);
  border-color: var(--gold);
}
.btn--gold:hover, .btn--gold:focus-visible { background: #D8B566; border-color: #D8B566; }

/* Two buttons that stay side by side, even on the narrowest phones. */
.cta-pair {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--s2);
  margin-top: var(--s4);
}
@media (max-width: 480px) {
  .cta-pair .btn { flex: 1 1 auto; padding-inline: 14px; }
}

.on-paper .btn--solid { background: var(--ink); color: var(--paper); border-color: var(--ink); } /* inverted: a paper button vanishes on paper */
.on-paper .btn--solid:hover, .on-paper .btn--solid:focus-visible { background: var(--ink-hover); border-color: var(--ink-hover); }
.on-paper .btn--ghost { color: var(--ink); border-color: rgba(14,15,18,0.2); }
.on-paper .btn--ghost:hover, .on-paper .btn--ghost:focus-visible { border-color: var(--ink); }

.chalk-link {
  position: relative;
  display: inline-block;
}
.chalk-link__underline {
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 100%;
  height: 8px;
  overflow: visible;
  pointer-events: none;
}
.chalk-link__underline path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.85;
}

/* Focus ring, everywhere */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--scarlet);
  outline-offset: 3px;
}
canvas:focus-visible { outline: 2px solid var(--scarlet); outline-offset: 4px; }

/* ==========================================================================
   Section header: number, title, chalk stroke to the margin
   ========================================================================== */

.sec-head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin-bottom: var(--s4);
}
.sec-head__num {
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--scarlet-text);
  flex-shrink: 0;
}
.sec-head__line {
  flex: 1;
  height: 12px;
  min-width: 40px;
}
.sec-head__line path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.85;
}
.on-paper .sec-head__line path { stroke: var(--ink); opacity: 0.5; }
.on-paper .sec-head__num { color: var(--scarlet); } /* the true scarlet already passes on paper (4.6:1) */

/* ==========================================================================
   Reveal-on-scroll
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 560ms var(--ease), transform 560ms var(--ease);
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* Chalk-drawn SVG lines, general */
.chalk-path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.85;
  transition: stroke-dashoffset 900ms var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .chalk-path { transition: none !important; stroke-dashoffset: 0 !important; }
}

/* ==========================================================================
   Hero: THE FLIGHT
   A football descends over 520vh of native scroll. Five stops. The stage
   sticks, releases, the page continues underneath.
   ========================================================================== */

.hero {
  position: relative;
  padding-block: 0; /* override the generic section padding: the hero runs edge to edge */
}

/* A page opened via a #page-nav link lands scrolled past the hero, not
   at it -- but that landing spot depends on JS (which hero mode is
   active, and nav's own entrance animation settling into its real
   resting position) resolving first. Until it has, the hero stays
   hidden rather than flashing on screen at the wrong scroll position
   for a frame or two before hero-flight.js corrects it and lifts
   this class. */
html.hash-settling .hero { visibility: hidden; }

/* ---------- The static hero: the default, and the five-gate fallback ----------
   Shown until JS confirms a real browser, a wide-enough screen, a fine
   pointer, and no reduced-motion preference. Composed on the ending
   frame, the ball at rest exactly as it settles, not a random grab. */
.hero-static {
  position: relative;
  min-height: 100vh;
  min-height: 100svh; /* the whole phone screen, measured with the browser's own bars showing */
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  padding: var(--s6) var(--gutter) var(--s6) var(--gutter);
}
.hero-static__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.hero-static__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(100deg,
      rgba(14,15,18,0.94) 0%,
      rgba(14,15,18,0.84) 30%,
      rgba(14,15,18,0.5) 46%,
      rgba(14,15,18,0.12) 60%,
      rgba(14,15,18,0) 74%),
    linear-gradient(0deg, rgba(14,15,18,0.55), transparent 30%);
}
.hero-static__copy {
  position: relative;
  z-index: 2;
  max-width: 640px;
}
.hero-static__label { display: block; margin-bottom: var(--s3); color: var(--muted); }
.hero-static__lead { max-width: 46ch; color: var(--paper); margin-block: var(--s2) var(--s4); }
.hero.is-enhanced .hero-static,
html.hero-scrub-early .hero-static { display: none; } /* -early: set in <head> before first paint */

/* ---------- The scrub hero ---------- */
.hero-scrub {
  position: relative;
  display: none;
}
.hero.is-enhanced .hero-scrub,
html.hero-scrub-early .hero-scrub { display: block; height: 600vh; }

.hero-scrub__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.hero-scrub__bg { position: absolute; inset: 0; z-index: 0; }
.hero-scrub__poster,
.hero-scrub__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transform: translateZ(0);
  will-change: transform;
}
.hero-scrub__video { opacity: 0; transition: opacity 500ms var(--ease); }
.hero-scrub.video-ready .hero-scrub__video { opacity: 1; }
/* The poster stays up underneath until the video has fully faded in over
   it (the 500ms delay matches the video's fade). Hiding it the instant the
   video became ready left half a second of near-black between the two:
   a visible blink right as the homepage loads. */
.hero-scrub.video-ready .hero-scrub__poster { opacity: 0; transition: opacity 0s linear 500ms; }

/* Global base scrim: no frame is ever raw behind the page. */
.hero-scrub__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse 120% 90% at 66% 45%, rgba(14,15,18,0) 35%, rgba(14,15,18,0.6) 100%);
}

.hero-scrub__copy {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  padding: var(--s6) var(--gutter);
}
.band {
  position: absolute;
  inset: auto var(--gutter) var(--s6) var(--gutter);
  max-width: 620px;
  opacity: 0;
  pointer-events: none;
}
.band::before {
  content: "";
  position: absolute;
  inset: -8% -6%;
  pointer-events: none;
  z-index: -1;
  opacity: calc(0.3 + 0.7 * var(--k, 1));
  background: radial-gradient(ellipse 78% 66% at 30% 60%, rgba(5,5,10,0.6) 0%, rgba(5,5,10,0.4) 46%, rgba(5,5,10,0) 76%);
}
.band[data-active="true"] { pointer-events: auto; }
:root { --tshadow: 0 1px 2px rgba(5,5,10,0.95), 0 3px 12px rgba(5,5,10,0.78), 0 10px 44px rgba(5,5,10,0.8); }
.band { text-shadow: var(--tshadow); }
.band .btn { text-shadow: none; }

.band__label { display: block; margin-bottom: var(--s2); color: var(--muted); text-shadow: none; }
.band__display { color: var(--paper); }
.band__sub { max-width: 46ch; color: var(--paper); margin-block: var(--s3); }

/* Word/char split, driven by --k (0..1 assembly progress) written by the scrub loop. */
.band .w { display: inline-block; }
.band .c { display: inline-block; }

.band--drift .c {
  --kc: clamp(0, (var(--k, 0) - var(--th, 0)) * 2.6, 1);
  opacity: var(--kc);
  transform: translateY(calc((1 - var(--kc)) * -18px));
}
.band--scatter .c {
  --kc: clamp(0, (var(--k, 0) - var(--th, 0)) * 2.6, 1);
  opacity: var(--kc);
  transform: translate(calc((1 - var(--kc)) * var(--jx, 0px)), calc((1 - var(--kc)) * var(--jy, 0px))) rotate(calc((1 - var(--kc)) * var(--jr, 0deg)));
}
.band--grid .w {
  --kc: clamp(0, (var(--k, 0) - var(--th, 0)) * 2.6, 1);
  opacity: var(--kc);
  transform: translateX(calc((1 - var(--kc)) * var(--jx, 18px)));
}
.band--blur .band__display { position: relative; display: block; }
.band--blur .sharp { display: block; opacity: var(--k, 0); transition: opacity 0ms; }
.band--blur .soft { position: absolute; inset: 0; opacity: calc(1 - var(--k, 0)); filter: blur(10px); }
.line { display: block; }
.band--rise .w {
  --kc: clamp(0, (var(--k, 0) - var(--th, 0)) * 2.8, 1);
  opacity: var(--kc);
  transform: translateY(calc((1 - var(--kc)) * 20px));
}
.band--rise .band__sub,
.band--blur .band__sub { opacity: var(--ks, 0); transition: none; }
.band--rise .band__cta,
.band--blur .band__cta { opacity: var(--kb, 0); transform: translateY(calc((1 - var(--kb, 0)) * 8px)); transition: none; pointer-events: none; }

@media (max-width: 720px) {
  .band { max-width: none; right: var(--gutter); }
}


/* ==========================================================================
   Four doors
   ========================================================================== */

.doors {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
@media (min-width: 720px) {
  .doors { grid-template-columns: repeat(5, 1fr); }
}

.door {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--ink);
  padding: var(--s3);
  transition: background 300ms var(--ease);
}
.door:hover, .door:focus-visible { background: #16181d; }
.door__photo {
  aspect-ratio: 16 / 10;
  width: 100%;
  margin-bottom: var(--s2);
}
/* .photo-slot's own grayscale-to-color reveal only fires on :hover of the
   photo itself -- too small a target here, with the title/description
   taking up most of each card. Bloom it for the whole door instead, so
   resting anywhere on the card brings its photo to full color. */
.door:hover .door__photo img,
.door:focus-within .door__photo img {
  filter: grayscale(0%) contrast(1.02);
  transform: scale(1.05);
}
.door__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin-bottom: var(--s1);
  position: relative;
  display: inline-block;
  width: fit-content;
  padding-right: var(--s4); /* keeps the arrow from overlapping a full-width title */
}
.door__title svg {
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 100%;
  height: 6px;
  overflow: visible;
}
.door__title path {
  fill: none;
  stroke: var(--scarlet);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 240;
  stroke-dashoffset: 240;
  transition: stroke-dashoffset 500ms var(--ease);
}
.door:hover .door__title path,
.door:focus-visible .door__title path { stroke-dashoffset: 0; }
.door__desc { color: var(--muted); max-width: 34ch; font-size: 0.9rem; }

/* ==========================================================================
   Stat blocks
   ========================================================================== */

.stats {
  display: grid;
  gap: var(--s4);
}
@media (min-width: 640px) {
  .stats { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
  .stats--2x2 { grid-template-columns: repeat(2, 1fr); }
}
/* Shrink-wraps the number so the chalk underline beneath it (width 100%)
   runs exactly the number's width, not the whole grid column. */
.stat__figure { display: inline-block; }
.stat__figure .stat__underline { width: 0; min-width: 100%; } /* adds nothing to the shrink-wrap, then fills it */
.stat__num {
  display: inline-block;
  position: relative;
}
.stat__underline {
  display: block;
  width: 100%;
  height: 10px;
  margin-top: 6px;
  overflow: visible;
}
.stat__underline path {
  fill: none;
  stroke: var(--scarlet);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.stat__label {
  margin-top: var(--s2);
  color: var(--muted);
}

/* ==========================================================================
   Foundation pillars
   ========================================================================== */

.pillars {
  position: relative;
  display: grid;
  gap: var(--s4);
  text-align: center;
}
.pillars { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 719px) {
  .pillars { gap: var(--s2); }
  .pillar__name { font-size: 1.1rem; }
}
.pillars__line {
  display: none;
}
@media (min-width: 720px) {
  .pillars__line {
    display: block;
    position: absolute;
    left: 8%;
    right: 8%;
    top: 28px;
    height: 24px;
    overflow: visible;
    z-index: 0;
  }
}
.pillars__line path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.85;
}
.pillar { position: relative; z-index: 1; }
.pillar__dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--scarlet);
  margin: 0 auto var(--s2);
}
.pillar__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(1.3rem, 3vw, 1.8rem);
  text-transform: uppercase;
}

/* ==========================================================================
   Interior page hero (H1 block)
   ========================================================================== */

.page-head {
  padding-top: var(--s6);
  padding-bottom: var(--s4);
}
.page-head__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin-bottom: var(--s3);
}
.page-head__eyebrow .sec-head__num { flex-shrink: 0; }

/* ==========================================================================
   Diagram blocks (four jobs of a safety, foundation pillars, etc.)
   ========================================================================== */

.diagram-card {
  border: 1px solid var(--rule);
  padding: var(--s3);
}
.diagram-card__svg {
  width: 100%;
  height: 90px;
  margin-bottom: var(--s3);
  overflow: visible;
}
.diagram-card__svg path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: 0.85;
}
.diagram-card__title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-bottom: var(--s1);
}
.diagram-card__desc { color: var(--muted); }

.hairline-box {
  border: 1px solid var(--rule);
  padding: var(--s3);
}

/* Stretched-link card: the headline <a> is the only real anchor (no
   nested links), but its ::after covers the whole card, so a click
   anywhere in the card follows it. .media-card opts a hairline-box
   into this -- plain hairline-box uses (Programs, the PFF stat box)
   stay inert. */
.media-card {
  position: relative;
  transition: border-color 260ms var(--ease), background 260ms var(--ease);
}
/* Photo-topped variant: a .photo-slot flush against the card's own
   border (no padding), text block padded below it. */
.media-card:has(.photo-slot) {
  padding: 0;
  display: flex;
  flex-direction: column;
}
.media-card .photo-slot { border-width: 0 0 1px; }
/* Press photography reads better in color, so article-card photos skip
   the grayscale-to-color hover reveal other .photo-slots use. */
.media-card .photo-slot img,
.media-card .photo-slot:hover img,
.media-card .photo-slot:focus-within img {
  filter: contrast(1.02);
}
.media-card:hover,
.media-card:focus-within {
  border-color: var(--paper);
  background: rgba(232,227,217,0.03);
}
.media-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* ==========================================================================
   Photo placeholder (story page, cleared photography drops in later)
   ========================================================================== */

.photo-slot {
  position: relative;
  aspect-ratio: 4 / 5;
  background:
    linear-gradient(160deg, #1a1c21, #0b0c0e);
  border: 1px solid var(--rule);
  overflow: hidden;
}
.photo-slot img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Real photos read desaturated at rest, same graphite ground as
     everything else, and bloom to color on hover/focus, the one
     place the site lets a photograph win. */
  filter: grayscale(70%) contrast(1.02);
  transform: scale(1.001); /* establishes a transform layer so the hover scale doesn't jump */
  transition: filter 420ms var(--ease), transform 420ms var(--ease);
}
.photo-slot:hover img,
.photo-slot:focus-within img {
  filter: grayscale(0%) contrast(1.02);
  transform: scale(1.05);
}
@media (prefers-reduced-motion: reduce) {
  .photo-slot img { transition: filter 420ms var(--ease); }
  .photo-slot:hover img,
  .photo-slot:focus-within img { transform: none; }
}
.photo-slot__mark {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s3);
}
.photo-slot__mark svg { width: 60%; max-width: 220px; opacity: 0.5; }
.photo-slot__mark svg ellipse,
.photo-slot__mark svg path {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 1.5;
  stroke-linecap: round;
}

/* Small, unobtrusive photographer/org credit pinned to a photo-slot's
   own bottom edge -- a scrim keeps it legible over any photo beneath. */
.photo-slot__credit {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: var(--s3) var(--s2) var(--s2);
  background: linear-gradient(to top, rgba(5,5,10,0.65), rgba(5,5,10,0));
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(244,246,248,0.7);
  pointer-events: none;
}

/* Button rows (e.g. the Everyday Legends links): real spacing between
   buttons in both directions, so wrapped rows don't touch on phones. */
.hero__ctas { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* A page-head photo that should lead on phones (above the heading),
   while keeping its desktop spot beside the text. */
@media (max-width: 819px) {
  .page-head__photo--first { order: -1; }
}

/* About page, "Off the Field": on desktop the couch portrait breaks out of
   its section, pinned up and to the right. That positioning used to be
   inline, so phones got it too and the photo sat on top of the text.
   Phones now get it in normal flow, under the text. */
.offfield__photo { order: 2; }
@media (min-width: 820px) {
  .offfield { position: relative; min-height: 400px; }
  .offfield__photo { position: absolute; top: -50px; right: 94px; width: 400px; max-width: 100%; }
}

/* Football page-head portrait: a transparent-background render, shown full
   and uncropped (no .photo-slot box) so the transparency reads against the
   field backdrop behind it. The source art itself cuts off hard at his
   legs -- an alpha mask fades the bottom edge to nothing instead, so it
   dissolves into whatever's beneath rather than ending on a hard line.
   The negative margin pulls him up snug against the headline.

   The hover glow lives on the *wrapping* frame, not the masked image
   itself: mask-image clips a mask-carrying element's own filter output to
   its layout box, so a drop-shadow placed on .jersey-portrait directly got
   cut off in a visible rectangle right where the glow should keep
   blooming. Filter on the unmasked frame instead reads the image's
   already-masked (already-faded) alpha shape and can bloom past it freely. */
.jersey-portrait-frame {
  display: block;
  transition: filter 420ms var(--ease);
}
.jersey-portrait-frame:hover,
.jersey-portrait-frame:focus-within {
  filter:
    drop-shadow(0 0 34px rgba(200,16,46,0.55))
    drop-shadow(0 0 70px rgba(200,16,46,0.32));
}
@media (prefers-reduced-motion: reduce) {
  .jersey-portrait-frame { transition: none; }
}
.jersey-portrait {
  width: 100%;
  height: auto;
  display: block;
  margin-top: -40px;
  -webkit-mask-image: linear-gradient(to bottom, #000 74%, transparent 96%);
          mask-image: linear-gradient(to bottom, #000 74%, transparent 96%);
}

/* ==========================================================================
   Forms
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: var(--s3);
}
.field label {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.field input, .field textarea {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--rule);
  padding: 12px 2px;
  font-family: var(--body);
  font-size: 1.05rem;
  color: var(--paper);
  min-height: 44px;
  transition: border-color 240ms var(--ease);
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:focus, .field textarea:focus {
  border-color: var(--paper);
  outline: none;
}
.field input::placeholder, .field textarea::placeholder { color: var(--placeholder); }

/* On the paper (light) ground the dark-ground colors above vanish:
   cream text and a cream hairline on a cream section. Ink instead,
   with a clearly visible writing line under each field. */
.on-paper .field label { color: var(--muted-on-paper); }
.on-paper .field input,
.on-paper .field textarea {
  color: var(--ink);
  border-bottom: 2px solid rgba(14,15,18,0.55);
}
.on-paper .field input:focus,
.on-paper .field textarea:focus { border-color: var(--scarlet); box-shadow: 0 1px 0 0 var(--scarlet); } /* red, thicker line = focus */
.field__error { color: var(--scarlet); margin-top: -2px; }

/* Honeypot: visually hidden without display:none, so it still gets filled by bots, and screen-reader-invisible for humans */
.hp-field {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  left: -9999px;
}

.form-status {
  margin-top: var(--s3);
  font-family: var(--mono);
  font-size: 0.85rem;
}
.form-status[data-state="ok"] { color: var(--paper); }
.form-status[data-state="err"] { color: var(--scarlet); }

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  position: relative;
  z-index: 1;
  border-top: 1px solid var(--rule);
  padding-block: var(--s5);
  background: var(--ink);
}
.footer__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s4);
}
.footer__col a {
  display: block;
  color: var(--muted);
  padding-block: 8px; /* 44px+ tap target */
}
.footer__col a:hover, .footer__col a:focus-visible { color: var(--paper); }
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-top: var(--s5);
}
.footer__legal { color: var(--muted); }
.footer__legal a { color: inherit; text-decoration: underline; text-underline-offset: 3px; margin-left: 0.4em; }
.footer__legal a:hover, .footer__legal a:focus-visible { color: var(--paper); }
.form-note { margin-top: var(--s2); }
/* The Work With Jaylen form starts closer to the top of its section than
   the default section padding (144px on desktop). */
.form-section { padding-top: var(--s4); }
@media (min-width: 1024px) { .form-section { padding-top: var(--s5); } }
.form-note a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

/* Privacy page: one readable column of short sections. */
.privacy { display: flex; flex-direction: column; max-width: 68ch; }
.privacy h2 { margin-top: var(--s5); font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
.privacy h2:first-child { margin-top: 0; }
.privacy p { margin-top: var(--s2); color: var(--paper); }
.privacy a { color: var(--paper); text-decoration: underline; text-underline-offset: 3px; }

.footer__credit {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-block: 12px; /* 44px+ tap target without moving the row */
  margin-block: -12px;
}
.footer__credit-mark {
  display: block;
  height: 21px;
  width: auto;
  flex-shrink: 0;
  opacity: 0.7;
  transition: opacity 200ms var(--ease);
}
.footer__credit .t-label { color: var(--muted); transition: color 200ms var(--ease); }
.footer__credit:hover .footer__credit-mark,
.footer__credit:focus-visible .footer__credit-mark { opacity: 1; }
.footer__credit:hover .t-label,
.footer__credit:focus-visible .t-label { color: var(--paper); }

/* ==========================================================================
   Closing CTA
   ========================================================================== */

.closing {
  text-align: center;
  padding-block: var(--s6);
  background: linear-gradient(180deg, rgba(14,15,18,0) 0%, rgba(14,15,18,0.55) 45%, rgba(14,15,18,0.8) 100%);
}
.closing .btn { margin-top: var(--s4); }

/* ==========================================================================
   Utility
   ========================================================================== */

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

.skip-link {
  position: absolute;
  left: var(--s2);
  top: -60px;
  z-index: 100;
  background: var(--paper);
  color: var(--ink);
  padding: 12px 20px;
  font-family: var(--mono);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  transition: top 200ms var(--ease);
}
.skip-link:focus { top: var(--s2); }

hr.rule {
  border: none;
  height: 1px;
  background: var(--rule);
  margin-block: var(--s4);
}

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

/* reCAPTCHA's widget is a fixed 304px iframe; on the narrowest phones it
   scales down rather than overflowing the form's column. */
.field--captcha { margin-top: var(--s1); }
@media (max-width: 360px) {
  .field--captcha .g-recaptcha { transform: scale(0.9); transform-origin: left top; }
}

/* ==========================================================================
   Videos (video-dock.js) on /football/ and /legends/.
   Desktop/tablet: .vdock, a card pinned to the bottom-right corner with a
   soft white glow. Clicking it dims the page (.vdock-backdrop) and grows it
   to the center, where .vlayer takes over with a carousel (.vcarousel): the
   current video in color, the ones just newer/older beside it -- smaller,
   lower, black and white, a quarter tucked under. Arrows sit under it.
   Phones: the same carousel inline, in its own section (.vsection).
   ========================================================================== */

.vdock {
  --vd-w: 272px;
  --vd-gap: 24px;
  position: fixed;
  right: calc(var(--vd-gap) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--vd-gap) + env(safe-area-inset-bottom, 0px));
  width: var(--vd-w);
  aspect-ratio: 16 / 9;
  z-index: 35; /* over the page, under the sticky nav (40) and the phone menu (39) */
  border-radius: 14px;
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.22),
    0 0 28px 4px rgba(255,255,255,0.22),
    0 12px 32px rgba(0,0,0,0.5);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 420ms var(--ease), transform 420ms var(--ease), box-shadow 320ms var(--ease);
}
.vdock.is-ready { opacity: 1; transform: none; }
.vdock:has(.vdock__trigger:focus-visible) { outline: 2px solid var(--paper); outline-offset: 4px; }
html:has(.nav__sheet[data-open="true"]) .vdock { visibility: hidden; }

.vdock.is-open,
.vdock[data-state="closing"] {
  z-index: 91;
  box-shadow: 0 30px 90px rgba(0,0,0,0.65); /* the glow goes while it's open */
}
.vdock.is-open {
  right: auto;
  bottom: auto;
  left: calc(50% - var(--vd-open-w) / 2);
  top: calc(50% - var(--vd-open-h) / 2);
  width: var(--vd-open-w);
  height: var(--vd-open-h);
  aspect-ratio: auto;
  border-radius: 12px;
}
.vdock.is-parked { visibility: hidden; } /* the carousel is showing its video */

.vdock__frame {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  background: #000;
}
.vdock__trigger {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: #000;
  cursor: pointer;
}
.vdock__trigger:focus-visible { outline: none; } /* drawn on .vdock instead, outside the clip */
.vdock__trigger::after,
.vcard__play::before { /* keeps the play button readable on bright stills */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, rgba(0,0,0,0.38), rgba(0,0,0,0.08) 70%);
}
.vdock__still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.vdock__play {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  width: 52px;
  height: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(14,15,18,0.55);
  border: 1.5px solid rgba(255,255,255,0.9);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  transition: transform 220ms var(--ease), background 220ms var(--ease), opacity 200ms var(--ease);
}
.vdock__play svg { width: 22px; height: 22px; fill: currentColor; } /* the path is drawn a touch right of center, so its visual weight lands dead center */
.vdock__trigger:hover .vdock__play,
.vdock__trigger:focus-visible .vdock__play,
.vcard__play:hover .vdock__play,
.vcard__play:focus-visible .vdock__play { transform: scale(1.08); background: rgba(14,15,18,0.75); }
.vdock.is-open .vdock__play { opacity: 0; transform: scale(0.85); }

.vdock-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(8,9,11,0.82);
  opacity: 0;
  visibility: hidden;
  transition: opacity 360ms var(--ease), visibility 0s linear 360ms;
}
.vdock-backdrop.is-visible { opacity: 1; visibility: visible; transition-delay: 0s; }
html.vdock-lock body { overflow: hidden; }
/* Other sites' embeds on the page (Instagram, X) can paint through the dim
   layer in Chrome; they're behind it anyway, so hide them until it closes. */
html.vdock-lock main iframe { visibility: hidden; }

/* ---------- The carousel (both versions) ---------- */

.vcarousel { position: relative; }
.vcard {
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 12px;
  overflow: hidden;
  background: #000;
  box-shadow: 0 24px 70px rgba(0,0,0,0.55);
  /* keep the duration in step with MOVE_MS in video-dock.js */
  transition: transform 560ms var(--ease), filter 560ms var(--ease), opacity 420ms var(--ease);
}
.vcarousel.no-anim .vcard { transition: none; }
.vcard.is-side { cursor: pointer; }
.vcard__stage { position: absolute; inset: 0; }
.vcard__stage iframe,
.vcard__stage video {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: #000;
  opacity: 0;
  transition: opacity 300ms var(--ease);
}
.vcard__stage .is-loaded { opacity: 1; }
.vcard__play {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.vcard:not(.is-current) .vcard__play,
.vcard.is-playing .vcard__play { display: none; }
.vcard:has(.vcard__play:focus-visible) { outline: 2px solid var(--paper); outline-offset: 4px; }

/* Arrows under the current video, close together; missing ones keep their
   place so the other doesn't jump. */
.vcontrols {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s3);
}
.vcontrols .vdock__nav[hidden] { display: grid; visibility: hidden; }

/* ---------- Desktop overlay ---------- */

.vlayer {
  position: fixed;
  inset: 0;
  z-index: 92;
  visibility: hidden;
  pointer-events: none;
}
.vlayer.is-open { visibility: visible; }
.vlayer .vcarousel { position: absolute; inset: 0; }
.vlayer.is-open .vcard,
.vlayer.is-open button { pointer-events: auto; }
.vlayer.is-closing .vcard.is-current { visibility: hidden; } /* the corner card rides it back */
.vlayer.is-closing .vcard { opacity: 0 !important; }
.vlayer .vcontrols {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% + var(--cur-h) / 2 + 20px);
  transition: top 560ms var(--ease);
}

/* Close (the screen's corner) and the arrows share one round-button look. */
.vdock__close,
.vdock__nav {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 0;
  color: var(--paper);
  background: rgba(232,227,217,0.1);
  border: 1px solid rgba(232,227,217,0.4);
  cursor: pointer;
  transition: background 200ms var(--ease), border-color 200ms var(--ease);
}
.vdock__close svg,
.vdock__nav svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.vdock__close:hover, .vdock__close:focus-visible,
.vdock__nav:hover, .vdock__nav:focus-visible { background: rgba(232,227,217,0.2); border-color: var(--paper); }
.vdock__close:focus-visible,
.vdock__nav:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.vdock__close {
  position: fixed;
  top: calc(20px + env(safe-area-inset-top, 0px));
  right: calc(20px + env(safe-area-inset-right, 0px));
}
.vlayer .vdock__close,
.vlayer .vcontrols { opacity: 0; transition: opacity 240ms var(--ease), top 560ms var(--ease); }
.vlayer.is-open .vdock__close,
.vlayer.is-open .vcontrols { opacity: 1; }
.vlayer.is-closing .vdock__close,
.vlayer.is-closing .vcontrols { opacity: 0; }

/* ---------- Phones: the section ---------- */

/* The breakpoint matches phoneQuery in video-dock.js. */
@media (max-width: 699px) {
  .vdock, .vdock-backdrop, .vlayer { display: none !important; }
}
@media (min-width: 700px) {
  .vsection { display: none; }
}
.vsection {
  overflow: hidden; /* side videos peek in from the screen edges */
  overflow: clip;
}
.vsection .vcarousel {
  margin-top: var(--s4);
  transition: height 560ms var(--ease);
}
.vsection .vcontrols { margin-top: var(--s4); }

@media print {
  .vdock, .vdock-backdrop, .vlayer, .vsection { display: none !important; }
}
