/* scroll-fx.css — the art's scroll choreography: every moving PSB layer comes IN as it
 * enters and goes OUT as it leaves, and reverses when you scroll back.
 *
 * DOM per cutout (build/build.cjs):   .cut          geometry + the hero's load entrance
 *                                       > .cut-mv   THIS file: scroll-driven in / out
 *                                         > .cut-in ambient loop (css/ambient.css)
 * Three nodes so the load entrance, the scroll scrub and the idle loop never fight over
 * one element's `transform`.
 *
 * Two mutually exclusive branches, split by @supports (pukhraj-poorva's contract):
 *   1. view() timelines — scrubbed by each cutout's own scroll position. Each .cut owns a
 *      named view timeline (--cut) and its .cut-mv runs TWO animations on it: the IN
 *      (fill both) over --rin and the OUT (fill forwards only) over --rout. Before --rout
 *      starts the OUT is inactive, so the IN's resting state shows; the OUT's `from` IS
 *      that resting state, so the hand-over is seamless. build.cjs sets --rin/--rout per
 *      cutout: items in the last screen of the page use entry-based ranges, because they
 *      can never scroll up to "cover 30%" and would otherwise stay half-formed forever.
 *      linear easing on purpose: the scroll is the easing.
 *   2. no view() (Firefox, Safari < 26) — js/reveal.js toggles .is-in both ways with an
 *      IntersectionObserver and the transitions below run on a clock.
 *
 * Never-invisible: hidden states live ONLY in keyframe `from`s (an inactive timeline =
 * no effect = resting PSB frame) and, on the IO branch, behind html.anim-ready which
 * js/reveal.js adds after its observers exist. Reduced motion: everything rests.
 */
.cut { view-timeline: --cut block; }
.cut-mv { transform-origin: var(--o, 50% 50%); }
.cut-in { transform-origin: var(--o, 50% 50%); }

/* ---------------------------------------------------------------- keyframes -- */
/* flowers, trees, palms, plants: grow out of their edge with a small twist */
@keyframes fx-flora-in {
  from { opacity: 0; transform: translateX(calc(var(--sx) * var(--flora-travel) * -1)) rotate(calc(var(--sx) * -6deg)) scale(0.8); }
  40%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-flora-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(calc(var(--sx) * var(--flora-travel) * -0.6)) rotate(calc(var(--sx) * -4deg)) scale(0.88); }
}
/* peacocks: glide in from their side, glide back out */
@keyframes fx-bird-in {
  from { opacity: 0; transform: translateX(calc(var(--sx) * var(--bird-travel) * -1)) translateY(-4%); }
  35%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-bird-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(calc(var(--sx) * var(--bird-travel) * -0.7)) translateY(-3%); }
}
/* event couples: step forward out of the frame (pukhraj-poorva's promenade, front-loaded
   opacity so a half-scrubbed couple is never left ghosted) */
