/* Landing (/): five pinned scenes. Each .scene is a tall scroll track whose
   sticky .stage holds the art; its view timeline plays the scene, and the next
   track overlaps it by one viewport so the next stage cross-fades in on top.
   Base styles are each scene's poster frame: without scroll timelines, with
   reduced motion or on a short viewport, the tracks collapse and stills stack.
   Palette copied from design/tokens (colors, motion): design/ is outside the
   image's build context. */
:root {
  color-scheme: dark;
  --ink: #14202e;
  --ink-deep: #0b131c;
  --ink-sunken: #08101a;
  --ink-2: #1b2a3a;
  --ink-3: #243345;
  --line: #38485b;
  --paper: #f4efe6;
  --paper-0: #fbf9f4;
  --fg: #f4efe6;
  --fg-2: #c7cdd4;
  --fg-3: #8e97a2;
  --teal: #2c8c9c;
  --teal-ink: #0e3a43;
  --teal-hi: #6fcfd9;
  --teal-hi-2: #a8e2e8;
  --safe: #4f7c84;
  --safe-ink: #c7dddf;
  --mild: #9c9430;
  --mild-ink: #e0dda7;
  --moderate: #c58418;
  --moderate-ink: #f0cc93;
  --high: #c5562a;
  --high-ink: #ecb498;
  --severe: #8a1e54;
  --severe-ink: #f1b4cb;
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --font: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --vh: 100vh;
  --gutter: clamp(1rem, 6vw, 6rem);
  /* Decimal mark for the CSS-counter readouts (scenes 3, 4); locale pages set lang. */
  --decimal: '.';
}

:root:is(:lang(fr), :lang(de), :lang(es), :lang(uk), :lang(ru)) {
  --decimal: ',';
}

@supports (height: 100svh) {
  :root {
    --vh: 100svh;
  }
}

html {
  background: var(--ink-deep);
}

.cine {
  margin: 0;
  color: var(--fg);
  background: var(--ink-deep);
  font: 1rem/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.cine a {
  color: var(--teal-hi);
}

.cine a:focus-visible {
  outline: 2px solid var(--teal-hi);
  outline-offset: 2px;
}

/* ---------- Masthead ---------- */
/* Opens the film like a title card and scrolls away with it: a fixed mark
   would sit over every scene's top copy, and over scene 5's at the page end. */
.masthead {
  position: absolute;
  isolation: isolate;
  z-index: 10;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: clamp(0.75rem, 2.5vh, 1.5rem) var(--gutter);
  pointer-events: none;
}

/* A faint top shade keeps the mark legible over the night sky. */
.masthead::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0 0 -2.5rem;
  background: linear-gradient(rgb(11 19 28 / 0.38), transparent);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--fg);
  text-decoration: none;
  pointer-events: auto;
}

.cine .brand {
  color: var(--fg);
}

.mark {
  width: 2rem;
  height: 2rem;
  filter: drop-shadow(0 1px 6px rgb(11 19 28 / 0.55));
}

.mark .ring {
  stroke: var(--teal-hi);
}

.mark .bead {
  fill: var(--fg);
}

.wordmark {
  font: 600 1.375rem/1 var(--font);
  letter-spacing: -0.02em;
  text-shadow: 0 1px 8px rgb(11 19 28 / 0.6);
}

/* ---------- Story player (landing.js) ---------- */
/* A small island at the top centre, clear of the mark and of each scene's
   copy; the caption hangs under it. Hidden in the markup, so a page without
   the script shows no dead control. */
.player {
  position: fixed;
  z-index: 20;
  top: calc(env(safe-area-inset-top, 0px) + 0.6rem);
  left: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: max-content;
  max-width: calc(100vw - 2 * var(--gutter));
  transform: translateX(-50%);
  pointer-events: none;
}

.player[hidden],
.player-sound[hidden],
.player-line[hidden] {
  display: none;
}

