/* ============================================================
   SCADE
   ============================================================ */

@font-face {
  font-family: 'Geist';
  src: url('../font/geist-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Scade Script';
  src: url('../font/script-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Scade Script';
  src: url('../font/script-latin-ext.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+2113, U+2C60-2C7F;
}
@font-face {
  font-family: 'Geist';
  src: url('../font/geist-latin-ext.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+2113, U+2C60-2C7F;
}

:root {
  /* soft charcoal — nothing here is pure black or pure white */
  --ground:   #141416;
  --raised:   #1e1e21;
  --raised-2: #232326;
  --edge:     rgba(255, 255, 255, 0.07);
  --edge-lit: rgba(255, 255, 255, 0.16);
  --spec: inset 0 1px 0 rgba(255, 255, 255, 0.055);

  /* the one accent: amber, how an edit timeline marks a selected range.
     10.3:1 on the ground, so it works as ink or as a surface. */
  --accent:      #ffb23f;
  --accent-lift: #ffc163;
  --on-accent:   #1d1303;

  --ink-1: #f5f5f7;   /* 17.6:1 */
  --ink-2: #a1a1a6;   /*  7.0:1 */
  --ink-3: #8e8e93;   /*  5.5:1 */

  /* SF Pro where it exists, the closest open face everywhere else */
  --sans: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display',
          'Geist', 'Segoe UI Variable Text', 'Segoe UI', system-ui, sans-serif;

  --r-md: 18px;
  --r-lg: 26px;
  --r-xl: 34px;
  --pill: 999px;
  --bar-h: 62px;

  --pad: clamp(22px, 5vw, 76px);
  --script: 'Scade Script', 'Segoe Script', cursive;
  --soft: cubic-bezier(0.32, 0.72, 0, 1);
  /* --soft leaves fast and coasts, which reads as quick however long it runs.
     The finder travels on a symmetric curve instead, so it eases out of one
     position and into the next. */
  --glide: cubic-bezier(0.45, 0, 0.22, 1);
  /* the one curve that overshoots, reserved for the cycling disc */
  --bounce: cubic-bezier(0.34, 1.46, 0.44, 1);

  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  background: var(--ground);
  scrollbar-color: #3a3a3c var(--ground);
  scrollbar-width: thin;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: rgba(245, 245, 247, 0.22); color: var(--ink-1); }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--ground); }
::-webkit-scrollbar-thumb { background: #3a3a3c; border-radius: var(--pill); border: 3px solid var(--ground); }
::-webkit-scrollbar-thumb:hover { background: #4d4d50; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 12px; }

img, video { display: block; max-width: 100%; }
h1, h2, h3, p { margin: 0; }

.skip {
  position: absolute; left: 16px; top: -60px; z-index: 100;
  background: var(--ink-1); color: var(--ground);
  padding: 12px 20px; border-radius: var(--pill);
  font-size: 15px; font-weight: 500; text-decoration: none;
}
.skip:focus { top: 16px; }

.wrap { width: 100%; max-width: 1180px; margin: 0 auto; padding-inline: var(--pad); }

/* ---------- controls ---------- */

.btn {
  appearance: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 14px 28px;
  border: 0; border-radius: var(--pill);
  font: inherit; font-size: 16px; font-weight: 500; letter-spacing: -0.012em;
  cursor: pointer; text-decoration: none;
  transition: background 240ms var(--soft), color 240ms var(--soft),
              transform 240ms var(--soft), opacity 240ms var(--soft);
}
.btn:active { transform: scale(0.97); }

.btn--soft { background: var(--raised-2); color: var(--ink-1); box-shadow: var(--spec); }
.btn--soft:hover, .btn--soft:focus-visible { background: #2d2d31; }

/* The one coloured thing on the page: a real glass control.
   Translucent blue over the ground, blurred backdrop, a specular rim that
   catches the light along the top, and weight at the bottom. */
.btn--glass {
  --tint: 255, 178, 63;
  position: relative;
  isolation: isolate;
  padding: 15px 32px;
  color: var(--on-accent);
  font-weight: 500;
  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.34) 0%,
      rgba(255, 255, 255, 0.09) 38%,
      rgba(255, 255, 255, 0) 62%),
    rgba(var(--tint), 0.9);
  -webkit-backdrop-filter: blur(22px) saturate(200%);
          backdrop-filter: blur(22px) saturate(200%);
  box-shadow:
    inset 0 -12px 22px -12px rgba(92, 52, 0, 0.5),
    0 1px 2px rgba(0, 0, 0, 0.32),
    0 12px 32px rgba(var(--tint), 0.26);
  transition: background 260ms var(--soft), box-shadow 320ms var(--soft),
              transform 240ms var(--soft);
}
.btn--glass > span { position: relative; z-index: 1; }

/* the lit edge: bright where the light lands, faint at the waist */
.btn--glass::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.88) 0%,
    rgba(255, 255, 255, 0.30) 34%,
    rgba(255, 255, 255, 0.12) 58%,
    rgba(255, 255, 255, 0.42) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  pointer-events: none;
}

.btn--glass:hover, .btn--glass:focus-visible {
  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.4) 0%,
      rgba(255, 255, 255, 0.11) 38%,
      rgba(255, 255, 255, 0) 62%),
    rgba(var(--tint), 1);
  box-shadow:
    inset 0 -12px 22px -12px rgba(92, 52, 0, 0.42),
    0 1px 2px rgba(0, 0, 0, 0.32),
    0 16px 42px rgba(var(--tint), 0.38);
}
.btn--glass:focus-visible { outline-color: var(--accent-lift); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn:disabled:active { transform: none; }

.btn svg { width: 18px; height: 18px; flex: none; }

/* ---------- header ---------- */

.bar {
  position: sticky; top: 0; z-index: 50;
  background: rgba(20, 20, 22, 0.78);
  -webkit-backdrop-filter: saturate(160%) blur(20px);
  backdrop-filter: saturate(160%) blur(20px);
}
.bar-in { display: flex; align-items: center; gap: 18px; height: 62px; }
.mark {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 19px; font-weight: 600; letter-spacing: -0.021em;
  color: var(--ink-1); text-decoration: none;
}
/* the light disc reads whether the file is transparent or sits on white */
.avatar {
  width: 32px; height: 32px; flex: none;
  border-radius: var(--pill);
  /* same disc as the one on the script, so both memoji read as one mark */
  background: linear-gradient(180deg, #ffffff 0%, #ffa246 100%);
  /* The head sits inside the disc, not cropped by it: 3px of padding shrinks the
     image to 26px (81%, the same proportion as the hero's 82%) while the
     gradient keeps painting the full 32px circle under the padding. Pixel
     padding is safe here because the img is its own box — unlike percentage
     padding on the hero, which resolved against a 648px parent. */
  padding: 3px;
  object-fit: contain;
  box-shadow: var(--spec), 0 1px 3px rgba(0, 0, 0, 0.42);
}
.bar-nav { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.bar-nav a:not(.btn) {
  padding: 9px 15px; border-radius: var(--pill);
  font-size: 15px; color: var(--ink-2); text-decoration: none;
  transition: color 200ms var(--soft), background 200ms var(--soft);
}
.bar-nav a:not(.btn):hover, .bar-nav a:not(.btn):focus-visible { color: var(--ink-1); background: var(--raised); }
.bar-nav .btn { padding: 10px 22px; font-size: 15px; margin-left: 6px; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  overflow: clip;
  padding: 0 0 clamp(50px, 9vh, 100px);
}
/* load the page and this is all you get: the name, centred in what is left
   of the viewport under the bar. The work starts one scroll down. */
.hero-intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: calc(100svh - var(--bar-h));
  padding-block: clamp(24px, 5vh, 64px);
}
.hero-say {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* ---------- the name ---------- */

.name {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: clamp(10px, 1.4vw, 22px);
  margin: 0;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--ink-1);
}
.name-hi {
  flex: none;
  white-space: nowrap;
  font-size: clamp(28px, 8vw, 96px);
  font-weight: 250;
  letter-spacing: 0.01em;
}
.name-mark {
  position: relative;
  display: inline-block;
  flex: none;
  white-space: nowrap;
  font-family: var(--script);
  font-weight: 600;
  font-size: clamp(64px, 24vw, 290px);
  line-height: 0.92;
  letter-spacing: 0.005em;
  padding-right: 0.06em;
}
/* the face sits on the word, over the middle of it */
.name-face {
  position: absolute;
  /* the 'd' spans 60%-81.9% of the word; its bowl sits at the front of that
     advance and the ascender rises behind it, so aim left of the letter's
     own centre to land on the round part rather than the stem */
  left: 66%;
  top: 63%;
  translate: -50% -50%;
  width: clamp(36px, 9.5vw, 116px);
  height: auto;
  aspect-ratio: 1;
  border-radius: var(--pill);
  /* lands on amber at the foot so the face ties into the accent */
  background: linear-gradient(180deg, #ffffff 0%, #ffa246 100%);
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* the disc is the wrapper and the face sits inside it — percentage padding on
   the image itself would resolve against the script span, not the disc */
.name-face img {
  width: 82%;
  height: 82%;
  object-fit: contain;
}

.tagline {
  margin-top: clamp(24px, 4vh, 52px);
  /* wide enough to run on one line from tablet up; it only wraps on a phone */
  max-width: 100%;
  font-size: clamp(17px, 1.7vw, 24px);
  font-weight: 300;
  line-height: 1.24;
  letter-spacing: -0.018em;
  color: var(--ink-1);
  text-wrap: balance;
}

/* ---------- ambient light ----------
   Two soft light sources drifting behind the copy. On a charcoal ground a dark
   object reads as a hole, so the ambient element here is light, not a shape:
   no edge to look broken, and it moves slowly enough to notice only in passing. */

.glow {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: clip;
}
.hero .wrap { position: relative; z-index: 1; }

.gl {
  position: absolute;
  display: block;
  border-radius: var(--pill);
  filter: blur(46px);
}
.gl--a {
  top: 4%; right: 6%;
  width: clamp(320px, 34vw, 540px); aspect-ratio: 1;
  background: radial-gradient(circle at 50% 50%,
    rgba(255, 255, 255, 0.085) 0%,
    rgba(255, 255, 255, 0.035) 42%,
    rgba(255, 255, 255, 0) 70%);
  animation: drift-a 34s ease-in-out infinite;
}
.gl--b {
  bottom: -6%; right: 26%;
  width: clamp(240px, 26vw, 400px); aspect-ratio: 1;
  background: radial-gradient(circle at 50% 50%,
    rgba(255, 255, 255, 0.055) 0%,
    rgba(255, 255, 255, 0.02) 46%,
    rgba(255, 255, 255, 0) 72%);
  animation: drift-b 27s ease-in-out infinite;
}

@keyframes drift-a {
  0%, 100% { translate: 0 0;      scale: 1; }
  50%      { translate: -46px 34px; scale: 1.1; }
}
@keyframes drift-b {
  0%, 100% { translate: 0 0;      scale: 1.06; }
  50%      { translate: 38px -30px; scale: 0.94; }
}

/* ---------- why short form ----------
   The one section on the page that argues instead of showing. It sits between
   the name and the work because a visitor who is not yet sure short form is
   worth paying for will not be talked round by more clips. Centred, because it
   inherits the hero's axis; the catalogue sections below go back to left.
   ---------------------------------------------------------------------- */

.sec--why { padding-top: clamp(72px, 12vh, 150px); }

.why { text-align: center; }
.why h2 {
  margin-inline: auto;
  max-width: 26ch;
  font-size: clamp(30px, 4.3vw, 58px);
  line-height: 1.07;
  /* Display tracking. Neither SF Pro nor Geist carries a width axis, so this is
     the only way to compress the line; `font-stretch` and `wdth` are inert on
     both and were measured as such. Small sizes get it back at the 760px
     breakpoint, because the same ratio reads tighter the smaller the type. */
  letter-spacing: -0.048em;
  font-weight: 600;
  color: var(--ink-1);
  text-wrap: balance;
}
/* The setup dims so the claim after it carries the weight. It is a block, not
   an inline span: left to balance, the wrap put the full stop mid-line and the
   two tones read as an accident instead of a structure. */
.why h2 .why-setup { display: block; color: var(--ink-3); }
/* The turn takes the shared display gradient (see `.display-run` below). It
   stays `inline` so that when it wraps on a phone each line gets its own
   gradient — as a block the single run would span both lines and leave the
   first white and the second amber. */
.why h2 .why-turn { display: inline; }

.why-lede {
  margin: clamp(16px, 2.2vh, 26px) auto 0;
  max-width: 54ch;
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.58;
  letter-spacing: -0.012em;
  color: var(--ink-2);
}

/* Proof on the left, reasons on the right. The screen and the stack are near
   enough the same height that the row reads as one object rather than a big
   picture with notes stuck beside it. */
.why-row {
  margin-top: clamp(36px, 5.5vh, 72px);
  display: grid;
  /* Measured, not picked: at 1.25/0.75 the screen is as large as it can get
     while the cards still hold their paragraphs to two lines, and the two
     columns come closest in height. Widening the screen further tips the
     narrower cards to three lines and the stack grows again. */
  grid-template-columns: minmax(0, 1.16fr) minmax(0, 0.84fr);
  align-items: stretch;
  gap: clamp(18px, 2.4vw, 38px);
  text-align: left;
}
/* Inside the row the screen fills its column instead of centring in the page,
   and it takes its height from the card stack beside it so the two columns
   share a top and a bottom edge. That costs the strict 16:9 — see the note in
   the section text — which is why the aspect is released only in here. */
.why-row .find { margin: 0; width: 100%; max-width: none; height: 100%; }
.why-row .screen { height: 100%; aspect-ratio: auto; }

/* three parallel claims. No numerals and no accent: amber is spoken for, and
   numbering three things implies an order they do not have. */
.why-list {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.1vw, 15px);
  list-style: none;
  padding: 0;
}
.why-list li {
  padding: clamp(17px, 1.9vw, 25px) clamp(19px, 2.1vw, 29px);
  border-radius: var(--r-lg);
  background: var(--raised);
  box-shadow: var(--spec), 0 1px 2px rgba(0, 0, 0, 0.24), 0 10px 30px rgba(0, 0, 0, 0.22);
}
/* The card titles run the same white-and-amber, inverted: amber at the top,
   white at the baseline, so they answer the headline above rather than repeat
   it. Stops are pulled in from 0/100 because `background-clip: text` paints the
   whole line box, leading included — at 0 and 100 neither end reaches the
   glyphs. Both ends stay light on Raised, so contrast holds all the way down. */
.why-list h3 {
  font-size: clamp(16px, 1.3vw, 18px);
  line-height: 1.32;
  letter-spacing: -0.02em;
  font-weight: 600;
  background: linear-gradient(180deg, var(--accent) 12%, #ffffff 74%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
}
.why-list p {
  margin-top: 9px;
  font-size: clamp(14.5px, 1.15vw, 16.5px);
  line-height: 1.62;
  color: var(--ink-3);
}


/* ---------- the finder ----------
   The pitch is that the useful part of a stream is tiny and finding it is the
   work. So the hero shows that rather than claiming it: a screen carrying one
   long scrubber, and a short segment that hunts across it, breathing in length
   while it looks, until it stops on one moment and goes amber.
   The box is what makes the drifting shapes read as footage instead of debris. */

.find {
  margin: clamp(36px, 5.5vh, 72px) auto 0;
  width: 100%;
  max-width: clamp(400px, 60vw, 850px);
}

.screen {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-lg);
  background: var(--raised);
  overflow: hidden;
  box-shadow:
    var(--spec),
    0 2px 8px rgba(0, 0, 0, 0.34),
    0 26px 60px rgba(0, 0, 0, 0.44);
}

/* stand-in for footage: a talking head, which is most of what he cuts.
   Silhouette only — no face, no mouth, nothing that has to be animated
   convincingly to avoid looking wrong. */
.screen-art { position: absolute; inset: 0; }

.backlight {
  position: absolute;
  left: 50%; top: 10%;
  translate: -50% 0;
  width: 64%; aspect-ratio: 1;
  border-radius: var(--pill);
  background: radial-gradient(circle at 50% 50%,
    rgba(255, 255, 255, 0.15) 0%,
    rgba(255, 255, 255, 0.05) 45%,
    rgba(255, 255, 255, 0) 72%);
  filter: blur(14px);
  animation: lamp 7s ease-in-out infinite;
}

/* Sized from the frame's HEIGHT, not its width. The rule was always "78% of
   the frame", and while the screen was locked to 16:9 a width of 36% happened
   to mean the same thing. Once the frame takes its height from the cards next
   to it that stopped being true and the figure shrank down the frame, so the
   intent is now written directly. The aspect below is the figure's own:
   head 0.56W + gap 0.045W + body 0.617W = 1.222W tall, so 1 / 1.222 = 0.818.
   At 16:9 this resolves to a 36%-wide figure, exactly as before. */
.fig {
  position: absolute;
  left: 50%; bottom: 0;
  translate: -50% 0;
  height: 78%;
  aspect-ratio: 0.818;
  display: block;
}
.fig-head,
.fig-body {
  display: block;
  background: rgba(255, 255, 255, 0.93);
}
.fig-head {
  width: 56%;
  aspect-ratio: 1;
  margin: 0 auto;
  border-radius: var(--pill);
  box-shadow: 0 0 34px rgba(255, 255, 255, 0.35);
  transform-origin: 50% 120%;
  animation: nod 3.6s ease-in-out infinite;
}
.fig-body {
  width: 100%;
  aspect-ratio: 1.62;
  margin-top: 4.5%;
  border-radius: 50% 50% 0 0 / 78% 78% 0 0;
  box-shadow: 0 0 40px rgba(255, 255, 255, 0.22);
  transform-origin: 50% 100%;
  animation: sway 5.2s ease-in-out infinite;
}

/* the small, irregular movement of someone mid-sentence */
@keyframes nod {
  0%, 100% { translate: 0 0;      rotate: -1.6deg; }
  38%      { translate: 0 -2.5%;  rotate:  1.4deg; }
  64%      { translate: 0 1.5%;   rotate: -0.4deg; }
}
@keyframes sway {
  0%, 100% { translate: 0 0;    scale: 1; }
  50%      { translate: 0 0.8%; scale: 1.015; }
}
@keyframes lamp {
  0%, 100% { opacity: 0.8;  scale: 1; }
  50%      { opacity: 1;    scale: 1.07; }
}

/* the player's own furniture */
.screen-ui {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: clamp(40px, 13%, 76px) clamp(14px, 3.6%, 26px) clamp(14px, 3.6%, 26px);
  background: linear-gradient(180deg,
    rgba(20, 20, 22, 0) 0%,
    rgba(20, 20, 22, 0.42) 40%,
    rgba(20, 20, 22, 0.82) 74%,
    rgba(20, 20, 22, 0.9) 100%);
}
/* the source label sits in the corner, the way a broadcast bug does */
.find-a {
  position: absolute;
  top: clamp(14px, 6.4%, 26px);
  left: clamp(14px, 3.6%, 26px);
  z-index: 2;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ink-3);
}
.find-scan { position: relative; padding-top: 26px; }

/* the caption rides the marker and changes what it says when the search ends */
.find-b {
  position: absolute;
  top: 0; left: 24%;
  translate: -50% 0;
  white-space: nowrap;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--ink-1);
  /* it crosses the lit figure, so it carries its own separation */
  text-shadow: 0 1px 12px rgba(10, 10, 12, 0.7);
  opacity: 0.68;
  /* only the position eases. The words and the gradient change on one beat,
     so fading the colour would leave the new text grey for a quarter second. */
  transition: left 980ms var(--glide), opacity 420ms var(--glide);
}
.find-b.found {
  /* white into amber, the same run the memoji disc makes; white holds the
     top third so the letterforms never go muddy */
  background: linear-gradient(180deg, #ffffff 0%, #ffffff 34%, var(--accent) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  opacity: 1;
}

.find-track {
  position: relative;
  height: 5px;
  border-radius: var(--pill);
  background: rgba(255, 255, 255, 0.16);
}
.find-mark {
  position: absolute;
  top: 0; bottom: 0; left: 24%;
  translate: -50% 0;
  width: 4.5%;
  border-radius: var(--pill);
  background: var(--ink-1);
  opacity: 0.55;
  box-shadow: 0 0 16px rgba(255, 255, 255, 0.26);
  transition: left 980ms var(--glide), width 620ms var(--glide),
              opacity 480ms var(--glide), background-color 560ms var(--glide),
              box-shadow 560ms var(--glide);
}
/* while it is still looking, the segment breathes along its length */
.find-mark.seeking { animation: seek 2.8s ease-in-out infinite; }
/* anchored at the found width at both ends, so starting the breathing on a
   new cycle does not pop the segment to a different size */
@keyframes seek {
  0%, 100% { width: 5.6%; }
  30%      { width: 3.2%; }
  70%      { width: 6.8%; }
}
/* and when it finds the one, it stops breathing and turns amber */
.find-mark.found {
  width: 5.6%;
  opacity: 1;
  background: var(--accent);
  box-shadow: 0 0 22px rgba(255, 178, 63, 0.6);
}

/* the headline and the cycling disc share a row; the disc drops below the
   headline rather than squeezing it when there is not room for both */
.title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(16px, 2vw, 28px);
}
/* Two things at once: flex-wrap decides from the base size, so the headline
   needs one small enough to share a line on desktop and large enough to wrap
   on a phone — and it must not grow, or its box runs on past the last word
   and opens a gap the disc cannot close. */
.title-row h1 {
  flex: 0 1 15.6ch;
  min-width: 0;
}

.cycle {
  position: relative;
  flex: none;
  display: block;
  width: clamp(84px, 9.5vw, 136px);
  aspect-ratio: 1;
  border-radius: var(--pill);
  /* dark, because one of these marks is itself a black disc — a light
     ground would ring it in white */
  background: var(--raised-2);
  overflow: hidden;
  box-shadow:
    var(--spec),
    0 2px 8px rgba(0, 0, 0, 0.3),
    0 18px 44px rgba(0, 0, 0, 0.36);
}
/* each mark rides up into the circle and the last one keeps going out the top,
   so the cycle reads as a mechanism rather than a dissolve */
.cycle img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  translate: 0 62%;
  scale: 0.88;
  transition: opacity 260ms var(--soft),
              translate 560ms var(--bounce),
              scale 560ms var(--bounce);
}
.cycle img.on {
  opacity: 1;
  translate: 0 0;
  scale: 1;
}
.cycle img.out {
  opacity: 0;
  translate: 0 -62%;
  scale: 0.88;
  transition: opacity 300ms var(--soft),
              translate 420ms var(--soft),
              scale 420ms var(--soft);
}

