/* ==========================================================================
   yatayat-motion.css
   --------------------------------------------------------------------------
   Motion layer for the public site.

   THE CONTRACT THIS FILE KEEPS
   ---------------------------
   1. CONTENT IS NEVER HIDDEN BY THIS STYLESHEET ALONE.
      Every reveal rule is gated behind `html.yt-motion`, a class that only
      yatayat-motion.js adds - and it adds it only after confirming that
      IntersectionObserver exists and that the user has not asked for reduced
      motion. If the JS file fails to load, 404s, is blocked, or throws, the
      class is never added and every element renders at full opacity in its
      final position. There is no flash-of-missing-content failure mode.

   2. NOTHING HERE CAUSES LAYOUT SHIFT.
      Only `opacity` and `transform` are animated. Both are composited and
      neither participates in layout, so Cumulative Layout Shift is unaffected.
      No reveal animates height, margin, padding, top/left or display.

   3. prefers-reduced-motion IS HONOURED THREE TIMES OVER.
      a) The duration tokens in yatayat-tokens.css collapse to ~0ms.
      b) The block at the end of this file force-shows every animated element.
      c) yatayat-motion.js refuses to add `html.yt-motion` at all.
      Belt, braces, and a second pair of braces - because a stuck invisible
      page is far worse than a missing animation.

   4. THE EXISTING WOW.js LAYER IS LEFT ALONE.
      95 elements across the site use `wow fadeInUp` / `wow zoomIn` and
      animate.css. Those keep working exactly as they do now. This file only
      adds the reduced-motion escape hatch that WOW.js does not implement.
   ========================================================================== */


/* ==========================================================================
   1. SCROLL REVEAL
   Applied by adding data-yt-reveal to any element. The attribute alone does
   nothing until html.yt-motion is present.
   ========================================================================== */

html.yt-motion [data-yt-reveal] {
    opacity: 0;
    transform: translate3d(0, var(--yt-reveal-distance), 0);
    transition:
        opacity var(--yt-dur-slow) var(--yt-ease-out),
        transform var(--yt-dur-slow) var(--yt-ease-out);
    transition-delay: var(--yt-reveal-delay, 0ms);
    will-change: opacity, transform;
}

html.yt-motion [data-yt-reveal="left"]  { transform: translate3d(calc(var(--yt-reveal-distance) * -1.4), 0, 0); }
html.yt-motion [data-yt-reveal="right"] { transform: translate3d(calc(var(--yt-reveal-distance) * 1.4), 0, 0); }
html.yt-motion [data-yt-reveal="down"]  { transform: translate3d(0, calc(var(--yt-reveal-distance) * -1), 0); }
html.yt-motion [data-yt-reveal="zoom"]  { transform: scale(0.94); }
html.yt-motion [data-yt-reveal="fade"]  { transform: none; }

/* The revealed state. Once set, the element is permanently visible - reveals
   never replay on scroll-up, which is both less distracting and cheaper. */
html.yt-motion [data-yt-reveal].yt-revealed {
    opacity: 1;
    transform: none;
    will-change: auto;
}


/* ==========================================================================
   2. STAGGERED GROUP ENTRANCES
   Put data-yt-stagger on a grid/row; its revealable children inherit an
   increasing delay. The delay is capped so a 40-card grid never leaves the
   last card waiting three seconds.
   ========================================================================== */

html.yt-motion [data-yt-stagger] > * {
    --yt-reveal-delay: 0ms;
}

html.yt-motion [data-yt-stagger] > *:nth-child(1)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 0); }
html.yt-motion [data-yt-stagger] > *:nth-child(2)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 1); }
html.yt-motion [data-yt-stagger] > *:nth-child(3)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 2); }
html.yt-motion [data-yt-stagger] > *:nth-child(4)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 3); }
html.yt-motion [data-yt-stagger] > *:nth-child(5)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 4); }
html.yt-motion [data-yt-stagger] > *:nth-child(6)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 5); }
html.yt-motion [data-yt-stagger] > *:nth-child(7)  { --yt-reveal-delay: calc(var(--yt-stagger-step) * 6); }
html.yt-motion [data-yt-stagger] > *:nth-child(n+8) { --yt-reveal-delay: calc(var(--yt-stagger-step) * 7); }


/* ==========================================================================
   3. HOVER LIFT
   Only on devices with a real hover-capable pointer, so touch users never
   get a stuck hover state. Uses transform, so no reflow.
   ========================================================================== */

