/* =====================================================================
   LAGNIAPPE: the stage for Sammie's show
   This page sits in an iframe over the Let It Snow pen, so it has no
   background of its own: the snow and St. Charles Avenue show through.
   ===================================================================== */

/* bubble size, animated by show.js */
@property --d { syntax: "<number>"; inherits: true; initial-value: 30; }

html, body, main { background: transparent !important; overflow: hidden; }

/* The same 16:9 set as the pen's St. Charles stage: it fills the screen like a
   movie poster and stands on the bottom edge, so Sammie lines up with the avenue. */
.viewport { position: fixed; inset: 0; display: block; container-type: normal; }
.scene,
.scene.scene {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: max(100vw, 177.78vh);
  aspect-ratio: 16 / 9;
  translate: -50% 0;
  background: transparent;
  overflow: visible;
  --fit: 1;
  --ground: 100%;
  --wu: 1cqmin;
}
.world { overflow: visible; }

/* Kristin and Sammie start off-stage, top left */
.bubble { left: -14%; top: -20%; }
.bubble.kristin { opacity: 0; transition: opacity 0.4s; }
.bubble.kristin.here { opacity: 1; }

/* once she lets him out, Kristin bobs on her own, with a little talking wiggle */
.bubble.kristin.hover { animation: kristin-bob 3.2s ease-in-out infinite alternate; }
.bubble.kristin.wiggle .bubble-front { animation: kristin-wiggle 0.5s ease-in-out 2; }
@keyframes kristin-bob { to { translate: 0 -2.5cqh; } }
@keyframes kristin-wiggle {
  25% { transform: scale(1.06, 0.95); }
  75% { transform: scale(0.96, 1.05); }
}

/* ---------- Kristin's magic: hearts and sparkles ---------- */
.magic { position: absolute; inset: 0; pointer-events: none; }
.magic i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s, 2.4cqh);
  aspect-ratio: 1;
  translate: -50% -50%;
  background: var(--c, #ff6fb5);
  clip-path: path("M12 21 C5 15 1 11 1 7 C1 3.7 3.7 1 7 1 C9 1 11 2.2 12 4 C13 2.2 15 1 17 1 C20.3 1 23 3.7 23 7 C23 11 19 15 12 21 Z");
  animation: heart-float var(--t, 2.2s) ease-out forwards;
}
.magic i.spark {
  background: #fff6c8;
  clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
}
/* clip-path path() uses px: scale the 24px heart to the element */
.magic i:not(.spark) { clip-path: none; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 22'%3E%3Cpath d='M12 21C5 15 1 11 1 7 1 3.7 3.7 1 7 1c2 0 4 1.2 5 3 1-1.8 3-3 5-3 3.3 0 6 2.7 6 6 0 4-4 8-11 14z'/%3E%3C/svg%3E") center / contain no-repeat; }
@keyframes heart-float {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.3) rotate(0deg); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1) rotate(var(--r, 20deg)); }
}

@media (prefers-reduced-motion: reduce) {
  .bubble.kristin.hover, .bubble-sheen { animation: none; }
}

/* =====================================================================
   ADDED FOR THE FIVE ACTS
   ===================================================================== */

/* ---------- the snow puff and the snow swirl (fx.js) ---------- */
.snowpuff { position: absolute; z-index: 10; width: 0; height: 0; pointer-events: none; }
.snowpuff i {
  position: absolute; left: 0; top: 0;
  width: calc(var(--s) * var(--r)); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #ffffff, #eef4fb 60%, #c9d6ea);
  box-shadow: 0 0 0 0.5cqh #fff8ea, 0.4cqh 0.6cqh 0 0.5cqh rgb(0 0 0 / 0.2);
  translate: calc(-50% + var(--dx) * var(--s)) calc(-50% + var(--dy) * var(--s));
  animation: puff-blob var(--ms) cubic-bezier(.2, 1.3, .4, 1) calc(var(--i) * 25ms) both;
}
@keyframes puff-blob { 0% { scale: 0; opacity: 0; } 25% { scale: 1.1; opacity: 1; } 60% { scale: 1; opacity: 1; } 100% { scale: 1.25; opacity: 0; } }
.snowpuff b {
  position: absolute; left: 0; top: 0; font-size: calc(var(--s) * 0.16); line-height: 1; color: #fff; font-style: normal;
  text-shadow: 0 0 0.6cqh #bfe3ff; translate: -50% -50%;
  animation: puff-flake var(--ms) ease-out calc(var(--ms) * 0.35) both;
}
@keyframes puff-flake {
  from { transform: rotate(var(--a)) translateY(0); opacity: 0; }
  20% { opacity: 1; }
  to { transform: rotate(var(--a)) translateY(calc(var(--s) * var(--d) * -1)) rotate(180deg); opacity: 0; }
}
.snowswirl { position: absolute; z-index: 10; width: 0; height: 0; pointer-events: none; }
.snowswirl b {
  position: absolute; left: 0; top: 0; color: #fff; font-style: normal; line-height: 1; font-size: calc(var(--s) * 0.07);
  text-shadow: 0 0 0.5cqh #bfe3ff;
  animation: swirl calc(var(--ms) * var(--sp)) cubic-bezier(.4, 0, .6, 1) calc(var(--i) * 18ms) both;
}
@keyframes swirl {
  0%   { transform: rotate(0deg) translateX(calc(var(--s) * 1.1)) translateY(calc(var(--h) * var(--s))); opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: rotate(900deg) translateX(calc(var(--s) * 0.15)) translateY(calc(var(--h) * var(--s) * 0.2)); opacity: 0.2; }
}

