/* ═══════════════════════════════════════════
   with-love — the family's blessing (the last page)
   pages.md "with-love" · screens.md "6. with-love" · scene: finale

   Lifecycle (app.js writes it, this module reacts):
     [data-sv-state="pending"] / entering without [data-sv-ready]  -> pre-entrance state
     [data-sv-state="entering"][data-sv-ready]                      -> the entrance, once
     [data-sv-state="done"] (or no lifecycle at all)                -> end state, no animation
     [data-sv-view="on"]                                            -> loops run; paused otherwise
     [data-sv-view="far"]                                           -> loops display:none, content-visibility:auto
   Module state classes (set by js/with-love.js, compound-qualified):
     .with-love-container.with-love-is-alive    butterflies + sparkles (1400 ms, or at once when done)
     .with-love-container.with-love-is-falling  petals (3000 ms, or at once when done)

   Finale art (960 x 1440): pavilion eave x 602-958, couple x 725-860 / y 81-93%, peacock
   x 30-280 / y 87-99%. The backdrop is anchored RIGHT and bottom (object-position 100% 100%)
   so the whole pavilion and both figures are in frame on every phone; the image's visible
   x is 150-960 at 360x640 / 375x667 and 295-960 at 375x812 / 390x844. On the page that puts
   the pavilion at x >= 46-56% and the couple at x 65-88%; the peacock shows on short pages
   only (its tail is cropped) and is off frame on tall ones (no anchor can hold both).
   Text: column --col-scene, 11% -> <= 55%. Petals and sparkles: x < 8% or > 92%.
   Butterflies: y 62-92%, kept off the pavilion's couple.
   Animates transform, opacity and clip-path only.
   ═══════════════════════════════════════════ */

/* ───── The page (the one container; the snap area) ───── */
.with-love-container {
    --with-love-marigold: rgba(242, 158, 31, 1);
    --with-love-marigold-deep: rgba(232, 117, 26, 1);
    --with-love-rose-light: rgba(246, 186, 204, 1);
    --with-love-emblem-w: 30px;

    position: relative;
    display: block;
    width: 100%;
    height: 100dvh;
    overflow: clip;
    scroll-snap-align: start;
    scroll-snap-stop: always;
    background: var(--wash-finale);
    color: var(--ink);
    isolation: isolate;
}

/* ───── Art: wash + finale.webp (rate 0.22, settles from 1.04), then the cream lift (rate 0) ───── */
.with-love-art {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.with-love-backdrop {
    position: absolute;
    inset: 0;
    background: var(--wash-finale);
    transform: translate3d(0, calc(var(--d, 0) * var(--px-backdrop, 0.22) * -1px), 0);
}

.with-love-backdrop-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 100% 100%;    /* the pavilion and both figures in frame (header) */
    transform-origin: 100% 60%;    /* the 1.04 settle grows leftward: the eave stays in frame */
}

.with-love-lift {
    position: absolute;
    inset: 0;
    background: var(--lift-cream);
}

/* ───── Text block: column --col-scene, from 11% to <= 55% ─────
   --fit (1 -> 0.88) is written by js/with-love.js; every size below scales with it. */
.with-love-text {
    --fit: 1;
    position: absolute;
    z-index: 3;
    top: 11%;
    left: 0;
    right: 0;
    width: var(--col-scene);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    color: var(--ink);
    text-shadow: var(--halo, none);
}

.with-love-emblem {
    display: block;
    width: calc(var(--with-love-emblem-w) * var(--fit));
    height: calc(var(--with-love-emblem-w) * 1.24 * var(--fit));
    object-fit: contain;
    margin: 0 0 calc(10px * var(--fit));
}

#sv-card[data-sv-emblem="none"] .with-love-emblem {
    display: none;
}

.with-love-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 600;
    font-size: calc(var(--type-title-sm) * var(--fit));
    line-height: 1.22;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink-title);
    text-wrap: balance;
    overflow-wrap: anywhere;
}

/* closingMessage: the buyer's line breaks are kept; blank removes the line.
   Never clamped: js/with-love.js fits the block instead. Body text never below 14px. */
