@keyframes pulse-dot {
  0%, 100% { opacity: 1; transform: scale(1); box-shadow: 0 0 6px var(--green); }
  50%       { opacity: 0.5; transform: scale(0.7); box-shadow: 0 0 0px var(--green); }
}

@keyframes bounce-y {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(6px); }
}

@keyframes tab-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.badge-dot   { animation: pulse-dot 2.4s ease-in-out infinite; }
.scroll-arrow { animation: bounce-y 2.2s ease-in-out infinite; }

/* ── Scroll reveal ──
   Por defecto el contenido está VISIBLE: si el JS no corre, igual se ve.
   El estado oculto/animado solo se activa cuando interactions.js marca
   <html class="js-anim">, garantizando que la página nunca quede en blanco. */
.reveal { opacity: 1; }

.js-anim .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

.js-anim .reveal.is-visible { opacity: 1; transform: translateY(0); }

.pricing-grid      .reveal:nth-child(2) { transition-delay: 0.07s; }
.pricing-grid      .reveal:nth-child(3) { transition-delay: 0.14s; }
.pricing-grid      .reveal:nth-child(4) { transition-delay: 0.21s; }

/* ── Respeta la preferencia del sistema de reducir animaciones ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}
