/* ==========================================================
   DinnTro — opening intro "Knock knock, welcome in!" (14s).
   Real house front (photo) at golden hour with a slow camera. The 3D guest walks up, seen from
   behind, and knocks three times (4.35 / 4.85 / 5.35s); lights come on inside, the double door
   swings open on a party room, and the 3D host walks up waving him in. The scene fades to dark,
   the DinnTro wordmark glows in, and at 13s the overlay clears to reveal the homepage (gone at 14s).
   Stage coordinates are % of the 2400x1600 house photo; the door sits at x 955–1480, y 418–1377.
   ========================================================== */
html.dn-intro-lock { scrollbar-gutter: stable; background: #120a1f; }   /* the empty gutter matches the intro */
html.dn-intro-lock, html.dn-intro-lock body { overflow: hidden; }

.dn-intro {
  --sw: max(100vw, 150vh);   /* stage width: the 3:2 photo always covers the viewport */
  position: fixed; inset: 0; z-index: 9999;
  background: #120a1f;
  font-family: 'Outfit', system-ui, sans-serif;
  overflow: hidden;
}
.dn-intro.dn-skip { opacity: 0; transition: opacity .35s ease; pointer-events: none; }
.dn-intro.dn-go { animation: dn-bg-clear 1s ease 13s forwards; }   /* homepage shows through */
.dn-intro.dn-exit { pointer-events: none; }

.dn-loader {
  position: absolute; left: 50%; top: 50%;
  width: 64px; height: 64px; margin: -32px 0 0 -32px; border-radius: 30%;
  display: grid; place-items: center;
  font: 800 2rem 'Outfit', sans-serif; color: #fff;
  background: linear-gradient(135deg, #7c3aed, #ec4899);
  box-shadow: 0 16px 40px rgba(124,58,237,.45);
  animation: dn-pulse 1s ease-in-out infinite alternate;
}
.dn-go .dn-loader { display: none; }

/* soft blurred copy of the scene filling any space around the stage (tall phone screens) */
.dn-backdrop {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  filter: blur(18px) brightness(.45) saturate(1.2); transform: scale(1.12); opacity: 0;
}
.dn-go .dn-backdrop { animation: dn-fade-in 1.2s ease both, dn-hide .01s linear 12s forwards; }

/* ---------- stage & camera ---------- */
.dn-stage {
  position: absolute; left: 50%; top: 50%;
  width: var(--sw); aspect-ratio: 3 / 2;
  transform: translate(-50%, -50%);
  opacity: 0;
}
.dn-go .dn-stage { animation: dn-fade-in 1.2s ease both, dn-hide .01s linear 12s forwards; }
.dn-cam { position: absolute; inset: 0; transform-origin: 48% 58%; }   /* between the guest and the door */
.dn-go .dn-cam { animation: dn-camera 11.2s linear both; }

/* the scene fades in out of a warm golden glow */
.dn-glow {
  position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0;
  background: radial-gradient(60% 60% at 50% 55%, #fff1cf 0%, #ffc27a 45%, #c8742f 100%);
}
.dn-go .dn-glow { animation: dn-glow-out 1.5s ease-out both; }

.dn-house { position: absolute; inset: 0; width: 100%; height: 100%; display: block; filter: brightness(.86) saturate(1.12) contrast(1.04); }
.dn-go .dn-house { animation: dn-focus 3s ease-in-out 3.6s both; }
.dn-grade {   /* golden-hour grade + vignette */
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(70% 70% at 50.7% 55%, rgba(0,0,0,0) 40%, rgba(18,8,30,.55) 100%),
    linear-gradient(180deg, rgba(40,18,70,.38) 0%, rgba(255,150,60,.10) 45%, rgba(20,10,30,.30) 100%);
}

/* ---------- doorway & the party inside ---------- */
.dn-doorway {
  position: absolute; left: 39.792%; top: 26.125%; width: 21.875%; height: 59.9375%;
  overflow: hidden; perspective: calc(var(--sw) * .9);
  background: #1a0f08;
}
/* ---------- the party room: a real 3D box seen through the door ----------
   .dn-box is wider and taller than the doorway; its planes sit in CSS perspective (camera at the
   doorway): back wall at depth --D, floor/ceiling/side walls joining it, and object layers in between.
   The whole room starts dark and the lights come on at 6.9s; it stays a touch soft (depth of field). */
.dn-room { position: absolute; inset: 0; filter: brightness(.12) blur(calc(var(--sw) * .0018)); }
.dn-go .dn-room { animation: dn-room-on 1.2s ease 6.9s forwards; }
.dn-box {
  --D: calc(var(--sw) * .5);
  position: absolute; left: -70%; right: -70%; top: -15%; bottom: 0;
  perspective: calc(var(--sw) * .25); perspective-origin: 52% 40%;
}
.dn-go .dn-box { animation: dn-room-look 4.2s ease-out 7s both; }   /* parallax as the camera pushes in */
.dn-box .pl { position: absolute; backface-visibility: hidden; }
.dn-box .back {
  inset: 0; transform: translateZ(calc(var(--D) * -1));
  background:
    radial-gradient(45% 40% at 50% 18%, rgba(255,214,150,.55), rgba(255,190,120,0) 70%),
    radial-gradient(120% 100% at 50% 40%, rgba(0,0,0,0) 55%, rgba(40,16,6,.45) 100%),
    linear-gradient(180deg, rgba(0,0,0,0) 0 67%, #6e4128 67% 68.2%, #c79a74 68.2% 100%),
    repeating-linear-gradient(90deg, rgba(255,255,255,.07) 0 1.4%, rgba(120,60,30,.05) 1.4% 2.8%),
    #ecc9a7;
}
.dn-box .back .win {   /* night window with curtains, left of centre */
  position: absolute; left: 9%; top: 22%; width: 17%; height: 36%;
  background: linear-gradient(180deg, #1b2346, #2c3a66 70%, #3c3f5e);
  border: calc(var(--sw) * .004) solid #f1e2cf;
  box-shadow: 0 calc(var(--sw) * .004) calc(var(--sw) * .01) rgba(60,25,10,.35);
}
.dn-box .back .win::before, .dn-box .back .win::after {   /* curtains */
  content: ""; position: absolute; top: -8%; bottom: -12%; width: 30%;
  background: repeating-linear-gradient(90deg, #b0465c 0 12%, #c75a70 12% 24%); border-radius: 0 0 30% 30%;
}
.dn-box .back .win::before { left: -24%; }
.dn-box .back .win::after { right: -24%; }
.dn-box .back .win i { position: absolute; left: 50%; top: 0; bottom: 0; width: 4%; background: #f1e2cf; }
.dn-box .garland { position: absolute; left: 0; top: 4%; width: 100%; height: 18%; overflow: visible; }
.dn-box .garland path { fill: none; stroke: #3a2a1c; stroke-width: .25; }
.dn-box .bulbs i {
  position: absolute; width: 1.1%; aspect-ratio: 1; margin-left: -.55%; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #fff, #ffe2a0 45%, #ffb35c);
  box-shadow: 0 0 calc(var(--sw) * .008) calc(var(--sw) * .003) rgba(255,200,120,.75),
              0 0 calc(var(--sw) * .02) calc(var(--sw) * .008) rgba(255,170,80,.35);
  animation: dn-twinkle 1.7s ease-in-out infinite alternate;
}
.dn-box .floor {
  left: 0; right: 0; bottom: 0; height: var(--D); transform-origin: 50% 100%; transform: rotateX(90deg);
  background:
    radial-gradient(40% 30% at 50% 45%, rgba(255,200,130,.35), rgba(255,180,100,0) 70%),
    linear-gradient(0deg, rgba(20,8,2,.35), rgba(20,8,2,0) 30%, rgba(20,8,2,0) 80%, rgba(20,8,2,.45)),
    repeating-linear-gradient(90deg, #8d5b36 0 3.4%, #7a4c2c 3.4% 3.6%, #9c6a42 3.6% 7%, #6f4427 7% 7.2%),
    #855530;
}
.dn-box .rug {   /* round rug in the middle of the room */
  position: absolute; left: 36%; top: 30%; width: 28%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, #c98a7a 0 52%, #e9c9a9 52% 56%, #b26a5f 56% 88%, #e9c9a9 88% 92%, #9a5850 92%);
}
.dn-box .ceil {
  left: 0; right: 0; top: 0; height: var(--D); transform-origin: 50% 0; transform: rotateX(-90deg);
  background: radial-gradient(50% 45% at 52% 55%, #f4e2c8, #d6b896 70%, #9c7a5a);
}
.dn-box .wl, .dn-box .wr {
  top: 0; bottom: 0; width: var(--D);
  background:
    linear-gradient(rgba(40,16,6,.28), rgba(40,16,6,.28)),
    linear-gradient(180deg, rgba(0,0,0,0) 0 67%, #5e3620 67% 68.2%, #ad8160 68.2% 100%),
    repeating-linear-gradient(90deg, rgba(255,255,255,.05) 0 1.4%, rgba(120,60,30,.05) 1.4% 2.8%),
    #c9a384;
}
.dn-box .wl { left: 0; transform-origin: 0 50%; transform: rotateY(90deg); }
.dn-box .wr { right: 0; transform-origin: 100% 50%; transform: rotateY(-90deg); }

/* objects standing in the room (props layer at 80% depth: its bottom edge lies on the floor) */
.dn-box .props { inset: 0; transform: translateZ(calc(var(--D) * -.8)); }
.dn-box .lamp { inset: 0; transform: translateZ(calc(var(--D) * -.45)); }
.dn-box .table {   /* party table with a long cloth, left of the host's path */
  position: absolute; left: 6%; bottom: 0; width: 30%; height: 27%;
  background: linear-gradient(180deg, #fff7ee 0 12%, #e9d2c0 12% 14%, #fbefe4 14%);
  border-radius: 1% 1% 0 0;
}
.dn-box .table::before {   /* cloth folds */
  content: ""; position: absolute; left: 0; right: 0; top: 14%; bottom: 0;
  background: repeating-linear-gradient(90deg, rgba(0,0,0,0) 0 6%, rgba(120,70,50,.09) 6% 9%);
}
.dn-box .table::after {   /* table shadow on the floor */
  content: ""; position: absolute; left: -4%; right: -4%; bottom: -3%; height: 6%;
  background: radial-gradient(closest-side, rgba(20,8,2,.55), rgba(20,8,2,0));
}
.dn-box .cake { position: absolute; left: 34%; bottom: 86%; width: 30%; height: 70%; }
.dn-box .cake i { position: absolute; left: 50%; transform: translateX(-50%); border-radius: 10% 10% 4% 4% / 20% 20% 6% 6%; }
.dn-box .cake .t1 {
  bottom: 0; width: 100%; height: 42%;
  background: linear-gradient(90deg, rgba(0,0,0,0) 60%, rgba(150,70,80,.18)),
              linear-gradient(180deg, #fff 0 22%, #f6b9c8 22% 30%, #fde3ea 30%);
}
.dn-box .cake .t2 {
  bottom: 40%; width: 64%; height: 34%;
  background: linear-gradient(90deg, rgba(0,0,0,0) 60%, rgba(100,60,140,.18)),
              linear-gradient(180deg, #fff 0 24%, #c9a5e8 24% 32%, #efe2fb 32%);
}
.dn-box .cake b {   /* candles with flickering flames */
  position: absolute; bottom: 73%; width: 4%; height: 18%;
  background: repeating-linear-gradient(180deg, #fff 0 20%, #f08aa5 20% 40%);
}
.dn-box .cake b:nth-of-type(1) { left: 36%; }
.dn-box .cake b:nth-of-type(2) { left: 48%; }
.dn-box .cake b:nth-of-type(3) { left: 60%; }
.dn-box .cake b::after {
  content: ""; position: absolute; left: 50%; bottom: 100%; width: 260%; aspect-ratio: 1 / 1.7; transform: translateX(-50%);
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
  background: radial-gradient(circle at 50% 70%, #fff 0 22%, #ffd36b 40%, rgba(255,140,40,0) 72%);
  animation: dn-flame .18s ease-in-out infinite alternate;
}
.dn-box .gift { position: absolute; bottom: 86%; }
.dn-box .gift::before {   /* ribbon */
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 44%, rgba(255,255,255,.85) 44% 56%, transparent 56%),
              linear-gradient(180deg, transparent 40%, rgba(255,255,255,.85) 40% 52%, transparent 52%);
}
.dn-box .gift.g1 { left: 72%; width: 13%; height: 26%; background: linear-gradient(90deg, #7c3aed, #5b21b6); }
.dn-box .gift.g2 { left: 85%; width: 9%; height: 18%; background: linear-gradient(90deg, #ec4899, #be185d); }
.dn-box .pendant {   /* pendant lamp hanging from the ceiling over the room */
  position: absolute; left: 50%; top: 0; width: 7%; height: 22%; transform: translateX(-50%);
  background: linear-gradient(90deg, transparent 48%, #2b1d12 48% 52%, transparent 52%) top / 100% 72% no-repeat;
}
.dn-box .pendant::before {   /* shade */
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 30%;
  border-radius: 50% 50% 8% 8% / 90% 90% 10% 10%;
  background: linear-gradient(180deg, #3a2a1c, #21160d);
}
.dn-box .pendant::after {   /* glowing bulb + light cone */
  content: ""; position: absolute; left: 50%; top: 100%; width: 520%; height: 380%; transform: translateX(-50%);
  background: radial-gradient(9% 7% at 50% 2%, #fff6d8, rgba(255,220,150,.9) 50%, rgba(255,200,120,0) 100%),
              radial-gradient(50% 100% at 50% 0, rgba(255,214,150,.35), rgba(255,200,120,0) 70%);
}
/* glossy party balloons on strings */
.dn-box .balloon {
  position: absolute; width: 7%; aspect-ratio: 5 / 6; border-radius: 50% 50% 47% 47% / 56% 56% 44% 44%;
  background:
    radial-gradient(18% 14% at 34% 27%, var(--h), rgba(255,255,255,0) 100%),
    radial-gradient(90% 90% at 70% 78%, rgba(0,0,0,.4), rgba(0,0,0,0) 60%),
    radial-gradient(60% 60% at 40% 35%, var(--c), color-mix(in srgb, var(--c) 70%, #000) 100%);
  animation: dn-float 3.2s ease-in-out infinite alternate;
}
.dn-box .balloon::before {   /* tied knot */
  content: ""; position: absolute; left: 44%; top: 97%; width: 12%; height: 7%;
  background: color-mix(in srgb, var(--c) 75%, #000); clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.dn-box .balloon::after {   /* string */
  content: ""; position: absolute; left: 49%; top: 103%; width: 10%; height: 190%;
  border-left: 1px solid rgba(255,245,230,.55); border-radius: 0 0 0 60%;
}
.dn-room::after {   /* evening interior light: a little darker toward the edges, warm overall */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(110% 90% at 50% 40%, rgba(0,0,0,0) 50%, rgba(25,10,4,.5) 100%),
    linear-gradient(180deg, rgba(255,170,90,.06), rgba(255,170,90,.1));
}
/* the thickness of the door frame: shadowed inner edges where wall meets doorway */
.dn-reveal {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(20,10,4,.75) 0%, rgba(20,10,4,0) 7%, rgba(20,10,4,0) 93%, rgba(20,10,4,.75) 100%),
    linear-gradient(180deg, rgba(20,10,4,.7) 0%, rgba(20,10,4,0) 6%);
}

/* host: walks from inside the room up to the threshold (7.5–9.5s), waving */
.dn-host {
  position: absolute; left: 34.5%; bottom: .6%; height: 80%; aspect-ratio: 571 / 1772;
  transform-origin: 50% 100%;
  transform: translateY(-46.75%) scale(.45); filter: brightness(.5); opacity: 0;
}
.dn-go .dn-host { animation: dn-host-walk 2s cubic-bezier(.35,.1,.4,1) 7.5s forwards; }
/* puppet rig: legs (behind) step in turn, the upper body sways with each step, then rocks as she greets */
.dn-host .bob, .dn-host .upper { position: absolute; inset: 0; }
.dn-host .bob { transform-origin: 50% 100%; }
.dn-host .upper { transform-origin: 50% 65%; }
.dn-go .dn-host .bob { animation: dn-bob .3333s ease-in-out 7.5s 6; }
.dn-go .dn-host .upper {
  animation: dn-sway .6667s ease-in-out 7.5s 3, dn-greet .9s ease-in-out 9.5s, dn-idle 2.2s ease-in-out 10.4s infinite alternate;
}
.dn-host img { position: absolute; display: block; }
.dn-host .torso, .dn-host .leg { inset: 0; width: 100%; height: 100%; }
.dn-host .leg.l { transform-origin: 42.4% 63.6%; }
.dn-host .leg.r { transform-origin: 65% 63.6%; }
.dn-go .dn-host .leg.l { animation: dn-lift-a .6667s ease-in-out 7.5s 3; }
.dn-go .dn-host .leg.r { animation: dn-lift-b .6667s ease-in-out 7.5s 3; }
.dn-host .hand { left: 0; top: 15.745%; width: 29.597%; transform-origin: 47.34% 93.65%; }
.dn-go .dn-host .hand { animation: dn-wave .3s ease-in-out 7.9s 16 alternate; }
.dn-host .bob::after {   /* contact shadow on the floor, under and slightly behind her (lamp in front) */
  content: ""; position: absolute; left: -6%; right: -2%; bottom: -2%; height: 5%;
  border-radius: 50%; background: radial-gradient(closest-side, rgba(15,6,2,.7), rgba(15,6,2,0));
  z-index: -1;
}

/* the real door leaves: rattle with each knock, then swing open together at 7.0s */
.dn-leaf {
  position: absolute; top: 0; height: 100%;
  background-size: 100% 100%;
  backface-visibility: hidden;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.25);
  filter: brightness(.86) saturate(1.12) contrast(1.04);   /* match the graded house */
}
.dn-leaf.l { left: 0; width: 47.24%; background-image: url(../img/intro/door-left.jpg); transform-origin: 0 50%; }
.dn-leaf.r { right: 0; width: 52.76%; background-image: url(../img/intro/door-right.jpg); transform-origin: 100% 50%; }
.dn-go .dn-leaf.l { animation: dn-rattle-l 1.5s linear 4.1s, dn-open-l 1s cubic-bezier(.55,0,.2,1) 7s forwards; }
.dn-go .dn-leaf.r { animation: dn-rattle-r 1.5s linear 4.1s, dn-open-r 1s cubic-bezier(.55,0,.2,1) 7s forwards; }
/* lights coming on behind the diamond glass: someone is coming to the door */
.dn-leaf .glass {
  position: absolute; top: 10.5%; height: 18%;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  background: radial-gradient(circle at 50% 55%, #fff1cf, #ffb35c 70%);
  mix-blend-mode: screen; opacity: 0;
}
.dn-leaf.l .glass { left: 30%; width: 34%; }
.dn-leaf.r .glass { left: 42%; width: 29%; }
.dn-go .dn-leaf .glass { animation: dn-glass 1s ease 6s forwards; }
.dn-gap {   /* warm line of light under the door */
  position: absolute; left: 0; right: 0; bottom: 0; height: 1.4%;
  background: linear-gradient(180deg, rgba(255,200,120,0), rgba(255,200,120,.95));
  filter: blur(2px); opacity: 0;
}
.dn-go .dn-gap { animation: dn-glass .8s ease 6s forwards; }

/* a ripple where each knock lands */
.dn-ripple {
  position: absolute; left: 19%; top: 31%; width: 14%; aspect-ratio: 1;
  border-radius: 50%; border: 2px solid rgba(255,236,200,.9);
  opacity: 0; transform: translate(-50%, -50%) scale(.3);
}
.dn-go .dn-ripple    { animation: dn-ripple .5s ease-out 4.35s 1; }
.dn-go .dn-ripple.r2 { animation-delay: 4.85s; }
.dn-go .dn-ripple.r3 { animation-delay: 5.35s; }

/* warm light blooming out of the open doorway over the facade */
.dn-bloom {
  position: absolute; left: 28%; top: 18%; width: 46%; height: 76%; pointer-events: none;
  background: radial-gradient(42% 46% at 50% 52%, rgba(255,214,150,.75), rgba(255,170,90,.25) 55%, rgba(255,160,80,0) 78%);
  mix-blend-mode: screen; filter: blur(calc(var(--sw) * .01)); opacity: 0;
}
.dn-go .dn-bloom { animation: dn-bloom 2.4s ease-out 7s forwards; }
@keyframes dn-bloom { 0% { opacity: 0; } 35% { opacity: .85; } 100% { opacity: .45; } }

/* warm light spilling over the threshold and porch once open */
.dn-spill {
  position: absolute; left: 33%; top: 85.6%; width: 35.5%; height: 14%;
  background: radial-gradient(50% 50% at 50% 12%, rgba(255,196,120,.8), rgba(255,160,80,.22) 55%, rgba(255,160,80,0) 75%);
  mix-blend-mode: screen; opacity: 0; pointer-events: none;
}
.dn-go .dn-spill { animation: dn-fade-in 1.2s ease 7.2s forwards; }

/* ---------- guest at the door, seen from behind ---------- */
.dn-guest {
  position: absolute; left: 34.46%; bottom: 10%; width: 10.69%; aspect-ratio: 504 / 1611;
  transform-origin: 50% 100%;
}
/* puppet rig: legs swing from the hips in turn (8 steps), the body dips on each stride and sways,
   the arm swings low while walking, then lifts the fist to knock; he leans into each knock,
   breathes and shifts his weight while waiting, and hops once with squash and stretch */
.dn-guest .walk, .dn-guest .upper, .dn-guest .limb { position: absolute; inset: 0; }
.dn-guest .walk { transform-origin: 50% 100%; }
.dn-guest .upper { transform-origin: 50% 60%; }
.dn-guest .limb { transform-origin: 68.6% 22.7%; transform: rotate(14deg); }   /* shoulder */
.dn-guest img { position: absolute; display: block; }
.dn-guest .torso, .dn-guest .uparm, .dn-guest .leg { inset: 0; width: 100%; height: 100%; }
.dn-guest .leg.l { transform-origin: 26.2% 59.1%; }
.dn-guest .leg.r { transform-origin: 58.1% 59.1%; }
.dn-guest .arm { left: 74.206%; top: 9.497%; width: 25.794%; transform-origin: 62.31% 84.96%; opacity: 0; }
.dn-guest img { filter: brightness(.88) contrast(1.05) saturate(1.05); }
.dn-go .dn-guest { animation: dn-guest-in 2.5s cubic-bezier(.3,.2,.35,1) 1.5s both, dn-hop .6s ease-in-out 10s 1; }
.dn-go .dn-guest .walk { animation: dn-bob .3125s ease-in-out 1.5s 8, dn-breathe 1.3s ease-in-out 4s infinite alternate; }
.dn-go .dn-guest .upper {
  animation: dn-sway .625s ease-in-out 1.5s 4, dn-lean 1.5s ease-in-out 4.1s, dn-idle 2.4s ease-in-out 5.8s infinite alternate;
}
.dn-go .dn-guest .leg.l { animation: dn-stride-a .625s ease-in-out 1.5s 4; }
.dn-go .dn-guest .leg.r { animation: dn-stride-b .625s ease-in-out 1.5s 4; }
.dn-go .dn-guest .limb { animation: dn-arm-swing .625s ease-in-out 1.5s 4, dn-arm-up .4s cubic-bezier(.3,0,.3,1) 3.7s forwards, dn-arm-down .5s ease-in-out 5.75s forwards; }
.dn-go .dn-guest img { animation: dn-lit 1.2s ease 7.4s forwards; }
.dn-go .dn-guest .arm { animation: dn-fist-up .4s cubic-bezier(.3,0,.3,1) 3.7s forwards, dn-knock 1.5s ease-in-out 4.1s, dn-fist-down .5s ease-in-out 5.75s forwards, dn-lit 1.2s ease 7.4s forwards; }
.dn-guest::before {   /* contact shadow: stays on the ground while he bobs and hops */
  content: ""; position: absolute; left: 0; right: 0; bottom: -1.5%; height: 3%;
  border-radius: 50%; background: radial-gradient(closest-side, rgba(0,0,0,.5), rgba(0,0,0,0));
}
.dn-go .dn-guest::before { animation: dn-shadow-hop .6s ease-in-out 10s 1; }

/* ---------- depth: dappled leaf shadows, light rays, out-of-focus foreground, petals ---------- */
.dn-dapple {   /* soft leaf shadows drifting on the wall */
  position: absolute; inset: -4%; pointer-events: none; mix-blend-mode: multiply; opacity: .55;
  background:
    radial-gradient(9% 7% at 12% 22%, rgba(60,30,10,.55), transparent 70%),
    radial-gradient(6% 9% at 22% 12%, rgba(60,30,10,.45), transparent 70%),
    radial-gradient(8% 6% at 30% 30%, rgba(60,30,10,.4), transparent 70%),
    radial-gradient(10% 7% at 78% 16%, rgba(60,30,10,.5), transparent 70%),
    radial-gradient(7% 8% at 88% 30%, rgba(60,30,10,.45), transparent 70%),
    radial-gradient(6% 6% at 70% 8%, rgba(60,30,10,.4), transparent 70%);
  filter: blur(calc(var(--sw) * .006));
  animation: dn-dapple 5s ease-in-out infinite alternate;
}
.dn-rays {   /* warm late-sun rays and lens bloom from the top left */
  position: absolute; inset: 0; z-index: 2; pointer-events: none; mix-blend-mode: screen;
  background:
    radial-gradient(28% 34% at 4% -4%, rgba(255,214,150,.55), rgba(255,180,90,0) 70%),
    repeating-conic-gradient(from 118deg at -4% -10%, rgba(255,215,150,0) 0deg, rgba(255,215,150,.13) 4deg, rgba(255,215,150,0) 8deg 17deg);
  -webkit-mask-image: linear-gradient(160deg, #000 0%, rgba(0,0,0,.45) 30%, transparent 58%);
  mask-image: linear-gradient(160deg, #000 0%, rgba(0,0,0,.45) 30%, transparent 58%);
  filter: blur(calc(var(--sw) * .005));
  opacity: .7;
  animation: dn-rays 6s ease-in-out infinite alternate;
}
.dn-fg {   /* nearest the camera: blurred, in shade, moves more than the house (parallax) */
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 3; pointer-events: none;
  filter: blur(calc(var(--sw) * .0045)) brightness(.62) saturate(1.1);
  transform-origin: 48% 58%;
}
.dn-go .dn-fg { animation: dn-camera-fg 11.2s linear both; }
.dn-petals { position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden; }
.dn-petals i {
  position: absolute; top: -4%; width: calc(var(--sw) * .006); height: calc(var(--sw) * .0042);
  border-radius: 70% 0 70% 0; background: linear-gradient(135deg, #ffd1d6, #f49aa8);
  filter: blur(.6px);
  opacity: 0; animation: dn-petal var(--t) linear var(--d) infinite;
}

/* ---------- cinematic subtitles, letterbox and film grain ---------- */
.dn-caps {
  --bar: 8vh;
  position: absolute; left: 0; right: 0; bottom: calc(var(--bar) + 3.2vh); z-index: 6;
  height: 1.3em; font-size: clamp(22px, 3.1vw, 46px); pointer-events: none;
}
.dn-cap {
  position: absolute; left: 0; right: 0; margin: 0; text-align: center;
  font: italic 400 1em/1.2 'Instrument Serif', Georgia, serif; letter-spacing: .01em; color: #fff8ec;
  text-shadow: 0 2px 18px rgba(0,0,0,.55), 0 0 2px rgba(0,0,0,.4);
  opacity: 0;
}
.dn-go .dn-cap.knock   { animation: dn-cap 2s ease 4.25s both; }
.dn-go .dn-cap.coming  { animation: dn-cap 1.5s ease 6s both; }
.dn-go .dn-cap.welcome { animation: dn-cap 1.9s ease 9.45s both; }
@keyframes dn-cap {
  0%   { opacity: 0; transform: translateY(.25em); filter: blur(6px); letter-spacing: .08em; }
  22%  { opacity: 1; transform: none; filter: blur(0); letter-spacing: .01em; }
  80%  { opacity: 1; filter: blur(0); }
  100% { opacity: 0; filter: blur(4px); }
}
/* letterbox: bars ease in with the opening shot and part again for the logo */
.dn-bars { position: absolute; inset: 0; z-index: 9; pointer-events: none; }
.dn-bars::before, .dn-bars::after {
  content: ""; position: absolute; left: 0; right: 0; height: 8vh; background: #07040e;
  transform: scaleY(0);
}
.dn-bars::before { top: 0; transform-origin: 50% 0; }
.dn-bars::after { bottom: 0; transform-origin: 50% 100%; }
.dn-go .dn-bars::before, .dn-go .dn-bars::after {
  animation: dn-bar-in 1.4s cubic-bezier(.65,0,.35,1) .1s both, dn-bar-out 1s cubic-bezier(.65,0,.35,1) 11.6s forwards;
}
@keyframes dn-bar-in  { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes dn-bar-out { from { transform: scaleY(1); } to { transform: scaleY(0); } }
/* fine moving film grain over everything */
.dn-grain {
  position: absolute; inset: -50%; z-index: 9; pointer-events: none; opacity: .09; mix-blend-mode: overlay;
  background-image: 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%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1.4 -.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: dn-grain .5s steps(5) infinite;
}
.dn-go .dn-grain { animation: dn-grain .5s steps(5) infinite, dn-unveil .8s ease 13s forwards; }
@keyframes dn-grain {
  0% { transform: translate(0, 0); } 20% { transform: translate(-3%, 2%); } 40% { transform: translate(2%, -3%); }
  60% { transform: translate(-2%, -1%); } 80% { transform: translate(3%, 3%); } 100% { transform: translate(0, 0); }
}

/* ---------- confetti (stage units) & motes ---------- */
.dn-confetti { position: absolute; left: 50.5%; top: 33%; width: 0; height: 0; z-index: 6; }
.dn-confetti i {
  position: absolute; width: calc(var(--sw) * .0042 * var(--s, 1)); height: calc(var(--sw) * .0068 * var(--s, 1));
  border-radius: 1px; background: linear-gradient(135deg, var(--c), color-mix(in srgb, var(--c) 70%, #000)); opacity: 0;
  filter: blur(var(--b, 0));
}
.dn-go .dn-confetti i { animation: dn-conf 2.8s cubic-bezier(.12,.6,.35,1) var(--d) forwards; }
.dn-go .dn-motes { animation: dn-hide .01s linear 12s forwards; }
.dn-motes i {
  position: absolute; width: 4px; height: 4px; border-radius: 50%;
  background: #ffd9a0; box-shadow: 0 0 8px 2px rgba(255,200,120,.7);
  opacity: 0; animation: dn-mote var(--t) linear var(--d) infinite;
}

/* ---------- fade to dark, logo, clear into the homepage ---------- */
.dn-dark { position: absolute; inset: 0; z-index: 7; background: #0b0617; opacity: 0; pointer-events: none; }
.dn-go .dn-dark { animation: dn-fade-in .8s ease 11.2s forwards, dn-unveil 1s ease 13s forwards; }
.dn-title {
  position: absolute; left: 0; right: 0; top: 50%; z-index: 8;
  text-align: center; padding: 0 16px; color: #fff;
  opacity: 0; transform: translateY(-50%) scale(.94);
}
.dn-title::before {   /* soft brand aura behind the wordmark */
  content: ""; position: absolute; left: 50%; top: 50%; width: min(80vw, 760px); aspect-ratio: 2.2;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(236,72,153,.22), rgba(124,58,237,.14) 45%, rgba(124,58,237,0));
  filter: blur(20px); z-index: -1;
}
.dn-go .dn-title { animation: dn-logo-in 1s cubic-bezier(.22,1,.36,1) 11.9s forwards, dn-logo-out .65s cubic-bezier(.5,0,.75,0) 13s forwards; }   /* gone before the final homepage frames */
.dn-logo {
  display: inline-block; line-height: 0;
  filter: drop-shadow(0 0 22px rgba(236,72,153,.4));   /* soft brand glow */
}
.dn-logo img { display: block; width: min(78vw, 560px); height: auto; }

/* ---------- controls ---------- */
.dn-ctrls {
  position: absolute; right: 16px; bottom: max(16px, env(safe-area-inset-bottom)); z-index: 10;
  display: flex; gap: 8px;
}
.dn-go .dn-ctrls { animation: dn-unveil .4s ease 13s forwards; }
.dn-ctrls button {
  font: 600 .85rem 'Inter', system-ui, sans-serif; color: #fff;
  background: rgba(15,10,31,.45); border: 1px solid rgba(255,255,255,.25);
  padding: .55rem 1rem; border-radius: 999px; cursor: pointer;
  backdrop-filter: blur(6px);
  transition: background .2s;
}
.dn-ctrls button:hover { background: rgba(15,10,31,.7); }
.dn-ctrls button[hidden] { display: none; }

/* ---------- phones / portrait: nudge the shot left so the guest stays in frame ---------- */
@media (max-aspect-ratio: 1/1) {
  .dn-intro { --sw: max(100vw, 100vh); }   /* zoomed out: the stage no longer fills the full height */
  .dn-stage { transform: translate(-46.5%, -50%); }
  .dn-caps { font-size: 26px; }
}

/* ---------- keyframes ---------- */
@keyframes dn-pulse     { from { transform: scale(.92); } to { transform: scale(1.05); } }
@keyframes dn-fade-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes dn-hide      { to { opacity: 0; visibility: hidden; } }
@keyframes dn-unveil    { from { opacity: 1; } to { opacity: 0; visibility: hidden; } }
@keyframes dn-glow-out  { from { opacity: 1; } to { opacity: 0; } }
@keyframes dn-bg-clear  { from { background-color: #120a1f; } to { background-color: transparent; } }
@keyframes dn-twinkle   { from { opacity: .55; } to { opacity: 1; } }
@keyframes dn-float     { from { transform: translateY(0) rotate(-3deg); } to { transform: translateY(-6%) rotate(3deg); } }
@keyframes dn-sweep     { from { transform: translate(-6%, -3%) rotate(-4deg); } to { transform: translate(6%, 3%) rotate(4deg); } }

/* camera over 11.2s: a slow dolly in drifting right with the guest (0–2.5s), a push in close for the
   knock (2.5–4.3s), a pull back as the doors open (6–7s), then a push toward the doorway (7–11.2s). translateX stays within the zoom margin
   so the stage edges never show. */
@keyframes dn-camera {
  0%     { transform: translateX(1.4%) scale(1.06);  animation-timing-function: cubic-bezier(.4,0,.6,1); }
  22.32% { transform: translateX(.6%) scale(1.1);    animation-timing-function: cubic-bezier(.45,0,.55,1); }
  38.39% { transform: translateX(.4%) scale(1.17);   animation-timing-function: linear; }
  53.57% { transform: translateX(.3%) scale(1.18);   animation-timing-function: cubic-bezier(.45,0,.55,1); }
  62.5%  { transform: translateX(-.2%) scale(1.1);   animation-timing-function: cubic-bezier(.45,0,.55,1); }
  100%   { transform: translateX(-.8%) scale(1.2); }
}
/* the same move, exaggerated for the foreground nearest the camera (parallax) */
@keyframes dn-camera-fg {
  0%     { transform: translateX(2.6%) scale(1.1);   animation-timing-function: cubic-bezier(.4,0,.6,1); }
  22.32% { transform: translateX(1.2%) scale(1.17);  animation-timing-function: cubic-bezier(.45,0,.55,1); }
  38.39% { transform: translateX(.8%) scale(1.29);   animation-timing-function: linear; }
  53.57% { transform: translateX(.6%) scale(1.3);    animation-timing-function: cubic-bezier(.45,0,.55,1); }
  62.5%  { transform: translateX(-.4%) scale(1.17);  animation-timing-function: cubic-bezier(.45,0,.55,1); }
  100%   { transform: translateX(-1.6%) scale(1.33); }
}
/* the party room is deeper than the facade: it moves less as the camera pushes in */
@keyframes dn-room-look { from { perspective-origin: 57% 40%; } to { perspective-origin: 47% 42%; } }
@keyframes dn-flame { from { transform: translateX(-50%) scale(1, 1) rotate(-3deg); } to { transform: translateX(-50%) scale(.85, 1.12) rotate(3deg); } }
/* focus pull: the house goes soft while the guest knocks on the (sharp) door */
@keyframes dn-focus {
  0%, 100% { filter: brightness(.86) saturate(1.12) contrast(1.04) blur(0); }
  20%, 72% { filter: brightness(.82) saturate(1.12) contrast(1.04) blur(calc(var(--sw) * .0011)); }
}
@keyframes dn-dapple { from { transform: translate(0, 0); } to { transform: translate(1.2%, .8%); } }
@keyframes dn-rays   { from { opacity: .5; transform: translateX(-1%); } to { opacity: .8; transform: translateX(1%); } }
@keyframes dn-petal {
  0%   { opacity: 0; transform: translate(0, 0) rotate(0); }
  10%  { opacity: .9; }
  50%  { transform: translate(calc(var(--px) * .3 + var(--sw) * .02), calc(var(--sw) * .35)) rotate(calc(var(--pr) * .5)); }
  90%  { opacity: .9; }
  100% { opacity: 0; transform: translate(var(--px), calc(var(--sw) * .7)) rotate(var(--pr)); }
}

@keyframes dn-guest-in { from { transform: translateX(-440%); } to { transform: none; } }   /* starts off-screen left */
/* walk cycle: one stride = two steps; the body dips as the legs reach their widest */
@keyframes dn-bob      { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(1%); } }
@keyframes dn-sway     { 0%, 100% { transform: none; } 25% { transform: rotate(1.2deg); } 75% { transform: rotate(-1.2deg); } }
@keyframes dn-stride-a { 0%, 100% { transform: none; } 25% { transform: rotate(8deg); } 75% { transform: rotate(-8deg); } }
@keyframes dn-stride-b { 0%, 100% { transform: none; } 25% { transform: rotate(-8deg); } 75% { transform: rotate(8deg); } }
@keyframes dn-lift-a   { 0%, 50%, 100% { transform: none; } 25% { transform: translateY(-1.6%) rotate(-1.5deg); } }
@keyframes dn-lift-b   { 0%, 50%, 100% { transform: none; } 75% { transform: translateY(-1.6%) rotate(1.5deg); } }
@keyframes dn-arm-swing { 0%, 100% { transform: rotate(14deg); } 25% { transform: rotate(8deg); } 75% { transform: rotate(20deg); } }
@keyframes dn-arm-up   { from { transform: rotate(14deg); } to { transform: none; } }
@keyframes dn-arm-down { from { transform: none; } to { transform: rotate(14deg); } }
@keyframes dn-fist-down { 0% { opacity: 1; transform: none; } 60% { opacity: 0; } 100% { opacity: 0; transform: rotate(80deg); } }
@keyframes dn-fist-up  { 0% { opacity: 0; transform: rotate(80deg); } 40% { opacity: 1; } 100% { opacity: 1; transform: none; } }
@keyframes dn-breathe  { from { transform: scaleY(1); } to { transform: scaleY(1.006); } }
@keyframes dn-idle     { from { transform: rotate(-.5deg); } to { transform: rotate(.6deg); } }
@keyframes dn-greet    { 0%, 100% { transform: none; } 35% { transform: translateY(.6%) rotate(-2.5deg); } 70% { transform: rotate(1deg); } }
/* he leans into each knock (impacts at 4.35 / 4.85 / 5.35s, same offsets as dn-knock) */
@keyframes dn-lean {
  0%, 100% { transform: none; }
  8%, 41.333%, 74.667% { transform: rotate(-.6deg); }
  16.667%, 50%, 83.333% { transform: rotate(1.4deg); }
  25%, 58.333%, 91.667% { transform: rotate(.4deg); }
}
/* three raps over 1.5s from 4.1s: wind up, fist hits the door at 4.35 / 4.85 / 5.35s */
@keyframes dn-knock {
  0%, 100% { transform: rotate(0); }
  8%, 41.333%, 74.667% { transform: rotate(-5deg); }
  16.667%, 50%, 83.333% { transform: rotate(9deg); }
  25%, 58.333%, 91.667% { transform: rotate(1deg); }
}
@keyframes dn-lit  { to { filter: brightness(.97) contrast(1.05) saturate(1.08) sepia(.1); } }
/* one happy hop: crouch, spring up, land, settle */
@keyframes dn-hop {
  0%, 100% { transform: none; }
  18% { transform: scale(1.05, .92); }
  50% { transform: translateY(-5%) scale(.96, 1.05); }
  78% { transform: scale(1.04, .94); }
}
@keyframes dn-shadow-hop { 0%, 100% { transform: none; opacity: 1; } 50% { transform: scale(.7); opacity: .5; } }

@keyframes dn-rattle-l {
  0%, 12%, 26%, 45.333%, 59.333%, 78.667%, 92.667%, 100% { transform: none; }
  16.667%, 50%, 83.333% { transform: rotateY(1.4deg); }
  21%, 54.333%, 87.667% { transform: rotateY(-.4deg); }
}
@keyframes dn-rattle-r {
  0%, 12%, 26%, 45.333%, 59.333%, 78.667%, 92.667%, 100% { transform: none; }
  16.667%, 50%, 83.333% { transform: rotateY(-.8deg); }
  21%, 54.333%, 87.667% { transform: rotateY(.3deg); }
}
@keyframes dn-open-l   { to { transform: rotateY(80deg); filter: brightness(.55) saturate(1.15) sepia(.15); } }
@keyframes dn-open-r   { to { transform: rotateY(-80deg); filter: brightness(.55) saturate(1.15) sepia(.15); } }
@keyframes dn-glass    { to { opacity: .95; } }
@keyframes dn-ripple   { from { opacity: .9; transform: translate(-50%, -50%) scale(.3); } to { opacity: 0; transform: translate(-50%, -50%) scale(1.6); } }
@keyframes dn-room-on  { to { filter: brightness(1.05) saturate(1.08) blur(calc(var(--sw) * .0018)); } }
/* she walks out of the dim room into the warm doorway light: darker and softer far back, lit and
   sharp at the threshold, with a warm rim light from the lamps behind her */
@keyframes dn-host-walk {
  0%   { opacity: 0; transform: translateY(-46.75%) scale(.45);
         filter: brightness(.5) sepia(.25) blur(calc(var(--sw) * .0006)) drop-shadow(0 0 0 rgba(255,180,100,0)); }
  12%  { opacity: 1; }
  100% { opacity: 1; transform: none;
         filter: brightness(.98) contrast(1.04) saturate(1.02) sepia(.12) blur(0) drop-shadow(0 0 calc(var(--sw) * .003) rgba(255,186,110,.55)); }
}
@keyframes dn-wave     { from { transform: rotate(-9deg); } to { transform: rotate(9deg); } }

@keyframes dn-pop      { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@keyframes dn-pop-out {
  0% { opacity: 0; transform: scale(.4); }
  12%, 82% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(.9) translateY(-8px); }
}
@keyframes dn-conf {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0); }
  30%  { opacity: 1; transform: translate(calc(var(--dx) * .6), var(--up)) rotate(calc(var(--r) * .4)) rotateX(240deg); }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--fall)) rotate(var(--r)) rotateX(900deg); }
}
@keyframes dn-mote {
  0%   { opacity: 0; transform: translate(0, 0); }
  20%  { opacity: .9; }
  100% { opacity: 0; transform: translate(var(--mx), -18vh); }
}
@keyframes dn-logo-in  {
  from { opacity: 0; transform: translateY(-50%) scale(.94); filter: blur(14px); letter-spacing: .12em; }
  to   { opacity: 1; transform: translateY(-50%) scale(1); filter: blur(0); letter-spacing: 0; }
}
@keyframes dn-logo-out { from { opacity: 1; transform: translateY(-50%) scale(1); } to { opacity: 0; transform: translateY(-50%) scale(1.12); } }

/* local keyframe export: scene only */
.dn-clean .dn-caps, .dn-clean .dn-confetti, .dn-clean .dn-motes, .dn-clean .dn-ctrls, .dn-clean .dn-ripple { display: none; }

@media (prefers-reduced-motion: reduce) {
  .dn-intro { display: none; }
}

/* demo-only replay button */
.dn-replay {
  position: fixed; left: 16px; bottom: 16px; z-index: 50;
  font: 600 .85rem 'Inter', system-ui, sans-serif; color: #fff;
  background: linear-gradient(135deg, #7c3aed, #ec4899); border: 0;
  padding: .65rem 1.1rem; border-radius: 999px; cursor: pointer;
  box-shadow: 0 10px 30px rgba(124,58,237,.35);
}
