/* ==========================================================================
   Spidergence landing
   The design is laid out on an 846px reference width. One `--u` equals one
   reference pixel, scaled to the viewport (capped at 1536px), so horizontal
   layout and type keep their proportions at any desktop width.

   Page:  Hero (100svh, one picture — hero.png — and a lens on the pointer that reveals hero-mask.png through it)
          → Feature strip
          → pinned scroll stage (hero.glb lowers itself on its thread over the
            landing.png particles while the background.png city fades in)
          → Features / Media panels (fixed overlays opened from the menus)
   Play now is the fall: html.is-falling drops the camera off whatever is on screen (src/hero/main.js), then a
   cross-document view transition carries the last frame into game.html (the inbound animation lives in game.css).
   ========================================================================== */

@font-face {
  font-family: "Anybody";
  src: url("assets/fonts/anybody.woff2") format("woff2");
  font-weight: 200 500;
  font-stretch: 100% 150%;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("assets/fonts/inter.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Roboto Mono";
  src: url("assets/fonts/robotomono.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}

:root {
  /* palette */
  --boot-bg: #030406;   /* the loading screen's ground (boot.css), matched to this page's */
  --bg: #020304;
  --black: #000;
  --text: #f1f2f2;
  --text-2: #a0a3a6;
  --text-3: #6f7377;
  --line: rgba(255, 255, 255, 0.16);
  --line-strong: rgba(255, 255, 255, 0.28);
  --line-btn: rgba(255, 255, 255, 0.68);
  --accent-red: #e8202a;

  /* type */
  --font-display: "Anybody", "Eurostile", "Microgramma", "Bank Gothic", "Michroma", sans-serif;
  --font-body: "Inter", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Roboto Mono", "SFMono-Regular", Menlo, monospace;

  /* layout */
  --design-w: 846;
  --page-max: 1536px;
  --u: calc(min(100vw, var(--page-max)) / var(--design-w)); /* src/hero/main.js refines this from the real client width */
  --content-max: 1360px;
  --page-pad: clamp(28px, 4vw, 72px);
  --header-h: calc(42 * var(--u));

  /* motion */
  --dur: 220ms;
  --ease: cubic-bezier(0.25, 0.1, 0.25, 1);

  /* scroll stage length: the viewport stays pinned while the visitor scrolls this far */
  --stage-track: 200vh;
}

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

/* overflow-x: clip (not hidden) keeps the pinned stage's position: sticky working */
html { background: var(--black); color-scheme: dark; -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, p, dl, dd { margin: 0; }
:focus-visible { outline: 1px solid rgba(255, 255, 255, 0.7); outline-offset: 3px; }

.site { position: relative; overflow: clip; }

/* inner containers: exactly 846u wide, centred */
.header__inner, .hero__inner, .strip__list, .stage__inner {
  position: relative;
  width: 100%;
  max-width: calc(846 * var(--u));
  margin: 0 auto;
}

/* ==========================================================================
   Shared type & UI
   ========================================================================== */

.display {
  font-family: var(--font-display);
  font-weight: 260;
  font-stretch: 137%;
  font-size: calc(24.6 * var(--u));
  line-height: calc(25 * var(--u));
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--text);
}
.display--hero {
  font-stretch: 150%;
  font-size: calc(26.6 * var(--u));
  line-height: calc(26.5 * var(--u));
  letter-spacing: 0;
}

.eyebrow {
  font-size: calc(8.2 * var(--u));
  line-height: calc(10 * var(--u));
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #c6c8ca;
  white-space: nowrap;
}
.eyebrow__mark { display: inline-block; font-size: 0.72em; margin-right: 0.6em; transform: translateY(-0.05em); color: #8e9194; }
.eyebrow--plain { color: var(--text-2); }

.lede {
  font-size: calc(11 * var(--u));
  line-height: calc(14 * var(--u));
  font-weight: 400;
  color: #d9dbdc;
  letter-spacing: 0.002em;
}

.actions { display: flex; align-items: center; gap: calc(12 * var(--u)); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.9em;
  height: calc(26 * var(--u));
  padding: 0 calc(13 * var(--u));
  border: 1px solid var(--line-btn);
  border-radius: calc(2.5 * var(--u));
  background: rgba(0, 0, 0, 0.35);
  color: var(--text);
  font-family: var(--font-body);
  font-size: calc(7.3 * var(--u));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn:hover { border-color: #fff; background: rgba(255, 255, 255, 0.06); }
.btn__arrow { display: inline-block; width: 1.45em; height: 1.1em; flex: none; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.btn--sm { height: calc(23 * var(--u)); padding: 0 calc(10 * var(--u)); font-size: calc(6.6 * var(--u)); }
.btn--wide { padding: 0 calc(12 * var(--u)) 0 calc(14 * var(--u)); gap: 1.8em; }
.btn--play { gap: 1.1em; padding: 0 calc(14 * var(--u)) 0 calc(11 * var(--u)); font-weight: 600; }
.play {
  width: calc(9.5 * var(--u));
  height: calc(9.5 * var(--u));
  border: 1px solid rgba(255, 255, 255, 0.85);
  border-radius: 50%;
  position: relative;
  flex: none;
}
.play::after {
  content: "";
  position: absolute;
  left: 38%;
  top: 28%;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: calc(2.1 * var(--u)) 0 calc(2.1 * var(--u)) calc(3.4 * var(--u));
  border-color: transparent transparent transparent #fff;
}

.tagline, .city__foot {
  font-size: calc(6.5 * var(--u));
  font-weight: 500;
  letter-spacing: 0.27em;
  text-transform: uppercase;
  color: #a5a8ab;
  white-space: nowrap;
}
.x { color: #6a6d70; margin: 0 0.9em; font-weight: 400; }

/* tiny vertical side notes with a thin rule */
.side-note {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: calc(4.6 * var(--u));
  font-size: calc(6.4 * var(--u));
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #8f9295;
  white-space: nowrap;
}
.side-note::before {
  content: "";
  position: absolute;
  top: calc(-4 * var(--u));
  bottom: calc(-4 * var(--u));
  width: 1px;
  background: rgba(255, 255, 255, 0.34);
}
.side-note--rule-right { align-items: flex-end; padding-right: calc(10 * var(--u)); }
.side-note--rule-right::before { right: 0; }
.side-note--rule-left { align-items: flex-start; padding-left: calc(7 * var(--u)); }
.side-note--rule-left::before { left: 0; }
.side-note--loose { gap: calc(12 * var(--u)); letter-spacing: 0.18em; color: #9a9da0; }
.side-note--loose::before { top: calc(-7 * var(--u)); bottom: calc(-7 * var(--u)); }

/* ==========================================================================
   Header (overlays the 100svh hero)
   ========================================================================== */

.header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  height: var(--header-h);
  background: linear-gradient(to bottom, rgba(2, 3, 4, 0.85), rgba(2, 3, 4, 0.55));
  border-bottom: 1px solid var(--line);
}
.header__inner { height: 100%; }

.logo {
  position: absolute;
  left: calc(46 * var(--u));
  top: 0;
  width: calc(115 * var(--u));
  height: 100%;
  overflow: hidden;
}
.logo img {
  position: absolute;
  left: 0;
  top: calc(-12 * var(--u));
  width: 100%;
  height: auto;
}

.nav { position: absolute; left: calc(257 * var(--u)); top: 0; height: 100%; }
.nav__list { display: flex; align-items: center; height: 100%; gap: calc(22 * var(--u)); }
.nav__link {
  position: relative;
  display: inline-block;
  padding: calc(8 * var(--u)) 0;
  font-size: calc(6.5 * var(--u));
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #c4c7ca;
  transition: color var(--dur) var(--ease);
}
.nav__link:hover, .nav__link.is-active { color: #fff; }
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-4.5 * var(--u));
  height: calc(1.6 * var(--u));
  background: #fff;
  box-shadow: 0 0 calc(5 * var(--u)) rgba(255, 255, 255, 0.9);
  opacity: 0;
  transform: scaleX(0.6);
  transform-origin: center;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.nav__link.is-active::after { opacity: 1; transform: none; }

.header__cta { position: absolute; right: calc(53 * var(--u)); top: calc(10 * var(--u)); }
.header__cta--mobile { display: none; }
.menu-toggle { display: none; }

/* ==========================================================================
   1. Hero — the glass and the lens. One picture on the frame: hero.png, the civilian portrait, graded down under
   a dark glass so it reads as a lit ground rather than a photograph filling the screen. The pointer carries a
   small round window that clears the glass and shows hero-mask.png — the suit world — through it, and nothing
   else reveals it. src/hero/main.js writes the lens's centre (--lx / --ly), its radius (--lens-r) and how far up
   it is (--lens-o); without JS, or without a pointer to carry it, the graded portrait stands on its own.
   ========================================================================== */

.hero {
  position: relative;
  height: 100svh;
  min-height: 560px;
  background: var(--black);
  overflow: hidden;
  /* the lens (JS refines the radius from the viewport; it stays down until a pointer is over the hero) */
  --lens-r: 150px;
  --lx: 50vw;
  --ly: 50svh;
  --lens-o: 0;
}
.hero__base,
.hero__lens-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: 65% 50%;
}
/* the portrait (hero.png is already near-monochrome, so no colour filter: it would cost a full-plate raster) */
.hero__base { opacity: 0.9; }
@keyframes rim-flicker {
  0%, 100% { opacity: 1; }
  7% { opacity: 0.7; }
  9% { opacity: 1; }
  41% { opacity: 0.8; }
  43% { opacity: 1; }
  44% { opacity: 0.6; }
  46% { opacity: 1; }
  78% { opacity: 0.85; }
  79% { opacity: 1; }
}
/* The glass. The portrait is graded down under an even scrim and a vignette so it sits back as a lit ground
   rather than a photograph filling the screen — the type carries the frame, the picture is what it stands on.
   Darkest on the copy's side, lightest across the face, falling off at the corners. It sits under the lens, so
   the lens is the one clear place in it. */
.hero__glass {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to right, rgba(2, 3, 4, 0.9) 0%, rgba(2, 3, 4, 0.72) 30%, rgba(2, 3, 4, 0.46) 58%, rgba(2, 3, 4, 0.42) 100%),
    radial-gradient(118% 96% at 64% 40%, rgba(2, 3, 4, 0) 34%, rgba(2, 3, 4, 0.62) 100%);
}
/* The lens. One box, exactly the disc's size, translated to the pointer; the suit plate inside it is a
   full-frame image pushed back by the same offset the box was moved by, which keeps it registered with the
   portrait behind while nothing but this small square is ever repainted. The suit plate is transparent
   everywhere but the mask and the suit, so the window reveals those and leaves the rest of the portrait alone. */
.hero__lens {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(2 * var(--lens-r));
  height: calc(2 * var(--lens-r));
  transform: translate3d(calc(var(--lx) - var(--lens-r)), calc(var(--ly) - var(--lens-r)), 0);
  opacity: var(--lens-o);
  pointer-events: none;
  /* down, it is out of the paint entirely: no layer, no filter, nothing for the ring's flicker to redraw */
  visibility: hidden;
}
.hero.is-lens .hero__lens {
  visibility: visible;
  will-change: transform, opacity;
}
.hero__lens-disc {
  position: absolute;
  inset: 0;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--lens-r) - 6px), transparent var(--lens-r));
  mask-image: radial-gradient(circle at 50% 50%, #000 calc(var(--lens-r) - 6px), transparent var(--lens-r));
}
/* the glass, cleared: the portrait drawn again over the scrim, at the same 0.9 the plate below it carries, so the
   circle is exactly the ungraded picture and the suit above it lands on its own exposure */
.hero__lens-disc--clear { opacity: 0.9; }
.hero__lens-img {
  left: calc(var(--lens-r) - var(--lx));
  top: calc(var(--lens-r) - var(--ly));
  width: var(--hero-w, 100vw);
  height: var(--hero-h, 100svh);
}
/* the rim: a hairline circle put through #rift-ring, which warps it, splits its channels and lights it red */
.hero__lens-ring {
  position: absolute;
  inset: 0;
  border: 2px solid rgba(255, 236, 236, 0.85);
  border-radius: 50%;
  filter: url(#rift-ring);
  animation: rim-flicker 3.4s steps(1, end) infinite;
}
/* no pointer, no lens: the portrait stands on its own */
@media (hover: none), (pointer: coarse) {
  .hero__lens { display: none; }
}
.rift-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
/* the headline is split into letters by JS; a letter is civilian (wide, light) until the lens is over it, and
   takes the suit's width and weight while it is */
.display--hero .ch { display: inline-block; white-space: pre; font-stretch: inherit; font-weight: inherit; }
.display--hero .ch.is-suit { color: #fff; text-shadow: 0 0 calc(6 * var(--u)) rgba(255, 70, 80, 0.55); }
.hero__inner {
  height: 100%;
  display: flex;
  align-items: center;
  padding-top: var(--header-h);
}
.hero__copy {
  position: relative;
  z-index: 1;
  padding-left: calc(55 * var(--u));
  width: calc(360 * var(--u));
}
.hero__copy .eyebrow { margin-bottom: calc(6.5 * var(--u)); }
.hero__copy .display { margin-bottom: calc(11 * var(--u)); }
.hero__copy .lede { margin-bottom: calc(18 * var(--u)); }
.hero__copy .actions { margin-bottom: calc(18 * var(--u)); }

.hero__note { right: calc(45 * var(--u)); bottom: 14%; font-size: calc(8.4 * var(--u)); gap: calc(4.4 * var(--u)); }

/* ==========================================================================
   2. Feature strip
   ========================================================================== */

.strip {
  position: relative;
  z-index: 2;
  background: var(--black);
  border-top: 1px solid var(--line-strong);
  border-bottom: 1px solid var(--line-strong);
}
.strip__list {
  display: grid;
  grid-template-columns: repeat(4, calc(200 * var(--u)));
  padding-left: calc(32 * var(--u));
  height: calc(75 * var(--u));
}
.feature {
  position: relative;
  display: flex;
  align-items: center;
  gap: calc(20 * var(--u));
  padding-left: calc(21 * var(--u));
}
.feature:first-child { padding-left: calc(20 * var(--u)); }
.feature + .feature::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(11 * var(--u));
  bottom: calc(11 * var(--u));
  width: 1px;
  background: var(--line-strong);
}
.feature__icon {
  flex: none;
  width: calc(36 * var(--u));
  height: calc(36 * var(--u));
  fill: none;
  stroke: #d4d6d8;
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.feature__title {
  font-size: calc(6.8 * var(--u));
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: #eef0f1;
  margin-bottom: calc(4.5 * var(--u));
  white-space: nowrap;
}
.feature__desc {
  font-size: calc(8.3 * var(--u));
  line-height: calc(12 * var(--u));
  color: #b6b9bc;
}

/* ==========================================================================
   3. Pinned scroll stage: hero.glb lowers on its thread → City
   All stage variables are written by src/hero/main.js from one progress value.
   Defaults describe the completed city so the page still reads without JS.
   ========================================================================== */

.transition {
  position: relative;
  height: var(--stage-track);
  background: var(--black);
  --p: 1;
  --dust-o: 0;
  --city-o: 1; --city-s: 1;
  --ui-o: 1;   --ui-y: 0px;
  --beam-b: 13.8%;
  --beam-o: 1;
  --fig-o: 1;
}
.transition__end { position: absolute; left: 0; bottom: 100svh; width: 1px; height: 1px; }

.stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--black);
}
.stage__inner { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }

.layer { position: absolute; inset: 0; }
.layer__img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; }

/* z1 — city */
.layer--city {
  z-index: 1;
  opacity: var(--city-o);
  transform: scale(var(--city-s));
  transform-origin: 50% 60%;
  will-change: opacity, transform;
}
.layer--city .layer__img { object-position: 40% 55%; filter: brightness(0.8) saturate(0.95); }
.layer--city::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, #000 0%, rgba(0,0,0,0.85) 6%, rgba(0,0,0,0.4) 16%, rgba(0,0,0,0) 30%),
    linear-gradient(to right, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.35) 22%, rgba(0,0,0,0) 40%),
    linear-gradient(to top, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0) 16%);
}

