/* ═══ MOTION — css/motion.css (Prompt 24) ═══
   Una sola capa de movimiento para Terminal y Desk. Se engancha a `.card` y `.tier-box`
   (el chasis del Prompt 23), y en Desk también a `.mc` (tarjetas KPI), no a cada módulo. Cargada tras primitives.css en las dos apps
   (ni Terminal ni Desk cargan css/components.css: ese es el design system de hub/landing).

   CÓMO FUNCIONA
   · La entrada de panel NO deja nada oculto por defecto. El estado inicial (.cbm-pre) lo
     pone js/83-motion.js sobre el elemento concreto que va a animar, y lo retira él mismo
     (al entrar en viewport, al cambiar de panel, o por el failsafe). Si el script no carga,
     está desactivado (window.CBM_MOTION = false) o hay prefers-reduced-motion, ningún
     elemento pasa por opacity:0.
   · Solo se animan transform y opacity. will-change existe únicamente mientras dura la
     animación (.cbm-entering) y se retira al terminar.
   · Los tokens --ease-out / --duration-* viven en css/tokens.css y están espejados en
     css/terminal.css (Terminal/Desk no cargan tokens.css); los fallbacks de aquí son solo
     red de seguridad.

   LO QUE NO SE ANIMA (es lo que separa un terminal de una landing page)
   · Tablas y listas largas: aparecen de golpe. Una tabla dentro de una .card llega con su
     panel; sus filas nunca se escalonan.
   · Nada que el usuario tenga que leer mientras se mueve: el texto de lectura no entra con
     retardo, y una cifra tarda un cuarto de segundo en contar, no más.
   · El cambio de panel dentro de un módulo es inmediato, sin transición de página.
   · Nada en bucle salvo .is-live, y solo en indicadores de estado (nunca sobre texto).
   · Repetir la entrada: un módulo ya visitado no vuelve a animar.
   · Las `.mc` solo se animan en Desk; en Terminal (resumen de Portfolio, etc.) aparecen de golpe.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 1. ENTRADA DE PANEL ─────────────────────────────────────────────────────────
   Inclinación ligera: 3°, no 15°. El retardo escalonado (30 ms por panel, tope 240 ms) lo
   calcula el JS una vez por lote y lo deja en --cbm-d; aquí solo se consume. */
.card.cbm-pre,
.tier-box.cbm-pre,
.mc.cbm-pre {            /* .mc solo llega a armarse en Desk (js/83-motion.js PANEL_SEL) */
  opacity: 0;
  transform: perspective(900px) rotateX(3deg) translateY(10px);
}
.cbm-entering {
  animation: cbm-panel-in var(--duration-slow, 0.4s) var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1)) var(--cbm-d, 0ms) backwards;
  will-change: opacity, transform;
}
@keyframes cbm-panel-in {
  from { opacity: 0; transform: perspective(900px) rotateX(3deg) translateY(10px); }
  to   { opacity: 1; transform: perspective(900px) rotateX(0deg) translateY(0); }
}

/* ── 2. BARRAS QUE CRECEN ────────────────────────────────────────────────────────
   Crecen desde cero con scaleX (nunca width/height). Solo dentro de un panel que acaba de
   entrar: el JS pone data-cbm-enter en el pane activo durante la ventana de entrada y lo
   retira después, así una re-renderización posterior no vuelve a animar las barras.
   .pbar-fill y .curr-fill son los rellenos canónicos del terminal; .bar-grow es para el
   resto (la clase va en el elemento que ya lleva el ancho, p. ej. style="width:62%"). */
.tab-pane[data-cbm-enter] .bar-grow,
.tab-pane[data-cbm-enter] .pbar-fill,
.tab-pane[data-cbm-enter] .curr-fill {
  transform-origin: left center;
  animation: cbm-bar-grow var(--duration-slow, 0.4s) var(--ease-out, cubic-bezier(0.23, 1, 0.32, 1)) 120ms backwards;
}
@keyframes cbm-bar-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ── 3. LATIDO DE ESTADO ACTIVO ──────────────────────────────────────────────────
   Pulsación de opacidad muy contenida (0.55 → 1, 2 s) para indicadores de estado activo
   (punto «live», «conectado»). Nunca sobre texto que haya que leer. Con reduced-motion
   la regla de abajo la deja en su último fotograma: opacidad 1. */
.is-live {
  animation: cbm-live 2s ease-in-out infinite;
}
@keyframes cbm-live {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* ── 4. CIFRAS QUE CUENTAN ───────────────────────────────────────────────────────
   Dígitos de ancho fijo para que el número no baile mientras cuenta. El JS además fija un
   min-width provisional con el ancho del valor final. */
[data-count] {
  font-variant-numeric: tabular-nums;
}

/* ── IMPRESIÓN / EXPORTACIÓN ─────────────────────────────────────────────────────
   Un panel por debajo del pliegue puede seguir en su estado inicial (aún no ha entrado en
   viewport): al imprimir o exportar a PDF todo debe salir visible y quieto. */
@media print {
  .cbm-pre { opacity: 1 !important; transform: none !important; }
  .cbm-entering, .bar-grow, .pbar-fill, .curr-fill, .is-live { animation: none !important; }
}

/* ── REGLA ÚNICA DE ACCESIBILIDAD (prefers-reduced-motion) ───────────────────────
   Sustituye a las reglas parciales que había dispersas en terminal.css, glass-system.css
   y redesign-mobile.css. css/tokens.css conserva la suya porque hub/landing/auth/admin no
   cargan este fichero. Queda al final para que gane en la cascada.
   Doble cinturón: aunque el JS hubiera armado un panel antes de que el usuario activara
   «reducir movimiento», .cbm-pre no puede dejarlo invisible. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .cbm-pre { opacity: 1 !important; transform: none !important; }
  /* Excepción deliberada del owner (ticket 102): la cinta de cotizaciones se desplaza
     siempre, aunque el sistema pida reducir movimiento. Es la única animación exenta.
     .ticker-inner (0,1,0) supera a * (0,0,0) pese a que ambos llevan !important. */
  .ticker-inner {
    animation-duration: 75s !important;
    animation-iteration-count: infinite !important;
  }
}
/* ═══ /MOTION ═══ */
