/* ==========================================================================
   Chern & Javier — invitation page — "Cinematic panorama"
   One seamless journey down the page:
   night sky → periwinkle boarding → white flight → pink dusk arrival → night.
   (theme.css is loaded first: tokens, reset, buttons, shared keyframes)
   ========================================================================== */

body {
  background: var(--night);
  color: var(--ink);
}

/* Film grain over the whole panorama — kills gradient banding and gives the
   long color washes a printed, cinematic texture. Pure decoration. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 60; /* under the teaser modal (1000) and confetti (9999) */
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* -- seam guards: every decorated background layer fades out before the
      section boundary, so the base gradients hand over seamlessly. The
      seams are sacred; the decorations live strictly inside them. -- */

.hero-bg {
  -webkit-mask-image: linear-gradient(180deg, #000 82%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 82%, transparent 100%);
}

.flight-bg,
.arrival-bg,
.rsvp-bg {
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
}

.footer-bg {
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 14%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 14%);
}

/* -- aurora ribbons: huge blurred color fields drifting behind each zone -- */

.aurora {
  position: absolute;
  width: 72vmax;
  height: 72vmax;
  border-radius: 50%;
  filter: blur(72px);
  mix-blend-mode: screen;
  pointer-events: none;
  will-change: transform, opacity;
}

.aurora-1 {
  top: -24%;
  left: -18%;
  background:
    radial-gradient(circle at 32% 34%, rgba(194, 24, 91, 0.42) 0%, transparent 58%),
    radial-gradient(circle at 68% 62%, rgba(127, 127, 184, 0.55) 0%, transparent 62%);
  animation: aurora-drift-a 18s ease-in-out infinite alternate;
}

.aurora-2 {
  top: 18%;
  right: -22%;
  background:
    radial-gradient(circle at 62% 38%, rgba(226, 202, 130, 0.3) 0%, transparent 56%),
    radial-gradient(circle at 30% 70%, rgba(75, 72, 133, 0.6) 0%, transparent 64%);
  animation: aurora-drift-b 24s ease-in-out infinite alternate;
}

.aurora-3 {
  top: 10%;
  left: 26%;
  width: 54vmax;
  height: 54vmax;
  background: radial-gradient(circle at 50% 50%, rgba(168, 216, 200, 0.26) 0%, transparent 58%);
  animation: aurora-drift-a 30s ease-in-out -12s infinite alternate-reverse;
}

@keyframes aurora-drift-a {
  from { transform: translate3d(0, 0, 0) rotate(0deg) scale(1); opacity: 0.75; }
  50%  { opacity: 1; }
  to   { transform: translate3d(13%, 9%, 0) rotate(52deg) scale(1.28); opacity: 0.8; }
}

@keyframes aurora-drift-b {
  from { transform: translate3d(0, 0, 0) rotate(0deg) scale(1.18); opacity: 0.85; }
  50%  { opacity: 1; }
  to   { transform: translate3d(-11%, -9%, 0) rotate(-42deg) scale(0.96); opacity: 0.75; }
}

/* -- scroll parallax (progressive enhancement, Chromium/modern engines):
      atmosphere layers ride the scroll on the standalone `translate`
      channel, which composes with their transform animations -- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes parallax-drift {
      from { translate: 0 6vh; }
      to   { translate: 0 -6vh; }
    }

    @keyframes parallax-sink {
      from { translate: 0 -7vh; }
      to   { translate: 0 7vh; }
    }

    .cloud {
      animation-name: cloud-drift, parallax-drift;
      animation-duration: var(--cd, 48s), auto;
      animation-timing-function: ease-in-out, linear;
      animation-delay: var(--cdel, 0s), 0s;
      animation-iteration-count: infinite, 1;
      animation-direction: alternate, normal;
      animation-fill-mode: none, both;
      animation-timeline: auto, view();
    }

    .sunset-sun {
      animation-name: sun-breathe, parallax-sink;
      animation-duration: 11s, auto;
      animation-timing-function: ease-in-out, linear;
      animation-iteration-count: infinite, 1;
      animation-fill-mode: none, both;
      animation-timeline: auto, view();
    }

    .dusk-glow {
      animation-name: dusk-shimmer, parallax-sink;
      animation-duration: 14s, auto;
      animation-timing-function: ease-in-out, linear;
      animation-iteration-count: infinite, 1;
      animation-fill-mode: none, both;
      animation-timeline: auto, view();
    }
  }
}

/* --------------------------------------------------------------------------
   Shared: eyebrows, section heads, scroll reveal, atmosphere
   -------------------------------------------------------------------------- */

.eyebrow {
  font-size: clamp(0.66rem, 2vw, 0.74rem);
  font-weight: 700;
  letter-spacing: 0.32em;
  text-indent: 0.32em;
  text-transform: uppercase;
  color: var(--indigo-deep);
}

