/* ================================================================
   KASPA RALLY — MOBILE-FIRST DESIGN SYSTEM
   High-contrast neutrals. Teal is used as a deliberate design element,
   never as default text on white.
   ================================================================ */

/* Barlow, self-hosted --------------------------------------------
   Generated by tools/fetch-fonts.js - do not hand-edit these blocks.

   Self-hosted so the site makes no third-party request on load: fetching
   these from fonts.googleapis.com sends every visitor's IP to Google
   before any consent, which is the usual reason a cookie-free site still
   needs a banner in the EU.

   font-display: swap renders fallback text immediately and swaps when the
   webfont arrives, so the copy is never invisible. unicode-range is kept
   per subset, so a browser downloads only the ranges it needs.
   ---------------------------------------------------------------- */

/* vietnamese */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/barlow-400-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/barlow-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/barlow-400-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;
}

/* vietnamese */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/barlow-500-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/barlow-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('assets/fonts/barlow-500-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;
}

/* vietnamese */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/barlow-600-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/barlow-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('assets/fonts/barlow-600-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;
}

/* vietnamese */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-700-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-700-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;
}

/* vietnamese */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-800-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}

/* latin-ext */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-800-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('assets/fonts/barlow-condensed-800-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 {
  --font-display: "Barlow Condensed", "Arial Narrow", sans-serif;
  --font-body: "Barlow", Arial, sans-serif;

  --white: #ffffff;
  --black: #0d0d0d;
  --off-white: #f5f5f1;
  --grey: #d8d8d2;
  --muted: #696963;
  --teal: #16c7b7;

  --bg: var(--white);
  --surface: var(--off-white);
  --text: var(--black);
  --text-muted: #555550;
  --line: #cfcfca;
  --header-bg: rgb(255 255 255 / 92%);

  --page-gutter: clamp(1.25rem, 4vw, 4.5rem);
  --section-space: clamp(5rem, 11vw, 10rem);
  --header-height: 4.75rem;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html[data-theme="dark"] {
  --bg: #0d0d0d;
  --surface: #151515;
  --text: #ffffff;
  --text-muted: #b9b9b2;
  --line: #353531;
  --header-bg: rgb(13 13 13 / 92%);
}

* {
  box-sizing: border-box;
}

html {
  font-size: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-height) + 1rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.55;
  text-rendering: optimizeLegibility;
  transition: background-color 220ms ease, color 220ms ease;
}

body.nav-open {
  overflow: hidden;
}

img {
  display: block;
  width: 100%;
  height: auto;
}

button,
a {
  font: inherit;
}

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

button {
  color: inherit;
}

::selection {
  background: var(--teal);
  color: var(--black);
}

:focus-visible {
  outline: 0.1875rem solid var(--teal);
  outline-offset: 0.25rem;
}

.skip-link {
  position: fixed;
  z-index: 1000;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--black);
  color: var(--white);
  transform: translateY(-180%);
  transition: transform 180ms ease;
}

.skip-link:focus {
  transform: translateY(0);
}

/* Header --------------------------------------------------------- */
.site-header {
  position: sticky;
  z-index: 100;
  top: 0;
  display: flex;
  min-height: var(--header-height);
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-inline: var(--page-gutter);
  background: var(--header-bg);
  border-bottom: 0.0625rem solid var(--line);
  backdrop-filter: blur(0.75rem);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: uppercase;
}

/* Temporary abstract checker mark. Swap for the final SVG logo. */
.brand__mark {
  display: grid;
  width: 1.75rem;
  grid-template-columns: repeat(3, 0.5rem);
  gap: 0.125rem;
  transform: skewY(-7deg);
}

.brand__mark span {
  aspect-ratio: 1;
  background: currentColor;
}

.brand__mark span:nth-child(2),
.brand__mark span:nth-child(6) {
  background: var(--teal);
}

