/* ============================================================
   VETERINARIA ANDRADE · animaciones.css
   Todo lo que se mueve. Sin librerías: CSS + IntersectionObserver.

   Criterio: cada animación tiene que "hablar de selva" y tener
   una razón. Nada de efectos porque sí, nada caricaturesco.
   ============================================================ */

/* ════════════════════════════════════════════════════════════
   1. DOSEL · rayos de luz filtrándose entre las hojas
   Es la firma visual del sitio. Tres gradientes cónicos muy
   tenues, con inclinación distinta y deriva lentísima: imita
   la luz atravesando el follaje cuando el aire lo mueve.
   ════════════════════════════════════════════════════════════ */

/* width:100% en vez de inset:0 con hijos anchos: los rayos miden
   45vmax y, aunque el padre tenga overflow:hidden, un hijo
   posicionado seguía contando para el scrollWidth del documento
   (13px de desborde real a 320px). contain lo aísla del layout. */
.dosel {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100dvh;
  z-index: var(--z-fondo);
  pointer-events: none;
  overflow: hidden;
  contain: strict;
}

.dosel__rayo {
  position: absolute;
  top: -40%;
  width: 45vmax;
  height: 180vmax;
  background: linear-gradient(180deg,
    rgba(99, 150, 60, .16) 0%,
    rgba(143, 212, 78, .09) 40%,
    transparent 75%);
  filter: blur(52px);
  transform-origin: top center;
  will-change: transform;
}

.dosel__rayo--1 { left: -10%; transform: rotate(14deg); animation: deriva-rayo 26s ease-in-out infinite alternate; }
.dosel__rayo--2 { left: 32%;  transform: rotate(-8deg); animation: deriva-rayo 34s ease-in-out infinite alternate-reverse; opacity: .7; }
.dosel__rayo--3 { right: -8%; transform: rotate(19deg); animation: deriva-rayo 30s ease-in-out infinite alternate; opacity: .55; }

@keyframes deriva-rayo {
  from { transform: rotate(var(--rot, 14deg)) translateX(0)    scaleY(1); }
  to   { transform: rotate(var(--rot, 14deg)) translateX(4vw) scaleY(1.06); }
}

.dosel__rayo--1 { --rot: 14deg; }
.dosel__rayo--2 { --rot: -8deg; }
.dosel__rayo--3 { --rot: 19deg; }

/* Vignette: cierra los bordes para que el centro respire */
/* Sobre fondo claro la vignette no oscurece: aclara los bordes,
   como luz que entra por los costados del sotobosque. */
.dosel::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 0%, transparent 45%, rgba(247,250,243,.75) 100%);
}

/* ════════════════════════════════════════════════════════════
   1.b SELVA · follaje que se mece en los bordes
   Cuatro capas de frondas SVG entrando desde los costados, con
   velocidades y amplitudes distintas para dar profundidad. El
   giro nace de la base de cada fronda (transform-origin abajo),
   que es como se mueve una hoja real cuando la empuja el aire.

   Va MUY tenue a propósito: tiene que sentirse, no verse. Si
   compite con el contenido, deja de ser ambiente y estorba.
   ════════════════════════════════════════════════════════════ */

.selva {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100dvh;
  z-index: var(--z-fondo);
  pointer-events: none;
  overflow: hidden;
  contain: strict;
}

.selva__capa {
  position: absolute;
  bottom: -4%;
  color: var(--verde-hondo);
  will-change: transform;
}

.selva__capa svg { width: 100%; height: 100%; display: block; }

