/* ============================================================================
   DESIGN SYSTEM · 03 · MOTION
   ----------------------------------------------------------------------------
   Subtle, agency-style microanimations. All <= 480ms. All respect
   prefers-reduced-motion (tokens collapse to 1ms in 01-tokens.css).

   Naming convention:
     .fx-*       → entrance / state animations (apply once)
     .interact-* → interactive hover/press patterns
   ============================================================================ */

/* ── Keyframes ──────────────────────────────────────────────────────────── */
@keyframes ds-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes ds-slide-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes ds-slide-down {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

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

@keyframes ds-sheet-up {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

@keyframes ds-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

@keyframes ds-pulse-ring {
  0%   { box-shadow: 0 0 0 0 var(--ds-brand-ring); }
  70%  { box-shadow: 0 0 0 10px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

@keyframes ds-spin {
  to { transform: rotate(360deg); }
}

/* ── Entrance utilities ─────────────────────────────────────────────────── */
.fx-fade-in   { animation: ds-fade-in   var(--ds-motion-base) var(--ds-ease-out) both; }
.fx-slide-up  { animation: ds-slide-up  var(--ds-motion-slow) var(--ds-ease-out-expo) both; }
.fx-slide-down{ animation: ds-slide-down var(--ds-motion-slow) var(--ds-ease-out-expo) both; }
.fx-scale-in  { animation: ds-scale-in  var(--ds-motion-base) var(--ds-ease-out-expo) both; }
.fx-sheet-up  { animation: ds-sheet-up  var(--ds-motion-slow) var(--ds-ease-out-expo) both; }

/* Stagger children — apply .fx-stagger to a parent and .fx-slide-up to kids */
.fx-stagger > * { animation-delay: 0ms; }
.fx-stagger > *:nth-child(2)  { animation-delay:  60ms; }
.fx-stagger > *:nth-child(3)  { animation-delay: 120ms; }
.fx-stagger > *:nth-child(4)  { animation-delay: 180ms; }
.fx-stagger > *:nth-child(5)  { animation-delay: 240ms; }
.fx-stagger > *:nth-child(6)  { animation-delay: 300ms; }
.fx-stagger > *:nth-child(7)  { animation-delay: 360ms; }
.fx-stagger > *:nth-child(8)  { animation-delay: 420ms; }
.fx-stagger > *:nth-child(n+9){ animation-delay: 480ms; }

/* ── Skeleton (single, unified) ─────────────────────────────────────────── */
.fx-skeleton {
  background: linear-gradient(
    90deg,
    var(--ds-surface-2) 25%,
    var(--ds-surface-3) 50%,
    var(--ds-surface-2) 75%
  );
  background-size: 200% 100%;
  animation: ds-shimmer 1.4s linear infinite;
  border-radius: var(--ds-radius-sm);
  color: transparent !important;
  user-select: none;
  pointer-events: none;
}

/* ── Spinner ────────────────────────────────────────────────────────────── */
.fx-spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ds-spin 0.7s linear infinite;
  vertical-align: -0.15em;
}

/* ── Pulse ring (notification dot, live indicator) ──────────────────────── */
.fx-pulse-ring {
  position: relative;
}
.fx-pulse-ring::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  animation: ds-pulse-ring 1.8s var(--ds-ease-out) infinite;
  pointer-events: none;
}

/* ── Interactive press (tactile feedback on click) ──────────────────────── */
.interact-press {
  transition: transform var(--ds-motion-quick) var(--ds-ease-out);
}
.interact-press:active {
  transform: scale(0.97);
}

/* ── Lift on hover (cards, list items) ──────────────────────────────────── */
.interact-lift {
  transition:
    transform var(--ds-motion-base) var(--ds-ease-out-expo),
    box-shadow var(--ds-motion-base) var(--ds-ease-out);
}
@media (hover: hover) {
  .interact-lift:hover {
    transform: translateY(-2px);
    box-shadow: var(--ds-shadow-lg);
  }
}

/* ── Soft glow on hover (brand-tinted) ──────────────────────────────────── */
.interact-glow {
  transition: box-shadow var(--ds-motion-base) var(--ds-ease-out);
}
@media (hover: hover) {
  .interact-glow:hover {
    box-shadow: var(--ds-shadow-brand);
  }
}

/* ── HTMX & Alpine-friendly transitions ─────────────────────────────────── */
.htmx-swapping { opacity: 0; transition: opacity var(--ds-motion-quick) var(--ds-ease-out); }
.htmx-settling { opacity: 1; transition: opacity var(--ds-motion-base) var(--ds-ease-out); }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-indicator { opacity: 0; transition: opacity var(--ds-motion-quick) var(--ds-ease-out); }

/* x-cloak — hide until Alpine boots */
[x-cloak] { display: none !important; }

/* ── Reduced motion: kill all entrance animations cleanly ───────────────── */
@media (prefers-reduced-motion: reduce) {
  .fx-fade-in, .fx-slide-up, .fx-slide-down, .fx-scale-in, .fx-sheet-up,
  .fx-stagger > *, .fx-pulse-ring::after, .fx-skeleton, .fx-spinner {
    animation: none !important;
  }
  .interact-press:active, .interact-lift:hover {
    transform: none !important;
  }
}