.player-pill,
.player-line,
.player-lang-menu {
  border: 1px solid rgb(244 239 230 / 0.12);
  /* Night ink, dense enough to hold over scene 5's sky. */
  background: rgb(6 10 17 / 0.82);
  box-shadow: 0 4px 16px rgb(0 0 0 / 0.3);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  backdrop-filter: blur(10px) saturate(1.2);
}

.player-pill {
  display: flex;
  align-items: center;
  gap: 0.1rem;
  height: 2rem;
  padding: 0 0.2rem;
  border-radius: 999px;
  pointer-events: auto;
}

.player-play,
.player-sound,
.player-cc {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  color: var(--fg);
  background: none;
  font: inherit;
  white-space: nowrap;
  cursor: pointer;
}

/* A 44 px touch target around the small icons, drawn nowhere. */
:is(.player-play, .player-sound, .player-cc, .player-lang > summary)::after {
  content: '';
  position: absolute;
  inset: min(0px, (100% - 2.75rem) / 2);
}

.player-play:focus-visible,
.player-sound:focus-visible,
.player-cc:focus-visible {
  outline: 2px solid var(--teal-hi);
  outline-offset: 2px;
}

.player-icon {
  box-sizing: content-box;
  width: 0.95rem;
  height: 0.95rem;
  padding: 0.33rem;
  border-radius: 50%;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 0;
}

.player-play .player-icon {
  color: var(--paper-0);
  background: var(--teal);
}

.player-cc[aria-pressed='true'] {
  color: var(--teal-hi);
}

.player-cc[aria-pressed='false'] {
  opacity: 0.6;
}

.player-text {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  padding-right: 0.55rem;
}

.player-label {
  font-weight: 600;
  font-size: 0.8rem;
}

.player-meta {
  color: var(--fg-2);
  font: 0.75rem var(--mono);
}

.player-hint {
  padding-right: 0.5rem;
  color: var(--teal-hi-2);
  font-size: 0.75rem;
}

.hint-click {
  display: none;
}

@media (pointer: fine) {
  .hint-touch {
    display: none;
  }

  .hint-click {
    display: inline;
  }
}

/* Phones: the island sits top-right, clear of the wordmark in every state,
   and idle shows only the play button and the length. */
@media (max-width: 40rem) {
  .player {
    right: calc(env(safe-area-inset-right, 0px) + var(--gutter));
    left: auto;
    align-items: flex-end;
    transform: none;
  }

  .player[data-state='idle'] .player-label {
    display: none;
  }
}

.player-bar {
  position: relative;
  overflow: hidden;
  width: 3.5rem;
  height: 3px;
  margin-inline: 0.3rem;
  border-radius: 1.5px;
  background: rgb(244 239 230 / 0.28);
}

.player-bar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--teal-hi);
  transform: scaleX(var(--progress, 0));
  transform-origin: left;
}

/* Language: the page's own code; the menu opens under the island. Links work
   without the script (a <details>), and each locale page is its own URL. */
.player-lang {
  position: relative;
}

.player-lang > summary {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  height: 1.6rem;
  padding: 0 0.55rem;
  border-radius: 999px;
  color: var(--fg-2);
  font: 600 0.7rem/1 var(--mono);
  letter-spacing: 0.06em;
  list-style: none;
  cursor: pointer;
}

.player-lang > summary::-webkit-details-marker {
  display: none;
}

.player-globe {
  width: 0.8rem;
  height: 0.8rem;
  stroke: currentColor;
}

.player-lang > summary::before {
  content: '';
  order: 1;
  width: 0.3rem;
  height: 0.3rem;
  border-right: 1.5px solid;
  border-bottom: 1.5px solid;
  transform: translateY(-1px) rotate(45deg);
}

.player-lang[open] > summary,
.player-lang > summary:hover {
  color: var(--fg);
  background: rgb(244 239 230 / 0.1);
}

.player-lang > summary:focus-visible {
  outline: 2px solid var(--teal-hi);
  outline-offset: 2px;
}