.eyebrow-magenta { color: var(--magenta); }
.eyebrow-gold { color: #F2DFA3; }

.section-head { text-align: center; }

.section-head h2 {
  margin-top: 0.8rem;
  font-size: clamp(2.1rem, 8vw, 3.4rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
}

.section-sub {
  margin-top: 0.85rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1rem, 3vw, 1.2rem);
  color: var(--ink-soft);
  max-width: 40ch;
  margin-inline: auto;
  text-wrap: balance;
}

.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity 0.7s ease var(--d, 0ms),
    transform 0.7s cubic-bezier(0.16, 0.8, 0.32, 1) var(--d, 0ms);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* -- twinkling stars (spans spawned by invite.js) -- */

.star-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.twinkle {
  position: absolute;
  border-radius: 50%;
  opacity: 0.7;
  animation: twinkle var(--tdur, 3s) ease-in-out var(--tdelay, 0s) infinite;
}

@keyframes twinkle {
  0%, 100% { opacity: 0.12; transform: scale(0.8); }
  50%      { opacity: 0.95; transform: scale(1.3); }
}

/* -- rising light embers (spans spawned by invite.js) -- */

.ember-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.ember {
  position: absolute;
  bottom: -3vh;
  border-radius: 50%;
  background: var(--ec, #E2CA82);
  box-shadow: 0 0 6px 1px var(--ec, #E2CA82);
  opacity: 0;
  animation: ember-rise var(--edur, 14s) linear var(--edel, 0s) infinite;
  will-change: transform, opacity;
}

@keyframes ember-rise {
  0%   { transform: translate3d(0, 0, 0) scale(1); opacity: 0; }
  8%   { opacity: var(--eo, 0.7); }
  70%  { opacity: var(--eo, 0.7); }
  100% { transform: translate3d(var(--esw, 20px), -78vh, 0) scale(0.55); opacity: 0; }
}

/* -- a little plane crossing the night sky, contrail behind it -- */

.sky-plane {
  position: absolute;
  top: 15%;
  left: -12%;
  color: rgba(255, 255, 255, 0.9);
  filter: drop-shadow(0 0 7px rgba(255, 255, 255, 0.5));
  opacity: 0;
  animation: plane-cross 18s linear 2.5s infinite;
  pointer-events: none;
  will-change: transform;
}

.sky-plane svg {
  display: block;
  transform: rotate(90deg); /* the glyph points up; fly it to the right */
}

.sky-plane::before {
  content: "";
  position: absolute;
  top: 50%;
  right: 100%;
  width: clamp(90px, 18vw, 220px);
  height: 2px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55));
}

@keyframes plane-cross {
  0%   { transform: translate3d(0, 2.5vh, 0); opacity: 0; }
  4%   { opacity: 1; }
  44%  { opacity: 1; }
  50%  { transform: translate3d(126vw, -5vh, 0); opacity: 0; }
  100% { transform: translate3d(126vw, -5vh, 0); opacity: 0; }
}

/* -- drifting clouds / mist (position + size via inline custom props) -- */

.cloud {
  position: absolute;
  left: var(--cx, 10%);
  top: var(--cy, 50%);
  width: var(--cw, 300px);
  aspect-ratio: 3 / 1;
  opacity: var(--co, 0.5);
  pointer-events: none;
  background:
    radial-gradient(closest-side at 30% 66%, var(--cc, #FFFFFF) 0%, transparent 100%),
    radial-gradient(closest-side at 58% 36%, var(--cc, #FFFFFF) 0%, transparent 100%),
    radial-gradient(closest-side at 79% 68%, var(--cc, #FFFFFF) 0%, transparent 100%);
  animation: cloud-drift var(--cd, 48s) ease-in-out var(--cdel, 0s) infinite alternate;
  will-change: transform;
}

@keyframes cloud-drift {
  from { transform: translateX(-28px); }
  to   { transform: translateX(28px); }
}

/* --------------------------------------------------------------------------
   HERO — night sky melting into periwinkle, cabin scene as centerpiece
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(2.6rem, 7vh, 4.2rem) 1.25rem 2.4rem;
  /* periwinkle dusk with deep indigo accents (brief) — not black night.
     The tail eases into #C9CBE4 with a decaying slope so the hand-off to
     the flight zone (which continues at the same gentle rate) has no
     visible Mach band at the seam. */
  background: linear-gradient(180deg,
    #34305E 0%,
    #403B71 14%,
    var(--indigo-deep) 38%,
    #5E5B9D 56%,
    var(--jet-blue) 72%,
    #9C9BC6 84%,
    #B3B4D6 90%,
    #C1C3DF 95%,
    #C7C9E2 98%,
    #C9CBE4 100%);
}

.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* slow celestial sheen: a huge blurred conic wheel turning behind the stars */
.hero-bg::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 26%;
  width: 130vmax;
  aspect-ratio: 1;
  translate: -50% -50%;
  background: conic-gradient(from 0deg,
      transparent 0deg,
      rgba(127, 127, 184, 0.17) 42deg,
      transparent 84deg,
      rgba(194, 24, 91, 0.11) 148deg,
      transparent 200deg,
      rgba(226, 202, 130, 0.13) 268deg,
      transparent 320deg);
  mix-blend-mode: screen;
  filter: blur(42px);
  animation: sheen-spin 46s linear infinite;
  will-change: transform;
}

@keyframes sheen-spin {
  to { transform: rotate(360deg); }
}

#hero-stars { height: 55%; }

/* -- passing light streaks / contrails -- */

.streak {
  position: absolute;
  height: 2px;
  width: clamp(140px, 30vw, 300px);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.75), transparent);
  opacity: 0;
  animation: streak-fly 9s ease-in-out infinite;
}

.streak-1 { top: 14%; left: -4%; animation-delay: 1.6s; }
.streak-2 { top: 7%; right: 2%; animation-delay: 5.8s; }
.streak-3 { top: 24%; left: 34%; animation-delay: 3.4s; }

@keyframes streak-fly {
  0%   { transform: translateX(-70px) rotate(-14deg); opacity: 0; }
  10%  { opacity: 0.7; }
  28%  { transform: translateX(160px) rotate(-14deg); opacity: 0; }
  100% { transform: translateX(160px) rotate(-14deg); opacity: 0; }
}

.hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
  max-width: 680px;
}

.greeting {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.02rem, 3vw, 1.3rem);
  color: #D9DCF3;
  margin-bottom: 1rem;
  text-shadow: 0 2px 14px rgba(13, 10, 30, 0.55);
  animation: fade-up 0.8s ease 0.1s backwards;
}

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.9em;
  color: var(--gold-soft);
  text-indent: 0;
  animation: fade-up 0.8s ease 0.2s backwards;
}

.hero-eyebrow::before,
.hero-eyebrow::after {
  content: "";
  width: clamp(18px, 6vw, 38px);
  height: 1px;
  flex: none;
}

.hero-eyebrow::before { background: linear-gradient(90deg, transparent, var(--gold-soft)); }
.hero-eyebrow::after  { background: linear-gradient(90deg, var(--gold-soft), transparent); }

.names {
  position: relative;
  z-index: 2;
  margin-top: 1.1rem;
  color: #FFFFFF;
  /* floor low enough that 11.5vw always wins on phones: the line width is
     then ~83vw, so "Chern & Javier" stays on ONE line on any screen */
  font-size: clamp(1.9rem, 11.5vw, 5.4rem);
  line-height: 1.02;
  letter-spacing: 0.005em;
  white-space: nowrap;
  text-shadow:
    0 3px 20px rgba(13, 10, 30, 0.35),
    0 0 58px rgba(127, 127, 184, 0.38);
}

.names .word {
  display: inline-block;
  white-space: nowrap;
}

.names .amp {
  font-style: italic;
  color: var(--gold-soft);
  font-size: 0.72em;
  padding: 0 0.08em;
}

/* letter-by-letter reveal (spans injected by invite.js) */
.names .ltr {
  display: inline-block;
  animation: letter-in 0.8s cubic-bezier(0.16, 0.8, 0.32, 1) both;
  animation-delay: calc(240ms + var(--i) * 70ms);
}

@keyframes letter-in {
  from {
    opacity: 0;
    transform: translateY(0.5em) scale(0.92);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.subtitle {
  position: relative;
  z-index: 2;
  margin-top: 0.9rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.08rem, 3.6vw, 1.5rem);
  color: #D9DCF3;
  text-shadow: 0 2px 16px rgba(13, 10, 30, 0.6);
  animation: fade-up 0.9s ease 1.1s backwards;
}

/* -- the photo scenes: soft-masked, feathered into the sky -- */

.scene {
  position: relative;
  margin: 0;
}

/* The oval mask lives on this wrapper, NOT on the img: the visible oval
   stays locked to the gold frame ring while the photo pans inside it. */
.scene-mask {
  overflow: hidden;
  /* graceful fallback shape if masks are unsupported */
  border-radius: 38% 38% 42% 42% / 30% 30% 34% 34%;
  -webkit-mask-image: radial-gradient(ellipse 64% 56% at 50% 44%,
      #000 44%, rgba(0, 0, 0, 0.85) 58%, transparent 79%);
          mask-image: radial-gradient(ellipse 64% 56% at 50% 44%,
      #000 44%, rgba(0, 0, 0, 0.85) 58%, transparent 79%);
}

.scene-mask img {
  width: 100%;
  height: auto;
}

/* drawn edge: offset gold hairline ring echoing the mask ellipse (v3 graft) */
.scene::after {
  content: "";
  position: absolute;
  inset: 1% 0 9%;
  border: 1px solid var(--gold);
  border-radius: 50%;
  transform: rotate(-4deg) scale(1.04);
  opacity: 0.6;
  pointer-events: none;
}

.scene-glow {
  position: absolute;
  inset: -16% -20%;
  z-index: -1;
  background: radial-gradient(closest-side,
      rgba(127, 127, 184, 0.55) 0%,
      rgba(75, 72, 133, 0.32) 55%,
      transparent 100%);
  animation: glow-breathe 7s ease-in-out infinite;
}

@keyframes glow-breathe {
  0%, 100% { opacity: 0.75; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.045); }
}

.scene-cabin {
  width: min(100%, 430px);
  /* cap by small-viewport height so greeting + names + photo + tail + cue
     all fit the first screen even with tall browser chrome (Brave etc.) */
  width: min(100%, 430px, 52svh);
  margin-top: clamp(-2.1rem, -4vw, -1rem);
  animation: float-drift 10s ease-in-out infinite;
}

/* The source picture is shot off-center — pan the photo left INSIDE the
   fixed oval mask so its content centers under the frame ring, and zoom it
   so its pixels cover the whole mask fade (no flat cut at the box edges).
   scale() is applied after the translate, so the pan stays content-centering
   at any zoom. */
.scene-cabin .scene-mask img {
  transform: scale(1.14) translateX(-5.5%);
}

.hero-tail {
  position: relative;
  z-index: 2;
  margin-top: clamp(-4.8rem, -12vw, -3.2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  animation: fade-up 0.9s ease 1.4s backwards;
}

.tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.05rem, 3.2vw, 1.3rem);
  color: #F4F5FE;
  text-shadow: 0 2px 18px rgba(13, 10, 30, 0.8);
}

.hero-date {
  font-size: clamp(0.72rem, 2.3vw, 0.88rem);
  letter-spacing: 0.26em;
  text-indent: 0.26em;
  text-transform: uppercase;
  color: #E9EBFA;
  text-shadow: 0 2px 12px rgba(13, 10, 30, 0.8);
}

.scroll-hint {
  margin-top: 1.3rem;
  padding: 0.5em 1.2em;
  border-radius: 999px;
  /* opaque-ish night pill: keeps white text ≥ 4.5:1 even on the light
     bottom band of the hero gradient */
  background: rgba(29, 24, 55, 0.5);
  font-size: clamp(0.68rem, 2.2vw, 0.8rem);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  text-transform: uppercase;
  color: #FFFFFF;
}

@media (max-height: 700px) {
  .hero { padding-top: 1.6rem; padding-bottom: 1.6rem; }
  .greeting { margin-bottom: 0.4rem; }
  .names { margin-top: 0.7rem; }
  .subtitle { margin-top: 0.4rem; }
  /* shrink the photo further so names + photo + tail + cue all fit,
     even with the personalized greeting line present */
  .scene-cabin { width: min(100%, 430px, 40svh); }
  .hero-tail { gap: 0.25rem; }
  .scroll-hint { margin-top: 0.8rem; }
}

.scroll-cue {
  margin-top: 0.5rem;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  color: #FFFFFF;
  background: rgba(29, 24, 55, 0.28);
  animation: cue-bob 2.4s ease-in-out 2.4s infinite;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.scroll-cue:hover {
  border-color: #FFFFFF;
  background: rgba(29, 24, 55, 0.5);
}

@keyframes cue-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(8px); }
}

/* --------------------------------------------------------------------------
   THE FLIGHT — brightest zone; the KUL → DUS ← ALC converging routes
   -------------------------------------------------------------------------- */

.flight {
  position: relative;
  overflow: hidden;
  padding: clamp(4rem, 10vw, 6.5rem) 1.25rem clamp(4.5rem, 11vw, 7.5rem);
  background: linear-gradient(180deg,
    #C9CBE4 0%,
    var(--sky-soft) 26%,
    var(--cloud) 52%,
    #FAF3F2 78%,
    var(--blush) 100%);
}

/* high-altitude daylight: a soft sun halo, kept well inside the zone so the
   hero → flight gradient hand-off stays perfectly smooth */
.flight-bg::before {
  content: "";
  position: absolute;
  top: 6%;
  left: 50%;
  width: min(110vw, 820px);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle,
      rgba(255, 255, 255, 0.55) 0%,
      rgba(255, 250, 236, 0.28) 34%,
      transparent 66%);
  pointer-events: none;
}

