/* ==========================================================================
   Dr. Eduardo Álvarez Lozano — Sistema de diseño para landing pages
   Ortopedia y Traumatología · Monterrey, N.L.

   Dirección: cálida y cercana. Crema y arena, verde salvia, tinta cálida.
   Pensada para un paciente de 50+ con dolor crónico y miedo a operarse:
   cuerpo grande, interlineado amplio, cero alto contraste agresivo.
   ========================================================================== */

:root {
  /* ---- Superficies ---- */
  /* El fondo pasa de crema a blanco. Los otros dos tonos de superficie bajan
     con él, si no el sitio queda a medias: sobre blanco, un crema que antes
     era casi imperceptible se convierte en una franja amarillenta evidente.
     --cream-deep se queda neutro, no cálido, para que la alternancia de
     secciones siga leyéndose sin volver a introducir el crema por la puerta
     de atrás.

     --paper sube a blanco puro por un motivo concreto: valía #FFFDFA, más
     claro que el fondo de antes, y sobre blanco habría quedado más OSCURO que
     la página. Una tarjeta más sucia que su fondo se ve sin saber por qué.
     Ahora empatan y quien define la tarjeta es su sombra, que es lo que ya
     hacía el trabajo.

     --sand era el crema fuerte: la franja de credenciales bajo el hero, el
     recuadro de la letra pequeña y el plato de los sellos. Es el tono que más
     se notaba al dejarlo cálido, porque va en bloques grandes. Pasa a gris,
     pero un escalón por DEBAJO de --cream-deep: el disclaimer vive dentro de
     una sección --cream-deep y si empatan desaparece el recuadro. */
  --cream: #FFFFFF;
  --cream-deep: #F4F4F5;
  --sand: #EDEDF0;
  --sand-line: #E4E4E6;
  --paper: #FFFFFF;

  /* ---- Tinta (nunca negro puro) ---- */
  --ink: #2B2723;
  --ink-soft: #57504A;
  --ink-muted: #877E74;

  /* ---- Acento primario: verde salvia ---- */
  --sage: #4A6B52;          /* blanco encima = 5.8:1 ✓ */
  --sage-deep: #3A5541;
  --sage-mid: #6B8F71;      /* decorativo */
  --sage-pale: #E6EDE5;

  /* ---- Acento secundario: barro ---- */
  --clay: #9C5433;          /* blanco encima = 6.5:1 ✓ */
  --clay-pale: #F5E7DE;

  /* ---- Marca (del logotipo) ---- */
  --navy: #1B3A57;

  /* ---- Tipografía ---- */
  --font-head: 'Satoshi', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-body: 'Satoshi', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* ---- Marca oscura para la píldora de navegación y el hero ---- */
  --pill: #14273A;

  /* ---- Layout ---- */
  --wrap: 1140px;
  --wrap-narrow: 780px;
  --r-lg: 26px;
  --r-md: 18px;
  --r-sm: 12px;
  --shadow-soft: 0 2px 6px rgba(43, 39, 35, .03), 0 14px 40px rgba(43, 39, 35, .06);
  --shadow-lift: 0 3px 10px rgba(43, 39, 35, .05), 0 22px 60px rgba(43, 39, 35, .09);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 18.5px;
  font-weight: 300;
  line-height: 1.75;
  letter-spacing: .004em;
  color: var(--ink-soft);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Grano de papel: da textura cálida en vez de plano digital */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}
body > * { position: relative; z-index: 2; }

img, video { max-width: 100%; display: block; }
/* Las que sí recortan (hero, consultorio) declaran su propio object-fit. */
.split__media img, .card img, .quote img { height: auto; }
a { color: var(--sage-deep); text-decoration: none; }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.16;
  letter-spacing: -.022em;
  margin: 0 0 .55em;
  /* Evita el desbordamiento en pantallas angostas sin partir palabras con guion */
  overflow-wrap: break-word;
  hyphens: manual;
  text-wrap: pretty;
}
h1 { font-size: clamp(2.15rem, 5vw, 3.6rem); line-height: 1.11; letter-spacing: -.02em; }
h2 { font-size: clamp(1.75rem, 3.4vw, 2.65rem); }
h3 { font-size: clamp(1.22rem, 1.9vw, 1.5rem); line-height: 1.28; }

p { margin: 0 0 1.15em; }
ul { margin: 0 0 1.15em; padding-left: 1.2em; }
li { margin-bottom: .55em; }
strong { color: var(--ink); font-weight: 500; }
em { font-style: italic; }

/* ---------- Utilidades ---------- */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: 24px; }
.wrap-narrow { max-width: var(--wrap-narrow); }
/* El fondo es obligatorio, no decorativo: el hero queda sticky por debajo y
   una sección transparente lo dejaría verse a través. Coincide con el fondo
   del body, así que no cambia nada a la vista. Los modificadores de más
   abajo (--surface, --sand, --deep) lo sobrescriben. */
.section { padding: clamp(64px, 9vw, 120px) 0; background: var(--cream); }
.section--surface { background: var(--cream-deep); }
.section--sand { background: var(--sand); }
.center { text-align: center; }

