/* ═══════════════════════════════════════════
   shubh-vivah: the-functions (one 100dvh page per event; js/the-functions.js renders them)

   Lifecycle (app.js writes the attributes; this file only reads them):
     pre-entrance  [data-sv-state="pending"], or "entering" before [data-sv-ready]
     entrance      [data-sv-state="entering"][data-sv-ready]
     end state     [data-sv-state="done"] (and no state at all): the static styles, no animation
     loops         run only under [data-sv-view="on"]; loop layers display:none under "far"
   Parallax: --d / --dp (app.js) drive the individual `translate` property, so the
   entrance keyframes (on `transform`) never fight it.

   Wedding set: when the LAST event is a wedding, its page sits in
   div.the-functions-set[data-sv-set="wedding"] with a sticky stack (art + loops) after it.
   While #sv-card[data-sv-last-event="wedding"][data-sv-programme="on"] the set is 200dvh and
   the-programme (pulled up by its own CSS) scrolls its words over the still mandap.
   ═══════════════════════════════════════════ */

/* A published gift with no events renders no pages and hides the section (js). */
#screen-the-functions[hidden] {
    display: none !important;
}

.the-functions-pages {
    display: block;
    position: relative;
}

/* ───── Page: one 100dvh snap area per event ───── */
.the-functions-page {
    position: relative;
    height: 100dvh;
    overflow: hidden;
    overflow: clip;
    scroll-snap-align: start;
    scroll-snap-stop: always;
    container-type: size;              /* cqw/cqh = this page: the art box below mirrors object-fit: cover */
    --fit: 1;
    --the-functions-wash: var(--wash-celebration);
    --the-functions-top: 14%;
    --the-functions-from: 1.04;
    --the-functions-settle: 1400ms;
    --the-functions-lag: 0ms;
    --the-functions-origin: 50% 60%;
    --the-functions-amp: 0.7deg;
}

.the-functions-stack {
    --the-functions-wash: var(--wash-wedding);
    --the-functions-from: 1.04;
    --the-functions-settle: 1400ms;
    --the-functions-origin: 50% 60%;
}

/* Per type: wash, text-block top (pages.md table), entrance particulars. */
:is(.the-functions-page, .the-functions-stack)[data-scene="engagement"] {
    --the-functions-wash: var(--wash-engagement);
    --the-functions-top: 16%;
    --the-functions-from: 1.12;           /* the reference's pull-back */
    --the-functions-settle: 2400ms;
    --the-functions-lag: 250ms;           /* text steps 3-7 start 250 ms later */
    --the-functions-origin: 50% 92%;
    --the-functions-amp: 1.4deg;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="haldi"] {
    --the-functions-wash: var(--wash-haldi);
    --the-functions-top: 14%;
    --the-functions-amp: 0.7deg;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="mehendi"] {
    --the-functions-wash: var(--wash-mehendi);
    --the-functions-top: 12%;
    --the-functions-amp: 0.5deg;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="sangeet"] {
    --the-functions-wash: var(--wash-sangeet);
    --the-functions-top: 20%;
    --the-functions-amp: 1deg;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="wedding"] {
    --the-functions-wash: var(--wash-wedding);
    --the-functions-top: 9%;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="reception"] {
    --the-functions-wash: var(--wash-reception);
    --the-functions-top: 10%;
}
:is(.the-functions-page, .the-functions-stack)[data-scene="celebration"] {
    --the-functions-wash: var(--wash-celebration);
    --the-functions-top: 14%;
    --the-functions-amp: 0.7deg;
}

/* ───── Layer 1: the art box (wash + backdrop + halos), rate 0.22 ─────
   Exactly the box object-fit: cover / object-position: 50% 100% gives a 2:3 image, so
   halo percentages are image percentages and stay on the painted flames at any aspect. */
.the-functions-art {
    position: absolute;
    bottom: 0;
    left: calc(50% - max(50cqw, 33.3333cqh));
    width: max(100cqw, 66.6667cqh);
    height: max(100cqh, 150cqw);
    background: var(--the-functions-wash);
    transform-origin: var(--the-functions-origin);
    translate: 0 calc(var(--d, 0) * var(--px-backdrop) * -1px);
    pointer-events: none;
}
.the-functions-backdrop {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 100%;
}

