/* ============================================================================
   THE PROCESSIONAL - a full-screen room opened over the entourage.

   It keeps the light half's cream. Built dark first, borrowing the hero's
   espresso, and the room was handsome but it was a cinema: it broke away from
   the page instead of opening out of it, and a two in the afternoon wedding is
   not lit that way. In cream it reads as the same church the postcards show,
   which is what it is.

   The aisle therefore cannot be a runner of light, because light on cream is
   nothing. It is a warm shadow instead, and the far end is a bloom of daylight
   in the doorway they are walking out of.

   YOU SCROLL THEM IN. The overlay is its own scroll container with a named
   scroll timeline, a sticky frame you watch through, and a tall empty track
   behind it that supplies the length. Every walker is a scroll-driven
   animation with its own `animation-range`, so the procession does not play at
   you: it advances exactly as far as you move, stops when you stop, and goes
   back if you scroll up. A timed fallback is kept for engines without
   `animation-timeline` (Safari before 26), because otherwise they would open
   an empty aisle.

   ONE MOTION, ONE KEYFRAME. Every walker, the dogs' line, each group heading
   and each row of names, travels the same path: it appears small and soft at
   the far end of the aisle, grows as it comes down it, passes through the
   reading position, and finally goes by the camera, large and out of focus.
   They walk TOWARD you. Built the other way first, receding to the altar, it
   read as the entourage leaving rather than arriving, which is the opposite of
   what a processional is for. The only
   thing that differs between them is the delay, set inline by the director in
   js/processional.js from two constants. A processional is not a sequence of
   slides; it is a continuous stream of people walking past you, and one shared
   path with staggered delays is exactly that.

   PAUSE IS FREE. Every animation here is a CSS animation, so a single
   `animation-play-state: paused` on the overlay stops all of them mid-stride,
   including the progress bar, without the director tracking any of it.
   ============================================================================ */
/* how large they get as they pass. Smaller on a phone, where a pair of long
   names at full growth would break onto three lines. */
.pr{--grow:1.22}
@media (max-width:560px){.pr{--grow:1.06}}
.pr{position:fixed;inset:0;z-index:var(--z-gate);display:none;
  overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;
  color:var(--ink);font-family:var(--font-display);
  scroll-timeline-name:--pr;scroll-timeline-axis:block}
.pr[hidden]{display:none}
.pr.is-open{display:block}
.pr.is-paused *{animation-play-state:paused !important}

/* The window you watch through. It sticks for the whole length of the track,
   so the aisle stays put while the scroll runs underneath it. PERSPECTIVE
   LIVES HERE, not on .pr: on the scroller it would become the containing block
   for the chrome and pin the buttons to the track instead of the screen. */
.pr-frame{position:sticky;top:0;height:100svh;overflow:hidden;
  perspective:900px;perspective-origin:50% 34%}
/* nothing in it; it is the distance */
.pr-track{height:var(--track,900vh)}
.pr--timed .pr-track{display:none}
.pr--timed .pr{overflow:hidden}

.pr-veil{position:absolute;inset:0;background:var(--cream);
  opacity:0;transition:opacity .7s ease}
.pr.is-lit .pr-veil{opacity:1}

/* the aisle: a runner of light narrowing to the altar. Drawn as a trapezoid
   with a clip-path rather than a 3D-rotated plane, which would fight the
   perspective the walkers already use. */
.pr-aisle{position:absolute;left:50%;top:6%;bottom:0;width:min(88vw,760px);
  transform:translateX(-50%);
  clip-path:polygon(50% 0,50% 0,100% 100%,0 100%);
  background:linear-gradient(to top,
    rgba(36,28,23,.055) 0%, rgba(36,28,23,.028) 46%, transparent 86%);
  opacity:0;transition:opacity 1.4s ease .3s}
.pr.is-lit .pr-aisle{opacity:1}

