/* ==========================================================================
   animations.css — keyframes, scroll reveal, micro-interactions
   Every motion rule here is neutralised by the reduced-motion block at the
   end of the file, so accessibility is handled in one place.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Keyframes
   -------------------------------------------------------------------------- */
@keyframes fade-in       { from { opacity: 0 } to { opacity: 1 } }
@keyframes fade-up       { from { opacity: 0; transform: translate3d(0, 28px, 0) } to { opacity: 1; transform: none } }
@keyframes fade-down     { from { opacity: 0; transform: translate3d(0, -20px, 0) } to { opacity: 1; transform: none } }
@keyframes fade-left     { from { opacity: 0; transform: translate3d(32px, 0, 0) } to { opacity: 1; transform: none } }
@keyframes fade-right    { from { opacity: 0; transform: translate3d(-32px, 0, 0) } to { opacity: 1; transform: none } }
@keyframes zoom-in       { from { opacity: 0; transform: scale(.94) } to { opacity: 1; transform: none } }
@keyframes ken-burns     { from { transform: scale(1) } to { transform: scale(1.09) } }
@keyframes spin          { to { transform: rotate(360deg) } }
@keyframes cue-slide     { 0% { transform: scaleY(0); transform-origin: top } 45% { transform: scaleY(1); transform-origin: top } 55% { transform: scaleY(1); transform-origin: bottom } 100% { transform: scaleY(0); transform-origin: bottom } }
@keyframes ripple        { to { transform: scale(3.2); opacity: 0 } }
@keyframes pulse-ring    { 0% { transform: scale(.9); opacity: .55 } 70% { transform: scale(1.45); opacity: 0 } 100% { opacity: 0 } }
@keyframes loader-out    { to { opacity: 0; visibility: hidden } }

/* --------------------------------------------------------------------------
   2. Page loader
   -------------------------------------------------------------------------- */
.loader {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  display: grid;
  place-items: center;
  gap: var(--sp-4);
  background: var(--c-primary);
}
.loader__mark {
  font-family: var(--f-display);
  font-size: 2rem;
  letter-spacing: .2em;
  color: var(--c-secondary-300);
}
.loader__ring {
  width: 40px; height: 40px;
  border: 1.5px solid rgba(202, 183, 167, .25);
  border-top-color: var(--c-secondary);
  border-radius: var(--r-circle);
  animation: spin 900ms linear infinite;
}
.loader.is-done { animation: loader-out 420ms var(--e-soft) forwards; }

/* --------------------------------------------------------------------------
   3. Scroll reveal
   Elements start hidden and are revealed by IntersectionObserver adding
   .is-in. If JS never runs, .no-js in <html> keeps everything visible.
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  will-change: opacity, transform;
}
[data-reveal="up"]    { transform: translate3d(0, 28px, 0); }
[data-reveal="down"]  { transform: translate3d(0, -20px, 0); }
[data-reveal="left"]  { transform: translate3d(32px, 0, 0); }
[data-reveal="right"] { transform: translate3d(-32px, 0, 0); }
[data-reveal="zoom"]  { transform: scale(.94); }

[data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--t-reveal) var(--e-out),
              transform var(--t-reveal) var(--e-out);
  transition-delay: var(--reveal-delay, 0ms);
}

.no-js [data-reveal] { opacity: 1; transform: none; }

/* Stagger helper — set on a parent, children inherit incremental delays */
[data-reveal-group] > * { --reveal-delay: 0ms; }
[data-reveal-group] > *:nth-child(2) { --reveal-delay: 90ms; }
[data-reveal-group] > *:nth-child(3) { --reveal-delay: 180ms; }
[data-reveal-group] > *:nth-child(4) { --reveal-delay: 270ms; }
[data-reveal-group] > *:nth-child(5) { --reveal-delay: 360ms; }
[data-reveal-group] > *:nth-child(6) { --reveal-delay: 450ms; }
[data-reveal-group] > *:nth-child(n+7) { --reveal-delay: 520ms; }

/* --------------------------------------------------------------------------
   4. Hero motion
   -------------------------------------------------------------------------- */
.hero__slide.is-active img { animation: ken-burns 9s var(--e-soft) forwards; }

.hero__content.is-active .hero__eyebrow { animation: fade-up 800ms var(--e-out) 120ms both; }
.hero__content.is-active .hero__title   { animation: fade-up 900ms var(--e-out) 240ms both; }
.hero__content.is-active .hero__text    { animation: fade-up 900ms var(--e-out) 380ms both; }
.hero__content.is-active .hero__actions { animation: fade-up 900ms var(--e-out) 500ms both; }

.hero__cue::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--c-secondary);
  animation: cue-slide 2.4s var(--e-in-out) infinite;
}

/* Subtle parallax on the hero image; driven by main.js */
.hero__slide.is-active img { transform: translate3d(0, var(--parallax, 0px), 0) scale(1); }

/* --------------------------------------------------------------------------
   5. Button ripple
   -------------------------------------------------------------------------- */
.btn .ripple {
  position: absolute;
  border-radius: var(--r-circle);
  background: rgba(255, 255, 255, .38);
  transform: scale(0);
  pointer-events: none;
  animation: ripple 620ms var(--e-out) forwards;
  z-index: -1;
}
.btn--outline .ripple { background: rgba(28, 44, 52, .16); }

/* --------------------------------------------------------------------------
   6. Micro-interactions
   -------------------------------------------------------------------------- */
.fbtn--wa { position: relative; }
.fbtn--wa::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: var(--r-circle);
  background: #25d366;
  animation: pulse-ring 2.6s var(--e-out) infinite;
  z-index: -1;
}

.nav__link, .drawer__link, .btn, .gal-filter, .acc__btn { -webkit-tap-highlight-color: transparent; }

/* Lazy images fade in once decoded.
   This selector and `.media > img` in style.css have equal specificity, and
   this file loads later — so a bare `transition: opacity` here silently
   replaced the whole shorthand and left the hover zoom snapping with no
   easing on every lazy image, which is nearly all of them. Both transitions
   have to be declared together. */
img[loading="lazy"] {
  opacity: 0;
  transition:
    opacity 500ms var(--e-soft),
    transform var(--t-slow) var(--e-out),
    filter var(--t-slow) var(--e-out);
}
img[loading="lazy"].is-loaded, .no-js img[loading="lazy"] { opacity: 1; }

/* Counters hold layout while animating */
.stat__num { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   7. Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }

  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .hero__slide.is-active img { animation: none; transform: none; }
  .hero__cue { display: none !important; }
  .fbtn--wa::before { animation: none; opacity: 0; }
  .rail__hint::after { animation: none; opacity: 1; }

  /* The blanket `animation-duration: .01ms` above does not stop the marquee,
     it fast-forwards it — the track lands on its -50% end state and parks the
     duplicate copy on screen. Stop it outright, drop the duplicate that only
     existed to hide the loop seam, and hand the row over as a normal scroller. */
  .marquee {
    overflow-x: auto;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .marquee__track {
    animation: none !important;
    transform: none !important;
    width: auto;
  }
  .marquee__track > [aria-hidden="true"] { display: none; }
  .btn .ripple { display: none; }
  img[loading="lazy"] { opacity: 1; }
  .media:hover > img,
  a:hover .media > img,
  .card:hover .media > img,
  .tile:hover .media > img,
  .gal-item:hover .media > img,
  .feature:hover .media > img,
  .media--zoom:hover > img { transform: none; filter: none; }
  .card:hover, .feature:hover, .fbtn:hover { transform: none; }
}
