/* =========================================================
   ANIMACIONES.CSS
   ---------------------------------------------------------
   REGLA DE ORO: el estado inicial (oculto/desplazado) solo se
   aplica si <html> tiene la clase .con-animacion, que pone
   tema.js. Si el JavaScript falla, no se carga o el usuario
   pidió reducir movimiento, la página se ve completa y
   estática. Nunca queda un texto a medio desplazar.
   ========================================================= */

/* ---------- 1. Revelado de elementos --------------------- */
.con-animacion .revelar {
  opacity: 0;
  transition: opacity .55s var(--curva), transform .55s var(--curva);
  transition-delay: var(--retardo, 0ms);
  will-change: opacity, transform;
}

/* Ahora que el estado final sí limpia el transform, el recorrido
   puede ser más largo sin riesgo: 18px se nota y sigue cabiendo
   dentro del gap del grid. */
.con-animacion .revelar[data-dir="izq"]   { transform: translateX(-18px); }
.con-animacion .revelar[data-dir="der"]   { transform: translateX(18px); }
.con-animacion .revelar[data-dir="abajo"] { transform: translateY(16px); }
.con-animacion .revelar[data-dir="zoom"]  { transform: scale(.96); }

/* El estado final necesita [data-dir] en el selector. Sin él,
   `.con-animacion .revelar--visible` pesa 0-2-0 y pierde contra
   `.con-animacion .revelar[data-dir="izq"]`, que pesa 0-3-0 por
   el selector de atributo. Resultado: la opacidad sí llegaba a 1
   pero el translate NUNCA se quitaba, y las tarjetas quedaban
   corridas para siempre. La segunda regla cubre los elementos
   .revelar que no declaran dirección.
   Ref: https://developer.mozilla.org/docs/Web/CSS/Specificity */
.con-animacion .revelar--visible[data-dir],
.con-animacion .revelar--visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ---------- 2. Entrada del modal ------------------------- */
.con-animacion .modal__fondo {
  opacity: 0;
  transition: opacity .3s ease;
}

.con-animacion .modal__tarjeta {
  opacity: 0;
  transform: translateY(14px) scale(.94);
  transition: opacity .34s var(--curva), transform .34s var(--curva);
}

/* La clase --abierto la pone modal.js un par de frames después
   de insertar el nodo, para que la transición sí se dispare. */
.con-animacion .modal--abierto .modal__fondo { opacity: 1; }
.con-animacion .modal--abierto .modal__tarjeta { opacity: 1; transform: none; }

.con-animacion .modal--cerrando .modal__fondo { opacity: 0; }
.con-animacion .modal--cerrando .modal__tarjeta {
  opacity: 0;
  transform: translateY(8px) scale(.97);
}

/* ---------- 3. Barrido del encabezado -------------------- */
/* Una sola pasada de luz al abrirse la página: es el momento
   orquestado de la landing, no se repite. */
.hero__brillo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg,
    transparent 30%,
    rgba(255, 255, 255, .20) 50%,
    transparent 70%);
  transform: translateX(-100%);
  opacity: 0;
}

.con-animacion body.listo .hero__brillo {
  opacity: 1;
  animation: barrido 1.1s var(--curva) .15s 1 forwards;
}

@keyframes barrido {
  to { transform: translateX(100%); }
}

/* ---------- 4. Marca de confirmación --------------------- */
.exito__marca .icono path {
  stroke-dasharray: 26;
  stroke-dashoffset: 26;
  animation: trazar .45s var(--curva) .1s forwards;
}

@keyframes trazar {
  to { stroke-dashoffset: 0; }
}

/* ---------- 5. Movimiento reducido ----------------------- */
/* Doble protección: tema.js ya evita poner .con-animacion cuando
   el sistema pide reducir movimiento, y aquí se anula cualquier
   transición que quede suelta.

   El :not() es lo que permite que ?con-animacion funcione aunque
   el sistema pida reducir movimiento; sin él, este bloque ganaba
   siempre por el !important y no había forma de probar. */
@media (prefers-reduced-motion: reduce) {
  html:not(.con-animacion) *,
  html:not(.con-animacion) *::before,
  html:not(.con-animacion) *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  html:not(.con-animacion) .revelar {
    opacity: 1 !important;
    transform: none !important;
  }
  html:not(.con-animacion) .modal__tarjeta,
  html:not(.con-animacion) .modal__fondo {
    opacity: 1 !important;
    transform: none !important;
  }
  html:not(.con-animacion) .exito__marca .icono path { stroke-dashoffset: 0; }
}