/* the daylight in the doorway they are all walking out of */
.pr-altar{position:absolute;left:50%;top:6%;width:min(52vw,360px);height:34vh;
  transform:translate(-50%,-38%);border-radius:50%;
  background:radial-gradient(ellipse at 50% 50%,
    rgba(255,252,245,.96) 0%, rgba(250,244,231,.60) 33%,
    rgba(201,162,75,.10) 58%, transparent 76%);
  opacity:0;transition:opacity 2s ease .4s}
.pr.is-lit .pr-altar{opacity:1}

.pr-stage{position:absolute;inset:0;transform-style:preserve-3d}

/* ---- the walkers ------------------------------------------------------- */
/* CENTRE IT OFF ITS OWN WIDTH. `margin-left:min(-46vw,-360px)` looks like the
   mirror of the width but is not: min() of two negatives takes the MORE
   negative, so past 783px the box kept sliding left while its width stopped
   growing, and the procession walked up the left edge of the aisle. transform
   is spoken for by the walk, so the offset is computed from the width. */
/* SIZED FOR ITS LARGEST MOMENT, not its natural one. A walker is at scale
   var(--grow) when it passes the camera and still fully lit, so a box measured
   at 92vw is 92vw x grow wide by then. At 768 that put the far end of a long
   pair past the edge of the screen. Dividing the width by the growth up front
   means the widest it ever gets is the width it was asked for. */
.pr-w{position:absolute;left:50%;top:52%;
  width:min(calc(92vw / var(--grow)),720px);
  margin-left:calc(min(calc(92vw / var(--grow)),720px) / -2);
  text-align:center;opacity:0}
/* scrolled: the range is this walker's slice of the whole aisle */
.pr--scroll .pr-w{animation:prWalk linear both;
  animation-timeline:--pr;animation-range:var(--r0) var(--r1)}
/* timed: the fallback, and the same keyframe */
.pr--timed .pr-w{animation:prWalk var(--walk) cubic-bezier(.33,.02,.56,1) var(--d) both}
@keyframes prWalk{
  0%  {opacity:0;  transform:translateY(-30vh) scale(.60);            filter:blur(4px)}
  17% {opacity:1;  transform:translateY(-18vh) scale(.78);            filter:blur(.8px)}
  50% {opacity:1;  transform:translateY(2vh)   scale(1);              filter:blur(0)}
  79% {opacity:.85;transform:translateY(24vh)  scale(var(--grow));    filter:blur(.7px)}
  100%{opacity:0;  transform:translateY(46vh)  scale(calc(var(--grow) * 1.14));filter:blur(3.4px)}}

/* the dogs speak first, and only once */
.pr-say{font-style:italic;color:var(--ink-mute);line-height:1.5;
  font-size:clamp(1.15rem,2.9vw,1.75rem);padding:0 6vw}

.pr-head{display:flex;flex-direction:column;align-items:center;gap:.6rem}
.pr-head span{font-family:var(--font-ui);font-size:12.5px;font-weight:600;
  letter-spacing:.32em;text-transform:uppercase;color:var(--olive)}
.pr-sig{display:block;width:clamp(58px,8vw,80px);height:auto;color:var(--olive);
  opacity:.7}

.pr-row{display:grid;grid-template-columns:1fr auto 1fr;align-items:baseline;
  column-gap:clamp(14px,2.6vw,34px);
  font-size:clamp(.98rem,3.3vw,1.62rem);line-height:1.45}
.pr-row i{font-style:normal;color:var(--gold-deep)}
.pr-a{grid-column:1;text-align:right}
.pr-b{grid-column:3;text-align:left}
.pr-solo{grid-column:1/-1;text-align:center}
.pr-mid{grid-column:2;font-family:var(--font-ui);font-size:9.5px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-faint);
  white-space:nowrap}
.pr-role{display:block;font-family:var(--font-ui);font-size:9.5px;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--ink-faint);
  margin-bottom:.3rem}