/* z2 — atmospheric particles */
.layer--dust {
  z-index: 2;
  opacity: var(--dust-o);
  will-change: opacity;
}
.layer--dust .layer__img { object-position: 60% 40%; opacity: 0.55; }

/* z3 — the live world of the fall (src/game/preview.js), hidden until the release */
.stage__live {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  display: block;
  visibility: hidden;
  pointer-events: none;
}

/* z4 — hero.glb */
.stage__canvas {
  position: absolute;
  inset: 0;
  z-index: 4;
  width: 100%;
  height: 100%;
  display: block;
  opacity: var(--fig-o);
  pointer-events: none;
}

/* z5 — the thread the figure lowers itself on.
   Coloured and shaded like the rope on hero.glb (charcoal core, lighter band right of centre,
   cool rim on the left) so the two read as one continuous line. */
.beam {
  position: absolute;
  z-index: 5;
  left: calc(501.6 * var(--u));
  top: 0;
  height: var(--beam-b);
  width: calc(4.2 * var(--u));
  margin-left: calc(-1.3 * var(--u));
  opacity: var(--beam-o);
  background: linear-gradient(to right, #1c1f2c 0%, #232324 18%, #2a2a2b 42%, #343436 62%, #2a2a2c 80%, #15171c 100%);
  box-shadow: 0 0 calc(3 * var(--u)) rgba(0, 0, 0, 0.55);
  pointer-events: none;
  will-change: height, opacity;
}

/* z6 — city typography / UI */
.city-ui {
  z-index: 6;
  opacity: var(--ui-o);
  transform: translateY(var(--ui-y));
  pointer-events: none;
  will-change: opacity, transform;
}
.city-ui.is-live { pointer-events: auto; }

.subnav {
  position: absolute;
  left: calc(31 * var(--u));
  top: 6%;
  display: flex;
  gap: calc(36 * var(--u));
}
.subnav__link {
  position: relative;
  padding-bottom: calc(9 * var(--u));
  font-size: calc(10.3 * var(--u));
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #c3c6c9;
  transition: color var(--dur) var(--ease);
}
.subnav__link:hover, .subnav__link.is-active { color: #fff; }
.subnav__link.is-active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(1.8 * var(--u));
  background: var(--accent-red);
  box-shadow: 0 0 calc(5 * var(--u)) rgba(214, 35, 43, 0.7);
}

.city__note-top { left: calc(750 * var(--u)); top: 12%; font-size: calc(6.9 * var(--u)); }
.city__note-top::before { top: calc(-6 * var(--u)); bottom: calc(-40 * var(--u)); }

.city__copy {
  position: absolute;
  left: calc(45 * var(--u));
  top: 36%;
  width: calc(380 * var(--u));
  height: calc(250 * var(--u));
}
.kicker {
  font-size: calc(10.5 * var(--u));
  line-height: calc(17 * var(--u));
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #dcdedf;
  white-space: nowrap;
}
.kicker--sub {
  position: absolute;
  left: 0;
  top: calc(167 * var(--u));
  font-size: calc(10.2 * var(--u));
  line-height: calc(18 * var(--u));
  letter-spacing: 0.22em;
  color: #d3d5d7;
}
.city__wordmark {
  position: absolute;
  left: calc(-7 * var(--u));
  top: calc(-2 * var(--u));
  width: calc(350 * var(--u));
  height: auto;
  max-width: none;
  filter: drop-shadow(0 calc(2 * var(--u)) calc(8 * var(--u)) rgba(0, 0, 0, 0.8));
}
.city__copy .actions { position: absolute; left: 0; top: calc(218 * var(--u)); }

.city__foot {
  position: absolute;
  left: calc(50 * var(--u));
  bottom: 6%;
  line-height: calc(11 * var(--u));
  font-size: calc(8 * var(--u));
  letter-spacing: 0.3em;
  color: #b9bcbf;
}
.dash {
  display: inline-block;
  vertical-align: middle;
  width: calc(20 * var(--u));
  height: calc(1.6 * var(--u));
  background: var(--accent-red);
  margin: calc(-1 * var(--u)) calc(13 * var(--u)) 0 0;
  box-shadow: 0 0 calc(4 * var(--u)) rgba(214, 35, 43, 0.6);
}
.city__note-bottom { right: calc(44 * var(--u)); bottom: 5.5%; gap: calc(7 * var(--u)); font-size: calc(6 * var(--u)); color: #c9cccf; }
.city__note-bottom::before { top: calc(-6 * var(--u)); bottom: calc(-10 * var(--u)); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .btn, .nav__link, .nav__link::after, .subnav__link { transition: none; }
  .hero__lens-ring { animation: none; }
}

/* ==========================================================================
   Responsive
   ========================================================================== */

/* ---- Tablet & below: switch from proportional units to a flowing layout ---- */
@media (max-width: 1100px) {
  .site { --u: 1.3px; }
  :root { --header-h: 60px; }
  .header__inner, .hero__inner, .strip__list, .stage__inner { max-width: none; }

  .header { height: 60px; }
  .logo { left: var(--page-pad); width: 150px; }
  .logo img { top: -18px; }
  .nav { left: 50%; transform: translateX(-50%); }
  .nav__list { gap: 26px; }
  .nav__link { font-size: 10px; letter-spacing: 0.18em; }
  .nav__link::after { bottom: -12px; height: 2px; }
  .header__cta { right: var(--page-pad); top: 14px; height: 32px; font-size: 9.5px; padding: 0 16px; }

  .display { font-size: 38px; line-height: 1.04; }
  .display--hero { font-size: 40px; }
  .eyebrow { font-size: 11px; line-height: 1.2; }
  .lede { font-size: 16px; line-height: 1.5; }
  .lede br { display: none; }
  .btn { height: 40px; font-size: 10.5px; padding: 0 22px; border-radius: 3px; }
  .btn--sm { height: 32px; }
  .play { width: 15px; height: 15px; }
  .play::after { border-width: 3px 0 3px 5px; }
  .tagline, .city__foot { font-size: 9.5px; }
  .side-note { font-size: 9px; gap: 7px; }
  .side-note--loose { gap: 16px; }

  /* hero */
  .hero__base, .hero__lens-img { object-position: 68% 50%; }
  .panel-card { padding: 30px 26px 26px; }
  .hero__copy { width: min(560px, 62%); padding-left: var(--page-pad); }
  .hero__copy .eyebrow { margin-bottom: 14px; }
  .hero__copy .display { margin-bottom: 22px; }
  .hero__copy .lede { margin-bottom: 30px; }
  .hero__copy .actions { margin-bottom: 30px; gap: 14px; }
  .hero__note { right: var(--page-pad); bottom: 60px; }

  /* strip */
  .strip__list { grid-template-columns: repeat(2, 1fr); height: auto; padding: 0 var(--page-pad); }
  .feature { padding: 26px 20px 26px 0; gap: 20px; }
  .feature:first-child { padding-left: 0; }
  .feature:nth-child(even) { padding-left: 26px; }
  .feature:nth-child(n+3) { border-top: 1px solid var(--line); }
  .feature + .feature::before { display: none; }
  .feature:nth-child(even)::before { display: block; top: 16px; bottom: 16px; }
  .feature__icon { width: 44px; height: 44px; }
  .feature__title { font-size: 10px; margin-bottom: 6px; }
  .feature__desc { font-size: 13.5px; line-height: 1.4; }
  .feature__desc br { display: none; }

  /* stage */
  .beam { left: 76%; width: 6px; margin-left: -3px; }

  /* city UI */
  .subnav { left: var(--page-pad); top: 7%; gap: 40px; }
  .subnav__link { font-size: 12px; padding-bottom: 12px; }
  .city__note-top { left: auto; right: var(--page-pad); top: 15%; }
  .city__copy { left: 0; top: auto; bottom: 13%; width: min(560px, 80%); height: auto; padding-left: var(--page-pad); }
  .kicker { font-size: 14px; line-height: 1.9; }
  .kicker--sub { position: static; font-size: 13px; line-height: 1.9; }
  .city__wordmark { position: static; width: min(520px, 90%); margin: -50px 0 -60px -6%; }
  .city__copy .actions { position: static; margin-top: 22px; }
  .city__foot { left: var(--page-pad); bottom: 4.5%; }
  .dash { width: 26px; height: 2px; margin-right: 16px; }
  .city__note-bottom { right: var(--page-pad); bottom: 4%; gap: 9px; }
}

/* ---- Mobile: compact menu, copy kept clear of the figure ---- */
@media (max-width: 720px) {
  :root { --page-pad: 22px; --header-h: 56px; --stage-track: 180vh; }

  .header { height: 56px; }
  .logo { width: 128px; }
  .logo img { top: -15px; }
  .header__cta { display: none; }
  .header__cta--mobile { display: inline-flex; position: static; margin-top: 26px; height: 42px; }

  .menu-toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
    position: absolute;
    right: var(--page-pad);
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    padding: 0 10px;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 3px;
    cursor: pointer;
  }
  .menu-toggle span { display: block; height: 1px; background: #fff; transition: transform var(--dur) var(--ease); }
  .menu-toggle[aria-expanded="true"] span:first-child { transform: translateY(3.5px) rotate(45deg); }
  .menu-toggle[aria-expanded="true"] span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

  .nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: auto;
    transform: none;
    padding: 12px var(--page-pad) 30px;
    background: #020304;
    border-bottom: 1px solid var(--line);
    z-index: 30;
    display: none;
  }
  .nav.is-open { display: block; }
  .nav__list { flex-direction: column; align-items: flex-start; gap: 0; height: auto; }
  .nav__list li { width: 100%; border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
  .nav__link { display: block; padding: 16px 0; font-size: 11px; }
  .nav__link::after { display: none; }

  .display { font-size: clamp(26px, 7.6vw, 34px); }
  .display--hero { font-size: clamp(28px, 8.4vw, 36px); }
  .lede { font-size: 15px; }

  /* hero: portrait in the upper half, copy anchored to the bottom */
  .hero { min-height: 640px; }
  .hero__base, .hero__lens-img { object-position: 60% 50%; }
  /* the copy is anchored to the bottom here, so the glass grades up the frame instead of across it */
  .hero__glass {
    background:
      linear-gradient(to top, rgba(2, 3, 4, 0.95) 0%, rgba(2, 3, 4, 0.86) 34%, rgba(2, 3, 4, 0.44) 62%, rgba(2, 3, 4, 0.4) 100%),
      radial-gradient(120% 70% at 55% 28%, rgba(2, 3, 4, 0) 32%, rgba(2, 3, 4, 0.55) 100%);
  }
  .hero__inner { align-items: flex-end; padding-bottom: 9vh; }
  .hero__copy { width: 100%; max-width: 480px; padding-right: var(--page-pad); }
  .hero__copy .actions { flex-wrap: wrap; }
  .hero__note { display: none; }
  .tagline { white-space: normal; line-height: 1.8; }

  .strip__list { grid-template-columns: 1fr; }
  .feature, .feature:nth-child(even) { padding: 22px 0; }
  .feature:nth-child(n+2) { border-top: 1px solid var(--line); }
  .feature::before { display: none !important; }

  .beam { left: 74%; }

  .subnav { top: 5%; gap: 28px; }
  .subnav__link { font-size: 11px; }
  .city__note-top { display: none; }
  .city__copy { bottom: 11%; width: 100%; max-width: 480px; padding-right: var(--page-pad); }
  .city__wordmark { width: 100%; margin: -34px 0 -44px -4%; }
  .city__note-bottom { display: none; }
  .city__foot { bottom: 3.5%; font-size: 8.5px; letter-spacing: 0.22em; }
  .city__foot .dash { width: 18px; margin-right: 10px; }
}

/* ==========================================================================
   Features / Media panels (fixed overlays, opened from the header and the
   stage's chapter menu; Escape or the backdrop closes them)
   ========================================================================== */

/* index.html asks for viewport-fit=cover so the rift reaches the screen edges, which also lays the panel out under
   the display cutout. The card — and the close button in its corner, the only pointer way out of the panel — keeps
   the cutout's distance; the insets are 0 px on a screen without one, which leaves every desktop untouched. */
/* the -webkit- prefix as well as the plain property: WebKit only dropped the prefix requirement in Safari 18, and
   the fill behind it is opaque enough that losing the blur on an older one is a softer look, not a broken panel */
.panel { position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; background: rgba(2, 3, 4, 0.78); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  padding: calc(24px + env(safe-area-inset-top, 0px)) calc(24px + env(safe-area-inset-right, 0px)) calc(24px + env(safe-area-inset-bottom, 0px)) calc(24px + env(safe-area-inset-left, 0px)); }
.panel[hidden] { display: none; }
.panel-card {
  position: relative; width: min(920px, 100%); overflow: auto; padding: 40px 44px 36px;
  max-height: calc(100vh - 48px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  background: linear-gradient(180deg, rgba(14, 16, 20, 0.97), rgba(4, 5, 7, 0.98));
  border: 1px solid var(--line-strong);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.panel h2 {
  margin: 0 0 22px;
  font-family: var(--font-display); font-weight: 300; font-stretch: 137%;
  font-size: clamp(26px, 2.6vw, 36px); line-height: 1; letter-spacing: 0.04em; text-transform: uppercase;
}
.panel h2::after { content: ""; display: block; width: 48px; height: 2px; margin-top: 14px; background: var(--accent-red); box-shadow: 0 0 6px rgba(232, 32, 42, 0.6); }
.panel .note { margin: -8px 0 20px; color: var(--text-2); }
.close { position: absolute; top: 14px; right: 16px; width: 40px; height: 40px; border: 1px solid var(--line); border-radius: 3px; background: transparent; color: var(--text); font-size: 24px; line-height: 1; cursor: pointer; }
.close:hover, .close:focus-visible { border-color: #fff; color: #fff; outline: none; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px 28px; margin: 0 0 30px; }
.grid li { color: var(--text-2); font-size: 14.5px; line-height: 1.5; }
.grid b { display: block; margin-bottom: 4px; color: #fff; font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; }
.shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
.shots figure { margin: 0; }
.shots img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border: 1px solid var(--line); }
.shots figcaption { margin-top: 8px; color: var(--text-2); font-size: 10.5px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; }
.panel .btn { height: 44px; padding: 0 22px; font-size: 11px; border-radius: 3px; }

/* ==========================================================================
   The fall. Clicking Play now adds html.is-falling: the composition is gone the same instant — header, hero, strip,
   thread, copy, buttons, panels — and only the stage remains, fixed over the viewport. With the live world ready
   (html.is-live, src/game/preview.js) the plates and the hanging figure go too: the game character dives through
   the real city. Without it the plates scale past the camera while the figure dives on its own (src/hero/figure.js).
   FALL.swapAt later the page navigates to the game; game.css carries the last frame into the live city through a
   cross-document view transition typed 'fall' (src/hero/main.js sets the type at pageswap).
   ========================================================================== */

@view-transition { navigation: auto; }
/* coming back from the game: a plain crossfade (the fall only runs into the game) */
::view-transition-old(root) { animation: 320ms var(--ease) both vt-fade-out; }
::view-transition-new(root) { animation: 320ms var(--ease) both vt-fade-in; }
@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in { from { opacity: 0; } }

:root { --fall-ease: cubic-bezier(0.55, 0, 1, 0.45); }
.is-falling { pointer-events: none; overflow: hidden; }
.is-falling body { overflow: hidden; }
/* the composition: gone at once, nothing fades or lingers */
.is-falling .header, .is-falling .hero, .is-falling .strip, .is-falling .panel, .is-falling .city-ui, .is-falling .beam, .is-falling .transition__end {
  visibility: hidden !important;
  transition: none !important;
  animation: none !important;
}
/* the stage takes the viewport wherever the page was scrolled */
.is-falling .stage { position: fixed; inset: 0; height: 100vh; height: 100svh; z-index: 100; }
/* the live world replaces the plates and the hanging figure */
.is-live .layer--city, .is-live .layer--dust, .is-live .stage__canvas { visibility: hidden !important; }
.is-live .stage__live { visibility: visible; }
/* no live world: the plates scale past the camera (transitions live under .is-falling only — outside the fall these
   layers are driven by scroll and must not lag) while the figure dives in its own canvas */
.is-falling:not(.is-live) .layer--city, .is-falling:not(.is-live) .layer--dust { transition: transform 900ms var(--fall-ease), filter 900ms var(--fall-ease); }
.is-falling:not(.is-live) .layer--city { transform: scale(calc(var(--city-s) * 1.6)) translateY(-4%); filter: blur(6px); }
.is-falling:not(.is-live) .layer--dust { transform: scale(1.9); filter: blur(4px); }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .is-falling .layer--city, .is-falling .layer--dust { transition: none; }
}
