/* ==========================================================================
   sections.css — the gate, the bloom, and all nine sections.
   ========================================================================== */

/* ==========================================================================
   GATE
   ========================================================================== */

.gate {
  position: fixed;
  inset: 0;
  z-index: var(--z-gate);
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: linear-gradient(170deg, var(--blush) 0%, var(--sky) 62%, var(--lilac) 100%);
  overflow: hidden;
  transition: opacity var(--d-slow) var(--ease-soft);
}
.gate.is-opening { opacity: 0; pointer-events: none; }

.gate__sky { position: absolute; inset: 0; }

.gate__inner {
  position: relative;
  z-index: var(--z-content);
  width: min(420px, 100%);
  text-align: center;
}

.gate__phase {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--d-slow) var(--ease-out),
              transform var(--d-slow) var(--ease-out);
}
.gate__phase.is-active { opacity: 1; transform: none; }

.gate__lock {
  color: var(--pink-deep);
  margin-bottom: var(--s-5);
  animation: float-y 5s var(--ease-soft) infinite;
}

.gate__title {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-style: italic;
  color: var(--ink);
  margin-bottom: var(--s-2);
}
.gate__title--script {
  font-family: var(--font-script);
  font-style: normal;
  font-size: var(--t-2xl);
  margin-bottom: var(--s-4);
}

.gate__sub {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  letter-spacing: .06em;
  margin-bottom: var(--s-7);
}

.gate__prompt {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--ink-soft);
  margin-bottom: var(--s-5);
}

/* --- countdown ------------------------------------------------------------ */

.countdown {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-2);
}

.countdown__unit {
  background: rgba(255, 251, 247, .72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--r-md);
  padding: var(--s-4) var(--s-1);
  box-shadow: var(--lift-1);
}

.countdown__num {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 7vw, 2.4rem);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  line-height: 1;
}

.countdown__label {
  display: block;
  margin-top: var(--s-2);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--ink-faint);
}

@keyframes tick {
  0%   { transform: translateY(-3px); opacity: .55; }
  100% { transform: none;             opacity: 1; }
}
.countdown__num.is-tick { animation: tick 260ms var(--ease-out); }

/* --- code boxes ----------------------------------------------------------- */

.code { position: relative; margin-bottom: var(--s-4); }

/* The real input sits invisibly over the boxes so taps focus it and the
   mobile keyboard, paste and screen readers all behave normally. */
.code__input {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  opacity: 0;
  border: 0;
  z-index: 2;
  cursor: pointer;
  font-size: 16px;             /* < 16px makes iOS zoom the whole page */
}

.code__boxes {
  display: flex;
  justify-content: center;
  gap: var(--s-2);
}

.code__box {
  width: clamp(38px, 12vw, 48px);
  aspect-ratio: 3 / 4;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: rgba(255, 251, 247, .8);
  border: 1.5px solid var(--pink);
  font-size: var(--t-lg);
  color: var(--ink);
  transition: border-color var(--d-fast) var(--ease-soft),
              background   var(--d-fast) var(--ease-soft),
              transform    var(--d-fast) var(--ease-out);
}
.code__box.is-filled { background: var(--cream); border-color: var(--pink-deep); }
.code__box.is-active { border-color: var(--pink-deep); box-shadow: var(--glow-pink); }

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-8px); }
  40%      { transform: translateX(7px); }
  60%      { transform: translateX(-5px); }
  80%      { transform: translateX(3px); }
}
.code__boxes.is-wrong { animation: shake 560ms var(--ease-soft); }
.code__boxes.is-wrong .code__box { border-color: var(--pink-deep); }

.code__boxes.is-correct .code__box {
  border-color: var(--gold-deep);
  background: var(--gold);
  box-shadow: var(--glow-gold);
  transform: translateY(-4px);
}
/* ripple outward so it reads as a lock releasing */
.code__boxes.is-correct .code__box:nth-child(1) { transition-delay:   0ms; }
.code__boxes.is-correct .code__box:nth-child(2) { transition-delay:  60ms; }
.code__boxes.is-correct .code__box:nth-child(3) { transition-delay: 120ms; }
.code__boxes.is-correct .code__box:nth-child(4) { transition-delay: 180ms; }
.code__boxes.is-correct .code__box:nth-child(5) { transition-delay: 240ms; }
.code__boxes.is-correct .code__box:nth-child(6) { transition-delay: 300ms; }