.desktop-nav {
  display: none;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.theme-toggle,
.menu-toggle {
  border: 0;
  background: transparent;
  cursor: pointer;
}

.theme-toggle {
  display: inline-flex;
  min-height: 2.75rem;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.theme-toggle__indicator {
  width: 0.625rem;
  aspect-ratio: 1;
  background: currentColor;
  transition: transform 220ms var(--ease), background-color 220ms ease;
}

.theme-toggle[aria-pressed="true"] .theme-toggle__indicator {
  background: var(--teal);
  transform: rotate(45deg);
}

.menu-toggle {
  position: relative;
  z-index: 120;
  display: grid;
  width: 2.875rem;
  height: 2.875rem;
  place-content: center;
  gap: 0.4375rem;
  padding: 0;
}

.menu-toggle__line {
  display: block;
  width: 1.625rem;
  height: 0.125rem;
  background: currentColor;
  transform-origin: center;
  transition: transform 280ms var(--ease), width 280ms var(--ease);
}

.menu-toggle[aria-expanded="true"] .menu-toggle__line:first-child {
  transform: translateY(0.28125rem) rotate(45deg);
}

.menu-toggle[aria-expanded="true"] .menu-toggle__line:last-child {
  transform: translateY(-0.28125rem) rotate(-45deg);
}

/* Mobile navigation ---------------------------------------------- */
.mobile-nav {
  position: fixed;
  z-index: 90;
  inset: var(--header-height) 0 0;
  visibility: hidden;
  background: var(--black);
  color: var(--white);
  opacity: 0;
  transform: translateX(100%);
  transition: transform 420ms var(--ease), opacity 300ms ease, visibility 0s linear 420ms;
}

.mobile-nav.is-open {
  visibility: visible;
  opacity: 1;
  transform: translateX(0);
  transition-delay: 0s;
}

.mobile-nav__inner {
  display: flex;
  height: 100%;
  flex-direction: column;
  padding: clamp(2rem, 9vw, 4rem) var(--page-gutter);
  overflow-y: auto;
}

.mobile-nav__inner > a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 0.35rem;
  border-bottom: 0.0625rem solid #383838;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 13vw, 5rem);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1;
  text-transform: uppercase;
}

.mobile-nav__external {
  display: grid;
  gap: 0.75rem;
  margin-top: auto;
  padding-top: 3rem;
}

.mobile-nav__external a {
  width: fit-content;
  font-weight: 600;
}

/* Shared typography ---------------------------------------------- */
.eyebrow {
  margin: 0 0 1rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1.2;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

h1,
h2,
h3,
.footer-display {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
}

h1 {
  margin-bottom: 1.5rem;
  font-size: clamp(4.5rem, 24vw, 9.5rem);
  letter-spacing: -0.045em;
  line-height: 0.78;
}

h2 {
  margin-bottom: 1.5rem;
  font-size: clamp(3.5rem, 17vw, 7rem);
  letter-spacing: -0.04em;
  line-height: 0.83;
}

h3 {
  margin-bottom: 0.25rem;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  line-height: 1;
}

.section-shell {
  padding: var(--section-space) var(--page-gutter);
}

.section-index {
  font-family: var(--font-display);
  font-size: clamp(5rem, 26vw, 13rem);
  font-weight: 800;
  /* Was -0.06em, the tightest tracking in the file. At the 13rem ceiling that
     pulled each glyph ~12.5px left and the 1 flag collided with the 0. Kept
     negative so the numerals still read as tight display type, but brought
     inside the range the rest of the display headings use (-0.02 to -0.05). */
  letter-spacing: -0.02em;
  line-height: 0.7;
  opacity: 0.12;
}

/* Hero ----------------------------------------------------------- */
/* Mobile: the copy and the photo SHARE one viewport instead of stacking up to
   more than one. With min-height the two blocks summed to roughly 724px on a
   390px phone (480px content floor + 244px of 16:10 photo) against about 670px
   of usable height, so the photo sat half below the fold on arrival.

   height, not min-height, is the fix: it gives the hero a real box for its
   children to divide. Overridden wholesale at 48rem, where .hero becomes a
   two-column grid. */
.hero {
  display: flex;
  flex-direction: column;
  height: calc(100svh - var(--header-height));
  /* Floor for very short screens, e.g. a phone in landscape, where dividing
     the viewport would leave the headline unreadable. Scrolling is the better
     failure there. */
  min-height: 26rem;
}

.hero__content {
  display: flex;
  /* flex: 0 0 auto - grow 0, SHRINK 0. The whole copy block is guaranteed its
     natural height and the photo below absorbs whatever is left.

     The shrink value is the important one. With flex-shrink: 1 the block could
     be squeezed on a short screen, and because the copy is bottom-aligned
     (justify-content: flex-end) the overflow goes off the TOP - so the eyebrow
     "Portugal / Kaspa / Rally" is the first thing to disappear, silently. All
     five elements must stay on screen: eyebrow, headline, lede, and both
     links.

     The old min-height: 30rem was the opposite problem - a hard 480px floor
     that could not yield, which is what pushed the photo below the fold. */
  flex: 0 0 auto;
  min-height: 0;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(2rem, 9vw, 5rem) var(--page-gutter) 2rem;
}

.hero__lede {
  max-width: 31rem;
  margin-bottom: 2rem;
  font-size: clamp(1.1rem, 4vw, 1.35rem);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem 2rem;
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  padding-bottom: 0.2rem;
  border-bottom: 0.125rem solid currentColor;
  font-weight: 600;
}

.text-link span,
.site-footer a span,
.mobile-nav a span,
.button span {
  display: inline-block;
  transition: transform 180ms var(--ease);
}

.text-link--external:hover span,
.site-footer a:hover span,
.mobile-nav__external a:hover span,
.button:hover span {
  transform: translate(0.1875rem, -0.1875rem);
}

.text-link--internal:hover span {
  transform: translateX(0.1875rem);
}

.hero__media {
  position: relative;
  min-height: 29rem;
  margin: 0;
  overflow: hidden;
  background: var(--surface);
}

.hero__media img {
  width: 100%;
  height: 100%;
  min-height: 29rem;
  object-fit: cover;
}

.hero__media::after {
  position: absolute;
  top: 0;
  left: 0;
  width: 0.625rem;
  height: 38%;
  background: var(--teal);
  content: "";
}

/* Media captions.
   ONE rule for every caption on the site, at every screen size: flush to the
   bottom-left corner of its own frame. Previously the base sat bottom-right
   and only the hero was flipped left above 48rem, so captions jumped corners
   between phone and tablet. Anything that overrides left/right/bottom here
   will reintroduce that, so keep the anchoring in this block. */
.hero__media figcaption,
.video-placeholder figcaption,
.build-grid figcaption {
  position: absolute;
  left: 0;
  right: auto;
  bottom: 0;
  max-width: min(90%, 34rem);
  padding: 0.5rem 0.75rem;
  background: var(--black);
  color: var(--white);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.35;
  text-transform: uppercase;
  text-align: left;
}

/* StagHunt ------------------------------------------------------- */
.stag-hunt {
  display: grid;
  gap: 2rem;
  /* Bottom padding is deliberately about half the shared --section-space. The
     kas.coffee widget closes this section, and a fixed-height frame followed by
     a full 10rem of teal reads as a large empty block rather than as section
     rhythm. The top keeps the standard spacing. */
  padding: var(--section-space) var(--page-gutter) clamp(3rem, 6vw, 5rem);
  background: var(--teal);
  color: var(--black);
}

.stag-hunt .section-index {
  opacity: 0.18;
}

/* The video section sits on --black with white text, so the shared 0.12 index
   opacity is too faint to read. Same bump the teal stag-hunt section uses.
   The margin reproduces the 2rem grid gap that .stag-hunt and .build-teaser put
   between their numeral and their content; this heading is a plain block, so
   the spacing has to be stated rather than inherited from a grid gap. */
.video-section .section-index {
  margin-bottom: 2rem;
  opacity: 0.18;
}

.stag-hunt__copy {
  max-width: 38rem;
  font-size: 1.125rem;
}

/* Column 3 of the section: the StagHunt route, sitting beside the kas.coffee
   widget. This replaces the old .stag-hunt__note, which was dropped when the
   widget was added. The rule set is deliberately the same shape as that note
   was, so the block reads as part of the original design rather than an
   addition: a thick top border and a display-face heading. */
.stag-hunt__join {
  padding-top: 1.25rem;
  border-top: 0.125rem solid var(--black);
}

.stag-hunt__join h3 {
  margin-bottom: 0.75rem;
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 0.95;
  text-transform: uppercase;
}

.stag-hunt__join p {
  max-width: 28rem;
  font-size: 0.9375rem;
}

.button {
  display: inline-flex;
  min-height: 3.5rem;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  width: min(100%, 22rem);
  margin-top: 1rem;
  padding: 0.875rem 1rem;
  border: 0.125rem solid transparent;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.button--dark {
  background: var(--black);
  color: var(--white);
}

/* Icon slot inside a .button, used where a brand mark replaces the shared
   arrow glyph (currently the staghunt.app crosshair). The wrapper is still a
   span, so it keeps the button's hover nudge; only the contents differ.

   Sized at 1.5rem, which is exactly the button's content box: min-height 3.5rem
   less 1.75rem padding and 0.25rem border, under box-sizing: border-box. Go
   larger and the icon stops fitting and stretches the button taller than the
   3.5rem the component is specified at.

   At 1.5rem the mark renders at 24px, a scale of 0.375 against its 64-unit
   canvas, so the inline SVG carries thicker stroke widths than the source file
   in assets/icons: 4.0 and 2.7 instead of 2.0 and 1.2. Those land on 1.5px and
   1.0px. The original weights fell below one device pixel, and a sub-pixel
   white stroke is drawn as a partly covered pixel, which reads as grey however
   white the colour actually is. The divergence from the source file is
   deliberate optical compensation, not drift.

   The selector is .button .button__icon, not .button__icon, because the
   .button span rule above sets display: inline-block and would otherwise win
   on specificity. */
.button .button__icon {
  display: inline-flex;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
}

.button__icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Legal / long-form text page ------------------------------------
   The site had no prose component: every other block is a heading plus a short
   paragraph. This is the minimum needed to make a readable text column, built
   only from existing tokens - no new colours, no radius, no shadow.

   The measure is capped at 38rem, matching .stag-hunt__copy, because long
   lines are the main thing that makes body text hard to read. */
.legal {
  max-width: 38rem;
}

.legal h2 {
  margin-top: 3rem;
  margin-bottom: 0.75rem;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  text-transform: uppercase;
}

.legal p {
  margin-bottom: 1rem;
}

.legal__lede {
  margin-bottom: 1rem;
  font-size: 1.125rem;
}

.legal ul {
  margin: 0 0 1rem;
  padding-left: 1.25rem;
}

.legal li {
  margin-bottom: 0.5rem;
}

/* Inline code, for the one storage key named in the text. Flat and squared
   like everything else. */
.legal code {
  padding: 0.1rem 0.3rem;
  background: var(--surface);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.9em;
}

.legal__updated {
  margin-top: 2.5rem;
  margin-bottom: 2rem;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* Season --------------------------------------------------------- */
.section-heading {
  display: grid;
  gap: 1rem;
  margin-bottom: clamp(3rem, 8vw, 5rem);
}

.section-heading > p {
  max-width: 35rem;
  color: var(--text-muted);
}

.rally-list {
  border-top: 0.125rem solid var(--text);
}

.rally-row {
  display: grid;
  grid-template-columns: 3rem 1fr;
  gap: 0.75rem 1rem;
  align-items: center;
  padding-block: 1.5rem;
  border-bottom: 0.0625rem solid var(--line);
}

.rally-row__round {
  grid-row: 1 / 3;
  margin: 0;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 800;
  line-height: 1;
}

.rally-row__name h3,
.rally-row__name p,
.rally-row time,
.rally-row__status {
  margin: 0;
}

.rally-row__name p {
  margin-top: 0.3rem;
  color: var(--text-muted);
  font-size: 0.875rem;
}

.rally-row time,
.rally-row__status {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.rally-row time {
  grid-column: 2;
}

.rally-row__status {
  grid-column: 2;
}

.rally-row--next {
  position: relative;
}

.rally-row--next::before {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--page-gutter) * -1);
  width: 0.375rem;
  background: var(--teal);
  content: "";
}

.status-dot {
  display: inline-block;
  width: 0.55rem;
  aspect-ratio: 1;
  margin-right: 0.45rem;
  background: var(--teal);
}

/* Video ---------------------------------------------------------- */
.video-section {
  padding: var(--section-space) var(--page-gutter);
  background: var(--black);
  color: var(--white);
}

.video-section__heading {
  margin-bottom: clamp(2rem, 7vw, 4rem);
}

.video-placeholder {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: #1c1c1c;
}

.video-placeholder img {
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.video-placeholder__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.25rem;
  background: rgb(0 0 0 / 30%);
  text-align: left;
}

.video-placeholder__play {
  display: grid;
  width: 4rem;
  aspect-ratio: 1;
  place-items: center;
  flex: 0 0 auto;
  background: var(--teal);
  color: var(--black);
}

/* Keep the play glyph proportionate to its teal control background. */
.video-placeholder__overlay .video-placeholder__play {
  font-size: 1.625rem;
  letter-spacing: 0;
  line-height: 1;
}

.video-placeholder__overlay strong,
.video-placeholder__overlay span {
  display: block;
}

.video-placeholder__overlay strong {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 5vw, 2.5rem);
  text-transform: uppercase;
}

.video-placeholder__overlay span {
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Build teaser --------------------------------------------------- */
.build-teaser {
  display: grid;
  gap: 2rem;
}

.build-teaser__heading > p:last-child {
  max-width: 34rem;
  color: var(--text-muted);
}

.build-grid {
  display: grid;
  gap: 1rem;
}

.build-grid__item {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--surface);
}

.build-grid__item img {
  height: 100%;
  object-fit: cover;
}

.build-grid__item--landscape {
  aspect-ratio: 4 / 3;
}

.build-grid__item--portrait {
  width: 78%;
  justify-self: end;
  aspect-ratio: 3 / 4;
}

.build-teaser__future {
  margin: 1rem 0 0;
  padding-top: 1rem;
  border-top: 0.0625rem solid var(--line);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Footer --------------------------------------------------------- */
.site-footer {
  padding: var(--section-space) var(--page-gutter) 2rem;
  background: var(--black);
  color: var(--white);
}

.footer-display {
  margin: 0;
  font-size: clamp(4.5rem, 20vw, 9rem);
  letter-spacing: -0.05em;
  line-height: 0.78;
}

.site-footer__links {
  display: grid;
  gap: 2rem;
  margin-top: clamp(4rem, 12vw, 8rem);
  padding-top: 2rem;
  border-top: 0.0625rem solid #3a3a3a;
}

.footer-label {
  margin-bottom: 0.35rem;
  color: #9f9f99;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.site-footer__links a {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
  font-weight: 600;
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 4rem;
  padding-top: 1rem;
  border-top: 0.0625rem solid #3a3a3a;
  color: #aaa;
  font-size: 0.75rem;
}

/* Tablet --------------------------------------------------------- */
@media (min-width: 48rem) {
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  }

  .hero__content,
  .hero__media,
  .hero__media img {
    min-height: calc(100svh - var(--header-height));
  }

  .stag-hunt {
    grid-template-columns: minmax(6rem, 0.3fr) minmax(0, 1.2fr) minmax(15rem, 0.55fr);
    align-items: start;
  }

  /* Explicit placement so the widget and the StagHunt block share row 2 and
     therefore start at exactly the same y: their top edges align by
     construction, which no align-self value could achieve while the widget sat
     inside the content column below the headline and copy.

     The widget stays in column 2, so the column width the 1.15 / 1.35 scale
     steps below are calibrated against is unchanged. Do not move it to a
     different column without re-deriving those. */
  .stag-hunt .section-index {
    grid-column: 1;
    grid-row: 1;
  }

  .stag-hunt__content {
    grid-column: 2;
    grid-row: 1;
  }

  .stag-hunt > .donate-embed {
    grid-column: 2;
    grid-row: 2;
  }

  .stag-hunt__join {
    grid-column: 3;
    grid-row: 2;
    align-self: start;
  }

  .section-heading {
    grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.55fr);
    align-items: end;
  }

  .rally-row {
    grid-template-columns: 4rem minmax(0, 1.4fr) minmax(6rem, 0.45fr) minmax(7rem, 0.45fr);
    gap: 1rem;
  }

  .rally-row__round {
    grid-row: auto;
  }

  .rally-row time,
  .rally-row__status {
    grid-column: auto;
  }

  .build-teaser {
    /* Column 1 holds the 03 numeral. It was minmax(5rem, 0.25fr), narrower than
       01 uses, and far narrower than the numeral itself - so 03 overflowed its
       column and crowded the headline in column 2. max-content as the floor
       makes the column always contain the numeral, so the column-gap below is
       real clearance rather than space the numeral is already eating into.
       Self-correcting if the numeral font, size or tracking ever changes. */
    grid-template-columns: minmax(max-content, 0.3fr) minmax(0, 0.75fr) minmax(0, 1.4fr);
    column-gap: clamp(3rem, 6vw, 6rem);
    row-gap: 2rem;
    align-items: start;
  }

  .build-grid {
    grid-column: 3;
    grid-template-columns: 1.35fr 0.65fr;
    align-items: end;
  }

  .build-grid__item--portrait {
    width: 100%;
  }

  .build-teaser__future {
    grid-column: 3;
  }

  .site-footer__links {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Desktop -------------------------------------------------------- */
@media (min-width: 64rem) {
  :root {
    --header-height: 5.25rem;
  }

  .desktop-nav {
    display: flex;
    align-items: center;
    gap: clamp(1.5rem, 3vw, 3rem);
    margin-left: auto;
  }

  .desktop-nav a {
    position: relative;
    padding-block: 0.5rem;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
  }

  .desktop-nav a::after {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 0.125rem;
    background: var(--teal);
    content: "";
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 220ms var(--ease);
  }

  .desktop-nav a:hover::after,
  .desktop-nav a:focus-visible::after {
    transform: scaleX(1);
    transform-origin: left;
  }

  .menu-toggle {
    display: none;
  }

  .mobile-nav {
    display: none;
  }

  .hero__content {
    padding-bottom: clamp(4rem, 7vw, 7rem);
  }

  .season {
    padding-inline: max(var(--page-gutter), calc((100vw - 92rem) / 2));
  }

  .video-section {
    display: grid;
    grid-template-columns: minmax(18rem, 0.55fr) minmax(0, 1.45fr);
    gap: clamp(3rem, 7vw, 8rem);
    /* Top-aligned, not bottom-aligned: the .section-index numeral must line up
       with the top edge of the video, matching how 01 and 03 sit in their
       single-column sections. */
    align-items: start;
  }

  .video-section__heading {
    margin: 0;
  }
}

/* Very large screens -------------------------------------------- */
@media (min-width: 90rem) {
  .hero__content {
    padding-left: max(var(--page-gutter), calc((100vw - 100rem) / 2));
  }
}

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

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}


/* Demo YouTube embed — fills the existing 16:9 media treatment. */
.video-placeholder--embed {
  aspect-ratio: 16 / 9;
  background: #0d0d0d;
}

.video-placeholder--embed iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* The video caption inherits its corner anchoring from the shared caption
   rule above. Only its own colour and stacking are set here — it used to be
   inset by 1rem and hidden below 32rem, which is why it both sat differently
   from the image captions and disappeared on phones. */
.video-placeholder__caption {
  z-index: 2;
  background: rgba(13, 13, 13, 0.88);
  color: #fff;
  pointer-events: none;
}


/* Hero media refinement
   Keep the dramatic rally photograph, but crop it inside a controlled frame so
   a tall source image cannot push the hero copy below the initial viewport. */
.hero__media {
  /* Takes all the height the copy did not use, so the frame always ends at the
     fold rather than past it. aspect-ratio is dropped because the height now
     comes from the flex share; the photo is object-fit: cover, so a shorter
     frame crops it rather than squashing it. min-height keeps it from
     collapsing to a sliver if the copy runs long. */
  flex: 1 1 auto;
  /* Floor so the photo can never become a decorative sliver when the copy runs
     long. 9rem is a compromise: on the smallest phones (375px wide, ~553px of
     viewport) the copy alone needs most of the screen, and this trades a small
     scroll for a photo that is still recognisably a photo. */
  min-height: 9rem;
  aspect-ratio: auto;
  overflow: hidden;
}

/* <picture> is inline by default and has no size of its own. Every image that
   fills a fixed-ratio frame is wrapped in one (for the AVIF sources), so the
   wrapper must become a block that fills the frame — otherwise the image's
   height:100% resolves against nothing and the layout collapses. */
.hero__media picture,
.build-slider__slide picture,
.build-grid__item picture {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__media img,
.hero__image {
  /* Mobile fix: the base rule pins this image to min-height 29rem. Below
     48rem nothing reset it, so the img box stayed 464px tall inside a
     16:10 frame — cover then zoomed the photo and centre-cropped the car
     out of the visible strip. The frame owns the height here.  */
  min-height: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The hero is now one 16:10 photo at every size. Below 64rem the frame is
     also 16:10, so nothing is cropped and this value is inert. Above 64rem the
     split-screen column is wider than 16:10 and cover() trims left/right (and
     top/bottom past ~1.6). In this photo the car occupies x 750-2150, y
     816-1302 of 2400x1500 — right of centre and low — so a centred crop would
     keep dust and treetops and cut the car. 70% 70% centres those crops on the
     car instead. Re-measure this if the hero photo is ever replaced. */
  object-position: 70% 70%;
}

/* The teal accent rule reads as a vertical edge marker beside the tall
   desktop image. Against the short, wide mobile frame the same 38% height
   becomes a small floating block, so it is dropped below the breakpoint
   where the hero switches to its tall layout. */
@media (max-width: 63.999rem) {
  .hero__media::after {
    content: none;
  }
}

@media (min-width: 64rem) {
  .hero {
    min-height: calc(100svh - var(--header-height, 5rem));
    max-height: 54rem;
    align-items: stretch;
  }

  .hero__media {
    aspect-ratio: auto;
    min-height: 32rem;
    max-height: 54rem;
  }
}


/* Laptop/desktop hero refinement
   The original split hero bottom-aligned its copy and forced each column to
   viewport height. Keep the same composition, but make it intentionally
   compact on laptops and vertically centre the copy. */
@media (min-width: 48rem) {
  .hero {
    min-height: 34rem;
    height: min(42rem, calc(100svh - var(--header-height)));
    max-height: 42rem;
    align-items: stretch;
  }

  .hero__content,
  .hero__media,
  .hero__media img {
    min-height: 0;
  }

  .hero__content {
    justify-content: center;
    padding-top: 2.5rem;
    padding-bottom: 3.5rem;
  }

  .hero__media {
    height: 100%;
    aspect-ratio: auto;
  }

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


/* ================================================================
   BUILD ARCHIVE — FOUR-STAGE EDITORIAL SLIDERS
   ================================================================ */
.build-archive--sliders { padding: 0 var(--page-gutter) clamp(4rem, 8vw, 8rem); }
.build-story { display:grid; gap:1.75rem; padding:clamp(3.5rem,8vw,7.5rem) 0; border-top:1px solid var(--border); }
.build-story:first-child { border-top-width:2px; }
.build-story__copy { display:grid; grid-template-columns:auto minmax(0,1fr); align-items:start; gap:clamp(1.25rem,4vw,4rem); max-width:68rem; }
.build-story__number { margin:-0.08em 0 0; font-family:var(--font-display); font-size:clamp(5rem,12vw,10rem); font-weight:800; line-height:.72; letter-spacing:-.055em; }
.build-story__text { max-width:39rem; }
.build-story__text h2 { margin:.4rem 0 1.25rem; font-family:var(--font-display); font-size:clamp(2.75rem,7vw,6rem); font-weight:800; line-height:.88; letter-spacing:-.035em; text-transform:uppercase; }
.build-story__text > p:last-child { max-width:35rem; margin-bottom:0; line-height:1.65; }
.build-slider { min-width:0; outline:none; }
.build-slider:focus-visible { outline:3px solid var(--teal); outline-offset:.4rem; }
.build-slider__viewport { position:relative; overflow:hidden; background:#0d0d0d; }
.build-slider__track { display:flex; margin:0; padding:0; list-style:none; transition:transform 420ms cubic-bezier(.22,1,.36,1); touch-action:pan-y; }
.build-slider__slide { flex:0 0 100%; min-width:0; aspect-ratio:16/10; }
.build-slider__slide img { display:block; width:100%; height:100%; object-fit:cover; }
.build-slider__arrow { position:absolute; top:50%; z-index:2; display:grid; place-items:center; width:clamp(3.5rem,6vw,5rem); height:clamp(3.5rem,6vw,5rem); padding:0; border:0; border-radius:0; background:var(--teal); color:#0d0d0d; font:inherit; cursor:pointer; transform:translateY(-50%); }
.build-slider__arrow span { display:block; font-size:clamp(1.65rem,3vw,2.5rem); font-weight:600; line-height:1; transition:transform 180ms ease; }
.build-slider__arrow--prev { left:0; }
.build-slider__arrow--next { right:0; }
@media (hover:hover) and (pointer:fine) { .build-slider__arrow--prev:hover span { transform:translateX(-.2rem); } .build-slider__arrow--next:hover span { transform:translateX(.2rem); } }
.build-slider__arrow:focus-visible { outline:3px solid currentColor; outline-offset:-.45rem; }
/* Placeholder for build stages whose photography is not shot yet.

   This replaces assets/build/coming-soon.svg, which was embedded with <img>.
   A webfont can never load inside an SVG referenced that way, so the display
   face silently fell through to Arial Narrow and the type read as off-brand.
   As ordinary markup it uses the Barlow Condensed the page has already loaded.

   Treated editorially rather than as a centred label: eyebrow over a large
   condensed headline, set bottom-left, which is how the section headings are
   built elsewhere on the site. */
.coming-soon {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 16 / 10;
  padding: clamp(1.5rem, 4vw, 3rem);
  background: var(--teal);
  color: var(--black);
}

.coming-soon__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 9vw, 6rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 0.85;
  text-transform: uppercase;
}

.build-slider__meta { display:flex; align-items:center; justify-content:space-between; gap:1rem; padding-top:.85rem; }
.build-slider__status { margin:0; font-family:var(--font-display); font-size:1rem; font-weight:700; letter-spacing:.08em; }
.build-slider__dots { display:flex; gap:.4rem; }
.build-slider__dots span { width:1.8rem; height:.2rem; background:var(--border); }
.build-slider__dots span.is-active { background:var(--teal); }
@media (min-width:64rem) { .build-story { grid-template-columns:minmax(18rem,.72fr) minmax(0,1.28fr); gap:clamp(3rem,6vw,7rem); align-items:start; } .build-story__copy { position:sticky; top:calc(var(--header-height) + 2rem); grid-template-columns:1fr; gap:2rem; } .build-story__number { font-size:clamp(7rem,10vw,11rem); } .build-story__text h2 { font-size:clamp(3.5rem,5vw,5.75rem); } }
@media (prefers-reduced-motion:reduce) { .build-slider__track,.build-slider__arrow span { transition:none; } }


/* ================================================================
   BUILD PAGE + CALENDAR POLISH
   ================================================================ */

/* 1. Align the Build page hero with the same page gutter as the
   header logo and archive content. */
.build-hero {
  display: grid;
  gap: 2rem;
  padding: clamp(4rem, 8vw, 7rem) var(--page-gutter) clamp(3.5rem, 7vw, 6rem);
  border-bottom: 1px solid var(--line);
}

.build-hero__copy {
  max-width: 58rem;
}

.build-hero h1 {
  margin: 0.4rem 0 1.5rem;
}

.build-hero__lede {
  max-width: 42rem;
  margin: 0;
  line-height: 1.6;
}

.build-hero__index {
  align-self: end;
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 4rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
}

@media (min-width: 64rem) {
  .build-hero {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
  }
}

/* 2. Make slider arrows heavier and more mechanical.
   The glyph is replaced visually by a CSS-built shaft and arrowhead,
   which centres consistently regardless of font rendering. */
.build-slider__arrow {
  width: clamp(3.75rem, 6vw, 5.25rem);
  height: clamp(3.75rem, 6vw, 5.25rem);
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--teal);
  color: var(--black);
  transform: translateY(-50%);
}

.build-slider__arrow span {
  position: relative;
  display: block;
  width: 1.9rem;
  height: 1.35rem;
  font-size: 0;
  line-height: 0;
  transform: none;
}

/* Thick horizontal shaft */
.build-slider__arrow span::before {
  position: absolute;
  top: 50%;
  left: 0.15rem;
  width: 1.55rem;
  height: 0.28rem;
  background: currentColor;
  content: "";
  transform: translateY(-50%);
}

/* Heavy angled arrowhead */
.build-slider__arrow span::after {
  position: absolute;
  top: 50%;
  width: 0.85rem;
  height: 0.85rem;
  border-top: 0.28rem solid currentColor;
  border-right: 0.28rem solid currentColor;
  content: "";
}

.build-slider__arrow--next span::after {
  right: 0.08rem;
  transform: translateY(-50%) rotate(45deg);
}

.build-slider__arrow--prev span::after {
  left: 0.08rem;
  transform: translateY(-50%) rotate(-135deg);
}

/* Keep hover movement restrained and mechanical. */
@media (hover: hover) and (pointer: fine) {
  .build-slider__arrow--prev:hover span,
  .build-slider__arrow--next:hover span {
    transform: none;
  }

  .build-slider__arrow:hover {
    filter: brightness(0.94);
  }
}

/* 3. Pull the first-rally teal marker back into the calendar content.
   Previously it used a negative gutter, which pushed it toward the
   viewport edge and detached it visually from the row. */
.rally-row--next {
  padding-left: 1rem;
}

.rally-row--next::before {
  left: 0;
  width: 0.4rem;
}

/* ================================================================
   HOMEPAGE MICRO-ALIGNMENT POLISH
   ================================================================ */

/* Build teaser captions keep both labels the same visual height.
   Corner anchoring comes from the shared caption rule. */
.build-grid figcaption {
  display: flex;
  min-height: 2.25rem;
  align-items: center;
  padding-block: 0.5rem;
}

/* Calendar highlight: keep all row content on the exact same grid.
   The teal marker is purely decorative and sits inside the row without
   changing padding or column alignment. */
.rally-row--next {
  padding-left: 0;
}

.rally-row--next::before {
  left: 0.45rem;
  width: 0.4rem;
}


/* Build slider controls — monochrome so vibrant photography remains dominant. */
.build-slider__arrow {
  background: var(--black);
  color: var(--white);
  border: 1px solid var(--black);
}

[data-theme="dark"] .build-slider__arrow {
  background: var(--white);
  color: var(--black);
  border-color: var(--white);
}

@media (hover: hover) and (pointer: fine) {
  .build-slider__arrow:hover {
    filter: none;
    opacity: 0.82;
  }
}


/* ================================================================
   Homepage micro-corrections
   ================================================================ */

/* Calendar marker:
   Keep all row text on the same grid, but move the teal marker into
   the row's outer gutter so it never crosses the round number. */
.rally-row--next {
  padding-left: 0;
}

.rally-row--next::before {
  left: -0.85rem;
  width: 0.35rem;
}

/* Build teaser captions:
   Use an explicit shared block height so the landscape and portrait
   image labels remain visually identical even when their text wraps
   differently. */
.build-teaser .placeholder-label {
  box-sizing: border-box;
  left: 0;
  right: auto;
  width: auto;
  min-width: 10.75rem;
  height: 4.75rem;
  min-height: 4.75rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding: 0.75rem 1rem;
}


/* Homepage final micro-polish ------------------------------------ */

/* External-link arrow
   The diagonal arrow is the plain "→" (U+2192) rotated -45deg, NOT the
   literal "↗" (U+2197). U+2197 carries an emoji presentation, so iOS
   falls back to Apple Color Emoji and paints it as a white arrow on a
   blue rounded square. U+2192 has no emoji form and exists in every
   font, so it renders as text on every platform — and because it is
   the same glyph used by the internal links, the stroke weight and
   proportions match exactly. */
.arrow-ne {
  display: inline-block;
  transform: rotate(-45deg);
  transform-origin: 50% 50%;
}

/* Preserve the existing nudge-on-hover, with the rotation reapplied.
   Order matters: translate in the parent's axes first, then rotate. */
.text-link--external:hover .arrow-ne,
.text-link--internal:hover .arrow-ne,
.site-footer a:hover .arrow-ne,
.mobile-nav__external a:hover .arrow-ne,
.button:hover .arrow-ne {
  transform: translate(0.1875rem, -0.1875rem) rotate(-45deg);
}

/* Suppress iOS Safari's translucent blue tap overlay on links/buttons.
   Focus and hover styling is handled explicitly elsewhere. */
a,
button {
  -webkit-tap-highlight-color: transparent;
}

/* Navigation
   Use the established two-line menu control at every viewport width.
   The off-canvas navigation remains the single navigation pattern. */
.desktop-nav {
  display: none !important;
}

.menu-toggle {
  display: inline-grid !important;
  margin-left: auto;
}

.mobile-panel {
  display: flex;
}


/* All-screen off-canvas navigation fix -------------------------- */
.mobile-panel {
  display: flex !important;
  position: fixed;
  inset: var(--header-height) 0 0 auto;
  width: min(26rem, 100%);
  max-width: 100%;
  height: calc(100% - var(--header-height));
  z-index: 90;
  transform: translateX(100%);
  visibility: hidden;
  pointer-events: none;
  opacity: 0;
  transition:
    transform 260ms ease,
    opacity 180ms ease,
    visibility 0s linear 260ms;
}

.mobile-panel.is-open,
body.menu-open .mobile-panel {
  transform: translateX(0);
  visibility: visible;
  pointer-events: auto;
  opacity: 1;
  transition:
    transform 260ms ease,
    opacity 180ms ease,
    visibility 0s;
}

.menu-toggle {
  position: relative;
  z-index: 100;
}

@media (prefers-reduced-motion: reduce) {
  .mobile-panel,
  .mobile-panel.is-open,
  body.menu-open .mobile-panel {
    transition: none;
  }
}


/* All-screen menu: original JS state hook */
body.nav-open .mobile-panel {
  transform: translateX(0);
  visibility: visible;
  pointer-events: auto;
  opacity: 1;
  transition:
    transform 260ms ease,
    opacity 180ms ease,
    visibility 0s;
}

/* All-screen off-canvas navigation — final corrected selector. */
.mobile-nav {
  display: block !important;
}

body.nav-open .mobile-nav,
.mobile-nav.is-open {
  visibility: visible;
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}

@media (min-width: 64rem) {
  .desktop-nav {
    display: none !important;
  }

  .menu-toggle {
    display: grid !important;
  }

  .mobile-nav {
    display: block !important;
  }
}


/* Dedicated section pages ---------------------------------------
   Reuse the homepage section designs unchanged; this only gives a
   single-section page enough vertical breathing room below the header. */
body:not(.home-page) #main-content > .stag-hunt,
body:not(.home-page) #main-content > .video-section,
body:not(.home-page) #main-content > .season {
  min-height: calc(100svh - var(--header-height));
}

/* The all-screen off-canvas navigation is the primary navigation. */
.mobile-nav__inner > a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.25em;
}


/* ================================================================
   MULTI-PAGE REFINEMENTS
   ================================================================ */

/* Remove current-page underline from the off-canvas navigation. */
.mobile-nav__inner > a[aria-current="page"] {
  text-decoration: none;
}

/* Video page uses a light page surface while preserving the existing
   dark video treatment itself. */
.video-page {
  background: var(--white);
  color: var(--black);
}

.video-page .site-header,
.video-page .site-footer {
  background: var(--white);
  color: var(--black);
}

.video-page .video-section {
  background: var(--white);
  color: var(--black);
}

/* Make sure landing copy is visible immediately on dedicated pages.
   Do not vertically pin headings to media bottoms. */
.section-page #main-content {
  display: block;
}

.section-page #main-content > .stag-hunt,
.section-page #main-content > .video-section,
.section-page #main-content > .season {
  min-height: auto;
  padding-top: clamp(3rem, 6vw, 5rem);
  padding-bottom: clamp(4rem, 8vw, 7rem);
}

