/* ══════════════════════════════════════════════════════════════════════════
   CARRUSEL / SLIDESHOW — el COMPONENTE, autocontenido
   ══════════════════════════════════════════════════════════════════════════

   Su comportamiento vive en `templates/sections/_partials/carousel-engine.html`
   (`window.czCarousel`) y su vestido aquí. Los dos juntos son el componente, y
   se declaran juntos: quien lo usa carga esta hoja e incluye aquel partial.

   ── POR QUÉ EXISTE ESTA HOJA (2026-09-07) ─────────────────────────────────

   Estas reglas vivían en `site.css`, que carga **sólo el sitio público**. El
   panel carga `design-system.css` + `cms.css`, y **el core no tiene ninguna
   hoja en común entre sus dos caras** (medido). Así que al reusar el motor en
   el visor de comprobantes del panel, el comportamiento llegaba y el efecto no:
   se veía pasar la imagen sin transición, y Adán lo notó a la primera.

   Se movieron aquí y NO al design system: meter el sistema de diseño entero en
   el sitio público cambiaría cómo se ve el sitio de un cliente para arreglar un
   carrusel. Una hoja por componente es la unidad correcta — es lo que Adán
   pidió con estas palabras: *«dejar lo del slider como componente, autocontenido
   y reutilizable, se puede usar en front o en backend»*.

   ⚠️ Las reglas movidas son **las mismas byte a byte**: si el sitio público
   cambia de aspecto, es que algo se perdió por el camino.

   ── LOS DOS EFECTOS ───────────────────────────────────────────────────────

   `fade`      — funde por opacidad. Discreto; para secciones de contenido.
   `archive-x` — el que sale **se escala al 60 % desvaneciéndose** y el que entra
                 **desliza desde la izquierda**. Es el de las galerías nativas
                 (WhatsApp, Fotos): da profundidad en vez de un fundido plano, y
                 es el que un visor de imágenes quiere por defecto.
   ══════════════════════════════════════════════════════════════════════════ */

.cz-slide { position:absolute; top:0; left:0; right:0; bottom:0; opacity:0; pointer-events:none; overflow:hidden; }
.cz-slide.is-on { pointer-events:auto; }
.cz-fade { transition:opacity .9s ease; }
.cz-fade.is-on { opacity:1; z-index:10; }
/* archive-x: al avanzar, la vieja se encoge y la nueva entra deslizando; al retroceder, inverso. */
/* 🔑 EL MOVIMIENTO de `archive-x` —su duracion, sus cuatro direcciones y sus
   cuatro keyframes— VIVE EN `assets/css/motion-ax.css`, porque lo consumen DOS
   piezas: este carrusel y el visor del motor de rejilla.
   🗣️ Lo dicto Adan: *«una cosa es el dialog de apertura del grid y otra el
   efecto carousel; el carousel tambien mueve los testimonials»*. Mientras vivio
   aqui dentro, el visor del album tenia que elegir entre declarar esta hoja
   ENTERA —el vestido de otra pieza— o quedarse sin efecto; y se quedo sin
   efecto, medido en produccion (`animationName: none` en las dos imagenes).
   ⚠️ Lo que NO se fue de aqui son los velos de abajo: oscurecer el fondo
   durante el paso es diseño de ESTA pieza, no movimiento.
   🚨 Quien encole `carousel.css` tiene que encolar tambien `motion-ax.css`: sin
   ella las animaciones apuntan a keyframes ausentes y **no pasa nada, sin un
   solo error**. Lo vigila `MotionVocabularyIsEnqueuedTest`. */
.cz-ax.is-on     { opacity:1; z-index:2; }
/* Las cuatro direcciones de ESTA pieza: el movimiento sale de `motion-ax.css`
   (los `@keyframes`), y el apilado y la duracion son de su diseño. */