.code__hint {
  font-family: var(--font-hand);
  font-size: var(--t-base);
  color: var(--ink-soft);
  margin-bottom: var(--s-2);
}

.code__error {
  min-height: 1.5em;
  font-size: var(--t-sm);
  color: var(--pink-deep);
  margin-bottom: var(--s-4);
}

/* --- keypad ---------------------------------------------------------------- */

.keypad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
  max-width: 260px;
  margin-inline: auto;
}

.keypad__key {
  aspect-ratio: 1;
  border-radius: var(--r-pill);
  background: rgba(255, 251, 247, .78);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--t-lg);
  box-shadow: var(--lift-1);
  transition: background var(--d-fast) var(--ease-soft),
              transform  var(--d-fast) var(--ease-soft);
}
.keypad__key:hover  { background: var(--pink); }
.keypad__key:active { transform: scale(.94); background: var(--pink-deep); }
.keypad__key--del   { font-size: var(--t-base); color: var(--ink-soft); }
.keypad__gap        { pointer-events: none; }

/* ==========================================================================
   BLOOM — peonies flood outward, then clear
   ========================================================================== */

.bloom {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-gate) + 10);
  pointer-events: none;
  display: grid;
  place-items: center;
  background: radial-gradient(circle at 50% 50%, var(--blush) 0%, transparent 70%);
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease-soft);
}
.bloom.is-flooding { opacity: 1; }
.bloom.is-clearing { opacity: 0; transition-duration: 1100ms; }

.bloom__petals {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.petal {
  position: absolute;
  border-radius: 60% 40% 55% 45% / 55% 60% 40% 45%;
  opacity: 0;
  filter: blur(.4px);
  animation: petal-out var(--d-bloom) var(--ease-out) forwards;
  animation-delay: var(--d);
}

@keyframes petal-out {
  0%   { opacity: 0;   transform: translate3d(0, 0, 0) scale(.1) rotate(0deg); }
  22%  { opacity: .95; }
  100% { opacity: 0;   transform: translate3d(var(--x), var(--y), 0) scale(1.15) rotate(var(--r)); }
}

/* ==========================================================================
   0 · INTRO
   ========================================================================== */

.section--intro {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  text-align: center;
  background: linear-gradient(180deg, var(--blush) 0%, var(--cream) 100%);
}

.intro__lines {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-lg);
  color: var(--ink-soft);
  min-height: 3em;
  transition: opacity var(--d-base) var(--ease-soft);
}
.intro__lines.is-fading { opacity: 0; }
.intro__lines.is-done   { display: none; }

.intro__lines.is-typing::after {
  content: "";
  display: inline-block;
  width: 2px; height: 1em;
  margin-left: 3px;
  background: var(--pink-deep);
  vertical-align: -.12em;
  animation: caret 800ms steps(2) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

.intro__greeting {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 900ms var(--ease-out), transform 900ms var(--ease-out);
}
.intro__greeting.is-in { opacity: 1; transform: none; }

.intro__hello {
  display: block;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-lg);
  color: var(--ink-soft);
  letter-spacing: .04em;
}
.intro__name {
  display: block;
  font-family: var(--font-script);
  font-size: var(--t-3xl);
  color: var(--ink);
  margin-top: var(--s-2);
  line-height: 1.05;
}

.intro__pet {
  display: block;
  max-width: 22ch;
  margin: var(--s-4) auto 0;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-base);
  line-height: 1.5;
  color: var(--ink-soft);
}

.intro__cue, .intro__arrow {
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease-soft);
}
.intro__cue.is-in, .intro__arrow.is-in { opacity: 1; }

.intro__cue {
  margin-top: var(--s-8);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--ink-faint);
}
.intro__arrow {
  display: block;
  font-size: var(--t-xl);
  color: var(--pink-deep);
  animation: float-y 2.4s var(--ease-soft) infinite;
}