/* Dedicated video page: heading first, then media, with controlled gap. */
.section-page .video-section {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}

.section-page .video-section__heading {
  align-self: start;
  margin: 0;
}

.section-page .video-placeholder {
  margin: 0;
}

/* Dedicated StagHunt page: keep copy high in the viewport. */
.section-page .stag-hunt {
  align-items: start;
}

.section-page .stag-hunt__content,
.section-page .stag-hunt__status {
  align-self: start;
}

/* Rally page: prevent over-stretching and keep the table close to its copy. */
.section-page .season {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
}

.section-page .section-heading {
  margin-bottom: 0;
}

/* Improve subpage width/readability on large screens without changing
   homepage section widths. */
@media (min-width: 64rem) {
  .section-page #main-content > .stag-hunt,
  .section-page #main-content > .video-section,
  .section-page #main-content > .season {
    width: min(100%, 90rem);
    margin-inline: auto;
  }

  .section-page .video-section {
    grid-template-columns: minmax(16rem, 0.72fr) minmax(0, 1.55fr);
  }

  .section-page .video-section__heading {
    position: static;
    padding-top: 0;
  }
}

/* Tablet and mobile: text always precedes the media. */
@media (max-width: 63.99rem) {
  .section-page .video-section {
    grid-template-columns: 1fr;
  }

  .section-page .video-section__heading {
    order: 1;
  }

  .section-page .video-placeholder {
    order: 2;
  }
}


