/* ==========================================================================
   Jameck Services India (P) Ltd. — Animation layer
   --------------------------------------------------------------------------
   Everything that moves lives here so motion can be tuned (or stripped)
   without touching layout in style.css.

   HOW IT WORKS
     - Elements marked [data-reveal] start hidden and are revealed when
       animations.js adds .is-revealed (IntersectionObserver, fires once).
     - Containers marked [data-stagger] get an incremental --i index on each
       child from JS, which becomes the transition-delay.
     - Hero and body entrance animations are pure CSS (no JS dependency), so
       above-the-fold content never waits on a script.
     - The final @media (prefers-reduced-motion: reduce) block neutralises
       every animation on this page. Keep it last.
   Durations stay in the 200–600ms band; entrances use ease-out.
   ========================================================================== */

/* ==========================================================================
   01. KEYFRAMES
   ========================================================================== */
@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fade-up {
  from { opacity: 0; transform: translate3d(0, 26px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes fade-right {
  from { opacity: 0; transform: translate3d(-28px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

@keyframes zoom-in {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: scale(1); }
}

/* The track holds two identical copies of the logo list, so shifting by
   exactly -50% lands back on a visually identical frame. */
@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes nudge-down {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}

@keyframes pulse-ring {
  0%   { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0.55); }
  70%  { box-shadow: 0 0 0 16px rgba(37, 211, 102, 0); }
  100% { box-shadow: 0 0 0 0 rgba(37, 211, 102, 0); }
}

/* ==========================================================================
   02. PAGE LOAD
   Short body fade so navigating between pages doesn't flash.
   ========================================================================== */
body {
  animation: fade-in 400ms var(--ease-out) both;
}

/* ==========================================================================
   03. SCROLL REVEAL
   Applied by animations.js. Defaults to fade + rise; direction variants let a
   section vary its rhythm without new CSS.
   ========================================================================== */
[data-reveal] {
  opacity: 0;
  transform: translate3d(0, 28px, 0);
  transition:
    opacity 620ms var(--ease-out),
    transform 620ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 90ms);
  will-change: opacity, transform;
}
[data-reveal="left"]  { transform: translate3d(-34px, 0, 0); }
[data-reveal="right"] { transform: translate3d(34px, 0, 0); }
[data-reveal="zoom"]  { transform: scale(0.95); }
[data-reveal="fade"]  { transform: none; }

[data-reveal].is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

/* Once the reveal has played, drop the hint so hover transforms stay smooth. */
[data-reveal].is-revealed { will-change: auto; }

/* If JS never runs (disabled/blocked), show everything rather than a blank page. */
.no-js [data-reveal] {
  opacity: 1;
  transform: none;
}

/* Stagger step overrides for tighter or looser grids. */
[data-stagger="fast"] > * { transition-delay: calc(var(--i, 0) * 60ms); }
[data-stagger="slow"] > * { transition-delay: calc(var(--i, 0) * 130ms); }

/* ==========================================================================
   04. HERO ENTRANCE (CSS only — plays on load, no observer)
   ========================================================================== */
[data-hero] {
  animation: fade-up 700ms var(--ease-out) both;
  animation-delay: calc(140ms + var(--hero-i, 0) * 110ms);
}
[data-hero="media"] {
  animation-name: zoom-in;
  animation-duration: 820ms;
}
.hero__float {
  animation: fade-up 620ms var(--ease-out) both;
  animation-delay: 760ms;
}
.hero__scroll svg {
  animation: nudge-down 2.4s var(--ease-in-out) infinite;
}

/* Inner-page heroes get the same treatment, slightly quicker. */
.page-hero [data-hero] {
  animation-duration: 560ms;
  animation-delay: calc(80ms + var(--hero-i, 0) * 90ms);
}

/* ==========================================================================
   05. MARQUEE
   Duration scales with the number of items via --marquee-duration (set inline
   or left at the default).
   ========================================================================== */
.marquee__track {
  animation: marquee-scroll var(--marquee-duration, 38s) linear infinite;
}
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track {
  animation-play-state: paused;
}

/* ==========================================================================
   06. COUNTERS
   The number itself is animated in JS; this only smooths the container.
   ========================================================================== */
.stat__num { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   07. FILTER GRID TRANSITIONS (products page)
   ========================================================================== */
.filter-grid > * {
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
}
.filter-grid > .is-hiding {
  opacity: 0;
  transform: scale(0.96) translateY(10px);
  pointer-events: none;
}

/* ==========================================================================
   08. MOBILE NAV ITEM STAGGER
   Links cascade in behind the sliding panel.
   ========================================================================== */
@media (max-width: 960px) {
  .nav__list li,
  .nav__cta {
    opacity: 0;
    transform: translateX(22px);
    transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
  }
  body.nav-open .nav__list li,
  body.nav-open .nav__cta {
    opacity: 1;
    transform: translateX(0);
    transition-delay: calc(160ms + var(--i, 0) * 55ms);
  }
}

/* ==========================================================================
   09. MISC MICRO-INTERACTIONS
   ========================================================================== */
.whatsapp-float { animation: pulse-ring 3.2s var(--ease-out) infinite; }

/* Product detail: main image cross-fades when a thumbnail is chosen. */
.pd-gallery__main.is-swapping .ph { animation: fade-in 340ms var(--ease-out) both; }

/* Lightbox content settles in after the scrim. */
.lightbox.is-open .lightbox__caption { animation: fade-up 420ms var(--ease-out) 100ms both; }

/* ==========================================================================
   10. REDUCED MOTION — global off switch
   Every animated behaviour above degrades to an instant, legible state.
   JS also reads this preference (see prefersReducedMotion in animations.js)
   to skip counters, autoplay and smooth scrolling.
   KEEP THIS BLOCK LAST.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* Content must be visible immediately — never left mid-reveal. */
  [data-reveal],
  [data-reveal].is-revealed,
  [data-hero],
  .hero__float,
  .nav__list li,
  .nav__cta {
    opacity: 1 !important;
    transform: none !important;
  }

  /* Stop the infinite loops outright rather than running them at 0ms. */
  .marquee__track { animation: none !important; transform: none !important; }
  .marquee { overflow-x: auto; }
  .hero__scroll svg { animation: none !important; }
  .whatsapp-float { animation: none !important; }

  /* Hover transforms become colour-only feedback. */
  .card:hover,
  .feature:hover,
  .mvv:hover,
  .cert-card:hover,
  .quote:hover,
  .gallery-item:hover,
  .btn:hover,
  .to-top:hover,
  .whatsapp-float:hover,
  .media-frame:hover > .ph,
  .card:hover .media-frame > .ph { transform: none !important; }
}
