/* ==========================================================================
   intensity3d.css — high-amplitude scroll 3D, concentrated in the band
   immediately below the hero.

   Why this file exists: the original scroll3d.css was deliberately restrained
   (max 5-6deg tilts, -90px Z). This layer raises the amplitude and adds a
   perspective "floor" so the page reads as a deep 3D space as you scroll,
   while keeping body copy at a readable angle.

   Readability rule used throughout:
     - Container wrappers may rotate aggressively (max ~14deg). Nobody reads
       text off a wrapper directly; its children counter-rotate below.
     - Anything the visitor actually READS (h2, p, card text) is held to a
       small angle (<= 5deg) or counter-rotated back toward flat.

   Composition: like scroll3d.css, this uses the individual `rotate` property
   so it composes with the `transform` used by hero3d.css and premium.js
   instead of overwriting it. Nested rotations multiply, so the counters below
   are what actually keep text flat and legible.
   ========================================================================== */

/* ---------- 1. THE FLOOR ---------------------------------------------- */

/* A perspective grid receding to a vanishing point. Anchored to the top of the
   services section so it reads as "the page continues into depth" right after
   the hero. Purely decorative, aria-hidden, and cheap: one repeating gradient
   plus a transform. */
.av3d-floor {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 260px;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
    opacity: 0.5;
    mask-image: linear-gradient(180deg, #000 0%, transparent 92%);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 92%);
}

.av3d-floor__grid {
    position: absolute;
    inset: -60% -50% -20% -50%;
    /* One gradient draws both axes: vertical rails + horizontal rungs. */
    background-image:
        repeating-linear-gradient(90deg,
            rgba(37, 99, 235, 0.16) 0 1px, transparent 1px 84px),
        repeating-linear-gradient(0deg,
            rgba(37, 99, 235, 0.13) 0 1px, transparent 1px 74px);
    transform: perspective(520px) rotateX(74deg);
    transform-origin: 50% 0%;
    /* --av3d-floor-push is written by intensity3d.js */
    translate: 0 var(--av3d-floor-push, 0px);
    will-change: translate;
    opacity: var(--av3d-floor-opacity, 0.5);
}

/* Sections that follow the hero need to sit above the floor. */
.services,
.gallery-section,
.testimonials,
.quote-section {
    position: relative;
    z-index: 1;
}

/* ---------- 2. HIGH-AMPLITUDE CONTAINER TILT --------------------------- */

/* The wrapper takes the big rotation. Children counter-rotate below so the
   copy stays readable. Magnitudes come from the original 6deg up to 14deg. */

.av3d-hot .section-container,
.av3d-hot .gallery-container {
    /* Pitch + Z push + scale. No rotateY: a full-width block rotated on the
       Y axis swings like a door and was the "tilting left to right" effect. */
    /* Pitch + Z push + scale. No rotateY: a full-width block rotated on the
       Y axis swings like a door and was the "tilting left to right" effect. */
    transform:
        rotateX(var(--av3d-hot-x, 0deg))
        translateZ(calc(var(--av3d-hot-z, 0px) * -1))
        scale(var(--av3d-hot-s, 1));
    transform-origin: 50% 0%;
    /* NO perspective and NO preserve-3d here.
       This wrapper is a 3D-transformed ANCESTOR of every service tile link.
       With `perspective` + `preserve-3d` the browser hit-tests the wrapper's
       own projected plane instead of the links beneath it, so the lower row of
       tiles stopped responding to clicks entirely (verified: top row 3/3
       clickable, bottom row 0/3). Removing the nested 3D context restores
       hit-testing. The wrapper's own transform still renders the depth, and
       the cards keep their individual fan transforms, so the look survives. */
    perspective: none;
    transform-style: flat;
}

/* Counter-rotation: pull the readable content back toward flat while the
   wrapper is tilted. Uses the negated custom props so the two cancel. */
.av3d-hot .section-header,
.av3d-hot .avp-stats-band,
.av3d-hot .quote-section .section-container > * {
    /* Counter only the pitch, so headings stay level through the whole move. */
    transform: rotateX(calc(var(--av3d-hot-x, 0deg) * -1));
    transform-style: preserve-3d;
}

/* ---------- 3. DRAMATIC CARD FAN --------------------------------------- */

/* Cards are small, so a modest yaw still reads as a fanned deck. The dominant
   motion is Z depth, which reads as depth rather than a left/right swing. */
.av3d-hot .service-card,
.av3d-hot .testimonial,
.av3d-hot .gallery-card,
.av3d-hot .trust-item {
    --av3d-fan-deg: 7deg;
    --av3d-fan-rise: 74px;
    --av3d-fan-depth: -300px;

    transform: rotateX(calc((0.5 - var(--av3d-fan, 1)) * -3deg))
               rotateY(calc((0.5 - var(--av3d-fan, 1)) * var(--av3d-fan-deg)));
    translate:
        0 calc((1 - var(--av3d-fan, 1)) * var(--av3d-fan-rise))
        calc((1 - var(--av3d-fan, 1)) * var(--av3d-fan-depth));
    scale: calc(1 - (1 - var(--av3d-fan, 1)) * 0.18);
}

/* Counter-tilt card interiors so the copy inside stays level. */
.av3d-hot .service-card > *,
.av3d-hot .testimonial > * {
    rotate: y calc((0.5 - var(--av3d-fan, 1)) * var(--av3d-fan-deg) * -0.85);
}

/* ---------- 4. AGGRESSIVE HERO DOLLY ---------------------------------- */

/* The hero now recedes much further and the headline sweeps past the camera
   faster, which is what makes the transition into the 3D body feel sudden and
   cinematic rather than a gentle drift. */
.av3d-hot .hero-container {
    translate: 0 0 var(--av3d-hot-hero-z, 0px);
    scale: var(--av3d-hot-hero-s, 1);
}

/* ---------- 5. TRUST BAR: the first real 3D moment below the hero ------ */

/* The trust bar is the first thing under the hero, so it gets the most
   pronounced entrance: the row tilts in as a single plane, then the four
   badges pop forward in sequence. */
.av3d-hot .trust-bar {
    perspective: 900px;
    overflow: hidden;
}

.av3d-hot .trust-container {
    rotate: x var(--av3d-trust-x, 0deg);
    /* Flat, not preserve-3d -- see scroll3d.css for why a preserve-3d context
       on a card container breaks click hit-testing. */
    transform-style: flat;
}

.av3d-hot .trust-item {
    --av3d-fan-deg: 9deg;
    --av3d-fan-depth: -170px;
    translate:
        0 calc((1 - var(--av3d-fan, 1)) * 46px)
        calc((1 - var(--av3d-fan, 1)) * -170px);
    scale: calc(1 + (1 - var(--av3d-fan, 1)) * 0.08);
}

/* Counter-rotate the trust text so the four labels stay crisp while the row
   itself is tilted. */
.av3d-hot .trust-item .trust-text,
.av3d-hot .trust-item .trust-icon {
    rotate: x calc(var(--av3d-trust-x, 0deg) * -1);
}

/* ---------- 6. PERFORMANCE + FALLOFF GUARDS ---------------------------- */

/* will-change is set on many elements; drop it once they stop moving so the
   compositor can release the layers. */
.av3d-hot.is-settled .service-card,
.av3d-hot.is-settled .testimonial,
.av3d-hot.is-settled .gallery-card,
.av3d-hot.is-settled .trust-item,
.av3d-hot.is-settled .hero-container,
.av3d-hot.is-settled .av3d-floor__grid {
    will-change: auto;
}

/* ---------- 7. MOBILE --------------------------------------------------- */

/* On phones the whole scene is flattened: strong 3D on a small screen makes
   text hard to read and costs battery for no gain. */
@media (max-width: 768px) {
    .av3d-floor {
        display: none;
    }

    .av3d-hot .section-container,
    .av3d-hot .gallery-container,
    .av3d-hot .trust-container,
    .av3d-hot .section-header,
    .av3d-hot .avp-stats-band,
    .av3d-hot .quote-section .section-container > *,
    .av3d-hot .trust-item .trust-text,
    .av3d-hot .trust-item .trust-icon,
    .av3d-hot .service-card > *,
    .av3d-hot .testimonial > *,
    .av3d-hot .service-card,
    .av3d-hot .testimonial,
    .av3d-hot .gallery-card,
    .av3d-hot .trust-item,
    .av3d-hot .hero-container {
        rotate: none;
        translate: none;
        scale: none;
    }
}

/* ---------- 8. REDUCED MOTION ------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
    .av3d-floor {
        display: none;
    }

    .av3d-hot .section-container,
    .av3d-hot .gallery-container,
    .av3d-hot .trust-container,
    .av3d-hot .section-header,
    .av3d-hot .avp-stats-band,
    .av3d-hot .quote-section .section-container > *,
    .av3d-hot .trust-item .trust-text,
    .av3d-hot .trust-item .trust-icon,
    .av3d-hot .service-card > *,
    .av3d-hot .testimonial > *,
    .av3d-hot .service-card,
    .av3d-hot .testimonial,
    .av3d-hot .gallery-card,
    .av3d-hot .trust-item,
    .av3d-hot .hero-container {
        rotate: none !important;
        translate: none !important;
        scale: none !important;
        will-change: auto;
    }
}

/* ---------- 9. SERVICE TILES: 3D REMOVED (owner decision) ---------------- */

/* Owner decision 2026-09-28: the service tiles are flat, no 3D.
   This block is appended last in the cascade, so at equal specificity it wins
   over both the scroll3d fan rules and the intensity3d fan rules.

   Every 3D-derived property is explicitly reset rather than relying on
   --av3d-fan: the resting fan value of 1 is NOT neutral (it resolves to a
   few degrees of residual rotation), so zeroing the custom property alone
   would still leave the cards tilted. */
.av3d-scroll .service-card,
.av3d-hot .service-card {
    transform: none;
    translate: none;
    rotate: none;
    scale: 1;
    transform-style: flat;
    will-change: auto;
}

/* The interior counter-rotation existed only to offset the card's own fan. */
.av3d-hot .service-card > * {
    rotate: none;
    transform: none;
}

/* The reveal animation is a 3D entrance (rotateX). Keep the fade and the rise,
   drop the tilt, so the tiles still animate in but stay flat. */
.av3d-scroll .service-card.av3d-reveal {
    transform: translateY(26px);
}

.av3d-scroll .service-card.av3d-reveal.av3d-in {
    transform: translateY(0);
}