/* Smoother all-screen off-canvas navigation. */
.mobile-nav {
  transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

.mobile-nav.is-open,
body.nav-open .mobile-nav {
  transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  .mobile-nav,
  .mobile-nav.is-open,
  body.nav-open .mobile-nav {
    transition: none;
  }
}


/* ================================================================
   TWO-PAGE NAVIGATION + TRANSITION
   ================================================================ */

html {
  scroll-behavior: smooth;
}

body.page-transition-ready {
  opacity: 1;
  transition: opacity 180ms ease;
}

body.page-transition-ready.page-leaving {
  opacity: 0;
}

#season,
#build,
#stag-hunt,
#video {
  scroll-margin-top: calc(var(--header-height) + 1.5rem);
}

/* Current-page nav items remain visually clean. */
.mobile-nav__inner > a[aria-current="page"] {
  text-decoration: none;
}

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

  body.page-transition-ready,
  body.page-transition-ready.page-leaving {
    opacity: 1;
    transition: none;
  }
}


/* ================================================================
   STABLE PAGE LOAD / MOTION-SAFE NAVIGATION
   ================================================================ */

/* Reserve scrollbar space even while the off-canvas menu locks scrolling.
   This prevents the whole layout shifting sideways when the menu closes. */
html {
  scrollbar-gutter: stable;
}