.cz-ax { --cz-ax-dur: .7s; }
.cz-ax.navOutNext { z-index:1;    opacity:1; animation:czScaleHalfDownX  var(--cz-ax-dur,.7s) forwards cubic-bezier(.7,0,.3,1); }
.cz-ax.navInNext  { z-index:1001; opacity:1; animation:czSlideInFromLeftX var(--cz-ax-dur,.7s) forwards cubic-bezier(.7,0,.3,1); }
.cz-ax.navOutPrev { z-index:1001; opacity:1; animation:czSlideOutToLeftX  var(--cz-ax-dur,.7s) forwards cubic-bezier(.7,0,.3,1); }
.cz-ax.navInPrev  { z-index:1;             animation:czScaleHalfUpX     var(--cz-ax-dur,.7s) forwards cubic-bezier(.7,0,.3,1); }
.cz-ax::before, .cz-ax::after { content:''; position:absolute; inset:0; pointer-events:none; background:rgba(0,0,0,.6); transition:opacity var(--cz-ax-dur,.7s) cubic-bezier(.7,0,.3,1); z-index:5; }
.cz-ax::before { opacity:0; } .cz-ax::after { opacity:1; }
.cz-ax.is-on::after { opacity:0; }
.cz-ax.navOutNext::before { opacity:1; }
.cz-ax.navInNext::after, .cz-ax.navInPrev::after { opacity:0; }
.cz-ax.navInNext::after { transition:none; }
/* Los cuatro keyframes y el respeto a `prefers-reduced-motion` viven en
   `motion-ax.css`, con las reglas que los invocan. */

/* ── NAVEGACIÓN POR MINIATURAS ────────────────────────────────────────────
   La variante que pidió Adán: *«ahora soportaría las miniaturas en lugar de los
   dots»*. Los puntos dicen CUÁNTOS hay y dónde estás; las miniaturas dicen
   además QUÉ hay — y cuando los slides son fotos de justificantes, eso es la
   diferencia entre contar y encontrar.

   No sustituyen a los dots: conviven. Una galería de tres fotos se lee mejor con
   puntos, y una de veinte comprobantes sólo se navega con miniaturas. */
.cz-thumbs {
  display: flex;
  gap: var(--space-2, 8px);
  padding: var(--space-3, 12px);
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
}

.cz-thumb {
  flex: 0 0 auto;
  width: 68px;
  height: 52px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-sm, 6px);
  overflow: hidden;
  cursor: pointer;
  background: none;
  opacity: .55;
  scroll-snap-align: center;
  /* 🔴 **`box-shadow` ESTABA FUERA DE LA LISTA, y por eso «se perdió la
     transición»** — medido el 2026-10-10 contando `transitionend` al pasar de
     una miniatura a otra: salían 10 (`border-*-color` ×4 y `opacity`, en la que
     sale y en la que entra) y **ninguno del halo**. El activo se marca con
     CUATRO señales (opacidad, borde, halo y la barra de abajo) y sólo dos
     transicionaban: las otras dos aparecían de golpe, y el conjunto se lee
     como «aparece y desaparece» aunque dos de las cuatro fundan bien.
     🗣️ Es exactamente lo que describió Adán: *«daba la sensación de que el borde
     del activo se deslizaba, ahora sólo aparece y desaparece»*. */
  transition: opacity .18s ease, border-color .18s ease,
              transform .18s ease, box-shadow .18s ease;

  /* La entrada EN CASCADA: cada miniatura llega un poco después que la anterior.
     La referencia la dio Adán (tympanus, «Animated Border Menus»), y el retardo
     lo pone una variable que escribe el consumidor con su índice — así el CSS no
     necesita saber cuántas hay. */
  /* `backwards` y NO `both`: `both` conserva el estado final del keyframe al
     terminar y **pisa** las propiedades de la clase —de ahí que el activo no se
     distinguiera y que hiciera falta una segunda animación, que fue el defecto
     que Adán vio—. Con `backwards` sólo se aplica el estado INICIAL antes de
     arrancar, y al acabar mandan las clases. */
  /* 📐 Las CUATRO medidas de la cascada son variables, y no por gusto: el
     consumidor que abre un visor con morph necesita otras —la cascada tiene que
     empezar CUANDO LLEGA la foto, no cuando nace el elemento— y el mecanismo es
     el mismo. Es el contrato de siempre: el core pone la pieza, quien la usa
     aplica su particularidad. Los valores por defecto son los de una tira que
     aparece con su página; los del visor viven en `morph.css`. */
  animation: czThumbIn var(--cz-thumb-dur, .32s) var(--cz-thumb-ease, cubic-bezier(.2, .7, .3, 1)) backwards;
  animation-delay: calc(var(--cz-rail-in, 0ms) + var(--i, 0) * var(--cz-rail-step, 40ms));
}