/* the two who walk alone, in the face their names are set in everywhere else */
.pr-named .pr-solo{font-family:var(--font-script);
  font-size:clamp(2.6rem,8vw,5rem);line-height:1.1;color:var(--ink)}

/* a paw appears on the runner every few steps: they said they would walk you */
.pr-paw{position:absolute;left:50%;top:50%;width:20px;height:20px;
  margin-left:var(--px);color:var(--olive);opacity:0;
  animation:prPaw 5.4s ease-out var(--d) infinite}
.pr--scroll .pr-paw{animation:prPaw linear infinite;animation-timeline:--pr;
  animation-range:0 var(--pawspan,14%)}
.pr-paw svg{display:block;width:100%;height:100%;fill:currentColor}
/* the trail comes toward you with them, spreading as the runner widens */
@keyframes prPaw{
  0%  {opacity:0;   transform:translate(calc(var(--px) * -.7),-24vh) scale(.42) rotate(var(--pr))}
  16% {opacity:.34; transform:translate(calc(var(--px) * -.5),-16vh) scale(.58) rotate(var(--pr))}
  72% {opacity:.34; transform:translate(0,14vh) scale(1) rotate(var(--pr))}
  100%{opacity:0;   transform:translate(calc(var(--px) * .45),34vh) scale(1.3) rotate(var(--pr))}}

/* ---- chrome ------------------------------------------------------------ */
.pr-bar{position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--rule-ink)}
.pr-bar i{display:block;height:100%;width:100%;background:var(--olive);
  transform-origin:0 50%;transform:scaleX(0);animation:prBar linear both}
.pr--scroll .pr-bar i{animation-timeline:--pr}
.pr--timed .pr-bar i{animation-duration:var(--total)}
@keyframes prBar{to{transform:scaleX(1)}}

.pr-ui{position:absolute;right:clamp(14px,3vw,28px);top:clamp(14px,3vw,24px);
  display:flex;gap:.6rem}
.pr-btn{appearance:none;background:transparent;cursor:pointer;
  border:1px solid var(--rule-ink);border-radius:999px;
  padding:.62rem 1.1rem;min-height:44px;
  font-family:var(--font-ui);font-size:10.5px;font-weight:600;
  letter-spacing:.22em;text-transform:uppercase;color:var(--ink-mute);
  transition:border-color .25s ease,color .25s ease}
.pr-btn:hover{border-color:var(--olive);color:var(--olive);
  background:rgba(85,103,47,.06)}
.pr-btn:focus-visible{outline:2px solid var(--olive);outline-offset:3px}

.pr-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---- the trigger, in the entourage ------------------------------------- */
.ent-watch{display:flex;align-items:center;gap:.6rem;margin:1.6rem auto 0;
  appearance:none;cursor:pointer;background:transparent;
  border:1px solid var(--rule-ink);border-radius:999px;
  padding:.7rem 1.35rem;min-height:44px;color:var(--olive);
  font-family:var(--font-ui);font-size:10.5px;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;
  transition:border-color .25s ease,color .25s ease,background-color .25s ease}
.ent-watch:hover{border-color:var(--olive);background:rgba(107,111,90,.07)}
.ent-watch:focus-visible{outline:2px solid var(--olive);outline-offset:3px}
.ent-watch-i{width:17px;height:17px;fill:currentColor;opacity:.8}

@media (prefers-reduced-motion:reduce){
  /* No walk. The overlay becomes what it is underneath: the same names in the
     order they come down the aisle, readable at rest. */
  .pr{overflow-y:auto;align-items:flex-start;perspective:none}
  .pr-stage{position:static;padding:clamp(4rem,10vh,7rem) 0 6rem}
  /* .pr--timed .pr-w outranks a bare .pr-w, so the mode class has to be named
     here too or the fallback walk runs for someone who asked for no motion. */
  .pr--timed .pr-w,.pr--scroll .pr-w,.pr-w{
    position:static;margin:2.2rem auto 0;width:min(92vw,720px);opacity:1;
    animation:none;transform:none;filter:none}
  .pr-aisle,.pr-altar,.pr-paw,.pr-bar{display:none}
  .pr-veil{transition:none}
  .ent-watch{transition:none}
}

