/* ---------- the scroll reel ----------
   Six seconds of a camera crossing a working office, driven by the scroll
   instead of by a clock: the visitor's own scrolling walks the camera along
   the room, and two sentences arrive in turn as it goes.

   Edge to edge, always. An earlier pass opened the picture from an inset card
   on a dark ground, and what that actually looked like was a video in a black
   box — the box read as the design and the room read as a thumbnail inside it.
   There is no frame now: the clip is the full width of the page from the first
   pixel of the section to the last.

   Three things it must never do, in order of how badly they hurt:
   · download the best part of a megabyte to a phone that will show it in a
     375px column — under 900px the still is the whole treatment and the
     <video> never gets a src at all (see reel.js). The phone pays 94 KB for
     the WebP and nothing else;
   · move for somebody who asked the browser for less movement;
   · leave a hole where it is if the script never arrives. Without JavaScript
     the stage is one screen tall with the still frame in it and both sentences
     stacked and legible, which is a perfectly good section.

   The height of .reel-track IS the scroll distance, and it stays at 320vh now
   that the clip is six seconds rather than five. The mapping is proportional,
   so the same track spread over a longer clip is the same scroll buying less
   video — which is the point: each sentence holds for about a third more
   scrolling than it did before without the section growing a single pixel
   taller. Raising the track would have bought the same effect by making the
   page longer, which is not an improvement. */

.reel {
  --reel-dim: 1;
  --reel-line-1: 1;
  --reel-line-2: 1;
}

.reel-track {
  position: relative;
  height: 100vh;
}

.reel-stage {
  position: relative;
  display: grid;
  overflow: clip;
  height: 100vh;
  place-items: center;
}

/* The still frame is its own <img> rather than the <video poster> attribute,
   so it is the visible layer on a phone and with no script — neither of which
   ever loads the video. It used to be a CSS background here; it moved into the
   markup so the browser can choose WebP or JPEG for itself, so it can be
   deferred until the section is near, and so the build fingerprints its URL.
   The frame keeps the dark ground underneath for the moment before the image
   has decoded — a hole here is a white flash between two dark sections. */
.reel-frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #0b0b14;
}

/* Two layers, one box. Both are taken out of flow so the video lies over the
   still instead of below it — the still is a sibling now, not a background,
   and a video left in normal flow would stack under it and show nothing. */
.reel-still,
.reel-video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.reel-video {
  /* Hidden until the script has both loaded it and put it on the frame the
     scroll position asks for; otherwise the first painted frame is the clip's
     first frame and the picture visibly jumps. */
  opacity: 0;
  transition: opacity 240ms ease;
}

.reel.is-live .reel-video { opacity: 1; }

/* Dark enough for white type over any point in the clip — the camera crosses
   a bright window wall, so the veil is doing real work, not decoration. */
.reel-veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(9 9 18 / 30%), rgb(9 9 18 / 58%));
  opacity: var(--reel-dim);
  pointer-events: none;
}

/* The type scale lives on the container, not on the sentences, because the
   measure is set in `ch` and `ch` is measured in the font of the element that
   declares it. With the size on the <p> and the width on its parent, 24ch was
   24 characters of the page's 16px body text — 190px — and a 54px headline was
   laid out one word per line. That is the exact defect this site was just
   repaired for, reintroduced by me in the one section the layout audit was
   excluding because I had told it these were pictures. */
.reel-copy {
  position: relative;
  display: grid;
  max-width: 22ch;
  padding: 0 var(--space-6, 24px);
  gap: var(--space-5, 20px);
  color: #fff;
  font-size: clamp(26px, 4vw, 54px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-align: center;
}

.reel-line {
  margin: 0;
  font: inherit;
  text-shadow: 0 2px 30px rgb(9 9 18 / 45%);
  text-wrap: balance;
}

/* ---------- what everybody else gets ----------
   No script, or a phone: one screen, the still frame, both sentences stacked
   and readable. The sticky machinery needs a track taller than the stage to
   have anything to be sticky against, so without it the track collapses to the
   stage's height and nothing sticks — which is exactly right. */

.reel.is-scrubbing .reel-track { height: 320vh; }
.reel.is-scrubbing .reel-stage { position: sticky; top: 0; }

/* Scrubbing puts the two sentences in the same grid cell so they cross-fade in
   place. Stacked they would push each other around the screen for the whole
   scroll; overlapped, each one owns the middle of the picture in its turn. */
.reel.is-scrubbing .reel-copy { gap: 0; }
.reel.is-scrubbing .reel-line { grid-area: 1 / 1; }
.reel.is-scrubbing .reel-line:first-child { opacity: var(--reel-line-1); }
.reel.is-scrubbing .reel-line:last-child { opacity: var(--reel-line-2); }

@media (prefers-reduced-motion: reduce) {
  /* reel.js does not scrub here either; this only makes sure that if the class
     ever lands anyway, nothing about the layout moves. */
  .reel.is-scrubbing .reel-track { height: 100vh; }
  .reel.is-scrubbing .reel-stage { position: relative; }
  .reel.is-scrubbing .reel-copy { gap: var(--space-5, 20px); }
  .reel.is-scrubbing .reel-line { grid-area: auto; opacity: 1; }
  .reel-video { transition: none; }
}
