/* ═══════════════════════════════════════════════════
   ROBIN & PIERCE — a lookbook
   Ground: warm black. Light source: the photographs.

   TYPE — three voices, PAPER-mag logic:
     Anton            heavy condensed caps, set enormous
     Instrument Serif italic, the soft counterweight
     Archivo          10px tracked caps for every label
   The whole look lives in the size jump between the
   first and the third. Don't close that gap.
   ═══════════════════════════════════════════════════ */

:root{
  --bk:      #0B0A09;
  --bk-2:    #121010;
  --wh:      #F4F1EC;
  --wh-dim:  rgba(244,241,236,.58);
  --wh-fnt:  rgba(244,241,236,.3);
  --em:      #E97451;
  --em-lo:   #F2A98F;

  --display: "Anton", "Haettenschweiler", "Arial Narrow", Impact, sans-serif;
  --serif:   "Instrument Serif", Georgia, "Times New Roman", serif;
  --sans:    "Archivo", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;

  --pad: clamp(1.1rem, 3.2vw, 3.2rem);
  --ease: cubic-bezier(.22,1,.36,1);
  --ease-io: cubic-bezier(.76,0,.24,1);
  --spring: cubic-bezier(.34,1.56,.64,1);
}

*,*::before,*::after{ box-sizing:border-box; }

html{ background:var(--bk); scroll-behavior:smooth; -webkit-text-size-adjust:100%; }

body{
  margin:0;
  background:var(--bk);
  color:var(--wh);
  font-family:var(--sans);
  font-size:clamp(.95rem,.9rem + .25vw,1.1rem);
  line-height:1.55;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}

img{ display:block; max-width:100%; }
button{ font:inherit; color:inherit; }

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

:focus-visible{ outline:2px solid var(--em); outline-offset:5px; }
::selection{ background:var(--em); color:var(--bk); }

/* ── the 10px layer ── */
.meta,.kick{
  margin:0;
  font-family:var(--sans);
  font-size:clamp(9px,.42rem + .22vw,11px);
  font-weight:600;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--wh-dim);
}
.meta i,.kick i{
  font-family:var(--serif);
  font-style:italic; font-weight:400;
  font-size:1.35em; letter-spacing:.02em;
  text-transform:none; color:var(--em);
}
.frame__type .meta, .cover__type .kick{
  color:var(--wh);
  text-shadow:0 1px 14px rgba(11,10,9,.9);
}

/* ═════════ intro ═════════ */
.intro{ display:none; }
html.js .intro{
  display:grid; position:fixed; inset:0; z-index:500;
  background:var(--bk);
  place-content:center; justify-items:center; gap:1.5rem;
  transition:opacity .7s var(--ease), visibility .7s;
}
.intro.gone{ opacity:0; visibility:hidden; pointer-events:none; }
.intro__num{
  margin:0; font-family:var(--sans); font-size:10px; font-weight:600;
  letter-spacing:.36em; color:var(--em);
}
.intro__sig{
  margin:0;
  font-family:var(--display);
  font-size:clamp(2.2rem,8vw,5rem);
  text-transform:uppercase; letter-spacing:-.015em; line-height:1;
  opacity:0; transform:translateY(.4em);
  animation:introSig 1.2s var(--ease) .2s forwards;
}
@keyframes introSig{ to{ opacity:1; transform:none; } }
.intro__bar{ width:min(46vw,340px); height:2px; background:rgba(244,241,236,.15); overflow:hidden; }
.intro__bar i{ display:block; height:100%; width:100%; background:var(--em);
  transform:scaleX(0); transform-origin:0 50%; }

/* body is held dark for the intro but never trapped:
   if main.js never runs, the failsafe lights it anyway. */
html.js body{ opacity:0; animation:failsafe 0s linear 3.5s forwards; }
html.js body.lit{ opacity:1; animation:none; transition:opacity .8s var(--ease); }
@keyframes failsafe{ to{ opacity:1; } }

/* ═════════ HUD ═════════ */
.hud{
  position:fixed; inset:0; z-index:300; pointer-events:none;
  font-family:var(--sans); font-size:10px; font-weight:600;
  letter-spacing:.3em; text-transform:uppercase;
  color:var(--wh); mix-blend-mode:difference;
}
.hud span{ position:absolute; }
.hud__tl{ top:var(--pad); left:var(--pad); }
.hud__tr{ top:var(--pad); right:var(--pad); letter-spacing:.22em; }
.hud__bl{ bottom:var(--pad); left:var(--pad); font-variant-numeric:tabular-nums; }

.rail{ position:fixed; top:0; left:0; right:0; height:2px; z-index:310;
       background:rgba(244,241,236,.1); pointer-events:none; }