.flight-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.flight-inner {
  position: relative;
  z-index: 1;
  max-width: 760px;
  margin: 0 auto;
}

.flight .eyebrow { color: var(--indigo-deep); }
.flight h2 { color: var(--ink); }

.route {
  margin: clamp(1.4rem, 5vw, 2.6rem) auto 0;
  max-width: 620px;
}

#route-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.route-line {
  animation: dash-march 1.5s linear infinite;
}

@keyframes dash-march {
  to { stroke-dashoffset: -9.5; }
}

.stop-dot {
  fill: var(--gold);
  stroke: #FFFFFF;
  stroke-width: 1.6;
}

.stop-dot-final { fill: var(--magenta); }

.stop-ring {
  fill: none;
  stroke: var(--jet-blue);
  stroke-width: 1.4;
  transform-box: fill-box;
  transform-origin: center;
  animation: ring-pulse 3.2s ease-out infinite;
}

.stop-2 .stop-ring { animation-delay: 1.1s; }
.stop-3 .stop-ring { animation-delay: 2.2s; stroke: var(--rose); }

@keyframes ring-pulse {
  0%   { transform: scale(0.35); opacity: 0.9; }
  65%  { transform: scale(1.3); opacity: 0; }
  100% { transform: scale(1.3); opacity: 0; }
}

