/* =========================================================================
   FunLida Motion Layer — Stage 3 (W5), intensity: Balanced (decision D4)
   Loads after funlida-material.css. Pairs with funlida-motion.js.
   Revert: novamira/disable-file on this file (and/or the .js — they are
   independently disableable, see NO-FLASH CONTRACT below).

   Transform and opacity only. Nothing here animates a layout property,
   so Stage 3 contributes no CLS.

   NO-FLASH CONTRACT
   This file never hides anything on its own. The hidden pre-reveal state
   lives on `.fl-reveal`, and only funlida-motion.js ever applies that
   class — and only to elements that are below the fold at init. So:
     - JS disabled / failed / blocked  -> nothing is ever hidden
     - CSS disabled                    -> JS toggles classes that do nothing
   Neither half can strand content invisible. Do not move the hidden state
   onto a class that is present in the served HTML.

   DURATION NOTE
   The plan's "nothing over 600ms" governs transitions and reveals, and is
   held here (400ms max). The idle loops in section 3 are deliberately
   4-6s per FRONTEND-PLAN W5 ("long durations, amplitude <=8px - felt, not
   noticed"). Those are the stated exception, not a miss.
   ========================================================================= */


/* --- 1. SCROLL REVEAL -----------------------------------------------------
   JS adds .fl-reveal to below-fold targets, then .is-in when they cross
   the viewport. Fires once, then unobserves. --fl-reveal-y and the
   durations collapse to ~0 under prefers-reduced-motion via the token
   kill-switch already in funlida-tokens.css.                            */

.fl-reveal {
  opacity: 0;
  transform: translateY(var(--fl-reveal-y));
  transition:
    opacity var(--fl-dur-slow) var(--fl-ease-out),
    transform var(--fl-dur-slow) var(--fl-ease-out);
  will-change: opacity, transform;
}

.fl-reveal.is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}


/* --- 2. HOVER CHOREOGRAPHY ------------------------------------------------
   One vocabulary: cards lift 4px, buttons lift 2px, photos scale 1.04.
   design.css lifts cards 6px, which reads as a jump rather than a
   response; these selectors sit at (0,3,0) to win that.                 */

.fl-section .fl-step-card,
.fl-section .fl-explore-card,
.fl-plan-grid .fl-plan-card,
.fl-tst-grid .fl-tst-card,
.fl-hts-track .fl-hts-card {
  transition:
    transform var(--fl-dur-base) var(--fl-ease-out),
    box-shadow var(--fl-dur-base) var(--fl-ease-out);
}

.fl-section .fl-step-card:hover,
.fl-section .fl-explore-card:hover,
.fl-plan-grid .fl-plan-card:hover,
.fl-tst-grid .fl-tst-card:hover,
.fl-hts-track .fl-hts-card:hover {
  transform: translateY(-4px);
}

/* Buttons respond at half the card amplitude — a control is smaller than
   an object, so it should move less. */
.fl-section .elementor-button,
.fl-plan-grid .fl-plan-btn .elementor-button,
.fl-newsletter-btn {
  transition:
    transform var(--fl-dur-fast) var(--fl-ease-out),
    background-color var(--fl-dur-fast) var(--fl-ease-out),
    box-shadow var(--fl-dur-fast) var(--fl-ease-out);
}

.fl-section .elementor-button:hover,
.fl-plan-grid .fl-plan-btn .elementor-button:hover,
.fl-newsletter-btn:hover {
  transform: translateY(-2px);
}

/* Teacher photo scales inside the card; transform only, so the grid and
   the card box never reflow. */
.fl-hts-track .fl-hts-card img {
  transition: transform var(--fl-dur-base) var(--fl-ease-out);
}
.fl-hts-track .fl-hts-card:hover img {
  transform: scale(1.04);
}

/* Pressed state: the lift collapses, so a click feels like contact. */
.fl-section .fl-step-card:active,
.fl-section .fl-explore-card:active,
.fl-plan-grid .fl-plan-card:active,
.fl-hts-track .fl-hts-card:active,
.fl-section .elementor-button:active,
.fl-newsletter-btn:active {
  transform: translateY(0);
  transition-duration: var(--fl-dur-fast);
}


/* --- 3. IDLE LIFE ---------------------------------------------------------
   Balanced intensity. The two hero chips drift; the badges are handled by
   the parallax in funlida-motion.js so they are left alone here (one
   transform owner per element, or they fight).

   design.css hides .fl-doodle below 1024px, so this is desktop-only by
   construction — no mobile battery cost.                                */

@keyframes fl-float {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -8px, 0); }
}

.fl-chip-talk {
  animation: fl-float 5.5s var(--fl-ease-inout) infinite alternate;
}

.fl-chip-cando {
  animation: fl-float 4.5s var(--fl-ease-inout) infinite alternate;
  animation-delay: -1.8s;   /* desync, so they never bob in lockstep */
}


/* --- 4. REDUCED MOTION ----------------------------------------------------
   The token kill-switch in funlida-tokens.css already collapses every
   duration and --fl-reveal-y. Keyframe loops and hover transforms are not
   durations, so they are stopped explicitly here. This block is the
   backstop for the whole stage.                                         */

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

  .fl-chip-talk,
  .fl-chip-cando {
    animation: none;
  }

  .fl-reveal,
  .fl-reveal.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .fl-section .fl-step-card:hover,
  .fl-section .fl-explore-card:hover,
  .fl-plan-grid .fl-plan-card:hover,
  .fl-tst-grid .fl-tst-card:hover,
  .fl-hts-track .fl-hts-card:hover,
  .fl-section .elementor-button:hover,
  .fl-plan-grid .fl-plan-btn .elementor-button:hover,
  .fl-newsletter-btn:hover,
  .fl-hts-track .fl-hts-card:hover img {
    transform: none;
  }

  /* Snap without smooth-scrolling to it. */
  .fl-hts-track {
    scroll-behavior: auto;
  }
}


/* --- 5. PRINT / NON-SCROLLING RENDERERS -----------------------------------
   A reveal that depends on scrolling is invisible to anything that never
   scrolls. Verified during Stage 3 QA: a full-page screenshot captured
   from the top renders How It Works, Why Choose, Explore, Packages,
   Testimonials and Contact as blank bands, because the compositor never
   moves the viewport and IntersectionObserver never fires.

   Live scrolling is unaffected (all 30 targets confirmed revealing), but
   print, PDF export and screenshot tooling all hit this. The content is
   only ever hidden by opacity, never removed, so this restores it in one
   rule. Paired with the beforeprint handler in funlida-motion.js for
   browsers that evaluate print CSS after the paint.                    */

@media print {
  .fl-reveal,
  .fl-reveal:not(.is-in) {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}