.hero h1 {
  max-width: 19ch;
  font-size: clamp(40px, 6.2vw, 76px);
  line-height: 1.07;
  letter-spacing: -0.035em;
  font-weight: 600;
  color: var(--ink-1);
  text-wrap: balance;
}

.tags {
  margin-top: clamp(28px, 4vh, 42px);
  display: flex; flex-wrap: wrap; gap: 10px;
  list-style: none; padding: 0;
}
.tags li {
  padding: 9px 17px;
  background: var(--raised);
  border-radius: var(--pill);
  box-shadow: var(--spec);
  font-size: 14.5px;
  color: var(--ink-2);
}

/* ---------- sections ---------- */

.sec { padding: clamp(56px, 9vh, 104px) 0 0; }

/* The 56ch cap used to sit on the whole block, which also throttled the lede.
   The heading needs no cap — every one of them is two words — so the measure
   now lives on the paragraph, where it can be set for reading rather than
   inherited from the heading. */
.sec-head { max-width: 100%; }
.sec-head h2 {
  font-size: clamp(28px, 3.4vw, 42px);
  line-height: 1.14;
  letter-spacing: -0.028em;
  font-weight: 600;
  text-wrap: balance;
}

/* ---- the display run -------------------------------------------------
   White into amber, cut into the glyphs. Every section heading wears it and
   so does the turn in the Why headline, from one declaration so the two can
   never drift apart. Stops are pulled off 0/100 because `background-clip:
   text` paints the whole line box, leading included: at 0 and 100 the amber
   lands past the descenders instead of at the baseline. `clone` gives each
   line of a wrapped heading its own run rather than splitting one across two.
   ---------------------------------------------------------------------- */
