/* =========================================================================
   TELETÓN 20-30 · CAPA DE MOVIMIENTO — "Materia en movimiento"
   -------------------------------------------------------------------------
   Los objetos táctiles de la campaña son materia: tienen peso, plano y
   deriva. La tipografía Poppins Black no aparece: sube desde una máscara,
   como un titular que entra en cadena.

   Reglas de la capa (no negociables):
   1. El contenido es legible sin JS y sin movimiento. Esta capa solo suma.
   2. Solo se animan `transform` y `opacity`. Nunca layout ni color de texto.
   3. Un elemento, un movimiento. La deriva vive en el hijo, el plano en el padre.
   4. La decoración se mueve; el texto, los CTA y los datos nunca se desplazan
      debajo de otro elemento.
   5. `prefers-reduced-motion: reduce` apaga la capa completa.
   ========================================================================= */

:root {
  --ease-material: cubic-bezier(.22, 1, .36, 1);
  /* Guía UX/UI v6.2 §4: entradas grandes ≤400ms, componentes ≤300ms,
     escalón 30–50ms con un total ≤300ms (índice máximo 5 × 40ms). */
  --motion-reveal:  var(--motion-scene, 400ms);
  --motion-choreo:  var(--motion-slow, 300ms);
  --stagger-step:   var(--motion-stagger, 40ms);
  --parallax-clamp:  30px;
}

/* =========================================================================
   1. PLANOS DE PROFUNDIDAD
   `--py` lo escribe el scroll; `--mx` / `--my` el puntero. Se componen en
   una sola transformación para no pelear entre sí.
   ========================================================================= */
.js [data-parallax] {
  transform: perspective(1200px) translate3d(var(--mx, 0px), calc(var(--py, 0px) + var(--my, 0px)), 0) rotateY(var(--ry, 0deg));
  will-change: transform;
}

/* La escena del héroe reacciona al puntero solo en dispositivos con cursor. */
.hero__art { touch-action: manipulation; }

/* =========================================================================
   2. DERIVA — los objetos 3D flotan como materia, nunca giran en bucle.
   La deriva vive en la imagen interna para no chocar con el plano del padre.
   ========================================================================= */
@keyframes t30-drift {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%      { transform: translate3d(0, -9px, 0) rotate(2.4deg); }
}

.js .deco > img {
  animation: t30-drift var(--drift-dur, 12s) ease-in-out infinite;
  animation-delay: var(--drift-delay, 0s);
}
.js .deco:nth-of-type(2n) > img  { --drift-dur: 15s; --drift-delay: -4s; }
.js .deco:nth-of-type(3n) > img  { --drift-dur: 10s; --drift-delay: -7s; }
.js .deco:nth-of-type(4n) > img  { --drift-dur: 17s; --drift-delay: -2s; }

/* =========================================================================
   3. TIPOGRAFÍA EN MOVIMIENTO
   El JS parte el titular en líneas reales (medidas, no supuestas) y las
   envuelve en una máscara. El relleno compensa acentos y descendentes: en
   mayúsculas la Á sube y la Q baja fuera de la caja de línea (line-height .94).
   ========================================================================= */
.js .split-line {
  display: block;
  overflow: hidden;
  padding-block: 0.16em;
  margin-block: -0.16em;
}
.js .split-line__inner {
  display: block;
  transform: translate3d(0, 108%, 0);
  transition: transform var(--motion-reveal) var(--ease-material);
  transition-delay: calc(var(--i, 0) * 50ms);
}
.js .is-split-in .split-line__inner { transform: none; }
.js .type-split__word { display: inline-block; }
/* El contenedor debe ser bloque: las máscaras son bloques y anidarlas dentro
   de un span en línea obliga al motor a partir la caja en cajas anónimas,
   lo que rompe el ancho del titular. Nombre propio: `.split` ya es la rejilla
   de dos columnas del sitio y no debe recibir `display: block`. */
.js .type-split { display: block; }

/* =========================================================================
   4. ENTRADAS EN CADENA
   Se conserva `.reveal` de la capa base y se le añaden dirección y escalón.
   ========================================================================= */