/* ==========================================================================
   1 · BALLOONS
   ========================================================================== */

.balloons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s-5) var(--s-4);
  align-items: start;
}

.balloon__slot { min-height: 210px; display: grid; place-items: center; }

.balloon {
  position: relative;
  width: 96px; height: 190px;
  display: grid;
  place-items: start center;
  animation: float-y 4s var(--ease-soft) infinite;
  animation-delay: var(--delay);
  transition: transform var(--d-fast) var(--ease-soft);
}
.balloon:hover { transform: translateY(-6px) scale(1.04); }

.balloon__body {
  width: 92px; height: 116px;
  border-radius: 50% 50% 48% 48% / 56% 56% 44% 44%;
  display: block;
  box-shadow: inset -10px -12px 22px rgba(255, 255, 255, .55),
              var(--lift-1);
  position: relative;
}
/* the knot */
.balloon__body::after {
  content: "";
  position: absolute;
  bottom: -7px; left: 50%;
  transform: translateX(-50%);
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 10px solid currentColor;
}

.balloon--pink  .balloon__body { background: var(--pink);  color: var(--pink); }
.balloon--sky   .balloon__body { background: var(--sky);   color: var(--sky); }
.balloon--lilac .balloon__body { background: var(--lilac); color: var(--lilac); }
.balloon--gold  .balloon__body { background: var(--gold);  color: var(--gold); }

.balloon__string {
  position: absolute;
  top: 124px; left: 50%;
  width: 1.5px; height: 62px;
  background: linear-gradient(180deg, var(--ink-faint), transparent);
  transform: translateX(-50%) rotate(2deg);
}

.balloon__num {
  position: absolute;
  top: 44px; left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-display);
  font-size: var(--t-lg);
  color: rgba(90, 64, 72, .5);
}

@keyframes pop {
  0%   { transform: scale(1);   opacity: 1; }
  45%  { transform: scale(1.22); opacity: 1; }
  100% { transform: scale(.2);  opacity: 0; }
}
.balloon.is-popped { animation: pop 260ms var(--ease-pop) forwards; }

.balloon__card {
  width: min(190px, 100%);
  opacity: 0;
  transform: translateY(14px) scale(.94);
  transition: opacity var(--d-base) var(--ease-out),
              transform var(--d-base) var(--ease-out);
}
.balloon__card.is-in { opacity: 1; transform: none; }

/* sparkle burst on pop */
.sparkles {
  position: fixed;
  z-index: var(--z-confetti);
  pointer-events: none;
}
.sparkles__dot {
  position: absolute;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--gold);
  animation: sparkle-out 700ms var(--ease-out) forwards;
}
@keyframes sparkle-out {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(0); opacity: 0; }
}

/* ==========================================================================
   2 · GALLERY
   ========================================================================== */

.gallery {
  display: flex;
  gap: var(--s-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: var(--s-6) var(--gutter) var(--s-7);
  touch-action: pan-x pan-y;          /* Risk 6 — let touch scroll natively */
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
}
.gallery::-webkit-scrollbar { display: none; }
.gallery.is-dragging { cursor: grabbing; scroll-snap-type: none; }

/* flex: 0 0 auto is load-bearing. Without it the track (a flex item of the
   scroller) shrinks to the scroller's width, its last children spill outside
   its box, and those photos never enter the viewport for lazy loading. */
.gallery__track {
  display: flex;
  flex: 0 0 auto;
  gap: var(--s-5);
}

/* A flex scroller drops its own trailing padding, so the last polaroid would
   sit flush against the right edge. This spacer restores the breathing room. */
.gallery__track::after {
  content: "";
  flex: 0 0 var(--gutter);
}

.gallery__item {
  flex: 0 0 auto;
  width: clamp(170px, 46vw, 216px);
  scroll-snap-align: center;
  transform: rotate(var(--tilt));
  transition: transform var(--d-base) var(--ease-out);
}
.gallery__item:hover { transform: rotate(0deg) translateY(-8px) scale(1.03); }
.gallery__item .polaroid { display: block; }

.gallery__cue {
  text-align: center;
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--ink-faint);
}