.sec-head h2,
.why h2 .why-turn {
  background: linear-gradient(180deg, #ffffff 0%, #ffffff 34%, var(--accent) 86%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
}
.sec-head p {
  margin-top: 14px;
  /* Runs the full content width: at 18px that is about 115 characters, so a
     150-character lede fills one line and spills a short tail onto a second
     rather than breaking into three even-looking ones. Capped in `ch` so an
     ultra-wide monitor does not stretch it past a readable measure. */
  max-width: min(100%, 108ch);
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.6;
  color: var(--ink-3);
  /* keeps a lede from ending on a one-word last line; ignored where unsupported */
  text-wrap: pretty;
}

/* ---- a section with nothing in it yet --------------------------------
   Shown in place of the grid whenever a list is empty. It is a real panel
   rather than an apology in small grey text: an empty section that looks
   unfinished reads worse than one that says plainly what is coming.
   ---------------------------------------------------------------------- */
.soon {
  margin-top: 26px;
  display: grid;
  place-items: center;
  gap: 10px;
  padding: clamp(46px, 9vh, 96px) clamp(24px, 5vw, 56px);
  border-radius: var(--r-xl);
  background: var(--raised);
  box-shadow: var(--spec), 0 1px 2px rgba(0, 0, 0, 0.24), 0 16px 44px rgba(0, 0, 0, 0.22);
  text-align: center;
}
/* no amber here: it marks what you can act on and what the finder found, and
   a status label is neither */
.soon-tag {
  font-size: clamp(18px, 1.7vw, 22px);
  font-weight: 600;
  letter-spacing: -0.022em;
  color: var(--ink-1);
}
.soon-say {
  max-width: 46ch;
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.6;
  color: var(--ink-3);
}

/* The honeypot. Off-screen rather than `display: none`, because the cruder
   bots skip anything that is plainly hidden and fill in everything else. */
.gotcha {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* ---------- players ---------- */

/* Grid, with the column count coming from the data rather than from the
   browser guessing. `auto-fit` counts tracks against the MAX track size when
   that is a fixed length, so a fixed 320px max could not shrink three cards
   into an 812px row and dropped one to a second line; a `1fr` max fixes the
   counting but stretches two cards to half the page each.

   Flex-wrap with `justify-content: center` was tried, to centre a short final
   row — five clips make a row of three and a row of two. It was worse: flex
   grows the items on a short line, so at 900px the two cards on row two came
   out 320px wide against 257px on row one, and cards of two sizes in one reel
   read as broken. A left-aligned final row is not a compromise here; once
   there are enough clips to form columns, the fourth card lining up under the
   first is the rhythm, and centring would break it. Two clips are a different
   case — no columns to align to — and `--cols` handles that by making the
   grid two wide and centring the whole thing. */
.reel {
  --cols: 3;
  --gap: clamp(16px, 2.2vw, 28px);
  margin: clamp(32px, 4.6vh, 52px) auto 0;
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gap);
  max-width: calc(var(--cols) * 320px + (var(--cols) - 1) * var(--gap));
}
.reel[data-count='1'] { --cols: 1; }
.reel[data-count='2'] { --cols: 2; }.reel--wide { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: none; }
/* the opener leads at full width; the rest follow beneath it */
.reel--wide > .piece:first-child { grid-column: 1 / -1; }

.piece { min-width: 0; }

.stage {
  position: relative;
  width: 100%;
  border-radius: var(--r-lg);
  background: var(--raised);
  overflow: hidden;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3), 0 18px 44px rgba(0, 0, 0, 0.34);
  transition: transform 420ms var(--soft), box-shadow 420ms var(--soft);
}
.stage--tall { aspect-ratio: 9 / 16; }
.stage--wide { aspect-ratio: 16 / 9; }

