/* autopilot/motion.css — single source of truth for every animation/transition
   in SEO Autopilot. Every duration/easing used anywhere in app.html or
   app.js must reference one of these tokens, not a one-off literal value.
   Premium = fewer, slower, softer — if an effect draws attention to itself,
   remove it rather than add another one here. */
:root {
  /* Durations */
  --dur-instant: 100ms;   /* hover color/opacity shifts */
  --dur-fast:    180ms;   /* buttons, chips, toggles, focus rings */
  --dur-base:    280ms;   /* cards, dropdowns, accordions, tooltips */
  --dur-slow:    450ms;   /* panel/step transitions, modals */
  --dur-scene:   700ms;   /* full-screen scene changes (welcome->scan->results) */

  /* Easings */
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);     /* default - everything entering */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);    /* moving/morphing elements */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* ONLY pin drops, checkmarks, badge pops */

  /* Shared enter/exit distances - transform only, never top/left/width */
  --rise-enter: 10px;   /* entering elements fade + rise this much */
  --fall-exit:  4px;    /* exiting elements fade + fall this much */
}

/* ---- Reusable enter/exit keyframes - transform-only (GPU, no layout thrash) ---- */
@keyframes mo-enter {
  from { opacity: 0; transform: translateY(var(--rise-enter)); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes mo-exit {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(var(--fall-exit)); }
}
@keyframes mo-pop {
  0%   { opacity: 0; transform: scale(.9); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes mo-shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
@keyframes mo-breathe {
  0%, 100% { opacity: .5; }
  50%      { opacity: 1; }
}
@keyframes mo-pulse-once {
  0%   { box-shadow: 0 0 0 0 rgba(47,191,113,.5); }
  100% { box-shadow: 0 0 0 10px rgba(47,191,113,0); }
}
@keyframes mo-count-tick { /* placeholder hook - actual count-up is JS-driven (rAF), see obCountUp() */
  from { opacity: .001; } to { opacity: 1; }
}

/* ---- Utility classes ---- */
.mo-enter { animation: mo-enter var(--dur-base) var(--ease-out) both; }
.mo-enter-scene { animation: mo-enter var(--dur-scene) var(--ease-out) both; }
.mo-exit { animation: mo-exit calc(var(--dur-base) * .6) var(--ease-in-out) both; }
.mo-pop { animation: mo-pop var(--dur-fast) var(--ease-spring) both; }
.mo-stagger > * { opacity: 0; animation: mo-enter var(--dur-base) var(--ease-out) both; }
/* Stagger delays generated up to 12 children - covers stat cards (3), table
   rows (capped at 8), and FAQ-style lists. Anything beyond child 12 shows
   instantly (no stagger) per the "cap at first 8 rows" rule. */
.mo-stagger > *:nth-child(1)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 0); }
.mo-stagger > *:nth-child(2)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 1); }
.mo-stagger > *:nth-child(3)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 2); }
.mo-stagger > *:nth-child(4)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 3); }
.mo-stagger > *:nth-child(5)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 4); }
.mo-stagger > *:nth-child(6)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 5); }
.mo-stagger > *:nth-child(7)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 6); }
.mo-stagger > *:nth-child(8)  { animation-delay: calc(var(--mo-stagger-unit, 30ms) * 7); }
.mo-stagger > *:nth-child(n+9) { animation-delay: 0ms; } /* capped - rest appear instantly */

/* Numbers must never wiggle as they update (money, ranks, countdowns). */
.mo-nums, .sc-hero-n, .sc-mini-v, .gg-s .v, .sc-table td, .vc-score, .rl-eta,
#scCountdown, #rl-eta {
  font-variant-numeric: tabular-nums;
}

/* Skeleton shimmer - navy-700 block, cream sweep at 4% opacity, shaped like
   the content it replaces (callers size/border-radius the element itself). */
.mo-skeleton {
  position: relative; overflow: hidden;
  background: var(--rlt-navy-700, #1B3A63);
}
.mo-skeleton::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(247,243,234,.04), transparent);
  animation: mo-shimmer 1.8s linear infinite;
}

/* Breathing dot (CHECKING status only) and single-pulse (LIVE on first appearance) */
.mo-breathe { animation: mo-breathe 2s ease-in-out infinite; }
.mo-pulse-once { animation: mo-pulse-once var(--dur-scene) var(--ease-out) 1; }

/* "No" gesture (e.g. a duplicate chip) - 4px each way, two cycles, never
   used for anything that draws attention TOWARD itself. */
@keyframes mo-shake {
  0%, 100% { transform: translateX(0); }
  20%, 60% { transform: translateX(-4px); }
  40%, 80% { transform: translateX(4px); }
}
.mo-shake { animation: mo-shake calc(var(--dur-base) * 1.6) var(--ease-in-out) 1; }

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-instant: 1ms; --dur-fast: 1ms; --dur-base: 1ms; --dur-slow: 1ms; --dur-scene: 1ms;
  }
  .mo-enter, .mo-enter-scene, .mo-exit, .mo-pop, .mo-stagger > *,
  .mo-breathe, .mo-pulse-once, .mo-shake, .sm-sweep, .sm-sweep::before, .rl-sweep, .rl-dot, .rl-ping {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
  .mo-skeleton::after { animation: none; }
}
