/*
 * Animaciones locales.
 *
 * Reemplazan a animate.css cargado desde un CDN. Se autohospedan por tres
 * motivos: el panel deja de depender de que cdnjs esté disponible, no se
 * filtra la IP del cliente a un tercero en cada carga, y la CSP puede
 * mantenerse en `default-src 'self'` sin abrir excepciones.
 *
 * Solo se implementan las clases que el panel usa realmente.
 */

.animate__animated {
  animation-duration: 0.5s;
  animation-fill-mode: both;
}

.animate__infinite {
  animation-iteration-count: infinite;
  animation-duration: 2s;
}

/* ── fadeIn ─────────────────────────────────────────────── */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.animate__fadeIn { animation-name: fadeIn; }

/* ── fadeInDown ─────────────────────────────────────────── */
@keyframes fadeInDown {
  from { opacity: 0; transform: translate3d(0, -1.5rem, 0); }
  to { opacity: 1; transform: none; }
}
.animate__fadeInDown { animation-name: fadeInDown; }

/* ── fadeInUp ───────────────────────────────────────────── */
@keyframes fadeInUp {
  from { opacity: 0; transform: translate3d(0, 1.5rem, 0); }
  to { opacity: 1; transform: none; }
}
.animate__fadeInUp { animation-name: fadeInUp; }

/* ── zoomIn ─────────────────────────────────────────────── */
@keyframes zoomIn {
  from { opacity: 0; transform: scale3d(0.94, 0.94, 0.94); }
  50% { opacity: 1; }
  to { transform: none; }
}
.animate__zoomIn { animation-name: zoomIn; }

/* ── pulse ──────────────────────────────────────────────── */
@keyframes pulse {
  from { transform: scale3d(1, 1, 1); }
  50% { transform: scale3d(1.04, 1.04, 1.04); }
  to { transform: scale3d(1, 1, 1); }
}
.animate__pulse { animation-name: pulse; }

/* Respeta la preferencia del sistema de reducir movimiento. */
@media (prefers-reduced-motion: reduce) {
  .animate__animated {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
