/* ============================================================
   AllTheMuse — Motion System (Track 6)
   ONE coherent, premium motion language for the whole site.
   Calm · confident · physical. No casino energy.

   Usage (additive only — never restyle sections to adopt):
     <link rel="stylesheet" href="/assets/motion.css?v=…">
     Classes are all prefixed "m-" so they never collide with
     section styles. Add a class to markup and get the behavior:

     .m-reveal            section/element enter-on-scroll (JS observes)
     .m-reveal[data-stagger]  children enter staggered
     .m-lift              hover lift with depth shadow (fine pointers)
     .m-press             subtle press scale on :active (fine pointers)
     .m-card              .m-lift + .m-press together (cards/tiles)
     .m-para[data-speed]  parallax layer (motion.js drives it)
     .m-toast             spring slide-up entrance (toasts, pills)
     .m-modal-pop         spring pop entrance (modal panels)
     .m-skel              calm skeleton shimmer (loading placeholders)
     .m-celebrate         tasteful unlock/collection celebration
     .m-fade              simple fade-in (JS toggles .in)

   Motion JS (assets/motion.js) drives .m-reveal / .m-para and
   exposes window.AtmMotion.reducedMotion(). Everything is still
   under prefers-reduced-motion — see the guard at the bottom.
   ============================================================ */

:root {
  /* ---- Spring-physics cubic-bezier approximations ---- */
  --motion-spring:       cubic-bezier(0.22, 0.9, 0.28, 1.08);  /* gentle overshoot, default */
  --motion-spring-soft:  cubic-bezier(0.20, 0.80, 0.25, 1.00); /* settle, no overshoot */
  --motion-spring-snap:  cubic-bezier(0.20, 0.90, 0.30, 1.22);  /* decisive snap (small elems) */
  --motion-ease-out:     cubic-bezier(0.16, 0.80, 0.24, 1.00);  /* reveals, exits */
  --motion-ease-in-out:  cubic-bezier(0.65, 0.00, 0.35, 1.00);  /* emphasis */
  --motion-ease-in:      cubic-bezier(0.55, 0.06, 0.68, 0.19);  /* rare dismisses */

  /* ---- Durations: quick to trigger, slow to feel ---- */
  --motion-dur-instant:  120ms;
  --motion-dur-fast:     180ms;
  --motion-dur-med:      320ms;
  --motion-dur-slow:     480ms;
  --motion-dur-glacial:  800ms;

  /* ---- Reveal (section enter) ---- */
  --motion-reveal-distance: 24px;
  --motion-reveal-duration: 560ms;
  --motion-stagger-step:    70ms;

  /* ---- Press & lift ---- */
  --motion-press-scale:  0.965;
  --motion-press-duration: var(--motion-dur-instant);
  --motion-lift:        -6px;
  --motion-lift-distance: 6px;
  --motion-lift-shadow: 0 22px 60px rgba(0, 0, 0, 0.12);

  /* ---- Skeleton shimmer ---- */
  --motion-skel-duration: 1800ms;
}

/* ============================================================
   Reveal — enter-on-scroll (motion.js adds .in via observer)
   ============================================================ */
.m-reveal {
  opacity: 0;
  transform: translateY(var(--motion-reveal-distance));
  transition:
    opacity var(--motion-reveal-duration) var(--motion-ease-out),
    transform var(--motion-reveal-duration) var(--motion-ease-out);
  transition-delay: var(--m-d, 0ms);
  will-change: opacity, transform;
}
.m-reveal.in,
.m-reveal.m-static {  /* .m-static: force-visible (SSR / no-JS) */
  opacity: 1;
  transform: none;
}

/* Softer variant: scale-in for hero/featured pieces */
.m-reveal-scale {
  opacity: 0;
  transform: translateY(16px) scale(0.98);
  transition:
    opacity var(--motion-dur-slow) var(--motion-ease-out),
    transform var(--motion-dur-slow) var(--motion-spring-soft);
  transition-delay: var(--m-d, 0ms);
  will-change: opacity, transform;
}
.m-reveal-scale.in { opacity: 1; transform: none; }

/* Stagger: children enter one after another, 70ms apart */
.m-reveal[data-stagger] > *:nth-child(1) { --m-d: 0ms; }
.m-reveal[data-stagger] > *:nth-child(2) { --m-d: calc(var(--motion-stagger-step) * 1); }
.m-reveal[data-stagger] > *:nth-child(3) { --m-d: calc(var(--motion-stagger-step) * 2); }
.m-reveal[data-stagger] > *:nth-child(4) { --m-d: calc(var(--motion-stagger-step) * 3); }
.m-reveal[data-stagger] > *:nth-child(5) { --m-d: calc(var(--motion-stagger-step) * 4); }
.m-reveal[data-stagger] > *:nth-child(6) { --m-d: calc(var(--motion-stagger-step) * 5); }
.m-reveal[data-stagger] > *:nth-child(7) { --m-d: calc(var(--motion-stagger-step) * 6); }
.m-reveal[data-stagger] > *:nth-child(8) { --m-d: calc(var(--motion-stagger-step) * 7); }

/* Simple fade (JS toggles .in, or add .m-static to pre-show) */
.m-fade {
  opacity: 0;
  transition: opacity var(--motion-dur-med) var(--motion-ease-out);
  transition-delay: var(--m-d, 0ms);
}
.m-fade.in { opacity: 1; }

/* ============================================================
   Hover lift with depth shadow — fine pointers only
   ============================================================ */