.with-love-message {
    margin: calc(12px * var(--fit)) 0 0;
    font-family: var(--font-body);
    font-style: italic;
    font-weight: 600;
    font-size: max(14px, calc(var(--type-detail) * var(--fit)));
    line-height: var(--leading-detail);
    white-space: pre-line;
    overflow-wrap: anywhere;
    color: var(--ink);
    text-wrap: pretty;
}

.with-love-message:empty {
    display: none;
}

/* Divider: 1px --rule, --rule-width long, 5px diamond ends; draws from the centre. */
.with-love-divider {
    position: relative;
    display: block;
    flex: none;
    width: var(--rule-width);
    height: 1px;
    margin: calc(16px * var(--fit)) 0 calc(6px * var(--fit));
    background: var(--rule);
    transform-origin: 50% 50%;
}

.with-love-divider::before,
.with-love-divider::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    background: var(--rule);
    transform: rotate(45deg);
}

.with-love-divider::before { left: -3px; }
.with-love-divider::after { right: -3px; }

/* "With love": script hero. fit-content so the write-on wipes the word, not the column;
   inline padding holds Great Vibes' swashes inside the box. */
.with-love-script {
    width: fit-content;
    max-width: 100%;
    margin: 0;
    padding: 0.06em 0.22em 0;
    font-family: var(--font-script);
    font-weight: 400;
    font-size: calc(var(--type-script-hero) * var(--fit));
    line-height: var(--leading-script);
    color: var(--ink-script);
    white-space: nowrap;
}

.with-love-family {
    margin: calc(2px * var(--fit)) 0 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: max(14px, calc(var(--type-family) * var(--fit)));
    line-height: 1.25;
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink-title);
    overflow-wrap: anywhere;
    text-wrap: balance;
}

.with-love-family:empty {
    display: none;
}

/* ───── Squeeze (short pages with long words only; set by js/with-love.js when --fit 0.88
   is not enough): the block starts at the text zone's top (7%, the branches stay in the
   top corners), the gaps close and the leading tightens, then --fit may go to 0.76.
   Nothing is ever clamped: the buyer's words always show whole. ───── */
.with-love-text.with-love-is-squeezed {
    top: var(--text-zone-top, 7%);
}

.with-love-text.with-love-is-squeezed .with-love-emblem {
    margin-bottom: calc(4px * var(--fit));
}

.with-love-text.with-love-is-squeezed .with-love-title {
    line-height: 1.14;
}

.with-love-text.with-love-is-squeezed .with-love-message {
    margin-top: calc(6px * var(--fit));
    line-height: 1.22;
}

.with-love-text.with-love-is-squeezed .with-love-divider {
    margin: calc(9px * var(--fit)) 0 calc(2px * var(--fit));
}

.with-love-text.with-love-is-squeezed .with-love-script {
    line-height: 1.02;
}

.with-love-text.with-love-is-squeezed .with-love-family {
    margin-top: 0;
    line-height: 1.16;
}

/* ───── Pre-entrance state (held until settle + decode, <= 1500 ms) ───── */
.with-love-container[data-sv-state="pending"] .with-love-backdrop-img,
.with-love-container[data-sv-state="entering"]:not([data-sv-ready]) .with-love-backdrop-img {
    transform: scale(1.04);
}

.with-love-container[data-sv-state="pending"] .with-love-text > *,
.with-love-container[data-sv-state="entering"]:not([data-sv-ready]) .with-love-text > * {
    opacity: 0;
}

