/* ════════════════════════════════════════════════════════════
   MOTION — sistema de animación premium, compartido por las
   cuatro páginas (Dashboard, login, /analizar, /analizar-skool).

   Solo transform, opacity y filter ligero. Toda animación explica
   (jerarquía, estado, logro) o da feedback; nunca compite con el
   dato. prefers-reduced-motion se respeta vía el interruptor global
   de css/componentes.css (`*{transition:none!important;
   animation:none!important}`) — no hace falta repetirlo aquí regla
   a regla: el JS de motion.js sigue fijando los valores finales,
   solo deja de interpolarlos.

   Inventario y criterios: docs/sistema-de-diseno.md § Motion.
   ════════════════════════════════════════════════════════════ */

:root{
  /* duraciones */
  --dur-1: 120ms;   /* feedback inmediato: hover, press, foco */
  --dur-2: 220ms;   /* transición estándar: modal, dropdown, cross-fade */
  --dur-3: 650ms;   /* entradas, dibujado de gráficas, ticker */
  --dur-stagger: 70ms;

  /* easings */
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-in-out: cubic-bezier(.65,0,.35,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);

  /* modal/menú: abrir es invitación (más lento), cerrar se aparta (más rápido) */
  --dur-abrir: var(--dur-2);
  --dur-cerrar: 130ms;
}

/* ---------- pausa de loops ambientales fuera de pestaña ---------- */
html.tab-oculta .dot.ok,
html.tab-oculta [data-halo]::before{
  animation-play-state: paused;
}

/* ---------- aurora: quieta a propósito ----------
   Cualquier animación continua bajo las tarjetas (que llevan backdrop-filter) obliga al
   navegador a volver a difuminar todas las tarjetas en cada fotograma: lag en toda la
   página. Lo ambiental se limita a lo que va por compositor (transform/opacity en
   elementos pequeños). */

/* ---------- entrada escalonada de tarjetas ---------- */
@keyframes mo-entrada{
  from{ opacity: 0; transform: translateY(18px) scale(.985); }
  to  { opacity: 1; transform: none; }
}
.grid > .card,
.an-wrap > .an-card,
.acceso .card{
  animation: mo-entrada var(--dur-3) var(--ease-out) both;
}
.grid > .card:nth-child(2), .an-wrap > .an-card:nth-child(2){ animation-delay: calc(var(--dur-stagger) * 1); }
.grid > .card:nth-child(3), .an-wrap > .an-card:nth-child(3){ animation-delay: calc(var(--dur-stagger) * 2); }
.grid > .card:nth-child(4), .an-wrap > .an-card:nth-child(4){ animation-delay: calc(var(--dur-stagger) * 3); }
.grid > .card:nth-child(5), .an-wrap > .an-card:nth-child(5){ animation-delay: calc(var(--dur-stagger) * 4); }
.grid > .card:nth-child(6), .an-wrap > .an-card:nth-child(6){ animation-delay: calc(var(--dur-stagger) * 5); }
.an-wrap > .an-card:nth-child(7){ animation-delay: calc(var(--dur-stagger) * 6); }
.an-wrap > .an-card:nth-child(8){ animation-delay: calc(var(--dur-stagger) * 7); }
.an-wrap > .an-card:nth-child(9){ animation-delay: calc(var(--dur-stagger) * 8); }

/* ---------- cross-fade del cuerpo al cambiar periodo/cuenta/modo ---------- */
.card > .body{ transition: opacity var(--dur-2) var(--ease-in-out); }
.card > .body.mo-out,
.an-wrap.mo-out{ opacity: 0; }
.an-wrap{ transition: opacity var(--dur-2) var(--ease-in-out); }

