/* ===========================================================================
   reel.css — leaf 01's photographs, behind the tagline.

   Four pictures of the plant, cross-fading in the card's whole interior while
   YOUR SOURCE IN PACKAGING stands over them. They are the same four the palette
   itself was sampled from (see tokens.css §2: --plate-foam is the lit face of the
   bubble rolls in one of them), which is why the type can sit on them at all —
   the ground and the photographs are the same colour to begin with.

   THE SIGNATURE IS BLUR-INTO-FOCUS, exactly as carousel.css states it: the change
   is a crossfade with `filter: blur(N) -> blur(0)` and NO TRANSLATE. Nothing
   slides. The only travel is the slow scale settle the `.cut` photograph already
   uses on this site (word.css: 1.09 -> 1), so a frame arrives the way every other
   photograph here arrives.

   NO JAVASCRIPT, NO CLOCK, NO TIMER. It is four CSS animations with staggered
   delays, and it is PAUSED unless this leaf is live — so it costs nothing while
   the reader is eight leaves away, and it starts from the first frame when they
   come back. clock.js sleeps a still page on purpose; a background reel is not a
   reason to keep it awake.

   THE VEIL IS LOAD-BEARING. §7 decision 5 forbids type over a photograph, and
   this is the one deliberate exception on the site — so the photographs are held
   behind a radial wash of the card's own ground, heaviest dead centre where the
   words are and thinnest at the corners where they are not. --reel-veil is the
   one dial: raise it and the pictures recede, lower it and the type starts
   fighting them. Contrast at the centre must stay at AA for --stencil on
   --plate-foam, which is what the 0.9 floor protects.
   ======================================================================== */

/* IT ANCHORS TO THE STAGE, NOT TO THE LEAF. `.leaf__body` is a centred grid item
   sized to its own content — on this leaf that is 497x313, just the three glyph
   rows and the lede — so `inset: 0` against the body would wrap the words rather
   than fill the card. `.stage` is the positioned ancestor above it and IS the
   card's whole interior, which is the area the reel is meant to cover. Nothing
   leaks between leaves: the reel is still a child of `#body-01`, so the leaf's
   own `visibility` gate hides it with everything else on the leaf. */
.reel{
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: clip;                 /* the scale settle must not push past the card */
  /* A photograph on this site is always a tipped-in plate: 2px of softening and
     one hairline, never a shadow (polish.css §1). A full-bleed reel is still a
     plate, so it is edged like one. */
  border-radius: 2px;
  box-shadow: inset 0 0 0 1px var(--panel-edge);
  pointer-events: none;           /* the photographs are scenery, not targets */

  /* Centre and edge of the wash, as fractions of the ground colour. The centre is
     where the words are and is the only part that has to protect anything; the
     corners carry almost none, so the plant is genuinely legible around the type
     rather than implied behind it. */
  --reel-veil: 0.72;
  --reel-veil-edge: 0.3;
  /* How far out of focus a frame arrives and leaves. */
  --reel-blur: 14px;
  /* One frame's whole life, and the cycle it belongs to. Four frames, so the
     stagger below is a quarter of the cycle. */
  --reel-cycle: 32s;
}

/* ── Frames, driven by js/reel.js ────────────────────────────────────────────
   THE nth-child DELAY TABLE AND THE `infinite` ANIMATION ARE BOTH GONE, and the
   reason is leaf 02. Its carousel has to show the same photograph as the hero at
   the same moment whichever leaf is open, and the old scheme made that impossible:
   the animation carried `animation-play-state: paused` until its own leaf went
   live, so two reels paused at different times drift apart permanently with no
   shared phase left to sync to.

   js/reel.js now owns one index for the whole page and marks the active frame
   `data-on`. Both reels read the same counter, so they cannot disagree. This is
   also cheaper than what it replaces: a transition fires only when the frame
   actually changes, where the old `infinite` animation composited four full-bleed
   images forever, and it was the only infinite animation in this stylesheet tree.

   `data-on` rather than a nth-child table on purpose — this codebase has twice
   shipped a hard-coded child table that fell out of step with its markup (the
   hero's glyph stagger, the menu's five links against three delay rules). Any
   number of frames works here with no CSS change. */
.reel__frame{
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
  filter: blur(var(--reel-blur));
  transform: scale(1.06);
  /* The old keyframe's shape, as a transition: in fast and sharpen, hold, then
     leave slowly with the scale winding back ready for its next turn. */
  transition:
    opacity 2.1s var(--e-grade),
    filter 2.1s var(--e-grade),
    transform 8.4s linear;
}