.rail i{ display:block; height:100%; background:var(--em);
         transform:scaleX(0); transform-origin:0 50%; }

/* ═════════ cursor ═════════ */
.cursor{ display:none; }
@media (hover:hover) and (pointer:fine){
  html.has-cursor, html.has-cursor *{ cursor:none !important; }
  .cursor{
    display:block; position:fixed; top:0; left:0; z-index:350;
    pointer-events:none; mix-blend-mode:difference;
  }
  .cursor__ring,.cursor__lbl{ position:absolute; top:0; left:0; transform:translate(-50%,-50%); }
  .cursor__ring{
    width:11px; height:11px; border-radius:50%; border:1px solid var(--wh);
    transition:width .45s var(--ease), height .45s var(--ease), border-color .35s;
  }
  .cursor.hot .cursor__ring{ width:84px; height:84px; border-color:rgba(244,241,236,.42); }
  .cursor.down .cursor__ring{ width:7px; height:7px; }
  .cursor__lbl{
    font-family:var(--sans); font-size:9px; font-weight:600;
    letter-spacing:.24em; text-transform:uppercase; color:var(--wh);
    white-space:nowrap; opacity:0; transition:opacity .3s;
  }
  .cursor.hot .cursor__lbl{ opacity:1; transition-delay:.1s; }
}

/* ═════════ grain ═════════ */
.grain{
  position:fixed; inset:-120%; z-index:290; pointer-events:none;
  opacity:.24; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:gr 5s steps(5) infinite;
}
@keyframes gr{
  0%{transform:translate(0,0)} 20%{transform:translate(-1.5%,1%)}
  40%{transform:translate(1%,-1.5%)} 60%{transform:translate(-1%,-1%)}
  80%{transform:translate(1.5%,1%)} 100%{transform:translate(0,0)}
}

/* ═════════ SHIP THIS COUPLE ═════════
   Bottom centre — this is the CTA, not a widget. */
.ship{
  position:fixed; z-index:322;
  left:50%; bottom:clamp(1rem,3.4vh,2.2rem);
  display:inline-flex; align-items:center; gap:.7em;
  padding:.92em 1.5em .92em 1.25em;
  font-family:var(--sans); font-size:clamp(11px,.62rem + .3vw,13px);
  font-weight:600; letter-spacing:.17em; text-transform:uppercase;
  color:var(--bk); background:var(--em);
  border:0; border-radius:999px;
  cursor:pointer;
  box-shadow:0 14px 44px -14px rgba(233,116,81,.95);
  transform:translateX(-50%) scale(var(--ss,1));
  transition:transform .45s var(--spring), background .3s, box-shadow .4s;
}
.ship:hover{ background:var(--wh); box-shadow:0 18px 52px -12px rgba(244,241,236,.55); }
.ship.pop{ transition-duration:.09s; --ss:.88; }
.ship__i{ font-size:1.3em; line-height:1; transform:translateY(-.04em); }
.ship:hover .ship__i{ animation:beat .7s var(--spring) infinite; }
@keyframes beat{ 0%,100%{transform:translateY(-.04em) scale(1)} 30%{transform:translateY(-.04em) scale(1.3)} }
.ship__n{
  font-variant-numeric:tabular-nums; letter-spacing:.06em;
  padding-left:.7em; border-left:1px solid rgba(11,10,9,.3);
}
.ship__t{ white-space:nowrap; }

/* page-wide flash behind the burst */
.flash{
  position:fixed; inset:0; z-index:318; pointer-events:none;
  opacity:0;
  background:radial-gradient(circle at 50% 100%,
             rgba(233,116,81,.5) 0%, rgba(233,116,81,.16) 34%, transparent 66%);
}

/* particle layer */
.fx{ position:fixed; inset:0; z-index:320; pointer-events:none; overflow:hidden; }
.fx i,.fx b{
  position:absolute; display:block;
  font-family:var(--sans); font-size:16px; font-style:normal;
  line-height:1; color:var(--em); will-change:transform,opacity;
}
.fx i.plus{ font-weight:600; font-size:13px; letter-spacing:.1em; }
/* the shockwave ring */
.fx b{
  border:2px solid var(--em); border-radius:50%;
  width:40px; height:40px; opacity:0;
}

/* ═════════ display voices ═════════ */
.mast{
  margin:.3em 0 0;
  font-family:var(--display);
  font-weight:400;
  font-size:clamp(2.5rem,.2rem + 9.5vw,9.9rem);
  /* Anton's caps very nearly fill its em box, so anything under
     ~.95 gets shaved by the reveal's overflow:hidden. */
  line-height:.97;
  letter-spacing:-.022em;
  text-transform:uppercase;
}
.mast__l{
  display:block; white-space:nowrap;
  /* headroom for the clip box without adding layout space */
  padding-top:.06em; margin-top:-.06em;
}
.mast__l:nth-child(2){ color:var(--wh); }