/* the processional locks the page behind it, the same way the gate does */
html.pr-open,html.pr-open body{overflow:hidden}

/* ---- the pack, at the head of the procession ---------------------------
   Head-and-chest portraits, not full bodies: only two of the five were shot
   standing, and a row mixing two whole dogs with three floating heads reads
   worse than five matched ones. The crop is dissolved into the page by the
   alpha fade baked into each file, so no hem shows.
   -------------------------------------------------------------------------- */
/* HEIGHTS, NOT WIDTHS. The five portraits have five different aspect ratios,
   so sizing them by width would leave their chins at five different levels.
   Sized by a share of the row's height and hung off its floor, they share a
   baseline, which is what makes them read as one pack standing together. */
.pr-pack-row{--rowh:clamp(118px,25vh,236px);
  position:relative;height:var(--rowh);width:min(92vw,560px);margin:0 auto}
/* the dogs are sized off the row's HEIGHT, so on a narrow screen the outermost
   of them hangs past the row's width and off the side of the phone */
@media (max-width:560px){.pr-pack-row{--rowh:clamp(92px,19vh,150px)}}
.pr-dog{position:absolute;bottom:0;left:var(--x);height:var(--h);
  transform:translateX(-50%);z-index:var(--z)}
.pr-dog img{display:block;height:100%;width:auto}
/* the names run as one line: huddled this close, a caption under each would
   collide with its neighbours */
.pr-pack-names{margin:.55rem 0 0;font-family:var(--font-ui);font-size:9.5px;
  font-weight:600;letter-spacing:.24em;text-transform:uppercase;
  color:var(--ink-faint)}
/* the same ring the hero gives him, sized off the row so it needs no numbers */
.pr-dog-halo{position:absolute;left:50%;bottom:calc(100% - .9em);
  width:58%;aspect-ratio:3.4/1;transform:translateX(-50%);
  border:.13em solid rgba(201,162,75,.85);border-radius:50%;
  font-size:calc(var(--rowh) * .1);pointer-events:none;z-index:1;
  filter:drop-shadow(0 0 4px rgba(201,162,75,.55))}

/* ---- the invitation to scroll ------------------------------------------- */
.pr-hint{position:absolute;left:50%;bottom:clamp(26px,6vh,58px);margin:0;
  transform:translateX(-50%);white-space:nowrap;
  font-family:var(--font-ui);font-size:10.5px;font-weight:600;
  letter-spacing:.24em;text-transform:uppercase;color:var(--ink-faint)}
.pr--scroll .pr-hint{animation:prHint linear both;
  animation-timeline:--pr;animation-range:0 7%}
.pr--timed .pr-hint{display:none}
@keyframes prHint{to{opacity:0;transform:translate(-50%,10px)}}

/* ---- the foliage, the page's own, brought inside the room ---------------- */
.pr .bo-layer{position:absolute;z-index:2;opacity:1;transition:none}
/* on the page the drift rides the window's scroll; in here it rides the aisle */
.pr--scroll .bo-s{animation-timeline:--pr}

/* ---- stacking inside the frame ------------------------------------------ */
.pr-veil{z-index:0}
.pr-aisle,.pr-altar{z-index:1}
.pr-stage{z-index:3}
.pr-hint{z-index:4}
.pr-bar,.pr-ui{z-index:5}

@media (prefers-reduced-motion:reduce){
  .pr-frame{position:static;height:auto;overflow:visible;perspective:none}
  .pr-track,.pr-hint,.pr .bo-layer,.pr-paw{display:none}
  .pr--timed .pr-bar i,.pr-bar i{animation:none;transform:scaleX(0)}
}

/* the second one, after the list; the first sits above it */
.ent-watch-foot{margin-top:clamp(2.6rem,5vw,3.6rem)}