@media (hover: hover) and (pointer: fine) {
  .m-lift {
    transition:
      transform var(--motion-dur-med) var(--motion-spring-soft),
      box-shadow var(--motion-dur-med) var(--motion-spring-soft);
  }
  .m-lift:hover {
    transform: translateY(var(--motion-lift));
    box-shadow: var(--motion-lift-shadow);
  }
}

/* ============================================================
   Press state — subtle scale, fine pointers only
   ============================================================ */
@media (hover: hover) and (pointer: fine) {
  .m-press {
    transition: transform var(--motion-press-duration) var(--motion-ease-out);
  }
  .m-press:active { transform: scale(var(--motion-press-scale)); }
}

/* Card = lift on hover + press on click (one class, both states) */
@media (hover: hover) and (pointer: fine) {
  .m-card {
    transition:
      transform var(--motion-dur-med) var(--motion-spring-soft),
      box-shadow var(--motion-dur-med) var(--motion-spring-soft);
  }
  .m-card:hover {
    transform: translateY(var(--motion-lift));
    box-shadow: var(--motion-lift-shadow);
  }
  .m-card:active { transform: translateY(-2px) scale(var(--motion-press-scale)); }
}

/* ============================================================
   Parallax — motion.js sets --m-py per scroll position
   data-speed="0.15" (positive = drift down slower than scroll)
   ============================================================ */
.m-para {
  will-change: transform;
  transform: translate3d(0, var(--m-py, 0px), 0);
  transition: transform 0.12s linear; /* smooths rAF steps */
}

/* ============================================================
   Toast / pill entrance — spring slide-up
   ============================================================ */
@keyframes mToastIn {
  from { opacity: 0; transform: translate(-50%, 18px) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
.m-toast { animation: mToastIn var(--motion-dur-med) var(--motion-spring); }

/* Modal panel entrance — spring pop */
@keyframes mModalPop {
  from { opacity: 0; transform: translateY(14px) scale(0.965); }
  to   { opacity: 1; transform: none; }
}
.m-modal-pop { animation: mModalPop var(--motion-dur-slow) var(--motion-spring); }

/* ============================================================
   Skeleton shimmer — calm, slow, single light sweep
   ============================================================ */
.m-skel {
  position: relative;
  overflow: hidden;
  background: var(--bg-soft, #f1f1f4);
  border-radius: var(--r-md, 14px);
}
.m-skel::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, 0.7) 50%, transparent 65%);
  transform: translateX(-100%);
  animation: mSkelSweep var(--motion-skel-duration) var(--motion-ease-in-out) infinite;
}
@keyframes mSkelSweep { to { transform: translateX(100%); } }

/* ============================================================
   Celebration — tasteful unlock/collect (JS triggers .go,
   motion.js's celebrate() adds it for you)
   ============================================================ */
@keyframes mGlowPulse {
  0%   { box-shadow: 0 0 0 0 rgba(124, 92, 255, 0); }
  35%  { box-shadow: 0 0 0 8px rgba(124, 92, 255, 0.22), 0 18px 60px rgba(0, 0, 0, 0.10); }
  100% { box-shadow: 0 0 0 0 rgba(124, 92, 255, 0); }
}
@keyframes mCelebrateRise {
  0%   { transform: scale(0.94) translateY(10px); opacity: 0; }
  60%  { transform: scale(1.015) translateY(0); opacity: 1; }
  100% { transform: scale(1) translateY(0); opacity: 1; }
}
.m-celebrate.go {
  animation:
    mCelebrateRise var(--motion-dur-slow) var(--motion-spring),
    mGlowPulse var(--motion-dur-glacial) var(--motion-ease-out);
}

/* Particle burst — motion.js's fxConfetti partner for CSS-only contexts.
   Spawn spans with style="--bx:..px;--by:..px;--rot:..deg" inside .m-burst. */
.m-burst { position: relative; }
.m-burst .m-bit {
  position: absolute;
  left: 50%; top: 50%;
  width: 8px; height: 8px;
  border-radius: 2px;
  background: var(--purple, #7c5cff);
  pointer-events: none;
  opacity: 0;
}
.m-burst.go .m-bit {
  animation: mBitFly 900ms var(--motion-ease-out) forwards;
}
@keyframes mBitFly {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
  100% { opacity: 0; transform: translate(var(--bx, 60px), var(--by, -60px)) scale(0.4) rotate(var(--rot, 200deg)); }
}

/* ============================================================
   Reduced motion — EVERYTHING STILL. No exceptions.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .m-reveal, .m-reveal-scale, .m-fade {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .m-lift, .m-card, .m-press, .m-para {
    transition: none !important;
    transform: none !important;
    animation: none !important;
  }
  .m-lift:hover, .m-card:hover { box-shadow: none; transform: none; }
  .m-toast, .m-modal-pop, .m-celebrate.go { animation: none !important; }
  .m-skel::after { animation: none !important; opacity: 0.35; }
  .m-burst .m-bit { animation: none !important; }
}

/* html.m-reduced-motion is set by motion.js as a programmatic hook
   (mirrors the media query above for tests and JS-driven guards). */
html.m-reduced-motion .m-reveal,
html.m-reduced-motion .m-reveal-scale,
html.m-reduced-motion .m-fade {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  animation: none !important;
}
html.m-reduced-motion .m-skel::after,
html.m-reduced-motion .m-toast,
html.m-reduced-motion .m-modal-pop,
html.m-reduced-motion .m-celebrate.go { animation: none !important; }
html.m-reduced-motion .m-lift:hover,
html.m-reduced-motion .m-card:hover { transform: none !important; box-shadow: none !important; }