/* Izquierda, grande y lenta: es el fondo */
.selva__capa--i1 {
  left: -6%;
  width: clamp(220px, 30vw, 460px);
  height: 92%;
  opacity: .09;
  transform-origin: 30% 100%;
  animation: mecer 14s ease-in-out infinite alternate;
}
/* Izquierda, pequeña y más rápida: primer plano */
.selva__capa--i2 {
  left: -2%;
  width: clamp(140px, 18vw, 280px);
  height: 62%;
  opacity: .13;
  transform-origin: 40% 100%;
  animation: mecer-corto 9s ease-in-out infinite alternate-reverse;
}
/* Derecha, grande */
.selva__capa--d1 {
  right: -7%;
  width: clamp(220px, 32vw, 500px);
  height: 88%;
  opacity: .08;
  transform-origin: 70% 100%;
  animation: mecer 17s ease-in-out infinite alternate-reverse;
  transform: scaleX(-1);
}
/* Derecha, pequeña */
.selva__capa--d2 {
  right: -1%;
  width: clamp(130px, 16vw, 250px);
  height: 55%;
  opacity: .12;
  transform-origin: 60% 100%;
  animation: mecer-corto 11s ease-in-out infinite alternate;
  transform: scaleX(-1);
}

/* Amplitudes pequeñas: 1.6° y 2.4°. Más que eso deja de parecer
   viento y empieza a parecer un limpiaparabrisas. */
@keyframes mecer {
  from { transform: rotate(-1.6deg) translateY(0); }
  to   { transform: rotate(1.6deg)  translateY(-6px); }
}
@keyframes mecer-corto {
  from { transform: rotate(2.4deg)  translateY(0); }
  to   { transform: rotate(-2.4deg) translateY(-10px); }
}
/* Las capas de la derecha van espejadas: hay que conservar el
   scaleX(-1) dentro de la animación o el espejo se pierde. */
.selva__capa--d1 { animation-name: mecer-espejo; }
.selva__capa--d2 { animation-name: mecer-corto-espejo; }
@keyframes mecer-espejo {
  from { transform: scaleX(-1) rotate(-1.6deg) translateY(0); }
  to   { transform: scaleX(-1) rotate(1.6deg)  translateY(-6px); }
}
@keyframes mecer-corto-espejo {
  from { transform: scaleX(-1) rotate(2.4deg)  translateY(0); }
  to   { transform: scaleX(-1) rotate(-2.4deg) translateY(-10px); }
}

@media (max-width: 640px) {
  /* En móvil solo se dejan las dos capas de fondo: las de primer
     plano se comen los márgenes del texto en pantallas estrechas. */
  .selva__capa--i2, .selva__capa--d2 { display: none; }
  .selva__capa--i1, .selva__capa--d1 { opacity: .07; }
}

/* ════════════════════════════════════════════════════════════
   2. HOJAS A LA DERIVA
   Formas de hoja reales con border-radius asimétrico, no
   partículas genéricas. Se generan en JS para repartir tamaños,
   posiciones y tiempos sin que se note el patrón.
   ════════════════════════════════════════════════════════════ */

/* DOS capas de hojas, y esto es lo importante:

   Las secciones de <main> tienen fondo OPACO y viven en z-index 2.
   Una sola capa de hojas en z-index 1 queda sepultada bajo cada
   sección y solo se ve en el footer — que era justo el síntoma
   de "a la mitad se ve muy simple".

   Solución: una capa detrás (se ve en los huecos y en el footer)
   y otra DELANTE del contenido, con opacidad muy baja y desenfoque,
   para que las hojas crucen por encima del texto sin estorbar la
   lectura. Ninguna captura eventos de puntero. */
.hojas {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100dvh;
  pointer-events: none;
  overflow: hidden;
  contain: strict;
}

.hojas--fondo  { z-index: 1; }

/* Por encima del contenido (2) pero por debajo del header (50),
   de la barra móvil y del botón de WhatsApp (60). */
.hojas--frente { z-index: 6; }

.hoja {
  position: absolute;
  top: -8vh;
  border-radius: 0 100% 0 100%;
  background: linear-gradient(135deg, var(--verde-claro), var(--verde));
  opacity: 0;
  will-change: transform, opacity;
  animation: caer-hoja linear infinite;
}

