@font-face {
  font-family: Windsor;
  src: url("assets/fonts/WindsorProRg.TTF") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: Windsor;
  src: url("assets/fonts/WindsorProBold.TTF") format("truetype");
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: WindsorHeavy;
  src: url("assets/fonts/WindsorProUltHv.TTF") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: WindsorCondensed;
  src: url("assets/fonts/WindsorProXBoldCn.TTF") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: WindsorElongated;
  src: url("assets/fonts/WindsorProElongated.TTF") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: FoodThink;
  src: url("assets/fonts/Food-Think-BF6a1d4958178d8.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: HelveticaRounded;
  src: url("assets/fonts/Helvetica Rounded LT Bold Condensed.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: HelveticaRounded;
  src: url("assets/fonts/Helvetica Rounded LT Bold Condensed Oblique.ttf") format("truetype");
  font-style: italic;
  font-display: swap;
}

:root {
  --paper: #edeade;
  --cream: #f6f1e7;
  --ink: #26211c;
  --brick: #cb5023;
  --mustard: #ccb833;
  --sky: #6fa9ba;
  --display: FoodThink, WindsorHeavy, Georgia, serif;
  --body: HelveticaRounded, "Arial Narrow", sans-serif;
  --slide-ratio: 2572 / 858;

  /* Print softness, the photocopied-one-sheet feel. One fixed radius for the
     whole deck, not a fixed ratio: a photocopier smears by the same amount
     whatever size the type is set at, so scaling the blur with font-size (the
     old 0.0085em) made the big display heads read as genuinely out of focus
     while the small copy stayed crisp — a 9.8x spread in actual radius across
     the deck. Matched to the How-far-can-a-person-go head, 0.0287vw at 3.38vw
     type. In vw so it tracks the viewport. Set to 0 for crisp type. */
  --print-blur: 0.0287vw;
}

* {
  box-sizing: border-box;
}

html {
  background: #080808;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  overflow-x: hidden;
  color: var(--ink);
  background: #080808;
  font-family: var(--body);
  font-synthesis: none;
}

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

a {
  color: inherit;
}

::selection {
  color: var(--cream);
  background: var(--brick);
}

.skip-link {
  position: fixed;
  z-index: 100;
  top: -80px;
  left: 16px;
  padding: 12px 18px;
  color: var(--ink);
  background: var(--cream);
  transition: top 0.2s;
}

.skip-link:focus {
  top: 16px;
}

.site-header {
  position: fixed;
  z-index: 50;
  top: 0;
  left: 0;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  width: 100%;
  padding: clamp(10px, 1.1vw, 28px);
  color: var(--cream);
  font-family: Arial, sans-serif;
  font-size: clamp(7px, 0.48vw, 12px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  mix-blend-mode: difference;
  pointer-events: none;
}

.site-header a {
  text-decoration: none;
  pointer-events: auto;
}

.mini-mark {
  grid-column: 2;
  font-family: WindsorCondensed, serif;
  font-size: clamp(11px, 0.78vw, 20px);
  letter-spacing: -0.02em;
}

/* --- Slide index dropdown ------------------------------------------------ */

.deck-menu {
  position: fixed;
  z-index: 52;
  top: 0;
  left: clamp(10px, 1.1vw, 28px);
  padding: clamp(10px, 1.1vw, 28px) 0;
  font-family: Arial, sans-serif;
  font-size: clamp(7px, 0.48vw, 12px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.deck-menu summary {
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.4em 0.2em;
  color: var(--cream);
  cursor: pointer;
  list-style: none;
  mix-blend-mode: difference;
}

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

.deck-menu summary:hover .deck-menu-current,
.deck-menu[open] summary .deck-menu-current {
  border-bottom-color: currentColor;
}

.deck-menu-current {
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s ease;
}

/* Caret. Rotates when the panel is open. */
.deck-menu summary i {
  width: 0;
  height: 0;
  border-top: 0.36em solid currentColor;
  border-right: 0.3em solid transparent;
  border-left: 0.3em solid transparent;
  transition: transform 0.25s ease;
}

.deck-menu[open] summary i {
  transform: rotate(180deg);
}

.deck-menu-list {
  position: absolute;
  top: 100%;
  left: 0;
  max-height: min(64vh, 620px);
  margin: 0;
  padding: 0.5em 0;
  overflow-y: auto;
  color: var(--cream);
  background: rgb(12 11 10 / 96%);
  border: 1px solid rgb(246 241 231 / 14%);
  border-radius: 2px;
  box-shadow: 0 1.4vw 3vw rgb(0 0 0 / 55%);
  list-style: none;
  animation: menu-in 0.22s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(-0.5em);
  }
}

.deck-menu-list button {
  display: flex;
  gap: 1.1em;
  width: 100%;
  padding: 0.62em 1.6em 0.62em 1.2em;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  text-transform: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, color 0.18s ease;
}

.deck-menu-list b {
  min-width: 2ch;
  font-weight: 400;
  opacity: 0.45;
}

.deck-menu-list button:hover,
.deck-menu-list button:focus-visible {
  background: rgb(246 241 231 / 9%);
  outline: 0;
}

.deck-menu-list [aria-current="true"] {
  color: var(--brick);
}

.deck-menu-list [aria-current="true"] b {
  opacity: 1;
}

/* Sound is opt-in so the Slide 03 cue survives browser autoplay policies. */
.sound-toggle {
  position: fixed;
  z-index: 52;
  bottom: clamp(10px, 1.1vw, 28px);
  left: 50%;
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.5em 0.2em;
  color: var(--cream);
  font-family: Arial, sans-serif;
  font-size: clamp(7px, 0.48vw, 12px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: none;
  border: 0;
  cursor: pointer;
  mix-blend-mode: difference;
  transform: translateX(-50%);
}

.sound-toggle i {
  width: 0.7em;
  height: 0.7em;
  border: 1px solid currentColor;
  border-radius: 50%;
  transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.sound-toggle span {
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s ease;
}

.sound-toggle:hover span,
.sound-toggle:focus-visible span {
  border-bottom-color: currentColor;
}

.sound-toggle:focus-visible {
  outline: 0;
}

.sound-toggle[aria-pressed="true"] i {
  background: currentColor;
  box-shadow: 0 0 0.7em currentColor;
}

/* --- Footer corners ------------------------------------------------------ */

.deck-download {
  position: fixed;
  z-index: 52;
  bottom: clamp(10px, 1.1vw, 28px);
  left: clamp(10px, 1.1vw, 28px);
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.5em 0.2em;
  color: var(--cream);
  font-family: Arial, sans-serif;
  font-size: clamp(7px, 0.48vw, 12px);
  letter-spacing: 0.16em;
  text-decoration: none;
  text-transform: uppercase;
  mix-blend-mode: difference;
}

/* Caret points down — this one takes a file, it doesn't travel. */
.deck-download i {
  width: 0;
  height: 0;
  border-top: 0.36em solid currentColor;
  border-right: 0.3em solid transparent;
  border-left: 0.3em solid transparent;
}

.deck-download:hover span {
  border-bottom: 1px solid currentColor;
}

.to-top {
  position: fixed;
  z-index: 52;
  right: clamp(10px, 1.1vw, 28px);
  bottom: clamp(10px, 1.1vw, 28px);
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.5em 0.2em;
  color: var(--cream);
  font-family: Arial, sans-serif;
  font-size: clamp(7px, 0.48vw, 12px);
  letter-spacing: 0.16em;
  text-decoration: none;
  text-transform: uppercase;
  mix-blend-mode: difference;
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.to-top i {
  width: 0;
  height: 0;
  border-right: 0.3em solid transparent;
  border-bottom: 0.36em solid currentColor;
  border-left: 0.3em solid transparent;
}

.to-top:hover span {
  border-bottom: 1px solid currentColor;
}

/* Nothing to go back to on the title card. */
body[data-idx="0"] .to-top {
  opacity: 0;
  transform: translateY(0.6em);
  pointer-events: none;
}

.header-meta {
  grid-column: 3;
  display: flex;
  justify-self: end;
  gap: 1.2vw;
  text-align: right;
}

.chapter-count {
  opacity: 0.7;
}

.progress {
  position: fixed;
  z-index: 51;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: rgb(255 255 255 / 16%);
  mix-blend-mode: difference;
}

.progress span {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--cream);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

main {
  display: flex;
  flex-direction: column;
  gap: clamp(3px, 0.38vw, 10px);
  width: 100%;
  padding: clamp(3px, 0.38vw, 10px) 0;
  background: #080808;
}

/* The lens element is the glass the whole strip is seen through. It only
   becomes a fixed, filtered viewport in deck mode; on small screens it stays
   inert so the page scrolls normally. */
.lens-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/*
 * Deck mode. The document itself no longer scrolls — script.js parks the strip
 * so the active slide sits dead centre, which means a slide at rest is exactly
 * the Figma composition: no parallax offset, no gate scaling. All the motion is
 * spent in the transition between frames.
 */
body.deck {
  height: 100%;
  overflow: hidden;
}

body.deck .lens {
  position: fixed;
  z-index: 1;
  inset: 0;
  overflow: hidden;
  /* Barrel distortion. Bleeding a few pixels of #080808 in at the edges is
     free here — that is exactly the colour behind the strip anyway. */
  filter: url("#lens");
}

body.deck main {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

/*
 * The gate. A slide is 33.4vw tall (2572×858), so ±16.7vw from centre is
 * exactly the active frame — held perfectly clear — and everything past it
 * falls off to the backing colour within a few vw. That leaves the neighbouring
 * frames as dim slivers, which is both what a projector gate looks like and
 * what keeps their in-transit parallax offsets from reading as broken layout.
 */
body.deck .lens::after {
  content: "";
  position: absolute;
  z-index: 30;
  inset: 0;
  /* Long, eased falloff. The stops trace an S-curve over ~14vw either side
     instead of ramping over 6vw, which is what made the old edge read as a
     hard band. The frame itself (±16.9vw) still stays perfectly clear. */
  background: linear-gradient(
    to bottom,
    #080808 0,
    #080808 calc(50% - 28vw),
    rgb(8 8 8 / 97.5%) calc(50% - 26.2vw),
    rgb(8 8 8 / 91%) calc(50% - 24.8vw),
    rgb(8 8 8 / 79%) calc(50% - 23.4vw),
    rgb(8 8 8 / 62%) calc(50% - 22.2vw),
    rgb(8 8 8 / 42%) calc(50% - 21vw),
    rgb(8 8 8 / 22%) calc(50% - 19.8vw),
    rgb(8 8 8 / 8%) calc(50% - 18.5vw),
    transparent calc(50% - 17.1vw),
    transparent calc(50% + 17.1vw),
    rgb(8 8 8 / 8%) calc(50% + 18.5vw),
    rgb(8 8 8 / 22%) calc(50% + 19.8vw),
    rgb(8 8 8 / 42%) calc(50% + 21vw),
    rgb(8 8 8 / 62%) calc(50% + 22.2vw),
    rgb(8 8 8 / 79%) calc(50% + 23.4vw),
    rgb(8 8 8 / 91%) calc(50% + 24.8vw),
    rgb(8 8 8 / 97.5%) calc(50% + 26.2vw),
    #080808 calc(50% + 28vw),
    #080808 100%
  );
  pointer-events: none;
}

.chapter {
  position: relative;
  isolation: isolate;
  display: block;
  flex: 0 0 auto;
  width: 100%;
  min-height: 0;
  aspect-ratio: var(--slide-ratio);
  overflow: hidden;
  color: var(--ink);
  background: var(--paper);

  /* The gate: the centred frame sits full size and full strength, the ones
     either side of it hang back and dim. --focus is eased in script.js, so the
     strip settles rather than snapping. The second term is the projector dim —
     the whole frame loses a little light while the film is running. */
  scale: calc(0.965 + 0.035 * var(--focus, 1));
  opacity: calc((0.52 + 0.48 * var(--focus, 1)) * (1 - 0.12 * var(--scroll-speed, 0)));
}

/* In deck mode the gate mask does the work of separating frames, so the dim
   here stays light — pushing a cream slide toward black just greys it out. */
body.deck .chapter {
  opacity: calc((0.88 + 0.12 * var(--focus, 1)) * (1 - 0.08 * var(--scroll-speed, 0)));
}

/* Every Figma slide owns an independent film frame and animated grain layer. */
.chapter::before,
.chapter::after {
  content: "";
  position: absolute;
  pointer-events: none;
}

.chapter::before {
  z-index: 20;
  inset: 0;
  background: url("assets/images/film-sprockets.png") center / 100% 100% no-repeat;
}

.chapter::after {
  z-index: 19;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  /* Grain boils up while the film is moving and settles when it stops. */
  opacity: calc(0.12 + 0.2 * var(--scroll-speed, 0));
  background: url("assets/images/noise.webp") repeat;
  background-size: 9.95vw 9.95vw;
  animation: noise 1.2s steps(3) infinite both;
  will-change: transform;
}

/* script.js writes --parallax per layer. Using the standalone `translate`
   property keeps the drift independent of `transform`, so a layer can carry a
   rotation and the .reveal transition at the same time without either
   clobbering the other. */
[data-parallax] {
  translate: 0 var(--parallax, 0px);
}

.paper {
  color: var(--ink);
  background: var(--paper);
}

.still {
  color: var(--cream);
  background: #10100f;
}

.section-inner {
  position: absolute;
  z-index: 4;
  margin: 0;
}

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

/*
 * One blur radius for every line in the deck. Applied per text block rather
 * than to a wrapper, because filter on a wrapper would also catch the artwork
 * inside it. Chrome outside <main> stays crisp — it's interface, not print,
 * and it blends in difference mode.
 */
h1,
h2,
.hero-title p,
.scroll-cue,
.body-copy,
.eyebrow,
.script-note,
.three-col p,
.two-copy p,
.wide-copy p,
.west .section-inner p,
.genre-strip,
.quote blockquote > p,
.quote blockquote footer,
.quote blockquote cite,
.closing p,
.closing a,
.coverage blockquote,
.coverage figcaption,
.poster-card h3,
.poster-card p {
  filter: blur(var(--print-blur));
}

h2 {
  margin-bottom: 0;
  font-family: var(--display);
  font-weight: 400;
  line-height: 0.85;
  /* Display face set at its designed spacing — the old -0.025em was reading
     tight. Every head keeps at least 3.5% of its measure in slack at desktop
     widths (1.8% at 375px), so nothing re-wraps. */
  letter-spacing: normal;
  text-transform: uppercase;
  text-shadow: -0.04vw 0.04vw 0 #000;
}

h2 em {
  color: var(--brick);
  font-style: normal;
}

.body-copy {
  margin: 0;
  line-height: 1.2;
}

/* Figma sets emphasis at 48/32 through most of the deck; a handful of slides
   pick their own ratio and override below. */
.body-copy strong,
.two-copy strong,
.wide-copy strong {
  color: var(--brick);
  font-size: 1.5em;
  font-weight: 400;
}

.intro .body-copy strong {
  font-size: 1.25em;
}

.eyebrow {
  margin: 0 0 0.85vw;
  font-family: Arial, sans-serif;
  font-size: 0.86vw;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

/*
 * Hand-drawn strokes. Each export is 11px thick (0.43vw of the 2572 artboard)
 * and sized to the rule it belongs to, so every one is used at or near its
 * native width — no scribble gets stretched enough to read as smeared.
 *   rule-long      115×11  → the 114px rules, and the 143px ones stretched 1.24×
 *   rule-short      35×11  → genre separators, and the quote attribution
 *   rule-vertical   11×144 → the pinball column dividers
 *   rule-dot        11×11  → the visual-language tag separators
 * Margins run 0.215vw tighter than the 1.63vw gap so the stroke's optical
 * centre lands where Figma's zero-height line sat.
 */
.rule {
  display: block;
  width: 5.56vw;
  height: 0.43vw;
  margin: 1.42vw 0;
  background: url("assets/images/rule-long.png") left center / 100% 100% no-repeat;
}


/* No filter here on purpose: text carries its own print blur, and animating
   filter on the wrapper would override it for anything inside. */
.reveal {
  opacity: 0;
  transform: translate3d(0, 0.32vw, 0);
  transition:
    opacity 0.75s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/*
 * Industry-coverage pull quotes. The same block appears on four slides, all
 * hung off the 11.66% margin — only the anchor edge, the measure and the ink
 * colour change per slide.
 */
.coverage {
  position: absolute;
  z-index: 4;
  left: 11.66%;
  margin: 0;
  color: var(--cream);
}

.coverage blockquote {
  margin: 0;
  font-size: 1.24vw;
  line-height: 1.19;
}

.coverage figcaption {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.93vw;
  margin-top: 0.47vw;
  font-family: Arial, sans-serif;
  font-size: 0.93vw;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
}

/* The short stroke at its native 34.5×10.5, without the standalone rule's
   stacked margins. */
.coverage .rule {
  width: 1.34vw;
  height: 0.41vw;
  margin: 0;
  background-image: url("assets/images/rule-short.png");
}

.delay-1 { transition-delay: 0.08s; }
.delay-2 { transition-delay: 0.14s; }
.delay-3 { transition-delay: 0.2s; }

.backdrop {
  position: absolute;
  z-index: 0;
  top: 0;
  max-width: none;
  height: 100%;
  object-fit: cover;
  /* Just enough overscan that the slowest layer can drift without dragging its
     own edge into frame. Deliberately tiny: every crop is hand-placed, the
     sprocket overlay masks the outer ~2%, and the gate has a frame nearly dark
     by the time its drift gets large. */
  transform: scale(calc(1.03 * var(--flip, 1)), 1.03);
}

/* Four stills are mirrored in the deck so the subject lands opposite the type
   instead of behind it. In Figma they read as a node whose x sits past the
   right edge of the slide — the tell for a negative horizontal scale. */
.backdrop.flip-x {
  --flip: -1;
}

.shade {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
}

.shade-left {
  background: linear-gradient(90deg, rgb(0 0 0 / 82%) 0%, rgb(0 0 0 / 38%) 36%, transparent 68%);
}

.shade-right {
  background: linear-gradient(270deg, rgb(0 0 0 / 82%) 0%, rgb(0 0 0 / 38%) 36%, transparent 68%);
}

.shade-center {
  background: linear-gradient(90deg, rgb(0 0 0 / 65%), transparent 38%, transparent 62%, rgb(0 0 0 / 65%));
}

/* Figma runs the closing frame ungraded; this is the lightest wash that still
   holds the quote legible over the Taurus. */
.shade-bottom {
  background: linear-gradient(0deg, rgb(0 0 0 / 72%), rgb(0 0 0 / 3%) 62%);
}

/* 01 — Title */
.hero {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.hero-art {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  width: 75.19%;
  height: 94.76%;
  transform: translate(-50%, -50%);
}

.hero-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-title {
  position: relative;
  z-index: 4;
  width: 34.18%;
  transform: rotate(-5deg) skewX(-5deg);
}

.hero-title.reveal,
.hero-title.reveal.is-visible {
  transform: rotate(-5deg) skewX(-5deg);
}

.hero-title h1 {
  width: 100%;
  /* Figma tucks the byline into the title's descender space by 34px, not by the
     full 75px of the frame overlap — the extra 41px is the byline's own leading. */
  margin: 0 0 -1.32vw;
  color: var(--brick);
  font-family: WindsorCondensed, serif;
  font-size: 6.89vw;
  font-weight: 400;
  line-height: 1.1;
  /* No negative tracking — Figma sets none, and the tightening was pulling the
     title ~2.4vw narrower than the byline beneath it. At normal spacing the two
     lines measure the same width, which is how the lockup is drawn. */
  letter-spacing: normal;
  text-transform: uppercase;
}

.hero-title p {
  margin: 0;
  color: var(--mustard);
  font-family: WindsorHeavy, serif;
  font-size: 1.36vw;
  line-height: 1;
  text-transform: uppercase;
  text-shadow: -0.04vw 0.04vw #000;
}

.scroll-cue {
  display: none;
}

/* 02 — A modern story */
.intro .section-inner {
  /* Slide 02 only: increase this value to move its body copy right. */
  --slide-2-body-x: 0.5vw;

  top: 28%;
  left: 21.75%;
  display: grid;
  grid-template-columns: 56.44% 43.56%;
  width: 56.49%;
}

.intro .eyebrow {
  display: none;
}

.intro .display-copy {
  min-width: 0;
}

.intro h2 {
  /* The heading's measure is the full text block in Figma (1453px), not its
     column — it deliberately runs past the body copy and sets three lines. */
  width: 56.49vw;
  color: var(--brick);
  font-size: 4.98vw;
  line-height: 0.85;
}

.intro h2 em {
  color: var(--ink);
}

/* Sits hard against the heading — beside OF INACTION, tucked under TRAGEDY.
   Pulled a touch left of its column start and lifted, tighter into the corner
   the heading makes than the Figma placement. The measure is set by the first
   line: "A blown-out tire. Stolen suit. A desperate shortcut" has to hold
   together, which is what pushes it past the Figma column and moves the
   MoonPie up out of its way. */
.intro .body-copy {
  width: 30vw;
  margin-top: 7.9vw;
  margin-left: calc(-0.46vw + var(--slide-2-body-x));
  font-size: 1.56vw;
}

.moonpie {
  position: absolute;
  z-index: 2;
  top: -14%;
  right: 1.5%;
  width: 19%;
  max-width: none;
  opacity: 0.85;
  filter: blur(0.025vw);
  transform: rotate(22.94deg);
}

/* 03 — Mosaic */
.manifesto .section-inner {
  top: 31.5%;
  left: 29.88%;
  width: 40.24%;
}

.manifesto .eyebrow {
  display: none;
}

.manifesto h2 {
  color: var(--brick);
  font-size: 3.96vw;
  line-height: 0.74;
}

.manifesto h2 em {
  color: var(--ink);
}

.manifesto .body-copy {
  margin-top: 0vw;
  font-size: 1.48vw;
  line-height: 1.2;
}

/* Centred with auto margins, not translateX(-50%): this is also a .reveal
   element, and .reveal.is-visible sets its own transform, which would win on
   specificity and silently drop the centring. */
.genre-strip {
  position: absolute;
  z-index: 4;
  right: 0;
  bottom: 10%;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2.29vw;
  width: fit-content;
  margin: 0 auto;
  padding: 0;
  font-family: Arial, sans-serif;
  font-size: 0.86vw;
  line-height: 0.85;
  letter-spacing: 0.19em;
  list-style: none;
  text-transform: uppercase;
  white-space: nowrap;
}

.genre-strip li + li::before {
  content: "";
  display: inline-block;
  width: 1.32vw;
  height: 0.43vw;
  margin-right: 2.29vw;
  vertical-align: middle;
  background: url("assets/images/rule-short.png") center / 100% 100% no-repeat;
}

/* 04 — How far */
.chapter[data-chapter="How far can a person go"] .backdrop {
  left: 7%;
  width: 85.96%;
  object-position: center 45%;
}

.chapter[data-chapter="How far can a person go"] .cinematic-copy {
  top: 16%;
  left: 11.66%;
  width: 28.81%;
}

.chapter[data-chapter="How far can a person go"] h2 {
  color: var(--brick);
  font-size: 3.38vw;
  line-height: 0.85;
}

.chapter[data-chapter="How far can a person go"] h2 span,
.chapter[data-chapter="How far can a person go"] h2 em {
  color: var(--cream);
}

.chapter[data-chapter="How far can a person go"] h2 em {
  font-size: 1.32em;
}

.chapter[data-chapter="How far can a person go"] .body-copy {
  width: 21.11vw;
  font-size: 1.52vw;
}

.chapter[data-chapter="How far can a person go"] .body-copy strong {
  font-size: 1em;
  text-transform: uppercase;
}

/* 05 — Camera */
.chapter[data-chapter="The camera"] .backdrop {
  top: 0;
  left: 3.5%;
  width: 89.54%;
  height: 111%;
  object-position: center bottom;
}

.chapter[data-chapter="The camera"] .cinematic-copy {
  top: 20%;
  right: 11.66%;
  width: 38.61%;
  text-align: right;
}

.chapter[data-chapter="The camera"] .coverage {
  bottom: 10%;
  width: 26.87%;
}

.chapter[data-chapter="The camera"] h2 {
  color: var(--brick);
  font-size: 5.79vw;
}

.chapter[data-chapter="The camera"] h2 em {
  color: var(--cream);
}

/* 06 — What we say */
/* This frame is wider than the still (2.64 vs 2.34), so cover has to lose some
   height. Splitting it evenly instead of anchoring the bottom keeps the
   headroom above him that the deck has, rather than shaving his head. */
.chapter[data-chapter="What we say"] .backdrop {
  left: 5.95%;
  width: 88.06%;
  object-position: center center;
}

.chapter[data-chapter="What we say"] .cinematic-copy {
  top: 17%;
  right: 11.66%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: 36.12%;
  text-align: right;
}

.chapter[data-chapter="What we say"] h2 {
  color: var(--brick);
  font-size: 4.47vw;
}

.chapter[data-chapter="What we say"] h2 span {
  color: var(--cream);
}

.chapter[data-chapter="What we say"] .body-copy {
  width: 25.35vw;
  font-size: 1.24vw;
}

/* 07 — Martin */
.chapter[data-chapter="This guy Martin"] .backdrop {
  left: 0;
  width: 100.78%;
  object-position: center 48%;
}

.chapter[data-chapter="This guy Martin"] .cinematic-copy {
  top: 15%;
  left: 11.66%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: 34.14%;
}

.chapter[data-chapter="This guy Martin"] h2 {
  width: 100%;
  color: var(--cream);
  font-size: 5.56vw;
  text-align: left;
}

.chapter[data-chapter="This guy Martin"] h2 em {
  display: block;
  color: var(--brick);
  font-size: 1.5em;
}

.chapter[data-chapter="This guy Martin"] .body-copy {
  width: 28.07vw;
  font-size: 1.67vw;
}

.chapter[data-chapter="This guy Martin"] .body-copy strong {
  font-size: 1.19em;
  font-style: italic;
}

/* 08 — Picture a guy */
.chapter[data-chapter="Picture a guy"] .backdrop {
  left: 6.57%;
  width: 86.86%;
  object-position: center 45%;
}

.chapter[data-chapter="Picture a guy"] .cinematic-copy {
  right: 11.66%;
  bottom: 10%;
  width: 41.41%;
  text-align: right;
}

/* The only one of the four anchored to the top of its slide. */
.chapter[data-chapter="Picture a guy"] .coverage {
  top: 10%;
  width: 19.13%;
}

.chapter[data-chapter="Picture a guy"] .script-note {
  margin: 0 0 0.14vw;
  color: var(--cream);
  font-family: var(--display);
  font-size: 2.22vw;
  line-height: 0.8;
}

.chapter[data-chapter="Picture a guy"] h2 {
  color: var(--brick);
  font-size: 5.51vw;
  line-height: 0.8;
}

.chapter[data-chapter="Picture a guy"] .body-copy {
  margin-top: 0.5vw;
  font-size: 1.67vw;
}

/* 09 — Pinball */
.chapter[data-chapter="The pinball"] .backdrop {
  left: 6.03%;
  width: 87.91%;
  object-position: center 45%;
}

.chapter[data-chapter="The pinball"] .section-inner {
  bottom: 10%;
  left: 11.66%;
  width: 47.43%;
}

.chapter[data-chapter="The pinball"] h2 {
  width: 33.2vw;
  color: var(--brick);
  font-size: 4.55vw;
}

.chapter[data-chapter="The pinball"] h2 em {
  color: var(--cream);
  font-size: 1.24em;
}

/* Uneven measures, straight from the design: 380 / 296 / 332 of 2572. */
.three-col {
  display: grid;
  grid-template-columns: 14.77vw 11.51vw 12.91vw;
  gap: 4.12vw;
  width: 100%;
}

.three-col p {
  position: relative;
  margin: 0;
  font-size: 1.48vw;
  line-height: 1.2;
}

/* Short centred tick between columns, not a full-height divider. Uses the
   stroke drawn vertically rather than a rotated horizontal one, so its taper
   reads the right way up. */
.three-col p + p::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -2.06vw;
  width: 0.43vw;
  height: 5.6vw;
  background: url("assets/images/rule-vertical.png") center / 100% 100% no-repeat;
  transform: translateY(-50%);
}

/* 10 — Agency */
.chapter[data-chapter="A lack of agency"] .backdrop {
  left: 6.96%;
  width: 86%;
  height: 101.5%;
  object-position: center bottom;
}

.chapter[data-chapter="A lack of agency"] .section-inner {
  inset: 10% 11.66%;
  width: auto;
  height: 80%;
}

.chapter[data-chapter="A lack of agency"] h2 {
  width: 55.21vw;
  color: var(--cream);
  font-size: 4.28vw;
}

.chapter[data-chapter="A lack of agency"] h2 em.louder {
  font-size: 1.21em;
}

.chapter[data-chapter="A lack of agency"] .trailing {
  position: absolute;
  right: 0;
  bottom: 0;
  margin: 0;
  color: var(--cream);
  font-size: 1.2vw;
  letter-spacing: 0.17em;
}

/* 11 — John */
.chapter[data-chapter="You’ve got John"] .backdrop {
  left: 0;
  width: 97.82%;
  object-position: center 47%;
}

.chapter[data-chapter="You’ve got John"] .cinematic-copy {
  top: 10%;
  right: 11.66%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: 31.84%;
  text-align: right;
}

.chapter[data-chapter="You’ve got John"] h2 {
  width: 23.33vw;
  color: var(--brick);
  font-size: 8.4vw;
  text-align: left;
}

.chapter[data-chapter="You’ve got John"] h2 span {
  display: block;
  color: var(--cream);
  font-size: 0.42em;
  text-align: right;
}

.chapter[data-chapter="You’ve got John"] h2 em {
  color: var(--brick);
}

.chapter[data-chapter="You’ve got John"] .body-copy {
  width: 29.67vw;
  font-size: 1.6vw;
}

.chapter[data-chapter="You’ve got John"] .body-copy strong {
  font-size: 1.62em;
}

.chapter[data-chapter="You’ve got John"] .coverage {
  bottom: 10%;
  width: 23.17%;
}

/* 12 — Sitting across */
.chapter[data-chapter="Sitting across from you"] .backdrop {
  left: 6.3%;
  width: 87.4%;
  object-position: center 48%;
}

.chapter[data-chapter="Sitting across from you"] .two-copy {
  top: 10%;
  left: 11.66%;
  display: grid;
  grid-template-columns: 24.53vw 22.55vw;
  align-items: center;
  justify-content: space-between;
  width: 76.05%;
  height: 80%;
  gap: 0;
}

.chapter[data-chapter="Sitting across from you"] h2 {
  color: var(--brick);
  font-size: 4.04vw;
}

.chapter[data-chapter="Sitting across from you"] h2 span {
  color: var(--cream);
}

.two-copy p {
  margin: 0 0 0.75vw;
  font-size: 1.24vw;
  line-height: 1.15;
}

.two-copy > div:last-child {
  text-align: right;
}

/* Sits on its own line at nearly twice the body size, so the tight leading left
   it crowding the line above — the taller line box opens that gap back up. */
.big-word {
  color: var(--brick);
  font-family: var(--display);
  font-size: 1.9em !important;
  line-height: 1.35;
  text-transform: uppercase;
}

/* 13 — Nowhere */
.nowhere .section-inner {
  top: 14.5%;
  left: 23.33%;
  width: 53.3%;
}

.nowhere h2 {
  width: 53.3vw;
  color: var(--brick);
  font-size: 5.79vw;
}

.nowhere h2 em {
  color: var(--ink);
}

.suzuki {
  position: absolute;
  z-index: 2;
  top: 5%;
  right: 4.7%;
  width: 33.31%;
  max-width: none;
  filter: blur(0.025vw);
  transform: rotate(5.95deg);
}

/* 14 — West Coast */
.west .backdrop {
  left: 6.1%;
  width: 87.75%;
  object-position: center 35%;
}

.west .section-inner {
  top: 10%;
  left: 11.66%;
  width: 76.67%;
  height: 80%;
}

.west h2 {
  width: 39.93vw;
  color: var(--cream);
  font-size: 2.56vw;
}

.west h2 em {
  color: var(--cream);
  font-size: 1.44em;
}

.west .section-inner > p {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 19.75vw;
  margin: 0;
  color: var(--brick);
  font-family: var(--display);
  font-size: 2.56vw;
  line-height: 0.85;
  text-align: right;
}

/* 15 — Wide frames */
/* The only crop that sat inside the frame vertically; squared up so the
   parallax drift can't lift its edge past the sprocket mask. */
.wide-frames .backdrop {
  top: 0;
  left: 5.81%;
  width: 88.37%;
  height: 101%;
  object-position: center 46%;
}

.wide-frames .section-inner {
  bottom: 10%;
  left: 11.66%;
  width: 76.67%;
}

.wide-frames .eyebrow {
  color: var(--brick);
  letter-spacing: 0.28em;
}

.wide-frames h2 {
  color: var(--cream);
  font-size: 4.12vw;
}

.wide-frames h2 span {
  display: block;
  font-size: 0.64em;
}

.wide-frames .rule {
  width: 4.43vw;
  margin: 1.63vw 0;
}

.wide-copy {
  display: grid;
  grid-template-columns: 31.61vw;
  gap: 4vw;
}

.wide-copy p {
  margin: 0;
  font-size: 1.13vw;
  line-height: 1.2;
}

/* Figma centres this line against the whole left stack — title, rule and body —
   rather than resting it on the body's baseline. */
.wide-copy p:last-child {
  position: absolute;
  top: 42.4%;
  right: 0;
  width: 19.44vw;
  text-align: right;
  transform: translateY(-50%);
}

.wide-copy p:last-child strong {
  font-size: 1.55em;
}

/* The left column's emphasis is a colour change only, at body size. */
.wide-copy p:first-child strong {
  font-size: 1em;
}

/* Left-aligned in the copy block here, not centred on the slide. */
.wide-frames .genre-strip {
  position: static;
  justify-content: flex-start;
  gap: 2.1vw;
  margin: 2.18vw 0 0;
  color: var(--cream);
}

/* A dot here, not the 34px stroke the genre strip uses. */
.wide-frames .genre-strip li + li::before {
  width: 0.43vw;
  margin-right: 2.1vw;
  background-image: url("assets/images/rule-dot.png");
}

/* 16 — Driving */
.driving .backdrop {
  left: 6.03%;
  width: 87.95%;
  height: 102.8%;
  object-position: center top;
}

.driving .cinematic-copy {
  right: 11.66%;
  bottom: 15%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: 32.93%;
  text-align: right;
}

.driving .rule {
  width: 4.43vw;
}

/* Ink here, not cream — this one sits on the sun-bleached road. */
.driving .coverage {
  bottom: 10%;
  width: 26.09%;
  color: var(--ink);
}

.driving h2 {
  width: 25.66vw;
  color: var(--cream);
  font-size: 4.12vw;
}

.driving .body-copy {
  width: 100%;
  font-size: 1.24vw;
}

.driving .score-note {
  width: 32.31vw;
  margin: 1.63vw 0 0;
  color: var(--brick);
  font-size: 0.93vw;
  line-height: 1.2;
  letter-spacing: 0.17em;
}

/* 17 — References */
.references .section-inner {
  top: 10%;
  left: 11.66%;
  width: 76.67%;
  height: 80%;
}

.reference-heading {
  display: none;
}

.poster-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2.54vw;
  width: 100%;
}

.poster-card {
  min-width: 0;
}

/* The exports carry their own drawn border and film title, so there is no CSS
   frame and no title overlay — the art is the whole poster. Ratio matches the
   457×531 export exactly so nothing crops. */
.poster {
  position: relative;
  width: 100%;
  aspect-ratio: 457 / 531;
}

.poster > img:first-child {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.poster-card h3 {
  margin: 1.63vw 0 0.35vw;
  color: var(--brick);
  font-family: var(--display);
  font-size: 1.24vw;
  font-weight: 400;
  line-height: 1.2;
  text-transform: uppercase;
}

.poster-card p {
  margin: 0;
  font-size: 0.89vw;
  line-height: 1.2;
}

/* 18 — Quote */
.quote .backdrop {
  left: -1.77%;
  width: 103.54%;
  object-position: center 44%;
}

.quote .section-inner {
  right: 11.66%;
  bottom: 10%;
  left: 11.66%;
  width: auto;
}

.quote blockquote {
  margin: 0;
}

/* Two lines, split by the <br>: the brick one, then the cream one. The measure
   is set by the longer of the two — "This is not about ambition." needs 48.6vw
   to hold together, so anything tighter re-wraps it. */
.quote blockquote > p {
  width: 50vw;
  margin: 0 0 0.47vw;
  font-family: var(--display);
  font-size: 3.27vw;
  line-height: 0.85;
  text-transform: none;
  text-shadow: -0.04vw 0.04vw #000;
}

.quote blockquote em {
  color: var(--brick);
  font-style: normal;
}

.quote blockquote span {
  font-size: 1.19em;
}

.quote blockquote footer {
  width: 100%;
  font-size: 1.67vw;
  line-height: 1.2;
}

.quote blockquote cite {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1.63vw;
  margin-top: 1.63vw;
  color: var(--brick);
  font-family: Arial, sans-serif;
  font-size: 1.17vw;
  font-style: normal;
  letter-spacing: 0.17em;
  text-transform: uppercase;
}

.quote blockquote cite .rule {
  width: 1.56vw;
  margin: 0;
  background-image: url("assets/images/rule-short.png");
}

.closing {
  display: none;
}

@keyframes noise {
  0% { transform: translate3d(1%, -1%, 0); }
  10% { transform: translate3d(-5%, -2%, 0); }
  20% { transform: translate3d(10%, 5%, 0); }
  30% { transform: translate3d(5%, -11%, 0); }
  40% { transform: translate3d(-12%, -5%, 0); }
  50% { transform: translate3d(10%, 9%, 0); }
  60% { transform: translate3d(15%, 0, 0); }
  70% { transform: translate3d(-10%, 8%, 0); }
  80% { transform: translate3d(10%, 2%, 0); }
  90% { transform: translate3d(1%, 5%, 0); }
  100% { transform: translate3d(0, 8%, 0); }
}

@media (max-width: 700px) {
  .site-header,
  .deck-menu,
  .to-top {
    display: none;
  }

  /* Mobile drops every other piece of chrome; the download stays, sized for a
     thumb rather than the micro meta scale. */
  .deck-download {
    bottom: 0;
    left: 0;
    padding: 16px;
    font-size: 9px;
  }

  .sound-toggle {
    bottom: 0;
    padding: 16px;
    font-size: 9px;
  }

  .progress {
    height: 1px;
  }

  main {
    gap: 2px;
    padding: 2px 0;
  }
}

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

  .chapter,
  body.deck .chapter {
    scale: 1;
    opacity: 1;
  }

  .chapter::after {
    opacity: 0.12;
    animation: none;
  }

  .reveal,
  .reveal.is-visible {
    opacity: 1;
    filter: none;
    transform: none;
    transition: none;
  }

  .hero-title.reveal,
  .hero-title.reveal.is-visible {
    transform: rotate(-5deg) skewX(-5deg);
  }
}