.stop-code {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.08em;
  fill: var(--ink);
}

.stop-city {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 11px;
  fill: var(--ink-soft);
}

.dus-heart {
  fill: var(--magenta);
  transform-box: fill-box;
  transform-origin: center;
  animation: float-slow 5s ease-in-out infinite;
}

.route-plane { fill: var(--ink); }

.story {
  margin: clamp(1.8rem, 6vw, 3rem) auto 0;
  max-width: 37rem;
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.08rem, 3.1vw, 1.35rem);
  line-height: 1.75;
  color: #4A4570;
}

/* --------------------------------------------------------------------------
   ARRIVAL — pink dusk; the arrival scene + the facts
   -------------------------------------------------------------------------- */

.arrival {
  position: relative;
  overflow: hidden;
  padding: clamp(4rem, 10vw, 6.5rem) 1.25rem clamp(4.5rem, 10vw, 7rem);
  background: linear-gradient(180deg,
    var(--blush) 0%,
    #EEC0B6 30%,
    #E39D9C 64%,
    var(--rose) 100%);
}

.arrival-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* a low, breathing sun sinking into the dusk at the bottom of the zone
   (the .arrival-bg seam mask melts it away before the next section) */
.sunset-sun {
  position: absolute;
  left: 50%;
  bottom: -18%;
  width: min(95vw, 720px);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle,
      rgba(255, 226, 178, 0.85) 0%,
      rgba(255, 176, 146, 0.45) 30%,
      rgba(210, 116, 126, 0.18) 52%,
      transparent 70%);
  filter: blur(6px);
  animation: sun-breathe 11s ease-in-out infinite;
  will-change: transform, opacity;
}

