/* ══════════════════════════════════════════════════════════════════
   A SHOW FOR ONE
   Palette:  velvet #7B1120 · shadow #4A0A14 · gilt #E8B84B
             paper #F6EDDD · ink #1A1114 · night #07060A
   Type:     Bodoni Moda (marquee) · Caveat (hand) · system (chrome)
   ══════════════════════════════════════════════════════════════════ */

:root{
  --velvet:#7B1120;  --velvet-lo:#4A0A14;  --velvet-hi:#A5182C;
  --gilt:#E8B84B;    --gilt-lo:#B98B22;
  --paper:#F6EDDD;   --paper-lo:#E6D8C1;
  --ink:#1A1114;     --night:#07060A;      --night-lo:#12101A;
  --hand:'Caveat', ui-rounded, cursive;
  --display:'Bodoni Moda', Georgia, serif;
  --ui:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --ease:cubic-bezier(.22,1,.36,1);
  --ease-in:cubic-bezier(.55,0,.68,.28);
}

*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none !important}
html{-webkit-text-size-adjust:100%; scroll-snap-type:y mandatory}   /* one act per screen; a swipe is a page turn */
html.nosnap{scroll-snap-type:none}
body{
  margin:0; background:var(--night); color:var(--paper);
  font-family:var(--ui); -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
body.is-locked{overflow:hidden; height:100dvh}
img{max-width:100%; display:block}
button{font:inherit; color:inherit; cursor:pointer; border:0; background:none}
:focus-visible{outline:2px solid var(--gilt); outline-offset:3px; border-radius:2px}

/* ── persistent layers ─────────────────────────────────────────── */
#fx{position:fixed; inset:0; width:100%; height:100%; pointer-events:none; z-index:110}   /* above #gate (100): the heart-burst happens while the gate is still up */
#flash{position:fixed; inset:0; background:#fff; opacity:0; pointer-events:none; z-index:112}  /* the strobe still whites out the confetti */
#flash.strobe{animation:strobe 1.5s steps(1,end)}
#grain{ /* film grain over everything; static tile, no blend mode, so it costs nothing on a phone */
  position:fixed; inset:0; z-index:85; pointer-events:none; opacity:.05;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0/220px 220px;
}
@keyframes strobe{
  0%,100%{opacity:0}
  6%,14%,26%{opacity:1; background:#fff}
  10%,20%,32%{opacity:1; background:#000}
  40%{opacity:1; background:#fff} 55%{opacity:0}
}

/* ══ 1. COUNTDOWN GATE ═════════════════════════════════════════════ */
#gate{
  position:fixed; inset:0; z-index:100; display:grid; place-items:center;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--velvet-hi) 0%, var(--velvet) 34%, var(--velvet-lo) 78%, #2B060C 100%);
  transition:opacity .9s var(--ease), transform 1.1s var(--ease);
  padding:clamp(20px,6vw,60px);
}
#gate::before{ /* velvet folds */
  content:''; position:absolute; inset:0; opacity:.5; mix-blend-mode:multiply;
  background:repeating-linear-gradient(90deg,
    rgba(0,0,0,.38) 0, rgba(0,0,0,0) 22px, rgba(255,255,255,.035) 40px, rgba(0,0,0,.3) 70px, rgba(0,0,0,0) 96px);
}
.gate-vignette{position:absolute; inset:0; background:radial-gradient(70% 60% at 50% 45%, transparent 40%, rgba(0,0,0,.6) 100%)}
#gate.gone{opacity:0; transform:scale(1.06); pointer-events:none}

.gate-inner{
  position:relative; text-align:center; max-width:min(92vw,880px);
  /* the pair is pinned to the bottom of the gate, and this block is centred in
     it: without room reserved below, adding the "watch something" offer pushed
     the footer onto the mascots on every screen wider than a phone */
  margin-bottom:clamp(110px,20vh,190px);
}
.gate-kicker{
  font-family:var(--hand); font-size:clamp(1.4rem,4.4vw,2.2rem);
  color:var(--gilt); margin:0 0 .5em; letter-spacing:.01em;
}
.clock{display:flex; justify-content:center; gap:clamp(2px,1.5vw,20px); flex-wrap:nowrap; width:100%}
.unit{display:flex; flex-direction:column; align-items:center; min-width:0; flex:1 1 0}
.num{
  font-family:var(--display); font-weight:900; font-variant-numeric:tabular-nums;
  font-size:clamp(2.3rem,11.5vw,6rem); line-height:.92; color:var(--paper);
  text-shadow:0 2px 0 rgba(0,0,0,.35), 0 0 42px rgba(232,184,75,.28);
  transition:transform .28s var(--ease);
}
.num.tick{transform:translateY(-5px) scale(1.05)}
.lbl{
  font-size:clamp(.66rem,2vw,.74rem); letter-spacing:.2em; text-transform:lowercase;
  color:rgba(246,237,221,.46); margin-top:1em;
}
.begin{
  margin-top:clamp(28px,6vw,48px); display:inline-flex; align-items:center; gap:.7em;
  padding:.85em 1.7em; border-radius:999px; background:var(--gilt); color:#2B060C;
  font-weight:700; font-size:clamp(.92rem,2.6vw,1.02rem); letter-spacing:.01em;
  box-shadow:0 10px 34px rgba(0,0,0,.4); transition:transform .2s var(--ease), background .2s, scale .15s var(--ease);
}
.begin.playing{background:transparent; color:var(--gilt); box-shadow:inset 0 0 0 1px rgba(232,184,75,.5)}
.begin-dot{width:7px; height:7px; border-radius:50%; background:currentColor}
.begin.playing .begin-dot{animation:pulse 1.6s infinite}
@keyframes pulse{50%{opacity:.25; transform:scale(.7)}}
.gate-foot{
  margin:1.6em auto 0; max-width:34ch; font-size:.82rem; line-height:1.6;
  color:rgba(246,237,221,.44);
}

/* ══ 1b. MIDNIGHT — aim for the heart ═══════════════════════════════
   The clock gives way to a pale page, a glowing heart and a bow. Pull
   back anywhere and let go (or tap the heart): the arrow flies, the heart
   bursts into little hearts, the page floods velvet, the curtain rises. */