.piece:hover .stage {
  transform: translateY(-4px);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.34), 0 26px 60px rgba(0, 0, 0, 0.42);
}

.stage video, .stage .poster {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* The poster sits ABOVE the video, not under it. Both are absolutely placed
   and the video comes later in the markup, so without this the browser paints
   the video's own first frame over the poster the moment metadata loads — and
   frame zero of a real edit is usually a transition, a flash or a whip, which
   is the worst possible still to greet anyone with. */
.stage .poster { z-index: 1; pointer-events: none; transition: opacity 460ms var(--soft); }
.piece[data-playing='true'] .poster { opacity: 0; }

/* the play affordance — soft, centred, the only thing asking to be touched */
.play {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  appearance: none; border: 0; padding: 0;
  background: transparent;
  color: var(--ink-1);
  cursor: pointer;
  font: inherit;
  transition: opacity 380ms var(--soft);
}
.play span {
  display: grid; place-items: center;
  width: 66px; height: 66px;
  border-radius: var(--pill);
  background: rgba(28, 28, 31, 0.66);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.28), 0 10px 26px rgba(0, 0, 0, 0.3);
  transition: transform 380ms var(--soft), background 260ms var(--soft);
}
.play svg { width: 23px; height: 23px; display: block; }

/* ---- sound ------------------------------------------------------------
   One pill in the stage's top-right holding the toggle and, once you reach
   for it, a volume slider that grows out of its left side. The toggle is
   always visible: a muted video with no visible way to unmute it is simply a
   silent video, and the visitor cannot tell which. The slider is not, because
   it is the third thing on the card and a permanent slider on every clip is
   a control panel nobody asked for.
   ---------------------------------------------------------------------- */
