/* ============================================================
   animations.css — keyframes only
   ============================================================ */

/* Nixie tubes flicker — irregular, organic rhythm like real gas discharge */
@keyframes nixie-flicker {
  0%, 82%, 100% {
    opacity: 1;
    box-shadow:
      0 0 12px var(--nixie-glow),
      inset 0 0 6px rgba(255, 255, 255, 0.4);
  }
  84% {
    opacity: 0.6;
    box-shadow:
      0 0 4px var(--nixie-glow),
      inset 0 0 3px rgba(255, 255, 255, 0.15);
  }
  86% { opacity: 1; }
  88% { opacity: 0.75; }
  90% { opacity: 1; }
  93% { opacity: 0.85; }
  95% { opacity: 1; }
}

/* Vacuum tube warm glow — subtle amber breathing on the selected cell,
   like a real tube filament flickering with current */
@keyframes tube-warm {
  0%, 100% {
    box-shadow:
      0 0 15px var(--tube-glow),
      0 0 30px rgba(243, 207, 135, 0.25),
      inset 0 0 10px rgba(243, 207, 135, 0.15),
      inset 0 1px 0 rgba(255, 255, 255, 0.4);
  }
  50% {
    box-shadow:
      0 0 20px var(--tube-glow-strong),
      0 0 40px rgba(243, 207, 135, 0.35),
      inset 0 0 14px rgba(243, 207, 135, 0.22),
      inset 0 1px 0 rgba(255, 255, 255, 0.5);
  }
}

/* Steam plumes rise from the board frame edges, fade and drift */
@keyframes steam-rise {
  0% {
    transform: translateY(0) scale(0.8);
    opacity: 0;
  }
  10% {
    opacity: 0.3;
  }
  50% {
    transform: translateY(-60px) translateX(-12px) scale(1.1);
    opacity: 0.18;
  }
  100% {
    transform: translateY(-140px) translateX(16px) scale(1.3);
    opacity: 0;
  }
}

/* Gauge value jitter — mechanical readout trembles under pressure */
@keyframes gauge-jitter {
  0%  { transform: translate(0, 0); }
  50% { transform: translate(0.3px, -0.3px); }
}

/* The whole machine gently hums like a pressurized engine */
@keyframes machine-hum {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(0.7px); }
}

@keyframes noise-drift {
  0% { background-position: 0 0; }
  50% { background-position: 12px -8px; }
  100% { background-position: 0 0; }
}

@keyframes vignette-drift {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.9; transform: scale(1.02); }
}

@keyframes fog-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.32; }
  50% { transform: translate3d(10px, -8px, 0) scale(1.06); opacity: 0.45; }
}

/* Gauge needle swings in a constrained arc */
@keyframes gauge-needle {
  0%, 100% { transform: translateX(-50%) rotate(-10deg); }
  50%      { transform: translateX(-50%) rotate(10deg); }
}

/* Brass keys subtly settle under mechanical weight */
@keyframes key-idle {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(0.4px); }
}

/* Tiny valve chatter when hovering action controls */
@keyframes valve-chatter {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  25%      { transform: translateY(-1px) rotate(-0.5deg); }
  75%      { transform: translateY(-1px) rotate(0.5deg); }
}

/* Rivet shimmer — light glint sweeps across the screw head */
@keyframes rivet-shimmer {
  0%, 85%, 100% { left: -8px; opacity: 0; }
  90%           { opacity: 0.7; }
  95%           { left: 12px; opacity: 0; }
}

/* Cell shake on a wrong placement */
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-3px); }
  50% { transform: translateX(3px); }
  75% { transform: translateX(-2px); }
}

/* Survival countdown — slow red breathing when time is running out */
@keyframes pulse-warning {
  0%, 100% {
    color: var(--danger);
    text-shadow: 0 0 6px var(--danger-glow), 0 0 12px var(--danger-glow);
  }
  50% {
    color: var(--warning-amber);
    text-shadow: 0 0 10px var(--danger-glow), 0 0 20px var(--danger-glow);
  }
}

/* Survival button gentle red pulse to draw the eye to it */
@keyframes survival-idle {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 0 4px var(--danger-glow); }
  50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), 0 0 10px var(--danger-glow); }
}

/* Time-bonus flash on chrono when +5s ticks in */
@keyframes time-bonus-flash {
  0%   { color: var(--success); text-shadow: 0 0 12px rgba(107, 196, 109, 0.9); }
  100% { color: var(--nixie);   text-shadow: 0 0 6px var(--nixie-glow); }
}

/* Time-penalty flash on chrono when -15s hits */
@keyframes time-penalty-flash {
  0%   { color: var(--danger); text-shadow: 0 0 14px var(--danger-glow); }
  100% { color: var(--nixie);  text-shadow: 0 0 6px var(--nixie-glow); }
}

/* Hint reveal — brief gold pulse on the cell that the engine fills in */
@keyframes hint-pulse {
  0% {
    background-color: rgba(255, 210, 90, 0.85);
    box-shadow: 0 0 20px rgba(255, 200, 80, 0.95), inset 0 0 12px rgba(255, 230, 140, 0.9);
  }
  100% {
    background-color: transparent;
    box-shadow: none;
  }
}

/* Help modal — overlay fade and panel rise */
@keyframes modal-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

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

@keyframes modal-rise {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}

@keyframes modal-sink {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(12px) scale(0.98); }
}

/* Rank-up banner — slide down, pause, slide back up */
@keyframes rank-up-slide {
  0%   { transform: translateX(-50%) translateY(-100%); opacity: 0; }
  12%  { transform: translateX(-50%) translateY(0);     opacity: 1; }
  75%  { transform: translateX(-50%) translateY(0);     opacity: 1; }
  100% { transform: translateX(-50%) translateY(-100%); opacity: 0; }
}

/* Rank name glow pulse inside the banner */
@keyframes rank-up-glow {
  0%, 100% { text-shadow: 0 0 14px var(--nixie-glow); }
  50%      { text-shadow: 0 0 28px var(--nixie-glow), 0 0 6px #fff; }
}

/* Victory certificate — scales up from a rolled-up scroll feel */
@keyframes certificate-reveal {
  0%   { opacity: 0; transform: scale(0.7) rotateX(15deg); }
  50%  { opacity: 1; transform: scale(1.03) rotateX(-2deg); }
  100% { opacity: 1; transform: scale(1) rotateX(0); }
}

/* Wax seal gear — spins in as if being stamped */
@keyframes seal-spin {
  0%   { transform: rotate(-180deg) scale(0.4); opacity: 0; }
  60%  { transform: rotate(15deg) scale(1.1); opacity: 1; }
  100% { transform: rotate(0deg) scale(1); opacity: 1; }
}

/* XP earned — amber pulse to draw the eye */
@keyframes xp-pulse {
  0%, 100% {
    text-shadow: 0 0 14px var(--tube-glow-strong), 0 0 30px var(--tube-glow);
    transform: scale(1);
  }
  50% {
    text-shadow: 0 0 24px var(--tube-glow-strong), 0 0 50px var(--tube-glow), 0 0 8px #fff;
    transform: scale(1.08);
  }
}

/* Game over — sharp shake like a boiler explosion */
@keyframes gameover-shake {
  0%   { transform: translateY(14px) scale(0.97); opacity: 0; }
  20%  { transform: translateX(-6px) scale(1); opacity: 1; }
  40%  { transform: translateX(5px); }
  60%  { transform: translateX(-3px); }
  80%  { transform: translateX(2px); }
  100% { transform: translateX(0); }
}