/* Glow halos over painted light sources (positions measured from the delivered art). */
.the-functions-halo {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: var(--s);
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 214, 140, 0.55), rgba(255, 214, 140, 0));
    opacity: 0.8;
    animation: the-functions-flicker var(--dur, 2s) var(--ease-breath) var(--delay, 0s) infinite;
}
.the-functions-halo--fire {
    animation-name: the-functions-fire;
}
/* Dark scenes: halos take the scene's light gold (tokens.css re-sets --accent-warm-glow). */
:is(.the-functions-page, .the-functions-stack):is([data-scene="engagement"], [data-scene="sangeet"], [data-scene="reception"]) :is(.the-functions-halo, .the-functions-chand-glow) {
    background: radial-gradient(closest-side, var(--accent-warm-glow), rgba(255, 214, 140, 0));
}

/* ───── Layer 2: the scene's scrim (lift or veil), rate 0, with the text ───── */
.the-functions-scrim {
    position: absolute;
    inset: 0;
    background: var(--scrim);
    pointer-events: none;
}

/* ───── Layer 3: decor overlays, rate -0.06 ───── */
.the-functions-decor {
    position: absolute;
    inset: 0;
    translate: 0 calc(var(--d, 0) * var(--px-hang) * -1px);
    pointer-events: none;
}
.the-functions-decor-img {
    display: block;
    width: 100%;
    height: auto;
}
.the-functions-drop,
.the-functions-sway {
    position: relative;
    transform-origin: 50% 0;
}
.the-functions-sway {
    animation: the-functions-sway var(--sd, 6s) var(--ease-breath) var(--sdel, 0s) infinite;
}

/* Engagement: three chandeliers. Tops are capped so the bodies end above the text
   block (outer ≈ 12%, middle ≈ 9% at 360 x 740) on any aspect. */
.the-functions-chand {
    position: absolute;
}
.the-functions-chand--l,
.the-functions-chand--r {
    width: 30cqw;
    top: min(-9cqw, calc(15% - 33.4cqw));
}
.the-functions-chand--l { left: calc(16% - 15cqw); }
.the-functions-chand--r { left: calc(84% - 15cqw); }
.the-functions-chand--m {
    width: 20cqw;
    left: calc(50% - 10cqw);
    top: min(-4cqw, calc(10% - 22.3cqw));
}
/* Candle halo behind each body (the candle row is at ≈ 44% of chandelier.webp). */
.the-functions-chand-glow {
    position: absolute;
    left: 50%;
    top: 45%;
    width: 60%;
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 214, 140, 0.55), rgba(255, 214, 140, 0));
    opacity: 0.8;
    animation: the-functions-flicker var(--dur, 2s) var(--ease-breath) var(--delay, 0s) infinite;
}

/* Haldi + celebration: hanging-decor.webp as two halves. Measured: the outer strands
   (image x 5% and 14%, page x 2-17%) hang to 100% of its height, the centre tassel to
   60%. Lifted so EVERY strand ends above 13%, clear of a wide two-line title at 14%. */
.the-functions-hang {
    position: absolute;
    left: 0;
    width: 100%;
    aspect-ratio: 1080 / 463;
    top: min(-16cqw, calc(13% - 42.87cqw));
}
.the-functions-half,
.the-functions-half > .the-functions-drop,
.the-functions-half .the-functions-sway {
    position: absolute;
    inset: 0;
}
.the-functions-half--l > .the-functions-drop { clip-path: inset(0 50% 0 0); }
.the-functions-half--r > .the-functions-drop { clip-path: inset(0 0 0 50%); }
.the-functions-half--l .the-functions-drop,
.the-functions-half--l .the-functions-sway { transform-origin: 25% 0; }
.the-functions-half--r .the-functions-drop,
.the-functions-half--r .the-functions-sway { transform-origin: 75% 0; }

/* Sangeet: two garland swags as a toran. Sized to the delivered garland.webp (508 x 600,
   a U with a tassel) so the U bottoms sit ≈ 14-16% and the tassels end above 19.5%. */
