/* Shared keyframes + effect utility classes. Interface motion is choppy on purpose (steps(), ~12 fps).
   Durations divide by --speed so ?speed=20 makes tests fast. */

@keyframes pop-in {
  0% { transform: scale(0.6); opacity: 0; }
  60% { transform: scale(1.06); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-6px); }
  50% { transform: translateX(6px); }
  75% { transform: translateX(-3px); }
}

@keyframes wiggle {
  0%, 100% { transform: rotate(0); }
  25% { transform: rotate(-8deg); }
  75% { transform: rotate(8deg); }
}

@keyframes blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}

@keyframes squash {
  0% { transform: scale(1, 1); }
  30% { transform: scale(1.2, 0.75); }
  60% { transform: scale(0.9, 1.1); }
  100% { transform: scale(1, 1); }
}

@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

@keyframes ants {
  to {
    background-position: 12px 0, -12px 100%, 0 -12px, 100% 12px;
  }
}

@keyframes flash {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

.fx-shake { animation: shake calc(330ms / var(--speed)) steps(4) 1; }
.fx-wiggle { animation: wiggle calc(330ms / var(--speed)) steps(4) 2; }
.fx-blink { animation: blink calc(800ms / var(--speed)) steps(1) infinite; }
.fx-bob { animation: bob calc(660ms / var(--speed)) steps(2) infinite; }
.fx-squash { animation: squash calc(330ms / var(--speed)) steps(4) 1; }
.fx-pulse { animation: pulse calc(700ms / var(--speed)) steps(4) infinite; }
.fx-pop { animation: pop-in var(--t-med) steps(4) both; }
.fx-fade-in { animation: fade-in var(--t-med) steps(4) both; }

/* full-screen white flash (reveal) */
.fx-flash {
  position: fixed;
  inset: 0;
  background: var(--paper);
  pointer-events: none;
  z-index: var(--z-top);
  animation: flash calc(400ms / var(--speed)) steps(4) 1 both;
}

/* confetti layer (see ui/confetti.js) */
.confetti {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-toast);
  overflow: hidden;
}

.confetti__bit {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .fx-shake, .fx-wiggle, .fx-bob, .fx-pulse, .fx-squash { animation: none !important; }
  .confetti { display: none; }
  .fx-flash { animation: fade-out var(--t-med) both; }
}

html.reduced-motion :is(.fx-shake, .fx-wiggle, .fx-bob, .fx-pulse, .fx-squash) { animation: none !important; }
html.reduced-motion .confetti { display: none; }