@keyframes sun-breathe {
  0%, 100% { opacity: 0.85; transform: translateX(-50%) scale(1); }
  50%      { opacity: 1; transform: translateX(-50%) scale(1.06); }
}

.arrival-inner {
  position: relative;
  z-index: 1;
  max-width: 1020px;
  margin: 0 auto;
}

.arrival h2 { color: var(--wine); }
.arrival .section-sub { color: #7A4048; }

.arrival-grid {
  margin: clamp(1.8rem, 6vw, 3.4rem) auto 0;
  display: grid;
  gap: clamp(0.4rem, 2vw, 1.5rem);
  align-items: center;
}

.scene-arrival {
  width: min(100%, 430px);
  margin-inline: auto;
  /* pull the facts up into the feathered bottom — no dead pink band on mobile */
  margin-bottom: clamp(-2.5rem, -7vw, -1rem);
  animation: float-drift 11s ease-in-out infinite;
}

/* a true soft-edged oval whose fade completes INSIDE the box on every side
   (no flat cuts at the top or sides), still framed by the gold ring */
.scene-arrival .scene-mask {
  -webkit-mask-image: radial-gradient(ellipse 49.5% 45.5% at 50% 46%,
      #000 70%, rgba(0, 0, 0, 0.85) 82%, transparent 99%);
          mask-image: radial-gradient(ellipse 49.5% 45.5% at 50% 46%,
      #000 70%, rgba(0, 0, 0, 0.85) 82%, transparent 99%);
}

.scene-arrival::after {
  inset: 0 0 6%;
  transform: rotate(-4deg) scale(1.05);
}

.scene-glow-pink {
  inset: -4% -7%;
  background: radial-gradient(closest-side,
      rgba(235, 148, 158, 0.22) 0%,
      rgba(194, 24, 91, 0.08) 55%,
      transparent 100%);
}

.facts {
  max-width: 34rem;
  margin-inline: auto;
  text-align: center;
}

.fact-label {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  /* deep magenta: ≥ 4.5:1 even on the rose end of the arrival gradient */
  color: #4A0C26;
}

.fact-big {
  margin-top: 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(1.65rem, 6vw, 2.35rem);
  line-height: 1.15;
  color: #421D26;
}

.fact-text {
  margin-top: 0.55rem;
  line-height: 1.65;
  /* dark plum: ≥ 4.5:1 on the darkest band behind the lowest fact card */
  color: #421D26;
}

.fact-time {
  display: inline-block;
  margin-top: 0.45rem;
  color: #421D26;
}

.fact + .fact {
  margin-top: 1.9rem;
  padding-top: 1.9rem;
  border-top: 1px solid rgba(201, 162, 39, 0.55); /* thin gold hairline */
}

.map-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin-top: 1.05rem;
  padding: 0.6em 1.4em;
  border: 1.5px solid var(--wine);
  border-radius: 999px;
  color: var(--wine);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  transition:
    background-color 0.2s ease,
    color 0.2s ease,
    transform 0.18s ease,
    box-shadow 0.2s ease;
}

.map-link:hover {
  background: var(--wine);
  color: #FFFFFF;
  transform: translateY(-2px);
  box-shadow: 0 10px 24px rgba(142, 47, 60, 0.35);
}

/* -- itinerary: the day's flight plan, a small timeline with gold stops -- */

.itinerary {
  margin: clamp(3rem, 8vw, 4.5rem) auto 0;
  max-width: 34rem;
  text-align: center;
}

.itinerary h3 {
  margin-top: 0.7rem;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 5.5vw, 2.1rem);
  line-height: 1.15;
  color: #421D26;
}

.itin {
  list-style: none;
  margin: clamp(1.4rem, 4vw, 2rem) 0 0;
  padding: 0;
  text-align: left;
  display: grid;
  gap: 0;
}

.itin-row {
  position: relative;
  display: grid;
  grid-template-columns: 5.2rem 28px minmax(0, 1fr); /* fits '10:45 AM' in mono */
  align-items: start;
  column-gap: 0.4rem;
  padding-bottom: 1.5rem;
}

.itin-row:last-child { padding-bottom: 0; }

/* connecting line between the gold stops */
.itin-row:not(:last-child)::before {
  content: "";
  position: absolute;
  left: calc(5.2rem + 0.4rem + 13px);
  top: 20px;
  bottom: -4px;
  width: 2px;
  background: linear-gradient(180deg, rgba(201, 162, 39, 0.8), rgba(201, 162, 39, 0.35));
}

.itin-time {
  white-space: nowrap;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.5;
  color: #421D26;
  text-align: right;
}

.itin-dot {
  justify-self: center;
  width: 12px;
  height: 12px;
  margin-top: 5px;
  border-radius: 50%;
  background: var(--gold);
  border: 2px solid #FFF6F0;
  box-shadow: 0 0 0 2px rgba(201, 162, 39, 0.45);
}

.itin-what {
  font-weight: 600;
  line-height: 1.5;
  color: #421D26;
}

.itin-note {
  margin-top: 0.15rem;
  font-size: 0.92rem;
  line-height: 1.5;
  color: #5C2A33;
}

@media (min-width: 880px) {
  .arrival-grid {
    grid-template-columns: minmax(0, 440px) minmax(0, 1fr);
    column-gap: clamp(2.4rem, 5vw, 3.5rem);
    align-items: center; /* photo and fact column share a midline */
  }

  .scene-arrival { margin-bottom: 0; }

  .facts {
    margin-inline: 0;
    text-align: left;
  }

  .fact-label { text-indent: 0; }
}

/* --------------------------------------------------------------------------
   RSVP — dusk deepens; the boarding pass
   -------------------------------------------------------------------------- */

.rsvp-zone {
  position: relative;
  overflow: hidden;
  padding: clamp(3.6rem, 9vw, 6rem) 1.25rem clamp(4.5rem, 11vw, 7.5rem);
  /* one step warmer than wine, so the pass header + magenta button pop */
  background: linear-gradient(180deg,
    var(--rose) 0%,
    #C05C68 55%,
    #A34351 100%);
}

.rsvp-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* last light of the day: a wide amber glow rising behind the boarding pass */
.dusk-glow {
  position: absolute;
  left: 50%;
  top: -18%;
  width: min(130vw, 1100px);
  aspect-ratio: 2 / 1;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 0%,
      rgba(255, 197, 154, 0.35) 0%,
      rgba(226, 202, 130, 0.14) 42%,
      transparent 70%);
  animation: dusk-shimmer 14s ease-in-out infinite;
}

@keyframes dusk-shimmer {
  0%, 100% { opacity: 0.75; }
  50%      { opacity: 1; }
}

.zone-head {
  position: relative;
  z-index: 1;
  text-align: center;
  margin-bottom: clamp(1.6rem, 5vw, 2.6rem);
}

.zone-title {
  margin-top: 0.6rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.95rem, 7vw, 2.9rem);
  line-height: 1.08;
  color: #FFF6F4;
  text-shadow: 0 4px 28px rgba(80, 17, 32, 0.5);
}

