/* =====================================================================
   HIDRATACCIÓN — El personaje

   Va aparte de style.css a propósito: es una pieza que se saca de una página
   borrando dos líneas del HTML, y mezclarla en las 5.000 líneas de la hoja
   principal sería perder esa propiedad.

   Vive abajo a la izquierda. El botón de WhatsApp está abajo a la derecha
   (.wapp, z-index 120) y no se tocan nunca.

   Todo lo que se mueve es transform y opacity, como el resto del sitio: lo
   resuelve el compositor y no compite con el dibujo del sobre, que va por el
   hilo principal.
   ===================================================================== */

.avatar {
  /* El alto del MARCO de los sprites, no el del dibujo. Todas las poses vienen
     en un marco de 457x416 con el personaje apoyado abajo y al medio (ver
     scripts/recortar-avatar.mjs), así que el dibujo ocupa entre el 65% y el
     95% de este alto según la pose. Por eso el número es más grande de lo que
     mide el muñeco en pantalla. */
  --avatar-alto: clamp(8rem, 13vw, 11rem);
  --avatar-aire: clamp(1rem, 2.5vw, 1.75rem);

  position: fixed;
  left: var(--avatar-aire);
  bottom: var(--avatar-aire);
  z-index: 130;

  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;

  /* Entra desde abajo y crece. Arranca apagado: lo prende el puente cuando
     hay algo para decir, así no aparece en pantalla antes de tener motivo. */
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, 1.25rem, 0) scale(0.9);
  transform-origin: left bottom;
  transition:
    opacity 0.32s ease,
    transform 0.42s var(--transition-spring),
    visibility 0s linear 0.42s;
}

.avatar--presente {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0) scale(1);
  transition:
    opacity 0.32s ease,
    transform 0.42s var(--transition-spring),
    visibility 0s;
}

/* ── El muñeco ─────────────────────────────────────────────────────── */

/* El muñeco y su aspa van juntos acá para que el aspa se cuelgue de la esquina
   del marco y no del rincón de la pantalla. */
.avatar__cuerpo {
  position: relative;
  display: block;
}

.avatar__munieco {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  /* El área táctil real es la imagen; el borde de foco sigue su forma. */
  border-radius: 1rem;
  transition: transform 0.3s var(--transition-spring);
}

/* La escena: la caja donde vive el muñeco, sea por capas o de una pieza. Le
   da el tamaño —se lo pone la estampa, que trae la proporción del marco en
   sus atributos width/height— y se queda con el golpe del cambio de cara.
   El respirar va adentro, en las capas, para que los dos transform no se
   pisen: el CSS deja ganar a una sola animación por propiedad. */
.avatar__escena {
  position: relative;
  display: block;
  /* La sombra del piso va en el filtro y no en un pseudo-elemento: así sigue
     la silueta recortada —que cambia con cada pose— en vez de ser una elipse
     debajo de un rectángulo. Dos capas: una pegada, que apoya al personaje,
     y una abierta y teñida de marca, que lo despega del fondo. */
  filter:
    drop-shadow(0 2px 3px rgba(6, 95, 117, 0.22))
    drop-shadow(0 12px 22px rgba(14, 164, 207, 0.28));
}

.avatar__pose {
  display: block;
  height: var(--avatar-alto);
  width: auto;
}

/* ── El muñeco por capas ───────────────────────────────────────────── */

/* Se apila encima de la estampa, del mismo tamaño y en la misma posición: los
   archivos de las capas vienen todos del mismo marco, así que no hay nada que
   acomodar. Las dos nunca se ven a la vez. */
.munieco {
  position: absolute;
  inset: 0;
}

.munieco__capa {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* El punto de giro lo pone el JS con los datos que generó el script: es
     dónde cae el hombro de cada brazo dentro del marco. */
}

/* Reposo articulado: la estampa se esconde pero sigue ocupando su lugar, que
   es lo que le da el tamaño a la escena. */
