/* =====================================================================
   KaBoomz shared motion system (Milestone 2, 2026-09-22).

   ONE motion language for the host and the player: a small token set plus
   a handful of entrance/celebration utilities. Entrances play ONCE per
   meaningful state - the JS layer (core/motion.js) owns the replay
   guards; this file owns the look and the reduced-motion contract.

   Rules held here:
     - transform and opacity only (no layout animation);
     - no permanent will-change;
     - reduced motion removes every animation/transition and leaves the
       final state visible (a functional mode, not a shorter animation).
   ===================================================================== */

:root {
  /* durations (ms) */
  --kbm-standard: 260ms;      /* standard entrance */
  --kbm-spring: 360ms;        /* soft spring entrance */
  --kbm-celebration: 700ms;   /* celebrations (energetic moments) */
  --kbm-count: 520ms;         /* score count-up (400-600ms band) */
  --kbm-stagger: 110ms;       /* related-element stagger */
  --kbm-idle: 2800ms;         /* gentle idle loop */
  /* easings */
  --kbm-ease-out: cubic-bezier(0.22, 0.9, 0.32, 1);
  --kbm-ease-spring: cubic-bezier(0.34, 1.42, 0.64, 1);
  --kbm-ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --kbm-ease-pop: cubic-bezier(0.2, 1.5, 0.42, 1);
}

/* ---------- entrance / celebration utilities ----------
   Every utility uses `both` so the pre-animation frame is the hidden pose;
   the end frame is always the element's natural state, so removing the
   class later changes nothing. Set --kbm-delay for staggering. */

.kbm-rise {
  animation: kbm-rise var(--kbm-dur, var(--kbm-standard)) var(--kbm-ease, var(--kbm-ease-out)) var(--kbm-delay, 0ms) both;
}
.kbm-fade {
  animation: kbm-fade var(--kbm-dur, var(--kbm-standard)) var(--kbm-ease-soft) var(--kbm-delay, 0ms) both;
}
.kbm-pop {
  animation: kbm-pop var(--kbm-dur, var(--kbm-spring)) var(--kbm-ease, var(--kbm-ease-spring)) var(--kbm-delay, 0ms) both;
}
.kbm-bar-grow {
  transform-origin: 50% 100%;
  animation: kbm-bar-grow var(--kbm-dur, var(--kbm-spring)) var(--kbm-ease-out) var(--kbm-delay, 0ms) both;
}
.kbm-tick-pop {
  animation: kbm-tick-pop var(--kbm-dur, var(--kbm-spring)) var(--kbm-ease-pop) var(--kbm-delay, 0ms) both;
}
.kbm-mark-pop {
  animation: kbm-mark-pop var(--kbm-dur, var(--kbm-standard)) var(--kbm-ease-pop) var(--kbm-delay, 0ms) both;
}
/* gentle idle loop for the approved bomb character (never text/controls) */
.kbm-alive {
  animation: kbm-alive var(--kbm-idle) var(--kbm-ease-soft) infinite;
  transform-origin: 50% 78%;
}

@keyframes kbm-rise {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes kbm-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes kbm-pop {
  0% { opacity: 0; transform: scale(0.86); }
  60% { opacity: 1; transform: scale(1.035); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes kbm-bar-grow {
  from { transform: scaleY(0.02); }
  72% { transform: scaleY(1.04); }
  to { transform: scaleY(1); }
}
@keyframes kbm-tick-pop {
  0% { opacity: 0; transform: scale(0.4); }
  70% { opacity: 1; transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes kbm-mark-pop {
  from { opacity: 0; transform: scale(0.5); }
  70% { opacity: 1; transform: scale(1.08); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes kbm-alive {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-5px) scale(1.018); }
}

/* ---------- reduced motion: functional, not decorative ----------
   Every entrance ends in the natural state, so removing the animation
   simply presents the final state immediately. Count-up is handled in
   JS (final value written at once). */
@media (prefers-reduced-motion: reduce) {
  .kbm-rise, .kbm-fade, .kbm-pop,
  .kbm-bar-grow, .kbm-tick-pop, .kbm-mark-pop, .kbm-alive {
    animation: none !important;
  }
}