/* boarding-pass card: white surface with punched side notches */
.pass {
  position: relative;
  z-index: 1;
  max-width: 560px;
  margin: 0 auto;
  border-radius: 22px;
  box-shadow: 0 26px 55px rgba(46, 10, 25, 0.4);
  background:
    radial-gradient(circle 11px at 0 calc(100% - 84px), rgba(0, 0, 0, 0) 10px, #FDFDFF 11px)
      left / 50.5% 100% no-repeat,
    radial-gradient(circle 11px at 100% calc(100% - 84px), rgba(0, 0, 0, 0) 10px, #FDFDFF 11px)
      right / 50.5% 100% no-repeat;
}

.pass-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.15rem 0.8rem;
  padding: 0.85rem 1.25rem;
  border-radius: 22px 22px 0 0;
  background: linear-gradient(110deg, var(--night) 0%, var(--indigo-deep) 55%, #7A2E63 100%);
  color: #E9EAF8;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.pass-flight { color: var(--gold-soft); }

.pass-main {
  padding: clamp(1.5rem, 4.5vw, 2.2rem) clamp(1.15rem, 4vw, 2rem) clamp(1.7rem, 5vw, 2.3rem);
  text-align: center;
}

/* -- boarding-pass meta: mono route row + flight facts (v2 graft) -- */

.pass-meta-block { margin-bottom: 1.5rem; }

/* guests fly in from everywhere — the pass only names the destination:
   ARRIVAL stacked over ✈ DUS, city beneath, everything centered */
.pr-label {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-soft);
  margin-bottom: 0.35rem;
}

.pass-route-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.5rem, 2.5vw, 0.85rem);
  font-family: var(--font-mono);
}

.pr-plane {
  color: var(--gold);
  font-size: clamp(1.35rem, 5.5vw, 1.9rem);
  line-height: 1;
}