.reel__frame[data-on]{
  opacity: 1;
  filter: blur(0);
  transform: scale(1.005);
}

/* will-change only on the two frames that are actually moving — the one coming in
   and the one going out — never on all four at once. */
.reel__frame[data-on],
.reel__frame[data-was]{
  will-change: opacity, filter;
}

.reel__frame img{
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 55%;       /* the floor and the stock, not the roof steel */
  /* The site's one photographic grade (polish.css §1), pulled a little further
     toward the plate because these carry type. */
  filter: saturate(0.62) contrast(1.02) brightness(1.05) sepia(0.08);
}

/* The wash. Painted over every frame and under everything else in the card.
   `--plate-now` is the CURRENT card ground (leaf.css §3.3), not a fixed colour:
   the reel appears on a foam leaf and on a cream one, and a wash in the wrong
   white reads instantly as a grey box laid over the card. */
.reel::after{
  content: "";
  position: absolute;
  inset: 0;
  background: var(--plate-now, var(--plate-foam));
  opacity: var(--reel-veil);
}
/* A TIGHTER, DENSER CORE. The wash used to fall away from 100% of --reel-veil in a
   single slow ramp, which meant the type sat on the same wash as the empty corners.
   Now the middle — where every word on the leaf is — holds a denser core out to
   45%, and the falloff past that is steeper, so the corners show MORE photograph
   than before while the letterforms sit on a calmer ground. The centre is pulled
   up to 44% because the wordmark's optical centre is above the box's. */
@supports (background: radial-gradient(farthest-side, color-mix(in srgb, red 50%, transparent), red)){
  .reel::after{
    opacity: 1;
    /* CLAMPED, and it has to be: the narrow-card override below takes --reel-veil
       to 0.93, and a bare `* 116%` would compute 107.9% — an out-of-range
       color-mix percentage drops the whole declaration, which would fall back to
       the flat `background: var(--plate-now)` above and hide the photograph
       completely on every phone. */
    background: radial-gradient(96% 66% at 50% 44%,
      color-mix(in srgb, var(--plate-now, var(--plate-foam)) min(100%, calc(var(--reel-veil) * 116%)), transparent) 0%,
      color-mix(in srgb, var(--plate-now, var(--plate-foam)) min(100%, calc(var(--reel-veil) * 108%)), transparent) 45%,
      color-mix(in srgb, var(--plate-now, var(--plate-foam)) calc(var(--reel-veil) * 74%), transparent) 78%,
      color-mix(in srgb, var(--plate-now, var(--plate-foam)) calc(var(--reel-veil-edge) * 100%), transparent) 100%);
  }
}

/* --- one photograph, held -------------------------------------------------
   A reel of one is not a reel: with the cycle running, a single frame would
   fade up, hold, and then leave the leaf bare for three quarters of every
   32 seconds. `.reel--still` is the same plate and the same wash with the
   change taken out. */
.reel--still .reel__frame{
  opacity: 1;
  filter: none;
  transform: none;
  transition: none;
  will-change: auto;
}

/* `@keyframes reel-frame` AND `animation-play-state: running` USED TO LIVE HERE.
   Both are deleted rather than left as dead rules, because leaving them would be
   actively misleading: an `animation` on `.reel__frame` would outrank the
   transitions above (the animation origin beats the author origin) and quietly
   take the frames back off js/reel.js, exactly the way `animation: settle` took
   the hero's glyphs off js/word.js for months. If a reel ever needs a keyframe
   again, it has to take the index with it.

   The old rule also tied the cycle to `[data-live]`, which is precisely what made
   two synchronised reels impossible — see the frame block above. */

/* The reel is the only positioned thing beneath this leaf's type, and a
   positioned element paints over in-flow content whatever the source order says.
   `.word` already claims its own layer (word.css); the lede did not.

   AND IT TAKES THE PRIMARY INK. tokens.css states the rule mechanically: the
   quiet grey (--stencil-3) is permitted on --plate-foam and nowhere else, because
   it only clears AA against that exact colour — and a photograph under the ground
   is not that colour. At this wash even --stencil-2 lands near 4:1 over a dark
   frame, so the lede takes --on-plate: 5.9:1 against the worst case the reel can
   produce (a frame gone to black under the centre of the veil), and comfortably
   more against any real frame. It is one 14px line; the hierarchy is carried by
   the display type above it, which at that size clears AA-large many times over.

   `:has(.reel)` for two reasons: contact.html composes as #body-01 with no reel
   and must not be touched, and compose.css sets this lede's colour further down
   the cascade — the extra class beats it without an !important. */
