/* motion.css — keyframes y reglas de animación compartidas (FUENTE ÚNICA).

   Filosofía emil-design-eng: el motion debería ser invisible. Si el
   usuario lo nota, es porque algo está mal. Duraciones cortas (80–
   180 ms), easing único (cubic-bezier 0.4,0,0.2,1) y respeto absoluto
   de prefers-reduced-motion.

   Carga después de tokens.css / base.css. */

/* ── reduced-motion ────────────────────────────────────────────────
   Override universal: si el OS pide reduced-motion, todo dura 1ms
   (transición casi instantánea pero sin layout flash). Cualquier
   keyframe específico se cancela. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── keyframes utilitarios ─────────────────────────────────────────
   Solo los que están en uso compartido. Mantener lista chica: el catálogo
   crece más rápido de lo que se limpia. */

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

@keyframes fade-up {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes slide-down {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes pulse-soft {
    0%, 100% { opacity: 0.85; }
    50%      { opacity: 1; }
}

@keyframes shimmer {
    /* skeleton/loading: gradiente cruzando el ancho */
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

/* ── clases de aplicación rápida ───────────────────────────────────
   Usar inline en el HTML cuando una página específica necesita el
   motion, en vez de duplicar la regla en N components.css. */

.motion-fade-in   { animation: fade-in   var(--dur-slow, 180ms) var(--ease-out, ease) both; }
.motion-fade-up   { animation: fade-up   var(--dur-slow, 180ms) var(--ease-out, ease) both; }
.motion-slide-down{ animation: slide-down var(--dur-slow, 180ms) var(--ease-out, ease) both; }
.motion-pulse     { animation: pulse-soft 2.2s var(--ease) infinite; }

/* ── stagger entrance ─────────────────────────────────────────────────
   Para grids/listas: aplicar `.motion-stagger` al CONTENEDOR y los
   children animan con delay calculado por --stagger-step × --i.

   Uso template:
     <div class="kpi-grid motion-stagger">
       <div class="kpi-card" style="--i: 0">…</div>
       <div class="kpi-card" style="--i: 1">…</div>
       <div class="kpi-card" style="--i: 2">…</div>
     </div>

   Si --i no está set, default 0 → todos arrancan juntos (no rompe). */
.motion-stagger > * {
    animation: fade-up var(--dur-slow, 180ms) var(--ease-out, ease) both;
    animation-delay: calc(var(--stagger-step, 50ms) * var(--i, 0));
}
/* Versión con grid auto-stagger usando nth-child (no requiere --i en el
   template — útil para listas dinámicas como tabs, lista de
   compromisos, etc.). Hasta 6 elementos visibles iniciales. */
.motion-stagger-auto > *:nth-child(1) { animation-delay: 0ms; }
.motion-stagger-auto > *:nth-child(2) { animation-delay: 50ms; }
.motion-stagger-auto > *:nth-child(3) { animation-delay: 100ms; }
.motion-stagger-auto > *:nth-child(4) { animation-delay: 150ms; }
.motion-stagger-auto > *:nth-child(5) { animation-delay: 200ms; }
.motion-stagger-auto > *:nth-child(6) { animation-delay: 250ms; }
.motion-stagger-auto > * {
    animation: fade-up var(--dur-slow, 180ms) var(--ease-out, ease) both;
}

/* skeleton placeholder: usar con `.skeleton` sobre un div con dimensiones
   propias. background-size 200% para que shimmer cruce el ancho real. */
.skeleton {
    background: linear-gradient(
        90deg,
        var(--bg-soft) 0%,
        var(--border) 50%,
        var(--bg-soft) 100%
    );
    background-size: 200% 100%;
    animation: shimmer 1.6s linear infinite;
    border-radius: var(--radius-chip);
    color: transparent !important;
    user-select: none;
    pointer-events: none;
}

/* ── B.3.7 smooth scroll en anchors internos ─────────────────────────── */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ── live-dot pulse (B.4 polish-plan) ────────────────────────────────── */
@keyframes live-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.45; transform: scale(0.9); }
}

/* ── K.1 #6 @view-transition cross-fade entre páginas MPA ──────────────
   Safari 18.2+, Chrome 111+. Progressive enhancement: navegadores sin
   soporte no degradan (es como una mejora visual). 200ms fade. */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 220ms;
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) { animation-duration: 1ms; }
}

/* ── @starting-style — enter animations CSS-native (K.2 context7) ──────
   Aplicada a items entrando vía Alpine x-show o htmx swap. */
@starting-style {
    .motion-enter { opacity: 0; transform: translateY(4px); }
}
.motion-enter {
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
    opacity: 1; transform: translateY(0);
}