/* ───── Entrance (on settle, once). Done at 3000 ms. ───── */
.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-backdrop-img {
    animation: with-love-settle 1400ms var(--ease-expo-out) 0ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-emblem {
    animation: with-love-emblem-in 400ms var(--ease-expo-out) 200ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-title {
    animation: with-love-fade-scale var(--dur-title, 500ms) var(--ease-expo-out) 400ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-message {
    animation: with-love-fade-up 600ms var(--ease-expo-out) 900ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-divider {
    animation: with-love-rule 500ms var(--ease-expo-out) 1500ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-script {
    animation: with-love-write 800ms var(--ease-silk) 1700ms both;
}

.with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-family {
    animation: with-love-family-in 600ms var(--ease-expo-out) 2400ms both;
}

@keyframes with-love-settle {
    from { transform: scale(1.04); }
    to   { transform: scale(1); }
}

@keyframes with-love-emblem-in {
    from { opacity: 0; transform: scale(0.9); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes with-love-fade-scale {
    from { opacity: 0; transform: scale(0.92); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes with-love-fade-up {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes with-love-rule {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

/* write-on: opacity over the first 150 ms of 800 ms; the wipe runs left to right.
   Negative insets leave room for the script's ascenders, descenders and swashes. */
@keyframes with-love-write {
    0%      { opacity: 0; clip-path: inset(-40% 100% -40% -12%); }
    18.75%  { opacity: 1; }
    100%    { opacity: 1; clip-path: inset(-40% -12% -40% -12%); }
}

@keyframes with-love-family-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes with-love-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ───── Loops: petals, butterflies, sparkles. Outer bands / lower band only. ───── */
.with-love-loops {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
}

.with-love-container[data-sv-view="far"] {
    content-visibility: auto;
    contain-intrinsic-size: auto 100dvh;
}

.with-love-container[data-sv-view="far"] .with-love-loops {
    display: none;
}

/* Petals: CSS ellipses with a two-stop radial fill, 8-14 px, falling the full page in the
   outer bands with +-4% sway, 9-14 s, drift. They begin at 3000 ms and fall for as long
   as the page is on screen. */
.with-love-petals {
    position: absolute;
    inset: 0;
}

.with-love-petal {
    position: absolute;
    top: 0;
    width: var(--s, 11px);
    height: calc(var(--s, 11px) * 0.62);
    margin-left: calc(var(--s, 11px) * -0.5);
    border-radius: 50%;
    opacity: 0;
    background: radial-gradient(ellipse at 38% 40%, var(--with-love-marigold) 0%, var(--with-love-marigold-deep) 100%);
    animation-duration: var(--dur, 11s);
    animation-delay: var(--delay, 0s);
    animation-timing-function: var(--ease-drift);
    animation-iteration-count: infinite;
    animation-fill-mode: backwards;
    animation-play-state: paused;
}

.with-love-petal--deep {
    background: radial-gradient(ellipse at 38% 40%, var(--with-love-marigold-deep) 0%, var(--with-love-marigold) 100%);
}

.with-love-petal--rose {
    background: radial-gradient(ellipse at 38% 40%, var(--with-love-rose-light) 0%, var(--accent-rose) 100%);
}

.with-love-container.with-love-is-falling .with-love-petal {
    animation-name: with-love-fall-a;
}

.with-love-container.with-love-is-falling .with-love-petal--b {
    animation-name: with-love-fall-b;
}

.with-love-container.with-love-is-falling[data-sv-view="on"] .with-love-petal {
    animation-play-state: running;
}

@keyframes with-love-fall-a {
    0%   { opacity: 0;    transform: translate3d(0, -4dvh, 0) rotate(0deg); }
    6%   { opacity: 0.95; }
    25%  {                transform: translate3d(4cqi, 22dvh, 0) rotate(80deg); }
    50%  {                transform: translate3d(-3cqi, 50dvh, 0) rotate(160deg); }
    75%  {                transform: translate3d(4cqi, 77dvh, 0) rotate(250deg); }
    90%  { opacity: 0.95; }
    100% { opacity: 0;    transform: translate3d(-1cqi, 103dvh, 0) rotate(330deg); }
}

@keyframes with-love-fall-b {
    0%   { opacity: 0;    transform: translate3d(0, -4dvh, 0) rotate(20deg); }
    6%   { opacity: 0.95; }
    25%  {                transform: translate3d(-4cqi, 24dvh, 0) rotate(-60deg); }
    50%  {                transform: translate3d(3cqi, 51dvh, 0) rotate(-150deg); }
    75%  {                transform: translate3d(-4cqi, 78dvh, 0) rotate(-230deg); }
    90%  { opacity: 0.95; }
    100% { opacity: 0;    transform: translate3d(1cqi, 103dvh, 0) rotate(-310deg); }
}

/* Butterflies: blue and coral, 26 / 30 px, waypoint flights of 13 / 11.5 s (drift) in
   y = 62-86%, x 14-76%, over the open sky, the banana leaves and the dome. Never above
   58%, never on the couple (page x >= 65%, y >= 81% with the right-anchored backdrop).
   Wing beat scaleX 1 -> 0.32 -> 1, 300 ms, breath. */
.with-love-butterflies {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 600ms var(--ease-silk);
}

.with-love-container.with-love-is-alive .with-love-butterflies {
    opacity: 1;
}

.with-love-flight {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    transform: translate3d(14cqi, 68dvh, 0);
    animation-timing-function: var(--ease-drift);
    animation-iteration-count: infinite;
    animation-play-state: paused;
}

.with-love-flight--a {
    width: 26px;
    animation-duration: 13s;
}

.with-love-flight--b {
    width: 30px;
    transform: translate3d(58cqi, 76dvh, 0);
    animation-duration: 11.5s;
    animation-delay: -4s;
}

.with-love-wing {
    display: block;
    width: 100%;
    height: auto;
    transform-origin: 50% 50%;
    animation: with-love-wing 300ms var(--ease-breath) infinite paused;
}

.with-love-flight--b .with-love-wing {
    animation-duration: 340ms;
}

.with-love-container.with-love-is-alive .with-love-flight--a {
    animation-name: with-love-flight-a;
}

.with-love-container.with-love-is-alive .with-love-flight--b {
    animation-name: with-love-flight-b;
}

.with-love-container.with-love-is-alive[data-sv-view="on"] .with-love-flight,
.with-love-container.with-love-is-alive[data-sv-view="on"] .with-love-wing {
    animation-play-state: running;
}

@keyframes with-love-wing {
    0%, 100% { transform: scaleX(1); }
    50%      { transform: scaleX(0.32); }
}

@keyframes with-love-flight-a {
    0%, 100% { transform: translate3d(14cqi, 68dvh, 0) rotate(-6deg); }
    20%      { transform: translate3d(30cqi, 63dvh, 0) rotate(4deg); }
    42%      { transform: translate3d(50cqi, 69dvh, 0) rotate(-3deg); }
    63%      { transform: translate3d(38cqi, 79dvh, 0) rotate(6deg); }
    82%      { transform: translate3d(22cqi, 75dvh, 0) rotate(-4deg); }
}

@keyframes with-love-flight-b {
    0%, 100% { transform: translate3d(58cqi, 76dvh, 0) rotate(5deg); }
    24%      { transform: translate3d(68cqi, 66dvh, 0) rotate(-5deg); }
    48%      { transform: translate3d(54cqi, 62dvh, 0) rotate(3deg); }
    72%      { transform: translate3d(42cqi, 72dvh, 0) rotate(-6deg); }
    88%      { transform: translate3d(50cqi, 84dvh, 0) rotate(4deg); }
}

/* Sparkles (_shared/effects/sparkles.css, light variant): 6 motes, outer bands, 3-4.4 s.
   Their keyframes are the shared ones; this module only gates visibility and play state. */
.with-love-sparkles {
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity 600ms var(--ease-silk);
}

.with-love-container.with-love-is-alive .with-love-sparkles {
    opacity: 1;
}

.with-love-sparkles > span {
    animation-play-state: paused;
}

.with-love-container.with-love-is-alive[data-sv-view="on"] .with-love-sparkles > span {
    animation-play-state: running;
}

/* ───── Reduced motion: text lines fade in (400 ms, 150 ms stagger). No petals,
   butterflies or sparkles. The backdrop is in place. ───── */
@media (prefers-reduced-motion: reduce) {
    .with-love-loops {
        display: none;
    }

    .with-love-container[data-sv-state="pending"] .with-love-backdrop-img,
    .with-love-container[data-sv-state="entering"]:not([data-sv-ready]) .with-love-backdrop-img,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-backdrop-img {
        transform: none;
        animation: none;
    }

    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-emblem,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-title,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-message,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-divider,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-script,
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-family {
        animation: with-love-fade 400ms var(--ease-silk) both;
    }

    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-title   { animation-delay: 150ms; }
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-message { animation-delay: 300ms; }
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-divider { animation-delay: 450ms; }
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-script  { animation-delay: 600ms; }
    .with-love-container[data-sv-state="entering"][data-sv-ready] .with-love-family  { animation-delay: 750ms; }
}