.section--deep {
  background: var(--sage-deep);
  color: #D5E0D6;
}
.section--deep h2, .section--deep h3 { color: #FDFBF7; }

.eyebrow {
  font-family: var(--font-body);
  font-size: .8rem;
  font-weight: 500;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--clay);
  margin: 0 0 1rem;
}
.section--deep .eyebrow { color: #B9CDBB; }

.lead { font-size: 1.16rem; line-height: 1.72; color: var(--ink-soft); }
.section--deep .lead { color: #C6D4C8; }

.section-head { max-width: 680px; margin-bottom: clamp(40px, 5.5vw, 64px); }
.section-head.center { margin-inline: auto; }

/* ---------- Botones ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55em;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.3;
  padding: 1.02em 1.75em;
  border: 1.5px solid transparent;
  border-radius: 100px;
  cursor: pointer;
  text-align: center;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease, transform .2s ease;
}
.btn:hover { transform: translateY(-1px); }

/* Primario: salvia. Es el único botón con relleno fuerte. */
.btn--primary { background: var(--sage); color: #FDFBF7; }
.btn--primary:hover { background: var(--sage-deep); }

/* WhatsApp: secundario y discreto, no compite con la marca */
.btn--wa { background: var(--paper); color: var(--sage-deep); border-color: var(--sand-line); }
.btn--wa:hover { border-color: var(--sage); background: var(--sage-pale); }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--sand-line); }
.btn--ghost:hover { border-color: var(--ink-muted); background: var(--paper); }

.btn--light { background: #fff; color: var(--pill); }
.btn--light:hover { background: #fff; }
.btn--outline-light { background: transparent; color: #EAF0EA; border-color: rgba(255,255,255,.34); }
.btn--outline-light:hover { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.6); }

.btn-row { display: flex; flex-wrap: wrap; gap: 14px; }
.btn-note { font-size: .93rem; color: var(--ink-muted); margin: 1.15rem 0 0; line-height: 1.6; }
/* Sobre el verde oscuro, la nota heredaba --ink-muted (#877E74), un gris
   cálido pensado para fondo crema: daba 2,06:1, muy por debajo del 4,5:1 de
   AA. El .cta-final no es .section--deep, así que la regla de al lado nunca
   llegaba a aplicarse allí. Ahora se cubren las dos, con un tono que da 6,05:1. */
.section--deep .btn-note,
.cta-final .btn-note { color: #D5E0D6; }

/* El precio tachado es información, no adorno: tiene que leerse. Con opacidad
   .6 se quedaba en 1,56:1; con .82 sube a 4,7:1. Y la línea del tachado pasa a
   un barro aclarado, porque el --clay original daba 1,46:1 sobre este verde. */
.section--deep .btn-note .precio-antes,
.cta-final .btn-note .precio-antes {
  opacity: .82;
  text-decoration-color: #D3A98C;
}

/* ---------- Píldora de navegación flotante ---------- */
.navpill { position: sticky; top: 16px; z-index: 60; padding-top: 16px; }
.navpill__inner {
  background: var(--pill);
  border-radius: 44px;
  min-height: 66px;
  display: flex; align-items: center; gap: 22px;
  padding: 9px 9px 9px 26px;
  box-shadow: 0 8px 30px rgba(20, 39, 58, .18);
}
.navpill__logo img { height: 34px; width: auto; display: block; filter: brightness(0) invert(1); }
.navpill__links { display: flex; gap: 26px; margin-left: 12px; }
.navpill__links a { color: rgba(255,255,255,.82); font-size: .97rem; font-weight: 400; }
.navpill__links a:hover { color: #fff; }
.navpill__spacer { flex: 1; }
.navpill__phone { color: rgba(255,255,255,.82); font-size: .95rem; white-space: nowrap; }
.navpill .btn { padding: .72em 1.5em; font-size: .95rem; }
@media (max-width: 1000px) { .navpill__links { display: none; } }
@media (max-width: 720px)  { .navpill__phone { display: none; } }
@media (max-width: 460px)  { .navpill__inner { padding-left: 18px; } .navpill__logo img { height: 28px; } }
/* En móvil la píldora va justa: el botón del header se acorta a "Agendar".
   Solo afecta al header; el CTA del hero mantiene el texto completo. */
@media (max-width: 640px)  { .navpill .btn .solo-ancho { display: none; } }

/* ---------- Hero a sangre ---------- */
.hero {
  /* El hero se queda anclado arriba y las secciones siguientes suben por
     encima de él. No se desactiva con prefers-reduced-motion: sticky es
     maquetación, el scroll sigue siendo 1:1 y no hay efecto de paralaje.
     No hace falta tocar z-index: todas las hermanas comparten el z-index 2 de
     `body > *`, y al ir después en el DOM se pintan encima. */
  position: sticky;
  top: 0;
  /* Pantalla completa. svh usa el alto visible real del móvil (sin contar la
     barra del navegador cuando está desplegada), así el hero no queda cortado.
     La regla vh de arriba es el respaldo para navegadores sin svh. */
  min-height: 100vh;
  min-height: 100svh;
  margin-top: -82px;          /* la píldora flota encima de la foto */
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--pill);
}
.hero__bg { position: absolute; inset: 0; }
.hero__bg img {
  /* Se ensancha la imagen (sin desplazarla) para que la figura caiga a la
     derecha y la columna del titular quede libre. Con margin-left quedaba
     una franja vacía en el borde izquierdo.

     --hero-zoom gobierna el tamaño del doctor: al ser object-fit:cover, la
     escala la marca el ancho. Subirlo acerca, bajarlo aleja. 1.18 era el
     valor original; 1.09 lo deja levemente más pequeño. */
  --hero-zoom: 1.09;
  width: calc(var(--hero-zoom) * 100%);
  height: 100%;
  object-fit: cover;
  object-position: 50% 28%;
}

/* Velo doble: uno inferior para anclar el texto, otro lateral para el titular */
.hero__scrim { position: absolute; inset: 0; background: linear-gradient(rgba(0,0,0,.06) 0%, rgba(0,0,0,.42) 78%, rgba(0,0,0,.64) 100%); }
.hero__scrim::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(96deg, rgba(0,0,0,.66) 0%, rgba(0,0,0,.44) 26%, rgba(0,0,0,.12) 52%, transparent 68%);
}

.hero__content { position: relative; z-index: 3; width: 100%; padding: 120px 0 clamp(42px, 5.5vw, 76px); }
.hero__grid { display: grid; grid-template-columns: 1.34fr .66fr; gap: clamp(28px, 4vw, 60px); align-items: end; }

/* El H1 de verdad de la página.
   El titular grande del hero es un gancho emocional: «Recupera la rodilla que
   el dolor te quitó» no dice el procedimiento ni la ciudad, que es justo lo
   que un H1 tiene que decirle a un buscador. En vez de estropear el titular,
   el H1 va aquí, como línea de contexto entre las etiquetas y el titular, y
   ese titular pasa a H2 sin tocar ni una letra ni un píxel de su aspecto.
   Va debajo de las etiquetas y no encima para que caiga por debajo de la
   cara del doctor: el bloque está alineado abajo, así que intercambiarlos no
   cambia el alto total, sólo baja la línea unos 40px.

   Va VISIBLE a propósito. Un H1 metido en un .sr-only sólo para el buscador es
   texto oculto, y ahí Google distingue mal entre accesibilidad y relleno de
   palabras clave. Visible cuesta dos renglones y no tiene ese riesgo. */
.hero__h1 {
  color: rgba(255, 255, 255, .78);
  font-family: var(--font-body);
  font-size: .92rem;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0;
  margin: 0 0 13px;
  /* Sin tope de ancho: cabe en un renglón. Medido con el texto real de las
     cinco páginas, el más largo (condrograft, 90 caracteres) ocupa 592px y la
     columna del hero da 697px. El 46ch que había antes lo partía en dos sin
     necesidad. Por debajo de ~700px de ventana ya no cabe en una línea a un
     tamaño legible —harían falta 9px— así que ahí se parte, y se parte
     equilibrado. */
  max-width: 100%;
  text-wrap: balance;
  text-shadow: 0 1px 14px rgba(0, 0, 0, .4);
}

/* Franja incómoda: a partir de 901px el hero se parte en dos columnas y el H1
   pasa de tener la ventana entera a tener sólo la columna izquierda, que ahí
   todavía es más angosta que el texto. Medido: a 901px la columna da ~542px y
   el H1 más largo (condrograft) necesita 592px; a 1024px ya da 616px y cabe.
   Un punto menos de tamaño en esa banda mantiene el renglón único. */
@media (min-width: 901px) and (max-width: 1010px) {
  .hero__h1 { font-size: .82rem; }
}

/* El titular del hero. Es un H2 desde que el H1 pasó a ser la línea de
   contexto de arriba; el aspecto no cambió, sólo la etiqueta. Se apunta por
   .hero__headline h2 y no por .hero h2 para no alcanzar los H2 de las demás
   secciones, que sí llevan el tamaño normal. */
.hero__headline h2 {
  color: #fff;
  font-size: clamp(2.3rem, 5.2vw, 4.25rem);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -.024em;
  margin: 0;
  max-width: 15ch;
  text-shadow: 0 2px 30px rgba(0,0,0,.34);
}
.hero__headline h2 em { font-style: normal; color: rgba(255,255,255,.62); }

.hero__aside p { color: rgba(255,255,255,.9); font-size: 1.02rem; line-height: 1.66; margin: 0 0 1.5rem; text-shadow: 0 1px 16px rgba(0,0,0,.35); }
.hero__aside .btn-note { color: rgba(255,255,255,.66); margin-top: 1rem; font-size: .88rem; }

@media (max-width: 900px) {
  .hero { min-height: 100vh; min-height: 100svh; }
  .hero__bg img { width: 100%; margin-left: 0; object-position: 52% 20%; }
  .hero__grid { grid-template-columns: 1fr; gap: 30px; align-items: start; }
  .hero__headline h2 { max-width: 100%; }
  /* El velo se aligera donde no hay texto y se mantiene donde sí lo hay. No es
     una reducción uniforme a propósito: el titular cae justo sobre el ventanal
     del fondo, que es la zona más clara de la foto, y ahí bajar el velo se
     lleva por delante el contraste. Medido sobre los píxeles reales de la
     imagen, en el peor de todos ellos: titular 3,46:1 (AA de texto grande pide
     3), párrafo 5,40:1 y píldora de reseñas 5,07:1 (AA pide 4,5).

     Arriba (donde está la cara) y abajo se aligera mucho: .30 → .10 el velo
     superior y .74 → .56 el pie. En el centro casi no se toca: .50 → .48. */
  .hero__scrim { background: linear-gradient(rgba(0,0,0,.06) 0%, rgba(0,0,0,.48) 52%, rgba(0,0,0,.56) 100%); }
  .hero__scrim::after { background: linear-gradient(rgba(0,0,0,.10) 0%, transparent 45%); }
}

/* ---------- El hero en teléfono ----------
   El hero mide la pantalla MENOS la barra fija de WhatsApp y Llamar. Así el
   hero entra entero de una vez y la barra queda debajo, no encima: antes se
   montaba sobre él y se comía la última línea del párrafo.

   --cta-movil es el alto de esa barra. Va como variable porque lo usan las dos
   reglas y tienen que moverse juntas; si algún día cambia el tamaño del botón,
   se toca aquí y basta.

   El bloque de texto está anclado abajo, así que para bajarlo sólo cabe que
   ocupe menos: cada píxel recortado es un píxel más de retrato visible. De ahí
   que se quite el botón —la píldora superior es `sticky` y lleva el mismo CTA
   a la vista todo el rato, así que no se pierde ninguna llamada a la acción— y
   que se aprieten los espacios intermedios. */
@media (max-width: 700px) {
  :root { --cta-movil: 76px; }
  .hero {
    min-height: calc(100vh - var(--cta-movil));
    min-height: calc(100svh - var(--cta-movil));
  }
  /* Sin botón en el hero: el CTA queda en la píldora superior, que es `sticky`
     y no se va nunca, y en la barra inferior.

     Ojo en las páginas de procedimiento: la barra inferior de esas cuatro es
     WhatsApp y Llamar, así que al quitar este botón el formulario se queda sin
     ningún acceso fijo sobre la línea de flotación en móvil. Está decidido así
     a propósito; si algún día se quiere recuperar, lo natural es cambiar el
     botón verde de `.mobile-cta` por uno con data-modal="lead". */
  .hero__aside .btn { display: none; }
  /* El botón está oculto justo encima, así que el párrafo es el último
     elemento que se ve y su margen inferior era espacio muerto: 24px que en
     un teléfono corto salen de la última línea del propio párrafo.
     Antes esto decía p:last-child y no llegaba a aplicarse nunca: :last-child
     mira el DOM, no lo que se ve, y el último hijo del aside sigue siendo el
     botón aunque esté en display:none. */
  .hero__aside p { margin-bottom: 0; }
  .hero__grid { gap: 20px; }
  .hero__content { padding-bottom: 28px; }
}

/* ---------- Teléfonos de pantalla corta ----------
   La foto llena el alto exacto del hero: no sobra ni un píxel por arriba ni
   por abajo, así que el recorte es proporcional y la cara del doctor cae
   siempre en el mismo PORCENTAJE del hero, mida lo que mida. El bloque de
   texto, en cambio, mide 400px fijos y va anclado abajo.

   De ahí el problema: en un hero de 820px el texto arranca al 51% del alto,
   por debajo de la cara; en uno de 624px —un iPhone con las barras de Safari
   desplegadas— arranca al 31%, justo encima de ella. La foto no cambia; lo que
   cambia es cuánto se come el texto.

   La solución es apretar el bloque cuando el hero es corto, no tocar la foto:
   así el texto vuelve a arrancar cerca del 38% y la composición se parece a la
   de una pantalla alta. Nada se elimina, sólo encoge.

   Los dos escalones no son arbitrarios. Medido sobre los píxeles de la propia
   foto: la cabeza empieza al 15,8% del alto, la barbilla ronda el 36% y el
   cuello del uniforme está al 48,7%. Para que el texto no se le monte a la
   cara tiene que arrancar por debajo del 38%, es decir, el bloque más su
   margen inferior no pueden pasar del 62% del alto del hero. Con los valores
   de siempre eso sólo se cumple a partir de un hero de 780px. */
@media (max-width: 700px) and (max-height: 800px) {
  .hero__headline h2 { font-size: 2.05rem; }
  .hero__h1 { font-size: .85rem; line-height: 1.34; margin-bottom: 9px; }
  .hero__aside p { line-height: 1.55; }
  .hero__headline { gap: 12px; }
  .hero__grid { gap: 14px; }
  .hero__reviews { margin-top: 14px; }
  .hero__content { padding-bottom: 20px; }
}
/* Segundo escalón para los teléfonos pequeños con las barras del navegador
   desplegadas, donde el hero se queda por debajo de 600px. */
@media (max-width: 700px) and (max-height: 700px) {
  .hero__headline h2 { font-size: 1.82rem; }
  .hero__h1 { font-size: .8rem; line-height: 1.3; margin-bottom: 7px; }
  .hero__headline { gap: 9px; }
  .hero__grid { gap: 10px; }
  .hero__reviews { margin-top: 10px; }
  .hero__aside p { font-size: .92rem; line-height: 1.45; }
  .hero__content { padding-bottom: 10px; }
  .play-cta__disc { width: 46px; height: 46px; }
}

/* ---------- Franja de confianza ---------- */
.trustbar {
  background: var(--sand);
  /* Sombra hacia arriba: da el relieve de la sección montándose sobre el hero */
  box-shadow: 0 -18px 46px rgba(20, 39, 58, .22);
}
.trustbar__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 34px 28px;
  padding: clamp(38px, 5vw, 56px) 0;
}
.trustbar__item { text-align: center; }
.trustbar__item b {
  /* Rejilla centrada y con alto fijo: en esta franja conviven cifras y sellos,
     y sin una caja común cada columna empujaría su descripción a una altura
     distinta. 1,3em de la propia tipografía deja sitio al sello sin que las
     cifras queden flotando. */
  display: grid;
  place-items: center;
  min-height: 1.3em;
  font-family: var(--font-head);
  font-size: clamp(1.7rem, 2.7vw, 2.3rem);
  font-weight: 500;
  color: var(--sage-deep);
  line-height: 1.05;
  letter-spacing: -.02em;
  /* Cifras de ancho fijo: el contador va de 0 a 30 y sin esto el número
     bailaría de lado en cada fotograma. */
  font-variant-numeric: tabular-nums;
}
.trustbar__item b img { height: 1.25em; width: auto; display: block; }
.trustbar__item span {
  font-size: .89rem;
  color: var(--ink-soft);
  display: block;
  margin-top: 9px;
  line-height: 1.5;
}
@media (max-width: 720px) { .trustbar__grid { grid-template-columns: repeat(2, 1fr); } }

/* ---------- Rejillas ---------- */
.grid { display: grid; gap: 24px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .grid--2, .grid--3 { grid-template-columns: 1fr; } }

.card {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: 34px 32px;
  box-shadow: var(--shadow-soft);
}
.card h3 { margin-bottom: .5em; }
.card p:last-child { margin-bottom: 0; }
.card__icon {
  width: 50px; height: 50px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--sage-pale);
  color: var(--sage-deep);
  margin-bottom: 20px;
}
.card__icon svg { width: 24px; height: 24px; }
.section--deep .card { background: rgba(255,255,255,.07); box-shadow: none; }

/* La negrita heredaba `strong { color: var(--ink) }`, que es la tinta oscura
   del sitio. Sobre el verde de una sección oscura eso daba 2,64:1 — la frase
   que más se quería destacar era la que peor se leía. La excepción existía
   sólo para .creds li strong; se generaliza. Blanco papel sobre el velo del
   10%: 6,05:1. */
.section--deep strong { color: #FDFBF7; }

/* Tarjeta destacada: la opción que el texto recomienda va con más velo para
   separarse de la otra. Estaba al 14% en un `style` suelto del HTML, y ese
   punto extra de claridad dejaba el párrafo en 4,14:1. Al 10% sube a 4,61:1
   sin perder la distinción. */
.section--deep .card--destaca { background: rgba(255, 255, 255, .10); }

/* ---------- Lista de síntomas ---------- */
.symptoms { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px 36px; margin: 0; padding: 0; list-style: none; }
.symptoms li {
  position: relative;
  padding-left: 38px;
  margin: 0;
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--ink);
}
.symptoms li::before {
  content: "";
  position: absolute; left: 0; top: .18em;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--sage-pale) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%233A5541' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / 13px no-repeat;
}
@media (max-width: 640px) { .symptoms { grid-template-columns: 1fr; } }

/* ---------- Bloque partido ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(34px, 5vw, 68px); align-items: center; }
.split--wide-text { grid-template-columns: 1.12fr .88fr; }
/* En la sección de autoridad la lista de credenciales es larga: la foto se
   queda fija mientras se recorre, en vez de irse por arriba de la pantalla.
   Hace falta align-self:start porque el contenedor centra sus ítems y un ítem
   centrado ocupa toda la fila, sin margen donde poder pegarse. */
.section--deep .split__media {
  position: sticky;
  top: clamp(96px, 12vh, 130px);
  align-self: start;
}
@media (max-width: 900px) {
  .section--deep .split__media { position: static; }
}

.split__media img {
  border-radius: var(--r-lg); box-shadow: var(--shadow-lift);
  width: 100%;
  /* Sin esto el navegador usa el atributo height="…" como altura literal y
     deforma la foto. Hace falta siempre que se fije el ancho en porcentaje. */
  height: auto;
}
@media (max-width: 900px) { .split, .split--wide-text { grid-template-columns: 1fr; } }

/* ---------- Credenciales ---------- */
/* ---------- Credenciales ----------
   Lenguaje shadcn/21st.dev: filete de separación, chip cuadrado de esquina
   suave con el icono, y la jerarquía puesta en el peso del texto y no en el
   color. El icono va en un ::before con SVG embebido para no tocar el HTML. */
.creds {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(28px, 3.4vw, 52px);
  row-gap: 0;
}
/* Con dos columnas el filete superior sobra en los dos primeros ítems, no
   sólo en el primero. */
.creds li:nth-child(-n+2) { border-top: 0; padding-top: 0; }
.creds li:nth-child(-n+2)::before { top: 1px; }
/* El chip va absoluto y no como columna de una rejilla: con display:grid en el
   <li>, cada <strong> del texto se convierte en celda y la frase se despedaza. */