/* La opacidad máxima la fija JS por hoja (--op) según su capa de
   profundidad: las del fondo son más tenues que las del frente. */
@keyframes caer-hoja {
  0%   { opacity: 0;              transform: translate3d(0, -10vh, 0) rotate(0deg) scale(1); }
  8%   { opacity: var(--op, .3); }
  50%  {                          transform: translate3d(6vw, 50vh, 0) rotate(180deg) scale(.95); }
  92%  { opacity: calc(var(--op, .3) * .7); }
  100% { opacity: 0;              transform: translate3d(-3vw, 112vh, 0) rotate(400deg) scale(.85); }
}

/* ════════════════════════════════════════════════════════════
   3. LIANA · indicador de progreso de lectura
   Una liana orgánica recorre el costado izquierdo y se dibuja
   conforme bajas. Es el hilo que impide que las secciones se
   sientan como bloques sueltos, y de paso dice en qué punto vas.
   ════════════════════════════════════════════════════════════ */

.liana {
  position: fixed;
  top: 0; left: 0;
  width: 54px;
  height: 100dvh;
  z-index: 3;
  pointer-events: none;
  display: none;
}

.liana svg { width: 100%; height: 100%; }

.liana__trazo {
  fill: none;
  stroke: url(#degradadoLiana);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
}

.liana__hoja {
  fill: var(--verde);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 0% 50%;
  transform: scale(0) rotate(-25deg);
  transition: opacity var(--dur-3) var(--ease-hoja),
              transform var(--dur-3) var(--ease-hoja);
}
.liana__hoja.brotada { opacity: .85; transform: scale(1) rotate(0deg); }

@media (min-width: 1100px) { .liana { display: block; } }

/* ════════════════════════════════════════════════════════════
   4. REVEALS · "crecimiento"
   Nada de fade genérico: los elementos suben, se desenfocan de
   menos a más y se asientan. Simula algo que brota.
   ════════════════════════════════════════════════════════════ */

[data-revelar] {
  opacity: 0;
  transform: translateY(28px);
  filter: blur(6px);
  transition:
    opacity   var(--dur-3) var(--ease-salida),
    transform var(--dur-3) var(--ease-salida),
    filter    var(--dur-3) var(--ease-salida);
  transition-delay: var(--retraso, 0ms);
}
[data-revelar].visible { opacity: 1; transform: none; filter: blur(0); }

/* Variante lateral, para las columnas de texto */
[data-revelar='lado'] { transform: translateX(-24px); }
[data-revelar='lado'].visible { transform: none; }

/* Variante escala, para imágenes y tarjetas grandes */
[data-revelar='escala'] { transform: scale(.96); }
[data-revelar='escala'].visible { transform: none; }

/* ════════════════════════════════════════════════════════════
   5. TITULAR POR LÍNEAS
   Cada línea sube tras una máscara. El texto se pinta opaco en
   el primer frame (no retrasa el LCP): solo se desplaza.
   ════════════════════════════════════════════════════════════ */

.linea-mascara { display: block; overflow: hidden; padding-bottom: .08em; }
.linea-mascara > span {
  display: block;
  transform: translateY(105%);
  animation: subir-linea var(--dur-4) var(--ease-salida) forwards;
  animation-delay: var(--retraso, 0ms);
}
@keyframes subir-linea { to { transform: translateY(0); } }

/* ════════════════════════════════════════════════════════════
   6. EMBLEMA · respiración
   El logo late muy despacio, como algo vivo. Solo en el hero.
   ════════════════════════════════════════════════════════════ */

.emblema-hero {
  animation: respirar 7s ease-in-out infinite;
  filter: drop-shadow(0 6px 18px rgba(44, 74, 27, .18));
}
@keyframes respirar {
  0%, 100% { transform: scale(1)     rotate(0deg); }
  50%      { transform: scale(1.035) rotate(.6deg); }
}

/* ════════════════════════════════════════════════════════════
   7. MARQUEE de especies · cinta infinita
   ════════════════════════════════════════════════════════════ */

.cinta { overflow: hidden; mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.cinta__pista { display: flex; gap: var(--e-m); width: max-content; animation: correr-cinta 42s linear infinite; }
.cinta:hover .cinta__pista { animation-play-state: paused; }
@keyframes correr-cinta { to { transform: translateX(-50%); } }

/* ════════════════════════════════════════════════════════════
   8. CONTADOR · los números suben al entrar en pantalla
   El valor lo anima JS; aquí solo se fija la tipografía tabular
   para que no "bailen" los dígitos mientras cuentan.
   ════════════════════════════════════════════════════════════ */

[data-contador] { font-variant-numeric: tabular-nums; }

/* ════════════════════════════════════════════════════════════
   9. BRILLO QUE SIGUE AL CURSOR
   Muy tenue, solo en escritorio. Da sensación de profundidad
   sin dibujar nada.
   ════════════════════════════════════════════════════════════ */

.con-brillo { position: relative; isolation: isolate; }
.con-brillo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(400px circle at var(--mx, 50%) var(--my, 50%),
              rgba(143, 212, 78, .22), transparent 70%);
  transition: opacity var(--dur-2) var(--ease-suave);
}
@media (hover: hover) and (pointer: fine) {
  .con-brillo:hover::before { opacity: 1; }
}

/* ════════════════════════════════════════════════════════════
   10. ENTRADA DEL HERO
   ════════════════════════════════════════════════════════════ */

.hero-anima {
  opacity: 0;
  transform: translateY(20px);
  animation: entrar-hero var(--dur-4) var(--ease-salida) forwards;
  animation-delay: var(--retraso, 0ms);
}
@keyframes entrar-hero { to { opacity: 1; transform: none; } }

/* ════════════════════════════════════════════════════════════
   REDUCED MOTION · todo queda quieto y legible
   ════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .dosel__rayo, .hoja, .emblema-hero, .cinta__pista, .selva__capa { animation: none !important; }
  .hojas { display: none; }
  [data-revelar] { opacity: 1 !important; transform: none !important; filter: none !important; }
  .linea-mascara > span { transform: none !important; animation: none !important; }
  .hero-anima { opacity: 1 !important; transform: none !important; animation: none !important; }
  .liana__trazo { stroke-dashoffset: 0 !important; }
  .liana__hoja { opacity: .85 !important; transform: none !important; }
}

/* ════════════════════════════════════════════════════════════
   11. DIVISORES ORGÁNICOS ENTRE SECCIONES
   Los cambios de fondo eran líneas rectas y hacían que la página
   se leyera como bloques apilados. Cada divisor es el borde
   inferior de la sección ANTERIOR, dibujado como una silueta de
   dosel: curvas irregulares, no una onda de plantilla.

   El relleno lo fija la variante --desde-N con el color de la
   sección de arriba, así el borde parece pertenecerle a ella.
   ════════════════════════════════════════════════════════════ */

.divisor {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: clamp(28px, 4vw, 56px);
  z-index: 1;
  pointer-events: none;
  line-height: 0;
  transform: translateY(-1px); /* mata la costura de subpíxel */
}

.divisor svg { width: 100%; height: 100%; display: block; }

.divisor--desde-1 svg { fill: var(--claro); }
.divisor--desde-2 svg { fill: var(--claro-2); }
.divisor--desde-3 svg { fill: var(--claro-3); }

/* El contenido de la sección tiene que respirar por debajo */
.seccion { padding-top: calc(var(--seccion-y) + clamp(28px, 4vw, 56px)); }

/* ════════════════════════════════════════════════════════════
   12. ICONOS QUE SE DIBUJAN
   Los trazos se dibujan al entrar en pantalla en vez de aparecer
   hechos. main.js mide cada path con getTotalLength() y fija el
   dasharray exacto: con un valor fijo, los iconos cortos se
   dibujarían de golpe y los largos se quedarían a medias.
   ════════════════════════════════════════════════════════════ */

[data-dibujar] path,
[data-dibujar] circle,
[data-dibujar] rect,
[data-dibujar] line {
  stroke-dashoffset: var(--largo, 0);
  stroke-dasharray: var(--largo, 0);
}

[data-dibujar].dibujado path,
[data-dibujar].dibujado circle,
[data-dibujar].dibujado rect,
[data-dibujar].dibujado line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--dur-4) var(--ease-salida);
  transition-delay: var(--retraso-trazo, 0ms);
}