.js .reveal,
.js .reveal.is-in { transition-delay: calc(var(--i, 0) * var(--stagger-step)); }

.js .reveal[data-reveal="left"]  { transform: translate3d(-26px, 0, 0); }
.js .reveal[data-reveal="right"] { transform: translate3d(26px, 0, 0); }
.js .reveal[data-reveal="scale"] { transform: scale(0.955); }
.js .reveal[data-reveal="art"]   { transform: translate3d(0, 20px, 0) scale(0.965); }
.js .reveal.is-in[data-reveal]   { transform: none; }

/* =========================================================================
   5. CABECERA — peso al desprenderse del tope + avance de lectura
   ========================================================================= */
.header {
  transition: box-shadow var(--motion-base) var(--ease-standard);
}
.header.is-scrolled { box-shadow: var(--shadow-raised); }

.progress-rail {
  position: absolute; inset-inline: 0; bottom: -1px;
  height: 2px; overflow: hidden; pointer-events: none;
}
.progress-rail__fill {
  display: block; height: 100%; width: 100%;
  transform: scaleX(var(--read, 0));
  transform-origin: 0 50%;
  background: var(--t30-action-donate-bg);
}

/* El corazón institucional late al señalar la marca. Un latido, no un bucle. */
@keyframes t30-heartbeat {
  0%   { transform: scale(1); }
  22%  { transform: scale(1.18); }
  38%  { transform: scale(1); }
  56%  { transform: scale(1.11); }
  100% { transform: scale(1); }
}
.brand__heart { transition: transform var(--motion-base) var(--ease-material); }
.brand:hover .brand__heart,
.brand:focus-visible .brand__heart { animation: t30-heartbeat 600ms var(--ease-standard); }

/* =========================================================================
   6. COREOGRAFÍA DE TARJETA DE EVENTO
   Al señalar, el logotema se adelanta y los objetos regionales se abren
   hacia afuera: la tarjeta gana profundidad en vez de solo levantarse.
   ========================================================================= */
.event-card__lockup,
.event-card__obj {
  transition: transform var(--motion-choreo) var(--ease-material);
}
.card--link:hover .event-card__lockup,
.card--link:focus-within .event-card__lockup { transform: scale(1.045); }

.card--link:hover .event-card__obj--a,
.card--link:focus-within .event-card__obj--a { transform: translate3d(-7px, 5px, 0) rotate(-8deg); }
.card--link:hover .event-card__obj--b,
.card--link:focus-within .event-card__obj--b { transform: translate3d(7px, -5px, 0) rotate(8deg); }

/* `.js .reveal.is-in { transform: none }` tiene más peso que `.card--link:hover`.
   Se restituye el levantamiento con especificidad suficiente. */
.js .card--link.reveal.is-in:hover,
.js .card--link.reveal.is-in:focus-within,
.card--link:focus-within {
  border-color: var(--t30-color-black);
  box-shadow: var(--shadow-raised);
  transform: translateY(-2px);
}

/* El panel de arte respira al señalar la fila del evento.
   Solo el logotema (hijo directo). Los objetos decorativos van en `.deco`. */
.art-panel > img { transition: transform var(--motion-choreo) var(--ease-material); }
.split:hover .art-panel > img,
.split:focus-within .art-panel > img { transform: scale(1.03); }

/* =========================================================================
   7. BANDA CINÉTICA — el lema se mueve con la lectura
   Sin JS queda quieta y legible. Con JS avanza y acelera con el scroll.
   ========================================================================= */
