/*
 * AldeOn — Clases de efectos reutilizables (base de la modernización
 * visual, 2026-09-07). Consume las variables de tokens.css — cargar
 * SIEMPRE tokens.css antes que este archivo.
 */

/* ---------- Overlay de grano (noise) ----------
 * CSS puro, sin ninguna imagen de red: el ruido es un SVG con
 * <feTurbulence> incrustado como data-URI directamente en el
 * background-image, así que no añade ninguna petición HTTP ni
 * decodificación de PNG — el coste real es solo pintar un tile de
 * 120x120 en bucle, prácticamente gratis para el navegador.
 *
 * Uso: añadir la clase `grain-overlay` a cualquier <section> (u otro
 * contenedor) que deba llevar la textura. El propio contenedor pasa a
 * ser el "marco" del grano (position: relative + isolation: isolate
 * crean un contexto de apilamiento propio), y sus hijos directos se
 * suben por encima automáticamente — no hace falta tocar nada más en
 * el contenido de dentro.
 */
.grain-overlay {
  position: relative;
  isolation: isolate;
}

.grain-overlay::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 120px 120px;
}

.grain-overlay > * {
  position: relative;
  z-index: 2;
}

/* ---------- Barra de progreso de scroll ----------
 * Fina franja fija arriba del todo; progress.js solo escribe
 * `transform: scaleX(...)` en cada scroll (nunca width), así que es
 * puramente composición de GPU — no dispara ni layout ni paint por
 * fotograma. Vinculada 1:1 al scroll del propio usuario (no es una
 * animación autónoma), así que se deja funcionando igual con
 * `prefers-reduced-motion` — mismo criterio que una scrollbar nativa.
 */
#scroll-progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: linear-gradient(90deg, var(--home), var(--votes));
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 9998;
  pointer-events: none;
}

/* ---------- Fondos "mesh gradient" ----------
 * Manchas de color de marca muy difuminadas, deriva lenta y sutil de
 * fondo — solo transform (translate + scale) y opacity, nunca
 * top/left/width/height, para que el navegador pueda animarlas por
 * GPU sin recalcular layout. `pointer-events: none` en todo el
 * conjunto: son decorativas, nunca deben robarle un clic a nada.
 *
 * Uso: `<div class="mesh-bg"><div class="mesh-blob mesh-blob-a"></div>
 * <div class="mesh-blob mesh-blob-b"></div>
 * <div class="mesh-blob mesh-blob-c"></div></div>` como PRIMER hijo de
 * cualquier sección con `position: relative` — el propio contenido de
 * la sección necesita su `z-index` propio (ya lo tienen `.hero-grid`,
 * `.story-grid`, etc.) para quedar por encima.
 */
.mesh-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
}

.mesh-blob {
  position: absolute;
  width: 46vw;
  height: 46vw;
  max-width: 520px;
  max-height: 520px;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.28;
  will-change: transform;
}

.mesh-blob-a {
  top: -10%;
  left: -8%;
  background: radial-gradient(circle, rgba(var(--mesh-green-light-rgb), 0.9), transparent 70%);
  animation: mesh-drift-a 26s ease-in-out infinite;
}

.mesh-blob-b {
  top: 20%;
  right: -12%;
  background: radial-gradient(circle, rgba(var(--mesh-amber-light-rgb), 0.85), transparent 70%);
  animation: mesh-drift-b 32s ease-in-out infinite;
}

.mesh-blob-c {
  bottom: -14%;
  left: 28%;
  background: radial-gradient(circle, rgba(var(--mesh-indigo-light-rgb), 0.8), transparent 70%);
  animation: mesh-drift-c 29s ease-in-out infinite;
}

@keyframes mesh-drift-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(6%, 8%) scale(1.12); }
}

@keyframes mesh-drift-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-8%, 6%) scale(0.92); }
}

@keyframes mesh-drift-c {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(5%, -7%) scale(1.08); }
}

/* La deriva en bucle es barata (solo 3 elementos, solo transform),
   pero en pantallas pequeñas se desactiva igualmente — un móvil de
   gama media agradece no tener 3 animaciones infinitas más corriendo
   de fondo mientras hace scroll. Las manchas se quedan quietas pero
   perfectamente visibles. Petición del usuario, 2026-09-07: "verifica
   que la página sigue siendo rápida en un móvil de gama media". */
@media (max-width: 640px) {
  .mesh-blob { animation: none; }
}

/* ---------- Red de seguridad de prefers-reduced-motion ----------
 * `motion.js` ya evita crear ninguna animación de GSAP/Lenis cuando el
 * sistema tiene "reducir movimiento" activado, pero esta regla es el
 * segundo cinturón: apaga en bloque CUALQUIER transición/animación
 * CSS normal (incluida cualquiera que se añada en una fase futura sin
 * acordarse de comprobar `AldeonMotion.reducedMotion`) y desactiva el
 * `scroll-behavior: smooth` del <html>. Patrón estándar de
 * accesibilidad, no específico de AldeOn.
 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto !important;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