.pr-city {
  margin-top: 0.2rem;
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.pr-code {
  font-size: clamp(1.45rem, 6.8vw, 2.1rem);
  font-weight: 700;
  letter-spacing: 0.05em;
  line-height: 1.1;
  color: var(--night);
}

.pr-dest { color: var(--magenta); }

.pass-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.55rem clamp(1.2rem, 5vw, 2.2rem);
  margin: 0.9rem 0 0;
  padding-bottom: 1.15rem;
  border-bottom: 1.5px dashed rgba(29, 24, 55, 0.2);
}

.pass-meta > div { text-align: center; }

.pass-meta dt {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.pass-meta dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--night);
}

.pass-heart { color: var(--magenta); }

@media (min-width: 560px) {
  .pass-head { flex-wrap: nowrap; }
}

#rsvp-title {
  font-size: clamp(1.5rem, 5vw, 1.9rem);
  color: var(--ink);
}

.rsvp-sub {
  color: var(--ink-soft);
  margin-top: 0.45rem;
}

.prize-badge {
  display: inline-block;
  margin-top: 1.1rem;
  padding: 0.5em 1.1em;
  background: linear-gradient(120deg, var(--gold-soft), #F4E7BE 50%, var(--gold-soft));
  border: 1px solid var(--gold);
  border-radius: 999px;
  color: #4A3A08;
  font-weight: 600;
  font-size: 0.95rem;
  box-shadow: 0 4px 14px rgba(201, 162, 39, 0.3);
  animation: badge-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes badge-pop {
  from { transform: scale(0.6); opacity: 0; }
}

.rsvp-loading {
  margin-top: 1.6rem;
  color: var(--ink-soft);
  font-style: italic;
  animation: loading-pulse 1.6s ease-in-out infinite;
}

@keyframes loading-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/* -- answered / result card -- */

.rsvp-status {
  margin-top: 1.4rem;
  animation: fade-up 0.6s ease;
}

.status-icon {
  font-size: 2.6rem;
  line-height: 1.2;
}

.rsvp-status h3 {
  font-size: 1.5rem;
  margin-top: 0.4rem;
}

.status-text {
  color: var(--ink-soft);
  margin-top: 0.6rem;
  max-width: 44ch;
  margin-inline: auto;
}

.status-msg {
  font-family: var(--font-display);
  font-style: italic;
  color: var(--ink-soft);
  background: var(--cream-100);
  border-radius: 12px;
  padding: 0.7em 1em;
  margin-top: 0.9rem;
  overflow-wrap: anywhere;
}

#change-answer {
  margin-top: 1.3rem;
}

/* -- form -- */

#rsvp-form {
  margin-top: 0.4rem;
  text-align: left;
}

.party-field {
  margin-top: 1.5rem;
  text-align: center;
}

.field-label {
  font-weight: 600;
  margin-bottom: 0.85rem;
}

.stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
}

.step-btn {
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--indigo-deep);
  border-radius: 50%;
  background: var(--cloud);
  color: var(--ink);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s ease, background-color 0.15s ease, opacity 0.15s ease;
}

.step-btn:hover:not(:disabled) {
  background: var(--sky-soft);
  transform: scale(1.07);
}

.step-btn:active:not(:disabled) {
  transform: scale(0.93);
}

.step-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.step-count {
  display: inline-block;
  min-width: 3ch;
  text-align: center;
  font-family: var(--font-display);
  font-size: 2.2rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.step-hint {
  margin-top: 0.6rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
  text-align: center;
}

.wishes-label {
  display: block;
  margin: 1.6rem 0 0.5rem;
  font-weight: 600;
}

.wishes-label span {
  font-weight: 400;
  font-size: 0.9em;
  color: var(--ink-soft);
}

#wishes,
#dietary {
  width: 100%;
  min-height: 92px;
  padding: 0.9em 1em;
  background: var(--cloud);
  border: 1px solid var(--cream-200);
  border-radius: 12px;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

#wishes:focus,
#dietary:focus {
  outline: none;
  border-color: var(--magenta);
  box-shadow: 0 0 0 3px rgba(194, 24, 91, 0.14);
}

.rsvp-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.8rem;
  margin-top: 1.6rem;
}

.rsvp-actions .btn-primary {
  font-size: 1.08rem;
  padding: 1em 2em;
}

/* secondary actions need a visible outline on the white card */
.pass-main .btn-ghost {
  border-color: var(--jet-blue);
  color: var(--indigo-deep);
}

@media (min-width: 560px) {
  .rsvp-actions {
    flex-direction: row;
    justify-content: center;
    align-items: center;
  }
}

.rsvp-error {
  margin-top: 1rem;
  text-align: center;
  font-size: 0.95rem;
  color: var(--wine);
}

.rsvp-fallback {
  margin-top: 1.6rem;
  padding: 1.2rem 1.4rem;
  background: var(--cream-100);
  border: 1px dashed var(--periwinkle);
  border-radius: 12px;
  color: var(--ink-soft);
}

/* -- tear-off stub: compact single row on every screen —
      SEAT · GATE · DATE on the left, barcode on the right -- */

.pass-stub {
  position: relative;
  height: 84px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(0.6rem, 3vw, 1.6rem);
  padding: 0 clamp(0.9rem, 4vw, 1.25rem);
}

/* the tear-off dashes run BETWEEN the two punched notch circles (r = 11px),
   not through them */