.creds li {
  position: relative;
  margin: 0;
  padding: 17px 0 17px 46px;
  line-height: 1.62;
  border-top: 1px solid var(--sand-line);
}
.creds li:last-child { padding-bottom: 0; }
.creds li::before {
  content: "";
  position: absolute; left: 0; top: 18px;
  width: 28px; height: 28px;
  border-radius: 9px;
  background-color: var(--sage-pale);
  border: 1px solid rgba(74, 107, 82, .22);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A6B52' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 13px;
}

/* Sobre el fondo oscuro con foto, el chip se vuelve traslúcido para no
   convertirse en siete manchas claras sobre la imagen. */
.section--deep .creds li { color: #C6D4C8; border-top-color: rgba(255, 255, 255, .13); }
.section--deep .creds li strong { color: #FDFBF7; font-weight: 500; }
.section--deep .creds li::before {
  background-color: rgba(255, 255, 255, .1);
  border-color: rgba(255, 255, 255, .2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23D8E5DA' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
}

@media (max-width: 560px) {
  .creds li { padding: 14px 0 14px 38px; }
  .creds li::before { width: 24px; height: 24px; border-radius: 8px; background-size: 11px; top: 15px; }
  .creds li:first-child::before { top: 0; }
}

/* ---------- Pasos ---------- */
.steps { display: grid; gap: 20px; counter-reset: step; }

/* ---------- Pasos que se apilan al bajar ----------
   Cada tarjeta se queda pegada un poco más abajo que la anterior, así al
   desplazarse se van amontonando en lugar de salir por arriba. El desfase
   creciente deja ver el borde de las que quedan debajo. */
.steps--apiladas { display: block; }
.steps--apiladas .step {
  position: sticky;
  margin-bottom: 20px;
  /* Fondo opaco: si fuera translúcido se verían las de debajo a través */
  background: var(--paper);
}
/* Los desfases van dentro de la consulta, no fuera con un `top: auto` que los
   deshaga después: llevan `:nth-child` y ganaban por especificidad a cualquier
   intento de anularlos desde el bloque de móvil. Si sólo existen cuando el
   apilado está activo, no hay nada que deshacer. */
@media (min-width: 701px) {
  .steps--apiladas .step:nth-child(1) { top: 110px; }
  .steps--apiladas .step:nth-child(2) { top: 124px; }
  .steps--apiladas .step:nth-child(3) { top: 138px; }
  .steps--apiladas .step:nth-child(4) { top: 152px; }
  .steps--apiladas .step:nth-child(5) { top: 166px; }
  .steps--apiladas .step:nth-child(6) { top: 180px; }
  .steps--apiladas .step:nth-child(7) { top: 194px; }
}
/* Espacio al final para que la última llegue a pegarse antes de que acabe */
.steps--apiladas::after { content: ""; display: block; height: 40vh; }

@media (max-width: 700px) {
  /* En pantallas bajas apilar deja muy poco visible: vuelve al flujo normal.

     `relative` y no `static`, que es lo que había: el número de cada paso es un
     ::before con `position: absolute`, y con la tarjeta en `static` deja de ser
     su bloque contenedor. Los seis números se escapaban al ancestro posicionado
     más cercano y se amontonaban en la esquina de la sección, uno encima de
     otro; sólo se veía el último, que marcaba 6, flotando sobre el titular, y
     las tarjetas quedaban sin numerar.

     Y hace falta `top: auto`. Con `static` los `top: 110px…180px` del apilado
     se ignoraban; con `relative` vuelven a contar y desplazan cada tarjeta
     hacia abajo sin mover su hueco, así que se montaban entre ellas y la
     última se salía de la sección por 180px justos. */
  .steps--apiladas .step { position: relative; top: auto; }
  .steps--apiladas::after { display: none; }
}
/* No se desactiva con prefers-reduced-motion: sticky es maquetación, no
   animación. El scroll sigue siendo 1:1 y no produce el efecto vestibular del
   paralaje. Sí se desactiva en pantallas bajas, donde apilar deja poco visible. */
.step {
  position: relative;
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: 30px 34px 30px 92px;
  box-shadow: var(--shadow-soft);
}
.step::before {
  counter-increment: step;
  content: counter(step);
  position: absolute; left: 30px; top: 30px;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--sage-pale);
  color: var(--sage-deep);
  font-family: var(--font-head);
  font-weight: 500;
  font-size: 1.15rem;
}
.step h3 { font-size: 1.2rem; margin-bottom: .35em; }
.step p { margin: 0; font-size: 1.01rem; }
.step__time {
  display: inline-block;
  font-size: .78rem;
  font-weight: 400;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--clay);
  margin-bottom: .65em;
}
@media (max-width: 560px) {
  .step { padding: 76px 26px 28px; }
  .step::before { left: 26px; top: 24px; }
}

/* ---------- Precio ---------- */
.pricing { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
/* Una sola tarjeta: sin esto se queda en la mitad izquierda de una rejilla de
   dos, descuadrada. Se usa en las páginas donde sólo se publica el precio de
   la consulta y no el de la cirugía. */
.pricing--sola { grid-template-columns: 1fr; max-width: 560px; margin-inline: auto; }
.price-card {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: 38px 36px;
  box-shadow: var(--shadow-soft);
}
.price-card--main { box-shadow: var(--shadow-lift); outline: 2px solid var(--sage); outline-offset: -2px; }
.price-card__label { font-size: .87rem; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: .7rem; }
.price-card__amount {
  font-family: var(--font-head);
  font-size: clamp(2.1rem, 3.6vw, 2.9rem);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.05;
  letter-spacing: -.025em;
}
.precio-antes {
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--clay);
  opacity: .55;
  font-weight: 300;
  margin-right: .18em;
}
.price-card__amount .precio-antes { font-size: .62em; }
.btn-note .precio-antes { opacity: .6; }

.price-card__amount small { font-size: .38em; font-weight: 300; color: var(--ink-muted); letter-spacing: 0; font-family: var(--font-body); }
/* La condición del precio va pegada al importe, antes que la duración: es la
   letra pequeña de la cifra tachada y tiene que leerse junto a ella. */
.price-card__anticipado {
  font-size: .88rem;
  line-height: 1.5;
  color: var(--ink-muted);
  margin: .35rem 0 0;
  max-width: 34ch;
}
.price-card__meta { font-size: .97rem; color: var(--ink-muted); margin: .9rem 0 1.5rem; }
.price-card ul { list-style: none; padding: 0; margin: 0 0 1.7rem; }
.price-card ul li { position: relative; padding-left: 30px; font-size: 1rem; line-height: 1.55; }
.price-card ul li::before {
  content: ""; position: absolute; left: 0; top: .4em;
  width: 16px; height: 16px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A6B52' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / contain no-repeat;
}
.price-note { font-size: .91rem; color: var(--ink-muted); line-height: 1.65; margin-top: 24px; }
@media (max-width: 760px) { .pricing { grid-template-columns: 1fr; } }

/* ---------- Testimonios en video ---------- */
/* ---------- Carrusel de testimonios ----------
   Fila única, arrastrable, con bucle infinito: la lista se duplica y al llegar
   al final se salta al mismo punto del clon sin animación, así el usuario no
   percibe el corte. Las tarjetas de los extremos se difuminan con una máscara
   para sugerir que hay más a los lados. */
.videos-carrusel { position: relative; }
.videos {
  display: flex;
  gap: 18px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding: 4px 0 10px;
  cursor: grab;
  scroll-behavior: smooth;
}
.videos::-webkit-scrollbar { display: none; }
.videos.is-dragging { cursor: grabbing; scroll-behavior: auto; }
.videos.is-dragging * { pointer-events: none; }
.video-card { flex: 0 0 clamp(180px, 22vw, 250px); }

/* Flechas */
.carrusel-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 46px; height: 46px; border: 0; border-radius: 50%;
  background: var(--paper); color: var(--ink);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: var(--shadow-soft);
  transition: background-color .2s ease, transform .2s ease;
}
.carrusel-nav:hover { background: var(--sand); transform: translateY(-50%) scale(1.06); }
.carrusel-nav svg { width: 18px; height: 18px; }
.carrusel-nav--prev { left: -10px; }
.carrusel-nav--next { right: -10px; }
@media (max-width: 700px) { .carrusel-nav { display: none; } }
@media (prefers-reduced-motion: reduce) { .videos { scroll-behavior: auto; } }

.video-card { background: var(--paper); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-soft); }
.video-card video {
  width: 100%;
  /* Los testimonios están grabados en vertical 9:16 (formato de Reels).
     Forzarlos a 1/1 recortaba casi la mitad de la imagen. */
  aspect-ratio: 9 / 16;
  object-fit: cover;
  background: var(--sand); display: block;
}
.video-card__body { padding: 20px 24px 24px; }
.video-card__body b { display: block; font-family: var(--font-head); font-weight: 500; color: var(--ink); font-size: 1.06rem; }
.video-card__body span { font-size: .89rem; color: var(--ink-muted); }


/* ---------- Citas ---------- */
.quote {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: 34px 36px;
  box-shadow: var(--shadow-soft);
  position: relative;
}
.quote::before {
  content: "\201C";
  font-family: var(--font-head);
  font-size: 4.6rem;
  line-height: 1;
  color: var(--sage-pale);
  position: absolute;
  top: 18px; left: 26px;
}
.quote p {
  position: relative;
  font-size: 1.06rem;
  line-height: 1.7;
  color: var(--ink);
  margin-bottom: 1.2rem;
}
.quote cite { font-style: normal; font-family: var(--font-head); font-weight: 500; color: var(--sage-deep); font-size: 1.03rem; }
.quote cite span { display: block; font-weight: 300; font-size: .89rem; color: var(--ink-muted); font-family: var(--font-body); margin-top: 2px; }

/* ---------- FAQ ---------- */
/* ---------- Acordeón de preguntas frecuentes ----------
   Lenguaje shadcn/21st.dev: sin tarjetas flotantes ni sombras, sólo filetes de
   separación, disparador a todo lo ancho y un chevron que gira. La apertura se
   anima desde landing.js: <details> cambia el display al abrir, así que una
   transición en CSS puro no llega a ejecutarse. */
.faq {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--sand-line);
}
.faq details {
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  border-bottom: 1px solid var(--sand-line);
}
.faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: 20px;
  padding: 24px 4px;
  font-family: var(--font-head);
  font-weight: 500;
  font-size: clamp(1.02rem, 1.5vw, 1.14rem);
  line-height: 1.45;
  color: var(--ink);
  transition: color .2s ease;
}
.faq summary:hover { color: var(--sage-deep); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary:focus-visible {
  outline: 2px solid var(--sage);
  outline-offset: 4px;
  border-radius: var(--r-sm);
}

/* El chevron va en un chip circular, como el trigger del acordeón de shadcn */
.faq summary::after {
  content: "";
  flex: 0 0 auto;
  margin-left: auto;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--sand-line);
  background: var(--paper)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A6B52' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")
    center / 13px no-repeat;
  transition: transform .32s cubic-bezier(.16, 1, .3, 1), border-color .2s ease, background-color .2s ease;
}
.faq summary:hover::after { border-color: var(--sage); background-color: var(--sage-pale); }
.faq details[open] summary::after { transform: rotate(180deg); }

.faq__body {
  overflow: hidden;                       /* el alto lo anima el JS */
  padding: 0 54px 4px 4px;
}
.faq__body p { color: var(--ink-soft); }
.faq__body p:last-child, .faq__body ul:last-child { margin-bottom: 26px; }

@media (max-width: 560px) {
  .faq summary { padding: 20px 2px; gap: 14px; font-size: 1rem; }
  .faq summary::after { width: 26px; height: 26px; background-size: 12px; }
  .faq__body { padding-right: 40px; }
}