@media (hover: hover) and (pointer: fine) {
    .yt-lift,
    .destination-item,
    .place-item,
    .blog-item,
    .service-item,
    .car-item,
    .listing-item,
    .package-item,
    .testimonial-item {
        transition:
            transform var(--yt-dur) var(--yt-ease-out),
            box-shadow var(--yt-dur) var(--yt-ease-out);
    }

    .yt-lift:hover,
    .yt-lift:focus-within,
    .destination-item:hover,
    .place-item:hover,
    .blog-item:hover,
    .service-item:hover,
    .car-item:hover,
    .listing-item:hover,
    .package-item:hover,
    .testimonial-item:hover {
        transform: translate3d(0, -6px, 0);
        box-shadow: var(--yt-shadow-md);
    }

    /* Buttons lift less - they are smaller, so the same distance reads as
       a jump rather than a nudge. */
    .btn:hover {
        transform: translate3d(0, -2px, 0);
        box-shadow: var(--yt-shadow-sm);
    }

    .btn:active {
        transform: translate3d(0, 0, 0);
        box-shadow: none;
    }

    /* Image zoom inside a fixed frame. The frame clips, so nothing reflows. */
    .yt-zoom-frame {
        overflow: hidden;
    }

    .yt-zoom-frame img {
        transition: transform var(--yt-dur-slower) var(--yt-ease-out);
    }

    .yt-zoom-frame:hover img {
        transform: scale(1.06);
    }
}


/* ==========================================================================
   4. COUNTERS
   The counting itself is done in JS. This only reserves the digit box so the
   number changing width from "0" to "1,284" cannot shift the layout.
   ========================================================================== */

.yt-counter {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}


/* ==========================================================================
   5. HEADER / MENU MOTION
   ========================================================================== */

.yt-header-shrink {
    transition:
        box-shadow var(--yt-dur) var(--yt-ease),
        background-color var(--yt-dur) var(--yt-ease);
}

html.yt-motion .yt-header-shrink.yt-stuck {
    box-shadow: var(--yt-shadow-sm);
}

/* Off-canvas / mobile menu panel. The theme drives open/close; this only
   smooths the transition it already performs. */
.offcanvas-info,
.mobile-menu {
    transition: transform var(--yt-dur-slow) var(--yt-ease-out);
}


/* ==========================================================================
   6. BACK TO TOP
   ========================================================================== */

.back-to-top {
    transition:
        opacity var(--yt-dur) var(--yt-ease),
        transform var(--yt-dur) var(--yt-ease-out);
}

.back-to-top-icon {
    transition: transform var(--yt-dur-fast) var(--yt-ease-out);
}

@media (hover: hover) {
    .back-to-top-icon:hover {
        transform: translate3d(0, -3px, 0);
    }
}


/* ==========================================================================
   7. REDUCED MOTION - THE OVERRIDE THAT WINS
   Everything animated is forced into its final, visible, static state. This
   block is last so it beats every rule above, and it also covers the theme's
   own WOW.js/animate.css layer, which has no reduced-motion support of its
   own.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

    /* Our own reveal layer. */
    html.yt-motion [data-yt-reveal],
    html.yt-motion [data-yt-reveal].yt-revealed {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
        animation: none !important;
    }

    /* The pre-existing WOW.js / animate.css layer. WOW injects
       `.wow { visibility: hidden }` at runtime; this forces it back. */
    .wow,
    .animated,
    [class*="animate__"] {
        visibility: visible !important;
        opacity: 1 !important;
        transform: none !important;
        animation: none !important;
        animation-name: none !important;
        transition: none !important;
    }

    /* Hover transforms are motion too. */
    .yt-lift:hover,
    .destination-item:hover,
    .place-item:hover,
    .blog-item:hover,
    .service-item:hover,
    .car-item:hover,
    .listing-item:hover,
    .package-item:hover,
    .testimonial-item:hover,
    .btn:hover,
    .yt-zoom-frame:hover img,
    .back-to-top-icon:hover {
        transform: none !important;
    }

    /* Catch-all. Anything still moving is stopped, but nothing is hidden -
       note that opacity and visibility are deliberately NOT reset here, so a
       legitimately hidden element (a closed modal) stays hidden. */
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}


/* ==========================================================================
   8. NO-JS SAFETY NET
   Mirrors rule 1 explicitly. Without html.yt-motion nothing above applies,
   but this states the guarantee in code so a future edit cannot quietly
   break it.
   ========================================================================== */

html:not(.yt-motion) [data-yt-reveal] {
    opacity: 1;
    transform: none;
}
