/*
 * Scroll effects — the start/end states for the scroll_effects controller (Design-QA 2026-07-27).
 *
 * EVERY hidden start state lives behind BOTH `.pv-fx-on` (added by the controller on connect) and
 * `@media (prefers-reduced-motion: no-preference)`. So with JS off, before the controller connects,
 * or under reduced motion, nothing is hidden and nothing moves — the page renders complete.
 * Never move a hidden state out of this block.
 */
/* Lenis smooth-scroll core (see assets/smooth_scroll.js) — the html.lenis classes exist only
   when Lenis actually initialised (fine pointer + motion OK), so none of this affects VRT/touch. */
html.lenis,
html.lenis body {
    height: auto;
}

.lenis.lenis-smooth {
    scroll-behavior: auto !important;
}

.lenis.lenis-smooth [data-lenis-prevent] {
    overscroll-behavior: contain;
}

.lenis.lenis-stopped {
    overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
    /* Sideways entrances would widen the page while they play. `clip` (not `hidden`) keeps the
       vertical axis visible and creates no scroll container, so nothing else changes. */
    .pv-fx-on {
        overflow-x: clip;
    }

    .pv-fx-on [data-fx] {
        transition:
            opacity .7s ease,
            transform .7s cubic-bezier(.22, .61, .36, 1),
            clip-path .9s cubic-bezier(.22, .61, .36, 1);
    }

    /* The arming class. The controller adds it TOGETHER with `.pv-fx-on` and drops it one frame
       later, so the hidden start states below land as a plain style change instead of starting a
       0.7s visible→hidden transition that the reveal would then merely reverse (which capped every
       above-the-fold entrance at ~8px of its 64px travel). Never remove it from the controller. */
    .pv-fx-init [data-fx] {
        transition: none !important;
    }

    .pv-fx-on [data-fx]:not(.is-in) {
        opacity: 0;
    }

    /* "Iš kairės atvažiuoja tekstai" / "atskrenda iš dešinės" / "išvažiuoja iš viršaus" */
    .pv-fx-on [data-fx='left']:not(.is-in) {
        transform: translateX(-64px);
    }

    .pv-fx-on [data-fx='right']:not(.is-in) {
        transform: translateX(64px);
    }

    .pv-fx-on [data-fx='up']:not(.is-in) {
        transform: translateY(48px);
    }

    .pv-fx-on [data-fx='down']:not(.is-in) {
        transform: translateY(-48px);
    }

    /* The catalog card's backdrop unfolds upwards AFTER its wine + texts are in (Design-QA y≈1167
       "fone iš apačios išsiskleidžia tas shapsas"). It keeps its own hover colour tween, which the
       blanket transition above would otherwise drop. A clip (not scaleY) — a zero-height box never
       intersects, so a scaled-down backdrop would never be revealed at all. */
    .pv-fx-on .pv-product-card__bg[data-fx] {
        transition:
            clip-path .7s cubic-bezier(.22, .61, .36, 1),
            background-color .35s ease;
    }

    /* Same trap one level up: the card itself carries data-fx="up", so the blanket rule was
       replacing its `transition: color` outright. The hover text then SNAPPED to white while the
       backdrop behind it still tweened for 350ms — the two halves of one hover visibly out of step.
       Re-declare the reveal here WITH colour, exactly as the backdrop above does. */
    .pv-fx-on .pv-product-card[data-fx] {
        transition:
            opacity .7s ease,
            transform .7s cubic-bezier(.22, .61, .36, 1),
            color .35s ease;
    }

    /* Brand shapes / monograms — "gal AI gali animuoti šių shapes atsiradimą".
       Halved from 1s (Design-QA #25: "logo monogram animation too slow"). */
    .pv-fx-on [data-fx='shape'] {
        transition-duration: .5s;
    }

    .pv-fx-on [data-fx='shape']:not(.is-in) {
        transform: scale(.9);
    }

    /* "Iš kairės į dešinę išsiskleidžia foto" — the photo unrolls, it does not fade. The end
       state is spelled out (`inset(0)`, not `none`): clip-path does not interpolate against
       `none`, so without it the wipe would snap instead of play. Wire it on the IMAGE, never on a
       wrapper that has deco straddling its edge — the resting `inset(0)` would crop that deco. */
    .pv-fx-on [data-fx^='wipe'] {
        clip-path: inset(0);
    }

    .pv-fx-on [data-fx^='wipe']:not(.is-in) {
        opacity: 1;
    }

    .pv-fx-on [data-fx='wipe-left']:not(.is-in) {
        clip-path: inset(0 100% 0 0);
    }

    .pv-fx-on [data-fx='wipe-right']:not(.is-in) {
        clip-path: inset(0 0 0 100%);
    }

    .pv-fx-on [data-fx='wipe-up']:not(.is-in) {
        clip-path: inset(100% 0 0 0);
    }

    /* Scroll-linked layers. A parallax layer is bigger than its frame; the frame clips it, and the
       spare (half above, half below) IS the amplitude the controller may spend. */
    .pv-fx-on [data-fx-parallax] {
        /* 1.6 (was 1.25 → ~130px of travel at 1440, still "moves too small", 2026-07-29): 30% of
           the frame height of spare per side, ~330px of visible travel at 1440. Resolution is not
           the limit here — every band source is 3458–3462px wide, so the layer renders at 2304px
           at a 1440 viewport, still a 0.67× DOWNscale of the original.
           A band whose source carries spare HEIGHT of its own buys the same budget without zooming
           in: it sets --pv-parallax-scale: 1 and grows its own height instead (see
           .pv-hero__photo-img in pages/home.css). Anything set here is a uniform zoom, so it
           crops the comp framing sideways too — raise it only as far as the amplitude needs. */
        scale: var(--pv-parallax-scale, 1.6);
        /* `translate` listed explicitly: the drift writes the individual translate property, and
           not every engine promotes it under a bare will-change: transform. */
        will-change: translate, transform;
    }

    .pv-fx-on:has(> [data-fx-parallax]),
    .pv-fx-on *:has(> [data-fx-parallax]) {
        overflow: hidden;
    }

    .pv-fx-on [data-fx-scroll] {
        will-change: translate, transform;
    }

    /* An image whose bytes arrive after its entrance already played (the controller's 1.2s decode
       cap) fades in rather than snapping. The controller adds .pv-img-faded on the load event, so
       an image that was ready in time simply starts and ends at opacity 1. */
    .pv-fx-on [data-fx] img[data-fx-fade],
    .pv-fx-on img[data-fx][data-fx-fade] {
        opacity: 0;
        transition: opacity .45s ease;
    }

    .pv-fx-on [data-fx] img.pv-img-faded,
    .pv-fx-on img[data-fx].pv-img-faded {
        opacity: 1;
    }
}