/* The page never translates or slides during document navigation.
   On JS-capable loads, content waits for the webfonts and then fades in. */
html.js body {
  opacity: 0;
}

html.js body.page-ready {
  opacity: 1;
  transition: opacity 220ms ease-out;
}

html.js body.page-leaving,
body.page-transition-ready.page-leaving {
  opacity: 0;
  transition: opacity 170ms ease-in;
}

/* The old ready class should not introduce its own competing transition. */
body.page-transition-ready {
  opacity: inherit;
  transition: none;
}

/* Keep the viewport width stable while the navigation panel is open. */
body.nav-open {
  overflow: hidden;
}

/* No transforms are used for whole-page loading or leaving states. */
html.js body,
html.js body.page-ready,
html.js body.page-leaving {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html.js body,
  html.js body.page-ready,
  html.js body.page-leaving,
  body.page-transition-ready,
  body.page-transition-ready.page-leaving {
    opacity: 1;
    transition: none;
  }
}


/* The footer Funding link is an in-page jump to section 01 now, so its arrow
   nudges right like the other internal links rather than up-right, which the
   shared .site-footer a:hover span rule applies for the off-site ones. */
.site-footer a[href$="#stag-hunt"]:hover span {
  transform: translateX(0.1875rem);
}

/* ================================================================
   KAS.COFFEE EMBED (index.html section 01)
   ================================================================ */