.aim{
  position:absolute; inset:0; z-index:2; overflow:hidden; touch-action:none; user-select:none; -webkit-user-select:none;
  background:radial-gradient(90% 70% at 50% 42%, #FFF4F6 0%, #FBE1E8 50%, #F3C6D2 100%);
  opacity:0; transition:opacity 1.1s var(--ease); cursor:grab;
}
.aim.drawing{cursor:grabbing}
#gate.midnight .aim{opacity:1}
#gate.midnight .gate-inner{opacity:0; pointer-events:none; transition:opacity .5s}
#gate.midnight::before,#gate.midnight .gate-vignette{opacity:0; transition:opacity .8s}
#gate.midnight .cutie-tag{color:var(--velvet)}
#gate.hit .cutie-tag{color:var(--gilt)}
.flood{ /* the velvet that floods the page when the heart is hit */
  position:absolute; inset:0; opacity:0; transition:opacity .45s var(--ease);
  background:radial-gradient(90% 70% at 50% 42%, #B0203A 0%, var(--velvet) 50%, var(--velvet-lo) 100%);
}
#gate.hit .flood{opacity:1}
#gate.hit .aim > :not(.flood){opacity:0; transition:opacity .4s}
.aim-copy{position:absolute; left:16px; right:16px; top:clamp(44px,10vh,100px); text-align:center; pointer-events:none}
.aim-line{margin:0; font-family:var(--display); font-style:italic; font-weight:700; font-size:clamp(1.7rem,6vw,3rem); color:var(--velvet); letter-spacing:-.01em}
.aim-hint{margin:.5em auto 0; max-width:30ch; font-family:var(--hand); font-size:clamp(1rem,3vw,1.25rem); line-height:1.35; color:var(--cocoa)}
.heart-glow{
  position:absolute; left:50%; top:47%; width:min(80vw,520px); aspect-ratio:1; translate:-50% -50%; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, rgba(242,90,130,.5), rgba(242,90,130,.14) 42%, transparent 68%);
  animation:glowPulse 3.2s infinite ease-in-out;
}
.heart{
  position:absolute; left:50%; top:47%; width:clamp(120px,32vw,190px); translate:-50% -50%; padding:0; background:none; cursor:pointer;
  filter:drop-shadow(0 18px 30px rgba(184,20,63,.35));
  transition:scale .2s var(--ease), opacity .25s;
}
/* the bob runs on the drawing, not the button: the button's box stays put
   (an infinitely moving interactive element fails Playwright's stability
   check — decision 6) */
.heart svg{display:block; width:100%; height:auto; animation:heartBob 3.2s infinite ease-in-out}
.heart.pop{scale:1.35; opacity:0; transition:scale .28s var(--ease), opacity .22s .08s}
.heart.pop svg{animation:none}
@keyframes heartBob{50%{translate:0 -12px}}
@keyframes glowPulse{50%{opacity:.72; scale:1.08}}
.bow{
  position:absolute; left:clamp(18px,6vw,80px); bottom:clamp(120px,19vh,210px); height:clamp(104px,26vw,176px); aspect-ratio:1/2;
  transform-origin:64% 50%; rotate:var(--aim,0deg); filter:drop-shadow(0 8px 12px rgba(0,0,0,.18)); pointer-events:none;
}
.bow svg{display:block; width:100%; height:100%; overflow:visible}
.bow .limb{fill:none; stroke:#5A3A22; stroke-width:6; stroke-linecap:round}
.bow .grip{fill:none; stroke:#3A2314; stroke-width:11; stroke-linecap:round}
.bow .string{fill:none; stroke:#4A2A30; stroke-width:1.6}
.arrow{position:absolute; left:0; top:0; width:var(--alen,110px); height:14px; margin-top:-7px; transform-origin:0 50%; pointer-events:none; opacity:0; transition:opacity .3s}
.arrow.on{opacity:1}
.arrow svg{display:block; width:100%; height:100%; overflow:visible}
.arrow .shaft{fill:none; stroke:#5A3A22; stroke-width:2.6; stroke-linecap:round}
.arrow .tip{fill:#2E2226}
.arrow .fletch{fill:var(--rose)}

/* ══ 2. THE STAGE ══════════════════════════════════════════════════ */
#stage{position:fixed; inset:0; z-index:80; pointer-events:none; opacity:0;
  background:var(--night);           /* opaque: the acts must NOT show through the parting curtains */
  overflow:hidden; overflow:clip}    /* the curtains slide off-screen but stay in layout — clip them */
#stage.live{opacity:1}
#stage.done{position:relative; inset:auto; height:100dvh; z-index:5; scroll-snap-align:start; scroll-snap-stop:always}
#stage::after{ /* stage floor + spotlight pool */
  content:''; position:absolute; left:0; right:0; bottom:0; height:34%; z-index:0; pointer-events:none;
  background:
    radial-gradient(60% 100% at 50% 100%, rgba(232,184,75,.16), transparent 70%),
    linear-gradient(transparent, rgba(123,17,32,.22) 60%, rgba(40,6,12,.6));
}

.curtain{
  position:absolute; top:0; bottom:0; width:52%; z-index:2;
  background:
    linear-gradient(90deg, var(--velvet-lo), var(--velvet) 22%, var(--velvet-hi) 46%, var(--velvet) 70%, var(--velvet-lo)),
    var(--velvet);
  transition:transform 3.2s cubic-bezier(.6,0,.2,1);   /* heavy fabric: slow to start, slow to settle */
  will-change:transform;
}
.curtain::before{
  content:''; position:absolute; inset:0; mix-blend-mode:multiply; opacity:.62;
  background:repeating-linear-gradient(90deg,
    rgba(0,0,0,.48) 0, rgba(0,0,0,.05) 14px, rgba(255,255,255,.05) 24px, rgba(0,0,0,.12) 36px,
    rgba(0,0,0,.5) 52px, rgba(0,0,0,.06) 66px, rgba(255,255,255,.04) 76px, rgba(0,0,0,.14) 88px);
}
.curtain::after{ /* bottom sweep */
  content:''; position:absolute; left:0; right:0; bottom:0; height:16%;
  background:linear-gradient(transparent, rgba(0,0,0,.55));
}
.curtain-l{left:0; border-right:3px solid rgba(0,0,0,.4)}
.curtain-r{right:0; border-left:3px solid rgba(0,0,0,.4)}
#stage.open .curtain-l{transform:translateX(-102%)}
#stage.open .curtain-r{transform:translateX(102%)}

.valance{
  position:absolute; top:0; left:0; right:0; height:16vh; z-index:3;
  background:linear-gradient(var(--velvet-hi), var(--velvet-lo));
  transition:transform 3.2s cubic-bezier(.6,0,.2,1);
  -webkit-mask-image:radial-gradient(22px 26px at 22px 100%, transparent 98%, #000 100%);
  mask-image:radial-gradient(22px 26px at 22px 100%, transparent 98%, #000 100%);
  -webkit-mask-size:44px 100%; mask-size:44px 100%;
  box-shadow:0 10px 40px rgba(0,0,0,.6);
}
#stage.open .valance{transform:translateY(-70%)}

.marquee{
  position:absolute; inset:0; z-index:1; display:grid; place-content:center;
  text-align:center; padding:8vw 8vw max(26vh, 230px); opacity:0; transform:scale(.94);   /* the pair lives in the bottom quarter */
  transition:opacity 1.4s var(--ease) .9s, transform 1.6s var(--ease) .9s;
}
#stage.open .marquee{opacity:1; transform:none}
.age{
  font-family:var(--display); font-weight:900; font-style:italic; font-variant-numeric:tabular-nums;
  font-size:min(clamp(5.4rem,26vw,14rem), 20dvh); line-height:1; height:1em; overflow:hidden; margin:0 auto .04em;   /* capped by height so it never meets the pair below */
  color:var(--gilt); letter-spacing:-.04em;
  /* a filter, not text-shadow: text-shadow gets clipped into a hard box by the overflow */
  filter:drop-shadow(0 0 22px rgba(232,184,75,.28));
  transition:filter 1s var(--ease) .9s;
}
.age.flipped{filter:drop-shadow(0 0 46px rgba(232,184,75,.65))}
.age-roll{display:flex; flex-direction:column; transition:transform 1.1s cubic-bezier(.7,0,.2,1)}
.age-roll span{display:block; height:1em; line-height:1}
.age.flipped .age-roll{transform:translateY(-1em)}
.marquee-line{
  font-family:var(--display); font-weight:900; font-style:italic;
  font-size:min(clamp(2rem,8.5vw,5.6rem), 11dvh); line-height:.95; margin:0;
  color:var(--paper); letter-spacing:-.015em;
  text-shadow:0 0 60px rgba(232,184,75,.4), 0 4px 0 rgba(0,0,0,.3);
}
.marquee-sub{
  font-family:var(--hand); font-size:clamp(1.05rem,3.2vw,1.6rem);
  color:var(--gilt); margin:1.1em 0 0; opacity:.85;
}
.bulbs{position:relative; width:min(84vw,680px); height:12px; margin:0 auto clamp(14px,3vh,30px)}
.bulbs::before,.bulbs::after{
  content:''; position:absolute; inset:0;
  background:radial-gradient(circle 4px at 14px 6px, #FFE7A8 0 45%, var(--gilt) 46% 62%, transparent 70%) 0 0/56px 12px repeat-x;
  filter:drop-shadow(0 0 6px rgba(232,184,75,.9)); animation:bulbs 1.3s steps(1,end) infinite;
}
.bulbs::after{background-position:28px 0; animation-delay:.65s}
@keyframes bulbs{0%,49%{opacity:1}50%,100%{opacity:.22}}

.scroll-cue{
  position:absolute; left:50%; bottom:2vh; z-index:4; transform:translateX(-50%);
  width:16px; height:16px; opacity:0; transition:opacity .8s 2.6s;
}
#stage.open .scroll-cue{opacity:1}
.scroll-cue span{
  position:absolute; inset:0; border-right:2px solid rgba(246,237,221,.6); border-bottom:2px solid rgba(246,237,221,.6);
  animation:cue 1.8s infinite var(--ease);
}
@keyframes cue{0%,100%{transform:translateY(-4px) rotate(45deg); opacity:.35}50%{transform:translateY(4px) rotate(45deg); opacity:1}}

/* ══ SHARED ACT SCAFFOLD ═══════════════════════════════════════════ */
#show{position:relative; z-index:10}
.act{
  position:relative; height:100dvh; padding:clamp(48px,9vh,110px) clamp(18px,5vw,56px) clamp(72px,11vh,120px);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:clamp(18px,3.4vh,40px);
  overflow:hidden; overflow:clip; scroll-snap-align:start; scroll-snap-stop:always;
  isolation:isolate;   /* so the stickers can sit at z -1: above the act's background, under its content */
}
.act-decor{position:absolute; inset:0; z-index:-1; pointer-events:none; overflow:hidden}
#act-universe .act-decor{z-index:1}   /* above the star canvas, below the phone */
#act-universe .act-decor img.secret{pointer-events:auto; cursor:pointer}   /* the moon keeps a secret */
#act-universe .act-decor img.secret:focus-visible{outline:2px solid var(--gilt); outline-offset:4px; border-radius:50%}
.decor.nudge{animation:moonNudge .35s}
@keyframes moonNudge{30%{rotate:-18deg}70%{rotate:-2deg}}
.moon-note{
  position:absolute; right:14px; top:max(12px, env(safe-area-inset-top)); max-width:min(56vw,240px); margin:0; text-align:right;
  font-family:var(--hand); font-size:clamp(1rem,3vw,1.15rem); line-height:1.3; color:var(--gilt);
  opacity:0; translate:0 6px; transition:opacity .6s var(--ease), translate .6s var(--ease); pointer-events:none;
}
.moon-note.show{opacity:1; translate:0 0}
.decor{position:absolute; width:clamp(64px,15vw,130px); height:auto; filter:drop-shadow(0 6px 10px rgba(0,0,0,.28))}
.act-cream .decor{filter:drop-shadow(0 6px 10px rgba(74,54,44,.25))}
.decor.d0{left:2%; top:3%; rotate:-10deg}
.decor.d1{right:2%; bottom:5%; rotate:8deg}
.decor.d2{right:3%; top:4%; rotate:9deg}
.decor.d3{left:2%; bottom:6%; rotate:-7deg}
/* the moon is the universe act's secret (tap it three times): on a phone the
   two-line heading starts at ~70px, so it sits tight in the corner, clear of it */
@media (max-width:480px){#act-universe .decor.d0{top:2px; left:4px; width:54px}}
/* the chevron to the next act; shows once the act's beat has played */
.next{
  position:absolute; left:50%; bottom:max(14px, env(safe-area-inset-bottom)); transform:translateX(-50%);
  width:48px; height:48px; z-index:6; opacity:0; pointer-events:none; transition:opacity .7s var(--ease), scale .15s var(--ease);
}
.next span{
  position:absolute; left:50%; top:50%; width:14px; height:14px; margin:-10px 0 0 -7px;
  border-right:2px solid var(--gilt); border-bottom:2px solid var(--gilt); animation:cue 1.8s infinite var(--ease);
}
.act-cream .next span{border-color:var(--cocoa)}
.act.ready .next{opacity:1; pointer-events:auto}
.next:active{scale:.9}
.act-dark{background:linear-gradient(var(--night-lo), var(--night))}
.act-night{background:var(--night); overflow:hidden}
.act-head{text-align:center; max-width:46ch}
.act-head h2{
  font-family:var(--display); font-weight:700; font-style:italic;
  font-size:clamp(1.9rem,6.5vw,3.4rem); margin:0; line-height:1.05; letter-spacing:-.01em;
  text-wrap:balance;   /* the box is a 46ch cap measured in the sans, ~397px; a two-line Bodoni title breaks at the middle, not after the last word that fits */
}
.act-head p{
  font-family:var(--hand); font-size:clamp(1.1rem,3.2vw,1.42rem);
  color:var(--gilt); margin:.5em 0 0; opacity:.8;
}
.ghost-btn{
  padding:.7em 1.5em; border-radius:999px; font-size:.88rem; font-weight:600;
  box-shadow:inset 0 0 0 1px rgba(246,237,221,.28); color:rgba(246,237,221,.8);
  transition:box-shadow .2s, color .2s, transform .2s var(--ease), scale .15s var(--ease);
}

.rv{opacity:0; translate:0 22px; transition:opacity .9s var(--ease), translate .9s var(--ease)}   /* `translate`, so it never fights an element's own transform */
.rv-2{transition-delay:.1s} .rv-3{transition-delay:.2s} .rv-4{transition-delay:.3s}
.act.in .rv{opacity:1; translate:0 0}

/* ── the wait/watch offer on the countdown screen ─────────────────── */
.gate-wait{display:flex; flex-direction:column; align-items:center; gap:.7em; margin-top:.2em}
.gate-ask{
  margin:0; font-family:var(--hand); font-size:clamp(1.05rem,3.6vw,1.35rem);
  color:rgba(246,237,221,.82); text-align:center; text-wrap:balance; max-width:22ch;
}
.gate-watch{   /* secondary on purpose: "Turn the music on" is the audio unlock and must stay the loud one (decision 1) */
  font-family:var(--ui); font-size:clamp(.82rem,2.7vw,.95rem); font-weight:600; line-height:1.25;
  color:var(--gilt); border-radius:999px; padding:.8em 1.4em;
  max-width:min(88vw,30ch); text-align:center; box-shadow:inset 0 0 0 1px rgba(232,184,75,.5);
  transition:scale .15s var(--ease), background .2s, color .2s;
}
.gate-watch:focus-visible{outline:2px solid var(--gilt); outline-offset:3px}
.gate-watch:active{scale:.97}
@media (hover:hover) and (pointer:fine){ .gate-watch:hover{background:var(--gilt); color:var(--night)} }
#gate.midnight .gate-wait{display:none}   /* the clock has run out; the heart owns the screen now */

/* the player itself: full screen, above the gate (100) but under #fx (110) */
.reels{
  position:fixed; inset:0; z-index:105; background:#05040688;
  backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px;
  padding:clamp(12px,3vh,28px); animation:reelIn .32s var(--ease);
}
@keyframes reelIn{from{opacity:0}to{opacity:1}}
.reel-video{
  width:min(92vw, calc((100dvh - 150px) * 9 / 16)); max-height:calc(100dvh - 150px);
  aspect-ratio:9/16; object-fit:cover; border-radius:16px; background:#000;
  box-shadow:0 30px 70px rgba(0,0,0,.6);
}
.reel-bar{display:flex; align-items:center; gap:clamp(10px,3vw,22px); flex-wrap:wrap; justify-content:center}
.reel-back,.reel-next{
  font-family:var(--ui); font-size:.85rem; font-weight:600; padding:.65em 1.2em; border-radius:999px;
  color:var(--paper); box-shadow:inset 0 0 0 1px rgba(246,237,221,.32); transition:background .2s, scale .15s var(--ease);
}
.reel-next{background:var(--gilt); color:var(--night); box-shadow:none}
.reel-back:active,.reel-next:active{scale:.97}
.reel-back:focus-visible,.reel-next:focus-visible{outline:2px solid var(--gilt); outline-offset:3px}
.reel-count{margin:0; font-family:var(--ui); font-size:.72rem; letter-spacing:.14em; color:rgba(246,237,221,.55)}
@media (prefers-reduced-motion:reduce){ .reels{animation:none} }

/* ══ 3. CAMERA + POLAROIDS ═════════════════════════════════════════ */
#act-camera{background:linear-gradient(#1B0A0F, var(--night-lo)); padding-top:clamp(120px,17vh,170px)}
.camera-rig{
  position:absolute; top:0; left:50%; transform:translate(-50%,-130%);
  z-index:5; transition:transform 1.5s var(--ease);
}
#act-camera.shot .camera-rig{transform:translate(-50%,-6%)}   /* hangs just inside the top edge, top plate visible */
.cam-body{
  width:clamp(120px,26vw,180px); height:clamp(78px,17vw,116px); border-radius:12px;
  background:linear-gradient(#E9EAEE 0 31%, #B9BCC4 31% 34%, #1C1C21 34% 100%);   /* chrome top plate, leatherette body */
  position:relative;
  box-shadow:0 18px 40px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.6);
}
.cam-body::before{ /* shutter button */
  content:''; position:absolute; right:38px; top:7px; width:11px; height:11px; border-radius:50%;
  background:radial-gradient(circle at 40% 35%, #E25566, #A81E30 70%); box-shadow:0 1px 2px rgba(0,0,0,.4);
}
.cam-body::after{ /* leatherette grain */
  content:''; position:absolute; left:0; right:0; top:36%; bottom:0; border-radius:0 0 12px 12px;
  background:repeating-linear-gradient(90deg,#131317 0 2px,#26262C 2px 4px); opacity:.8;
}
.cam-lens{
  position:absolute; left:50%; top:52%; transform:translate(-50%,-50%);
  width:clamp(42px,9vw,60px); aspect-ratio:1; border-radius:50%;
  background:radial-gradient(circle at 34% 30%, #4E5560, #0A0A0D 62%);
  box-shadow:0 0 0 4px #1D1D22, 0 0 0 7px #D8DAE0, 0 8px 16px rgba(0,0,0,.5), inset 0 0 14px rgba(0,0,0,.9); z-index:2;   /* chrome ring */
}
.cam-lens i{
  position:absolute; left:26%; top:22%; width:22%; aspect-ratio:1; border-radius:50%;
  background:rgba(180,220,255,.5); filter:blur(1px);
}
.cam-flash{
  position:absolute; right:12px; top:8px; width:20px; height:11px; border-radius:2px;
  background:linear-gradient(#FBFBFD,#B4B7C0); box-shadow:inset 0 0 0 1px rgba(0,0,0,.28);
}
#act-camera.shot .cam-flash{animation:flashpop 1.5s ease-out}
@keyframes flashpop{0%,18%{background:#C9CBD2}22%{background:#fff; box-shadow:0 0 40px 18px rgba(255,255,255,.95)}60%,100%{background:#C9CBD2; box-shadow:none}}
.cam-dial{ /* viewfinder window */
  position:absolute; left:12px; top:7px; width:22px; height:13px; border-radius:2px;
  background:linear-gradient(#2B3540,#0C1014); box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.35);
}
.cam-strap{
  width:clamp(120px,26vw,180px); height:20px; margin-top:-4px;
  background:linear-gradient(90deg,transparent 0 8%, #6B2230 8% 92%, transparent 92%);
  border-radius:0 0 40% 40%; opacity:.9;
}

.cheese{
  position:absolute; top:22%; left:50%; transform:translate(-50%,0) rotate(-4deg);
  font-family:var(--hand); font-weight:700; font-size:clamp(3rem,15vw,8rem);
  color:var(--gilt); margin:0; opacity:0; pointer-events:none; z-index:6;
  text-shadow:0 0 50px rgba(232,184,75,.6);
}
#act-camera.shot .cheese{animation:cheese 2.2s var(--ease) .35s}
/* the stamp lands where the heading sits on every viewport (there is no empty
   band under the camera on a desktop), so the heading waits until the stamp is
   leaving: flash, "Cheese!", then the words */
@media (prefers-reduced-motion:no-preference){#act-camera.in .act-head.rv{transition-delay:2.3s}}
@keyframes cheese{0%{opacity:0;transform:translate(-50%,20px) rotate(-4deg) scale(.7)}22%,62%{opacity:1;transform:translate(-50%,0) rotate(-4deg) scale(1)}100%{opacity:0;transform:translate(-50%,-30px) rotate(-4deg) scale(1.1)}}

/* the tile is sized from the width (four across) and from the height (two
   rows must fit under the header on one screen), whichever is tighter; the
   wall itself is never wider than four tiles, so a short screen (small tiles)
   still reads 4 + 4 and not 7 + 1 */
.polaroid-wall{
  --rows:2; --zoom:1.45; --gap:clamp(14px,2.4vw,26px);
  --polw:min(clamp(120px,20vw,216px), calc((100dvh - 365px) / var(--rows) / 1.22));
  display:flex; flex-wrap:wrap; justify-content:center; align-items:flex-start;
  gap:var(--gap); max-width:calc(4 * var(--polw) + 3 * var(--gap) + 8px); perspective:1400px;
}
.pol{
  width:var(--polw); aspect-ratio:1/1.22; position:relative;
  transform-style:preserve-3d; transition:transform .75s var(--ease), scale .15s var(--ease), translate .75s var(--ease);
  cursor:pointer; background:none; padding:0;
}
.pol:nth-child(odd){rotate:-2.4deg} .pol:nth-child(even){rotate:2deg}
.pol:nth-child(3n){rotate:-4deg}
/* a flipped photo lifts toward her so the handwriting on the back is legible,
   and the ones on the edges slide inward so the lift never leaves the screen */
.pol.flipped{transform:rotateY(180deg) scale(var(--zoom)); z-index:5; translate:var(--shift,0) 0}
.pol:nth-child(4n+1){--shift:calc(var(--polw) * .22)} .pol:nth-child(4n){--shift:calc(var(--polw) * -.22)}
.pol-face{
  position:absolute; inset:0; backface-visibility:hidden; -webkit-backface-visibility:hidden;
  background:var(--paper); border-radius:3px; padding:9px 9px 0;
  box-shadow:0 14px 30px rgba(0,0,0,.55), 0 1px 0 rgba(255,255,255,.4) inset;
  display:flex; flex-direction:column;
}
.pol-img{
  flex:1; background:#241A1D center/cover no-repeat; border-radius:1px;
  filter:contrast(.4) brightness(1.5) saturate(.2); transition:filter 2.6s ease-out;
}
.pol.developed .pol-img{filter:none}
.pol-cap{
  font-family:var(--hand); font-size:clamp(.82rem, calc(var(--polw) * .105), 1.2rem); color:#4A3A2E;
  text-align:center; padding:.45em 0 .55em; margin:0; line-height:1.2; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pol-back{
  position:absolute; inset:0; backface-visibility:hidden; -webkit-backface-visibility:hidden;
  transform:rotateY(180deg); background:var(--paper-lo); border-radius:3px;
  padding:calc(var(--polw) * .1); display:grid; place-content:center; text-align:center; overflow:hidden;
  box-shadow:0 14px 30px rgba(0,0,0,.55);
  /* sized from the tile, not the viewport: the message must fit the back
     of a 100px phone tile as well as a 216px laptop one */
  font-size:calc(var(--polw) * .105);
}
.pol-back p{
  font-family:var(--hand); font-size:inherit; line-height:1.5; color:#3A2C24; margin:0;
  background-image:linear-gradient(rgba(74,58,46,.13) 1px, transparent 1px);   /* a rule under every line, at the text's own pitch */
  background-size:100% 1.5em; background-position:0 calc(1.5em - 1px);
}

/* ══ 3b. 22 BALLOONS, 22 REASONS ═══════════════════════════════════ */
.act-reasons{justify-content:flex-start; gap:0}
.act-reasons .act-head{position:relative; z-index:3}
.balloon-sky{position:absolute; inset:0; overflow:hidden; z-index:1}
.bln{
  position:absolute; left:calc(4% + var(--x) * (92% - clamp(62px,15vw,92px))); bottom:-24%; width:clamp(62px,15vw,92px); aspect-ratio:40/62; padding:0; background:none; cursor:pointer;   /* --x is 0..1: at 86% + its own width a phone balloon spawned a fifth off the right edge */
  animation:blnUp var(--d) linear forwards; animation-delay:var(--delay,0s);
  filter:drop-shadow(0 10px 14px rgba(0,0,0,.4));
}
.bln > span{display:block; width:100%; height:100%; animation:blnSway 2.8s ease-in-out infinite alternate; animation-delay:var(--sd,0s)}
.bln svg{display:block; width:100%; height:100%; overflow:visible}
.bln .no{
  position:absolute; left:0; right:0; top:26%; text-align:center; font-family:var(--display); font-weight:900; font-style:italic;
  font-size:clamp(1.1rem,3.6vw,1.5rem); color:rgba(255,255,255,.92); pointer-events:none; text-shadow:0 1px 2px rgba(0,0,0,.25);
}
.bln.pop{animation:blnPop .32s var(--ease) forwards; pointer-events:none}
.bln:focus-visible{outline:none} .bln:focus-visible svg{filter:drop-shadow(0 0 0 3px var(--gilt))}
.bln.pop > span{animation:none}
@keyframes blnUp{to{translate:0 -150dvh}}
@keyframes blnSway{from{rotate:-6deg; translate:-6px 0}to{rotate:6deg; translate:6px 0}}
@keyframes blnPop{40%{scale:1.25; opacity:1}100%{scale:1.6; opacity:0}}
.act-reasons.still .bln{animation:none; bottom:auto; top:var(--y)}   /* prefers-reduced-motion: they hang where they are */
.act-reasons.still .bln > span{animation:none}
.reason-card{
  position:relative; z-index:4; margin:auto 0; width:min(88vw,460px); text-align:center;
  padding:clamp(18px,4vw,28px) clamp(18px,5vw,34px); border-radius:16px; background:var(--paper); color:#33261F;
  box-shadow:0 24px 60px rgba(0,0,0,.6), 0 0 0 1px rgba(232,184,75,.35); pointer-events:none;
  animation:reasonIn .45s cubic-bezier(.2,1.3,.4,1);
}
.reason-card b{display:block; font:600 .66rem var(--ui); letter-spacing:.24em; text-transform:uppercase; color:var(--cocoa); margin-bottom:.5em}
.reason-card span{font-family:var(--hand); font-size:clamp(1.35rem,5vw,2rem); line-height:1.25; display:block}
@keyframes reasonIn{from{opacity:0; scale:.85; translate:0 10px}}
.reason-count{
  position:absolute; left:0; right:0; bottom:calc(max(14px, env(safe-area-inset-bottom)) + 52px); margin:0; text-align:center; z-index:3;
  font:600 .66rem var(--ui); letter-spacing:.22em; text-transform:uppercase; color:rgba(246,237,221,.5); pointer-events:none;
}
.reason-count.done{color:var(--gilt); font-family:var(--hand); font-size:clamp(1.1rem,3.4vw,1.4rem); letter-spacing:0; text-transform:none}

/* ══ 4. CAKE ═══════════════════════════════════════════════════════ */
.cake-stage{position:relative; display:grid; place-items:end center; min-height:clamp(200px,30vh,270px)}
.cake{position:relative; width:min(clamp(200px,52vw,300px), 42dvh); transition:transform .6s var(--ease)}
.cake-art{display:block; width:100%; height:auto; filter:drop-shadow(0 18px 30px rgba(0,0,0,.45))}
.cake .slice{transition:transform .7s var(--ease)}
.cake.cut .slice{transform:translate(26px,9px) rotate(2.5deg)}
.cake .cut-face{opacity:0; transition:opacity .25s .15s}
.cake.cut .cut-face{opacity:1}
.candles{
  position:absolute; top:25.8%; left:50%; transform:translate(-50%,-100%);   /* feet on the top tier's face */
  display:flex; gap:clamp(12px,3.6vw,22px); z-index:3;
}
.candle{position:relative; width:7px; height:clamp(34px,8vw,48px); border-radius:3px; transition:scale .15s var(--ease);
  background:repeating-linear-gradient(180deg,#F6EDDD 0 5px,#D9536A 5px 10px)}
.candle::before{content:''; position:absolute; left:50%; top:-4px; width:1.5px; height:5px; background:#4A3A2E; transform:translateX(-50%)}
.candle::after{content:''; position:absolute; inset:-18px -8px -6px}   /* a 7px candle needs a thumb-sized target; never wider than half the gap or taps land on the neighbour */
.candles.digits{gap:4px}
.candle.digit::after{inset:-18px -1px -6px}
.candle.digit{width:auto; height:auto; background:none; border-radius:0}
.candle.digit .num{
  display:block; font-family:var(--display); font-weight:900; font-style:italic; line-height:1;
  font-size:clamp(2.3rem,8.5vw,3.2rem); letter-spacing:-.03em; color:transparent;
  background:repeating-linear-gradient(135deg,#F6EDDD 0 5px,#D9536A 5px 10px); -webkit-background-clip:text; background-clip:text;
  filter:drop-shadow(0 2px 1px rgba(0,0,0,.35));
}
.candle.digit::before{top:-6px}
.flame{
  position:absolute; left:50%; bottom:100%; width:11px; height:17px;
  transform:translateX(-50%) translateY(-3px);
  background:radial-gradient(ellipse at 50% 72%, #FFF6C2 0 18%, var(--gilt) 42%, #E8622B 72%, transparent 78%);
  border-radius:50% 50% 46% 46%; filter:blur(.4px);
  animation:flicker .42s infinite alternate var(--ease);
  transform-origin:50% 100%;
}
@keyframes flicker{to{transform:translateX(-50%) translateY(-5px) scale(1.1,1.16) rotate(2deg); opacity:.88}}
.candle.out .flame{animation:none; opacity:0; transition:opacity .3s}
.smoke{
  position:absolute; left:50%; bottom:100%; width:5px; height:26px; opacity:0; transform:translateX(-50%);
  background:linear-gradient(rgba(220,220,220,.5), transparent); filter:blur(3px); pointer-events:none;
}
.candle.out .smoke{animation:smoke 2s ease-out forwards}
@keyframes smoke{from{opacity:.9; transform:translateX(-50%)}to{transform:translate(-50%,-32px) scaleX(2.4); opacity:0}}

.cake.cut{transform:translateY(4px)}

.knife{
  position:absolute; left:64%; top:50%; transform:translateX(-50%) rotate(-24deg);
  padding:0; line-height:0; z-index:4; touch-action:none;
  filter:drop-shadow(0 6px 12px rgba(0,0,0,.6)); transition:opacity .4s;
}
.knife svg{width:clamp(78px,19vw,122px); height:auto; display:block}
.knife.hidden{opacity:0; pointer-events:none}
.knife:not(.hidden){animation:knifeNudge 1.9s var(--ease) 4}
@keyframes knifeNudge{0%,100%{transform:translateX(-50%) rotate(-24deg)}50%{transform:translateX(calc(-50% + 12px)) rotate(-17deg)}}
.cake-actions{display:flex; gap:12px}
.cake-actions.hidden{display:none}
#act-cake .act-head{transition:opacity .6s var(--ease), translate .9s var(--ease)}
#act-cake.cut .act-head{opacity:0}
.wish{
  font-family:var(--hand); font-size:clamp(1.5rem,5.5vw,2.6rem); color:var(--gilt);
  margin:0; opacity:0; transition:opacity 1s var(--ease); text-align:center;
}
.wish.in{opacity:1}

/* ══ 5. LETTER — "you got a mail" ═════════════════════════════════════
   A pale page, a mail slot, and a deep-red envelope that drops through it.
   She taps the button (or the envelope): the seal breaks, the flap opens,
   the letter slides out and types itself. The paper scrolls inside
   #letterWrap, never the window (decision 17). */
.act-paper{
  background:radial-gradient(120% 80% at 50% 0%, #FFF3F5 0%, #FBE2E8 45%, #F5CDD8 100%);
  justify-content:flex-start;
}
.mail-head{max-width:none}
.mail-head h2{
  font-style:normal; text-transform:uppercase; letter-spacing:.16em; white-space:nowrap;
  font-size:clamp(1.25rem,4.4vw,2.2rem); color:var(--velvet);
}
.mail-head p{color:var(--cocoa); opacity:.9}
#act-letter .cutie-tag{color:var(--velvet)}
#act-letter .next span{border-color:var(--velvet)}
.letter-wrap{
  /* the envelope is sized from the width, and capped so heading + envelope +
     the claim button fit one screen even on a short laptop */
  --envw:min(88vw, 620px, calc((100dvh - 340px) / .59)); --envh:calc(var(--envw) * .59);
  --peek:min(clamp(64px,11vw,100px), 12dvh);
  position:relative; width:100%; max-width:var(--envw); flex:1 1 auto; min-height:0;
  overflow-y:auto; overflow-x:hidden; scrollbar-width:none;   /* no overscroll-behavior:contain: a wheel past the end must turn the page */
}
.letter-wrap::-webkit-scrollbar{display:none}
.letter-inner{position:relative; padding-top:var(--peek); min-height:calc(var(--envh) + var(--peek))}
.cuties.letter-cuties{
  position:absolute; left:50%; top:var(--peek); z-index:0; gap:clamp(34px,12vw,110px);
  transform:translate(-50%,-8%); opacity:0;
  transition:opacity .7s var(--ease), transform 1s var(--ease);
}
.letter-wrap.peeking .letter-cuties{opacity:1; transform:translate(-50%,-57%)}

/* the slot the mail comes through: a pale bar with a dark slit, just above
   where the envelope lands */
.mail-slot{
  position:absolute; z-index:2; left:0; top:calc(var(--peek) - 30px); width:100%; height:26px; border-radius:999px;
  background:linear-gradient(#FBF4F5,#DCC9CE); box-shadow:0 8px 22px rgba(123,17,32,.16), inset 0 1px 0 #fff, inset 0 -1px 0 rgba(0,0,0,.08);
  display:grid; place-items:center; opacity:0; transform:translateY(-12px);
  transition:opacity .6s var(--ease) .1s, transform .7s var(--ease) .1s;
}
.mail-slot i{display:block; width:86%; height:6px; border-radius:999px; background:#2A1A20; box-shadow:inset 0 2px 3px #000, 0 1px 0 rgba(255,255,255,.7)}
#act-letter.in .mail-slot{opacity:1; transform:none}
#letterWrap.opened .mail-slot{opacity:0; transition-delay:.2s}   /* its job is done once she claims the mail (same specificity as the rule above, later wins) */

/* the envelope: one group so it drops through the slot as one thing. The drop
   moves it down while a clip keeps everything above the slit hidden — both
   in one animation so they stay in step. The animation has no forwards fill:
   once it has landed the group has no transform and no clip, so it is not a
   stacking context and its parts keep their own z-order — the letter slides
   out between the back and the front pocket exactly as before. */
.env-group{position:absolute; left:4%; top:var(--peek); width:92%; height:var(--envh); visibility:hidden}
.letter-wrap.arrive .env-group{visibility:visible; animation:mailDrop 1.5s cubic-bezier(.22,.9,.32,1) backwards; cursor:pointer}
@keyframes mailDrop{
  from{transform:translateY(calc(-100% - 17px)); clip-path:inset(100% 0 0 0)}
  to{transform:translateY(0); clip-path:inset(0 0 0 0)}
}
.env-back,.env-front,.env-flap{
  position:absolute; inset:0; border-radius:8px; pointer-events:none;
  transition:transform 1s var(--ease) .45s, opacity .7s var(--ease) .6s;
}
.env-back{z-index:1; background:linear-gradient(#5E0B1A,#6E0F20)}   /* the inside: darker than the pocket so the open V reads */
.env-group::before{ /* the shadow, cast by a narrower box so #letterWrap's overflow never cuts it to a hard edge;
                        the box stays inside the envelope: a shadow is not painted inside its own box, so any part
                        poking out showed as a pale ledge under the envelope */
  content:''; position:absolute; z-index:0; inset:12px 30px 8px 30px; border-radius:14px;
  box-shadow:0 38px 40px rgba(123,17,32,.34); transition:opacity .7s var(--ease) .6s;
}
.letter-wrap.out .env-group::before{opacity:0}
.env-front{z-index:3; background:linear-gradient(170deg,#C72C3E,#A31C2D 55%,#8C1425); clip-path:polygon(0 0,50% 56%,100% 0,100% 100%,0 100%)}
.env-front::after{ /* the side folds */
  content:''; position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(90deg, rgba(0,0,0,.16), transparent 28% 72%, rgba(0,0,0,.16));
}
.env-flap{
  z-index:4; background:linear-gradient(#B4233A,#8E1526); clip-path:polygon(0 0,100% 0,50% 60%);
  transform-origin:50% 0; transition:transform .85s var(--ease), opacity .6s var(--ease) .6s, z-index 0s .35s;
}
.env-seal{ /* gold wax */
  position:absolute; z-index:5; left:50%; top:60%; width:clamp(46px,9vw,62px); height:clamp(46px,9vw,62px);
  transform:translate(-50%,-50%); border-radius:50%; display:grid; place-items:center; pointer-events:none;
  background:radial-gradient(circle at 35% 30%, #FBE6A3, #D9A63A 52%, #9A6D15);
  box-shadow:0 5px 12px rgba(0,0,0,.35), inset 0 0 0 3px rgba(255,255,255,.14), inset 0 2px 3px rgba(255,255,255,.4);
  font-family:var(--display); font-style:italic; font-weight:900; color:#6E4608; font-size:clamp(1.3rem,3.2vw,1.9rem);
  transition:transform .4s var(--ease), opacity .3s;
}
.letter-wrap.opened .env-seal{transform:translate(-50%,-50%) scale(1.6); opacity:0}
.letter-wrap.opened .env-flap{transform:perspective(900px) rotateX(180deg); z-index:0; opacity:0; transition:transform .85s var(--ease), opacity .4s var(--ease) .25s, z-index 0s .35s}   /* fully open it would poke above #letterWrap and be cut flat */
.letter-wrap.out .env-back,.letter-wrap.out .env-front{transform:translateY(60%); opacity:0}
.letter-wrap.out .env-flap{opacity:0}

/* the button under the slot */
.claim{
  position:absolute; left:50%; bottom:clamp(22px,4vh,40px); translate:-50% 12px; z-index:5;   /* Acts.letter moves it to just under the envelope */
  padding:.85em 1.6em; border-radius:999px; background:var(--velvet); color:var(--paper);
  font-weight:700; font-size:clamp(.86rem,2.5vw,.98rem); letter-spacing:.01em; white-space:nowrap;
  box-shadow:0 12px 30px rgba(123,17,32,.35); opacity:0; pointer-events:none;
  transition:opacity .5s var(--ease), translate .6s var(--ease), scale .15s var(--ease), background .2s;
}
.claim.show{opacity:1; pointer-events:auto; translate:-50% 0; animation:claimPulse 1.5s 4 .6s}   /* 4 runs, not infinite (decision 6) */
.claim.gone{opacity:0; pointer-events:none; scale:.9}
@keyframes claimPulse{50%{box-shadow:0 12px 30px rgba(123,17,32,.35), 0 0 0 12px rgba(123,17,32,.12)}}

.letter{
  width:92%; margin-inline:auto; background:var(--paper);
  padding:clamp(30px,7vw,64px) clamp(24px,6vw,58px);
  color:#33261F; border-radius:2px; position:relative; z-index:2;
  box-shadow:0 24px 60px rgba(123,17,32,.22);
  opacity:0; transform:translateY(30%) scale(.7); transform-origin:50% 0; clip-path:inset(0 0 100% 0);
  transition:transform 1.3s var(--ease), opacity .45s var(--ease), clip-path 1.3s var(--ease);
}
.letter-wrap.out .letter{opacity:1; transform:none; clip-path:inset(-20px 0 -90px 0); z-index:6;   /* -90 at the bottom: the 60px shadow fades out instead of being cut to a band under the torn edge (the envelope is gone by now, nothing to hide) */ transition:transform 1.3s var(--ease), opacity .45s var(--ease), clip-path 1.3s var(--ease), z-index 0s .9s}
.letter::after{ /* torn edge */
  content:''; position:absolute; left:0; right:0; bottom:-9px; height:10px; background:var(--paper);
  -webkit-mask-image:radial-gradient(7px 9px at 7px 0, transparent 98%, #000 100%);
  mask-image:radial-gradient(7px 9px at 7px 0, transparent 98%, #000 100%);
  -webkit-mask-size:14px 100%; mask-size:14px 100%;
}
.l-salut,.l-signoff,.l-sign{font-family:var(--hand); margin:0}
.l-salut{font-size:clamp(1.5rem,4.6vw,2rem); font-weight:700; margin-bottom:.7em}
.l-body p{
  font-family:var(--hand); font-size:clamp(1.22rem,3.6vw,1.6rem); line-height:1.9;
  margin:0 0 .9em; white-space:pre-wrap; min-height:1.9em;
  background-image:linear-gradient(rgba(74,58,46,.13) 1px, transparent 1px);
  background-size:100% 1.9em; background-position:0 calc(1.9em - 1px);
}
.l-body .caret{display:inline-block; width:2px; height:1em; background:#33261F; vertical-align:-2px; animation:caret .9s steps(1) infinite}
@keyframes caret{50%{opacity:0}}
.l-signoff{font-size:clamp(1.2rem,3.4vw,1.5rem); margin-top:1.4em; opacity:.85}
.l-sign{font-size:clamp(1.9rem,6vw,2.7rem); font-weight:700; margin-top:.15em; color:#7B1120}

/* P.S. — the voice note and the "open when" envelopes, under the signature */
.ps{margin-top:.6em}
.l-voice{
  display:inline-flex; align-items:center; gap:.55em; margin:.6em 0 .2em; padding:.5em .95em; border-radius:999px;
  border:1px solid rgba(123,17,32,.35); background:transparent; color:var(--velvet);
  font-family:var(--hand); font-size:clamp(1.05rem,3.2vw,1.2rem); cursor:pointer; transition:scale .15s var(--ease), background .2s;
}
.l-voice:active{scale:.97}
.lv-dot{width:9px; height:9px; border-radius:50%; background:var(--velvet)}
.lv-bars{display:none; align-items:flex-end; gap:2px; height:14px}   /* a fixed box: the button never moves while the bars dance (decision 26) */
.lv-bars i{width:3px; height:6px; border-radius:2px; background:var(--velvet)}
.l-voice.on .lv-dot{display:none}
.l-voice.on .lv-bars{display:inline-flex}
.l-voice.on .lv-bars i{animation:lvb .7s ease-in-out infinite alternate}
.l-voice.on .lv-bars i:nth-child(2){animation-delay:.15s} .l-voice.on .lv-bars i:nth-child(3){animation-delay:.3s} .l-voice.on .lv-bars i:nth-child(4){animation-delay:.1s}
@keyframes lvb{to{height:14px}}
.ow{margin-top:1.1em; padding-top:1em; border-top:1px dashed rgba(123,17,32,.25)}
.ow-kicker{font-family:var(--hand); font-size:clamp(1rem,3vw,1.15rem); color:#6B5344; margin:0 0 .7em}
.ow-row{display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(6px,2vw,18px)}
.ow-env{
  display:flex; flex-direction:column; align-items:center; gap:.4em; width:100%; background:none; padding:.3em .1em; cursor:pointer;
  transition:scale .15s var(--ease);
}
.ow-env:active{scale:.96}
.ow-env:focus-visible{outline:2px solid var(--velvet); outline-offset:2px; border-radius:8px}
.ow-ico{
  position:relative; width:clamp(50px,14vw,68px); aspect-ratio:1.5/1; border-radius:5px;
  background:linear-gradient(170deg,#C72C3E,#8C1425); box-shadow:0 8px 18px rgba(123,17,32,.3);
}
.ow-ico::before{content:''; position:absolute; inset:0; border-radius:5px; background:linear-gradient(#5E0B1A,#6E0F20); clip-path:polygon(0 0,50% 58%,100% 0)}   /* the inside, under the flap */
.ow-flap{position:absolute; left:0; top:0; width:100%; height:60%; background:linear-gradient(#B4233A,#8E1526); clip-path:polygon(0 0,100% 0,50% 100%); transform-origin:50% 0; transition:transform .55s var(--ease), opacity .3s .2s}
.ow-seal{
  position:absolute; left:50%; top:54%; width:24%; aspect-ratio:1; translate:-50% -50%; border-radius:50%;
  background:radial-gradient(circle at 35% 30%, #FBE6A3, #D9A63A 52%, #9A6D15); box-shadow:0 2px 4px rgba(0,0,0,.3);
  transition:opacity .3s, scale .3s var(--ease);
}
.ow-env.open .ow-flap{transform:perspective(200px) rotateX(180deg); opacity:0}
.ow-env.open .ow-seal{opacity:0; scale:1.6}
.ow-env.locked .ow-ico{filter:saturate(.45) brightness(.92)}
.ow-env.locked .ow-seal{background:radial-gradient(circle at 35% 30%, #E6E6E9, #A2A2AA 52%, #6C6C74)}   /* a silver seal: not yet */
.ow-label{font-family:var(--hand); font-size:clamp(.88rem,2.7vw,1.05rem); line-height:1.15; color:#33261F; text-align:center}
.ow-env.locked .ow-label{color:#8A7A70}
.ow-env.nope{animation:owNope .4s}
@keyframes owNope{25%{translate:-5px 0}50%{translate:5px 0}75%{translate:-3px 0}}
.ow-note{font-family:var(--hand); font-size:clamp(1.15rem,3.4vw,1.45rem); line-height:1.8; color:#33261F; margin:.7em 0 0; white-space:pre-wrap}
.ow-note:empty{margin:0}
.ow-note.nope{color:#8A7A70}

/* ══ 7. UNIVERSE ═══════════════════════════════════════════════════ */
#act-universe{justify-content:flex-start}
#sky{position:absolute; inset:0; width:100%; height:100%; z-index:0}
#act-universe > *:not(#sky):not(.act-decor):not(.next){position:relative; z-index:2}
.phone{
  width:auto; height:min(calc(clamp(248px,76vw,310px) * 1.711), calc(100dvh - 250px)); aspect-ratio:9/15.4; border-radius:34px; position:relative;
  background:#0B0B0F; padding:8px; box-shadow:0 0 0 2px #26262E, 0 30px 70px rgba(0,0,0,.8),
    0 0 90px rgba(77,124,254,.18);
  display:flex; flex-direction:column; overflow:hidden;
}
.phone-notch{
  position:absolute; left:50%; top:8px; transform:translateX(-50%);
  width:86px; height:19px; background:#0B0B0F; border-radius:0 0 12px 12px; z-index:4;
}
.phone-bar{
  display:flex; align-items:center; gap:9px; padding:30px 10px 10px;
  border-bottom:1px solid rgba(255,255,255,.07); flex:none;
}
.phone-status{
  position:absolute; top:0; left:0; right:0; height:30px; z-index:3; pointer-events:none;
  display:flex; align-items:center; justify-content:space-between; padding:8px 20px 0;
  font-size:.7rem; font-weight:600; color:#fff; letter-spacing:.01em;
}
.ps-right{display:flex; align-items:center; gap:5px}
.ps-signal{
  width:15px; height:10px; background:repeating-linear-gradient(90deg,#fff 0 2.5px,transparent 2.5px 4.2px);
  clip-path:polygon(0 65%,26% 65%,26% 40%,52% 40%,52% 18%,78% 18%,78% 0,100% 0,100% 100%,0 100%);
}
.ps-batt{width:20px; height:10px; border-radius:3px; box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.55); position:relative}
.ps-batt::after{content:''; position:absolute; inset:2.5px 5px 2.5px 2.5px; border-radius:1.5px; background:#5EDB8A}
.back{color:#4D7CFE; font-size:1.4rem; line-height:1}
.pc-avatar{width:30px; height:30px; border-radius:50%; background:#2A2A33 center/cover no-repeat; flex:none}
.pc-meta{display:flex; flex-direction:column; line-height:1.25; min-width:0}
.pc-meta b{font-size:.84rem}
.pc-meta i{font-size:.66rem; font-style:normal; color:#5EDB8A}
.thread{
  flex:1; overflow-y:auto; padding:12px 10px; display:flex; flex-direction:column; gap:7px;
  scrollbar-width:none;
}
.thread > :first-child{margin-top:auto}  /* pins bubbles to the bottom without flex-end, so a long chat still scrolls */
.thread::-webkit-scrollbar{display:none}
.bub{
  max-width:78%; padding:.55em .8em; border-radius:17px; font-size:.86rem; line-height:1.4;
  animation:pop .3s var(--ease); word-break:break-word;
}
@keyframes pop{from{opacity:0; transform:translateY(8px) scale(.94)}}
.bub.her{align-self:flex-start; background:#26262E; border-bottom-left-radius:5px}
.bub.me{align-self:flex-end; background:#4D7CFE; color:#fff; border-bottom-right-radius:5px}
.bub.img{padding:3px; max-width:62%}
.bub.img img{border-radius:14px}
.bub.typing{display:flex; gap:4px; padding:.75em .85em}
.bub.typing i{width:6px; height:6px; border-radius:50%; background:rgba(255,255,255,.55); animation:dots 1.2s infinite}
.bub.typing i:nth-child(2){animation-delay:.18s} .bub.typing i:nth-child(3){animation-delay:.36s}
@keyframes dots{0%,60%,100%{opacity:.3; transform:translateY(0)}30%{opacity:1; transform:translateY(-3px)}}
.phone-input{
  flex:none; margin:6px; padding:.6em 1em; border-radius:999px; background:#17171D;
  font-size:.78rem; color:rgba(255,255,255,.3);
}
.replay{margin-top:4px}

/* ══ 8. STREAMING ══════════════════════════════════════════════════ */
.enter-stream{
  padding:1em 2.2em; border-radius:6px; background:var(--velvet-hi); color:#fff;
  font-weight:800; font-size:clamp(.98rem,3vw,1.14rem); letter-spacing:.01em;
  box-shadow:0 14px 44px rgba(165,24,44,.45); transition:transform .2s var(--ease), background .2s, scale .15s var(--ease);
}

#flix{
  position:fixed; inset:0; z-index:120; background:#0A0A0A; overflow-y:auto; overscroll-behavior:contain;
  transition:opacity .45s var(--ease), transform .55s var(--ease);
}
@starting-style{#flix{opacity:0; transform:scale(.985)}}   /* fades in when unhidden; exit stays instant */
.brand{
  font-family:var(--display); font-weight:900; font-style:italic; letter-spacing:-.02em;
  color:var(--velvet-hi); margin:0; font-size:clamp(1.7rem,6vw,2.8rem);
  text-shadow:0 0 30px rgba(165,24,44,.5);
}
.brand.sm{font-size:clamp(1.05rem,3.6vw,1.4rem)}

.flix-ident{position:absolute; inset:0; display:grid; place-items:center; background:#000; overflow:hidden; z-index:2}
.ident-stage{position:relative; width:1em; height:1.1em; font:italic 900 clamp(7rem,32vw,15rem)/1 var(--display); color:var(--velvet-hi)}
.ident-strip{
  position:absolute; inset:0; display:grid; place-items:center; letter-spacing:-.04em;
  clip-path:inset(0 calc((var(--n) - var(--i) - 1) / var(--n) * 100%) 0 calc(var(--i) / var(--n) * 100%));
  color:color-mix(in srgb, var(--velvet-hi) calc(100% - var(--i) * 7%), #E8B84B);
  filter:drop-shadow(0 0 22px rgba(201,56,74,.55));
  transform:scale(.92); opacity:0;
}
.ident-mark{position:absolute; left:50%; top:50%; transform:translate(-50%,-50%) scale(.9); opacity:0; margin:0; font-size:clamp(2.2rem,9vw,4.8rem)}
.flix-ident.go .ident-strip{animation:identStrip 2.3s cubic-bezier(.6,0,.2,1) forwards; animation-delay:calc(var(--i) * .06s)}
@keyframes identStrip{
  0%{transform:scale(.92); opacity:0}
  14%{transform:scale(1); opacity:1}
  46%{transform:scale(1); opacity:1}
  70%{transform:translateY(calc((var(--i) - 3) * -34%)) scaleY(1.7); opacity:.9}
  100%{transform:translateY(calc((var(--i) - 3) * -120%)) scaleY(2.6); opacity:0}
}
.flix-ident.go .ident-mark{animation:identMark 1.1s var(--ease) 1.45s forwards}
@keyframes identMark{to{transform:translate(-50%,-50%) scale(1); opacity:1}}
.flix-who{min-height:100dvh; display:grid; place-content:center; justify-items:center; gap:clamp(20px,5vh,40px); padding:6vw}
.who-prompt{font-size:clamp(1.3rem,5vw,2.2rem); font-weight:300; margin:0; color:#EDEDED}
.profiles{display:flex; gap:clamp(16px,5vw,40px); list-style:none; padding:0; margin:0; flex-wrap:wrap; justify-content:center}
.profiles button{display:grid; justify-items:center; gap:.7em; padding:0; transition:scale .15s var(--ease)}   /* UA button padding made three tiles wrap at 360px */
.pf-av{
  width:clamp(84px,22vw,132px); aspect-ratio:1; border-radius:6px; background:#1C1C22 center/cover no-repeat;
  box-shadow:inset 0 0 0 3px transparent; transition:box-shadow .2s, transform .2s var(--ease);
  display:grid; place-items:center; font-family:var(--display); font-weight:900;
  font-size:clamp(2rem,7vw,3.2rem); color:rgba(255,255,255,.18);
}
.pf-name{font-size:clamp(.82rem,2.8vw,1rem); color:#8E8E8E; transition:color .2s}

.flix-browse{min-height:100dvh; padding-bottom:70px}
.flix-top{
  position:sticky; top:0; z-index:12; display:flex; align-items:center; justify-content:space-between;
  padding:14px clamp(14px,4vw,44px) 26px; background:linear-gradient(#0A0A0A 0 58%, rgba(10,10,10,.7) 80%, transparent);   /* solid behind the wordmark and Leave, fading under them: tile art was showing through the words once scrolled */
}
.flix-exit{font-size:.84rem; font-weight:600; color:#B3B3B3; padding:.5em .9em; border-radius:4px; transition:color .2s, background .2s, scale .15s var(--ease)}
.flix-hero{
  position:relative; min-height:clamp(230px,44vh,380px); margin-top:-62px;
  display:flex; flex-direction:column; justify-content:flex-end; gap:.7em;
  padding:clamp(70px,12vh,120px) clamp(16px,4vw,44px) clamp(20px,4vh,40px);
  background:#141418 center/cover no-repeat;
}
.flix-hero::after{content:''; position:absolute; inset:0; background:linear-gradient(90deg, rgba(10,10,10,.92) 8%, rgba(10,10,10,.35) 60%, rgba(10,10,10,.9)), linear-gradient(transparent 40%, #0A0A0A)}
.flix-hero > *{position:relative; z-index:2}
.hero-title{font-family:var(--display); font-weight:900; font-style:italic; font-size:clamp(1.6rem,7vw,3.2rem); margin:0; line-height:1}
.hero-meta{display:flex; gap:.8em; font-size:.76rem; color:#9A9A9A; margin:0; align-items:center; flex-wrap:wrap}
.hero-meta span{padding:.12em .5em; box-shadow:inset 0 0 0 1px rgba(255,255,255,.22); border-radius:2px}
.hero-blurb{font-size:clamp(.86rem,2.6vw,.98rem); color:#D6D6D6; max-width:46ch; line-height:1.55; margin:0}
.hero-play{
  align-self:flex-start; margin-top:.4em; padding:.65em 1.6em; border-radius:4px;
  background:#fff; color:#111; font-weight:700; font-size:.94rem; transition:background .2s, scale .15s var(--ease);
}

.flix-rows{display:flex; flex-direction:column; gap:clamp(22px,4vh,40px); padding:0 0 clamp(20px,4vh,40px)}
.row h3{font-size:clamp(.94rem,3vw,1.16rem); font-weight:700; margin:0 0 .7em; padding:0 clamp(16px,4vw,44px); color:#E5E5E5}
.rail{
  display:flex; gap:clamp(7px,1.6vw,12px); overflow-x:auto; padding:0 clamp(16px,4vw,44px) 6px;
  scroll-snap-type:x mandatory; scroll-padding-inline:clamp(16px,4vw,44px); scrollbar-width:none;   /* the snap position keeps the padding, so the first tile lines up with the row heading instead of the screen edge */
}
.rail::-webkit-scrollbar{display:none}
.tile{
  flex:none; width:clamp(116px,31vw,190px); aspect-ratio:2/3; border-radius:4px;
  background:#1A1A20 center/cover no-repeat; scroll-snap-align:start; position:relative;
  overflow:hidden; transition:transform .3s var(--ease), box-shadow .3s, scale .15s var(--ease);
}
.tile.has-photo .tile-fallback{display:none}
.pf-av.has-photo{color:transparent}
.tile-fallback{
  position:absolute; inset:0; z-index:0; display:grid; place-content:center; text-align:center; padding:1em;
  font-family:var(--display); font-style:italic; font-weight:700; font-size:.92rem;
  color:rgba(255,255,255,.72); background:linear-gradient(160deg,#2A1016,#121216);
}
.tile-name{
  position:absolute; z-index:1; left:0; right:0; bottom:0; padding:1.6em .6em .5em;
  background:linear-gradient(transparent, rgba(0,0,0,.92)); font-size:.72rem; font-weight:600;
  line-height:1.25;
}

.flix-player{position:fixed; inset:0; z-index:130; background:#000; display:grid; place-items:center; transition:opacity .35s var(--ease)}
@starting-style{.flix-player{opacity:0}}
#flixVideo{width:100%; height:100%; object-fit:contain; background:#000}
.player-exit{position:absolute; top:max(14px,env(safe-area-inset-top)); left:14px; z-index:5; background:rgba(0,0,0,.5)}
.player-title{
  position:absolute; top:max(16px,env(safe-area-inset-top)); left:0; right:0; text-align:center;
  font-family:var(--display); font-style:italic; font-weight:700; font-size:clamp(.94rem,3vw,1.2rem);
  pointer-events:none; text-shadow:0 2px 10px rgba(0,0,0,.9);
}
.credits{position:absolute; inset:0; background:#000; overflow:hidden; display:grid; place-items:center}
.credits-roll{
  text-align:center; padding:0 6vw; animation:roll 34s linear forwards;
  position:absolute; top:100%; width:100%;
}
@keyframes roll{to{top:-140%}}
.cr-title{
  font-family:var(--display); font-weight:900; font-style:italic;
  font-size:clamp(1.6rem,7vw,3rem); margin:0 0 2em; color:var(--gilt);
}
.cr-line{margin:0 0 1.6em}
.cr-role{font-size:.68rem; letter-spacing:.22em; color:#7A7A7A; margin:0 0 .35em; text-transform:lowercase}
.cr-name{font-family:var(--display); font-size:clamp(1.05rem,4vw,1.5rem); margin:0; color:#EDEDED}
.cr-close{font-family:var(--hand); font-size:clamp(1.2rem,4vw,1.7rem); color:var(--gilt); margin-top:3em; line-height:1.5}

/* ══ 9. FINALE ═════════════════════════════════════════════════════ */
/* the last act has no chevron under it, so less bottom padding; the stack
   (headline, sub, clock, coupon, mascots, restart) must fit a 1366x640 laptop,
   so the tall pieces also scale with the height (see the coupon and #finCuties) */
.act-fin{background:radial-gradient(110% 80% at 50% 100%, #2A1016 0%, var(--night) 60%); text-align:center; gap:clamp(10px,2vh,30px); padding-bottom:clamp(24px,4vh,60px); cursor:crosshair}
.act-fin h2{font-family:var(--display); font-style:italic; font-weight:900; font-size:clamp(2rem,min(8vw,9dvh),4rem); margin:0}
#finCuties .critter{width:min(clamp(72px,18vw,128px),10dvh)}
.act-fin .fin-sub{font-family:var(--hand); font-size:clamp(1.2rem,4vw,1.8rem); color:var(--gilt); margin:.2em 0 0}
.fin-next{font:600 .66rem var(--ui); letter-spacing:.18em; text-transform:uppercase; color:rgba(246,237,221,.5); margin:-.4em 0 0}
.fin-next b{font-family:var(--display); font-weight:600; font-size:.95rem; letter-spacing:.02em; color:var(--gilt); font-variant-numeric:tabular-nums}
.sky-hint{
  position:absolute; top:clamp(14px,2.6vh,26px); left:0; right:0; margin:0; text-align:center;
  font-family:var(--hand); font-size:clamp(.95rem,2.8vw,1.15rem); color:rgba(246,237,221,.42); pointer-events:none;
  opacity:0; transition:opacity 1s var(--ease) 2.4s;
}
.act-fin.in .sky-hint{opacity:1}
.act-fin.lit .sky-hint{opacity:0; transition-delay:0s}   /* she's found it */

/* the scratch card: a printed coupon under a foil she rubs off */
.scratch{display:flex; flex-direction:column; align-items:center; gap:.5em; cursor:auto}
.scratch-kicker{font-family:var(--hand); font-size:clamp(1rem,3vw,1.2rem); color:rgba(246,237,221,.6); margin:0}
.coupon{
  position:relative; width:min(86vw,420px,48dvh); aspect-ratio:2.2/1; border-radius:14px; overflow:hidden; isolation:isolate;
  background:var(--paper); color:#33261F; box-shadow:0 24px 60px rgba(0,0,0,.6), 0 0 0 1px rgba(232,184,75,.35);
  outline:none; transition:scale .15s var(--ease);
}
.coupon:focus-visible{box-shadow:0 24px 60px rgba(0,0,0,.6), 0 0 0 3px var(--gilt)}
.coupon::before{ /* punched ticket edge */
  content:''; position:absolute; inset:0; pointer-events:none; z-index:1;
  background:
    radial-gradient(circle at 0 50%, var(--night) 9px, transparent 10px),
    radial-gradient(circle at 100% 50%, var(--night) 9px, transparent 10px);
}
.coupon-inner{
  position:absolute; inset:0; display:grid; place-content:center; text-align:center; padding:6% 9%;
  background:
    repeating-linear-gradient(90deg, transparent 0 6px, rgba(123,17,32,.05) 6px 7px),
    linear-gradient(#FBF4E6, var(--paper));
}
.coupon-inner::after{ /* a gilt rule around the print */
  content:''; position:absolute; inset:9px; border:1px solid rgba(160,110,76,.45); border-radius:9px; pointer-events:none;
}
.coupon-title{font-family:var(--ui); font-size:clamp(.6rem,1.8vw,.7rem); letter-spacing:.24em; text-transform:uppercase; color:var(--cocoa); margin:0 0 .5em}
.coupon-prize{font-family:var(--display); font-style:italic; font-weight:700; font-size:clamp(1.2rem,4.4vw,1.75rem); line-height:1.1; margin:0; color:var(--velvet); text-wrap:balance}
.coupon-sub{font-family:var(--hand); font-size:clamp(.9rem,2.7vw,1.05rem); line-height:1.3; margin:.45em 0 0; color:#6B5344}
.coupon-stamp{
  position:absolute; right:14px; bottom:12px; padding:.18em .5em; border:2px solid var(--velvet); border-radius:4px; color:var(--velvet);
  font-family:var(--ui); font-weight:800; font-size:clamp(.6rem,1.9vw,.72rem); letter-spacing:.16em; text-transform:uppercase;
  rotate:-12deg; opacity:0; scale:1.9; mix-blend-mode:multiply;
}
.coupon.done .coupon-stamp{opacity:.8; scale:1; transition:opacity .25s .35s, scale .35s cubic-bezier(.2,1.5,.4,1) .35s}
.foil{position:absolute; inset:0; width:100%; height:100%; z-index:2; touch-action:none; cursor:grab; transition:opacity .6s var(--ease)}
.foil:active{cursor:grabbing}
.coupon.done .foil{opacity:0; pointer-events:none}
.coupon.done{animation:couponPop .5s cubic-bezier(.2,1.4,.4,1)}
@keyframes couponPop{40%{scale:1.05}}

/* the fan of posters on the way in */
.stream-tease{position:relative; width:min(90vw,560px); height:clamp(160px,36vw,240px); margin:0 auto}
.tease-card{
  position:absolute; top:50%; left:50%; width:clamp(72px,21vw,138px); aspect-ratio:2/3; border-radius:6px; overflow:hidden;   /* the fan spans four card widths: 92px cards ran off both edges of a 360px phone */
  background:#1A1A20 center/cover no-repeat; box-shadow:0 22px 50px rgba(0,0,0,.65); cursor:pointer;
  transform:translate(-50%,-50%) translateX(var(--x)) rotate(var(--r));
  animation:teaseFloat 4.2s ease-in-out infinite; animation-delay:var(--d);
}
.tease-card:nth-child(1){--x:-150%; --r:-14deg; --d:0s;   z-index:1}
.tease-card:nth-child(2){--x:-76%;  --r:-7deg;  --d:-.9s; z-index:2}
.tease-card:nth-child(3){--x:0;     --r:0deg;   --d:-1.8s; z-index:3}
.tease-card:nth-child(4){--x:76%;   --r:7deg;   --d:-2.7s; z-index:2}
.tease-card:nth-child(5){--x:150%;  --r:14deg;  --d:-3.6s; z-index:1}
@keyframes teaseFloat{0%,100%{translate:0 0}50%{translate:0 -7px}}
.tease-name{
  position:absolute; inset:0; display:grid; place-content:center; text-align:center; padding:.6em;
  font-family:var(--display); font-style:italic; font-weight:700; font-size:clamp(.72rem,2vw,.9rem);
  color:rgba(255,255,255,.72); background:linear-gradient(160deg,#2A1016,#121216);
}
.tease-card.has-photo .tease-name{display:none}

/* hover only where there is a real pointer; touch would keep a sticky :hover */
@media (hover:hover) and (pointer:fine){
  .begin:hover{transform:translateY(-2px)}
  .claim:hover{background:#921427}
  .heart:hover{scale:1.06}
  .ghost-btn:hover{box-shadow:inset 0 0 0 1px var(--gilt); color:var(--gilt); transform:translateY(-1px)}
  .pol:hover{translate:0 -8px}
  .enter-stream:hover{transform:translateY(-2px); background:#C01D34}
  .profiles button:hover .pf-av{transform:scale(1.05)}
  .profiles button:hover .pf-name{color:#fff}
  .flix-exit:hover{color:#fff; background:rgba(255,255,255,.08)}
  .hero-play:hover{background:#D6D6D6}
  .tile:hover{transform:scale(1.06); box-shadow:0 14px 34px rgba(0,0,0,.7); z-index:2}
  .sp-tile:hover{z-index:40; box-shadow:0 20px 42px rgba(74,54,44,.38)}
  .tease-card:hover{animation-play-state:paused}
}
/* everything pressable presses */
.begin:active, .ghost-btn:active, .enter-stream:active, .hero-play:active, .flix-exit:active,
.profiles button:active, .tile:active, .pol:active, .sp-tile:active, .candle:active, .tease-card:active, .claim:active, .heart:active{scale:.96}

/* ══ THE SCRAPBOOK (ported from the prototype; API in app.js mountBook) ═══ */
/* ============================================================
   BOOK ACT — everything below is prefixed .book and ports as-is
   into styles.css. Vars are redeclared on .book-act so the block
   is self-sufficient; the site's :root vars win if they exist.
   ============================================================ */
.book-act{
  --cream:#FFF6E9;--paper:#F6EDDD;--blush:#F5C6CE;--rose:#E0768C;--butter:#FFD98C;
  --cocoa:#A06E4C;--ink:#4A362C;--velvet:#7B1120;--gilt:#E8B84B;--night:#07060A;
  --board:#1B1512;
  --ease:cubic-bezier(.22,1,.36,1);
  --flip:cubic-bezier(.6,0,.2,1);
  --flip-t:900ms;
  --shade:rgba(74,54,44,.25);
  /* one page: 78vw, max 340, aspect 3/4, and it must fit 100dvh with chrome above/below */
  --bw:min(78vw,340px,calc((100dvh - 260px) * 3 / 4));
  --bh:calc(var(--bw) * 4 / 3);
  --spine:26px;
  position:relative;min-height:100dvh;overflow:clip;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:max(20px,env(safe-area-inset-top)) 16px max(18px,env(safe-area-inset-bottom));
  box-sizing:border-box;
  background:
    radial-gradient(90% 70% at 18% 8%,#FFE9D6 0%,transparent 60%),
    radial-gradient(80% 70% at 92% 96%,#FDE2E6 0%,transparent 62%),
    var(--cream);
  color:var(--ink);
  font-family:system-ui,-apple-system,"Segoe UI",sans-serif;
  -webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;
}
.book-head{text-align:center;margin:0 0 22px}
.book-head h2{
  margin:0;font-family:"Bodoni Moda",serif;font-style:italic;font-weight:400;
  font-size:clamp(1.7rem,6vw,2.6rem);letter-spacing:.01em;line-height:1.1;color:var(--ink);
}
.book-head p{margin:4px 0 0;font-family:Caveat,cursive;font-size:1.15rem;color:var(--cocoa);opacity:.9}

/* ---- scene: the perspective box; also the hit area for taps/swipes ---- */
.book-scene{
  position:relative;width:var(--bw);height:var(--bh);
  touch-action:pan-y;cursor:pointer;outline:none;
}
.book-scene:focus-visible{outline:2px solid var(--rose);outline-offset:14px;border-radius:8px}
.book{
  position:absolute;inset:0;width:100%;height:100%;
  /* perspective only reaches direct children, so it lives here, not on the scene */
  perspective:1700px;perspective-origin:50% 50%;
  transition:translate var(--flip-t) var(--flip);
}
/* phone: anything that swings past the spine is clipped, so a turning page folds
   into the rings instead of poking out of the viewport (rings sit at -spine/2) */
.book-scene{clip-path:inset(-80px -80px -80px calc(var(--spine) / -2))}
/* stacked board edges under the pile (phone: whole book; desktop: right half) */
.book::before,.book::after{
  content:"";position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;
  background:var(--paper);border:1px solid rgba(74,54,44,.18);border-radius:3px 6px 6px 3px;
  translate:3px 3px;
}
.book::after{translate:6px 6px;background:#EFE4D2}

/* ---- a sheet: two faces, flips about the spine ---- */
.book-sheet{
  position:absolute;top:0;left:0;width:100%;height:100%;
  transform-origin:left center;transform-style:preserve-3d;
  transform:rotateY(0deg);
  transition:transform var(--flip-t) var(--flip),visibility 0s 0s;
  will-change:transform;
}
/* never put opacity on a sheet: Chromium flattens the 3D context for it and the
   front face renders mirrored (backface-visibility breaks) */
.book-sheet.turned{transform:rotateY(-180deg);visibility:hidden;transition:transform var(--flip-t) var(--flip),visibility 0s var(--flip-t)}
.book-sheet.flying{z-index:400 !important}
.book-face{
  position:absolute;inset:0;overflow:hidden;
  -webkit-backface-visibility:hidden;backface-visibility:hidden;
  border-radius:3px 6px 6px 3px;
  box-shadow:0 18px 40px -16px rgba(74,54,44,.45),0 2px 6px rgba(74,54,44,.12);
  /* grid paper */
  background:
    repeating-linear-gradient(0deg,rgba(160,110,76,.085) 0 1px,transparent 1px 22px),
    repeating-linear-gradient(90deg,rgba(160,110,76,.085) 0 1px,transparent 1px 22px),
    #FCF7EE;
}
.book-back{transform:rotateY(180deg);border-radius:6px 3px 3px 6px}
/* punched holes along the spine edge, 22px pitch to match the rings */
.book-face::before{
  content:"";position:absolute;top:0;bottom:0;left:6px;width:14px;z-index:3;pointer-events:none;
  background:radial-gradient(circle at 50% 50%,rgba(60,42,34,.55) 0 3px,rgba(60,42,34,.15) 3.5px,transparent 4.5px) 0 5px/14px 22px repeat-y;
}
.book-back::before{left:auto;right:6px}
/* dark boards (cover + back cover) */
.book-face.book-board{
  background:
    radial-gradient(70% 55% at 28% 18%,rgba(255,255,255,.07),transparent 70%),
    radial-gradient(60% 50% at 80% 90%,rgba(123,17,32,.28),transparent 70%),
    repeating-linear-gradient(35deg,rgba(255,255,255,.018) 0 2px,transparent 2px 6px),
    repeating-linear-gradient(-55deg,rgba(0,0,0,.12) 0 1px,transparent 1px 7px),
    var(--board);
  box-shadow:0 22px 44px -14px rgba(40,24,18,.6),0 2px 8px rgba(40,24,18,.25);
}
.book-board::before{background-image:radial-gradient(circle at 50% 50%,rgba(0,0,0,.75) 0 3px,rgba(255,255,255,.12) 3.5px,transparent 4.5px)}

/* ---- the spiral rings: one fixed strip at the spine, above every sheet ---- */
.book-rings{
  position:absolute;top:0;bottom:0;left:calc(var(--spine) / -2);width:var(--spine);z-index:500;pointer-events:none;
  background:
    repeating-linear-gradient(180deg,transparent 0 7px,#15100e 7px 8px,#4a403b 8px 9px,#9a8f88 9px 10px,#3b322e 10px 12px,#15100e 12px 13px,rgba(20,14,12,.35) 13px 14px,transparent 14px 22px);
  -webkit-mask:linear-gradient(90deg,rgba(0,0,0,.55),#000 18%,#000 82%,rgba(0,0,0,.55));
  mask:linear-gradient(90deg,rgba(0,0,0,.55),#000 18%,#000 82%,rgba(0,0,0,.55));
}

/* ---- inside content: pages ---- */
.book-page{position:absolute;inset:0 0 0 var(--spine);font-family:Caveat,cursive;color:var(--ink)}
.book-back .book-page{inset:0 var(--spine) 0 0}
.book-photo{
  position:absolute;left:8%;top:6%;width:64%;
  background:#FFFDF9;padding:10px 10px 0;box-sizing:border-box;
  box-shadow:0 10px 24px -8px var(--shade),0 1px 3px rgba(74,54,44,.15);
  rotate:var(--tilt,-3deg);
}
.book-img{
  aspect-ratio:5/6;width:100%;background:#F3E9DA center/cover no-repeat;
  display:grid;place-items:center;
}
.book-img.missing::after{
  content:"photo missing";font:500 .72rem/1 system-ui,sans-serif;letter-spacing:.06em;text-transform:lowercase;
  color:rgba(74,54,44,.45);
}
.book-cap{
  min-height:38px;box-sizing:border-box;padding:7px 2px 6px;
  font-size:clamp(.95rem,3.6vw,1.2rem);line-height:1.05;color:var(--ink);text-align:center;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;
}
.book-tape{
  position:absolute;left:50%;top:-9px;width:64px;height:18px;translate:-50% 0;rotate:-5deg;
  background:var(--butter);opacity:.72;
  box-shadow:0 1px 2px rgba(74,54,44,.15);
  -webkit-mask:repeating-linear-gradient(90deg,#000 0 3px,rgba(0,0,0,.85) 3px 5px);
  mask:repeating-linear-gradient(90deg,#000 0 3px,rgba(0,0,0,.85) 3px 5px);
}
.book-note{
  position:absolute;left:6%;right:8%;bottom:6%;
  background:var(--cream);color:var(--ink);
  padding:10px 14px 12px;font-size:clamp(1.05rem,4.2vw,1.4rem);line-height:1.15;
  box-shadow:0 8px 18px -8px var(--shade);
  rotate:var(--tilt,2deg);
  clip-path:polygon(0 4%,3% 0,8% 3%,15% 0,22% 4%,31% 1%,40% 3%,49% 0,58% 3%,67% 1%,76% 4%,85% 0,93% 3%,100% 1%,100% 96%,96% 100%,88% 97%,80% 100%,71% 96%,62% 100%,53% 97%,44% 100%,35% 96%,26% 100%,17% 97%,8% 100%,0 96%);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.book-sticker{
  position:absolute;width:26%;height:auto;pointer-events:none;z-index:4;
  rotate:var(--r,0deg);filter:drop-shadow(0 4px 6px rgba(74,54,44,.28));
}
.book-sticker.s0{right:3%;top:4%}
.book-sticker.s1{left:2%;bottom:24%}
.book-sticker.s2{right:1%;top:46%}

/* ---- cover ---- */
.book-cover{position:absolute;inset:0 0 0 var(--spine)}
.book-cover.has-art,.book-fin.has-art{background-size:cover;background-position:center;background-repeat:no-repeat}
.book-cover.has-art .book-washi,.book-cover.has-art .book-scrap,.book-cover.has-art .book-heart,
.book-fin.has-art .book-washi,.book-fin.has-art .book-heart{display:none}
.book-cover.has-art .book-label{top:auto;bottom:9%;left:6%;right:auto;width:auto;padding:.1em .5em;font-size:clamp(1.6rem,7vw,2.4rem)}
.book-fin.has-art > div{background:rgba(27,21,18,.72);padding:14px 18px;border-radius:10px;backdrop-filter:blur(2px)}
.book-corner{position:absolute;width:48%;height:auto;z-index:0;pointer-events:none;opacity:.95}
.book-corner.tl{left:-4%;top:-3%;rotate:-2deg}
.book-corner.br{right:-4%;bottom:-3%;rotate:2deg}
.book-photo,.book-note{z-index:1}
.book-scrap{
  position:absolute;right:5%;top:4%;width:44%;padding:8px 9px;box-sizing:border-box;
  background:#EFE3CC;color:#5a4a3e;font-family:"Bodoni Moda",serif;font-size:.5rem;line-height:1.35;
  clip-path:polygon(2% 0,98% 3%,100% 96%,95% 100%,3% 97%,0 90%);
  rotate:4deg;opacity:.92;
}
.book-scrap b{display:block;font-size:.62rem;margin-bottom:2px}
.book-label{
  position:absolute;left:5%;top:30%;width:74%;padding:8px 14px 10px;box-sizing:border-box;
  background:var(--paper);color:var(--ink);
  font-family:"Bodoni Moda",serif;font-style:italic;font-weight:900;
  font-size:clamp(1.7rem,9vw,2.7rem);line-height:1;letter-spacing:-.01em;
  clip-path:polygon(0 8%,4% 0,12% 5%,24% 0,36% 6%,50% 1%,64% 5%,78% 0,90% 6%,100% 2%,100% 94%,94% 100%,82% 95%,68% 100%,54% 96%,40% 100%,26% 95%,12% 100%,3% 96%,0 88%);
  rotate:-3deg;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  box-shadow:0 10px 22px -8px rgba(0,0,0,.6);
}
.book-cover .book-photo{left:auto;right:6%;top:auto;bottom:7%;width:50%;--tilt:6deg}
.book-cover .book-photo .book-img{aspect-ratio:1}
.book-cover .book-tape{left:12px;top:-6px;translate:0;rotate:-28deg;width:54px}
.book-cover .book-sticker.s0{right:auto;left:3%;bottom:6%;top:auto;width:30%}
.book-cover .book-sticker.s1{left:auto;right:4%;top:40%;bottom:auto}
.book-cover .book-sticker.s2{left:40%;top:6%;right:auto}
.book-heart{position:absolute;left:8%;top:62%;width:11%;rotate:-14deg;filter:drop-shadow(0 2px 3px rgba(0,0,0,.5))}
.book-washi{
  position:absolute;left:-6%;top:8%;width:60%;height:16px;rotate:-24deg;
  background:var(--blush);opacity:.75;
  -webkit-mask:repeating-linear-gradient(90deg,#000 0 6px,rgba(0,0,0,.8) 6px 9px);
  mask:repeating-linear-gradient(90deg,#000 0 6px,rgba(0,0,0,.8) 6px 9px);
}

/* ---- inside front cover ---- */
.book-inside{position:absolute;inset:0 var(--spine) 0 0;display:grid;place-items:center;font-family:Caveat,cursive}
.book-inside p{margin:0;font-size:1.5rem;color:var(--cocoa);rotate:-4deg;text-align:center;line-height:1.1}
.book-inside p small{display:block;font-size:.95rem;opacity:.8}

/* ---- back cover ---- */
.book-fin{position:absolute;inset:0 0 0 var(--spine);display:grid;place-items:center;text-align:center;color:var(--cream)}
.book-fin p{margin:0;font-family:Caveat,cursive;font-size:clamp(1.6rem,7vw,2.3rem);line-height:1.1;color:var(--cream)}
.book-fin small{display:block;margin-top:14px;font:500 .7rem/1 system-ui,sans-serif;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,246,233,.55)}
.book-fin .book-washi{left:auto;right:-8%;top:auto;bottom:12%;rotate:18deg;background:var(--butter)}
.book-fin .book-heart{left:auto;right:10%;top:10%;width:12%;rotate:12deg}

/* ---- dots ---- */
.book-dots{display:flex;gap:7px;align-items:center;justify-content:center;margin:22px 0 0;min-height:10px}
.book-dot{width:7px;height:7px;border-radius:99px;background:rgba(160,110,76,.32);transition:width .35s var(--ease),background .35s var(--ease)}
.book-dot.on{width:20px;background:var(--rose)}

/* ---- press feedback (scale, never transform) ---- */
.book-scene:active .book-sheet:not(.turned):not(.flying){scale:.995}

/* ---- desktop: open two-page spread, spine in the middle ---- */
@media (min-width:860px){
  .book-act{--bw:min(400px,40vw,calc((100dvh - 250px) * 3 / 4));--spine:30px}
  .book-head h2{font-size:2.8rem}
  .book-scene{width:calc(var(--bw) * 2)}
  .book{translate:calc(var(--bw) / -2) 0}
  .book-act.is-open .book{translate:0 0}
  .book::before,.book::after{left:50%;width:50%}
  .book-sheet{left:50%;width:50%}
  .book-scene{clip-path:none}
  .book-sheet.turned{visibility:visible}
  .book-rings{left:calc(50% - var(--spine) / 2)}
  .book-note{font-size:1.4rem}
  .book-cap{font-size:1.2rem}
  .book-label{font-size:2.9rem}
  .book-img.missing::after{font-size:.8rem}
}
@media (hover:hover) and (pointer:fine){
  .book-scene:hover .book-dot{background:rgba(160,110,76,.45)}
  .book-scene:hover .book-dot.on{background:var(--rose)}
}
@media (prefers-reduced-motion:reduce){
  .book-act{--flip-t:0ms}
  .book,.book-sheet,.book-sheet.turned{transition:none}
  .book-sheet.flying,.book-sheet.riffle{animation:bookBlink .32s linear both}
  @keyframes bookBlink{0%{opacity:1}45%{opacity:0}55%{opacity:0}100%{opacity:1}}
  .book-dot{transition:none}
}
/* ============================================================ end BOOK ACT */
/* the mount lives inside #act-book, which already provides the screen, padding, background and header */
.book-act{min-height:0; padding:0; background:none; overflow:visible; --bw:min(78vw,340px,calc((100dvh - 300px) * 3 / 4))}
.book-act .book-head{display:none}
@media (min-width:860px){ .book-act{--bw:min(38vw,340px,calc((100dvh - 300px) * 3 / 4))} }

/* ══ RESPONSIVE + A11Y ═════════════════════════════════════════════ */
@media (max-width:640px){
  .clock{gap:6px}
  .polaroid-wall{--gap:10px; --rows:3; --zoom:1.8; --polw:min(calc((100vw - 60px) / 3), calc((100dvh - 300px) / 3 / 1.22)); max-width:none}   /* eight photos: 3 + 3 + 2 */
  .pol:nth-child(4n+1),.pol:nth-child(4n){--shift:0}
  .pol:nth-child(3n+1){--shift:calc(var(--polw) * .4)} .pol:nth-child(3n){--shift:calc(var(--polw) * -.4)}
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.15s !important}
  .credits-roll{animation-duration:34s !important}
  #flash.strobe{animation:none}
}

/* missing-asset placeholders — so a wrong path is obvious, not invisible */
.pol-img.empty::after{
  content:'photo missing'; display:grid; place-items:center; height:100%;
  font-family:var(--ui); font-size:.62rem; letter-spacing:.14em;
  color:rgba(246,237,221,.3); text-align:center; padding:1em;
}

/* ══════════════════════════════════════════════════════════════════
   THE SOFT SIDE — cream, blush, butter. Runs against the velvet
   so the show has more than one mood.
   ══════════════════════════════════════════════════════════════════ */
:root{
  --cream:#FFF6E9;  --blush:#F5C6CE;  --rose:#E0768C;
  --butter:#FFD98C; --sage:#A8C5A2;   --cocoa:#A06E4C;
  --soft-ink:#4A362C;
}

.act-cream{
  background:
    radial-gradient(90% 70% at 18% 8%, #FFE9D6 0%, transparent 60%),
    radial-gradient(80% 70% at 92% 96%, #FDE2E6 0%, transparent 62%),
    var(--cream);
  color:var(--soft-ink);
}
.act-cream .act-head h2{color:var(--soft-ink)}
.act-cream .act-head p{color:var(--rose); opacity:1}

/* ── THE SPIRAL ────────────────────────────────────────────────── */
#act-spiral{padding-inline:clamp(16px,4vw,70px)}
.spiral-grid{
  width:100%; max-width:1180px; display:grid; gap:clamp(18px,3vw,50px);
  grid-template-columns:1fr; align-items:center;
}
@media (min-width:900px){ .spiral-grid{grid-template-columns:minmax(300px,.85fr) 1.15fr} }

.spiral-copy{text-align:center}
@media (min-width:900px){ .spiral-copy{text-align:left} }
.sp-kicker{
  font-family:var(--hand); font-size:clamp(1.05rem,3vw,1.4rem);
  color:var(--cocoa); margin:0 0 .3em;
}
.sp-title{
  font-family:var(--display); font-weight:900; font-size:clamp(2.6rem,10vw,4.6rem);
  line-height:.92; margin:0; letter-spacing:-.025em; color:var(--soft-ink);
}
.sp-title em{
  font-style:italic; color:var(--rose); position:relative; display:inline-block;
  padding:0 .06em; isolation:isolate;   /* keeps the z-index:-1 swipe inside the word, not behind the act */
}
.sp-title em::after{ /* highlighter swipe, drawn not decorative */
  content:''; position:absolute; left:-.04em; right:-.04em; bottom:.1em; height:.34em;
  background:var(--butter); z-index:-1; border-radius:3px; transform:rotate(-1.2deg);
}
.sp-note{
  font-family:var(--hand); font-size:clamp(1.1rem,3vw,1.4rem); line-height:1.5;
  color:var(--cocoa); margin:1.1em 0 0; max-width:30ch;
}
@media (max-width:899px){ .sp-note{margin-inline:auto} .sp-title{font-size:clamp(2.4rem,8vw,4rem)} }

.spiral-stage{
  position:relative; width:100%; aspect-ratio:1/1;
  max-width:min(92vw,620px,calc(100dvh - 160px)); margin:0 auto;   /* the height term: on a 640px laptop a 620px ring ran under the chevron */
  animation:spSpin 50s linear infinite;   /* the ring turns; a held photo pauses it */
}
/* stacked layout must still fit one screen (phone and iPad portrait). These
   come after the base rule: same specificity, so before it they lost and the
   ring was 620px on an iPad, its lowest tiles under the chevron */
@media (max-width:899px){ .spiral-stage{max-width:min(92vw, calc(100dvh - 440px))} }
@media (min-width:640px) and (max-width:899px){ .spiral-stage{max-width:min(92vw, calc(100dvh - 560px))} }   /* tablet portrait: bigger type, same screen */
.spiral-stage.hold{animation-play-state:paused}
@keyframes spSpin{to{rotate:360deg}}
.sp-tile{
  position:absolute; width:16%; aspect-ratio:1/1.14; padding:0; border-radius:2px;
  background:#fff; box-shadow:0 6px 16px rgba(74,54,44,.2);
  transition:transform .5s var(--ease), box-shadow .4s, z-index 0s, scale .15s var(--ease);
  cursor:pointer; overflow:hidden; z-index:1;
}
.sp-tile i{
  display:block; position:absolute; inset:5% 5% 14%; background:#EDE2D2 center/cover no-repeat;
}
.sp-tile.pop{
  z-index:40; box-shadow:0 20px 42px rgba(74,54,44,.38);
}
.sp-readout{
  font-family:var(--hand); font-size:clamp(1.1rem,3vw,1.5rem); line-height:1.4;
  color:var(--rose); margin:.9em 0 0; min-height:1.4em; max-width:28ch;
  opacity:0; transform:translateY(6px); transition:opacity .35s, transform .35s var(--ease);
}
.sp-readout.show{opacity:1; transform:none}
@media (max-width:899px){ .sp-readout{margin-inline:auto} }

/* ── THE SCRAPBOOK ─────────────────────────────────────────────── */
#act-book{gap:clamp(12px,2.4vh,26px)}
.book-mount{width:100%; display:grid; place-items:center}

/* ── INTERMISSION ──────────────────────────────────────────────── */
#act-cat{gap:clamp(14px,2.5vh,28px)}
.act-head.dark h2{color:var(--soft-ink)}
.cat-floor{
  position:relative; display:flex; align-items:flex-end; justify-content:center; gap:clamp(4px,2vw,26px);
  min-height:clamp(150px,26vh,230px); width:100%; max-width:640px;
}
.cat-floor video{width:min(90vw,420px); border-radius:14px; box-shadow:0 16px 40px rgba(74,54,44,.3)}
.cat-line{
  font-family:var(--hand); font-size:clamp(1.25rem,4.4vw,2rem); color:var(--soft-ink);
  margin:0; text-align:center; max-width:32ch;
}
.cat-tap{
  font-family:var(--ui); font-size:.76rem; letter-spacing:.14em;
  color:rgba(74,54,44,.45); margin:0;
}

/* the cat itself — upright, paws up, swaying like the clip */
.catmeme{width:clamp(170px,44vw,240px); height:auto; overflow:visible; cursor:pointer;
  filter:drop-shadow(0 10px 16px rgba(74,54,44,.22))}
.catmeme .cat-all{transform-origin:70px 160px; animation:scuba .5s infinite var(--ease)}
@keyframes scuba{0%,100%{transform:rotate(-8deg) translateY(0)}50%{transform:rotate(8deg) translateY(-6px)}}
.catmeme .head{transform-origin:70px 88px; animation:scubaHead .5s infinite var(--ease)}
@keyframes scubaHead{0%,100%{transform:rotate(-5deg)}50%{transform:rotate(5deg)}}
.catmeme .paw-l{animation:pawPump .5s infinite var(--ease)}
.catmeme .paw-r{animation:pawPump .5s infinite var(--ease) .25s}
@keyframes pawPump{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
.catmeme .tail{transform-origin:96px 140px; animation:tailWag .5s infinite var(--ease)}
@keyframes tailWag{0%,100%{transform:rotate(-12deg)}50%{transform:rotate(16deg)}}
.catmeme.hype .cat-all, .catmeme.hype .head, .catmeme.hype .paw-l, .catmeme.hype .paw-r, .catmeme.hype .tail{animation-duration:.22s}

/* the real clip: hidden source video + keyed canvas */
.cat-floor .cat-src{position:absolute; width:2px; height:2px; opacity:0; pointer-events:none}
.cat-floor .cat-key{flex:none; width:min(92vw, 520px, calc((100dvh - 350px) * 1.17)); height:auto; cursor:pointer;
  filter:drop-shadow(0 10px 16px rgba(74,54,44,.22))}

/* ── THE TWO LITTLE ONES ───────────────────────────────────────── */
.cuties{display:flex; align-items:flex-end; gap:clamp(2px,1.6vw,18px); pointer-events:none}
.cuties.has-tag{flex-direction:column; align-items:center}
.cutie-pair{display:flex; align-items:flex-end; gap:inherit}
.cuties img{width:clamp(66px,17vw,120px); height:auto}
.critter{width:clamp(72px,18vw,128px); height:auto; overflow:visible}

/* resting pose + breathing */
.critter .ch-all{transform-origin:60px 146px; animation:chIdle 2.6s infinite var(--ease)}
@keyframes chIdle{0%,100%{transform:scale(1,1)}50%{transform:scale(1.035,.96)}}
.critter .head{transform-origin:60px 90px; transition:transform .5s var(--ease)}
.critter .arm{transition:transform .5s var(--ease)}
.critter .arm-l{transform-origin:31px 105px; transform:rotate(14deg)}
.critter .arm-r{transform-origin:89px 105px; transform:rotate(-14deg)}
.critter .eye-shut, .critter .eye-happy, .critter .mouth-o, .critter .mouth-wob,
.critter .tears, .critter .paw, .critter .zs{display:none}

/* sleep — eyes shut, head lolls, z's */
.critter.sleep .ch-all{animation-duration:3.6s}
.critter.sleep .head{transform:rotate(-8deg)}
.critter.sleep .eye-open{display:none}
.critter.sleep .eye-shut, .critter.sleep .zs{display:block}
.zzz{font-family:var(--hand); font-weight:700; fill:var(--gilt); animation:zzzFloat 2.4s infinite ease-out}
@keyframes zzzFloat{0%{opacity:0; transform:translate(0,4px)}30%{opacity:.9}100%{opacity:0; transform:translate(7px,-16px)}}

/* wave — one arm up and going */
.critter.wave .arm-r{animation:chWave .8s infinite var(--ease)}
@keyframes chWave{0%,100%{transform:rotate(-150deg)}50%{transform:rotate(-190deg)}}

/* dance — the whole body bops, arms swing */
.critter.dance{animation:chDance .5s infinite var(--ease)}
@keyframes chDance{
  0%,100%{transform:rotate(-8deg) translateY(0)}
  50%{transform:rotate(8deg) translateY(-11px)}
}
.critter.dance .arm-l{animation:armSwingL .5s infinite alternate var(--ease)}
.critter.dance .arm-r{animation:armSwingR .5s infinite alternate var(--ease)}
@keyframes armSwingL{from{transform:rotate(30deg)}to{transform:rotate(-40deg)}}
@keyframes armSwingR{from{transform:rotate(40deg)}to{transform:rotate(-30deg)}}

/* cheer — both arms up, eyes squeezed happy, little jumps */
.critter.cheer{animation:chJump .55s var(--ease) 6}
@keyframes chJump{0%,100%{transform:translateY(0)}45%{transform:translateY(-14px)}}
.critter.cheer .arm-l{transform:rotate(150deg)}
.critter.cheer .arm-r{transform:rotate(-150deg)}
.critter.cheer .eye-open, .critter.cheer .mouth{display:none}
.critter.cheer .eye-happy, .critter.cheer .mouth-o{display:block}

/* peek — only the top of the head shows, paws on the edge (the mount
   point hides the lower half behind the paper) */
.critter.peek .paw{display:block}
.critter.peek .ch-all{animation:chPeek 3.2s infinite var(--ease)}
@keyframes chPeek{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
.critter.peek .head{transform:rotate(-4deg)}
.critter-two.peek .head{transform:rotate(5deg)}

/* cry — happy tears, wobbly mouth, one slow wave goodbye */
.critter.cry .eye-open, .critter.cry .mouth{display:none}
.critter.cry .eye-happy, .critter.cry .mouth-wob, .critter.cry .tears{display:block}
.critter.cry .tear{animation:tearFall 1.3s infinite ease-in}
.critter.cry .tear.t2{animation-delay:.55s}
@keyframes tearFall{0%{opacity:0; transform:translateY(0)}25%{opacity:.95}100%{opacity:0; transform:translateY(16px)}}
.critter.cry .arm-r{animation:chWave 1.6s infinite var(--ease)}
.critter.cry .head{transform:rotate(-5deg)}

.cutie-tag{
  font-family:var(--hand); font-size:clamp(.85rem,2.4vw,1.05rem);
  color:var(--gilt); margin:.1em 0 0; text-align:center; white-space:nowrap;
}
.cuties.gate-cuties{
  position:absolute; left:50%; bottom:max(6px, env(safe-area-inset-bottom)); transform:translateX(-50%);
  z-index:3; align-items:flex-end;
}
.cuties.gate-cuties .critter{width:min(clamp(72px,18vw,128px), 15dvh)}   /* width-only sizing made them 128px tall on a 640px laptop */
/* a short screen (laptop, landscape phone, a small window): the clock and the
   offer are the point, the pair is decoration — drop it and tighten the stack
   rather than letting the footer land on their heads */
@media (max-height:700px) and (min-width:600px){   /* short AND wide: the clock caps at 6rem, so the stack is tallest here */
  .cuties.gate-cuties{display:none}
  .gate-inner{margin-bottom:0}
  .gate-kicker{font-size:clamp(1.1rem,3.4vh,1.6rem); margin-bottom:.35em}
  .num{font-size:clamp(2rem,10vh,4rem)}
  .begin{margin-top:clamp(14px,3vh,26px)}
  .gate-wait{gap:.5em}
  .gate-foot{margin-top:.6em}
}
@media (max-height:430px){   /* phone held sideways: the clock and the two buttons, nothing else */
  .gate-kicker{font-size:1rem; margin-bottom:.2em}
  .num{font-size:clamp(1.5rem,8vh,2.4rem)}
  .lbl{font-size:.55rem}
  .gate-ask{font-size:.95rem}
  .gate-foot{display:none}
  .begin{margin-top:10px; padding:.6em 1.3em}
}
.cuties.gate-cuties.has-tag{align-items:center}   /* column layout: the tag is centred under the pair, not tucked under the bear */
.cuties.stage-cuties{
  position:absolute; left:50%; bottom:7vh; transform:translateX(-50%); z-index:4;
  opacity:0; transition:opacity 1s var(--ease) 2.2s;
}
#stage.open .cuties.stage-cuties{opacity:1}
.stage-cuties .critter{width:clamp(66px,14vw,108px)}
.cuties.cake-cuties{justify-content:center}
.cuties.cake-cuties .cutie-tag{color:var(--gilt)}
.cuties.fin-cuties{justify-content:center; margin-bottom:0}
.act-cream .cutie-tag{color:var(--cocoa)}