/* ---------- CTA final ---------- */
.cta-final { background: var(--sage-deep); color: #C6D4C8; text-align: center; }
.cta-final h2 { color: #FDFBF7; max-width: 15em; margin-inline: auto; }
.cta-final .lead { color: #BACCBC; max-width: 38em; margin-inline: auto; margin-bottom: 2rem; }
.cta-final .btn-row { justify-content: center; }
/* Sobre fondo salvia, el botón principal se invierte para conservar contraste */
.cta-final .btn--primary,
.section--deep .btn--primary { background: #FDFBF7; color: var(--sage-deep); }
.cta-final .btn--primary:hover,
.section--deep .btn--primary:hover { background: #fff; }
.cta-final .btn--ghost,
.section--deep .btn--ghost { color: #EAF0EA; border-color: rgba(255,255,255,.34); }
.cta-final .btn--ghost:hover,
.section--deep .btn--ghost:hover { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.6); }

/* ---------- Consultorio ---------- */
.office { display: grid; grid-template-columns: .92fr 1.08fr; gap: clamp(32px, 4.5vw, 60px); align-items: center; }
/* El mapa ocupa el lugar que tenían las fotos del consultorio. Lleva alto
   explícito, no porcentaje: el iframe necesita apoyarse en un alto definido o
   se queda plano dentro de una columna de rejilla. */
.office__mapa {
  height: clamp(340px, 46vh, 520px);
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--sand-line);
  box-shadow: var(--shadow-soft);
  background: var(--sand);
}
.office__mapa iframe { display: block; width: 100%; height: 100%; border: 0; }
@media (max-width: 900px) { .office__mapa { height: clamp(280px, 42vh, 380px); } }
.office dl { display: grid; grid-template-columns: auto 1fr; gap: 15px 24px; margin: 0 0 2rem; font-size: 1.02rem; }
.office dt { font-size: .82rem; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-muted); padding-top: .42em; }
.office dd { margin: 0; color: var(--ink); line-height: 1.6; }
@media (max-width: 900px) { .office { grid-template-columns: 1fr; } }

/* ---------- Aviso ---------- */
.disclaimer {
  background: var(--sand);
  border-radius: var(--r-md);
  padding: 24px 28px;
  font-size: .95rem;
  color: var(--ink-soft);
  line-height: 1.68;
}
.disclaimer p:last-child { margin-bottom: 0; }

/* ---------- Footer ---------- */
.footer { background: var(--ink); color: #A79E93; padding: 62px 0 38px; font-size: .97rem; }
.footer a { color: #D3CCC2; }
.footer a:hover { color: #fff; }
.footer__grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 40px; margin-bottom: 40px; }
.footer__logo { height: 44px; width: auto; margin-bottom: 18px; filter: brightness(0) invert(1); opacity: .9; }
.footer__titulo {
  font-family: var(--font-head); color: #FDFBF7;
  font-size: 1.05rem; font-weight: 500; margin: 0 0 15px;
}
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li { margin-bottom: 10px; line-height: 1.5; }
.footer__bottom {
  border-top: 1px solid rgba(255,255,255,.11);
  padding-top: 24px;
  display: flex; flex-wrap: wrap; gap: 12px 28px; justify-content: space-between;
  font-size: .88rem; color: #857C72;
}
@media (max-width: 800px) { .footer__grid { grid-template-columns: 1fr; gap: 30px; } }

/* ---------- WhatsApp flotante ---------- */
.wa-float {
  position: fixed;
  right: 22px; bottom: 22px;
  z-index: 70;
  width: 54px; height: 54px;
  border-radius: 50%;
  background: var(--sage);
  display: grid; place-items: center;
  box-shadow: 0 6px 20px rgba(43, 39, 35, .2);
  transition: background-color .2s ease, transform .2s ease;
}
.wa-float:hover { background: var(--sage-deep); transform: scale(1.05); }
.wa-float svg { width: 27px; height: 27px; fill: #FDFBF7; }

/* ---------- Barra CTA móvil ---------- */
.mobile-cta {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 65;
  background: rgba(250, 247, 242, .97);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--sand-line);
  padding: 11px 14px calc(11px + env(safe-area-inset-bottom));
  gap: 10px;
}
.mobile-cta .btn { flex: 1; padding: .95em 1em; font-size: .97rem; }
/* En la barra, WhatsApp va sólo con su icono: la palabra sobra cuando el
   símbolo es de los más reconocibles que hay, y así el botón deja de competir
   por espacio con «Llamar».

   Verde con el icono en blanco. El color va escrito aquí y no se hereda de
   .btn--primary a propósito: existe una clase .btn--wa con el estilo claro de
   WhatsApp, declarada después, y si este botón la llevara —o alguien se la
   pusiera mañana— se volvería blanco sin que nada avise. Blanco sobre el
   verde de marca da 5,8:1. */
.mobile-cta__wa {
  background: var(--sage);
  color: var(--paper);
  border-color: transparent;
}
.mobile-cta__wa svg { width: 23px; height: 23px; fill: currentColor; display: block; }

@media (max-width: 700px) {
  .mobile-cta { display: flex; }
  body { padding-bottom: 80px; }
  /* El flotante desaparece en teléfono: repetía el WhatsApp que ya está fijo
     en la barra y, con el hero ajustado al alto de pantalla, se le montaba
     encima al párrafo. En escritorio no hay barra, así que allí se queda. */
  .wa-float { display: none; }
}

/* ---------- Accesibilidad ---------- */
:focus-visible { outline: 3px solid var(--sage); outline-offset: 3px; border-radius: 6px; }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* El pulso del botón se exceptúa más abajo, por decisión del cliente.
     [data-reveal] también se exceptúa: bajo esta preferencia la entrada pierde
     el desplazamiento y queda como fundido puro, que no produce el malestar
     vestibular que la preferencia busca evitar. Sin la excepción, esta regla
     dejaba la transición en .01ms y la aparición era un salto seco. */
  *:not(.play-cta__disc):not([data-reveal]):not(.faq__body):not(.proceso__panel):not(.modal__panel):not(.banco__check), *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  /* El sello del titular también se exceptúa: es un elemento de 1em que crece
     en su sitio, sin desplazar nada a su alrededor. Se acorta a la mitad en
     vez de suprimirse, que es lo que se viene haciendo en el resto. */
  .banco__check { transition-duration: .34s, .2s !important; }
  /* El panel del modal también se exceptúa: nace en el sitio y el tamaño del
     elemento que lo abrió y crece hasta su posición final. Es un movimiento
     corto y localizado, no un desplazamiento de página, y sin él el vídeo
     aparece de golpe a pantalla completa —que es más brusco, no menos. Se
     acorta a un tercio en vez de suprimirse. */
  .modal__panel { transition-duration: .26s !important; }
}

/* ==========================================================================
   Hero: botón de play, reseñas y modales
   ========================================================================== */

/* ---------- Titular + botón de play ---------- */
.hero__headline { display: flex; align-items: flex-end; gap: clamp(18px, 2vw, 30px); flex-wrap: wrap; }
.hero__headline h2 { margin: 0; }
/* En escritorio el play va en la misma línea que el titular, no debajo */
@media (min-width: 901px) {
  .hero__headline {
    flex-wrap: nowrap;
    /* Se declaran aquí para poder calcular el alto de una línea del titular
       y centrar el botón justo sobre el último renglón. */
    --titular-size: clamp(2.2rem, 3.9vw, 3.45rem);
    --titular-lh: 1.12;
    --titular-linea: calc(var(--titular-size) * var(--titular-lh));
    --play-disco: 54px;
  }
  .hero__headline h2 { min-width: 0; font-size: var(--titular-size); line-height: var(--titular-lh); }
  /* Selector más específico: la regla base de .play-cta vive más abajo en el
     archivo y, a igual especificidad, ganaba por orden. */
  .hero__headline .play-cta {
    flex: none;
    /* Con align-items:flex-end el botón se apoya en la base del titular. Subirlo
       la mitad de lo que sobra deja su centro sobre el centro del último
       renglón, en vez de sobre la base del bloque entero. */
    margin-bottom: calc((var(--titular-linea) - var(--play-disco)) / 2);
  }
}

.play-cta {
  display: inline-flex; align-items: center; gap: 13px;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: #fff; font-family: var(--font-body); text-align: left;
  margin-bottom: .4rem;   /* solo móvil; en escritorio lo pisa el cálculo de abajo */
}
.play-cta__disc {
  position: relative; flex: none;
  width: 54px; height: 54px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.16);
  border: 1.5px solid rgba(255,255,255,.55);
  backdrop-filter: blur(10px);
  transition: background-color .22s ease, transform .22s ease;
}
.play-cta__disc svg {
  width: 19px; height: 19px; fill: #fff;
  /* El trazado del triángulo está descentrado dentro de su viewBox (va de
     x=8 a x=19.63, centro 13.82 en vez de 12). Se compensa con la misma
     proporción a la que está escalado: 1.82 × 19/24 = 1.44px. */
  transform: translateX(-1.44px);
}
/* Pulso cada 3s: dos anillos concéntricos que crecen desde el borde del disco
   y se desvanecen. El segundo va retrasado 0.6s para que se lea como onda
   continua y no como un parpadeo. El disco en sí no se mueve. */
.play-cta__disc::before,
.play-cta__disc::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,.75);
  animation: playPulso 3s cubic-bezier(.22, .61, .36, 1) infinite;
  pointer-events: none;
}
.play-cta__disc::after { animation-delay: .6s; }

@keyframes playPulso {
  0%   { transform: scale(1);    opacity: .85; border-width: 2px; }
  65%  { transform: scale(2.15); opacity: 0;   border-width: .5px; }
  100% { transform: scale(2.15); opacity: 0;   border-width: .5px; }
}

/* Al pasar el ratón se detiene: ya tiene la atención del visitante */
.play-cta:hover .play-cta__disc::before,
.play-cta:hover .play-cta__disc::after { animation-play-state: paused; }
.play-cta:hover .play-cta__disc { background: rgba(255,255,255,.28); transform: scale(1.05); }
.play-cta__label b { display: block; font-size: .95rem; font-weight: 500; line-height: 1.3; }
.play-cta__label span { font-size: .8rem; color: rgba(255,255,255,.72); }
/* Decisión explícita del cliente: los anillos siguen corriendo aunque el
   sistema pida reducir movimiento. Se exime a mano de la regla global de más
   arriba, que reduce toda animación a .01ms. Es una animación decorativa, así
   que lo habitual sería respetarla; queda anotado. */
@media (prefers-reduced-motion: reduce) {
  .play-cta__disc { animation: none !important; }
  .play-cta__disc::before,
  .play-cta__disc::after {
    animation: playPulso 3s cubic-bezier(.22, .61, .36, 1) infinite !important;
    animation-duration: 3s !important;
    opacity: 1;
  }
  .play-cta__disc::after { animation-delay: .6s !important; }
}
@media (max-width: 560px) {
  .play-cta__disc { width: 46px; height: 46px; }
  .play-cta__disc svg { width: 16px; height: 16px; }
}

/* ---------- Reseñas de Google sobre la foto ---------- */
.hero__reviews { margin-top: clamp(24px, 3vw, 34px); max-width: 640px; }
.hero__reviews iframe { display: block; width: 100%; height: 230px; border: 0; overflow: hidden; }
@media (max-width: 900px) { .hero__reviews { max-width: none; } }

/* ---------- Resumen de reseñas del hero, sólo en móvil ----------
   El widget de reseñas ocupa 230px: en una pantalla de teléfono se come el
   hero entero y empuja el titular fuera de vista. Ahí se cambia por la píldora
   de resumen —estrellas, número y logotipo—, que da la misma señal de confianza
   en 40px. La cita completa sigue estando, más abajo, en el muro de reseñas. */
.hero__resumen { display: none; }
@media (max-width: 700px) {
  .hero__reviews iframe { display: none; }
  .hero__resumen {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 9px 15px;
    background: rgba(255, 255, 255, .14);
    border: 1px solid rgba(255, 255, 255, .24);
    backdrop-filter: blur(10px);
    border-radius: 100px;
    color: #fff; text-decoration: none;
    font-size: .9rem; line-height: 1;
  }
  .hero__resumen .resena__estrellas { margin: 0; gap: 1px; }
  .hero__resumen .resena__estrellas svg { width: 13px; height: 13px; }
  .hero__resumen-txt b { font-weight: 600; }
  .hero__resumen-g { width: 15px; height: 15px; flex: 0 0 auto; }
}

/* ---------- Modal genérico ---------- */
body.is-locked { overflow: hidden; }

.modal {
  position: fixed; inset: 0; z-index: 200;
  /* En iOS, un `inset: 0` fijo se mide contra la ventana SIN las barras del
     navegador, así que la caja llega por debajo de la barra inferior de Chrome
     o de Safari. Y como el panel va centrado en esa caja, se desplaza hacia
     abajo y lo último que trae —el botón «Continuar» del calendario, la línea
     de tiempo del vídeo— queda tapado.

     `100svh` es el alto de la ventana CON las barras desplegadas, es decir, lo
     que de verdad se ve siempre. Con top, height y bottom declarados a la vez,
     CSS descarta el bottom y manda el height, que es justo lo que se busca.
     Los navegadores sin svh se quedan con el inset de arriba. */
  height: 100svh;
  display: grid; place-items: center;
  padding: 24px;
  opacity: 0;
  /* Entrada y salida con curvas distintas: al abrir conviene una expo-out
     larga, que arranca rápido y frena suave; al cerrar, algo corto y directo,
     porque una salida lenta se percibe como que la interfaz no responde. */
  transition: opacity .34s cubic-bezier(.16, 1, .3, 1);
}
.modal:not(.is-open) { transition: opacity .18s cubic-bezier(.4, 0, 1, 1); }
.modal[hidden] { display: none; }
.modal.is-open { opacity: 1; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(13, 22, 31, .74); backdrop-filter: blur(6px); }
.modal__panel {
  position: relative; z-index: 2;
  width: 100%; max-width: 560px;
  /* Misma razón que en .modal: el tope se mide contra lo que se ve, no contra
     la ventana completa. La línea vh queda de respaldo para lo que no conozca
     svh; el orden importa, gana la última que el navegador entienda. */
  max-height: 92vh;
  max-height: 92svh;
  overflow: auto; -webkit-overflow-scrolling: touch;
  /* El panel no va en blanco a propósito. Los campos del formulario son
     blancos con un borde de 1px muy tenue; sobre un panel blanco el único
     límite de cada campo sería ese borde. Con el panel un tono por debajo los
     campos se recortan solos, que es como funcionaba con el crema. */
  background: var(--cream-deep); border-radius: var(--r-lg);
  box-shadow: 0 30px 90px rgba(13, 22, 31, .42);
  transform: translateY(28px) scale(.94);
  opacity: 0;
  transition:
    transform .52s cubic-bezier(.16, 1, .3, 1),
    opacity   .30s cubic-bezier(.16, 1, .3, 1);
}
.modal.is-open .modal__panel { transform: none; opacity: 1; }
.modal:not(.is-open) .modal__panel {
  transform: translateY(10px) scale(.98);
  transition:
    transform .2s cubic-bezier(.4, 0, 1, 1),
    opacity   .16s linear;
}

/* El velo entra un poco antes que el panel, así el fondo se asienta primero */
.modal__backdrop { opacity: 0; transition: opacity .3s cubic-bezier(.16, 1, .3, 1); }
.modal.is-open .modal__backdrop { opacity: 1; }
.modal__close {
  position: absolute; top: 14px; right: 14px; z-index: 6;
  width: 42px; height: 42px; border: 0; border-radius: 50%;
  background: rgba(20, 39, 58, .09); color: var(--ink);
  display: grid; place-items: center; cursor: pointer;
  transition: background-color .2s ease;
}
.modal__close:hover { background: rgba(20, 39, 58, .18); }
.modal__close svg { width: 18px; height: 18px; }
.modal__head { padding: 30px 32px 0; }
.modal__head h2 { font-size: 1.5rem; margin: 0 0 .3em; }
.modal__head p { font-size: .98rem; color: var(--ink-muted); margin: 0; }
.modal__body {
  /* Sin cabecera, hace falta hueco para que el botón de cerrar (42px a 14px
     del borde) no quede encima del calendario. */
  padding: 64px 26px 26px;
}

/* Marcador de carga mientras el calendario aún no responde */
#cal-mount { min-height: 400px; position: relative; }
#cal-mount::before {
  content: "Cargando agenda…";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: var(--ink-muted); font-size: .95rem;
}
#cal-mount.is-ready::before { content: none; }
#cal-mount iframe { position: relative; z-index: 1; }