.the-functions-garland {
    position: absolute;
    width: 44cqw;
    aspect-ratio: 508 / 600;
    top: min(-8.6cqw, calc(19.5% - 52cqw));
}
.the-functions-garland--l { left: -1%; }
.the-functions-garland--r { right: -1%; }

/* Mehendi: two vines from the bottom corners; 42% tall, so the tendrils stop at 58%. */
.the-functions-vine {
    position: absolute;
    bottom: 0;
    height: 42%;
    aspect-ratio: 390 / 1152;
}
.the-functions-vine--l { left: 0; }
.the-functions-vine--r { right: 0; }
.the-functions-vine .the-functions-grow,
.the-functions-vine .the-functions-sway {
    position: relative;
    height: 100%;
}
.the-functions-vine .the-functions-decor-img {
    width: auto;
    height: 100%;
}
.the-functions-vine--r .the-functions-decor-img { transform: scaleX(-1); }
.the-functions-vine--l .the-functions-sway { transform-origin: 0 100%; }
.the-functions-vine--r .the-functions-sway { transform-origin: 100% 100%; }

/* ───── Layer 5: loops (outer bands or below 58% only), rate 0 ───── */
.the-functions-loops {
    position: absolute;
    inset: 0;
    overflow: hidden;
    overflow: clip;
    pointer-events: none;
}
.the-functions-loops .the-functions-star {
    width: 2px;
    height: 2px;
}

.the-functions-petal {
    position: absolute;
    left: var(--x);
    top: 0;
    opacity: 0;
    animation: the-functions-fall var(--dur, 12s) linear var(--delay, 0s) infinite;
}
.the-functions-petal-leaf {
    display: block;
    width: var(--s);
    height: calc(var(--s) * 0.66);
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%, var(--c1), var(--c2));
    animation: the-functions-flutter var(--sd, 3s) var(--ease-breath) var(--sdel, 0s) infinite;
}

.the-functions-note {
    position: absolute;
    left: var(--x);
    top: var(--y);
    font-family: var(--font-body);
    font-size: 1.25rem;
    line-height: 1;
    color: var(--ink-script);      /* the scene's script gold: #f5c26b engagement, #ffd27a sangeet */
    text-shadow: var(--halo);
    opacity: 0;
    animation: the-functions-rise var(--dur, 5.5s) var(--ease-drift) var(--delay, 0s) infinite;
}

.the-functions-bokeh {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: var(--s);
    aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 252, 236, 0.55), rgba(255, 252, 236, 0));
    opacity: 0;
    animation: the-functions-bokeh var(--dur, 18s) var(--ease-drift) var(--delay, 0s) infinite;
}

.the-functions-fly {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: var(--s);
    translate: -50% -50%;
    animation: the-functions-flight var(--dur, 12s) var(--ease-drift) var(--delay, 0s) infinite;
}
.the-functions-wing {
    display: block;
    width: 100%;
    height: auto;
    animation: the-functions-wing var(--wb, 320ms) var(--ease-breath) infinite;
}

/* Loops run only on screen. (Two classes deep, so the shared .sparkle shorthand never wins.) */
.the-functions-page .the-functions-loopy,
.the-functions-stack .the-functions-loopy {
    animation-play-state: paused;
}
.the-functions-page[data-sv-view="on"] .the-functions-loopy,
.the-functions-set[data-sv-view="on"] .the-functions-loopy {
    animation-play-state: running;
}
.the-functions-page[data-sv-view="far"] {
    content-visibility: auto;
    contain-intrinsic-size: auto 100dvh;
}
.the-functions-page[data-sv-view="far"] .the-functions-loops,
.the-functions-set[data-sv-view="far"] .the-functions-loops {
    display: none;
}

