/* ===================================================================
   MOTION — the opening sequence, scroll reveals, and every keyframe
   Everything here is opt-out: with JS off, or reduced motion on, the
   page renders as plain static type.
   =================================================================== */

/* ===============================================================
   1 · OPENING SEQUENCE
   The hero pieces arrive in order: names, portrait, invitation,
   rings, the RSVP line. Whole words move as one so the cursive
   shaping and spacing stay exactly as designed.
   =============================================================== */
html.intro-pending .lockup,
html.intro-pending .hero__photo,
html.intro-pending .hero__greeting,
html.intro-pending .hero__invite,
html.intro-pending .hero__rings,
html.intro-pending .hero__rsvp,
html.intro-pending .vines{opacity:0}

html.intro-playing .lockup .n1  {animation:fade-up .95s var(--ease-soft) .05s both}
html.intro-playing .lockup .amp {animation:fade-in-soft .9s var(--ease-soft) .55s both}
html.intro-playing .lockup .n2  {animation:fade-up .95s var(--ease-soft) .35s both}
html.intro-playing .lockup      {opacity:1}
html.intro-playing .hero__photo img{animation:portrait-in 1.5s var(--ease-soft) .15s both}
html.intro-playing .hero__photo {opacity:1}
html.intro-playing .hero__greeting{animation:fade-up .8s var(--ease-soft) 1.15s both}
html.intro-playing .hero__invite{animation:fade-up .8s var(--ease-soft) 1.35s both}
html.intro-playing .hero__rings {animation:fade-in-soft 1.1s var(--ease-soft) 1.6s both}
html.intro-playing .hero__rsvp  {animation:fade-up .8s var(--ease-soft) 1.85s both}
html.intro-playing .vines{animation:fade-in-soft 1.4s ease 1.7s both}

/* ===============================================================
   2 · SCROLL REVEALS
   [data-reveal] starts hidden and is released by an observer.
   --d on a child inside [data-stagger] shifts its delay.
   =============================================================== */
html.js [data-reveal]{opacity:0;will-change:opacity,transform}
html.js [data-reveal="up"]     {transform:translateY(26px)}
html.js [data-reveal="left"]   {transform:translateX(-26px)}
html.js [data-reveal="right"]  {transform:translateX(26px)}
html.js [data-reveal="scale"]  {transform:scale(.95)}
html.js [data-reveal].is-in{
  opacity:1;transform:none;will-change:auto;
  transition:opacity .95s var(--ease-soft) var(--d,0s),
             transform .95s var(--ease-soft) var(--d,0s);
}
/* the corner sprays only ever fade — a transform would shift them off
   the corner they are anchored to */
html.js .corner[data-reveal],
html.js .corner[data-reveal].is-in{transform:none}
html.js .corner--tr[data-reveal],
html.js .corner--tr[data-reveal].is-in,
html.js .corner--br[data-reveal],
html.js .corner--br[data-reveal].is-in{transform:scaleX(-1)}
html.js .corner[data-reveal].is-in{transition:opacity 1.3s var(--ease-soft) var(--d,0s)}

/* line art that inks itself in — JS measures each path and hands the
   length to CSS as --len */
html.js [data-draw] path{stroke-dasharray:var(--len,0);stroke-dashoffset:var(--len,0)}
html.js [data-draw].is-drawn path{
  stroke-dashoffset:0;
  transition:stroke-dashoffset 1.6s var(--ease-soft) var(--dd,0s);
}

/* ===============================================================
   3 · AMBIENT LOOPS
   =============================================================== */
.band__car{animation:drift 9s ease-in-out infinite}
.schedule__flutes{animation:drift 10s ease-in-out infinite}
.rsvp__art img{animation:drift 12s ease-in-out infinite}

/* gentle parallax — one scroll pass writes --par, CSS moves the piece */
.band__figure{transform:translate3d(0,var(--par,0px),0)}

/* cards lift under the pointer */
.card{transition:transform .45s var(--ease-soft)}
@media (hover:hover){
  .card:hover{transform:translateY(-6px)}
}

/* countdown numerals cross-fade as they change */
.count__num.is-tick{animation:tick .55s var(--ease-soft)}

/* ===============================================================
   4 · KEYFRAMES
   =============================================================== */
@keyframes fade-up{
  from{opacity:0;transform:translateY(16px)}
  to{opacity:1;transform:none}
}
@keyframes fade-in-soft{from{opacity:0}to{opacity:1}}
@keyframes portrait-in{
  from{opacity:0;transform:scale(1.05)}
  to{opacity:1;transform:none}
}
@keyframes drift{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-7px)}
}
@keyframes tick{
  0%{opacity:.15;transform:translateY(-14%)}
  100%{opacity:1;transform:none}
}

/* ===============================================================
   5 · OPT-OUTS
   =============================================================== */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  html.js [data-reveal]{opacity:1;transform:none}
  html.js .corner--tr[data-reveal],
  html.js .corner--br[data-reveal]{transform:scaleX(-1)}
  html.js [data-draw] path{stroke-dashoffset:0}
}
@media print{
  html.js [data-reveal]{opacity:1!important}
  html.js [data-draw] path{stroke-dashoffset:0!important}
}
