/* =========================================================
   FinCo CRM — Motion system
   Timing values live in tokens.css (--motion-*).
   Behaviour is wired up in assets/js/motion.js.

   Rules to keep motion easy on the eyes:
   - Only opacity and transform are animated (smooth on every device).
   - No bounce, shake, spin or flashing; everything eases out softly.
   - Reveal plays once per element, never again on scroll-back.
   - "Reduce motion" OS setting: everything is shown in its final state.

   Combining effects: reveal and parallax both use `transform`, float uses
   `translate`. Put reveal/parallax on a wrapper and float on its child.
   ========================================================= */

/* ---------- Reveal: [data-reveal] ----------
   Hidden only when JS is running (html.js), so content never stays
   invisible if scripts fail. Stagger: add [data-reveal-stagger] to a parent. */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, var(--motion-reveal-distance), 0);
  transition:
    opacity var(--motion-reveal-duration) var(--ease-out-soft),
    transform var(--motion-reveal-duration) var(--ease-out-soft);
  transition-delay: calc(var(--reveal-index, 0) * var(--motion-stagger));
}
.js [data-reveal="fade"] { transform: none; }
.js [data-reveal="scale"] { transform: scale(0.97); }

/* Reset while off screen (motion.js): everything snaps back without animating */
.js .is-resetting,
.js .is-resetting * { transition: none !important; }

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

/* ---------- Float: .float ----------
   Runs on its own, independent of scrolling.
   Per-element variation:
     --float-pace      cycle length as a ratio of the token (1.5 = 50% slower)
     --float-delay     negative = start mid-cycle, so items never move in sync
     --float-scale     multiplies the token distance (e.g. 0.5 for large items)
     --float-x         horizontal drift ratio (0 = vertical only, 0.5 = half the vertical distance) */
.float {
  animation: motion-float calc(var(--motion-float-duration) * var(--float-pace, 1)) ease-in-out infinite alternate;
  animation-delay: var(--float-delay, 0s);
}
.float.is-offscreen { animation-play-state: paused; }

@keyframes motion-float {
  from {
    translate:
      calc(var(--motion-float-distance) * var(--float-scale, 1) * var(--float-x, 0) * -1)
      calc(var(--motion-float-distance) * var(--float-scale, 1) * -1);
  }
  to {
    translate:
      calc(var(--motion-float-distance) * var(--float-scale, 1) * var(--float-x, 0))
      calc(var(--motion-float-distance) * var(--float-scale, 1));
  }
}

/* ---------- Parallax: [data-parallax="0.1"] ----------
   JS sets --parallax-y (0–40 px): the element sits at its design position
   and lags behind the page as it scrolls up past the middle of the screen. */
[data-parallax] {
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}

/* ---------- Hover lift: .lift ---------- */
.lift {
  transition:
    transform var(--duration-base) var(--ease-standard),
    box-shadow var(--duration-base) var(--ease-standard);
}
@media (hover: hover) {
  .lift:hover {
    transform: translate3d(0, calc(var(--motion-lift-distance) * -1), 0);
    box-shadow: 0 2px 4px rgba(21, 33, 43, 0.04), 0 16px 32px -8px rgba(30, 86, 195, 0.14);
  }
}

/* ---------- Cross-fade: [data-crossfade] ----------
   Children stack in one grid cell; JS moves .is-active every N ms. */
[data-crossfade] {
  display: grid;
}
[data-crossfade] > * {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity var(--motion-crossfade-duration) var(--ease-standard);
}
[data-crossfade] > .is-active,
[data-crossfade]:not(.is-ready) > :first-child {
  opacity: 1;
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .float { animation: none; }
  [data-parallax] { transform: none; }
  .lift:hover { transform: none; }
}