@keyframes fx-couple-in {
  from { opacity: 0; transform: translateY(var(--couple-rise)) scale(0.93); }
  45%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-couple-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(calc(var(--couple-rise) * -0.5)) scale(0.97); }
}
/* ornamental rules: draw out from the centre diamond */
@keyframes fx-rule-in {
  from { opacity: 0; transform: scaleX(0); }
  50%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-rule-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: scaleX(0.3); }
}
/* itinerary curtains: part from a slightly drawn position to their PSB rest */
@keyframes fx-curtain-in {
  from { transform: translateX(calc(var(--sx) * 16%)) rotate(calc(var(--sx) * 0.8deg)); }
  to   { transform: none; }
}
/* itinerary plaque: lowered into place */
@keyframes fx-plaque-in {
  from { opacity: 0; transform: translateY(-12%) scale(0.94); }
  40%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
/* table pieces: set down onto the table; petals: drift down and settle */
@keyframes fx-table-in {
  from { opacity: 0; transform: translateY(-16%); }
  50%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-petals-in {
  from { opacity: 0; transform: translateY(-1.6cqw) rotate(-4deg); }
  45%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@keyframes fx-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
/* crest pieces (crest, its shine streaks, the PP monogram) share one transform origin
   in canvas space (build sets --o to the crest centre for each), so they move as one */
@keyframes fx-crest-in {
  from { opacity: 0; transform: translateY(1.4cqw) scale(0.88); }
  45%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
/* procession: as the hero scrolls away the baraat keeps walking off to the right */
@keyframes fx-march-out {
  from { transform: none; }
  to   { transform: translateX(var(--mx, 10%)); }
}

/* ---------------------------------------------------- 1. view() scrubbed ---- */
@supports (animation-timeline: view()) {
  /* NOTE: animation-timeline is reset-only in the `animation` shorthand — it must stay in
     the same rule as, and after, the shorthand. */
  html.js .cut[data-role="flora"] > .cut-mv {
    animation: fx-flora-in linear both, fx-flora-out linear forwards;
    animation-timeline: --cut, --cut;
    animation-range: var(--rin), var(--rout);
  }
  html.js .cut[data-role="bird"] > .cut-mv {
    animation: fx-bird-in linear both, fx-bird-out linear forwards;
    animation-timeline: --cut, --cut;
    animation-range: var(--rin), var(--rout);
  }
  html.js .cut[data-role="couple"] > .cut-mv {
    animation: fx-couple-in linear both, fx-couple-out linear forwards;
    animation-timeline: --cut, --cut;
    animation-range: var(--rin), var(--rout);
  }
  html.js .cut[data-role="rule"] > .cut-mv {
    animation: fx-rule-in linear both, fx-rule-out linear forwards;
    animation-timeline: --cut, --cut;
    animation-range: var(--rin), var(--rout);
  }
  html.js .cut[data-role="curtain"] > .cut-mv {
    animation: fx-curtain-in linear both;
    animation-timeline: --cut;
    animation-range: var(--rin);
  }
  html.js .cut[data-role="plaque"] > .cut-mv {
    animation: fx-plaque-in linear both, fx-fade-out linear forwards;
    animation-timeline: --cut, --cut;
    animation-range: var(--rin), var(--rout);
  }
  html.js .cut[data-role="table"] > .cut-mv {
    animation: fx-table-in linear both;
    animation-timeline: --cut;
    animation-range: var(--rin);
  }
  html.js .cut[data-role="petals"] > .cut-mv {
    animation: fx-petals-in linear both;
    animation-timeline: --cut;
    animation-range: var(--rin);
  }
  html.js .cut[data-role="crest"] > .cut-mv,
  html.js .cut[data-role="shine"] > .cut-mv {
    animation: fx-crest-in linear both;
    animation-timeline: --crest;
    animation-range: var(--rin);
  }
  html.js .cut[data-role="march"] > .cut-mv {
    animation: fx-march-out linear both;
    animation-timeline: --hero;
    animation-range: exit 0% exit 100%;
  }
  html.js .cut[data-role="car"] > .cut-mv {
    animation: fx-car-arrive linear both;     /* keyframes: css/gen/car.css */
    animation-timeline: --cut;
    animation-range: var(--rin);
  }
}
/* the crest pieces + the procession scrub off ONE shared subject each, so the pieces of
   a group can never drift apart (each piece has a different box height) */
.art { timeline-scope: --crest, --hero; }
.tl-crest { view-timeline: --crest block; }
.tl-hero  { view-timeline: --hero block; }

/* ---------------------------------------------- 2. IntersectionObserver ---- */
@supports not (animation-timeline: view()) {
  html.js.anim-ready .cut > .cut-mv {
    transition: transform var(--fx-dur) var(--fx-ease), opacity calc(var(--fx-dur) * 0.7) var(--fx-ease);
  }
  html.js.anim-ready .cut[data-role="flora"]:not(.is-in) > .cut-mv {
    opacity: 0; transform: translateX(calc(var(--sx) * var(--flora-travel) * -1)) rotate(calc(var(--sx) * -6deg)) scale(0.8);
  }
  html.js.anim-ready .cut[data-role="bird"]:not(.is-in) > .cut-mv {
    opacity: 0; transform: translateX(calc(var(--sx) * var(--bird-travel) * -1)) translateY(-4%);
  }
  html.js.anim-ready .cut[data-role="couple"]:not(.is-in) > .cut-mv {
    opacity: 0; transform: translateY(var(--couple-rise)) scale(0.93);
  }
  html.js.anim-ready .cut[data-role="rule"]:not(.is-in) > .cut-mv { opacity: 0; transform: scaleX(0); }
  html.js.anim-ready .cut[data-role="curtain"]:not(.is-in) > .cut-mv {
    transform: translateX(calc(var(--sx) * 16%)) rotate(calc(var(--sx) * 0.8deg));
  }
  html.js.anim-ready .cut[data-role="plaque"]:not(.is-in) > .cut-mv { opacity: 0; transform: translateY(-12%) scale(0.94); }
  html.js.anim-ready .cut[data-role="table"]:not(.is-in) > .cut-mv { opacity: 0; transform: translateY(-16%); }
  html.js.anim-ready .cut[data-role="petals"]:not(.is-in) > .cut-mv { opacity: 0; transform: translateY(-1.6cqw) rotate(-4deg); }
  html.js.anim-ready .cut[data-role="crest"]:not(.is-in) > .cut-mv,
  html.js.anim-ready .cut[data-role="shine"]:not(.is-in) > .cut-mv { opacity: 0; transform: translateY(1.4cqw) scale(0.88); }
  /* the car drives in from Padam Palace on a clock the first time the map is reached */
  html.js.anim-ready .cut[data-role="car"].is-in > .cut-mv {
    transition: none;
    animation: fx-car-arrive 3.4s cubic-bezier(0.45, 0, 0.25, 1) both;
  }
  html.js.anim-ready .cut[data-role="car"]:not(.is-in):not(.was-in) > .cut-mv { opacity: 0; }
  /* stagger siblings that enter together */
  html.js.anim-ready .cut.is-in > .cut-mv { transition-delay: var(--d, 0ms); }
}

@media (prefers-reduced-motion: reduce) {
  html.js .cut > .cut-mv { animation: none !important; transition: none !important; opacity: 1 !important; transform: none !important; }
}
@media print {
  .cut > .cut-mv { animation: none !important; opacity: 1 !important; transform: none !important; }
}