/* ---------- feedback de interacción: hover / press / foco ---------- */
.btn, .seg button, .tabs button, .gear, .opcion, .menu button,
.an-sort, .an-graf-abrir, .cal-dia, .kpi, .dona-fila, [data-ajustes]{
  transition:
    transform var(--dur-1) var(--ease-out),
    background-color var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    color var(--dur-1) var(--ease-out);
}
.btn:active, .seg button:active, .tabs button:active, .gear:active,
.opcion:active, .menu button:active, .cal-dia:active{
  transform: scale(.97);
}
.kpi:hover{ transform: translateY(-2px); box-shadow: 0 10px 22px -16px color-mix(in srgb, var(--a) 70%, transparent); }
tbody tr td{ transition: background-color var(--dur-1) var(--ease-out); }
.pill{ transition: filter var(--dur-1) var(--ease-out); }
.pill:hover{ filter: brightness(1.15); }

/* ---------- shimmer con pausa: botones primarios de acción ----------
   El brillo es un pseudo-elemento que se desplaza con transform: va por compositor y no
   repinta el botón ni la tarjeta. Barrido de 2 s y pausa de 4,5 s. */
.btn:not(.mini):not(.peligro){ position: relative; overflow: hidden; }
.btn:not(.mini):not(.peligro)::after{
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0; width: 60%; pointer-events: none;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,.28) 50%, transparent 80%);
  transform: translateX(-170%);
  animation: mo-shimmer-btn 6.5s var(--ease-in-out) infinite;
}
@keyframes mo-shimmer-btn{
  0%    { transform: translateX(-170%); }
  30.8% { transform: translateX(270%); }
  100%  { transform: translateX(270%); }
}

/* ---------- modal: abrir invita (más lento), cerrar se aparta (más rápido) ---------- */
.modal{
  opacity: 0;
  transition: opacity var(--dur-abrir) var(--ease-out);
}
.modal.is-open{ opacity: 1; }
.modal.is-closing{ opacity: 0; transition-duration: var(--dur-cerrar); }
.modal .card{
  transform: scale(.96);
  transition: transform var(--dur-abrir) var(--ease-out);
}
.modal.is-open .card{ transform: scale(1); }
.modal.is-closing .card{ transform: scale(.98); transition-duration: var(--dur-cerrar); }

/* ---------- menú contextual: crece desde el punto de clic ---------- */
.menu{
  transform-origin: top left;
  transform: scale(.97);
  opacity: 0;
  transition: transform var(--dur-abrir) var(--ease-out), opacity var(--dur-abrir) var(--ease-out);
}
.menu.is-open{ transform: scale(1); opacity: 1; }
.menu.is-closing{ transform: scale(.99); opacity: 0; transition-duration: var(--dur-cerrar); }

/* ---------- skeleton: shimmer mientras cargarReal no responde ---------- */
.body.mo-cargando{ position: relative; pointer-events: none; }
.body.mo-cargando > *{ opacity: .45; }
.body.mo-cargando::after{
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--a) 38%, transparent) 50%, transparent 70%);
  background-size: 200% 100%;
  animation: mo-shimmer-skel 1.6s linear infinite;
}
@keyframes mo-shimmer-skel{
  from{ background-position: 140% 0; }
  to  { background-position: -40% 0; }
}

/* ---------- punto de estado «live»: pulso lento, sin urgencia ---------- */
@keyframes mo-pulso-live{
  0%,100%{ transform: scale(1); }
  50%    { transform: scale(1.05); }
}
.dot.ok{ animation: mo-pulso-live 4s var(--ease-in-out) infinite; }

/* ---------- micro-festejo: sincronización o carga de CSV completada ---------- */
@keyframes mo-glow-ok{
  0%  { box-shadow: 0 1px 0 rgba(255,255,255,.045) inset, 0 14px 40px -24px rgba(0,0,0,.9), 0 0 0 0 color-mix(in srgb, var(--ok) 0%, transparent); }
  35% { box-shadow: 0 1px 0 rgba(255,255,255,.045) inset, 0 14px 40px -24px rgba(0,0,0,.9), 0 0 30px 2px color-mix(in srgb, var(--ok) 55%, transparent); }
  100%{ box-shadow: 0 1px 0 rgba(255,255,255,.045) inset, 0 14px 40px -24px rgba(0,0,0,.9), 0 0 0 0 color-mix(in srgb, var(--ok) 0%, transparent); }
}
.mo-sync-ok{ animation: mo-glow-ok .45s var(--ease-out); }

