/*
 * ═══════════════════════════════════════════════════════════════════════════════
 * Lavisa Destinations Theme — ENHANCED ANIMATIONS & UTILITIES (E3)
 * ═══════════════════════════════════════════════════════════════════════════════
 *
 * @file        assets/css/ldt-enhanced-animations.css
 * @package     Lavisa_Destinations_Theme
 * @since       2.9.4  (E3 — Visual Enhancement Roadmap v2)
 * @depends     ldt-tokens-enhanced.css (E1 — uses --ldt-glass-*, --ldt-shadow-*,
 *              --ldt-ease-portal, --ldt-duration-*)
 *
 *   Canonical home of the portal motion library + opt-in utility classes
 *   (glass, 3D tilt, hover lift, hover-zoom image, scroll reveal, shimmer
 *   skeleton). Every keyframe and class here is OPT-IN — the theme renders
 *   pixel-identically to E2 output unless a template explicitly applies one.
 *
 *   COEXISTS WITH E2:
 *     ldt-enhanced-base.css ships inline copies of @keyframes ldt-pulse-glow,
 *     ldt-float-shape, and ldt-float-shape-centered so its primitives animate
 *     correctly even before this file is installed. Both definitions are
 *     identical; the cascade just uses whichever loads last (this file —
 *     enqueued AFTER ldt-enhanced-base by class-ldt-enqueue.php).
 *
 *   STRUCTURE:
 *     1. KEYFRAMES — full motion library (12 named keyframes)
 *     2. UTILITIES — glassmorphism, 3D card tilt, hover lift, image zoom,
 *        decorative spinners, shimmer skeleton
 *     3. SCROLL REVEAL — .ldt-reveal initial+visible states (driven by
 *        ldt-main.js IntersectionObserver added in E3)
 *     4. REDUCED MOTION — global guards
 *
 * ═══════════════════════════════════════════════════════════════════════════════
 */


/* ═══════════════════════════════════════════════════════════════════════════════
 * 1. KEYFRAMES — full motion library
 *
 * All keyframes prefixed `ldt-` so they don't collide with other theme/plugin
 * animations. Durations and curves match the lavisatravel.com portal exactly.
 * ═══════════════════════════════════════════════════════════════════════════════ */

/* Background blob drift — used by .ldt-bg-shape--1 / --2 (the third uses
   ldt-float-shape-centered to preserve its translate(-50%,-50%) centering) */
@keyframes ldt-float-shape {
    0%, 100% {
        transform: translate(0, 0) scale(1);
    }
    33% {
        transform: translate(30px, -30px) scale(1.1);
    }
    66% {
        transform: translate(-30px, 30px) scale(0.9);
    }
}

/* Centered variant — preserves translate(-50%, -50%) for elements that
   anchor at top:50%/left:50% with the centering already baked in */
@keyframes ldt-float-shape-centered {
    0%, 100% {
        transform: translate(-50%, -50%) scale(1);
    }
    33% {
        transform: translate(calc(-50% + 30px), calc(-50% - 30px)) scale(1.1);
    }
    66% {
        transform: translate(calc(-50% - 30px), calc(-50% + 30px)) scale(0.9);
    }
}

/* Decorative icon float — gentle bob with full 360 rotate at midpoint.
   Used on hero floating travel emojis (✈ 🌍 🏖) */
@keyframes ldt-float-icon {
    0%, 100% {
        transform: translateY(0) rotate(0deg);
    }
    50% {
        transform: translateY(-20px) rotate(180deg);
    }
}

/* Pulse-glow — used by .ldt-section-decoration__icon (E2) and any decorative
   icon that should breathe. Subtle scale + brightness boost. */
@keyframes ldt-pulse-glow {
    0%, 100% {
        transform: scale(1);
        filter: brightness(1);
    }
    50% {
        transform: scale(1.1);
        filter: brightness(1.2);
    }
}

/* Concentric icon ripple — pseudo-element on top of an icon scales out and
   fades. Used on service-card icon halos and offer-badge auras. */