.modal__photo { margin: 0 0 var(--s-5); }
.modal__photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-md);
}
.modal__title {
  font-family: var(--font-script);
  font-size: var(--t-xl);
  margin-bottom: var(--s-3);
}
.modal__text {
  font-size: var(--t-base);
  color: var(--ink-soft);
  line-height: var(--lh-body);
  margin-bottom: var(--s-5);
}
.modal__eyebrow {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--gold-deep);
  margin-bottom: var(--s-2);
}
.modal__emoji { font-size: 3rem; margin-bottom: var(--s-3); }

/* ==========================================================================
   3 · LETTERS
   ========================================================================== */

.envelopes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-6);
}

.envelope {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: var(--r-sm);
  background: var(--cream);
  box-shadow: var(--lift-2);
  overflow: hidden;
  transition: transform var(--d-base) var(--ease-out),
              box-shadow var(--d-base) var(--ease-out);
}
.envelope:hover { transform: translateY(-6px); box-shadow: var(--lift-3); }

.envelope__flap {
  position: absolute;
  top: 0; left: 0; right: 0; height: 62%;
  background: var(--pink);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transition: transform var(--d-slow) var(--ease-out);
  transform-origin: top center;
}
.envelope:hover .envelope__flap { transform: rotateX(38deg); }

.envelope__body {
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--pink);
  border-radius: var(--r-sm);
}

.envelope__seal {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--cream);
  box-shadow: var(--lift-1);
  font-size: 1.1rem;
}

.envelope__label {
  position: absolute;
  left: 0; right: 0; bottom: var(--s-3);
  font-family: var(--font-hand);
  font-size: var(--t-base);
  color: var(--ink-soft);
  text-align: center;
}

/* --- the opened letter ----------------------------------------------------- */

.letter__overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: rgba(46, 36, 56, .42);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--d-base) var(--ease-soft);
}
.letter__overlay.is-open { opacity: 1; }

.letter__sheet {
  width: min(520px, 100%);
  max-height: 84dvh;
  display: flex;
  flex-direction: column;
  background: var(--cream);
  border-radius: var(--r-md);
  box-shadow: var(--lift-3);
  overflow: hidden;
  transform: translateY(24px) scale(.97);
  transition: transform var(--d-slow) var(--ease-out);
}
.letter__overlay.is-open .letter__sheet { transform: none; }

.letter {
  flex: 1;
  overflow-y: auto;
  padding: var(--s-7) var(--s-6);
  /* ruled paper */
  background-image: repeating-linear-gradient(
    180deg, transparent, transparent 31px, var(--paper-line) 31px, var(--paper-line) 32px);
  background-position: 0 var(--s-7);
}

.letter__salutation,
.letter__signoff,
.letter__from { font-family: var(--font-hand); font-size: var(--t-lg); color: var(--ink); }
.letter__salutation { margin-bottom: var(--s-4); }
.letter__signoff    { margin-top: var(--s-5); color: var(--ink-soft); }
.letter__from       { color: var(--pink-deep); }

.letter__body p {
  font-family: var(--font-hand);
  font-size: var(--t-lg);
  line-height: 32px;              /* matched to the rule spacing above */
  color: var(--ink);
  margin-bottom: var(--s-4);
}

.letter__close {
  flex: 0 0 auto;
  padding: var(--s-4);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  background: rgba(247, 202, 208, .22);
  border-top: 1px solid var(--hairline);
}
.letter__close:hover { background: var(--pink); color: var(--ink); }

/* ==========================================================================
   4 · PLAYER
   ========================================================================== */

.player {
  max-width: 420px;
  margin-inline: auto;
  padding: var(--s-7) var(--s-5) var(--s-5);
  background: linear-gradient(165deg, var(--blush), var(--cream));
  border-radius: var(--r-xl);
  box-shadow: var(--lift-2);
  text-align: center;
}

.vinyl {
  position: relative;
  width: 168px; height: 168px;
  margin: 0 auto var(--s-5);
  display: grid;
  place-items: center;
}
.vinyl__disc {
  position: absolute; inset: 0;
  border-radius: 50%;
  background:
    repeating-radial-gradient(circle at 50% 50%,
      var(--night) 0 2px, var(--night-soft) 2px 4px);
  box-shadow: var(--lift-2);
  animation: spin 4s linear infinite;
  animation-play-state: paused;
}
.player.is-playing .vinyl__disc { animation-play-state: running; }
@keyframes spin { to { transform: rotate(360deg); } }