/* ---------- Modal de video ---------- */
.modal__panel--video {
  max-width: min(420px, 92vw);
  background: transparent; box-shadow: none;
  overflow: visible; border-radius: 0;
}

/* La cruz de este modal cae directamente sobre el video, no sobre el papel
   crema de los demás: la tinta oscura y el fondo casi transparente que sirven
   allí aquí desaparecen. Se invierte a blanco sobre un disco oscuro, que es lo
   único que aguanta un fotograma cualquiera. En el peor caso posible —un
   fotograma completamente blanco— el velo deja el fondo en gris medio y la
   cruz mantiene 4,74:1, por encima del 3:1 que pide un elemento no textual. */
#modal-video .modal__close {
  color: #fff;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(4px);
}
#modal-video .modal__close:hover { background: rgba(0, 0, 0, .72); }

/* ---------- Llamada a la acción dentro del vídeo ----------
   Aparece sobre el minuto 1:24, cuando el doctor termina de explicar por qué
   conviene una segunda opinión. Va por encima de la barra del reproductor
   —que ocupa los 90px de abajo cuando se muestra— para no taparle los
   controles ni que se tapen entre ellos. */
.video-cta {
  position: absolute; z-index: 8;
  left: 50%; bottom: 96px; transform: translateX(-50%);
  white-space: nowrap;
  font-family: var(--font-body); font-size: .97rem; font-weight: 500;
  color: var(--paper); background: var(--sage);
  border: 0; border-radius: 100px;
  padding: .92em 1.7em; cursor: pointer;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
  animation: ctaVideoEntra .42s cubic-bezier(.16, 1, .3, 1);
}
.video-cta:hover { background: var(--sage-deep); }
.video-cta[hidden] { display: none; }
@keyframes ctaVideoEntra {
  from { opacity: 0; transform: translate(-50%, 14px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
@media (max-width: 700px) { .video-cta { bottom: 86px; font-size: .93rem; } }

/* ==========================================================================
   Reproductor de video
   Diseño portado del componente de referencia (React/Tailwind) a CSS propio:
   disco central translúcido con desenfoque, barra inferior sobre degradado,
   y controles que se ocultan solos mientras se reproduce.
   ========================================================================== */
.rp {
  position: relative;
  width: 100%;
  background: #000;
  border-radius: var(--r-lg);
  overflow: hidden;
  line-height: 0;
}
.rp:focus-visible { outline: 3px solid var(--sage); outline-offset: 3px; }
.rp video { width: 100%; height: 100%; display: block; cursor: pointer; }

/* Disco central */
.rp__centro {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  pointer-events: none;
  opacity: 0; transition: opacity .3s ease;
}
.rp.is-paused .rp__centro,
.rp.is-hover  .rp__centro { opacity: 1; }
.rp__disco {
  width: 64px; height: 64px; border-radius: 50%;
  background: rgba(255,255,255,.2);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,.3);
  display: grid; place-items: center;
  color: #fff; cursor: pointer; pointer-events: auto;
  transition: background-color .2s ease, transform .2s ease;
}
.rp__disco:hover { background: rgba(255,255,255,.3); transform: scale(1.05); }
.rp__disco svg { width: 24px; height: 24px; fill: currentColor; }

/* Barra inferior */
.rp__barra {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: linear-gradient(to top, rgba(0,0,0,.8), transparent);
  padding: 34px 14px 12px;
  opacity: 0; pointer-events: none;
  transition: opacity .3s ease;
  line-height: 1;
}
.rp.is-paused .rp__barra,
.rp.is-hover  .rp__barra { opacity: 1; pointer-events: auto; }

.rp__fila { display: flex; align-items: center; gap: 8px; }
.rp__fila + .rp__fila { margin-top: 10px; justify-content: space-between; }
.rp__grupo { display: flex; align-items: center; gap: 2px; }
.rp__tiempo {
  color: #fff; font-size: .72rem;
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  min-width: 34px; text-align: center;
}

/* Barras de progreso y volumen: un range nativo repintado */
.rp__range {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 4px; border-radius: 4px;
  background: rgba(255,255,255,.3);
  cursor: pointer; outline: none;
}
.rp__range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 12px; height: 12px; border-radius: 50%;
  background: #fff; cursor: pointer;
  transition: transform .2s ease;
}
.rp__range:hover::-webkit-slider-thumb { transform: scale(1.25); }
.rp__range::-moz-range-thumb {
  width: 12px; height: 12px; border: 0; border-radius: 50%; background: #fff;
}
.rp__progreso { flex: 1; }

.rp__btn {
  width: 32px; height: 32px; flex: none;
  border: 0; border-radius: 6px;
  background: none; color: #fff;
  display: grid; place-items: center; cursor: pointer;
  transition: background-color .18s ease;
}
.rp__btn:hover { background: rgba(255,255,255,.2); }
.rp__btn svg { width: 16px; height: 16px; }

/* El volumen se despliega al pasar por encima, como en la referencia */
.rp__vol { display: flex; align-items: center; gap: 6px; }
.rp__vol .rp__range { width: 0; transition: width .2s ease; }
.rp__vol:hover .rp__range, .rp__vol:focus-within .rp__range { width: 68px; }

/* En reproductores estrechos (tarjetas del carrusel) solo caben lo esencial */
.rp--compacto .rp__btn--salto,
.rp--compacto .rp__btn--stop,
.rp--compacto .rp__vol { display: none; }
.rp--compacto .rp__barra { padding: 26px 10px 9px; }
.rp--compacto .rp__disco { width: 48px; height: 48px; }
.rp--compacto .rp__disco svg { width: 18px; height: 18px; }

@media (max-width: 620px) {
  .modal { padding: 0; }
  /* Aquí estaba el fallo de verdad en teléfono: estos dos `100vh` pisaban el
     tope de arriba y devolvían la medida sin las barras del navegador. El
     panel llegaba por debajo de la barra inferior de Chrome y se comía lo
     último de cada modal: el botón «Continuar» del calendario y la línea de
     tiempo del reproductor. Se repiten en vh y svh —el orden importa, gana la
     última que el navegador entienda— para no dejar tirado a lo que no
     conozca svh. */
  .modal__panel { max-width: none; border-radius: 0; max-height: 100vh; max-height: 100svh; }

  /* El formulario no: es contenido corto y a sangre parece una pantalla del
     sistema, no algo que se pueda cerrar. Se queda como tarjeta con esquinas
     redondeadas y aire alrededor, que además deja ver el fondo y hace evidente
     que se sale tocando fuera. */
  #modal-lead { padding: 18px; }
  #modal-lead .modal__panel {
    border-radius: var(--r-lg);
    max-height: calc(100svh - 36px);
  }
  .modal__panel--video {
    display: grid; place-items: center; padding: 0 12px;
    height: 100vh;
    height: 100svh;
  }
  .vp { width: 100%; border-radius: var(--r-md); }
  /* La cruz de salida queda arriba a la derecha de la pantalla */
  .modal__panel--video .modal__close {
    top: calc(14px + env(safe-area-inset-top)); right: 14px;
    width: 44px; height: 44px;
  }

  /* ---------- El calendario, a pantalla completa y con scroll propio ----------
     El iframe crecía a lo alto según su contenido: la ficha se pinta primero y
     los horarios llegan después, así que el alto final supera la pantalla y el
     botón «Continuar» acaba por debajo del borde.

     Acotar el panel no bastaba. En iOS, el gesto de arrastre sobre un iframe se
     lo queda el iframe, y como iba con el scroll desactivado no llegaba al
     contenedor de detrás: el botón no sólo no se veía, es que no había forma
     de alcanzarlo.

     Así que en teléfono el iframe ocupa exactamente lo visible y se desplaza
     por dentro. El alto lo manda esta regla, no los mensajes de altura del
     widget, que landing.js ignora a este tamaño. */
  #modal-cita .modal__panel { height: 100vh; height: 100svh; overflow: hidden; }
  #modal-cita .modal__body { height: 100%; padding: 0; }
  #modal-cita #cal-mount { height: 100%; min-height: 0; border-radius: 0; }
  #modal-cita #cal-mount iframe { height: 100%; }
}

/* ==========================================================================
   Sección de segunda opinión (video + carta) y formulario de contacto
   ========================================================================== */
/* La sección ocupa el 80% del alto de pantalla y el vídeo va a sangre por la
   izquierda, sin esquinas redondeadas. El padding vertical se anula: quien
   manda el alto es la propia sección. */
.opinion { background: var(--cream-deep); padding: 0; }
.opinion__grid {
  display: grid;
  grid-template-columns: minmax(300px, .8fr) 1.2fr;
  gap: clamp(32px, 5vw, 68px);
  align-items: stretch;          /* el vídeo estira hasta el alto completo */
  min-height: 80vh;
  min-height: 80svh;
  /* Anula el .wrap para que la columna del vídeo llegue al borde */
  max-width: none;
  padding-inline: 0;
}
.opinion__video {
  position: relative; margin: 0;
  border-radius: 0;              /* a sangre: sin esquinas redondeadas */
  overflow: hidden;
  background: var(--sand); box-shadow: none;
  max-width: none;
  /* Tiene que ser height, no min-height: un porcentaje sobre un alto que sólo
     viene de min-height resuelve a 0, y el vídeo absoluto se quedaba plano.
     Con height definido, el height:100% del vídeo se apoya en 80svh. */
  height: 80vh;
  height: 80svh;
}
/* Aquí ya no hay <video>: es un cartel que abre el modal. El fotograma está
   recortado a 2:3, la misma proporción de la ventana, así que no se pierde
   encuadre al aplicar cover. */
.opinion__abrir {
  display: block; width: 100%; height: 100%;
  margin: 0; padding: 0; border: 0; background: none;
  position: relative; overflow: hidden; cursor: pointer;
}
.opinion__abrir img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Anclado arriba, no al centro: la ventana de esta columna es más ancha que
     el cartel en casi todas las pantallas, así que cover recorta alto. Con el
     50% por defecto la mitad de ese recorte se comía el aire sobre la cabeza. */
  object-position: 50% 18%;
}
.opinion__abrir:focus-visible { outline: 3px solid var(--sage); outline-offset: -3px; }
.opinion__abrir:hover .opinion__play { transform: scale(1.06); }

/* El texto conserva el margen derecho del resto del sitio, para que su borde
   coincida con el de las demás secciones aunque la rejilla vaya a sangre. */