/* ---------- 6. Esqueleto de carga ------------------------ */
/* Mientras el modal obligatorio está abierto, el <body> lleva la
   clase .esqueleto: la página existe pero cada texto se pinta como
   barras grises, una por línea, con un brillo que las recorre. Al
   registrarse, app.js quita la clase y entra el contenido real.

   Va al final del archivo a propósito: sus reglas empatan en peso
   con las del revelado (sección 1) y en un empate gana la última.

   Ref: https://developer.mozilla.org/docs/Web/CSS/length#lh */

.esqueleto {
  /* Color de las barras sobre fondo claro y color del brillo. */
  --esq: color-mix(in oklab, var(--tinta) 9%, white);
  --esq-brillo: rgba(255, 255, 255, .6);
}

/* Sobre el encabezado de color, barras blancas translúcidas. */
.esqueleto .hero {
  --esq: rgba(255, 255, 255, .16);
  --esq-brillo: rgba(255, 255, 255, .16);
}

/* 1. Lo que normalmente arranca oculto para animarse, aquí queda
      visible y quieto: son las barras las que se ven. */
.esqueleto .revelar,
.esqueleto .revelar[data-dir] {
  opacity: 1;
  transform: none;
  transition: none;
}

/* 2. Textos: el texto se vuelve transparente (sigue ocupando su
      espacio, así que la maqueta no salta al aparecer) y el fondo
      dibuja una barra por línea.
        - Capa de arriba: el brillo que se desplaza.
        - Capa de abajo: las barras. Cada franja mide 1lh (una
          línea) y la barra ocupa su 60% central.
      El primer background-image es el respaldo en em para
      navegadores sin lh; los que sí lo entienden usan el segundo. */
.esqueleto :is(
  .hero__lema, .hero__rif,
  .acerca__destacado, .acerca__texto p,
  .dato__valor, .dato__etiqueta,
  .bloque__titulo,
  .red__etiqueta, .red__detalle,
  .encuesta__intro, .pregunta__texto, .opcion__texto, .escala__limites span,
  .pie p
) {
  color: transparent;
  border-radius: 4px;
  background-image:
    linear-gradient(100deg, transparent 30%, var(--esq-brillo) 50%, transparent 70%),
    repeating-linear-gradient(to bottom,
      transparent 0 .3em, var(--esq) .3em 1.25em, transparent 1.25em 1.55em);
  background-image:
    linear-gradient(100deg, transparent 30%, var(--esq-brillo) 50%, transparent 70%),
    repeating-linear-gradient(to bottom,
      transparent 0 .2lh, var(--esq) .2lh .8lh, transparent .8lh 1lh);
  background-size: 200% 100%, 100% 100%;
  background-repeat: no-repeat, repeat;
  animation: esqueleto 1.4s linear infinite;
}

/* Lo que va DENTRO de esos textos (asteriscos, enlaces) tiene su
   propio color y no hereda el transparent: se apaga aparte. */
.esqueleto :is(
  .hero__lema, .hero__rif, .acerca__destacado, .acerca__texto p,
  .bloque__titulo, .pregunta__texto, .pie p
) * {
  color: transparent;
  text-decoration: none;
}

/* 3. Imágenes: el dibujo se empuja fuera de su caja con
      object-position y queda a la vista solo el fondo, que hace
      de bloque. La caja conserva su tamaño exacto. */
.esqueleto .pagina img {
  object-position: -99999px 0;
  background-color: var(--esq);
  border-radius: 8px;
}

/* 4. Íconos de redes: un círculo en lugar del dibujo. */
.esqueleto .red__icono {
  background: var(--esq);
  border-radius: 50%;
}

.esqueleto .red__icono svg { visibility: hidden; }

/* 5. Banner: bloque liso, sin el texto del marcador. */
.esqueleto .banner__marcador {
  color: transparent;
  background: var(--esq);
}

/* 6. Controles de la encuesta: bloques del mismo tamaño. */
.esqueleto .escala__cara {
  color: transparent;
  background: var(--esq);
  border-color: transparent;
}

.esqueleto .opcion__entrada { visibility: hidden; }

/* Solo dentro de .pagina: el modal también usa .campo__control y
   sus textos de ejemplo tienen que seguir viéndose. */
.esqueleto .pagina .campo__control::placeholder,
.esqueleto .contador { color: transparent; }

.esqueleto .encuesta__form .boton {
  color: transparent;
  background: var(--esq);
}

/* El brillo va de izquierda a derecha. Con la capa al 200% de
   ancho, la posición 200% la deja fuera por la izquierda y -100%
   fuera por la derecha. */
@keyframes esqueleto {
  from { background-position: 200% 0, 0 0; }
  to   { background-position: -100% 0, 0 0; }
}

/* Paso del esqueleto al estado oculto sin animar (lo usa
   Animaciones.quitarEsqueleto). */
.sin-transicion .revelar,
.sin-transicion .revelar[data-dir] {
  transition: none;
}
