/*
Theme Name: Vinculare
Description: Tema a medida para Vinculare, gabinete de psicología y psiquiatría. Landing informativa con animaciones GSAP/ScrollTrigger.
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: vinculare
*/

/* Reset básico */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* Bug real, reportado en móvil (iPhone): al llegar al final de las 3
     secciones "telón" de Inicio (ver animateFullscreenSnap en
     animations.js) y seguir haciendo scroll hacia el footer, la página
     "rebotaba" de vuelta a la última sección en vez de seguir. Causa:
     el gesto de rebote elástico nativo del navegador al llegar al
     final real de la página (el "estirón" que hace iOS/Android al
     tocar el límite) cruza de nuevo hacia arriba el umbral de
     ScrollTrigger de esa última sección, disparando su "onEnterBack"
     como si el usuario hubiera dado marcha atrás de verdad.
     overscroll-behavior-y:none desactiva ese rebote elástico del
     navegador en los bordes del documento — sin él, no hay ningún
     cruce falso que reactivar. No afecta al scroll normal del resto de
     la página, solo a ese gesto de "tirar de más" en los extremos. */
  overscroll-behavior-y: none;
}

/* Barra de scroll a medida, en toda la web (la de la página y la de
   cualquier contenedor con su propio scroll interno, como el texto
   del diálogo de "Leer más" en Conócenos): finita, rectangular (sin
   esquinas redondeadas ni sombra), siempre fondo niebla y barrita
   oliva — colores fijos, no dependen de en qué página/zona esté
   (se probó a seguir el tinte de cada página con una variable CSS,
   pero al ser un elemento tan fino la diferencia era imperceptible y
   no compensaba la complejidad). Firefox usa
   scrollbar-width/scrollbar-color (heredable, por eso va en *);
   Chrome/Edge/Safari usan los pseudo-elementos ::-webkit-scrollbar-*,
   que hay que declarar en cada elemento (de ahí el selector * en vez
   de solo html/body).
   Desde Chrome 121, si un elemento tiene scrollbar-width/scrollbar-color
   con un valor no inicial, Chrome descarta TODAS sus reglas
   ::-webkit-scrollbar-* (ancho, sin flechas, colores) y usa su propio
   "thin" nativo de ancho fijo — por eso scrollbar-width/scrollbar-color
   va dentro de @supports not selector(::-webkit-scrollbar): así solo
   lo ve Firefox (que no soporta ::-webkit-scrollbar), y Chrome/Edge/
   Safari siguen aplicando el estilo fino y sin flechas de más abajo. */
:root {
  /* Ancho real de la barra en Chrome/Edge/Safari — variable en vez de
     un valor repetido, para que el hueco de separación de
     .team-bio-dialog__layout (ver más abajo) mida siempre exactamente
     lo mismo que la barra, se toque un valor u otro. Firefox no tiene
     forma de igualarse a esto: scrollbar-width solo acepta
     thin/auto/none, sin control en px. */
  --scrollbar-width: 3.75px;
}

@supports not selector(::-webkit-scrollbar) {
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--color-oliva) var(--color-niebla);
  }
}

*::-webkit-scrollbar {
  width: var(--scrollbar-width);
  height: var(--scrollbar-width);
}

*::-webkit-scrollbar-track {
  background: var(--color-niebla);
  margin: 0;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

*::-webkit-scrollbar-thumb {
  background-color: var(--color-oliva);
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

*::-webkit-scrollbar-corner {
  background: var(--color-niebla);
}

/* Sin flechas en los extremos — hay que anular cada estado por
   separado (:single-button, :double-button, :start, :end,
   :increment, :decrement); con solo *::-webkit-scrollbar-button
   Chrome sigue dibujando la flecha en algunos casos. */
*::-webkit-scrollbar-button,
*::-webkit-scrollbar-button:single-button,
*::-webkit-scrollbar-button:double-button,
*::-webkit-scrollbar-button:start,
*::-webkit-scrollbar-button:end,
*::-webkit-scrollbar-button:increment,
*::-webkit-scrollbar-button:decrement {
  display: none !important;
  width: 0 !important;
  height: 0 !important;
  background: transparent !important;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* En Inicio, el color de fondo del body se anima con GSAP/ScrollTrigger
   según la zona por la que se va scrolleando (ver animations.js) —
   sin transición CSS aquí para no competir con esa animación. */
body {
  margin: 0;
  font-family: var(--font-texto);
  color: var(--color-berenjena);
  background-color: var(--color-niebla);
  line-height: 1.5;
}

/* Fondo limpio por página (ver header.php): toda la página, no una
   franja aparte. .site-header hereda este mismo color
   (background-color:inherit), así que no hace falta tocarlo aquí.
   bg-tint-lavanda/bg-tint-pistacho ya no las asigna ninguna página
   (Servicios y las 15 hijas de Qué tratamos comparten ahora este mismo
   tinte melocotón, ver header.php) — --color-lavanda-tint/
   --color-pistacho-tint se dejan definidas en tokens.css por si hace
   falta variedad de tinte en el futuro, pero estas dos reglas de fondo
   ya no tenían ningún sitio que las usara. */
body.bg-tint-melocoton {
  background-color: var(--color-melocoton-tint);
}

/* Conócenos, a petición expresa: melocotón "casi sin aclarar" en vez
   del tinte pálido de arriba — el mínimo aclarado posible que deje el
   texto del menú superior (berenjena, sin --zone-text en esta página)
   legible. El melocotón de marca SIN diluir ya da 5.2:1 contra
   berenjena (por encima del 4.5:1 mínimo AA), y diluirlo con blanco
   solo AUMENTA ese contraste (nunca lo empeora) — así que el propio
   color de marca, tal cual, ya es el punto de "mínimo aclarado que
   sigue siendo legible": no hace falta aclarar nada más. */
body.bg-tint-melocoton-fuerte {
  background-color: var(--color-melocoton);
}

/* Contacto, a petición expresa: mismo criterio que bg-tint-melocoton-fuerte
   de arriba (color de marca SIN diluir) pero en pistacho — pistacho contra
   berenjena da ~6:1, por encima del 4.5:1 mínimo AA, así que tampoco hace
   falta aclarar nada. */
body.bg-tint-pistacho-fuerte {
  background-color: var(--color-pistacho);
}

/* Qué tratamos (solo la página índice, ver header.php) — a petición
   expresa, para probar: fondo oliva SIN diluir, la única página fuera
   de Inicio con un tinte OSCURO en vez de uno claro, así que (a
   diferencia de las reglas de arriba) aquí SÍ hace falta voltear el
   color de texto del body entero — el resto de páginas dejan el
   default de <body> (berenjena, ver arriba) sin tocarlo porque sus
   tintes son todos claros. niebla-clara, no blanco puro ni niebla
   base: mismo criterio que --color-niebla-clara en tokens.css (el
   niebla base falla AA de texto normal sobre oliva). */
body.bg-tint-oliva {
  background-color: var(--color-oliva);
  color: var(--color-niebla-clara);
}

/* El menú hereda el fondo (background-color:inherit en .site-header,
   ver más abajo) pero NO el color de texto — .site-header fija el
   suyo propio (var(--zone-text, var(--color-berenjena)), pensado para
   Inicio) y aquí, fuera de Inicio, --zone-text nunca está definida,
   así que sin este override el menú se quedaría en el berenjena de
   respaldo, ilegible sobre oliva. */
body.bg-tint-oliva .site-header {
  color: var(--color-niebla-clara);
}

/* .page-header__intro fija su propio berenjena (ver más abajo, pensado
   para el resto de páginas, todas con fondo claro) — aquí necesita el
   mismo volteo que el body. */
body.bg-tint-oliva .page-header__intro {
  color: var(--color-niebla-clara);
}

/* Contorno de foco: el berenjena por defecto (ver el bloque grande más
   abajo) da solo 2.36:1 contra oliva, por debajo del 3:1 mínimo AA
   para componentes de interfaz (WCAG 2.2, "non-text contrast") —
   apenas se vería. Mismo criterio que ya usa Inicio para su propia
   zona oscura, ver [data-bg-zone="berenjena"] a:focus-visible más
   abajo. */
body.bg-tint-oliva a:focus-visible,
body.bg-tint-oliva button:focus-visible {
  outline-color: var(--color-niebla-clara);
}

/* Servicios — a petición expresa, para probar: "todo el fondo de la
   página fuese en lavanda con todo el texto en blanco". Mismo patrón
   que body.bg-tint-oliva justo arriba (fondo OSCURO sin diluir, texto
   niebla-clara), pero lavanda es el MÁS CLARO de los tres colores de
   marca lo bastante oscuros para texto claro encima (berenjena/oliva/
   lavanda, ver brandbook-vinculare) — pasa AA con niebla-clara encima
   (5.02:1, la misma cifra que ya usa Inicio para su propia zona oscura
   en .section--about-cta) pero NO con berenjena (solo 2.16:1): a
   diferencia de oliva, aquí el respaldo de var(--zone-text, ...) que
   usan varios componentes de la web (pensado para Inicio, con
   berenjena de vuelta) NO sirve de nada — hay que voltear cada
   componente que dé por hecho un fondo claro, uno a uno, ver los
   bloques de más abajo.

   Esta clase sigue siendo el respaldo sin JS/con prefers-reduced-motion
   (página lavanda de principio a fin, como aquí) pero, a petición
   expresa, YA NO es el punto de partida real de la página con JS
   activo: animateBgFade() en animations.js arranca la cadena en niebla/
   berenjena/pistacho (cabecera + Psicología/Psiquiatría) y funde a este
   mismo lavanda/niebla-clara justo al llegar a "Áreas de atención" (ver
   data-bg-fade="lavanda" ahí, page-servicios.php) — el primer eslabón
   de la cadena que antes solo cubría FAQ/Tarifas. `color` aquí y en
   .site-header/.page-header__intro/el contorno de foco de más abajo
   pasan a leer var(--zone-text, ...) en vez del niebla-clara fijo de
   siempre, para que esa animación (que solo toca --zone-text, nunca
   estas reglas de clase) los pueda ir mezclando; el respaldo
   (niebla-clara) dentro del var() es exactamente el valor fijo de
   antes, así que sin JS el resultado no cambia. */
body.bg-tint-lavanda {
  background-color: var(--color-lavanda);
  color: var(--zone-text, var(--color-niebla-clara));
}

/* Corrige un parpadeo real reportado al cargar/recargar Servicios (o
   entrar desde el menú): "por un momento se ve lavanda antes de
   ponerse el fondo niebla correcto". Causa — ya documentada arriba,
   "YA NO es el punto de partida real de la página con JS activo":
   esta clase pinta lavanda de inmediato (CSS puro, en el primer
   frame), pero con JS activo el punto de partida REAL a scroll 0 es
   niebla (animateBgFade() en animations.js no llega a correr y
   sobreescribir background-color hasta que el script se carga/ejecuta,
   unos frames más tarde) — ese hueco entre "pinta lavanda" y "JS
   corrige a niebla" es el parpadeo. @media (prefers-reduced-motion:
   no-preference) en vez de arreglarlo por JS (adelantar el cálculo no
   evitaría el hueco, solo lo acortaría): así el niebla correcto se
   pinta ya en el primer frame, sin esperar a ningún script, y SOLO
   para el mismo caso en el que animateBgFade() va a correr de verdad
   — con prefers-reduced-motion activado (donde animateBgFade() ni
   se ejecuta, ver el bloque grande al principio de animations.js) el
   body se queda en el lavanda de la regla base de arriba, tal como se
   pensó como respaldo. */
@media (prefers-reduced-motion: no-preference) {
  body.bg-tint-lavanda {
    background-color: var(--color-niebla);
  }
}

body.bg-tint-lavanda .site-header {
  color: var(--zone-text, var(--color-niebla-clara));
}

body.bg-tint-lavanda .page-header__intro {
  color: var(--zone-text, var(--color-niebla-clara));
}

/* Contorno de foco: el berenjena por defecto da solo 2.16:1 contra
   lavanda, por debajo del 3:1 mínimo AA para componentes de interfaz
   — igual que ya le pasaba a oliva (2.36:1), apenas se vería.
   var(--zone-text, ...), no el niebla-clara fijo de antes — mismo
   motivo que las reglas de arriba: en la zona niebla/berenjena inicial
   (antes de "Áreas de atención") el contorno berenjena por defecto SÍ
   pasa AA de sobra contra niebla, así que aquí también tiene que poder
   seguir a --zone-text en vez de quedarse en blanco fijo. */
body.bg-tint-lavanda a:focus-visible,
body.bg-tint-lavanda button:focus-visible,
body.bg-tint-lavanda summary:focus-visible {
  outline-color: var(--zone-text, var(--color-niebla-clara));
}

/* Mismo parpadeo/mismo arreglo que el fondo del body más arriba —
   estos tres --zone-text tenían el respaldo (niebla-clara, pensado
   para lavanda de fondo) sin actualizar: con el fondo ya corregido a
   niebla en el primer frame (arriba), un texto/contorno CLARO ahí
   encima habría sido casi invisible hasta que animateBgFade() fijara
   --zone-text de verdad — el mismo hueco de antes, solo que de texto
   en vez de fondo. berenjena, no niebla-clara: es el color de texto
   correcto sobre niebla (zona CLARA, ver el porqué en
   animateSectionBackgrounds()/lightZones en animations.js). Con
   prefers-reduced-motion (fondo lavanda de la regla base, sin este
   override) el respaldo se queda en niebla-clara, correcto ahí. */
@media (prefers-reduced-motion: no-preference) {
  body.bg-tint-lavanda .site-header,
  body.bg-tint-lavanda .page-header__intro {
    color: var(--zone-text, var(--color-berenjena));
  }

  body.bg-tint-lavanda a:focus-visible,
  body.bg-tint-lavanda button:focus-visible,
  body.bg-tint-lavanda summary:focus-visible {
    outline-color: var(--zone-text, var(--color-berenjena));
  }
}

/* .btn--secondary es un botón de contorno en el resto del tema (fondo
   transparente, borde/texto en berenjena) — aquí, a petición expresa,
   pasa a ser un relleno sólido blanco (niebla-clara) con el texto en
   lavanda, a juego con el propio fondo de la página. border-color iva
   al mismo blanco que el fondo (no currentColor/lavanda): así no
   dibuja un contorno lavanda alrededor del botón, y el grosor de 2px
   ya reservado por .btn (ver más abajo) no cambia el tamaño del botón
   al pasar de esta regla al hover.
   El hover/foco se repite aquí, EXACTAMENTE igual que el de
   .btn--secondary:hover sin escopar (mismo relleno berenjena sólido +
   texto niebla) — a petición expresa, "que el hover lo siga haciendo
   igual". No basta con dejar que el hover sin escopar de más abajo
   "gane" solo: body.bg-tint-lavanda .btn--secondary tiene más
   especificidad (dos clases + el tipo "body") que .btn--secondary:hover
   (dos clases), así que sin repetirlo aquí el relleno blanco de
   reposo se quedaría fijo también en hover, tapando el cambio a
   berenjena. */
body.bg-tint-lavanda .btn--secondary {
  background-color: var(--color-niebla-clara);
  color: var(--color-lavanda);
  border-color: var(--color-niebla-clara);
}

body.bg-tint-lavanda .btn--secondary:hover,
body.bg-tint-lavanda .btn--secondary:focus-visible {
  background-color: var(--color-berenjena);
  /* Blanco, no niebla — a petición expresa, "todos los botones con
     fondo berenjena, texto en blanco" (ver --color-blanco en
     tokens.css). */
  color: var(--color-blanco);
  border-color: transparent;
}

/* .btn--primary ("Pide tu primera cita", en Tarifas) — mismo cambio y
   mismo motivo que .btn--secondary justo arriba: relleno sólido
   blanco con texto lavanda en reposo, a petición expresa, con el
   hover/foco (berenjena sólido + texto niebla) repetido aquí para que
   no deje de invertir al pasar el ratón — .btn--primary no fija
   border-color propio (se queda transparente heredado de .btn), así
   que aquí no hace falta tocarlo. */
body.bg-tint-lavanda .btn--primary {
  background-color: var(--color-niebla-clara);
  color: var(--color-lavanda);
}

body.bg-tint-lavanda .btn--primary:hover,
body.bg-tint-lavanda .btn--primary:focus-visible {
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
}

/* .service-card__answer ul YA NO necesita el volteo a niebla-clara que
   llevaba aquí: ese texto vivía antes directamente sobre el lavanda
   oscuro de la página (el desplegable in-place); ahora vive dentro de
   la "ventanita" flotante (.service-bio-dialog, ver más abajo), una
   tarjeta melocotón-tint clara igual que las de Conócenos — el lavanda
   fijo de base en .service-card__answer ul ya pasa AA ahí tal cual,
   igual que en el resto de escenarios donde se usa ese mismo texto. */

/* FAQ: línea divisoria, icono +/− e texto de la respuesta
   (.faq-item__answer fija lavanda fijo — invisible sobre el propio
   lavanda del fondo de esta página sin este volteo). El enlace dentro
   de una respuesta
   (.faq-item__answer a, la política de cancelación) fija berenjena —
   aquí pasa a niebla-clara también; sigue distinguiéndose del resto
   del párrafo por su propio font-weight:600 y subrayado, no solo por
   color, así que no hace falta un tercer color solo para el enlace. */
/* var(--zone-text, ...), NO el niebla-clara fijo que llevaba antes —
   a petición expresa ("que las líneas separadoras de FAQ también
   hagan la transición de color junto con el texto"): sin esto, estas
   líneas se quedaban fijas en niebla-clara durante todo el scrub de
   FAQ→Tarifas (--zone-text pasando de niebla-clara a berenjena, ver
   data-zone-text="berenjena" en .section--pricing, page-servicios.php)
   mientras el resto de texto sin color propio (los h3 de cada
   pregunta, ver .faq-item__question h3 más abajo, sin color propio,
   heredan var(--zone-text, ...) del body) sí iba mezclándose en
   tiempo real — un desajuste visible entre línea y texto según se
   acercaba Tarifas. Mismo mecanismo ya en uso en
   body.bg-tint-lavanda .pricing-list__item, más abajo. */
body.bg-tint-lavanda .faq-item,
body.bg-tint-lavanda .faq-item:first-child {
  border-color: color-mix(in srgb, var(--zone-text, var(--color-niebla-clara)) 25%, transparent);
}

/* var(--zone-text, ...), NO el niebla-clara fijo que llevaba antes —
   mismo motivo/mismo mecanismo que .faq-item más arriba ("que las
   líneas separadoras de FAQ también hagan la transición de color
   junto con el texto"): sin esto el icono +/− se quedaba fijo en
   niebla-clara (blanco) durante todo el scrub FAQ→Tarifas mientras el
   resto (línea divisoria, texto de la pregunta) sí iba mezclándose. */
body.bg-tint-lavanda .faq-item__icon::before,
body.bg-tint-lavanda .faq-item__icon::after {
  background-color: var(--zone-text, var(--color-niebla-clara));
}

/* var(--zone-text, ...), NO el niebla-clara fijo que llevaba antes — a
   petición expresa ("que las respuestas desplegadas de FAQ también
   hagan la transición de color junto con el resto de los textos ahí"):
   mismo mecanismo/mismo motivo que .faq-item y .faq-item__icon aquí
   arriba (la pregunta/línea/icono ya se mezclaban con --zone-text
   durante el scrub FAQ→Tarifas; la respuesta desplegada se quedaba
   fija en niebla-clara, desajustada del resto en cuanto se abría una
   pregunta cerca de Tarifas). */
body.bg-tint-lavanda .faq-item__answer,
body.bg-tint-lavanda .faq-item__answer a {
  color: var(--zone-text, var(--color-niebla-clara));
}

/* Tarifas: .pricing-list__duration, .pricing-note p, .pricing-list__price
   y .pricing-group__title fijan cada uno su propio color base (más
   abajo), así que sin este volteo se quedarían con ese color fijo
   pensado para un fondo claro. var(--zone-text, ...), NO el
   niebla-clara fijo que llevaba antes — a petición expresa ("que el
   texto de Tarifas también pase a berenjena"): con --zone-text ya
   puesta a "berenjena" en este tramo (ver data-zone-text="berenjena"
   en .section--pricing, page-servicios.php), estas cuatro excepciones
   tienen que seguir ese mismo cambio en vez de quedarse coladas en
   niebla-clara — ahí un texto casi blanco sobre el pistacho tan claro
   de este tramo apenas se leería. El respaldo (niebla-clara) es el
   mismo de siempre para prefers-reduced-motion/sin JS (--zone-text sin
   definir en ese escenario, toda la página lavanda de principio a fin,
   donde berenjena SÍ fallaría el contraste — 2.16:1). .pricing-list__title
   no lleva color propio (hereda del body), así que ya se voltea solo
   sin tocarlo aquí. */
body.bg-tint-lavanda .pricing-list__duration,
body.bg-tint-lavanda .pricing-note p,
body.bg-tint-lavanda .pricing-list__price,
body.bg-tint-lavanda .pricing-group__title {
  color: var(--zone-text, var(--color-niebla-clara));
}

/* Mismo volteo que las cuatro excepciones de arriba y por el mismo
   motivo — a petición expresa ("las líneas divisorias de Tarifas
   también en berenjena"): color-mix con niebla-clara se quedaba casi
   invisible sobre el pistacho claro de este tramo (una línea casi
   blanca sobre un fondo casi blanco), igual que le habría pasado al
   texto de arriba sin este mismo cambio. */
body.bg-tint-lavanda .pricing-list__item {
  border-color: color-mix(in srgb, var(--zone-text, var(--color-niebla-clara)) 25%, transparent);
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-titulos);
  /* A petición expresa: EB Garamond solo en su versión Medium (500)
     en toda la web — sin esto, los navegadores ponen negrita por
     defecto en los títulos (700), y Google Fonts ahora solo carga el
     peso 500 (ver functions.php), así que sin este font-weight
     explícito el navegador tendría que "inventarse" una negrita
     sintética en vez de usar una versión real de la fuente. */
  font-weight: 500;
  line-height: 1.2;
  margin: 0 0 0.5em;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: inherit;
}

/* Accesibilidad: enlace "saltar al contenido" */
.skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  background: var(--color-berenjena);
  color: #fff;
  padding: 0.75em 1.25em;
  z-index: 1000;
  transition: top 0.2s ease;
}

.skip-link:focus {
  top: 0;
}

/* Foco visible en todos los elementos interactivos (WCAG 2.2 AA).
   Berenjena, no melocotón: melocotón da 1.74:1 contra niebla y 2.2:1
   contra blanco, ambos por debajo del 3:1 mínimo para componentes de
   interfaz — el foco por defecto apenas se veía en Servicios,
   Conócenos, Blog, Qué tratamos y el formulario de contacto (todo lo
   que no tiene una anulación más específica para zonas oscuras). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--color-berenjena);
  outline-offset: 2px;
}

/* .section--about-cta (única zona oscura que queda en Inicio, ver
   style.css) ya fija su propio color de texto — este contorno de foco
   en blanco puro es lo único que sigue haciendo falta aparte: el
   contorno por defecto es melocotón, con poco contraste sobre fondo
   oscuro; blanco puro vale igual aquí (es un anillo fino, no texto,
   así que basta con 3:1, no con el 4.5:1 que pediría texto). */
[data-bg-zone="berenjena"] a:focus-visible {
  outline-color: #fff;
}

/* Cursor personalizado (solo dispositivos con ratón, ver animations.js) */
.cursor-dot,
.cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 9999;
}

.cursor-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--color-melocoton);
}

.cursor-ring {
  /* Trazo dibujado a mano (ver header.php), no un círculo geométrico,
     para que encaje con el estilo de las ilustraciones del hero. */
  width: 44px;
  height: 44px;
  fill: none;
  stroke: var(--color-melocoton);
  stroke-width: 4;
  overflow: visible;
  transition: scale 0.25s ease, stroke 0.25s ease;
}

.cursor-ring.is-active {
  scale: 1.5;
  stroke: var(--color-berenjena);
}

html.has-custom-cursor,
html.has-custom-cursor a,
html.has-custom-cursor button {
  cursor: none;
}

html.has-custom-cursor .cursor-dot,
html.has-custom-cursor .cursor-ring {
  opacity: 1;
}

/* Con un <dialog> abierto (ver animations.js), el navegador lo pinta
   en el "top layer", por encima de CUALQUIER z-index del documento
   normal — el punto/aro del cursor personalizado (por altos que
   tengan el z-index) quedan tapados detrás, así que no se ve ningún
   cursor en absoluto mientras el diálogo está abierto. Aquí se
   recupera el cursor nativo del sistema mientras dure — pero SOLO en
   html.dialog-open a secas, ya NO en "html.dialog-open a"/"html.
   dialog-open button" (quitados): con el cursor personalizado
   desactivado (ver el "cursor nativo del sistema en toda la web" en
   animations.js), esas dos líneas de más ya no tenían nada que
   restaurar y en su lugar causaban un bug real, reportado con
   capturas — forzaban cursor:auto en CUALQUIER botón/enlace dentro de
   un diálogo abierto (más específico que ".btn { cursor: pointer }",
   ver ahí), y el navegador resuelve ese "auto" ahí dentro como cursor
   de texto en vez de la manita, aunque el propio enlace/botón siguiera
   funcionando con normalidad al pulsarlo. */
/* Con la tarjeta flotante abierta, la página de fondo no debe poder
   hacer scroll ni enseñar su propia barra: overflow:hidden en <html>
   bloquea el scroll del documento entero mientras dure — el
   <dialog>/su tarjeta interior siguen haciendo su propio scroll con
   toda normalidad, al vivir en el "top layer", ajenos al overflow de
   <html>. Misma clase, puesta/quitada por DOS sitios distintos —
   animations.js (el diálogo de biografías de Conócenos) y
   hoja-a-mesa.js (las tarjetas de las ilustraciones que caen en
   Inicio) — a petición expresa, "no tiene sentido" que se pudiera
   seguir haciendo scroll por detrás de NINGÚN <dialog> del sitio:
   showModal() por sí solo no lo impide, solo bloquea foco/clic. */
html.dialog-open {
  overflow: hidden;
}

html.dialog-open {
  cursor: auto;
}

html.dialog-open .cursor-dot,
html.dialog-open .cursor-ring {
  opacity: 0;
}

/* Sobre la cabecera y el hero (fondo oliva) el cursor cambia a blanco
   para seguir siendo visible. */
html.cursor-on-accent .cursor-dot {
  background-color: #fff;
}

html.cursor-on-accent .cursor-ring {
  stroke: #fff;
}

html.cursor-on-accent .cursor-ring.is-active {
  stroke: var(--color-niebla);
}

/* Cabecera del sitio: siempre pegada arriba (sticky) y con el mismo
   fondo que la zona visible en ese momento (background-color:inherit
   hereda el color en vivo que anima animateSectionBackgrounds() sobre
   <body> — en páginas sin ese sistema se queda en el niebla por
   defecto). El color de texto sigue la variable --zone-text que
   actualiza ese mismo script: niebla-clara en zona oscura
   (oliva/lavanda), berenjena en el resto. El logo hereda este mismo
   color (fill: currentColor en su SVG), así que cambia con el menú.
   SIN transition en "color" a propósito (se probó, ver el porqué
   largo en animateSectionBackgrounds(), animations.js): --zone-text
   ya se actualiza fotograma a fotograma desde JS con su propio
   fundido continuo ligado al scroll real, así que una transición CSS
   encima competía con esa animación en vez de sumarse a ella (cada
   nuevo valor por fotograma reiniciaba su propia transición de 0.25s,
   una carrera de metas móviles que se sentía con retraso/deriva
   respecto al fondo en vez de sincronizada con él). */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--header-height);
  padding: 1rem clamp(1rem, 4vw, 3rem);
  background-color: inherit;
  color: var(--zone-text, var(--color-berenjena));
  /* -webkit-sticky antes de "sticky" — Safari (sobre todo iOS)
     necesitaba históricamente este prefijo para no tratar la
     propiedad entera como inválida y caer a position:static (la
     cabecera dejaría de pegarse arriba en scroll, se iría con el
     resto de la página). Las versiones actuales ya no lo necesitan,
     pero declararlo de más no hace nada en un Safari moderno (que ya
     entiende "sticky" sin prefijo) — cuesta una línea, cubre cualquier
     versión más vieja que quede en uso real. */
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 100;
  /* translateZ(0) — a petición expresa, tras reportarse "al hacer
     scroll en móvil aparece un hueco encima del menú" CON la sesión de
     WordPress iniciada (barra de administración visible). Comprobado
     con un script de prueba (Playwright, simulando la barra de admin
     real de WordPress): el CÁLCULO en sí es correcto — top:46px dejaba
     esta cabecera pegada al borde inferior de la barra de admin en
     TODAS las posiciones de scroll probadas, hueco:0px siempre. Encaja
     con un tipo de bug conocido de Safari/Chrome en móvil, no con un
     error de este CSS: la barra de direcciones del propio navegador se
     esconde al hacer scroll (para dar más pantalla), y tanto ella como
     cualquier elemento position:fixed/sticky de la página (aquí, la
     PROPIA barra de administración de WordPress — position:fixed, ver
     #wpadminbar, fuera del control de este tema) pueden quedarse un
     instante "rezagados" repintándose mientras dura esa animación,
     dejando ver un hueco pasajero justo donde debería estar la barra —
     no un fallo de posición real y permanente, sino un instante de
     descoordinación del propio navegador. translateZ(0) (con
     backface-visibility de refuerzo) es la mitigación estándar
     documentada para esto: obliga a esta cabecera a su propia capa de
     composición en la GPU de antemano, en vez de que el navegador
     decida crearla tarde, a mitad de scroll — puede notarse mejor o
     peor según el dispositivo/navegador exacto, al ser un
     comportamiento del propio sistema, no de este código.
     position:absolute (no fixed) en .main-nav, más abajo: importante
     que siga siendo así — un transform aquí convierte a ESTA cabecera
     en el "containing block" de cualquier descendiente position:fixed
     (rompería el panel de menú a pantalla completa si volviera a ser
     fixed, ver su propio comentario largo). */
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Con sesión iniciada, la barra de admin de WordPress empuja la
   página hacia abajo al cargar (32px, 46px en móvil), pero eso no
   mueve el "top: 0" del sticky — al hacer scroll, la cabecera se pega
   al borde real de la pantalla, debajo de esa barra (que sí se queda
   fija ahí siempre), y parece que "sube" y pierde el hueco de arriba.
   Un visitante sin sesión nunca ve esto: solo afecta a quien gestiona
   el sitio. .admin-bar es la clase que WordPress añade solo al
   <body> cuando la barra está visible. */
body.admin-bar .site-header {
  top: 32px;
}

@media (max-width: 782px) {
  /* Mismo punto de corte que usa WordPress para la barra de admin en
     móvil (más alta: 46px en vez de 32px). */
  body.admin-bar .site-header {
    top: 46px;
  }
}

/* Mientras .section--about-cta está detrás de la cabecera (ver el
   mismo listener de scroll+rAF en animations.js, reutilizado también
   para .section--about más abajo): sin fondo propio — sus dos flores
   decorativas (.about-cta-flor, ver style.css) asoman por encima del
   propio borde superior de la sección, y con la cabecera opaca
   encima la de arriba a la derecha se veía cortada en seco justo
   debajo del menú (mismo motivo, y mismo reporte, que llevó a
   .site-header--over-arena más abajo: "una barrita" tapando el SVG).
   Transparente, se ve la flor entera. Este es el fondo "por defecto"
   mientras la sección entera está detrás de la cabecera — ver
   site-header--over-about-cta-link más abajo para el "fondito" que se
   superpone SOLO cerca de la frase "Conocer nuestro equipo". */
.site-header.site-header--over-about-cta {
  background-color: transparent;
}

/* "Fondito" del menú SOLO mientras la frase-enlace "Conocer nuestro
   equipo" (.about-cta-link-wrap--left, la primera de las dos, la que
   está pegada arriba dentro de .about-cta-links — ver
   flex-direction:column ahí — así que es la que se acerca a la
   cabecera primero al hacer scroll hacia el footer) está a punto de
   quedar detrás del menú — a petición expresa ("que aparezca solo
   cuando el espacio del menú va a entrar en contacto con ESE texto",
   no durante toda la sección): esa frase es del mismo color casi
   blanco que el texto del menú sobre el mismo fondo berenjena, sin
   nada que los separase visualmente. Clase e icono de seguimiento
   aparte (site-header--over-about-cta-link, ver el nuevo tracked{} en
   animations.js) en vez de reutilizar site-header--over-about-cta de
   arriba: esa otra sigue haciendo falta transparente durante TODA la
   sección para el color del texto del menú (ver --zone-text más
   abajo) y para las flores — estrechar esa regla a solo el tramo de
   la primera frase habría dejado el resto de la sección (y la segunda
   frase, "Descubrir cómo podemos ayudarte") sin ese ajuste de color.
   "Cristal" translúcido + desenfocado (mismo tratamiento que
   body.bg-tint-lavanda .site-header en Servicios, ver más abajo), no
   un fondo sólido: por si la flor de arriba-derecha llegase a rozar
   el borde del menú en pantallas más bajas, se leería como un
   desenfoque suave por detrás, no como un corte en seco. var(--live-
   bg, ...) sigue el mismo fundido continuo de
   animateSectionBackgrounds() que ya pinta el body (ver el porqué de
   --zone-text más abajo): con un color fijo aquí, el fondo del menú se
   habría desincronizado del real igual que ya pasaba antes con el
   texto. Va DESPUÉS de site-header--over-about-cta en el archivo a
   propósito: las dos clases conviven a la vez sobre <header> mientras
   dura este tramo (misma especificidad, dos clases cada una), así que
   el orden en la hoja de estilos decide qué "background-color" gana. */
.site-header.site-header--over-about-cta-link {
  background-color: color-mix(in srgb, var(--live-bg, var(--color-berenjena)) 88%, transparent);
}

@supports ( backdrop-filter: blur(1px) ) or ( -webkit-backdrop-filter: blur(1px) ) {
  .site-header.site-header--over-about-cta-link {
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
  }
}

/* Panel del menú hamburguesa en móvil: mismo motivo que
   body.bg-tint-melocoton-fuerte/-oliva/etc. .main-nav más abajo (ver
   ese comentario grande) — hereda background-color:inherit, así que
   sin esto se quedaría con el mismo cristal translúcido+desenfocado de
   la cabecera fina, dejando ver el contenido de la página moviéndose
   por debajo de los enlaces (ilegible). Sólido, no color-mix con
   --live-bg: un panel de navegación real prioriza la legibilidad sobre
   seguir el efecto cristal, igual que las otras páginas "cristal". */
body .site-header.site-header--over-about-cta-link .main-nav {
  background-color: var(--color-berenjena);
}

/* about-cta depende de --zone-text: aquí el berenjena de fondo no es
   un color fijo, lo produce enteramente el fundido continuo de
   animateSectionBackgrounds() mientras se hace scroll. Con un
   niebla-clara fijo aquí (como se probó antes), el texto del menú
   saltaba de golpe al valor final en cuanto la sección empezaba a
   asomar tras la cabecera —el propio cruce de rect.top/headerHeight
   que activa esta clase—, un instante discreto que casi nunca
   coincidía con lo mezclado que estuviera YA el fondo real en ese
   momento exacto: a veces el texto se veía clarear de golpe antes de
   que el fondo hubiera oscurecido lo bastante, otras veces se quedaba
   con un tono a medio camino un rato de más — reportado como que el
   menú "cambia de color" fuera de sincronía con el fondo.
   var(--zone-text, ...) sigue actualizándose en el MISMO fotograma
   que ya pinta document.body (nunca puede desincronizarse EN EL
   TIEMPO de él), pero ya NO es literalmente el mismo número que el
   fondo interpolado — bug real reportado después: mezclar --zone-text
   en RGB entre berenjena y niebla-clara a la vez que el fondo mezcla
   pistacho→berenjena cruza, a mitad de camino, por dos tonos
   intermedios casi igual de oscuros (fondo aclarándose desde
   berenjena, texto oscureciéndose hacia él desde el otro lado) —
   contraste medido de ~1.5:1 justo ahí, el menú "se quedaba en
   berenjena e ilegible" al entrar en esta sección. Ahora
   animateSectionBackgrounds() elige en cada fotograma el extremo
   (berenjena o niebla-clara) con más contraste WCAG contra el fondo
   real de ESE fotograma, así que --zone-text salta entre los dos
   extremos en vez de mezclarse — el "transition: color" de .site-
   header (más arriba) es lo que convierte ese salto discreto en un
   fundido corto y suave, sincronizado con el punto exacto en el que
   el fondo real deja de dar buen contraste con uno y empieza a darlo
   con el otro. El respaldo (berenjena) cubre prefers-reduced-motion/
   sin JS: sin animateSectionBackgrounds(), about-cta se queda con el
   niebla claro por defecto del body (ver el hueco documentado ahí),
   así que ahí hace falta texto OSCURO, no claro.

   La regla de color en sí (.site-header.site-header--over-about-cta)
   vive MÁS ABAJO en este archivo, después de -hero/-arena/-hero-cta —
   a propósito, no por descuido: bug real reportado ("el menú del
   footer... el texto sigue oscuro al llegar a las flores"), confirmado
   con la consola del navegador — .site-header llegaba a la última
   sección (Inicio) con DOS clases de zona puestas a la vez,
   site-header--over-about-cta Y site-header--over-hero-cta (la
   sección justo anterior, pistacho/clara), porque el propio rect de
   .section--hero-cta seguía dando "todavía solapa" (rect.bottom > 0)
   en el navegador real del usuario aun con about-cta ya llenando toda
   la pantalla. Con las cuatro reglas de zona a la misma especificidad
   (dos clases cada una), el ORDEN en la hoja de estilos decide cuál
   "color" gana cuando dos coinciden a la vez — y -hero-cta (más abajo
   en el archivo antes de este cambio) fijaba berenjena FIJO, ganándole
   al var(--zone-text, ...) correcto de about-cta. Resultado: menú
   ilegible (berenjena sobre el propio berenjena de fondo) justo en la
   sección que más lo necesita. Declarando about-cta DESPUÉS de las
   otras tres zonas de Inicio, su color (el único de los cuatro que
   seguía el contraste real en vivo) gana cualquier empate futuro,
   pase lo que pase con el resto de zonas. */
/* Mientras el hero de Inicio está detrás de la cabecera (ver el mismo
   listener de scroll+rAF de arriba) — sin fondo propio, a petición
   expresa, para que .hero__bg-illustration (bailando.svg, ver el
   comentario grande de .hero más abajo) se vea también por debajo del
   menú en vez de quedar cortada en seco por su fondo opaco justo donde
   asoma por arriba (mismo motivo, y mismo reporte, que llevó a
   .site-header--over-arena un poco más abajo). Berenjena, no niebla-
   clara: niebla es una zona CLARA, mismo motivo que en la arena. */
.site-header.site-header--over-hero {
  background-color: transparent;
  color: var(--color-berenjena);
}

.site-header.site-header--over-hero a:focus-visible {
  outline-color: var(--color-berenjena);
}

/* Mientras la arena física de ilustraciones (.section--about) está
   detrás de la cabecera (ver el mismo IntersectionObserver de arriba):
   sin fondo propio, no por un motivo de color (niebla es la misma
   zona clara antes y después, ver el fundido continuo) sino porque
   las 5 ilustraciones "caen" desde fuera de la vista, por encima de
   su propia caja (ver initArena en hoja-a-mesa.js), atravesando de
   verdad la franja de la cabecera mientras "llueven" hacia su sitio.
   Con la cabecera opaca encima, cada una se veía cortada en seco
   justo en su borde inferior — reportado como "aparece una barrita y
   no se ven los SVG ahí". Transparente, se ve la caída completa, sin
   ese corte. Berenjena, no niebla-clara: niebla es una zona CLARA, así
   que le hace falta texto oscuro encima. */
.site-header.site-header--over-arena {
  background-color: transparent;
  color: var(--color-berenjena);
}

.site-header.site-header--over-arena a:focus-visible {
  outline-color: var(--color-berenjena);
}

/* .section--hero-cta, de vuelta en este sistema (ver el porqué largo
   en animations.js, justo encima de donde se añade esta clase al
   array "tracked"): en móvil, la hoja--left asoma bastante por ARRIBA
   del párrafo (ver .hero-outro-hoja--left en su propio breakpoint más
   abajo) — con la cabecera opaca encima se cortaba en seco justo en
   su borde inferior según la sección se metía debajo.

   var(--zone-text, ...), YA NO berenjena fijo (a diferencia de
   .site-header--over-hero/-arena, que sí se quedan fijas — ver el
   porqué de cada una arriba): "pistacho es una zona CLARA" solo es
   cierto en el PROPIO punto de anclaje de hero-cta, no durante todo su
   scroll — animateSectionBackgrounds() funde el fondo real EN
   CONTINUO desde ese pistacho hacia el berenjena de about-cta a lo
   LARGO DE TODO EL ALTO de esta sección (los dos son "stops"
   consecutivos, ver stops[] en animations.js), así que el fondo real
   ya está bastante oscurecido bastante ANTES de llegar siquiera a
   about-cta. Con berenjena fijo aquí (versión anterior), el menú se
   quedaba en texto oscuro sobre un fondo que llevaba un buen tramo
   oscureciéndose de verdad — y, reportado aparte ("el menú no hace la
   transición al mismo ritmo que el fondo"): en cuanto about-cta
   entraba en juego y esta regla dejaba de ganar el empate (ver el
   comentario grande junto a site-header--over-about-cta más abajo),
   --zone-text aparecía de golpe ya con el valor al que hubiera
   llegado mientras tanto SIN QUE EL MENÚ LO HUBIERA MOSTRADO NUNCA —
   un salto instantáneo en vez del fundido gradual que sí se veía en el
   propio fondo. Con --zone-text aquí también, el menú sigue el MISMO
   contraste en vivo, todo el tiempo, sin ninguna costura entre esta
   zona y la siguiente: solo hay UNA fuente de color de texto para las
   dos, así que no puede haber salto entre ellas. El
   respaldo (berenjena) cubre el mismo escenario sin JS/con
   prefers-reduced-motion que el resto de usos de --zone-text: sin
   animateSectionBackgrounds(), esta sección se queda con el fondo
   niebla claro por defecto del body (nunca llega a pintarse pistacho
   de verdad), así que ahí también hace falta texto oscuro. */
.site-header.site-header--over-hero-cta {
  background-color: transparent;
  color: var(--zone-text, var(--color-berenjena));
}

.site-header.site-header--over-hero-cta a:focus-visible {
  outline-color: var(--zone-text, var(--color-berenjena));
}

/* Declarada AQUÍ, después de -hero/-arena/-hero-cta (ver el comentario
   grande junto a --zone-text más arriba en este archivo, junto a
   .site-header.site-header--over-about-cta-link, para el porqué
   exacto): con las cuatro reglas de zona a la misma especificidad, el
   orden en la hoja de estilos decide cuál gana cuando el navegador
   marca dos clases de zona a la vez (bug real confirmado por consola:
   -over-hero-cta seguía puesta, junto a esta, ya con about-cta
   llenando toda la pantalla). -over-hero-cta ya usa var(--zone-text,
   ...) también (ver su propio comentario más arriba, mismo motivo), así
   que hoy por hoy las dos reglas coinciden siempre que ambas clases
   conviven a la vez — este orden ya no cambia el resultado visual, pero
   se deja así (about-cta la última) como red de seguridad ante
   cualquier futura zona de Inicio que vuelva a fijar un color propio
   sin pasar por --zone-text. */
.site-header.site-header--over-about-cta {
  color: var(--zone-text, var(--color-berenjena));
}

.site-header.site-header--over-about-cta a:focus-visible {
  outline-color: var(--zone-text, var(--color-berenjena));
}

/* Conócenos, a petición expresa: el estampado de hojas de fondo
   (.conocenos-hojas-fondo, dentro de #main) tiene que leerse como el
   MISMO fondo que el resto de la página también por debajo del menú,
   no cortado en seco al llegar a la cabecera. Con background-color
   normal (heredado, sólido) la cabecera sticky tapaba las hojas en
   cuanto pasaban por debajo al hacer scroll.
   background-color TRANSLÚCIDO (rgba del propio --color-melocoton) +
   backdrop-filter:blur(), no transparent del todo (versión anterior) —
   a petición expresa, tras reportarse que al hacer scroll el menú
   quedaba encima de las fichas del equipo (y del diálogo de bio de
   cada una, ver .team-bio-dialog más abajo) "solapado y feo, no se
   lee bien": con transparencia total, cualquier cosa que pasara por
   detrás de la cabecera —no solo las hojas decorativas, también fotos
   y tarjetas con su propio color— se veía a través DEL TODO, así que
   el contraste del texto del menú dejaba de estar garantizado en
   cuanto había una ficha (en vez del fondo liso de siempre) justo
   debajo. 88% de opacidad del propio melocotón: ya casi opaco (mismo
   contraste que el fondo sólido de siempre para el texto berenjena del
   menú, sea lo que sea que haya detrás), pero con ese 12% restante +
   el desenfoque de fondo, las hojas (y cualquier otra cosa) se siguen
   intuyendo suavemente A TRAVÉS en vez de cortarse en seco — ni el
   corte duro que se quería evitar en la versión original, ni la
   transparencia total que rompía la legibilidad sobre las fichas.
   @supports: navegadores sin backdrop-filter (raros hoy, pero los
   hay) se quedan con el translúcido sin desenfocar — sigue siendo
   igual de legible, solo que lo que se intuye detrás se ve algo menos
   "esmerilado" y más "rayado". */
body.bg-tint-melocoton-fuerte .site-header {
  background-color: rgb(243 153 93 / 88%);
}

/* Contacto — a diferencia de bg-tint-melocoton-fuerte justo arriba,
   SIN tinte de color: a petición expresa, "que el svg decorativo de
   fondo (grupo.svg) se vea también por debajo del menú, que el fondo
   del menú no lo tape". Un color-mix() al 88% (como el resto de
   páginas "cristal") lo tapaba casi del todo — transparent del todo
   dejando solo el desenfoque (ver @supports más abajo) para que el
   texto del menú se siga leyendo bien cuando pasa algo por detrás,
   sin ocultar la ilustración. */
body.bg-tint-pistacho-fuerte .site-header {
  background-color: transparent;
}

/* Blog y "Qué tratamos" (bg-tint-oliva) — a petición expresa, "que el
   menú adquiera el mismo efecto [cristal con vaho] que tiene el de
   Conócenos": mismo mecanismo que body.bg-tint-melocoton-fuerte justo
   arriba (fondo translúcido del propio color de la página + desenfoque
   detrás, ver el porqué largo ahí), aplicado ahora también aquí.
   color-mix(), no un rgb() calculado a mano como el bloque de arriba
   (escrito antes de que este patrón entrara en el resto del archivo,
   ver .faq-item más abajo para el mismo color-mix ya en uso): mismo
   resultado sin tener que convertir cada hex de marca a decimal. Esta
   página tiene un fondo FIJO (a diferencia de Servicios, ver el bloque
   siguiente), así que basta con el color de marca directo, sin nada
   dinámico. */
body.bg-tint-melocoton .site-header {
  background-color: color-mix(in srgb, var(--color-melocoton-tint) 88%, transparent);
}

body.bg-tint-oliva .site-header {
  background-color: color-mix(in srgb, var(--color-oliva) 88%, transparent);
}

/* Servicios (bg-tint-lavanda) — mismo efecto, pero el fondo de esta
   página YA NO es un color fijo: arranca en niebla y se funde a
   lavanda/berenjena/oliva según el scroll (ver animateBgFade() en
   animations.js). Un translúcido fijo de un solo color se habría
   quedado "enganchado" en el tono equivocado en cuanto el fondo real
   cambiara de color por debajo del menú. --live-bg (fijada por esa
   misma función, en paralelo a backgroundColor, en cada fotograma)
   lleva siempre el mismo color exacto que el body en ese instante, así
   que el cristal del menú sigue al fondo real en todo momento del
   fundido. Respaldo (--color-lavanda) para prefers-reduced-motion/sin
   JS, donde --live-bg nunca llega a definirse: mismo color fijo que ya
   pinta body.bg-tint-lavanda en ese escenario. */
body.bg-tint-lavanda .site-header {
  background-color: color-mix(in srgb, var(--live-bg, var(--color-lavanda)) 88%, transparent);
}

@supports ( backdrop-filter: blur(1px) ) or ( -webkit-backdrop-filter: blur(1px) ) {
  body.bg-tint-melocoton-fuerte .site-header,
  body.bg-tint-pistacho-fuerte .site-header,
  body.bg-tint-melocoton .site-header,
  body.bg-tint-oliva .site-header,
  body.bg-tint-lavanda .site-header {
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
  }
}

/* Bug real, reportado en móvil: .main-nav (el panel del menú
   hamburguesa, ver @media max-width:64rem más abajo) hereda
   background-color:inherit — en estas 5 páginas "cristal" de arriba,
   eso significa que el panel del menú abierto se queda con el MISMO
   88% translúcido + desenfoque que la cabecera compacta, dejando ver
   el contenido de la página moviéndose por debajo de los enlaces de
   navegación (ilegible, "roto"). El cristal tiene sentido en la
   cabecera fina (deja intuir la ilustración/tarjeta de detrás), pero
   no en un panel de navegación real: aquí prioriza la legibilidad
   (mismo criterio que el resto del sitio con el contraste WCAG) sobre
   seguir el efecto — mismo color de cada página, pero sólido, sin
   mezclar con transparencia ni desenfoque. No hace falta media query:
   en escritorio .main-nav es display:contents (ver más abajo), así
   que un background-color aquí no llega a pintar nada. */
body.bg-tint-melocoton-fuerte .main-nav {
  background-color: var(--color-melocoton);
}

body.bg-tint-pistacho-fuerte .main-nav {
  background-color: var(--color-pistacho);
}

body.bg-tint-melocoton .main-nav {
  background-color: var(--color-melocoton-tint);
}

body.bg-tint-oliva .main-nav {
  background-color: var(--color-oliva);
}

body.bg-tint-lavanda .main-nav {
  background-color: var(--live-bg, var(--color-lavanda));
}

/* Mismo parpadeo que el ya corregido en body.bg-tint-lavanda (ver
   arriba), reportado otra vez pero "ahora solo en la barra de menú de
   arriba": la cabecera y el panel de menú móvil de Servicios usan
   var(--live-bg, ...) con el mismo respaldo --color-lavanda de antes
   de arreglar el fondo del body — --live-bg no existe hasta que
   animateBgFade() lo fija en su primer fotograma, así que hasta
   entonces la cabecera se pintaba con ESE respaldo (lavanda) en vez
   del niebla real de partida, el mismo hueco de antes de corregirlo
   ahí solo en el body. Mismo arreglo, mismo criterio de cuándo
   aplicarlo (solo si animateBgFade() va a correr de verdad). */
@media (prefers-reduced-motion: no-preference) {
  body.bg-tint-lavanda .site-header {
    background-color: color-mix(in srgb, var(--live-bg, var(--color-niebla)) 88%, transparent);
  }

  body.bg-tint-lavanda .main-nav {
    background-color: var(--live-bg, var(--color-niebla));
  }
}

/* Bug real, reportado en móvil: al llegar al pie de página, la
   cabecera sticky (en las páginas "cristal" de arriba) sigue
   translúcida+desenfocada — deja ver borroso el logo grande del
   footer justo detrás, un choque de color feo contra el pie (siempre
   berenjena sólido) y encima ilegible. site-header--over-footer (ver
   el nuevo seguimiento de .site-footer en animations.js, mismo
   mecanismo que site-header--over-hero/-arena/-about-cta, antes solo
   en Inicio) fuerza el mismo berenjena sólido que el propio footer
   mientras dure el solape — se lee como una continuación del pie, no
   como un cristal roto encima. "body" en el selector, no solo
   ".site-header.site-header--over-footer": sube la especificidad por
   encima de las reglas body.bg-tint-* .site-header de arriba (mismas
   2 clases que estas, así que sin este empate a favor el orden en el
   archivo decidiría el ganador en vez de la intención). */
body .site-header.site-header--over-footer {
  background-color: var(--color-berenjena);
  color: var(--color-niebla-clara);
}

body .site-header.site-header--over-footer a:focus-visible {
  outline-color: var(--color-niebla-clara);
}

body .site-header.site-header--over-footer .main-nav {
  background-color: var(--color-berenjena);
}

@supports ( backdrop-filter: blur(1px) ) or ( -webkit-backdrop-filter: blur(1px) ) {
  body .site-header.site-header--over-footer {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

.site-header a:focus-visible {
  /* El contorno de foco por defecto es melocotón, con poco contraste
     tanto sobre fondo oscuro como sobre niebla. */
  outline-color: var(--zone-text, var(--color-berenjena));
}

.site-header__logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* position:relative + z-index — mismo motivo que .nav-toggle (ver su
     comentario): se queda visible por encima del panel de menú a
     pantalla completa en móvil (ver .main-nav más abajo), en vez de
     desaparecer detrás en cuanto se abre. En escritorio no hace nada
     (.main-nav nunca cubre nada ahí), así que no hace falta media
     query. */
  position: relative;
  z-index: 2;
  color: inherit;
  text-decoration: none;
  font-family: var(--font-titulos);
  font-size: 1.25rem;
}

.site-header__logo svg {
  width: auto;
  /* Antes 3rem: hacía que el logo pesara mucho más que el resto del
     menú. A esta altura queda a la escala de un elemento más del
     menú, no de un bloque aparte. */
  height: 1.75rem;
}

.site-header__logo svg path {
  fill: currentColor;
}

/* .main-nav y su <ul> no generan caja propia: así el logo y cada
   enlace quedan como hijos directos de .site-header y
   justify-content: space-between los reparte a todos por igual a lo
   largo de toda la cabecera (en vez de agrupar los enlaces aparte). */
.main-nav,
.main-nav ul {
  display: contents;
}

.main-nav ul {
  /* display: contents no genera caja, así que solo list-style (que se
     hereda a los <li>) tiene efecto aquí; margin/padding no aplicarían. */
  list-style: none;
}

.main-nav a {
  color: inherit;
  font-family: var(--font-titulos);
  font-size: 1.2rem;
  text-decoration: none;
  font-weight: 500;
}

.main-nav a[aria-current="page"] {
  /* Antes negrita (700) para distinguir la página activa sin
     subrayado ni color de acento — a petición expresa, EB Garamond
     solo en Medium (500) en toda la web, así que aquí ya no hay
     negrita real disponible (Google Fonts solo carga el peso 500, ver
     functions.php). underline con offset generoso como alternativa
     sin depender de un peso de fuente distinto. */
  text-decoration: underline;
  text-underline-offset: 0.35em;
}

/* Oculto visualmente pero legible por lectores de pantalla */
.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Botón de menú hamburguesa (solo visible en móvil/tablet, ver media
   query más abajo). position:relative + z-index: a petición expresa,
   el propio botón (que ya se convierte en una "X" al abrir, ver
   .nav-toggle[aria-expanded="true"] arriba) tiene que seguir visible Y
   pulsable POR ENCIMA del panel de menú a pantalla completa (ver
   .main-nav más abajo) — sin esto, al ser .main-nav un elemento
   position:fixed añadido DESPUÉS en el DOM dentro de la misma cabecera,
   pintaría por delante de este botón (static, sin z-index propio) y lo
   dejaría tapado del todo, sin forma de volver a cerrar el menú. */
.nav-toggle {
  display: none;
  position: relative;
  z-index: 2;
  background: none;
  border: none;
  padding: 0.5rem;
  margin: -0.5rem;
  color: inherit;
  cursor: pointer;
}

.nav-toggle__box {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 1.75rem;
}

.nav-toggle__bar {
  display: block;
  height: 2px;
  background-color: currentColor;
  border-radius: 2px;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

@media (max-width: 64rem) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* Por debajo de este ancho, el truco "display: contents" (que
     reparte el logo y los enlaces como hijos directos de .site-header
     para el diseño de escritorio) se desactiva: el menú pasa a ser un
     panel propio a pantalla completa. */
  .main-nav,
  .main-nav ul {
    display: block;
  }

  /* Pantalla completa, no un panel corto desplegándose justo debajo de
     la cabecera (versión anterior, max-height:28rem) — a petición
     expresa: "que el despliegue ocupe toda la página completa de
     móvil, con las opciones alineadas y todo legible". z-index:1 (por
     debajo del logo/botón, ver el comentario de .nav-toggle más
     arriba): dentro de la propia cabecera (que ya crea su propio
     contexto de apilamiento, sticky + z-index), así que solo tiene que
     ganarle a sus DOS hermanos directos (el logo y el botón), no al
     resto de la página — el resto de la página ya queda por debajo sin
     más, heredado del z-index alto de .site-header.

     position:absolute (NO fixed, versión anterior) + height:100vh/dvh
     (NO inset:0) — bug real, reportado como "el menú sigue tan
     bugueado" (Servicios/Conócenos/Qué tratamos/Blog/Contacto, todas
     las páginas "cristal"): estas páginas ponen backdrop-filter:blur()
     en .site-header (ver @supports más abajo, para el efecto "vaho" del
     menú compacto) — y backdrop-filter, aunque no lo parezca, es una de
     las pocas propiedades CSS que convierten a su propio elemento en el
     "containing block" de CUALQUIER descendiente position:fixed, ni
     más ni menos que si tuviera un transform. Con "position:fixed" (lo
     que había antes), el propio <header> —no la ventana— pasaba a ser
     el marco de referencia de este panel en esas páginas: "inset:0" ya
     no cubría toda la pantalla, solo la cajita de ~72px de la propia
     cabecera, así que los enlaces (mucho más altos que eso) se
     amontonaban unos encima de otros, desbordando por fuera de esa
     caja diminuta SIN el fondo sólido de detrás (el fondo solo se
     pinta dentro de la caja real del elemento, no en el desbordamiento)
     — de ahí "transparente y todo amontonado", comprobado con una
     captura real. position:absolute no tiene este problema con
     backdrop-filter (que solo afecta a position:fixed) — sigue
     necesitando un marco de referencia, y aquí es .site-header (ya
     positioned de por sí, por su propio position:sticky, con o sin
     backdrop-filter) — pero como esta cabecera está siempre "pegada"
     arriba del todo del viewport en cuanto hay scroll (top:0, sticky
     desde el primer píxel, ver su comentario), anclar este panel a su
     borde superior (top:0) equivale visualmente a anclarlo a la
     ventana. height:100vh (con 100dvh justo después, que las gana en
     los navegadores que lo soportan) en vez de "bottom:0" — con
     absolute, "bottom" mediría desde el borde INFERIOR de la propia
     cabecera de 72px, no desde el de la ventana; un alto explícito en
     unidades de viewport no depende en absoluto del tamaño real del
     elemento al que está anclado.

     background-color explícito con var(--live-bg, ...), NO
     "background-color: inherit" (versión de antes de esta, todavía más
     vieja) — bug real, reportado como "falta fondo sólido": "inherit"
     toma el fondo YA PINTADO del padre inmediato (.site-header), y ese
     fondo se vuelve A PROPÓSITO transparent mientras la cabecera está
     sobre el hero/la arena/las flores de cierre en Inicio (ver
     .site-header--over-hero/-arena/-about-cta más arriba) — con
     "inherit", abrir el menú en cualquiera de esos tres tramos dejaba
     el panel entero transparente, mostrando lo que hubiera detrás a
     medio pintar, sin fondo sólido de verdad. --live-bg (rellenada
     tanto por animateSectionBackgrounds() como por animateBgFade(), ver
     animations.js) lleva SIEMPRE el color real y actual del fondo de la
     página, exista o no ese truco de transparencia en la cabecera — el
     respaldo (--color-niebla) cubre cualquier página sin ninguna de las
     dos animaciones corriendo (prefers-reduced-motion/sin JS), donde el
     fondo real de la página ya es niebla o un tinte fijo de todos
     modos.

     opacity+visibility (no display, que no se puede animar) para la
     transición de apertura — visibility evita que los enlaces sigan
     siendo tabulables/clicables mientras el panel está oculto de
     verdad, algo que "opacity:0" por sí solo no impide. */
  .main-nav {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100vh;
    height: 100dvh;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--live-bg, var(--color-niebla));
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease;
  }

  .main-nav.is-open {
    opacity: 1;
    visibility: visible;
  }

  /* Enlaces centrados, uno debajo de otro, con bastante más aire entre
     sí que el panel corto de antes — a petición expresa ("con las
     opciones del menú alineadas"), ahora que hay una pantalla entera
     de alto disponible en vez de solo un hueco corto bajo la
     cabecera. */
  .main-nav ul {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
    margin: 0;
    padding: 0 clamp(1rem, 4vw, 3rem);
    text-align: center;
  }

  /* Bastante más grande que antes (1.1rem → clamp hasta 2rem) — a
     petición expresa, "que la fuente del texto del menú sea más
     grande": con todo el alto de la pantalla disponible (ver
     .main-nav arriba) un tamaño de titular tiene sitio de sobra, y se
     lee como un menú a pantalla completa de verdad, no como una lista
     compacta. */
  .main-nav a {
    display: block;
    padding: 0.4rem 0;
    font-size: clamp(1.5rem, 6vw, 2rem);
  }
}

/* Evita el scroll de fondo mientras el menú móvil está abierto. */
body.nav-open {
  overflow: hidden;
}

/* Pie del sitio */
.site-footer {
  padding: clamp(1.5rem, 4vw, 3rem);
  background-color: var(--color-berenjena);
  color: var(--color-niebla);
}

.site-footer a {
  color: var(--color-niebla);
  transition: color 0.2s ease;
}

/* Bug reportado: dentro del footer, el "crecer" (transform: scale) del
   botón "Pide tu primera cita" se veía brusco/instantáneo en vez de
   suave como el resto de botones de la web. Motivo: ".site-footer a"
   (type + clase, justo arriba) tiene MÁS especificidad que ".btn" (una
   sola clase, ver más abajo), así que su "transition: color 0.2s ease"
   corto sustituye entero al "transition" largo de .btn (transform,
   background-color, color, border-color) en vez de sumarse — el
   shorthand "transition" no hace merge de listas, la última que gana
   se queda con todas las propiedades. Repitiendo aquí la misma lista
   completa de .btn, con ".site-footer .btn" (dos clases) ganando por
   especificidad, se recupera la transición de transform/fondo también
   dentro del footer. */
.site-footer .btn {
  transition: transform 0.2s ease, background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

/* Antes: opacity: 0.8 en vez de color — a petición expresa, "se ve
   demasiado oscuro y no se nota", sustituido por un cambio de color a
   melocotón (pasa AA de sobra sobre este fondo berenjena, ~5.2:1, ver
   la fórmula WCAG). */
.site-footer a:hover,
.site-footer a:focus-visible {
  color: var(--color-melocoton);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(1.5rem, 4vw, 2.5rem);
  border-bottom: 1px solid rgba(234, 227, 221, 0.25);
}

@media (max-width: 720px) {
  .site-footer__grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
}

/* Antes llevaba align-self:end para alinear el logo/eslogan por abajo
   con el resto de columnas, pero eso dejaba su parte de ARRIBA 67px
   más abajo que "Mapa del sitio"/"Contacto", dando sensación de
   desalineado — a petición expresa, ahora las 3 columnas arrancan a
   la misma altura (comportamiento por defecto del grid, align-items:
   start), sin necesidad de regla propia aquí. */

.site-footer__logo {
  display: inline-block;
  width: 15rem;
}

.site-footer__logo svg {
  display: block;
  width: 100%;
  height: auto;
}

.site-footer__tagline {
  margin-top: 1rem;
  max-width: 13.7em;
  color: var(--color-niebla-clara);
  font-family: var(--font-titulos);
  font-size: clamp(1rem, 1.2vw + 0.55rem, 1.25rem);
}

.site-footer__heading {
  font-family: var(--font-titulos);
  font-size: 1.15rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* margin-top:0 — es un <p>, y sin resetear su margen superior por
     defecto del navegador (~1em, el tamaño de su propia fuente) caía
     ~18px más abajo que el logo de al lado, que es un <a> sin ese
     margen: mismo top en el grid pero visualmente desalineados. */
  margin-top: 0;
  margin-bottom: 1rem;
  color: var(--color-pistacho);
}

.site-footer__nav ul,
.site-footer__contact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.85rem;
}

.site-footer__nav a,
.site-footer__contact-list a {
  text-decoration: none;
}

.site-footer__contact-list {
  color: var(--color-niebla-clara);
}

/* display:flex column, no el flujo por bloques de siempre: la columna
   de contacto (.site-footer__contact) es un grid item, y por defecto
   (align-items:stretch del propio grid, ver .site-footer__grid) ya
   mide de alto lo mismo que la columna más alta de la fila (Mapa del
   sitio, con 8 enlaces) — pero su contenido en flujo normal no llenaba
   ese alto de sobra, así que el botón se quedaba pegado justo debajo
   de la lista de contacto, más arriba que "Política de privacidad". A
   petición expresa, que su borde inferior quede a la misma altura que
   el de esa lista: con flex-column, el margin-top:auto de
   .site-footer__contact-cta (justo abajo) empuja el botón hasta el
   borde inferior real de la columna, que coincide con el de "Mapa del
   sitio" al ser esta la columna que marca el alto de la fila. */
.site-footer__contact {
  display: flex;
  flex-direction: column;
}

.site-footer__contact-cta {
  margin-top: auto;
  /* Nunca menos separación de la lista de encima que antes (1.2rem
     fijo) aunque el "auto" de arriba ya empuje hacia abajo — en el
     apilado a una columna en móvil (ver el @media más arriba) no hay
     alto de sobra que repartir, así que sin este mínimo el "auto" se
     quedaría en 0 y el botón tocaría la lista. */
  padding-top: 1.2rem;
}

.footer-collaborators {
  margin-top: 2rem;
}

.footer-collaborators__title {
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 1rem;
  color: var(--color-pistacho);
}

.footer-collaborators__list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin: 0;
  padding: 0;
}

.footer-collaborators__list img {
  max-height: 40px;
  width: auto;
  filter: grayscale(1);
  opacity: 0.8;
  transition: filter 0.2s ease, opacity 0.2s ease;
}

.footer-collaborators__list img:hover,
.footer-collaborators__list img:focus {
  filter: grayscale(0);
  opacity: 1;
}

.site-footer__bottom {
  margin-top: clamp(1.5rem, 4vw, 2.5rem);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  color: var(--color-niebla-clara);
}

/* EB Garamond peso medium (500), no Work Sans heredado de
   .site-footer__bottom — a petición expresa, mismo criterio
   tipográfico que .site-footer__heading/.wpcf7-response-output (ver
   más abajo) en vez del texto genérico del resto del footer.
   1.05rem, no 0.95rem — "un pelín más grandes", a petición expresa. */
.site-footer__copyright,
.site-footer__credit {
  margin: 0;
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: 1.05rem;
}

/* Móvil/tablet (mismo breakpoint que el menú hamburguesa, ver
   @media max-width:64rem de .main-nav): a petición expresa, aquí el
   copyright y el crédito pasan a dos líneas (una debajo de la otra,
   alineadas a la derecha) en vez de compartir fila con
   justify-content:space-between, y con un tamaño de letra un poco
   mayor todavía que el ya subido de la regla base de arriba — en este
   ancho estrecho, cada línea tiene toda la fila para ella sola, así
   que puede permitirse ser más grande sin chocar con la otra. */
@media (max-width: 64rem) {
  .site-footer__bottom {
    flex-direction: column;
    align-items: flex-end;
  }

  .site-footer__copyright,
  .site-footer__credit {
    font-size: 1.15rem;
  }
}

/* Botones */
.btn {
  display: inline-block;
  font-family: var(--font-texto);
  font-weight: 600;
  text-decoration: none;
  padding: 0.85em 1.75em;
  border-radius: 999px;
  border: 2px solid transparent;
  transition: transform 0.2s ease, background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
  /* Explícito, no dejado al "auto" del navegador — bug real, reportado
     dentro del <dialog> nativo de la biografía en Conócenos (el botón
     "Pedir tu primera cita" de .team-profile__cta): sin esto, algunos
     navegadores resuelven el cursor "auto" de un <a> ahí dentro como
     cursor de texto en vez de la manita de siempre, aunque el enlace
     siga siendo clicable con normalidad. */
  cursor: pointer;
}

.btn--primary {
  background-color: var(--color-melocoton);
  color: var(--color-berenjena);
}

.btn--primary:hover,
.btn--primary:focus-visible {
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
}

.btn--secondary {
  background-color: transparent;
  color: var(--color-berenjena);
  border-color: currentColor;
}

.btn--secondary:hover,
.btn--secondary:focus-visible {
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
  /* Sin borde visible en el hover, a petición expresa: border-color
     transparent en vez de quitar el borde entero (border: none), para
     que el padding no salte ni un px al pasar el ratón — el borde
     sigue "ahí" (2px, mismo grosor que en reposo), solo que del mismo
     color que el propio relleno de fondo, así que se vuelve invisible
     en vez de dibujarse. */
  border-color: transparent;
}

/* .btn--cita: EL MISMO botón en toda la web para "Pide tu primera
   cita"/"Enviar mensaje"/"Escríbenos por WhatsApp" — a petición
   expresa, "que todos los botones normales de la web sigan una
   coherencia". A diferencia de .btn--primary/--secondary (arriba),
   nunca cambia de fondo según la página (ver body.bg-tint-lavanda
   .btn--primary/--secondary, más arriba: aquí no aplican, es una
   clase distinta a propósito) ni al pasar el ratón: fondo berenjena
   fijo siempre, el hover/foco solo agranda (transform), nunca cambia
   de color. */
.btn--cita {
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
}

.btn--cita:hover,
.btn--cita:focus-visible {
  transform: scale(1.08);
}

/* En el footer (fondo berenjena, ver .site-footer) el mismo botón
   berenjena se volvería invisible contra su propio fondo — se voltea
   a un relleno claro con el texto en berenjena, igual de "coherente"
   pero visible; el hover sigue siendo solo el agrandado de arriba. */
.site-footer .btn--cita {
  background-color: var(--color-niebla);
  color: var(--color-berenjena);
}

/* A petición expresa: en el footer, el hover/foco pasa el fondo a
   pistacho (en vez de quedarse en niebla) manteniendo el texto en
   berenjena — contraste ~6:1, pasa WCAG AA de sobra (mismo par de
   colores que .section--hero-cta .btn--cita, ver más abajo, solo que
   invertido fondo/texto). El "crecer" (transform: scale) lo sigue
   poniendo la regla general .btn--cita:hover de arriba, que también
   aplica aquí: son propiedades distintas, no hace falta repetirlo. */
.site-footer .btn--cita:hover,
.site-footer .btn--cita:focus-visible {
  background-color: var(--color-pistacho);
  color: var(--color-berenjena);
}

/* Antes llevaba color:pistacho aquí (excepción solo para este botón,
   para conectar visualmente con el fondo pistacho de la propia
   sección) — revertido a petición expresa más reciente, "absolutamente
   todos los botones con fondo berenjena, texto en blanco", sin
   excepciones: se queda con el --color-blanco heredado de .btn--cita
   general, sin sobreescribir "color" aquí.
   Transform aquí (no solo en .btn general), NO como atajo "scale" —
   combina las mismas variables --hero-outro-scale/--hero-outro-y que
   escribe GSAP en este botón (ver animateHeroOutroTextReveal() en
   animations.js) con transformOrigin "50% 100%" ya fijado por esa
   misma función; el "transform" en sí queda declarado aquí, nunca como
   inline por GSAP, así el hover de justo abajo puede multiplicarlo sin
   que un estilo inline se lo pise. */
.section--hero-cta .btn--cita {
  transform-origin: 50% 100%;
  transform: translateY(calc(var(--hero-outro-y, 0) * 1px)) scale(var(--hero-outro-scale, 1));
}

/* El hover/foco de .btn--cita (arriba) escribe "transform: scale(1.08)"
   sin más — aquí no basta: este botón YA tiene un "transform" propio
   en todo momento (la regla de justo arriba, ligada al scroll), y ese
   scale(1.08) a secas lo borraría de golpe en cuanto se pasa el ratón
   (el botón "saltaría" a su tamaño de reposo real en vez de crecer
   desde el tamaño que tenga en ese momento del scroll) — bug real
   reportado ("no hace la animación de hover de crecer como el resto
   de botones"). Repitiendo aquí la misma composición con var()/calc()
   de arriba y multiplicando solo el factor de escala por 1.08 (nunca
   el desplazamiento) se preserva el resto de la transformación viva;
   más específica que ".btn--cita:hover" de arriba (una clase de
   ancestro más), así que gana sin necesidad de !important. */
.section--hero-cta .btn--cita:hover,
.section--hero-cta .btn--cita:focus-visible {
  transform: translateY(calc(var(--hero-outro-y, 0) * 1px)) scale(calc(var(--hero-outro-scale, 1) * 1.08));
}

/* .btn--melocoton: mismo criterio que .btn--cita justo arriba (el
   hover solo agranda) pero en melocotón, para "Ver qué tratamos"/"Ver
   tarifas" en Servicios (ver .services-grid__cta).
   background-color usa var(--decor-fill, var(--color-melocoton)), no
   el token directo — a petición expresa, "que transicionen de color
   también, como el resto de cosas": mismo var() que ya llevan los 6
   iconos decorativos del estampado de esta misma página (ver el
   porqué largo en page-servicios.php, junto a $vinculare_estampado_iconos)
   — animateBgFade() (animations.js) interpola --decor-fill de
   melocotón a pistacho al entrar en Preguntas frecuentes, así que estos
   botones (que viven justo antes, al final de Áreas de atención) pasan
   de color en el mismo scrub exacto que esos iconos y el fondo del
   body, no por su cuenta. Fallback var(--color-melocoton): mismo
   aspecto de siempre sin JS/con prefers-reduced-motion (animateBgFade()
   nunca llega a definir --decor-fill en ese caso). */
.btn--melocoton {
  background-color: var(--decor-fill, var(--color-melocoton));
  color: var(--color-berenjena);
  /* Sin "background-color" en la transición heredada de .btn (arriba):
     ese fundido lo controla scroll+GSAP fotograma a fotograma a través
     de --decor-fill, no un cambio de estado puntual (hover/foco) — con
     la transición de 0.2s puesta, el color renderizado iría siempre un
     paso por detrás del valor real de scroll, en vez de seguirlo 1:1
     (mismo motivo, a menor escala, que .section--hero-cta .btn--cita no
     usa "scale"/"y" de GSAP como transición CSS, ver ese comentario más
     abajo). El resto de propiedades sí se queda con transición: el
     "crecer" del hover, más abajo, sigue siendo instantáneo→suave. */
  transition-property: transform, color, border-color;
}

.btn--melocoton:hover,
.btn--melocoton:focus-visible {
  transform: scale(1.08);
}

/* Botón flotante de WhatsApp, fijo en la esquina inferior derecha en
   TODA la web (ver footer.php, justo fuera de <footer> para que no
   herede el volteo de colores de .site-footer .btn--cita/.btn de más
   arriba — ese volteo existe solo porque el pie de verdad tiene fondo
   berenjena de por sí; este botón flota sobre lo que sea que haya
   detrás en cada página). Reusa .btn--cita (mismo aspecto/hover que el
   resto de botones "cita" de la web, a petición expresa) en vez de
   inventar un color nuevo por página: al llevar su propio fondo sólido
   siempre encima de cualquier contenido, el contraste real es siempre
   el de berenjena+niebla (ver .btn--cita más arriba, pasa WCAG AA de
   sobra) sea cual sea el color de fondo de la página en ese momento
   del scroll — ninguna variante "adaptada a la página" podría
   garantizar eso al ser fixed. Sin box-shadow (ver CLAUDE.md/memoria,
   "no shadows"): se distingue del fondo por su propio color sólido, no
   por una sombra. */
.whatsapp-float {
  position: fixed;
  right: clamp(1rem, 4vw, 2rem);
  bottom: calc(clamp(1rem, 4vw, 2rem) + env(safe-area-inset-bottom, 0px));
  z-index: 500;
  /* SIN font-weight/line-height propios a propósito — a petición
     expresa, "mismo bold, mismo tamaño de fuente, misma altura que el
     resto de botones": heredando el font-weight:600 y el line-height
     normal de .btn/body (los mismos que usa cualquier otro .btn de la
     web) este botón mide EXACTAMENTE lo mismo de alto que los demás,
     con el mismo padding. El icono (ver .whatsapp-link__icon más abajo)
     se queda centrado con el texto de todos modos gracias al
     align-items:center de .whatsapp-link — ese centrado no depende del
     line-height, solo de que ambos sean flex items del mismo contenedor. */
}

/* A petición expresa: aunque el fondo berenjena propio del botón ya
   pasa WCAG AA él solo (ver el porqué más arriba), si el fondo de LA
   PÁGINA detrás resulta ser ese mismo berenjena (o cualquier otro fondo
   igual de oscuro), el botón deja de "leerse" como un elemento aparte
   — su borde se funde con el fondo aunque el contraste de su texto
   siga intacto. Esto no es un problema de contraste de texto, es que
   el propio botón se vuelve invisible como forma.
   .whatsapp-float--on-dark: clase que pone updateWhatsappFloat() en
   animations.js, calculada a partir de --live-bg (la variable que YA
   mantiene el sitio con el color real de fondo en cada instante, la
   escriban animateSectionBackgrounds() en Inicio o animateBgFade() en
   Servicios/otras páginas con [data-bg-fade] — ver ambas en
   animations.js) — así que funciona igual en cualquier página que use
   cualquiera de las dos, sin tener que enumerar aquí "en esta sección
   de esta página el fondo es oscuro".
   border-color, no un box-shadow (memoria: "no shadows, ever") — ya
   forma parte del "transition" largo de .btn de más arriba, así que
   entra/sale con la misma transición suave de 0.2s que el resto. */
.whatsapp-float.whatsapp-float--on-dark {
  border-color: var(--color-niebla);
}

/* Solo icono en móvil/tablet — a petición expresa, "con la palabra es
   demasiado grande y tapa demasiado": 64rem, el mismo umbral que ya
   separa "escritorio" de "móvil+tablet" en el resto del sitio (ver
   .nav-toggle más abajo). display:none en vez de solo ocultar
   visualmente el texto: así el botón se encoge de verdad (deja de
   reservar el ancho del texto), no solo lo tapa. El aria-label del
   propio enlace (ver footer.php) ya dice "Escríbenos por WhatsApp"
   completo, así que sigue siendo igual de accesible sin el texto
   visible. Padding a juego (igual en los 4 lados, no el 0.85em/1.75em
   de .btn) para que quede un botón circular alrededor del icono, no
   una píldora ancha con aire de sobra a los lados donde ya no hay
   texto que llenarlo. */
@media (max-width: 64rem) {
  .whatsapp-float__label {
    display: none;
  }

  .whatsapp-float {
    padding: 0.85em;
  }
}

#main {
  position: relative;
  overflow: hidden;
}

/* Hero de Inicio — a petición expresa, sin foto: solo el logo y el
   título, centrados sobre el fondo niebla de la propia sección (sin
   fondo propio, sin marco). min-height (no un padding grande a
   secas): en pantallas altas/portátiles da presencia real de
   "primera pantalla" sin depender de cuánto ocupe el contenido; en
   pantallas bajas el propio contenido decide la altura (nunca la
   fuerza por debajo de lo que necesita). */
.hero {
  position: relative;
  /* Más alto (era min(34rem, 78vh)) — a petición expresa, para que el
     conjunto logo+título quede centrado en la pantalla inicial de
     verdad, no pegado arriba con la siguiente sección entrando ya a
     media pantalla. */
  min-height: min(44rem, 92vh);
  /* max-width:100rem (1600px) + margin-inline:auto — a petición
     expresa, tras reportarse que en monitores grandes (>1600px) la
     composición "se descolocaba": bailando/nudo/vinculo-* se
     posicionan en % o en right/left respecto al ANCHO de .hero (ver
     esas reglas más abajo), mientras que el logo/título se centran
     con este mismo flex. Con .hero a ancho completo de la pantalla,
     en monitores muy anchos nudo/bailando (anclados a los bordes)
     se alejaban cada vez más del logo (que se queda en el centro),
     rompiendo el conjunto que sí se ve bien en portátiles. Todos los
     clamp() de tamaño/offset de esas ilustraciones (ver más abajo)
     ya dejan de crecer exactamente a 1600px de ancho — ese es el
     ancho "de referencia" para el que está compuesta esta escena —
     así que capar .hero ahí y centrarlo mantiene esa misma
     composición íntegra en monitores más grandes, con más fondo
     niebla visible a los lados en vez de estirarse. */
  max-width: 100rem;
  margin-inline: auto;
  padding-block: clamp(2.5rem, 8vw, 5rem);
  padding-inline: var(--section-padding-inline);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Reducido (era clamp(1.5rem, 3.5vw, 2.5rem)) — a petición expresa,
     menos espacio entre .hero__logo y .hero__title. */
  gap: clamp(0.5rem, 1.5vw, 1rem);
  text-align: center;
}

/* .hero__bg-stage envuelve las 5 ilustraciones de fondo (bailando/nudo/
   vinculo-1/2/3) en un "escenario" de ancho FIJO (100rem, el ancho de
   referencia para el que está pensada toda la composición — mismo
   valor que el max-width de .hero) — a petición expresa, tras varios
   intentos de hacer que la composición "escalara" con la ventana
   (primero con vw, después con container queries/cqw) que seguían
   solapándose en anchos intermedios: en vez de intentar que las 5
   piezas + el logo/título encojan todas en la misma proporción exacta
   (frágil: cualquier pieza que no siga exactamente la misma base de
   escalado rompe el conjunto), esta composición deja de "escalar" del
   todo. Se comporta como una foto de tamaño fijo: siempre mide 100rem
   de ancho, siempre centrada (left:50% + translateX(-50%), igual que
   .hero__center) sobre el punto medio de .hero — y punto. Si la
   ventana es más estrecha que esos 100rem, sencillamente no cabe
   entera: la parte que sobra por los lados se queda fuera de la vista,
   tapada (no borrada) por el overflow:hidden que ya lleva #main (ver
   su regla más arriba) — el mismo mecanismo que ya recortaba el
   pequeño sangrado de bailando.svg por el lado/por abajo, ahora
   recortando bastante más en ventanas estrechas. Como todas las
   posiciones/tamaños de las 5 piezas (ver sus reglas más abajo) vuelven
   a ser valores FIJOS en rem (nada de vw/cqw/clamp), su colocación
   relativa entre ellas y respecto al centro de la pantalla no cambia
   NUNCA, sea cual sea el ancho de la ventana — solo cambia cuánto de
   ese escenario fijo entra en la parte visible.

   height:100% (no un valor fijo): sigue atada al alto real de .hero
   (que si depende de vh, ver el comentario grande de .hero más arriba)
   para que el top:0/top:50%/etc. de cada ilustración siga
   refiriéndose al mismo alto de siempre — el ancho es lo único que se
   fija, el alto no formaba parte de la queja (nadie ha reportado
   solapes verticales, solo al variar el ANCHO de la ventana).

   pointer-events:none aquí (el escenario en sí no es clicable/hoverable
   — es un simple contenedor invisible) + pointer-events:auto en cada
   .hero__bg-illustration hijo (ver más abajo, sin tocar) para que el
   hover siga funcionando igual que antes en cada silueta individual. */
.hero__bg-stage {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100rem;
  height: 100%;
  pointer-events: none;
}

/* Ilustraciones de fondo del hero (bailando.svg + nudo.svg) — dos
   instancias independientes de la MISMA clase base, cada una con su
   propio modificador (--bailando/--nudo) para su posición/tamaño/
   transform, a un lado cada una (bailando a la derecha, nudo a la
   izquierda) para no chocar entre sí ni con el logo/título centrados
   (ver el max-width de esos dos en .hero__logo/.hero__title más abajo
   — dejan hueco de sobra a ambos lados en pantallas anchas). En su
   opacidad completa: a este nivel, cruzarse con el título de verdad
   bajaría su contraste, por eso ninguna de las dos se mete debajo de
   él. Posición/tamaño en rem fijo (no vw/cqw): ver el comentario grande
   de .hero__bg-stage justo arriba para el porqué. */
.hero__bg-illustration {
  position: absolute;
  z-index: 0;
  pointer-events: none;
}

/* 56rem → 40rem — a petición expresa, tras reportarse que la copia de
   vinculo.svg de encima del título (--vinculo-1) desaparecía "de la
   nada" al reducir un poco más la ventana, sin que pasara nada más a
   la vista en ese punto: este display:none es de ANTES de que
   .hero__bg-stage pasara a tener tamaño fijo (ver su comentario grande
   más arriba) — en aquella versión, nudo/bailando/vinculo-* encogían
   con la ventana, así que ocultar las tres copias de vinculo a partir
   de 56rem tenía su propia lógica (evitar que se solaparan con el
   logo/título, que en ese punto empezaba a quedarse sin sitio). Ahora
   que las 5 piezas viven en un escenario de tamaño FIJO que solo se
   recorta (nunca reordena ni encoge), ese motivo ya no aplica en
   56rem — las tres copias de vinculo simplemente se recortan por el
   borde como el resto, sin ningún conflicto real con el logo/título
   hasta el breakpoint de @media(max-width:40rem) de más abajo, donde
   el título SÍ cambia de forma (pasa a envolver en varias líneas con
   letra más grande): ahí sigue haciendo falta ocultarlas para que no
   choquen con ese texto más grande, así que el display:none se mueve
   a ese mismo punto en vez de disparar antes por su cuenta. */
@media (max-width: 40rem) {
  .hero__bg-illustration--vinculo-1,
  .hero__bg-illustration--vinculo-2,
  .hero__bg-illustration--vinculo-3 {
    display: none;
  }
}

.hero__bg-illustration svg {
  display: block;
}

/* Hover interactivo sobre las ilustraciones del hero — a petición
   expresa: NO lavanda para todas (versión anterior), sino que
   intercambien su color de reposo entre pistacho y melocotón —
   bailando.svg (melocotón en reposo) pasa a pistacho, y el resto
   (pistacho en reposo: nudo + las tres copias de vinculo) pasan a
   melocotón. Misma opacidad que en reposo: solo cambia el color, no
   la opacidad.

   pointer-events:auto en .hero__bg-illustration (el rectángulo entero
   del span), NO en el <path> — versión anterior, quitada a petición
   expresa: con el hit-test pegado a la silueta pintada, cada hueco/
   curva interna del SVG entraba y salía del hover en cada pixel de
   ratón, y el color parpadeaba rápido al cruzar esas zonas. Con el
   rectángulo entero como zona de hover, el color solo cambia una vez
   al entrar/salir de esa zona — a cambio, dicha zona ya no se ciñe
   milimétricamente al contorno de la figura, incluye también parte
   del espacio "vacío" alrededor. */
.hero__bg-illustration {
  pointer-events: auto;
}

.hero__bg-illustration svg path {
  transition: fill 0.3s ease;
}

.hero__bg-illustration--bailando:hover svg path {
  fill: var(--color-pistacho-medio);
}

.hero__bg-illustration--nudo:hover svg path,
.hero__bg-illustration--vinculo-1:hover svg path,
.hero__bg-illustration--vinculo-2:hover svg path,
.hero__bg-illustration--vinculo-3:hover svg path {
  fill: var(--color-melocoton-clara);
}

/* height fijo (70rem, no un clamp/vw/cqw) — a petición expresa: ver el
   comentario grande de .hero__bg-stage más arriba para el porqué de
   fijar toda la composición de fondo en vez de intentar que escale con
   la ventana. 70rem es el valor que ya usaba el clamp() anterior en su
   tope máximo (min(180%, 70rem) del alto de .hero, alcanzado en la
   composición de referencia) — mismo aspecto/tamaño de siempre, ahora
   simplemente constante en vez de recalcularse. right:-4rem, igual:
   valor máximo del clamp() anterior (-4vw a 1600px de ancho). */
.hero__bg-illustration--bailando {
  top: 0;
  right: -4rem;
  width: auto;
  height: 70rem;
}

.hero__bg-illustration--bailando svg {
  height: 100%;
  width: auto;
}

/* nudo.svg, al lado contrario que bailando.svg (izquierda) — a
   petición expresa, "grande" y "rotado como espejado":
   scaleX(-1) espeja horizontalmente el nudo (misma forma, orientación
   invertida — junto con rotate(), no se lee como una simple copia del
   original), y rotate() le da el giro. Centrada verticalmente
   (top:50% + translate, no anclada arriba/abajo como bailando.svg):
   el nudo es casi cuadrado en vez de una figura alta (viewBox
   152.13x149.95, ver nudo.svg), así que no necesita la misma lógica
   de altura/recorte — width normal de sobra. transform-origin:center
   (por defecto) para que rotate() gire sobre su propio centro, no
   sobre la esquina que le tocaría por el translate del centrado. */
.hero__bg-illustration--nudo {
  top: 50%;
  /* left/width fijos (antes clamp/vw/cqw) — mismo motivo que en
     .hero__bg-illustration--bailando: ver el comentario grande de
     .hero__bg-stage más arriba. Mismos valores que el tope máximo del
     clamp() anterior a 1600px de ancho (composición de referencia). */
  left: -2rem;
  /* left: clamp(6rem, 5vw, 1rem); */
  /* left: 0; */
  width: 46rem;
  height: auto;
  transform: translateY(-50%) rotate(-10deg);
}

.hero__bg-illustration--nudo svg {
  width: 100%;
  height: auto;
}

/* Tres copias de vinculo.svg — a petición expresa, rellenando los
   huecos vacíos que quedan entre nudo.svg (izquierda) y bailando.svg
   (derecha), repartidas a una distancia parecida entre sí y respecto
   a las otras dos. Comprobado a mano con las cajas reales de nudo/
   bailando (getBoundingClientRect en un navegador headless, viewport
   1440x900): con su tamaño/posición actual (nudo: width hasta 46rem,
   left:0 — bailando: ancla a la derecha) quedan tres huecos
   genuinamente despejados (sin contar los huecos pequeños DENTRO de
   las propias formas orgánicas de nudo/bailando, donde ya asoma el
   niebla de fondo entre sus curvas): uno justo debajo del título
   (--vinculo-1, el mismo sitio de la versión con una sola copia), y
   dos más abajo, uno a cada lado (--vinculo-2 a la izquierda, entre la
   cola de nudo y el centro; --vinculo-3 a la derecha, entre el centro
   y las piernas de bailando) — un triángulo aproximado, cada uno a
   parecida distancia de sus dos vecinos. Mismo width en las tres: se
   leen como el mismo motivo repetido, no tres piezas distintas.

   left/top en % + translate (no rem fijo): aproximado a estos huecos
   concretos en escritorio — si nudo/bailando cambian de tamaño o
   posición más adelante, los huecos reales se mueven con ellos y
   estos % habrá que revisarlos a ojo.

   Más arriba, más grandes y rotadas (a petición expresa, sobre la
   versión anterior): top% más bajo sube cada una (siguen sin tocar el
   logo/título, que llevan su propio z-index:1 más abajo, pero se
   mantiene la separación a ojo); width más grande; rotate() (un
   ángulo distinto por copia, no el mismo en las tres, para que no se
   lean como copias idénticas giradas igual) DESPUÉS del translate del
   centrado en cada transform — con transform-origin:center (por
   defecto) da igual el orden entre translate y rotate aquí (ambos
   comparten el mismo centro), a diferencia del caso con scaleX(-1) de
   .hero__bg-illustration--nudo más arriba (ver el porqué ahí, si hace
   falta rotar+espejar CUALQUIER OTRA cosa en el futuro). */
.hero__bg-illustration--vinculo-1,
.hero__bg-illustration--vinculo-2,
.hero__bg-illustration--vinculo-3 {
  height: auto;
}

/* Anchos fijos (antes clamp/vw/cqw) — mismo motivo que en bailando/nudo:
   ver el comentario grande de .hero__bg-stage más arriba. Mismos
   valores que el tope máximo de cada clamp() anterior a 1600px de
   ancho (composición de referencia); top/left en % se dejan igual —
   ahora son % de .hero__bg-stage, que mide siempre 100rem de ancho,
   así que ya son fijos de por sí (no hace falta pasarlos a rem). */
.hero__bg-illustration--vinculo-1 {
  top: 35%;
  left: 40%;
  transform: translate(-50%, -50%) rotate(80deg);
  width: 22rem;
}

.hero__bg-illustration--vinculo-2 {
  top: 98%;
  left: 8%;
  transform: translate(-50%, -50%) rotate(-90deg);
  width: 18rem;
}

.hero__bg-illustration--vinculo-3 {
  top: 59%;
  left: 92%;
  transform: translate(-50%, -50%) rotate(-75deg);
  width: 28rem;
}

.hero__bg-illustration--vinculo-1 svg,
.hero__bg-illustration--vinculo-2 svg,
.hero__bg-illustration--vinculo-3 svg {
  width: 100%;
  height: auto;
}

/* .hero__center envuelve SOLO el logo — a petición expresa, "que lo
   que esté centrado sea el logo": su alto es el alto real del logo
   (el título vive dentro pero position:absolute, fuera del flujo, así
   que no cuenta para este alto). .hero centra este wrapper con
   justify-content:center, así que centra el logo de verdad, no el
   punto medio de logo+título juntos (que antes quedaba desplazado
   hacia arriba por el alto del título). */
.hero__center {
  position: relative;
  z-index: 1;
  /* width explícito (no dejar que lo decida el ancho intrínseco del
     logo): .hero__title es hijo position:absolute con su propio width
     en % de ESTE contenedor (ver más abajo) — sin un width fijo aquí,
     ese % entra en un cálculo circular (el ancho de este wrapper
     dependería a su vez del contenido) y el título acababa envolviendo
     línea por línea de más.

     Nota: bailando/nudo/vinculo-* (ver sus reglas más arriba) ya NO
     escalan con este ancho — viven en .hero__bg-stage, un escenario de
     tamaño FIJO (100rem) que se recorta sin más en ventanas estrechas
     (ver su comentario grande) — así que el logo/título puede seguir
     encogiendo con total libertad aquí sin que eso vuelva a "descuadrar"
     el conjunto: ya no hay dos elementos con bases de escalado
     distintas compitiendo por el mismo espacio. */
  width: min(100%, 34rem);
}

.hero__logo {
  /* Mismo ancho máximo que .hero__title (34rem) — a petición expresa,
     que el logo se lea al mismo ancho que la frase de debajo. */
  width: min(100%, 34rem);
}

.hero__logo svg {
  /* El color lo fija .cls-1 más abajo, no el <style> interno del SVG. */
  width: 100%;
  height: auto;
}

/* Berenjena, no el color de fábrica del SVG (.cls-1 trae un pistacho)
   — a petición expresa, el logo tiene que leerse en el mismo berenjena
   que el resto del texto de marca, sobre el fondo niebla del hero. */
.hero__logo svg .cls-1 {
  fill: var(--color-berenjena);
}

.hero__title {
  /* position:absolute anclado a top:100% del wrapper (borde inferior
     del logo, ver comentario de .hero__center) + left:50%/translateX
     para centrarlo horizontalmente sin que cuente para el alto del
     wrapper. Sin width (antes min(100%,34rem)): a petición expresa,
     ahora es una sola línea (white-space:nowrap), así que el ancho lo
     decide el propio contenido, no un box que forzaba el salto de
     línea. font-size mucho más pequeño y fluido en vw (no un clamp con
     mínimo grande): tiene que caber en una sola línea también en
     móvil, donde el ancho disponible es mucho menor. */
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(0.85rem, 2.8vw, 1.5rem);
  color: var(--color-berenjena);
  white-space: nowrap;
  /* Separación respecto al logo (ver comentario de arriba: ya no
     comparte el gap de .hero con el logo, así que este margin-top es
     ahora el único que la controla). */
  margin-top: 3rem;
}

/* Oculto en escritorio (título a una sola línea, ver white-space:nowrap
   arriba) — pasa a display:inline en el media query móvil más abajo,
   donde SÍ debe forzar el salto de línea. Ver el comentario en el <br>
   en front-page.php para el porqué completo. */
.hero__title-break {
  display: none;
}

/* Móvil/tablet estrecho — tres ajustes a petición expresa, tras
   revisar capturas reales:
   1) bailando/nudo (ver display:none de las 3 copias de vinculo.svg
      más arriba) recortadas a un tamaño mucho más discreto: sus
      medidas de escritorio (pensadas para una composición de hasta
      100rem de ancho, ver el comentario grande de .hero más arriba)
      values de tipo "vw"/"rem" con un mínimo grande (bailando llega a
      medir el 180% del alto del propio hero; nudo tiene un mínimo de
      24rem de ancho) — sin recortar aquí, en una pantalla de ~24rem
      de ancho cualquiera de las dos ocuparía la pantalla entera,
      tapando el logo/título en vez de acompañarlos de fondo.
   2) .hero__center sube un poco (a petición expresa, "el logo grande
      me gustaría que saliera aunque sea solo un poquitín más arriba"):
      un translateY pequeño, no un cambio de justify-content — sigue
      centrado por .hero, solo desplazado desde ese centro.
   3) .hero__title dispensa el white-space:nowrap de escritorio (pensado
      para una sola línea larga, ver su comentario) y pasa a envolver en
      varias líneas con un tamaño de letra bastante mayor — a petición
      expresa ("el texto de debajo sale demasiado pequeño"): con
      nowrap, el clamp() de escritorio encogía la frase entera lo
      bastante para caber en una sola línea incluso en ~24rem de ancho,
      quedando minúscula (y, en pantallas más estrechas que ese clamp,
      directamente desbordando por el lado derecho, cortada por el
      propio viewport — comprobado con una captura real). Un ancho
      fijo (no 100%, para que seguir centrado con left:50%/
      translateX(-50%) del elemento no cambie) más white-space:normal
      permite 2-3 líneas cortas con un tamaño de letra mucho más
      legible, sin tocar el mecanismo de centrado (ver el comentario de
      .hero__title arriba: sigue siendo position:absolute, así que
      .hero__center no crece con este alto y el logo se mantiene
      centrado de verdad). */
@media (max-width: 40rem) {
  /* .hero__bg-stage vuelve a medir el 100% real de .hero (en vez de
     los 100rem fijos de escritorio, ver su comentario grande más
     arriba) — a petición expresa, tras reportarse que en móvil no se
     veía NINGUNA ilustración de fondo (ni bailando, que en teoría sigue
     activa en este breakpoint, ver la regla de abajo): con el escenario
     todavía a 100rem/1600px de ancho fijo y centrado, "right:-3.25rem"
     en la regla de bailando de aquí abajo la anclaba al borde derecho
     de ESE escenario de 1600px, no al borde real de una pantalla de
     móvil mucho más estrecha — así que bailando acababa muy lejos a la
     derecha, fuera de cualquier viewport real. Devolviendo el escenario
     a "ancho real de .hero" en este breakpoint, ese mismo right/left ya
     vuelve a anclarse al borde de la pantalla de verdad, exactamente
     como funcionaba antes de que existiera .hero__bg-stage. */
  .hero__bg-stage {
    left: 0;
    width: 100%;
    transform: none;
  }

  /* Vuelven a ser grandes — a petición expresa, tras un primer ajuste
     demasiado conservador ("se ven como dos pequeñitos arriba, no
     tienen sentido, tienen que ser grandes"): el tamaño de arriba las
     dejaba discretas de más, leyéndose como un detalle suelto en vez
     de como parte de la composición del hero. Bastante más grandes
     aquí (aunque sigan sin acercarse al 180%/24rem+ de escritorio, que
     sí llegaría a tapar el logo entero en una pantalla de ~24rem de
     ancho) — con algo de solape ligero contra la esquina superior del
     logo, a propósito: mismo idioma que en escritorio, donde bailando
     ya "asoma" detrás de la cabecera (ver el comentario grande de
     .hero más arriba) en vez de vivir en un hueco perfectamente
     recortado. */
  /* Mucho más grande — a petición expresa, "que ocupe la altura casi
     entera de la pantalla": el 52% de antes se quedaba corto (leído
     como "un detalle de fondo" en vez de la pieza protagonista que se
     pedía ahora). min(92%, 40rem) del alto de .hero (que en móvil ya
     mide casi la pantalla entera, min(44rem, 92vh), ver el comentario
     grande de .hero más arriba) — 92%, no 100%, deja un pequeño margen
     de sobra respecto al propio borde inferior de la sección para que
     no encaje justo al pixel con .section--about justo debajo. right
     bajado a la vez (-2.5rem → -1.5rem): con la figura bastante más
     ancha al crecer en altura (el SVG mantiene su proporción, ver
     height:100%/width:auto en la regla de abajo), el -2.5rem de antes
     la empujaba a asomar de más por el lado derecho de la pantalla. Un
     poco más a la derecha después — a petición expresa: right(-1.5rem)
     →right(-2.5rem). Bajada un poco más tras quitar nudo.svg de esta
     vista (ver comentario de .hero__bg-illustration--nudo aquí debajo)
     — a petición expresa, "pon el de bailando un poco más abajo": top
     de 0 a 1.5rem. Un poco más grande después — a petición expresa:
     height min(92%, 40rem) → min(97%, 43rem). Un poco más a la derecha
     y más abajo otra vez — a petición expresa: right(-2.5rem)→
     right(-3.25rem), top(1.5rem)→top(2.5rem). */
  .hero__bg-illustration--bailando {
    top: 2.5rem;
    right: -3.25rem;
    height: min(97%, 43rem);
  }

  /* Quitado de esta vista entera — a petición expresa, "deja solo el de
     bailando": en móvil ya no queda ningún ajuste de tamaño/posición/
     giro que le afecte (todo ese historial, si hace falta, en el
     historial de git), solo este display:none. Sigue existiendo tal
     cual en escritorio (ver su regla base más arriba, sin tocar). */
  .hero__bg-illustration--nudo {
    display: none;
  }

  .hero__center {
    transform: translateY(-1.5rem);
  }

  /* Un punto intermedio — a petición expresa, tras un ajuste que se
     quedó demasiado pequeño (0.9rem/1.1rem) al recortarlo desde el
     "doble de grande" de antes (1.7rem/2.2rem): ni tan protagonista
     como para competir con bailando.svg (ver más arriba) ni tan
     diminuto que cueste leerlo — a medio camino entre los dos
     extremos ya probados. margin-top se deja igual (4rem, "más
     abajo" ya conseguido, no se ha pedido tocarlo otra vez).

     max-width recortado (27rem → 23rem) — a petición expresa, "menos
     ancho, que ocupe dos líneas más equilibradas". El salto en sí ya NO
     depende de este ancho (ver .hero__title-break más abajo: un <br>
     que se activa aquí y fuerza el corte siempre justo después de
     "vínculo", en vez de dejarlo al wrap natural — que con solo el
     ancho de caja cambiaba de punto de corte, e incluso llegó a saltar
     DOS veces en pantallas más anchas de esta horquilla, con font-size
     ya creciendo vía clamp pero la caja sin crecer con él). 23rem sigue
     haciendo falta como red de seguridad para que la SEGUNDA mitad
     ("contigo y con quienes te rodean.") quepa siempre en una sola
     línea, incluso con la letra en su tamaño máximo del clamp. */
  .hero__title-break {
    display: inline;
  }

  .hero__title {
    white-space: normal;
    width: 94vw;
    max-width: 23rem;
    font-size: clamp(1.25rem, 5.2vw, 1.6rem);
    margin-top: 4rem;
  }
}

/* Nota: hubo aquí una versión "achicada" de bailando.svg para tablet
   táctil (mismo criterio que el bloque "@media (max-width: 40rem)" de
   justo arriba, pero por pointer:coarse en vez de por ancho), pensada
   para que su cola no se solapara con "Encaja las piezas" — quitada a
   petición expresa, "se ven mal, quiero que se vean como en pantallas
   de pc de proporciones parecidas": en una tablet, bien ancha, esa
   versión encogida (pensada para el hueco estrecho de un móvil) se
   leía fuera de proporción. El solape que motivó ese achicado se
   resolvió por el otro lado en su lugar (ver .hoja-mesa-puzzle-hint en
   hoja-a-mesa.css, movida al centro fijo de la roseta, 58%, bien por
   debajo de donde sangra esta ilustración en cualquier tablet real) —
   así que bailando.svg puede quedarse a tamaño de escritorio también
   en tablet táctil, sin volver a chocar con nada. */

.hero__title .word-mask {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.15em;
  margin-bottom: -0.15em;
}

.hero__title .word {
  display: inline-block;
}

/* Secciones genéricas */
.section {
  padding: var(--section-padding-block) var(--section-padding-inline);
}

.section__inner {
  max-width: var(--content-max-width);
  margin-inline: auto;
}

.section--hero-cta .section__inner {
  text-align: center;
}

/* .section--hero-cta: zona pistacho (fundido continuo por scroll, ver
   animateSectionBackgrounds() en animations.js) a pantalla completa,
   con el mismo "enganche" de scroll que .section--about un poco más
   abajo (ver animateFullscreenSnap() en animations.js) — llega justo
   debajo de ella en Inicio (ver front-page.php), pensada para leerse
   como una continuación directa del mismo gesto de scroll, sin la
   esquina redondeada que sí llevó una versión anterior. Sin
   background-color propio a propósito: es una zona clara (pistacho),
   como el niebla de .section--about o el berenjena de
   .section--about-cta, deja que el fondo animado del body se vea a
   través (ver el porqué en animateSectionBackgrounds()). Color
   de texto berenjena fijo, no ligado a --zone-text: pistacho es clara
   en cualquier escenario (con o sin JS/con prefers-reduced-motion, ver
   ahí el hueco), así que el texto oscuro siempre es correcto. */
.section--hero-cta {
  color: var(--color-berenjena);
  min-height: 100vh;
  display: flex;
  align-items: center;
}

/* Frase que antes iba en el hero (.hero__subtitle, quitada de ahí:
   demasiado pequeña para leerse bien encima de la foto) — ahora en su
   propia sección debajo, con scroll. EB Garamond (la misma familia de
   los títulos, no Work Sans): a petición expresa, más grande que el
   cuerpo de texto normal pero sin llegar al tamaño de un titular. */
.hero-outro__text {
  font-family: var(--font-titulos);
  /* Bastante más pequeña que la primera versión en mayúsculas
     (clamp(3rem, 6.4vw, 4.5rem)) — a petición expresa, tiene que caber
     siempre junto con el botón de debajo dentro de .section--hero-cta
     (min-height: 100vh, ver más abajo), así que el máximo se queda
     corto a propósito en vez de crecer libre. El vw intermedio (no un
     tamaño fijo) es lo que la hace encoger/crecer con la ventana en
     vez de quedarse en un tamaño rígido. */
  /* Subido un poco (era clamp(1.8rem, 3.16vw, 2.87rem)) — a petición
     expresa, "un poquitín más grande": manteniendo el mismo criterio de
     arriba (tiene que caber junto con el botón dentro de los 100vh de
     .section--hero-cta), así que el máximo sigue sin crecer libremente,
     solo un empujón moderado en los tres valores. */
  font-size: clamp(2rem, 3.4vw, 3.1rem);
  text-transform: uppercase;
  font-weight: 400;
  line-height: 1.5;
  /* 90%, no un rem fijo: el ancho del bloque de texto (el del botón lo
     marca su propio contenido, ver .btn) escala con el ancho real de
     la sección en vez de quedarse fijo en cuanto la ventana crece o se
     encoge — subido de 70% a 90% a petición expresa, menos margen a
     los lados. */
  max-width: 90%;
  margin: 5rem auto 5rem;
  /* --hero-outro-scale/--hero-outro-y: escritas por GSAP en cada
     fotograma del scroll (ver animateHeroOutroTextReveal() en
     animations.js) — el propio "transform" se queda declarado aquí, no
     como atajo "scale"/"y" de GSAP, precisamente para que el botón de
     abajo (.section--hero-cta .btn, mismo patrón) pueda combinar estas
     mismas variables con su propio hover sin que un estilo inline se
     lo pise; ver el porqué largo en animateHeroOutroTextReveal(). Sin
     JS/con prefers-reduced-motion las variables nunca se definen y los
     respaldos (0 y 1) dejan el texto en su posición/tamaño final,
     igual que antes. transform-origin aquí también (no por gsap.set,
     ver el porqué en animations.js): necesario para que el "crecer"
     de la escala de arriba salga desde la base, no desde el centro. */
  transform-origin: 50% 100%;
  transform: translateY(calc(var(--hero-outro-y, 0) * 1px)) scale(var(--hero-outro-scale, 1));
  /* position:relative + z-index:2 — a petición expresa, "las hojas
     siempre por debajo del texto": sin position, este párrafo vive en
     el flujo normal, y un descendiente position:absolute (.hero-outro-
     hoja, z-index:1, ver más abajo) SIEMPRE pinta por ENCIMA de
     cualquier hermano sin position, sea cual sea su z-index — el
     z-index de la hoja no tenía ningún hermano posicionado con el que
     compararse. Con este párrafo ahora también posicionado y con un
     z-index mayor (2 > 1), pasa a pintarse por encima de las hojas en
     cualquier punto donde lleguen a solaparse. */
  position: relative;
  z-index: 2;
}

/* En pantallas anchas (a petición expresa, "en su versión más ancha"),
   texto normal (sin <br> ni spans, mejor para lectores de pantalla) en
   una caja más estrecha que el 90% de arriba: así el propio ajuste de
   línea del navegador cae justo en "En Vinculare combinamos" /
   "psicología y psiquiatría para" / "acompañarte sin juicios." sin
   dejar ninguna palabra suelta, en vez de forzarlo con saltos
   artificiales. 18em (no un px/rem fijo): relativo al font-size del
   propio párrafo, que a su vez escala con el viewport (ver
   font-size arriba) — comprobado que el corte de línea se mantiene
   igual en toda la franja ancha (960px a 2560px+) porque crece a la
   misma proporción que el texto. Por debajo de este breakpoint se
   queda con el max-width:90% de arriba y el ajuste de línea que le
   toque según el ancho real de pantalla. */
@media (min-width: 60rem) {
  .hero-outro__text {
    max-width: 18em;
  }
}

/* Envuelve SOLO el párrafo (no el botón de debajo, ver front-page.php):
   position:relative de referencia para las dos hojas decorativas de
   abajo, que se posicionan por sus lados y se solapan un poco encima
   del texto. Sin alto/ancho propios: es un <div> normal sin padding ni
   borde, así que los márgenes verticales del propio párrafo (5rem
   arriba/abajo, ver .hero-outro__text) colapsan a través de él con
   total normalidad — el resultado visual es idéntico a si las hojas
   estuvieran posicionadas respecto al párrafo mismo, que es lo que se
   quiere (que sigan "pegadas" al texto, no a un hueco de margen vacío
   alrededor). */
/* width:100vw + margin-left:calc(50% - 50vw) — a petición expresa,
   tras reportarse que las hojas (ver .hero-outro-hoja--left/--right más
   abajo) se veían "raras, sin asomar desde fuera" en un rango de
   anchos concreto (aprox. 1150-1800px, comprobado con capturas
   reales). Causa raíz: sin esto, .hero-outro-frame mide como mucho
   72rem (var(--content-max-width), heredado de .section__inner, que lo
   envuelve — ver front-page.php) y esos 72rem se quedan FIJOS en
   cualquier ventana más ancha que eso — así que el % (o el vw) que
   posicionaba las hojas hacia fuera se calculaba sobre un ancho de
   referencia que dejaba de crecer con la ventana mucho antes que el
   propio hueco hasta el borde real, y el resultado visual "se quedaba
   corto" cada vez más cuanto más ancha la ventana (o se quedaba corto
   de una forma distinta según en qué punto del clamp() de tamaño de la
   propia hoja se cayera — de ahí lo "raro" en un rango y no en otro).
   Con este "full bleed" clásico (técnica estándar: width:100vw cancela
   el ancho real del contenedor, margin-left:calc(50% - 50vw) cancela
   su propio centrado), .hero-outro-frame pasa a medir el ancho REAL de
   la ventana de borde a borde, sea cual sea — así que left:0/right:0
   en las hojas (ver más abajo) ya anclan de verdad al borde de la
   ventana en cualquier tamaño, sin ningún cálculo intermedio que se
   pueda quedar corto. El párrafo de dentro (.hero-outro__text, con su
   propio max-width + margin:auto) sigue leyéndose centrado con total
   normalidad — un contenedor más ancho no lo estira, solo le da más
   margen alrededor. Neutralizado en el breakpoint móvil (ver
   @media(max-width:40rem) más abajo): ahí las hojas ya usan otra
   referencia (.section--hero-cta .section__inner) para su propia
   lógica, así que este full-bleed no debe interferir. */
.hero-outro-frame {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
}

/* Dos hojas de assets/illustrations/hoja2.svg (mismo dibujo que ya usa
   la arena de "Trabajo en equipo...", ver front-page.php), animadas con
   el mismo patrón que .about-cta-flor un poco más abajo en esta misma
   hoja de estilos (crecimiento ligado al scroll + vibración sutil una
   vez asentadas, ver hoja2-animada.js) pero apuntando a
   .section--hero-cta en vez de a .section--about-cta. Tamaño un 20%
   menor que esas flores (a petición expresa) — antes clamp(16rem,
   34vw, 30rem), literal, mismo tamaño; ahora ese mismo clamp con cada
   número al 80%. Sin la opacidad baja de la flor, a propósito: ahí
   tenía sentido (niebla-clara casi invisible sobre fondo oscuro, para
   leerse "como parte del fondo"), pero aquí el relleno (sólido, ver
   .hoja2-animada__path más abajo para el color exacto en uso) tiene
   que leerse con fuerza sobre el fondo pistacho claro. */
.hero-outro-hoja {
  position: absolute;
  z-index: 1;
  /* Un 15% más grandes que antes (clamp(12.8rem, 27.2vw, 24rem)) — a
     petición expresa. */
  width: clamp(14.7rem, 31.3vw, 27.6rem);
  pointer-events: none;
}

.hero-outro-hoja svg {
  display: block;
  width: 100%;
  height: auto;
  /* visible, no el "hidden" implícito por defecto: la onda del
     crecimiento (ver hoja2-animada.js) sobresale unos pocos px por
     fuera del viewBox en su pico, igual que en .about-cta-flor svg. */
  overflow: visible;
}

.hoja2-animada__path {
  fill: var(--color-melocoton);
}

/* En las esquinas del párrafo (a petición expresa) — antes más al
   centro, a los lados a media altura (left/right:0 + top:38%/58% +
   translateY(-50%)). Ahora cada hoja se ancla a una esquina real del
   contenedor (.hero-outro-frame), las dos ABAJO: bottom:0/left:0 la de
   la izquierda, bottom:0/right:0 la de la derecha. El translateY
   (70% del alto de la propia hoja, ver la regla de más abajo) deja la
   mayor parte de la hoja fuera de esa esquina hacia abajo y solo un
   30% solapando "un poquito" el borde del texto por encima — el
   translateX, en cambio, ya NO es un % de la propia hoja (ver el
   porqué del cambio en el comentario de más abajo, junto a la regla).
   La de la izquierda, además, en espejo (scaleX(-1)): mismo trazado
   que la derecha, sin duplicar puntos, para que las dos sigan
   "mirando" hacia el párrafo que enmarcan.

   rotate(), en sentidos opuestos pero MISMA magnitud (25deg/-25deg:
   horario en la de la izquierda, antihorario en la de la derecha) — a
   petición expresa, "que la hoja izquierda sea una copia exacta de la
   derecha, solo que volteada en espejo" — con magnitudes distintas en
   cada lado, probado antes, quedaban visualmente asimétricas: cada
   hoja "abría" un ángulo distinto y dejaba de leerse como un par en
   espejo de verdad. La razón
   por la que el mismo efecto de espejo exige signos OPUESTOS (no el
   mismo rotate() literal en las dos) está en el orden de las funciones
   de la lista, ver más abajo: como scaleX(-1) en la de la izquierda se
   aplica ANTES que rotate() (mirroring primero, giro después), un
   rotate() con el mismo signo en las dos giraría cada una hacia SU
   lado exterior (abriéndose como un libro), no la una hacia la otra —
   invertir el signo en la de la izquierda es lo que hace que el
   conjunto sea un espejo de verdad: mirror(rotate(R)(hoja)) =
   rotate(-R)(mirror(hoja)), la identidad matemática de espejar una
   forma ya girada. Colocado entre translate() y scaleX() en la
   lista, no antes de translate ni (en la de la izquierda) antes de
   scaleX — el orden de las funciones en "transform" no es solo
   estético, cambia el resultado real:
     - Después de translate (a su izquierda en la lista, que es donde
       se aplica AL FINAL): gira la hoja alrededor de su propio centro
       YA colocada en la esquina, no alrededor del centro del párrafo
       — sin esto describiría un arco al girar, en vez de girar sobre
       su propio eje.
     - Antes de scaleX (a su derecha en la lista, que es donde se
       aplica PRIMERO) en la de la izquierda: scaleX(-1) refleja la
       hoja antes de girarla, así que el ángulo gira la forma YA
       reflejada — invertir ese orden (girar y reflejar después)
       voltearía también el sentido en el que se ve girar. */

/* 25deg/-25deg — a petición expresa, "misma rotación", para que la
   hoja izquierda sea de verdad una copia en espejo de la derecha (ver
   el porqué largo, con la identidad matemática del espejo, en el
   comentario grande de arriba de .hero-outro-hoja).

   Historial largo de ajustes de posición horizontal (varios pasos de
   "más/menos hacia fuera", con --hoja-t moviendo la hoja según crecía)
   descartado a petición expresa, "estamos metiendo demasiadas
   variaciones para demasiados tamaños de ventana" — ver el historial
   de git si hace falta el detalle. Sustituido por algo mucho más
   simple y robusto: -3rem/3rem FIJOS (ni % de la propia hoja ni vw),
   posibles ahora gracias al full-bleed de .hero-outro-frame de más
   arriba (ancho real de la ventana en vez de los 72rem con tope de
   antes) — con el ancla ya en el borde real, un rem fijo alcanza para
   "asomar un poquito desde fuera" sea cual sea el ancho de ventana, sin
   ningún cálculo relativo que se pueda quedar corto o pasarse según el
   tamaño exacto. Ya no depende de --hoja-t (que sigue existiendo, pero
   solo dibuja el crecimiento del propio trazado SVG, ver
   hoja2-animada.js): la posición ya no se mueve al crecer, solo el
   tamaño/la silueta. */
.hero-outro-hoja--left {
  bottom: 0;
  left: 0;
  transform: translate(-3rem, 70%) rotate(25deg) scaleX(-1);
}

.hero-outro-hoja--right {
  bottom: 0;
  right: 0;
  transform: translate(3rem, 70%) rotate(-25deg);
}

/* Por debajo de 60rem (mismo breakpoint que .hero-outro__text unas
   líneas más arriba, donde el párrafo deja de tener su ancho máximo en
   "em" y pasa a ocupar más ancho real de ventana): a ese punto, con la
   misma posición horizontal de arriba (pensada para asomar desde el
   borde), las hojas ya se acercan demasiado a la línea final del
   párrafo. Solo se toca el desplazamiento vertical (70% → 95%, más
   abajo) — la horizontal se deja igual a propósito, para que sigan
   asomando desde el borde en vez de "meterse" hacia el centro. */
@media (max-width: 60rem) {
  .hero-outro-hoja--left {
    transform: translate(-3rem, 95%) rotate(25deg) scaleX(-1);
  }

  .hero-outro-hoja--right {
    transform: translate(3rem, 95%) rotate(-25deg);
  }
}

@media (max-width: 40rem) {
  /* Mismo criterio que .about-cta-flor en su propio breakpoint (menos
     margen de sobra en pantallas estrechas, donde el párrafo ya ocupa
     casi todo el ancho útil), con el mismo 80% aplicado arriba —
     antes clamp(11rem, 48vw, 18rem). */
  .hero-outro-hoja {
    width: clamp(10.1rem, 44.2vw, 16.6rem);
  }

  /* En móvil, a petición expresa: ya no las dos abajo (se veían
     amontonadas contra el borde inferior del párrafo en pantallas
     estrechas) — la izquierda pasa a asomar por ARRIBA y la derecha
     se queda abajo, para que enmarquen el párrafo por esquinas
     opuestas. Última vuelta, también a petición expresa: "más arriba
     y más abajo" Y "tienen que salir por debajo del texto y del
     botón" — con .hero-outro-frame como referencia (como en
     escritorio, ver más arriba) esto no llega: el frame SOLO envuelve
     el párrafo (ver su propio comentario), así que bottom:0 ahí cae
     justo debajo del texto, nunca del botón de después, por mucho
     translateY que se le eche encima.

     Por eso aquí cambia la referencia misma: .hero-outro-frame pasa a
     position:static (dejar de ser el "contenedor con posición" de sus
     hijos) y .section--hero-cta .section__inner — que sí envuelve
     párrafo Y botón — pasa a serlo en su lugar. Con eso, top:0/
     bottom:0 en las hojas quedan pegados de verdad al borde superior
     del párrafo y al borde INFERIOR DEL BOTÓN respectivamente, y el
     translateY (-85%/85%, más extremo que antes) las saca de verdad
     por fuera de los dos. X (35%) más corta todavía que la vuelta
     anterior (40%): menos invasión lateral, ahora que se apoyan en un
     contenedor más alto. Mismo --hoja-t de siempre para el
     acercamiento al crecer. */
  .section--hero-cta .section__inner {
    position: relative;
  }

  .hero-outro-frame {
    position: static;
    /* Neutraliza el full-bleed de la regla base (ver su comentario
       grande más arriba): aquí las hojas ya NO se posicionan respecto
       a .hero-outro-frame (pasa a serlo .section--hero-cta
       .section__inner, ver más abajo), así que ese full-bleed no hace
       ninguna falta — y sin anularlo, el párrafo de dentro (que calcula
       su propio max-width:90% contra ESTE contenedor) quedaría un
       pelín más ancho de lo que le toca en móvil. */
    width: auto;
    margin-left: 0;
  }

  .hero-outro-hoja--left {
    top: 0;
    bottom: auto;
    left: 0;
    transform: translate(calc(-35% + var(--hoja-t, 1) * 15%), -85%) rotate(25deg) scaleX(-1);
  }

  .hero-outro-hoja--right {
    top: auto;
    bottom: 0;
    right: 0;
    transform: translate(calc(35% - var(--hoja-t, 1) * 15%), 85%) rotate(-25deg);
  }
}

/* .section--about-cta: zona berenjena (fundido continuo por scroll,
   ver animateSectionBackgrounds() en animations.js) a pantalla
   completa, con el mismo "enganche" de scroll (ver
   animateFullscreenSnap() en animations.js) — llega justo debajo de
   .section--hero-cta en Inicio (ver front-page.php), como continuación
   directa del mismo gesto. Sin background-color propio a propósito,
   mismo criterio que .section--hero-cta de arriba: deja ver el fondo
   animado del body.

   min-height:100vh EXACTO, sin tocar — a propósito, a diferencia de
   .about-cta-frame más abajo (que sí se agranda). Esta sección es la
   que animateFullscreenSnap() mide de verdad (getBoundingClientRect())
   para calcular a qué scrollY enganchar — cualquier cambio aquí (un
   min-height mayor, un margin negativo para compensarlo) desplazaría
   ese cálculo, y el "telón" dejaría de aterrizar donde debe. Por eso
   el recorte/agrandado que necesitan las flores vive en
   .about-cta-frame, un envoltorio APARTE (ver front-page.php) que
   puede ser todo lo grande que haga falta sin que este cálculo se
   entere.
   SIN overflow-x:hidden aquí, aunque parezca buena idea "por
   seguridad" (versión anterior: lo tenía, redundante con el propio
   overflow de .about-cta-frame, que ya cubre el ancho real) — a
   petición expresa, tras reportarse una SEGUNDA barra de scroll
   asomando solo en esta sección. Motivo real, una rareza real de CSS:
   si "overflow-x" vale algo distinto de "visible" (aquí, "hidden") y
   "overflow-y" no se toca (se queda en su valor por defecto,
   "visible"), la propia especificación OBLIGA al navegador a convertir
   ese "visible" en "auto" — nunca se quedan "hidden" en un eje y
   "visible" de verdad en el otro a la vez, ver
   https://www.w3.org/TR/css-overflow-3/#overflow-properties. Con
   overflow-y ya convertido en "auto" sin haberlo pedido, el navegador
   se puso a vigilar si esta sección tiene contenido que se sale por
   arriba/abajo de su propia caja para decidir si hace falta una barra
   — y .about-cta-frame, su propio hijo, se sale a propósito por los
   dos lados (inset:-260px 0, ver ahí el porqué): el navegador cuenta
   eso como "hay overflow real" (mira la posición del hijo, no si el
   HIJO ya lo recorta él solo con su propio overflow:hidden) y dibuja
   la barra igualmente. Sin overflow-x aquí, el eje Y se queda de
   verdad en "visible" (sin ninguna barra), y el ancho sigue tan
   contenido como antes: .about-cta-frame ya cubre exactamente el mismo
   ancho que esta sección (left/right:0 en su propio inset) con su
   propio overflow:hidden, así que el recorte horizontal no depende en
   ningún momento de esta regla.
   Color de texto: var(--zone-text, ...) en vez de niebla-clara fija,
   mismo patrón que .site-header (ver más arriba) — imprescindible
   aquí, a diferencia de .section--hero-cta/.section--about: berenjena
   es una zona OSCURA (necesita texto claro), pero su fondo de
   respaldo sin JS/con prefers-reduced-motion es el niebla CLARO por
   defecto del body (ver el hueco de animateSectionBackgrounds() más
   abajo) — con niebla-clara fija, ese escenario dejaría texto claro
   sobre fondo claro, ilegible. El fallback de var() (berenjena) cubre
   justo ese caso; con JS activo, --zone-text ya vale niebla-clara en
   cuanto el scroll llega a esta zona. */
.section--about-cta {
  position: relative;
  color: var(--zone-text, var(--color-berenjena));
  min-height: 100vh;
}

/* Envuelve TODO el contenido de la sección (las 2 flores + las
   frases, ver front-page.php) — vive AQUÍ, no directo en
   .section--about-cta, el min-height/overflow "de más" que antes se
   probó en la sección misma (dos versiones, las dos con problemas
   reales — ver el porqué en .section--about-cta más arriba): al ser
   un envoltorio APARTE, puede agrandarse sin que
   animateFullscreenSnap() (que mide la sección, no este div) note
   ningún cambio.
   position:absolute + inset:-260px 0 (arriba/abajo 260px de más que
   la sección, izquierda/derecha pegado a sus bordes reales) en vez de
   position:relative + alto normal: así este envoltorio pasa a medir
   él solo alto_de_la_sección + 520px, con su propio overflow:hidden
   recortando en ese límite ampliado. Las dos flores ya no llegan a
   asomar por fuera de la sección (ver .about-cta-flor--top-right/
   --bottom-left más abajo: ahora quedan enteras DENTRO), así que este
   margen de 260px ya no hace falta para contener ningún asomo real —
   se deja igual de todos modos, como red de seguridad ante la propia
   ondulación del contorno durante la animación de crecimiento (unos
   pocos px de sobra, ver el comentario de overflow:visible en
   .about-cta-flor svg) y por si se retocan las flores más adelante.
   Sigue habiendo, en cualquier caso, un tope real que evita cualquier
   fuga descontrolada durante el tramo en movimiento del "telón" de
   scroll (justo lo que fallaba con overflow-y:visible sin límite en la
   sección misma: se veía "roto",
   con contenido solapándose de forma fea con la sección anterior
   mientras aún estaba en marcha el enganche).
   display:flex + align-items:center (heredado de la sección en la
   versión anterior, trasladado aquí): centra .about-cta-links
   verticalmente dentro de este envoltorio más alto, pero da
   exactamente el mismo resultado final que centrarlo en la sección
   sin agrandar — con inset:-260px 0 arriba/abajo, el propio centrado
   flex reparte ese hueco de más a partes iguales por encima y por
   debajo del contenido, así que el contenido acaba en la misma
   posición final, ni un píxel de diferencia. */
.about-cta-frame {
  position: absolute;
  inset: -260px 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  /* pointer-events:none + .about-cta-links en auto justo debajo: el
     inset negativo de arriba (260px) hace que este envoltorio invisible
     se extienda por ENCIMA del borde superior real de la sección,
     invadiendo la parte de ABAJO de .section--hero-cta (la sección
     justo anterior en Inicio, ver front-page.php). Al venir después en
     el orden del documento, ese tramo invadido se pinta POR ENCIMA del
     contenido de esa sección anterior aunque esté vacío/transparente —
     un <div> normal sigue recibiendo (y por tanto bloqueando) los
     clics sobre toda su caja aunque no se vea nada ahí. Reportado como
     "el botón de 'Pide tu primera cita' ha dejado de funcionar": ese
     botón cae justo dentro de esa franja de 260px invadida en varias
     alturas de ventana. Sin pointer-events:none aquí, cualquier futuro
     contenido interactivo cerca del final de la sección anterior corre
     el mismo riesgo. */
  pointer-events: none;
}

/* Las dos frases de navegación (ver front-page.php), sin
   .section__inner de por medio (que limita el ancho a
   --content-max-width): a petición expresa tienen que poder ocupar
   hasta el 80% del ancho REAL de la ventana, no del contenido
   centrado habitual del resto de la web — de ahí el padding lateral
   propio (mismo valor que usa .section__inner en el resto del sitio,
   para no quedar más pegadas al borde que las demás secciones) en vez
   de heredarlo de esa clase. */
.about-cta-links {
  position: relative;
  /* Por encima de .about-cta-flor no en general (ella va a z-index:2,
     ver más abajo) — solo lo justo para participar del mismo contexto
     de apilado que las flores en vez de quedar suelta en el 0 por
     defecto, que en algunos navegadores desordena cuál de las dos
     "gana" en la zona de solape. */
  z-index: 1;
  /* Restaura los clics: .about-cta-frame (el padre, ver más arriba)
     está en pointer-events:none entero, así que sin esto los dos
     enlaces reales de aquí dentro heredarían ese "none" y dejarían de
     poder pulsarse. */
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  /* 2rem → 4rem — a petición expresa, "más separados" (repetido varias
     veces contra capturas de ~1120px de ancho, fuera del breakpoint
     móvil de 40rem de más abajo, que solo tocaba el gap AHÍ): el
     problema real era que esas capturas ya usaban este mismo valor
     base, no el de móvil — subido aquí para que la separación mayor
     aplique en todo el rango, no solo por debajo de 40rem. */
  gap: 4rem;
  width: 100%;
  padding-inline: var(--section-padding-inline);
}

/* Sube .about-cta-links por encima de las flores (normalmente al
   revés, z-index:1 aquí contra z-index:2 de .about-cta-flor más
   abajo, a propósito para que las flores "invadan un poco" por encima
   de las frases en reposo) SOLO mientras el ratón/foco está sobre uno
   de los dos enlaces — a petición expresa, tras reportarse que el
   texto se veía "translúcido" en hover. No es opacidad real del
   propio texto (comprobado: opacity:1 en todo momento) — es la flor
   de fondo (niebla-clara al 40%, ver .about-cta-flor más abajo)
   tapando parte de las letras por encima. En reposo, con el texto en
   niebla-clara (var(--zone-text, ...), un color parecido al de la
   propia flor), ese solape apenas se notaba; con el pistacho, mucho
   más saturado y distinto, el mismo solape se lee como un parche
   traslúcido cruzando las letras. :has() en vez de tocar el z-index
   de cada .about-cta-link-wrap por separado: la comparación real es
   contra .about-cta-flor, hermana de .about-cta-links (no de
   .about-cta-link-wrap, que ya está DENTRO del propio contexto de
   apilado de .about-cta-links y no puede "escapar" de él) — hace
   falta subir el propio .about-cta-links para ganarle a la flor. */
.about-cta-links:has(.about-cta-link:hover),
.about-cta-links:has(.about-cta-link:focus-visible) {
  z-index: 3;
}

.about-cta-link {
  font-family: var(--font-titulos);
  /* Muy grande a petición expresa ("como ocupando el 80% de la
     ventana") — vw, no un tamaño fijo, para que seguir siendo así de
     grande no dependa del tamaño real de pantalla. max-width: 80vw
     limita el ANCHO de la línea a ese 80% (con margen de sobra en
     frases largas para que quiebren en dos líneas en vez de
     desbordar), no controla el tamaño de letra en sí. */
  /* Suelo/vw subidos un poco (2.25rem/7vw → 2.6rem/7.5vw, máximo sin
     tocar) — a petición expresa, "en pantallas más pequeñas aumentar
     un poco el tamaño del texto": mismo criterio que
     .about-cta-flor más abajo, un empujón moderado sin llegar a
     "demasiado grande". */
  font-size: clamp(2.6rem, 7.5vw, 5.5rem);
  line-height: 1.1;
  text-decoration: none;
  max-width: 80vw;
  /* inline-block, no grid (versión anterior de este bloque): ese grid
     de dos capas (.about-cta-link__medida + __texto superpuestas)
     existía solo para reservar de antemano el ancho extra que ganaba
     el texto real al engordar/espaciarse en el hover — a petición
     expresa, "que no se estiren... sino que cambien de color", el
     hover ya no cambia font-weight/letter-spacing (ver
     .about-cta-link__texto más abajo), así que el ancho del enlace ya
     no cambia nunca y ese hack de reserva de ancho no hace falta. */
  display: inline-block;
  /* "Respira" al pasar el ratón/dar foco, en vez de subrayarse — a
     petición expresa ("inspiración" al entrar, "expiración" al salir,
     una animación orgánica, no un subrayado). Duración/curva
     asimétricas a propósito, calcadas del ritmo real de una
     respiración relajada (la inspiración es más corta y decidida; la
     espiración, más larga y que se deja ir) — ver el detalle exacto en
     :hover/:focus-visible más abajo, que sobreescribe esta transición
     SOLO mientras dura el hover/foco. El propio prefers-reduced-motion
     global (ver arriba del archivo) colapsa esta transición a 0.01ms
     sin tocar nada aquí. 1.6s → 1.3s (espiración) — a petición
     expresa, "un poquitín más rápida, solo un poquito", igual que la
     inspiración de :hover/:focus-visible más abajo (0.9s → 0.7s):
     mismo ritmo asimétrico de siempre (entrada más corta y decidida,
     salida más larga y que se deja ir), solo con las dos mitades
     acortadas en la misma proporción. */
  transition: transform 1.3s cubic-bezier(0.61, 1, 0.55, 1);
  /* will-change/backface-visibility — a petición expresa, "en el
     proceso de crecer tampoco quiero que se haga translúcido": la
     opacidad real del texto ya es 1 en todo momento (comprobado con
     capturas fotograma a fotograma durante toda la transición), pero
     algunos navegadores recalculan el antialiasing del texto justo
     cuando empiezan a promocionar un elemento a su propia capa de
     composición para animar su "transform" — ese recálculo puede
     verse como un instante de "suavizado"/pérdida de nitidez, fácil
     de confundir con transparencia. Con will-change avisando de
     antemano que este "transform" va a animarse, el navegador ya
     tiene la capa preparada antes de que empiece el hover, en vez de
     crearla de golpe en cuanto se dispara — sin ese "salto" de capa,
     no hay recálculo de antialiasing a mitad de la animación.
     backface-visibility:hidden es el mismo apaño de siempre para el
     mismo síntoma en Chrome/Safari (texto "blurry"/suavizado durante
     un transform), sin efecto visible aquí (el enlace nunca gira). */
  will-change: transform;
  backface-visibility: hidden;
}

.about-cta-link:hover,
.about-cta-link:focus-visible {
  /* 1.025 → 1.05 — a petición expresa, "agrandar un poquito más": aún
     lejos de un scale agresivo que se sienta como un salto en vez de
     una respiración, a este tamaño de letra (hasta 88px). Sin reflow
     (transform, no font-size/letter-spacing), así que ya no hace
     falta ningún hack de reserva de ancho. */
  transform: scale(1.05);
  /* Inspiración: más corta y con un arranque más decidido que la
     espiración de arriba (que hereda la transición larga de la clase
     base al soltar el hover/foco). 0.9s → 0.7s, mismo motivo que el
     1.6s → 1.3s de arriba. */
  transition: transform 0.7s cubic-bezier(0.34, 0, 0.24, 1);
}

.about-cta-link__texto {
  /* 400 (Regular), no 500 (Medium, el peso que usa el resto de
     títulos de la web) — a petición expresa, a un tamaño tan grande
     (hasta 88px) el Medium se leía más grueso/pesado de lo que se ve a
     tamaño normal de titular. Fijo en 400 siempre, también en hover —
     a diferencia de una versión anterior que subía a 650 ahí (ver
     abajo el porqué de quitarlo). */
  font-weight: 400;
  /* color hereda var(--zone-text, ...) de body (ver el bloque grande
     de --zone-text más arriba en este archivo) mientras no hay hover:
     el mismo fundido sincronizado con el scroll que ya seguía este
     enlace antes de este cambio, sin tocarlo. transition solo en
     "color" — el resto (font-weight de arriba) ya no anima, así que no
     hace falta declararlo aquí. 1.6s → 1.3s, mismo motivo/mismo ritmo
     que el transform de .about-cta-link de arriba. 1.3s → 0.65s — a
     petición expresa, "que el cambio de color al pasar el ratón sea
     más rápido": el transform (scale, "respirar") se queda con su
     ritmo de siempre, solo el color se acelera. */
  transition: color 0.65s cubic-bezier(0.61, 1, 0.55, 1);
}

/* Antes (versión descartada, "no me ha gustado"): el hover engordaba
   el trazo (font-weight 400→650) y separaba las letras (letter-spacing),
   un "estirado" que además obligaba al hack de reserva de ancho de
   arriba. A petición expresa, sustituido por un cambio de color a
   pistacho — más elegante, sin ensanchar el propio texto — manteniendo
   SOLO el zoom sutil de .about-cta-link de arriba como "crecimiento".
   --color-pistacho (marca, sin aclarar — se probó primero
   --color-pistacho-medio aclarado, descartado también a petición
   expresa): ya pasa AA de sobra contra este fondo (berenjena, ~6:1,
   ver el comentario de body.bg-tint-pistacho-fuerte más arriba en
   este archivo), así que aclararlo no hacía falta para el contraste. */
.about-cta-link:hover .about-cta-link__texto,
.about-cta-link:focus-visible .about-cta-link__texto {
  color: var(--color-pistacho);
  /* 0.7s → 0.35s, mismo motivo/misma proporción que el 1.3s → 0.65s de
     la transición de salida en .about-cta-link__texto de arriba — a
     petición expresa, cambio de color más rápido al entrar el hover. */
  transition: color 0.35s cubic-bezier(0.34, 0, 0.24, 1);
}

/* Alineadas a lados opuestos, a petición expresa: la primera frase
   pegada a la izquierda, la segunda (debajo) pegada a la derecha.
   align-self, no text-align por sí solo: cada bloque tiene que medir
   solo lo que su propio texto necesita (hasta el tope de max-width de
   arriba), no el 100% de .about-cta-links — si no, "a la derecha"
   solo movería el texto DENTRO de una caja ya pegada a la izquierda,
   sin acercarla de verdad al borde derecho.
   margin-inline-start/end (clamp, responsive): un empujón hacia el
   centro además del padding normal de la sección — a petición
   expresa, "un poquito más al centro" las dos, sin llegar a
   centrarlas del todo (siguen pegadas cada una a su lado, solo con
   más aire hasta el borde real de la ventana).
   Sin transform-origin propio (a diferencia de una versión anterior,
   que lo ponía a juego con cada lado: left/right center, para que el
   "respirar" del hover -ver .about-cta-link más arriba- creciera
   desde el borde al que está pegado el texto) — a petición expresa,
   ahora crece hacia sus cuatro lados por igual (el centro por
   defecto), como una inspiración real, no empujando hacia un lado.

   En .about-cta-link-wrap (el <div> que envuelve cada .about-cta-link,
   ver front-page.php), no en el propio .about-cta-link como antes —
   a propósito: el wrapper es ahora el hijo directo de flex real (el
   que necesita align-self para pegarse a un lado), y además es quien
   anima la entrada por scroll (deslizamiento desde el lado, ver
   animateAboutCtaLinksReveal() en animations.js) con su propio
   "transform" por JS — si align-self siguiera viviendo en
   .about-cta-link, tendría el mismo problema que ya se evitó moviendo
   TODO lo demás aquí: dos animaciones (el "respirar" del hover por CSS
   y el deslizamiento de entrada por JS) peleando por el mismo
   "transform" del mismo elemento. */
.about-cta-link-wrap--left {
  align-self: flex-start;
  text-align: left;
  margin-inline-start: clamp(1rem, 6vw, 6rem);
}

.about-cta-link-wrap--right {
  align-self: flex-end;
  text-align: right;
  margin-inline-end: clamp(1rem, 6vw, 6rem);
}

/* Las dos flores de fondo (mismo assets/illustrations/flor.svg que ya
   usa la arena de "Podemos acompañarte", ver front-page.php)
   asomando desde esquinas opuestas, mucho más grandes que su propio
   hueco visible (de ahí el desplazamiento negativo de top/right y
   bottom/left: la mitad de la flor asoma por fuera del área "de
   siempre" de la sección — .about-cta-frame, su contenedor real, deja
   de sobra para que quepa entera sin cortarse, ver ahí el porqué).
   Niebla-
   clara a baja opacidad, no un color de acento — a petición expresa,
   para que se lean "como si formaran parte del fondo" en vez de una
   ilustración propia compitiendo con las frases. z-index por encima de
   .about-cta-links (que es 1) a propósito: para que invadan "un
   poquito" por encima de las frases, tal como se pidió, en vez de
   quedar tapadas por ellas — pointer-events:none además de
   aria-hidden en el HTML, para que esa invasión nunca le robe el clic
   a los enlaces de debajo. */
.about-cta-flor {
  position: absolute;
  z-index: 2;
  /* Un 20% más pequeñas que antes (clamp(20rem, 42vw, 38rem)) — a
     petición expresa, tras seguir viéndose cortadas por arriba/abajo
     incluso con el margen de sobra de .about-cta-frame: más pequeñas
     Y más adentro (ver el porqué del offset en
     .about-cta-flor--top-right/--bottom-left más abajo) entre las dos
     dejan mucho más colchón real dentro de ese margen.

     16rem → 18rem de suelo — a petición expresa, "en pantallas más
     pequeñas las flores se hacen muy pequeñas": el suelo de 16rem se
     alcanzaba ya en torno a los 753px de ancho (34vw = 16rem justo
     ahí) y se quedaba clavado en ese tamaño el resto del camino hasta
     el breakpoint móvil de 40rem — un poco más grande sin llegar a
     "demasiado". */
  width: clamp(18rem, 36vw, 30rem);
  opacity: 0.4;
  pointer-events: none;
}

.about-cta-flor svg {
  display: block;
  width: 100%;
  height: auto;
  /* visible, no el "hidden" implícito por defecto: la onda del
     crecimiento (ver flor-animada.js) sobresale unos pocos px por
     fuera del viewBox en su pico — con el recorte por defecto se
     vería un contorno cortado en línea recta durante ese instante. */
  overflow: visible;
}

.flor-animada__path {
  fill: var(--color-niebla-clara);
}

/* calc(260px + 3vh), no simplemente 3vh: el contenedor real de estas
   flores ya no es .section--about-cta, es .about-cta-frame (ver más
   arriba), que empieza 260px MÁS ARRIBA que la sección de verdad (su
   propio inset:-260px 0). Los 260px de la fórmula cancelan exactamente
   ese desplazamiento del contenedor, así que el resultado visual final
   es el mismo que pedir "3vh desde el borde real de la sección" — que
   es lo que de verdad se quiere. Sin esa compensación, la flor
   quedaría 260px más arriba/abajo de la cuenta.
   +3vh, no -Xvh (como en las versiones anteriores, que hacían que la
   flor asomara por FUERA de la sección) — a petición expresa: la de
   arriba a la derecha "más abajo" y la de abajo a la izquierda "más
   arriba", las dos entrando ya del todo DENTRO de la sección en vez de
   asomar por su borde. -2%, no -4%, en el eje horizontal por el mismo
   motivo ("un poco más al centro"). */
.about-cta-flor--top-right {
  top: calc(260px + 3vh);
  right: -2%;
}

.about-cta-flor--bottom-left {
  bottom: calc(260px + 3vh);
  left: -2%;
}

/* 64rem, no 40rem: mismo umbral que .nav-toggle (móvil+tablet, no solo
   móvil) — a petición expresa, "en pantallas móvil y en tablet" las dos
   frases deben separarse más, no solo por debajo de 40rem. .about-cta-links
   se centra verticalmente como bloque (ver align-items:center en
   .about-cta-frame más arriba), así que agrandar el gap entre los dos
   empuja a cada uno por igual hacia su lado — el primero hacia arriba,
   el segundo hacia abajo — sin mover el punto medio del conjunto. */
@media (max-width: 64rem) {
  .about-cta-links {
    gap: 6rem;
  }
}

@media (max-width: 40rem) {
  /* Menos margen de sobra en pantallas estrechas: el 80vw de arriba ya
     casi coincide con el ancho útil real (menos el padding lateral),
     así que un tope adicional no aporta nada y solo arriesga cortar
     antes de tiempo. */
  .about-cta-link {
    max-width: 100%;
  }

  /* 2rem → 3.5rem → 6rem — a petición expresa, "los dos textos un poco
     más separados entre sí, el de arriba un poco más arriba y el de
     abajo un poco más abajo" (y después, "ponlos más separados"): ver
     el porqué del gap en el @media (max-width: 64rem) de arriba, que ya
     cubre este rango también. */

  /* 11rem/48vw/18rem → 13rem/50vw/20rem — a petición expresa, mismo
     motivo que el suelo de la regla de escritorio de más arriba: un
     poco más grandes en móvil también, sin pasarse. */
  .about-cta-flor {
    width: clamp(13rem, 50vw, 20rem);
  }
}

/* .section--about: zona niebla (fundido continuo por scroll, ver
   animateSectionBackgrounds() en animations.js), mismo criterio que el
   resto de zonas de Inicio. Sin background-color propio a propósito:
   deja ver el fondo animado del body — coincide además con el propio
   --color-niebla de fondo por defecto del body (ver arriba), así que
   incluso sin JS/con prefers-reduced-motion (ver el hueco de
   animateSectionBackgrounds()) el fondo visible ya es el correcto sin
   depender de la animación. Berenjena, no niebla-clara: aquí el fondo
   es claro, hace falta texto oscuro (mismo criterio de contraste que
   en las páginas interiores). */
.section--about {
  color: var(--color-berenjena);
  /* Bloque interactivo (arena física de ilustraciones, ver
     .hoja-mesa-arena en hoja-a-mesa.css) a pantalla completa en
     cualquier tamaño de pantalla, a petición expresa — mismo patrón
     que .hero (min-height:100vh + flex centrado) más arriba. */
  min-height: 100vh;
  display: flex;
  align-items: center;
  /* El "enganche" de scroll a pantalla completa (que se coloque
     centrada, ocupando toda la ventana, en cuanto se entra en ella)
     vive en JS (animateHeroArenaSnap, ver animations.js) con un
     scroll animado real vía ScrollTrigger — no aquí: un scroll-snap
     nativo por CSS no producía ningún movimiento visible cuando se
     entraba despacio en la sección, sin llegar a soltar el gesto de
     scroll justo al borde. */
  /* Sin el padding-block/padding-inline de .section (ver arriba) — a
     petición expresa, solo para esta sección: con el padding puesto,
     la arena física quedaba metida en una caja más pequeña que la
     pantalla real, y su propio overflow:hidden recortaba (o dejaba
     "esconderse" detrás del padding, del mismo color niebla que el
     fondo, así que parecía que las ilustraciones desaparecían) a
     cualquier ilustración que llegara a rozar ese borde. El resto de
     secciones de la web siguen con su padding normal — esto no lo
     toca, solo anula la regla genérica aquí. */
  padding: 0;
}

.section--about .section__inner {
  /* Sin esto, al ser hijo único de un flex container en fila (por
     defecto), este bloque se encogería a su contenido en vez de
     ocupar el ancho completo de la sección — el max-width propio de
     .hoja-mesa-arena dentro dejaría de calcularse contra el ancho real
     de la sección. */
  width: 100%;
  /* Sin tope de ancho aquí tampoco (a diferencia del resto de
     secciones, que si respetan --content-max-width): la arena entera
     debe poder usar el 100% del ancho de pantalla, no solo el ancho de
     lectura cómodo del resto del contenido. */
  max-width: none;
}

/* Antes limitaba .section__inner a 44rem (ancho de lectura cómodo
   para las 5 secciones de texto corrido que había antes) — con la
   "arena" física de ilustraciones grandes de ahora (ver
   .hoja-mesa-arena en hoja-a-mesa.css), ese ancho se quedaba corto.
   .hoja-mesa-arena ya pone su propio max-width, así que aquí no hace
   falta ninguno. */

/* Tamaño explícito para los títulos de las secciones oscuras de
   Inicio (antes dependían del tamaño h2 por defecto del navegador).
   El color ya lo hereda de la sección (--color-niebla-clara). */
.section--about .section__inner h2 {
  font-size: clamp(1.4rem, 3vw, 1.9rem);
}

.section--about p {
  margin: 0 0 1.2em;
}

.section--about p:last-child {
  margin-bottom: 0;
}

/* "Podemos acompañarte": antes eran 5 secciones seguidas a toda
   pantalla (un título+párrafo cada una, fondo alternando oliva/lavanda
   al pasar de una a otra), después una rejilla de 5 tarjetas "hoja →
   mesa" — a petición expresa, ahora las 5 ilustraciones conviven en una
   misma "arena" física (Matter.js, ver hoja-a-mesa.css/.js): caen,
   chocan entre sí y se dejan atraer con suavidad por el cursor
   (magnético), sin fondo propio, solo el fondo niebla de la sección.
   El layout de la arena en sí (tamaño,
   posicionamiento de cada ilustración) vive entero en hoja-a-mesa.css. */

.section__intro {
  /* Sin color propio a propósito: hereda del contexto — en Servicios
     (la única página que usa esta clase ahora mismo) no hay ninguna
     zona oscura alrededor, así que hereda el berenjena por defecto del
     body (legible sobre fondo claro). Ponerlo fijo en blanco aquí lo
     dejaba invisible ahí — ya nos pasó con la intro de la sección de
     Tarifas. */
  max-width: 40rem;
  margin: 0 auto 2.5rem;
  text-align: center;
}

/* Título de sección (h2 suelto, directo dentro de .section__inner):
   mismo patrón en toda la web — centrado, como ya iba el h1 de
   .page-header. No afecta a títulos de tarjetas/ítems de lista
   (esos viven anidados más adentro, no como hijo directo). */
.section__inner > h2 {
  text-align: center;
  font-size: clamp(1.6rem, 3vw, 2.1rem);
}

/* Cabecera de página interior (Servicios, Equipo, Contacto...). Sin
   fondo propio: el color de cada página lo pone body.bg-tint-* (ver
   header.php), toda la página de una vez, no una franja aparte. */
.page-header {
  padding: clamp(3rem, 8vw, 6rem) var(--section-padding-inline) 0;
}

.page-header__inner {
  max-width: var(--content-max-width);
  margin-inline: auto;
  text-align: center;
}

/* Entrada de blog: cabecera (título/fecha/volver) en la misma columna
   de ancho de lectura que .entry-content (65ch) más abajo en la misma
   página, en vez de quedarse en el ancho completo de --content-max-width
   como el resto de páginas — para que toda la entrada, de arriba abajo,
   se lea en una única columna consistente. */
/* 62rem, no 65ch — a petición expresa, "que ocupe casi el mismo ancho
   de la foto, sin llegar a ocuparlo": .single-post__cover (la foto,
   más abajo) llega hasta --content-max-width (72rem); 62rem se queda
   claramente por debajo sin volver a la columna de lectura estrecha
   de antes. Solo el ancho del bloque cambia — el h1 sigue con el
   mismo font-size (.page-header h1 más abajo, sin tocar), así que
   ahora tiene más sitio para respirar antes de partir línea. */
body.single-post .page-header__inner {
  max-width: 62rem;
}

.page-header h1 {
  font-size: clamp(2rem, 4.5vw, 3rem);
}

.page-header__intro {
  max-width: 40rem;
  margin: 1rem auto 0;
  /* Berenjena, no lavanda: lavanda sobre niebla da 4.19:1, por debajo
     del mínimo AA (4.5:1) para texto normal. */
  color: var(--color-berenjena);
}

/* position:relative + overflow:hidden, mismo patrón que .section--pricing
   más abajo (ver ese comentario para el porqué grande): esta sección
   aloja su PROPIO estampado decorativo (.servicios-estampado-fondo con
   data-estampado-local, ver page-servicios.php/servicios-estampado.js),
   así que necesita ser el contenedor posicionado sobre el que se mide
   ese inset:0 — sin esto, heredaría el position:relative de #main y su
   "top" en % se mediría contra el alto de toda la página, no contra el
   de esta sección sola (que es justo lo que se quiso evitar al separar
   el estampado en un recinto por sección: que Preguntas frecuentes o
   Tarifas creciendo desajustara también las filas de aquí, que ni
   siquiera cambian de tamaño). */
.section--areas-atencion {
  position: relative;
  overflow: hidden;
}

/* Servicios: el resto de la página (Áreas de atención, FAQ, Tarifas)
   usa el ancho completo de .section__inner, pero el texto de la intro
   (h1 y de cada sección) NO se ensancha hasta ahí — a ese ancho
   (1152px) las líneas superan de largo los ~75 caracteres recomendados
   para texto largo. 65ch, igual que el resto del texto largo de la
   web (.entry-content/.condition-content/.policy-content): más ancho
   que la columna de lectura estrecha (40rem) que usan el resto de
   páginas interiores —sigue leyéndose mejor que pegado a esa
   columna estrecha—, pero ya no estira la línea hasta perder la
   medida de lectura cómoda.
   Escogido por estructura (":has(+ .section--servicios-detalle)" /
   ".section--areas-atencion"), no por la clase de tinte del body: esta
   página comparte ahora el mismo fondo melocotón que Blog (ver
   body.bg-tint-melocoton en header.php), así que ya no tiene una
   clase de tinte propia que la distinga de esa otra página. */
.page-header:has(+ .section--servicios-detalle) .page-header__intro,
.section--areas-atencion .section__intro {
  max-width: 65ch;
}

/* El margen inferior base de .section__intro (2.5rem) sumado al
   margin-top de .service-areas dejaba casi 70px de aire entre la
   intro y "Adultos" — a petición expresa, se recorta aquí solo para
   esta intro concreta (única .section__intro de la página). Bajado de
   0.75rem a 0.25rem (junto con .service-areas más abajo, que pasa de
   0.25rem a 0 de margin-top): a petición expresa, "más cerquita del
   texto" — con las tarjetas ahora más bajas (ver
   .service-area-card__tile) el hueco de antes se notaba de sobra. */
.section--areas-atencion .section__intro {
  margin-bottom: 0.25rem;
}

/* "Áreas de atención" (h2 + intro) — a petición expresa, "no hace falta
   que haga la transición de color, puede aparecer directamente en
   blanco": sin esto, este título y párrafo heredan el color del body
   (var(--zone-text, ...), ver body.bg-tint-lavanda más arriba), que se
   va mezclando de berenjena a niebla-clara EN VIVO durante el primer
   fundido de animateBgFade() (animations.js) — el mismo fundido que
   lleva el fondo de niebla a lavanda justo en esta sección (ver
   data-bg-fade="lavanda" en page-servicios.php). Niebla-clara fijo,
   sin var(--zone-text, ...): este título/párrafo ya nace en blanco,
   sin acompañar ese fundido de fondo con el suyo propio. El resto de
   la sección (tarjetas, botones) no se toca — solo este bloque, que es
   el que se pidió expresamente. */
.section--areas-atencion h2,
.section--areas-atencion .section__intro {
  color: var(--color-niebla-clara);
}

/* Servicios: el hueco entre el h1+intro y la lista de debajo
   (Psicología/Psiquiatría) usaba el espaciado grande entre secciones
   (--section-padding-block, 56–112px) — se igualó primero al hueco
   título→contenido de 2.5rem que usan "Áreas de atención"/"Tarifas"
   (margen inferior de .section__intro), pero con los botones ahora
   mucho más grandes (hoja/flor animadas de fondo, ver
   .condition-list__summary más abajo) ese mismo 2.5rem se notaba de
   sobra — a petición expresa, "más pegados al texto", rebajado aquí
   solo para esta sección (que ya no tiene por qué mantener la misma
   proporción exacta que Áreas de atención/Tarifas: son bloques
   visualmente muy distintos ahora). Bajado otra vez de 1rem a 0.5rem, a
   petición expresa ("subela un poquito"). margin-top negativo añadido
   después, a petición expresa ("que invada un poquito el espacio de la
   caja que tiene encima"): .page-header no lleva padding-bottom propio
   (ver .page-header más abajo, termina justo en el texto de la intro),
   así que solo con padding-top no bastaba para invadir de verdad su
   espacio — hacía falta un margin-top negativo para que esta sección
   se solape con el tramo final de la de arriba. Sigue siendo "un
   poquito": la hoja/flor son formas orgánicas con bastante espacio en
   blanco hacia sus esquinas superiores, así que este solape cae ahí,
   no sobre el propio texto de "Todas nuestras sesiones...". */
/* -2rem fijo → clamp fluido en vw — a petición expresa, "en pantalla
   completa más grandes, y a medida que la ventana va empequeñeciendo
   que bajen un poquito para no tapar el texto de arriba": con el
   cuadrado compartido ahora más grande en este tramo (28rem de tope,
   ver .condition-list__summary más abajo), la hoja/flor (que sobresale
   de su cuadrado al escalar) se acerca más al texto de la intro que
   antes en cualquier punto de este tramo — así que en vez de un
   solape fijo de -2rem en todo momento, este clamp lo mantiene solo en
   la ventana más ancha de verdad (a partir de ~120rem/1920px, -5vw+4rem
   ya toca el suelo de -2rem) y lo va reduciendo (menos negativo, "más
   abajo") según la ventana se estrecha hacia el siguiente tramo
   (64rem-96rem, que ya usa su propio margin-top:0 y un cuadrado bastante
   más pequeño, con margen de sobra sin necesitar este ajuste). */
.page-header + .section--servicios-detalle {
  padding-top: 0.5rem;
  margin-top: clamp(-2rem, -5vw + 4rem, -0.5rem);
}

/* Mismo motivo/mismo arreglo que @media(max-width:40rem) más abajo —
   a petición expresa, tras comprobarse con capturas reales que entre
   40rem y 64rem (donde .condition-list ya cae en una sola columna, ver
   el comentario grande de esa regla más abajo) este margin-top negativo
   (pensado solo para "invadir un poquito" en escritorio, con Psicología/
   Psiquiatría LADO A LADO) volvía a solapar de verdad con el texto de
   la intro, igual que ya pasaba en móvil por debajo de 40rem. */
@media (min-width: 40.0625rem) and (max-width: 64rem) {
  .page-header + .section--servicios-detalle {
    margin-top: 0;
  }
}

/* El hueco entre Psicología/Psiquiatría y "Áreas de atención" sumaba el
   padding inferior de una sección con el superior de la siguiente
   (2 × --section-padding-block, hasta 224px) — demasiado, sobre todo
   con la nota de "presencial u online" justo encima. A petición
   expresa ("el mismo espacio exacto entre todo, de la parte de abajo
   de algo a la parte de arriba de lo siguiente"), se iguala al mismo
   2.5rem que ya usan el resto de huecos título→contenido de esta
   página (ver comentario de arriba), en vez de dejar un
   --section-padding-block completo (56–112px, seguía siendo más). */
.section--servicios-detalle {
  padding-bottom: 4rem;
}

/* A petición expresa, "que 'Áreas de atención' salga un poco más
   abajo": un pequeño padding-top propio en vez del 0 de antes (que
   dejaba esta sección pegada del todo al hueco de arriba, con el
   padding-bottom:4rem de .section--servicios-detalle como único
   aire). Sigue siendo bastante menos que un --section-padding-block
   completo (56–112px) para no reintroducir el hueco de sobra que
   describe el comentario de arriba. */
.section--servicios-detalle + .section {
  padding-top: 2.5rem;
}

/* A partir de los botones "Ver qué tratamos"/"Ver tarifas" (fin de
   "Áreas de atención"): mismo criterio que el hueco de arriba —
   sumar el padding inferior de una sección con el superior de la
   siguiente daba hasta 224px de aire entre bloques que ya vienen
   pegados por contenido corto (CTA → FAQ → Tarifas). Un solo
   --section-padding-block entre cada par es suficiente. */
.section--areas-atencion + .section,
.section--faq + .section {
  padding-top: 0;
}

/* Áreas de atención: tarjetas cuadradas con la ilustración y el
   título superpuestos, y un hilo melocotón que se dibuja a mano al
   pasar el cursor o dar foco — trasladado tal cual desde la maqueta
   vinculare-servicios.html (assets/animations/), a petición expresa
   ("mantén exactamente la misma animación del hilo, la tipografía y
   el layout"), solo renombrando las clases a la convención BEM
   (.service-area-card__algo) que ya usa el resto del tema. Cada
   tarjeta es un .service-area-card (el <a>, ver page-servicios.php)
   con una .service-area-card__tile dentro que fija el cuadrado
   (aspect-ratio) sobre el que se posicionan, en capas, el título, la
   ilustración y el SVG del hilo. */
/* Dos columnas INDEPENDIENTES (flex, no grid) — a petición expresa:
   "que las dos columnas estén más desajustadas, pero que cada
   elemento tenga menos espacio con el que tiene debajo". Con un
   grid de 2 columnas (versión anterior de este bloque) las dos cosas
   no se podían pedir por separado: el grid comparte las mismas
   "filas" entre columnas, así que el margen que desalineaba la
   columna derecha también engordaba la fila entera y, con ello, el
   hueco de la IZQUIERDA hasta la siguiente tarjeta — más desajuste
   entre columnas significaba, sí o sí, más espacio dentro de cada
   columna también. Con dos .service-areas__col por separado, cada
   una con su propio "gap" interno, y el desajuste puesto una única
   vez como margin-top del contenedor derecho entero (no repetido por
   tarjeta), las dos distancias son variables sueltas: el "gap" de
   abajo controla SOLO la distancia de una tarjeta a la siguiente en
   su misma columna, y el margin-top de .service-areas__col--offset
   controla SOLO cuánto más abajo arranca la columna derecha frente a
   la izquierda. */
/* Con 5 tarjetas en 2 columnas independientes (3 arriba a la
   izquierda, 2 a la derecha — ver el reparto par/impar en
   page-servicios.php), la columna izquierda es, sí o sí, una tarjeta
   más alta que la derecha: con poco desajuste entre columnas eso
   dejaba la última tarjeta (Terapia de pareja) colgando sola abajo a
   la izquierda, sin ninguna otra tarjeta a su altura al lado — a
   petición expresa, ahora se reparte como un auténtico "muro de
   ladrillo" (offset = medio "paso" de tarjeta, no un valor cualquiera):
   .service-areas__col--offset arranca justo a mitad de camino entre
   el inicio de una tarjeta y la siguiente de la columna vecina, así
   que el grupo entero — leído de arriba abajo, columna a columna — cae
   en el MISMO intervalo constante en vez de solo dos alturas de
   arranque distintas. El cálculo (0.27 × ancho del bloque + mitad del
   gap vertical) sale de la propia aspect-ratio de la baldosa
   (1/1.08 sobre la mitad del ancho del bloque menos el gap horizontal):
   así el desajuste se recalcula solo si cambia el ancho del bloque
   (--service-areas max-width más arriba) o el propio aspect-ratio, sin
   tocar este valor a mano. Las columnas siguen leyéndose
   "desalineadas" (a petición expresa, ver más arriba), pero el
   conjunto ya no se siente descompensado. */
/* max-width/margin-inline: la baldosa de cada tarjeta (.service-area-card__tile)
   es aspect-ratio 1/0.92 sobre el 100% de su columna — a todo el
   ancho de la sección (1152px) eso daba baldosas de ~570×615px, con
   la ilustración topada en un máximo fijo en px (calcado de la
   maqueta, ver .service-area-card__illustration--*) dejando mucho
   espacio vacío alrededor. Se acota aquí el ancho del bloque entero
   para que la baldosa encoja con él y la ilustración ocupe
   proporcionalmente más, en vez de tocar esos topes en px uno a uno
   (46rem originalmente, subido a 52.9rem —un 15% más— a petición
   expresa junto con el resto del contenido de la tarjeta más abajo). */
.service-areas {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 auto 0;
  max-width: 60.8rem;
}

.service-areas__col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.service-areas__col--offset {
  margin-top: calc((100% - 12px) * 0.27 + 0.75rem);
}

@media (max-width: 40rem) {
  .service-areas {
    flex-direction: column;
    gap: 24px;
    /* align-items:flex-start (arriba, pensado para que en escritorio
       las dos columnas no se estiren a la misma altura) pasa a ser el
       eje CRUZADO al apilar en columna — sin este reset, cada tarjeta
       se encoge a su contenido en vez de ocupar el ancho completo, y
       con contenido interno todo en position:absolute (título,
       ilustración...) ese "encoger" prácticamente colapsa la tarjeta
       entera. */
    align-items: stretch;
  }

  /* Una sola columna: aplana las dos .service-areas__col (que dejan
     de generar caja propia, sus tarjetas pasan a ser hijas directas
     de .service-areas) para que el "gap" de arriba las reparta a
     todas por igual, en vez de mantenerlas en dos grupos separados
     con el hueco de columna a columna entre ellos. order (ver el
     "style" inline de cada tarjeta, puesto en
     vinculare_render_service_area_card() en functions.php) las
     reordena de vuelta a su secuencia real — sin esto quedarían
     agrupadas "primero toda la izquierda, luego toda la derecha" en
     vez de intercaladas. */
  .service-areas__col {
    display: contents;
  }

  .service-areas__col--offset {
    margin-top: 0;
  }
}

.service-area-card {
  position: relative;
  display: block;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}

/* El outline base (3px solid, ya volteado a niebla-clara sobre este
   fondo lavanda — ver body.bg-tint-lavanda a:focus-visible más
   arriba) sirve tal cual; aquí solo se amplía el offset y se redondea
   la esquina, igual que en la maqueta, para que no quede pegado al
   borde de una tarjeta tan grande. */
.service-area-card:focus-visible {
  outline-offset: 6px;
  border-radius: 4px;
}

.service-area-card__tile {
  width: 100%;
  aspect-ratio: 1 / 0.92;
  position: relative;
  /* Contenedor de consulta para el "cqi" de .service-area-card__title-line
     (ver más abajo) — sin esta línea no había ningún elemento con
     container-type en toda la hoja de estilos, así que ese "cqi" no
     tenía ningún contenedor del que medir y se resolvía a 0: el título
     se quedaba siempre en el mínimo del clamp(), nunca llegaba a
     crecer con el ancho real de la tarjeta como estaba pensado. */
  container-type: inline-size;
}

.service-area-card__title {
  position: absolute;
  left: 12%;
  top: 14%;
  width: 68%;
  z-index: 3;
  pointer-events: none;
  font-family: var(--font-titulos);
  line-height: 0.98;
  text-align: left;
  color: var(--color-niebla-clara);
  transform-origin: left top;
  transition: transform 0.5s cubic-bezier(0.22, 0.9, 0.3, 1);
}

/* El título crece bastante más que la ilustración al pasar el cursor
   o dar foco — a petición expresa, "que con los hovers no solo
   aumente el tamaño del svg sino también el del título" y, tras
   probar el mismo 1.045 que la ilustración, "quiero que se hagan aún
   más grandes" (probado primero también con un cambio de color, mismo
   hover, pero descartado: "lo del cambio de color no me ha gustado").
   transform:scale en vez de tocar font-size: mismo mecanismo que
   .service-area-card__illustration (--hover-transform), sin
   recalcular el clamp() con cqi de .service-area-card__title-line en
   cada hover. z-index:3 ya por encima de la ilustración (z-index:2,
   ver más arriba), así que crecer más no la tapa. */
.service-area-card:hover .service-area-card__title,
.service-area-card:focus-visible .service-area-card__title,
.service-area-card.is-inview .service-area-card__title {
  transform: scale(1.2);
}

.service-area-card__title-line {
  display: block;
  font-weight: 500;
  font-size: clamp(1.96rem, 9.9cqi, 2.88rem);
}

.service-area-card__title-line--italic {
  font-style: italic;
  margin-top: 0.05em;
}

/* Ilustración en Berenjena (currentColor, ver vinculare_inline_svg_recolor()
   en page-servicios.php) que se acerca un poco al pasar el cursor —
   cada área fija su propia posición/tamaño y su propio
   --hover-transform más abajo, igual que en la maqueta. */
.service-area-card__illustration {
  position: absolute;
  z-index: 2;
  color: var(--color-berenjena);
  transition: transform 0.5s cubic-bezier(0.22, 0.9, 0.3, 1);
}

.service-area-card__illustration svg {
  width: 100%;
  height: auto;
  display: block;
}

.service-area-card:hover .service-area-card__illustration,
.service-area-card:focus-visible .service-area-card__illustration,
.service-area-card.is-inview .service-area-card__illustration {
  transform: var(--hover-transform);
}

.service-area-card__thread {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  overflow: visible;
  pointer-events: none;
}

/* stroke-dasharray/dashoffset a 1 + pathLength="1" en el propio <path>
   (ver page-servicios.php): el hilo se "dibuja" de un extremo a otro
   animando solo el dashoffset, sin depender de la longitud real de
   cada trazado (distinta en cada tarjeta). */
.service-area-card__thread-path {
  fill: none;
  stroke: var(--color-melocoton);
  stroke-width: 3.45;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.8s cubic-bezier(0.45, 0, 0.55, 1);
}

.service-area-card:hover .service-area-card__thread-path,
.service-area-card:focus-visible .service-area-card__thread-path,
.service-area-card.is-inview .service-area-card__thread-path {
  stroke-dashoffset: 0;
}

.service-area-card__thread-knot--start {
  fill: var(--color-melocoton);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.service-area-card:hover .service-area-card__thread-knot--start,
.service-area-card:focus-visible .service-area-card__thread-knot--start,
.service-area-card.is-inview .service-area-card__thread-knot--start {
  opacity: 1;
}

/* El nudo final aparece con retraso (1.65s) para que coincida con el
   momento en que el trazo del hilo llega hasta él, no antes. */
.service-area-card__thread-knot--end {
  fill: var(--color-melocoton);
  opacity: 0;
  transition: opacity 0.3s ease 1.65s;
}

.service-area-card:hover .service-area-card__thread-knot--end,
.service-area-card:focus-visible .service-area-card__thread-knot--end,
.service-area-card.is-inview .service-area-card__thread-knot--end {
  opacity: 1;
}

.service-area-card__summary {
  position: absolute;
  z-index: 3;
  right: 6%;
  bottom: 15%;
  max-width: 56%;
  margin: 0;
  text-align: right;
  font-size: 1.13rem;
  line-height: 1.42;
  color: var(--color-niebla-clara);
  opacity: 0.88;
}

/* .service-area-cursor-hint — "Leer más +" siguiendo al cursor, a
   petición expresa, en vez del aviso que antes aparecía fijo en la
   esquina de cada tarjeta (versión anterior de este bloque,
   .service-area-card__cta). Mismo mecanismo/mismas propiedades
   visuales que .condition-cursor-hint más abajo en esta misma hoja
   (ver el porqué largo ahí): un único elemento compartido, hijo de
   .service-areas (position:relative, más arriba), con left/top
   reescritos en cada "pointermove" por
   assets/js/servicios-condition-svg.js. color fijo en niebla-clara,
   no var(--zone-text, ...) como en .condition-cursor-hint: esta
   sección no vive dentro de la cadena de fundido de
   animateBgFade()/animateSectionBackgrounds() (ver
   data-zone-text="niebla-clara" fijo en .section--areas-atencion,
   page-servicios.php) — el mismo color fijo que ya usan
   .service-area-card__title/__summary aquí al lado. */
.service-area-cursor-hint {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
  margin: 0;
  font-family: var(--font-texto);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--color-niebla-clara);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform: translate(0.9rem, -1.6rem);
  transition: opacity 0.2s ease;
}

.service-area-cursor-hint.is-visible {
  opacity: 1;
}

/* .service-area-card__cta-mobile — equivalente en móvil de
   .service-area-cursor-hint de arriba, a petición expresa: "como no
   existe el hover en pantallas móviles... que ya al pasar con el
   scroll por encima de cada uno se haga la animación... y que
   aparezca ya... el 'Leer más +'... desde el principio". Sin cursor
   real que seguir, no tiene sentido reescribir left/top en cada
   "pointermove" (eso solo pasa con ratón, ver "(pointer: fine)" en
   animations.js) — en su lugar, fijo en la misma esquina que ocupaba
   el antiguo .service-area-card__cta (antes de sustituirlo por el
   hint que sigue al cursor en escritorio, ver el comentario ahí
   arriba), revelado por ".is-inview" (clase que añade GSAP
   ScrollTrigger en vez de ":hover", ver
   assets/js/servicios-condition-svg.js). El "@media" no es solo
   defensivo: ScrollTrigger.matchMedia ya crea/destruye los triggers
   por su cuenta al cruzar este mismo breakpoint (64rem: mismo tope
   que usa servicios-condition-svg.js para ambos matchMedia, el móvil
   Y el de tablet que revela las tarjetas una a una — ver ahí el
   porqué), pero así ninguna tarjeta se queda con el aviso encendido
   en escritorio si ".is-inview" tardara un instante en limpiarse
   durante ese cruce.
   display:none fuera del "@media" — a petición expresa, tras
   detectar en devtools que en escritorio este <span> se colaba como
   texto normal ("Leer más +" suelto, sin posicionar) dentro de la
   tarjeta: sin ninguna regla fuera del breakpoint, el <span> no tenía
   ni position ni opacity propios y el navegador lo pintaba tal cual,
   en flujo normal.
   Ampliado de "max-width: 40rem" a "max-width: 64rem" — a petición
   expresa, para que este mismo "Leer más +" fijo (en vez del hint que
   sigue al cursor, sin sentido sin ratón real) también se vea en
   tablet, no solo en móvil, ahora que servicios-condition-svg.js
   también añade ".is-inview" ahí. */
.service-area-card__cta-mobile {
  display: none;
}

@media (max-width: 64rem) {
  .service-area-card__cta-mobile {
    display: inline-block;
    position: absolute;
    z-index: 3;
    right: 6%;
    bottom: 5%;
    margin: 0;
    font-family: var(--font-texto);
    font-weight: 500;
    font-size: 0.95rem;
    color: var(--color-niebla-clara);
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.35s ease;
  }

  .service-area-card.is-inview .service-area-card__cta-mobile {
    opacity: 1;
  }
}

/* Ajustes propios de cada ilustración dentro de su tile (posición,
   tamaño y escala al pasar el cursor) — un valor por área, calcado de
   la maqueta (max-width subido un 15% sobre el original a petición
   expresa, junto con el resto del contenido de la tarjeta). */
.service-area-card__illustration--adultos {
  left: 54%;
  top: 56%;
  width: 82%;
  max-width: 437px;
  transform: translate(-50%, -50%);
  --hover-transform: translate(-50%, -50%) scale(1.045);
}

.service-area-card__illustration--familia {
  left: 56%;
  top: 58%;
  width: 86%;
  max-width: 450px;
  transform: translate(-50%, -50%);
  --hover-transform: translate(-50%, -50%) scale(1.045);
}

.service-area-card__illustration--perinatal {
  left: 58%;
  top: 56%;
  width: 60%;
  max-width: 305px;
  transform: translate(-50%, -50%);
  --hover-transform: translate(-50%, -50%) scale(1.045);
}

.service-area-card__illustration--infancia {
  left: 68%;
  top: 56%;
  width: 28%;
  max-width: 152px;
  transform: translate(-50%, -50%);
  --hover-transform: translate(-50%, -50%) scale(1.045);
}

.service-area-card__illustration--pareja {
  left: 56%;
  top: 56%;
  width: 80%;
  max-width: 416px;
  transform: translate(-50%, -50%);
  --hover-transform: translate(-50%, -50%) scale(1.045);
}

/* El ancho de lectura y el centrado ya no viven aquí: los pone
   .service-bio-dialog__content, el mismo mecanismo (70% de la
   tarjeta) que .team-bio-dialog__content en Conócenos — a petición
   expresa, "el mismo ancho de texto... todo igual". */
.service-card__answer {
  margin-top: 1.5rem;
}

.service-card__answer h2 {
  font-family: var(--font-texto);
  font-weight: 400;
  font-size: 1.45rem;
  margin-top: 1.5em;
}

.service-card__answer p {
  margin: 0 0 1.1em;
}

.service-card__answer ul {
  padding-left: 1.25em;
  color: var(--color-lavanda);
  margin: 0 0 1.1em;
}

.service-card__answer li {
  margin-bottom: 0.4em;
}

.services-grid__cta {
  margin-top: 2.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  /* 2rem, no 1rem — a petición expresa, "un poquito más separados
     entre sí". */
  gap: 2rem;
}

/* position:relative + overflow:hidden — mismo motivo/mismo patrón que
   .section--areas-atencion y .section--pricing (ver esos comentarios):
   esta sección aloja su propio estampado decorativo local
   (data-estampado-local, ver page-servicios.php), que necesita medirse
   contra el alto de ESTA sección, no el de #main entero. */
.section--faq {
  position: relative;
  overflow: hidden;
}

/* Preguntas frecuentes (Servicios). Sin tarjetas: cada pregunta se
   separa de la siguiente con una línea, no con una caja de color.
   max-width 65ch: mismo ancho de lectura que el resto del texto largo
   de la web, en vez de estirarse a los 1152px de la sección. */
.faq-list {
  margin: 1.25rem auto 0;
  max-width: 65ch;
  display: flex;
  flex-direction: column;
}

.faq-item {
  padding: 1.25rem 0;
  /* 2px, no 1px — a petición expresa, "un poco más gruesitas, más o
     menos como el grosor de las líneas del + de desplegar" (ver
     .faq-item__icon::before/::after más abajo, ese mismo 2px). Mismo
     grosor en .pricing-list__item de Tarifas, ver más abajo. */
  border-bottom: 2px solid color-mix(in srgb, var(--color-berenjena) 15%, transparent);
}

.faq-item:first-child {
  border-top: 2px solid color-mix(in srgb, var(--color-berenjena) 15%, transparent);
}

.faq-item__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  cursor: pointer;
  list-style: none;
}

/* Oculta el triángulo nativo de <summary> (Chrome/Firefox/Safari) para
   usar nuestro propio icono +/×. */
.faq-item__question::-webkit-details-marker {
  display: none;
}

.faq-item__question h3 {
  font-family: var(--font-texto);
  font-weight: 400;
  font-size: 1.3rem;
  margin: 0;
}

.faq-item__icon {
  position: relative;
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
}

.faq-item__icon::before,
.faq-item__icon::after {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo de
     3:1 para componentes de interfaz sobre esta tarjeta blanca
     (2.2:1) — el icono +/− apenas se distinguía. */
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background-color: var(--color-berenjena);
  transition: transform 0.25s ease;
}

.faq-item__icon::before {
  width: 100%;
  height: 2px;
  transform: translate(-50%, -50%);
}

.faq-item__icon::after {
  width: 2px;
  height: 100%;
  transform: translate(-50%, -50%);
}

.faq-item[open] .faq-item__icon::after {
  transform: translate(-50%, -50%) rotate(90deg) scaleY(0);
}

.faq-item__answer {
  margin-top: 1rem;
  color: var(--color-lavanda);
}

.faq-item__answer a {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo como
     texto sobre esta tarjeta blanca. */
  color: var(--color-berenjena);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.faq-item__answer a:hover,
.faq-item__answer a:focus-visible {
  opacity: 0.72;
}

.faq-item__answer p,
.faq-item__answer ul {
  /* 2em, no 0.85em: ~2 líneas de aire entre párrafos, igual que el
     resto del texto largo de la web, para las respuestas con más de
     un párrafo. */
  margin: 0 0 2em;
}

.faq-item__answer p:last-child,
.faq-item__answer ul:last-child {
  margin-bottom: 0;
}

.faq-item__answer ul {
  padding-left: 1.25em;
}

.faq-item__answer li {
  margin-bottom: 0.4em;
}

/* Tarifas. max-width/margin-inline: cada grupo (título + lista de
   precios) centrado en una columna de ancho de lectura (65ch), igual
   que el resto del texto largo de la web, en vez de estirarse a los
   1152px de la sección. */
.pricing-group {
  max-width: 65ch;
  margin-inline: auto;
}

.pricing-group__title {
  /* Melocotón como texto falla el contraste mínimo sobre fondos claros
     (ya nos pasó varias veces con este color) — berenjena en su lugar. */
  margin: 0 0 1.25rem;
  font-family: var(--font-texto);
  font-weight: 400;
  font-size: 1.48rem;
  color: var(--color-berenjena);
}

.pricing-list {
  margin: 0 0 2.5rem;
  padding: 0;
  list-style: none;
  text-align: left;
}

.pricing-list__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.5rem 0;
  /* 2px, mismo motivo/mismo grosor que .faq-item más arriba. */
  border-bottom: 2px solid color-mix(in srgb, var(--color-berenjena) 15%, transparent);
}

.pricing-list__title {
  font-family: var(--font-titulos);
  font-weight: 400;
  font-size: 1.4rem;
  margin: 0 0 0.25rem;
}

.pricing-list__duration {
  /* Lavanda, igual que .condition-list__description (mini-descripciones
     de "Áreas de atención"): en Servicios el fondo es melocotón-tint, no
     niebla, y ahí lavanda sí pasa AA (~4.6:1). */
  margin: 0;
  font-size: 1rem;
  color: var(--color-lavanda);
}

.pricing-list__price {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo como
     texto sobre este fondo claro. Misma fuente y tamaño que
     .pricing-list__title, para que precio y título queden a la misma
     altura visual (el align-items:baseline de .pricing-list__item ya
     los alinea por la línea base). */
  flex-shrink: 0;
  font-family: var(--font-texto);
  font-size: 1.4rem;
  font-weight: 400;
  color: var(--color-berenjena);
  white-space: nowrap;
}

.pricing-cta {
  margin-top: 2.5rem;
  text-align: center;
}

/* A petición expresa, "que Tarifas tenga algo más de espacio por
   debajo para que respire": Tarifas es la última sección de Servicios
   (justo antes del footer), así que el padding-bottom normal de
   .section (--section-padding-block, hasta 7rem) es lo único que la
   separa del footer — un poco más aquí, solo para esta sección.
   position:relative + overflow:hidden, mismo patrón que #main (ver
   style.css arriba): esta sección aloja su PROPIO estampado decorativo
   (.servicios-estampado-fondo con data-estampado-local, ver
   page-servicios.php/servicios-estampado.js para el porqué de tenerlo
   aparte del de #main), así que necesita ser el contenedor posicionado
   sobre el que se mide ese inset:0 — sin esto, el estampado local
   heredaría el position:relative de #main en su lugar y taparía el
   estampado ya existente ahí en vez de vivir dentro de Tarifas. */
.section--pricing {
  position: relative;
  overflow: hidden;
  padding-bottom: calc(var(--section-padding-block) + 3rem);
}

/* A petición expresa, "un poco más de espacio entre 'Tarifas' y
   'Psiquiatría adultos e infantojuvenil'" (el h2 de la sección y el
   primer .pricing-group__title): Tarifas no lleva .section__intro
   entre medias (a diferencia de Áreas de atención/Qué tratamos), así
   que el único hueco entre los dos era el margin-bottom por defecto
   de los h2 (0.5em, ver la regla general de h1-h6 más arriba) —
   insuficiente aquí. */
.section--pricing h2 {
  margin-bottom: 2rem;
}

/* Política de cancelación */
.policy-content {
  /* 65ch, no un rem fijo: a 16px (tamaño heredado del body, sin
     font-size propio aquí) un rem fijo como el 46rem anterior daba
     líneas de más de 90 caracteres, por encima del máximo de 75
     recomendado para texto largo — "ch" ata el ancho al ancho real de
     los caracteres de la fuente en uso, así que la medida de lectura
     se mantiene correcta aunque cambie el tamaño de letra. Mismo
     criterio en .condition-content/.entry-content más abajo. */
  max-width: 65ch;
  margin-inline: auto;
}

.policy-content p {
  /* Explícito: sin esto, el margen de párrafo lo pone el user-agent
     por defecto (1em arriba/abajo, que colapsa a solo 1em entre dos
     párrafos seguidos) — bastante por debajo de las ~2 líneas de aire
     recomendadas entre párrafos de texto largo. */
  margin: 0 0 2em;
}

/* .policy-content h3, no solo h2 — a petición expresa, "todos los
   subtítulos del mismo tamaño para que haya coherencia": "Reembolso de
   gastos médicos" es un <h3> (subordinado a "Aseguradoras", un <h2>,
   ver page-politica-de-cancelacion.php — jerarquía semántica correcta,
   h1 > h2 > h3), pero sin este mismo tamaño se quedaba con el 1.17em
   por defecto del navegador (h3 no tiene ninguna regla propia en el
   resto del sitio), visiblemente más pequeño que el resto de
   subtítulos de esta página. */
.policy-content h2,
.policy-content h3 {
  /* Mismo margen que el resto de subtítulos dentro de un bloque de
     texto largo (.condition-content, .entry-content): 1.5em, no un
     valor suelto. */
  font-size: 1.35rem;
  margin-top: 1.5em;
}

.policy-content ul {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). Margen igual que
     .condition-list/.faq-list para el mismo hueco título → lista. */
  margin-top: 1.25rem;
  padding-left: 1.25em;
  color: var(--color-berenjena);
}

.policy-content li {
  margin-bottom: 0.6em;
}

/* Qué tratamos/Área de atención: enlace de "volver" encima del h1 en
   cada página hija — antes en mayúsculas+subrayado, propio, distinto
   del resto de enlaces de "volver" de la web (a petición expresa,
   unificado con el mismo estilo que .back-link/.single-post__back:
   flechita + texto normal, berenjena, sin subrayar). El contenedor
   .page-header__eyebrow en sí solo pone el espaciado; el aspecto visual
   del enlace vive en el grupo compartido de .back-link, más abajo en
   este fichero. */
.page-header__eyebrow {
  margin: 0 0 0.75rem;
}

/* Menos espacio entre un grupo y el siguiente (p. ej. "General" y
   "Salud mental perinatal"): sin el padding superior propio, que se
   sumaba al padding inferior del grupo anterior y dejaba un hueco muy
   grande entre dos bloques que en realidad van seguidos. */
.section--que-tratamos + .section--que-tratamos {
  padding-top: 0;
}

/* Qué tratamos debe seguir exactamente el mismo sistema visual que
   Servicios: mismos tamaños de letra, mismas distancias. El hueco
   entre el h1+intro y el primer grupo ("General") se iguala al hueco
   título→contenido de 2.5rem que usan "Áreas de atención"/"Tarifas"
   en Servicios (antes usaba el espaciado grande entre secciones).
   65ch, no "none": iguala el mismo tope de ancho de lectura que
   .page-header__intro tiene en Servicios (ver
   .page-header:has(+ .section--servicios-detalle) .page-header__intro
   más arriba) — "none" dejaba la línea estirarse hasta el ancho
   completo de la sección (1152px), muy por encima de los ~75
   caracteres recomendados. */
.page-header:has(+ .section--que-tratamos) .page-header__intro {
  max-width: 65ch;
}

.page-header + .section.section--que-tratamos {
  padding-top: 2.5rem;
}

/* Dos hojas animadas de fondo en Qué tratamos (para probar, ver
   hoja1-animada.js — mismo demo que
   assets/animations/hoja1-animada.html), una a cada lado de la página
   y a alturas distintas — ver el porqué de que sean hijas de #main (no
   del <header>) en page-que-tratamos.php. #main ya es
   position:relative + overflow:hidden en todo el sitio (ver más
   arriba), así que no hace falta ningún ajuste de posicionamiento
   adicional aquí, y cualquier parte que sobresalga por el lado queda
   recortada en el borde real de la página en vez de provocar scroll
   horizontal.
   Opacidad baja + niebla-clara, mismo criterio que .about-cta-flor en
   Inicio (ver más abajo): sobre el fondo oscuro oliva de esta página
   (body.bg-tint-oliva) se leen "como parte del fondo" en vez de
   competir con el texto — con pointer-events:none además de
   aria-hidden en el HTML, nunca roban el foco/clic a nada. Ocultas por
   debajo de 900px: a esos anchos ya no queda margen lateral real fuera
   del texto/los botones donde encajarlas sin solaparse. */
.que-tratamos-hoja-fondo {
  position: absolute;
  width: clamp(18rem, 30vw, 32rem);
  opacity: 0.35;
  pointer-events: none;
  z-index: 0;
}

.que-tratamos-hoja-fondo svg {
  display: block;
  width: 100%;
  height: auto;
  /* visible, no el "hidden" implícito por defecto: la onda del
     crecimiento (ver hoja1-animada.js) sobresale unos pocos px por
     fuera del viewBox en su pico, igual que en .about-cta-flor svg. */
  overflow: visible;
}

.hoja1-animada__path {
  fill: var(--color-niebla-clara);
}

/* Asomando desde el borde — izquierda arriba del todo, derecha
   bastante más abajo (entre los dos grupos de botones) y algo más
   pequeña, para que de verdad se note que están a "alturas distintas"
   y no sean un simple espejo una encima de la otra.
   translateX(...) SIEMPRE primero en la lista de transform, antes de
   scaleX — no al revés: los transform de una lista se acumulan de
   dentro hacia fuera, así que puesto antes actúa "por fuera" del
   espejo, midiéndose en el eje normal de la página en vez de en el eje
   ya volteado. var(--hoja-t) (0 a 1, ver hoja1-animada.js): mismo
   patrón que --hoja-t en .hero-outro-hoja (hoja2-animada.js) — cada
   hoja no solo crece, también se desliza un poco desde el borde
   mientras lo hace. Respaldo en 1 (reposo) para cuando JS todavía no
   ha fijado la variable (prefers-reduced-motion/sin JS). */
.que-tratamos-hoja-fondo--left {
  top: 1%;
  left: 3rem;
  transform: translateX(calc((var(--hoja-t, 1) - 1) * 2rem)) scaleX(-1);
}

.que-tratamos-hoja-fondo--right {
  top: 63%;
  right: 8rem;
  width: clamp(14rem, 22vw, 24rem);
  /* Sin scaleX(-1) — a petición expresa, orientación normal (sin
     espejo), distinta a la de arriba-izquierda. */
  transform: translateX(calc((1 - var(--hoja-t, 1)) * 6rem));
  rotate: 0deg;
}

@media (max-width: 900px) {
  .que-tratamos-hoja-fondo {
    display: none;
  }
}

/* Mismas dos hojas animadas (hoja1-animada.js), ahora en cada una de
   las 15 páginas de condición (page-que-tratamos-item.php) — a
   petición expresa, una arriba a la derecha y otra abajo a la
   izquierda en espejo. Mismo tamaño/opacidad/comportamiento que
   .que-tratamos-hoja-fondo de la página índice, pero SIN heredar esa
   clase: esta página tiene fondo CLARO (bg-tint-melocoton, ver
   header.php), no el oscuro oliva de la página índice, así que el
   niebla-clara de .hoja1-animada__path (pensado para leerse sobre un
   fondo oscuro) apenas se vería aquí — override de color más abajo. */
.que-tratamos-item-hoja-fondo {
  position: absolute;
  width: clamp(16rem, 26vw, 28rem);
  opacity: 0.35;
  pointer-events: none;
  z-index: 0;
}

.que-tratamos-item-hoja-fondo svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* Lavanda, no niebla-clara: mismo criterio de color que ya usa
   .conocenos-hoja en Conócenos (otra página de fondo claro con
   ilustraciones decorativas de hoja) — se lee con suavidad sobre el
   melocotón claro de esta página sin perder contraste hasta
   desaparecer. */
.que-tratamos-item-hoja-fondo .hoja1-animada__path {
  fill: var(--color-lavanda);
}

.que-tratamos-item-hoja-fondo--top-right {
  top: 1%;
  right: 2rem;
}

.que-tratamos-item-hoja-fondo--bottom-left {
  bottom: 2%;
  left: 2rem;
  transform: scaleX(-1);
}

@media (max-width: 900px) {
  .que-tratamos-item-hoja-fondo {
    display: none;
  }
}

/* position:relative + z-index:0 (no solo position:relative): un
   z-index EXPLÍCITO es lo que de verdad abre un contexto de apilado
   propio para .condition-buttons — necesario para que el z-index
   NEGATIVO de las dos hojitas de dentro (ver
   .que-tratamos-hoja-fondo--mini-left/--mini-right más abajo) quede
   contenido aquí (por detrás de los propios botones, que son
   contenido normal sin position) en vez de escaparse hacia el contexto
   de apilado de toda la página. Puestas DENTRO de .condition-buttons
   en el HTML (no como hermanas sueltas de .section__inner, ver
   page-que-tratamos.php) para que left/top se midan sobre el ancho
   real de los botones (62rem) y de verdad queden solapadas por debajo
   de alguno, no flotando en el margen vacío de la sección. */
.condition-buttons {
  position: relative;
  z-index: 0;
}

/* Dos hojitas más, para probar: más grandes que el primer intento y en
   sitios bien distintos entre sí (no un simple espejo a la misma
   altura) — una arriba a la izquierda, otra más abajo y más adentro a
   la derecha, y esta última en espejo (scaleX(-1)). z-index negativo,
   no 0 como las dos grandes de la cabecera: así quedan por detrás de
   los botones (contenido normal, se pinta por encima de cualquier
   descendiente con z-index negativo) — el efecto es que parecen crecer
   "desde detrás" de ellos. */
.que-tratamos-hoja-fondo--mini-left,
.que-tratamos-hoja-fondo--mini-right {
  /* -1, no 1: con z-index positivo (como había quedado) las hojas se
     pintan por ENCIMA de los botones — se notaba sobre todo en hover
     (.condition-button:hover añade su propio transform, que lo mete en
     un nivel de apilado más alto todavía, y aun así la hoja seguía
     tapándolo). Negativo es lo que de verdad las manda detrás, contenidas
     dentro del contexto de apilado propio de .condition-buttons (ver
     arriba) sin importar el estado de los botones. */
  z-index: -1;
}

.que-tratamos-hoja-fondo--mini-left {
  top: 5%;
  left: 90%;
  width: clamp(8rem, 14vw, 14rem);
  rotate: 50deg;
}

.que-tratamos-hoja-fondo--mini-right {
  top: 110%;
  right: 80%;
  width: clamp(8rem, 14vw, 14rem);
  transform: scaleX(-1);
  rotate: -20deg;
}

/* Los grupos de Qué tratamos no llevan párrafo de intro bajo el h2
   (a diferencia de "Áreas de atención"/"Tarifas" en Servicios), así
   que sin este margen explícito el hueco título→contenido se quedaría
   en ~1.25rem (el margen inferior por defecto del h2) en vez de los
   2.5rem de Servicios. .section--que-tratamos .section__inner > h2 ya
   no fija su propio font-size: hereda el mismo clamp(1.6rem, 3vw,
   2.1rem) que "Áreas de atención"/"Preguntas frecuentes"/"Tarifas". */
.section--que-tratamos .condition-buttons {
  margin-top: 2.5rem;
}

/* Botones sueltos, en vez de la lista con línea divisoria de
   .condition-list (esa se queda intacta para Servicios/FAQ, que la
   siguen usando tal cual) — a petición expresa, "todos los clickables
   ahí con botones ordenados en varias filas, que quede bonito".
   flex-wrap, no una grid de columnas fijas: los títulos varían mucho
   de largo ("TDAH" frente a "Trastornos de la conducta alimentaria
   (TCA)"), así que cada botón se ciñe a su propio contenido (como una
   etiqueta/chip) en vez de forzar celdas del mismo ancho con hueco
   vacío de sobra en las cortas — el ancho variable de cada botón es
   justo lo que hace que "las varias filas" salgan solas, sin fijar
   cuántos caben por fila (varía con el ancho real de la ventana, sin
   media queries propias). justify-content:center, no el "flex-start"
   por defecto — a petición expresa: sin esto cada fila empieza pegada
   al borde izquierdo (con la última fila, más corta, quedando suelta a
   la izquierda en vez de centrada bajo las de arriba); centrado, cada
   fila queda equilibrada respecto a las demás, tenga los botones que
   tenga. gap horizontal bajado de 1rem a 0.6rem, a petición expresa
   ("menos espacio de ancho") — el vertical (0.85rem) se deja igual,
   ese no se pidió tocar.
   max-width + margin-inline:auto — a petición expresa, "menos botones
   por línea": sin tocar el propio ancho de cada botón (que se sigue
   ciñendo a su texto) ni el mecanismo de "las filas salen solas" de
   arriba, esto solo estrecha el ESPACIO disponible para esas filas,
   así que menos botones caben en cada una antes de saltar a la
   siguiente — el mismo efecto que pedir "menos por línea" sin volver a
   una grid de columnas fijas.
   Historial: 46rem → 40rem (para que no quedara un botón suelto en la
   última fila) → ahora 62rem, a petición expresa ("unos 4 botones por
   línea, más o menos"). "Más o menos" a propósito en el valor
   elegido: con filas de ancho variable (cada botón mide lo que mide su
   propio texto, no una columna fija) no hay una talla exacta que dé
   "4" siempre — los botones más cortos ("TDAH") caben más de 4 por
   fila y los más largos ("Trastornos de la conducta alimentaria
   (TCA)") menos, así que el número real por fila varía según qué
   textos caigan juntos. 62rem es la aproximación razonable para que la
   mayoría de filas ronden los 4; si al verlo en el navegador se queda
   corto o largo de más, es cuestión de subir/bajar este mismo número. */
.condition-buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.85rem 0.6rem;
  max-width: 62rem;
  margin: 0 auto;
  padding: 0;
}

/* Tres tintes de marca (mismos que .hoja-mesa-morph/
   .team-bio-dialog__morph ya usan en el resto del sitio, ver
   tokens.css) — berenjena como texto pasa AA sobrado sobre los tres
   (tintes muy claros, >9:1 medido con la fórmula WCAG). Antes hubo una
   versión con cinco variantes (añadiendo oliva/lavanda A TAMAÑO REAL,
   oscuras, con texto niebla-clara) — vuelta a solo tres claras a
   petición expresa, ahora que la página entera tiene fondo oliva
   OSCURO (ver body.bg-tint-oliva en style.css/header.php): con la
   página ya oscura, un botón TAMBIÉN oscuro apenas se distinguiría del
   propio fondo — los tres tintes claros son justo lo que hace que los
   botones "salten" encima del oliva, en vez de fundirse con él.

   .condition-button--melocoton/--pistacho/--lavanda, NO
   :nth-child(3n+...) (versión anterior de este mismo bloque) — a
   petición expresa, tras reportarse que "se ven repetidos los colores
   en diferentes líneas". Motivo real: .condition-buttons envuelve en
   flex-wrap con cada botón midiendo lo que mide su propio texto (ver
   ahí), así que el número de botones por fila varía según el ancho
   real de cada uno — y en cuanto una fila mide justo un múltiplo de 3
   (el propio ciclo de color), el mismo color cae siempre en la misma
   columna, fila tras fila: una franja vertical de color en vez de
   variedad real. Ninguna fórmula automática (nth-child o cualquier
   otra) puede evitar esto sola porque el CSS no sabe dónde caen los
   saltos de línea reales de un flex-wrap — solo se puede corregir
   mirando cómo envuelve de verdad y eligiendo el color de cada botón a
   mano para que no coincida con el de la misma columna en la fila de
   encima (ver el color de cada elemento en el array de
   page-que-tratamos.php, con el porqué de cada elección ahí mismo). */
.condition-button {
  display: inline-flex;
  align-items: center;
  /* --font-titulos (EB Garamond), no --font-texto (Work Sans) — a
     petición expresa, "la otra fuente que usamos, en medium". Mismo
     peso (500) que ya usan h1-h6 en toda la web (ver el porqué del
     500 exacto más abajo en el archivo, en la regla h1-h6): Google
     Fonts carga EB Garamond como variable con el rango 400..700 (ver
     functions.php), así que 500 es un peso real de la propia fuente,
     no una negrita sintética. */
  font-family: var(--font-titulos);
  /* font-size ajustado a petición expresa contra el fondo oliva de la
     página. El peso ya no se toca aquí (ver font-family arriba): vive
     fijo en el 500 de EB Garamond. */
  font-size: 1.5rem;
  font-weight: 500;
  text-align: center;
  text-decoration: none;
  /* Más aire alrededor del texto que antes (0.85em 1.5em, luego
     1.15em 2em) — a petición expresa, subido otra vez: los botones
     más largos ("Trastorno obsesivo-compulsivo (TOC)") quedaban muy
     anchos pero apenas más altos que los cortos, y con tan poca altura
     de sobra el blob de abajo (border-radius en %, ver ahí) se
     estiraba en una elipse afilada/puntiaguda en los extremos en vez
     de leerse redondo — más padding VERTICAL sube la altura real del
     botón, acerca su proporción ancho:alto a algo más cuadrado y
     suaviza esos picos. */
  padding: 1.6em 2.2em;
  color: var(--color-berenjena);
  /* Color plano, sin degradado — a petición expresa, tras probar un
     brillo tipo "gotita de aceite en agua" que no encajó con el resto
     de la web (ilustraciones/colores siempre planos en Vinculare, ver
     brandbook-vinculare). Melocotón-tint de respaldo si por lo que sea
     faltara la clase --melocoton/--pistacho/--lavanda (ver más abajo,
     y el porqué de por qué esa clase se decide a mano en PHP, no por
     nth-child, en page-que-tratamos.php). */
  background-color: var(--color-melocoton-tint);
  /* border-radius: ver el porqué largo ("formas orgánicas") justo
     debajo del ciclo de color, un poco más abajo en este archivo —
     vive aquí, en la regla base, para no repetir el selector
     ".condition-button" dos veces por el archivo. En rem, no en % (ver
     el porqué largo ahí) — a petición expresa, tras reportarse que los
     botones más largos seguían quedando puntiagudos incluso con más
     padding. Valores subidos otra vez (2.2/1.5rem de máximo/mínimo →
     3.2/1.6rem) y más separados entre sí — a petición expresa, tras
     verse "como chips normales, no formas orgánicas": con las ocho
     esquinas tan cerca unas de otras (1.5–2.2rem) apenas se notaba el
     blob a simple vista, se leía como un rectángulo redondeado
     corriente. Más separación entre el máximo y el mínimo de cada
     esquina (ahora hasta 3.4rem en el extremo más grande) es lo que
     hace que el bulto se note de verdad. */
  border-radius: 3.2rem 1.6rem 2.6rem 1.9rem / 1.8rem 2.8rem 1.6rem 3.4rem;
  transition: transform 0.2s ease, background-color 0.2s ease, color 0.2s ease,
    border-radius 0.3s ease;
}

.condition-button--melocoton {
  background-color: var(--color-melocoton-tint);
}

.condition-button--pistacho {
  background-color: var(--color-pistacho-tint);
}

.condition-button--lavanda {
  background-color: var(--color-lavanda-tint);
}

/* Formas orgánicas tipo "blob"/célula al microscopio, no un pill
   uniforme de 999px — a petición expresa ("aún más orgánicas...
   como un microorganismo, una célula"), en línea con el resto de
   ilustraciones de la web (flor.svg/hoja.svg/espiral.svg, siluetas
   redondeadas irregulares, no geométricas). Primera versión: solo
   CUATRO esquinas con un radio distinto cada una (un rectángulo
   redondeado desigual, no un blob de verdad) — a petición expresa,
   subido al truco real de "blob" en CSS: border-radius con OCHO
   valores, dos grupos de cuatro separados por "/" (radio horizontal
   de cada esquina / radio vertical de cada esquina, en vez de un único
   radio igual en los dos ejes por esquina) — así cada esquina puede
   curvarse distinto en horizontal que en vertical, el mismo motivo por
   el que un blob generado así se lee como algo orgánico/celular y
   cuatro esquinas redondeadas normales no.

   En rem, NO en % — cambiado a petición expresa, tras reportarse que
   los botones más largos ("Trastorno obsesivo-compulsivo (TOC)")
   seguían quedando puntiagudos en los extremos incluso después de
   subir el padding. El motivo real es de CSS, no de padding: un
   border-radius en % se calcula sobre el ANCHO/ALTO real de la propia
   caja — en un botón mucho más ancho que alto (texto largo, una sola
   línea), el radio horizontal (% del ancho) crece muchísimo más que
   el vertical (% del alto), y las curvas de arriba y abajo de cada
   esquina, en vez de encontrarse en un arco suave, se estiran hasta
   casi tocarse en punta por el medio — el mismo motivo por el que un
   pill de toda la vida usa un valor FIJO enorme (999px) en vez de un
   50%: un valor fijo no depende del tamaño de la caja, así que da
   igual lo ancho que sea el botón, la curva de cada esquina siempre
   mide lo mismo en px reales y nunca se estira hasta la punta. Con
   rem en vez de %, el blob se comporta igual: cada esquina se curva
   con el mismo radio real sea cual sea el largo del texto de dentro,
   ni las cortas ("TDAH") ni las largas quedan afiladas.
   Rotación en un ciclo de CUATRO, independiente del ciclo de color (de
   tres) — al no compartir múltiplo, la combinación color+forma de
   cada botón concreto no se repite hasta el botón 13, así que se lee
   variado de verdad y no como un patrón que se repite cada pocos
   botones. La primera variante (radio base) vive en la regla base de
   arriba, no repetida aquí. */
.condition-button:nth-child(4n+2) {
  border-radius: 1.7rem 3.3rem 2rem 2.7rem / 3rem 1.7rem 3.2rem 1.6rem;
}

.condition-button:nth-child(4n+3) {
  border-radius: 2.8rem 2.2rem 1.6rem 3.4rem / 2rem 2.6rem 1.8rem 3rem;
}

.condition-button:nth-child(4n) {
  border-radius: 2.4rem 2.8rem 3.2rem 1.6rem / 2.6rem 1.7rem 2.4rem 2.2rem;
}

/* Mismo patrón hover/foco que .btn--primary (ver más arriba): invierte
   a berenjena sólido + texto claro, con un pequeño "levantamiento"
   (translateY) que refuerza que es clicable. El contorno de foco (ver
   el bloque grande de más arriba, más el volteo específico para esta
   página en body.bg-tint-oliva a:focus-visible) se sigue viendo bien
   aquí: outline-offset lo dibuja FUERA del propio botón, sobre el
   fondo de la página (oliva), no sobre este relleno berenjena, así
   que nunca queda invisible contra ninguno de los dos. */
.condition-button:hover,
.condition-button:focus-visible {
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
  /* Sin border-radius aquí — a petición expresa, "no quiero que
     cambien de forma, solo el color": se queda con el blob orgánico
     que ya tuviera cada botón (ver el ciclo nth-child más abajo) en
     vez de redondearse a píldora en hover/foco. */
  transform: translateY(-0.15rem);
}

/* Psicología/Psiquiatría: dos botones lado a lado (mismo mecanismo
   flex-wrap que .condition-buttons en Qué tratamos, ver ahí el porqué
   largo del flex-wrap). Ya no son <details>/<summary> que expanden
   aquí mismo: cada botón abre su biografía completa en una ventanita
   flotante, igual que "Leer más" en Conócenos (ver .service-bio-dialog
   más abajo y el bloque compartido "[data-bio-dialog]" en
   animations.js). */
/* .section--servicios-detalle .section__inner: position:relative —
   ancla real de .condition-cursor-hint (ver más abajo), que sigue al
   cursor con left/top absolutos escritos por
   assets/js/servicios-condition-svg.js. Sin esto heredaría el
   position:relative de #main (ver style.css) en su lugar, mucho más
   arriba en el documento, y "seguir al cursor" quedaría desplazado por
   todo el scroll acumulado hasta aquí. */
.section--servicios-detalle .section__inner {
  position: relative;
}

/* Monitores grandes (96rem+): ver el porqué largo del column-gap en
   .condition-list más abajo — con las dos ilustraciones a su tope de
   28rem de cuadrado, un hueco visible de verdad entre ellas (no solo
   entre las dos cajas, entre las SILUETAS ya escaladas/desbordadas)
   necesita más ancho del que da --content-max-width (72rem, pensado
   para columnas de texto, no para esta pareja de ilustraciones
   grandes). Solo aquí, no en el resto de la página (el h1/intro de
   .page-header__inner de arriba sigue en 72rem de toda la vida) — a
   petición expresa, "ponlos más separados con un huequito entre
   ellos", tras comprobarse con capturas reales que a 72rem las dos
   siluetas se tocaban/solapaban en vez de dejar hueco. */
@media (min-width: 96.0625rem) {
  .section--servicios-detalle .section__inner {
    /* 84rem → 88rem, a juego con el column-gap 20rem → 24rem de
       .condition-list (ver ahí, "un poquitito más separados"). */
    max-width: 88rem;
  }
}

.condition-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: bottom;
  gap: 9rem;
  /* 9rem, subido desde 7rem — a petición expresa, para separar un poco
     más la hoja y la flor entre sí ahora que las dos ilustraciones son
     un 40% más grandes (ver .condition-hoja-crece/.condition-flor-crece
     más abajo) y quedaban más juntas visualmente.
     44rem → 20rem — bug real, reportado en monitores grandes: 44rem se
     escogió mirando el ANCHO DE VENTANA (~1920px), pero este contenedor
     vive dentro de .section__inner, con max-width fijo en
     --content-max-width (72rem = 1152px) SIEMPRE, por grande que sea la
     ventana — 44rem de column-gap más los dos cuadrados a su tope de
     28rem cada uno (ver .condition-list__summary más abajo) suman 100rem,
     muy por encima de esos 72rem disponibles. flex-wrap:wrap (arriba) no
     tenía sitio para colocarlos lado a lado y los apilaba en dos líneas
     (Psicología encima, Psiquiatría debajo) en cualquier ventana que
     llegara a los 96rem+ donde ya no aplica ningún otro @media de los de
     más abajo.
     20rem de HUECO ENTRE CAJAS no es lo mismo que hueco entre SILUETAS:
     la flor/hoja de dentro se escalan 1.7×/1.5× y desbordan su propia
     caja de 28rem por los lados (ver .condition-flor-crece/
     .condition-hoja-crece más abajo) — con solo 8rem de column-gap las
     dos siluetas ya escaladas se tocaban/solapaban en vez de dejar
     hueco visible ("ponlos más separados con un huequito entre ellos").
     20rem → 24rem — a petición expresa, "un poquitito más separados"
     (visto ya con hueco real entre siluetas, solo pidiendo un poco
     más). Container ensanchado a juego, ver el @media más abajo.
     20rem sí deja un hueco real entre las siluetas ya desbordadas, a
     costa de necesitar más ancho de contenedor del que da
     --content-max-width — ver el @media (min-width: 96.0625rem) de
     .section--servicios-detalle .section__inner un poco más arriba,
     que ensancha el contenedor SOLO para esta pareja de ilustraciones
     (28+28+24=80rem, cabe de sobra en los 88rem de ese ensanche). */
  column-gap: 24rem;
  /* -4rem → -2rem — a petición expresa, "un poquito más abajo": menos
     invasión del espacio de la intro de arriba (ver el margin-top
     negativo de ".page-header + .section--servicios-detalle", en
     paralelo, sin tocar), deja que la hoja/flor caigan un poco más
     lejos del texto "Todas nuestras sesiones...". Solo afecta a este
     tramo ≥96rem: los tramos más estrechos ya fijan su propio
     margin-top positivo (3rem/1.5rem/0, ver sus @media más abajo), que
     esta base nunca llega a pisar. */
  margin-top: -2rem;
  /* 4rem → 6rem — a petición expresa, "un poco más de espacio con
     respecto a los svg de debajo": más aire antes de que empiecen a
     asomar los iconos decorativos de "Áreas de atención" (ver
     .section--servicios-detalle padding-bottom, un poco más abajo en
     este archivo, que suma a este mismo margen). */
  margin-bottom: 6rem;
  max-width: none;
  padding: 0;
}

.condition-list__item {
  flex: 0 0 auto;
}

/* Ya no un blob berenjena sólido — a petición expresa, sustituido por
   la hoja/flor animadas de .condition-list__svg (ver más abajo)
   creciendo detrás del texto, mismas ilustraciones que ya usa Inicio
   (ver el porqué del disparo distinto en
   assets/js/servicios-condition-svg.js). El botón en sí queda sin
   fondo/forma propia: un cuadrado (aspect-ratio:1) del mismo tamaño
   para los dos servicios, para que "ambos SVG animados" tengan
   literalmente el mismo tamaño de caja sea cual sea la proporción real
   de cada ilustración (ver preserveAspectRatio por defecto del <svg>
   de dentro, que centra y ajusta cada una dentro de ese cuadrado sin
   deformarla). */
.condition-list__summary {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 24.5rem → 28rem de tope — a petición expresa, "en ventana completa
     quiero que sean más grandes": solo afecta a partir de ~85rem de
     ancho (donde 33vw ya supera el 24.5rem de antes) — por debajo de
     eso, el tramo de 64rem-96rem de más abajo ya fija su propio tope
     más pequeño y gana por especificidad de todos modos, así que este
     cambio no le afecta. */
  width: clamp(16rem, 33vw, 28rem);
  aspect-ratio: 1;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
}

/* Ocupa todo el cuadrado del botón, detrás del texto (z-index implícito
   por orden en el DOM: va antes que .condition-list__label). overflow
   visible en el <svg> de dentro: la onda del crecimiento (ver
   servicios-condition-svg.js) sobresale unos pocos px por fuera de su
   viewBox en el pico, igual que ya le pasa a estas mismas ilustraciones
   en Inicio. pointer-events:none: es puramente decorativo (aria-hidden
   en el HTML), nunca debe robarle el clic al <button>. */
.condition-list__svg {
  position: absolute;
  inset: 0;
  display: flex;
  pointer-events: none;
}

.condition-list__svg svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Ligero giro en sentido horario, a petición expresa — sobre el propio
   <svg> (no sobre .condition-list__svg, que necesita quedarse sin
   transform propio para el inset:0 de arriba): el "d" del <path> lo
   reescribe servicios-condition-svg.js en cada fotograma (crecimiento +
   vibración), así que rotar el contorno punto a punto ahí sería mucho
   más frágil que un simple transform CSS aplicado una vez, encima del
   resultado ya dibujado. transform-origin por defecto (50% 50%, el
   propio centro del cuadrado) evita que el giro desplace la silueta
   fuera de su caja. Mismo ángulo (15°) en las dos, a petición expresa.
   ver .condition-hoja-crece__path/.condition-flor-crece__path (el
   color) más abajo — aquí solo el giro. */
/* scale(1.4) a petición expresa ("un 40% más grande") — mismo mecanismo
   que .condition-hoja-crece justo abajo: se escala el propio <svg>
   hacia su centro porque el cuadrado (.condition-list__summary) es
   compartido con la hoja y no puede crecer solo para una de las dos.
   translateY(20%) a petición expresa ("que la flor y la hoja salgan
   por debajo de todo el texto, que no tapen texto"): porcentaje (no
   rem) para que el desplazamiento escale con el propio cuadrado
   responsive (clamp 16-24.5rem). Va PRIMERO en la lista (no al final):
   así se aplica en último lugar, en coordenadas de pantalla ya
   rotadas/escaladas, y el desplazamiento hacia abajo sale siempre
   recto sea cual sea el ángulo de rotate() de cada silueta — si fuera
   al revés, el rotate ya aplicado "torcería" la dirección del
   translateY. overflow:visible en el <svg> de dentro (ver más arriba)
   permite que sobresalga del cuadrado sin recortarse. */
.condition-flor-crece {
  transform: translateY(10%) rotate(140deg) scale(1.7);
}

/* scale(0.85) además del giro, a petición expresa ("la hoja de
   psicología un poquitín más pequeña") — ambas ilustraciones comparten
   el mismo cuadrado (.condition-list__summary, aspect-ratio:1) a
   propósito para que ninguna destaque más que la otra por tamaño de
   caja (ver el comentario ahí), así que la única forma de que la hoja
   en sí se vea más pequeña sin tocar ese cuadrado compartido es
   escalar el propio <svg> hacia su centro. translateY(20%): mismo
   ajuste y mismo porqué que en .condition-flor-crece justo arriba
   ("que la flor y la hoja salgan por debajo de todo el texto, que no
   tapen texto") — mismo 20% en las dos para que bajen lo mismo. */
.condition-hoja-crece {
  transform: translateY(5%) rotate(23deg) scale(1.5);
}

/* Berenjena, a petición expresa (antes melocotón) — sólido, sin
   opacidad reducida: berenjena es uno de los pocos colores de marca
   con la suficiente oscuridad para que niebla-clara siga pasando de
   sobra el contraste AA de texto grande encima (10.8:1, comprobado con
   la fórmula de luminancia relativa WCAG — muy por encima del 3:1
   mínimo), a diferencia de melocotón, que obligaba a rebajar la
   opacidad para no perder ese contraste. Ese berenjena se queda como
   RESPALDO sin JS/con prefers-reduced-motion (mismo motivo que
   body.bg-tint-lavanda más arriba: sin animación, toda la página,
   incluida esta zona, se queda en el lavanda oscuro de siempre con
   texto niebla-clara encima, y ahí este berenjena sigue pasando AA).
   Con JS activo, --decor-fill-grande (fijada una sola vez, sin scrub,
   en animateBgFade(), animations.js) la sustituye por melocotón — a
   petición expresa (antes pistacho) — a juego con el fondo niebla y
   el texto berenjena de esta primera zona (.condition-list__label más
   abajo); berenjena sobre melocotón sigue pasando AA de sobra
   (melocotón es de los colores claros de la marca, mismo criterio que
   ya pasaba con pistacho). No se anima con el resto de la cadena: estas dos
   ilustraciones solo viven en esta zona y ya han salido de pantalla
   para cuando arranca el primer fundido (a "Áreas de atención"). */
.condition-hoja-crece__path,
.condition-flor-crece__path {
  fill: var(--decor-fill-grande, var(--color-berenjena));
  transition: fill 0.3s ease;
}

/* Pistacho al pasar el ratón/dar foco sobre el botón — a petición
   expresa. En .condition-list__summary:hover, no en el propio <svg>
   (que lleva pointer-events:none, ver .condition-list__svg más arriba
   — nunca podría recibir su propio :hover). Mismo tono que ya usa
   bailando.svg en el hover del hero (var(--color-pistacho-medio), ver
   .hero__bg-illustration--bailando:hover en style.css) para mantener
   el mismo criterio de color en toda la web.
   Envuelto en "min-width: 64.0625rem" — a petición expresa, "en
   pantallas móviles y de tablets... que no hagan el cambio de color":
   sin hover real por debajo de ese ancho (mismo tope que el resto de
   ajustes móvil/tablet de esta pareja de ilustraciones, ver
   ".condition-list__item--a/--b" y el desvanecido de
   servicios-condition-svg.js), el color se queda siempre en melocotón
   ahí — el ":focus-visible" del teclado también se excluye a propósito
   (mismo ancho, mismo criterio "sin hover en este tramo") para que el
   comportamiento sea el mismo entrando con teclado o con el dedo. */
@media (min-width: 64.0625rem) {
  .condition-list__summary:hover .condition-hoja-crece__path,
  .condition-list__summary:hover .condition-flor-crece__path,
  .condition-list__summary:focus-visible .condition-hoja-crece__path,
  .condition-list__summary:focus-visible .condition-flor-crece__path {
    fill: var(--color-pistacho-medio);
  }
}

/* Texto encima de la ilustración (position:relative, sigue en el flujo
   normal, pero por delante en el eje Z gracias al orden en el DOM) —
   más grande y con la otra fuente (Work Sans, no la EB Garamond serif
   de títulos) en un peso ligero, a petición expresa: "más light". Sube
   de peso al pasar el ratón/dar foco (ver más abajo) en vez de solo
   cambiar de color — con las dos variables registradas en el
   @font-face de Work Sans (100..900, ver vinculare-google-fonts en
   functions.php) el navegador interpola el grosor de verdad durante la
   transición, no un salto en seco entre dos archivos.
   top:-0.9rem: bajado desde -2.5rem a petición expresa ("bajalas un
   poquito que queden en el centro de los svg") — desde que la flor/hoja
   llevan translateY(20%) (ver .condition-flor-crece/.condition-hoja-crece
   más arriba), su centro visual quedó más abajo que el centro del
   cuadrado, así que el texto necesitaba bajar para volver a quedar
   centrado sobre ellas. El offset va en el texto y no en el svg
   (.condition-list__svg sigue con inset:0 completo) para no descentrar
   la hoja/flor dentro de su cuadrado. */
/* var(--zone-text, ...): mismo mecanismo que body.bg-tint-lavanda más
   arriba, no un niebla-clara fijo — este texto vive dentro de la
   primera zona de la cadena de animateBgFade() (niebla/berenjena antes
   de "Áreas de atención"), así que tiene que poder seguir a
   --zone-text cuando hay JS. El respaldo (niebla-clara) es el valor
   fijo de siempre, para prefers-reduced-motion/sin JS (toda la página
   en lavanda oscuro, ver el porqué grande en body.bg-tint-lavanda). */
.condition-list__label {
  position: relative;
  top: 0rem;
  font-family: var(--font-texto);
  font-weight: 400;
  font-size: clamp(1.95rem, 3.3vw, 2.6rem);
  color: var(--zone-text, var(--color-niebla-clara));
  text-align: center;
  /* 0.30s → 0.45s, ease → cubic-bezier — a petición expresa, "que el
     aumento sea un poquito mayor, siendo elegante, que no sea brusco":
     con el multiplicador subido (ver más abajo) un poco más de
     duración y una curva con salida suave (mismo tipo de easing
     "respirar" que .about-cta-link, no un ease genérico) evitan que el
     salto de tamaño se note repentino. */
  transition: font-size 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

/* A petición expresa, "que el hover haga crecer el tamaño de la
   fuente": font-size normal, no un transform:scale — calc() sobre el
   mismo clamp() de arriba (no un valor fijo aparte) para que el
   crecimiento se mantenga proporcional al tamaño responsive real en
   cualquier ancho de ventana, en vez de un tamaño de hover fijo que
   quedara desproporcionado en pantallas muy pequeñas o muy grandes.
   Solo font-size, SIN tocar font-weight — a petición expresa ("que
   solo aumente el tamaño de fuente, no su grosor"): el weight se queda
   fijo en 400 tanto en reposo como en hover/focus (subido desde 300
   a petición expresa, "un poquitín más bold", un peso más dentro de
   la variable de Work Sans).

   ×1.12 → ×1.22 — a petición expresa, "que el aumento de tamaño sea un
   poquito mayor": ver también la transición más suave de arriba, para
   que ese crecimiento algo mayor se siga sintiendo elegante y no
   brusco. */
.condition-list__summary:hover .condition-list__label,
.condition-list__summary:focus-visible .condition-list__label {
  font-size: calc(clamp(1.95rem, 3.3vw, 2.6rem) * 1.22);
}

/* .condition-cursor-hint — "Leer más +" siguiendo al cursor, a petición
   expresa: "como usaron en la página de Inicio, mismo tamaño así" (ver
   .hoja-mesa-cursor-hint en hoja-a-mesa.css). Mismas propiedades
   visuales que esa, reproducidas aquí en vez de compartidas
   directamente: hoja-a-mesa.css solo se encola en Inicio (ver
   functions.php), y traer todo ese archivo a Servicios solo por esta
   pieza no compensa. left/top escritos en cada "pointermove" por
   assets/js/servicios-condition-svg.js, relativos a .section__inner
   (position:relative, ver más arriba) — mismo mecanismo que
   initHeadline() en hoja-a-mesa.js. color: var(--zone-text, ...), no
   un berenjena fijo como en Inicio — a diferencia del hero (siempre
   sobre niebla), esta zona sigue la cadena de fundido de
   animateBgFade() (ver .condition-list__label justo arriba, mismo
   var()): este texto tiene que seguir el mismo color en todo momento
   para mantener el contraste correcto sobre el fondo que le toque. */
.condition-cursor-hint {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
  margin: 0;
  font-family: var(--font-texto);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--zone-text, var(--color-niebla-clara));
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transform: translate(0.9rem, -1.6rem);
  transition: opacity 0.2s ease;
}

.condition-cursor-hint.is-visible {
  opacity: 1;
}

/* .condition-list__cta-mobile — equivalente estático de
   .condition-cursor-hint para móvil/tablet, a petición expresa: "en
   pantallas móviles y de tablets, como no hay hover... que el 'Leer
   más +' ya salga desde el principio" en vez de depender de un cursor
   que ahí no existe. Oculto por defecto (fuera del "@media" de más
   abajo) — a propósito, mismo motivo que
   ".service-area-card__cta-mobile" más arriba en este archivo: sin
   esto el <span> se colaría como texto normal suelto dentro del botón
   en escritorio, donde el hint de verdad (el que sigue al cursor) es
   el que debe seguir apareciendo. Se oculta también
   .condition-cursor-hint en ese mismo tramo (ver el "@media" de abajo)
   — sin ratón real no tiene sentido que seguir mostrándolo si el
   focus llega a disparar su show()/hide() al tocar el botón. */
.condition-list__cta-mobile {
  display: none;
}

@media (max-width: 64rem) {
  .condition-cursor-hint {
    display: none;
  }

  /* position:absolute dentro de .condition-list__summary
     (position:relative, ver más abajo) — mismo mecanismo que
     .condition-list__svg (inset:0) y .condition-list__label
     (position:relative): al no llevar z-index, pinta por delante de
     .condition-hoja-crece/.condition-flor-crece (position:absolute,
     antes en el DOM) por el mismo motivo que ya pinta el label por
     delante, "de encima del svg también" a petición expresa. "right"
     en vez de "inset:0 + text-align:right": alinea el propio bloque de
     texto a la derecha del cuadrado en vez de centrarlo como el label,
     "alineado a la derecha" a petición expresa. "top" (no "bottom"):
     colocado debajo de la palabra con una separación vertical fija
     (top de la palabra + su alto aproximado + el hueco), no pegado al
     borde inferior del cuadrado, que con las ilustraciones más grandes
     de esta pareja (escaladas 1.4-1.7×, ver más arriba) cae fuera de
     la zona donde todavía se lee cómodo bajo el texto. Fondo
     transparente (heredado, sin declarar nada) y texto berenjena fijo
     — a petición expresa: a diferencia del label o el hint de
     escritorio (que seden --zone-text para seguir el fundido de fondo
     de animateBgFade()) — bug real, reportado en móvil (con captura):
     la suposición de que este texto siempre vive sobre el fondo niebla
     de esta zona (y por tanto un berenjena fijo bastaba) no se cumple
     de verdad — en una pantalla real el fondo ya había cambiado a
     lavanda mientras "Psiquiatría"/"Psicología" (con var(--zone-text,
     ...) justo arriba, ver .condition-list__label) sí se aclaraban
     correctamente para seguir contrastando, dejando el berenjena fijo
     de aquí casi invisible sobre ese mismo fondo oscuro. var(--zone-text,
     ...), mismo patrón que .condition-list__label: sigue el mismo
     fundido en vivo en vez de asumir un fondo que puede no serlo ya. */
  .condition-list__cta-mobile {
    display: block;
    position: absolute;
    z-index: 2;
    right: 8%;
    /* 3.4rem → 4.6rem — a petición expresa, "baja un poquito más los
       'Leer más +'": más separación vertical respecto a la palabra. */
    top: calc(50% + 4.6rem);
    margin: 0;
    background: transparent;
    color: var(--zone-text, var(--color-berenjena));
    font-family: var(--font-texto);
    font-weight: 500;
    font-size: 0.95rem;
    white-space: nowrap;
  }
}

/* Tramo intermedio (40rem-64rem) — a petición expresa, tras revisar
   capturas reales: por debajo de 64rem, Psicología/Psiquiatría ya no
   caben lado a lado sin más (el ancho del cuadrado, ver
   .condition-list__summary más abajo, más el column-gap de 23rem de la
   regla base ya no entran en el ancho disponible), así que flex-wrap
   las apila en una sola columna — pero seguían usando el tamaño y el
   margin-top negativo pensados para el caso lado a lado, así que la
   hoja/flor (que sobresale de su cuadrado al escalar, ver
   .condition-hoja-crece/.condition-flor-crece más abajo) tapaba el
   título "Servicios" y el texto de la intro de encima. flex-direction:
   column explícito (no dejarlo solo en manos del flex-wrap, que depende
   de que el ancho exacto no llegue a caber): así esta columna se
   mantiene estable en todo el tramo, no solo justo donde el cálculo de
   ancho cuadra por casualidad. gap/tamaño/escala rebajados, en la misma
   dirección que el propio breakpoint móvil de más abajo pero sin llegar
   a esos mismos valores (aquí hay bastante más ancho de sobra que en un
   móvil real). */
@media (min-width: 40.0625rem) and (max-width: 64rem) {
  .condition-list {
    flex-direction: column;
    align-items: center;
    gap: 4rem;
    /* 0 → 3rem — a petición expresa, "cuando se ponen en vertical uno
       debajo de otro, que estén separados más del texto de arriba":
       quitar el margin-top negativo (ver el comentario grande de
       arriba) ya evitaba el solape directo, pero seguían quedando
       pegadas al texto — este margin-top positivo añade aire real de
       sobra entre el párrafo de la intro y la primera ilustración. */
    margin-top: 3rem;
  }

  .condition-list__summary {
    width: clamp(14rem, 28vw, 18rem);
  }

  /* Ligero zigzag — a petición expresa, "el de arriba un poco más a la
     izquierda y el de abajo un poco más a la derecha": mismo recurso
     que ya usa el breakpoint móvil de más abajo (transform, no
     margin-left/right, que pelearía con el align-items:center de la
     regla de arriba — un translate no afecta al cálculo de layout de
     flex, así que cada uno se sigue centrando primero como siempre y
     solo se desplaza visualmente después). Selectores por
     ".condition-list__item--a"/"--b" (el modificador real de cada
     servicio), no ":first-child"/":last-child", por el mismo motivo que
     en móvil: el orden sigue siendo correcto aunque el array de
     servicios se reordene algún día. */
  .condition-list__item--a {
    transform: translateX(-20%);
  }

  .condition-list__item--b {
    transform: translateX(20%);
  }

  .condition-flor-crece {
    transform: translateY(10%) rotate(140deg) scale(1.25);
  }

  .condition-hoja-crece {
    transform: translateY(5%) rotate(23deg) scale(1.1);
  }
}

/* Tramo siguiente (64rem-96rem) — a petición expresa, "un poco más
   pequeños que en pantallas grandes": aquí Psicología/Psiquiatría ya
   caben lado a lado de sobra (ver el tramo de arriba, pensado para
   cuando NO caben), así que se deja la regla base (flex-direction:row
   por defecto) tal cual — solo se recorta el tope del cuadrado
   compartido (24.5rem en la regla base, ver .condition-list__summary
   más abajo) para que la hoja/flor, que escala por encima de ese
   cuadrado, deje de alcanzar el título/intro de la sección de encima
   en este tramo concreto. Por encima de 96rem (pantallas grandes de
   verdad) se queda con el tamaño máximo de siempre. */
@media (min-width: 64.0625rem) and (max-width: 96rem) {
  .condition-list__summary {
    width: clamp(16rem, 24vw, 19rem);
  }

  /* column-gap 23rem (pensado para el cuadrado mucho más grande de
     pantallas anchas de verdad) empujaba las dos casi hasta pegarse a
     los bordes de la ventana con el cuadrado ya reducido de arriba, sin
     apenas margen real hasta el borde — a petición expresa, "se queda
     demasiado pegado a los lados". Rebajado bastante (23rem → 14rem),
     manteniendo separación de sobra entre las dos sin invadir el margen
     de los bordes. 14rem → 20rem después — a petición expresa, "siguen
     igual de pegados, necesito que estén más separados": vuelve a
     abrir un poco el hueco entre las dos sin llegar a los 23rem
     originales (que sí las pegaba a los bordes).
     margin-top: la fluida de ".page-header + .section--servicios-detalle"
     (ver más arriba) ya se acerca a 0 en la parte más estrecha de este
     tramo, pero seguía sin ser suficiente — a petición expresa, "un
     poquito más abajo", un valor positivo fijo aquí, por encima de ese
     mínimo fluido. */
  .condition-list {
    column-gap: 20rem;
    margin-top: 1.5rem;
  }
}

/* Bug real, reportado en móvil: .condition-list (arriba) no tenía
   ningún ajuste propio por debajo de 40rem. gap/column-gap (9rem/23rem)
   están pensados para separar la hoja y la flor cuando van LADO A
   LADO en escritorio — en móvil, con flex-wrap apilándolas en una sola
   columna, ese mismo row-gap (9rem, ~144px) dejaba un hueco enorme y
   vacío entre Psicología y Psiquiatría. margin-top:-4rem (pensado para
   "invadir un poquito" el espacio de la cabecera en escritorio, ver el
   comentario de .page-header + .section--servicios-detalle) pasaba a
   solapar de verdad con el texto de la intro en vez de solo acercarse.
   Y el floor de 16rem en .condition-list__summary (pensado como tamaño
   mínimo razonable en escritorio) hacía que la hoja/flor decorativa
   (que escala 1.5-1.7× ese mismo cuadrado, ver
   .condition-hoja-crece/.condition-flor-crece más arriba) creciera más
   grande que la propia pantalla, tapando el título y el texto de
   alrededor — "necesitan más espacio". */
@media (max-width: 40rem) {
  .condition-list {
    gap: 4rem;
    margin-top: 0;
  }

  /* Psicología/Psiquiatría ya no centradas en línea recta una debajo de
     otra — a petición expresa, "que el primero esté más a la izquierda
     y el segundo más a la derecha, y ambos un poco más abajo y más
     grandes": un ligero zigzag en vez de una columna perfectamente
     centrada, más dinámico. transform (no margin-left/right, que
     pelearía con el "justify-content:center" ya puesto en
     .condition-list): un translate no afecta al cálculo de layout de
     flex, así que cada uno se sigue centrando primero como siempre y
     solo se desplaza visualmente después, sin desordenar el resto del
     hueco/gap entre los dos. Selectores por ".condition-list__item--a"/
     "--b" (el modificador real de cada servicio, ver "forma" en el
     array de PHP), no ":nth-child", para que el orden siga siendo
     correcto aunque algún día se reordene el array de servicios.
     Porcentajes (no rem fijo) para el eje X: se desplaza en proporción
     al propio ancho del elemento (más grande ahora, ver
     .condition-list__summary más abajo), no un valor fijo que se
     quedaría corto o largo si ese ancho cambia. */
  .condition-list__item--a {
    transform: translate(-14%, 1.5rem);
  }

  .condition-list__item--b {
    transform: translate(14%, 1.5rem);
  }

  /* Aún más grandes — a petición expresa, dos subidas seguidas (antes
     clamp hasta 12rem, luego hasta 15rem). El porcentaje del translate
     de arriba se bajó de 18% a 14% a la vez que este ancho sube: con
     el mismo 18% de un cuadrado ahora bastante mayor, el desplazamiento
     en px se hacía tan grande que empujaba el lado exterior de cada
     ilustración a rozar el borde de la pantalla — 14% del nuevo ancho
     mayor da un desplazamiento en px parecido al 18% de antes (sigue
     leyéndose "uno a la izquierda, el otro a la derecha" con claridad),
     sin llegar a recortarse contra ningún borde. */
  .condition-list__summary {
    width: clamp(13rem, 64vw, 17rem);
  }

  /* La hoja/flor seguían "comiéndose" el texto de la intro de encima
     ("Todas nuestras sesiones...") incluso con el cuadrado ya reducido
     arriba — a petición expresa, tras revisar una captura real: el
     escalado de escritorio (1.5×/1.7×, ver .condition-hoja-crece/
     .condition-flor-crece más arriba) seguía aplicándose tal cual, así
     que la silueta real sobresalía muy por encima de su propio
     cuadrado (ya de por sí solapado con el texto de arriba por el
     margin-top negativo de ".page-header + .section--servicios-detalle",
     pensado solo para invadir "un poquito" en escritorio). Rebajado
     aquí a un escalado mucho más discreto — sigue siendo más grande
     que el propio cuadrado (para que se note que crece de verdad), sin
     llegar a tapar nada del texto de alrededor. */
  .condition-flor-crece {
    transform: translateY(10%) rotate(140deg) scale(1.05);
  }

  .condition-hoja-crece {
    transform: translateY(5%) rotate(23deg) scale(1);
  }
}

/* El margin-top negativo de arriba (".page-header + .section--servicios-detalle",
   pensado para invadir "un poquito" el espacio de la caja de encima en
   escritorio, ver su comentario) se queda sin motivo en móvil una vez
   la hoja/flor ya no necesitan ese margen de sobra — a petición
   expresa, tras comprobarse que en pantallas estrechas ese solape caía
   sobre el propio texto de la intro ("Todas nuestras sesiones..."),
   no solo sobre el espacio en blanco de la esquina de la hoja/flor
   como en escritorio. */
@media (max-width: 40rem) {
  .page-header + .section--servicios-detalle {
    margin-top: 0;
  }
}

/* Biografía completa de Psicología/Psiquiatría: mismo patrón de
   <dialog> nativo "ventanita flotante" que .team-bio-dialog en
   Conócenos (ver style.css arriba y animations.js) — a petición
   expresa. Se queda como componente propio en vez de reutilizar
   directamente las clases team-bio-dialog__*: aquí no hay foto ni
   cabecera de identidad, solo un título y texto largo en una sola
   columna, así que la estructura interna es más simple (mismo criterio
   que .hoja-mesa-panel/.hoja-mesa-morph en hoja-a-mesa.css, que tampoco
   reutiliza las clases de Conócenos aun copiando el mismo patrón). El
   <dialog> en sí se queda transparente y sin aspecto propio — todo el
   fondo/borde redondeado vive en .service-bio-dialog__morph — por el
   mismo motivo que .team-bio-dialog: un transform de apertura
   aplicado directamente al <dialog> en el "top layer" le rompe el
   compositing en Chrome. */
.service-bio-dialog {
  position: fixed;
  top: 6vmin;
  left: 50%;
  translate: -50% 0;
  /* Mismo ancho que .team-bio-dialog (54rem) — a petición expresa,
     "el mismo ancho de texto... todo igual a como está en las
     tarjetas grandes de Conócenos": el ancho de texto sale de un % del
     ancho de la propia tarjeta (ver --bio-column-width en
     .service-bio-dialog__layout más abajo), así que para que ese
     texto mida lo mismo en las dos "ventanitas" la tarjeta que lo
     contiene tiene que medir lo mismo también. */
  width: min(calc(100vw - 12vmin), 54rem);
  /* 100dvh justo después de 100vh, no en su lugar — mismo patrón que
     .hero/.section--about ya usan en este fichero (buscar "100dvh").
     100vh en móvil se calcula como si la barra de direcciones del
     navegador estuviera SIEMPRE oculta, así que puede ser más alto que
     el espacio realmente visible — bug real, reportado como tarjetas
     que se cortan por abajo (el botón "Pide tu primera cita" quedaba
     fuera de la vista). 100dvh sí se recalcula según el espacio
     visible real en cada momento; se declara DESPUÉS para que gane en
     los navegadores que lo soportan y quede ignorada (con el 100vh de
     arriba como fallback intacto) en los que no. */
  height: calc(100vh - 12vmin);
  height: calc(100dvh - 12vmin);
  margin: 0;
  border: none;
  padding: 0;
  background-color: transparent;
  color: var(--color-berenjena);
  /* overflow:visible, mismo motivo que .team-bio-dialog: el scroll
     real lo gestiona .service-bio-dialog__layout, que asoma su barra
     por el borde derecho a propósito (ver ahí) — con el overflow:auto
     por defecto del propio <dialog>, ese sobrante se detectaba como
     contenido "que se sale" y aparecía una segunda barra falsa. */
  overflow: visible;
}

@media (max-width: 40rem) {
  .service-bio-dialog {
    /* Mismo ajuste que .team-bio-dialog en móvil: alto automático
       (ceñido al contenido) en vez de forzar pantalla completa cuando
       el texto es corto, con el mismo hueco mínimo de 6vmin. */
    bottom: 6vmin;
    height: auto;
    margin-block: auto;
  }
}

.service-bio-dialog__morph {
  display: flex;
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 1.75rem;
  /* Melocotón aclarado, igual que .team-bio-dialog__morph — para que
     no se sienta un blanco genérico de "ventana de sistema". */
  background-color: var(--color-melocoton-tint);
  /* overflow:visible (igual que .team-bio-dialog__morph, ver el
     porqué largo ahí): .service-bio-dialog__layout, más ancha que
     esta tarjeta a propósito, asoma su barra de scroll por el borde
     derecho — con overflow:hidden aquí, esa barra quedaría cortada en
     vez de flotar fuera. */
  overflow: visible;
}

@media (max-width: 40rem) {
  .service-bio-dialog__morph {
    height: auto;
    /* 100dvh tras 100vh, ver el porqué largo en .service-bio-dialog
       más arriba en este fichero. */
    max-height: calc(100vh - 12vmin);
    max-height: calc(100dvh - 12vmin);
  }
}

.service-bio-dialog__layout {
  /* Mismo truco que .team-bio-dialog__layout para que la barra de
     scroll (siempre pegada al borde de SU PROPIA caja) quede flotando
     FUERA de la tarjeta en vez de cortando la esquina redondeada: esta
     caja mide más ancho que .service-bio-dialog__morph (100% + 1.5rem)
     y ese mismo 1.5rem de más se sepulta como padding-right extra — el
     texto de dentro no se entera y queda donde estaría con un 100%
     normal, pero la barra asoma más allá del borde de .morph (que
     tiene overflow:visible, así que nada la recorta ahí fuera). */
  flex-shrink: 0;
  width: calc(100% + 1.5rem);
  height: 100%;
  padding: 3rem;
  /* padding-top más generoso que el resto (4.5rem, no 3rem) — a
     petición expresa, "un poco más de espacio por arriba antes de
     empezar el texto": sin esto el título quedaba casi a la misma
     altura que el botón de cerrar (.service-bio-dialog__close, que
     ocupa ese mismo rincón superior). */
  padding-top: 4.5rem;
  padding-right: calc(3rem + 1.5rem);
  overflow-y: auto;
}

@media (max-width: 40rem) {
  .service-bio-dialog__layout {
    /* Hueco más pequeño en móvil, mismo motivo que
       .team-bio-dialog__layout: la pantalla ya es estrecha de por sí. */
    width: calc(100% + 0.75rem);
    height: auto;
    /* 100dvh tras 100vh, ver el porqué largo en .service-bio-dialog
       más arriba en este fichero. */
    max-height: calc(100vh - 12vmin);
    max-height: calc(100dvh - 12vmin);
    padding: 1.5rem;
    padding-top: 3rem;
    padding-right: calc(1.5rem + 0.75rem);
  }
}

.service-bio-dialog__content {
  /* Columna centrada en medio de la tarjeta — mismo % que
     .team-bio-dialog__content (70% del ancho de la tarjeta grande),
     a petición expresa, "el mismo ancho de texto... todo igual". */
  max-width: 70%;
  margin: 0 auto;
  text-align: left;
  padding: 0 0.5rem;
}

@media (max-width: 40rem) {
  .service-bio-dialog__content {
    max-width: 100%;
  }
}

.service-bio-dialog__content h2 {
  /* Mismo tamaño que el nombre en .team-bio-dialog__identity h2, para
     que las dos "ventanitas" del sitio se lean como el mismo
     componente. */
  font-size: 1.75rem;
  margin: 0 0 1.5rem;
  /* outline:none — mismo motivo que .team-bio-dialog__identity h2, más
     arriba en este fichero: este título recibe foco por script al
     abrir el <dialog> (tabindex="-1" + .focus() en animations.js), y
     sin este outline:none el navegador pinta su propio anillo nativo
     por defecto aquí en vez de ninguno. */
  outline: none;
}

.service-bio-dialog::backdrop {
  /* Mismos valores que .team-bio-dialog::backdrop. */
  background-color: var(--color-berenjena);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.service-bio-dialog.is-open::backdrop {
  opacity: 0.55;
}

/* Mismo botón de cerrar que .team-bio-dialog__close en Conócenos (ver
   arriba), a petición expresa — círculo niebla con icono berenjena,
   pistacho + giro 90° al pasar el ratón/dar foco. */
.service-bio-dialog__close {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background-color: var(--color-niebla);
  color: var(--color-berenjena);
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.service-bio-dialog__close:hover,
.service-bio-dialog__close:focus-visible {
  background-color: var(--color-pistacho);
  transform: rotate(90deg);
}

/* Móvil y tablet — mismo tratamiento que .team-bio-dialog__close en
   Conócenos y .hoja-mesa-close en Inicio (ver el porqué largo junto a
   .team-bio-dialog__close, más arriba en este fichero): pistacho fijo
   (sin hover real en táctil), círculo VISIBLE más pequeño (para que no
   tape el texto al hacer scroll) con área PULSABLE (el botón en sí)
   más grande que ese círculo. */
@media (max-width: 64rem) {
  .service-bio-dialog__close {
    /* Sin "position" aquí: el botón ya es position:absolute (regla
       base, arriba) contra .service-bio-dialog__morph. */
    width: 2rem;
    height: 2rem;
    background-color: transparent;
  }

  /* Anula el ":hover"/":focus-visible" de escritorio (arriba) — mismo
     bug real que .hoja-mesa-close/.team-bio-dialog__close (ver el
     porqué largo en hoja-a-mesa.css): showModal() enfoca el primer
     elemento interactivo del <dialog>, que es este botón, así que sin
     esto cada tarjeta abría con él momentáneamente relleno pistacho a
     tamaño completo antes de "encogerse" al círculo pequeño de
     ::before. */
  .service-bio-dialog__close:hover,
  .service-bio-dialog__close:focus-visible {
    background-color: transparent;
    transform: none;
  }

  .service-bio-dialog__close::before {
    content: '';
    position: absolute;
    inset: 0;
    margin: auto;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background-color: var(--color-pistacho);
  }

  .service-bio-dialog__close svg {
    position: relative;
    z-index: 1;
    width: 10px;
    height: 10px;
  }
}

/* Qué tratamos: texto largo de cada condición (viene del editor de bloques) */
.condition-content {
  /* 65ch, no rem fijo — mismo motivo que .policy-content más arriba:
     a 16px, 46rem se quedaba por encima de los 75 caracteres por línea
     recomendados para texto largo. */
  max-width: 65ch;
  margin-inline: auto;
}

.condition-content h2 {
  /* text-align: left explícito: sin esto, .section__inner > h2 (que
     centra los títulos de sección) también pilla estos subtítulos de
     dentro del contenido de Gutenberg, porque este div lleva las dos
     clases (section__inner y condition-content) a la vez. Estos son
     subtítulos dentro de un texto largo, como en el blog — a la
     izquierda, no centrados. */
  font-size: 1.4rem;
  margin-top: 1.5em;
  text-align: left;
}

.condition-content p {
  /* 2em, no 1.2em: ~2 líneas de aire entre párrafos de texto largo,
     no solo 1.2, para que cada párrafo se lea como un bloque propio. */
  margin: 0 0 2em;
}

.condition-content ul {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). Afecta a las 15 páginas de
     condiciones de Qué tratamos. */
  padding-left: 1.25em;
  color: var(--color-berenjena);
  margin: 0 0 1.2em;
}

.condition-content li {
  margin-bottom: 0.5em;
}

/* Cierre de cada página de "Qué tratamos": sin caja, texto y botones
   sueltos sobre el mismo fondo lavanda claro del resto de la página. */
.condition-content__cta {
  margin-top: 2.5rem;
  text-align: center;
}

.condition-content__reassurance {
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: 1.25rem;
  color: var(--color-berenjena);
  margin: 0 0 1.25rem;
}

.condition-content__cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
}

/* Enlace berenjena discreto, reutilizado en varios sitios sueltos de
   la web que no comparten componente (el "volver" de las páginas de
   área de atención, el LinkedIn de cada ficha de equipo, el "volver"
   del blog, los datos de contacto) — mismo color/peso/decoración y el
   mismo gesto al pasar el ratón/dar foco (opacidad, no subrayado) en
   los cuatro sitios, agrupados aquí en vez de repetidos cuatro veces.
   Berenjena, no lavanda: lavanda falla el contraste mínimo sobre
   estos fondos claros. Cada selector conserva aparte solo lo que sí
   varía entre ellos (display/margin, ver más abajo cada uno). */
.back-link,
.team-profile__linkedin,
.single-post__back,
.page-header__eyebrow a,
.contact-details a {
  color: var(--color-berenjena);
  text-decoration: none;
  font-weight: 600;
}

.back-link:hover,
.back-link:focus-visible,
.team-profile__linkedin:hover,
.team-profile__linkedin:focus-visible,
.single-post__back:hover,
.single-post__back:focus-visible,
.page-header__eyebrow a:hover,
.page-header__eyebrow a:focus-visible,
.contact-details a:hover,
.contact-details a:focus-visible {
  opacity: 0.72;
}

.back-link {
  display: inline-block;
  margin-top: 2rem;
}

/* Conócenos: fichas largas (bio real), no tarjetas cortas.
   minmax(18rem, 22rem): marco flor grande (a petición expresa: casi
   tan ancho como el párrafo de la especialidad, que ocupa toda la
   columna) — con este máximo entran 3 fichas por fila dentro de
   --content-max-width (72rem), no 4 como antes; auto-fit cuenta
   columnas usando el tamaño MÁXIMO de la función, no el mínimo. En vez
   de 1fr (que con pocas fichas las estiraba para llenar todo el ancho
   en vez de mantenerlas del mismo tamaño). justify-content: center
   las centra en la fila. Según se añadan más profesionales, el grid
   va metiendo más columnas solo (auto-fit), sin tocar el CSS. */
.team-profiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 22rem));
  justify-content: center;
  gap: 2rem;
  max-width: var(--content-max-width);
  margin-inline: auto;
  /* stretch (no start): todas las fichas de una misma fila igualan su
     altura a la más alta de esa fila — la de Esther, con la ficha de
     texto más larga. Con solo Esther y Cristina (una vez se quiten las
     2 de prueba) las dos están siempre en la misma fila, así que
     ambas quedan siempre a la altura de Esther. */
  align-items: stretch;
}

/* Foto encima del texto (no al lado), las dos del mismo ancho: la
   columna es una sola, y la foto ocupa el 100% de esa columna (ver
   .team-profile__photo), igual que el texto de debajo.
   background-color: a petición expresa, cada ficha lleva su propio
   fondo de tarjeta en lavanda — excepción puntual solo en esta página
   al criterio general "sin cajas de color superpuestas" (ver
   tokens.css / CLAUDE.md). Con lavanda de fondo el texto pasa a
   niebla-clara (ver .team-profile__role y compañía más abajo): 5.03:1,
   por encima del 4.5:1 mínimo AA — berenjena (el texto por defecto en
   el resto de la web) da solo 2.16:1 aquí, así que no vale en esta
   ficha.
   display: flex (no grid): con .team-profiles ahora estirando la
   ficha a la altura de la fila, hace falta que .team-profile__info
   pueda crecer para ocupar ese hueco de más y empujar "Leer biografía
   completa" hasta abajo del todo (ver .team-profile__info y
   .team-profile__details más abajo) — con grid de una sola columna,
   las filas implícitas no reparten así el espacio sobrante. */
.team-profile {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  text-align: left;
  background-color: var(--color-lavanda);
  /* 2rem, no 1.5rem: sin las esquinas redondeadas de antes, el
     contenido (foto, texto) quedaba casi pegado a la esquina recta de
     la tarjeta — un poco más de aire alrededor.
     Vertical mayor que el lateral a petición expresa: tarjetas más
     altas sin ensanchar la columna — equalize() en animations.js mide esta
     altura real (incluido este padding) y la aplica como mínimo al
     resto de fichas, así que basta con crecer aquí para que todas las
     tarjetas crezcan igual.
     border-radius, a petición expresa (mismo criterio que la tarjeta
     grande de la biografía, ver .team-bio-dialog__morph más abajo). */
  padding: 3.5rem 2rem 4.5rem;
  border-radius: 1.5rem;
}

/* Un poco más compactas en tablet/móvil (a petición expresa): mismo
   diseño, solo algo menos de padding y una columna algo más estrecha
   — el contenido interno (foto al 84%, texto) escala solo porque
   depende del ancho de la tarjeta, no hace falta tocar nada más. */
@media (max-width: 64rem) {
  .team-profiles {
    grid-template-columns: repeat(auto-fit, minmax(15.5rem, 19rem));
    gap: 1.5rem;
  }

  .team-profile {
    padding: 3rem 1.5rem 3.75rem;
  }
}

/* Foco visible dentro de la ficha: el contorno berenjena por defecto
   (ver más arriba, a:focus-visible/button:focus-visible) da solo
   2.16:1 sobre este fondo lavanda, por debajo del 3:1 mínimo para
   componentes de interfaz — niebla-clara (5.03:1, el mismo tono que ya
   usa el texto de la ficha) sí pasa. */
.team-profile a:focus-visible,
.team-profile button:focus-visible {
  outline-color: var(--color-niebla-clara);
}

/* Foto en círculo de borde ondulado (el marco lo define
   vinculare_wavy_circle_clip_defs() en functions.php, llamado desde
   page-conocenos.php) — un círculo de verdad, no la silueta literal
   de espiral.svg (una cinta enrollada, no redonda: probada como marco
   directo, se veía como una forma rota, no como "foto en círculo"),
   con un contorno que ondula un poco en cada ángulo para que tenga la
   misma textura de línea curva/orgánica que la ilustración de la
   espiral. La foto RELLENA la forma, como una máscara de recorte, no
   una mancha suelta detrás. Sin foto real todavía: relleno de color
   liso a modo de marcador de posición. El centrado de la foto dentro
   del marco lo hace object-fit/position en .team-profile__photo-img,
   no hace falta flex aquí. */
.team-profile__photo {
  display: block;
  /* No 100%, centrada — a petición expresa, para que el círculo no
     ocupe todo el ancho de la tarjeta. Subido de 70% a 84% (también a
     petición expresa): con 70% el nombre completo de algunas personas
     (segundo apellido incluido) no cabía en una línea dentro de
     .team-profile__info y bajaba de línea. .team-profile__info usa el
     mismo 84% + margin-inline: auto para que las dos columnas (foto y
     texto) midan siempre exactamente lo mismo, una debajo de la otra. */
  width: 84%;
  margin-inline: auto;
  /* 1/1, no una proporción rectangular: el marco es un círculo (aunque
     de borde ondulado) generado ya en un recuadro cuadrado — ver
     vinculare_wavy_circle_clip_defs(). Con una caja rectangular un
     giro por CSS lo ovalaría en vez de rotarlo tal cual. */
  aspect-ratio: 1 / 1;
  clip-path: url(#espiral-marco-1);
  background-color: var(--color-pistacho);
  /* .team-profile es ahora flex column: sin esto, si la ficha se
     estira más alta que su contenido natural (ver .team-profiles
     align-items: stretch), el flex podría encoger la foto para ceder
     espacio — el marco tiene que medir siempre lo mismo. min-height: 0
     apaga el tamaño mínimo automático que Chrome calcula para los
     hijos de un flex (basado en el contenido, aquí la foto real
     dentro) — sin esto, en alguna ficha ese mínimo ganaba al
     aspect-ratio y el marco salía más alto de la cuenta. */
  flex-shrink: 0;
  min-height: 0;
  /* Bug confirmado en Chrome (reportado: "la foto de Esther se ve
     pixelada/borrosa en la tarjeta pequeña, pero bien en la ventanita
     grande" — y se arreglaba de golpe con solo cambiar el zoom del
     navegador, la pista que confirma esto): un elemento con clip-path
     puede quedarse rasterizado en una capa que no coincide con la
     resolución real de pantalla tras un cambio de layout POSTERIOR al
     primer pintado — aquí, equalize() en animations.js reajusta el
     alto de las fichas (para igualarlas todas) tanto en
     DOMContentLoaded como otra vez en window "load", después de que
     Chrome ya haya rasterizado el recorte una primera vez. La
     ventanita grande (.team-bio-dialog__photo, mismo clip-path) no lo
     sufre porque no se pinta hasta que se abre con showModal(), ya con
     el layout de la página asentado del todo. translateZ(0) fuerza a
     que este elemento tenga su propia capa de composición desde el
     primer pintado, con la escala correcta, en vez de esperar a que
     Chrome decida promocionarlo más tarde (y posiblemente mal) tras el
     reajuste de equalize(). */
  transform: translateZ(0);
}

/* Mismo círculo ondulado, cada ficha con un ángulo distinto (el marco
   en sí, no la foto — ver vinculare_wavy_circle_clip_defs() en
   functions.php), para que las tarjetas seguidas no queden con el
   marco idéntico. Las 8 miden exactamente lo mismo, solo cambia el
   giro — son 8, no 4, para que una segunda fila (si el equipo crece)
   no repita los mismos ángulos en el mismo orden que la fila de
   arriba. */
.team-profile__photo--angulo-1 {
  clip-path: url(#espiral-marco-1);
}

.team-profile__photo--angulo-2 {
  clip-path: url(#espiral-marco-2);
}

.team-profile__photo--angulo-3 {
  clip-path: url(#espiral-marco-3);
}

.team-profile__photo--angulo-4 {
  clip-path: url(#espiral-marco-4);
}

.team-profile__photo--angulo-5 {
  clip-path: url(#espiral-marco-5);
}

.team-profile__photo--angulo-6 {
  clip-path: url(#espiral-marco-6);
}

.team-profile__photo--angulo-7 {
  clip-path: url(#espiral-marco-7);
}

.team-profile__photo--angulo-8 {
  clip-path: url(#espiral-marco-8);
}

.team-profile__photo-img {
  /* object-fit: cover: la foto rellena el marco entero (nunca se ve
     fondo de color por dentro de la espiral), recortando lo que sobre
     de ancho o alto según la foto — sin deformarse en ningún caso,
     cover siempre mantiene la proporción real, solo recorta el
     sobrante. */
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* flex-direction: column + flex: 1: ocupa todo el alto que le sobre a
   la ficha (ver .team-profiles align-items: stretch), para poder
   empujar "Leer más +" hasta abajo del todo sea cual sea el largo del
   nombre/cargo/especialidad de cada persona — ver
   .team-profile__more-btn, margin-top: auto.
   gap (no margin en cada hijo): solo tiene 2 hijos directos ahora
   (.team-profile__details, que agrupa nombre/cargo/especialidad/
   colegiado/linkedin, y el botón) — este gap es el hueco MÍNIMO
   garantizado entre ambos, a petición expresa, incluso en la ficha con
   el texto más largo (la que no le sobra espacio que repartir con el
   margin-top:auto del botón). En las fichas más cortas de esa misma
   fila, el margin-top:auto del botón sigue añadiendo aún más espacio
   por encima de este mínimo para empujarlo hasta el fondo real de la
   ficha. */
.team-profile__info {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 1.5rem;
  /* Mismo ancho + centrado que .team-profile__photo, ver ahí el
     porqué: así el texto queda exactamente del mismo ancho que la flor
     de arriba, no el ancho completo de la tarjeta. */
  width: 84%;
  margin-inline: auto;
}

/* Agrupa nombre/cargo/especialidad/colegiado/linkedin como un solo
   bloque, separado de "Leer más +" (ver el gap de .team-profile__info
   de arriba) — antes estos elementos eran hijos sueltos de
   .team-profile__info junto al botón, así que el margin-top:auto del
   botón podía dejarlo pegado al último de ellos en la ficha con más
   texto, sin ningún hueco mínimo garantizado. */
.team-profile__details {
  display: flex;
  flex-direction: column;
}

.team-profile__name {
  /* Sin esto hereda berenjena de <body> (2.16:1 sobre el fondo lavanda
     de la ficha, por debajo del 3:1 mínimo incluso para texto grande);
     niebla-clara pasa con 5.03:1. */
  color: var(--color-niebla-clara);
  font-size: 1.5rem;
  margin: 0 0 0.25rem;
}

.team-profile__role {
  /* Niebla-clara, no berenjena: la ficha ahora tiene fondo lavanda
     sólido (ver .team-profile), y berenjena da solo 2.16:1 ahí —
     niebla-clara pasa con 5.03:1. */
  color: var(--color-niebla-clara);
  font-weight: 600;
  margin: 0 0 0.25rem;
}

.team-profile__specialty {
  /* Niebla-clara, no berenjena: mismo motivo que .team-profile__role,
     fondo lavanda sólido de la ficha. */
  color: var(--color-niebla-clara);
  font-size: 1rem;
  margin: 0;
}

.team-profile__colegiado {
  color: var(--color-niebla-clara);
  font-size: 0.9rem;
  margin: 0.35rem 0 0;
}

.team-profile__summary {
  /* Ahora vive dentro de .team-profile__details-inner (que ya pone su
     propio margin-top), así que sin margen arriba para no duplicar el
     hueco. */
  color: var(--color-berenjena);
  text-align: left;
  margin: 0 0 1.25rem;
}

/* Botón "Leer más": abre el <dialog> con la biografía completa (ver
   animations.js). margin-top: auto lo empuja hasta abajo del todo de
   .team-profile__info (además del gap mínimo que ya separa ahí
   .team-profile__details del botón, ver ese selector) — así el botón
   queda siempre a la misma altura en todas las fichas, sea cual sea el
   largo del texto de arriba y exista o no enlace de LinkedIn. Solo
   necesita ser el ÚLTIMO hijo de .team-profile__info en el HTML
   (junto con .team-profile__details, que agrupa todo el texto) —
   margin-top:auto ancla de verdad al último elemento. */
.team-profile__more-btn {
  margin-top: auto;
  align-self: flex-start;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: none;
  background: none;
  /* Vertical, no horizontal (el texto+icono ya superan de sobra el
     ancho mínimo): sin esto la altura de toque depende por completo
     del line-height heredado, justo en el límite de 24px mínimo
     (WCAG 2.2 SC 2.5.8) sin ningún margen de seguridad. Solo
     margin-bottom, NUNCA margin-block/margin-top: margin-block es un
     shorthand que fija TANTO el margen de arriba como el de abajo —
     puesto aquí, después de "margin-top: auto" de más arriba, lo
     pisaba silenciosamente a -0.25rem fijo. Eso rompía por completo el
     alineado abajo: sin ningún margen automático de verdad, "Leer
     más +" dejaba de anclarse al fondo de la ficha y cada una lo
     mostraba a la altura natural de su propio texto (más abajo cuanto
     más larga la especialidad) en vez de todas a la misma altura. */
  padding: 0.25rem 0;
  margin-bottom: -0.25rem;
  font-family: var(--font-texto);
  font-size: 1rem;
  font-weight: 600;
  /* Niebla-clara, no berenjena: fondo lavanda sólido de la ficha (ver
     .team-profile), berenjena falla ahí (2.16:1). */
  color: var(--color-niebla-clara);
  /* transform-origin: left (no el centro por defecto) — align-self:
     flex-start de arriba pega el botón al borde izquierdo de la
     ficha, así que crecer desde el centro lo desplazaría un poco hacia
     la izquierda en cada hover; desde el borde por el que ya está
     anclado, solo crece hacia dentro/derecha. */
  transform-origin: left center;
  transition: color 0.2s ease, transform 0.2s ease;
}

/* Antes: opacity: 0.72 — a petición expresa, "se ve demasiado oscuro y
   no se nota" (el propio niebla-clara base ya está justo al límite de
   AA sobre este fondo lavanda, ~5:1, y con la opacity bajaba a ~3.5:1,
   por debajo del mínimo). Melocotón puro o cualquiera de sus variantes
   más saturadas (melocoton-clara, melocoton-medio) fallan igual sobre
   lavanda (2.4–3.5:1, comprobado con la fórmula WCAG) — melocoton-tint
   es la única variante de marca que sigue leyéndose como un cambio de
   color real y pasa AA aquí (~4.6:1).
   scale(1.05) — a petición expresa, "que crezca un poco también con el
   hover", mismo empujón sutil que el resto de hovers "respirando" de la
   web (ver .about-cta-link). */
.team-profile__more-btn:hover,
.team-profile__more-btn:focus-visible {
  color: var(--color-melocoton-tint);
  transform: scale(1.05);
}

.team-profile__more-btn span[aria-hidden] {
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: 1.15rem;
  line-height: 1;
}

/* Color/peso/decoración/hover: ver el enlace berenjena discreto
   compartido, junto a .back-link. */
.team-profile__linkedin {
  display: inline-block;
  margin-top: 1.25rem;
}

/* Anula el berenjena compartido con .back-link/.single-post__back/
   .contact-details (todos sobre fondos claros): dentro de la ficha de
   Conócenos el fondo es lavanda sólido, donde berenjena da solo
   2.16:1. */
.team-profile .team-profile__linkedin {
  color: var(--color-niebla-clara);
}

.team-profile__quote {
  font-family: var(--font-titulos);
  font-weight: 500;
  font-style: italic;
  font-size: 1.2rem;
  color: var(--color-berenjena);
  border-left: 4px solid var(--color-pistacho);
  padding-left: 1.1em;
  margin: 1.5rem 0;
  text-align: left;
}

.team-profile__formacion {
  margin-bottom: 1.5rem;
  text-align: left;
}

.team-profile__formacion h3 {
  font-size: 1.05rem;
  margin-bottom: 0.6rem;
}

.team-profile__formacion ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.team-profile__formacion li {
  background-color: var(--color-niebla);
  color: var(--color-berenjena);
  padding: 0.4em 0.9em;
  border-radius: 999px;
  font-size: 0.95rem;
}

.team-profile__bio {
  /* Berenjena, no lavanda: lavanda sobre el tinte lavanda de fondo de
     la página da 4.08:1, por debajo del mínimo AA. */
  color: var(--color-berenjena);
  text-align: left;
}

.team-profile__bio p {
  /* 2em, no 1em: ~2 líneas de aire entre párrafos de la biografía
     completa, no solo 1. */
  margin: 0 0 2em;
}

.team-profile__bio p:last-child {
  margin-bottom: 0;
}

/* CTA al final de la biografía completa (dentro del <dialog>, ver
   page-conocenos.php) — mismo criterio de espacio que .pricing-cta en
   Servicios: centrado, con su propio margen por encima para separarlo
   del último párrafo. */
.team-profile__cta {
  margin-top: 2rem;
  text-align: center;
}

/* Biografía completa de cada persona: <dialog> nativo (ver
   animations.js para el showModal()/cierre), no una caja que expande
   la propia ficha — "ventana" horizontal por encima del resto de la
   página. El navegador ya se encarga de lo importante en
   accesibilidad: atrapa el foco dentro mientras está abierto, Esc
   cierra, y el resto de la página queda inerte (inert) para lectores
   de pantalla sin tener que hacerlo a mano. */
.team-bio-dialog {
  /* position: fixed (no relative) — un <dialog> abierto con
     showModal() vive en el "top layer" del navegador; con
     position:relative el diálogo cae en el flujo normal del
     documento, justo donde está en el HTML (pegado a la ficha,
     solapando la siguiente) en vez de flotar por encima de toda la
     página.
     Tamaño y posición: proporcional a la ventana (crece/encoge con
     ella) y con el MISMO hueco libre arriba/abajo por los dos lados
     ('top'/'height', igual que antes). El ancho SÍ lleva tope ahora
     (max-width en el 'width' de abajo, con min()): a petición
     expresa, la tarjeta se había quedado demasiado ancha en pantallas
     grandes (hasta ocupar casi todo el viewport, con el texto de
     dentro llegando a ~116 caracteres por línea) — 54rem mantiene el
     texto (70% de este ancho, ver --bio-column-width) en una columna
     de lectura cómoda, similar a los ~65ch del resto del texto largo
     de la web. 'left: 50%' + 'translate' centra horizontalmente ahora
     que el ancho ya no depende directamente de 'left' (antes 'left:
     6vmin' + 'width: calc(100vw - 12vmin)' se encargaban de centrar
     sin necesitar transform de por medio) — sin tocar el <dialog>
     mismo con más transforms que este: el FLIP de apertura (ver
     animations.js) sigue animando solo .team-bio-dialog__morph, nunca
     este elemento, así que no hay conflicto entre los dos transforms. */
  position: fixed;
  top: 6vmin;
  left: 50%;
  translate: -50% 0;
  width: min(calc(100vw - 12vmin), 54rem);
  /* 100dvh tras 100vh, ver el porqué largo en .service-bio-dialog
     (misma tarjeta pero en Servicios) más arriba en este fichero. */
  height: calc(100vh - 12vmin);
  height: calc(100dvh - 12vmin);
  margin: 0;
  border: none;
  padding: 0;
  /* El propio <dialog> se queda transparente y sin fondo/sombra
     propios a propósito: todo el aspecto visual (fondo, borde
     redondeado, sombra) vive en .team-bio-dialog__morph, el div de
     dentro. Aplicar un transform (el efecto FLIP de apertura, ver
     animations.js) directamente al <dialog> mientras está en el "top
     layer" le rompe el compositing en Chrome — el fondo se vuelve
     translúcido y deja ver el resto de la página a través, bug
     confirmado durante el desarrollo. Por eso GSAP anima el div
     interior en vez del <dialog> mismo. */
  background-color: transparent;
  color: var(--color-berenjena);
  /* Los navegadores dan a <dialog> un overflow:auto por defecto (para
     poder hacer scroll solo si hace falta). Aquí eso sobra —el scroll
     real lo gestiona .team-bio-dialog__layout, más abajo— y además
     hace daño: como esa caja sobresale 1.5rem a la derecha a
     propósito (para que la barra flote fuera de la tarjeta, ver más
     abajo), el <dialog> lo detectaba como contenido "que se sale" y
     se ponía SU PROPIA barra horizontal para poder alcanzarlo — la
     barra falsa que aparecía abajo del todo. overflow:visible explícito
     anula ese valor por defecto: dialog deja de intentar contener ese
     sobrante y simplemente lo enseña, sin barra propia. */
  overflow: visible;
}

.team-bio-dialog__morph {
  /* La tarjeta en sí: estática, tamaño fijo — nunca se mueve ni cambia
     de tamaño al hacer scroll. Es solo el FONDO de la ventana; el
     contenido que se desplaza (foto + texto) vive dentro, en
     .team-bio-dialog__layout, con su propio scroll aislado (ver más
     abajo). display:flex (no necesita más de una columna: es un
     único hijo) en vez de bloque normal: evita el "colapso de
     márgenes" de CSS entre esta caja y layout, necesario para que
     margin-block en layout (la barra "un poco más cortita") funcione
     igual tenga esta tarjeta una altura fija (escritorio) o automática
     (móvil, ver media query) sin efectos raros de por medio. */
  display: flex;
  position: relative;
  width: 100%;
  height: 100%;
  /* Esquinas redondeadas, a petición expresa — mismo criterio que la
     tarjeta pequeña de la lista (ver .team-profile más arriba). El
     radio se aplica al fondo pintado de esta caja sin más: no hace
     falta overflow:hidden para que se vea (eso rompería la barra de
     scroll que asoma a propósito por el borde derecho, ver el
     comentario de overflow más abajo), y el contenido de dentro
     (.team-bio-dialog__layout) ya queda bien alejado de las esquinas
     por su propio padding. */
  border-radius: 1.75rem;
  /* Melocotón aclarado, no blanco/niebla-clara — igual que el fondo de
     las propias fichas, para que no se sienta un blanco genérico de
     "ventana de sistema". */
  background-color: var(--color-melocoton-tint);
  /* overflow:visible (el valor por defecto, explícito para que quede
     claro que es intencional): .team-bio-dialog__layout, más ancha
     que esta tarjeta a propósito (ver más abajo), asoma su barra de
     scroll por el borde derecho — con overflow:hidden aquí, esa barra
     quedaría cortada en vez de flotar fuera. */
  overflow: visible;
  /* .team-bio-dialog__photo YA NO vive dentro de este div (ver
     comentario en page-conocenos.php): este es el elemento que GSAP
     anima con transform al abrir el diálogo, y un hijo que sobresale
     de su caja con overflow:visible puede quedar recortado por el
     límite de la capa de composición de Chrome una vez termina la
     animación — recorte que solo se ve en uso real interactivo, no
     en una captura de pantalla. Sacar la foto fuera de este árbol
     evita el problema de raíz en vez de depender de overflow. */
}

.team-bio-dialog::backdrop {
  background-color: var(--color-berenjena);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.team-bio-dialog.is-open::backdrop {
  opacity: 0.55;
}

.team-bio-dialog__layout {
  /* Compartida con .team-bio-dialog__photo (más abajo): el 70% del
     bloque de texto y el desplazamiento a la izquierda de la foto
     tienen que moverse siempre juntos, así que salen del mismo número
     en vez de duplicarlo — igual que --scrollbar-width más arriba en
     este fichero. */
  --bio-column-width: 70%;
  /* Ya no es una rejilla de dos columnas (foto | texto): la foto (ver
     .team-bio-dialog__photo) es ahora un bloque normal arriba del
     todo, con su propio margen para desplazarla hacia la derecha —
     el texto de abajo sigue centrándose libremente en
     .team-bio-dialog__content, sin verse condicionado por el ancho
     de la foto. Foto y texto hacen scroll juntos aquí dentro, aislado
     de .team-bio-dialog__morph (que se queda quieta, ver arriba).
     El truco para que la barra de scroll (siempre pegada al borde de
     SU PROPIA caja, no se puede separar con padding) quede flotando
     FUERA de la tarjeta: esta caja mide más ancho que
     .team-bio-dialog__morph (100% + 1.5rem, el hueco pedido) y ese
     mismo 1.5rem de más se sepulta como padding-right extra — el
     contenido de dentro (foto/texto) no se entera y queda exactamente
     donde estaría si esta caja midiera el 100% normal, pero la barra,
     pegada al borde derecho de ESTA caja (más ancha que la tarjeta),
     asoma más allá del borde de .morph. Como .morph tiene
     overflow:visible, nada la recorta ahí fuera.
     flex-shrink:0 es imprescindible: .morph es flex (ver arriba), y
     por defecto un hijo flex se ENCOGE para caber en el contenedor
     — exactamente lo que NO queremos aquí, anularía el ancho de más
     de esta caja y la barra volvería a quedar pegada al borde de la
     tarjeta. */
  flex-shrink: 0;
  width: calc(100% + 1.5rem);
  /* Altura completa de la tarjeta: antes llevaba margin-block:1rem
     (pedido en su momento para que la barra de scroll se viera "un
     poco más cortita"), pero dejaba asomar una franja del fondo de
     .morph arriba y abajo — quitado a petición expresa. */
  height: 100%;
  padding: 3rem;
  padding-right: calc(3rem + 1.5rem);
  overflow-y: auto;
}

@media (max-width: 40rem) {
  .team-bio-dialog {
    /* Alto fijo solo en escritorio (ver la regla base de arriba:
       'top'+'height' ya dejan 6vmin arriba y abajo). En móvil eso
       forzaría una tarjeta a pantalla completa aunque la biografía
       sea corta — añadir 'bottom' explícito junto a height:auto y
       margin-block:auto vuelve a activar el centrado de "alto
       automático" (se ciñe al contenido, con el mismo hueco mínimo de
       6vmin arriba/abajo si el contenido es más corto que eso). */
    bottom: 6vmin;
    height: auto;
    margin-block: auto;
  }

  .team-bio-dialog__morph {
    /* Sin alto fijo (ver .team-bio-dialog arriba): se ciñe al
       contenido de dentro hasta este máximo, a partir del cual
       .team-bio-dialog__layout empieza a hacer scroll ella sola. */
    height: auto;
    /* 100dvh tras 100vh, ver el porqué largo en .service-bio-dialog
       más arriba en este fichero. */
    max-height: calc(100vh - 12vmin);
    max-height: calc(100dvh - 12vmin);
  }

  .team-bio-dialog__layout {
    /* Hueco más pequeño en móvil: la pantalla ya es estrecha de por
       sí, y con 1.5rem el texto perdería demasiado ancho útil. */
    width: calc(100% + 0.75rem);
    height: auto;
    /* 100dvh tras 100vh, ver el porqué largo en .service-bio-dialog
       más arriba en este fichero. */
    max-height: calc(100vh - 12vmin);
    max-height: calc(100dvh - 12vmin);
    padding: 1.5rem;
    padding-right: calc(1.5rem + 0.75rem);
  }
}

.team-bio-dialog__header {
  /* Fila que junta la foto con el nombre y la profesión, a petición
     expresa: antes ese hueco a la derecha de la foto se quedaba vacío
     (el nombre estaba debajo, no al lado). align-items:flex-end alinea
     el bloque de texto con el borde inferior de la foto, sin importar
     que el texto ocupe menos alto que ella.
     width:fit-content (no 100%/max-width): la fila mide solo lo que
     ocupan sus dos hijos (nombre + foto, con el gap entre medio), ni
     un pelo más — con justify-content:space-between (probado antes)
     la fila estiraba hasta el borde de .team-bio-dialog__layout y la
     foto (order:2, ver .team-bio-dialog__photo) se iba mucho más a la
     derecha de lo pedido, con un hueco enorme en medio. Con
     fit-content ese hueco es solo el 'gap' de abajo — la foto queda
     "un poco" más a la derecha del nombre, no empujada al extremo.
     El padding-left sitúa el nombre (order:1, ver
     .team-bio-dialog__identity) exactamente donde arranca el texto de
     .team-bio-dialog__content (mismo cálculo que usaba antes el
     margin-left de la foto). */
  display: flex;
  align-items: flex-end;
  width: fit-content;
  gap: 2.5rem;
  padding-left: calc((100% - var(--bio-column-width)) / 2 + 0.5rem);
  margin-bottom: 2rem;
}

@media (max-width: 40rem) {
  .team-bio-dialog__header {
    /* En móvil no cabe la foto y el texto en la misma fila sin
       apretujar el nombre contra un ancho mínimo — se apila igual que
       antes de este cambio (foto arriba, nombre y profesión debajo).
       width:auto: apilada en columna, tiene que volver a ocupar el
       ancho normal (no fit-content, que aquí solo mediría el más
       ancho de los dos hijos apilados).
       padding-left ya no lleva el hueco de centrado del 70% (ver
       arriba): en móvil .team-bio-dialog__content pasa a max-width:100%
       (ver su media query más abajo), así que su texto vuelve a
       arrancar en el mismo 0.5rem de padding base, sin ese hueco
       extra. */
    width: auto;
    padding-left: 0.5rem;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
  }
}

.team-bio-dialog__photo {
  /* Mismo tamaño aproximado que en la ficha cerrada (.team-profile__photo
     ronda las 15-19rem según el ancho de esa tarjeta), a petición
     expresa — 9rem se quedaba demasiado pequeña. Hay sitio de sobra
     para que quepa a su izquierda (ver .team-bio-dialog__header, que ya
     no limita la fila al 70% de .team-bio-dialog__content). */
  display: block;
  width: 16rem;
  /* order:2 la manda al final visualmente (a la derecha, ver
     .team-bio-dialog__header) aunque en el HTML siga siendo el primer
     hijo. */
  order: 2;
  /* No encoge: sin esto, si el nombre no cupiera igual encogería la
     foto en vez de solo envolver el texto (ver .team-bio-dialog__identity,
     que sí puede encoger y pasar a dos líneas). */
  flex-shrink: 0;
  margin: 0;
}

@media (max-width: 40rem) {
  .team-bio-dialog__photo {
    /* En móvil la fila se apila (ver media query de arriba), así que
       la foto ya no comparte ancho con el nombre: puede volver a un
       tamaño más generoso. order:0 deshace el order:2 de arriba —
       apilada, tiene que volver a ir primero (arriba), como en el
       HTML. */
    width: 15rem;
    order: 0;
  }
}

.team-bio-dialog__content {
  /* Columna centrada en medio de la tarjeta, no pegada a la derecha
     de la foto como antes. La foto ya no está en position:absolute
     (ver .team-bio-dialog__photo), así que ya no tiene sentido que
     solo esta columna tenga scroll propio — ahora es
     .team-bio-dialog__layout quien hace scroll con la foto y el
     texto juntos dentro.
     max-width en % (no en rem fijo): a petición expresa, el bloque de
     texto ocupa el 70% del ancho de la tarjeta grande — como es un
     porcentaje, se mantiene proporcional aunque la tarjeta cambie de
     ancho (ver .team-bio-dialog). En móvil ese 70% se anula (ver
     media query más abajo): en una tarjeta ya estrecha de por sí,
     dejar un 30% de hueco muerto a los lados perjudicaría la lectura
     en vez de ayudarla. */
  max-width: var(--bio-column-width);
  margin: 0 auto;
  text-align: left;
  padding: 0 0.5rem;
}

@media (max-width: 40rem) {
  .team-bio-dialog__content {
    max-width: 100%;
  }
}

.team-bio-dialog__identity {
  /* Encoge para no arrastrar el ancho de la fila (ver
     .team-bio-dialog__header) más allá de lo que ocupe el propio
     texto. */
  flex: 0 1 auto;
  min-width: 0;
  /* order:1 la manda al principio visualmente (a la izquierda, contra
     el borde que comparte con el texto de debajo) aunque en el HTML
     siga yendo después de la foto — ver .team-bio-dialog__header y
     .team-bio-dialog__photo. */
  order: 1;
}

@media (max-width: 40rem) {
  .team-bio-dialog__identity {
    /* Apilada bajo la foto (ver media query de .team-bio-dialog__header
       y .team-bio-dialog__photo): order:0 deshace el order:1 de
       arriba, para que vuelva a ir después de la foto, como en el
       HTML. */
    order: 0;
  }
}

.team-bio-dialog__identity h2 {
  /* Un poco más grande que el nombre de la ficha cerrada
     (.team-profile__name, 1.5rem), a petición expresa. */
  font-size: 1.75rem;
  margin: 0 0 0.25rem;
  /* Nombre y profesión (ver .team-bio-dialog__role) tienen que salir
     siempre completos en una sola línea, a petición expresa — ya hay
     hueco de sobra para eso (ver .team-bio-dialog__header), así que
     nowrap aquí es solo la garantía, no lo que hace sitio. */
  white-space: nowrap;
  /* outline:none — este título recibe foco por script al abrir el
     <dialog> (tabindex="-1" en el HTML + .focus() en animations.js,
     ver el porqué largo ahí: mover el foco aquí en vez de dejarlo caer
     en el botón de cerrar por defecto). Mismo motivo que
     .hoja-mesa-title-inside en hoja-a-mesa.css: sin esto, el navegador
     pinta su propio anillo nativo por defecto aquí (un h2 no está
     cubierto por el button:focus-visible de más abajo), cambiando un
     anillo raro por otro en vez de quitarlo. */
  outline: none;
}

.team-bio-dialog__role {
  color: var(--color-berenjena);
  font-weight: 600;
  white-space: nowrap;
  font-size: 1.1rem;
  /* Sin margen inferior: ya no le sigue el resumen en la misma
     columna (ver .team-bio-dialog__header) — el hueco antes del
     resumen lo pone ahora el margin-bottom de .team-bio-dialog__header. */
  margin: 0;
}

.team-bio-dialog__close {
  position: absolute;
  /* 1.5rem, no 1.1rem: con la esquina de la tarjeta ya recta (sin
     border-radius), el botón quedaba casi tocando el vértice — un poco
     más separado de los dos bordes. */
  top: 1.5rem;
  right: 1.5rem;
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background-color: var(--color-niebla);
  color: var(--color-berenjena);
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.team-bio-dialog__close:hover,
.team-bio-dialog__close:focus-visible {
  background-color: var(--color-pistacho);
  transform: rotate(90deg);
}

/* Móvil Y tablet (64rem, mismo tope que .nav-toggle más arriba en este
   fichero) — mismo tratamiento que .hoja-mesa-close en Inicio (ver el
   porqué largo en hoja-a-mesa.css): sin hover real (dedo, no ratón), el
   círculo pistacho pasa a ser el estado de siempre; el círculo VISIBLE
   se hace más pequeño (a petición expresa, "para que no tape el texto
   cuando se va leyendo y scrolleando" — el botón no se mueve con el
   scroll de .team-bio-dialog__layout, así que el texto pasa por
   debajo); y el ÁREA PULSABLE (el <button> en sí) se queda más grande
   que ese círculo, para que siga siendo fácil de acertar con el dedo. */
@media (max-width: 64rem) {
  .team-bio-dialog__close {
    /* Área pulsable — sin "position" aquí: el botón ya es
       position:absolute (regla base, arriba) contra
       .team-bio-dialog__morph, y sirve igual de bien como referencia
       de posición para su propio ::before. */
    width: 2rem;
    height: 2rem;
    background-color: transparent;
  }

  /* Anula el ":hover"/":focus-visible" de escritorio (arriba) — mismo
     bug real que .hoja-mesa-close (ver el porqué largo en
     hoja-a-mesa.css): showModal() pone el foco en el primer elemento
     interactivo del <dialog>, que es justo este botón, así que sin
     esto cada tarjeta abría con él momentáneamente relleno pistacho a
     tamaño completo (2rem) antes de "encogerse" al círculo pequeño de
     ::before — un ":focus-visible" puntúa más que una clase sola por
     especificidad, así que necesita esta anulación explícita, no basta
     con el orden en el archivo. */
  .team-bio-dialog__close:hover,
  .team-bio-dialog__close:focus-visible {
    background-color: transparent;
    transform: none;
  }

  .team-bio-dialog__close::before {
    content: '';
    position: absolute;
    inset: 0;
    margin: auto;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background-color: var(--color-pistacho);
  }

  .team-bio-dialog__close svg {
    position: relative;
    z-index: 1;
    width: 10px;
    height: 10px;
  }
}

/* Contacto */
/* Al mover .contact-intro dentro de la sidebar (ver más abajo), el
   contenido visible ya no empieza hasta .contact-columns, así que el
   padding-top normal de .section (--section-padding-block, hasta
   7rem) dejaba mucho aire bajo el h1 "Contacto" — a petición expresa,
   "pegarlo un poco más arriba al título". */
.page-header + .section--contacto {
  padding-top: clamp(1.5rem, 4vw, 3rem);
}

/* Conócenos: mismo hueco título→contenido que el h1 "Contacto" guarda
   con el formulario (regla justo encima) — a petición expresa, para
   que "Conócenos" y las fichas del equipo queden a la misma distancia
   que "Contacto" y su formulario, en vez del padding-top normal de
   .section (--section-padding-block, hasta 7rem) que dejaba las
   fichas mucho más abajo. */
.page-header + .section--conocenos {
  padding-top: clamp(1.5rem, 4vw, 3rem);
}

/* Blog: mismo hueco título→contenido que "Contacto" guarda con su
   formulario (regla justo encima) — a petición expresa, para que las
   entradas empiecen igual de pegadas al h1 "Blog" que el formulario a
   "Contacto", en vez del padding-top normal de .section
   (--section-padding-block, hasta 7rem). */
.page-header + .section--blog {
  padding-top: clamp(1.5rem, 4vw, 3rem);
}

/* Ilustración de fondo de grupo.svg (ver el bloque nuevo antes de
   <main> en page-contacto.php, y ahí el porqué de vivir fuera de
   #main). Pistacho aclarado (--color-pistacho-medio, ver tokens.css),
   para que se siga distinguiendo del fondo pistacho sin diluir de
   esta página (body.bg-tint-pistacho-fuerte).
   A petición expresa, dos cosas a la vez:
   1) "más grande, ocupando el 120% del ancho de la ventana" — width
      en vw (no % de un contenedor), centrado con left:50% +
      translateX(-50%) para que sobresalga por igual a cada lado.
   2) "que el fondo se quede estático mientras el resto se mueve por
      encima" — position:fixed en vez de absolute: ligado al viewport,
      no al documento, así que no se desplaza con el scroll.
   z-index negativo, no 0: sin esto pintaría por encima del contenido
   normal en flujo aunque venga antes en el DOM (los descendientes
   posicionados se pintan delante de los bloques normales) — con
   z-index negativo queda detrás de todo, delante solo del color de
   fondo plano del body. Un position:fixed con z-index negativo sigue
   funcionando igual: crea su propio contexto de apilamiento, pero por
   debajo del resto de la página en ese contexto raíz.
   Sin envoltorio con su propio overflow:hidden: el 20% de más
   (120vw > 100vw) sale por los dos lados del viewport, pero al ser
   fixed (fuera del flujo normal) el propio navegador no lo cuenta
   como overflow real del documento — no añade scroll horizontal. */
.contacto-grupo-fondo {
  position: fixed;
  left: 60%;
  bottom: -40rem;
  transform: translateX(-50%);
  rotate: 10deg;
  width: 90vw;
  z-index: -1;
  opacity: 0.5;
  pointer-events: none;
}

.contacto-grupo-fondo svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Servicios — área de atención (Adultos, Terapia de familia...):
   ilustración de fondo propia de cada página, mismo criterio que
   .contacto-grupo-fondo justo arriba (grande, opacidad baja,
   position:fixed para quedarse estática mientras el resto de la
   página se mueve por encima) — a petición expresa, "como en
   Contacto".
   Abajo a la izquierda, no centrada — a petición expresa ("como si
   salieran por el lado inferior izquierdo"), y dimensionada por
   ALTURA (no por ancho, a diferencia de .contacto-grupo-fondo): con
   fixed anclado por bottom/left, limitar la altura a una fracción del
   alto de la ventana (en vez de un ancho en vw, que en pantallas bajas
   podría desbordar por arriba) es lo que garantiza que la ilustración
   entera quepa siempre sin cortarse por arriba, sea cual sea su
   proporción real.
   Lavanda, no pistacho-medio como en Contacto: estas páginas
   comparten el mismo fondo claro melocotón que ya usan las páginas de
   "Qué tratamos" (ver body.bg-tint-melocoton en header.php) — mismo
   color que sus hojas de fondo (.que-tratamos-item-hoja-fondo más
   arriba), para que el criterio de "ilustración decorativa sobre
   fondo melocotón claro" sea el mismo en toda la web. */
.servicios-area-fondo {
  position: fixed;
  left: 1.5rem;
  bottom: 1.5rem;
  height: min(75vh, 44rem);
  width: auto;
  z-index: -1;
  opacity: 0.18;
  pointer-events: none;
}

.servicios-area-fondo svg {
  display: block;
  width: auto;
  height: 100%;
}

/* Terapia de familia e Infancia y adolescencia: a la derecha en vez de
   a la izquierda (el "left" compartido de arriba sigue siendo el
   valor por defecto para el resto) — a petición expresa, solo estas
   dos. left:auto para anular el left heredado, si no compite con este
   right y el navegador prioriza left. */
.servicios-area-fondo--terapia-de-familia,
.servicios-area-fondo--infancia-y-adolescencia {
  left: auto;
  right: 1.5rem;
}

/* Infancia y adolescencia: un poco más hacia la izquierda que Terapia
   de familia (misma regla de arriba) — a petición expresa, solo
   esta. */
.servicios-area-fondo--infancia-y-adolescencia {
  right: 5rem;
}

.contact-intro {
  /* Prueba: vive ahora dentro de .contact-sidebar, junto al
     formulario, en vez de como bloque suelto a ancho de página
     encima de .contact-columns — mismo centrado/izquierda que el
     resto de la sidebar (.contact-alt/.contact-map-section) según el
     ancho, ver la media query de más abajo. */
  margin: 0;
  text-align: center;
}

.contact-intro h2 {
  /* Ya no es hijo directo de .section__inner (esa regla lo centraba y
     le daba tamaño de título de sección) — tamaño propio, más
     contenido para encajar en la columna estrecha de la sidebar. */
  font-size: clamp(1.4rem, 2.4vw, 1.7rem);
  margin: 0 0 0.75rem;
}

.contact-intro p {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  color: var(--color-berenjena);
  margin: 0 0 0.75em;
}

.contact-intro p:last-child {
  margin-bottom: 0;
}

.process-steps {
  /* Ahora vive dentro de .contact-sidebar (columna estrecha junto al
     formulario, ver .contact-columns), no como bloque suelto a ancho
     de página — por eso una sola columna apilada, ya no la rejilla de
     4 en línea que tenía cuando ocupaba todo el ancho. */
  list-style: none;
  display: grid;
  gap: 1.5rem;
  padding: 0;
  margin: 0;
}

.process-steps__number {
  /* Sin círculo: el número solo, alineado a la izquierda con el
     título y el texto de debajo. Berenjena (no melocotón): sobre el
     fondo melocoton-tint de esta página, melocotón como texto no
     llega ni al 3:1 de contraste al ser un tinte tan claro del mismo
     color — aquí el número SÍ es texto de lectura (a diferencia del
     borde decorativo que sustituye), así que necesita el 4.5:1 de AA. */
  display: block;
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: 2rem;
  line-height: 1;
  color: var(--color-berenjena);
}

.process-steps__item h3 {
  font-size: 1.1rem;
  margin: 0.4rem 0 0.35rem;
}

.process-steps__item p {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  margin: 0;
  color: var(--color-berenjena);
  font-size: 1rem;
}

/* Formulario (columna ancha) + barra lateral (WhatsApp/teléfono/email
   + mapa), en vez de una única columna centrada apilando todo — a
   petición expresa, "que esté mejor organizado". El formulario pesa
   más (1.6fr) por ser el canal de contacto preferente (ver
   .contact-alt__intro más abajo); por debajo de 64rem no cabían las
   dos columnas con comodidad (el formulario tiene bastantes campos),
   así que se apilan en una sola, formulario primero. */
.contact-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  align-items: start;
  max-width: 68rem;
  margin: 0 auto;
}

@media (min-width: 64rem) {
  .contact-columns {
    /* 1.6fr → 1.75fr: formulario un poco más ancho, sidebar un poco
       más estrecha. No más de eso: al ancho máximo de página (68rem)
       la sidebar se queda en ~23rem (~368px), que a 1rem/16px de
       Work Sans sigue dando ~45-47 caracteres por línea — el mínimo
       recomendado de legibilidad. Estrecharla más la bajaría de ese
       mínimo. */
    grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr);
    gap: 3.5rem;
  }
}

/* Tarjeta blanca para el formulario: separa visualmente el bloque
   "accionable" del resto de la página (que se queda en el tinte
   melocotón plano del body, sin cajas de color — ver el porqué de esa
   norma en CLAUDE.md). Blanco neutro + borde fino, no un color de
   marca de fondo, y SIN box-shadow (norma del sitio, ver
   no-shadows-vinculare): el propio contraste de blanco sobre el tinte
   del body ya basta para "levantarla" un poco. */
.contact-form-card {
  background-color: #fff;
  border-radius: 1.5rem;
  padding: clamp(1.75rem, 4vw, 3rem);
}

/* Mismo patrón que .page-header__eyebrow (ver más abajo en el
   archivo): etiqueta pequeña, mayúsculas, con tracking, encima de un
   título — reutilizado aquí para "Formulario de contacto" y "Otras
   formas de escribirnos", así ambos bloques (formulario/tarjeta y
   barra lateral) leen con la misma jerarquía tipográfica. */
.contact-eyebrow {
  font-family: var(--font-texto);
  font-weight: 600;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-berenjena);
  margin: 0 0 0.5rem;
}

.contact-sidebar {
  display: flex;
  flex-direction: column;
  gap: 3.5rem;
}

.contact-alt {
  text-align: center;
}

.contact-alt__intro {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  color: var(--color-berenjena);
  margin: 0 0 1.25rem;
}

.contact-form__pending {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). El borde se queda en
     lavanda (solo decorativo, pasa de sobra el 3:1 de un borde). */
  padding: 1.5rem;
  border: 1px dashed var(--color-lavanda);
  border-radius: 0.75rem;
  color: var(--color-berenjena);
}

.whatsapp-link {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}

/* 1.5em, no 1.2em — a petición expresa, "el icono más grande" en los
   dos botones de WhatsApp de la web (el de Contacto y el flotante, ver
   .whatsapp-float en style.css): un solo tamaño, sin excepción por
   botón, para que ambos midan siempre exactamente lo mismo. */
.whatsapp-link__icon {
  width: 1.5em;
  height: 1.5em;
  fill: currentColor;
  flex-shrink: 0;
}

.contact-details {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem 1.75rem;
  margin: 1.25rem 0 0;
  padding: 0;
}

.contact-details a {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

.contact-details__icon {
  width: 1.15em;
  height: 1.15em;
  fill: currentColor;
  flex-shrink: 0;
}

.contact-map-section {
  text-align: center;
}

.contact-address {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  margin: 0 0 1rem;
  color: var(--color-berenjena);
  font-weight: 600;
}

.contact-address__icon {
  width: 1.2em;
  height: 1.2em;
  fill: currentColor;
  flex-shrink: 0;
}

.contact-map {
  width: 100%;
  aspect-ratio: 16 / 7;
  border-radius: 1rem;
  overflow: hidden;
  text-align: left;
}

.contact-map iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* Nota de autobuses cercanos, debajo del minimapa — mismo berenjena
   sobre fondo claro que .contact-address justo arriba (pasa AA de
   sobra, ver el porqué ahí), pero más pequeña y sin negrita: es un
   dato complementario, no el dato principal de "dónde estamos" que ya
   da .contact-address. */
.contact-transit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  margin: 1rem 0 0;
  color: var(--color-berenjena);
  font-size: 0.9rem;
}

.contact-transit__icon {
  width: 1.2em;
  height: 1.2em;
  fill: currentColor;
  flex-shrink: 0;
}

@media (min-width: 64rem) {
  .contact-transit {
    justify-content: flex-start;
  }
}

/* A partir de 64rem la barra lateral vive junto al formulario (no
   debajo, centrada): se alinea a la izquierda, como corresponde a una
   columna secundaria, no a un bloque de cierre de página. */
@media (min-width: 64rem) {
  .contact-intro,
  .contact-alt,
  .contact-map-section {
    text-align: left;
  }

  .contact-details,
  .contact-address {
    justify-content: flex-start;
  }
}

/* Formulario de contacto (Contact Form 7) */
.contact-form-card > h2 {
  /* Alineado a la izquierda, no centrado como el resto de títulos de
     sección: dentro de su propia tarjeta, con los campos también a la
     izquierda debajo, lee mejor como cabecera de un formulario real
     que como un titular de sección más. */
  text-align: left;
  margin: 0 0 1.75rem;
}

.contact-form .wpcf7-form label {
  display: block;
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 1.25rem;
}

/* :not(.wpcf7-radio):not(.wpcf7-acceptance) — Contact Form 7 marca el
   CONTENEDOR de cada grupo de radios/aceptación con la misma clase
   "wpcf7-form-control" que un campo de texto real, así que sin esta
   exclusión este marco de campo se dibujaba también alrededor de todo
   el grupo, encima del marco propio de cada píldora/tarjeta de dentro
   (.wpcf7-list-item, ver más abajo) — un doble marco visible, sobre
   todo en el checkbox de RGPD. El grupo en sí no necesita marco propio:
   ya lo dan sus píldoras/tarjetas de dentro.
   :not(.wpcf7-submit) — el botón de enviar también lleva la clase
   "wpcf7-form-control" (ver más abajo) pero tiene su propio aspecto de
   botón "pill" completamente distinto; sin excluirlo aquí, los dos
   :not() de arriba suben la especificidad de este selector por encima
   de la de ".contact-form .wpcf7-submit" (misma cantidad de clases
   antes), así que este marco de campo blanco/niebla acababa ganando y
   tapando el botón melocotón. */
.contact-form .wpcf7-form-control:not(.wpcf7-radio):not(.wpcf7-acceptance):not(.wpcf7-submit) {
  display: block;
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.75em 1em;
  font-family: var(--font-texto);
  font-size: 1rem;
  color: var(--color-berenjena);
  background-color: #fff;
  border: 2px solid var(--color-niebla);
  border-radius: 0.6rem;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.contact-form textarea.wpcf7-form-control {
  min-height: 8rem;
  resize: vertical;
}

/* Contador de caracteres de "Cuéntanos, ¿en qué podemos ayudarte?":
   creado por JS (ver el bloque dedicado en animations.js), oculto por
   defecto — a petición expresa, solo debe aparecer cuando quedan 50
   caracteres o menos de los 2000 del maxlength del campo, no todo el
   rato como el contador nativo de Contact Form 7 (clase
   wpcf7-character-count, siempre visible tipo "120 / 2000"). A
   petición expresa: cifra pequeña "usados/total" (p. ej. "1950/2000"),
   no una píldora con frase — la píldora anterior quedaba demasiado
   grande/llamativa para un simple aviso de límite.
   position:absolute anclada a .wpcf7-form-control-wrap (el <span> que
   CF7 pone como hermano del <textarea>, con position:relative ya fijo
   por el propio plugin — ver includes/css/styles.css), no al flujo
   normal: así el contador queda pegado a la esquina inferior derecha
   pero *fuera* del campo (bottom negativo), sin solaparse nunca con el
   texto que se esté escribiendo dentro del textarea. */
.contact-form__char-count {
  position: absolute;
  right: 0.2em;
  bottom: -1.7em;
  color: var(--color-berenjena);
  font-size: 0.8rem;
  font-weight: 700;
}

.contact-form .wpcf7-form-control:focus-visible {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo de
     3:1 sobre el fondo blanco del campo (2.2:1). Un toque de fondo
     melocotón muy suave (6%, decorativo, no cambia el color del texto
     que se escribe encima) para que el foco se sienta cálido, a tono
     con el resto de la página, no solo un contorno frío.
     outline-offset:0, no el 2px que usa el foco por defecto del sitio
     (ver más arriba en este archivo): con separación se veían DOS
     marcos concéntricos con hueco entre medias (el borde de 2px del
     campo y, un poco más afuera, el contorno de foco) — a petición
     expresa, "que engorde el marco que ya tiene, no que se le ponga
     otro". Sin separación, contorno y borde quedan pegados y se leen
     como un único marco más grueso. */
  outline: 3px solid var(--color-berenjena);
  outline-offset: 0;
  border-color: var(--color-berenjena);
  background-color: color-mix(in srgb, var(--color-melocoton) 6%, #fff);
}

/* Campo obligatorio sin rellenar, tras un intento de envío: mismo
   melocotón que ya usa el botón de enviar (5.2:1 con el berenjena de
   encima, pasa AA de sobra) en vez del lavanda de antes — a petición
   expresa, "que se note con claridad", y lavanda quedaba demasiado
   parecido en tono al berenjena de las etiquetas/leyendas de al lado
   como para leerse como un aviso real. destello-contacto lo hace
   parpadear (respiración lenta, 2.4s por ciclo) de forma indefinida — a
   petición expresa, hasta que la persona vuelve a ese campo, no solo
   un par de veces al aparecer: el punto en el que para no es un
   temporizador fijo, es la propia corrección del campo. Contact Form
   7 de por sí NO quita aria-invalid hasta el siguiente intento de
   envío (revalida el formulario entero, no campo a campo mientras se
   escribe) — sin más, el parpadeo habría seguido durante todo ese
   rato aunque la persona ya estuviera corrigiendo el campo. Por eso
   quitarCampoInvalido() en animations.js adelanta esa limpieza al
   primer "input"/"change" del campo (mismas tres cosas que hace CF7
   al revalidar: aria-invalid a "false", quita wpcf7-not-valid y el
   aviso), así el parpadeo se detiene en cuanto se empieza a escribir
   de nuevo, no cuando se reenvía el formulario. El criterio de "parar
   tras un rato" de WCAG 2.2 para contenido que destella pide un modo
   de pararlo, y aquí existe: basta con volver a escribir en el campo.
   prefers-reduced-motion ya lo colapsa a un resalte fijo sin animar en
   cualquier caso (ver la regla global al principio del archivo). */
@keyframes destello-contacto {
  0%,
  100% {
    background-color: color-mix(in srgb, var(--color-melocoton) 18%, #fff);
  }

  50% {
    background-color: color-mix(in srgb, var(--color-melocoton) 42%, #fff);
  }
}

.contact-form .wpcf7-form-control[aria-invalid="true"] {
  border-color: var(--color-melocoton);
  background-color: color-mix(in srgb, var(--color-melocoton) 18%, #fff);
  animation: destello-contacto 2.4s ease-in-out infinite;
}

/* Aviso bajo cada campo: antes era solo texto en color, se confundía
   con las leyendas/etiquetas de alrededor (mismo berenjena, pesos
   parecidos). Ahora es una píldora de fondo sólido con un icono
   redondo — se lee como una alerta puntual, no como una línea de
   texto más. aria-hidden="true" (lo pone Contact Form 7): el aviso
   accesible real para lectores de pantalla es otro, ligado por
   aria-describedby a una lista aparte (.screen-reader-response), así
   que este es solo el aviso VISUAL para quien ve la pantalla. */
.contact-form .wpcf7-not-valid-tip {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.3em 0.85em;
  border-radius: 999px;
  background-color: var(--color-melocoton);
  color: var(--color-berenjena);
  font-size: 0.85rem;
  font-weight: 700;
}

/* Mismo aspecto que .btn.btn--cita (ver arriba) en vez del botón
   nativo del navegador que CF7 deja por defecto — a petición expresa,
   "todos los botones normales de la web con la misma coherencia":
   fondo berenjena fijo, el hover/foco solo agranda, nunca cambia de
   color. No se puede añadir la clase "btn"/"btn--cita" al propio
   <input type="submit"> (su markup lo genera Contact Form 7 desde
   wp-admin, fuera de este código), así que se replican aquí las mismas
   propiedades contra su selector real. appearance:none quita el
   aspecto nativo del sistema operativo (que si no pelea con el
   fondo/borde propios); font:inherit porque los controles de
   formulario no heredan la tipografía de la página por defecto en
   todos los navegadores. */
.contact-form .wpcf7-submit {
  appearance: none;
  display: inline-block;
  /* width:auto explícito: sin esto hereda el width:100% de
     .wpcf7-form-control (arriba) — el botón de enviar no es un campo,
     no debe estirarse a todo lo ancho, igual que el resto de botones
     "pill" del sitio (ver .btn), todos de ancho según su texto. */
  width: auto;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  margin-top: 0.5rem;
  padding: 0.85em 1.75em;
  border-radius: 999px;
  border: 2px solid transparent;
  background-color: var(--color-berenjena);
  color: var(--color-blanco);
  transition: transform 0.2s ease, background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.contact-form .wpcf7-submit:hover,
.contact-form .wpcf7-submit:focus-visible {
  transform: scale(1.08);
}

/* El párrafo que envuelve el botón y el spinner de Contact Form 7:
   antes, con el botón a ancho completo (ver el porqué justo arriba),
   el spinner no cabía al lado y cf7 lo dejaba caer a la línea de
   abajo, montado sobre la esquina del botón — con el botón ya a su
   ancho natural, basta con centrar ambos en la misma fila.
   justify-content:center — a petición expresa ("que el botón de
   enviar salga centrado, no alineado a la izquierda"): sin esto,
   flex por defecto los deja en flex-start (izquierda), como el resto
   de campos del formulario a ancho completo. */
.contact-form .wpcf7-form > p:has(.wpcf7-submit) {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.9rem;
}

/* Aviso de conjunto (arriba del botón de enviar): antes solo un borde
   izquierdo de 4px sobre fondo transparente, apenas se notaba — a
   petición expresa, "que se vea con claridad". Ahora una franja de
   fondo sólido de ancho completo, mismo criterio de color que el
   resto de avisos de esta página (melocotón para error, tinte oliva
   para éxito, ambos con berenjena encima pasan AA).
   El selector ".wpcf7 form" iguala la especificidad de las reglas
   propias de Contact Form 7 (includes/css/styles.css), que si no
   ganan por especificidad y dejan el marco azul/amarillo del plugin. */
/* A petición expresa, "más elegante": EB Garamond (--font-titulos, la
   misma serif de los títulos) en vez de Work Sans (--font-texto, la
   misma que ya usa el resto del formulario alrededor) y peso medium
   (500) en vez de semibold (600) — menos "grito de aviso de sistema",
   más en línea con la tipografía de marca.
   font-size:1.1rem — a petición expresa, "un poco más grande, como el
   tamaño de las cosas del formulario o el botón de enviar": sin un
   tamaño propio aquí hereda el 1rem/16px por defecto del body, técnicamente
   igual que los campos (.wpcf7-form-control, font-size:1rem) y el botón
   (font:inherit), pero EB Garamond tiene una altura de x notablemente
   menor que Work Sans al mismo tamaño nominal, así que a ojo se leía
   más pequeño que el resto pese a compartir el mismo rem. */
.contact-form .wpcf7 form .wpcf7-response-output {
  margin-top: 1.75rem;
  padding: 1em 1.25em;
  border: 0;
  border-radius: 0.85rem;
  background-color: var(--color-niebla);
  color: var(--color-berenjena);
  font-family: var(--font-titulos);
  font-size: 1.1rem;
  font-weight: 500;
}

.contact-form .wpcf7 form.sent .wpcf7-response-output {
  background-color: var(--color-oliva-tint);
}

.contact-form .wpcf7 form.invalid .wpcf7-response-output,
.contact-form .wpcf7 form.unaccepted .wpcf7-response-output,
.contact-form .wpcf7 form.payment-required .wpcf7-response-output,
.contact-form .wpcf7 form.failed .wpcf7-response-output,
.contact-form .wpcf7 form.aborted .wpcf7-response-output,
.contact-form .wpcf7 form.spam .wpcf7-response-output {
  background-color: var(--color-melocoton);
}

/* El spinner por defecto de Contact Form 7 (includes/css/styles.css)
   es un círculo gris oscuro genérico con un puntito claro girando
   dentro — no combina con la marca. Mismos tamaño/animación (el
   plugin ya los define), solo se cambian los dos colores: círculo en
   el tinte melocotón de esta página, puntito en berenjena. */
/* display:none — bug real, reportado en móvil/tablet: "el botón de
   enviar sale un poco movido a la izquierda". Causa: el CSS propio de
   Contact Form 7 (includes/css/styles.css) pone visibility:hidden en
   este spinner mientras no se envía el formulario, no display:none —
   sigue ocupando su ancho (24px + margin:0 24px = 72px) dentro del
   flex de arriba, así que el grupo [botón + hueco invisible del
   spinner] se centra como conjunto y el botón queda desplazado ~36px
   a la izquierda del centro real. Con display:none ese hueco
   fantasma deja de contar del todo y el botón se centra solo; al
   enviar el formulario, form.submitting (clase que añade el propio
   cf7) lo vuelve a poner en flujo junto al botón, ya centrados ambos
   como grupo durante ese momento breve. */
.contact-form .wpcf7-spinner {
  display: none;
  margin: 0 0 0 0.6rem;
  background-color: var(--color-melocoton-tint);
  opacity: 1;
}

.contact-form .wpcf7-form.submitting .wpcf7-spinner {
  display: inline-block;
}

.contact-form .wpcf7-spinner::before {
  background-color: var(--color-berenjena);
}

/* Formulario de contacto: grupos (fieldset) */
.contact-form .wpcf7-form fieldset.contact-form__group {
  border: 0;
  padding: 0;
  margin: 0;
}

/* Cada fieldset/párrafo de nivel superior del formulario ocupa el
   ancho completo por defecto; "Modalidad preferida" y "Disponibilidad"
   (dos listas cortas de 2-3 opciones cada una) pasan a compartir fila
   a partir de 40rem — el resto (datos, motivo, tipo de atención,
   contacto preferido, aceptación, enviar) se queda a ancho completo,
   ver el porqué de cada selector más abajo. Selección por
   [data-name="..."] (el atributo que ya pone Contact Form 7 en cada
   campo) en vez de nth-of-type: sigue funcionando aunque se reordene
   o se añada un campo nuevo en el formulario real (editado desde
   wp-admin, fuera de este código). */
.contact-form .wpcf7-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}

.contact-form .wpcf7-form > fieldset,
.contact-form .wpcf7-form > p,
.contact-form .wpcf7-form > div {
  grid-column: 1 / -1;
  margin: 0;
}

@media (min-width: 40rem) {
  .contact-form .wpcf7-form {
    grid-template-columns: 1fr 1fr;
  }

  .contact-form .wpcf7-form fieldset:has([data-name="modalidad"]),
  .contact-form .wpcf7-form fieldset:has([data-name="disponibilidad"]) {
    grid-column: span 1;
  }
}

/* Leyendas de cada grupo ("Datos de contacto", "Motivo de consulta"...):
   antes casi del mismo color/peso que las etiquetas de los campos de
   debajo, costaba distinguir dónde empezaba cada bloque nuevo. Ahora
   con una línea de acento debajo que las separa con claridad de las
   etiquetas, sin necesidad de subirles el tamaño más de la cuenta.
   Pistacho-tint, no melocotón-tint: a petición expresa, las líneas
   decorativas de base del formulario pasan a pistacho — el melocotón
   se queda solo para el aviso de error (ver [aria-invalid="true"] más
   abajo). */
.contact-form .wpcf7-form legend {
  display: block;
  width: 100%;
  font-family: var(--font-titulos);
  font-weight: 600;
  font-size: 1.1rem;
  color: var(--color-berenjena);
  padding: 0 0 0.6rem;
  margin: 0 0 1.1rem;
  border-bottom: 2px solid var(--color-pistacho-tint);
}

/* Datos de contacto en fila cuando hay espacio */
.contact-form__group--datos {
  display: grid;
  gap: 0 1.25rem;
  grid-template-columns: 1fr;
}

@media (min-width: 30rem) {
  .contact-form__group--datos {
    grid-template-columns: 1fr 1fr;
  }

  .contact-form__group--datos label:first-child {
    grid-column: 1 / -1;
  }
}

.contact-form__group--datos label {
  margin-bottom: 1.25rem;
}

/* Grupos de opciones (radio) como tarjetas seleccionables */
.contact-form .wpcf7-radio {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  border-radius: 0.85rem;
  transition: background-color 0.2s ease;
}

/* Al fallar la validación, Contact Form 7 marca el CONTENEDOR entero
   de las opciones (no cada píldora suelta) con esta clase: se resalta
   el grupo completo, igual criterio de color que un campo de texto
   inválido (ver arriba), para que quede claro que hace falta elegir
   una opción, no solo que "algo" está mal. */
.contact-form .wpcf7-radio.wpcf7-not-valid {
  padding: 0.85rem;
  margin: -0.85rem;
  background-color: color-mix(in srgb, var(--color-melocoton) 20%, #fff);
  animation: destello-contacto 2.4s ease-in-out infinite;
}

/* El marco de cada píldora va en .wpcf7-list-item (el <span> que
   Contact Form 7 genera de verdad para cada opción de radio), NO en un
   <label> descendiente: a diferencia del checkbox de RGPD (ver más
   abajo), que sí envuelve su opción en un <label> real, las opciones
   de [radio] de CF7 no llevan <label> propio en este formulario (solo
   el <input> y un <span class="wpcf7-list-item-label"> sueltos como
   hermanos) — la regla anterior, que apuntaba a "label", nunca
   encontraba nada que colorear y las píldoras se quedaban sin marco
   propio, dejando visible solo el marco (accidental) del grupo entero
   completo (ver la exclusión en .wpcf7-form-control más arriba). Sin
   <label>, el <input> es lo único clicable de forma nativa — con la
   píldora entera ya con aspecto de botón (cursor:pointer aquí abajo),
   el bloque dedicado al final de animations.js reenvía el click de
   cualquier punto de la píldora al campo real. */
.contact-form .wpcf7-list-item {
  /* Berenjena explícito: esta píldora tiene fondo blanco propio, así
     que no debe heredar el blanco de la sección (data-bg-zone). */
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
  padding: 0.6em 1.1em;
  font-weight: 400;
  color: var(--color-berenjena);
  background-color: #fff;
  border: 2px solid var(--color-niebla);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.contact-form .wpcf7-list-item:hover {
  border-color: var(--color-lavanda);
}

.contact-form .wpcf7-list-item:has(input:checked) {
  /* Berenjena, no melocotón, de borde: melocotón falla el contraste
     mínimo de 3:1 sobre el fondo blanco de la píldora (2.2:1) como
     indicador de selección.
     Pistacho, no melocotón, de fondo: melocotón es también el color
     del aviso de error (ver .wpcf7-not-valid-tip y
     [aria-invalid="true"] más abajo) — con el mismo tono aquí, una
     opción ya elegida correctamente se leía como si tuviera algo mal.
     Pistacho aclarado queda inequívoco como "correcto/seleccionado",
     sin pisar el significado de "error" del melocotón. */
  border-color: var(--color-berenjena);
  background-color: color-mix(in srgb, var(--color-pistacho) 15%, #fff);
}

.contact-form .wpcf7-list-item:has(input:focus-visible) {
  /* Engorda el marco de LA PÍLDORA en vez de sumar un contorno nuevo
     de foco a su alrededor (mismo criterio que .wpcf7-form-control:focus-visible
     más arriba) — el contorno de foco de tamaño normal que ya recibe
     el propio <input> (regla global de foco visible, ver arriba del
     todo del archivo) se queda tal cual, alrededor del círculo/casilla
     nada más, no de la píldora entera. */
  border-color: var(--color-berenjena);
  border-width: 3px;
}

.contact-form .wpcf7-list-item input {
  margin: 0;
  accent-color: var(--color-berenjena);
  cursor: pointer;
}

/* Consentimiento RGPD: es un .wpcf7-list-item más por dentro (mismo
   marco que las píldoras de radio de arriba), pero un párrafo largo
   de texto legal no lee bien estirado en forma de píldora — esta
   regla, más específica, sustituye ese aspecto por una tarjeta
   rectangular normal, mejor proporcionada para varias líneas. Aquí SÍ
   hay un <label> real por dentro (CF7 sí lo genera para [acceptance]),
   pero solo para alinear el checkbox con el texto (ver
   .wpcf7-acceptance label debajo) — el marco de la tarjeta sigue
   yendo en .wpcf7-list-item, igual que el radio, para no duplicarlo. */
.contact-form .wpcf7-acceptance {
  display: block;
}

.contact-form .wpcf7-acceptance label {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-weight: 400;
}

.contact-form .wpcf7-acceptance .wpcf7-list-item {
  border-radius: 0.85rem;
  padding: 1em 1.25em;
}

.contact-form .wpcf7-acceptance input {
  margin-top: 0.25em;
  accent-color: var(--color-berenjena);
}

/* Al enviar sin marcar la casilla, se resalta igual que un campo de
   texto inválido: fondo/borde melocotón. */
.contact-form .wpcf7-acceptance:has(input[aria-invalid="true"]) .wpcf7-list-item {
  border-color: var(--color-melocoton);
  background-color: color-mix(in srgb, var(--color-melocoton) 18%, #fff);
  animation: destello-contacto 2.4s ease-in-out infinite;
}

/* Nota de cierre antes de enviar */
.contact-form__note {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). Esta clase se usa dentro
     del propio formulario de Contact Form 7 (contenido de wp-admin). */
  font-family: var(--font-titulos);
  font-weight: 500;
  font-style: italic;
  font-size: 1.05rem;
  color: var(--color-berenjena);
  border-left: 4px solid var(--color-pistacho);
  padding-left: 1.1em;
  margin: 1.75rem 0;
}

/* Blog: listado. La sección entera (no solo el texto) se queda más
   estrecha que el ancho completo de --content-max-width (1152px) — a
   petición expresa, para que el listado no quede tan ancho como antes
   y se acerque más a una columna de lectura, en línea con el resto de
   páginas de texto largo (Servicios/Qué tratamos). "body.blog", no
   "body.bg-tint-melocoton": ese tinte también lo llevan las 15 páginas
   hija de Qué tratamos (ver header.php), que no deben estrecharse
   igual — "blog" es la clase que WordPress añade solo a esta
   plantilla (home.php), sea cual sea la página elegida como "página
   de entradas" en Ajustes > Lectura.
   Ensanchado de 48rem a 64rem a petición expresa, para que quepan 3
   columnas de tarjetas en vez de 2 (ver .blog-grid más abajo): 64rem
   sigue dejando sitio de sobra para 3 columnas sin llegar a caber una
   4ª. */
body.blog .section__inner {
  max-width: 64rem;
}

/* gap subido de 4.5rem a 5.5rem a petición expresa ("un poco más de
   separación entre las entradas") — separa tanto filas como columnas,
   ver el porqué del valor base más arriba.
   Nº de columnas por breakpoint explícito (no auto-fit/minmax): con
   auto-fit, subir el gap a 5.5rem ya no dejaba sitio para 3 columnas
   dentro de los 64rem de .section__inner de arriba (3×18rem + 2×5.5rem
   = 65rem, más que el propio contenedor) y el grid caía solo a 2 en
   escritorio — bug real, reportado. Con columnas fijas por
   media query en su lugar, cada columna se reparte el ancho disponible
   a partes iguales (1fr) en vez de depender de un mínimo fijo de
   18rem, así el nº de columnas por tamaño de pantalla queda explícito
   y ya no depende de si el gap del momento deja sitio o no.
   Mismos breakpoints que el resto del sitio (ver
   @media (min-width:40.0625rem)/(min-width:64.0625rem) más abajo en
   esta misma hoja): 1 columna en móvil, 2 en tablet, 3 en portátil/
   monitor — a petición expresa. */
.blog-grid {
  list-style: none;
  display: grid;
  gap: 5.5rem;
  grid-template-columns: 1fr;
  margin: 0 0 2.5rem;
  padding: 0;
}

@media (min-width: 40.0625rem) {
  .blog-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 64.0625rem) {
  .blog-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Ancla para .blog-card__more (más abajo): esquina inferior derecha
   de CADA entrada completa, alineada con el resto de la fila — a
   petición expresa, "que se vean todos alineados entre sí" en vez de
   pegado al final del resumen de cada una (que varía de largo entrada
   a entrada). .blog-card__link ya estira a height:100% la fila del
   grid (ver debajo), así esta esquina cae siempre a la misma altura
   real para todas las tarjetas de una fila, sea cual sea su resumen. */
.blog-card {
  position: relative;
}

.blog-card__link {
  display: block;
  color: inherit;
  text-decoration: none;
  height: 100%;
}

.blog-card__thumbnail {
  /* Sin tarjeta: solo la portada lleva esquinas redondeadas; el texto
     queda suelto debajo, sobre el fondo de la página. */
  display: block;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: 1rem;
}

.blog-card__thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.blog-card__link:hover .blog-card__thumbnail img,
.blog-card__link:focus-visible .blog-card__thumbnail img {
  transform: scale(1.04);
}

.blog-card__body {
  display: block;
  /* padding-bottom (antes 0): reserva el hueco donde cae
     .blog-card__more (esquina inferior derecha de la tarjeta, ver ahí
     abajo) — sin él, el resumen de la entrada más larga de la fila
     podría llegar hasta esa misma esquina y solaparse con el texto. */
  padding: 1.25rem 0 1.75rem;
}

.blog-card__date {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo como
     texto sobre esta tarjeta blanca. */
  display: block;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-berenjena);
  margin-bottom: 0.5rem;
}

.blog-card__title {
  font-size: 1.6rem;
  margin: 0 0 0.5rem;
}

.blog-card__excerpt {
  display: block;
  color: var(--color-lavanda);
}

/* .blog-card__more — "Leer más +" en la esquina inferior derecha de
   cada entrada, a petición expresa ("alineados entre sí, como la
   esquina de la caja contenedora de la ficha"): position:absolute
   anclado a .blog-card (más arriba), no en flujo normal debajo del
   resumen — así cae siempre a la misma altura en toda la fila, sea
   cual sea el largo de cada resumen (ver .blog-card__body de arriba
   para el hueco reservado que evita que el resumen más largo llegue a
   solaparse con esta esquina). Sin fondo (texto suelto, mismo criterio
   que .team-profile__more-btn en Conócenos), en berenjena — mismo
   color que .blog-card__date/.single-post__date sobre este fondo
   claro, ya probado que pasa AA. */
.blog-card__more {
  position: absolute;
  right: 0;
  bottom: 0;
  color: var(--color-berenjena);
  font-family: var(--font-texto);
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(0.4rem);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.blog-card__link:hover .blog-card__more,
.blog-card__link:focus-visible .blog-card__more {
  opacity: 1;
  transform: translateY(0);
}

/* Sin hover real en móvil/tablet (mismo breakpoint que el menú
   hamburguesa, @media max-width:64rem) — a petición expresa, "Leer
   más +" se queda siempre visible ahí en vez de depender de un hover
   que en esos dispositivos no existe. */
@media (max-width: 64rem) {
  .blog-card__more {
    opacity: 1;
    transform: none;
  }
}

.blog-pagination nav {
  display: flex;
  justify-content: center;
  gap: 1rem;
}

/* Blog: entrada individual. Color/peso/decoración/hover: ver el
   enlace berenjena discreto compartido, junto a .back-link. */
.single-post__back {
  display: inline-block;
  margin-bottom: 1rem;
}

.single-post__date {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo como
     texto sobre este fondo claro. */
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-berenjena);
}

.single-post__cover {
  max-width: var(--content-max-width);
  margin: 2rem auto 0;
  padding-inline: var(--section-padding-inline);
}

.single-post__cover img {
  width: 100%;
  border-radius: 1rem;
  max-height: 32rem;
  object-fit: cover;
}

.single-post__gallery {
  /* Misma columna de 65ch que .entry-content: la galería cierra el
     artículo, no debe volver al ancho completo de .section__inner. */
  max-width: 65ch;
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 1rem;
}

.single-post__gallery img {
  width: 100%;
  height: 100%;
  border-radius: 0.75rem;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.single-post__nav-inner {
  /* Misma columna de 65ch que el resto de la entrada (ver
     body.single-post .page-header__inner/.entry-content) — sin esto,
     hereda el ancho completo de .section__inner (1152px). */
  max-width: 65ch;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1.5rem;
  font-weight: 600;
}

.single-post__nav a {
  text-decoration: none;
}

.single-post__nav a:hover,
.single-post__nav a:focus-visible {
  opacity: 0.72;
}

/* Tipografía del contenido de Gutenberg (entry-content) */
.entry-content {
  /* 65ch, no rem fijo — mismo motivo que .policy-content/.condition-content:
     a 1.1rem, 42rem ya rozaba los 75 caracteres por línea recomendados
     como máximo para texto largo; "ch" mantiene la medida de lectura
     correcta pase lo que pase con el tamaño de letra. */
  max-width: 65ch;
  margin-inline: auto;
  font-size: 1.1rem;
}

.entry-content > * {
  margin-top: 0;
  /* 2em, no 1.5em: ~2 líneas de aire entre párrafos/bloques. */
  margin-bottom: 2em;
}

.entry-content h2 {
  font-size: 1.75rem;
  margin-top: 1.5em;
}

.entry-content h3 {
  font-size: 1.35rem;
  margin-top: 1.5em;
}

.entry-content a {
  /* Berenjena, no melocotón: melocotón falla el contraste mínimo como
     texto sobre este fondo claro. Negrita en vez de subrayado. */
  color: var(--color-berenjena);
  font-weight: 600;
  text-decoration: none;
}

.entry-content a:hover,
.entry-content a:focus-visible {
  opacity: 0.72;
}

.entry-content blockquote {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  margin: 2em 0;
  padding-left: 1.5em;
  border-left: 4px solid var(--color-pistacho);
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: 1.3rem;
  font-style: italic;
  color: var(--color-berenjena);
}

.entry-content img {
  border-radius: 0.75rem;
}

.entry-content figcaption {
  /* Berenjena, no lavanda: lavanda como texto falla el contraste
     mínimo sobre el fondo niebla (4.19:1). */
  font-size: 0.9rem;
  color: var(--color-berenjena);
  text-align: center;
  margin-top: 0.5em;
}

.entry-content ul,
.entry-content ol {
  padding-left: 1.5em;
}

.entry-content li {
  margin-bottom: 0.5em;
}

/* Puntitos/números de las listas en oliva, a petición expresa, como
   pequeño toque de color de marca — ::marker cambia solo el
   punto/número, no el color del texto de la propia línea (que sigue
   en berenjena, heredado de .entry-content). */
.entry-content li::marker {
  color: var(--color-oliva);
}

/* Dos hojas animadas de fondo en cada entrada del blog (hoja2 — "la
   otra hoja", no la de Qué tratamos —, ver hoja2-animada-simple.js/
   single.php), a distintas alturas de la página — mismo criterio que
   .que-tratamos-item-hoja-fondo más arriba (misma familia de fondo
   claro melocotón, ver body.bg-tint-melocoton en header.php: lavanda,
   no niebla-clara, para que se lea bien sobre este fondo claro).
   top/bottom en % (no rem) sobre #main: así la segunda hoja se coloca
   proporcionalmente más abajo sea cual sea la longitud real de cada
   entrada, en vez de un valor fijo que en una entrada corta caería
   fuera de la página. */
/* --hoja-escala (0.85-1.3, ver single.php): tamaños variados entre
   las hojas de una misma entrada, a petición expresa ("que se note la
   variedad pero sin ninguna demasiado pequeñita") — multiplica el
   ancho base en vez de sustituirlo, así el clamp() de ese ancho base
   (mín/máx según viewport) se sigue respetando en cualquier
   pantalla. */
.entry-hoja-fondo {
  position: absolute;
  width: calc(clamp(12rem, 16vw, 18rem) * var(--hoja-escala, 1));
  opacity: 0.3;
  pointer-events: none;
  z-index: 0;
}

.entry-hoja-fondo svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.entry-hoja-fondo .hoja2-animada-simple__path {
  fill: var(--color-melocoton);
}

/* "top" va inline por PHP (ver single.php): calculado según el número
   de hojas de cada entrada, no fijo aquí. Solo el lado (izquierda/
   derecha, alternado) va por CSS. 4rem, no 1.5rem — a petición
   expresa, "más hacia dentro, que no estén tan al borde". */
.entry-hoja-fondo--izquierda {
  left: 4rem;
  transform: translateX(calc((var(--hoja-t, 1) - 1) * 2rem));
}

.entry-hoja-fondo--derecha {
  right: 4rem;
  transform: scaleX(-1) translateX(calc((var(--hoja-t, 1) - 1) * 2rem));
}

@media (max-width: 1100px) {
  .entry-hoja-fondo {
    display: none;
  }
}

/* Página de error 404. Sin tinte propio (ver 404.php/header.php):
   fondo niebla por defecto, igual que Política de cancelación — una
   página de utilidad, no una de las páginas principales de la marca.
   min-height + flex centra el bloque verticalmente en vez de quedar
   pegado arriba, para que no se sienta corto/desangelado en pantallas
   grandes con tan poco contenido. */
.section--404 {
  min-height: 70vh;
  display: flex;
  align-items: center;
}

.error-404 {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
}

/* Contenedor del "montoncito" de 3 ilustraciones (ver 404.php) — mide
   lo que ocupa el cluster entero, cada .error-404__shape de dentro se
   posiciona contra ESTE borde (position:relative), no contra el de
   .error-404. */
.error-404__illustration {
  position: relative;
  width: 11rem;
  height: 8rem;
  margin: 0 auto 1.25rem;
}

.error-404__shape {
  position: absolute;
  display: block;
  /* Pequeño gesto al pasar el cursor por encima de todo el cluster
     (ver .error-404__illustration:hover más abajo) — la misma idea de
     "reaccionar al cursor" que el resto de la web (ver CLAUDE.md), aquí
     en CSS puro por ser un gesto tan pequeño. */
  transition: rotate 0.4s ease;
}

.error-404__shape svg {
  width: 100%;
  height: auto;
  display: block;
}

/* Cada forma con su propio tamaño/giro/posición, a ojo, para que el
   montón se lea como caído de cualquier manera — no una rejilla
   ordenada. La hoja va encima (z-index más alto) por ser la más
   reconocible de las 3, "coronando" el montón. */
.error-404__shape--espiral {
  width: 4.5rem;
  top: 0.5rem;
  left: 0;
  rotate: -18deg;
  z-index: 1;
}

.error-404__shape--nudo {
  width: 4rem;
  top: 1.5rem;
  right: 0;
  rotate: 22deg;
  z-index: 1;
}

.error-404__shape--hoja {
  width: 5.5rem;
  top: 0;
  left: 50%;
  translate: -50% 0;
  rotate: -10deg;
  z-index: 2;
}

/* Al pasar el cursor, cada forma gira un poco más hacia su lado, como
   si el montón se hubiese movido un poco. */
.error-404__illustration:hover .error-404__shape--espiral {
  rotate: -30deg;
}

.error-404__illustration:hover .error-404__shape--nudo {
  rotate: 34deg;
}

.error-404__illustration:hover .error-404__shape--hoja {
  rotate: -18deg;
}

@media (prefers-reduced-motion: reduce) {
  .error-404__shape {
    transition: none;
  }
}

.error-404__code {
  font-family: var(--font-titulos);
  font-weight: 500;
  font-size: clamp(3rem, 8vw, 4.5rem);
  letter-spacing: 0.02em;
  color: var(--color-oliva);
  margin: 0 0 0.15em;
}

.error-404 h1 {
  margin-bottom: 0.75em;
}

.error-404__intro {
  /* Berenjena, no lavanda: lavanda sobre niebla da 4.19:1, por debajo
     del mínimo AA (4.5:1) para texto normal — el mismo motivo que
     .page-header__intro más arriba, misma página sin tinte. */
  color: var(--color-berenjena);
  margin: 0 0 2.5rem;
}

.error-404__cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  /* Sin margen inferior: era el hueco antes del bloque de enlaces
     "también puede interesarte", ya quitado — ahora es el último
     elemento, no le hace falta separación de nada. */
  margin-bottom: 0;
}