/* ───── Text block: column --col-scene, from the type's top to ≤ --text-zone-bottom ───── */
.the-functions-text {
    position: absolute;
    left: 50%;
    top: var(--the-functions-top);
    width: var(--col-scene);
    translate: -50% 0;
    color: var(--ink);
    text-shadow: var(--halo);
    text-align: center;
    /* No max-height or clip: buyer text is never cut. js fit() keeps the block above
       --text-zone-bottom (55%), or, for at-cap text, above 57.5% (the art starts at 58%). */
}
.the-functions-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.the-functions-inner > * {
    margin: 0;
    max-width: 100%;
    overflow-wrap: anywhere;          /* a 40-character unbroken venue still wraps inside the column */
    text-wrap: balance;
}
.the-functions-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: calc(var(--type-title) * var(--fit));
    line-height: 1.12;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink-title);
}
.the-functions-tagline {
    margin-top: calc(4px * var(--fit));
    padding: 0 0.15em;
    font-family: var(--font-script);
    font-weight: 400;
    font-size: calc(var(--type-script) * var(--fit));
    line-height: var(--leading-script);
    color: var(--ink-script);
}
.the-functions-rule {
    position: relative;
    display: block;
    flex: none;
    width: var(--rule-width);
    height: 1px;
    margin: calc(12px * var(--fit)) 0;
    background: var(--rule);
}
.the-functions-rule::before,
.the-functions-rule::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    width: 5px;
    height: 5px;
    background: var(--rule);
    transform: translate(-50%, -50%) rotate(45deg);
}
.the-functions-rule::after {
    left: 100%;
}
.the-functions-detail {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: calc(var(--type-detail-caps) * var(--fit));
    line-height: 1.3;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
}
.the-functions-when {
    margin-top: calc(3px * var(--fit));
}
.the-functions-at {
    margin-bottom: calc(2px * var(--fit));
    font-family: var(--font-body);
    font-style: italic;
    font-weight: 600;
    font-size: calc(var(--type-connector) * var(--fit));
    line-height: 1.2;
}
.the-functions-address {
    margin-top: calc(2px * var(--fit));
    font-family: var(--font-body);
    font-weight: 600;
    font-size: calc(var(--type-detail) * var(--fit));
    line-height: var(--leading-detail);
}
/* At-cap text only (js fit(), steps 2-4): tighter gaps and leading, then, as the last
   resort below --fit 0.76, venue and address hold at 2 lines each. */
.the-functions-text[data-tight] .the-functions-title { line-height: 1.04; }
.the-functions-text[data-tight] .the-functions-tagline { margin-top: 0; line-height: 1.08; }
.the-functions-text[data-tight] .the-functions-rule { margin: calc(6px * var(--fit)) 0; }
.the-functions-text[data-tight] .the-functions-detail { line-height: 1.2; }
.the-functions-text[data-tight] .the-functions-when { margin-top: 0; }
.the-functions-text[data-tight] .the-functions-at { margin-bottom: 0; line-height: 1.1; }
.the-functions-text[data-tight] .the-functions-address { margin-top: 0; line-height: 1.18; }
.the-functions-text[data-clamp] .the-functions-venue,
.the-functions-text[data-clamp] .the-functions-address {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}
.the-functions-inner > [hidden] {
    display: none !important;
}

/* ───── Wedding set (the last event is a wedding) ───── */
.the-functions-set {
    position: relative;
    isolation: isolate;
}
.the-functions-set > .the-functions-page {
    z-index: 1;                        /* the words over the stack */
}
.the-functions-stack {
    position: sticky;
    top: 0;
    z-index: 0;
    height: 100dvh;
    margin-top: -100dvh;               /* behind the page; sticky through the set's second half */
    overflow: hidden;
    overflow: clip;
    container-type: size;
    pointer-events: none;
}
#sv-card[data-sv-last-event="wedding"][data-sv-programme="on"] .the-functions-set {
    height: 200dvh;
}
/* A plain (100dvh) set: the stack's art lags like any backdrop. */
.the-functions-stack .the-functions-art {
    translate: 0 calc(var(--d, 0) * var(--px-backdrop) * -1px);
}
/* The active set: still while stuck (--dp in [-1, 0]); rate 0.22 only on the way in and out. */
#sv-card[data-sv-last-event="wedding"][data-sv-programme="on"] .the-functions-stack .the-functions-art {
    translate: 0 calc((max(var(--dp, 0), 0) + min(var(--dp, 0) + 1, 0)) * var(--px-backdrop) * -100cqh);
}