/* ---------- the song's sparkle bursts (from Trick or Jest) ---------- */
#sammie-magic-layer { position: absolute; inset: 0; z-index: 12; pointer-events: none; overflow: visible; }
.sammie-magic { position: absolute; font-family: Georgia, serif; font-size: clamp(15px, 2.6vw, 30px); line-height: 1; color: #ffe27c;
  text-shadow: 0 0 7px #ffce5a, 0 0 14px #fff2ad; opacity: 0; animation: sammie-magic-fly 850ms ease-out var(--delay, 0ms) both; }
@keyframes sammie-magic-fly { 0% { transform: translate(-50%, -50%) scale(.25) rotate(-20deg); opacity: 0; } 18% { opacity: 1; } 75% { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--mx)), calc(-50% + var(--my))) scale(1.3) rotate(45deg); opacity: 0; } }
.sammie-magic.hair { font-size: clamp(11px, 1.9vw, 22px); color: #fff6c2; animation: sammie-twinkle 900ms ease-out var(--delay, 0ms) both; }
@keyframes sammie-twinkle { 0% { transform: translate(-50%, -50%) scale(0) rotate(0); opacity: 0; } 30% { transform: translate(-50%, -50%) scale(1.25) rotate(var(--rot)); opacity: 1; }
  100% { transform: translate(calc(-50% + var(--mx)), calc(-50% + var(--my))) scale(.2) rotate(calc(var(--rot) * 2)); opacity: 0; } }
.sammie-magic.hearts { color: #ff88c9; text-shadow: 0 0 9px #f66cb7; animation: sammie-heart-rise 1500ms cubic-bezier(.3, .6, .4, 1) var(--delay, 0ms) both; }
@keyframes sammie-heart-rise { 0% { transform: translate(-50%, -50%) scale(.3); opacity: 0; } 15% { opacity: 1; }
  50% { transform: translate(calc(-50% + var(--mx) * .4 + 8px), calc(-50% + var(--my) * .5)) scale(1); }
  100% { transform: translate(calc(-50% + var(--mx)), calc(-50% + var(--my))) scale(1.15) rotate(var(--rot)); opacity: 0; } }
.sammie-magic.crown { color: #fff0a4; font-size: clamp(20px, 3.4vw, 42px); animation: sammie-fountain 1000ms cubic-bezier(.15, .7, .4, 1) var(--delay, 0ms) both; }
@keyframes sammie-fountain { 0% { transform: translate(-50%, -50%) scale(.4); opacity: 0; } 12% { opacity: 1; } 70% { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--mx)), calc(-50% + var(--my))) scale(.9) rotate(var(--rot)); opacity: 0; } }
.sammie-magic.toss { color: #f5c542; font-size: clamp(9px, 1.4vw, 16px); text-shadow: 0 0 6px #ffcf4a; animation: sammie-toss 1100ms linear var(--delay, 0ms) both; }
.sammie-magic.toss.flake { color: #ffffff; text-shadow: 0 0 6px #bfe3ff; font-size: clamp(12px, 1.8vw, 20px); }
@keyframes sammie-toss { 0% { transform: translate(-50%, -50%); opacity: 0; } 8% { opacity: 1; } 45% { transform: translate(calc(-50% + var(--mx) * .5), calc(-50% - 90px)); }
  100% { transform: translate(calc(-50% + var(--mx)), calc(-50% + var(--my))) rotate(var(--rot)); opacity: 0; } }

/* ---------- captions (his lines) and title cards (Act 2) ---------- */
.caption {
  /* up top, BEHIND Sammie and his bubble: he floats in front of the words, and you see them through her */
  position: absolute; left: 50%; top: 16cqh; translate: -50% 0; z-index: 1; max-width: 60cqw;
  padding: 1.1cqh 2.4cqh; background: #fff8ea; color: #2a1a3a; border-radius: 0.6cqh;
  font: 700 2.7cqh/1.25 Archivo, system-ui, sans-serif; text-align: center;
  box-shadow: 0.5cqh 0.7cqh 0 rgb(0 0 0 / 0.35); rotate: -1deg;
  opacity: 0; scale: 0.9; transition: opacity 0.2s, scale 0.25s cubic-bezier(.3, 1.6, .5, 1); pointer-events: none;
}
.caption.on { opacity: 1; scale: 1; }
#world { z-index: 2; }                                      /* Sammie, Kristin and the sparkles: in front of the captions */
body.nocaps .caption { display: none; }
.rulecard {
  position: absolute; left: 50%; top: 5cqh; translate: -50% 0; z-index: 14;
  padding: 1.2cqh 3cqh 1.4cqh; background: #ffd36b; color: #2a1a3a; border: 0.5cqh solid #fff8ea;
  font: 400 5cqh/1 Rye, Georgia, serif; letter-spacing: 0.02em; white-space: nowrap;
  box-shadow: 0.7cqh 1cqh 0 rgb(0 0 0 / 0.4); rotate: 2deg; transform-origin: 50% 100%;
  opacity: 0; pointer-events: none;
}
.rulecard.on { animation: rule-pop 0.7s cubic-bezier(.25, 1.6, .45, 1) both; }
@keyframes rule-pop { from { transform: perspective(60cqw) rotateX(80deg); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- dev mode: this page opened on its own ---------- */
body:not(.dev) .panel-toggle, body:not(.dev) .panel { display: none !important; }
body.dev { background: linear-gradient(#0d1530, #24315c 70%, #dfe8f5 70.5%, #f4f7fb) !important; }
.devbar {
  position: fixed; top: 0.6rem; left: 0.6rem; z-index: 40; display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center;
  max-width: calc(100% - 9rem); padding: 0.4rem; background: rgb(20 18 30 / 0.85); border-radius: 0.5rem;
}
.devbar button { padding: 0.35rem 0.6rem; font-size: 0.8rem; }
.devbar button[aria-pressed="true"] { background: #ffd36b; color: #2a1a3a; }
.devbar .pink { display: none; background: #ff8cc6; color: #3a0d24; }
.devbar[data-part="explain"] [data-dev="shush"], .devbar[data-part] [data-dev="onwith"] { display: inline-block; }
.devbar[data-part=""] .pink { display: none; }
.devclock { min-width: 7.5rem; color: #ffd36b; font: 700 0.85rem/1 ui-monospace, monospace; padding: 0 0.3rem; }

@media (prefers-reduced-motion: reduce) {
  .rulecard.on { animation: none; transform: none; opacity: 1; }
  .snowpuff i, .snowpuff b, .snowswirl b { animation-duration: 1ms; }
}

/* ===== the gown (from Trick or Jest's street.css): its tulle skirt and sparkles ===== */
.sugar-spark { transform-box: fill-box; transform-origin: center; animation: sugarspark 1.8s ease-in-out infinite; }
@keyframes sugarspark { 0%, 100% { opacity: 0.15; scale: 0.4; } 45% { opacity: 1; scale: 1.15; } }
#rig .tutu { transform-box: fill-box; transform-origin: 50% 0; transition: transform 0.5s cubic-bezier(.3,1.8,.5,1); }
#rig.in-bubble .tutu { transform: scale(0.82, 0.9); }                     /* squished against the inside of the bubble */
#rig.poof .tutu { animation: poof 0.7s cubic-bezier(.2,1.6,.4,1); }      /* poof! when he lands */
@keyframes poof { 0% { transform: scale(0.82, 0.9); } 40% { transform: scale(1.18, 1.06); } 100% { transform: none; } }
#rig .tutu .sugar-spark { animation-name: sugarfade; }
@keyframes sugarfade { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sugar-spark, #rig .tutu { animation: none !important; } }

/* ===== his Christmas lights (sammie/christmas.js): the bulbs blink in two sets, back and forth ===== */
#rig .xl-bulb { animation: xl-blink var(--blink, 0.95s) steps(1) infinite; }
#rig .xl-bulb.b1 { animation-delay: calc(var(--blink, 0.95s) / -2); }
@keyframes xl-blink { 0% { opacity: 1; filter: drop-shadow(0 0 4px currentColor) brightness(1.15); } 50% { opacity: 0.35; filter: none; } }
@media (prefers-reduced-motion: reduce) { #rig .xl-bulb { animation: none; } }

/* Kristin becomes the shield (Act 3): she flattens out over the buttons and fades into the pen's pink glass */
.bubble.kristin.spread { transition: transform 0.6s ease-in, opacity 0.6s ease-in !important; transform: translate(-50%, -50%) scale(4, 0.3); opacity: 0; }

/* layers, back to front: the spotlight's darkness, then the captions, then Sammie and Kristin.
   So the captions and Sammie stay bright while everything else (the pen too) goes dark around him. */
#spotlight { z-index: 0 !important; }

/* =====================================================================
   KRISTIN'S BUBBLE: A REAL SOAP BUBBLE WITH A PERSONALITY (v3.4)
   The same look serves both of her: the bubble carrying Sammie in Act 1
   and Kristin on her own. Everything here moves with transforms and
   opacity only, so it stays light on a heavy page.
   ===================================================================== */

/* swirling soap film: a second wash of color, off-center and turning the other
   way from the rim sheen, so the colors marble instead of spinning as one ring */
.bubble-back::after {
  content: ""; position: absolute; inset: -18%; border-radius: 50%;
  background: conic-gradient(from 30deg at 40% 60%,
    rgb(120 215 255 / 0), rgb(120 215 255 / 0.42) 10%, rgb(255 150 220 / 0) 24%,
    rgb(255 228 140 / 0.36) 40%, rgb(255 120 200 / 0) 56%,
    rgb(185 140 255 / 0.4) 74%, rgb(120 215 255 / 0) 90%);
  -webkit-mask: radial-gradient(circle, transparent 50%, #000 68%);
          mask: radial-gradient(circle, transparent 50%, #000 68%);
  mix-blend-mode: screen;
  animation: film-swirl 13s linear infinite reverse;
}
@keyframes film-swirl { to { transform: rotate(360deg); } }

/* her blush: a deeper pink that floods in and fades (JS adds .blush) */
.bubble-back::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; opacity: 0;
  background: radial-gradient(circle at 50% 58%, rgb(255 110 185 / 0.18) 30%, rgb(255 80 165 / 0.5) 86%, rgb(255 170 215 / 0.7) 100%);
}
.bubble.blush .bubble-back::before { animation: blush 1.9s ease-out; }
@keyframes blush { 0% { opacity: 0; } 22% { opacity: 1; } 60% { opacity: 0.8; } 100% { opacity: 0; } }

/* the window: real bubbles reflect a bright window pane, top left, curved to the surface.
   It slides a little as she wobbles, which is what sells the roundness. */
.bubble-front::before {
  content: ""; position: absolute; left: 17%; top: 13%; width: 27%; height: 21%;
  border-radius: 46% 38% 30% 42%;
  background:
    linear-gradient(90deg, transparent 47%, rgb(255 255 255 / 0) 47%, rgb(255 240 250 / 0.35) 50%, transparent 53%),
    linear-gradient(0deg, transparent 47%, rgb(255 240 250 / 0.3) 50%, transparent 53%),
    linear-gradient(160deg, rgb(255 255 255 / 0.62), rgb(255 255 255 / 0.12) 70%, transparent);
  -webkit-mask: radial-gradient(ellipse 70% 70% at 50% 50%, #000 55%, transparent 100%);
          mask: radial-gradient(ellipse 70% 70% at 50% 50%, #000 55%, transparent 100%);
  rotate: -24deg;
  animation: window-slide 5.3s ease-in-out infinite alternate;
}
@keyframes window-slide { to { translate: 3% 4%; scale: 0.94 1.04; } }

/* gravity: the film drains down, so the bottom of a bubble runs thicker and brighter */
.bubble-front::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background:
    radial-gradient(ellipse 62% 30% at 50% 99%, rgb(255 120 195 / 0.3), transparent 70%),
    radial-gradient(circle at 50% 50%, transparent 86%, rgb(150 215 255 / 0.28) 91%, rgb(255 236 150 / 0.22) 94%, transparent 97%);
  -webkit-mask: linear-gradient(to bottom, transparent 35%, #000 85%);
          mask: linear-gradient(to bottom, transparent 35%, #000 85%);
}

/* breathing: a soap bubble is never a perfect circle for long. A slow, uneven jelly. */
.bubble.kristin.here,
#bubble.in-skin { animation: jelly 3.7s ease-in-out infinite; }
.bubble.kristin.here.hover { animation: kristin-bob 3.2s ease-in-out infinite alternate, jelly 3.7s ease-in-out infinite; }
@keyframes jelly {
  0%, 100% { scale: 1 1; }
  28% { scale: 1.022 0.979; }
  52% { scale: 0.986 1.016; }
  77% { scale: 1.009 0.992; }
}
.bubble.kristin.spread { animation: none; }

/* her baby bubbles: little ones she lets go when she's happy. They drift up, wobble and pop. */
.magic i.bub {
  width: var(--s, 1.6cqh);
  background: radial-gradient(circle at 32% 30%, rgb(255 255 255 / 0.9) 0 12%, transparent 22%),
              radial-gradient(circle, rgb(255 200 230 / 0.08) 55%, rgb(255 150 210 / 0.5) 85%, rgb(190 225 255 / 0.65) 100%);
  border-radius: 50%; mask: none; clip-path: none;
  animation: bub-rise var(--t, 2.6s) ease-out forwards;
}
@keyframes bub-rise {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.2); }
  12%  { opacity: 1; transform: translate(calc(var(--dx) * 0.1), calc(var(--dy) * 0.1)) scale(1); }
  50%  { transform: translate(calc(var(--dx) * 0.6), calc(var(--dy) * 0.5)) scale(1.05, 0.95); }
  88%  { opacity: 1; transform: translate(var(--dx), var(--dy)) scale(1); }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1.7); }
}

@media (prefers-reduced-motion: reduce) {
  .bubble-back::after, .bubble-front::before, .bubble.kristin.here, #bubble.in-skin { animation: none; }
}

/* while the pen's program marquee is up (it sits top right), his captions move over to the left;
   on a tall phone screen the marquee sits up top, so they drop below it */
body.program-up .caption { left: 31%; max-width: 46cqw; }
@media (max-aspect-ratio: 1 / 1) {
  body.program-up .caption { left: 50%; top: 50vh; max-width: 86vw; }
}

/* ---------- Act 2: the glamorous St. Charles lady and her poodle ----------
   She slides in at the far left as a backlit silhouette (a pink glow, no face: is that HER?),
   turns into the light on "False alarm", the poodle says its piece, and she slides off. */
.lady {
  position: absolute; left: 12%; top: 91%; width: 15cqh; aspect-ratio: 170 / 240;
  translate: -50% -100%; z-index: 1; pointer-events: none;
  opacity: 0; transform: translateX(-40cqw);
  transition: transform 1.4s cubic-bezier(.2, .8, .3, 1), opacity 0.4s;
}
.lady svg { width: 100%; height: 100%; overflow: visible; filter: brightness(0.12) drop-shadow(0 0 0.6cqh #ff8cc6) drop-shadow(0 0 1.4cqh rgb(255 140 198 / 0.7)); transition: filter 0.5s; }
.lady.in { opacity: 1; transform: none; }
.lady.lit svg { filter: drop-shadow(0.4cqh 0.6cqh 0 rgb(0 0 0 / 0.3)); animation: lady-turn 0.5s ease-in-out; }
.lady.out { transform: translateX(-40cqw); transition-duration: 1.6s; transition-timing-function: ease-in; }
@keyframes lady-turn { 50% { transform: scaleX(0.05); } }
.yip {
  position: absolute; left: 92%; top: 62%; padding: 0.5cqh 1cqh; border-radius: 1cqh;
  background: #fff8ea; color: #2a1a3a; font: 700 1.9cqh/1 Archivo, system-ui, sans-serif;
  box-shadow: 0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.3); opacity: 0; scale: 0.6; transition: opacity 0.2s, scale 0.25s cubic-bezier(.3, 1.6, .5, 1);
}
.yip.on { opacity: 1; scale: 1; }

/* ---------- Act 2: the drift that buries St. Charles Avenue ----------
   --drift 0..1: it rises from the bottom up past the rooftops (only chimney smoke peeks out),
   behind Sammie and in front of the pen's scene. A lumpy top, soft blue shadows. */
.drift {
  --drift: 0;
  position: absolute; left: -5%; right: -5%; bottom: 0; z-index: 1; pointer-events: none;
  height: calc(var(--drift) * 82cqh);
  transition: height 5s cubic-bezier(.35, .1, .3, 1);
  background:
    radial-gradient(ellipse 14% 3.2cqh at 8% 0, #fff 96%, transparent 100%),
    radial-gradient(ellipse 18% 4.4cqh at 30% 0.6cqh, #fff 96%, transparent 100%),
    radial-gradient(ellipse 15% 3.6cqh at 52% 0, #fff 96%, transparent 100%),
    radial-gradient(ellipse 20% 4.8cqh at 74% 0.8cqh, #fff 96%, transparent 100%),
    radial-gradient(ellipse 14% 3.4cqh at 94% 0, #fff 96%, transparent 100%),
    linear-gradient(#fff 2cqh, #eef4ff 30%, #dbe6f7 100%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  filter: drop-shadow(0 -0.6cqh 1cqh rgb(160 185 225 / 0.6));
  overflow: visible;
}
.drift::before {                                   /* the lumpy top, sitting above the edge */
  content: ""; position: absolute; left: 0; right: 0; top: -3.5cqh; height: 4cqh;
  opacity: min(1, calc(var(--drift) * 6));
  background:
    radial-gradient(ellipse 9% 100% at 6% 100%, #fff 98%, transparent 100%),
    radial-gradient(ellipse 12% 80% at 22% 100%, #fff 98%, transparent 100%),
    radial-gradient(ellipse 10% 100% at 40% 100%, #fff 98%, transparent 100%),
    radial-gradient(ellipse 13% 70% at 58% 100%, #fff 98%, transparent 100%),
    radial-gradient(ellipse 9% 100% at 76% 100%, #fff 98%, transparent 100%),
    radial-gradient(ellipse 12% 85% at 93% 100%, #fff 98%, transparent 100%);
}

/* =====================================================================
   SHOW BITS (v3.11): the effects that land on a line
   ===================================================================== */
.showbits { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.showbits > .out { opacity: 0 !important; transition: opacity 0.5s; }

/* the dice: pink, tumbling in from the left, landing on whatever they land on */
.die {
  position: absolute; width: 7cqh; aspect-ratio: 1; translate: -50% -100%;
  animation: die-roll 1.2s cubic-bezier(.25, .8, .35, 1) both;
}
.die-face {
  width: 100%; height: 100%; display: grid; grid-template-columns: repeat(3, 1fr); padding: 0.9cqh; gap: 0.4cqh;
  background: linear-gradient(145deg, #ffd0ea, #ff8cc6); border-radius: 1.4cqh;
  box-shadow: inset -0.5cqh -0.6cqh 0 rgb(200 40 120 / 0.35), 0.4cqh 0.6cqh 0 rgb(0 0 0 / 0.3);
}
.die-face i { border-radius: 50%; }
.die-face i.on { background: #fff; box-shadow: inset 0.2cqh 0.25cqh 0 rgb(150 20 90 / 0.4); }
@keyframes die-roll {
  0%   { transform: translate(var(--from), -24cqh) rotate(0deg); }
  55%  { transform: translate(0, -3cqh) rotate(calc(var(--spin) * .85)); }
  75%  { transform: translate(0, -1.2cqh) rotate(calc(var(--spin) * .97)); }
  100% { transform: translate(0, 0) rotate(var(--spin)); }
}

/* the ghost: he fades almost away, then pops back */
#bubble { transition: opacity 0.6s, filter 0.6s; }
#bubble.ghosted { opacity: 0.16; filter: grayscale(1) blur(0.15cqh); }

/* the gift bow on his head */
.gift-bow { position: absolute; width: 9cqh; translate: -50% -70%; animation: bow-pop 0.5s cubic-bezier(.3, 1.8, .5, 1); transition: left 0.12s linear, top 0.12s linear; }
.gift-bow svg { width: 100%; display: block; filter: drop-shadow(0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.3)); }
@keyframes bow-pop { from { scale: 0; rotate: -30deg; } }

/* the top of the St. Charles Ave sign, poking out of the drift */
.drift-sign {
  position: absolute; left: 44%; top: -6.5cqh; z-index: 1;
  padding: 0.7cqh 1.4cqh; background: #1f6b3a; color: #fff; border: 0.35cqh solid #fff; border-radius: 0.6cqh;
  font: 700 2.1cqh/1 "DM Sans", system-ui, sans-serif; letter-spacing: 0.04em; white-space: nowrap;
  box-shadow: 0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.25); rotate: -6deg;
  translate: 0 4cqh; opacity: 0; transition: translate 0.5s cubic-bezier(.3, 1.6, .5, 1), opacity 0.3s;
}
.drift-sign::after { content: ""; position: absolute; left: 50%; top: 100%; width: 0.8cqh; height: 3cqh; translate: -50% 0; background: #8a8f99; }
.drift-sign.on { translate: 0 0; opacity: 1; }

/* the listening limit: a progress bar at the top, about 2% full */
.limit-meter {
  position: absolute; left: 50%; top: 3cqh; translate: -50% -150%; z-index: 4; display: flex; align-items: center; gap: 1.2cqh;
  padding: 0.9cqh 1.6cqh; background: #fff8ea; color: #2a1a3a; border-radius: 99px; box-shadow: 0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.3);
  font: 700 1.8cqh/1 "DM Sans", system-ui, sans-serif; opacity: 0; transition: translate 0.4s cubic-bezier(.3, 1.4, .5, 1), opacity 0.3s;
}
.limit-meter span { display: block; width: 26cqh; height: 1.3cqh; border-radius: 99px; background: #e9dcd0; overflow: hidden; }
.limit-meter i { display: block; width: 0; height: 100%; background: #ff4f9a; transition: width 2.4s ease-out 0.4s; }
.limit-meter em { font-style: normal; color: #c2185b; }
.limit-meter.on { translate: -50% 0; opacity: 1; }
.limit-meter.on i { width: 2%; }

/* the trophies: his is bigger */
.trophy { position: absolute; width: 6cqh; translate: -50% -100%; animation: bow-pop 0.45s cubic-bezier(.3, 1.8, .5, 1); }
.trophy.big { width: 15cqh; }
.trophy svg { width: 100%; display: block; filter: drop-shadow(0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.3)); }

/* the resume, as a paper airplane */
.paper-plane { position: absolute; width: 7cqh; animation: plane-fly 3s ease-in forwards; }
.paper-plane svg { width: 100%; display: block; }
@keyframes plane-fly {
  0%   { transform: translate(0, 0) rotate(-8deg) scale(0.6); opacity: 0; }
  10%  { opacity: 1; }
  100% { transform: translate(70cqw, -30cqh) rotate(-18deg) scale(0.4); opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) { .die, .gift-bow, .paper-plane, .trophy { animation: none; } }

/* Act 1's flight moves the bubble with transforms only (no left/top), so nothing re-lays out mid-flight */
#bubble.flying { left: 0 !important; top: 0 !important; will-change: transform; }

/* =====================================================================
   ACT 3: CHENOWETH (v4.1)
   ===================================================================== */
/* the kittens' window: a warm lit window with a wooden frame and panes, red curtains tied back,
   a wreath on top and snow on the sill with a candle. Two Christmas kittens pop up from below the sill. */
.cat-window {
  position: absolute; width: 14cqh; height: 15cqh; translate: -50% -50%;
  animation: bow-pop 0.45s cubic-bezier(.3, 1.6, .5, 1); transition: opacity 0.6s;
}
.cat-window.out { opacity: 0; }
.cw-glass {
  position: absolute; inset: 1.6cqh 0.8cqh 1.4cqh; overflow: hidden; border-radius: 6cqh 6cqh 0.4cqh 0.4cqh;
  border: 0.8cqh solid #f3e2b0; box-shadow: inset 0 0 0 0.25cqh #b88a4a, 0 0 2.6cqh rgb(255 200 120 / 0.65);
  background:
    linear-gradient(90deg, transparent calc(50% - 0.25cqh), #f3e2b0 calc(50% - 0.25cqh) calc(50% + 0.25cqh), transparent 0),
    linear-gradient(0deg, transparent calc(55% - 0.25cqh), #f3e2b0 calc(55% - 0.25cqh) calc(55% + 0.25cqh), transparent 0),
    radial-gradient(ellipse at 50% 70%, #ffd38a, #e89a4a 45%, #8a4a2a 100%);
}
.cw-kit { position: absolute; bottom: -1cqh; width: 7cqh; transition: translate 0.45s cubic-bezier(.3, 1.7, .5, 1); translate: 0 110%; }
.cw-kit svg { width: 100%; display: block; }
.cw-kit1 { left: 4%; }
.cw-kit2 { right: 4%; width: 6.2cqh; transition-delay: 0.05s; }
.cat-window.k1 .cw-kit1, .cat-window.k2 .cw-kit2 { translate: 0 8%; }
.cw-kit .kit-eyes { animation: kit-blink 3.4s steps(1) infinite; transform-box: fill-box; transform-origin: center; }
.cw-kit2 .kit-eyes { animation-delay: -1.3s; }
@keyframes kit-blink { 0%, 93% { scale: 1 1; } 94%, 97% { scale: 1 0.12; } }
.cat-window.k2 .cw-kit1 { animation: kit-tilt 1.6s ease-in-out infinite alternate; }
@keyframes kit-tilt { to { rotate: -8deg; } }
.cw-curtain { position: absolute; top: 1.2cqh; width: 3.4cqh; height: 10cqh; background: linear-gradient(90deg, #a8131d, #d8232f 50%, #a8131d); }
.cw-left  { left: 0;  border-radius: 0 0 100% 0; clip-path: polygon(0 0, 100% 0, 30% 60%, 60% 100%, 0 100%); }
.cw-right { right: 0; border-radius: 0 0 0 100%; clip-path: polygon(0 0, 100% 0, 100% 100%, 40% 100%, 70% 60%); }
.cw-sill {
  position: absolute; left: -0.6cqh; right: -0.6cqh; bottom: 0; height: 1.8cqh; border-radius: 0.4cqh;
  background: linear-gradient(#fff 0 45%, #d8c49a 45%);
  box-shadow: 0 0.3cqh 0.4cqh rgb(0 0 0 / 0.3);
}
.cw-candle { position: absolute; left: 44%; bottom: 1.3cqh; width: 0.9cqh; height: 2.2cqh; background: #fff8e8; border-radius: 0.2cqh; }
.cw-candle::after { content: ""; position: absolute; left: 50%; bottom: 100%; width: 0.7cqh; height: 1.2cqh; translate: -50% 0; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; background: #ffd23f; box-shadow: 0 0 1.2cqh #ffb02e; animation: candle 0.7s ease-in-out infinite alternate; }
@keyframes candle { to { scale: 0.85 1.1; } }
.cw-wreath {
  position: absolute; left: 50%; top: -1.6cqh; width: 4.2cqh; height: 4.2cqh; translate: -50% 0; z-index: 2; border-radius: 50%;
  background: radial-gradient(circle, transparent 38%, #2a6b3a 40% 66%, transparent 68%),
              radial-gradient(circle at 50% 88%, #d8232f 0 14%, transparent 15%);
  filter: drop-shadow(0 0.2cqh 0.2cqh rgb(0 0 0 / 0.35));
}

/* the dream bubble: matching gowns */
.dream { position: absolute; width: 19cqh; translate: -50% -100%; animation: bow-pop 0.5s cubic-bezier(.3, 1.6, .5, 1); }
.dream svg { width: 100%; display: block; filter: drop-shadow(0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.25)); }
.dream i { position: absolute; border-radius: 50%; background: #fff8ea; border: 0.3cqh solid #ffb3d9; }
.dream .d1 { width: 2.4cqh; height: 2.4cqh; left: 6%; bottom: -14%; }
.dream .d2 { width: 1.4cqh; height: 1.4cqh; left: 0; bottom: -30%; }

/* ON AIR */
.on-air {
  position: absolute; translate: -50% -100%; padding: 0.5cqh 1.2cqh; border-radius: 0.6cqh;
  background: #d8232f; color: #fff; font: 800 2cqh/1 "DM Sans", system-ui, sans-serif; letter-spacing: 0.12em;
  box-shadow: 0 0 1.4cqh rgb(255 60 70 / 0.9), 0.3cqh 0.4cqh 0 rgb(0 0 0 / 0.3);
  animation: bow-pop 0.4s cubic-bezier(.3, 1.6, .5, 1), on-air 0.8s steps(1) infinite 0.4s;
}
@keyframes on-air { 50% { background: #8a1018; box-shadow: none; } }

/* knock, knock, knock */
.knock { position: absolute; font: italic 700 2cqh/1 Georgia, serif; color: #fff; text-shadow: 0 0.2cqh 0.4cqh rgb(0 0 0 / 0.6); animation: knock-pop 0.6s ease-out forwards; }
@keyframes knock-pop { from { opacity: 0; scale: 0.5; } 30% { opacity: 1; scale: 1.15; } to { opacity: 0; translate: 0 -2cqh; } }

/* the light upstairs: on... and off */
.upstairs {
  position: absolute; width: 3.4cqh; height: 4.4cqh; translate: -50% -50%; border-radius: 0.5cqh;
  background: #ffe9a6; box-shadow: 0 0 3cqh 1cqh rgb(255 220 140 / 0.85);
  animation: bow-pop 0.18s ease-out; transition: opacity 0.25s;
}
.upstairs.off { opacity: 0; }

/* the bow, flying from his hat to her doorstep */
.door-bow { position: absolute; width: 5.5cqh; translate: -50% -100%; }
.door-bow svg { width: 100%; display: block; filter: drop-shadow(0.2cqh 0.3cqh 0 rgb(0 0 0 / 0.3)); }
.door-bow.fly { transition: left 1.4s cubic-bezier(.3, 0, .5, 1), top 1.4s cubic-bezier(.2, -0.8, .6, 1); }

/* against the moon: a silhouette, like a Christmas card */
#bubble.silhouette { filter: brightness(0.08) saturate(0) drop-shadow(0 0 1.2cqh rgb(255 240 200 / 0.7)); transition: filter 1.4s; }

/* THE END, in marquee bulbs */
.the-end {
  position: absolute; left: 50%; top: 46%; translate: -50% -50%; z-index: 6;
  padding: 2.4cqh 5cqh; border-radius: 1.6cqh; border: 1.2cqh solid #e7b53a;
  background: radial-gradient(ellipse at 50% 20%, #c62a35, #7d1520 80%);
  box-shadow: 0 0 0 0.5cqh #fbf3e2, 0 0 5cqh rgb(255 215 130 / 0.7);
  animation: end-in 0.9s cubic-bezier(.3, 1.5, .5, 1) both;
}
.the-end span { font: 400 9cqh/1 Rye, Georgia, serif; color: #fff3d6; letter-spacing: 0.04em; text-shadow: 0 0.4cqh 0 #4a0910, 0 0 2cqh rgb(255 220 150 / 0.7); white-space: nowrap; }
.the-end::before {
  content: ""; position: absolute; inset: -1.25cqh; border-radius: 2cqh; pointer-events: none;
  background:
    radial-gradient(circle, #ff4b4b 0 0.55cqh, transparent 0.75cqh) 0 0 / 6cqh 3cqh,
    radial-gradient(circle, #45e07e 0 0.55cqh, transparent 0.75cqh) 2cqh 0 / 6cqh 3cqh,
    radial-gradient(circle, #fff3b0 0 0.55cqh, transparent 0.75cqh) 4cqh 0 / 6cqh 3cqh;
  -webkit-mask: linear-gradient(#000 0 0) top / 100% 1.5cqh no-repeat, linear-gradient(#000 0 0) bottom / 100% 1.5cqh no-repeat;
          mask: linear-gradient(#000 0 0) top / 100% 1.5cqh no-repeat, linear-gradient(#000 0 0) bottom / 100% 1.5cqh no-repeat;
  animation: end-chase 0.6s steps(3) infinite;
}
@keyframes end-chase { to { background-position: 6cqh 0, 8cqh 0, 10cqh 0; } }
@keyframes end-in { from { opacity: 0; scale: 0.4; rotate: -6deg; } }

/* "Opening night of Wicked. Two thousand three." an old theater ticket, stamped on "the lobby" */
.ticket {
  position: absolute; left: 50%; top: 34%; translate: -50% -50%; rotate: -4deg; z-index: 5;
  display: grid; justify-items: center; gap: 0.5cqh; padding: 1.8cqh 4.4cqh 1.6cqh;
  background: radial-gradient(circle at 0 50%, transparent 1.4cqh, #fbf1d8 1.5cqh) left / 51% 100% no-repeat,
              radial-gradient(circle at 100% 50%, transparent 1.4cqh, #fbf1d8 1.5cqh) right / 51% 100% no-repeat;
  filter: drop-shadow(0.4cqh 0.6cqh 0 rgb(0 0 0 / 0.3));
  color: #7d1520; font-family: Rye, Georgia, serif; text-align: center;
  animation: end-in 0.7s cubic-bezier(.3, 1.5, .5, 1) both; transition: opacity 0.6s, translate 0.6s;
}
.ticket::before { content: ""; position: absolute; inset: 0.8cqh 2.4cqh; border: 0.25cqh dashed #c9a35a; border-radius: 0.6cqh; pointer-events: none; }
.ticket b { font: 400 3.6cqh/1 Rye, Georgia, serif; letter-spacing: 0.04em; }
.ticket span { font: 700 4.4cqh/1 Georgia, serif; color: #1f5a34; letter-spacing: 0.2em; }
.ticket small { font: italic 600 1.7cqh/1 Georgia, serif; color: #6b4a2a; letter-spacing: 0.06em; }
.ticket em {                                                    /* the stamp, waiting for "the lobby" */
  position: absolute; right: -2cqh; bottom: -1.2cqh; padding: 0.4cqh 1cqh; border: 0.35cqh solid #d8232f; border-radius: 0.5cqh;
  font: normal 800 2cqh/1 "DM Sans", system-ui, sans-serif; color: #d8232f; letter-spacing: 0.08em; text-transform: uppercase;
  background: rgb(255 255 255 / 0.55); rotate: -12deg; opacity: 0; scale: 2.4;
  transition: opacity 0.12s, scale 0.22s cubic-bezier(.5, 0, .7, 1.4);
}
.ticket.lobby em { opacity: 1; scale: 1; }
.ticket.out { opacity: 0; translate: -50% -80%; }

/* "Tonight. Sammie and Chenoweth." their names in lights */
.names-marquee {
  position: absolute; left: 50%; top: 33%; translate: -50% -50%; z-index: 5;
  display: grid; justify-items: center; gap: 0.6cqh; padding: 1.8cqh 4cqh 1.5cqh; border-radius: 1.2cqh; border: 0.9cqh solid #e7b53a;
  background: radial-gradient(ellipse at 50% 20%, #c62a35, #7d1520 80%);
  box-shadow: 0 0 0 0.4cqh #fbf3e2, 0 0 4cqh rgb(255 215 130 / 0.7);
  animation: end-in 0.8s cubic-bezier(.3, 1.5, .5, 1) both, names-out 0.6s ease-in 4s forwards;
}
.names-marquee span { font: 400 5cqh/1 Rye, Georgia, serif; color: #fff3d6; white-space: nowrap; text-shadow: 0 0.3cqh 0 #4a0910, 0 0 1.6cqh rgb(255 220 150 / 0.75); }
.names-marquee span i { font-style: normal; color: #ffb3dc; }
.names-marquee small { font: italic 600 1.9cqh/1 Georgia, serif; color: #ffe27c; letter-spacing: 0.1em; }
.names-marquee::before {
  content: ""; position: absolute; inset: -1cqh; border-radius: 1.5cqh; pointer-events: none;
  background:
    radial-gradient(circle, #fff3b0 0 0.45cqh, transparent 0.65cqh) 0 0 / 3cqh 3cqh,
    radial-gradient(circle, #ffb3dc 0 0.45cqh, transparent 0.65cqh) 1.5cqh 0 / 3cqh 3cqh;
  -webkit-mask: linear-gradient(#000 0 0) top / 100% 1.2cqh no-repeat, linear-gradient(#000 0 0) bottom / 100% 1.2cqh no-repeat;
          mask: linear-gradient(#000 0 0) top / 100% 1.2cqh no-repeat, linear-gradient(#000 0 0) bottom / 100% 1.2cqh no-repeat;
  animation: names-chase 0.5s steps(2) infinite;
}
@keyframes names-chase { to { background-position: 3cqh 0, 4.5cqh 0; } }
@keyframes names-out { to { opacity: 0; scale: 0.8; } }

/* "It has random snow." a puff of flakes off the bubble */
.snow-puff { position: absolute; width: 0; height: 0; z-index: 4; }
.snow-puff i {
  position: absolute; width: 1.1cqh; height: 1.1cqh; margin: -0.55cqh; border-radius: 50%; scale: var(--s);
  background: radial-gradient(circle, #fff 45%, rgb(255 255 255 / 0)); opacity: 0;
  animation: snow-puff 2s cubic-bezier(.2, .7, .4, 1) forwards;
}
@keyframes snow-puff {
  0% { translate: 0 0; opacity: 0; } 10% { opacity: 1; }
  45% { translate: var(--dx) var(--dy); opacity: 1; }
  100% { translate: var(--dx) calc(var(--dy) + 9cqh); opacity: 0; }
}

/* BLACK TIE (v4.5): THE END and the names in lights wear the tux too (see the pen's stage.css) */
.the-end, .names-marquee {
  border-color: transparent;
  background:
    linear-gradient(115deg, transparent 30%, rgb(255 255 255 / 0.07) 42%, transparent 54%) padding-box,
    radial-gradient(ellipse at 50% 30%, #23222b, #0a0a0e 75%) padding-box,
    linear-gradient(145deg, #f8e6a6, #d2a54a 22%, #8a6420 48%, #e9c76a 68%, #a8792a 88%, #f1d68a) border-box;
  box-shadow: inset 0 0 0 0.25cqh #0a0a0e, inset 0 0 0 0.45cqh rgb(231 190 100 / 0.75),
              0 2cqh 4cqh -1cqh rgb(0 0 0 / 0.7), 0 0 5cqh rgb(255 205 120 / 0.4);
}
.the-end span, .names-marquee span {
  font-family: Limelight, "Bodoni 72", Didot, Georgia, serif;
  background: linear-gradient(180deg, #fff3c8 0%, #f0cf73 42%, #b8862a 58%, #f6dc92 100%); -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: none; filter: drop-shadow(0 0.25cqh 0 #2a1d05) drop-shadow(0 0 1.2cqh rgb(255 210 120 / 0.4));
}
.names-marquee span i { color: #ff8cc6; -webkit-text-fill-color: #ff8cc6; }
.names-marquee small { color: #f4ead2; }
.the-end::before {
  background:
    radial-gradient(circle, #fff4d6 0 0.55cqh, #8a6420 0.6cqh 0.75cqh, transparent 0.85cqh) 0 0 / 6cqh 3cqh,
    radial-gradient(circle, #fff4d6 0 0.55cqh, #8a6420 0.6cqh 0.75cqh, transparent 0.85cqh) 2cqh 0 / 6cqh 3cqh,
    radial-gradient(circle, #ff4b5a 0 0.55cqh, #8a6420 0.6cqh 0.75cqh, transparent 0.85cqh) 4cqh 0 / 6cqh 3cqh;
}
.names-marquee::before {
  background:
    radial-gradient(circle, #fff4d6 0 0.45cqh, #8a6420 0.5cqh 0.62cqh, transparent 0.7cqh) 0 0 / 3cqh 3cqh,
    radial-gradient(circle, #ff4b5a 0 0.45cqh, #8a6420 0.5cqh 0.62cqh, transparent 0.7cqh) 1.5cqh 0 / 6cqh 3cqh;
}
.the-end::after {                                     /* his bow tie */
  content: ""; position: absolute; left: 50%; top: 0; width: 7cqh; height: 3.5cqh; translate: -50% -60%;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 32'%3E %3Cpath d='M29 16 L5 3 Q1 1.5 1.5 6.5 L3.5 16 L1.5 25.5 Q1 30.5 5 29 Z' fill='%23c8102e' stroke='%235a0612' stroke-width='1.6' stroke-linejoin='round'/%3E %3Cpath d='M35 16 L59 3 Q63 1.5 62.5 6.5 L60.5 16 L62.5 25.5 Q63 30.5 59 29 Z' fill='%23c8102e' stroke='%235a0612' stroke-width='1.6' stroke-linejoin='round'/%3E %3Cpath d='M26 14 L8 6 Q6 6 6.5 9 L8 15 Z M38 14 L56 6 Q58 6 57.5 9 L56 15 Z' fill='%23ff6b7d' opacity='.55'/%3E %3Cpath d='M24 19 L10 25 M40 19 L54 25' stroke='%238a0a1e' stroke-width='1.4' stroke-linecap='round' opacity='.7'/%3E %3Crect x='26' y='9' width='12' height='14' rx='3.5' fill='%23a50d25' stroke='%235a0612' stroke-width='1.6'/%3E %3Crect x='28.5' y='11' width='4' height='5' rx='1.5' fill='%23ff8a98' opacity='.6'/%3E%3C/svg%3E") center / contain no-repeat; filter: drop-shadow(0 0.3cqh 0.4cqh rgb(0 0 0 / 0.5));
}