.player-lang-menu {
  position: absolute;
  /* Denser than the island, so the moon doesn't ghost through the list. */
  background: rgb(10 16 28 / 0.94);
  top: calc(100% + 0.6rem);
  right: -0.2rem;
  min-width: 9.5rem;
  margin: 0;
  padding: 0.3rem;
  border-radius: 0.7rem;
  list-style: none;
}

/* stylelint-disable-next-line no-descending-specificity -- sets no outline: .cine a:focus-visible's stands */
.player-lang-menu a {
  position: relative;
  display: block;
  padding: 0.45rem 0.7rem 0.45rem 1.4rem;
  border-radius: 0.45rem;
  color: var(--fg);
  font-size: 0.85rem;
  text-decoration: none;
}

.player-lang-menu a:hover,
.player-lang-menu a:focus-visible {
  outline: none;
  background: rgb(244 239 230 / 0.1);
}

/* Current language: a dot as well as the colour. */
.player-lang-menu a[aria-current] {
  color: var(--teal-hi);
}

.player-lang-menu a[aria-current]::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0.6rem;
  width: 0.35rem;
  height: 0.35rem;
  border-radius: 50%;
  background: currentColor;
  transform: translateY(-50%);
}

/* The menu is the task while open: the caption under the island steps aside. */
.player:has(.player-lang[open]) .player-line {
  display: none;
}

/* State: idle invites, playing shows progress, paused and ended offer the way back. */
.i-pause,
.i-replay,
.i-mute,
.player:not([data-hint='sound']) .player-hint,
.player[data-state='idle'] :is(.player-bar, .player-sound, .player-cc),
.player[data-state='ended'] .player-bar,
/* stylelint-disable-next-line no-descending-specificity -- the open menu's rule wins by specificity, not order */
.player[data-captions='off'] .player-line,
.player:is([data-state='playing'], [data-state='paused']) .player-text,
.player:not([data-state='idle']) .player-meta,
.player-sound[aria-pressed='true'] .i-wave {
  display: none;
}

.player[data-state='playing'] .i-pause,
.player[data-state='ended'] .i-replay,
.player-sound[aria-pressed='true'] .i-mute {
  display: inline;
}

.player[data-state='playing'] .i-play,
.player[data-state='ended'] .i-play {
  display: none;
}

/* 20rem clears scene 1's moon and scene 4's mirror. */
/* stylelint-disable-next-line no-descending-specificity -- as above */
.player-line {
  max-width: 20rem;
  margin: 0;
  padding: 0.35rem 0.7rem;
  border-radius: 0.6rem;
  color: var(--fg);
  font-size: 0.85rem;
  line-height: 1.4;
  text-align: center;
  text-wrap: pretty;
}

/* Scene 4's rear-view mirror hangs at the top centre: its caption moves to the
   dark windscreen on the left. Phones keep the column (captions are opt-in there). */