.opinion__texto {
  /* Ritmo vertical comprimido para que el bloque quepa dentro del 80vh en
     portátiles de 900px de alto. En pantallas más altas sobra sitio. */
  padding-block: clamp(34px, 4.4vh, 62px);
  padding-right: max(24px, calc((100vw - var(--wrap)) / 2 + 24px));
  align-self: center;
}
.opinion__texto p { margin-bottom: .92em; }
.opinion__texto h2 { margin-bottom: .42em; }
.opinion__texto .eyebrow { margin-bottom: .7rem; }
.opinion__texto .opinion__firma { margin: 16px 0 4px; }
.opinion__texto .opinion__cargo { margin-bottom: 1.15rem; }
.opinion__play {
  position: absolute; inset: 0; margin: auto;
  width: 74px; height: 74px; border: 0; border-radius: 50%;
  background: rgba(255,255,255,.92); display: grid; place-items: center; cursor: pointer;
  transition: opacity .2s ease, transform .2s ease;
}
.opinion__play svg { width: 26px; height: 26px; fill: var(--pill); transform: translateX(-1.97px); }
.opinion__play:hover { transform: scale(1.06); }
.opinion__video.is-playing .opinion__play { opacity: 0; pointer-events: none; }

.opinion__firma {
  display: block; width: 190px; height: auto; margin: 28px 0 6px;
  /* Ya es un SVG vectorial con transparencia real, así que no hace falta el
     mix-blend-mode: multiply que antes disimulaba el fondo blanco del PNG.
     Al ser vector se mantiene nítida en pantallas 2x y 3x. */
  opacity: .88;
}
.opinion__cargo { font-size: .92rem; color: var(--ink-muted); margin: 0 0 1.9rem; }
@media (max-width: 900px) {
  /* Apilado: el sangrado y el 80vh dejan de tener sentido en vertical */
  .opinion__grid { grid-template-columns: 1fr; min-height: 0; gap: 0; }
  .opinion__video { max-width: none; height: auto; }
  /* Apilado, el cartel marca su propio alto por proporción */
  .opinion__abrir { height: auto; }
  .opinion__abrir img { height: auto; aspect-ratio: 4 / 5; max-height: 70svh; }
  .opinion__texto { padding: clamp(36px, 6vw, 56px) 24px; }
}

/* ---------- Formulario ---------- */
.form-campo { margin-bottom: 18px; }
.form-campo label { display: block; font-size: .93rem; color: var(--ink); margin-bottom: 7px; }
.form-campo input {
  width: 100%; font-family: var(--font-body); font-size: 1.02rem;
  /* Borde propio, no --sand-line. Al pasar el panel a gris neutro el borde
     genérico quedó a 1,16:1 contra el panel, por debajo del 1,33:1 que daba
     sobre el crema. Este tono devuelve el mismo recorte que tenía antes. */
  padding: .85em 1.1em; border: 1.5px solid #D6D6DB; border-radius: var(--r-sm);
  background: var(--paper); color: var(--ink);
}
/* ---------- Bandera del país en el teléfono ----------
   Va como adorno dentro del campo, no como parte del valor: el `+52 ` sigue
   siendo texto editable, así que quien tenga un número de otro país puede
   borrarlo y escribir el suyo, y la normalización de landing.js no cambia.
   `pointer-events: none` para que el toque caiga en el campo y no en la
   bandera, que si no roba el foco en teléfono. */
.form-tel { position: relative; }
.form-tel__bandera {
  position: absolute;
  left: 13px; top: 50%;
  transform: translateY(-50%);
  font-size: 1.12rem;
  line-height: 1;
  pointer-events: none;
}
/* Hueco para la bandera. Sólo en este campo: el resto sigue con su relleno. */
.form-tel input { padding-left: 42px; }