.kinetic {
  position: relative;
  overflow: clip;
  border-block: 1px solid var(--t30-border-default);
  padding-block: clamp(var(--space-6), 3vw, var(--space-10));
  background: var(--t30-bg-canvas);
}
.kinetic__track {
  display: flex; align-items: center;
  width: max-content;
  transform: translate3d(var(--kx, 0px), 0, 0);
  will-change: transform;
}
.kinetic__track > * { margin-inline-end: clamp(var(--space-6), 3vw, var(--space-12)); }
.kinetic__word {
  flex: none;
  font-family: var(--font-display);
  font-weight: var(--weight-black);
  font-size: clamp(2.25rem, 7vw, 5rem);
  line-height: 1;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* El contorno solo se vacía donde el trazo de texto existe; si no, la palabra
   se queda sólida en gris en vez de desaparecer. */
.kinetic__word--outline { color: var(--t30-border-400); }
@supports (-webkit-text-stroke: 1px black) {
  .kinetic__word--outline {
    color: transparent;
    -webkit-text-stroke: 1.5px var(--t30-border-400);
  }
}
.kinetic__heart { flex: none; width: clamp(28px, 3.4vw, 48px); height: auto; display: block; }

/* =========================================================================
   8. MICRO-INTERACCIONES
   ========================================================================= */
.btn { transition: background-color var(--motion-fast) var(--ease-standard),
                   border-color var(--motion-fast) var(--ease-standard),
                   color var(--motion-fast) var(--ease-standard),
                   box-shadow var(--motion-fast) var(--ease-standard),
                   transform var(--motion-fast) var(--ease-standard); }
.btn:active { transform: translateY(1px) scale(0.99); }

/* La flecha del enlace ya se desplaza; se le suma un acento al pulsar. */
.link-arrow:active svg { transform: translateX(5px); }

/* Contador: el número entra al revelarse el bloque (el padre sale de [hidden],
   así que la animación arranca en ese momento, no al cargar la página). */
.countdown__value {
  display: inline-block;
  animation: t30-rise-in var(--motion-reveal) var(--ease-material) both;
}

/* Tarjetas de evento reordenadas por estado: la que pasa a primera
   posición entra con la misma máscara que el resto. */
.event-live-dot {
  display: inline-block; width: .55rem; height: .55rem; border-radius: 50%;
  background: var(--t30-color-brand-red-700);
  animation: t30-live-dot 1.6s ease-in-out infinite;
}
@keyframes t30-live-dot { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* =========================================================================
   8b. PAUSA DE MOVIMIENTO (control del usuario, WCAG 2.2.2)
   `html.motion-paused` lo escribe el botón del pie. Todo lo que se mueve
   solo (deriva, banda, latido, paralaje) se detiene; las transiciones de
   estado (hover, foco, entradas) siguen porque explican un cambio.
   ========================================================================= */
.motion-paused .js .deco > img,
.js.motion-paused .deco > img { animation-play-state: paused; }
.js.motion-paused [data-parallax] { transform: none; }
.js.motion-paused .kinetic__track { transform: none; }
.motion-paused .event-live-dot { animation: none; }
@keyframes t30-rise-in {
  from { opacity: 0; transform: translate3d(0, 0.35em, 0); }
  to   { opacity: 1; transform: none; }
}

/* =========================================================================
   9. MOVIMIENTO REDUCIDO — la capa entera se apaga, el contenido permanece.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .event-live-dot { animation: none; }
  .js [data-parallax] { transform: none !important; }
  .js .deco > img { animation: none !important; }
  .js .split-line__inner { transform: none !important; transition: none !important; }
  .js .split-line { overflow: visible; }
  .countdown__value { animation: none !important; }
  .kinetic__track { transform: none !important; }
  .card--link:hover .event-card__lockup,
  .card--link:hover .event-card__obj--a,
  .card--link:hover .event-card__obj--b,
  .split:hover .art-panel > img { transform: none !important; }
  .btn:active { transform: none !important; }
}

/* =========================================================================
   10. RESPONSIVE — el movimiento se reduce antes que el contenido.
   ========================================================================= */
@media (max-width: 48rem) {
  :root { --parallax-clamp: 16px; }
  .kinetic__word { font-size: clamp(1.875rem, 9vw, 3rem); }
}
@media (max-width: 26.875rem) {
  :root { --parallax-clamp: 10px; }
  .js .deco > img { animation-duration: 18s; }
}

@media print {
  .kinetic, .progress-rail { display: none !important; }
}
