/* ── The stage ──────────────────────────────────────────────────────────
   Three stacked full-bleed layers, every one 100vw × 100dvh:

     .still   z1  the room you are standing in (always present)
     .clip    z2  the transition, revealed only while it plays
     .copy    z3  the words, over a scrim

   The still and the clip show identical pixels at the moment of the swap
   (the still IS the clip's first/last frame), so neither reveal is visible.
*/
.stage{
  position:fixed; inset:0;
  width:100vw; height:100dvh;
  background:var(--ground);
  overflow:hidden;
}

/* ── Layer 1 — the room ─────────────────────────────────────────────── */
.still{
  position:absolute; inset:0; z-index:1;
  width:100%; height:100%;
  object-fit:cover;
  /* Alt text is for assistive tech, not for painting across the stage while
     the file is in flight. */
  color:transparent; font-size:0;
  /* Biased upward, not centred. The sources are portrait subjects inside a
     16:9 frame, so on a wide-and-short window cover crops top and bottom —
     centring cut the head off the full-length shot. */
  object-position:50% 32%;
}
/* Second still element: the crossfade partner. Idle at opacity 0. */
.still--next{opacity:0}

/* ── Layer 2 — the transition ───────────────────────────────────────── */
.clip{
  position:absolute; inset:0; z-index:2;
  width:100%; height:100%;
  object-fit:cover;
  object-position:50% 32%;   /* must match .still or the seam shifts */
  opacity:0;
  visibility:hidden;
  pointer-events:none;
}
.clip.is-playing{opacity:1;visibility:visible}

/* Preload pool — never painted, never laid out against the stage. */
.preload{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;left:-9999px}

/* ── Layer 3 — the words ────────────────────────────────────────────── */
.copy{
  position:absolute; inset:0; z-index:4;
  display:grid;
  align-content:end;
  padding:
    var(--pad)
    var(--pad)
    max(calc(var(--pad) + 64px), calc(env(safe-area-inset-bottom) + 64px));
  /* A photograph cannot be trusted to carry text. The scrim is what makes
     the measured contrast ratios in tokens.css true on screen.

     Two of them, because one is not enough: the bottom ramp covers rooms
     whose copy sits low, but room 0 centres its copy vertically — right in
     the transparent part of that ramp. The second, column-anchored ramp
     backs the text wherever it sits, and stays clear of the right half of
     the frame so the photograph is still the thing you look at.
     Verified by tools/contrast-check.sh. */
}

/* ── The scrim — its own layer, and it NEVER animates ───────────────────
   This used to live on .copy. But .copy fades out during a transition, so
   the scrim went with it: the photograph jumped to full brightness for the
   length of the move and then darkened again when the words came back.
   That was the flash. The treatment is permanent, so it gets a permanent
   layer; only the text is allowed to move. */
.scrim{
  position:absolute; inset:0; z-index:3;
  pointer-events:none;
  background-image:var(--copy-scrim);
}

/* Declared once so room overrides can stack extra layers under it without
   restating the gradients. */
:root{
  --copy-scrim:
    linear-gradient(to bottom,
      rgba(0,0,0,0) 34%,
      var(--scrim) 74%,
      var(--ground) 100%),
    /* Reaches 62% across the frame, which on the portrait rooms is exactly
       where the face is — the photograph visibly darkens a beat after it
       paints, and the subject is the thing that loses. The text does not
       need this ramp to be readable: .copy-inner below carries its own
       backing, anchored to the block. Pulled back to clear the centre.
       Re-measured with tools/contrast-check.sh. */
    linear-gradient(to right,
      var(--scrim) 0%,
      rgba(20,16,14,.42) 24%,
      rgba(0,0,0,0) 44%);
}

/* The frame-wide ramps above handle the general case, but they cannot know
   where the text block actually is. This one is anchored to the block, so
   the small type keeps its ratio no matter what the photograph does behind
   it. Radial with a long falloff, not a panel — it should read as light
   falling off, not as a grey box laid over the picture. */
.copy-inner{
  max-width:52ch;
  padding:24px 28px;
  margin:-24px -28px;
  /* Vertical radius 50% = exactly the box half-height, so the gradient
     reaches transparent AT the top and bottom edges. At 145% it was still
     ~0.7 opaque where the element clipped it, which drew a hard-edged grey
     panel over the photograph — the exact thing this was meant to avoid. */
  background:radial-gradient(130% 50% at 0% 50%,
    rgba(20,16,14,.88) 0%,
    rgba(20,16,14,.60) 42%,
    rgba(0,0,0,0) 100%);
}

.kicker{
  display:flex; align-items:center; gap:9px;
  margin:0 0 12px;
  font-family:var(--font-mono);
  font-size:10.5px;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--accent);
}
.kicker .dot{width:5px;height:5px;border-radius:50%;background:var(--accent);flex:none}