.sound {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  display: flex; align-items: center;
  border-radius: var(--pill);
  background: rgba(20, 20, 22, 0.62);
  -webkit-backdrop-filter: blur(14px);
          backdrop-filter: blur(14px);
  box-shadow: var(--spec), 0 2px 8px rgba(0, 0, 0, 0.3);
  opacity: 0.72;
  transition: opacity 240ms var(--soft), background 240ms var(--soft);
}
.sound:hover, .sound:focus-within { opacity: 1; background: rgba(30, 30, 34, 0.82); }
.piece[data-sound='on'] .sound { opacity: 1; }

.mute {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  flex: none;
  appearance: none; border: 0; padding: 0;
  background: transparent;
  border-radius: var(--pill);
  color: var(--ink-1);
  cursor: pointer;
  transition: transform 240ms var(--soft), color 240ms var(--soft);
}
.mute svg { width: 19px; height: 19px; display: block; }
.mute:active { transform: scale(0.94); }
/* once it is making sound it stops being an offer and becomes a state */
.piece[data-sound='on'] .mute { color: var(--accent); }

/* The slider is laid out at full size and scaled to nothing on its right edge,
   so the pill grows out of the button rather than the button sliding across
   the card. It stays in the tab order while collapsed: tabbing to it triggers
   :focus-within on the pill, which opens it. */