#body-01:has(.reel) .lede{
  position: relative;
  z-index: 1;
  color: var(--on-plate);
  /* A little more stem over texture. Archivo's variable weight, not a fake bold. */
  font-variation-settings: "wdth" 104, "wght" 480;
}

/* --- the letterforms, over a photograph -----------------------------------
   A STURDIER CUT, NOT MORE CONTRAST. Measured on the live page, the worst-case
   contrast of the wordmark against the darkest pixel any of the four frames puts
   behind it — through the wash — is 11.4:1, and the lede's is 11.5:1. Both are
   already far past AA, so darkening the wash would only cost photograph and buy
   nothing. What actually makes them hard to read is frequency, not value: Bodoni's
   hairlines at "opsz" 96 are two or three pixels at this size, which is the same
   scale as the detail in a photograph of stacked rolls, so the thin strokes break
   up against it.

   Lowering the optical size moves toward Bodoni's TEXT cut, which thickens the
   thins; raising the weight thickens the stems. The letterforms stay unmistakably
   Didone — this is the axis the family provides for exactly this problem — and
   they stop dissolving into the picture. Applied only where a reel is present, so
   the wordmark on a plain plate keeps the full display cut. */
.leaf__body:has(.reel) .glyphs{
  font-variation-settings: "opsz" 48;
  font-weight: 500;
}

/* --- leaf 09, the closing plate -------------------------------------------
   The building itself, behind YOURS. This leaf is far denser in small type than
   the hero — a colophon of addresses, nine line names and the legal column runs
   right across its foot — so it takes a heavier wash and, under the colophon, a
   second one.

   TWO GRADIENTS, ONE LAYER. The linear is listed FIRST, which paints it on top
   of the radial: the bottom third goes to near-solid ground so the colophon is
   read off the plate and not off a photograph, and the fade is finished well
   before the closing word. On this leaf the quiet ink is --stencil-2 (cream is
   not foam — leaf.css states the rule), which needs the ground at 0.9 or better
   to hold 4.5:1 over a dark frame; the stops below never go under that anywhere
   type sits. */
#body-09 .reel{
  --reel-veil: 0.88;
  --reel-veil-edge: 0.6;
}
@supports (background: radial-gradient(farthest-side, color-mix(in srgb, red 50%, transparent), red)){
  #body-09 .reel::after{
    background:
      linear-gradient(to top,
        color-mix(in srgb, var(--plate-now, var(--plate-cream)) 95%, transparent) 0%,
        color-mix(in srgb, var(--plate-now, var(--plate-cream)) 92%, transparent) 26%,
        transparent 52%),
      radial-gradient(115% 78% at 50% 50%,
        color-mix(in srgb, var(--plate-now, var(--plate-cream)) calc(var(--reel-veil) * 100%), transparent) 0%,
        color-mix(in srgb, var(--plate-now, var(--plate-cream)) calc(var(--reel-veil) * 88%), transparent) 42%,
        color-mix(in srgb, var(--plate-now, var(--plate-cream)) calc(var(--reel-veil-edge) * 100%), transparent) 100%);
  }
}
/* The closing stack is all static content, and a positioned reel paints over
   static siblings whatever the source order. `.word` already has its own layer;
   the aside, the line, the pill and the colophon did not. */
#body-09:has(.reel) > :not(.reel){ position: relative; z-index: 1 }

/* --- no JS ----------------------------------------------------------------
   Nothing sets data-live, so the reel would sit paused on a frame at opacity 0
   and leaf 01 would be a blank plate. Run it. */
html:not(.js) .reel__frame{ animation-play-state: running }

/* --- reduced motion -------------------------------------------------------
   One photograph, held. The composition is the same; the change is simply
   absent — the same bargain the rest of the site makes. */
@media (prefers-reduced-motion: reduce){
  .reel__frame{
    animation: none;
    opacity: 0;
    will-change: auto;
  }
  .reel__frame:first-child{
    opacity: 1;
    filter: none;
    transform: none;
  }
}

/* --- narrow cards ---------------------------------------------------------
   Three stacked glyph rows fill a phone-width card almost edge to edge, so the
   wash goes flat and heavier: there is no corner left over to show a picture in,
   and a photograph read through the gaps between letters is just noise. */
@media (max-width: 560px){
  .reel{ --reel-veil: 0.93; --reel-veil-edge: 0.8 }
}
