:root {
  --stage-unit: 1svh;
  --stage-height: 100svh;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --night: #0b0d20;
  --night-soft: #15162d;
  --cream: #fff8ec;
  --muted: #cfccda;
  --pink: #f472a1;
  --pink-deep: #d9477b;
  --gold: #f4ce83;
  --ink: #583445;
  --note-ink: #ffeef4;
  --journey: 0;
  --warmth: 0;
  --ambient-x: 0vw;
  --ambient-y: calc(var(--stage-unit) * 0);
  --ambient-warm-x: 0vw;
  --ambient-warm-y: calc(var(--stage-unit) * 0);
  --ambient-cool-scale: 1;
  --ambient-warm-scale: 0.96;
  --ambient-cool-opacity: 0.82;
  --ambient-warm-opacity: 0.22;
  --star-y: calc(var(--stage-unit) * 0);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* A keyframe's timing function governs the segment that FOLLOWS it, so a
     strong ease-out on every stop makes a multi-pose reveal stutter. These two
     lead out of the first pose and land on the last; the middle runs linear. */
  --ease-lead: cubic-bezier(0.42, 0, 0.58, 1);
  --ease-settle: cubic-bezier(0.28, 0.62, 0.24, 1);
  --ease-weight: cubic-bezier(0.65, 0, 0.35, 1);
}

* {
  box-sizing: border-box;
}

html {
  overflow-x: hidden;
  overflow-x: clip;
  background: var(--night);
}

body {
  min-width: 20rem;
  min-height: calc(var(--stage-unit) * 100);
  margin: 0;
  overflow-x: hidden;
  overflow-x: clip;
  color: var(--cream);
  background: var(--night);
  font-family: "Nunito", system-ui, sans-serif;
  line-height: 1.65;
}

body.success-open {
  overflow: hidden;
}

button,
a {
  font: inherit;
}

button {
  -webkit-tap-highlight-color: transparent;
}

.ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    linear-gradient(180deg, #090b1c 0%, #11132b 53%, #171020 100%);
}

.ambient::after {
  position: absolute;
  inset: 0;
  content: "";
  background: linear-gradient(180deg, rgba(7, 9, 24, 0.04), rgba(29, 12, 29, 0.28));
  opacity: var(--warmth);
}

.ambient__wash {
  position: absolute;
  width: 90vmax;
  height: 90vmax;
  border-radius: 50%;
  will-change: transform, opacity;
}

.ambient__wash--cool {
  top: -50vmax;
  left: -38vmax;
  background: radial-gradient(circle, rgba(99, 82, 168, 0.29) 0%, rgba(73, 62, 137, 0.12) 34%, transparent 68%);
  opacity: var(--ambient-cool-opacity);
  transform:
    translate3d(
      var(--ambient-x),
      var(--ambient-y),
      0
    )
    scale(var(--ambient-cool-scale));
}

.ambient__wash--warm {
  right: -48vmax;
  bottom: -54vmax;
  background: radial-gradient(circle, rgba(194, 62, 112, 0.29) 0%, rgba(128, 45, 104, 0.13) 35%, transparent 68%);
  opacity: var(--ambient-warm-opacity);
  transform:
    translate3d(
      var(--ambient-warm-x),
      var(--ambient-warm-y),
      0
    )
    scale(var(--ambient-warm-scale));
}

.ambient__stars {
  position: absolute;
  inset: -8%;
  opacity: 0.28;
  background-image:
    radial-gradient(circle at 12% 20%, rgba(255, 255, 255, 0.85) 0 1px, transparent 1.35px),
    radial-gradient(circle at 72% 12%, rgba(255, 255, 255, 0.62) 0 1px, transparent 1.35px),
    radial-gradient(circle at 90% 42%, rgba(244, 206, 131, 0.7) 0 1px, transparent 1.35px),
    radial-gradient(circle at 34% 62%, rgba(255, 255, 255, 0.52) 0 1px, transparent 1.35px);
  background-size: 211px 211px, 293px 293px, 367px 367px, 431px 431px;
  transform: translate3d(0, var(--star-y), 0) scale(1.04);
  will-change: transform;
}

.fireworks {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  opacity: 0.46;
}