/* ───── Pre-entrance ───── */
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-art,
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) ~ .the-functions-stack .the-functions-art {
    transform: scale(var(--the-functions-from));
}
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-drop {
    transform: translateY(-104%);
}
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-grow {
    clip-path: inset(100% 0 0 0);
}
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-l,
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-loops,
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) ~ .the-functions-stack .the-functions-loops {
    opacity: 0;
}
.the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-rule {
    transform: scaleX(0);
}

/* ───── Entrance (ms from settle; pages.md, shared entrance) ───── */
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-art,
.the-functions-page[data-sv-state="entering"][data-sv-ready] ~ .the-functions-stack .the-functions-art {
    animation: the-functions-settle var(--the-functions-settle) var(--ease-expo-out) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-drop {
    animation: the-functions-drop var(--dur-drop) linear var(--dd, 0ms) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-drop--soft {
    animation-name: the-functions-drop-soft;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-grow {
    animation: the-functions-grow 1500ms var(--ease-expo-out) var(--dd, 0ms) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-title {
    animation: the-functions-title var(--dur-title) var(--ease-expo-out) calc(350ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-tagline {
    animation: the-functions-write var(--dur-write) var(--ease-silk) calc(750ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-rule--1 {
    animation: the-functions-rule var(--dur-rule) var(--ease-expo-out) calc(1250ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-rule--2 {
    animation: the-functions-rule var(--dur-rule) var(--ease-expo-out) calc(1370ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] :is(.the-functions-date, .the-functions-when) {
    animation: the-functions-up var(--dur-detail) var(--ease-expo-out) calc(1500ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] :is(.the-functions-at, .the-functions-venue, .the-functions-address) {
    animation: the-functions-up var(--dur-detail) var(--ease-expo-out) calc(1800ms + var(--the-functions-lag)) both;
}
.the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-loops,
.the-functions-page[data-sv-state="entering"][data-sv-ready] ~ .the-functions-stack .the-functions-loops {
    animation: the-functions-fade 600ms var(--ease-silk) 1400ms both;     /* loops start at 1400 ms */
}

/* ───── Keyframes ───── */
@keyframes the-functions-settle {
    from { transform: scale(var(--the-functions-from)); }
    to   { transform: scale(1); }
}
@keyframes the-functions-title {
    from { opacity: 0; transform: scale(0.92); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes the-functions-write {
    0%    { opacity: 0; clip-path: inset(-30% 100% -30% -10%); }
    16.7% { opacity: 1; }
    100%  { opacity: 1; clip-path: inset(-30% -10% -30% -10%); }
}
@keyframes the-functions-rule {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}
@keyframes the-functions-up {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes the-functions-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* concept.md's sv-drop-settle: expo-out to the hook, then a damped swing on `settle`. */
@keyframes the-functions-drop {
    0%   { transform: translateY(-104%) rotate(0deg); animation-timing-function: var(--ease-expo-out); }
    52%  { transform: translateY(0) rotate(1.6deg); animation-timing-function: var(--ease-settle); }
    70%  { transform: translateY(0) rotate(-0.9deg); animation-timing-function: var(--ease-settle); }
    84%  { transform: translateY(0) rotate(0.4deg); animation-timing-function: var(--ease-settle); }
    100% { transform: translateY(0) rotate(0deg); }
}
/* The chandeliers: the same curve at 0.6x the angles. */
@keyframes the-functions-drop-soft {
    0%   { transform: translateY(-104%) rotate(0deg); animation-timing-function: var(--ease-expo-out); }
    52%  { transform: translateY(0) rotate(0.96deg); animation-timing-function: var(--ease-settle); }
    70%  { transform: translateY(0) rotate(-0.54deg); animation-timing-function: var(--ease-settle); }
    84%  { transform: translateY(0) rotate(0.24deg); animation-timing-function: var(--ease-settle); }
    100% { transform: translateY(0) rotate(0deg); }
}
@keyframes the-functions-grow {
    from { clip-path: inset(100% 0 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}
@keyframes the-functions-sway {
    0%, 100% { transform: rotate(0deg); }
    25%      { transform: rotate(var(--the-functions-amp)); }
    75%      { transform: rotate(calc(var(--the-functions-amp) * -1)); }
}
@keyframes the-functions-flicker {
    0%, 100% { opacity: 0.55; }
    17%      { opacity: 0.92; }
    33%      { opacity: 0.7; }
    51%      { opacity: 1; }
    68%      { opacity: 0.62; }
    84%      { opacity: 0.9; }
}
@keyframes the-functions-fire {
    0%, 100% { opacity: 0.5; }
    14%      { opacity: 0.95; }
    29%      { opacity: 0.62; }
    46%      { opacity: 1; }
    63%      { opacity: 0.55; }
    81%      { opacity: 0.88; }
}
@keyframes the-functions-fall {
    0%   { opacity: 0; transform: translateY(-6cqh); }
    8%   { opacity: 1; }
    90%  { opacity: 1; }
    100% { opacity: 0; transform: translateY(104cqh); }
}
@keyframes the-functions-flutter {
    0%, 100% { transform: translateX(-4cqw) rotate(-25deg); }
    50%      { transform: translateX(4cqw) rotate(35deg); }
}
@keyframes the-functions-rise {
    0%   { opacity: 0; transform: translate(0, 0); }
    15%  { opacity: 0.95; }
    50%  { transform: translate(1.5cqw, calc(var(--rise) * -0.5)); }
    75%  { opacity: 0.85; }
    100% { opacity: 0; transform: translate(-1cqw, calc(var(--rise) * -1)); }
}
@keyframes the-functions-bokeh {
    0%   { opacity: 0; transform: translateY(0) scale(0.9); }
    20%  { opacity: 1; }
    80%  { opacity: 0.8; }
    100% { opacity: 0; transform: translateY(calc(var(--rise) * -1)) scale(1.05); }
}
@keyframes the-functions-flight {
    0%, 100% { transform: translate(0, 0); }
    20%      { transform: translate(calc(var(--fx) * 0.55), calc(var(--fy) * -0.5)); }
    40%      { transform: translate(var(--fx), calc(var(--fy) * 0.4)); }
    60%      { transform: translate(calc(var(--fx) * 0.4), var(--fy)); }
    80%      { transform: translate(calc(var(--fx) * -0.15), calc(var(--fy) * 0.4)); }
}
@keyframes the-functions-wing {
    0%, 100% { transform: scaleX(1); }
    50%      { transform: scaleX(0.32); }
}

/* ───── Reduced motion: art and decor in place, text lines fade in (400 ms, 150 ms
   stagger), no loops, halos static at 0.8. Parallax is zeroed in tokens.css. ───── */
@media (prefers-reduced-motion: reduce) {
    .the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-art,
    .the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) ~ .the-functions-stack .the-functions-art,
    .the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-drop {
        transform: none;
    }
    .the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-grow {
        clip-path: none;
    }
    .the-functions-page:is([data-sv-state="pending"], [data-sv-state="entering"]:not([data-sv-ready])) .the-functions-rule {
        transform: none;
        opacity: 0;
    }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] :is(.the-functions-art, .the-functions-drop, .the-functions-grow),
    .the-functions-page[data-sv-state="entering"][data-sv-ready] ~ .the-functions-stack .the-functions-art {
        animation: none;
    }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] :is(.the-functions-l, .the-functions-rule) {
        animation: the-functions-fade var(--dur-detail) var(--ease-silk) 0ms both;
    }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-tagline { animation-delay: 150ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-rule--1 { animation-delay: 300ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-date { animation-delay: 450ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-when { animation-delay: 600ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-rule--2 { animation-delay: 750ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-at { animation-delay: 900ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-venue { animation-delay: 1050ms; }
    .the-functions-page[data-sv-state="entering"][data-sv-ready] .the-functions-address { animation-delay: 1200ms; }

    .the-functions-loops {
        display: none;
    }
    .the-functions-page .the-functions-loopy,
    .the-functions-stack .the-functions-loopy {
        animation: none;
    }
}