@media (min-width: 40rem) {
  .player[data-scene='4'] .player-line {
    position: absolute;
    top: 0;
    right: calc(100% + 1rem);
    width: max-content;
    text-align: right;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .player[aria-busy] .player-play .player-icon {
    animation: player-busy 1.2s ease-in-out infinite alternate;
  }
}

@keyframes player-busy {
  to {
    opacity: 0.45;
  }
}

/* ---------- Start islands (landing.js) ---------- */
/* Before the story runs: two floating choices right of the copy column. The
   click is the gesture browsers want, so "with sound" is audible at once. They
   leave as soon as the story starts, by either button or the first scroll. */
.story-start {
  position: fixed;
  z-index: 19;
  top: 50%;
  left: max(calc(var(--gutter) + 31rem), 54%);
  display: flex;
  flex-direction: column;
  /* One width for both, so the primary never looks like the lesser choice. */
  align-items: stretch;
  gap: 0.8rem;
  translate: 0 -50%;
}

.story-start[hidden] {
  display: none;
}

.story-start button {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3.5rem;
  margin: 0;
  padding: 0 1.5rem 0 1.15rem;
  border: 1px solid rgb(244 239 230 / 0.14);
  border-radius: 999px;
  color: var(--fg);
  background: rgb(6 10 17 / 0.82);
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
  font: 600 1.05rem/1.2 var(--font);
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  backdrop-filter: blur(10px) saturate(1.2);
}

.story-start .story-start-sound {
  border-color: transparent;
  color: var(--ink-deep);
  background: var(--teal-hi);
}

.story-start button:hover {
  filter: brightness(1.08);
}

.story-start button:focus-visible {
  outline: 2px solid var(--teal-hi-2);
  outline-offset: 3px;
}

.story-start-icon {
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 0;
}

/* While they show, the top island holds only the language chip. */
.story-start:not([hidden]) + .player .player-play {
  display: none;
}

/* Phones and narrow tablets: up in the sky between the moon and the hills,
   clear of the car (below 52rem the copy column leaves too little room beside it). */
@media (max-width: 52rem) {
  .story-start {
    top: 20%;
    right: calc(env(safe-area-inset-right, 0px) + var(--gutter));
    left: auto;
  }

  .story-start button {
    min-height: 3.1rem;
    padding: 0 1.25rem 0 1rem;
    font-size: 1rem;
  }
}

/* Short landscape screens: one compact row under the masthead, clear of the copy card. */
@media not all and (min-height: 30rem) {
  .story-start {
    top: 3.75rem;
    right: calc(env(safe-area-inset-right, 0px) + var(--gutter));
    left: auto;
    flex-direction: row;
    gap: 0.5rem;
    translate: none;
  }

  .story-start button {
    min-height: 2.5rem;
    padding: 0 1rem 0 0.8rem;
    font-size: 0.875rem;
  }
}

/* The still is the cut-away car, larger and higher: keep to the sky above it. */
@media (prefers-reduced-motion: reduce) and (min-width: 52.01rem) and (min-height: 30rem) {
  .story-start {
    top: 30%;
  }
}

/* The pair floats as one, so a row never looks crooked. */
@media (prefers-reduced-motion: no-preference) {
  .story-start {
    animation: story-float 5s ease-in-out infinite alternate;
  }
}

@keyframes story-float {
  to {
    transform: translateY(-6px);
  }
}

/* ---------- Scene shell ---------- */
.scene {
  --pin: 300vh;
  position: relative;
  height: var(--vh);
}

.scene--1 {
  view-timeline: --s1 block;
}

.scene--2 {
  view-timeline: --s2 block;
}

.scene--3 {
  view-timeline: --s3 block;
}

.scene--4 {
  view-timeline: --s4 block;
}

.scene--5 {
  view-timeline: --s5 block;
}

.stage {
  --scene-bg: var(--ink-deep);
  position: sticky;
  top: 0;
  height: var(--vh);
  overflow: hidden;
  isolation: isolate;
  background: var(--scene-bg);
}

.art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* ---------- Copy ---------- */
.copy {
  position: absolute;
  z-index: 2;
  left: var(--gutter);
  bottom: clamp(2.5rem, 11vh, 7.5rem);
  max-width: 34rem;
}

.copy--right {
  left: auto;
  right: var(--gutter);
}

.copy--top {
  bottom: auto;
  top: clamp(5.5rem, 15vh, 10rem);
}

.copy--center {
  left: 50%;
  translate: -50% 0;
  text-align: center;
}

.chapter {
  margin: 0;
  font: 600 0.75rem/1 var(--mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--teal-hi);
}

.chapter span {
  color: var(--fg-3);
  margin-right: 0.75em;
}

.copy h1,
.copy h2 {
  margin: 0.75rem 0 1rem;
  font-weight: 650;
  font-size: clamp(2.1rem, 4.4vw, 4.25rem);
  line-height: 1.04;
  letter-spacing: -0.028em;
  text-wrap: balance;
}

.lede {
  margin: 0;
  max-width: 32rem;
  font-size: clamp(1.02rem, 1.35vw, 1.25rem);
  line-height: 1.5;
  color: var(--fg-2);
  text-wrap: pretty;
}

.lede + .lede {
  margin-top: 0.75rem;
}

.fine {
  font: 500 0.8rem/1.5 var(--mono);
  color: var(--fg-3);
  letter-spacing: 0.02em;
}

/* Beats: copy that changes mid-scene. Stacked in the still, overlaid when the
   scroll timeline can swap them. */
.beats > * + * {
  margin-top: 1.5rem;
}

/* ---------- Footer ---------- */
.colophon {
  position: relative;
  z-index: 3;
  padding: 3rem var(--gutter) 3.5rem;
  background: var(--ink-sunken);
  color: var(--fg-3);
  font-size: 0.875rem;
}

.colophon p {
  margin: 0 0 0.5rem;
  max-width: 48rem;
}

.colophon nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin-top: 1.25rem;
}