@keyframes ldt-icon-pulse {
    0% {
        transform: scale(1);
        opacity: 0.5;
    }
    100% {
        transform: scale(1.4);
        opacity: 0;
    }
}

/* Badge pulse — restrained scale loop for offer/discount badges */
@keyframes ldt-badge-pulse {
    0%, 100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.05);
    }
}

/* Ken-burns — slow zoom from 1.05 → 1.0 over a slide's active window.
   Used on .ldt-hero-slide.is-active backgrounds */
@keyframes ldt-ken-burns {
    from {
        transform: scale(1.05);
    }
    to {
        transform: scale(1.0);
    }
}

/* Shimmer — moving highlight band for skeleton placeholders */
@keyframes ldt-shimmer {
    0% {
        background-position: -1000px 0;
    }
    100% {
        background-position: 1000px 0;
    }
}

/* Fade-up — content reveal on scroll-into-view (the workhorse for .ldt-reveal) */
@keyframes ldt-fade-up {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Fade-in — simplest opacity reveal */
@keyframes ldt-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Zoom-in — modal / popup entrance */
@keyframes ldt-zoom-in {
    from {
        opacity: 0;
        transform: scale(0.92);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* Slide-in-left / slide-in-right — for cards revealing horizontally */
@keyframes ldt-slide-in-left {
    from {
        opacity: 0;
        transform: translateX(-30px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes ldt-slide-in-right {
    from {
        opacity: 0;
        transform: translateX(30px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Slow rotation — for loading spinners and decorative orbs */
@keyframes ldt-rotate-slow {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* Bounce-in — for save/heart click feedback */
@keyframes ldt-bounce-in {
    0% {
        transform: scale(1);
    }
    40% {
        transform: scale(1.3);
    }
    70% {
        transform: scale(0.92);
    }
    100% {
        transform: scale(1);
    }
}

/* Marquee — horizontal continuous scroll for urgency strips / logo carousels */
@keyframes ldt-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 2. GLASSMORPHISM UTILITY CLASSES
 *
 * Apply these to any element to get the portal's signature translucent surface.
 * Pair with backdrop-filter (handled here) — the parent must have something
 * visually behind it for the blur to be perceptible.
 *
 * SAFARI: backdrop-filter requires -webkit- prefix; included.
 *
 * USAGE:
 *   <div class="ldt-glass">…</div>
 *   <div class="ldt-glass ldt-glass--strong">…</div>
 *   <div class="ldt-glass ldt-glass--dark">…</div>     (for dark surface variant)
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-glass {
    background: var(--ldt-glass-light, rgba(255, 255, 255, 0.72));
    -webkit-backdrop-filter: blur(var(--ldt-glass-blur, 20px)) saturate(var(--ldt-glass-saturate, 180%));
            backdrop-filter: blur(var(--ldt-glass-blur, 20px)) saturate(var(--ldt-glass-saturate, 180%));
    border: var(--ldt-glass-border-light, 1px solid rgba(255, 255, 255, 0.5));
    border-radius: var(--ldt-radius-card, 1.25rem);
}

/* Stronger blur + higher opacity — for sticky headers, modals, fixed CTA bars */
.ldt-glass--strong {
    background: var(--ldt-glass-light-strong, rgba(255, 255, 255, 0.85));
    -webkit-backdrop-filter: blur(var(--ldt-glass-blur-strong, 32px)) saturate(var(--ldt-glass-saturate, 180%));
            backdrop-filter: blur(var(--ldt-glass-blur-strong, 32px)) saturate(var(--ldt-glass-saturate, 180%));
}

/* Dark variant — for headers/cards floating on light backgrounds, or for
   light text on a dark blur. */
.ldt-glass--dark {
    background: var(--ldt-glass-dark, rgba(15, 23, 42, 0.6));
    border: var(--ldt-glass-border-dark, 1px solid rgba(255, 255, 255, 0.1));
    color: rgba(255, 255, 255, 0.92);
}

.ldt-glass--dark.ldt-glass--strong {
    background: var(--ldt-glass-dark-strong, rgba(15, 23, 42, 0.78));
}

/* Fallback for browsers without backdrop-filter (older Firefox, very old
   Safari): solid-ish white that still reads as a card.
   @supports lets us scope the blur version cleanly. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .ldt-glass {
        background: rgba(255, 255, 255, 0.96);
    }
    .ldt-glass--dark {
        background: rgba(15, 23, 42, 0.92);
    }
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 3. 3D CARD TILT
 *
 * Two-class system:
 *   .ldt-card-3d         the perspective parent (pointer-events bubble through)
 *   .ldt-card-3d__inner  the actual content that tilts
 *
 * USAGE:
 *   <div class="ldt-card-3d">
 *     <div class="ldt-card-3d__inner">
 *       … card content …
 *     </div>
 *   </div>
 *
 * Disabled on mobile/touch — see media queries below.
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-card-3d {
    perspective: 1000px;
    /* The parent holds the perspective; content goes in __inner. */
}

.ldt-card-3d__inner {
    transform-style: preserve-3d;
    transform: rotateY(0) rotateX(0) translateZ(0);
    transition: transform 0.4s var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1));
    will-change: transform;
}

@media (hover: hover) and (pointer: fine) {
    .ldt-card-3d:hover .ldt-card-3d__inner {
        transform: rotateY(5deg) rotateX(-5deg) translateZ(20px);
    }
}

/* RTL — flip the Y rotation so the lift direction stays "outward" relative
   to reading direction */
[dir="rtl"] .ldt-card-3d:hover .ldt-card-3d__inner,
.ldt-rtl .ldt-card-3d:hover .ldt-card-3d__inner {
    transform: rotateY(-5deg) rotateX(-5deg) translateZ(20px);
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 4. HOVER LIFT — subtle translateY + shadow swap on hover
 *
 * Drop on any element that should "rise" toward the user on hover. Pairs well
 * with .ldt-glass cards and destination cards.
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-hover-lift {
    transition:
        transform 0.3s var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1)),
        box-shadow 0.3s var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1));
    will-change: transform;
}

@media (hover: hover) and (pointer: fine) {
    .ldt-hover-lift:hover {
        transform: translateY(-8px);
        box-shadow: var(--ldt-shadow-card-hover, 0 18px 40px -12px rgba(15, 23, 42, 0.22));
    }
}

/* Variant: stronger lift (used for feature/spotlight cards) */
.ldt-hover-lift--strong {
    transition:
        transform 0.4s var(--ldt-ease-portal),
        box-shadow 0.4s var(--ldt-ease-portal);
}

@media (hover: hover) and (pointer: fine) {
    .ldt-hover-lift--strong:hover {
        transform: translateY(-12px);
        box-shadow: 0 25px 60px -15px rgba(0, 53, 128, 0.30);
    }
}

/* Variant: subtle lift (used for list rows, sidebar items) */
.ldt-hover-lift--soft {
    transition: transform 0.2s var(--ldt-ease-portal),
                background-color 0.2s var(--ldt-ease-portal);
}

@media (hover: hover) and (pointer: fine) {
    .ldt-hover-lift--soft:hover {
        transform: translateY(-2px);
    }
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 5. HOVER ZOOM IMAGE — image scales inside its parent on parent hover
 *
 * Apply to the IMAGE element. The parent should have overflow:hidden.
 *
 * USAGE:
 *   <a class="ldt-card" style="overflow:hidden">
 *     <img class="ldt-hover-zoom-img" src="…">
 *   </a>
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-hover-zoom-img {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 0.6s var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1));
    will-change: transform;
}

@media (hover: hover) and (pointer: fine) {
    .ldt-card-dest:hover .ldt-hover-zoom-img,
    .ldt-card:hover .ldt-hover-zoom-img,
    .ldt-hover-lift:hover .ldt-hover-zoom-img,
    a:hover > .ldt-hover-zoom-img,
    *:hover > .ldt-hover-zoom-img {
        transform: scale(1.08);
    }
}

/* Mobile: tone down to 1.04 so it still feels alive but doesn't visually jolt
   on the smaller viewport where the image is bigger relative to viewport */
@media (max-width: 768px) {
    .ldt-hover-zoom-img {
        transition-duration: 0.4s;
    }
    *:hover > .ldt-hover-zoom-img {
        transform: scale(1.04);
    }
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 6. STANDALONE ANIMATION CLASSES
 *
 * Apply these to opt into a specific keyframe loop. Useful for one-off
 * decorative elements (floating travel icons, slowly rotating orbs, etc).
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-pulse {
    animation: ldt-pulse-glow 2s ease-in-out infinite;
}

.ldt-float {
    animation: ldt-float-icon 10s ease-in-out infinite;
}

.ldt-rotate {
    animation: ldt-rotate-slow 20s linear infinite;
}

.ldt-badge-pulse {
    animation: ldt-badge-pulse 2s ease-in-out infinite;
}

/* Apply staggered delays via inline style or CSS variables, e.g.:
   <span class="ldt-float" style="animation-delay: 1s"></span>
   <span class="ldt-float" style="animation-delay: 3s"></span>
   <span class="ldt-float" style="animation-delay: 6s"></span> */


/* ═══════════════════════════════════════════════════════════════════════════════
 * 7. SHIMMER SKELETON BACKGROUND
 *
 * Apply to placeholders while content loads. The element should size itself
 * via width/height (or aspect-ratio) before the class is applied.
 *
 * USAGE:
 *   <div class="ldt-shimmer-bg" style="height:200px;border-radius:12px"></div>
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-shimmer-bg {
    background:
        linear-gradient(
            90deg,
            var(--ldt-gray-200, #e2e8f0) 0%,
            var(--ldt-gray-300, #cbd5e1) 50%,
            var(--ldt-gray-200, #e2e8f0) 100%
        );
    background-size: 1000px 100%;
    background-repeat: no-repeat;
    animation: ldt-shimmer var(--ldt-duration-shimmer, 2500ms) linear infinite;
}

/* Variant: card-shape shimmer with built-in border-radius */
.ldt-shimmer-bg--card {
    border-radius: var(--ldt-radius-card, 1.25rem);
    aspect-ratio: 3 / 2;
}

/* Variant: text-line shimmer (one line of fake text) */
.ldt-shimmer-bg--text {
    height: 1em;
    border-radius: 4px;
    margin-bottom: 0.6em;
}

.ldt-shimmer-bg--text:last-child {
    width: 70%;
}

/* Variant: avatar circle */
.ldt-shimmer-bg--avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 8. SCROLL REVEAL — .ldt-reveal + .is-visible
 *
 * Driven by the IntersectionObserver added to ldt-main.js in E3.
 *
 * STATES:
 *   .ldt-reveal              initial — invisible, translated 20px down
 *   .ldt-reveal.is-visible   final   — visible, settled, runs transition
 *
 * USAGE:
 *   <div class="ldt-reveal">…</div>
 *   <div class="ldt-reveal" data-ldt-reveal-delay="200">…</div>   (200ms stagger)
 *   <div class="ldt-reveal ldt-reveal--zoom">…</div>              (zoom variant)
 *   <div class="ldt-reveal ldt-reveal--left">…</div>              (slide from left)
 *
 * The data-ldt-reveal-delay attribute sets a CSS variable
 * (--ldt-reveal-delay) so the transition delays without re-querying the DOM.
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-reveal {
    opacity: 0;
    transform: translateY(20px);
    transition:
        opacity 700ms var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1))
            var(--ldt-reveal-delay, 0ms),
        transform 700ms var(--ldt-ease-portal, cubic-bezier(0.4, 0, 0.2, 1))
            var(--ldt-reveal-delay, 0ms);
    will-change: opacity, transform;
}

.ldt-reveal.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Variant: zoom-in (used for hero offer badges, modal-style reveals) */
.ldt-reveal--zoom {
    opacity: 0;
    transform: scale(0.92);
}

.ldt-reveal--zoom.is-visible {
    opacity: 1;
    transform: scale(1);
}

/* Variants: slide-in from left/right */
.ldt-reveal--left {
    opacity: 0;
    transform: translateX(-30px);
}

.ldt-reveal--right {
    opacity: 0;
    transform: translateX(30px);
}

.ldt-reveal--left.is-visible,
.ldt-reveal--right.is-visible {
    opacity: 1;
    transform: translateX(0);
}

/* Variant: fade-only (no movement — for inline images, text fragments) */
.ldt-reveal--fade {
    opacity: 0;
    transform: none;
}

.ldt-reveal--fade.is-visible {
    opacity: 1;
}

/* RTL flip — slide-left from RTL means slide-right and vice versa */
[dir="rtl"] .ldt-reveal--left,
.ldt-rtl .ldt-reveal--left {
    transform: translateX(30px);
}

[dir="rtl"] .ldt-reveal--right,
.ldt-rtl .ldt-reveal--right {
    transform: translateX(-30px);
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 9. .ldt-no-anim — escape hatch
 *
 * Apply to any element (or body) to disable all animations on it and its
 * descendants. Useful for QA, screenshot capture, or sections that must stay
 * still (legal pages, embedded admin previews).
 * ═══════════════════════════════════════════════════════════════════════════════ */

.ldt-no-anim,
.ldt-no-anim * {
    animation: none !important;
    transition: none !important;
}

.ldt-no-anim .ldt-reveal {
    opacity: 1 !important;
    transform: none !important;
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 10. REDUCED-MOTION GUARD — global
 *
 * When the user has prefers-reduced-motion: reduce, neutralize all our
 * animations and reveal transitions. Functionality stays intact (links,
 * hover states still work) — only the motion is removed.
 *
 * Specific keyframes referenced by .ldt-bg-shape, .ldt-pulse etc. are
 * already neutralized at their own selectors in E2 + this file. This block
 * is the catch-all so any future utility we add here is automatically guarded.
 * ═══════════════════════════════════════════════════════════════════════════════ */

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

    /* Neutralize all standalone animation classes */
    .ldt-pulse,
    .ldt-float,
    .ldt-rotate,
    .ldt-badge-pulse,
    .ldt-shimmer-bg,
    .ldt-shimmer-bg--card,
    .ldt-shimmer-bg--text,
    .ldt-shimmer-bg--avatar {
        animation: none !important;
    }

    /* Reveal: show content immediately at rest position */
    .ldt-reveal,
    .ldt-reveal--zoom,
    .ldt-reveal--left,
    .ldt-reveal--right,
    .ldt-reveal--fade {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }

    /* 3D tilt: disable */
    .ldt-card-3d:hover .ldt-card-3d__inner,
    .ldt-rtl .ldt-card-3d:hover .ldt-card-3d__inner {
        transform: none !important;
    }

    /* Hover lift: disable */
    .ldt-hover-lift:hover,
    .ldt-hover-lift--strong:hover,
    .ldt-hover-lift--soft:hover {
        transform: none !important;
    }

    /* Image zoom: disable */
    .ldt-hover-zoom-img,
    *:hover > .ldt-hover-zoom-img {
        transform: none !important;
    }

    /* Cross-cutting: any element with explicit animation neutralizes
       (covers third-party / future CSS that uses our keyframes by name) */
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}


/* ═══════════════════════════════════════════════════════════════════════════════
 * 11. TOUCH DEVICES — disable hover effects that overlap with tap
 *
 * On touch devices the :hover state can stick after a tap and then "ghost"
 * the next interaction. We already gate hover-lift / 3D tilt / image zoom
 * via @media (hover: hover) — this block is the safety net.
 * ═══════════════════════════════════════════════════════════════════════════════ */

@media (hover: none) {
    .ldt-card-3d:hover .ldt-card-3d__inner,
    .ldt-hover-lift:hover,
    .ldt-hover-lift--strong:hover,
    .ldt-hover-lift--soft:hover {
        transform: none;
    }

    *:hover > .ldt-hover-zoom-img {
        transform: none;
    }
}


/* ─── END OF ldt-enhanced-animations.css ─────────────────────────────────── */
