/* ==========================================================================
   Solverra - Motion (#159)  |  Interactive Animation Layer
   GPU-cheap micro-interactions. Animates transform / opacity / composited
   filter ONLY -- never layout-affecting properties -> no reflow, no CLS.
   Every "hidden start state" is scoped under html.solm-on so a no-JS or
   prefers-reduced-motion visitor sees fully-rendered content with zero hiding.
   Consumes solverra-design-system tokens with hard fallbacks for portability.
   Coordinates with solverra-ux-elite (no duplicate scroll-progress / smooth-
   scroll / global reduced-motion sheet -- those belong to UX Elite).
   ASCII-only.
   ========================================================================== */

/* ---- Local token aliases (fall back gracefully off the design system) ---- */
:root {
  --solm-ease: var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1));
  --solm-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --solm-dur-fast: var(--dur-1, 120ms);
  --solm-dur: var(--dur-2, 220ms);
  --solm-dur-slow: var(--dur-3, 360ms);
  --solm-reveal-dur: 720ms;
  --solm-reveal-shift: 26px;
  --solm-accent: var(--color-primary, #8CC63F);
  --solm-accent-2: var(--color-accent, #C9A36A);
  --solm-glow: var(--shadow-lime, 0 8px 24px rgba(140, 198, 63, 0.32));
  --solm-lift: var(--shadow-3, 0 14px 32px rgba(31, 44, 23, 0.12), 0 2px 6px rgba(31, 44, 23, 0.06));
  --solm-radius: var(--r-md, 12px);
  --solm-spot-size: 320px;
}

/* ==========================================================================
   1. SCROLL-REVEAL  ([data-motion="reveal"] + variants, .solm-reveal)
   Start state hidden ONLY when html.solm-on (JS up + motion allowed).
   ========================================================================== */
html.solm-on [data-motion~="reveal"],
html.solm-on .solm-reveal {
  opacity: 0;
  transform: translate3d(0, var(--solm-reveal-shift), 0);
  transition:
    opacity var(--solm-reveal-dur) var(--solm-ease),
    transform var(--solm-reveal-dur) var(--solm-ease);
  will-change: transform, opacity;
}

/* Directional variants (transform-only, never affects layout box) */
html.solm-on [data-motion-from="up"]    { transform: translate3d(0, var(--solm-reveal-shift), 0); }
html.solm-on [data-motion-from="down"]  { transform: translate3d(0, calc(var(--solm-reveal-shift) * -1), 0); }
html.solm-on [data-motion-from="left"]  { transform: translate3d(calc(var(--solm-reveal-shift) * -1), 0, 0); }
html.solm-on [data-motion-from="right"] { transform: translate3d(var(--solm-reveal-shift), 0, 0); }
html.solm-on [data-motion-from="zoom"]  { transform: scale(0.92); }
html.solm-on [data-motion-from="fade"]  { transform: none; }
html.solm-on [data-motion-from="blur"]  { filter: blur(10px); transform: translate3d(0, 14px, 0); }

/* Revealed resting state (JS adds .is-revealed) */
html.solm-on [data-motion~="reveal"].is-revealed,
html.solm-on .solm-reveal.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  filter: none;
}
html.solm-on [data-motion~="reveal"].is-revealed { will-change: auto; }

/* ==========================================================================
   2. STAGGER  ([data-motion-stagger] container -> children reveal in sequence)
   Delay is set inline by JS via --solm-i; keeps CSS static + cache-friendly.
   ========================================================================== */