/* ════════════════════════════════════════════════════════════
   13. GUACAMAYA CRUZANDO
   Guiño al logo. Cruza MUY de vez en cuando (ciclo de 54s con
   solo ~9s de vuelo visible) y a opacidad baja: si se repitiera
   seguido pasaría de detalle a distracción.
   ════════════════════════════════════════════════════════════ */

.guacamaya {
  position: fixed;
  top: 14vh;
  left: -12vw;
  width: clamp(40px, 4.4vw, 76px);
  z-index: 4;
  pointer-events: none;
  color: var(--verde-hondo);
  opacity: 0;
  will-change: transform, opacity;
  animation: cruzar-guacamaya 54s linear infinite;
}

.guacamaya svg { width: 100%; height: auto; display: block; }

/* El ala late en un ciclo propio, más rápido, para que el vuelo
   no se vea como una calcomanía deslizándose. */
.guacamaya__ala {
  transform-origin: 62% 58%;
  animation: aletear 1.1s ease-in-out infinite;
}

@keyframes cruzar-guacamaya {
  0%    { opacity: 0;   transform: translate3d(0, 0, 0) rotate(-4deg); }
  2%    { opacity: var(--op-guacamaya, .14); }
  6%    {               transform: translate3d(30vw, -5vh, 0) rotate(2deg); }
  11%   {               transform: translate3d(62vw, 3vh, 0) rotate(-3deg); }
  15%   { opacity: calc(var(--op-guacamaya, .14) * .85); }
  17%   { opacity: 0;   transform: translate3d(124vw, -2vh, 0) rotate(1deg); }
  100%  { opacity: 0;   transform: translate3d(124vw, -2vh, 0); }
}