/* variante genérica: para elementos sin sombra propia (casilla de CSV, fila...) */
@keyframes mo-glow{
  0%,100%{ box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 0%, transparent); }
  35%    { box-shadow: 0 0 24px 2px color-mix(in srgb, var(--ok) 55%, transparent); }
}
.mo-glow{ animation: mo-glow .45s var(--ease-out); }

@keyframes mo-check-draw{ from{ stroke-dashoffset: 20; } to{ stroke-dashoffset: 0; } }
.mo-check{ width: 13px; height: 13px; flex: 0 0 auto; color: #7FE6C4; vertical-align: -2px; margin-right: 3px; }
.mo-check path{ stroke-dasharray: 20; stroke-dashoffset: 20; animation: mo-check-draw .4s var(--ease-out) .05s forwards; }

/* ---------- gráficas: trazo y crecimiento al aparecer ---------- */
.an-linea-trazo{ transition: stroke-dashoffset var(--dur-3) var(--ease-out); }
.an-tooltip{ transition: opacity 80ms var(--ease-out); }
.an-barra{ transition: height var(--dur-2) var(--ease-out), y var(--dur-2) var(--ease-out), filter .1s; }
.dona-porcion{ transition: stroke-dasharray var(--dur-3) var(--ease-out), stroke-width .12s ease, filter .12s ease; }

/* ---------- firma Dashboard: la tarjeta con foco o bajo el puntero se enciende ----------
   Sin bucle: un borde que respira infinito repinta la tarjeta (y su backdrop-filter) en
   cada fotograma. Aquí es una transición corta y se queda quieta. */
.grid > .card{ transition: border-color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.grid > .card:hover{ transform: translateY(-2px); box-shadow: 0 1px 0 rgba(255,255,255,.045) inset, 0 22px 48px -26px color-mix(in srgb, var(--a) 55%, rgba(0,0,0,.9)); }
.grid > .card:focus-within{ border-color: color-mix(in srgb, var(--a) 80%, var(--line)); }

/* ---------- firma Analizar / Analizar-Skool: halo de acento que sigue al puntero ----------
   El degradado no se recalcula: es una capa de 480 px centrada en el puntero que se mueve
   con transform (compositor). Mover --mx/--my dentro de un radial-gradient repintaba la
   tarjeta entera en cada movimiento. */
.an-card[data-halo]{ position: relative; overflow: hidden; }
.an-card[data-halo]::before{
  content: "";
  position: absolute; left: 0; top: 0; width: 480px; height: 480px; z-index: 0; pointer-events: none;
  margin: -240px 0 0 -240px; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--a) 22%, transparent), transparent 70%);
  opacity: 0; transition: opacity var(--dur-2) var(--ease-out);
  transform: translate(var(--mx, 50%), var(--my, 0px));
  will-change: transform;
}
.an-card[data-halo]:hover::before{ opacity: 1; }
.an-card[data-halo] > *{ position: relative; z-index: 1; }

/* ---------- firma Login: halo de acento en el campo con foco ---------- */
.acceso input{ transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out); }
.acceso input:focus{ box-shadow: 0 0 0 3px color-mix(in srgb, var(--a) 26%, transparent); }
@keyframes mo-shake{
  0%,100%{ transform: translateX(0); }
  25%    { transform: translateX(-4px); }
  75%    { transform: translateX(4px); }
}
.acceso .error.mo-shake{ animation: mo-shake .3s var(--ease-in-out); }