.avatar[data-articulado='true']  .avatar__pose { visibility: hidden; }
/* Estampa fija: las capas se sacan del todo, no solo se ocultan, para que no
   queden animaciones corriendo sobre algo que nadie ve. */
.avatar[data-articulado='false'] .munieco     { display: none; }

/* ── Respirar ──────────────────────────────────────────────────────── */

/* Sube y baja un poco mientras se ensancha y se afina: las dos cosas en una
   sola animación porque van sobre la misma propiedad. Lo llevan tanto las
   capas como la estampa, así que las catorce poses respiran, no solo la
   articulada. */
.munieco,
.avatar__pose {
  transform-origin: 50% 100%;
  animation: avatar-respira 3.6s ease-in-out infinite;
}

@keyframes avatar-respira {
  0%, 100% { transform: translate3d(0, 0, 0)         scale3d(1, 1, 1); }
  50%      { transform: translate3d(0, -0.35rem, 0)  scale3d(0.993, 1.014, 1); }
}

/* Los brazos van un poco atrasados respecto del cuerpo. Eso es lo que en
   animación llaman arrastre: si todo se mueve exactamente junto, se lee como
   una imagen escalando; si las puntas llegan tarde, se lee como un cuerpo. */
.munieco__capa--brazo-izq {
  animation: avatar-brazo-izq 3.6s ease-in-out -0.35s infinite;
}
.munieco__capa--brazo-der {
  animation: avatar-brazo-der 3.6s ease-in-out -0.5s infinite;
}

@keyframes avatar-brazo-izq {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-3.2deg); }
}
@keyframes avatar-brazo-der {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(3.2deg); }
}

/* ── Parpadear ─────────────────────────────────────────────────────── */

/* En reposo el párpado está aplastado contra el borde de arriba del ojo y no
   se ve. Parpadear es estirarlo hacia abajo y volver. Así no hubo que borrar
   el ojo abierto ni repintar la cara debajo. */
.munieco__capa--parpado-izq,
.munieco__capa--parpado-der {
  transform: scaleY(0);
}

.munieco--parpadea .munieco__capa--parpado-izq {
  animation: avatar-parpadeo 190ms ease-in-out;
}
/* El otro ojo, veinticinco milisegundos después. Dos párpados perfectamente
   sincronizados se leen como un obturador; desfasados, como una cara. */
.munieco--parpadea .munieco__capa--parpado-der {
  animation: avatar-parpadeo 190ms ease-in-out 25ms;
}

@keyframes avatar-parpadeo {
  0%        { transform: scaleY(0); }
  40%, 60%  { transform: scaleY(1); }
  100%      { transform: scaleY(0); }
}

/* ── La espuma arrastra ────────────────────────────────────────────── */

/* Va medio segundo atrás del cuerpo y se mece desde donde se apoya en el
   vaso. Es poco —un grado y medio— y es de lo que más se nota: la espuma es
   lo único del dibujo que debería tener inercia propia, y cuando la tiene el
   personaje deja de parecer una calcomanía. */
.munieco__capa--espuma {
  animation: avatar-espuma 3.6s ease-in-out -0.62s infinite;
}

@keyframes avatar-espuma {
  0%, 100% { transform: rotate(0deg)      translate3d(0, 0, 0); }
  50%      { transform: rotate(-1.4deg)   translate3d(0, -0.06rem, 0); }
}

/* ── La mirada ─────────────────────────────────────────────────────── */

/* Cada ojo va adentro de una caja recortada con su propia forma —la máscara la
   pone el JS, que es quien sabe de dónde salen los archivos— y lo que se mueve
   es la imagen de adentro. Así el ojo se corre hasta el borde y lo que se pasa
   se corta, en vez de andar la pupila suelta por la cara. */