.cz-thumb:hover  { opacity: .85; transform: translateY(-2px); }
.cz-thumb:focus-visible { outline: 2px solid var(--color-primary, #4f46e5); outline-offset: 2px; }

/* 🔴 La marca del ACTIVO tiene que verse de un vistazo — Adán: *«no sabes en
   cuál está»*. Un borde de color sobre una tira de fotos oscuras se pierde: se
   le suma OPACIDAD plena contra el `.55` de las demás, un halo que la despega
   del fondo y un punto de anclaje debajo. Tres señales redundantes, que es lo
   que hace que se lea también en una pantalla al sol y para quien no distingue
   ese color. */
/* ⚠️ **Este bloque decía «SIN `transform`: la animación de entrada lleva
   `both`»** — y **ya no lo lleva**: `8505e1bd` la pasó a `backwards`
   precisamente para que las clases ganasen al terminar. El motivo por el que se
   quitó el movimiento dejó de existir ese día y el comentario se quedó
   justificándolo, que es como una decisión de circunstancia sobrevive a su
   circunstancia.

   ⬜ **Y AUN ASÍ el `transform` NO vuelve aquí, a propósito.** Lo prohíbe
   `MediaViewerTest::test_selecting_a_thumbnail_does_not_replay_its_entrance`, y
   ese guard protege un defecto que Adán SUFRIÓ —*«cuando cambias de imagen la
   miniatura se coloca al pie y su posición se queda vacía»*—. Su premisa
   cambió, pero retirar un guard exige comprobar en navegador que el defecto no
   reaparece, y eso no cabía en esta tanda. **El movimiento se recupera por otra
   vía**: la barra de abajo, que ahora existe siempre y CRECE desde el centro.
   **DISPARADOR:** la próxima tanda que toque el carrusel. */
.cz-thumb.is-on {
  opacity: 1;
  border-color: var(--color-primary, #4f46e5);
  box-shadow: 0 0 0 2px rgba(79, 70, 229, .35), 0 4px 12px rgba(0, 0, 0, .45);
}

/* 🔴 **La barra de abajo EXISTE SIEMPRE y se escala, en vez de nacer con la
   clase.** Antes vivía en `.is-on::after`, así que el pseudo-elemento **se creaba
   y se destruía** con el estado: un nodo que no existía no podía transicionar, y
   aparecía de golpe. Ahora está siempre, invisible (`scaleX(0)`), y al activarse
   **crece desde el centro** — que es lo más cerca que está esta tira de lo que
   Adán recuerda como «se deslizaba», sin montar un marcador aparte. */
.cz-thumb::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 16px;
  height: 2px;
  border-radius: 2px;
  transform: translateX(-50%) scaleX(0);
  transform-origin: center;
  background: var(--color-primary, #4f46e5);
  transition: transform .18s ease;
}

.cz-thumb.is-on::after {
  transform: translateX(-50%) scaleX(1);
}

/* El `::after` necesita un contenedor posicionado, y el botón no lo era. */
.cz-thumb { position: relative; }

.cz-thumb.is-on:hover { transform: none; }   /* ni al pasar por encima: ver arriba */

.cz-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

@keyframes czThumbIn {
  from { opacity: 0; transform: translateY(var(--cz-thumb-rise, 10px)) scale(var(--cz-thumb-from, .94)); }
}

/* 🔴 AQUÍ HABÍA UN `animation-name` DISTINTO PARA LA ACTIVA, y era un defecto
   que se veía: al seleccionar una miniatura le CAMBIABA el `animation-name`, y
   eso hace que el navegador **re-ejecute la animación de entrada** — la
   miniatura bajaba 10 px y volvía, dejando su hueco vacío un instante. Adán lo
   describió exacto: *«cuando cambias de imagen la miniatura se coloca al pie y
   su posición se queda vacía»*.

   La entrada es de la TIRA, no del estado: una sola animación para todas, y el
   activo se marca sólo con propiedades que no compiten con ella. */

@media (prefers-reduced-motion: reduce) {
  .cz-thumb { animation: none; opacity: .55; }
  .cz-thumb.is-on { opacity: 1; }
  .cz-thumb:hover { transform: none; }
}
