/* ============================================================
   CREATED IN LA — main.css
   Order: 1) tokens  2) fonts/global  3) layout  4) utilities
          5) component blocks (section markers)  6) theme overrides
   Every design value flows from a :root token. Math is wrapped in calc().
   ============================================================ */

/* ------------------------------------------------------------
   1. DESIGN TOKENS (:root)
   ------------------------------------------------------------ */
:root {
  /* Site fundamentals — unitless */
  --site--viewport-min: 20;
  --site--viewport-max: 80;
  --site--column-count: 12;

  /* Max widths */
  --max-width--main: 80rem;
  --max-width--medium: 60rem;
  --max-width--small: 40rem;

  /* Site layout — fluid margin / gutter (1rem → 3rem, 1rem → 2rem) */
  --site--margin: clamp(
    1 * 1rem,
    ((1 - ((3 - 1) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((3 - 1) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    3 * 1rem
  );
  --site--gutter: clamp(
    1 * 1rem,
    ((1 - ((2 - 1) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((2 - 1) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    2 * 1rem
  );

  /* Spacing */
  --space--section-main: clamp(
    4 * 1rem,
    ((4 - ((8 - 4) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((8 - 4) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    8 * 1rem
  );

  /* Typography — families */
  --text--font-title: "Bahnschrift", "Arial Narrow", system-ui, sans-serif;
  --text--font-body: "Montserrat", system-ui, -apple-system, sans-serif;

  /* Title axis defaults (variable font). Bold + condensed now; italic later. */
  --text--title-wght: 700;
  --text--title-wdth: 75;

  /* Typography — body sizes (14→16 / 16→18 / 18→20) */
  --text--size-small: clamp(
    0.875 * 1rem,
    ((0.875 - ((1 - 0.875) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((1 - 0.875) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    1 * 1rem
  );
  --text--size-main: clamp(
    1 * 1rem,
    ((1 - ((1.125 - 1) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((1.125 - 1) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    1.125 * 1rem
  );
  --text--size-large: clamp(
    1.125 * 1rem,
    ((1.125 - ((1.25 - 1.125) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((1.25 - 1.125) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    1.25 * 1rem
  );

  /* Typography — heading / display sizes */
  --text--size-eyebrow: clamp(
    0.75 * 1rem,
    ((0.75 - ((0.9375 - 0.75) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((0.9375 - 0.75) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    0.9375 * 1rem
  );
  --text--size-h2: clamp(
    2 * 1rem,
    ((2 - ((3.5 - 2) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((3.5 - 2) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    3.5 * 1rem
  );
  --text--size-display: clamp(
    2.5 * 1rem,
    ((2.5 - ((5.5 - 2.5) / (var(--site--viewport-max) - var(--site--viewport-min)) * var(--site--viewport-min))) * 1rem
      + ((5.5 - 2.5) / (var(--site--viewport-max) - var(--site--viewport-min))) * 100vw),
    5.5 * 1rem
  );

  /* Line heights / spacing */
  --text--lh-display: 1.02;
  --text--ls-display: 0.01em;

  /* Colour */
  --color--bg: #000000;
  --color--text: #f8f8f8;
  --color--text-muted: rgba(248, 248, 248, 0.7);
  --color--accent: #00ffcf;
  --color--accent-text: #000000;

  /* Radius */
  --radius--small: 0.25rem;

  /* Green-tag slant — ONE calculation for every slanted green container.
     It's a horizontal offset in `em`, so it resolves against each tag's own
     font-size; because a tag's height also scales with font-size, the resulting
     slant ANGLE is consistent no matter the tag's width (a fixed % of width
     would make wide tags look much steeper than narrow ones). Tune here only.
     Set to MATCH THE LOGO: the "CREATED IN LA" box is a parallelogram whose
     edges run 8.67 across over 48.16 tall → atan(8.67/48.16) ≈ 10.2° (offset:
     height ≈ 0.18). On the ~1.28em-tall tags that lands at ≈0.23em. */
  --tag--slant: 0.23em;

  /* Component-local */
  --nav--height: 5.5rem;
  /* Nav-logo height. The nav now fades in only AFTER you scroll past the hero
     (the hero carries its own large logo), so this stays compact — no scroll
     shrink anymore. */
  --nav-logo-h: 4rem;
}

/* ------------------------------------------------------------
   2. FONTS + GLOBAL ELEMENT STYLES
   ------------------------------------------------------------ */
@font-face {
  font-family: "Bahnschrift";
  src: url("../assets/fonts/Bahnschrift%20Regular.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 50% 100%;
  font-style: normal;
  font-display: swap;
}
/* NOTE: there is no true Bahnschrift italic — the supplied bahnschrift.woff2 is
   the upright Regular (italicAngle 0, no slant axis). So we deliberately do NOT
   register an italic @font-face: with only a roman face present, `font-style:
   italic` makes the browser synthesize an oblique (a real slant). If a genuine
   italic file is supplied later, register it here as font-style: italic. */
@font-face {
  font-family: "Montserrat";
  src: url("../assets/fonts/Montserrat-VariableFont_wght.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Bahnschrift has no true italic — explicitly allow the synthesized oblique */
.nav_link,
.button,
.showreel_line,
.dayone_title {
  font-synthesis: style;
}

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

html,
body {
  margin: 0;
  padding: 0;
  /* Paint the root canvas black too (not just body): the last section's bottom
     can land on a fractional pixel, and at that sub-pixel seam a transparent
     <html> lets the browser's default (light) canvas show through as a thin line
     at the very bottom on mobile. Also covers iOS overscroll/rubber-band. */
  background-color: var(--color--bg);
}

body {
  background-color: var(--color--bg);
  color: var(--color--text);
  font-family: var(--text--font-body);
  font-size: var(--text--size-main);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* ============================================================
   RESPONSIVE BLOCKER — covers everything on viewports < 992px
   (the responsive build isn't ready yet). Desktop: never shown.
   ============================================================ */
.responsive-blocker {
  display: none;
}
@media (max-width: 991px) {
  .responsive-blocker {
    position: fixed;
    inset: 0;
    z-index: 99999; /* above the nav, mobile menu, everything */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    background-color: var(--color--bg);
    text-align: center;
  }
  .responsive-blocker_inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(1.5rem, 5vw, 2.5rem);
    max-width: 30rem;
  }
  .responsive-blocker_logo {
    width: clamp(12rem, 60vw, 18rem);
    height: auto;
  }
  .responsive-blocker_text {
    margin: 0;
    color: var(--color--text);
    font-family: var(--text--font-title);
    font-weight: var(--text--title-wght);
    font-stretch: 75%;
    font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    line-height: 1.2;
    font-size: clamp(1.3rem, 5vw, 1.9rem);
  }
  /* the body can't scroll behind the blocker */
  body:has(.responsive-blocker) {
    overflow: hidden;
  }
}

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--text--font-title);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  line-height: var(--text--lh-display);
  letter-spacing: var(--text--ls-display);
}

p {
  margin: 0;
}

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

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

/* Title elements are hidden until JS reveals them (prevents FOUC) */
[data-hero-title],
[data-split="heading"] {
  visibility: hidden;
}

/* ------------------------------------------------------------
   3. LAYOUT / STRUCTURE
   ------------------------------------------------------------ */
.page-wrap {
  position: relative;
  width: 100%;
  /* Safety net against horizontal overflow (which would push fixed UI like the
     mobile toggle off into an off-screen strip). `clip` — not `hidden` — so it
     doesn't create a scroll container (keeps position:sticky pins working) and
     doesn't clip the fixed nav (no transformed ancestor at rest). */
  overflow-x: clip;
}

.main-wrap {
  display: block;
  width: 100%;
}

.padding-global {
  padding-left: var(--site--margin);
  padding-right: var(--site--margin);
}

.container-large {
  width: 100%;
  max-width: var(--max-width--main);
  margin: 0 auto;
}
.container-medium {
  width: 100%;
  max-width: var(--max-width--medium);
  margin: 0 auto;
}
.container-small {
  width: 100%;
  max-width: var(--max-width--small);
  margin: 0 auto;
}

/* ------------------------------------------------------------
   4. UTILITIES
   ------------------------------------------------------------ */
.text-style-display {
  font-family: var(--text--font-title);
  font-size: var(--text--size-display);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  line-height: var(--text--lh-display);
  letter-spacing: var(--text--ls-display);
}

.text-style-eyebrow {
  font-family: var(--text--font-body);
  font-size: var(--text--size-eyebrow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  line-height: 1.2;
}

.text-style-small {
  font-size: var(--text--size-small);
}

.text-color-accent {
  color: var(--color--accent);
}

/* keep a phrase from breaking across lines (e.g. "the making" in the H1) */
.u-nowrap {
  white-space: nowrap;
}

/* responsive <br>: no break on desktop (one line), break on tablet+mobile */
.u-br-resp {
  display: none;
}
@media (max-width: 991px) {
  .u-br-resp {
    display: inline;
  }
}

/* Button — left "flag" / forked-tongue notch, right edge a straight slant
   (top further right than bottom) */
.button {
  --button--bg: transparent;
  --button--color: var(--color--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* tighter padding; extra top to optically centre the condensed caps */
  padding: 0.22em 1.05em 0.08em 1.15em;
  font-family: var(--text--font-title);
  font-size: clamp(1.95rem, 2.75vw, 2.75rem);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-style: italic;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--button--color);
  background-color: var(--button--bg);
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--tag--slant)) 100%, 0 100%, 17% 50%);
}
.button-accent {
  --button--bg: var(--color--accent);
  --button--color: var(--color--accent-text);
}

/* Character-stagger hover — each char rolls up to a duplicate (Osmo).
   Targets the [data-button-animate-chars] wrapper; split into spans in JS. */
[data-button-animate-chars] {
  position: relative;
  display: inline-block;
  overflow: hidden;
  line-height: 1.3;
  white-space: nowrap;
  vertical-align: bottom;
  padding-right: 0.18em; /* room for the italic overhang (overflow:hidden clips the slant) */
}
[data-button-animate-chars] span {
  display: inline-block;
  position: relative;
  text-shadow: 0 1.3em currentColor;
  transform: translateY(0) rotate(0.001deg);
  transition: transform 0.55s cubic-bezier(0.625, 0.05, 0, 1);
}
.nav_link:hover [data-button-animate-chars] span,
.button:hover [data-button-animate-chars] span {
  transform: translateY(-1.3em) rotate(0.001deg);
}

/* ============================================================
   HERO  —  section_hero
   Used on: Home
   Scroll-driven curtain reveal. A ~300vh track scrolls past a
   sticky 100vh stage; layers are driven by data-* hooks in JS.
   ============================================================ */
.section_hero {
  position: relative;
  background-color: var(--color--bg);
}

.hero_track {
  position: relative;
  height: 300vh; /* fallback; JS sets the real height from the strip width */
}

.hero_stage {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100%;
  overflow: hidden;
}

/* Layered media + content all fill the stage */
.hero_video,
.hero_overlay,
.hero_vignette,
.hero_cover,
.hero_content {
  position: absolute;
  inset: 0;
}

/* ============================================================
   TIMELINE  —  section_timeline
   Used on: Home
   Pinned horizontal timeline (saapro-style). A tall track scrolls past a
   sticky 100vh stage: a fixed centred square image swaps (scroll-driven
   Walk-wipe, no drag) while a dashed ruler + alternating year/copy blocks
   travel sideways. All motion is driven in JS (initTimelineScroll, ≥992px).
   Horizontal geometry flows from the two vars below:
     --timeline-seg   = viewport-x distance between consecutive stops
     --timeline-count = number of stops (= images = gallery slides)
   ============================================================ */
.section_timeline {
  position: relative;
  background-color: var(--color--bg);

  --timeline-count: 6; /* ruler stops (1921 sits AT centre when the strip arrives,
                          so the travel is count-1 = 5 segments) */
  --timeline-seg: clamp(30rem, 44vw, 50rem); /* horizontal gap per stop */
  --timeline-img: min(52vh, 40vw); /* centre square side — large; can kiss the nav */
  --timeline-img-y: 40%; /* vertical centre of the square */
  --timeline-ruler-y: 84%; /* ruler line, low on the stage — uses the empty bottom margin
                              and keeps the above-blocks clear of the image */
  /* Intro offset (square starts in the RIGHT column, then JS slides it x→0 to centre)
     is computed in initTimelineScroll from the square width + gutter, so the two-column
     start mirrors "Day One" instead of flinging the image to the viewport edge. */

  /* Dashed ruler tick pattern (thin, thick, thin, thick …). Opaque GREY so the
     wider/taller thick tick fully hides the thin tick it sits on (a translucent
     colour let the thin one show through → a visible double). */
  --tick-gap: 1.6rem; /* spacing between thin ticks */
  --tick-thin-w: 1.5px;
  --tick-thick-w: 2.5px;
  --tick-h-thin: 1.1rem;
  --tick-h-thick: 2rem;
  --tick-color: #6b6b6b;
}
.timeline_track {
  position: relative;
  height: 300vh; /* fallback; JS sets the real height from the strip width */
}
.timeline_stage {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background-color: var(--color--bg);
}

/* Centre square image — the swapping gallery (grid-stack + parallax inner,
   same mechanic as .walk_gallery, but scroll-driven). */
.timeline_media {
  position: absolute;
  z-index: 1;
  left: 50%;
  top: var(--timeline-img-y);
  transform: translate(-50%, -50%);
  width: var(--timeline-img);
  height: var(--timeline-img);
  border-radius: 0.75rem;
  overflow: hidden;
  isolation: isolate;
  background-color: #0a0a0a;
}
.timeline_slides {
  display: grid;
  grid-template-rows: 100%;
  grid-template-columns: 100%;
  place-items: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.timeline_slide {
  grid-area: 1 / 1 / -1 / -1;
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  opacity: 0;
  will-change: transform, opacity;
}
.timeline_slide.is--current {
  opacity: 1;
}
.timeline_slide-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  user-select: none;
}

/* Section title — intro state: sits on the LEFT, vertically centred on the square
   (which sits on the RIGHT). Reveals on pin (green marker); JS fades it out as the
   square slides to centre and the timeline fades in. */
.timeline_heading-wrap {
  position: absolute;
  z-index: 3;
  top: var(--timeline-img-y);
  /* container-large's LEFT edge — the same x every section title above sits on
     (site margin until the 80rem container caps, then centred). JS reads this
     rendered left edge to park the image on the container's RIGHT edge. */
  left: max(var(--site--margin), calc((100vw - var(--max-width--main)) / 2));
  transform: translateY(-50%);
  max-width: min(40rem, 46vw);
  text-align: left;
  pointer-events: none;
}
.timeline_heading {
  max-width: min(40rem, 46vw); /* fills the left column so it reads toward centre (Day-One two-col) */
  font-size: clamp(2.3rem, 4.5vw, 4.8rem);
  color: var(--color--text);
  text-align: left;
}

/* Travelling strip — full-stage box, translated left on scroll (JS). */
.timeline_strip {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(100vw + var(--timeline-seg) * (var(--timeline-count) - 1));
  will-change: transform;
}

/* Continuous dashed ruler: two stacked repeating gradients — a thin tick
   every --tick-gap, and a taller/wider thick tick every 2×--tick-gap that
   lands on every other thin tick → thin, thick, thin, thick. */
.timeline_ruler {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--timeline-ruler-y);
  height: var(--tick-h-thick);
  transform: translateY(-50%);
  background-repeat: no-repeat, no-repeat;
  background-position: 0 50%, 0 50%;
  background-size: 100% var(--tick-h-thin), 100% var(--tick-h-thick);
  background-image:
    repeating-linear-gradient(to right, var(--tick-color) 0 var(--tick-thin-w), transparent var(--tick-thin-w) var(--tick-gap)),
    repeating-linear-gradient(to right, var(--tick-color) 0 var(--tick-thick-w), transparent var(--tick-thick-w) calc(var(--tick-gap) * 2));
}
/* Tail gradient — sits INSIDE the strip over the ruler band, from just past the
   2026 stop to the strip's end: the ticks dissolve to black before SEPT's stop,
   so nothing ever shows under the SEPT block. Paints above the ruler (DOM order)
   and below the year/copy items. Travels with the strip → no extra JS. */
.timeline_ruler-fade {
  position: absolute;
  top: var(--timeline-ruler-y);
  left: calc(50vw + var(--timeline-seg) * 4 + 4rem); /* just past 2026 (i=5 → 4 segs in) */
  right: 0;
  height: calc(var(--tick-h-thick) * 2);
  transform: translateY(-50%);
  background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, var(--color--bg) 40%);
  pointer-events: none;
}

/* Year/copy blocks — centred on their stop (50vw + seg×--i), alternating
   above/below the ruler line. autoAlpha is the only thing JS animates, so
   the centring transform below is preserved. */
.timeline_item {
  position: absolute;
  /* --i is 1-based; the -1 puts 1921 (i=1) AT screen-centre when the strip is at
     x:0 — it appears together with the centred image as the intro completes,
     instead of a full empty segment of scroll before the first stop. */
  left: calc(50vw + var(--timeline-seg) * (var(--i) - 1));
  top: var(--timeline-ruler-y);
  width: max-content;
  max-width: min(44rem, 48vw);
  display: flex;
  align-items: flex-start;
  gap: clamp(0.8rem, 1.4vw, 1.5rem);
  opacity: 0.62; /* non-centred stops sit back; JS brightens the active one */
  transition: opacity 0.4s ease;
}
.timeline_item.is-active {
  opacity: 1;
}
/* Final stop: every earlier block fades out with the ruler (2026 would otherwise
   linger beside SEPT). Toggled by setActiveItem; the base opacity transition
   animates it, and it reverses when scrolling back. Placed after .is-active so
   it wins on source order. */
.timeline_item.is-passed {
  opacity: 0;
}
/* Left-aligned to the centre image: at each centred stop the block's left edge
   sits under the image's left edge (shift left by half the square from the stop
   centre) and the text reads out to the right — frees the space under the image
   so it can sit larger + higher without the copy hugging the ruler. */
.timeline_item.is-above {
  transform: translate(calc(var(--timeline-img) / -2), -100%);
  padding-bottom: clamp(1.2rem, 2.6vh, 2.4rem);
}
.timeline_item.is-below {
  transform: translate(calc(var(--timeline-img) / -2), 0);
  padding-top: clamp(1.2rem, 2.6vh, 2.4rem);
}
/* Sept (final stop): sits AT the ruler level — vertically centred on the line
   (the ticks have faded out here, so it reads as the timeline's end point). */
.timeline_item.is-level {
  transform: translate(calc(var(--timeline-img) / -2), -50%);
}
.timeline_year {
  flex: 0 0 auto;
  font-family: var(--text--font-title);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  font-size: clamp(2rem, 3.4vw, 3.4rem);
  line-height: 1;
  letter-spacing: var(--text--ls-display);
  text-transform: uppercase; /* "Sept" → "SEPT"; digits unaffected */
  color: var(--color--text);
}
.timeline_copy {
  max-width: 34ch; /* ~2rem tighter; verified the longest copy (2026) stays ≤3 lines */
  font-family: var(--text--font-body);
  font-size: clamp(1.15rem, 1.4vw, 1.55rem); /* larger than body — reads well on the timeline */
  font-weight: 500;
  line-height: 1.35;
  color: var(--color--text);
  text-align: left;
  text-wrap: pretty;
}

/* End title — overlaps the centre image on the final stop. "Now, it's" (white)
   + "our turn." (green tag, same slant as the other green tags). Hidden at rest;
   initTimelineScroll fades + rises it in as the last stop centres. */
.timeline_end {
  position: absolute;
  z-index: 4;
  left: 50%;
  top: var(--timeline-img-y); /* centred on the square */
  transform: translate(-50%, -50%);
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.25em;
  white-space: nowrap; /* one line — allowed to overflow the square (like The Biggest) */
  font-size: clamp(2.4rem, 4.8vw, 4.8rem);
  font-style: italic;
  font-synthesis: style;
  color: var(--color--text);
  text-shadow: 0 0.05em 0.5em rgba(0, 0, 0, 0.55); /* legibility over the photo */
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}
.timeline_end-tag {
  display: inline-block;
  padding: 0.18em 0.5em 0.04em 0.42em;
  background-color: var(--color--accent);
  color: var(--color--accent-text);
  font-style: italic;
  clip-path: polygon(var(--tag--slant) 0, 100% 0, calc(100% - var(--tag--slant)) 100%, 0 100%);
  text-shadow: none;
}

/* Highlight marker reveal — coloured bar over each line, scales away on reveal */
[data-highlight-marker-reveal] {
  visibility: hidden;
}
[data-highlight-marker-reveal] .highlight-marker-line {
  display: inline-block !important;
  width: auto;
  padding-right: 0.18em; /* room for the italic overhang (line is overflow:hidden) */
}
.highlight-marker-bar {
  position: absolute;
  inset: -0.07em 0;
  z-index: 2;
  pointer-events: none;
}
/* Every <video> gets a no-op filter. A playing video can otherwise be promoted
   to a hardware OVERLAY plane that paints ABOVE all web content and ignores
   z-index — that's what was hiding the fixed mobile menu toggle after it faded
   in ("flash then vanish"). Any filter forces the video to texture-composite
   instead, so normal z-index/stacking applies and the z600 menu stays on top.
   filter is independent of the `opacity` GSAP animates on the curtains. */
video {
  filter: opacity(0.999);
}

/* Videos — cover the stage */
.hero_video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Curtains sit above the Showreel layers (bg 0 / overlay 1 / content 2) */
.hero_curtain {
  z-index: 4;
}
.hero_loop {
  z-index: 5;
  opacity: 1; /* opaque immediately so the Showreel never flashes through before the reveal */
}

/* Overlays */
.hero_overlay {
  z-index: 6;
  background-color: rgba(0, 0, 0, 0.2);
  pointer-events: none;
}
.hero_vignette {
  z-index: 6;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.85) 0%,
    rgba(0, 0, 0, 0.4) 22%,
    rgba(0, 0, 0, 0) 48%
  );
  pointer-events: none;
}
/* Anti-flash cover — opaque black at load (hides any un-decoded video frame
   and the font-load wait), then fades out as the intro begins. */
.hero_cover {
  z-index: 7;
  background-color: #000;
  pointer-events: none;
}

/* Content */
.hero_content {
  z-index: 8;
  display: flex;
  flex-direction: column;
  align-items: stretch; /* keep padding-global/container full width for stable line splitting */
  justify-content: center;
  pointer-events: none;
  /* No top nav at load → lift the centred block up ~5rem (half the padding). The
     absolute "Presented by" is unaffected (it anchors to this padding box's bottom),
     and no transform is used so it doesn't become a containing block. Tune here. */
  padding-bottom: 10rem;
}
.hero_content-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1.25rem;
}
.hero_eyebrow {
  /* same size as the "Presented by" label at the bottom of the hero */
  font-size: clamp(1.05rem, 1.8vw, 1.5rem);
  letter-spacing: 0.26em;
  color: #fff; /* pure white (the token's #f8f8f8 read grey on the curtain) */
  /* sit ABOVE the H1's ::before radial scrim — the positioned title paints over
     static siblings, so without this lift the scrim's upper falloff darkens the
     date to grey (same fix as .hero_logo / .hero_apply). */
  position: relative;
  z-index: 2;
  /* hidden state for the rightward unmask; JS animates clip-path open */
  clip-path: inset(0 100% 0 0);
}
.hero_title {
  /* sized so "THE PREMIERE CREATOR EVENT" holds on one line (2 lines total) */
  font-size: clamp(2.6rem, 6.7vw, 5.7rem);
  width: 100%;
  max-width: none;
  white-space: nowrap; /* deterministic 2 lines (break only at the <br>) */
  color: var(--color--text);
  /* own stacking context so the scrim ::before sits cleanly behind the text */
  position: relative;
  isolation: isolate;
  /* NO drop-shadow: the SplitText line masks (`mask:"lines"` → per-line
     overflow:clip wrappers) clipped the parent's drop-shadow into hard-edged
     rectangles behind each line. The bold white type reads fine on the curtain
     without it (the hero_overlay wash + vignette already aid legibility). If a
     shadow is ever wanted again, it must be re-clip-margined per line, not a
     bare filter here. */
}
/* Soft radial scrim BEHIND the H1 — darkens the video/curtains directly behind
   the headline for legibility, then feathers to fully transparent. It rides on
   the title's ::before, so it inherits the H1's autoAlpha fade + yPercent rise
   on scroll (the scrim leaves exactly when the headline does — no lingering
   blob over the showreel). Unlike a parent drop-shadow, a ::before is NOT
   inside the per-line SplitText mask wrappers, so it never gets clipped into
   hard rectangles. Many gradient stops + a moderate peak opacity keep the
   falloff smooth (no banding rings / black dots / hard edges). */
.hero_title::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 142%;
  height: 300%;
  transform: translate(-50%, -50%);
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    ellipse 50% 46% at 50% 50%,
    rgba(0, 0, 0, 0.6) 0%,
    rgba(0, 0, 0, 0.56) 16%,
    rgba(0, 0, 0, 0.47) 33%,
    rgba(0, 0, 0, 0.34) 49%,
    rgba(0, 0, 0, 0.21) 64%,
    rgba(0, 0, 0, 0.11) 78%,
    rgba(0, 0, 0, 0.04) 90%,
    rgba(0, 0, 0, 0) 100%
  );
}

/* Main logo — centred at the TOP of the stage as the page enters (absolute, so
   it's lifted out of the centred date/H1/apply block). Fades in with the intro
   and lifts away on scroll exactly as before (buildHeroIntro / initHeroScroll
   animate its autoAlpha + yPercent — the translateX(-50%) centring is preserved). */
.hero_logo {
  pointer-events: auto; /* hero_content is pointer-events:none — re-enable the link */
  position: absolute;
  top: clamp(1.75rem, 4.5vh, 3.5rem);
  left: 50%;
  transform: translateX(-50%);
  width: clamp(13rem, 20vw, 18rem);
  opacity: 0; /* fades in with the intro */
  z-index: 2;
}
.hero_logo-img {
  display: block;
  width: 100%;
  height: auto;
}

/* See-through "Apply" flag below the H1. The green parallelogram + knocked-out
   letters are an inline SVG built by buildHeroApplyFlag() (so it uses the real
   web font + does the per-char hover roll). */
.hero_apply {
  pointer-events: auto;
  display: inline-block;
  width: clamp(5.75rem, 9.3vw, 8rem); /* ~nav-button size */
  margin-top: clamp(0.6rem, 1.6vh, 1.3rem);
  cursor: pointer;
  opacity: 0; /* fades in with the intro */
  position: relative; /* sit above the H1 + its scrim (see .hero_logo) */
  z-index: 2;
}
.hero_apply-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.hero_apply-shape {
  fill: #fff; /* white flag (knockout letters show the video through) */
}
.hero_apply-type {
  font-family: var(--text--font-title);
  font-style: italic;
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  letter-spacing: 0.02em;
}

/* Presented by Disney */
.hero_presented {
  z-index: 8;
  position: absolute;
  left: 50%;
  bottom: clamp(1.5rem, 4vh, 3rem);
  transform: translateX(-50%);
  display: flex;
  flex-direction: row; /* one line, including the logo */
  align-items: center;
  gap: 0.7em;
  white-space: nowrap;
  opacity: 0; /* fades in with nav */
  pointer-events: none;
}
.hero_presented-label {
  font-size: clamp(1.05rem, 1.8vw, 1.5rem); /* ~2.5x the prior eyebrow size */
  color: var(--color--text-muted);
}
.hero_presented-logo {
  height: clamp(3.9rem, 6.9vw, 5.4rem); /* +50% */
  width: auto;
}
/* end: HERO */

/* ============================================================
   NAV  —  .nav
   Used on: Home (persistent / global)
   ============================================================ */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding-top: clamp(0.5rem, 1.2vh, 1rem); /* breathing room from the top edge */
  opacity: 0; /* fades in during hero intro */
}
.nav_inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav--height);
}
.nav_left {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  align-self: flex-start; /* anchor the logo to the top; the big logo grows downward, never clipped at the page edge */
}
.nav_logo-img {
  height: var(--nav-logo-h); /* large on tall screens; JS shrinks the height on scroll, top-left anchored */
  width: auto;
  transform-origin: top left;
}
.nav_menu {
  display: flex;
  align-items: center;
  gap: clamp(0.875rem, 1.75vw, 1.75rem); /* ~30% tighter between the text links */
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Apply button — compact: ~half the text size and tighter padding vs the
   default hero .button. Left padding kept fuller so the type clears the
   forked-tongue notch (clip-path inset on the left edge). */
.nav_menu .button {
  margin-left: clamp(0.5rem, 1vw, 1rem);
  /* grown ~2/3 from clamp(1.05rem,1.45vw,1.45rem); top/bottom padding trimmed so it
     reads THINNER despite the larger type (horizontal padding scales with the font). */
  font-size: clamp(1.75rem, 2.42vw, 2.42rem);
  padding: 0.06em 0.6em 0.02em 0.95em;
  --tag--slant: 0.25em; /* nudge the right-edge slant to the logo's ~10.2° (it ran ~9.5°) */
}
/* Hide the text links (About / Details / Why) on desktop — only the Apply
   button remains in the bar. (All five still live in the ≤991px drop-down.) */
.nav_menu li:has(.nav_link) {
  display: none;
}
.nav_link {
  font-family: var(--text--font-title);
  font-size: clamp(1.75rem, 2.4vw, 2.4rem);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-style: italic;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color--text);
}
/* end: NAV */

/* ============================================================
   MOBILE MENU  —  .m-menu   (drop-down nav, ≤991px only)
   Toggle morphs hamburger → cross; the black panel drops from the
   top while the page-wrap is pushed down in sync. Hidden ≥992px.
   ============================================================ */
.m-menu {
  display: none;
}
.m-menu_toggle {
  pointer-events: auto;
  position: fixed;
  top: clamp(1rem, 2.8vw, 1.8rem);
  right: clamp(1.1rem, 4.2vw, 2.2rem);
  z-index: 2; /* above the panel within .m-menu */
  width: var(--m-toggle-size, 3.25rem);
  height: var(--m-toggle-size, 3.25rem);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  cursor: pointer;
  /* Starts hidden; the hero intro fades it in together with the nav logo
     (added to buildHeroIntro's fadeInGroup). Mirrors `.nav { opacity: 0 }`. */
  opacity: 0;
  transform: translateZ(0);
}
.m-menu_bar {
  position: absolute;
  width: var(--m-bar-w, 2.3rem);
  height: 2.5px;
  background: var(--color--text);
  transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1);
  transform: translateY(-0.34rem) rotate(0.001deg);
}
.m-menu_bar:nth-child(2) {
  transform: translateY(0.34rem) rotate(0.001deg);
}
[data-menu-status="open"] .m-menu_bar {
  transform: translateY(0) rotate(45deg);
}
[data-menu-status="open"] .m-menu_bar:nth-child(2) {
  transform: translateY(0) rotate(-45deg);
}
.m-menu_panel {
  pointer-events: none;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  height: 100dvh;
  background: #000;
  transform: translateY(-100%);
  transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1);
  display: flex;
  align-items: center;
  justify-content: center;
}
[data-menu-status="open"] .m-menu_panel {
  pointer-events: auto;
  transform: translateY(0);
}
.m-menu_nav {
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* Eyebrow above the links — same Montserrat eyebrow style as the hero
   ("September 17–18" / "Presented by"), rises in just before the first link. */
.m-menu_eyebrow {
  overflow: clip; /* mask for the rise */
  margin: 0 0 clamp(1.2rem, 3.5vh, 2.4rem);
  color: var(--color--text-muted);
  font-size: clamp(0.95rem, 1.8vw, 1.25rem);
  letter-spacing: 0.26em;
}
.m-menu_eyebrow span {
  display: block;
  transform: translateY(120%);
  transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1);
}
[data-menu-status="open"] .m-menu_eyebrow span {
  transform: translateY(0%);
}
.m-menu_list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.35rem, 1.6vh, 1rem);
  text-align: center;
}
.m-menu_item {
  /* Mask the vertical line-rise, but DON'T clip the horizontal italic ink
     overhang on the right (the synthesized oblique paints past the glyph box).
     `overflow:clip` on both axes was cutting the last letter of each link. */
  overflow-x: visible;
  overflow-y: clip;
}
.m-menu_link {
  display: block;
  font-family: var(--text--font-title);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-style: italic;
  font-synthesis: style;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.05;
  font-size: clamp(2.75rem, 11vw, 5rem);
  color: var(--color--text);
  text-decoration: none;
  padding: 0 0.45em; /* synthesized-italic overhang clearance (fallback if a
                        browser ignores the split overflow on .m-menu_item) */
}
.m-menu_link span {
  display: block;
  transform: translateY(120%);
  transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1);
}
[data-menu-status="open"] .m-menu_link span {
  transform: translateY(0%);
}
/* eyebrow rises first, then the links with a wider stagger + longer initial
   delay (snappy, undelayed retract on close) */
[data-menu-status="open"] .m-menu_eyebrow span { transition-delay: 0.08s; }
[data-menu-status="open"] .m-menu_item:nth-child(1) .m-menu_link span { transition-delay: 0.22s; }
[data-menu-status="open"] .m-menu_item:nth-child(2) .m-menu_link span { transition-delay: 0.34s; }
[data-menu-status="open"] .m-menu_item:nth-child(3) .m-menu_link span { transition-delay: 0.46s; }
[data-menu-status="open"] .m-menu_item:nth-child(4) .m-menu_link span { transition-delay: 0.58s; }
[data-menu-status="open"] .m-menu_item:nth-child(5) .m-menu_link span { transition-delay: 0.70s; }
/* end: MOBILE MENU */

/* ============================================================
   RESPONSIVE  —  tablet + mobile (≤991px)
   Nav scrolls with the page (no fixed shrink), desktop links give way
   to the drop-down menu, and "Presented by" sits under the H1.
   ============================================================ */
@media (max-width: 991px) {
  /* Show the drop-down menu component */
  .m-menu {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 600;
    pointer-events: none; /* only the toggle + open panel catch input */
    /* NB: deliberately NO transform here. A transform on this fixed ancestor
       makes the position:fixed toggle/panel its descendants' containing block,
       which on mobile triggers the classic "fixed inside transformed ancestor
       flickers / disappears" bug. The video-overlay problem is handled on the
       <video> side (filter: opacity) instead — see the global video rule. */
  }

  /* Nav: loads at a fixed size and stays in view ("follows you down the page")
     while scrolling — fixed on tablet AND mobile portrait (it just doesn't
     shrink; the shrink is desktop-only). */
  .nav {
    position: fixed;
    transition: opacity 0.3s ease;
    padding-top: 0;
  }
  /* Vertically centre the logo against the toggle: the nav bar height is built
     from the toggle's own top offset + size, so their centres always line up
     (toggle centre = top + size/2 = barHeight/2 = centred-logo centre). */
  .nav_inner {
    height: calc(2 * clamp(1rem, 2.8vw, 1.8rem) + 3.25rem);
  }
  .nav_left {
    align-self: center;
  }
  .nav_logo-img {
    height: clamp(2.75rem, 7.5vw, 3.5rem); /* phone; fixed, overrides the --nav-logo-h shrink */
  }
  .nav_menu {
    display: none; /* replaced by the drop-down menu */
  }

  /* "Presented by Disney" drops into flow, directly under the H1 */
  .hero_presented {
    position: static;
    left: auto;
    bottom: auto;
    transform: none;
    margin: clamp(1rem, 3vh, 2rem) auto 0;
  }

  /* Page push + nav fade while the menu is open */
  .page-wrap {
    transition: transform 0.6s cubic-bezier(0.625, 0.05, 0, 1);
  }
  [data-menu-open] .page-wrap {
    transform: translateY(100vh);
    transform: translateY(100dvh);
  }
  [data-menu-open] .nav {
    opacity: 0 !important;
    pointer-events: none;
  }
  [data-menu-open] body {
    overflow: hidden;
  }
}

/* --- Tablet (768–991px): bigger logo + cross, and a larger hero --- */
@media (min-width: 768px) and (max-width: 991px) {
  .nav_logo-img {
    height: clamp(4rem, 7vw, 5.5rem);
  }
  /* match the bar height to the larger tablet toggle (4rem) so the centred
     logo stays aligned with it */
  .nav_inner {
    height: calc(2 * clamp(1rem, 2.8vw, 1.8rem) + 4rem);
  }
  .m-menu {
    --m-toggle-size: 4rem;
    --m-bar-w: 3rem;
  }
  /* Scale the whole hero up — it reads small at this width */
  .hero_eyebrow {
    font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  }
  .hero_title {
    font-size: clamp(4rem, 8.2vw, 6.4rem);
  }
  .hero_presented-label {
    font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  }
  .hero_presented-logo {
    height: clamp(5rem, 9vw, 6.8rem);
  }
  /* NB: the tablet .showreel_line size lives in a late block (after the base
     showreel CSS) so it wins on source order. */
}

/* --- Mobile portrait: bigger H1 over 3–4 lines; stacked "Presented by" --- */
@media (max-width: 767px) and (orientation: portrait) {
  .hero_title {
    white-space: normal; /* wrap into more lines (the <br> still hard-breaks the two sentences) */
    font-size: clamp(3.1rem, 13vw, 5rem);
    line-height: 1.02;
  }
  .hero_presented {
    flex-direction: column;
    gap: 0.5em;
  }
  /* NB: the Day One/Two heading portrait rules live in a SECOND portrait block
     at the end of the file — they must come after the base .dayone_title CSS. */
}

/* ============================================================
   SHOWREEL  —  lives inside the hero stage (Section 1)
   Used on: Home
   Full-bleed background video + dark overlay + centred lines, sitting
   behind the curtains and revealed when they part. Layers: bg 0 /
   overlay 1 / content 2 (the hero curtains/overlays sit above at 4+).
   ============================================================ */
.showreel_bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.showreel_video {
  position: absolute;
  top: -10%;
  left: 0;
  width: 100%;
  height: 120%; /* extra height keeps edges covered */
  object-fit: cover;
}
.showreel_overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: rgba(0, 0, 0, 0.65); /* halfway between the original 0.43 and the too-dark 0.86 */
  pointer-events: none;
}
.showreel_content {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Blackout over the whole showreel — JS ramps opacity 0→1 as Section 3 scrolls in */
.showreel_blackout {
  position: absolute;
  inset: 0;
  z-index: 3;
  background-color: #000;
  opacity: 0;
  pointer-events: none;
}
.showreel_inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* uneven gaps: line 1 sits tight to the green box, then a bigger gap before
     line 3 ("Made for creators.") — set per-line below, not a uniform gap */
  gap: 0;
  text-align: center;
}
.showreel_line {
  color: #fff;
  font-style: italic;
  font-size: clamp(2.5rem, 5.7vw, 5rem); /* larger per client */
  line-height: 1; /* tight — trims the descender space that read as a gap */
  white-space: nowrap; /* each line is single-line — keeps SplitText to one line */
}
/* line 1 → line 2: small gap */
.showreel_line:nth-child(2) {
  margin-top: 0.08em;
}
/* line 2 → line 3 (green tag): match the line-1→2 gap so it doesn't sit too low */
.showreel_line:nth-child(3) {
  margin-top: 0.08em;
}
/* line 2 — green box; near-vertical edges (only a couple of px of slant) */
.showreel_tag {
  background-color: var(--color--accent);
  color: var(--color--accent-text);
  padding: 0.2em 0.85em 0.06em; /* more horizontal breathing room */
  clip-path: polygon(var(--tag--slant) 0, 100% 0, calc(100% - var(--tag--slant)) 100%, 0 100%);
}
/* "the Oscars." — inline on desktop (the whole tag is ONE line), its own block
   line ≤991 (the tag is TWO lines). A real <br> can't be used: GSAP SplitText
   (which the marker reveal runs over this h2) hard-splits on a <br> NODE even
   when it's display:none, so the desktop tag wrongly became two lines. Toggling
   inline↔block is read from layout, so SplitText sees one line ≥992 / two ≤991,
   and it survives the marker's autoSplit revert+re-split on resize with no JS. */
.showreel_tag-break {
  display: inline;
}
@media (max-width: 991px) {
  .showreel_tag-break {
    display: block;
  }
}
/* end: SHOWREEL */

/* ============================================================
   OVERVIEW  —  section_overview
   Used on: Home (after the showreel reveal)
   "Event Overview" H2 (marker reveal) + five short paragraphs (left).
   Right: two SQUARE images — a large one, and a smaller one below-right
   that overlaps its corner and parallaxes. Sizes flow from --ov-img-*.
   ============================================================ */
.section_overview {
  position: relative;
  z-index: 1; /* sits above the hero so it can overlap the background video */
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);

  --ov-img-lg: clamp(20rem, 30vw, 30rem); /* large square side */
  --ov-img-sm: clamp(12rem, 18vw, 18rem); /* small square side */
}
/* Desktop: pull up to overlap (and slide fully over) the background-video section.
   JS (data-overlap-reveal) animates a clip-path inset from 5vw+radius to 0.
   min-height keeps the black section covering the whole viewport so the showreel
   behind it never peeks out as the overview scrolls on. */
@media (min-width: 992px) {
  .section_overview {
    margin-top: -85vh;
    min-height: 100vh;
  }
}
.overview_inner {
  display: flex;
  align-items: center; /* text block sits vertically centred on the image cluster */
  gap: clamp(2rem, 5vw, 6rem);
}
.overview_text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.overview_title {
  width: fit-content; /* contain the marker pull-away bar to the text, not the column */
  max-width: 100%;
  color: var(--color--text);
  font-size: var(--text--size-h2);
  margin-bottom: clamp(1.6rem, 3vw, 2.6rem);
}
.overview_copy {
  display: flex;
  flex-direction: column;
}
.overview_p {
  color: var(--color--text);
  font-size: clamp(1.2rem, 1.65vw, 1.7rem);
  line-height: 1.4;
  max-width: 34rem;
  text-wrap: pretty; /* avoid 1–2 word orphan lines as the paragraph reflows on resize */
}
.overview_p + .overview_p {
  margin-top: 1.4em;
}
/* Right column — two squares, right-aligned: the small square's right edge sets
   the outer line; the large square sits a step left of it (margin-right), and
   the small one pulls UP to overlap the large square's bottom-right corner.
   Both are in-flow, so the section's height always includes the overhang. */
.overview_media {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.overview_img-main {
  width: var(--ov-img-lg);
  aspect-ratio: 1;
  z-index: 1;
  overflow: hidden;
  border-radius: 1rem;
  margin-right: calc(var(--ov-img-sm) * 0.35); /* the small square extends past this edge */
}
.overview_img-main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Image reveal — green mask over media that swipes away on scroll (JS-driven) */
[data-image-reveal] {
  position: relative;
}
.image-reveal-mask {
  position: absolute;
  inset: 0;
  z-index: 6;
  background-color: var(--color--accent);
  transform-origin: right center;
  pointer-events: none;
}
/* Smaller square — below-right, pulled up to overlap the large square's
   bottom-right corner. Keeps the parallax drift (data-parallax on the wrap). */
.overview_img-parallax {
  position: relative;
  z-index: 2; /* covers the large square's corner */
  width: var(--ov-img-sm);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 1rem;
  margin-top: calc(var(--ov-img-sm) * -0.32); /* the overlap up into the large square */
}
.overview_img-parallax img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* end: OVERVIEW */

/* ============================================================
   BANNER CROSS MARQUEE  —  section_banner
   Used on: Home (after the overview). Two full-bleed marquee bands (Osmo
   "Marquee with Scroll Direction") crossing at the centre. Front band =
   accent green, drifts left; back band = white, angled the other way,
   drifts right, opacity scrubbed 0.5→0.9→hold→0.5 by initBannerMarquee.
   Bands are 120vw so their rotated ends always sit off-page.
   ============================================================ */
.section_banner {
  position: relative;
  background-color: var(--color--bg);
  /* enough height that the crossed bands (±2.5deg over 120vw ≈ ±2.6vw rise)
     never clip: two band-heights + the rise + breathing room */
  height: clamp(16rem, 36vh, 24rem);
  overflow: hidden;
}
.banner_band {
  position: absolute;
  top: 50%;
  left: -10vw;
  width: 120vw;
  overflow: hidden; /* each band masks its own marquee */
}
.banner_band.is-front {
  z-index: 2;
  background-color: var(--color--accent);
  transform: translateY(-50%) rotate(-2.5deg);
}
.banner_band.is-back {
  z-index: 1;
  background-color: #fff;
  transform: translateY(-50%) rotate(2.5deg);
  opacity: 0.3; /* rest state; initBannerMarquee scrubs 0.3→0.9→0.3 on scroll */
}
/* Osmo recipe structure: scroll wrap (scroll-shift target) > collection (loop
   target, duplicated by JS) > items */
.banner_scroll {
  will-change: transform;
  width: 100%;
  display: flex;
  position: relative;
}
.banner_collection {
  will-change: transform;
  display: flex;
  position: relative;
}
.banner_item {
  display: flex;
  align-items: center;
  justify-content: flex-start;
}
/* h2-scale brand type — black on both band colours */
.banner_text {
  margin: 0 1.1em 0 0; /* the gap between repeating phrases */
  padding: 0.32em 0 0.18em; /* sets the band height; extra top optically centres the caps */
  white-space: nowrap;
  color: var(--color--accent-text);
  font-family: var(--text--font-title);
  font-size: var(--text--size-h2);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-style: italic;
  font-synthesis: style;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: 0.02em;
}
/* end: BANNER CROSS MARQUEE */

/* ============================================================
   DAY ONE  —  section_dayone
   Used on: Home (after the overview, before the timeline)
   Title (green tag + white heading, marker reveal) above a two-column
   row: looping video left, line-by-line revealing text right.
   ============================================================ */
.section_dayone {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
/* Whole heading highlighted green — a single slanted box (black text on accent),
   same pattern as the Showreel green line. The marker reveal runs over it: the
   green bar swipes away and the black text rises into the box. */
.dayone_title {
  width: fit-content; /* box hugs the text, not the page width */
  max-width: 100%;
  background-color: var(--color--accent);
  color: var(--color--accent-text);
  font-style: italic;
  font-size: clamp(2.4rem, 5vw, 4.6rem);
  line-height: 1;
  white-space: nowrap; /* one line → a single clean parallelogram */
  padding: 0.2em 0.6em 0.06em;
  clip-path: polygon(var(--tag--slant) 0, 100% 0, calc(100% - var(--tag--slant)) 100%, 0 100%);
  margin-bottom: clamp(2rem, 5vw, 4rem);
}
.dayone_columns {
  display: flex;
  align-items: center;
  gap: clamp(2rem, 5vw, 5rem);
}
/* Day Two — swap the video/text sides (text left, video right) */
.dayone_columns.is-reversed {
  flex-direction: row-reverse;
}
.dayone_video {
  flex: 1 1 52%;
  aspect-ratio: 4 / 3;
  border-radius: 0.5rem;
  overflow: hidden;
}
.dayone_video video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.dayone_text {
  flex: 1 1 48%;
  display: flex;
  flex-direction: column;
}
.dayone_p {
  color: var(--color--text);
  font-size: clamp(1.2rem, 1.65vw, 1.7rem);
  line-height: 1.4;
  text-wrap: pretty; /* avoids single-word last lines on resize */
}
.dayone_p + .dayone_p {
  margin-top: 1.4em;
}

/* Day One / Day Two reveal stack — Day One (is-over) pulls up to reveal Day Two */
.day-stack {
  position: relative;
  height: 200vh; /* scroll distance for the pull-up reveal */
}
.day-stack_pin {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}
.day-stack_layer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.day-stack_layer.is-over {
  z-index: 2; /* on top, slides up on scroll */
}
.day-stack_layer:not(.is-over) {
  z-index: 1; /* behind, revealed */
}
/* end: DAY ONE */

/* ============================================================
   WHY ATTEND  —  section_why
   Used on: Home (after the timeline). Two columns (like Day 1): title
   (marker swipe) + a stacked list of branded-bullet items on the left;
   a portrait image on the right that parallaxes inside its mask (same
   treatment as Meet Our Host).
   ============================================================ */
.section_why {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
.why_inner {
  display: flex;
  align-items: stretch; /* the image mask runs the full text-column height */
  gap: clamp(2rem, 5vw, 5.5rem);
}
.why_text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.why_title {
  width: fit-content; /* contain the marker pull-away bar to the text */
  max-width: 100%;
  color: var(--color--text);
  font-size: clamp(2.4rem, 5vw, 4.6rem);
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.why_list {
  display: flex;
  flex-direction: column;
  gap: clamp(2.5rem, 5vw, 4rem);
}
.why_item {
  display: grid;
  grid-template-columns: auto 1fr; /* icon | (title + paragraph) */
  column-gap: clamp(0.8rem, 1.4vw, 1.2rem);
  align-items: start;
}
.why_icon {
  width: clamp(1.4rem, 1.9vw, 1.9rem);
  height: auto;
  margin-top: 0.2em; /* nudge to sit on the mini-title cap line */
}
.why_item-title {
  margin: 0 0 0.55em;
  color: var(--color--text);
  font-family: var(--text--font-body);
  font-weight: 700;
  font-size: clamp(1.3rem, 1.85vw, 1.9rem);
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
.why_p {
  margin: 0;
  color: var(--color--text);
  font-size: clamp(1.2rem, 1.65vw, 1.7rem);
  line-height: 1.4;
  text-wrap: pretty;
}
/* the mask — full text-column height (flex stretch), fixed width; the image
   parallaxes within it (mirrors .host_media / .host_img). No aspect-ratio on
   desktop — the stretched height IS the crop; mobile re-adds one (stacked). */
.why_media {
  position: relative;
  flex: 0 0 auto;
  width: clamp(18rem, 34vw, 30rem);
  overflow: hidden;
  border-radius: 1rem;
}
.why_img {
  position: absolute;
  left: 0;
  top: -15%;
  width: 100%;
  height: 130%; /* taller than the mask → 15% slack each side for the parallax drift */
  object-fit: cover;
}
/* end: WHY ATTEND */

/* ============================================================
   MEET OUR HOST  —  section_host
   Used on: Home (after Why Attend). Image (left) parallaxes inside an
   overflow:hidden mask (the <img> is taller than its mask + is the parallax
   target); text (right) = title marker swipe + masked-rise paragraphs + signature.
   ============================================================ */
.section_host {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
.host_inner {
  display: flex;
  align-items: stretch; /* the image mask runs the full text-column height */
  gap: clamp(2rem, 5vw, 5.5rem);
}
/* the mask — full text-column height (flex stretch), fixed width; the image
   parallaxes within it. No aspect-ratio on desktop — the stretched height IS
   the crop; mobile re-adds one (stacked layout has no stretch height). */
.host_media {
  position: relative;
  flex: 0 0 auto;
  width: clamp(18rem, 34vw, 30rem);
  overflow: hidden;
  border-radius: 1rem;
}
.host_img {
  position: absolute;
  left: 0;
  top: -15%;
  width: 100%;
  height: 130%; /* taller than the mask → 15% slack each side for the parallax drift */
  object-fit: cover;
}
.host_text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.host_title {
  width: fit-content;
  max-width: 100%;
  color: var(--color--text);
  font-size: clamp(2.4rem, 5vw, 4.6rem);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
.host_p {
  color: var(--color--text);
  font-size: clamp(1.2rem, 1.65vw, 1.7rem);
  line-height: 1.4;
  text-wrap: pretty;
}
.host_p + .host_p {
  margin-top: 1.2em;
}
.host_signature {
  width: clamp(11rem, 18vw, 16rem);
  height: auto;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}
/* end: MEET OUR HOST */

/* ============================================================
   WALK WHERE WALT DID  —  section_walk
   Osmo "Parallax Image Gallery with Thumbnails" (Observer-driven wipe + inner
   parallax) inside a rounded overflow:hidden mask. Dark scrim over the slides;
   centred title + paragraph in front; thumbnail nav at the bottom. Radius 1rem
   to match Meet Our Host (.host_media).
   ============================================================ */
.section_walk {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
.walk_gallery {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 1rem; /* same radius as Meet Our Host's mask */
  overflow: hidden; /* the mask */
  isolation: isolate; /* own stacking context for scrim/content/nav */
  cursor: grab;
}
.walk_gallery:active {
  cursor: grabbing;
}
/* the slideshow list — grid stack: all slides share one cell */
.walk_slides {
  display: grid;
  grid-template-rows: 100%;
  grid-template-columns: 100%;
  place-items: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.walk_slide {
  grid-area: 1 / 1 / -1 / -1;
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}
.walk_slide.is--current {
  opacity: 1;
  pointer-events: auto;
}
.walk_slide-img {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
  user-select: none;
}
/* dark scrim so the centred text reads over any frame */
.walk_overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(
    ellipse at center,
    rgba(0, 0, 0, 0.62) 0%,
    rgba(0, 0, 0, 0.42) 55%,
    rgba(0, 0, 0, 0.32) 100%
  );
}
.walk_content {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35em;
  text-align: center;
  padding: var(--site--margin);
  pointer-events: none; /* let drag/swipe fall through to the gallery */
}
.walk_title {
  margin: 0;
  color: var(--color--text);
}
.walk_p {
  margin: 0;
  max-width: 42ch;
  color: var(--color--text);
  font-size: clamp(1.05rem, 1.4vw, 1.4rem);
  line-height: 1.45;
  opacity: 0.92;
  text-wrap: pretty;
}
/* thumbnail nav */
.walk_nav {
  position: absolute;
  z-index: 3;
  bottom: clamp(1rem, 2.2vw, 2rem);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  max-width: 92%;
  pointer-events: none; /* wrapper ignores; thumbs re-enable below */
}
.walk_thumb {
  position: relative;
  aspect-ratio: 1.5;
  width: clamp(3.4rem, 6vw, 6rem);
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 0.3125rem;
  cursor: pointer;
  pointer-events: auto;
  transition: border-color 0.2s ease;
}
.walk_thumb:hover {
  border-color: rgba(255, 255, 255, 0.4);
}
.walk_thumb.is--current {
  border-color: #fff;
}
.walk_thumb-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* end: WALK WHERE WALT DID */

/* ============================================================
   SPEAKERS  —  section_speakers   (Osmo "Basic GSAP Slider — Watch CSS")
   Draggable carousel: slides-per-view + gap come from the --slider-* vars below
   (JS reads them). Slider is flush to the LEFT site margin and bleeds off the
   right viewport edge (last card peeks). Prev/Next are right-aligned.
   ============================================================ */
.section_speakers {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
  overflow: hidden; /* clip the right-bleeding cards → no horizontal scroll */
}
.speakers_title {
  width: fit-content; /* contain the marker pull-away bar to the text */
  max-width: 100%;
  color: var(--color--text);
  font-size: clamp(2.4rem, 5vw, 4.6rem);
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}

/* Slider shell — left padding = site margin; no right padding so cards run to
   the viewport edge. JS reads these custom properties off [data-gsap-slider-init]. */
.speakers_slider {
  --slider-status: on; /* on/off */
  --slider-spv: 3.3; /* slides per view (3 + a peek of the 4th) */
  --slider-gap: 1.5rem;
  position: relative;
  padding-left: var(--site--margin);
}
.speakers_collection {
  width: 100%;
}
.speakers_list {
  display: flex;
  user-select: none;
  -webkit-user-select: none;
  will-change: transform;
  touch-action: pan-y;
  backface-visibility: hidden;
}
.speakers_item {
  width: calc(((100% - 1px) - (var(--slider-spv) - 1) * var(--slider-gap)) / var(--slider-spv));
  margin-right: var(--slider-gap);
  flex: none;
}
.speakers_item:last-child {
  margin-right: 0;
}
/* grab/grabbing cursors while dragging */
.speakers_list[data-gsap-slider-list-status="grab"] {
  cursor: grab;
}
.speakers_list[data-gsap-slider-list-status="grabbing"] {
  cursor: grabbing;
}

/* Card */
.speaker_card-media {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5; /* portrait crop — the real headshot will fill this mask */
  overflow: hidden; /* the mask */
  border-radius: 1.25rem;
  background-color: #2c2c2c;
}
.speaker_card-placeholder {
  position: absolute;
  inset: 0;
  background-color: #9a9a9a; /* flat grey stand-in until headshots arrive */
}
.speaker_card-name {
  display: flex;
  align-items: center;
  gap: 0.5em;
  margin: clamp(0.9rem, 1.4vw, 1.3rem) 0 0.4em;
  color: var(--color--text);
  font-family: var(--text--font-title);
  font-weight: var(--text--title-wght);
  font-style: italic;
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1;
  font-size: clamp(1.45rem, 2vw, 2rem);
}
.speaker_arrow {
  flex: 0 0 auto;
  width: 1.05em; /* branded bullet point.svg — already green (#77f9d0) */
  height: auto;
}
.speaker_card-bio {
  margin: 0;
  max-width: 30ch;
  color: var(--color--text);
  font-size: clamp(1rem, 1.2vw, 1.2rem);
  line-height: 1.4;
  opacity: 0.8;
  text-wrap: pretty;
}

/* Controls — RIGHT aligned (reference centres them) */
.speakers_controls {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: clamp(1.8rem, 3vw, 2.8rem);
  padding-right: var(--site--margin);
}
[data-gsap-slider-status="not-active"] .speakers_controls {
  display: none; /* hide when everything fits (no sliding needed) */
}
.speakers_control {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(2.8rem, 3.4vw, 3.4rem);
  height: clamp(2.8rem, 3.4vw, 3.4rem);
  padding: 0;
  color: var(--color--text);
  background-color: transparent;
  border: 1px solid rgba(248, 248, 248, 0.3);
  border-radius: 50%;
  cursor: pointer;
  transition: color 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
}
.speakers_control svg {
  width: 42%;
  height: auto;
}
.speakers_control:hover {
  color: var(--color--accent-text);
  background-color: var(--color--accent);
  border-color: var(--color--accent);
}
[data-gsap-slider-control-status="not-active"] {
  opacity: 0.2;
  pointer-events: none;
}
/* end: SPEAKERS */

/* ============================================================
   SPONSORS  —  section_sponsors
   Centred: title (marker swipe) + big Disney logo + a row of 4 linked logos.
   ============================================================ */
.section_sponsors {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
.sponsors_inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.sponsors_title {
  color: var(--color--text);
  font-size: var(--text--size-h2);
  margin: 0 auto;
}
.sponsors_main {
  margin-top: clamp(2.5rem, 5vw, 4.5rem);
}
.sponsors_main img {
  display: block;
  width: clamp(11rem, 20vw, 18rem);
  height: auto;
}
.sponsors_logos {
  list-style: none;
  margin: clamp(2.5rem, 5vw, 4.5rem) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(2rem, 5vw, 4.5rem);
}
.sponsors_logo img {
  display: block;
  width: auto;
  height: clamp(2.1rem, 3.2vw, 3.1rem); /* normalise the row by height */
  opacity: 0.92;
  transition: opacity 0.3s ease;
}
.sponsors_logo a:hover img {
  opacity: 1;
}
/* Once the four logos can no longer sit on one line (~620px), lay them out as a
   clean 2×2 grid instead of an uneven wrap. */
@media (max-width: 640px) {
  .sponsors_logos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    justify-items: center;
    align-items: center;
    gap: clamp(2rem, 7vw, 3rem) clamp(2rem, 8vw, 3.5rem);
  }
}
/* end: SPONSORS */

/* ============================================================
   FAQ  —  section_faq   (Osmo accordion, data-anm-*)
   Branded-bullet chevron + question + a +/- icon; answers reveal on open.
   ============================================================ */
.section_faq {
  position: relative;
  background-color: var(--color--bg);
  padding-top: var(--space--section-main);
  padding-bottom: var(--space--section-main);
}
.faq_title {
  width: fit-content;
  max-width: 100%;
  margin: 0 auto clamp(2.5rem, 5vw, 4.5rem);
  color: var(--color--text);
  font-size: clamp(2.4rem, 5vw, 4.6rem);
  text-align: center;
}
.faq_list {
  max-width: 60rem;
  margin: 0 auto;
}
.faq_item {
  border-bottom: 1px solid rgba(248, 248, 248, 0.16);
}
.faq_item:first-child {
  border-top: 1px solid rgba(248, 248, 248, 0.16);
}
.faq_trigger {
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 1.4vw, 1.2rem);
  width: 100%;
  padding: clamp(1.1rem, 1.8vw, 1.6rem) 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  color: var(--color--text);
}
.faq_bullet {
  flex: 0 0 auto;
  width: clamp(1.3rem, 1.8vw, 1.8rem);
  height: auto;
}
.faq_question {
  flex: 1 1 auto;
  font-family: var(--text--font-title);
  font-weight: var(--text--title-wght);
  font-stretch: 75%;
  font-variation-settings: "wght" var(--text--title-wght), "wdth" var(--text--title-wdth);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1.15;
  font-size: clamp(1.45rem, 2.2vw, 2.2rem);
}
.faq_icon {
  flex: 0 0 auto;
  width: clamp(1.1rem, 1.5vw, 1.4rem);
  height: auto;
  color: var(--color--accent); /* green +/- */
}
.faq_content {
  overflow: hidden; /* JS animates height from 0 */
}
.faq_answer {
  margin: 0;
  /* indent under the question (clear the bullet column) */
  padding: 0 0 clamp(1.1rem, 1.8vw, 1.6rem) calc(clamp(1.3rem, 1.8vw, 1.8rem) + clamp(0.8rem, 1.4vw, 1.2rem));
  max-width: 46rem;
  color: var(--color--text);
  font-size: clamp(1.1rem, 1.5vw, 1.55rem);
  line-height: 1.5;
  text-wrap: pretty;
}
/* end: FAQ */

/* ============================================================
   FOOTER  —  section_footer
   Big "Apply Now" parallelogram tag-button (char-stagger like the nav) over a
   green glow that expands on scroll + drifts in a small upright circle, masked.
   ============================================================ */
.section_footer {
  position: relative;
  overflow: hidden; /* mask: the 130vw glow can't widen the page */
  background-color: var(--color--bg);
  min-height: clamp(40rem, 80vh, 60rem);
  display: flex;
  flex-direction: column;
}
.footer_glow-wrap {
  position: absolute;
  inset: 0;
  overflow: hidden; /* the glow's own mask container */
  pointer-events: none;
  z-index: 0;
}
.footer_glow {
  position: absolute;
  /* min 1100px, otherwise 130vw — so it ALWAYS exceeds the viewport (full-bleed,
     much of the ellipse sits off-page either side). Centred via left:50% +
     negative margin so transform stays free for GSAP. */
  width: max(1100px, 130vw);
  margin-left: calc(max(1100px, 130vw) / -2);
  left: 50%;
  bottom: -14vh; /* reaches past the page bottom so the glow touches the bottom edge */
  aspect-ratio: 2 / 1; /* roughly the old image's shape — the scaleY tween reads the same */
  /* Brand "CREATED Gradient" (#037561 → #024C3F → #000000), as a true radial
     rising from bottom-centre and dissolving into the black footer — deliberately
     far subtler than the old glow image. Tune the stop percentages to taste. */
  background: radial-gradient(
    ellipse 55% 85% at 50% 100%,
    #037561 0%,
    #024c3f 38%,
    rgba(2, 76, 63, 0) 75%
  );
  transform-origin: 50% 100%; /* scale grows from the bottom-centre */
  will-change: transform;
}
.footer_main {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space--section-main) var(--site--margin);
}
/* Big parallelogram tag-button (overrides the nav .button notch/size) */
.footer_apply {
  /* larger text, same overall button size → trimmed padding (top, bottom AND sides) */
  padding: 0.12em 0.8em 0.04em;
  font-size: clamp(3rem, 7.2vw, 6rem);
  /* slant tuned to this button's height (line-height 1.3 makes it tall;
     offset = height·0.18 ≈ logo's 10.2°) */
  --tag--slant: 0.27em;
  clip-path: polygon(var(--tag--slant) 0, 100% 0, calc(100% - var(--tag--slant)) 100%, 0 100%); /* shared slant */
}
.footer_legal-wrap {
  position: relative;
  z-index: 1;
  padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
.footer_legal {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  color: #fff; /* white — the subtle brand gradient is dark, black text no longer reads */
  font-size: clamp(0.95rem, 1.1vw, 1.1rem);
  font-weight: 600;
}
.footer_legal-left {
  margin: 0;
  opacity: 0.75;
}
.footer_legal-right {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1rem, 2vw, 2rem);
}
.footer_legal-right a {
  color: #fff;
  text-decoration: none;
  opacity: 0.75;
  transition: opacity 0.3s ease;
}
.footer_legal-right a:hover {
  opacity: 1;
}
/* end: FOOTER */

/* ------------------------------------------------------------
   6. RESPONSIVE
   ------------------------------------------------------------ */
/* Tablet (768–991px): the Showreel reads small at this width. Placed AFTER the
   base .showreel_line so it wins on source order. */
@media (min-width: 768px) and (max-width: 991px) {
  /* H2 display headings — scale up noticeably for tablet (sections 2/4/5) */
  .showreel_line {
    font-size: clamp(4.6rem, 8.6vw, 7.2rem);
  }
  .dayone_title {
    font-size: clamp(3.9rem, 7.2vw, 5.9rem);
  }
  /* Body copy reads small relative to the tablet screen (the base clamps sit at
     their floor until ~1160px). Scale it up — bigger sections is fine. */
  .overview_p,
  .dayone_p {
    font-size: clamp(1.6rem, 2.7vw, 2.1rem);
  }
  /* Day One / Day Two: the video column stretches to the height of the text
     beside it (instead of a fixed 4:3 box) so the two columns match. */
  .dayone_columns {
    align-items: stretch;
  }
  .dayone_video {
    aspect-ratio: auto; /* let flex stretch govern the height */
  }
  /* (Overview squares scale via their vw clamps — no tablet overrides needed) */
}

/* Tablet + mobile (≤991px): the Day One / Day Two pull-up pin is desktop-only
   (initDayStack ≥992px). Flatten the 100vh stack so the two days flow
   vertically, each with its own section padding — no broken 100vh gaps.
   (Placed AFTER the .day-stack base rules so it wins on source order.) */
@media (max-width: 991px) {
  /* Speakers slider: fewer cards per view on tablet */
  .speakers_slider {
    --slider-spv: 2.2;
  }

  /* --- Day One / Day Two: flatten the 100vh pull-up pin (initDayStack ≥992px) --- */
  .day-stack {
    height: auto;
  }
  .day-stack_pin {
    position: static;
    height: auto;
    overflow: visible;
  }
  .day-stack_layer {
    position: relative;
    inset: auto;
    display: block;
  }

  /* --- Timeline: plain vertical stack on tablet + mobile (the pinned
         horizontal experience is initTimelineScroll ≥992px only). Lean
         placeholder — the real mobile design is a later pass. The ruler is
         hidden and each stop becomes a stacked image + year/copy block. --- */
  .timeline_track {
    height: auto;
  }
  .timeline_stage {
    position: static;
    height: auto;
    overflow: visible;
    padding: var(--space--section-main) var(--site--margin);
  }
  .timeline_media {
    position: relative;
    left: auto;
    top: auto;
    transform: none;
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    margin: 0 auto clamp(2rem, 6vw, 3rem);
  }
  /* mobile: no wipe controller runs, so just show the first image */
  .timeline_slide {
    opacity: 0;
  }
  .timeline_slide.is--current {
    opacity: 1;
  }
  .timeline_heading-wrap {
    position: static;
    width: 100%;
    transform: none;
    padding: 0 0 clamp(1.5rem, 5vw, 2.5rem);
  }
  /* the end-title overlay is a desktop-only device (fades in on the pinned last
     stop); the flattened stack shows the "our turn." copy inline instead */
  .timeline_end {
    display: none;
  }
  .timeline_ruler,
  .timeline_ruler-fade {
    display: none;
  }
  .timeline_strip {
    position: static;
    width: 100%;
    transform: none !important;
    display: flex;
    flex-direction: column;
    row-gap: clamp(2rem, 6vw, var(--space--section-main));
  }
  .timeline_item {
    position: static;
    left: auto;
    top: auto;
    transform: none !important;
    max-width: none;
    opacity: 1;
    padding: 0;
    flex-direction: row;
  }
}

@media screen and (max-width: 767px) {
  /* JS desktop matchMedia (≥768px) doesn't run, so sections flow vertically.
     NOTE: mobile still needs a dedicated design pass — this keeps it readable. */

  /* --- Section 1: the curtain hero runs on mobile too (initHeroScroll ≥1px),
         so the stage stays sticky and the curtain/loop videos stay visible —
         no flattening here. (.hero_presented handled by the ≤991px block.) --- */

  /* (Timeline flatten lives in the ≤991px block above) */

  /* Speakers slider: ~1 card + a peek on phones */
  .speakers_slider {
    --slider-spv: 1.15;
    --slider-gap: 1rem;
  }

  /* --- Why Attend: stack the columns (text, then the parallax image) --- */
  .why_inner {
    flex-direction: column;
    align-items: stretch;
    gap: clamp(2rem, 6vw, 3rem);
  }
  .why_media {
    width: 100%;
    aspect-ratio: 4 / 5; /* stacked column has no stretch height — the ratio provides it */
  }

  /* --- Meet Our Host: image stacks above the text --- */
  .host_inner {
    flex-direction: column;
    align-items: stretch;
    gap: clamp(2rem, 6vw, 3rem);
  }
  .host_media {
    width: 100%;
    aspect-ratio: 4 / 5; /* stacked column has no stretch height — the ratio provides it */
  }

  /* --- Overview: stack text, then the squares (which keep their own
         overlap geometry, scaled to the phone width via the vars) --- */
  .overview_inner {
    flex-direction: column;
    align-items: stretch;
    gap: 2rem;
  }
  .overview_p {
    max-width: none;
  }
  .section_overview {
    --ov-img-lg: min(78vw, 24rem);
    --ov-img-sm: min(46vw, 15rem);
  }
  .overview_media {
    flex: none;
    align-self: center;
  }

  /* --- Day One + Day Two: stack video over text. The is-reversed override
         (row-reverse, used for Day Two's alternating layout on tablet/desktop)
         must be neutralised here or it out-specifies the column rule. --- */
  .dayone_columns,
  .dayone_columns.is-reversed {
    flex-direction: column;
    align-items: stretch;
    gap: 2rem;
  }
}

/* Mobile portrait — Day One / Day Two green-box headings. Placed here (after the
   base .dayone_title rules) so it wins on source order. Font nudged down so the
   whole box ("DAY 1 THE PREMIERE") stays on one line on narrow phones. */
@media (max-width: 767px) and (orientation: portrait) {
  .dayone_title {
    font-size: clamp(1.8rem, 7.4vw, 2.5rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero_loop {
    opacity: 1;
  }
  .hero_cover {
    opacity: 0;
  }
  .hero_eyebrow {
    clip-path: none;
  }
  [data-hero-title],
  [data-split="heading"],
  [data-highlight-marker-reveal] {
    visibility: visible;
  }
}