/* The widget hardcodes max-width:420px on its own container, so widening the
   iframe only pads empty space around an identically sized card. It is instead
   rendered at its native 420px and scaled up as a whole, which leaves its
   internal proportions untouched - the same card, larger.

   Scale is capped by the column it sits in: .stag-hunt gives the content
   column roughly 510px at 64rem and 738px at 90rem, so 1.15 and 1.35 are the
   largest steps that fit without the wrapper clipping the card. Below 64rem no
   transform applies at all - the widget is fluid under its own 420px cap. */
.donate-embed {
  --w: 420;   /* the widget's own design width, not ours to choose */
  /* 470 is the height of the full card INCLUDING the donations list, which is
     where supporters comments appear. It was 340, roughly the height of the
     compact card, and because this wrapper is overflow: hidden the list was
     simply clipped off the bottom - the amount showed, the comments did not.
     Do not reduce it without checking the list is still visible.
     script.js raises this further if kas.coffee posts its own height. */
  --h: 470;
  --s: 1;     /* display scale */
  position: relative;
  width: min(100%, calc(var(--w) * var(--s) * 1px));
  height: calc(var(--h) * var(--s) * 1px);
  overflow: hidden;
}

/* Below 64rem there is no room to scale, and the widget is fluid under its own
   420px cap, so the frame simply fills the box and no transform is applied. */
.donate-embed iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
}

@media (min-width: 64rem) {
  .donate-embed {
    --s: 1.15;
  }

  /* Pinned to its native size, then scaled from the top-left so the scaled box
     lines up exactly with the height reserved on the wrapper above. */
  .donate-embed iframe {
    width: calc(var(--w) * 1px);
    height: calc(var(--h) * 1px);
    transform: scale(var(--s));
    transform-origin: top left;
  }
}

@media (min-width: 90rem) {
  .donate-embed {
    --s: 1.35;
  }
}

/* The global :focus-visible rule near the top of this file paints a teal ring
   with a 0.25rem offset. Browsers focus an iframe when you click into its
   content, so that ring appears around the whole widget and reads as a stray
   teal border rather than a focus cue. The widget draws its own focus states
   for its own controls, so suppress ours on this element only. */
.donate-embed iframe:focus-visible {
  outline: none;
}