.vinyl__label {
  width: 62px; height: 62px;
  border-radius: 50%;
  background: var(--pink);
  z-index: 1;
  box-shadow: 0 0 0 4px rgba(255, 251, 247, .5);
}
.player.is-voice .vinyl__label { background: var(--gold); }

.vinyl__hole {
  position: absolute;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--cream);
  z-index: 2;
}

.player__title  { font-family: var(--font-display); font-size: var(--t-lg); color: var(--ink); }
.player__artist { font-size: var(--t-sm); color: var(--ink-soft); margin-bottom: var(--s-3); }

.player__eq {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 3px;
  height: 18px;
  margin-bottom: var(--s-4);
}
.player__eq span {
  width: 3px; height: 4px;
  border-radius: var(--r-pill);
  background: var(--pink-deep);
  opacity: .35;
}
.player.is-playing .player__eq span {
  opacity: 1;
  animation: eq 900ms var(--ease-soft) infinite;
  animation-delay: calc(var(--n) * 110ms);
}
@keyframes eq {
  0%, 100% { height: 4px; }
  50%      { height: 17px; }
}

.player__scrubrow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}

.player__scrub {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--pink);
  cursor: pointer;
}
.player__scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--pink-deep);
  box-shadow: var(--lift-1);
}
.player__scrub::-moz-range-thumb {
  width: 14px; height: 14px;
  border: 0; border-radius: 50%;
  background: var(--pink-deep);
}

.player__time {
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  min-width: 34px;
}

.player__controls {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--s-5);
  margin-bottom: var(--s-3);
}
.player__btn {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--t-base);
  color: var(--ink-soft);
  transition: background var(--d-fast) var(--ease-soft),
              color var(--d-fast) var(--ease-soft);
}
.player__btn:hover { background: rgba(247, 202, 208, .4); color: var(--ink); }
.player__btn--play {
  width: 60px; height: 60px;
  background: var(--pink);
  color: var(--ink);
  font-size: var(--t-lg);
  box-shadow: var(--lift-1);
}
.player__btn--play:hover { background: var(--pink-deep); }

/* Shown between the tap and the first sound, so a slow connection never
   looks like a dead button. */
.player__spinner {
  display: block;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 2px solid rgba(90, 64, 72, .25);
  border-top-color: var(--ink);
  animation: spin 700ms linear infinite;
}
.player.is-loading .player__btn--play { cursor: progress; }

.player__note {
  min-height: 1.4em;
  font-size: var(--t-xs);
  color: var(--pink-deep);
  margin-bottom: var(--s-3);
}

.playlist {
  list-style: none;
  margin: 0;
  padding: var(--s-3) 0 0;
  border-top: 1px solid var(--hairline);
  text-align: left;
}
.playlist__row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-3);
  border-radius: var(--r-md);
  transition: background var(--d-fast) var(--ease-soft);
}
.playlist__row:hover { background: rgba(247, 202, 208, .28); }
.playlist__row.is-current { background: rgba(247, 202, 208, .45); }

