
  .stage { position:relative; width:min(100%, 480px, 64vh); height:100vh; height:100svh; margin:0 auto; overflow:hidden; background:var(--paper); contain:layout paint; }
  .L { position:absolute; display:block; pointer-events:none; user-select:none; backface-visibility:hidden; }
  .L img { display:block; width:100%; height:auto; }
  .L > img { display:block; width:100%; }

  /* ---------- layout: 1u = 1% of stage width, everything anchored to the bottom ---------- */
  .bg { left:0; bottom:calc(4 * var(--u)); width:calc(100 * var(--u)); will-change:auto; -webkit-mask-image:linear-gradient(transparent, #000 22%); mask-image:linear-gradient(transparent, #000 22%); }
  .ring { left:calc(27 * var(--u)); bottom:calc(40 * var(--u)); width:calc(46 * var(--u)); z-index:2; }
  .ring svg { position:absolute; left:28%; top:28%; width:44%; height:44%; }
  .magpie-perch { left:calc(56 * var(--u)); bottom:calc(88.5 * var(--u)); width:calc(10 * var(--u)); z-index:3; }
  .chand { left:calc(40 * var(--u)); top:0; width:calc(20 * var(--u)); z-index:3; transform-origin:50% 0; }
  .musicians { left:calc(10 * var(--u)); bottom:calc(31 * var(--u)); width:calc(26 * var(--u)); z-index:4; transform-origin:50% 100%; }
  .child { left:calc(33 * var(--u)); bottom:calc(27 * var(--u)); width:calc(8 * var(--u)); z-index:6; }
  .couple { left:calc(40 * var(--u)); bottom:calc(19 * var(--u)); width:calc(20 * var(--u)); z-index:5; transform-origin:50% 100%; }
  .waiter { right:calc(27 * var(--u)); bottom:calc(40 * var(--u)); width:calc(11 * var(--u)); z-index:3; }
  .parents { right:calc(10.5 * var(--u)); bottom:calc(30 * var(--u)); width:calc(28 * var(--u)); z-index:4; transform-origin:50% 100%; }
  .feast { left:calc(8 * var(--u)); bottom:calc(-6 * var(--u)); width:calc(84 * var(--u)); z-index:8; }
  .cur { top:0; height:100%; width:calc(51 * var(--u)); z-index:20; }
  .cur img { height:100%; object-fit:fill; }
  .cur.l { left:0; } .cur.r { right:0; }
  .tied { top:0; height:100%; width:calc(10 * var(--u)); z-index:19; }
  .tied img { height:100%; object-fit:cover; }
  .tied.l { left:0; } .tied.l img { object-position:left; }
  .tied.r { right:0; } .tied.r img { object-position:right; }
  .bow { top:calc(24% - 6 * var(--u)); width:calc(8 * var(--u)); z-index:21; }
  .bow.l { left:calc(4.5 * var(--u)); } .bow.r { right:calc(4.5 * var(--u)); }
  .fly { width:calc(13 * var(--u)); z-index:22; left:0; top:0; }

  /* ---------- choreography (only transform + opacity) ---------- */
  .cur { transition:transform 1.8s var(--io); }
  .go .cur.l { transform:translate3d(-101%,0,0); } .go .cur.r { transform:translate3d(101%,0,0); }
  .tied { opacity:0; transform:translate3d(0,0,0); transition:opacity .9s .9s var(--out); }
  .go .tied { opacity:1; }
  .bow { opacity:0; transform:translate3d(0,-20px,0) scale(.6); transition:opacity .5s 1.5s, transform .8s 1.5s var(--spring); }
  .go .bow { opacity:1; transform:none; }
  .chand { transform:translate3d(0,-105%,0); transition:transform 1.4s 1s var(--spring); }
  .go .chand { transform:none; }
  .go .chand.swing { animation:swing 4.4s ease-in-out infinite; }
  @keyframes swing { 0%,100% { transform:rotate(-2deg); } 50% { transform:rotate(2deg); } }
  .ring { opacity:0; transform:scale(.6) rotate(-20deg); transition:opacity .8s 1.6s, transform 1.2s 1.6s var(--spring); }
  .go .ring { opacity:1; transform:none; }
  .enter { opacity:0; transition:opacity .8s var(--out), transform 1s var(--out); }
  .feast.enter { transform:translate3d(0,30%,0); transition-delay:1.2s; }
  .musicians.enter { transform:translate3d(-60%,0,0); transition-delay:2.1s; }
  .parents.enter { transform:translate3d(0,15%,0); transition-delay:2.4s; }
  .child.enter { transform:translate3d(0,25%,0); transition-delay:2.7s; }
  .go .enter { opacity:1; transform:none; }
  .couple { opacity:0; transform:translate3d(170%,0,0); }
  .go .couple { animation:walkin 2.4s 2.6s var(--out) forwards; }
  @keyframes walkin {
    0% { opacity:1; transform:translate3d(170%,0,0); } 18% { transform:translate3d(135%,-3%,0); }
    36% { transform:translate3d(100%,0,0); } 54% { transform:translate3d(64%,-3%,0); }
    72% { transform:translate3d(30%,0,0); } 88% { transform:translate3d(8%,-1.5%,0); } 100% { opacity:1; transform:none; } }
  .go .couple.sway { opacity:1; animation:sway 3.6s ease-in-out infinite; }
  @keyframes sway { 0%,100% { transform:rotate(-1.5deg); } 50% { transform:rotate(1.5deg) translate3d(0,-1%,0); } }
  .waiter { opacity:0; }
  .go .waiter { animation:waiter 3s 3.3s var(--out) forwards; }
  @keyframes waiter { 0% { opacity:0; transform:translate3d(220%,0,0); } 15% { opacity:1; }
    50% { transform:translate3d(100%,-3%,0); } 100% { opacity:1; transform:none; } }
  .magpie-perch { opacity:0; transform:translate3d(0,-10px,0); transition:opacity .3s, transform .5s var(--spring); }
  .perched .magpie-perch { opacity:1; transform:none; }
  .fly.a { opacity:0; }
  .go .fly.a { animation:flyA 2.2s 2.2s var(--io) forwards; }
  @keyframes flyA { 0% { opacity:1; transform:translate3d(-40vw,40vh,0) rotate(-12deg); }
    50% { transform:translate3d(calc(30 * var(--u)),calc(70 * var(--u)),0) rotate(6deg); }
    96% { opacity:1; } 100% { opacity:0; transform:translate3d(calc(55 * var(--u)),var(--perchY),0) rotate(0); } }
  .fly.b { opacity:0; transform:scaleX(-1); }
  .go .fly.b { animation:flyB 3.4s 3.6s var(--io) forwards; }
  @keyframes flyB { 0% { opacity:1; transform:translate3d(110vw,calc(48 * var(--u)),0) scaleX(-1); }
    50% { transform:translate3d(calc(50 * var(--u)),calc(30 * var(--u)),0) scaleX(-1) rotate(-6deg); }
    100% { opacity:1; transform:translate3d(-30vw,calc(10 * var(--u)),0) scaleX(-1); } }
  /* idle loops, all transform-only */
  .go .musicians.live { animation:bob 1.1s ease-in-out infinite alternate; }
  @keyframes bob { from { transform:rotate(-1deg); } to { transform:rotate(1.2deg) translate3d(0,-1%,0); } }
  .go .parents.live { animation:clap .45s ease-in-out infinite alternate; }
  @keyframes clap { to { transform:translate3d(0,-1.4%,0); } }
  .go .child.live { animation:hop 2.2s ease-in-out infinite; }
  @keyframes hop { 50% { transform:translate3d(0,-5%,0); } }
  .notes { position:absolute; left:calc(16 * var(--u)); bottom:calc(64 * var(--u)); z-index:7; pointer-events:none; }
  .notes i { position:absolute; font-style:normal; font-size:calc(4.5 * var(--u)); color:var(--ink); opacity:0; }
  .live-notes .notes i { animation:note 2.6s ease-out infinite; }
  .notes i:nth-child(2) { left:calc(4 * var(--u)); animation-delay:.9s !important; }
  .notes i:nth-child(3) { left:calc(8 * var(--u)); animation-delay:1.7s !important; }
  @keyframes note { 0% { opacity:0; transform:translate3d(0,0,0) rotate(-10deg); } 20% { opacity:.8; } 100% { opacity:0; transform:translate3d(calc(5 * var(--u)), calc(-12 * var(--u)),0) rotate(12deg); } }

  /* ---------- type: letters rise one by one (compositor-only) ---------- */
  .title { position:absolute; left:0; right:0; top:calc(37 * var(--u)); bottom:calc(91 * var(--u)); display:flex; flex-direction:column; justify-content:center; text-align:center; z-index:10; color:var(--red); }
  .kicker { font-family:'Jost',sans-serif; font-weight:500; font-size:11px; letter-spacing:.42em; padding-left:.42em; }
  .names { font-family:'Ms Madi',cursive; font-weight:400; font-size:min(calc(17 * var(--u)), 7.6vh); line-height:1; margin-top:4px; }
  .names .w { display:block; white-space:nowrap; }
  .names .amp { font-size:.6em; line-height:.8; }
  .ch { display:inline-block; opacity:0; transform:translate3d(0,.18em,0); transition:opacity .45s var(--out), transform .6s var(--out); }
  .go .ch { opacity:1; transform:none; }
  .cn { font-family:'LXGW WenKai',serif; color:var(--ink); font-size:17px; letter-spacing:.32em; padding-left:.32em; margin-top:10px; }
  .cn small { display:block; font-family:'Jost',sans-serif; font-size:11px; letter-spacing:.36em; margin-top:6px; color:var(--red); }
  .fade { opacity:0; transform:translate3d(0,8px,0); transition:opacity .9s var(--out), transform .9s var(--out); }
  .go .fade { opacity:1; transform:none; }
  .kicker.fade { transition-delay:4.3s; } .cn.fade { transition-delay:6.6s; }

  /* ---------- tap / skip ---------- */
  .tap { position:absolute; inset:0; z-index:30; display:grid; place-items:center; background:none; border:0; cursor:pointer; }
  .tap span { font-family:'LXGW WenKai',serif; font-size:15px; letter-spacing:.4em; color:var(--ink); background:rgba(225,211,191,.9); padding:10px 18px 10px 24px; border:1px solid var(--ink); border-radius:999px; animation:breath 2.4s ease-in-out infinite; opacity:.35; }
  .tap span small { font-family:'Jost',sans-serif; font-size:9px; letter-spacing:.4em; display:block; text-align:center; color:var(--red); margin-top:2px; }
  .ready .tap span { opacity:1; }
  @keyframes breath { 50% { transform:scale(1.05); } }
  .go .tap { display:none; }
  .skip { position:absolute; right:14px; bottom:max(14px, env(safe-area-inset-bottom)); z-index:31; font-family:'LXGW WenKai',serif; font-size:12px; color:var(--ink); background:rgba(225,211,191,.85); border:1px solid rgba(42,36,32,.4); border-radius:999px; padding:4px 12px; display:none; }
  .go .skip { display:block; } .done .skip { display:none; }
  .done .L, .done .ch, .done .fade { transition:none !important; }
  .done .couple, .done .waiter { animation:none; opacity:1; transform:none; }
  .done .fly { display:none; }

  @media (prefers-reduced-motion: reduce) {
    *, .go * { animation:none !important; transition:none !important; }
    .couple, .waiter, .magpie-perch { opacity:1 !important; transform:none !important; }
    .fly { display:none; }
  }

/* ---------- v3 additions ---------- */
.go:not(.done) .L:not(.bg), .go:not(.done) .ch, .live-notes .notes i { will-change:transform, opacity; }
.swing, .live, .sway, .go .garland, .go .petals i { will-change:transform; }
.done .cur { visibility:hidden; }
.stage.off *, .stage.off { animation-play-state:paused !important; }

/* garland of lanterns and pennants across the top, behind the chandelier */
.garland { left:0; top:calc(1 * var(--u)); width:calc(100 * var(--u)); z-index:2; transform-origin:50% 0;
  opacity:0; transform:translate3d(0,-40%,0); transition:opacity .8s .8s var(--out), transform 1.2s .8s var(--out); }
.go .garland { opacity:1; transform:none; }
.go .garland.sway-g { animation:gsway 6s ease-in-out infinite; }
@keyframes gsway { 0%,100% { transform:rotate(-.6deg); } 50% { transform:rotate(.6deg) translate3d(0,.6%,0); } }

/* a few red paper-cut petals drifting down (max 8, transform/opacity only) */
.petals { position:absolute; inset:0; z-index:9; pointer-events:none; overflow:hidden; }
.petals i { position:absolute; top:-6%; width:calc(3.2 * var(--u)); height:calc(3.2 * var(--u)); opacity:0; }
.petals svg { display:block; width:100%; height:100%; }
.petals.on i { animation:petal var(--d,13s) linear var(--w,0s) infinite; }
@keyframes petal {
  0% { opacity:0; transform:translate3d(0,0,0) rotate(0); }
  8% { opacity:.85; }
  50% { transform:translate3d(calc(var(--x,6) * var(--u)), 55vh, 0) rotate(200deg); }
  88% { opacity:.75; }
  100% { opacity:0; transform:translate3d(calc(var(--x,6) * -.5 * var(--u)), 108vh, 0) rotate(400deg); } }

/* tap: disabled (half-transparent) until every layer is decoded */
.tap:disabled { cursor:default; }
.tap span { opacity:.45; }
.title .cn { font-size:18px; }

/* "往下滑" after the opening */
.hint { position:absolute; left:50%; bottom:max(16px, env(safe-area-inset-bottom)); z-index:25; margin-left:-40px; width:80px; text-align:center;
  font-family:'LXGW WenKai',serif; font-size:14px; color:var(--ink); opacity:0; transition:opacity .8s var(--out); pointer-events:none; }
.hint svg { display:block; width:18px; height:18px; margin:2px auto 0; }
.done .hint { opacity:1; }
.done .hint svg { animation:nudge 1.8s ease-in-out infinite; }
@keyframes nudge { 50% { transform:translate3d(0,5px,0); } }
.hint span { background:rgba(225,211,191,.85); padding:2px 8px; border-radius:999px; }

@media (prefers-reduced-motion: reduce) {
  .garland { opacity:1; transform:none; }
  .petals { display:none; }
}
/* short portrait screens (iPhone SE): drop the kicker so the date clears the window */
@media (min-aspect-ratio: 27/50) { .kicker { display:none; } .title .cn { margin-top:4px; } }
/* landscape: keep the stage a portrait column so nothing overlaps; paper fills the sides */
@media (orientation: landscape) { .stage { width:min(480px, 50vh); } .kicker { display:none; } .title .cn { font-size:14px; letter-spacing:.2em; } .cn small { letter-spacing:.2em; } }
.stage.reset *, .stage.reset { transition:none !important; animation:none !important; }