.towed{
  margin:.42em 0 0;
  font-family:var(--serif);
  font-size:clamp(1.25rem,.7rem + 2.1vw,2.7rem);
  font-style:italic; line-height:1;
  color:var(--em);
  letter-spacing:.01em;
}

/* masked line reveal */
/* Each [data-in] wraps its content in exactly one .rv — a bare
   `> *` here would blockify every inline child and split the
   line into as many line boxes as it has spans. */
[data-in]{ overflow:hidden; }
[data-in] > .rv{ display:block; transform:translateY(105%); opacity:0; }
body.lit [data-in] > .rv{
  animation:lineUp 1.25s var(--ease) forwards;
  animation-delay:calc(.12s + var(--i,0) * .1s);
}
@keyframes lineUp{ to{ transform:none; opacity:1; } }

/* Robin ⇄ Sayra
   Two whole words overlaid in one grid cell — NOT one cell per
   letter. Per-letter cells have to be as wide as the wider of the
   two glyphs, which opens a gap around narrow letters (the I in
   ROBIN sitting in a cell sized for SAYRA's R). Overlaying whole
   words lets every letter keep its natural width; only the box
   itself changes size, and that is animated. */
.swap{
  display:inline-grid;
  cursor:pointer;
  /* Vertical clip only. A horizontally generous mask means the
     wider word is never shaved while the box morphs width. */
  -webkit-mask-image:linear-gradient(#000,#000);
          mask-image:linear-gradient(#000,#000);
  -webkit-mask-size:500% 100%;  mask-size:500% 100%;
  -webkit-mask-position:center; mask-position:center;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  transition:width .72s var(--ease-io);
}
.swap.measuring{ transition:none; }
.swap__w{
  grid-area:1/1;
  justify-self:start;
  display:flex;
  white-space:pre;
}
.swap__w > span{
  display:block;
  transition:transform .6s var(--ease-io), opacity .42s, filter .42s;
  transition-delay:calc(var(--i) * 42ms);
}
.swap__b > span{ transform:translateY(104%); opacity:0; filter:blur(7px); }
.swap.b .swap__a > span{ transform:translateY(-104%); opacity:0; filter:blur(7px); }
.swap.b .swap__b > span{ transform:none; opacity:1; filter:blur(0); }

/* per-letter magnet */
.ltr{ display:inline-block; transform:translate3d(0,var(--ly,0),0);
      transition:color .35s var(--ease); will-change:transform; }
.ltr.near{ color:var(--em); }
.ltr--sp{ width:.22em; }

/* ═════════ COVER ═════════ */
.cover{
  position:relative; height:100svh; min-height:540px;
  overflow:hidden;
  display:flex; align-items:flex-end;
}
.cover__media{
  position:absolute; inset:0;
  transform:scale(var(--zs,1));
  will-change:transform;
}
/* Frame the cover on the ring — it's the whole reason this photo
   is the cover, and centred it lands behind the mast.

   object-position can't do it: at wide ratios object-fit:cover
   makes the photo width-constrained, so there is no horizontal
   slack to shift into. Scale up to create slack, then translate.

   If you retune these three, keep BOTH edges covered. With a 3:2
   photo, s = --fs, x = --fx, y = --fy:
     wide  (W/H > 3/2)   left: .5 - s/2 + s·x <= 0
                          top: (.5 + s·y)·H <= s·(W/3)
     tall  (W/H < 3/2)   left: (.5 + s·x)·W <= s·(3H/4)
                          top: .5 - s/2 + s·y <= 0
   At 1.34 / 11.5% / 11.7% every ratio clears, but the two left
   terms only clear by ~1.6% of the width — widen the shift and
   you will tear a gap open at the edge. */
.cover__media{
  --fs:1.34;      /* zoom, creates the slack to shift into */
  --fx:11.5%;     /* right, out from behind the type        */
  --fy:11.7%;     /* down, off the top edge                 */
}
.cover__media picture{
  display:block; width:100%; height:100%;
  transform:scale(var(--fs)) translate(var(--fx), var(--fy));
  transform-origin:50% 50%;
}
.cover__media img,.frame__media img{
  width:100%; height:100%; object-fit:cover;
  filter:saturate(1.03) contrast(1.05);
}
.cover__scrim{
  position:absolute; inset:0;
  background:
    linear-gradient(to top, rgba(11,10,9,.96) 0%, rgba(11,10,9,.86) 24%,
                    rgba(11,10,9,.44) 50%, rgba(11,10,9,.06) 74%, rgba(11,10,9,.42) 100%);
}

/* ── cut-ins: hard-edged blocks that mask in and out from the
      edges, on a loop. --hid is the clipped-away state for the
      side each one enters from. ── */
.cutin{
  position:absolute; z-index:2; margin:0;
  overflow:hidden;
  background:var(--bk);
  box-shadow:0 24px 60px -26px rgba(0,0,0,.85);
  clip-path:var(--hid);
  transition:clip-path 1.05s var(--ease-io),
             transform .7s var(--ease);
  transform:translate(var(--cx,0px),var(--cy,0px));
}
.cutin[data-side="l"]{ --hid:inset(0 100% 0 0); --fx:-16%; }
.cutin[data-side="r"]{ --hid:inset(0 0 0 100%); --fx:16%; }
.cutin.shown{ clip-path:inset(0 0 0 0); }

.cutin img{
  width:100%; height:100%; object-fit:cover;
  filter:saturate(1.02) contrast(1.04);
  transform:translateX(var(--fx)) scale(1.16);
  transition:transform 1.6s var(--ease);
}
.cutin.shown img{ transform:translateX(0) scale(1.03); }

.cutin--a{ left:0;  top:0;      width:clamp(150px,26vw,400px); aspect-ratio:2.4/1; }
.cutin--b{ right:0; top:19%;    width:clamp(96px,14vw,230px);  aspect-ratio:2/3; }
.cutin--c{ right:0; bottom:14%; width:clamp(130px,20vw,330px); aspect-ratio:3/2; }
/* the takeover — bigger, rarer, sits over the hero photograph */
.cutin--d{
  right:0; top:50%; z-index:3;
  width:clamp(190px,40vw,660px);
  height:min(62vh,620px);
  transform:translateY(-50%) translate(var(--cx,0px),var(--cy,0px));
  box-shadow:0 40px 90px -30px rgba(0,0,0,.95);
}

.cover__type{
  position:relative; z-index:3;
  padding:var(--pad);
  padding-bottom:clamp(3.2rem,7.5vh,4.8rem);
  width:100%;
}
.cover__date{
  margin:.3em 0 0;
  font-family:var(--display);
  font-size:clamp(1.9rem,.3rem + 5.5vw,5.6rem);
  line-height:1; letter-spacing:-.018em;
  text-transform:uppercase;
  color:var(--wh);
}
.tilde{ display:inline-block; animation:tld 6s ease-in-out infinite; }
@keyframes tld{ 0%,100%{transform:translateY(0) rotate(0)} 50%{transform:translateY(-.08em) rotate(-4deg)} }

/* slow self-animation on every photograph */
.drift{ will-change:transform; }
.drift--a{ animation:coverDrift 40s ease-in-out infinite alternate; }
.drift--b{ animation:kb2 40s ease-in-out infinite alternate; }
.drift--c{ animation:kb3 30s ease-in-out infinite alternate; }
.drift--d{ animation:kb1 44s ease-in-out infinite alternate; }
.drift--e{ animation:kb2 36s ease-in-out infinite alternate; }
.drift--f{ animation:kb3 38s ease-in-out infinite alternate; }
.drift--g{ animation:kb1 42s ease-in-out infinite alternate; }
@keyframes coverDrift{
  from{ transform:scale(1.01) translate(0,0) }
  to{   transform:scale(1.05) translate(-.7%,-.5%) }
}
@keyframes kb1{ from{transform:scale(1.06) translate(0,0)} to{transform:scale(1.15) translate(-1.6%,-1.4%)} }
@keyframes kb2{ from{transform:scale(1.14) translate(1.4%,1%)} to{transform:scale(1.04) translate(-.8%,-.6%)} }
@keyframes kb3{ from{transform:scale(1.05) translate(-1.2%,.8%)} to{transform:scale(1.16) translate(1.2%,-1%)} }

/* ═════════ FRAMES ═════════ */
.frames{ position:relative; }
.frame{
  position:sticky; top:0;
  height:100svh; min-height:540px;
  overflow:hidden; background:var(--bk);
}
.frame__media{
  position:absolute; inset:0;
  transform:scale(var(--zs,1)); will-change:transform;
}
.frame__veil{
  position:absolute; inset:0;
  background:
    linear-gradient(to top, rgba(11,10,9,.74) 0%, rgba(11,10,9,.24) 36%, rgba(11,10,9,.02) 62%),
    linear-gradient(to bottom, rgba(11,10,9,.42) 0%, transparent 30%);
}
/* ── Fig. 02 state outlines ──
   Her state over her, his over him. Decorative overlay on the
   frame, not inside .frame__media — living inside the media box
   would put them under --zs and they'd swell with the photo. */
.states{
  position:absolute; inset:0; z-index:2;
  pointer-events:none;
}
.states[data-r]{ opacity:1; transform:none; }   /* it reveals by drawing, not fading */
.state{
  position:absolute;
  overflow:visible;
  filter:drop-shadow(0 2px 10px rgba(11,10,9,.85));
}
.state path{
  stroke:var(--wh);
  /* user units, not non-scaling-stroke: the viewBox is ~100 wide,
     so the weight stays proportional at every breakpoint instead
     of thinning to a hairline as the shape grows */
  stroke-width:2.4;
  stroke-linejoin:round;
  stroke-dasharray:1;
  stroke-dashoffset:1;
  transition:stroke-dashoffset 2.1s var(--ease-io), stroke .35s var(--ease);
}
/* .states is pointer-events:none so it never eats clicks meant for
   the frame; each shape opts back in just to catch its own hover. */
.state{ pointer-events:auto; }
.state:hover path{ stroke:var(--em); }
.states.in .state path{ stroke-dashoffset:0; }
.states.in .state--tx path{ transition-delay:.42s; }

.state--wi{ left:7.5%;  top:37%; width:clamp(88px,15vw,215px); }
.state--tx{ right:12.5%; top:41%; width:clamp(104px,18.5vw,265px); }

@media (prefers-reduced-motion:reduce){
  .state path{ stroke-dashoffset:0 !important; }
}

.frame__type{
  position:absolute; z-index:3; padding:var(--pad);
  transform:translateY(var(--py,0px)); will-change:transform;
}
.frame__type--bl{ left:0; bottom:clamp(4rem,12vh,7rem); }
.frame__type--c{
  left:50%; top:50%;
  transform:translate(-50%,-50%) translateY(var(--py,0px));
  text-align:center;
}

.word{
  margin:.1em 0 0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(3.4rem,.2rem + 14.5vw,16rem);
  line-height:.84; letter-spacing:-.028em;
  text-transform:uppercase;
}
.word--it{
  font-family:var(--serif);
  font-size:clamp(3rem,.2rem + 12vw,13rem);
  letter-spacing:-.01em; text-transform:none;
}
.word--it em{ font-style:italic; }
.word--amp{
  font-family:var(--serif); text-transform:none;
  font-size:clamp(8rem,32vw,34rem); line-height:.8;
}
.word--amp em{
  font-style:italic; color:var(--em); display:inline-block;
  animation:ampBreathe 9s ease-in-out infinite;
}
@keyframes ampBreathe{ 0%,100%{transform:rotate(-3deg) scale(1)} 50%{transform:rotate(3deg) scale(1.05)} }
.word--r{ font-size:clamp(2.6rem,8.6vw,9rem); letter-spacing:-.025em; }
/* two-line copy needs tighter leading and a smaller cap so it
   doesn't crowd the photo edge it sits beside */
.word--wrap{ font-size:clamp(2rem,6.4vw,6.6rem); line-height:.9; }

/* Matrimony loading. Centred across the middle of the frame, over
   both the black panel and the photo, with the copy below it.
   Refills from empty every time it re-enters view (see main.js). */
.bar{
  /* The plate is 40fr black / 60fr photo, so the bar has to live in
     the left 40% — centred on the frame it straddled both. Right
     edge lines up with the copy's, which shares that padding. */
  position:absolute; z-index:4;
  right:calc(60% + clamp(1.6rem,4.4vw,4.5rem));
  top:50%;
  transform:translateY(-50%);
  width:min(320px,26vw); height:8px;
  background:rgba(244,241,236,.18);
  overflow:hidden;
  box-shadow:0 6px 22px -10px rgba(0,0,0,.9);
}
.bar i{
  display:block; height:100%; width:100%;
  background:var(--em);
  transform:scaleX(0); transform-origin:0 50%;
  transition:transform 1.6s var(--ease-io);
}
.bar.run i{ transform:scaleX(1); }
/* snap back to empty out of view, so the refill always reads as a
   fill rather than draining backwards on the way out */
.bar:not(.run) i{ transition:none; }
.bar::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(100deg,
    transparent 0%, rgba(244,241,236,.5) 46%, transparent 72%);
  transform:translateX(-100%);
  animation:barSheen 2.6s ease-in-out 1.2s infinite;
}
@keyframes barSheen{ 0%{transform:translateX(-100%)} 55%,100%{transform:translateX(320%)} }

.note{
  margin:1.4em 0 0; max-width:28ch;
  font-family:var(--sans);
  font-size:clamp(.92rem,.88rem + .25vw,1.05rem);
  color:var(--wh-dim); line-height:1.5;
}
.note em{ font-family:var(--serif); font-style:italic; font-size:1.2em; color:var(--em-lo); }

/* plate frames — the portrait bleeds top to bottom off one
   edge, the type answers it from the other. A photograph
   floating in the middle of black reads as a slideshow. */
.frame--plate{ background:var(--bk-2); }
.plate{
  height:100%;
  display:grid;
  grid-template-columns:60fr 40fr;
  align-items:end;
}
.plate--rev{ grid-template-columns:40fr 60fr; }
.plate__media{
  grid-column:1; grid-row:1;
  height:100%; overflow:hidden;
  transform:scale(var(--zs,1)); will-change:transform;
}
.plate--rev .plate__media{ grid-column:2; }
.plate__media img{
  width:100%; height:100%; object-fit:cover;
  filter:saturate(1.02) contrast(1.04);
}
.plate__type{
  grid-column:2; grid-row:1; align-self:end;
  padding:var(--pad) var(--pad) clamp(5rem,16vh,10rem) clamp(1.6rem,4.4vw,4.5rem);
  transform:translateY(var(--py,0px)); will-change:transform;
}
.plate--rev .plate__type{
  grid-column:1; text-align:right;
  padding-left:var(--pad); padding-right:clamp(1.6rem,4.4vw,4.5rem);
}
.plate--rev .plate__type .note{ margin-left:auto; }
.plate__type::before{
  content:""; display:block;
  width:clamp(2.4rem,5vw,4.5rem); height:2px;
  background:var(--em);
  margin-bottom:clamp(1.1rem,3vh,2rem);
}
.plate--rev .plate__type::before{ margin-left:auto; }
/* fig 06 already has a horizontal orange rule — the loading bar.
   The decorative dash directly under it just reads as a stutter. */
[data-fig="05"] .plate__type::before{ display:none; }

/* ═════════ COLLAGE ═════════
   Orthogonal, hard-edged, overlapping. No borders, no tilt — the
   photographs butt against each other and a flat colour field, and
   the only movement is per-piece parallax plus a lift on hover. */
.collage{
  position:relative;
  padding:clamp(4rem,11vh,8rem) var(--pad) clamp(2rem,6vh,4rem);
  background:var(--bk);
  overflow:hidden;
  border-top:2px solid rgba(244,241,236,.08);
}
.collage__head{ position:relative; z-index:9; }
.collage__t{
  margin:.24em 0 0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(2rem,.3rem + 6vw,6rem);
  line-height:.92; letter-spacing:-.025em;
  text-transform:uppercase;
}

.collage__stage{
  position:relative;
  height:clamp(680px,112vh,1240px);
  margin-top:clamp(1.5rem,4vh,3rem);
}

.pc{
  position:absolute; margin:0;
  transform:translateY(var(--py,0px)) scale(var(--sc,1));
  transition:transform .55s var(--ease), box-shadow .55s var(--ease);
  will-change:transform;
  box-shadow:0 26px 56px -30px rgba(0,0,0,.9);
}
.pc img{
  width:100%; height:auto; display:block;
  filter:saturate(1.03) contrast(1.05);
  transition:filter .55s var(--ease);
}
/* lift, and come to the front of the stack */
.pc:hover{
  --sc:1.035;
  z-index:20;
  box-shadow:0 44px 90px -34px rgba(0,0,0,.95);
}
.pc:hover img{ filter:saturate(1.16) contrast(1.07); }

.pc figcaption{
  position:absolute; left:0; bottom:-1.9em; white-space:nowrap;
  opacity:0; transform:translateY(-.4em);
  transition:opacity .4s var(--ease), transform .5s var(--ease);
}
.pc:hover figcaption{ opacity:1; transform:none; }

.pc--1{ left:4%;  top:12%; width:clamp(130px,24vw,340px); z-index:4; }
.pc--2{ left:20%; top:26%; width:clamp(210px,40vw,580px); z-index:5; }
.pc--3{ right:4%; top:8%;  width:clamp(115px,21vw,300px); z-index:4; }
.pc--4{ left:14%; top:56%; width:clamp(155px,27vw,390px); z-index:6; }

/* flat blocks — the collage ground */
.blk{
  position:absolute; display:block;
  transform:translateY(var(--py,0px));
  will-change:transform;
}
.blk--1{
  left:26%; top:4%; width:clamp(220px,50vw,720px); height:clamp(180px,34vh,380px);
  background:var(--em); z-index:2;
}
.blk--2{
  right:5%; top:54%; width:clamp(150px,28vw,400px); height:clamp(170px,32vh,360px);
  border:2px solid var(--em); z-index:2;
}

/* typographic scraps */
.slab{
  position:absolute; display:block;
  transform:translateY(var(--py,0px));
  will-change:transform;
}
.slab--1{
  left:62%; top:45%;
  background:var(--em); color:var(--bk);
  padding:.5em .95em .58em;
  font-family:var(--sans); font-size:clamp(10px,1.15vw,15px); font-weight:600;
  letter-spacing:.3em; text-transform:uppercase;
  z-index:8;
  box-shadow:0 10px 26px -12px rgba(0,0,0,.9);
}
.slab--2{
  left:36%; top:80%;
  font-family:var(--display); font-size:clamp(2.6rem,11vw,11rem);
  line-height:.8; letter-spacing:-.035em;
  color:transparent;
  -webkit-text-stroke:2px var(--em);
  z-index:3;
}

/* "love is real" — the two voices of the site in two lines */
.creed[data-r]{
  position:absolute; right:7.5%; top:59%; margin:0;
  z-index:7; text-align:right;
  opacity:1;
  transform:translateY(var(--py,0px));
}
.creed__l{
  display:block; overflow:hidden;
  padding-top:.08em; margin-top:-.08em;
}
.creed__l > *{
  display:block;
  transform:translateY(112%);
  transition:transform 1.15s var(--ease);
}
.creed.in .creed__l > *{ transform:none; }
.creed.in .creed__l:last-child > *{ transition-delay:.14s; }
.creed em{
  font-family:var(--serif); font-style:italic;
  font-size:clamp(2.6rem,9.4vw,9.4rem);
  line-height:.92; color:var(--wh);
  padding-right:.06em;
}
.creed b{
  font-family:var(--display); font-weight:400;
  font-size:clamp(2rem,6.8vw,6.8rem);
  line-height:.9; letter-spacing:-.03em;
  text-transform:uppercase; color:var(--em);
}

/* ═════════ STATEMENT ═════════ */
.stateme{
  min-height:92svh;
  display:grid; align-content:center;
  padding:clamp(5rem,16vh,10rem) var(--pad);
  background:var(--bk);
  border-top:2px solid rgba(244,241,236,.08);
}
.stateme__k{ margin-bottom:clamp(1.6rem,5vh,3rem); }
.stateme__big{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(3rem,.2rem + 13.2vw,14rem);
  line-height:.84; letter-spacing:-.028em;
  text-transform:uppercase;
  white-space:nowrap;
  color:var(--em);
}
.stateme__sub{
  margin:clamp(1.6rem,5vh,3rem) 0 0;
  font-family:var(--serif);
  font-size:clamp(1.2rem,.9rem + 1.3vw,2.3rem);
  font-style:italic; color:var(--wh-dim);
}

/* ═════════ FOOT ═════════ */
.foot{
  padding:clamp(4rem,12vh,8rem) var(--pad) clamp(4.5rem,9vh,5.5rem);
  border-top:2px solid rgba(244,241,236,.08);
}
.foot__big{
  margin:0 0 clamp(2.4rem,7vh,4.4rem);
  font-family:var(--display); font-weight:400;
  font-size:clamp(2.4rem,.2rem + 10vw,10rem);
  line-height:.86; letter-spacing:-.025em;
  text-transform:uppercase;
}
.foot__row{ display:flex; flex-wrap:wrap; gap:1.2rem 2.6rem; justify-content:space-between; }
.foot__row a{ color:inherit; text-decoration:none; }
.foot__row a:hover{ color:var(--em); }
.foot__wink{ color:var(--wh-fnt); transition:color .5s; }
.foot__wink:hover{ color:var(--em); }

/* ═════════ scroll reveals ═════════ */
[data-r]{ opacity:0; transform:translateY(1.6rem);
          transition:opacity 1s var(--ease), transform 1.1s var(--ease); }
[data-r].in{ opacity:1; transform:none; }

/* ═════════ responsive ═════════ */
@media (max-width:820px){
  .plate,.plate--rev{
    grid-template-columns:1fr; grid-template-rows:1fr auto; align-items:stretch;
  }
  .plate__media,.plate--rev .plate__media{ grid-column:1; grid-row:1; height:100%; }
  .plate__type,.plate--rev .plate__type{
    grid-column:1; grid-row:2; text-align:left;
    padding:clamp(1.4rem,4vh,2.2rem) var(--pad) clamp(2.4rem,7vh,4rem);
  }
  .plate--rev .plate__type::before{ margin-left:0; }
  .plate--rev .plate__type .note{ margin-left:0; }
  .word--r{ font-size:clamp(2.4rem,11vw,3.8rem); }
  /* stacked plate: the black band is the bottom row, so the bar drops
     into reserved space at the top of it rather than floating mid-frame */
  [data-fig="05"] .plate__type{ padding-top:11vh; }
  [data-fig="05"] .bar{
    right:var(--pad); left:var(--pad);
    width:auto; top:auto; bottom:27vh;
    transform:none;
  }
  /* An absolutely-placed collage can't hold together at phone
     widths — pieces either clip off the edge or pile up. Below
     820px it flows instead, overlapping with negative margins. */
  .collage__stage{ height:auto; padding-bottom:2rem; }
  .pc{ position:relative; left:auto; right:auto; top:auto; width:auto; }
  .pc--1{ width:70%; }
  .pc--2{ width:84%; margin:-9% 0 0 16%; }
  .pc--3{ width:54%; margin:-14% 0 0 46%; }
  .pc--4{ width:80%; margin:-10% 0 0 4%; }
  .pc:hover{ --sc:1; }

  .blk--1{ top:5vh; left:22%; width:74%; height:30vh; }
  .blk--2{ display:none; }

  .slab--1{ position:relative; top:auto; left:auto; display:inline-block; margin:9% 0 0 2%; }
  .slab--2{
    position:relative; top:auto; left:auto; right:auto;
    display:block; margin:2% 0 0 2%;
    font-size:clamp(2.6rem,17vw,5rem);
  }
  .creed[data-r]{
    position:relative; top:auto; right:auto;
    margin:8% 0 0; text-align:left;
    border:2px solid var(--em);
    padding:clamp(1rem,4vw,1.6rem) clamp(1rem,4vw,1.6rem) clamp(1.2rem,5vw,2rem);
  }
  .cutin--d{
    top:14%; width:60vw; height:34vh;
    transform:translate(var(--cx,0px),var(--cy,0px));
  }
  .cutin--a{ top:0; width:clamp(150px,42vw,260px); }
  .cutin--b{ display:none; }
  .cutin--c{ bottom:auto; top:28%; width:clamp(110px,26vw,170px); }
}
/* A portrait cover-crop keeps only 38% of a landscape frame's width.
   Fig 02 has one of them at each edge, so no crop holds both — show
   the whole frame instead and let the black take the rest. Fig 05's
   pair are both on the left, so that one only needs a shifted crop. */
@media (max-width:820px){
  [data-fig="02"] .frame__media img{
    object-fit:contain;
    object-position:50% 40%;
  }
  /* a contained image has no slack, so any scale >1 crops it again */
  [data-fig="02"] .drift{ animation:driftFit 34s ease-in-out infinite alternate; }
  [data-fig="02"] .frame__veil{ opacity:.55; }

  [data-fig="04"] .frame__media img{ object-position:22% 50%; }

  /* back over the actual people now that they're both in frame */
  .state--wi{ left:6%;  top:37%; width:24vw; }
  .state--tx{ right:5%; top:33%; width:27vw; }
}
@keyframes driftFit{
  from{ transform:scale(.98) translateY(0) }
  to{   transform:scale(1) translateY(-1.2%) }
}

@media (max-width:560px){
  .mast{ font-size:clamp(2.1rem,11.4vw,3.4rem); letter-spacing:-.018em; }
  .mast__l{ white-space:normal; }
  .cover__date{ font-size:clamp(1.6rem,8.6vw,2.6rem); }
  .towed{ font-size:clamp(1.15rem,6vw,1.8rem); }
  .word{ font-size:clamp(2.8rem,17vw,5rem); }
  .word--it{ font-size:clamp(2.4rem,14vw,4rem); }
  .word--amp{ font-size:clamp(6rem,46vw,11rem); }
  .stateme__big{ font-size:clamp(2.2rem,15vw,4.4rem); white-space:normal; }
  .foot__big{ font-size:clamp(2rem,13vw,4rem); }
  .foot__row{ flex-direction:column; gap:.9rem; }
  .pc--1{ width:76%; }
  .pc--2{ width:88%; margin-left:12%; }
  .pc--3{ width:60%; margin-left:40%; }
  .pc--4{ width:86%; margin-left:2%; }
  .creed em{ font-size:clamp(2.4rem,17vw,3.8rem); }
  .creed b{ font-size:clamp(1.7rem,12vw,3rem); }
  .ship{ font-size:10px; padding:.8em 1.05em .8em .9em; gap:.5em; letter-spacing:.13em; }
}

/* ═════════ reduced motion ═════════ */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  [data-in] > *{ transform:none !important; opacity:1 !important; }
  [data-r]{ opacity:1 !important; transform:none !important; }
  .creed__l > *{ transform:none !important; }
  .bar i{ transform:scaleX(1) !important; transition:none !important; }
  .bar::after{ display:none !important; }
  .drift{ animation:none !important; transform:scale(1.02) !important; }
  .cutin{ clip-path:inset(0 0 0 0) !important; }
  .cutin--d{ display:none !important; }
  .cutin img{ transform:none !important; }
  .flash{ display:none !important; }
  .cursor{ display:none !important; }
  html.has-cursor, html.has-cursor *{ cursor:auto !important; }
  html.js body{ opacity:1 !important; }
  .intro{ display:none !important; }
  .fx{ display:none !important; }
}