.firework {
  --size: 18rem;
  position: absolute;
  width: var(--size);
  aspect-ratio: 1;
  border-radius: 50%;
  background: repeating-conic-gradient(from 4deg, rgba(255, 215, 138, 0.95) 0deg 1.4deg, transparent 1.4deg 13deg);
  -webkit-mask: radial-gradient(circle, transparent 0 20%, #000 21% 22%, transparent 23% 43%, #000 44% 45%, transparent 46%);
  mask: radial-gradient(circle, transparent 0 20%, #000 21% 22%, transparent 23% 43%, #000 44% 45%, transparent 46%);
  animation: firework 10.5s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}

.firework:nth-child(1) { top: 5%; left: 4%; }
.firework:nth-child(2) { --size: 13rem; top: 20%; right: 3%; filter: hue-rotate(285deg); animation-delay: 3.4s; }
.firework:nth-child(3) { --size: 8rem; top: 3%; right: 28%; filter: hue-rotate(35deg); animation-delay: 6.4s; }

@keyframes firework {
  0%, 10% { transform: scale(0.15); opacity: 0; }
  20%, 46% { transform: scale(1); opacity: 0.88; }
  68%, 100% { transform: scale(1.18); opacity: 0; }
}

.ambient__ring {
  position: absolute;
  width: clamp(13rem, 22vw, 20rem);
  aspect-ratio: 1;
  border-radius: 50%;
  opacity: 0.1;
  background: repeating-conic-gradient(from 7deg, rgba(244, 206, 131, 0.85) 0deg 1deg, transparent 1deg 15deg);
  -webkit-mask: radial-gradient(circle, transparent 0 31%, #000 31.5% 32.4%, transparent 33% 47%, #000 47.5% 48.1%, transparent 48.7%);
  mask: radial-gradient(circle, transparent 0 31%, #000 31.5% 32.4%, transparent 33% 47%, #000 47.5% 48.1%, transparent 48.7%);
  will-change: transform, opacity;
}

.ambient__ring--left {
  top: 12%;
  left: -5rem;
}

.ambient__ring--right {
  right: -4rem;
  top: 29%;
}

.journey {
  position: relative;
  z-index: 1;
  height: 1180svh;
}

.journey-stage {
  position: sticky;
  top: 0;
  height: 100svh;
  min-height: 0;
  overflow: hidden;
  isolation: isolate;
  transition: transform 1100ms var(--ease-out), opacity 950ms var(--ease-out);
}

.scene {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  will-change: transform, opacity;
}

.shared-label {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 24;
  width: max-content;
  margin: 0;
  color: var(--gold);
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(2.35rem, 5.7vw, 4.35rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  text-align: center;
  white-space: nowrap;
  transform: translate3d(-50%, -5.4rem, 0);
  transform-origin: center;
  will-change: transform, opacity;
}

.opening-lines {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(90vw, 34rem);
  margin: 1.1rem 0 0;
  color: var(--muted);
  font-size: clamp(1.12rem, 2.5vw, 1.32rem);
  text-align: center;
  transform: translate3d(-50%, 0, 0);
  will-change: transform, opacity;
}

.opening-lines span {
  display: block;
}

.hero-lockup {
  width: min(92vw, 70rem);
  text-align: center;
  opacity: 0;
  transform: scale(0.94);
  will-change: transform, opacity;
}

.hero-lockup h1 {
  margin: 0;
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(3rem, 7.2vw, 5.8rem);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.hero-lockup .scroll-cue {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: max-content;
  margin: 2rem auto 0;
  color: rgba(255, 248, 236, 0.66);
  font-size: 0.92rem;
  opacity: 0;
  will-change: opacity;
}

.scroll-cue::before {
  width: 2.5rem;
  height: 1px;
  content: "";
  background: rgba(244, 206, 131, 0.52);
}

.portal-line {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: min(74vw, 66rem);
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(244, 206, 131, 0.58), transparent);
  opacity: 0;
  transform: translate3d(-50%, 9rem, 0);
  transform-origin: center;
  will-change: transform, opacity;
}

.story-scene {
  padding: 0 clamp(1rem, 4vw, 3.5rem);
  opacity: 0;
}

.story-shell {
  position: relative;
  width: min(72rem, 100%);
  height: 100%;
  margin: 0 auto;
}

.chapter-heading {
  position: absolute;
  top: clamp(4.25rem, calc(var(--stage-unit) * 10), 6.5rem);
  right: 0;
  left: 0;
  height: 7rem;
  text-align: center;
  will-change: transform, opacity;
}

.chapter-heading__layer {
  position: absolute;
  inset: 0;
  will-change: transform, opacity;
}

.chapter-heading__layer--reason {
  opacity: 0;
}

.chapter-heading .number {
  display: block;
  margin-bottom: 0.35rem;
  color: var(--pink);
  font-size: 0.77rem;
  font-weight: 800;
  letter-spacing: 0.25em;
}

.chapter-heading h2 {
  margin: 0;
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(2.15rem, 5vw, 3.85rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

.card-grid {
  position: absolute;
  top: clamp(13.5rem, calc(var(--stage-unit) * 31), 17.25rem);
  right: 0;
  left: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.4vw, 1.1rem);
  height: min(calc(var(--stage-unit) * 51), 25rem);
  perspective: 1200px;
}

/* Each phone chapter has three cards driven by native vertical scrolling. The
   arrows are optional shortcuts, and the same three dots restart when the
   second chapter begins. Desktop and reduced motion need neither control. */
.card-navigation { display: none; }

@media (max-width: 900px) and (prefers-reduced-motion: no-preference) {
  .card-navigation {
    position: absolute;
    top: calc(var(--card-grid-top) + var(--card-grid-height) + 0.35rem);
    right: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.1rem;
    opacity: var(--nav-opacity, 0);
    transition: opacity 260ms var(--ease-out);
  }

  /* Small enough to stay out of the story, with a finger-sized reach around it.
     A scene passes touches through, so the arrows have to ask for their own. */
  .card-navigation__button {
    display: flex;
    pointer-events: auto;
    width: 2.75rem;
    height: 2.75rem;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    color: rgba(255, 246, 222, 0.88);
    cursor: pointer;
    transition: opacity 240ms var(--ease-out), transform 240ms var(--ease-out);
    -webkit-tap-highlight-color: transparent;
  }

  .card-navigation__button:disabled {
    opacity: 0.16;
    cursor: default;
  }

  .card-navigation__button:not(:disabled):active { transform: scale(0.88); }

  .card-navigation__arrow {
    width: 1.6rem;
    height: 1.6rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
    filter: drop-shadow(0 0 0.45rem rgba(255, 226, 168, 0.5));
  }

  .card-dots {
    display: flex;
    justify-content: center;
    gap: 0.45rem;
    pointer-events: none;
  }

  .card-dots i {
    width: 0.3rem;
    height: 0.3rem;
    border-radius: 50%;
    background: rgba(238, 232, 250, 0.24);
    transition: background 260ms var(--ease-out), transform 260ms var(--ease-out);
  }

  .card-dots[data-active="0"] i:nth-child(1),
  .card-dots[data-active="1"] i:nth-child(2),
  .card-dots[data-active="2"] i:nth-child(3) {
    background: rgba(247, 243, 255, 0.82);
    transform: scale(1.4);
  }
}

.story-card {
  --card-x-pos: 0%;
  --card-y-pos: 0px;
  --card-scale: 0.94;
  --card-opacity: 0;
  position: relative;
  min-width: 0;
  height: 100%;
  overflow: hidden;
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.105), rgba(255, 255, 255, 0.052));
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 1.55rem;
  box-shadow:
    0 1.8rem 5rem rgba(0, 0, 0, 0.18),
    inset 0 1px rgba(255, 255, 255, 0.05);
  opacity: var(--card-opacity);
  transform:
    translate3d(
      var(--card-x-pos),
      var(--card-y-pos),
      0
    )
    scale(var(--card-scale)) rotateY(var(--card-tilt, 0deg));
  transform-origin: center;
  will-change: transform, opacity;
}

.story-card::after {
  position: absolute;
  right: -28%;
  bottom: -32%;
  width: 72%;
  aspect-ratio: 1;
  border-radius: 50%;
  content: "";
  background: radial-gradient(circle, rgba(244, 114, 161, 0.14), transparent 69%);
  opacity: 0.72;
}

.card-face {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: clamp(1.4rem, 2.3vw, 1.85rem);
  will-change: transform, opacity;
}

.card-face--reason {
  opacity: 0;
}

.card-face h3 {
  margin: 0 0 1.15rem;
  color: var(--gold);
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(1.24rem, 1.95vw, 1.51rem);
  font-weight: 600;
  line-height: 1.25;
}

.card-face p {
  margin: 0;
  color: var(--muted);
  font-size: clamp(1.03rem, 1.46vw, 1.17rem);
  line-height: 1.45;
}

.card-face p span {
  display: block;
  margin-bottom: 0.8rem;
  text-wrap: balance;
}

.card-face p span:last-child {
  margin-bottom: 0;
}

.card-illustration {
  position: absolute;
  right: 0.5rem;
  bottom: 0.45rem;
  z-index: 3;
  width: clamp(6rem, 8vw, 8.5rem);
  pointer-events: none;
  filter: drop-shadow(0 0.8rem 1.2rem rgba(0, 0, 0, 0.24));
}

/* lulu-hug-heart.png 圖案留白較少，單獨縮小以與另兩隻視覺等大 */
.story-card[data-card="0"] .card-illustration {
  width: clamp(5rem, 6.6vw, 7.05rem);
}

.card-illustration img {
  display: block;
  width: 100%;
  height: auto;
}

/* ── Memory relics ──────────────────────────────────────────────────────────
   Every card face hides one keepsake from a real date. Tapping it plays the
   relic's own animation, then a polaroid climbs out from behind it and develops.
   `.scene` is pointer-events: none, so the button re-enables hit testing for
   itself alone; cards.js drops `inert` on it whenever its face is faded, which
   is what stops the stacked phone layout from firing the card underneath.
   Stacking inside a card is ::after (0) < .card-face (2) < .card-illustration (3)
   < ::before sweep (4), so the polaroid takes 5 and the relic sits above it. */
.card-relic {
  position: absolute;
  right: 0.55rem;
  bottom: 0.5rem;
  z-index: 6;
  width: clamp(2.7rem, 3.7vw, 3.5rem);
  aspect-ratio: 1;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  pointer-events: auto;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* These two faces already park a Lulu in the bottom-right corner. */
.card-relic--left,
.card-polaroid--left {
  right: auto;
  left: 0.55rem;
}

.card-relic:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 4px;
}

.relic-art {
  display: block;
  width: 100%;
  height: 100%;
  /* Bubbles, steam and raindrops travel past the 64-unit box on purpose. */
  overflow: visible;
}

/* Some relics are supplied photos rather than drawings. There are no parts to
   move inside a bitmap, so those play one shared pop instead of their own scene. */
.relic-art--photo {
  object-fit: contain;
  filter: drop-shadow(0 0.5rem 0.85rem rgba(0, 0, 0, 0.45));
}

.card-polaroid {
  position: absolute;
  right: 0.5rem;
  bottom: 0.45rem;
  z-index: 5;
  width: min(62%, 11.5rem);
  padding: 0.45rem 0.45rem 0;
  border-radius: 0.3rem;
  background: linear-gradient(158deg, #fffdf7 0%, #f6efe2 62%, #ece2d2 100%);
  box-shadow:
    0 1.1rem 2.4rem rgba(0, 0, 0, 0.46),
    0 0 0 1px rgba(255, 255, 255, 0.34) inset;
  opacity: 0;
  transform: translate3d(0, 16%, 0) rotate(7deg) scale(0.84);
  transform-origin: 86% 108%;
  pointer-events: none;
}

.card-polaroid.is-open {
  opacity: 1;
  transform: translate3d(0, 0, 0) rotate(-3.2deg) scale(1);
}

/* A strip of washi tape, so it reads as stuck into an album rather than floating. */
.card-polaroid::before {
  position: absolute;
  top: -0.42rem;
  left: 50%;
  width: 42%;
  height: 0.85rem;
  content: "";
  background: linear-gradient(100deg, rgba(244, 114, 161, 0.42), rgba(244, 206, 131, 0.5));
  box-shadow: 0 0.15rem 0.3rem rgba(0, 0, 0, 0.22);
  transform: translateX(-50%) rotate(-2.5deg);
}

.polaroid-photo {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 0.12rem;
  object-fit: cover;
  background: #241d2e;
  opacity: 0.5;
  filter: brightness(0.3) contrast(0.55) saturate(0.15) blur(5px);
}

.card-polaroid.is-developed .polaroid-photo {
  opacity: 1;
  filter: none;
}

.polaroid-note {
  display: block;
  padding: 0.36rem 0.1rem 0.5rem;
  color: #6c5566;
  font-family: "Caveat", "Bradley Hand", "Segoe Script", cursive;
  font-size: clamp(0.92rem, 1.25vw, 1.06rem);
  font-weight: 600;
  line-height: 1.18;
  text-align: center;
  text-wrap: balance;
}

@media (prefers-reduced-motion: no-preference) {
  .card-polaroid {
    transition:
      opacity var(--interaction-polaroid-tuck, 260ms) var(--ease-out),
      transform var(--interaction-polaroid-tuck, 260ms) var(--ease-out);
  }

  .card-polaroid.is-open {
    transition-duration: var(--interaction-polaroid-rise, 340ms);
  }

  .polaroid-photo {
    transition:
      opacity var(--interaction-polaroid-develop, 1200ms) ease-out,
      filter var(--interaction-polaroid-develop, 1200ms) ease-out;
  }

  .card-relic[data-state="idle"] .relic-art--photo {
    animation: relic-photo-wait 3.2s ease-in-out infinite;
  }

  .card-relic[data-state="playing"] .relic-art--photo {
    animation: relic-photo-pop var(--interaction-relic-play, 450ms) var(--ease-out) both;
  }

  .card-relic[data-state="revealed"] .relic-art--photo {
    transform: scale(1.06) rotate(-3deg);
  }
}

@keyframes relic-photo-wait {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-2px) rotate(2.5deg); }
}

@keyframes relic-photo-pop {
  0% { transform: scale(1) rotate(0deg); }
  38% { transform: scale(1.22) rotate(-7deg); }
  70% { transform: scale(0.99) rotate(1.5deg); }
  100% { transform: scale(1.06) rotate(-3deg); }
}

/* ── Little card moments ────────────────────────────────────────────────────────────────────
   Each face gets one supplied image. The image itself is the only hit target;
   the glow, note and small particles never block scrolling. */
.card-face {
  padding-bottom: clamp(6.8rem, 14vh, 8.1rem);
}

.card-face--polaroid { padding-bottom: 8.7rem; }

.card-moment {
  --moment-width: 5.4rem;
  --moment-height: 5.4rem;
  position: absolute;
  right: 0.75rem;
  bottom: 0.7rem;
  z-index: 5;
  width: var(--moment-width);
  height: var(--moment-height);
  pointer-events: none;
}

.card-moment--beer { --moment-width: 4.2rem; --moment-height: 5.7rem; }
.card-moment--shine { --moment-width: 8.1rem; --moment-height: 5.35rem; }
.card-moment--mouse {
  --moment-width: 7.2rem;
  --moment-height: 7.2rem;
  --mouse-run: clamp(4.2rem, 7vw, 6rem);
  right: auto;
  bottom: -0.35rem;
  left: -2.65rem;
}
.card-moment--live { --moment-width: 5.35rem; --moment-height: 5.35rem; }
.card-moment--milktea { --moment-width: 5.7rem; --moment-height: 5.35rem; }
.card-moment--polaroid { --moment-width: 8.5rem; --moment-height: 8rem; }

.card-moment .card-relic {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  width: 100%;
  min-width: 44px;
  height: 100%;
  min-height: 44px;
  aspect-ratio: auto;
  margin: 0;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 1.4rem;
  background: none;
  color: inherit;
  pointer-events: auto;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.card-relic[aria-hidden="true"] { pointer-events: none; }

.card-moment .card-relic:focus-visible {
  outline: 2px solid rgba(255, 222, 174, 0.95);
  outline-offset: 4px;
}

.card-relic__aura {
  position: absolute;
  inset: 8% -7%;
  z-index: -1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 45%, rgba(255, 222, 174, 0.28), transparent 54%),
    radial-gradient(circle at 68% 54%, rgba(245, 145, 191, 0.24), transparent 62%);
  opacity: 0.34;
  filter: blur(8px);
  transform: scale(0.88);
}

.card-moment .relic-art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  overflow: visible;
  user-select: none;
  -webkit-user-select: none;
  filter:
    drop-shadow(0 0.55rem 0.85rem rgba(0, 0, 0, 0.36))
    drop-shadow(0 0 0.7rem rgba(255, 189, 214, 0.1));
}

.card-moment--shine .relic-art {
  border-radius: 46%;
  -webkit-mask-image: radial-gradient(ellipse 72% 78% at center, #000 54%, transparent 100%);
  mask-image: radial-gradient(ellipse 72% 78% at center, #000 54%, transparent 100%);
}

.card-tap {
  position: absolute;
  right: 0.1rem;
  bottom: -0.35rem;
  color: rgba(255, 238, 218, 0.78);
  font-family: "Nunito", system-ui, sans-serif;
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  opacity: 0;
  text-shadow: 0 0 0.7rem rgba(245, 154, 195, 0.62);
  text-transform: uppercase;
}

.card-memory-note {
  position: absolute;
  right: calc(100% + 0.45rem);
  bottom: 0.45rem;
  width: min(10.4rem, 43vw);
  color: rgba(255, 233, 213, 0.9);
  font-family: "Caveat", "Bradley Hand", "Segoe Script", cursive;
  font-size: clamp(0.94rem, 1.28vw, 1.08rem);
  font-weight: 600;
  line-height: 1.15;
  text-align: right;
  text-wrap: balance;
  opacity: 0;
  filter: drop-shadow(0 0 0.65rem rgba(244, 145, 188, 0.48));
  transform: translate3d(0.35rem, 0.2rem, 0);
}

.card-moment.is-playing .card-memory-note {
  opacity: 1;
  transform: none;
}

.card-moment-effects,
.card-moment-effects i {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.card-moment-effects i {
  display: block;
  width: 0.42rem;
  height: 0.42rem;
  opacity: 0;
}

.card-moment--beer .card-moment-effects i {
  top: 12%;
  left: 48%;
  border: 1px solid rgba(255, 229, 170, 0.78);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.86), rgba(246, 194, 104, 0.18) 42%, transparent 72%);
  box-shadow: 0 0 0.8rem rgba(246, 188, 88, 0.5);
}
.card-moment--beer .card-moment-effects i:nth-child(2) { left: 65%; width: 0.28rem; height: 0.28rem; }
.card-moment--beer .card-moment-effects i:nth-child(3) { left: 34%; width: 0.33rem; height: 0.33rem; }
.card-moment--beer .card-moment-effects i:nth-child(4) { left: 74%; width: 0.22rem; height: 0.22rem; }

.card-moment--shine .card-moment-effects i,
.card-moment--live .card-moment-effects i {
  top: 46%;
  left: 50%;
  border-radius: 50%;
  background: rgba(255, 218, 234, 0.9);
  box-shadow: 0 0 0.7rem rgba(246, 132, 183, 0.84), 0 0 1.35rem rgba(123, 185, 255, 0.58);
}
.card-moment--shine .card-moment-effects i:nth-child(2),
.card-moment--live .card-moment-effects i:nth-child(2) { background: rgba(180, 217, 255, 0.92); }
.card-moment--shine .card-moment-effects i:nth-child(3),
.card-moment--live .card-moment-effects i:nth-child(3) { background: rgba(255, 225, 168, 0.9); }
.card-moment--shine .card-moment-effects i:nth-child(4) { background: rgba(231, 191, 255, 0.86); }

.card-moment--mouse .card-memory-note {
  right: auto;
  bottom: 1.2rem;
  left: calc(100% + 0.15rem);
  width: min(11rem, 42vw);
  text-align: left;
  transform: translate3d(-0.35rem, 0.2rem, 0);
}

.card-moment--mouse.is-playing .card-memory-note { transform: none; }

.card-moment--mouse .card-tap {
  right: -0.1rem;
  bottom: 0.15rem;
}

.card-moment--mouse .card-moment-effects i {
  top: 35%;
  left: 68%;
  width: auto;
  height: auto;
  color: rgba(255, 174, 204, 0.88);
  font-style: normal;
  font-size: 0.74rem;
  text-shadow: 0 0 0.9rem rgba(255, 131, 181, 0.78);
}
.card-moment--mouse .card-moment-effects i:nth-child(2) { top: 48%; left: 83%; font-size: 0.56rem; }
.card-moment--mouse .card-moment-effects i:nth-child(3) { top: 25%; left: 92%; font-size: 0.46rem; }

.card-moment--milktea .card-moment-effects i:first-child {
  top: 20%;
  left: 52%;
  width: auto;
  height: auto;
  color: rgba(255, 177, 207, 0.9);
  font-style: normal;
  font-size: 0.9rem;
  text-shadow: 0 0 0.9rem rgba(246, 119, 174, 0.8);
}
.card-moment--milktea .card-moment-effects i:last-child {
  top: 35%;
  left: 52%;
  width: 1.8rem;
  height: 1.8rem;
  margin: -0.9rem;
  border: 1px solid rgba(255, 213, 174, 0.72);
  border-radius: 50%;
  box-shadow: 0 0 1rem rgba(245, 161, 196, 0.5);
}

.card-moment .card-polaroid {
  box-sizing: border-box;
  position: absolute;
  inset: 0;
  z-index: auto;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0.35rem 0.35rem 0;
  border-radius: 0.28rem;
  background: linear-gradient(158deg, #fffdf7 0%, #f6efe2 66%, #eadfce 100%);
  box-shadow:
    0 0.85rem 1.8rem rgba(0, 0, 0, 0.42),
    0 0 0 1px rgba(255, 255, 255, 0.38) inset;
  opacity: 1;
  transform: translate3d(0, 0.18rem, 0) rotate(3deg) scale(0.92);
  transform-origin: 82% 110%;
  pointer-events: none;
}

.card-moment .card-polaroid::before {
  top: -0.3rem;
  width: 38%;
  height: 0.62rem;
}

.card-moment--polaroid.is-playing .card-polaroid {
  transform: translate3d(-0.15rem, -0.55rem, 0) rotate(-2deg) scale(1.05);
}

.card-moment .polaroid-photo {
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: 0.1rem;
  object-fit: cover;
  opacity: 0.58;
  filter: brightness(0.45) contrast(0.7) saturate(0.35) blur(2.5px);
}

.card-moment--polaroid.is-developed .polaroid-photo {
  opacity: 1;
  filter: none;
}

.card-moment .polaroid-note {
  padding: 0.3rem 0.08rem 0.38rem;
  font-size: 0.78rem;
  line-height: 1.05;
  opacity: 0;
}

.card-moment--polaroid.is-playing .polaroid-note { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  .card-relic__aura,
  .card-memory-note,
  .card-moment .card-polaroid,
  .card-moment .polaroid-photo,
  .card-moment .polaroid-note {
    transition:
      opacity var(--interaction-polaroid-rise, 320ms) var(--ease-out),
      filter var(--interaction-polaroid-develop, 720ms) ease-out,
      transform var(--interaction-polaroid-rise, 320ms) var(--ease-out);
  }

  .card-moment.is-hinting .card-tap {
    animation: card-tap-hint var(--interaction-moment-hint, 1400ms) ease both;
  }
  .card-moment--beer.is-playing .relic-art { animation: card-beer 700ms var(--ease-out) both; }
  .card-moment--mouse.is-playing .relic-art {
    animation: card-mouse-scamper 1900ms var(--ease-out) both;
  }
  .card-moment--shine.is-playing .relic-art { animation: card-shine 900ms var(--ease-out) both; }
  .card-moment--live.is-playing .relic-art { animation: card-float 1000ms var(--ease-out) both; }
  .card-moment--milktea.is-playing .relic-art { animation: card-clink 720ms var(--ease-out) both; }

  .card-moment--beer.is-playing .card-moment-effects i { animation: card-bubble 900ms ease-out both; }
  .card-moment--beer.is-playing .card-moment-effects i:nth-child(2) { animation-delay: 90ms; }
  .card-moment--beer.is-playing .card-moment-effects i:nth-child(3) { animation-delay: 170ms; }
  .card-moment--beer.is-playing .card-moment-effects i:nth-child(4) { animation-delay: 260ms; }
  .card-moment--shine.is-playing .card-moment-effects i,
  .card-moment--live.is-playing .card-moment-effects i { animation: card-spark 850ms ease-out both; }
  .card-moment--shine.is-playing .card-moment-effects i:nth-child(2),
  .card-moment--live.is-playing .card-moment-effects i:nth-child(2) { --spark-x: 2.4rem; --spark-y: -1.2rem; animation-delay: 70ms; }
  .card-moment--shine.is-playing .card-moment-effects i:nth-child(3),
  .card-moment--live.is-playing .card-moment-effects i:nth-child(3) { --spark-x: -2rem; --spark-y: -1.65rem; animation-delay: 130ms; }
  .card-moment--shine.is-playing .card-moment-effects i:nth-child(4) { --spark-x: 1.3rem; --spark-y: 1.35rem; animation-delay: 190ms; }
  .card-moment--mouse.is-playing .card-moment-effects i { animation: card-mouse-heart 900ms 760ms ease-out both; }
  .card-moment--mouse.is-playing .card-moment-effects i:nth-child(2) { animation-delay: 900ms; }
  .card-moment--mouse.is-playing .card-moment-effects i:nth-child(3) { animation-delay: 1040ms; }
  .card-moment--milktea.is-playing .card-moment-effects i:first-child { animation: card-clink-heart 900ms var(--ease-out) both; }
  .card-moment--milktea.is-playing .card-moment-effects i:last-child { animation: card-clink-ring 800ms ease-out both; }

  @keyframes card-tap-hint {
    0%, 100% { opacity: 0; transform: translateY(0.2rem); }
    22%, 72% { opacity: 0.82; transform: none; }
  }
  @keyframes card-beer {
    0%, 100% { transform: rotate(0deg); }
    24% { transform: rotate(-7deg) translateY(-2px); }
    52% { transform: rotate(6deg) translateY(-3px); }
    76% { transform: rotate(-2deg); }
  }
  @keyframes card-mouse-scamper {
    0% { opacity: 1; transform: translate3d(-24%, 0, 0) rotate(-4deg) scale(0.96); }
    18% { transform: translate3d(8%, -5px, 0) rotate(5deg) scale(1.04); }
    34% { transform: translate3d(20%, 0, 0) rotate(-4deg) scale(1); }
    52% { transform: translate3d(var(--mouse-run), -7px, 0) rotate(6deg) scale(1.04); }
    68% { transform: translate3d(var(--mouse-run), 0, 0) rotate(-3deg) scale(1); }
    84% { opacity: 1; transform: translate3d(calc(var(--mouse-run) + 0.8rem), -2px, 0) rotate(4deg) scale(0.98); }
    100% { opacity: 0; transform: translate3d(calc(var(--mouse-run) + 2.2rem), 2px, 0) rotate(8deg) scale(0.9); }
  }
  @keyframes card-shine {
    0%, 100% { transform: scale(1); filter: brightness(1) drop-shadow(0 0.55rem 0.85rem rgba(0, 0, 0, 0.36)); }
    48% { transform: scale(1.055); filter: brightness(1.2) drop-shadow(0 0 1rem rgba(119, 188, 255, 0.55)) drop-shadow(0 0 1.3rem rgba(246, 136, 187, 0.42)); }
  }
  @keyframes card-float {
    0%, 100% { transform: translateY(0) scale(1); }
    48% { transform: translateY(-7px) scale(1.045); }
  }
  @keyframes card-clink {
    0%, 100% { transform: rotate(0deg) scale(1); }
    32% { transform: translateX(-3px) rotate(-2deg) scale(1.025); }
    58% { transform: translateX(2px) rotate(2deg) scale(1.04); }
  }
  @keyframes card-bubble {
    0% { opacity: 0; transform: translate3d(0, 0.8rem, 0) scale(0.4); }
    28% { opacity: 0.8; }
    100% { opacity: 0; transform: translate3d(0.4rem, -2.8rem, 0) scale(1.15); }
  }
  @keyframes card-spark {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
    35% { opacity: 0.95; }
    100% { opacity: 0; transform: translate(calc(-50% + var(--spark-x, -2.4rem)), calc(-50% + var(--spark-y, 1.15rem))) scale(1.2); }
  }
  @keyframes card-mouse-heart {
    0% { opacity: 0; transform: translate3d(0, 0.4rem, 0) scale(0.35) rotate(-8deg); }
    32% { opacity: 0.95; }
    100% { opacity: 0; transform: translate3d(1.2rem, -2rem, 0) scale(1.12) rotate(10deg); }
  }
  @keyframes card-clink-heart {
    0% { opacity: 0; transform: translate(-50%, 0.65rem) scale(0.25); }
    38%, 70% { opacity: 0.95; transform: translate(-50%, 0) scale(1.12); }
    100% { opacity: 0; transform: translate(-50%, -0.45rem) scale(0.8); }
  }
  @keyframes card-clink-ring {
    0% { opacity: 0; transform: scale(0.2); }
    34% { opacity: 0.65; }
    100% { opacity: 0; transform: scale(1.8); }
  }
}

.note-scene {
  padding: 1rem;
  opacity: 0;
}

.note-wrap {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(47rem, calc(100% - 2rem));
  height: clamp(19rem, calc(var(--stage-unit) * 45), 22rem);
  overflow: visible;
  transform: translate3d(-50%, -50%, 0);
}

.note-glow {
  position: absolute;
  inset: -30%;
  z-index: 0;
  background:
    radial-gradient(closest-side, rgba(232, 183, 155, 0.16), rgba(224, 143, 147, 0.09) 60%, rgba(255, 188, 220, 0) 100%),
    radial-gradient(closest-side at 32% 24%, rgba(244, 206, 131, 0.32), rgba(244, 206, 131, 0) 82%);

  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}

.note-surface {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  color: var(--note-ink);
  background:
    radial-gradient(120% 90% at 22% 12%, rgba(255, 214, 195, 0.09), rgba(255, 214, 232, 0) 62%),
    radial-gradient(110% 85% at 82% 88%, rgba(244, 206, 131, 0.07), rgba(244, 206, 131, 0) 60%),
    linear-gradient(155deg, rgba(255, 248, 236, 0.075), rgba(88, 52, 69, 0.1) 55%, rgba(11, 13, 32, 0.22));

  border: 1px solid rgba(255, 232, 240, 0.26);
  border-radius: 1.55rem;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    inset 0 0 4rem rgba(255, 196, 222, 0.16);
  opacity: 0;
  transform: scale(1);
  /* Keep the letter on one material plane while its silhouette closes. */
  will-change: transform, opacity;
}

.note-copy {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: clamp(3.5rem, 7vw, 5rem) clamp(1.25rem, 5vw, 2.75rem) 2.25rem;
  text-align: center;
  text-shadow: 0 1px 14px rgba(11, 13, 32, 0.45);
  opacity: 0;
  will-change: transform, opacity;
}

.note-copy p {
  display: grid;
  place-items: center;
  margin: 0;
  font-size: clamp(1.35rem, 2.8vw, 1.5rem);
  line-height: 1.5;
}

.note-copy span {
  display: block;
  grid-area: 1 / 1;
  max-width: min(44rem, 100%);
  opacity: 0;
  white-space: nowrap;
  will-change: transform, opacity;
}

.note-cupid {
  position: absolute;
  top: -4.8rem;
  right: 1.25rem;
  z-index: 4;
  width: clamp(6.2rem, 9vw, 8rem);
  opacity: 0;
  filter: drop-shadow(0 0.8rem 1.1rem rgba(76, 35, 54, 0.2));
  pointer-events: none;
  will-change: transform, opacity;
}

.note-cupid img {
  display: block;
  width: 100%;
  height: auto;
}

.shared-heart {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 32;
  display: grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  color: var(--pink);
  font-size: 2rem;
  opacity: 0;
  transform: translate3d(-50%, -8rem, 0);
  transform-origin: center;
  text-shadow: 0 0 2rem rgba(244, 114, 161, 0.24);
  will-change: transform, opacity;
}

.confession-scene {
  padding: 2rem 1.25rem;
  opacity: 0;
}

.confession-inner {
  position: relative;
  top: 3rem;
  width: min(50rem, 100%);
  text-align: center;
  transform: scale(0.97);
  will-change: transform, opacity;
}

.confession-inner .eyebrow {
  margin: 0 0 1rem;
  color: var(--gold);
  font-family: "Nunito", system-ui, sans-serif;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.28em;
}

.confession-inner h2 {
  margin: 0;
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(3rem, 7vw, 5.2rem);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.princess-line,
.question-line {
  display: block;
  will-change: transform, opacity;
}

.princess-line {
  margin-bottom: 0.16em;
  color: var(--gold);
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: 0.68em;
  font-weight: 600;
  letter-spacing: 0.025em;
  line-height: 1.2;
  text-shadow: 0 0.2em 1em rgba(244, 206, 131, 0.2);
}

.question-line {
  margin-bottom: -0.1em;
  padding: 0 0.08em 0.1em;
  color: #fff5f8;
  font-size: 1em;
  line-height: 1.08;
  text-shadow:
    0 0.18em 0.8em rgba(244, 114, 161, 0.18),
    0 1px 0 rgba(255, 255, 255, 0.12);
}

.decision-stage {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.15rem;
  min-height: 7rem;
  margin-top: 1.85rem;
  opacity: 0;
  transform: scale(0.96);
  pointer-events: none;
  will-change: transform, opacity;
}

.confession-scene.is-active .decision-stage {
  pointer-events: auto;
}

.primary-button,
.no-button {
  min-width: 10rem;
  padding: 0.95rem 1.8rem 1rem;
  border-radius: 999px;
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: 1.12rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.025em;
  cursor: pointer;
}

.primary-button {
  --yes-scale: 1;
  --yes-hover-scale: 1.018;
  position: relative;
  z-index: 25;
  overflow: hidden;
  color: #fffaf8;
  background: rgba(244, 114, 161, 0.18);
  backdrop-filter: blur(12px) saturate(1.08);
  -webkit-backdrop-filter: blur(12px) saturate(1.08);
  border: 1px solid rgba(255, 172, 205, 0.52);
  box-shadow:
    0 0.75rem 2rem rgba(130, 35, 80, 0.18),
    0 0 1.6rem rgba(244, 114, 161, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transform: scale(var(--yes-scale));
  transition:
    transform 220ms var(--ease-out),
    background 220ms var(--ease-out),
    border-color 220ms var(--ease-out),
    box-shadow 220ms var(--ease-out),
    opacity 260ms var(--ease-out);
}

/* Touch has no hover: without this guard the lit state sticks after her finger
   has gone, so the button sits there looking pressed. Matches how the blind-box
   character button guards its own hover. */
@media (hover: hover) and (pointer: fine) {
  .primary-button:hover:not(:disabled) {
    background: rgba(244, 114, 161, 0.28);
    border-color: rgba(255, 199, 223, 0.8);
    box-shadow:
      0 0.95rem 2.5rem rgba(130, 35, 80, 0.28),
      0 0 2.1rem rgba(244, 114, 161, 0.26),
      inset 0 1px 0 rgba(255, 255, 255, 0.3);
    transform: translateY(-1px) scale(var(--yes-hover-scale));
  }

  .no-button:hover:not(:disabled) {
    color: rgba(255, 250, 252, 0.95);
    border-color: rgba(255, 234, 243, 0.4);
    box-shadow:
      0 0.9rem 2.3rem rgba(0, 0, 0, 0.2),
      inset 0 1px 0 rgba(255, 255, 255, 0.14);
    transform: translateY(-1px);
  }

  .no-button.is-loose:hover:not(:disabled) {
    transform: translate3d(var(--no-x), calc(var(--no-y) - 1px), 0);
  }
}

.yes-label {
  position: relative;
  z-index: 2;
  transition: opacity 180ms var(--ease-out);
}

.no-button {
  position: relative;
  z-index: 24;
  color: rgba(255, 245, 248, 0.82);
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.025));
  backdrop-filter: blur(12px) saturate(1.04);
  -webkit-backdrop-filter: blur(12px) saturate(1.04);
  border: 1px solid rgba(255, 226, 238, 0.24);
  box-shadow:
    0 0.75rem 2rem rgba(0, 0, 0, 0.14),
    inset 0 1px 0 rgba(255, 255, 255, 0.09);
  transition:
    color 220ms var(--ease-out),
    background 220ms var(--ease-out),
    border-color 220ms var(--ease-out),
    box-shadow 220ms var(--ease-out),
    opacity 220ms var(--ease-out),
    transform 180ms var(--ease-out);
}

.primary-button:focus-visible,
.no-button:focus-visible {
  outline: 2px solid rgba(244, 206, 131, 0.9);
  outline-offset: 4px;
}

.no-button.is-loose {
  position: fixed;
  left: 0;
  top: 0;
  transform: translate3d(var(--no-x), var(--no-y), 0);
}
.no-button.is-loose.is-dismissed { transform: translate3d(var(--no-x), var(--no-y), 0) scale(0.98); }

/* The decision row is centred, so lifting No out of it to run loose would slide
   Yes sideways at the exact moment she is reaching for it. decision.js drops
   this same-size stand-in into No's place, keeping the row two items wide so
   Yes stays put. Purely a spacer: no paint, no hit area, no reading order. */
.no-slot {
  display: block;
  flex: none;
  visibility: hidden;
  pointer-events: none;
}

.loose-layer {
  position: fixed;
  inset: 0;
  z-index: 400;
  pointer-events: none;
}

.loose-layer .no-button {
  pointer-events: auto;
}

.loose-layer:not(.is-active) .no-button {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}

.confession-scene:not(.is-active) .no-button {
  pointer-events: none;
}

.reaction {
  min-height: 2rem;
  margin: 0.5rem 0 0;
  color: var(--gold);
  font-size: 0.95rem;
}

.scratch-card {
  --ritual-size: min(78vw, 22rem);
  --summon-core-opacity: 1;
  --summon-core-scale: 1;
  --summon-core-rotate: 0deg;
  --summon-seed-opacity: 0;
  --summon-seed-scale: 1;
  --summon-dust-opacity: 0;
  --summon-dust-scale: 0.08;
  --summon-dust-rotate: 62deg;
  --summon-trace-opacity: 0;
  --summon-trace-scale: 1;
  --summon-trace-rotate: 40deg;
  --summon-moon-opacity: 1;
  --summon-moon-x: 0px;
  --summon-moon-y: 0px;
  --summon-moon-scale: 1;
  position: relative;
  width: min(38rem, 100%);
  margin: 0.7rem auto 0;
  padding: 0;
  border: 0;
  background: none;
  isolation: isolate;
}

.ritual-portal {
  position: relative;
  width: var(--ritual-size);
  aspect-ratio: 1;
  margin: 0 auto;
  border-radius: 50%;
  isolation: isolate;
}

.ritual-core {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  opacity: var(--summon-core-opacity);
  transform: scale(var(--summon-core-scale)) rotate(var(--summon-core-rotate));
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.ritual-core::before,
.ritual-core::after {
  position: absolute;
  border-radius: 50%;
  content: "";
  pointer-events: none;
}

.ritual-core::before {
  inset: 4.5%;
  z-index: 0;
  background:
    radial-gradient(circle at 50% 45%, rgba(105, 75, 132, 0.2), transparent 44%),
    radial-gradient(circle at 50% 54%, #181329 0 51%, #0c0b18 74%, #070710 100%);
  border: 1px solid rgba(225, 216, 245, 0.25);
  box-shadow:
    0 0 0 1px rgba(135, 110, 162, 0.08),
    0 0 2.8rem rgba(116, 81, 145, 0.22),
    0 0 5.5rem rgba(231, 127, 180, 0.08),
    inset 0 0 2.5rem rgba(7, 5, 17, 0.78),
    inset 0 1px 0 rgba(255, 255, 255, 0.11);
}

.ritual-core::after {
  inset: 10.5%;
  z-index: 4;
  border: 1px solid rgba(221, 215, 238, 0.16);
  box-shadow: 0 0 1.2rem rgba(206, 190, 232, 0.08), inset 0 0 1.2rem rgba(206, 190, 232, 0.06);
}

/* The portal is summoned in place. Loose stars collapse into one bright seed,
   a light trace sweeps the rim, then the finished circle takes over. */
.summoning-effect {
  position: absolute;
  inset: -8%;
  z-index: 10;
  border-radius: 50%;
  pointer-events: none;
}

.summoning-effect::before {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.42rem;
  aspect-ratio: 1;
  border-radius: 50%;
  background: #fffaff;
  box-shadow:
    0 0 0.7rem 0.22rem rgba(248, 235, 255, 0.94),
    0 0 2.1rem 0.7rem rgba(214, 166, 229, 0.54),
    0 0 4rem 1.2rem rgba(232, 142, 191, 0.24);
  content: "";
  opacity: var(--summon-seed-opacity);
  transform: translate(-50%, -50%) scale(var(--summon-seed-scale));
  will-change: transform, opacity;
}

.summoning-effect::after {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 2%, #fff 0 0.08rem, transparent 0.12rem),
    radial-gradient(circle at 76% 8%, #e8b5d6 0 0.07rem, transparent 0.11rem),
    radial-gradient(circle at 94% 27%, #f1e9fa 0 0.09rem, transparent 0.13rem),
    radial-gradient(circle at 98% 53%, #d8c9eb 0 0.06rem, transparent 0.1rem),
    radial-gradient(circle at 86% 80%, #f0b4d4 0 0.08rem, transparent 0.12rem),
    radial-gradient(circle at 62% 96%, #fff 0 0.07rem, transparent 0.11rem),
    radial-gradient(circle at 35% 94%, #d9caed 0 0.09rem, transparent 0.13rem),
    radial-gradient(circle at 11% 76%, #f2bdd9 0 0.06rem, transparent 0.1rem),
    radial-gradient(circle at 2% 48%, #fff 0 0.08rem, transparent 0.12rem),
    radial-gradient(circle at 14% 18%, #d8c7e9 0 0.07rem, transparent 0.11rem),
    radial-gradient(circle at 34% 10%, #efb3d2 0 0.05rem, transparent 0.09rem),
    radial-gradient(circle at 73% 30%, #fff 0 0.05rem, transparent 0.09rem),
    radial-gradient(circle at 28% 67%, #ebdff5 0 0.06rem, transparent 0.1rem),
    radial-gradient(circle at 64% 72%, #efacce 0 0.07rem, transparent 0.11rem);
  content: "";
  opacity: var(--summon-dust-opacity);
  filter: drop-shadow(0 0 0.38rem rgba(239, 222, 250, 0.9));
  transform: rotate(var(--summon-dust-rotate)) scale(var(--summon-dust-scale));
  will-change: transform, opacity;
}

.summoning-effect span {
  position: absolute;
  inset: 3%;
  border-radius: 50%;
  background: conic-gradient(
    from 18deg,
    transparent 0 14deg,
    rgba(255, 249, 255, 0.96) 23deg,
    rgba(229, 183, 220, 0.34) 39deg,
    transparent 58deg 150deg,
    rgba(226, 211, 244, 0.78) 174deg,
    transparent 202deg 290deg,
    rgba(244, 190, 218, 0.62) 312deg,
    transparent 340deg
  );
  opacity: var(--summon-trace-opacity);
  filter: drop-shadow(0 0 0.55rem rgba(235, 211, 245, 0.78));
  transform: rotate(var(--summon-trace-rotate)) scale(var(--summon-trace-scale));
  -webkit-mask: radial-gradient(circle, transparent 0 48%, #000 48.5% 49.25%, transparent 49.7%);
  mask: radial-gradient(circle, transparent 0 48%, #000 48.5% 49.25%, transparent 49.7%);
  will-change: transform, opacity;
}

.ritual-rings {
  position: absolute;
  inset: -1%;
  z-index: 1;
  border-radius: 50%;
  pointer-events: none;
  animation: ritual-orbit 32s linear infinite;
}

.ritual-rings::before,
.ritual-rings::after,
.ritual-rings span {
  position: absolute;
  border-radius: 50%;
  content: "";
}

.ritual-rings::before {
  inset: 1%;
  border: 1px solid rgba(201, 191, 224, 0.18);
  background: repeating-conic-gradient(from 9deg, rgba(225, 216, 245, 0.68) 0 1deg, transparent 1deg 14deg);
  -webkit-mask: radial-gradient(circle, transparent 0 48.1%, #000 48.4% 49%, transparent 49.3%);
  mask: radial-gradient(circle, transparent 0 48.1%, #000 48.4% 49%, transparent 49.3%);
}

.ritual-rings::after {
  inset: 8%;
  border: 1px dashed rgba(215, 205, 235, 0.2);
}

.ritual-rings span:nth-child(1) {
  inset: 0;
  border: 1px solid transparent;
  border-top-color: rgba(234, 226, 247, 0.72);
  border-bottom-color: rgba(165, 135, 184, 0.4);
  filter: drop-shadow(0 0 5px rgba(222, 210, 242, 0.34));
}

.ritual-rings span:nth-child(2) {
  top: 7%;
  left: 24%;
  width: 0.32rem;
  height: 0.32rem;
  background: #f4edf9;
  box-shadow: 0 0 0.65rem 0.2rem rgba(222, 210, 242, 0.42);
}

.ritual-rings span:nth-child(3) {
  right: 10%;
  bottom: 24%;
  width: 0.24rem;
  height: 0.24rem;
  background: #e8b3d1;
  box-shadow: 0 0 0.6rem 0.18rem rgba(232, 179, 209, 0.38);
}

@keyframes ritual-orbit { to { transform: rotate(1turn); } }

.ritual-mark {
  position: absolute;
  z-index: 7;
  color: rgba(224, 216, 238, 0.64);
  font-family: "Nunito", system-ui, sans-serif;
  font-weight: 800;
  line-height: 1;
  pointer-events: none;
  text-shadow: 0 0 0.7rem rgba(221, 211, 240, 0.32);
  transition: color 500ms ease, text-shadow 500ms ease;
}

.ritual-mark--top {
  top: 1.8%;
  left: 50%;
  padding: 0 0.6rem;
  font-size: clamp(0.57rem, 1.7vw, 0.68rem);
  letter-spacing: 0.2em;
  transform: translateX(-50%);
  white-space: nowrap;
}

.ritual-mark--spark-one {
  top: 16%;
  left: 10%;
  font-size: 0.62rem;
  opacity: 0.72;
  transform: rotate(-14deg);
}

.ritual-mark--moon-one {
  top: 37%;
  right: 0.5%;
  font-size: 1.08rem;
  transform: rotate(13deg);
}

.ritual-mark--star-one {
  bottom: 18%;
  left: 7%;
  font-size: 0.9rem;
  opacity: 0.82;
  transform: rotate(-9deg);
}

.ritual-mark--spark-two {
  top: 19%;
  right: 14%;
  font-size: 0.72rem;
  opacity: 0.66;
  transform: rotate(18deg);
}

.ritual-mark--star-two {
  bottom: 7%;
  left: 35%;
  font-size: 0.78rem;
  opacity: 0.7;
  transform: rotate(8deg);
}

.ritual-reveal {
  position: absolute;
  inset: 10.8%;
  z-index: 2;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 46%, rgba(232, 186, 218, 0.12), transparent 27%),
    radial-gradient(circle at 50% 50%, rgba(77, 61, 102, 0.3), rgba(12, 10, 24, 0.94) 67%);
}

.ritual-reveal::before {
  position: absolute;
  inset: 10%;
  border: 1px dotted rgba(223, 215, 238, 0.18);
  border-radius: 50%;
  content: "";
}

.constellation-heart {
  position: absolute;
  inset: 13%;
  width: 74%;
  height: 74%;
  overflow: visible;
  opacity: 0.72;
  filter: drop-shadow(0 0 3px rgba(230, 221, 244, 0.5));
  transition: opacity 600ms ease 180ms, filter 600ms ease 180ms;
}

.constellation-heart path {
  fill: rgba(236, 163, 204, 0.025);
  stroke: rgba(225, 217, 240, 0.68);
  stroke-width: 0.72;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 250;
  stroke-dashoffset: 250;
}

.constellation-heart circle {
  fill: #f4edf9;
  stroke: rgba(189, 161, 207, 0.64);
  stroke-width: 0.6;
  opacity: 0.78;
  transform-box: fill-box;
  transform-origin: center;
  filter: drop-shadow(0 0 2px #fff) drop-shadow(0 0 5px rgba(211, 193, 233, 0.82));
}

.constellation-heart circle:nth-child(3n) { fill: #efacce; }

.confession-inner .scratch-card h2 {
  position: relative;
  z-index: 2;
  max-width: 95%;
  margin: 0;
  color: #fff8fd;
  font-size: clamp(1.5rem, 6.3vw, 2.35rem);
  line-height: 1.08;
  white-space: nowrap;
  text-shadow: 0 0 0.75rem rgba(252, 235, 249, 0.54), 0 0 1.8rem rgba(232, 130, 184, 0.24);
  opacity: 0;
  transform: translateY(0.55rem) scale(0.9);
}

/* The question receives focus after a keyboard reveal. Replace the browser's
   rectangular focus ring with a glyph-shaped halo while keeping that focus. */
.confession-inner .scratch-card h2:focus {
  outline: none;
}

.confession-inner .scratch-card h2:focus-visible {
  text-shadow:
    0 0 0.2rem rgba(255, 255, 255, 0.95),
    0 0 0.75rem rgba(252, 190, 222, 0.7),
    0 0 1.6rem rgba(232, 130, 184, 0.4);
}

.scratch-card .decision-stage {
  min-height: 3rem;
  margin-top: 1.45rem;
  gap: .65rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.65rem) scale(0.96);
  transition: opacity 450ms ease 480ms, transform 650ms var(--ease-out) 430ms, visibility 0s linear 430ms;
}

.scratch-card .primary-button,
.scratch-card .no-button {
  min-width: 0;
  width: clamp(6.2rem, 25vw, 9rem);
  padding: .85rem .65rem;
}

.scratch-card .primary-button { background: #d494bd30; color: #fff1fa; border-color: #e6b5d566; box-shadow: 0 0 22px #da94be20; }
.scratch-card .no-button { background: #bab1dc16; color: #e5d9ef; border-color: #d4c1e333; }
.scratch-card .reaction {
  min-height: 1.35rem;
  margin: 0.35rem 0 0;
  color: #d8c9df;
  font-size: .85rem;
  opacity: 0;
  transition: opacity 350ms ease 600ms;
}

.scratch-cover {
  position: absolute;
  inset: 10.8%;
  z-index: 5;
  border-radius: 50%;
  overflow: hidden;
  pointer-events: none;
  box-shadow: inset 0 0 1.8rem rgba(4, 3, 12, 0.62), 0 0 1.4rem rgba(104, 81, 132, 0.14);
  transition: opacity 500ms ease, transform 650ms var(--ease-out), filter 500ms ease;
  user-select: none;
  -webkit-user-select: none;
}

.scratch-cover.is-ready { pointer-events: auto; touch-action: none; cursor: crosshair; }
.scratch-cover:focus-visible { outline: 2px solid rgba(238, 227, 247, 0.94); outline-offset: 6px; }
.scratch-cover canvas { display: block; width: 100%; height: 100%; }

.scratch-glow {
  position: absolute;
  inset: 10.8%;
  z-index: 6;
  display: block;
  width: 78.4%;
  height: 78.4%;
  border-radius: 50%;
  mix-blend-mode: screen;
  pointer-events: none;
  transition: opacity 450ms ease, filter 450ms ease;
}

.ritual-moon {
  position: absolute;
  right: -0.55rem;
  bottom: -0.35rem;
  z-index: 8;
  width: clamp(6.4rem, 23vw, 8.3rem);
  aspect-ratio: 1.12;
  opacity: var(--summon-moon-opacity);
  transform: translate3d(var(--summon-moon-x), var(--summon-moon-y), 0) scale(var(--summon-moon-scale));
  transform-origin: 70% 75%;
  pointer-events: none;
  will-change: transform, opacity;
}

.ritual-crescent {
  position: absolute;
  right: 0.4rem;
  bottom: 0;
  width: 5.15rem;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f7f2fb 0, #c9bed8 38%, #7c6b8d 72%, #43374f 100%);
  box-shadow: 0 0 0.9rem rgba(222, 211, 239, 0.32), 0 0 2rem rgba(169, 130, 183, 0.2);
  transform: rotate(-25deg);
}

.ritual-crescent::after {
  position: absolute;
  top: -0.22rem;
  left: 1.28rem;
  width: 4.55rem;
  aspect-ratio: 1;
  border-radius: 50%;
  background: #0b0916;
  box-shadow: inset 0 0 0.9rem rgba(89, 63, 104, 0.25);
  content: "";
}

.scratch-kuromi {
  position: absolute;
  right: -0.05rem;
  bottom: 0.85rem;
  z-index: 2;
  width: clamp(4rem, 14vw, 5rem);
  filter: drop-shadow(0 0.5rem 0.75rem rgba(2, 1, 8, 0.62)) drop-shadow(0 0 0.55rem rgba(227, 158, 199, 0.15));
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.scratch-kuromi img {
  display: block;
  width: 100%;
  height: auto;
}

.scratch-card.is-revealing .scratch-cover {
  opacity: 0;
  filter: blur(3px);
  transform: scale(1.035);
}
.scratch-card.is-revealing .scratch-glow { opacity: 0; filter: blur(5px); }
.scratch-card.is-awake:not(.is-revealing) .ritual-core::before { animation: ritual-breathe 5.6s ease-in-out infinite; }
.scratch-card.is-revealing .ritual-core::before { animation: ritual-awaken 700ms var(--ease-out) both; }
.scratch-card.is-revealed .constellation-heart path { animation: constellation-draw 850ms var(--ease-out) both; }
.scratch-card.is-revealed .constellation-heart { opacity: 0.56; filter: drop-shadow(0 0 2px rgba(230, 221, 244, 0.28)); }
.scratch-card.is-revealed .constellation-heart circle { animation: constellation-star 700ms var(--ease-out) both; }
.scratch-card.is-revealed .constellation-heart circle:nth-child(2n) { animation-delay: 100ms; }
.scratch-card.is-revealed .constellation-heart circle:nth-child(3n) { animation-delay: 190ms; }
.scratch-card.is-revealed .question-line { animation: ritual-question 750ms var(--ease-out) 360ms both; }
.scratch-card.is-revealed .decision-stage {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.scratch-card.is-revealed .reaction { opacity: 1; }
.scratch-card.is-revealed .ritual-mark { color: rgba(239, 224, 240, 0.9); text-shadow: 0 0 0.8rem rgba(232, 168, 207, 0.46); }

@keyframes ritual-awaken {
  45% { box-shadow: 0 0 1.2rem rgba(226, 215, 242, 0.42), 0 0 4rem rgba(225, 121, 179, 0.24), inset 0 0 2.5rem rgba(7, 5, 17, 0.62); }
}
@keyframes ritual-breathe {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(135, 110, 162, 0.08),
      0 0 2.8rem rgba(116, 81, 145, 0.22),
      0 0 5.5rem rgba(231, 127, 180, 0.08),
      inset 0 0 2.5rem rgba(7, 5, 17, 0.78),
      inset 0 1px 0 rgba(255, 255, 255, 0.11);
  }
  50% {
    box-shadow:
      0 0 0 1px rgba(206, 184, 229, 0.14),
      0 0 3.6rem rgba(145, 100, 177, 0.31),
      0 0 6.8rem rgba(231, 127, 180, 0.14),
      inset 0 0 2.1rem rgba(7, 5, 17, 0.67),
      inset 0 1px 0 rgba(255, 255, 255, 0.16);
  }
}
@keyframes constellation-draw { to { stroke-dashoffset: 0; } }
@keyframes constellation-star {
  45% { opacity: 1; transform: scale(1.8); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes ritual-question {
  /* Keep filters off this glowing text: mobile WebKit rasterizes the filtered
     heading as a rectangle, which turns its text-shadow into a visible box. */
  from { opacity: 0; transform: translateY(0.55rem) scale(0.9); }
  to { opacity: 1; transform: none; }
}

@media (max-height: 500px) {
  .confession-inner { top: 2.5rem; }
  .scratch-card { --ritual-size: min(47svh, 12rem); margin-top: 0.15rem; }
  .confession-inner .scratch-card h2 { max-width: 96%; font-size: clamp(1rem, 3vw, 1.25rem); }
  .scratch-card .decision-stage { margin-top: .25rem; min-height: 2.5rem; }
  .scratch-card .reaction { min-height: 1rem; margin-top: .2rem; }
  .ritual-moon { right: -0.3rem; bottom: -0.15rem; width: 5.5rem; }
  .ritual-crescent { width: 3.7rem; }
  .ritual-crescent::after { left: 0.95rem; width: 3.35rem; }
  .scratch-kuromi { right: 0; bottom: 0.65rem; width: 3.45rem; }
  /* 橫躺時卡片只剩兩百出頭高，拍立得跟著縮才不會超出卡片。 */
  .card-relic { width: 2.4rem; }
  .card-polaroid { width: min(44%, 7.6rem); }
  .polaroid-note { font-size: 0.82rem; padding-bottom: 0.36rem; }
}

.primary-button.is-accepted {
  opacity: 0;
  transform: scale(0.94);
  pointer-events: none;
  transition: opacity 400ms var(--ease-out), transform 600ms var(--ease-out);
}

.primary-button.is-accepted .yes-label {
  opacity: 0;
}

.no-button.is-dismissed {
  opacity: 0;
  transform: translate3d(0, 0.45rem, 0) scale(0.96);
  pointer-events: none;
  transition:
    opacity 520ms var(--ease-out),
    transform 620ms var(--ease-out);
}

.success {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: 1.5rem;
  background: transparent;
  visibility: hidden;
  pointer-events: none;
  isolation: isolate;
}

.success.is-visible {
  visibility: visible;
  pointer-events: auto;
}

.success::after {
  position: absolute;
  inset: 0;
  z-index: 2;
  content: "";
  box-shadow: inset 0 0 18vmax rgba(22, 5, 18, 0.5);
  opacity: 0;
  pointer-events: none;
}

.success-atmosphere,
.success-backdrop {
  position: absolute;
  inset: 0;
}

.success-atmosphere {
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.success-backdrop {
  background:
    radial-gradient(ellipse at 50% 39%, rgba(214, 88, 132, 0.24) 0%, transparent 36%),
    radial-gradient(ellipse at 19% 12%, rgba(140, 74, 128, 0.22) 0%, transparent 40%),
    radial-gradient(circle at 82% 84%, rgba(233, 116, 160, 0.16) 0%, transparent 34%),
    linear-gradient(165deg, #120a1c 0%, #2a1128 58%, #3a1626 100%);
  opacity: 0;
  will-change: opacity;
}

.success-backdrop::before {
  position: absolute;
  inset: -18%;
  content: "";
  background:
    radial-gradient(ellipse at 52% 43%, rgba(255, 168, 196, 0.14) 0%, transparent 38%),
    radial-gradient(circle at 72% 72%, rgba(226, 104, 152, 0.12) 0%, transparent 32%);
  opacity: 0.7;
  transform: translate3d(-1.5%, 2%, 0) scale(0.96);
  will-change: transform;
}

.success-bloom {
  position: absolute;
  top: 39.5%;
  left: 50%;
  width: min(42rem, 92vw);
  height: min(25rem, calc(var(--stage-unit) * 54));
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255, 205, 220, 0.2) 0%, rgba(230, 96, 140, 0.09) 38%, transparent 70%);
  opacity: 0;
  filter: blur(10px);
  transform: translate3d(-50%, -50%, 0) scale(0.72);
  will-change: transform, opacity;
}

.celebration-flash,
.celebration-shockwaves,
.celebration-burst,
.floating-bubbles {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.celebration-flash {
  z-index: 1;
  background:
    radial-gradient(circle at 50% 39.5%, rgba(255, 226, 238, 0.3) 0%, rgba(247, 108, 168, 0.12) 28%, transparent 66%);
  opacity: 0;
  will-change: opacity;
}

.celebration-shockwaves {
  z-index: 1;
}

.celebration-shockwave {
  position: absolute;
  top: var(--burst-origin-y, 39.5%);
  left: var(--burst-origin-x, 50%);
  width: 140vmax;
  height: 140vmax;
  border: 2px solid rgba(255, 193, 218, 0.68);
  border-radius: 50%;
  background: radial-gradient(circle, transparent 59%, rgba(248, 139, 184, 0.12) 68%, rgba(255, 218, 232, 0.06) 74%, transparent 79%);
  box-shadow:
    inset 0 0 5vmax rgba(247, 122, 172, 0.12),
    0 0 4vmax rgba(247, 122, 172, 0.18);
  opacity: 0;
  transform: translate3d(-50%, -50%, 0) scale(0.015);
  will-change: transform, opacity;
}

.celebration-shockwave--soft {
  border-color: rgba(246, 195, 143, 0.38);
  filter: blur(7px);
}

.celebration-burst {
  z-index: 3;
}

.celebration-piece {
  --piece-size: 1.25rem;
  --piece-color: rgba(255, 161, 199, 0.9);
  --piece-glow: rgba(244, 104, 164, 0.72);
  --burst-x: 0vmax;
  --burst-y: -56vmax;
  --burst-spin: 360deg;
  --burst-duration: 1300ms;
  --burst-delay: 0ms;
  position: absolute;
  top: var(--burst-origin-y, 39.5%);
  left: var(--burst-origin-x, 50%);
  width: var(--piece-size);
  height: var(--piece-size);
  opacity: 0;
  transform: translate3d(-50%, -50%, 0) scale(0.12) rotate(0deg);
  will-change: transform, opacity;
}

.celebration-piece.tone-gold {
  --piece-color: rgba(255, 224, 171, 0.94);
  --piece-glow: rgba(246, 190, 138, 0.76);
}

.celebration-piece.tone-lilac {
  --piece-color: rgba(226, 183, 255, 0.86);
  --piece-glow: rgba(190, 118, 235, 0.62);
}

.celebration-piece--bubble {
  border: 1.5px solid var(--piece-color);
  border-radius: 50%;
  background:
    radial-gradient(circle at 31% 25%, rgba(255, 255, 255, 0.88) 0 6%, transparent 8%),
    radial-gradient(circle at 64% 68%, transparent 45%, var(--piece-color) 100%);
  box-shadow:
    inset 0 0 0.8rem rgba(255, 255, 255, 0.14),
    0 0 1.2rem var(--piece-glow);
}

.celebration-piece--heart {
  display: grid;
  place-items: center;
  color: var(--piece-color);
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: calc(var(--piece-size) * 1.32);
  line-height: 1;
  text-shadow:
    0 0 0.7rem var(--piece-glow),
    0 0 1.4rem var(--piece-glow);
}

.celebration-piece--heart::before {
  content: "\2665";
}

.celebration-piece--petal {
  height: calc(var(--piece-size) * 1.18);
  border-radius: 70% 30% 68% 32% / 75% 38% 62% 25%;
  background: linear-gradient(145deg, rgba(255, 239, 246, 0.96), var(--piece-color));
  box-shadow: 0 0 0.9rem var(--piece-glow);
}

.celebration-piece--star {
  background: linear-gradient(145deg, rgba(255, 251, 229, 0.98), var(--piece-color));
  clip-path: polygon(50% 0%, 61% 37%, 100% 50%, 61% 63%, 50% 100%, 39% 63%, 0% 50%, 39% 37%);
  filter: drop-shadow(0 0 0.55rem var(--piece-glow));
}

.floating-bubbles {
  z-index: 1;
}

.floating-bubble {
  --bubble-size: 2.5rem;
  --bubble-opacity: 0.24;
  --bubble-delay: 0ms;
  --bubble-duration: 12s;
  --bubble-drift-x: 1rem;
  --bubble-drift-y: -1.8rem;
  position: absolute;
  top: var(--bubble-y);
  left: var(--bubble-x);
  width: var(--bubble-size);
  height: var(--bubble-size);
  border: 1px solid rgba(255, 184, 215, 0.48);
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 24%, rgba(255, 255, 255, 0.7) 0 5%, transparent 7%),
    radial-gradient(circle at 66% 72%, transparent 48%, rgba(246, 121, 175, 0.2) 100%);
  box-shadow:
    inset 0 0 1rem rgba(255, 223, 235, 0.1),
    0 0 1.4rem rgba(239, 104, 162, 0.16);
  opacity: 0;
  transform: translate3d(0, 1rem, 0) scale(0.86);
  will-change: transform, opacity;
}

.success-card {
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: min(50rem, 100%);
  text-align: center;
  transform: translateY(calc(var(--stage-unit) * -1.5));
}

.light-pair {
  position: relative;
  width: 10rem;
  height: 6.75rem;
  margin-bottom: clamp(0.7rem, calc(var(--stage-unit) * 2), 1.15rem);
}

.soul-light {
  --light-from-x: 0px;
  --light-from-y: 0px;
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: 3.25rem;
  height: 3.25rem;
  margin: -1.625rem 0 0 -1.625rem;
  border-radius: 50%;
  opacity: 0;
  filter: blur(3px);
  transform: translate3d(var(--light-from-x), var(--light-from-y), 0) scale(0.34);
  mix-blend-mode: screen;
  will-change: transform, opacity, filter;
}

.soul-light::before,
.soul-light::after {
  position: absolute;
  border-radius: 50%;
  content: "";
}

.soul-light::before {
  inset: 28%;
  background: rgba(255, 251, 235, 0.98);
  filter: blur(1px);
}

.soul-light::after {
  inset: -72%;
  opacity: 0.62;
  filter: blur(12px);
}

.soul-light--gold {
  --fuse-x: 1.05rem;
  left: calc(50% - 1.05rem);
  background: radial-gradient(circle, rgba(255, 249, 222, 0.98) 0 15%, rgba(245, 207, 146, 0.9) 30%, rgba(245, 192, 121, 0.2) 62%, transparent 75%);
  box-shadow: 0 0 2.8rem rgba(245, 204, 139, 0.46);
}

.soul-light--gold::after {
  background: radial-gradient(circle, rgba(244, 205, 142, 0.38), transparent 68%);
}

.soul-light--rose {
  --fuse-x: -1.05rem;
  left: calc(50% + 1.05rem);
  background: radial-gradient(circle, rgba(255, 246, 237, 0.98) 0 15%, rgba(244, 139, 170, 0.9) 30%, rgba(225, 83, 126, 0.22) 62%, transparent 75%);
  box-shadow: 0 0 2.8rem rgba(236, 106, 147, 0.48);
}

.soul-light--rose::after {
  background: radial-gradient(circle, rgba(237, 112, 150, 0.4), transparent 68%);
}

.meeting-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  width: 8.5rem;
  height: 5.5rem;
  border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255, 226, 190, 0.52) 0%, rgba(244, 137, 153, 0.18) 38%, transparent 72%);
  opacity: 0;
  filter: blur(9px);
  transform: translate3d(-50%, -50%, 0) scale(0.72);
  will-change: transform, opacity;
}

.heart-shape {
  position: absolute;
  inset: 0;
  background: var(--heart-shape-fill);
  transform: rotate(45deg);
}

.heart-shape::before,
.heart-shape::after {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--heart-shape-fill);
  content: "";
}

.heart-shape::before {
  top: -50%;
  left: 0;
}

.heart-shape::after {
  top: 0;
  left: -50%;
}

.heart-core {
  --heart-fill: linear-gradient(150deg, rgba(255, 250, 246, 0.99) 0%, rgba(253, 194, 214, 0.97) 46%, rgba(243, 132, 173, 0.94) 100%);
  --heart-aura-fill: linear-gradient(150deg, rgba(255, 219, 186, 0.6) 0%, rgba(248, 146, 184, 0.55) 52%, rgba(228, 94, 148, 0.44) 100%);
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 4;
  width: 2rem;
  height: 2rem;
  margin: -1rem 0 0 -1rem;
  opacity: 0;
  transform: translate3d(0, 0.15rem, 0) scale(0.22);
  mix-blend-mode: screen;
  pointer-events: none;
  will-change: transform, opacity, filter;
}

.heart-core__shape {
  --heart-shape-fill: var(--heart-fill);
  border-radius: 0 0 12% 0;
  filter: blur(1.3px);
}

.heart-core__aura {
  --heart-shape-fill: var(--heart-aura-fill);
  opacity: 0.92;
  filter: blur(17px);
  transform: rotate(45deg) scale(1.7);
}

.heart-burst {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: 2rem;
  height: 2rem;
  margin: -1rem 0 0 -1rem;
  mix-blend-mode: screen;
  pointer-events: none;
}

.heart-burst__wave {
  --wave-peak: 0.9;
  --wave-scale: 4;
  opacity: 0;
  transform: rotate(45deg) scale(1);
  will-change: transform, opacity;
}

.heart-burst__wave--a {
  --heart-shape-fill: linear-gradient(150deg, rgba(255, 226, 240, 0.95) 0%, rgba(250, 140, 186, 0.9) 45%, rgba(236, 86, 150, 0.75) 100%);
  --wave-peak: 0.92;
  --wave-scale: 8.5;
  filter: blur(2px);
}

.heart-burst__wave--b {
  --heart-shape-fill: linear-gradient(150deg, rgba(255, 214, 176, 0.58) 0%, rgba(248, 136, 182, 0.52) 52%, rgba(226, 88, 146, 0.34) 100%);
  --wave-peak: 0.62;
  --wave-scale: 14;
  filter: blur(14px);
}

.heart-afterglow {
  --heart-shape-fill: linear-gradient(150deg, rgba(255, 233, 244, 0.62) 0%, rgba(248, 152, 192, 0.52) 48%, rgba(232, 100, 158, 0.38) 100%);
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  width: 3.2rem;
  height: 3.2rem;
  margin: -1.6rem 0 0 -1.6rem;
  opacity: 0;
  filter: blur(8px);
  transform: scale(0.7);
  mix-blend-mode: screen;
  pointer-events: none;
  will-change: transform, opacity;
}

.success h2 {
  max-width: 100%;
  margin: 0;
  font-family: "Fredoka", system-ui, sans-serif;
  font-size: clamp(2.45rem, 6vw, 4.55rem);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.035em;
  white-space: nowrap;
  opacity: 0;
  clip-path: inset(0 0 100% 0);
  transform: translate3d(0, 1rem, 0) scale(0.985);
  will-change: transform, opacity, clip-path;
}

.success p {
  margin: clamp(1.2rem, calc(var(--stage-unit) * 2.6), 1.65rem) 0 0;
  color: rgba(255, 244, 231, 0.76);
  font-size: clamp(1rem, 2vw, 1.22rem);
  line-height: 1.75;
}

.success p span {
  display: block;
  white-space: nowrap;
  opacity: 0;
  transform: translate3d(0, 0.65rem, 0);
  will-change: transform, opacity;
}

.success.is-playing .success-backdrop {
  animation: final-warmth var(--finale-backdrop-duration) ease forwards;
}

.success.is-playing .success-backdrop::before {
  animation: warm-drift var(--finale-warm-drift-duration) ease-in-out var(--finale-warm-drift-delay) infinite alternate;
}

.success.is-playing::after {
  animation: final-vignette var(--finale-vignette-duration) ease var(--finale-vignette-delay) forwards;
}

.success.is-playing .soul-light--gold {
  animation:
    soul-meet var(--finale-gold-meet-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-gold-meet-delay) forwards,
    soul-fuse var(--finale-gold-fuse-duration) ease-in var(--finale-gold-fuse-delay) forwards;
}

.success.is-playing .soul-light--rose {
  animation:
    soul-meet var(--finale-rose-meet-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-rose-meet-delay) forwards,
    soul-fuse var(--finale-rose-fuse-duration) ease-in var(--finale-rose-fuse-delay) forwards;
}

.success.is-playing .meeting-glow {
  animation: fusion-flash var(--finale-fusion-duration) ease-out var(--finale-fusion-delay) forwards;
}

.success.is-playing .success-bloom {
  animation:
    ambient-bloom var(--finale-bloom-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-bloom-delay) forwards,
    ambient-breathe var(--finale-breathe-duration) ease-in-out var(--finale-breathe-delay) infinite alternate;
}

.success.is-playing h2 {
  animation: final-title-reveal var(--finale-title-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-title-delay) forwards;
}

.success.is-playing p span:nth-child(1) {
  animation: final-line-reveal var(--finale-line-one-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-line-one-delay) forwards;
}

.success.is-playing p span:nth-child(2) {
  animation: final-line-reveal var(--finale-line-two-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-line-two-delay) forwards;
}

.success.is-playing p span:nth-child(3) {
  animation: final-line-reveal var(--finale-line-three-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-line-three-delay) forwards;
}

.success.is-playing .celebration-flash {
  animation: celebration-flash var(--finale-flash-duration) ease-out var(--finale-flash-delay) forwards;
}

.success.is-playing .celebration-shockwave--bright {
  animation: celebration-wave var(--finale-shockwave-duration) cubic-bezier(0.12, 0.72, 0.32, 1) var(--finale-shockwave-delay) forwards;
}

.success.is-playing .celebration-shockwave--soft {
  animation: celebration-wave-soft var(--finale-soft-shockwave-duration) cubic-bezier(0.12, 0.72, 0.32, 1) var(--finale-soft-shockwave-delay) forwards;
}

.success.is-playing .celebration-piece--escape {
  animation: celebration-fly var(--burst-duration) cubic-bezier(0.12, 0.72, 0.24, 1) calc(var(--finale-burst-delay) + var(--burst-delay)) forwards;
}

/* Settlers stop where they land, dim down, then breathe in place forever. */
.success.is-playing .celebration-piece--settle {
  animation:
    celebration-settle var(--burst-duration) cubic-bezier(0.12, 0.72, 0.24, 1) calc(var(--finale-burst-delay) + var(--burst-delay)) forwards,
    celebration-drift var(--drift-duration) ease-in-out calc(var(--finale-burst-delay) + var(--burst-delay) + var(--burst-duration)) infinite alternate;
}

.success.is-playing .floating-bubble {
  animation:
    bubble-reveal var(--finale-bubble-reveal-duration) ease calc(var(--finale-bubble-delay) + var(--bubble-delay)) forwards,
    bubble-float var(--bubble-duration) ease-in-out calc(var(--finale-bubble-delay) + var(--bubble-delay)) infinite alternate;
}

.success.is-playing .heart-core {
  animation:
    heart-form var(--finale-heart-form-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-heart-form-delay) forwards,
    heart-burst-out var(--finale-heart-burst-duration) cubic-bezier(0.24, 0.7, 0.4, 1) var(--finale-heart-burst-delay) forwards;
}

.success.is-playing .heart-burst__wave--a {
  animation: burst-heart-wave var(--finale-heart-wave-a-duration) cubic-bezier(0.16, 0.84, 0.44, 1) var(--finale-heart-wave-a-delay) forwards;
}

.success.is-playing .heart-burst__wave--b {
  animation: burst-heart-wave var(--finale-heart-wave-b-duration) cubic-bezier(0.16, 0.84, 0.44, 1) var(--finale-heart-wave-b-delay) forwards;
}

.success.is-playing .heart-afterglow {
  animation:
    afterglow-settle var(--finale-afterglow-duration) cubic-bezier(0.22, 1, 0.36, 1) var(--finale-afterglow-delay) forwards,
    afterglow-breathe var(--finale-afterglow-breathe-duration) ease-in-out var(--finale-afterglow-breathe-delay) infinite alternate;
}

@keyframes final-warmth {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes final-vignette {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes warm-drift {
  from { transform: translate3d(-1.5%, 2%, 0) scale(0.96); }
  to { transform: translate3d(1.2%, -1%, 0) scale(1.025); }
}

@keyframes soul-meet {
  0% {
    opacity: 0;
    filter: blur(3px);
    transform: translate3d(var(--light-from-x), var(--light-from-y), 0) scale(0.34);
  }
  14% {
    opacity: 0.82;
  }
  70% {
    filter: blur(0.3px);
  }
  100% {
    opacity: 1;
    filter: blur(0);
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes soul-fuse {
  0% {
    opacity: 1;
    filter: blur(0);
    transform: translate3d(0, 0, 0) scale(1);
  }
  55% {
    opacity: 1;
    filter: blur(0.6px);
    transform: translate3d(calc(var(--fuse-x) * 0.72), 0, 0) scale(0.9);
  }
  100% {
    opacity: 0;
    filter: blur(4px);
    transform: translate3d(var(--fuse-x), 0, 0) scale(0.5);
  }
}

@keyframes fusion-flash {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.5);
  }
  36% {
    opacity: 0.95;
    transform: translate3d(-50%, -50%, 0) scale(1.1);
  }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.74);
  }
}

@keyframes heart-form {
  0% {
    opacity: 0;
    filter: blur(6px);
    transform: translate3d(0, 0.15rem, 0) scale(0.22);
  }
  30% {
    opacity: 1;
  }
  62% {
    filter: blur(0.7px);
    transform: translate3d(0, 0, 0) scale(0.82);
  }
  100% {
    opacity: 1;
    filter: blur(0);
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes heart-burst-out {
  0% {
    opacity: 1;
    filter: blur(0) brightness(1);
    transform: translate3d(0, 0, 0) scale(1);
  }
  18% {
    opacity: 1;
    filter: blur(0) brightness(1.9);
    transform: translate3d(0, 0, 0) scale(1);
  }
  46% {
    opacity: 0.58;
    filter: blur(6px) brightness(1.35);
    transform: translate3d(0, 0, 0) scale(2.1);
  }
  100% {
    opacity: 0;
    filter: blur(13px) brightness(1);
    transform: translate3d(0, 0, 0) scale(4.2);
  }
}

@keyframes burst-heart-wave {
  0% {
    opacity: 0;
    transform: rotate(45deg) scale(1);
  }
  16% {
    opacity: var(--wave-peak);
    transform: rotate(45deg) scale(1.6);
  }
  62% {
    opacity: calc(var(--wave-peak) * 0.55);
  }
  100% {
    opacity: 0;
    transform: rotate(45deg) scale(var(--wave-scale));
  }
}

@keyframes celebration-flash {
  0% {
    opacity: 0;
  }
  22% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes celebration-wave {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.015);
  }
  12% { opacity: 0.86; }
  58% { opacity: 0.42; }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(1);
  }
}

@keyframes celebration-wave-soft {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.02);
  }
  16% { opacity: 0.62; }
  64% { opacity: 0.28; }
  100% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.82);
  }
}

@keyframes celebration-fly {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.12) rotate(0deg);
  }
  10% {
    opacity: 1;
    transform: translate3d(-50%, -50%, 0) scale(1.08) rotate(18deg);
  }
  72% { opacity: 0.92; }
  100% {
    opacity: 0;
    transform: translate3d(calc(var(--burst-x) - 50%), calc(var(--burst-y) - 50%), 0) scale(0.72) rotate(var(--burst-spin));
  }
}

@keyframes celebration-settle {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.12) rotate(0deg);
  }
  10% {
    opacity: 1;
    transform: translate3d(-50%, -50%, 0) scale(1.08) rotate(18deg);
  }
  68% { opacity: 0.94; }
  100% {
    opacity: var(--piece-rest-opacity);
    transform: translate3d(calc(var(--burst-x) - 50%), calc(var(--burst-y) - 50%), 0) scale(0.86) rotate(var(--burst-spin));
  }
}

@keyframes celebration-drift {
  from {
    opacity: var(--piece-rest-opacity);
    transform: translate3d(calc(var(--burst-x) - 50%), calc(var(--burst-y) - 50%), 0) scale(0.86) rotate(var(--burst-spin));
  }
  to {
    opacity: calc(var(--piece-rest-opacity) * 1.4);
    transform:
      translate3d(
        calc(var(--burst-x) - 50% + var(--drift-x)),
        calc(var(--burst-y) - 50% + var(--drift-y)),
        0
      )
      scale(0.94)
      rotate(calc(var(--burst-spin) + var(--drift-spin)));
  }
}

@keyframes bubble-reveal {
  from { opacity: 0; }
  to { opacity: var(--bubble-opacity); }
}

@keyframes bubble-float {
  from { transform: translate3d(0, 0.65rem, 0) scale(0.94); }
  to { transform: translate3d(var(--bubble-drift-x), var(--bubble-drift-y), 0) scale(1.04); }
}

@keyframes afterglow-settle {
  0% { opacity: 0; transform: scale(3); }
  36% { opacity: 1; }
  100% { opacity: 0.82; transform: scale(1.5); }
}

@keyframes afterglow-breathe {
  from { opacity: 0.7; transform: scale(1.44); }
  to { opacity: 0.95; transform: scale(1.6); }
}

@keyframes ambient-bloom {
  0% {
    opacity: 0;
    transform: translate3d(-50%, -50%, 0) scale(0.72);
  }
  100% {
    opacity: 1;
    transform: translate3d(-50%, -50%, 0) scale(1);
  }
}

@keyframes ambient-breathe {
  from { transform: translate3d(-50%, -50%, 0) scale(0.98); opacity: 0.86; }
  to { transform: translate3d(-50%, -50%, 0) scale(1.035); opacity: 1; }
}

@keyframes final-title-reveal {
  0% {
    opacity: 0;
    clip-path: inset(0 0 100% 0);
    transform: translate3d(0, 1rem, 0) scale(0.985);
  }
  100% {
    opacity: 1;
    clip-path: inset(0 0 0 0);
    transform: translate3d(0, 0, 0) scale(1);
  }
}

@keyframes final-line-reveal {
  from { opacity: 0; transform: translate3d(0, 0.65rem, 0); }
  to { opacity: 1; transform: translate3d(0, 0, 0); }
}

.success.is-immediate .success-backdrop,
.success.is-immediate::after,
.success.is-immediate .soul-light,
.success.is-immediate .success-bloom,
.success.is-immediate .meeting-glow,
.success.is-immediate .heart-core,
.success.is-immediate .heart-burst__wave,
.success.is-immediate .celebration-flash,
.success.is-immediate .celebration-shockwave,
.success.is-immediate .celebration-piece,
.success.is-immediate .floating-bubble,
.success.is-immediate .heart-afterglow,
.success.is-immediate h2,
.success.is-immediate p span,
.success.is-immediate .success-particle {
  animation: none;
}

.success.is-immediate .success-backdrop,
.success.is-immediate::after {
  opacity: 1;
}

.success.is-immediate .soul-light {
  opacity: 0;
}

.success.is-immediate .heart-core {
  opacity: 1;
  filter: none;
  transform: translate3d(0, 0, 0) scale(1.15);
}

.success.is-immediate .heart-burst__wave,
.success.is-immediate .celebration-flash,
.success.is-immediate .celebration-shockwave,
.success.is-immediate .celebration-piece--escape {
  opacity: 0;
}

.success.is-immediate .celebration-piece--settle {
  opacity: var(--piece-rest-opacity);
  transform:
    translate3d(calc(var(--burst-x) - 50%), calc(var(--burst-y) - 50%), 0)
    scale(0.86)
    rotate(var(--burst-spin));
}

.success.is-immediate .floating-bubble {
  opacity: var(--bubble-opacity);
  transform: translate3d(0, 0, 0) scale(1);
}

.success.is-immediate .heart-afterglow {
  opacity: 0.82;
  transform: scale(1.5);
}

.success.is-immediate .success-bloom {
  opacity: 1;
  transform: translate3d(-50%, -50%, 0) scale(1);
}

.success.is-immediate .meeting-glow {
  opacity: 0;
}

.success.is-immediate h2 {
  opacity: 1;
  clip-path: inset(0 0 0 0);
  transform: translate3d(0, 0, 0) scale(1);
}

.success.is-immediate p span {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

.success.is-immediate .success-particle {
  opacity: 0.22;
}

body.success-open .journey-stage {
  opacity: 0;
  filter: blur(1.5px);
  transform: scale(0.985);
}

.fireworks,
.ambient__stars,
.ambient__ring {
  transition: opacity 900ms ease;
}

body.success-open .fireworks {
  opacity: 0;
}

body.success-open .ambient__stars {
  opacity: 0.12;
}

body.success-open .ambient__ring {
  opacity: 0 !important;
}

.signature {
  position: absolute;
  top: 74%;
  left: 50%;
  z-index: 1;
  width: max-content;
  max-width: 90vw;
  margin: 0;
  color: rgba(255, 255, 255, 0.4);
  text-align: center;
  font-size: 0.8rem;
  transform: translate3d(-50%, 0, 0);
  will-change: opacity;
}

/* Shared light is the visual thread from the first scene to the last. */
.ambient__breath {
  position: absolute;
  inset: -15%;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 52%, rgba(195, 142, 109, 0.2), rgba(160, 97, 123, 0.055) 36%, transparent 66%);
  will-change: transform, opacity;
}
.ambient__breath {
  opacity: 0.32;
  animation: quiet-breath 22s var(--ease-weight) infinite alternate;
}
@keyframes quiet-breath {
  from { transform: translate3d(-2%, 1%, 0) scale(0.98); opacity: 0.25; }
  to { transform: translate3d(2%, -1%, 0) scale(1.045); opacity: 0.42; }
}
.chapter-heading .number { color: #d1af98; font-weight: 600; }
.card-face h3 { color: #edcda8; }
.story-card { border-color: rgba(244, 219, 194, 0.18); }
.story-card::before {
  position: absolute;
  inset: 0;
  content: "";
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(110deg, transparent 15%, rgba(255, 218, 171, 0.4) 50%, transparent 85%);
  opacity: var(--card-light-opacity, 0);
  transform: translate3d(var(--card-light-x, -110%), 0, 0);
}
.card-illustration { transform: translate3d(0, calc((1 - var(--card-focus, 1)) * 5px), 0); }
.opening-cue {
  display: block;
  margin-top: 0;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  color: rgba(244, 224, 204, 0.68);
}
.opening-cue > span { display: inline-block; margin-left: 0.45rem; }
.primary-button:active:not(:disabled) { transform: translateY(1px) scale(calc(var(--yes-scale) * 0.985)); }
.no-button:active:not(:disabled), .replay-button:active { transform: translateY(1px) scale(0.985); }
.replay-button {
  transition: background 220ms var(--ease-out), color 220ms var(--ease-out), transform 220ms var(--ease-out);
}
.success.is-playing:not(.is-immediate) .replay-button:not([hidden]) {
  animation: replay-resolve 600ms var(--ease-out) both;
}
@keyframes replay-resolve { from { opacity: 0; } to { opacity: 1; } }
body.success-open .ambient__breath { animation-play-state: paused; }
@media (prefers-reduced-motion: no-preference) {
  /* First paint has its own hierarchy; child animation never fights the scroll transform. */
  .label-ink { display: block; animation: opening-resolve 1300ms var(--ease-out) both; }
  .intro-scene .opening-lines span { animation: opening-resolve 1050ms var(--ease-out) both; }
  .intro-scene .opening-lines span:nth-child(1) { animation-delay: 220ms; }
  .intro-scene .opening-lines span:nth-child(2) { animation-delay: 550ms; }
  .opening-cue { animation: opening-resolve 850ms var(--ease-out) 1000ms both; }
}
@keyframes opening-resolve {
  from { opacity: 0; filter: blur(3px); transform: translateY(4px); }
  to { opacity: 1; filter: blur(0); transform: translateY(0); }
}

@media (max-width: 900px) {
  .journey {
    height: 1240svh;
  }

  .journey-stage {
    min-height: 0;
  }

  .shared-label {
    font-size: clamp(1.9rem, 8.8vw, 2.85rem);
  }

  .opening-lines {
    margin-top: 0.85rem;
    padding: 0 1rem;
    font-size: 1.1rem;
  }

  .signature {
    top: 72%;
  }

  .hero-lockup {
    width: calc(100% - 2rem);
  }

  .hero-lockup h1 {
    font-size: clamp(1.45rem, 7.25vw, 2.45rem);
    line-height: 1.38;
    white-space: nowrap;
  }

  .hero-lockup .scroll-cue {
    margin: 1.6rem auto 0;
  }

  .story-scene {
    padding: 0 0.5rem;
  }

  .chapter-heading {
    top: clamp(4.5rem, calc(var(--stage-unit) * 10), 6rem);
    height: 6.2rem;
    padding: 0 0.75rem;
  }

  .chapter-heading .number {
    font-size: 0.68rem;
    letter-spacing: 0.2em;
  }

  .chapter-heading h2 {
    font-size: clamp(1.85rem, 8.6vw, 2.45rem);
  }

  .story-shell {
    --card-grid-top: clamp(13rem, calc(var(--stage-unit) * 27), 15.25rem);
    --card-grid-height: min(calc(var(--stage-unit) * 48), 24rem);
  }

  .card-grid {
    top: var(--card-grid-top);
    right: 0.5rem;
    left: 0.5rem;
    display: block;
    height: var(--card-grid-height);
  }

  /* Two cards wait behind the one being read; only the visible one breathes. */
  .story-card:not(.is-card-active) .card-moment :is(.relic-art, .card-camera, .card-connect__point, .card-relic__aura, .card-flower-bouquet),
  .story-card:not(.is-card-active) .card-action-hint {
    animation: none;
  }

  .story-card {
    position: absolute;
    inset: 0;
  }

  .card-face {
    justify-content: center;
    padding: 1.5rem 1.25rem 7.2rem;
    text-align: center;
  }

  .card-face h3 {
    font-size: clamp(1.46rem, 6.5vw, 1.89rem);
  }

  .card-face p {
    font-size: clamp(1.19rem, 5.4vw, 1.38rem);
    line-height: 1.35;
  }

  .card-face p span {
    margin-bottom: 0.85rem;
  }

  .story-card[data-card="0"] .card-face--reason,
  .story-card[data-card="1"] .card-face--memory {
    padding-bottom: 7.2rem;
  }

  /* 手機卡片高度吃緊，插畫縮小才不會撞到最後一行字。 */
  .card-illustration {
    right: 0.3rem;
    bottom: 0.25rem;
    width: 4.8rem;
  }

  /* 這張卡文字最多行，插畫再小一點才留得出空隙。 */
  .story-card[data-card="0"] .card-illustration {
    width: 3.7rem;
  }
  /* 手機卡片矮，小物與拍立得都要縮，拍立得才不會被卡片邊緣切掉。 */
  .card-relic {
    right: 0.4rem;
    bottom: 0.35rem;
    width: 2.9rem;
  }

  .card-relic--left,
  .card-polaroid--left {
    right: auto;
    left: 0.4rem;
  }

  .card-polaroid {
    right: 0.4rem;
    bottom: 0.35rem;
    width: min(56%, 10.25rem);
  }

  .card-moment {
    right: 0.5rem;
    bottom: 0.5rem;
  }

  .card-moment--mouse {
    right: auto;
    bottom: -0.3rem;
    left: -2.7rem;
    --moment-width: 7rem;
    --moment-height: 7rem;
    --mouse-run: 4.4rem;
  }

  .card-moment--shine { --moment-width: 7.5rem; --moment-height: 5rem; }
  .card-face--polaroid { padding-bottom: 8.7rem; }
  .card-moment--polaroid { --moment-width: 7.9rem; --moment-height: 7.4rem; }

  .card-memory-note {
    width: min(9.7rem, 42vw);
    font-size: 0.94rem;
  }

  .note-wrap {
    width: calc(100% - 1rem);
    height: min(23rem, calc(var(--stage-unit) * 55));
  }

  .note-surface {
    border-radius: 1.25rem;
  }

  .note-copy {
    padding: 3.4rem 0.8rem 1.5rem;
  }

  .note-copy p {
    font-size: min(5.2vw, 1.5rem);
    line-height: 1.45;
  }

  .note-copy span {
    max-width: 100%;
  }

  .note-cupid {
    top: -4rem;
    right: 0.4rem;
    width: 6rem;
  }

  .confession-inner h2 {
    font-size: clamp(2.35rem, 11vw, 3.35rem);
    line-height: 1.08;
  }

  .confession-inner .eyebrow {
    font-size: 0.7rem;
    letter-spacing: 0.22em;
  }

  .decision-stage {
    gap: 0.65rem;
    min-height: 6rem;
    margin-top: 1.4rem;
  }

  .primary-button,
  .no-button {
    min-width: 8.2rem;
    padding: 0.82rem 1.15rem;
  }

  .success {
    padding: 1rem;
  }

  .success-card {
    transform: translateY(calc(var(--stage-unit) * -1));
  }

  .light-pair {
    width: 8.75rem;
    height: 6rem;
    margin-bottom: 0.7rem;
  }

  .soul-light {
    width: 2.9rem;
    height: 2.9rem;
    margin: -1.45rem 0 0 -1.45rem;
  }

  .success h2 {
    max-width: 22rem;
    font-size: clamp(1.75rem, 8vw, 3rem);
    line-height: 1.08;
  }

  .success p {
    max-width: 100%;
    margin-top: 1.15rem;
    font-size: min(3.5vw, 1.05rem);
    line-height: 1.7;
  }

  .heart-core {
    width: 1.75rem;
    height: 1.75rem;
    margin: -0.875rem 0 0 -0.875rem;
  }

  .heart-afterglow {
    width: 2.7rem;
    height: 2.7rem;
    margin: -1.35rem 0 0 -1.35rem;
  }

  .heart-burst {
    width: 1.75rem;
    height: 1.75rem;
    margin: -0.875rem 0 0 -0.875rem;
  }

  .success-particle:nth-child(n + 8) {
    display: none;
  }

  .ambient__ring {
    width: 14rem;
    opacity: 0.075;
  }

  .ambient__ring--left {
    left: -7rem;
  }

  .ambient__ring--right {
    right: -7rem;
  }

  .firework:nth-child(1) { left: -7rem; }
  .firework:nth-child(2) { right: -5rem; }
}

@media (min-width: 600px) and (max-width: 900px) {
  .story-shell { --card-grid-height: min(calc(var(--stage-unit) * 46), 27rem); }

  .card-grid {
    right: 10vw;
    left: 10vw;
  }

  .card-face {
    padding: 2.5rem 4rem 7.4rem;
  }

  .note-wrap {
    width: min(42rem, calc(100% - 3rem));
  }
}

@media (max-width: 390px) {
  .card-face {
    padding-inline: 0.8rem;
  }

  .card-face p {
    font-size: clamp(1.08rem, 4.97vw, 1.24rem);
  }

  .note-copy {
    padding-inline: 0.45rem;
  }

  .note-copy p {
    font-size: 5.2vw;
  }

  .primary-button,
  .no-button {
    min-width: 7.6rem;
    padding-inline: 0.9rem;
  }

  .success h2 {
    font-size: clamp(1.65rem, 8vw, 2.45rem);
  }

  .success p {
    font-size: 3.5vw;
  }
}


/* Keep touch targets and copy within the iPhone safe area. */
.journey-stage {
  padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
}
.scene {
  inset: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
}
.success {
  padding: max(1rem, var(--safe-top)) max(1rem, var(--safe-right))
    max(1rem, var(--safe-bottom)) max(1rem, var(--safe-left));
}
.journey:focus, #successTitle:focus { outline: none; }
.replay-button {
  position: absolute;
  top: calc(100% + 2.75rem);
  max-width: 100%;
  min-height: 44px;
  padding: 0.45rem 0.95rem;
  border: 1px solid rgba(255, 190, 217, 0.26);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  color: rgba(255, 244, 231, 0.58);
  font-size: 0.74rem;
  letter-spacing: 0.015em;
  line-height: 1.3;
  cursor: pointer;
}
.replay-button:hover { background: rgba(255, 255, 255, 0.1); color: rgba(255, 244, 231, 0.85); }
.replay-button:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
/* Replay is a fresh first frame, without the outgoing success transition. */
body.is-restarting .journey-stage { transition: none; }

/* A phone in landscape needs tighter type/spacing, not a taller hidden stage. */
@media (max-height: 600px) and (prefers-reduced-motion: no-preference) {
  .chapter-heading { top: calc(var(--stage-unit) * 5); height: 4.5rem; }
  .chapter-heading h2 { font-size: clamp(1.5rem, 5.4vw, 2.1rem); }
  .story-shell {
    --card-grid-top: calc(var(--stage-unit) * 22);
    --card-grid-height: calc(var(--stage-unit) * 60);
  }
  .card-grid { top: var(--card-grid-top); height: var(--card-grid-height); }
  .card-navigation { gap: 0.9rem; }
  .card-face { padding: 0.9rem 17rem 0.9rem 1.25rem; text-align: left; }
  .card-face h3 { font-size: 1.25rem; margin-bottom: 0.65rem; }
  .card-face p { font-size: 1rem; line-height: 1.3; }
  .card-face p span { margin-bottom: 0.5rem; }
  .story-card[data-card="0"] .card-face--reason,
  .story-card[data-card="1"] .card-face--memory { padding: 0.9rem 17rem 0.9rem 1.25rem; }
  .card-illustration, .story-card[data-card="0"] .card-illustration { width: 4rem; }
  .note-wrap { height: calc(var(--stage-unit) * 62); }
  .note-copy { padding: 1.6rem 1.25rem 1rem; }
  .note-copy p { font-size: 1.2rem; }
  .note-cupid { width: 4rem; top: -2.7rem; }
  .confession-inner .eyebrow { margin-bottom: 0.4rem; }
  .confession-inner h2 { font-size: clamp(1.7rem, 4.8vw, 2.7rem); }
  .decision-stage { min-height: 3.5rem; margin-top: 0.65rem; }
  .reaction { margin: 0.2rem 0 0; min-height: 1.5rem; font-size: 0.85rem; }
  .success-card { transform: translateY(-1.5rem); }
  .light-pair { height: 3.5rem; margin-bottom: 0.4rem; }
  .success h2 { font-size: clamp(1.4rem, 4.7vw, 2rem); }
  .success p { font-size: 0.9rem; line-height: 1.5; margin-top: 0.6rem; }
  .replay-button { top: calc(100% + 1.35rem); font-size: 0.7rem; min-height: 44px; padding: 0.35rem 0.8rem; }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .ambient__wash,
  .ambient__stars,
  .ambient__ring {
    transform: none !important;
  }

  .journey {
    height: auto;
  }

  .journey-stage {
    position: relative;
    height: auto;
    min-height: 0;
    overflow: visible;
  }

  .scene {
    position: relative;
    min-height: 100svh;
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    pointer-events: auto;
  }

  .shared-label {
    position: absolute;
    top: 50svh;
    opacity: 1 !important;
    transform: translate3d(-50%, -5rem, 0) !important;
  }

  .opening-lines,
  .signature,
  .hero-lockup,
  .chapter-heading__layer,
  .story-card,
  .card-face,
  .note-surface,
  .note-copy,
  .note-copy span,
  .note-cupid,
  .confession-inner,
  .decision-stage {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }

  .portal-line,
  .shared-heart,
  .note-glow {
    display: none;
  }

  .story-scene {
    min-height: auto;
    padding-block: 6rem;
  }

  .story-shell {
    height: auto;
  }

  .chapter-heading {
    position: relative;
    top: auto;
    height: auto;
    margin-bottom: 2.5rem;
  }

  .chapter-heading__layer {
    position: relative;
    margin-bottom: 2rem;
  }

  .card-grid {
    position: relative;
    top: auto;
    height: auto;
  }

  .story-card {
    min-height: 32rem;
  }

  .card-face {
    position: relative;
    min-height: 15rem;
  }

  .card-face--reason {
    border-top: 1px solid rgba(255, 255, 255, 0.12);
  }

  .signature {
    position: relative;
    top: auto;
    left: auto;
    width: auto;
    max-width: none;
    margin-top: 2rem;
  }

  .note-wrap {
    position: relative;
    top: auto;
    left: auto;
    transform: none !important;
  }

  .note-surface {
    position: relative;
  }

  .note-copy p {
    display: block;
  }

  .note-copy span {
    grid-area: auto;
    max-width: none;
    margin-bottom: 1rem;
  }

  .confession-scene {
    min-height: 100svh;
  }

  .confession-scene .decision-stage {
    pointer-events: auto;
  }

  .success-particle {
    animation: none !important;
    opacity: 0.18;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; filter: none !important; }
  .ambient__breath, .opening-cue, .fireworks { display: none; }
  .opening-lines { position: relative; top: auto; left: auto; width: 100%; margin-top: 4rem; }
  .signature { position: absolute; top: 76svh; width: 100%; }
  .story-card { position: relative; inset: auto; margin-bottom: 1rem; }
  .card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); gap: 1rem; }
  .card-face { min-height: 17rem; }
  .note-wrap, .note-surface { height: auto; min-height: 0; }
  .note-wrap { margin-block: 4rem; }
  .note-copy { position: relative; padding: 3rem 1rem; }
  .note-copy span { white-space: normal; }
  .note-cupid { display: none; }
  .success { overflow-y: auto; }
  .success-card { margin-block: 4rem; }
}

body.is-restarting .label-ink, body.is-restarting .opening-lines span, body.is-restarting .opening-cue { animation: none !important; }

/* ── Card reveal rituals ──────────────────────────────────────────────────
   The heading stays visible. A large keepsake hides the three original lines
   until its own gesture completes; the reveal then persists until replay. */
.story-card .card-face[data-reveal] {
  justify-content: flex-start;
  padding: clamp(1.4rem, 2.3vw, 1.85rem);
  text-align: center;
}

.card-face[data-reveal] h3 {
  position: relative;
  z-index: 8;
}

.card-copy {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: min(calc(100% - 2.8rem), 32rem);
  text-align: center;
  visibility: hidden;
  transform: translate(-50%, -50%);
}

.card-copy span {
  opacity: 0;
  filter: blur(7px);
  transform: translate3d(0, 0.9rem, 0) scale(0.96);
}

.card-face.is-revealed .card-copy {
  visibility: visible;
}

.card-face.is-revealed .card-copy span {
  opacity: 1;
  filter: none;
  transform: none;
}

.card-face[data-reveal] .card-moment {
  --relic-size: min(60%, 11rem);
  position: absolute;
  inset: 4.2rem 0.65rem 0.55rem;
  z-index: 5;
  width: auto;
  height: auto;
  pointer-events: none;
}

.card-face[data-reveal] .card-moment :where(.card-relic) {
  position: absolute;
  top: 48%;
  right: auto;
  bottom: auto;
  left: 50%;
  z-index: 4;
  width: var(--relic-size);
  min-width: 4.5rem;
  height: auto;
  min-height: 4.5rem;
  aspect-ratio: 1;
  margin: 0;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 1.4rem;
  background: none;
  color: inherit;
  transform: translate(-50%, -50%);
  transform-origin: center;
  pointer-events: auto;
  /* The story only moves when the page scrolls, so a finger resting on a relic
     must still be able to pan. The browser keeps the vertical axis; anything
     sideways or free-form is left for the card's own gesture to claim. */
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* Connecting the drinks is a free-form drag. Keep Safari from promoting a
   slightly diagonal connection into a native page pan while the finger is
   inside the milk-tea touch target; the rest of the card still scrolls. */
.card-face[data-reveal] .card-moment--milktea .card-relic {
  touch-action: none;
}

.card-face[data-reveal] .card-relic:focus-visible,
.card-replay:focus-visible {
  outline: 2px solid rgba(255, 225, 178, 0.96);
  outline-offset: 4px;
}

.card-face[data-reveal] .relic-art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  filter:
    drop-shadow(0 0.8rem 1.15rem rgba(0, 0, 0, 0.34))
    drop-shadow(0 0 1rem rgba(255, 175, 215, 0.13));
}

.card-face[data-reveal] .card-relic__aura {
  position: absolute;
  inset: 8% -7%;
  z-index: -1;
  border-radius: 50%;
  background:
    radial-gradient(circle at 42% 44%, rgba(255, 226, 179, 0.3), transparent 55%),
    radial-gradient(circle at 67% 56%, rgba(244, 132, 185, 0.3), transparent 66%);
  opacity: 0.45;
  filter: blur(10px);
}

.card-action-hint {
  position: absolute;
  bottom: 0.05rem;
  left: 50%;
  z-index: 7;
  min-height: 1rem;
  color: rgba(255, 237, 218, 0.86);
  font-family: "Nunito", system-ui, sans-serif;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  line-height: 1.2;
  text-align: center;
  text-shadow: 0 0 0.9rem rgba(245, 137, 188, 0.72);
  text-transform: uppercase;
  transform: translateX(-50%);
  white-space: nowrap;
}

.card-moment.is-revealing .card-action-hint,
.card-moment.is-revealed .card-action-hint {
  opacity: 0;
  visibility: hidden;
}

/* The last card in each chapter has no next-card arrow. Once its moment is
   open, this cue appears below the three dots to point back to page scrolling. */
.card-navigation .card-scroll-hint {
  position: absolute;
  top: calc(50% + 1rem);
  right: 0;
  left: 0;
  z-index: 9;
  margin: 0;
  color: rgba(255, 237, 218, 0.9);
  font-family: "Nunito", system-ui, sans-serif;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  line-height: 1.2;
  opacity: 0;
  pointer-events: none;
  text-align: center;
  text-shadow: 0 0 0.9rem rgba(245, 137, 188, 0.72);
  text-transform: uppercase;
  transform: translateY(-0.25rem);
  visibility: hidden;
  white-space: nowrap;
}

.card-navigation .card-scroll-hint.is-visible {
  opacity: 1;
  transform: none;
  visibility: visible;
}

.card-navigation .card-scroll-hint span {
  display: block;
  margin: 0.18rem auto 0;
}

@media (prefers-reduced-motion: no-preference) {
  .card-navigation .card-scroll-hint {
    transition: opacity 320ms var(--ease-out), transform 360ms var(--ease-out), visibility 0s linear 360ms;
  }

  .card-navigation .card-scroll-hint.is-visible {
    transition-delay: 180ms, 180ms, 0s;
  }

  .card-navigation .card-scroll-hint.is-visible span {
    animation: card-scroll-cue 1.45s ease-in-out infinite;
  }

  @keyframes card-scroll-cue {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(0.28rem); }
  }
}

.card-replay {
  position: absolute;
  right: 0.18rem;
  bottom: 0.18rem;
  z-index: 9;
  display: grid;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  padding: 0;
  border: 1px solid rgba(255, 224, 181, 0.24);
  border-radius: 50%;
  background: rgba(24, 22, 44, 0.62);
  color: rgba(255, 231, 202, 0.94);
  font-size: 0.68rem;
  line-height: 1;
  opacity: 0;
  box-shadow: 0 0 0.65rem rgba(245, 135, 184, 0.2);
  transform: scale(0.7) rotate(-50deg);
  pointer-events: none;
  cursor: pointer;
}

/* The mark stays small; the touch target keeps its comfortable reach. */
.card-replay::before {
  position: absolute;
  inset: -0.55rem;
  content: "";
}

.card-moment.is-revealed .card-replay {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* Once the keepsake has settled it is scenery, not a control. */
.card-moment.is-revealed .card-relic {
  pointer-events: none;
}

/* The source art is far larger than its box, so promote it for the reveal
   instead of re-rasterising the bitmap on every scale step. */
.card-moment.is-revealing .card-relic,
.card-moment.is-revealing .card-drink,
.card-moment.is-revealing .relic-art,
.card-moment.is-revealing .card-photo-print {
  will-change: transform, opacity;
}

/* Every moment ends the same way: enlarged and faded in behind the copy. */
.card-moment.is-revealed { z-index: 1; }

.card-face[data-reveal] .card-moment.is-revealed .card-relic {
  top: 52%;
  left: 50%;
  z-index: 1;
  opacity: 0.08;
  transform: translate(-50%, -50%) scale(1.42);
  /* Softened so the memory copy reads cleanly over it. */
  filter: blur(5px);
}

/* Let the bouquet fill a little more of the card once it becomes scenery. */
.card-face[data-reveal="flower"] .card-moment.is-revealed .card-relic {
  top: 50%;
  transform: translate(-50%, -50%) scale(1.8);
}

.card-face[data-reveal] .card-moment-effects,
.card-face[data-reveal] .card-moment-effects i {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.card-face[data-reveal] .card-moment-effects i {
  inset: auto;
  display: block;
  opacity: 0;
}

/* Beer: two real choices become a small pair after the toast. */
.card-moment--beer .card-drinks {
  position: absolute;
  inset: 0;
}

.card-face[data-reveal] .card-moment--beer .card-drink {
  top: 47%;
  width: min(43%, 7.4rem);
  height: min(78%, 12rem);
  min-width: 4.75rem;
  aspect-ratio: auto;
}

.card-face[data-reveal] .card-moment--beer .card-drink--can { --drink-scale: 1; left: 31%; }
.card-face[data-reveal] .card-moment--beer .card-drink--bottle { --drink-scale: 1.14; left: 69%; }
.card-moment--beer .card-drink--bottle .relic-art { transform: scale(1.14); }

.card-face[data-reveal] .card-moment--beer.is-revealed .card-drink--can {
  top: 52%;
  left: 40%;
  z-index: 1;
  opacity: 0.08;
  transform: translate(-50%, -50%) scale(1.42) rotate(-5deg);
  /* Softened so the memory copy reads cleanly over it. */
  filter: blur(5px);
}

.card-face[data-reveal] .card-moment--beer.is-revealed .card-drink--bottle {
  top: 52%;
  left: 60%;
  z-index: 1;
  opacity: 0.08;
  transform: translate(-50%, -50%) scale(1.42) rotate(5deg);
  /* Softened so the memory copy reads cleanly over it. */
  filter: blur(5px);
}

.card-moment--beer .card-moment-effects i {
  left: 50%;
  bottom: 24%;
  width: 0.5rem;
  height: 0.5rem;
  border: 1px solid rgba(255, 229, 170, 0.8);
  border-radius: 50%;
  background: rgba(255, 245, 218, 0.14);
  box-shadow: 0 0 0.8rem rgba(246, 188, 88, 0.55);
}

.card-moment--beer .card-moment-effects i:nth-child(2) { left: 43%; width: 0.34rem; height: 0.34rem; }
.card-moment--beer .card-moment-effects i:nth-child(3) { left: 58%; width: 0.28rem; height: 0.28rem; }
.card-moment--beer .card-moment-effects i:nth-child(4) { left: 37%; width: 0.42rem; height: 0.42rem; }
.card-moment--beer .card-moment-effects i:nth-child(5) { left: 64%; width: 0.38rem; height: 0.38rem; }
.card-moment--beer .card-moment-effects i:nth-child(6) { left: 52%; width: 0.24rem; height: 0.24rem; }

/* Mouse: burrowed into the left edge with only its tail out, so the art is
   turned a quarter-turn and the body is parked outside the card. */
.card-moment--mouse { --relic-size: min(58%, 10.25rem); }

.card-face[data-reveal] .card-moment--mouse .card-relic {
  top: 48%;
  left: -10%;
  transform: translate(-50%, -50%);
}

.card-face[data-reveal] .card-moment--mouse .relic-art {
  transform: rotate(-90deg);
}

/* Translate first, then the quarter-turn, so the drag still reads as sideways. */
.card-moment--mouse.is-gesturing .relic-art {
  transform: translateX(var(--gesture-x, 0)) rotate(-90deg);
}

.card-face[data-reveal] .card-moment--mouse.is-revealed .relic-art {
  transform: none;
}

.card-moment--mouse .card-moment-effects i {
  top: 48%;
  left: 55%;
  width: auto;
  height: auto;
  color: rgba(255, 171, 205, 0.95);
  font-style: normal;
  font-size: 0.9rem;
  text-shadow: 0 0 0.9rem rgba(255, 116, 176, 0.82);
}

.card-moment--mouse .card-moment-effects i:nth-child(2) { top: 36%; left: 65%; font-size: 0.7rem; }
.card-moment--mouse .card-moment-effects i:nth-child(3) { top: 56%; left: 73%; font-size: 0.55rem; }

/* Photo: the print rises out of the camera, is held, then sinks in behind. */
.card-moment--photo { --relic-size: min(66%, 11.5rem); }

.card-face[data-reveal] .card-moment--photo .card-relic {
  aspect-ratio: 1;
}

.card-camera {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  filter: drop-shadow(0 0.9rem 1.25rem rgba(0, 0, 0, 0.36));
}

.card-moment--photo .card-photo-print {
  box-sizing: border-box;
  position: absolute;
  top: 42%;
  left: 50%;
  z-index: 2;
  display: block;
  width: 62%;
  aspect-ratio: 1.32;
  padding: 4.5% 4.5% 13%;
  border-radius: 2%;
  background: linear-gradient(158deg, #fffdf7, #f2eadc 70%, #e6d9c6);
  opacity: 0;
  box-shadow: 0 0.5rem 1.2rem rgba(0, 0, 0, 0.42), 0 0 0 1px rgba(255, 255, 255, 0.45) inset;
  transform: translate(-50%, -50%);
  transform-origin: center;
  pointer-events: none;
}

.card-moment--photo .card-photo-print .polaroid-photo {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 0.12rem;
  object-fit: cover;
  opacity: 0.38;
  filter: brightness(0.34) contrast(0.55) saturate(0.12) blur(4px);
}

.card-photo-flash {
  position: absolute;
  inset: -8%;
  z-index: 8;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 247, 0.98), rgba(255, 233, 190, 0.5) 32%, transparent 70%);
  opacity: 0;
  pointer-events: none;
}

.card-face[data-reveal] .card-moment--photo.is-revealed .card-relic {
  top: 48%;
  left: 50%;
  opacity: 1;
  transform: translate(-50%, -50%);
}

.card-moment--photo.is-revealed .card-camera { opacity: 0; }

.card-moment--photo.is-revealed .card-photo-print {
  top: 52%;
  z-index: 5;
  opacity: 0.08;
  transform: translate(-50%, -50%) scale(2.3);
  /* Softened so the memory copy reads cleanly over it. */
  filter: blur(5px);
}

.card-moment--photo.is-revealed .card-photo-print .polaroid-photo {
  opacity: 1;
  filter: none;
}

/* Flower: the bouquet stays visible. A first tap puffs a few petals out of its
   flower heads, a second one shakes the whole bunch open. Only transform and
   opacity move on the large bitmap to keep Safari stable. */
.card-moment--flower { --relic-size: min(64%, 11.25rem); }

.card-moment--flower .card-action-hint { pointer-events: none; }

.card-flower-scene {
  position: absolute;
  inset: -5%;
  display: block;
  overflow: visible;
  pointer-events: none;
}

.card-face[data-reveal] .card-flower-bouquet {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: none;
  transform: rotate(6deg);
  transform-origin: 50% 74%;
}

/* The second hint replaces the first once the bunch has answered a tap. */
.card-action-hint--again { opacity: 0; visibility: hidden; }
.card-moment[data-stage="puffed"] .card-action-hint { opacity: 0; visibility: hidden; }
.card-moment[data-stage="puffed"]:not(.is-revealing):not(.is-revealed) .card-action-hint--again {
  opacity: 1;
  visibility: visible;
}

.card-moment--flower.is-revealed .card-flower-bouquet {
  opacity: 1;
  transform: rotate(6deg);
}

/* The bouquet's own button owns a stacking context, so the petals need to sit
   above it or they leave the flower heads behind the artwork. */
.card-face[data-reveal] .card-moment--flower .card-moment-effects { z-index: 5; }

/* The revealing face resets every effect to `inset: auto` with a heavier
   selector, so the petals have to out-weigh it to start at the flower heads
   instead of the card's top-left corner. */
.card-face[data-reveal] .card-moment--flower .card-moment-effects i {
  top: 33%;
  left: 50%;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  color: #ffe4a9;
  font-size: 1.2rem;
  font-style: normal;
  line-height: 1;
  text-shadow: 0 0 0.8rem rgba(255, 141, 190, 0.86);
}

.card-moment--flower .card-moment-effects i::before { content: "✿"; }
/* The first four are the small puff, and they lead the wide scatter as well. */
.card-moment--flower .card-moment-effects i:nth-child(1) { --flower-x: -6.2rem; --flower-y: -3.4rem; --puff-x: -1.5rem; --puff-y: -2.5rem; --flower-spin: -24deg; color: #ffd3e6; }
.card-moment--flower .card-moment-effects i:nth-child(2) { --flower-x: 6.4rem; --flower-y: -3.8rem; --puff-x: 1.6rem; --puff-y: -2.8rem; --flower-spin: 20deg; color: #f89bc3; font-size: 1rem; }
.card-moment--flower .card-moment-effects i:nth-child(3) { --flower-x: -8rem; --flower-y: -1.2rem; --puff-x: -0.6rem; --puff-y: -3.3rem; --flower-spin: -15deg; color: #fff2c6; font-size: 0.9rem; }
.card-moment--flower .card-moment-effects i:nth-child(4) { --flower-x: 8.2rem; --flower-y: -0.9rem; --puff-x: 0.7rem; --puff-y: -3.2rem; --flower-spin: 18deg; color: #f6b5da; }
.card-moment--flower .card-moment-effects i:nth-child(5) { --flower-x: -7.4rem; --flower-y: 2.6rem; --flower-spin: -12deg; color: #d8f2b0; font-size: 0.95rem; }
.card-moment--flower .card-moment-effects i:nth-child(6) { --flower-x: 7.6rem; --flower-y: 2.9rem; --flower-spin: 14deg; color: #ffd7a1; font-size: 1.05rem; }
.card-moment--flower .card-moment-effects i:nth-child(7) { --flower-x: -1.8rem; --flower-y: -5.4rem; --flower-spin: 26deg; color: #fff2c6; font-size: 0.85rem; }
.card-moment--flower .card-moment-effects i:nth-child(8) { --flower-x: 2rem; --flower-y: -5.8rem; --flower-spin: -20deg; color: #ffd3e6; font-size: 1.1rem; }
.card-moment--flower .card-moment-effects i:nth-child(9) { --flower-x: -5.6rem; --flower-y: 4.6rem; --flower-spin: -30deg; color: #f6b5da; font-size: 0.8rem; }
.card-moment--flower .card-moment-effects i:nth-child(10) { --flower-x: 5.8rem; --flower-y: 4.9rem; --flower-spin: 22deg; color: #d8f2b0; font-size: 0.9rem; }
.card-moment--flower .card-moment-effects i:nth-child(11) { --flower-x: -3rem; --flower-y: 6rem; --flower-spin: 16deg; color: #ffd7a1; font-size: 1rem; }
.card-moment--flower .card-moment-effects i:nth-child(12) { --flower-x: 3.2rem; --flower-y: 6.2rem; --flower-spin: -18deg; color: #f89bc3; font-size: 0.85rem; }

/* Live: a pat on the head, then the character fades back into the card. */
.card-moment--live { --relic-size: min(56%, 9.8rem); }

/* Little hearts rise off the head, so they are glyphs rather than dots. */
.card-moment--live .card-moment-effects i {
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  color: rgba(255, 164, 201, 0.98);
  font-style: normal;
  font-size: 0.9rem;
  text-shadow: 0 0 0.8rem rgba(255, 121, 177, 0.86);
  box-shadow: none;
}

.card-moment--live .card-moment-effects i:nth-child(1) { top: 30%; left: 42%; }
.card-moment--live .card-moment-effects i:nth-child(2) { top: 24%; left: 53%; }
.card-moment--live .card-moment-effects i:nth-child(3) { top: 37%; left: 61%; }
.card-moment--live .card-moment-effects i:nth-child(4) { top: 42%; left: 35%; }

/* Milk tea: the pointer draws a real line between the two supplied cups. */
.card-moment--milktea { --relic-size: min(69%, 12rem); }

.card-connect {
  position: absolute;
  inset: 0;
  z-index: 5;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.card-connect__line {
  stroke: url(#connectBeam);
  stroke-width: 1.05;
  stroke-linecap: round;
  opacity: 0;
  /* Thin core, wide bloom: the brightness lives in the halo, like the scratch spark. */
  filter:
    drop-shadow(0 0 0.12rem rgba(255, 255, 255, 1))
    drop-shadow(0 0 0.35rem rgba(236, 248, 255, 0.9))
    drop-shadow(0 0 0.9rem rgba(178, 228, 255, 0.75))
    drop-shadow(0 0 1.8rem rgba(150, 205, 255, 0.5));
}

/* A soft halo under the core line, so the pair reads as a beam of light. */
.card-connect__glow {
  stroke: rgba(206, 236, 255, 0.3);
  stroke-width: 3.4;
  stroke-linecap: round;
  opacity: 0;
  filter: blur(3px) drop-shadow(0 0 1.1rem rgba(176, 216, 255, 0.75));
}

.card-connect__point {
  fill: rgba(214, 240, 255, 0.14);
  stroke: rgba(255, 255, 255, 1);
  stroke-width: 0.7;
  filter:
    drop-shadow(0 0 0.1rem rgba(255, 255, 255, 1))
    drop-shadow(0 0 0.32rem rgba(238, 250, 255, 0.95))
    drop-shadow(0 0 0.8rem rgba(178, 228, 255, 0.8))
    drop-shadow(0 0 1.6rem rgba(150, 205, 255, 0.5));
  transform-box: fill-box;
  transform-origin: center;
}

.card-moment--milktea.is-gesturing .card-connect__line,
.card-moment--milktea.is-revealing .card-connect__line,
.card-moment--milktea.is-gesturing .card-connect__glow,
.card-moment--milktea.is-revealing .card-connect__glow {
  opacity: 1;
}

.card-moment--milktea.is-revealed .card-connect {
  visibility: hidden;
  opacity: 0;
}

.card-moment--milktea .card-moment-effects i:first-child {
  top: 43%;
  left: 51%;
  width: auto;
  height: auto;
  color: rgba(255, 167, 205, 0.98);
  font-style: normal;
  font-size: 1.35rem;
  text-shadow: 0 0 1rem rgba(255, 114, 177, 0.9);
}

.card-moment--milktea .card-moment-effects i:not(:first-child) {
  top: 48%;
  left: 50%;
  width: 2.4rem;
  height: 2.4rem;
  margin: -1.2rem;
  border: 1px solid rgba(255, 203, 225, 0.72);
  border-radius: 50%;
}

@media (prefers-reduced-motion: no-preference) {
  .card-action-hint,
  .card-replay,
  .card-face[data-reveal] .card-moment .card-relic,
  .card-face[data-reveal] .relic-art {
    transition: opacity 320ms var(--ease-out), transform 360ms var(--ease-out), filter 360ms ease-out;
  }

  .card-action-hint { animation: reveal-hint 2.3s ease-in-out infinite; }
  .card-moment[data-state="idle"] .card-relic__aura { animation: reveal-aura 2.8s ease-in-out infinite; }
  .card-moment--beer[data-state="idle"] .card-drink--can .relic-art { animation: hint-drink-left 2.6s ease-in-out infinite; }
  .card-moment--beer[data-state="idle"] .card-drink--bottle .relic-art { animation: hint-drink-right 2.6s 180ms ease-in-out infinite; }
  .card-moment--mouse[data-state="idle"] .relic-art { animation: hint-mouse-tail 2.2s ease-in-out infinite; }
  .card-moment--photo[data-state="idle"] .card-camera { animation: hint-camera 2.8s ease-in-out infinite; }
  .card-moment--flower[data-state="idle"] .card-flower-bouquet { animation: hint-flower 3s ease-in-out infinite; }
  .card-moment--live[data-state="idle"] .relic-art { animation: hint-pat 2.4s ease-in-out infinite; }
  .card-moment--milktea[data-state="idle"] .card-connect__point { animation: hint-connect 1.7s ease-in-out infinite; }
  .card-moment--milktea[data-state="idle"] .card-connect__point--right { animation-delay: 240ms; }

  .card-face.is-revealing .card-copy span {
    animation-duration: 820ms;
    animation-delay: var(--line-delay);
    animation-timing-function: var(--ease-out);
    animation-fill-mode: both;
  }
  .card-face.is-revealing .card-copy span:nth-child(1) { --line-delay: 900ms; }
  .card-face.is-revealing .card-copy span:nth-child(2) { --line-delay: 1740ms; }
  .card-face.is-revealing .card-copy span:nth-child(3) { --line-delay: 2580ms; }
  .card-face[data-reveal="beer"].is-revealing .card-copy span { animation-name: reveal-copy-bubble; }
  .card-face[data-reveal="mouse"].is-revealing .card-copy span { animation-name: reveal-copy-pop; }
  .card-face[data-reveal="photo"].is-revealing .card-copy span { animation-name: reveal-copy-develop; }
  .card-face[data-reveal="flower"].is-revealing .card-copy span { animation-name: reveal-copy-shine; }
  .card-face[data-reveal="live"].is-revealing .card-copy span { animation-name: reveal-copy-rise; }
  .card-face[data-reveal="milktea"].is-revealing .card-copy span { animation-name: reveal-copy-side; }
  .card-face[data-reveal="milktea"].is-revealing .card-copy span:nth-child(even) { --line-direction: -1; }

  .card-moment--beer.is-revealing .card-drink--can { animation: reveal-beer-can-close 3.2s linear both; }
  .card-moment--beer.is-revealing .card-drink--bottle { animation: reveal-beer-bottle-close 3.2s linear both; }
  .card-moment--beer.is-revealing[data-choice="can"] .card-drink--can .relic-art,
  .card-moment--beer.is-revealing[data-choice="bottle"] .card-drink--bottle .relic-art { animation: reveal-picked-drink 700ms var(--ease-out) both; }
  .card-moment--beer.is-revealing .card-moment-effects i { animation: reveal-bubble 1.6s 520ms ease-out both; }
  .card-moment--beer.is-revealing .card-moment-effects i:nth-child(2) { animation-delay: 660ms; }
  .card-moment--beer.is-revealing .card-moment-effects i:nth-child(3) { animation-delay: 800ms; }
  .card-moment--beer.is-revealing .card-moment-effects i:nth-child(4) { animation-delay: 940ms; }
  .card-moment--beer.is-revealing .card-moment-effects i:nth-child(5) { animation-delay: 1080ms; }
  .card-moment--beer.is-revealing .card-moment-effects i:nth-child(6) { animation-delay: 1220ms; }

  .card-moment--mouse.is-revealing .card-relic { animation: reveal-mouse-watermark 2.6s linear both; }
  .card-moment--mouse.is-revealing .relic-art { animation: reveal-mouse-upright 2.6s linear both; }
  .card-moment--mouse.is-revealing .card-moment-effects i { animation: reveal-mouse-heart 1s 620ms ease-out both; }
  .card-moment--mouse.is-revealing .card-moment-effects i:nth-child(2) { animation-delay: 820ms; }
  .card-moment--mouse.is-revealing .card-moment-effects i:nth-child(3) { animation-delay: 1020ms; }

  .card-moment--photo.is-revealing .card-photo-flash { animation: reveal-photo-flash 620ms ease-out both; }
  .card-moment--photo.is-revealing .card-photo-print { animation: reveal-photo-emerge 3.6s linear both; }
  .card-moment--photo.is-revealing .card-photo-print .polaroid-photo { animation: reveal-photo-develop 900ms 420ms ease-out both; }
  .card-moment--photo.is-revealing .card-camera { animation: reveal-camera-away 700ms 2700ms var(--ease-out) both; }

  .card-moment--flower.is-revealing .card-relic { animation: reveal-flower-watermark 3.4s linear both; }
  /* The nudge answers the tap, then the bunch goes back to breathing so it
     still reads as waiting for the second one. */
  .card-moment--flower[data-stage="puffed"]:not(.is-revealing) .card-flower-bouquet {
    animation: bloom-nudge 620ms var(--ease-out), hint-flower 3s 620ms ease-in-out infinite;
  }
  .card-moment--flower[data-stage="puffed"]:not(.is-revealing) .card-moment-effects i:nth-child(-n+4) { animation: bloom-puff 1.1s 60ms ease-out both; }
  .card-moment--flower[data-stage="puffed"]:not(.is-revealing) .card-moment-effects i:nth-child(2) { animation-delay: 130ms; }
  .card-moment--flower[data-stage="puffed"]:not(.is-revealing) .card-moment-effects i:nth-child(3) { animation-delay: 200ms; }
  .card-moment--flower[data-stage="puffed"]:not(.is-revealing) .card-moment-effects i:nth-child(4) { animation-delay: 270ms; }
  .card-moment--flower.is-revealing .card-flower-bouquet { animation: reveal-flower-bouquet 900ms 40ms var(--ease-out) both; }
  .card-moment--flower.is-revealing .card-moment-effects i { animation: reveal-flower-bloom 1.4s 180ms ease-out both; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(2) { animation-delay: 230ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(3) { animation-delay: 280ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(4) { animation-delay: 330ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(5) { animation-delay: 390ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(6) { animation-delay: 440ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(7) { animation-delay: 300ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(8) { animation-delay: 360ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(9) { animation-delay: 500ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(10) { animation-delay: 540ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(11) { animation-delay: 600ms; }
  .card-moment--flower.is-revealing .card-moment-effects i:nth-child(12) { animation-delay: 650ms; }

  .card-moment--live.is-revealing .card-relic { animation: reveal-head-pat 2.8s linear both; }
  .card-moment--live.is-revealing .card-moment-effects i { animation: reveal-pat-heart 1.15s ease-out both; }
  .card-moment--live.is-revealing .card-moment-effects i:nth-child(2) { animation-delay: 120ms; }
  .card-moment--live.is-revealing .card-moment-effects i:nth-child(3) { animation-delay: 240ms; }
  .card-moment--live.is-revealing .card-moment-effects i:nth-child(4) { animation-delay: 360ms; }

  .card-moment--milktea.is-revealing .card-relic { animation: reveal-milktea-watermark 3.1s linear both; }
  .card-moment--milktea.is-revealing .card-connect__line,
  .card-moment--milktea.is-revealing .card-connect__glow { animation: reveal-connection 1.25s ease-out both; }
  .card-moment--milktea.is-revealing .card-connect__point { animation: reveal-connect-point 1.25s ease-out both; }
  .card-moment--milktea.is-revealing .card-moment-effects i:first-child { animation: reveal-connect-heart 1.15s 280ms var(--ease-out) both; }
  .card-moment--milktea.is-revealing .card-moment-effects i:not(:first-child) { animation: reveal-connect-ring 1.2s 220ms ease-out both; }
  .card-moment--milktea.is-revealing .card-moment-effects i:nth-child(3) { animation-delay: 420ms; }

  /* Beer: the pair leans in until the rims meet, then parks along the base. */
  @keyframes reveal-beer-can-close {
    0% { top: 47%; left: 31%; opacity: 1; transform: translate(-50%, -50%) rotate(-2deg) scale(1); animation-timing-function: var(--ease-lead); }
    18% { top: 47%; left: 31%; opacity: 1; transform: translate(-50%, -60%) rotate(-5deg) scale(1.04); animation-timing-function: linear; }
    38%, 56% { top: 47%; left: 41%; opacity: 1; transform: translate(-50%, -58%) rotate(14deg) scale(1.04); animation-timing-function: var(--ease-lead); }
    76% { top: 49%; left: 40%; opacity: 0.8; transform: translate(-50%, -52%) rotate(-5deg) scale(1.14); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; left: 40%; opacity: 0.08; transform: translate(-50%, -50%) rotate(-5deg) scale(1.42); }
  }

  @keyframes reveal-beer-bottle-close {
    0% { top: 47%; left: 69%; opacity: 1; transform: translate(-50%, -50%) rotate(2deg) scale(1); animation-timing-function: var(--ease-lead); }
    18% { top: 47%; left: 69%; opacity: 1; transform: translate(-50%, -60%) rotate(5deg) scale(1.04); animation-timing-function: linear; }
    38%, 56% { top: 47%; left: 59%; opacity: 1; transform: translate(-50%, -58%) rotate(-14deg) scale(1.04); animation-timing-function: var(--ease-lead); }
    76% { top: 49%; left: 60%; opacity: 0.8; transform: translate(-50%, -52%) rotate(5deg) scale(1.14); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; left: 60%; opacity: 0.08; transform: translate(-50%, -50%) rotate(5deg) scale(1.42); }
  }

  /* Only the tail is on screen, so the idle hint is a flick of that tail. */
  @keyframes hint-mouse-tail {
    0%, 100% { transform: translateX(-1%) rotate(-84deg); }
    50% { transform: translateX(4%) rotate(-96deg); }
  }

  /* It rights itself as the drag pulls it clear of the edge. */
  @keyframes reveal-mouse-upright {
    0% { transform: rotate(-90deg); animation-timing-function: var(--ease-lead); }
    30% { transform: rotate(-52deg); animation-timing-function: linear; }
    58% { transform: rotate(6deg); animation-timing-function: var(--ease-settle); }
    100% { transform: rotate(0deg); }
  }

  @keyframes reveal-mouse-watermark {
    0% { top: 48%; left: -10%; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: var(--ease-lead); }
    18% { top: 46%; left: 24%; opacity: 1; transform: translate(-50%, -55%) rotate(3deg) scale(1.03); animation-timing-function: linear; }
    46% { top: 47%; left: 74%; opacity: 1; transform: translate(-50%, -50%) rotate(-4deg) scale(0.94); animation-timing-function: linear; }
    64% { top: 48%; left: 66%; opacity: 0.82; transform: translate(-50%, -50%) rotate(2deg) scale(1.1); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; left: 50%; opacity: 0.08; transform: translate(-50%, -50%) scale(1.42); }
  }

  @keyframes hint-camera {
    0%, 100% { transform: translateY(1px) rotate(-1deg); }
    50% { transform: translateY(-4px) rotate(1.5deg); }
  }

  /* The camera only leaves once the print has been read and starts sinking. */
  @keyframes reveal-camera-away {
    0% { opacity: 1; transform: scale(1); }
    100% { opacity: 0; transform: translateY(0.9rem) scale(0.82); }
  }

  /* Fed straight up out of the slot, held in front, then into the backdrop.
     It rides behind the camera until it has cleared the top edge. */
  @keyframes reveal-photo-emerge {
    0% { top: 42%; z-index: 2; opacity: 0; transform: translate(-50%, -50%) scale(1); animation-timing-function: linear; }
    4% { top: 42%; z-index: 2; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: var(--ease-lead); }
    20% { top: 10%; z-index: 2; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: linear; }
    21% { top: 10%; z-index: 5; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: linear; }
    30% { top: 12%; z-index: 5; opacity: 1; transform: translate(-50%, -50%) scale(1.06) rotate(-2deg); animation-timing-function: var(--ease-settle); }
    50%, 76% { top: 50%; z-index: 5; opacity: 1; transform: translate(-50%, -50%) scale(1.45) rotate(-2deg); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; z-index: 5; opacity: 0.08; transform: translate(-50%, -50%) scale(2.3) rotate(0deg); }
  }

  @keyframes reveal-flower-watermark {
    0% { top: 48%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: var(--ease-lead); }
    29% { top: 46%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1.12); animation-timing-function: linear; }
    49%, 64% { top: 47%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1.22); animation-timing-function: var(--ease-settle); }
    100% { top: 50%; left: 50%; opacity: 0.08; transform: translate(-50%, -50%) scale(1.8); }
  }

  @keyframes hint-pat {
    0%, 100% { transform: translateY(1px) scale(1); }
    50% { transform: translateY(4px) scale(1.025, 0.975); }
  }

  @keyframes reveal-head-pat {
    0% { top: 48%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1); animation-timing-function: var(--ease-lead); }
    18% { transform: translate(-50%, -45%) scale(1.06, 0.9); animation-timing-function: linear; }
    34% { transform: translate(-50%, -56%) scale(0.96, 1.06); animation-timing-function: linear; }
    52% { transform: translate(-50%, -50%) scale(1); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; left: 50%; opacity: 0.08; transform: translate(-50%, -50%) scale(1.42); }
  }

  @keyframes reveal-pat-heart {
    0% { opacity: 0; transform: translateY(0.4rem) scale(0.3) rotate(-8deg); }
    38% { opacity: 1; }
    100% { opacity: 0; transform: translateY(-2.5rem) scale(1.15) rotate(9deg); }
  }

  @keyframes reveal-milktea-watermark {
    0%, 24% { top: 48%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1); filter: brightness(1); animation-timing-function: var(--ease-lead); }
    46% { top: 46%; left: 50%; opacity: 1; transform: translate(-50%, -50%) scale(1.09); filter: brightness(1.18); animation-timing-function: var(--ease-settle); }
    100% { top: 52%; left: 50%; opacity: 0.08; transform: translate(-50%, -50%) scale(1.42); filter: brightness(1); }
  }

  @keyframes reveal-hint {
    0%, 100% { opacity: 0.62; transform: translateX(-50%) translateY(2px); }
    50% { opacity: 1; transform: translateX(-50%) translateY(-2px); }
  }
  @keyframes reveal-aura {
    0%, 100% { opacity: 0.3; transform: scale(0.9); }
    50% { opacity: 0.58; transform: scale(1.06); }
  }
  @keyframes hint-drink-left {
    0%, 100% { transform: translateY(0) rotate(-2deg) scale(var(--drink-scale)); }
    50% { transform: translateY(-4%) rotate(2deg) scale(var(--drink-scale)); }
  }
  @keyframes hint-drink-right {
    0%, 100% { transform: translateY(0) rotate(2deg) scale(var(--drink-scale)); }
    50% { transform: translateY(-4%) rotate(-2deg) scale(var(--drink-scale)); }
  }
  @keyframes hint-flower {
    0%, 100% { transform: scale(0.99) rotate(6deg); }
    50% { transform: scale(1.025) rotate(8deg); }
  }
  @keyframes hint-connect {
    0%, 100% { opacity: 0.62; transform: scale(0.88); }
    50% { opacity: 1; transform: scale(1.16); }
  }
  /* A first tap presses the bunch down and lets it spring back. */
  @keyframes bloom-nudge {
    0% { transform: scale(1) rotate(6deg); }
    26% { transform: scale(0.945, 0.92) rotate(5deg); }
    58% { transform: scale(1.035, 1.05) rotate(7.5deg); }
    100% { transform: scale(1) rotate(6deg); }
  }
  /* Three or four petals lift out of the flower heads and drift back down. */
  @keyframes bloom-puff {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.3) rotate(0deg); }
    24% { opacity: 1; transform: translate(calc(-50% + var(--puff-x) * 0.6), calc(-50% + var(--puff-y))) scale(1) rotate(calc(var(--flower-spin) * 0.5)); }
    100% { opacity: 0; transform: translate(calc(-50% + var(--puff-x)), calc(-50% + var(--puff-y) * 0.35)) scale(0.85) rotate(var(--flower-spin)); }
  }
  /* The second tap shakes the whole bunch open. */
  @keyframes reveal-flower-bouquet {
    0% { transform: scale(1) rotate(6deg); }
    18% { transform: scale(0.94, 0.9) rotate(2deg); }
    42% { transform: scale(1.06, 1.08) rotate(10.5deg); }
    62% { transform: scale(1.02) rotate(3.5deg); }
    80% { transform: scale(1.01) rotate(7.5deg); }
    100% { transform: scale(1) rotate(6deg); }
  }
  @keyframes reveal-copy-bubble {
    0% { opacity: 0; filter: blur(6px); transform: translateY(1.15rem) scale(0.92); }
    65% { opacity: 1; filter: none; transform: translateY(-2px) scale(1.012); }
    100% { opacity: 1; filter: none; transform: none; }
  }
  @keyframes reveal-copy-pop {
    0% { opacity: 0; filter: blur(5px); transform: translateX(-0.8rem) scale(0.78) rotate(-2deg); }
    65% { opacity: 1; filter: none; transform: translateX(2px) scale(1.025) rotate(0.5deg); }
    100% { opacity: 1; filter: none; transform: none; }
  }
  @keyframes reveal-copy-develop {
    0% { opacity: 0; filter: grayscale(1) brightness(0.45) blur(7px); transform: translateY(0.35rem); }
    100% { opacity: 1; filter: none; transform: none; }
  }
  @keyframes reveal-copy-shine {
    0% { opacity: 0; filter: blur(7px) brightness(1.8); clip-path: inset(0 100% 0 0); }
    100% { opacity: 1; filter: none; clip-path: inset(0); }
  }
  @keyframes reveal-copy-rise {
    0% { opacity: 0; filter: blur(5px); transform: translateY(1.2rem); }
    100% { opacity: 1; filter: none; transform: none; }
  }
  @keyframes reveal-copy-side {
    0% { opacity: 0; filter: blur(5px); transform: translateX(calc(var(--line-direction, 1) * 1rem)); }
    100% { opacity: 1; filter: none; transform: none; }
  }
  @keyframes reveal-picked-drink {
    0%, 100% { filter: brightness(1); }
    45% { filter: brightness(1.35) drop-shadow(0 0 1.2rem rgba(255,208,130,.7)); transform: scale(1.1); }
  }
  @keyframes reveal-bubble {
    0% { opacity: 0; transform: translateY(1rem) scale(0.3); }
    25% { opacity: 0.9; }
    100% { opacity: 0; transform: translateY(-7.5rem) translateX(0.8rem) scale(1.25); }
  }
  @keyframes reveal-mouse-heart {
    0% { opacity: 0; transform: translateY(0.5rem) scale(0.3) rotate(-8deg); }
    35% { opacity: 1; }
    100% { opacity: 0; transform: translate(2rem, -2.2rem) scale(1.15) rotate(10deg); }
  }
  @keyframes reveal-photo-flash {
    0%, 100% { opacity: 0; transform: scale(0.55); }
    18% { opacity: 1; transform: scale(1); }
    48% { opacity: 0.42; }
  }
  @keyframes reveal-photo-develop {
    0% { opacity: 0.4; filter: brightness(0.3) contrast(0.5) saturate(0.1) blur(5px); }
    100% { opacity: 1; filter: none; }
  }
  @keyframes reveal-flower-bloom {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.2) rotate(0deg); }
    30%, 68% { opacity: 1; }
    100% { opacity: 0; transform: translate(calc(-50% + var(--flower-x)), calc(-50% + var(--flower-y))) scale(1.3) rotate(var(--flower-spin)); }
  }
  @keyframes reveal-connection {
    0% { opacity: 0.25; stroke-dasharray: 1 10; stroke-width: 1; }
    48% { opacity: 1; stroke-dasharray: 12 2; stroke-width: 3.2; }
    100% { opacity: 0; stroke-dasharray: 40 0; stroke-width: 1.4; }
  }
  @keyframes reveal-connect-point {
    0%, 38% { opacity: 1; transform: scale(1); }
    62% { opacity: 1; transform: scale(1.32); }
    100% { opacity: 0; transform: scale(1.8); }
  }
  @keyframes reveal-connect-heart {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(0.25); }
    42%, 68% { opacity: 1; transform: translate(-50%, -50%) scale(1.2); }
    100% { opacity: 0; transform: translate(-50%, -75%) scale(0.8); }
  }
  @keyframes reveal-connect-ring {
    0% { opacity: 0; transform: scale(0.2); }
    32% { opacity: 0.72; }
    100% { opacity: 0; transform: scale(2); }
  }
}

@media (max-width: 900px) {
  .story-card .card-face[data-reveal] {
    justify-content: flex-start;
    padding: 1.35rem 1rem;
  }

  .card-face[data-reveal] h3 {
    margin-bottom: 0.85rem;
  }

  .card-face[data-reveal] .card-moment {
    inset: 4.5rem 0.35rem 0.35rem;
  }

  .card-copy {
    width: min(calc(100% - 2rem), 32rem);
  }

  .card-moment--mouse,
  .card-moment--live,
  .card-moment--flower { --relic-size: min(55%, 9.5rem); }

  .card-moment--photo,
  .card-moment--milktea { --relic-size: min(66%, 11rem); }

  .card-face[data-reveal] .card-moment--beer .card-drink {
    width: min(41%, 6.7rem);
  }
}

@media (max-height: 600px) and (prefers-reduced-motion: no-preference) {
  .story-card .card-face[data-reveal] {
    padding: 0.8rem 14rem 0.8rem 1.1rem;
    text-align: left;
  }

  .card-face[data-reveal] .card-moment {
    inset: 0.35rem 0.4rem 0.35rem auto;
    width: 13.2rem;
  }

  .card-action-hint { bottom: 0.1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .story-card .card-face[data-reveal] {
    min-height: 23rem;
    padding: 1.5rem 1.25rem;
  }

  .card-face[data-reveal] .card-moment {
    inset: 4.5rem 0.5rem 0.5rem;
  }

  .card-face.is-revealed .card-copy span {
    opacity: 1;
    filter: none !important;
    transform: none;
  }
}

/* Keep both final choice buttons the same size while No moves around. */
#yesButton {
  --yes-scale: 1;
  /* Transform only -- it lifts without changing the box, so the row stays put. */
  --yes-hover-scale: 1.035;
}
#yesButton,
#noButton {
  transform-origin: center;
  -webkit-tap-highlight-color: transparent;
}

#yesButton:active:not(:disabled),
#yesButton[data-pressed]:not(:disabled) {
  background: rgba(224, 88, 145, 0.3);
  border-color: rgba(255, 205, 226, 0.78);
  box-shadow:
    0 0.3rem 0.8rem rgba(89, 19, 53, 0.2),
    0 0 1rem rgba(244, 114, 161, 0.12),
    inset 0 4px 9px rgba(101, 25, 61, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
  transform: translateY(2px) scale(0.95);
  transition-duration: 60ms;
}

#noButton:not(.is-loose):active:not(:disabled),
#noButton[data-pressed]:not(.is-loose):not(:disabled) {
  background:
    linear-gradient(145deg, rgba(255, 255, 255, 0.055), rgba(0, 0, 0, 0.035));
  border-color: rgba(255, 226, 238, 0.34);
  box-shadow:
    0 0.3rem 0.8rem rgba(0, 0, 0, 0.16),
    inset 0 4px 9px rgba(0, 0, 0, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transform: translateY(2px) scale(0.95);
  transition-duration: 60ms;
}

#noButton.is-loose:active:not(:disabled),
#noButton.is-loose[data-pressed]:not(:disabled) {
  box-shadow:
    0 0.3rem 0.8rem rgba(0, 0, 0, 0.16),
    inset 0 4px 9px rgba(0, 0, 0, 0.26),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transform: translate3d(var(--no-x), calc(var(--no-y) + 2px), 0) scale(0.95);
  transition-duration: 60ms;
}

#noButton.is-loose {
  min-width: 0;
  padding: .85rem .65rem;
}