/* ---------- Phone portrait: art on top, copy below ---------- */
@media (max-aspect-ratio: 4/5) {
  .art {
    height: 68%;
    mask-image: linear-gradient(#000 78%, transparent);
  }

  .copy,
  .copy--right,
  .copy--top,
  .copy--center {
    left: 1.25rem;
    right: 1.25rem;
    top: auto;
    bottom: max(1.5rem, env(safe-area-inset-bottom));
    max-width: none;
    translate: none;
    text-align: left;
  }

  .copy h1,
  .copy h2 {
    font-size: clamp(1.85rem, 8.4vw, 2.6rem);
    margin: 0.5rem 0 0.75rem;
  }

  .lede {
    font-size: 1rem;
  }
}

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: no-preference) and (min-height: 30rem) {
  @supports (animation-timeline: view()) {
    /* Pinned tracks only when the scroll can play them: stills just stack. */
    .scene {
      height: calc(var(--vh) + var(--pin));
    }

    .scene + .scene {
      margin-top: calc(-1 * var(--vh));
      /* Keeps the stage's negative margin inside the track. */
      display: flow-root;
    }

    .beats {
      display: grid;
    }

    .beats > * {
      grid-area: 1 / 1;
    }

    .beats > * + * {
      margin-top: 0;
    }

    /* The incoming stage starts one viewport up, so sticky pins it through its
       entry: layout holds it in place, where an animated translate drifted off
       the scroll and let the outgoing scene show at the edge (a hairline at
       fractional track heights, a band on a slow frame). The timeline rules
       below must out-rank this shorthand, which resets it. */
    .scene + .scene > .stage {
      margin-top: calc(-1 * var(--vh));
      animation: stage-in linear both;
      animation-range: entry 0% entry 100%;
    }

    .scene + .scene--2 > .stage {
      animation-timeline: --s2;
    }

    .scene + .scene--3 > .stage {
      animation-timeline: --s3;
    }

    .scene + .scene--4 > .stage {
      animation-timeline: --s4;
    }

    .scene + .scene--5 > .stage {
      animation-timeline: --s5;
    }
  }
}

@keyframes stage-in {
  from {
    opacity: 0;
  }

  30% {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* Short viewports (landscape phones, 200 % zoom): the motion blocks above
   need 30rem, so the tracks stay collapsed; the copy joins the flow and the
   stage grows to fit it, and scene overlays (HUDs, cards) step aside so
   nothing is drawn over it. */
@media not all and (min-height: 30rem) {
  .scene {
    height: auto;
  }

  /* Out-ranks scene rules on the stage, e.g. a size container. */
  body .scene > .stage {
    container-type: normal;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    box-sizing: border-box;
    height: auto;
    min-height: var(--vh);
    padding: 4.5rem var(--gutter) 2rem;
  }

  /* Visually hidden, not removed: role="img" summaries stay readable. */
  .scene .stage > :not(.art, .copy) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .scene .stage > .copy {
    position: relative;
    inset: auto;
    translate: none;
    max-width: 40rem;
    padding: 1rem 1.25rem;
    border-radius: 0.5rem;
    background: rgb(11 19 28 / 0.78);
  }
}