html.solm-on [data-motion-stagger] > * {
  opacity: 0;
  transform: translate3d(0, var(--solm-reveal-shift), 0);
  transition:
    opacity var(--solm-reveal-dur) var(--solm-ease),
    transform var(--solm-reveal-dur) var(--solm-ease);
  transition-delay: calc(var(--solm-i, 0) * 70ms);
  will-change: transform, opacity;
}
html.solm-on [data-motion-stagger].is-revealed > * {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

/* ==========================================================================
   3. MAGNETIC / SPRING HOVER  (.solm-magnetic, [data-motion="magnetic"])
   JS writes --solm-mx / --solm-my (px). Spring easing on release.
   ========================================================================== */
html.solm-on .solm-magnetic,
html.solm-on [data-motion~="magnetic"] {
  transform: translate3d(var(--solm-mx, 0), var(--solm-my, 0), 0);
  transition: transform var(--solm-dur) var(--solm-ease-spring);
}
html.solm-on .solm-magnetic.is-magnet-active,
html.solm-on [data-motion~="magnetic"].is-magnet-active {
  transition: transform 60ms linear; /* track cursor tightly while engaged */
}

/* ==========================================================================
   4. 3D TILT  (.solm-tilt, [data-motion="tilt"])
   JS writes --solm-rx / --solm-ry (deg). Perspective on the element itself.
   ========================================================================== */
html.solm-on .solm-tilt,
html.solm-on [data-motion~="tilt"] {
  transform: perspective(800px)
             rotateX(var(--solm-rx, 0deg))
             rotateY(var(--solm-ry, 0deg))
             translateZ(0);
  transition: transform var(--solm-dur) var(--solm-ease);
  transform-style: preserve-3d;
}
html.solm-on .solm-tilt.is-tilting,
html.solm-on [data-motion~="tilt"].is-tilting {
  transition: transform 80ms linear;
}
/* Optional inner layer lifts on tilt for depth (opt-in via .solm-tilt__lift) */
html.solm-on .solm-tilt .solm-tilt__lift {
  transform: translateZ(40px);
  transition: transform var(--solm-dur) var(--solm-ease);
}

/* ==========================================================================
   5. PARALLAX  ([data-motion="parallax"])  JS writes --solm-py (px).
   Transform-only; never moves the layout box.
   ========================================================================== */
html.solm-on [data-motion~="parallax"] {
  transform: translate3d(0, var(--solm-py, 0), 0);
  will-change: transform;
}

/* ==========================================================================
   6. CLICK RIPPLE  (.solm-ripple, [data-motion="ripple"])
   Span injected by JS; pure transform/opacity expansion. Host needs clipping.
   ========================================================================== */
.solm-ripple,
[data-motion~="ripple"] {
  position: relative;
  overflow: hidden;
}
.solm-ripple__dot {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  background: currentColor;
  opacity: 0.28;
  transform: translate3d(0, 0, 0) scale(0);
  will-change: transform, opacity;
}
html.solm-on .solm-ripple__dot.is-go {
  animation: solm-ripple 620ms var(--solm-ease) forwards;
}
@keyframes solm-ripple {
  to { transform: translate3d(0, 0, 0) scale(1); opacity: 0; }
}

/* ==========================================================================
   7. ANIMATED COUNTERS  ([data-motion="counter"])
   No special start CSS needed -- JS swaps text content; tabular-nums avoids
   width jitter -> no horizontal CLS while digits change.
   ========================================================================== */
[data-motion~="counter"] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ==========================================================================
   8. SECTION TRANSITION  ([data-motion="section"])
   Soft cross-fade + gentle rise when a major section enters. Heavier shift
   than reveal; intended for full-width bands, not small items.
   ========================================================================== */
html.solm-on [data-motion~="section"] {
  opacity: 0;
  transform: translate3d(0, 40px, 0);
  transition:
    opacity 900ms var(--solm-ease),
    transform 900ms var(--solm-ease);
  will-change: transform, opacity;
}
html.solm-on [data-motion~="section"].is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

/* ==========================================================================
   9. CURSOR-AWARE HIGHLIGHT / SPOTLIGHT  (.solm-spotlight, [data-motion="spotlight"])
   JS writes --solm-spx / --solm-spy (px within the element). A radial sheen
   follows the cursor via a pseudo-element (composited, no repaint of content).
   ========================================================================== */
.solm-spotlight,
[data-motion~="spotlight"] {
  position: relative;
  isolation: isolate;
}
.solm-spotlight::before,
[data-motion~="spotlight"]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--solm-dur) var(--solm-ease);
  background: radial-gradient(
    var(--solm-spot-size) circle at var(--solm-spx, 50%) var(--solm-spy, 50%),
    color-mix(in srgb, var(--solm-accent) 26%, transparent),
    transparent 60%
  );
}
html.solm-on .solm-spotlight.is-lit::before,
html.solm-on [data-motion~="spotlight"].is-lit::before {
  opacity: 1;
}
/* Fallback for engines without color-mix(): plain low-alpha accent tint. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .solm-spotlight::before,
  [data-motion~="spotlight"]::before {
    background: radial-gradient(
      var(--solm-spot-size) circle at var(--solm-spx, 50%) var(--solm-spy, 50%),
      rgba(140, 198, 63, 0.22),
      transparent 60%
    );
  }
}

/* ==========================================================================
   10. PAGE-LOAD CHOREOGRAPHY  ([data-motion-choreo] container)
   Direct children rise + fade in a quick cascade on first paint. Distinct from
   scroll-reveal: this fires once, immediately, for above-the-fold hero content.
   ========================================================================== */