.playlist__icon  { font-size: var(--t-base); width: 22px; text-align: center; }
.playlist__meta  { display: flex; flex-direction: column; min-width: 0; }
.playlist__title {
  font-size: var(--t-sm); color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.playlist__artist { font-size: var(--t-xs); color: var(--ink-faint); }

/* ==========================================================================
   5 · CONSTELLATION
   ========================================================================== */

.sky {
  position: relative;
  aspect-ratio: 1 / 1.05;
  max-height: 62dvh;
  margin-inline: auto;
  border-radius: var(--r-xl);
  background: radial-gradient(ellipse at 50% 30%, var(--night-soft) 0%, var(--night) 70%);
  overflow: hidden;
  box-shadow: inset 0 0 60px rgba(0, 0, 0, .35);
}

.sky__lines { position: absolute; inset: 0; width: 100%; height: 100%; }
.sky__line {
  stroke: var(--lilac);
  stroke-width: .25;
  opacity: .3;
  vector-effect: non-scaling-stroke;
}

.sky__dust { position: absolute; inset: 0; }
.sky__dust span {
  position: absolute;
  width: 2px; height: 2px;
  border-radius: 50%;
  background: var(--cream);
  animation: twinkle 3.5s var(--ease-soft) infinite;
}

.star {
  position: absolute;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  padding: var(--s-4);
}
.star__glow {
  position: absolute;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(232, 196, 160, .55) 0%, transparent 70%);
  animation: twinkle 2.6s var(--ease-soft) infinite;
  animation-delay: var(--delay);
}
.star__dot {
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: var(--glow-gold);
  transition: transform var(--d-base) var(--ease-out);
}
.star:hover .star__dot { transform: scale(1.5); }
.star.is-found .star__dot { background: var(--cream); }

.star__name {
  position: absolute;
  top: calc(50% + 20px);
  font-size: 0.66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lilac);
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--d-base) var(--ease-soft);
}
.star:hover .star__name,
.star.is-found .star__name { opacity: .85; }

/* ==========================================================================
   6 · GIFTS
   ========================================================================== */

.gifts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
  max-width: 400px;
  margin-inline: auto;
}

.gift {
  position: relative;
  aspect-ratio: 1;
  transition: transform var(--d-base) var(--ease-out);
}
.gift:hover { transform: translateY(-6px); }

.gift__body {
  position: absolute;
  left: 8%; right: 8%; bottom: 4%;
  height: 66%;
  border-radius: var(--r-sm);
  background: linear-gradient(160deg, var(--pink), var(--pink-deep));
  box-shadow: var(--lift-1);
}
.gift__lid {
  position: absolute;
  left: 2%; right: 2%; top: 20%;
  height: 22%;
  border-radius: var(--r-sm);
  background: linear-gradient(160deg, var(--sky), var(--sky-deep));
  box-shadow: var(--lift-1);
  transform-origin: center bottom;
  transition: transform var(--d-slow) var(--ease-pop);
  z-index: 2;
}
.gift__ribbon {
  position: absolute;
  left: 46%; right: 46%; top: 20%; bottom: 4%;
  background: var(--gold);
  z-index: 1;
}

@keyframes gift-shake {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(-5deg); }
  75%      { transform: rotate(5deg); }
}
.gift.is-wrong { animation: gift-shake 560ms var(--ease-soft); }

.gift.is-open .gift__lid { transform: translateY(-58%) rotate(-16deg); }
.gifts.is-solved .gift:not(.is-open) { opacity: .4; pointer-events: none; }

.gifts__tease {
  min-height: 1.6em;
  margin-top: var(--s-5);
  text-align: center;
  font-family: var(--font-hand);
  font-size: var(--t-lg);
  color: var(--pink-deep);
}

/* ==========================================================================
   7 · CAKE
   ========================================================================== */

.cake {
  position: relative;
  width: min(300px, 84vw);
  margin: var(--s-7) auto 0;
}

.cake__candles {
  display: flex;
  justify-content: center;
  gap: var(--s-4);
  margin-bottom: -6px;
  position: relative;
  z-index: 2;
}

.candle { position: relative; width: 14px; padding: 0; }

