/* intro.css -- the envelope video intro (ported from hardik-nandini animations.css,
 * itself pukhraj-poorva's). js/intro.js drives the classes:
 *   .is-playing   tapped: the pill retires, the clip plays
 *   .is-leaving   the 2000ms dissolve: opacity + scale push toward the guest and a
 *                 warm ivory bloom, while the logo slide fades up underneath
 * JS removes the node on transitionend (opacity) with a fallback that MUST outlast
 * --intro-fade (js/intro.js REMOVE_FALLBACK_MS) -- change one, change both.
 * No logo page: the clip stops at 2.55 s, before ashish-priyanshi's baked monogram.
 */
.intro {
  --intro-bg: #d9e8ed;          /* the blue envelope's edge colour (ashish-priyanshi clip) */
  --intro-fade: 2000ms;
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--intro-bg);
  overflow: hidden;
  transform: scale(1);
  isolation: isolate;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.intro__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--intro-bg);
}

/* Sealed-envelope <img> stand-in for the video's poster: Chrome drops the poster
 * at play() ~430ms before the first frame presents, which flashes the background.
 * JS hides this the frame the video paints (requestVideoFrameCallback). */
.intro__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.intro__poster.is-hidden { display: none; }

/* Wider than a phone: show the whole envelope as a centred column (the clip is
 * 1080x1920) on its own edge colour instead of cropping it to the seal. */
@media (min-aspect-ratio: 3/4) {
  .intro__video, .intro__poster { object-fit: contain; }
}

/* The envelope PSD's own lines ("You're Cordially Invited" / "TAP TO UNVEIL THE
 * DETAILS") as live text on their PSD baselines. .intro__frame is the clip's 1080x1920
 * box as object-fit draws it (cover on phones, contain when wider), so the type sits
 * exactly where the PSD put it on the paper; 1 design px = --u as in stage.css. */
.intro { container-type: size; }
.intro__frame {
  position: absolute;
  left: 50%;
  top: 50%;
  width: max(100cqw, 100cqh * 1080 / 1920);
  aspect-ratio: 1080 / 1920;
  transform: translate(-50%, -50%);
  container-type: inline-size;
  --u: calc(100cqw / 1080);
  pointer-events: none;
}
@media (min-aspect-ratio: 3/4) {
  .intro__frame { width: min(100cqw, 100cqh * 1080 / 1920); }
}
.intro__line { z-index: 1; }
/* "Tap to unveil" breathes so it reads as the affordance (opacity only). */
.intro__line--2 .r { animation: su-breathe 2.6s ease-in-out infinite; }
@keyframes su-breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}
/* The labelled control: an invisible hit box over the two lines (tapping anywhere on
 * the envelope does the same -- js/intro.js). */
.intro__open {
  position: absolute;
  left: calc(250 * var(--u));
  top: calc(1180 * var(--u));
  width: calc(580 * var(--u));
  height: calc(140 * var(--u));
  padding: 0;
  border: 0;
  border-radius: calc(24 * var(--u));
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}
.intro__open:focus-visible { outline: 2px solid #8a3b3b; outline-offset: 2px; } /* keyboard only: no auto-focus */
/* Once playback starts, retire the affordance (opacity only). */
.intro.is-playing { cursor: default; }
.intro.is-playing .intro__open { pointer-events: none; }
.intro.is-playing .intro__line {
  opacity: 0;
  transition: opacity 240ms ease;
}

/* Exit: a slow dissolve on a curve that keeps light in the frame for the whole
 * fade, a gentle scale push-through, and a warm ivory bloom that swells once so
 * the envelope opens INTO light. */
.intro::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse at 50% 42%, rgba(255, 247, 232, 0.95), rgba(255, 247, 232, 0) 70%);
}
.intro.is-leaving::before { animation: sr-intro-bloom var(--intro-fade) ease-in-out both; }
@keyframes sr-intro-bloom {
  0%   { opacity: 0; }
  30%  { opacity: 0.85; }
  100% { opacity: 0; }
}
.intro.is-leaving {
  opacity: 0;
  transform: scale(1.07);
  pointer-events: none;
  transition:
    opacity var(--intro-fade) cubic-bezier(0.45, 0.05, 0.25, 1),
    transform var(--intro-fade) cubic-bezier(0.22, 1, 0.36, 1);
}

/* The logo slide waits unseen under the envelope, then fades up out of a slight
 * overscale as the envelope melts. intro.js owns this (adds .sr-enter, removes it
 * on animationend so no transform stays on the stage). Opacity is full by 45%; the
 * tail is a pure scale settle. */
html.is-locked .scene--logo .stage { opacity: 0; }
.scene--logo .stage.sr-enter {
  transform-origin: 50% calc(var(--sr-vh, 100vh) / 2);
  animation: sr-logo-enter 2.8s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes sr-logo-enter {
  from { opacity: 0; transform: scale(1.05); }
  45%  { opacity: 1; }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .intro__line--2 .r { animation: none; }
  .intro.is-leaving { transform: none; transition: opacity 250ms ease; }
  .intro::before, .intro.is-leaving::before { animation: none; opacity: 0; }
  .scene--logo .stage.sr-enter { animation: none; }
}