.munieco__capa--pupila-izq,
.munieco__capa--pupila-der {
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

/* Las pupilas las mueve el JS, que es el que sabe dónde está el cursor. Acá
   solo va el suavizado: sin la transición la mirada teletransporta y se ve
   como un error de dibujo, no como alguien que mira. */
.munieco__pupila {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}

/* ── Hablar ────────────────────────────────────────────────────────── */

/* La boca se abre y se cierra sobre la línea de sus comisuras, que es el punto
   de giro que le pone el JS con lo que midió el script. Las dos puntas se
   quedan clavadas ahí y lo que sube y baja es el medio: el labio de arriba y
   el de abajo se acercan a esa línea y se separan, que es como se abre una
   boca de verdad.

   Solo escala en Y. Con escala en X también —como estaba antes— las puntas se
   corrían hacia adentro y la boca parecía encogerse entera en vez de abrirse.

   Los tiempos son irregulares a propósito: una boca que sube y baja como un
   metrónomo se lee como una máquina, no como alguien diciendo algo. */
.munieco--habla .munieco__capa--boca {
  animation: avatar-habla 0.62s ease-in-out infinite;
}

@keyframes avatar-habla {
  0%   { transform: scaleY(1); }
  12%  { transform: scaleY(0.42); }
  26%  { transform: scaleY(0.92); }
  40%  { transform: scaleY(0.5); }
  55%  { transform: scaleY(1); }
  70%  { transform: scaleY(0.46); }
  85%  { transform: scaleY(0.84); }
  100% { transform: scaleY(1); }
}

/* ── Los gestos ────────────────────────────────────────────────────── */

/* Todos se piden igual: una clase en .munieco que dura lo que dura la
   animación. Los que mueven el cuerpo entero PISAN el respirar, y los que
   mueven un brazo pisan su mecerse. No se suman: el CSS deja ganar a una
   sola animación por propiedad, y eso acá viene bien —mientras el personaje
   salta no tiene que estar respirando también—. */

/* Saludar con el brazo de arriba. */
.munieco--saluda .munieco__capa--brazo-der {
  animation: avatar-saluda 1.15s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

@keyframes avatar-saluda {
  0%   { transform: rotate(0deg); }
  15%  { transform: rotate(-15deg); }
  38%  { transform: rotate(13deg); }
  60%  { transform: rotate(-11deg); }
  80%  { transform: rotate(8deg); }
  100% { transform: rotate(0deg); }
}

/* Festejar: los dos brazos al aire y un saltito. */
.munieco--festeja { animation: avatar-salta 0.95s cubic-bezier(0.34, 1.3, 0.64, 1); }
.munieco--festeja .munieco__capa--brazo-der { animation: avatar-festeja-der 0.95s ease-out; }
.munieco--festeja .munieco__capa--brazo-izq { animation: avatar-festeja-izq 0.95s ease-out; }

@keyframes avatar-festeja-der {
  0%   { transform: rotate(0deg); }
  30%  { transform: rotate(-26deg); }
  60%  { transform: rotate(-20deg); }
  100% { transform: rotate(0deg); }
}
@keyframes avatar-festeja-izq {
  0%   { transform: rotate(0deg); }
  30%  { transform: rotate(26deg); }
  60%  { transform: rotate(20deg); }
  100% { transform: rotate(0deg); }
}

/* Saltar. El achatarse antes de despegar y al caer es lo que le da peso; sin
   eso es un dibujo que sube y baja. */
.munieco--salta { animation: avatar-salta 0.95s cubic-bezier(0.34, 1.3, 0.64, 1); }

@keyframes avatar-salta {
  0%   { transform: translate3d(0, 0, 0)        scale3d(1, 1, 1); }
  18%  { transform: translate3d(0, 0.18rem, 0)  scale3d(1.1, 0.86, 1); }
  45%  { transform: translate3d(0, -1.5rem, 0)  scale3d(0.93, 1.12, 1); }
  72%  { transform: translate3d(0, 0.12rem, 0)  scale3d(1.08, 0.9, 1); }
  100% { transform: translate3d(0, 0, 0)        scale3d(1, 1, 1); }
}

/* Asentir: dos cabezadas cortas. Como el personaje es todo cabeza, la
   cabezada es del cuerpo entero inclinándose hacia adelante. */
.munieco--asiente { animation: avatar-asiente 0.9s ease-in-out; }

@keyframes avatar-asiente {
  0%, 100% { transform: translate3d(0, 0, 0)       rotate(0deg); }
  20%      { transform: translate3d(0, 0.28rem, 0) rotate(3.5deg); }
  40%      { transform: translate3d(0, 0, 0)       rotate(0deg); }
  60%      { transform: translate3d(0, 0.28rem, 0) rotate(3.5deg); }
  80%      { transform: translate3d(0, 0, 0)       rotate(0deg); }
}

/* Negar: dos sacudidas de costado. */
.munieco--niega { animation: avatar-niega 0.85s ease-in-out; }

@keyframes avatar-niega {
  0%, 100% { transform: rotate(0deg); }
  18%      { transform: rotate(-4.5deg); }
  42%      { transform: rotate(4.5deg); }
  66%      { transform: rotate(-3deg); }
  84%      { transform: rotate(2deg); }
}

/* Temblar: cuando algo sale mal. Rápido y chico. */
.munieco--tiembla { animation: avatar-tiembla 0.55s linear; }

@keyframes avatar-tiembla {
  0%, 100%          { transform: translate3d(0, 0, 0); }
  10%, 30%, 50%, 70% { transform: translate3d(-0.14rem, 0, 0); }
  20%, 40%, 60%, 80% { transform: translate3d(0.14rem, 0, 0); }
}

/* Estirarse: se despereza, con los ojos cerrados todo el rato. Es el gesto
   largo, para cuando hace un rato que nadie lo toca. */
.munieco--estira { animation: avatar-estira 1.9s ease-in-out; }
.munieco--estira .munieco__capa--brazo-der { animation: avatar-estira-der 1.9s ease-in-out; }
.munieco--estira .munieco__capa--brazo-izq { animation: avatar-estira-izq 1.9s ease-in-out; }
.munieco--estira .munieco__capa--parpado-izq,
.munieco--estira .munieco__capa--parpado-der { animation: avatar-ojos-cerrados 1.9s ease-in-out; }

@keyframes avatar-estira {
  0%, 100% { transform: translate3d(0, 0, 0)        scale3d(1, 1, 1); }
  45%      { transform: translate3d(0, -0.3rem, 0)  scale3d(0.94, 1.09, 1); }
  70%      { transform: translate3d(0, 0.1rem, 0)   scale3d(1.04, 0.95, 1); }
}
@keyframes avatar-estira-der {
  0%, 100% { transform: rotate(0deg); }
  45%      { transform: rotate(-30deg); }
}
@keyframes avatar-estira-izq {
  0%, 100% { transform: rotate(0deg); }
  45%      { transform: rotate(30deg); }
}
@keyframes avatar-ojos-cerrados {
  0%        { transform: scaleY(0); }
  14%, 72%  { transform: scaleY(1); }
  100%      { transform: scaleY(0); }
}

.avatar__munieco:hover  { transform: translateY(-2px) scale(1.03); }
.avatar__munieco:active { transform: translateY(0) scale(0.97); }
.avatar__munieco:focus-visible {
  outline: 3px solid var(--brand-primary);
  outline-offset: 4px;
}

/* El saltito al cambiar de cara: se achata, despega y vuelve. Es la
   diferencia entre una imagen que se reemplaza y un personaje que reacciona.
   Va en la escena y no en las capas para no pelearse con el respirar. */
.avatar__escena--cambia {
  transform-origin: 50% 100%;
  animation: avatar-golpe 0.5s var(--transition-spring);
}

@keyframes avatar-golpe {
  0%   { transform: translate3d(0, 0, 0)        scale3d(1, 1, 1); }
  22%  { transform: translate3d(0, 0.1rem, 0)   scale3d(1.08, 0.9, 1); }
  55%  { transform: translate3d(0, -0.5rem, 0)  scale3d(0.95, 1.07, 1); }
  100% { transform: translate3d(0, 0, 0)        scale3d(1, 1, 1); }
}

/* ── El globo ──────────────────────────────────────────────────────── */

.avatar__globo {
  order: -1; /* arriba del muñeco */
  position: relative;
  max-width: min(19rem, calc(100vw - 2 * var(--avatar-aire) - 1rem));
  padding: 0.85rem 1rem;
  border-radius: 1.1rem;
  border: 1px solid rgba(14, 164, 207, 0.16);

  /* Tres capas de superficie: el blanco, un velo del cian de marca arriba
     —que es lo que lo despega del paisaje— y la sombra teñida. */
  background:
    linear-gradient(180deg, rgba(14, 164, 207, 0.06), rgba(255, 255, 255, 0) 60%),
    #fff;
  box-shadow:
    0 1px 2px rgba(6, 95, 117, 0.08),
    0 10px 26px -8px rgba(14, 164, 207, 0.32),
    0 24px 52px -16px rgba(6, 95, 117, 0.24);

  transform-origin: calc(var(--avatar-alto) * 0.38) bottom;
  transition:
    opacity 0.22s ease,
    transform 0.34s var(--transition-spring);
}

.avatar[data-abierto='false'] .avatar__globo {
  opacity: 0;
  transform: translate3d(0, 0.5rem, 0) scale(0.92);
  pointer-events: none;
}

.avatar[data-abierto='true'] .avatar__globo {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

/* La colita del globo, apuntando al muñeco. Es un cuadrado girado con las dos
   mismas caras que el globo, tapado arriba por el propio globo. */
.avatar__globo::after {
  content: '';
  position: absolute;
  /* Apunta al cuerpo del personaje, que está centrado en su marco. */
  left: calc(var(--avatar-alto) * 0.38);
  bottom: -0.36rem;
  width: 0.72rem;
  height: 0.72rem;
  background: #fff;
  border-right: 1px solid rgba(14, 164, 207, 0.16);
  border-bottom: 1px solid rgba(14, 164, 207, 0.16);
  transform: rotate(45deg);
}

.avatar__texto {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--text-on-light);
}

.avatar__texto[hidden] { display: none; }

/* Los tres puntos de "pensando". Es el único momento en que el globo se
   queda abierto sin decir nada, y sin señal parece colgado. */
.avatar__globo[data-pensando='true'] .avatar__texto::after {
  content: '';
  display: inline-block;
  width: 0.2rem;
  height: 0.2rem;
  margin-left: 0.35rem;
  border-radius: 50%;
  background: var(--brand-primary);
  animation: avatar-late 1.1s ease-in-out infinite;
}

@keyframes avatar-late {
  0%, 100% { opacity: 0.25; transform: translate3d(0, 0, 0); }
  50%      { opacity: 1;    transform: translate3d(0, -0.15rem, 0); }
}

/* ── El campo para preguntar ───────────────────────────────────────── */

.avatar__consulta {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.7rem;
  padding-top: 0.7rem;
  border-top: 1px solid rgba(14, 164, 207, 0.14);
}

.avatar__consulta[hidden] { display: none; }

/* La etiqueta la necesita el lector de pantalla; en pantalla alcanza con el
   placeholder, que ya dice de qué va. */
.avatar__etiqueta {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.avatar__campo {
  flex: 1;
  min-width: 0;
  padding: 0.5rem 0.7rem;
  border: 1px solid rgba(14, 164, 207, 0.28);
  border-radius: 0.65rem;
  background: var(--bg-light);
  font-family: var(--font-body);
  font-size: 0.88rem;
  color: var(--text-on-light);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.avatar__campo::placeholder { color: var(--text-muted); opacity: 0.75; }

.avatar__campo:focus-visible {
  outline: none;
  border-color: var(--brand-primary);
  box-shadow: 0 0 0 3px rgba(14, 164, 207, 0.22);
}

.avatar__enviar {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  flex: none;
  border: 0;
  border-radius: 0.65rem;
  background: var(--brand-primary);
  color: #fff;
  cursor: pointer;
  transition: transform 0.22s var(--transition-spring), background-color 0.22s ease;
}

.avatar__enviar:hover  { background: var(--brand-dark); transform: scale(1.06); }
.avatar__enviar:active { transform: scale(0.94); }
.avatar__enviar:focus-visible {
  outline: 3px solid var(--brand-dark);
  outline-offset: 2px;
}

/* ── El botón de cerrarlo ──────────────────────────────────────────── */

.avatar__cerrar {
  position: absolute;
  top: -0.3rem;
  right: -0.3rem;
  display: grid;
  place-items: center;
  width: 1.55rem;
  height: 1.55rem;
  border: 1px solid rgba(14, 164, 207, 0.2);
  border-radius: 50%;
  background: #fff;
  color: var(--brand-dark);
  cursor: pointer;
  box-shadow: 0 2px 8px -2px rgba(6, 95, 117, 0.3);
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.2s ease, transform 0.24s var(--transition-spring),
              background-color 0.2s ease;
}

/* Aparece cuando el visitante se acerca al personaje. Siempre visible sería
   un aspa flotando sobre el dibujo; escondido para siempre sería un avatar
   que no se puede sacar. En pantalla táctil no hay hover, así que ahí se
   muestra desde el arranque. */
.avatar:hover .avatar__cerrar,
.avatar:focus-within .avatar__cerrar {
  opacity: 1;
  transform: scale(1);
}

.avatar__cerrar:hover  { background: var(--bg-light); }
.avatar__cerrar:active { transform: scale(0.9); }
.avatar__cerrar:focus-visible {
  outline: 3px solid var(--brand-primary);
  outline-offset: 2px;
}

@media (hover: none) {
  .avatar__cerrar { opacity: 1; transform: scale(1); }
}

/* ── Celular ───────────────────────────────────────────────────────── */

@media (max-width: 600px) {
  .avatar {
    /* Bastante más chico que en escritorio. En una pantalla de 390 px el
       muñeco de escritorio ocupa un tercio del ancho y se le sienta encima a
       lo que haya abajo de todo; a esta altura queda del orden del botón de
       WhatsApp, que es el otro que flota. */
    --avatar-alto: 6.5rem;
    /* Sube por encima de la barra de confianza y deja libre el pie. */
    bottom: calc(var(--avatar-aire) + 0.5rem);
  }
  .avatar__globo { font-size: 0.9rem; }
}

/* ── Menos movimiento ──────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .avatar,
  .avatar__globo,
  .avatar__munieco,
  .avatar__cerrar,
  .avatar__enviar,
  .avatar__campo {
    transition-duration: 0.01ms;
  }
  .avatar,
  .avatar--presente,
  .avatar[data-abierto='false'] .avatar__globo,
  .avatar[data-abierto='true'] .avatar__globo {
    transform: none;
  }
  /* Se apaga todo lo que respira, se mece, parpadea, salta o mira. El
     personaje queda quieto y entero: en reposo ninguna capa está corrida de
     su lugar, así que apagar las animaciones lo deja igual que la estampa.

     Va con !important, que en esta hoja no se usa en ningún otro lado. Es a
     propósito: las reglas de cada gesto son más específicas que estas, y la
     mirada la escribe el JS como estilo en línea. Acá no hay nada que
     matizar —el visitante pidió que no se mueva— así que gana esto y listo.

     Los párpados quedan afuera de la regla de transform: tienen que seguir
     aplastados en cero, o los ojos aparecen tapados por dos pastillas. */
  .munieco,
  .munieco__capa,
  .munieco__pupila,
  .avatar__pose,
  .avatar__escena,
  .avatar__globo[data-pensando='true'] .avatar__texto::after {
    animation: none !important;
  }
  .munieco,
  .avatar__pose,
  .avatar__escena,
  .munieco__pupila,
  .munieco__capa--brazo-izq,
  .munieco__capa--brazo-der,
  .munieco__capa--espuma,
  .munieco__capa--boca {
    transform: none !important;
  }
}
