/* animations.css – keyframes. All user-triggered motion ≤ 400 ms; idle motion only on Koffi (+ the hub sky,
   design round), always finite. Reduced motion: see base.css (system setting + app setting).
   JS effects: core/fx.js (named effects) and core/motion.js (Koffi animator, route direction, choreography).
   Choreography + micro-interactions of the design round: css/design.css. */

/* Screen transitions (router adds .screen-enter to the new screen; core/motion.js sets <html data-nav>):
   deeper (hub → list → game) slides in from the right, back slides in from the left, lateral rises softly.
   Spring with ≈ 5 % overshoot, ≤ 320 ms, input is never blocked. */
@keyframes screen-in {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
@keyframes screen-in-forward {
  0%   { opacity: 0; transform: translateX(42px) scale(.985); }
  45%  { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@keyframes screen-in-back {
  0%   { opacity: 0; transform: translateX(-42px) scale(.985); }
  45%  { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
.screen-enter { animation: screen-in 260ms var(--ease-out) both; }
:root[data-nav="forward"] .screen-enter { animation: screen-in-forward 320ms cubic-bezier(.3, 1.25, .5, 1) both; }
:root[data-nav="back"] .screen-enter { animation: screen-in-back 300ms cubic-bezier(.3, 1.2, .5, 1) both; }

@keyframes pop-in {
  0%   { opacity: 0; transform: scale(.4); }
  60%  { opacity: 1; transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1); }
}
.pop-in { animation: pop-in 300ms var(--spring) both; }

@keyframes sticker-in {
  0%   { opacity: 0; transform: translateY(18px) rotate(-6deg) scale(.9); }
  100% { opacity: 1; transform: rotate(var(--tile-rot, 0deg)); }
}

@keyframes wiggle {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px) rotate(-1.5deg); }
  40% { transform: translateX(6px) rotate(1.5deg); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(3px); }
}
.wiggle { animation: wiggle 360ms ease-in-out; }

@keyframes hint-glow {
  0%, 100% { box-shadow: inset 0 -4px 0 color-mix(in srgb, var(--ink) 8%, transparent), 0 0 0 0 var(--hint); }
  50% { box-shadow: inset 0 -4px 0 color-mix(in srgb, var(--ink) 8%, transparent), 0 0 0 7px var(--hint); background: var(--sun-t); }
}

@keyframes koffi-float {
  0%, 100% { transform: translateY(0) rotate(-1deg); }
  50% { transform: translateY(-6px) rotate(1.5deg); }
}
/* static Koffi floats a little (finite, battery); the animated twin (core/motion.js, .is-live) breathes by itself */
.koffi.is-floating:not(.is-live) { animation: koffi-float 3.6s ease-in-out 8; }

@keyframes koffi-hop {
  0% { transform: translateY(0) scale(1, 1); }
  30% { transform: translateY(0) scale(1.08, .9); }
  60% { transform: translateY(-18px) scale(.95, 1.06); }
  100% { transform: translateY(0) scale(1, 1); }
}
.koffi.is-hopping { animation: koffi-hop 420ms var(--ease-out); }

@keyframes think-bob {
  0%, 100% { transform: translateY(0) rotate(0); }
  25% { transform: translateY(-3px) rotate(-6deg); }
  75% { transform: translateY(-3px) rotate(6deg); }
}

@keyframes thinking-dots {
  0%, 80%, 100% { opacity: .25; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); }
}
.dots { display: inline-flex; gap: 3px; }
.dots i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: thinking-dots 1s infinite; }
.dots i:nth-child(2) { animation-delay: .15s; }
.dots i:nth-child(3) { animation-delay: .3s; }

@keyframes layer-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes dialog-in {
  0% { opacity: 0; transform: translateY(26px) scale(.92); }
  100% { opacity: 1; transform: none; }
}
.layer.is-entering .backdrop { animation: layer-in 200ms ease-out both; }
.layer.is-entering .dialog,
.layer.is-entering .celebrate,
.layer.is-entering .handover { animation: dialog-in 320ms var(--spring) both; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(20px) scale(.9); }
  to { opacity: 1; transform: none; }
}
.toast { animation: toast-in 260ms var(--spring) both; }

@keyframes banner-in {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.6) rotate(-4deg); }
  25% { opacity: 1; transform: translate(-50%, -50%) scale(1.06) rotate(1deg); }
  35% { transform: translate(-50%, -50%) scale(1) rotate(0); }
  80% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -58%) scale(.96); }
}
.turn-banner { animation: banner-in 1100ms var(--ease-out) both; }
.turn-banner.is-flipped { animation-name: banner-in-flipped; }
@keyframes banner-in-flipped {
  0% { opacity: 0; transform: translate(-50%, -50%) rotate(180deg) scale(.6); }
  25% { opacity: 1; transform: translate(-50%, -50%) rotate(180deg) scale(1.06); }
  35% { transform: translate(-50%, -50%) rotate(180deg) scale(1); }
  80% { opacity: 1; transform: translate(-50%, -50%) rotate(180deg) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -42%) rotate(180deg) scale(.96); }
}

@keyframes star-pop {
  0% { opacity: 0; transform: scale(0) rotate(-40deg); }
  70% { opacity: 1; transform: scale(1.25) rotate(8deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
.celebrate-stars svg { animation: star-pop 420ms var(--spring) both; }
.celebrate-stars svg:nth-child(2) { animation-delay: 120ms; }
.celebrate-stars svg:nth-child(3) { animation-delay: 240ms; }

/* staggered sticker entrance for the hub tiles (the one orchestrated moment) */
.hub-tiles .tile { animation: sticker-in 420ms var(--spring) backwards; }
.hub-tiles .tile:nth-child(2) { animation-delay: 70ms; }
.hub-tiles .tile:nth-child(3) { animation-delay: 140ms; }

@keyframes danger-pulse {
  0%, 100% { box-shadow: inset 0 0 0 3px var(--warn); }
  50% { box-shadow: inset 0 0 0 6px var(--warn), 0 0 0 4px color-mix(in srgb, var(--warn) 30%, transparent); }
}
@keyframes hint-strong {
  0%, 100% { box-shadow: 0 0 0 4px var(--sun); transform: scale(1); }
  50% { box-shadow: 0 0 0 9px var(--sun); transform: scale(1.04); }
}
@keyframes badge-reveal {
  0% { opacity: 0; transform: rotate(-12deg) scale(.6); }
  100% { opacity: 1; transform: none; }
}