.pass-stub::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 15px;
  right: 15px;
  border-top: 2px dashed var(--periwinkle);
}

.stub-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.3;
}

.stub-cell span {
  font-size: clamp(0.52rem, 1.8vw, 0.6rem);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.stub-cell strong {
  font-size: clamp(0.7rem, 2.4vw, 0.84rem);
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}

.stub-heart { color: var(--magenta); }

.stub-barcode {
  margin-left: auto;
  width: clamp(40px, 12vw, 62px);
  height: 36px;
  flex: none;
  opacity: 0.75;
  background: repeating-linear-gradient(90deg,
    var(--ink) 0 2px, transparent 2px 4px,
    var(--ink) 4px 7px, transparent 7px 9px);
}

/* --------------------------------------------------------------------------
   FOOTER — nightfall after the sunset
   -------------------------------------------------------------------------- */

.site-footer {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: clamp(4rem, 9vw, 5.5rem) 1.25rem 3rem;
  /* eases OUT of #A34351 slowly (matching the gentle slope at the end of
     the RSVP zone) before accelerating into the night — no seam band */
  background: linear-gradient(180deg,
    #A34351 0%,
    #A24252 7%,
    #97394C 20%,
    #7A2C45 36%,
    #55203E 60%,
    #2A1B3D 82%,
    var(--night) 100%);
  color: #E6E8F9;
}

.footer-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.aurora-footer {
  top: -40%;
  left: 10%;
  width: 60vmax;
  height: 60vmax;
  background:
    radial-gradient(circle at 40% 40%, rgba(194, 24, 91, 0.28) 0%, transparent 56%),
    radial-gradient(circle at 66% 60%, rgba(127, 127, 184, 0.35) 0%, transparent 62%);
  animation: aurora-drift-b 38s ease-in-out -8s infinite alternate;
}

.hibiscus-btn {
  position: relative;
  z-index: 1;
  display: inline-flex;
  padding: 6px;
  border: none;
  background: none;
  border-radius: 50%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 0 16px rgba(194, 24, 91, 0.55));
  animation: float-drift 6s ease-in-out infinite;
  transition: transform 0.2s ease;
}

.hibiscus-btn:hover { transform: scale(1.08) rotate(-6deg); }
.hibiscus-btn:active { transform: scale(0.95); }

.hibiscus-btn:focus-visible {
  outline: 3px solid var(--gold-soft);
  outline-offset: 3px;
}

.secret-hint {
  position: relative;
  z-index: 1;
  margin-top: 0.4rem;
  font-size: 0.85rem;
  font-style: italic;
  color: rgba(230, 232, 249, 0.72);
}

.footer-line {
  position: relative;
  z-index: 1;
  margin-top: 1.6rem;
  font-family: var(--font-display);
  color: #F4F5FE;
}

.footer-note {
  position: relative;
  z-index: 1;
  margin-top: 0.35rem;
  font-size: 0.85rem;
  color: rgba(230, 232, 249, 0.55);
}

.rsvp-locked {
  margin-top: 1.4rem;
  padding: 1.2rem 1.4rem;
  background: var(--cream-100);
  border: 1px solid var(--cream-200);
  border-radius: 12px;
  color: var(--ink-soft);
}

.locked-icon {
  font-size: 1.8rem;
  line-height: 1.2;
  margin-bottom: 0.35rem;
}

/* --------------------------------------------------------------------------
   Game teaser modal — shown while the escape room is still locked
   -------------------------------------------------------------------------- */

.teaser-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  overflow-y: auto; /* short/landscape phones: scroll instead of clipping */
  padding: 1.25rem;
}

body.teaser-scroll-lock { overflow: hidden; }

.teaser-backdrop {
  /* fixed, not absolute: must keep covering the page when the overlay scrolls */
  position: fixed;
  inset: 0;
  background: rgba(29, 24, 55, 0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.teaser-card {
  position: relative;
  width: min(100%, 430px);
  margin: auto; /* centers when it fits, scrolls from the top when it doesn't */
  padding: 2.2rem 1.7rem 1.9rem;
  border-radius: 22px;
  background: var(--cream-50);
  box-shadow: 0 30px 70px rgba(13, 10, 30, 0.5);
  text-align: center;
  animation: teaser-pop 0.4s cubic-bezier(0.34, 1.4, 0.64, 1);
}

@keyframes teaser-pop {
  from { transform: translateY(18px) scale(0.94); opacity: 0; }
}

.teaser-close {
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: var(--cream-100);
  color: var(--ink-soft);
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.teaser-close:hover {
  background: var(--cream-200);
  color: var(--ink);
}

.teaser-emoji {
  font-size: 2.6rem;
  line-height: 1.1;
}

.teaser-card h2 {
  margin-top: 0.6rem;
  font-size: clamp(1.4rem, 5vw, 1.7rem);
}

.teaser-text {
  margin-top: 0.8rem;
  color: var(--ink-soft);
  line-height: 1.65;
}

.teaser-text strong { color: var(--ink); }

/* --------------------------------------------------------------------------
   Confetti canvas (created by invite.js on accept)
   -------------------------------------------------------------------------- */

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