.form-campo input:focus-visible { border-color: var(--sage); outline: none; box-shadow: 0 0 0 3px var(--sage-pale); }
.form-campo input[aria-invalid="true"] { border-color: #B4482F; }
.form-error { display: none; font-size: .87rem; color: #B4482F; margin-top: 6px; }
.form-campo.is-mal .form-error { display: block; }
.form-aviso {
  display: none; margin-top: 14px; padding: 12px 16px; border-radius: var(--r-sm);
  background: #F7E6E1; color: #8A3520; font-size: .92rem;
}
.form-aviso.is-visible { display: block; }
/* El enlace a WhatsApp del aviso de error. Subrayado y en el mismo tono del
   texto: sobre el fondo rosa del aviso, el verde de marca queda en 2,4:1. */
.form-aviso a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.form-legal { font-size: .84rem; color: var(--ink-muted); margin: 14px 0 0; line-height: 1.55; }
.btn[aria-busy="true"] { opacity: .6; pointer-events: none; }

/* ═══════════════════════════════════════════════════════════════
   PÁGINA LEGAL (aviso de privacidad)
   ═══════════════════════════════════════════════════════════════ */
.navpill--solido { background: var(--cream); }
.legal { padding: 132px 0 96px; }
.legal h1 { font-size: clamp(2rem, 4.4vw, 3rem); margin: 0 0 10px; }
.legal__fecha { color: var(--ink-muted); font-size: .93rem; margin: 0 0 30px; }
.legal h2 {
  font-size: clamp(1.15rem, 2.1vw, 1.42rem);
  margin: 44px 0 12px; padding-top: 26px;
  border-top: 1px solid var(--sand-line);
}
.legal p { color: var(--ink-soft); line-height: 1.72; margin: 0 0 14px; }
.legal ul { color: var(--ink-soft); line-height: 1.72; margin: 0 0 18px; padding-left: 1.15rem; }
.legal li { margin-bottom: 9px; }
.legal strong { color: var(--ink); font-weight: 600; }
.legal a { color: var(--sage); text-decoration: underline; text-underline-offset: 3px; }
.legal a:hover { color: var(--sage-deep); }
/* El consentimiento expreso para datos de salud tiene que destacarse
   visualmente: es el punto que la LFPDPPP exige que el titular no pase por alto. */
.legal__destacado {
  background: var(--sage-pale); border-left: 3px solid var(--sage);
  padding: 16px 20px; border-radius: 0 var(--r-sm) var(--r-sm) 0;
  margin: 0 0 16px !important;
}
.legal__cierre {
  margin-top: 52px; padding-top: 30px; border-top: 1px solid var(--sand-line);
}
.legal__cierre .btn { margin-top: 8px; }

/* ═══════════════════════════════════════════════════════════════
   FOOTER · redes, COFEPRIS y firma +Pacientes
   ═══════════════════════════════════════════════════════════════ */
.footer__social { display: flex; gap: 10px; margin-top: 20px; }
.footer__social a {
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid rgba(255, 255, 255, .16);
  color: #D3CCC2; transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.footer__social a:hover { background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .3); color: #fff; }
.footer__social svg { width: 18px; height: 18px; fill: currentColor; }

.footer__cofepris {
  margin-top: 34px; padding: 15px 18px;
  border: 1px dashed rgba(255, 255, 255, .2); border-radius: var(--r-sm);
  font-size: .86rem; line-height: 1.6; color: #A79E93;
}
.footer__cofepris strong { color: #D3CCC2; font-weight: 600; }

/* ---------- Otros procedimientos, en el pie ----------
   Las cuatro landings eran callejones sin salida: se entraba desde un anuncio
   y no había forma de llegar a las demás. Aquí no estorban a la conversión
   —quedan por debajo del formulario y del CTA final— y hacen que las páginas
   se sostengan entre sí en vez de competir sueltas. */
.footer__procs { margin-top: 30px; padding-top: 24px; border-top: 1px solid rgba(255, 255, 255, .1); }
.footer__procs-tit {
  display: block; margin-bottom: 12px;
  font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(255, 255, 255, .48);
}
.footer__procs-lista { display: flex; flex-wrap: wrap; gap: 10px 12px; }
.footer__procs-lista a {
  padding: 8px 15px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .18);
  font-size: .9rem;
  transition: border-color .2s ease, background-color .2s ease;
}
.footer__procs-lista a:hover { border-color: rgba(255, 255, 255, .4); background: rgba(255, 255, 255, .07); }

.footer__legal { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 26px; }
.footer__legal a { text-decoration: underline; text-underline-offset: 3px; }

.footer__marca {
  margin-top: 26px; padding-top: 22px;
  border-top: 1px solid rgba(255, 255, 255, .1);
  display: flex; justify-content: center;
}
.footer__marca a {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: .88rem; color: #A79E93; opacity: .9;
  transition: opacity .2s ease, color .2s ease;
}
.footer__marca a:hover { opacity: 1; color: #fff; }
.footer__marca img { width: 20px; height: 20px; display: block; }

/* ═══════════════════════════════════════════════════════════════
   BANNER DE COOKIES
   ═══════════════════════════════════════════════════════════════ */
.cookies {
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 90;
  max-width: 640px; margin-inline: auto;
  background: var(--paper); border: 1px solid var(--sand-line);
  border-radius: var(--r-md); box-shadow: var(--shadow-lift);
  padding: 20px 22px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px;
  transform: translateY(140%); opacity: 0;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1), opacity .35s ease;
}
.cookies.is-visible { transform: translateY(0); opacity: 1; }
.cookies p { margin: 0; flex: 1 1 280px; font-size: .9rem; line-height: 1.6; color: var(--ink-soft); }
.cookies a { color: var(--sage); text-decoration: underline; text-underline-offset: 3px; }
.cookies__acciones { display: flex; gap: 10px; flex: 0 0 auto; }
.cookies .btn { padding: 10px 18px; font-size: .88rem; }
@media (max-width: 560px) {
  .cookies { padding: 18px; }
  .cookies__acciones { width: 100%; }
  .cookies__acciones .btn { flex: 1; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .cookies { transition: opacity .2s ease; transform: none; }
}

/* ---------- Panel de preferencias de cookies ----------
   Vive dentro de un .modal normal (#modal-cookies), así hereda el fondo, el
   cierre con Escape y el clic fuera. Sólo cambia lo de dentro. */
.ck { padding: 6px 32px 30px; }
.ck__fila {
  display: flex; align-items: flex-start; gap: 18px;
  padding: 17px 0; border-top: 1px solid var(--sand-line);
  cursor: pointer;
}
.ck__fila:first-child { border-top: 0; }
.ck__fila--fija { cursor: default; }
.ck__texto { flex: 1 1 auto; }
.ck__texto strong { display: block; font-size: 1rem; margin-bottom: .18em; }
.ck__texto span { display: block; font-size: .87rem; line-height: 1.55; color: var(--ink-muted); }
.ck__siempre {
  flex: 0 0 auto; margin-top: 3px;
  font-size: .76rem; letter-spacing: .01em; white-space: nowrap;
  color: var(--sage); background: var(--sage-pale);
  border-radius: 999px; padding: 5px 11px;
}

/* Interruptor. Es un <input type="checkbox"> de verdad: así el teclado, el
   lector de pantalla y el envío del formulario funcionan sin ayuda. */
.ck__sw {
  appearance: none; -webkit-appearance: none;
  flex: 0 0 auto; position: relative; margin: 2px 0 0;
  width: 46px; height: 27px; border: 0; border-radius: 999px;
  background: #D6CFC2; cursor: pointer;
  transition: background-color .22s ease;
}
.ck__sw::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 21px; height: 21px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .28);
  transition: transform .22s cubic-bezier(.3, 1.4, .5, 1);
}
.ck__sw:checked { background: var(--sage); }
.ck__sw:checked::after { transform: translateX(19px); }
.ck__sw:focus-visible { outline: 2px solid var(--sage); outline-offset: 3px; }

.ck__pie { display: flex; gap: 10px; margin-top: 26px; }
.ck__pie .btn { flex: 1 1 0; justify-content: center; }

@media (max-width: 520px) {
  .ck { padding: 6px 22px 24px; }
  .ck__pie { flex-direction: column; }
}

/* Enlace del pie para volver a abrir el panel una vez decidido */
.footer__legal button {
  appearance: none; background: none; border: 0; padding: 0;
  font: inherit; color: inherit; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}

/* ═══════════════════════════════════════════════════════════════
   PRUEBA SOCIAL EXTERNA (Google + Doctoralia) en testimonios
   ═══════════════════════════════════════════════════════════════ */
.prueba-social { margin-top: 54px; }
/* ---------- Muro de reseñas ----------
   Tres columnas equilibradas al generar el HTML, dentro de un contenedor con
   scroll propio. Se reparten en columnas ya montadas y no con column-count:
   las multicolumna fluyen en horizontal al limitar el alto, y aquí hace falta
   que el desbordamiento sea vertical. */
/* Sin scroll propio: se muestran 20 y el resto se cargan por lotes. */
.resenas__pie { display: flex; justify-content: center; margin-top: 26px; }
.resenas__mas[hidden] { display: none; }

/* Las que aún no se han cargado no ocupan sitio */
.resena--oculta { display: none; }

/* Entrada de cada tanda: una a una, con la misma curva del resto del sitio */
.resena--entrando { opacity: 0; transform: translateY(26px); }
.resena--dentro {
  opacity: 1; transform: none;
  transition:
    opacity   .62s cubic-bezier(.16, 1, .3, 1),
    transform .74s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--entrada, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  /* Fundido puro, sin desplazamiento */
  .resena--entrando { transform: none; }
  .resena--dentro { transition-duration: .4s !important; transition-delay: var(--entrada, 0ms) !important; }
}
.resenas__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
.resenas__col  { display: grid; gap: 16px; align-content: start; }

.resena {
  background: var(--paper);
  border: 1px solid var(--sand-line);
  border-radius: var(--r-md);
  padding: 20px 22px 22px;
  box-shadow: var(--shadow-soft);
}
.resena__cab { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.resena__avatar {
  width: 38px; height: 38px; flex: 0 0 auto;
  border-radius: 50%; display: grid; place-items: center;
  color: #fff; font-family: var(--font-head); font-weight: 500; font-size: 1.02rem;
}
.resena__nombre { margin: 0; font-family: var(--font-head); font-weight: 500; color: var(--ink); font-size: .98rem; line-height: 1.3; }
.resena__fecha  { margin: 0; font-size: .82rem; color: var(--ink-muted); }
.resena__estrellas { display: inline-flex; gap: 2px; margin-bottom: 10px; }
.resena__estrellas svg { width: 15px; height: 15px; fill: #FFD069; }
.resena__texto { margin: 0; font-size: .96rem; line-height: 1.62; color: var(--ink-soft); }

/* Las reseñas muy largas se recortan y se despliegan al pulsar */
.resena--larga .resena__texto {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 11;
  overflow: hidden;
}
.resena--larga.is-abierta .resena__texto { -webkit-line-clamp: unset; }
.resena__mas {
  margin-top: 10px; padding: 0; border: 0; background: none; cursor: pointer;
  font-family: var(--font-body); font-size: .9rem; color: var(--sage);
  text-decoration: underline; text-underline-offset: 3px;
}
.resena__mas:hover { color: var(--sage-deep); }

@media (max-width: 1000px) { .resenas__cols { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 660px)  {
  .resenas__cols { grid-template-columns: 1fr; }
  /* Aquí había un `max-height` sin `overflow`. Sobraba del diseño anterior,
     cuando el muro tenía scroll propio; al quitar el scroll y dejar el botón
     de «Cargar más», la altura máxima se quedó suelta. El resultado en
     teléfono era que las reseñas desbordaban la caja y los enlaces a Google y
     Doctoralia, que van justo debajo, se pintaban encima de ellas. */
}
.perfiles { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 22px; }
.perfil-chip {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 18px; border-radius: 999px;
  border: 1px solid var(--sand-line); background: var(--paper);
  color: var(--ink); font-size: .91rem; font-weight: 500;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.perfil-chip:hover { border-color: var(--ink-muted); box-shadow: var(--shadow-soft); transform: translateY(-1px); }
.perfil-chip svg { width: 17px; height: 17px; flex: 0 0 auto; }
.perfil-chip span { color: var(--ink-muted); font-weight: 400; }

/* ---------- Los dos perfiles, en la misma fila en teléfono ----------
   Sumaban 435px de ancho para los 327 disponibles a 375px de pantalla, así que
   el flex-wrap los apilaba. Se reparten la fila a partes iguales y se aprieta
   lo que se puede sin bajar de un tamaño legible; lo que no cabe en una línea
   se parte en dos dentro de su propia píldora, que es preferible a apilarlas.
   `min-width: 0` es lo que permite que un elemento flexible baje de su ancho
   de contenido: sin él, `flex: 1` no sirve de nada aquí. */
@media (max-width: 620px) {
  .perfiles { flex-wrap: nowrap; gap: 9px; }
  .perfil-chip {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    text-align: center;
    padding: 10px 12px;
    gap: 7px;
    font-size: .82rem;
    line-height: 1.28;
  }
  .perfil-chip svg { width: 16px; height: 16px; }
}

/* ═══════════════════════════════════════════════════════════════
   ANIMACIÓN DE ENTRADA AL SCROLLEAR

   El atributo data-reveal lo pone landing.js, nunca el HTML: si el
   JavaScript fallara, el contenido se queda visible en lugar de
   desaparecer para siempre.
   ═══════════════════════════════════════════════════════════════ */
/* Mientras landing.js reparte los data-reveal, la transición se apaga: si no,
   el navegador anima de opacidad 1 a 0 y el bloque se ve desvanecerse antes de
   entrar. Se quita en cuanto termina el etiquetado. */
.reveal-preparando [data-reveal] { transition: none !important; }

[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity .8s cubic-bezier(.22, 1, .36, 1),
              transform .8s cubic-bezier(.22, 1, .36, 1);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
/* Variante sin desplazamiento para elementos con position:sticky: moverlos
   con transform los saca de su contenedor y rompe el pegado. */
[data-reveal="fade"] { transform: none; }

[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;   /* se libera la capa de GPU una vez terminada */
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    transform: none;                      /* fundido puro, sin movimiento */
    transition-duration: .5s !important;
    transition-delay: var(--reveal-delay, 0ms) !important;
  }
}

/* ---------- Tarjeta con fotografía ---------- */
.card--foto { padding: 0; overflow: hidden; display: block; }
.card__foto {
  width: 100%;
  aspect-ratio: 8 / 5;
  object-fit: cover;
  /* Las fotos vienen del sitio anterior con fondo blanco; se generaron ya
     fundidas sobre --paper, así que empalman con la tarjeta sin costura. */
  background: var(--paper);
  transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}
.card--foto:hover .card__foto { transform: scale(1.035); }
.card--foto h3 { margin: 26px 32px .5em; }
.card--foto p  { margin: 0 32px 30px; }
@media (prefers-reduced-motion: reduce) {
  .card--foto:hover .card__foto { transform: none; }
}

/* ---------- Rejilla a sangre (procedimientos) ----------
   La rejilla vive fuera del .wrap, así que ya ocupa el ancho completo sin
   recurrir a 100vw ni a márgenes negativos, que en escritorio se cuelan por
   debajo de la barra de scroll. El encabezado sí se queda dentro del .wrap:
   un titular a todo lo ancho pierde legibilidad. */
.grid--sangrado {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;               /* pegadas entre sí, como en la web de referencia */
}
.grid--sangrado .card {
  border-radius: 0;
  box-shadow: none;
  border-right: 1px solid var(--sand-line);
}
.grid--sangrado .card:last-child { border-right: 0; }
.grid--sangrado .card--foto h3 { margin: 24px 26px .45em; font-size: clamp(1.1rem, 1.5vw, 1.28rem); }
.grid--sangrado .card--foto p  { margin: 0 26px 28px; font-size: .98rem; }

@media (max-width: 1100px) {
  .grid--sangrado { grid-template-columns: repeat(2, 1fr); }
  /* Con dos columnas el borde derecho sobra en las tarjetas pares */
  .grid--sangrado .card:nth-child(2n) { border-right: 0; }
  .grid--sangrado .card:nth-child(-n+2) { border-bottom: 1px solid var(--sand-line); }
}
@media (max-width: 640px) {
  .grid--sangrado { grid-template-columns: 1fr; }
  .grid--sangrado .card { border-right: 0; border-bottom: 1px solid var(--sand-line); }
  .grid--sangrado .card:last-child { border-bottom: 0; }
}




/* ---------- El pop-up de la agenda es el propio calendario ----------
   Sin tarjeta, sin relleno y sin fondo alrededor: el envé del calendario ya
   trae su propio diseño y encima quedaba una caja dentro de otra caja. */
#modal-cita .modal__panel {
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  overflow: visible;
  max-width: min(460px, 94vw);
}
#modal-cita .modal__body { padding: 0; }
#modal-cita #cal-mount {
  border-radius: var(--r-md);
  overflow: hidden;               /* recorta las esquinas del iframe */
  background: transparent;
}
/* El botón de cerrar flota sobre la esquina del propio calendario. Sacarlo por
   encima del panel lo dejaba fuera de pantalla cuando el modal arranca arriba. */
#modal-cita .modal__close {
  top: 12px; right: 12px;
  background: rgba(20, 39, 58, .08);
  color: var(--ink);
  backdrop-filter: blur(4px);
}
#modal-cita .modal__close:hover { background: rgba(20, 39, 58, .16); }

/* ═══════════════════════════════════════════════════════════════
   SECCIÓN CON FOTOGRAFÍA DE FONDO («Con quién te vas a operar»)

   Se usa <picture> y no background-image para conservar el WebP con su
   respaldo JPG y la carga diferida. El velo va en un pseudo-elemento
   aparte, no como filtro sobre la imagen, para no encarecer la composición.
   ═══════════════════════════════════════════════════════════════ */
.section--foto { position: relative; overflow: hidden; }

.section__fondo { position: absolute; inset: 0; z-index: 0; }
.section__fondo picture,
.section__fondo img { display: block; width: 100%; height: 100%; }
.section__fondo img { object-fit: cover; object-position: 50% 42%; }

/* Velo verde: la sección es --sage-deep con texto claro, así que la foto
   tiene que quedar por debajo del umbral de contraste del cuerpo de texto.
   Más denso a la izquierda, donde va el texto, y más abierto a la derecha,
   donde se deja ver el muro de certificaciones. */
.section__fondo::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(96deg,
      rgba(28, 45, 33, .95) 0%,
      rgba(28, 45, 33, .94) 58%,
      rgba(28, 45, 33, .86) 82%,
      rgba(28, 45, 33, .55) 100%);
}

.section--foto > .wrap { position: relative; z-index: 1; }

/* El texto ya no vive en una columna, así que necesita su propia medida:
   a todo lo ancho la línea se vuelve ilegible. */
.trayectoria__texto { max-width: 980px; }
.trayectoria__texto > .lead { max-width: 620px; }

@media (max-width: 900px) {
  /* En vertical el degradado lateral no cubre: se vuelve de arriba abajo */
  .section__fondo::after {
    background:
      linear-gradient(180deg,
        rgba(28, 45, 33, .93) 0%,
        rgba(28, 45, 33, .95) 55%,
        rgba(28, 45, 33, .96) 100%);
  }
  .trayectoria__texto { max-width: none; }
}


/* ---------- Entrada escalonada de las credenciales ----------
   Curva propia, más expresiva que la del resto de bloques: arranca rápido y
   frena largo al final (expo-out), con un desplazamiento algo mayor para que
   el escalonado se lea al bajar. */
.creds li[data-reveal] {
  transform: translateY(30px);
  transition:
    opacity   .72s cubic-bezier(.16, 1, .3, 1),
    transform .82s cubic-bezier(.16, 1, .3, 1);
  transition-delay: var(--reveal-delay, 0ms);
}
.creds li[data-reveal].is-revealed { transform: none; }

@media (max-width: 860px) {
  .creds { grid-template-columns: 1fr; }
  /* Vuelta a una columna: sólo el primero pierde el filete */
  .creds li:nth-child(-n+2) { border-top: 1px solid; border-top-color: inherit; padding-top: 17px; }
  .creds li:first-child { border-top: 0; padding-top: 0; }
  .creds li:nth-child(2)::before { top: 18px; }
  .creds li:first-child::before  { top: 1px; }
  .trayectoria__texto { max-width: none; }
}


/* Bloque de texto suelto dentro de una sección: necesita medida propia, que a
   todo lo ancho del contenedor la línea se vuelve incómoda de leer. */
.bloque-texto { max-width: 68ch; }
.bloque-texto h3 { margin-bottom: .6em; }

/* Bloque de autoridad sin imagen al lado: el titular y la entradilla necesitan
   medida propia para no cruzar los 1140px del contenedor. Las credenciales sí
   aprovechan todo el ancho, que ya van en dos columnas. */
/* La medida es 980px, la misma que .trayectoria__texto: el velo de
   .section__fondo está calibrado para que el contraste aguante hasta ese ancho.
   Si el bloque creciera, su borde derecho caería en la zona clara del degradado
   y el cuerpo de texto bajaría del mínimo AA. */
.bloque-autoridad { max-width: 980px; }
.bloque-autoridad > h2   { max-width: 22ch; }
.bloque-autoridad > .lead { max-width: 62ch; margin-bottom: 2.2rem; }

/* ═══════════════════════════════════════════════════════════════
   PROCESO EN DOS COLUMNAS QUE AVANZA CON EL SCROLL

   La sección mide N pantallas de alto y su contenido se ancla arriba: al bajar
   la vista no se mueve, pero la fase activa va cambiando. El alto extra es lo
   que da recorrido al scroll; el índice lo calcula landing.js desde la
   posición de la sección.
   ═══════════════════════════════════════════════════════════════ */
.proceso {
  /* Una pantalla por paso, más una de margen para entrar y salir */
  height: calc(var(--pasos, 6) * 78vh + 100vh);
  position: relative;
}
.proceso__fijo {
  position: sticky;
  top: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(240px, .82fr) 1.18fr;
  gap: clamp(36px, 6vw, 96px);
  align-items: center;
}

/* ---------- Columna izquierda: las fases ---------- */
.proceso__fases { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.proceso__fase {
  width: 100%;
  display: flex; align-items: baseline; gap: 16px;
  padding: 14px 4px;
  border: 0; background: none; cursor: pointer;
  font-family: var(--font-body);
  text-align: left;
  color: var(--ink-muted);
  transition: color .35s cubic-bezier(.16, 1, .3, 1);
}
.proceso__num {
  font-size: .78rem; letter-spacing: .1em;
  font-variant-numeric: tabular-nums;
  opacity: .55;
  transition: opacity .35s ease;
}
.proceso__rotulo {
  font-family: var(--font-head);
  font-size: clamp(1rem, 1.5vw, 1.18rem);
  line-height: 1.35;
  position: relative;
}
/* Filete que se rellena de izquierda a derecha en la fase activa */
.proceso__rotulo::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -6px;
  height: 1.5px; background: var(--sage);
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s cubic-bezier(.16, 1, .3, 1);
}
.proceso__fase:hover { color: var(--ink-soft); }
.proceso__fase[aria-current="true"] { color: var(--ink); }
.proceso__fase[aria-current="true"] .proceso__num { opacity: 1; color: var(--sage); }
.proceso__fase[aria-current="true"] .proceso__rotulo::after { transform: scaleX(1); }
.proceso__fase:focus-visible { outline: 2px solid var(--sage); outline-offset: 4px; border-radius: var(--r-sm); }

/* ---------- Columna derecha: los paneles ---------- */
.proceso__paneles {
  position: relative;
  min-height: 260px;
  /* La dirección la pone el JS según se baje o se suba */
  --entrada: 46px;
  --salida: -46px;
}
.proceso__paneles[data-dir="arriba"] { --entrada: -46px; --salida: 46px; }

.proceso__panel {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(var(--entrada));
  transition: opacity .42s cubic-bezier(.16, 1, .3, 1),
              transform .58s cubic-bezier(.16, 1, .3, 1),
              visibility 0s linear .6s;
}
/* El que entra: sube a su sitio y se descubre con un barrido desde abajo */
.proceso__panel[data-activo] {
  opacity: 1; visibility: visible; transform: none;
  transition-delay: 0s;
  /* El barrido lleva curva propia. La del desplazamiento, cubic-bezier(.16,1,.3,1),
     es muy frontal: a un cuarto del tiempo el borde ya iba por el 83% del
     recorrido y luego se arrastraba. Con esta la pasada se lee entera. */
  animation: barridoEntra .66s cubic-bezier(.38, .05, .2, 1);
}
.proceso__paneles[data-dir="arriba"] .proceso__panel[data-activo] { animation-name: barridoEntraArriba; }

/* El que sale se va en sentido contrario, no vuelve por donde vino */
.proceso__panel[data-saliente] {
  opacity: 0; visibility: visible;
  transform: translateY(var(--salida));
  transition-delay: 0s;
}

/* El barrido usa una máscara en degradado y no clip-path: el corte duro
   arrancaba el texto de golpe. Con la máscara, el borde que avanza lleva su
   propia transición de opacidad y el texto se va fundiendo a medida que sube.

   La máscara mide el triple que el panel y lo que se anima es su posición: al
   empezar, el panel cae sobre la zona transparente del degradado; al terminar,
   sobre la zona opaca. Las propiedades de máscara viven dentro de los
   fotogramas para que, al acabar, el panel se quede sin máscara ninguna. */
@keyframes barridoEntra {
  from {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 46%);
            mask-image: linear-gradient(to bottom, transparent 0%, #000 46%);
    -webkit-mask-size: 100% 300%;  mask-size: 100% 300%;
    -webkit-mask-position: 0% 0%;  mask-position: 0% 0%;
  }
  to {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 46%);
            mask-image: linear-gradient(to bottom, transparent 0%, #000 46%);
    -webkit-mask-size: 100% 300%;    mask-size: 100% 300%;
    -webkit-mask-position: 0% 100%;  mask-position: 0% 100%;
  }
}
@keyframes barridoEntraArriba {
  from {
    -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 46%);
            mask-image: linear-gradient(to top, transparent 0%, #000 46%);
    -webkit-mask-size: 100% 300%;    mask-size: 100% 300%;
    -webkit-mask-position: 0% 100%;  mask-position: 0% 100%;
  }
  to {
    -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 46%);
            mask-image: linear-gradient(to top, transparent 0%, #000 46%);
    -webkit-mask-size: 100% 300%;  mask-size: 100% 300%;
    -webkit-mask-position: 0% 0%;  mask-position: 0% 0%;
  }
}
.proceso__panel h3 { font-size: clamp(1.5rem, 2.8vw, 2.15rem); margin-bottom: .55em; }
.proceso__panel p  { font-size: 1.08rem; line-height: 1.72; margin: 0; }
.proceso__fase-movil { display: none; }

@media (prefers-reduced-motion: reduce) {
  /* No se desactiva, se acorta y se le quita el desplazamiento: el barrido es
     el contenido apareciendo, no un adorno, y sin él el cambio de paso pasa
     desapercibido. Misma decisión de cliente que en el acordeón de las FAQ. */
  .proceso__panel { transform: none; transition-duration: .3s !important; }
  .proceso__panel[data-saliente] { transform: none; }
  .proceso__panel[data-activo] { animation-duration: .42s !important; }
}

@media (max-width: 900px) {
  /* En vertical no hay sitio para dos columnas ni para anclar: se despliega
     todo en una lista normal y el scroll vuelve a ser el de siempre. */
  .proceso { height: auto; }
  .proceso__fijo { position: static; min-height: 0; display: block; }
  .proceso__fases { display: none; }
  .proceso__paneles { position: static; min-height: 0; display: grid; gap: 30px; }
  .proceso__panel {
    position: static; opacity: 1; visibility: visible; transform: none;
    background: var(--paper); border-radius: var(--r-lg);
    padding: 26px 28px; box-shadow: var(--shadow-soft);
  }
  .proceso__fase-movil {
    display: block; font-size: .8rem; letter-spacing: .1em; text-transform: uppercase;
    color: var(--clay); margin: 0 0 .5rem;
  }
  .proceso__panel h3 { font-size: 1.3rem; }
  .proceso__panel p { font-size: 1rem; }
}

/* El antetítulo del CTA final va en píldora: sobre el verde salvia, el texto
   suelto en #B9CDBB se diluye en el fondo y no ancla la sección. */
.cta-final .eyebrow {
  display: inline-block;
  margin-inline: auto;
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #EAF2EB;
  backdrop-filter: blur(2px);
}

/* ---------- Fondo fotográfico del CTA final ----------
   Aquí el texto va centrado y ocupa el ancho medio, así que el velo es
   uniforme y no en degradado como en las secciones de autoridad.
   La densidad no es estética: con el verde de la sección (58,85,65) haría
   falta más del 96 % para que el .lead llegase al mínimo AA, y a esa opacidad
   la foto ya no se vería. Con este verde más oscuro basta el 82 % y quedan
   4,81:1 en el peor caso, sobre un píxel blanco de la fotografía. */
.cta-final .section__fondo::after {
  background: rgba(28, 45, 33, .82);
}
.cta-final .section__fondo img { object-position: 50% 62%; }

/* ---------- Sello de la American Association of Tissue Banks ----------
   Va en línea con el texto de la credencial. El color se hereda con
   currentColor, así que basta cambiar `color` según el fondo. */
.logo-aatb {
  display: inline-block;
  height: 1.18em;
  width: auto;
  vertical-align: -.3em;
  margin-left: .32em;
  color: #36671D;
}
/* Sobre el velo verde oscuro de las secciones de autoridad, el #36671D queda
   en 2,15:1 y no se distingue del fondo. Se aclara al mismo verde de marca
   pero legible: 7,07:1. */
.section--deep .logo-aatb { color: #8CC46C; }

/* ==========================================================================
   EL BANCO DE TEJIDOS — sección propia con el retrato recortado

   La foto va a sangre contra el borde inferior: por eso la sección no lleva
   relleno abajo y se lo pone la columna de texto, que sí lo necesita. El
   `align-items: end` de la rejilla es lo que apoya al doctor en esa línea.

   `overflow: hidden` no es decorativo: en pantallas estrechas la foto se
   ensancha por encima de su columna y sin recorte asomaría por el costado.
   ========================================================================== */
.banco {
  background: #ECE2DF;
  padding-bottom: 0;
  overflow: hidden;
}
.banco__grid {
  display: grid;
  grid-template-columns: 1.06fr .94fr;
  gap: clamp(28px, 4vw, 68px);
  align-items: end;
}
.banco__texto { padding-bottom: clamp(64px, 9vw, 120px); }
.banco__texto h2 { margin-bottom: .5em; }

/* ---------- El sello de verificado del titular ----------
   Va en el flujo del texto y no absoluto: así el titular se parte solo en
   pantallas estrechas y el sello se lleva la primera línea con él, sin
   solaparse con nada. */
.banco__titulo { display: flex; align-items: center; gap: .5em; flex-wrap: wrap; }
.banco__check {
  flex: 0 0 auto;
  width: 1.16em; height: 1.16em;
  border-radius: 50%;
  background: var(--sage);
  color: var(--paper);
  display: inline-grid; place-items: center;
  /* Entra girando y creciendo desde nada, un pelo después que el texto: el
     retraso es lo que hace que se lea como un sello que se estampa y no como
     una parte más del titular. */
  transform: scale(.2) rotate(-35deg);
  opacity: 0;
  transition: transform .62s cubic-bezier(.34, 1.56, .64, 1),
              opacity   .32s ease-out;
  transition-delay: .18s;
}
.banco__check svg { width: .62em; height: .62em; }
[data-reveal].is-revealed .banco__check,
.banco__texto:not([data-reveal]) .banco__check {
  transform: none;
  opacity: 1;
}

/* La figura entra más tarde y desde más abajo que el texto: apoyada en el
   borde, subir es el único gesto que no la despega de él.

   El `:not(.is-revealed)` no es cosmético. `[data-reveal].is-revealed` tiene
   la misma especificidad que `.banco__foto[data-reveal]` —una clase y un
   atributo cada uno— y esta regla va después en el archivo, así que ganaba
   también una vez revelada y la foto se quedaba desplazada para siempre. */
.banco__foto[data-reveal]:not(.is-revealed) { transform: translateY(52px); }
.banco__foto[data-reveal] { transition-delay: .26s; }
.banco__texto p + p { margin-top: 1em; }
.banco__foto picture { display: block; }
.banco__foto img {
  display: block;
  width: 100%;
  height: auto;
  /* Pegada abajo del todo: es lo que hace que se lea como si estuviera de pie
     sobre el borde de la sección y no flotando dentro de ella. */
  margin-bottom: -1px;   /* mata el hueco de línea base del inline */
}
@media (max-width: 900px) {
  .banco__grid { grid-template-columns: 1fr; gap: 0; }
  .banco__texto { padding-bottom: clamp(28px, 5vw, 44px); }
  /* De frente ocupa demasiado alto; centrada y algo más chica respira mejor */
  .banco__foto { max-width: 420px; margin-inline: auto; width: 100%; }
}

/* ---------- Sellos de la U.A.N.L. y de la Universidad de Navarra ----------
   Van bastante más altos que el de la AATB (1,18em) a propósito. Aquél es un
   logotipo de cuatro letras y se lee a cualquier tamaño; éstos son sellos con
   trazo muy fino y por debajo de ~36px se convierten en una mancha. A 2,15em
   sobre el cuerpo de 18,5px salen 40px, que es donde empiezan a leerse.
   `vertical-align: middle` los deja repartidos por igual arriba y abajo del
   renglón; la línea que los contiene crece unos 10px y ninguna otra se mueve. */
.logo-uanl,
.logo-navarra {
  display: inline-block;
  height: 2.15em;
  width: auto;
  vertical-align: middle;
  margin-left: .34em;
}

/* El escudo de la U.A.N.L. es una mancha de color con anillo claro y aguanta
   solo sobre el velo verde. El de Navarra es de línea: a 40px el trazo no
   llega a cubrir un píxel entero, así que sobre fondo oscuro el rojo se mezcla
   y vira a marrón (2,65:1 en el peor caso) — y aclararlo lo vuelve gris. Se
   resuelve con la placa clara que usa cualquier manual de marca para fondos
   oscuros: el rojo institucional se conserva y se lee. */
.section--deep .logo-navarra {
  background: var(--sand);
  border-radius: 7px;
  padding: 2px 4px;
  box-sizing: content-box;
}