html.solm-on [data-motion-choreo] > * {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
}
html.solm-on [data-motion-choreo].is-choreo > * {
  animation: solm-choreo 760ms var(--solm-ease) both;
  animation-delay: calc(var(--solm-i, 0) * 90ms);
}
@keyframes solm-choreo {
  from { opacity: 0; transform: translate3d(0, 18px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ==========================================================================
   GENERIC HOVER / PRESS POLISH  (.solm-lift, .solm-press) -- opt-in helpers
   that work on hover (fine pointer) and tap (coarse) without JS.
   ========================================================================== */
.solm-lift {
  transition:
    transform var(--solm-dur) var(--solm-ease),
    box-shadow var(--solm-dur) var(--solm-ease);
}
@media (hover: hover) and (pointer: fine) {
  html.solm-on .solm-lift:hover {
    transform: translate3d(0, -4px, 0);
    box-shadow: var(--solm-lift);
  }
  html.solm-on .solm-glow-hover:hover {
    box-shadow: var(--solm-glow);
  }
}
.solm-press {
  transition: transform var(--solm-dur-fast) var(--solm-ease);
}
html.solm-on .solm-press:active {
  transform: scale(0.97);
}

/* ==========================================================================
   MOBILE TUNING  (coarse pointer = no hover)
   Disable cursor-driven effects that have no meaning without a pointer; give a
   crisp tap-scale instead. Reveal / counters / ripple / choreography stay on.
   ========================================================================== */
@media (hover: none), (pointer: coarse) {
  html.solm-on .solm-magnetic,
  html.solm-on [data-motion~="magnetic"],
  html.solm-on .solm-tilt,
  html.solm-on [data-motion~="tilt"],
  html.solm-on [data-motion~="parallax"] {
    transform: none !important;
    transition: transform var(--solm-dur-fast) var(--solm-ease);
  }
  html.solm-on .solm-spotlight::before,
  html.solm-on [data-motion~="spotlight"]::before {
    display: none;
  }
  /* Tap-press feedback for any interactive motion host on touch */
  html.solm-on .solm-magnetic:active,
  html.solm-on .solm-tilt:active,
  html.solm-on [data-motion~="magnetic"]:active,
  html.solm-on [data-motion~="tilt"]:active {
    transform: scale(0.97) !important;
  }
}

/* ==========================================================================
   SAVE-DATA / LOW-MEMORY (html.solm-lite)
   Keep meaning (reveal still happens) but make it instant + drop the expensive
   continuous effects (parallax, tilt, magnetic, spotlight follow).
   ========================================================================== */
html.solm-lite [data-motion~="reveal"],
html.solm-lite .solm-reveal,
html.solm-lite [data-motion-stagger] > *,
html.solm-lite [data-motion~="section"] {
  transition-duration: 0.001ms !important;
  transition-delay: 0ms !important;
}
html.solm-lite .solm-magnetic,
html.solm-lite [data-motion~="magnetic"],
html.solm-lite .solm-tilt,
html.solm-lite [data-motion~="tilt"],
html.solm-lite [data-motion~="parallax"] {
  transform: none !important;
}
html.solm-lite .solm-spotlight::before,
html.solm-lite [data-motion~="spotlight"]::before {
  display: none;
}

/* ==========================================================================
   PREFERS-REDUCED-MOTION  (fully honored -- EVERYTHING off, instantly)
   We do NOT rely on UX Elite's global sheet; we explicitly neutralize our own
   classes so this plugin is self-sufficient and safe even standalone. Because
   start-states are gated behind html.solm-on (which the boot guard never adds
   under reduced motion) content is already visible; this block is belt-and-
   suspenders for any element JS may have touched.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  [data-motion],
  [data-motion-stagger] > *,
  [data-motion-choreo] > *,
  .solm-reveal,
  .solm-magnetic,
  .solm-tilt,
  .solm-lift,
  .solm-press,
  .solm-spotlight {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
    animation: none !important;
  }
  .solm-spotlight::before,
  [data-motion~="spotlight"]::before,
  .solm-ripple__dot {
    display: none !important;
  }
}