.title{
  margin:0;
  font-family:var(--font-display);
  font-weight:400;
  font-size:clamp(38px,7.2vw,78px);
  line-height:1.02;
  letter-spacing:-.025em;
  text-wrap:balance;
}

.lede{
  margin:16px 0 0;
  max-width:46ch;
  font-family:var(--font-display);
  font-size:clamp(17px,1.9vw,21px);
  line-height:1.45;
  color:var(--ink-2);
  text-wrap:pretty;
}

.detail{
  margin:10px 0 0;
  max-width:52ch;
  font-family:var(--font-ui);
  font-size:clamp(13px,1.2vw,15px);
  line-height:1.55;
  color:var(--ink-2);
  text-wrap:pretty;
}

/* Sentence boundaries are deliberate. Lines can still wrap on narrow
   screens, but the next thought never begins at the end of the previous one. */
.copy-sentence{display:block}
.copy-sentence + .copy-sentence{margin-top:.14em}

/* Room 0 is the poster: centre it, it carries no body text. */
.stage[data-room="0"] .copy{align-content:center;justify-items:start}
.stage[data-room="0"] .copy-inner{max-width:none}

/* ── Call to action ─────────────────────────────────────────────────── */
.cta{
  display:inline-grid;
  grid-template-columns:1fr auto;
  align-items:center;
  gap:14px;
  margin-top:26px;
  min-height:56px;
  padding:12px 14px 12px 20px;
  border-radius:var(--r-card);
  background:linear-gradient(135deg,var(--accent),var(--accent-2));
  color:var(--accent-ink);
  box-shadow:
    0 12px 28px -12px rgba(0,0,0,.72),
    inset 0 1px 0 rgba(255,255,255,.3);
  transition:transform .15s ease, box-shadow .2s ease;
}
.cta-label{font-size:18px;font-weight:600;letter-spacing:-.01em}
.cta-go{
  display:grid; place-items:center;
  width:34px; height:34px;
  border-radius:50%;
  background:rgba(27,13,3,.17);
  font-size:15px;
  transition:transform .18s ease;
}
.cta:hover{transform:translateY(-2px);box-shadow:0 16px 34px -12px rgba(0,0,0,.8),inset 0 1px 0 rgba(255,255,255,.34)}
.cta:hover .cta-go{transform:translateX(3px)}
.cta:active{transform:translateY(0) scale(.995)}

/* ── Capability / proof chips ───────────────────────────────────────── */
.chips{
  display:flex; flex-wrap:wrap; gap:10px;
  margin:18px 0 0; padding:0;
  list-style:none;
}
.chips li{
  padding:7px 14px;
  border:1px solid var(--line);
  border-radius:999px;
  background:var(--surface);
  font-family:var(--font-mono);
  font-size:11.5px;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--ink-2);
}

/* The room copy column is deliberately narrow. Four variable-width pills
   wrapping 3+1 looks accidental, so inner rooms use an explicit 2×2 set. */
.stage:not([data-room="0"]) .chips{
  display:grid;
  grid-template-columns:repeat(2,max-content);
  gap:8px 10px;
}

/* The final room carries scope, privacy and the CTA. Keep its hierarchy
   inside short laptop viewports rather than letting it collide with the mark. */
.stage[data-room="5"] .title{font-size:clamp(36px,5vw,60px)}
.stage[data-room="5"] .lede{margin-top:10px}
.stage[data-room="5"] .detail{margin-top:6px}
.stage[data-room="5"] .chips{margin-top:12px}
.stage[data-room="5"] .cta{margin-top:18px;min-height:52px}

@media (max-width:719px){
  .copy-inner{padding:18px 22px;margin:-18px -22px}
  .lede{margin-top:12px;line-height:1.38}
  .detail{margin-top:8px;line-height:1.45}
  .chips{display:grid;grid-template-columns:repeat(2,max-content);gap:7px;margin-top:14px}
  .chips li{padding:6px 10px;font-size:10px}
}

/* ── Stat row (CONTROL) ─────────────────────────────────────────────── */
.stats{
  display:flex; flex-wrap:wrap; gap:24px;
  margin:24px 0 0; padding:0;
}
.stats div{display:grid;gap:2px}
.stats dt{
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:.16em;
  text-transform:uppercase;
  /* --ink-3 is the right weight for this label, but it only clears 4.5:1
     against a flat --ground. Over a scrimmed photograph it measured
     3.94:1 on the warmest room. Small text gets --ink-2. */
  color:var(--ink-2);
  order:2;
}
.stats dd{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(28px,3.4vw,40px);
  line-height:1;
  font-variant-numeric:tabular-nums;
  color:var(--ink);
  order:1;
}