@keyframes aletear {
  0%, 100% { transform: scaleY(1)   rotate(0deg); }
  50%      { transform: scaleY(.62) rotate(-7deg); }
}

@media (max-width: 640px) { .guacamaya { display: none; } }

/* ── Reduced motion para todo lo nuevo ─────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .guacamaya { display: none; }
  [data-dibujar] path, [data-dibujar] circle,
  [data-dibujar] rect, [data-dibujar] line { stroke-dashoffset: 0 !important; }
}

/* ── Guacamaya con imagen propia ────────────────────────────
   Si se sustituye el SVG por un PNG del cliente, la silueta pasa
   a ser un mapa de bits y el ala ya no puede aletear por separado.
   El balanceo del conjunto sustituye ese detalle. */
.guacamaya img {
  width: 100%;
  height: auto;
  display: block;
  /* Sin drop-shadow: sobre fondo claro y a opacidad .14 solo
     ensuciaría los bordes del recorte. */
  animation: planear 2.8s ease-in-out infinite;
}

@keyframes planear {
  0%, 100% { transform: rotate(-2deg) translateY(0); }
  50%      { transform: rotate(2deg)  translateY(-5px); }
}

/* Con foto conviene subir un poco la opacidad: un PNG a color se
   lee más tenue que una silueta plana del mismo valor. */
/* Una foto a todo color se percibe MÁS que una silueta plana del
   mismo valor, así que aquí la opacidad baja en vez de subir. */
.guacamaya--foto { --op-guacamaya: .30; }