.candle__stick {
  display: block;
  width: 9px; height: 44px;
  margin-inline: auto;
  border-radius: 2px;
  background: repeating-linear-gradient(
    -45deg, var(--cream) 0 5px, var(--pink) 5px 10px);
}
.candle__flame {
  position: absolute;
  top: -20px; left: 50%;
  width: 12px; height: 18px;
  transform: translateX(-50%);
  border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  background: radial-gradient(circle at 50% 65%, #FFF3D6 0%, var(--gold) 45%, var(--gold-deep) 100%);
  box-shadow: var(--glow-gold);
  transform-origin: bottom center;
  animation: flicker 700ms var(--ease-soft) infinite alternate;
  animation-delay: var(--delay);
}
@keyframes flicker {
  from { transform: translateX(-50%) scale(1)     rotate(-2deg); opacity: 1; }
  to   { transform: translateX(-50%) scaleY(1.16) rotate(2deg);  opacity: .88; }
}
.candle.is-out .candle__flame { opacity: 0; transform: translateX(-50%) scale(0); }

.candle__smoke {
  position: absolute;
  top: -22px; left: 50%;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: rgba(138, 112, 120, .5);
  opacity: 0;
  transform: translateX(-50%);
}
.candle.is-out .candle__smoke { animation: smoke 1.5s var(--ease-out) forwards; }
@keyframes smoke {
  0%   { opacity: .7; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0;  transform: translate(-50%, -46px) scale(2.6); }
}

.cake__stack { position: relative; }
.cake__frosting {
  display: block; height: 26px;
  border-radius: 50% 50% 12px 12px / 100% 100% 12px 12px;
  background: var(--cream);
  box-shadow: var(--lift-1);
}
.cake__layer { display: block; }
.cake__layer--top { height: 54px; background: var(--pink);  }
.cake__layer--mid { height: 62px; background: var(--pink-deep); border-radius: 0 0 var(--r-sm) var(--r-sm); }
.cake__plate {
  display: block; height: 12px;
  margin: 0 -18px;
  border-radius: var(--r-pill);
  background: var(--cream);
  box-shadow: var(--lift-2);
}

.cake.is-wished { animation: float-y 2.4s var(--ease-soft) infinite; }

.cake__done {
  min-height: 1.8em;
  margin-top: var(--s-6);
  text-align: center;
  font-family: var(--font-hand);
  font-size: var(--t-lg);
  color: var(--ink-soft);
}

/* ==========================================================================
   8 · FINALE
   ========================================================================== */

.section--finale {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  text-align: center;
  background: linear-gradient(180deg, var(--blush) 0%, var(--pink) 100%);
}

.finale__gate {
  transition: opacity var(--d-base) var(--ease-soft),
              transform var(--d-base) var(--ease-soft);
}
.finale__gate.is-gone { opacity: 0; transform: translateY(-12px); }

.finale__prompt {
  display: block;
  margin-bottom: var(--s-5);
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-lg);
  color: var(--ink-soft);
}

.finale__row {
  display: flex;
  gap: var(--s-3);
  justify-content: center;
  flex-wrap: wrap;
}

.finale__input {
  padding: var(--s-3) var(--s-5);
  min-width: 190px;
  font-size: 16px;                 /* keeps iOS from zooming */
  border: 1.5px solid var(--pink-deep);
  border-radius: var(--r-pill);
  background: var(--cream);
  text-align: center;
}
.finale__input::placeholder { color: var(--ink-faint); }

.finale__error {
  min-height: 1.5em;
  margin-top: var(--s-3);
  font-size: var(--t-sm);
  color: var(--ink);
}

.finale__message {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 900ms var(--ease-out), transform 900ms var(--ease-out);
}
.finale__message.is-in { opacity: 1; transform: none; }

.finale__text {
  max-width: var(--measure);
  margin-inline: auto;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--t-xl);
  line-height: 1.5;
  color: var(--ink);
}
.finale__signoff {
  margin-top: var(--s-6);
  font-family: var(--font-hand);
  font-size: var(--t-lg);
  color: var(--ink-soft);
}
.finale__heart {
  margin-top: var(--s-5);
  font-size: var(--t-xl);
  animation: float-y 3s var(--ease-soft) infinite;
}

/* ==========================================================================
   confetti canvas
   ========================================================================== */

.confetti {
  position: fixed;
  inset: 0;
  width: 100%; height: 100%;
  z-index: var(--z-confetti);
  pointer-events: none;
}

/* ==========================================================================
   narrow phones
   ========================================================================== */

@media (max-width: 380px) {
  .countdown { gap: var(--s-1); }
  .countdown__unit { padding: var(--s-3) 2px; }
  .balloons { grid-template-columns: repeat(2, 1fr); }
  .gifts { gap: var(--s-3); }
  .cake__candles { gap: var(--s-3); }
}

/* On a wide screen the gallery centres rather than hugging the left edge. */
@media (min-width: 900px) {
  .gallery { justify-content: center; }
}