.vol {
  appearance: none;
  width: 0; height: 38px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  transform-origin: 100% 50%;
  scale: 0 1;
  opacity: 0;
  transition: width 260ms var(--soft), margin-left 260ms var(--soft),
              scale 260ms var(--soft), opacity 200ms var(--soft);
}
/* Reaching for it opens it — and so does turning the sound on, which is the
   same rule rather than a touch-screen special case. A phone has no hover, so
   a hover-only slider would simply not exist there; keying it to the sound
   state instead means it appears exactly when it is wanted, on every device,
   and there is no branch that only some hardware ever runs. */
.sound:hover .vol,
.sound:focus-within .vol,
.piece[data-sound='on'] .vol {
  width: 82px; margin-left: 14px; scale: 1 1; opacity: 1;
}

.vol::-webkit-slider-runnable-track {
  height: 4px; border-radius: var(--pill);
  background: rgba(255, 255, 255, 0.28);
}
.vol::-moz-range-track {
  height: 4px; border-radius: var(--pill);
  background: rgba(255, 255, 255, 0.28);
}
.vol::-moz-range-progress { height: 4px; border-radius: var(--pill); background: var(--ink-1); }
.vol::-webkit-slider-thumb {
  appearance: none;
  width: 13px; height: 13px; margin-top: -4.5px;
  border: 0; border-radius: var(--pill);
  background: var(--ink-1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.vol::-moz-range-thumb {
  width: 13px; height: 13px;
  border: 0; border-radius: var(--pill);
  background: var(--ink-1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.piece[data-sound='on'] .vol::-webkit-slider-thumb { background: var(--accent); }
.piece[data-sound='on'] .vol::-moz-range-thumb { background: var(--accent); }
.play:hover span, .play:focus-visible span { transform: scale(1.08); background: rgba(38, 38, 42, 0.82); }
.piece[data-playing='true'] .play { opacity: 0; }
.piece[data-playing='true']:hover .play, .piece[data-playing='true'] .play:focus-visible { opacity: 1; }
.piece[data-playing='true'] .play span { background: rgba(28, 28, 31, 0.5); }

/* progress, soft and unobtrusive */
/* ---- the scrubber ------------------------------------------------------
   Two layers. The track and its filled portion are ordinary elements with an
   ordinary width, and a transparent `input[type=range]` sits on top of them
   carrying nothing but the thumb and all the behaviour — click-anywhere, drag,
   arrow keys, Home and End, and the screen-reader announcement.

   The fill was a gradient stop driven by a custom property, which is neater
   and does not survive contact with the real world: Dark Reader and similar
   extensions rewrite gradients and drop the property with them, pinning the
   bar at zero however far the clip has run. A width cannot be rewritten.

   The visible track is 4px and the hit area is 20px, because a 4px pointer
   target is a control only in theory. It sits above the full-stage play button
   and above the end plate, so it stays reachable in every state.
   The container is `.scrub`, not `.bar`: `.bar` is already the sticky site
   header, and reusing it made the header a 20px invisible strip while the
   header's own `top: 0` leaked back and pinned the scrubber to the top of the
   card (with a height set, `top` wins and `bottom` is dropped). Second time
   this project has been bitten by a class collision — see The Namespace Rule.
   ---------------------------------------------------------------------- */
.scrub {
  position: absolute; left: 14px; right: 14px; bottom: 6px; z-index: 5;
  height: 20px;
  display: grid; align-items: center;
  opacity: 0;
  transition: opacity 320ms var(--soft);
}
.piece[data-playing='true'] .scrub,
.piece[data-done='true'] .scrub,
.stage:hover .scrub,
.scrub:focus-within { opacity: 1; }

.scrub-track {
  grid-area: 1 / 1;
  height: 4px; border-radius: var(--pill);
  background: rgba(255, 255, 255, 0.22);
  overflow: hidden;
  pointer-events: none;
}
.scrub-fill {
  display: block; height: 100%; width: 0;
  border-radius: var(--pill);
  background: var(--ink-1);
}

.seek {
  grid-area: 1 / 1;
  width: 100%; height: 20px; margin: 0; padding: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
}
.seek::-webkit-slider-runnable-track { height: 4px; background: transparent; }
.seek::-moz-range-track { height: 4px; background: transparent; }

/* the handle only appears when the pointer is on the card, so a clip that is
   simply playing keeps the thin unbroken line it had before */
.seek::-webkit-slider-thumb {
  appearance: none;
  width: 12px; height: 12px; margin-top: -4px;
  border: 0; border-radius: var(--pill);
  background: var(--ink-1);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  scale: 0;
  transition: scale 200ms var(--soft);
}
.seek::-moz-range-thumb {
  width: 12px; height: 12px;
  border: 0; border-radius: var(--pill);
  background: var(--ink-1);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  scale: 0;
  transition: scale 200ms var(--soft);
}
.stage:hover .seek::-webkit-slider-thumb,
.seek:focus-visible::-webkit-slider-thumb,
.seek:active::-webkit-slider-thumb { scale: 1; }
.stage:hover .seek::-moz-range-thumb,
.seek:focus-visible::-moz-range-thumb,
.seek:active::-moz-range-thumb { scale: 1; }

/* what shows when the twenty seconds are up */
.done {
  position: absolute; inset: 0; z-index: 4;
  display: none;
  flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 28px;
  text-align: center;
  background: rgba(20, 20, 22, 0.86);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
}
.piece[data-done='true'] .done { display: flex; }
.done p { font-size: 16px; color: var(--ink-2); max-width: 30ch; line-height: 1.5; }

.meta { display: flex; align-items: baseline; gap: 12px; padding: 16px 4px 0; }
.meta h3 { font-size: 17px; font-weight: 500; letter-spacing: -0.014em; color: var(--ink-1); }
.meta span {
  margin-left: auto;
  font-size: 14.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


/* ---------- contact ---------- */

.connect {
  margin-top: clamp(32px, 4.6vh, 52px);
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(20px, 2.6vw, 34px);
  align-items: start;
}

.panel {
  background: var(--raised);
  border-radius: var(--r-xl);
  padding: clamp(26px, 3.4vw, 42px);
  box-shadow: var(--spec), 0 1px 2px rgba(0, 0, 0, 0.24), 0 16px 44px rgba(0, 0, 0, 0.26);
}

.field { margin-bottom: 16px; }
.field label { display: block; margin-bottom: 8px; font-size: 14.5px; color: var(--ink-3); }
.field input, .field textarea {
  appearance: none;
  width: 100%;
  padding: 14px 17px;
  background: var(--raised-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--ink-1);
  font: inherit; font-size: 16px;
  line-height: 1.5;
  caret-color: var(--ink-1);
  resize: vertical;
  transition: border-color 200ms var(--soft), background 200ms var(--soft);
}
.field textarea { min-height: 118px; }
.field input::placeholder, .field textarea::placeholder { color: #8e8e93; }
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: rgba(255, 178, 63, 0.62);
  background: #2a2a2e;
}
.field[data-bad='true'] input, .field[data-bad='true'] textarea { border-color: var(--ink-2); }
.err { display: none; margin-top: 7px; font-size: 14px; color: var(--ink-1); }
.field[data-bad='true'] .err { display: block; }

.form-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 22px; }
.say { font-size: 14.5px; line-height: 1.5; color: var(--ink-3); }
.say[data-state='ok'], .say[data-state='error'] { color: var(--ink-1); }

.route {
  display: flex; align-items: center; gap: 15px;
  padding: 19px 22px;
  border-radius: var(--r-lg);
  background: var(--raised-2);
  text-decoration: none;
  color: inherit;
  box-shadow: var(--spec), 0 1px 2px rgba(0, 0, 0, 0.2), 0 10px 28px rgba(0, 0, 0, 0.2);
  transition: background 240ms var(--soft), transform 240ms var(--soft);
}
/* only a route that actually goes somewhere behaves like one */
/* a live route is either a link with somewhere to go or a button that copies */
a.route[href]:hover, a.route[href]:focus-visible,
button.route:hover, button.route:focus-visible { background: #2d2d31; transform: translateY(-2px); }
button.route {
  width: 100%;
  appearance: none; border: 0;
  font: inherit; text-align: left;
  cursor: pointer;
}
.route[data-off='true'] { box-shadow: var(--spec); opacity: 0.66; cursor: default; }
.route + .route { margin-top: 12px; }
/* The icon wells wear the Send button's glass: same amber, same sheen down the
   top third, same lit rim, same weight at the bottom. Shadows are scaled to a
   42px disc rather than copied from a 130px pill, or the glow would swamp it. */
.route .ic {
  --tint: 255, 178, 63;
  position: relative;
  isolation: isolate;
  display: grid; place-items: center;
  width: 42px; height: 42px; flex: none;
  border-radius: var(--pill);
  color: var(--on-accent);
  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.34) 0%,
      rgba(255, 255, 255, 0.09) 38%,
      rgba(255, 255, 255, 0) 62%),
    rgba(var(--tint), 0.9);
  -webkit-backdrop-filter: blur(22px) saturate(200%);
          backdrop-filter: blur(22px) saturate(200%);
  box-shadow:
    inset 0 -8px 15px -9px rgba(92, 52, 0, 0.5),
    0 1px 2px rgba(0, 0, 0, 0.32),
    0 6px 18px rgba(var(--tint), 0.22);
}
/* the lit edge: bright where the light lands, faint at the waist */
.route .ic::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.88) 0%,
    rgba(255, 255, 255, 0.30) 34%,
    rgba(255, 255, 255, 0.12) 58%,
    rgba(255, 255, 255, 0.42) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  pointer-events: none;
}
/* a route pointing nowhere should not look like a live control */
.route[data-off='true'] .ic {
  background: var(--ground);
  color: var(--ink-3);
  box-shadow: var(--spec);
}
.route[data-off='true'] .ic::after { display: none; }
.route .ic svg { width: 20px; height: 20px; }
.route b { display: block; font-size: 16px; font-weight: 500; color: var(--ink-1); }
.route small { display: block; font-size: 14px; color: var(--ink-3); margin-top: 2px; }

.routes-title { font-size: 14.5px; color: var(--ink-3); margin-bottom: 14px; }

/* with fewer than two live routes the side column is mostly empty ground,
   so the routes lie under the form instead */
.connect--solo { grid-template-columns: 1fr; }
.connect--solo .routes { display: flex; flex-wrap: wrap; gap: 12px; }
.connect--solo .routes-title { width: 100%; margin-bottom: 2px; }
.connect--solo .route { flex: 1 1 280px; }
.connect--solo .route + .route { margin-top: 0; }

/* ---------- footer ---------- */

.foot { margin-top: clamp(64px, 10vh, 124px); padding: 0 0 38px; }
.foot-in {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding-top: 26px;
  border-top: 1px solid var(--edge);
  font-size: 14.5px; color: var(--ink-3);
}
.foot-in .sp { margin-left: auto; }

/* ---------- the one authored moment ----------
   The hero settles once, on arrival. Nothing else on the page animates in;
   an identical entrance on every section is choreography nobody asked for. */

@keyframes settle {
  from { opacity: 0; transform: translateY(15px); }
  to   { opacity: 1; transform: none; }
}
.js .hero-intro > * {
  opacity: 0;
  animation: settle 820ms var(--soft) forwards;
}
.js .hero-intro > *:nth-child(1) { animation-delay:  60ms; }
.js .hero-intro > *:nth-child(2) { animation-delay: 210ms; }

/* ---------- responsive ---------- */

@media (max-width: 980px) {
  .connect { grid-template-columns: 1fr; }
  .reel--wide { grid-template-columns: 1fr; }
  /* below this the two columns are too narrow for a 16:9 screen and a card
     stack side by side, so the proof goes above the reasons */
  .why-row { grid-template-columns: 1fr; gap: 26px; max-width: 62ch; margin-inline: auto; }
  /* Stacked there is nothing beside the screen to take a height from, and a
     percentage height against an auto-height parent resolves to auto — which
     collapsed the frame to zero. It goes back to its own 16:9 here. */
  .why-row .find { height: auto; }
  .why-row .screen { height: auto; aspect-ratio: 16 / 9; }
}

@media (max-width: 760px) {
  body { font-size: 16px; }
  .bar-nav a:not(.btn) { display: none; }
  .hero { padding-top: clamp(44px, 8vh, 72px); }
  .find-b { font-size: 13px; }

  .gl--b { display: none; }
  .gl--a { top: 0; right: -30%; opacity: 0.7; }
  .hero h1 { max-width: 14ch; }
  .why h2 { letter-spacing: -0.034em; line-height: 1.1; }
  .reel[data-count] { --cols: 1; max-width: 420px; gap: 22px; }
  .stage--tall, .meta { max-width: 420px; margin-inline: auto; }
  .play span { width: 60px; height: 60px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  .js .hero-intro > * { opacity: 1; animation: none; }
  /* the finder is driven from script, which skips straight to the found state */
  .gl, .find-mark, .fig-head, .fig-body, .backlight { animation: none !important; }
}
