/* ─────────────────────────────────────────────────────────────────────────
   Patrones — capa de componentes y plantillas de página
   Implementa "Dra Bianka Vazquez - 04 Patrones.dc.html" sobre los tokens
   del design system. Nada de valores sueltos: todo sale de tokens/*.css.

   Reglas duras del capítulo, codificadas aquí:
   · Blanco es el fondo por defecto. Máximo dos bandas coloreadas por página,
     nunca contiguas  → .band--warm / .band--sky / .band--muted
   · El letrero corrido aparece UNA sola vez por página, como bisagra.
   · Ninguna página termina en texto: antes del pie va galería o llamado.
   · Esquinas rectas en todo menos botones y chips (--radius-pill).
   · Sin emoji. Sin iconos fuera de social y utilería.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Paleta del arte de campaña ──────────────────────────────────────────
   El manual pinta sobre blanco puro y reserva el nude/celeste para redes.
   Decisión de Juan: el sitio toma la paleta del arte. La página deja de ser
   blanco clínico y arranca en un nude muy diluido; las tarjetas se quedan en
   blanco puro y por contraste ganan presencia. El azul de marca sigue siendo
   el único acento fuerte. */
:root {
  --surface-page: #FCFAF8;
  --superficie-tarjeta: var(--neutral-0);
}

/* El resaltador del arte: fondo #96C1FD detrás de una frase, como en la
   pieza de Rinoplastía Ultrasónica. Se usa UNA vez por página. */
.marca-alta {
  background: var(--highlight-mark);
  color: var(--brand-blue-ink);
  padding: 0.08em 0.28em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ── Layout ──────────────────────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--narrow { max-width: var(--container-narrow); }

/* Bandas: el ritmo vertical es el recurso de layout más fuerte del sistema. */
.band { padding-block: var(--section-y); }
.band--tight { padding-block: var(--section-y-tight); }
.band--warm { background: var(--surface-warm); color: var(--text-on-warm); }
.band--sky { background: var(--surface-sky); }
.band--muted { background: var(--surface-muted); }
.band--invert { background: var(--surface-invert); color: var(--text-on-dark); }
.band--brand { background: var(--surface-brand); color: var(--text-on-brand); }

/* Imagen a sangre: escapa del contenedor. */
.bleed { width: 100%; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-7);
  align-items: center;
}
.split--text-heavy { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
.split--top { align-items: start; }

.stack { display: flex; flex-direction: column; gap: var(--stack-gap); }

/* ── Tipografía de rol ───────────────────────────────────────────────── */

.eyebrow {
  font: var(--type-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-brand);
}
.eyebrow--muted { color: var(--text-muted); }
.eyebrow--on-dark { color: rgba(255, 255, 255, 0.8); }
.eyebrow--on-warm { color: var(--text-on-warm); }

.hero-title {
  font: var(--type-hero);
  letter-spacing: var(--tracking-hero);
  color: var(--text-on-dark);
  margin: 0;
  max-width: 16ch;
}

.display {
  font: var(--type-display);
  letter-spacing: var(--tracking-display);
  color: var(--text-strong);
  margin: 0;
  max-width: 20ch;
}
/* Titular de portada de sección: crece con la pantalla. */
.display--grande { font-size: clamp(2.5rem, 5.2vw, 5rem); line-height: 1.04; }

.h2 {
  font: var(--type-h2);
  letter-spacing: var(--tracking-heading);
  color: var(--text-strong);
  margin: 0;
}

.h3 { font: var(--type-h3); color: var(--text-strong); margin: 0; }
.h4 { font: var(--type-h4); color: var(--text-strong); margin: 0; }

.lede { font: var(--type-body-lg); color: var(--text-body); max-width: 62ch; }

.prose { font: var(--type-body); color: var(--text-body); }
.prose p { margin-block-end: var(--space-4); }
.prose p:last-child { margin-block-end: 0; }
.prose strong { color: var(--text-strong); font-weight: var(--weight-medium); }
.prose h2 { font: var(--type-h3); color: var(--text-strong); margin: var(--space-8) 0 var(--space-4); }
.prose h3 { font: var(--type-h4); color: var(--text-strong); margin: var(--space-7) 0 var(--space-3); }
.prose a { text-decoration: underline; text-underline-offset: 3px; }

.meta { font: var(--type-small); color: var(--text-muted); }

/* Los procedimientos se leen como texto corrido, nunca como lista con viñeta. */
.run { font: var(--type-body); line-height: var(--leading-loose); color: var(--text-body); }

/* Barra de 8px: eco del logotipo, marca bloques de énfasis. */
.rule-block { display: flex; gap: var(--space-5); align-items: stretch; }
.rule-block::before {
  content: "";
  flex: 0 0 var(--rule-width);
  background: var(--brand-blue);
}

/* ── Botones ─────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border: var(--border-width) solid transparent;
  border-radius: var(--button-radius);
  font: var(--type-button);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn:hover { opacity: 1; }
.btn:active { transform: scale(0.98); }
.btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

.btn--primary { background: var(--brand-blue); color: var(--text-on-brand); }
.btn--primary:hover { background: var(--brand-blue-hover); }
.btn--primary:active { background: var(--brand-blue-press); }

.btn--outline { border-color: var(--brand-blue); color: var(--brand-blue); background: transparent; }
.btn--outline:hover { background: var(--brand-blue); color: var(--text-on-brand); }

.btn--on-dark { border-color: rgba(255, 255, 255, 0.85); color: #fff; background: transparent; }
.btn--on-dark:hover { background: #fff; color: var(--brand-blue); }

/* WhatsApp: el único color ajeno del sistema, y solo aquí. */
.btn--whatsapp { background: var(--accent-whatsapp); color: #fff; }
.btn--whatsapp:hover { background: var(--accent-whatsapp); filter: brightness(0.95); }
.btn--whatsapp:active { background: var(--accent-whatsapp-press); }
.btn--whatsapp .icon { filter: brightness(0) invert(1); }

.btn--wide { width: 100%; }

.icon { width: 20px; height: 20px; flex: 0 0 auto; }
.icon--sm { width: 16px; height: 16px; }

.textlink {
  font: var(--type-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-blue);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.tag {
  display: inline-flex;
  padding: var(--space-1) var(--space-3);
  font: var(--type-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: var(--border-width) solid var(--border-default);
  color: var(--text-body);
  border-radius: var(--radius-none);
}

/* ── Encabezado y menú fuera de lienzo ───────────────────────────────── */

.site-header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-4) var(--gutter);
  transition: background var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
/* El encabezado se queda transparente siempre, como en el sitio actual: sin
   fondo, sin desenfoque y sin filete al hacer scroll. */
.site-header[data-scrolled="1"] {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}
/* Logotipo horizontal de una línea (el del sitio actual): se lee mucho mejor
   que el bloque apilado. Proporción 1861×216 ≈ 8.6:1. */
.site-header__logo { height: 30px; width: auto; }
.site-footer__logo { height: 26px; width: auto; }

/* Sobre el hero el encabezado es transparente y el logo va en blanco; al hacer
   scroll el fondo se vuelve blanco translúcido y ese logo desaparecía. Se
   cargan los dos y se alterna. */
.site-header__marca { position: relative; display: block; line-height: 0; }
.site-header__logo--oscuro { position: absolute; inset-block-start: 0; inset-inline-start: 0; opacity: 0; }
.site-header__logo--claro { opacity: 1; }
.site-header__logo--claro,
.site-header__logo--oscuro { transition: opacity var(--dur-base) var(--ease-out); }
.site-header[data-scrolled="1"] .site-header__logo--claro,
.site-header:not([data-over-hero="1"]) .site-header__logo--claro { opacity: 0; }
.site-header[data-scrolled="1"] .site-header__logo--oscuro,
.site-header:not([data-over-hero="1"]) .site-header__logo--oscuro { opacity: 1; }
.site-header__social { display: flex; align-items: center; gap: var(--space-4); }

/* Botón en círculo, como el logo: blanco sobre el hero y azul al bajar, para
   que nunca se pierda contra el fondo claro de la página. */
/* El color va por variable heredada del encabezado: así no depende de qué
   regla gana por especificidad, que es donde se estaba atorando. */
.site-header { --menu-fondo: #fff; }
.site-header[data-scrolled="1"],
.site-header:not([data-over-hero="1"]) { --menu-fondo: var(--brand-blue); }

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  /* background-color, no background: animar el atajo con un valor que viene
     de una variable deja el color congelado en el valor inicial. */
  background-color: var(--menu-fondo);
  border: 0;
  border-radius: var(--radius-pill);
  padding: 0;
  cursor: pointer;
  box-shadow: var(--shadow-card);
  transition: background-color var(--dur-base) var(--ease-out);
}
/* Doble seguro: además de la variable, la regla directa. Si un navegador se
   atora resolviendo el custom property, esta lo cubre. */
.site-header[data-scrolled="1"] .menu-toggle,
.site-header:not([data-over-hero="1"]) .menu-toggle { background-color: var(--brand-blue); }

.menu-toggle__texto { display: none; }
.menu-toggle .icon { filter: none; }
.site-header:not([data-over-hero="1"]) .menu-toggle .icon { filter: brightness(0) invert(1); }
/* El ícono se invierte a blanco cuando el círculo se pone azul. */
.site-header[data-scrolled="1"] .menu-toggle .icon { filter: brightness(0) invert(1); }
.menu-toggle:focus-visible { outline: none; box-shadow: var(--shadow-focus), var(--shadow-card); }

/* Redes: blancas sobre el hero oscuro, azules al bajar sobre el fondo claro.
   Mismo criterio que el logotipo y el botón del menú: nunca se pierden. */
.site-header__social > a .icon {
  filter: brightness(0) invert(1);
  transition: filter var(--dur-base) var(--ease-out);
}
/* brightness(0) las vuelve negras; el resto de filtros las lleva al azul de
   marca #0043C5 sin necesidad de un segundo juego de archivos. */
.site-header[data-scrolled="1"] .site-header__social > a .icon,
.site-header:not([data-over-hero="1"]) .site-header__social > a .icon {
  filter: brightness(0) saturate(100%) invert(19%) sepia(89%) saturate(3900%) hue-rotate(215deg) brightness(94%) contrast(101%);
}

/* SIN velo encima de la página. Con el menú abierto la página se encoge y se
   ve nítida, como en la referencia; el velo oscuro la dejaba gris lavada y su
   desvanecido al cerrar era la transición rara.
   Se conserva la capa, invisible, solo para cerrar al hacer clic fuera. */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: transparent;
  pointer-events: none;
}
.scrim[data-open="1"] { pointer-events: auto; }

/* Réplica del menú del sitio actual (Salient «material»): panel desde la
   derecha, fondo oscuro, enlaces enormes en blanco (54 px) y el contenido de
   atrás encogiéndose. Lo medí en vivo en drabiankavazquez.com. */
/* El menú no se desliza encima: se REVELA. La página se encoge hacia la
   izquierda y el menú queda en la franja negra de la derecha, con un botón
   circular de cerrar en la frontera. Igual que el sitio actual. */
.pagina {
  position: relative;
  z-index: 1;
  background: var(--surface-page);
  transition: transform var(--dur-slow) var(--ease-out);
}
/* El espacio de la barra de scroll se reserva SIEMPRE. Si no, al abrir el menú
   (overflow:hidden) desaparece, la página se ensancha, y al cerrar vuelve a
   angostarse a media animación: ese era el brinco raro. */
html { scrollbar-gutter: stable; }
body[data-menu="1"] { overflow: hidden; }
/* OJO con el origen: un 50% aquí se calcula sobre el alto TOTAL del documento
   (miles de px), no sobre la pantalla, y la página se iba hacia abajo. El
   punto exacto lo pone sitio.js en --menu-origen-y: el centro de lo que el
   usuario está viendo. Así encoge en su sitio y se recorre a la izquierda. */
/* La página ya NO se transforma. El menú es una capa aparte que se abre como
   un círculo creciendo desde el botón: una sola animación, imposible que se
   desfase con nada. */

/* Capa a pantalla completa que se revela como un círculo naciendo del botón.
   sitio.js pone --menu-x / --menu-y (centro del botón) y --menu-r (radio que
   alcanza la esquina más lejana). Una sola propiedad animada: clip-path. */
.offcanvas {
  position: fixed;
  inset: 0;
  z-index: 70;
  /* Azul de marca, no negro: es el único color del sistema y a pantalla
     completa es donde más presencia tiene. El negro no decía nada. */
  background: var(--brand-blue);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: var(--space-8);
  pointer-events: none;
  clip-path: circle(0px at var(--menu-x, 100%) var(--menu-y, 0px));
  transition: clip-path 620ms var(--ease-out);
}
.offcanvas[data-open="1"] {
  pointer-events: auto;
  clip-path: circle(var(--menu-r, 150vmax) at var(--menu-x, 100%) var(--menu-y, 0px));
}

/* Botón circular de cerrar, sobre la frontera entre la página y el menú. */
/* Ocupa el mismo sitio que la hamburguesa: se siente el mismo control. */
.offcanvas__cerrar {
  position: fixed;
  inset-inline-end: var(--gutter);
  inset-block-start: var(--space-4);
  z-index: 75;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius-pill);
  background: #fff;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease-out);
}
body[data-menu="1"] .offcanvas__cerrar { opacity: 1; pointer-events: auto; transition-delay: 380ms; }
.offcanvas__cerrar:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

.offcanvas__nav { display: flex; flex-direction: column; gap: var(--space-2); align-items: center; text-align: center; }
/* Los enlaces entran DESPUÉS de que el círculo terminó de abrirse. */
.offcanvas__nav a, .offcanvas__foot {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out);
}
.offcanvas[data-open="1"] .offcanvas__nav a,
.offcanvas[data-open="1"] .offcanvas__foot { opacity: 1; transform: none; }
.offcanvas[data-open="1"] .offcanvas__nav a:nth-child(1) { transition-delay: 380ms; }
.offcanvas[data-open="1"] .offcanvas__nav a:nth-child(2) { transition-delay: 440ms; }
.offcanvas[data-open="1"] .offcanvas__nav a:nth-child(3) { transition-delay: 500ms; }
.offcanvas[data-open="1"] .offcanvas__nav a:nth-child(4) { transition-delay: 560ms; }
.offcanvas[data-open="1"] .offcanvas__nav a:nth-child(5) { transition-delay: 620ms; }
.offcanvas[data-open="1"] .offcanvas__foot { transition-delay: 680ms; }
.offcanvas__nav a {
  font: var(--weight-light) clamp(2rem, 6vw, 3.375rem) / 1.15 var(--font-display);
  letter-spacing: var(--tracking-display);
  color: #fff;
}
.offcanvas__nav a:hover { color: var(--sky-mark); opacity: 1; }
.offcanvas__nav a[aria-current="page"] { border-block-end: 2px solid #fff; }
.offcanvas__foot .meta { color: rgba(255, 255, 255, 0.55); }
.offcanvas__foot a:not(.btn) { color: #fff; }

.offcanvas__foot { text-align: center; display: flex; flex-direction: column; gap: var(--space-4); }

/* ── Hero a sangre ───────────────────────────────────────────────────── */

/* Pantalla completa: la foto ocupa todo el alto visible, sin que asome la
   siguiente banda. 100svh evita el salto por la barra del navegador móvil. */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  background: var(--surface-invert);
  overflow: hidden;
}
.hero__media { position: absolute; inset: 0; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; opacity: 0.55; }
/* Protección de abajo hacia arriba, nunca una cápsula detrás del texto. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0) 60%);
}
/* Variante para fotografía de banco (clara) en vez de caso clínico (oscuro).
   El 0.55 del hero base está calibrado para una foto oscura sobre negro; con
   una toma de fondo gris claro deja la imagen lodosa. Aquí la imagen se ve
   casi entera y la legibilidad la sostiene el degradado de protección, que
   sube porque el titular blanco cae sobre piel y gris claro. */
/* Como la referencia: la cara LLENA el encuadre. La foto de origen trae mucho
   fondo gris vacío alrededor del sujeto, así que se acerca sobre el rostro en
   vez de mostrarla completa. */
/* La foto entra atenuada, como en el sitio actual: sobre el fondo oscuro se
   suaviza y el titular blanco se despega sin necesidad de velos pesados. */
.hero--editorial .hero__media img {
  opacity: 0.72;
  object-position: 58% 40%;
  transform-origin: 58% 42%;
}
.hero--editorial::after {
  background:
    linear-gradient(to top, rgba(0, 0, 0, 0.68) 0%, rgba(0, 0, 0, 0.30) 38%, rgba(0, 0, 0, 0.10) 70%, rgba(0, 0, 0, 0.22) 100%);
}

/* El titular va centrado en los dos ejes: a media altura del hero, no abajo. */
.hero--editorial { align-items: center; }
.hero--editorial .hero__body { padding-block-end: 0; }
.hero--editorial .hero__body .container { text-align: center; }
/* Titular a la escala de la referencia: crece con el ancho de la pantalla en
   vez de quedarse en los 88 px del sistema. */
.hero--editorial .hero-title {
  font-size: clamp(2.75rem, 7.4vw, 8.5rem);
  line-height: 0.98;
  max-width: 15ch;
  margin-inline: auto;
}
.hero--editorial .hero__cta { justify-content: center; }

.hero__body { position: relative; z-index: 1; width: 100%; padding-block-end: var(--space-9); }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-block-start: var(--space-6); }
.hero__scroll {
  font: var(--type-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
  margin-block-start: var(--space-6);
}

/* ── Galería de casos ────────────────────────────────────────────────── */

.gallery {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2px;
}
.gallery--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* La serie antigua es 16:9. En dos columnas cada caso salía a 608 px de ancho
   y se veía desproporcionado frente al resto de la página. Tres columnas la
   dejan en escala con las galerías cuadradas. */
.gallery--wide { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.gallery-grupo + .gallery-grupo { margin-block-start: var(--space-8); }
.gallery-grupo__titulo { display: flex; align-items: baseline; gap: var(--space-3); margin-block-end: var(--space-4); }

.case {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--surface-invert);
  overflow: hidden;
  display: block;
}
/* Va DESPUÉS de .case a propósito: misma especificidad, gana el último. */
.case--wide { aspect-ratio: 16 / 9; }

.case img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.case:hover img { transform: scale(1.04); }
.case__caption {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: var(--space-4);
  font: var(--type-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(to top, var(--case-scrim), rgba(0, 0, 0, 0));
  opacity: 0.6;
  transition: opacity var(--dur-base) var(--ease-out);
}
.case:hover .case__caption { opacity: 1; }

/* ── Letrero corrido (una vez por página) ────────────────────────────── */

/* Sin filetes arriba y abajo: el letrero flota, no va encajonado.
   Más grande y con aire debajo. */
.marquee {
  overflow: hidden;
  white-space: nowrap;
  padding-block: var(--space-7) var(--space-9);
}
.marquee__track {
  display: inline-flex;
  animation: marquee var(--marquee-dur) linear infinite;
}
/* Letra contorneada, sin relleno — como en el sitio actual. Pesa mucho menos
   en la página que el azul sólido y deja respirar la banda. */
.marquee__track span {
  font: var(--weight-light) clamp(3rem, 6.5vw, 7rem) / 1 var(--font-display);
  letter-spacing: var(--tracking-display);
  color: transparent;
  -webkit-text-stroke: 1px var(--brand-blue);
  text-stroke: 1px var(--brand-blue);
  padding-inline-end: var(--space-7);
  white-space: nowrap;
}
.marquee__track span i { display: none; }
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ── Sello circular ──────────────────────────────────────────────────────
   El texto en círculo del sitio actual, girando lento sobre la fotografía.
   Va una sola vez por página, como el letrero. */
.sello {
  position: absolute;
  inset-block-end: var(--space-6);
  inset-inline-start: var(--space-6);
  width: 148px;
  height: 148px;
  z-index: 2;
  animation: selloGira 26s linear infinite;
}
/* Como en el sitio actual: centrado abajo y partido por el borde inferior del
   hero — se ve solo la mitad superior del aro. El recorte lo hace el
   overflow:hidden del propio hero. */
.sello--hero {
  inset-block-end: -85px;
  inset-inline-start: 50%;
  inset-inline-end: auto;
  width: 170px;
  height: 170px;
  margin-inline-start: -85px;
}
.sello text { font: var(--weight-semibold) 11.5px var(--font-display); letter-spacing: 0.22em; fill: #fff; text-transform: uppercase; }
.sello--azul text { fill: var(--brand-blue); }
@keyframes selloGira { to { transform: rotate(360deg); } }

/* ── Tarjetas ────────────────────────────────────────────────────────── */

.card {
  background: var(--surface-card);
  box-shadow: var(--shadow-card);
  border-radius: var(--radius-none);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: box-shadow var(--dur-base) var(--ease-out);
}
.card:hover { box-shadow: var(--shadow-raised); }
.card__media { aspect-ratio: 16 / 10; background: var(--neutral-100); overflow: hidden; }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.card:hover .card__media img { transform: scale(1.04); }
.card__body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); }

.card-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-5); }
.card-grid--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Dos tarjetas: ocupan el ancho a la mitad cada una, sin hueco a la derecha. */
.card-grid--dos { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Tarjeta de procedimiento: media 4/5, sin sombra, borde hairline. */
.procedure {
  display: flex;
  flex-direction: column;
  border: var(--border-width) solid var(--border-hairline);
  background: var(--surface-card);
  transition: border-color var(--dur-base) var(--ease-out);
}
.procedure:hover { border-color: var(--brand-blue); }
.procedure__media { aspect-ratio: 4 / 5; background: var(--surface-invert); overflow: hidden; }

/* REGLA DURA: un caso clínico es un antes-y-después pegados en un solo cuadro,
   con la nariz operada contra el borde derecho. NUNCA se recorta: cualquier
   caja con proporción distinta a la del archivo le corta la nariz al "después",
   que es justo lo que la foto viene a demostrar.
   Cada caso se muestra en SU proporción nativa. Hoy hay dos series:
     · 1:1   — serie actual (800×800), fondo oscuro
     · 16:9  — serie antigua (1422×800), fondo azul
   Si un componente necesita otra proporción, no lleva caso clínico: lleva
   quirófano, banco editorial o el placeholder. */
/* Las tarjetas de procedimiento conviven en una fila, y la rejilla iguala
   alturas: mezclar una 16:9 con dos 1:1 dejaba un bloque vacío enorme bajo la
   corta. Las tres van en 16:9 y la imagen entra con `contain`, que NO recorta.
   El fondo de la caja es el mismo near-black del fondo de las fotos, así que
   los costados no se ven como marco. */
.procedure__media--caso,
.procedure__media--caso-wide { aspect-ratio: 16 / 9; }
.procedure__media--caso img,
.procedure__media--caso-wide img { object-fit: contain; }
.procedure__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.procedure:hover .procedure__media img { transform: scale(1.04); }
.procedure__body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-2); }

/* Tarjeta de servicio: SIN imagen. Cuatro de los seis procedimientos no
   tienen caso fotografiado, y meter un placeholder en cada uno sería ruido.
   La información es el contenido; la tipografía la sostiene sola. */
.servicio {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-hairline);
  transition: border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.servicio:hover { border-color: var(--brand-blue); box-shadow: var(--shadow-card); opacity: 1; }
.servicio__mas {
  margin-block-start: auto;
  padding-block-start: var(--space-4);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font: var(--type-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-blue);
}

/* ── Credenciales y cifras ───────────────────────────────────────────── */

.credential { font: var(--type-body); line-height: var(--leading-loose); color: var(--text-body); }

.stat__value {
  font: var(--weight-light) 3rem / 1 var(--font-display);
  color: var(--brand-blue);
}
.stat__label {
  font: var(--type-eyebrow);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-body);
  margin-block-start: var(--space-2);
}

.stat-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; }
.stat-row > * { padding: var(--space-5); }

/* Lista de credenciales agrupada — corrige el "volcado de currículum". */
.cred-group { display: flex; flex-direction: column; gap: var(--space-3); }
/* El currículum es EL argumento de la página: se lee, no se ojea. */
.cred-group { gap: var(--space-4); }
.cred-group li {
  list-style: none;
  padding-inline-start: var(--space-5);
  border-inline-start: var(--border-width-thick) solid var(--nude-200);
  font: var(--type-body);
  font-size: 1.125rem;
  line-height: var(--leading-body);
  color: var(--text-on-warm);
}
.cred-group--cool li { border-inline-start-color: var(--border-hairline); color: var(--text-body); }

/* ── Preguntas frecuentes ────────────────────────────────────────────── */

.faq { border-block-start: var(--border-width) solid var(--border-hairline); }
.faq__item { border-block-end: var(--border-width) solid var(--border-hairline); }
.faq__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) 0;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: start;
  font: var(--type-h4);
  color: var(--text-strong);
}
.faq__q:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.faq__item[data-open="1"] .faq__q { color: var(--brand-blue); }
.faq__sign { color: var(--brand-blue); transition: transform var(--dur-base) var(--ease-out); flex: 0 0 auto; }
.faq__item[data-open="1"] .faq__sign { transform: rotate(45deg); }
/* La pregunta va en <h3> por jerarquía de encabezados; el botón ya define la
   tipografía, así que el heading solo hereda. `flex: 1` y `min-width: 0` para
   que ceda espacio: sin eso, en móvil una pregunta larga empuja el signo «+»
   fuera del botón. */
.faq__q h3 { font: inherit; color: inherit; margin: 0; flex: 1; min-width: 0; }

/* Se pliega con grid en vez de `display: none`.
   Motivo: las respuestas son la materia prima de los motores de respuesta, y
   `display: none` las saca del árbol accesible. Colapsando la fila a 0fr el
   texto sigue en el documento y en el árbol, solo que sin alto. `min-height: 0`
   no es opcional: sin él el hijo conserva su alto automático y nunca llega a 0. */
/* Sin transición sobre grid-template-rows: al animarla, `1fr` se resuelve contra
   un contenedor que todavía mide 0 y la fila se queda clavada en cero. El patrón
   original tampoco animaba (alternaba display), así que no se pierde nada. */
.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  font: var(--type-body);
  color: var(--text-body);
  max-width: 68ch;
}
/* Tres niveles a propósito: la fila (0fr↔1fr), el recortador y el contenido.
   El relleno vive en el contenido, DENTRO de lo que se recorta. Puesto en el
   recortador le pondría un piso de altura —box-sizing es border-box— y además
   realimentaría la resolución de `1fr`, que se quedaba clavada en el alto del
   propio padding. */
.faq__a > * { overflow: hidden; min-height: 0; }
.faq__a p { margin: 0; padding-block-end: var(--space-5); }
.faq__item[data-open="1"] .faq__a { grid-template-rows: 1fr; }

/* ── Chips de filtro ─────────────────────────────────────────────────── */

.filters { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); }
.chip {
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-pill);
  border: var(--border-width) solid var(--border-default);
  background: transparent;
  color: var(--text-body);
  font: var(--type-button);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: var(--transition-base);
}
.chip:hover { border-color: var(--brand-blue); color: var(--brand-blue); }
.chip[aria-pressed="true"] { background: var(--brand-blue); border-color: var(--brand-blue); color: #fff; }
.chip:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* ── Migaja e índice fijo ────────────────────────────────────────────── */

.breadcrumb { font: var(--type-small); color: var(--text-muted); }
.breadcrumb a { color: var(--text-muted); }
.breadcrumb a:hover { color: var(--brand-blue); opacity: 1; }
.breadcrumb span { color: var(--neutral-200); padding-inline: var(--space-2); }

/* Índice fijo a la derecha — sustituye el que generaba el plugin. */
.editorial { display: grid; grid-template-columns: minmax(0, var(--container-narrow)) 240px; gap: var(--space-8); align-items: start; }
.toc { position: sticky; top: 120px; display: flex; flex-direction: column; gap: var(--space-3); }
.toc a {
  font: var(--type-small);
  color: var(--text-muted);
  padding-inline-start: var(--space-4);
  border-inline-start: var(--border-width) solid var(--border-hairline);
  padding-block: var(--space-1);
}
.toc a[data-active="1"] { color: var(--brand-blue); border-inline-start-color: var(--brand-blue); opacity: 1; }

/* ── Pie ─────────────────────────────────────────────────────────────── */

/* El pie tomaba el near-black del sistema y cortaba la página en seco.
   Ahora recoge la transición nude→celeste del arte de campaña: cierra en el
   mismo aire con el que abre la marca, y el azul sigue siendo el único
   acento fuerte. */
.site-footer {
  background: linear-gradient(165deg, var(--nude-100) 0%, var(--nude-200) 38%, var(--sky-100) 100%);
  color: var(--text-body);
  /* Espacio abajo para que el WhatsApp flotante no tape la línea de cédulas
     cuando se llega al final de la página. */
  padding-block: var(--space-9) calc(var(--space-7) + 56px);
  border-block-start: var(--border-width) solid var(--nude-200);
}
.site-footer a { color: var(--text-body); }
.site-footer a:hover { color: var(--brand-blue); opacity: 1; }
.site-footer__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-7); }
.site-footer__title {
  font: var(--type-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--brand-blue);
  margin-block-end: var(--space-4);
}
.site-footer__bottom {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: var(--border-width) solid var(--nude-200);
  display: flex;
  justify-content: space-between;
  gap: var(--space-5);
  font: var(--type-small);
  /* Sobre el pie oscuro el gris apagado alcanzaba; sobre el nude da 2.35 y no
     pasa. Las cédulas son contenido, no letra chica: van en el gris de cuerpo. */
  color: var(--text-body);
}

/* ── WhatsApp flotante ───────────────────────────────────────────────────
   Siempre presente, en todas las páginas y en todos los tamaños. Sustituye
   a la barra fija que solo aparecía en móvil: la conversión por WhatsApp es
   el único objetivo medible del sitio, así que no depende de dónde vaya el
   scroll ni de qué página sea. */

/* Solo el ícono: un círculo. El llamado con texto vive en «Dónde estamos». */
.wa-flotante {
  position: fixed;
  inset-inline-end: var(--gutter);
  inset-block-end: var(--gutter);
  z-index: 45;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  min-height: 60px;
  border-radius: var(--radius-pill);
  background: var(--accent-whatsapp);
  color: #fff;
  font: var(--type-button);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  box-shadow: var(--shadow-raised);
  transition: transform var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out);
}
.wa-flotante:hover { opacity: 1; transform: translateY(-2px); }
.wa-flotante:active { transform: scale(0.98); background: var(--accent-whatsapp-press); }
.wa-flotante:focus-visible { outline: none; box-shadow: var(--shadow-focus), var(--shadow-raised); }
.wa-flotante .icon { width: 28px; height: 28px; filter: brightness(0) invert(1); }

/* ── Landing de campaña ──────────────────────────────────────────────── */

/* El degradado nude→celeste es el ÚNICO lugar de la web donde se permite,
   y solo detrás de figura recortada. Nunca en el sitio principal. */
.campaign-hero {
  background: linear-gradient(160deg, var(--nude-500) 0%, #B6B4BE 48%, var(--sky-500) 100%);
  padding-block: var(--space-9);
}
.campaign-hero__grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-6); align-items: center; }
.campaign-mark {
  display: inline-block;
  background: var(--highlight-mark);
  color: var(--brand-blue-ink);
  font: var(--type-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: var(--space-1) var(--space-3);
}
/* Excepción documentada: peso 700 y caja alta, solo aquí, para que campaña
   y landing se reconozcan entre sí. */
.campaign-title {
  font: var(--weight-bold) var(--size-hero) / var(--leading-tight) var(--font-display);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  color: #fff;
  margin: var(--space-4) 0;
}
.campaign-figure { display: flex; align-items: flex-end; justify-content: flex-end; }
.campaign-figure img { max-height: 460px; width: auto; }

/* ── Animación de entrada ────────────────────────────────────────────── */

.reveal { opacity: 0; transform: translateY(16px); }
.reveal[data-shown="1"] {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

/* Entrada escalonada: los hijos aparecen uno tras otro, 60 ms de diferencia.
   Es lo que le faltaba de movimiento a las rejillas y galerías. */
.reveal-hijos > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.reveal-hijos[data-shown="1"] > * { opacity: 1; transform: none; }
.reveal-hijos[data-shown="1"] > *:nth-child(1) { transition-delay: 0ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(2) { transition-delay: 60ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(3) { transition-delay: 120ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(4) { transition-delay: 180ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(5) { transition-delay: 240ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(6) { transition-delay: 300ms; }
.reveal-hijos[data-shown="1"] > *:nth-child(n+7) { transition-delay: 340ms; }

/* El hero entra con un acercamiento muy lento. No es parallax sobre texto
   —que el manual prohíbe— sino la foto asentándose. */
.hero__media img { animation: heroAsentar 14s var(--ease-out) both; }
@keyframes heroAsentar {
  from { transform: scale(1.07); }
  to { transform: scale(1); }
}

/* Cifras que cuentan al entrar en pantalla. */
.stat__value[data-contar] { font-variant-numeric: tabular-nums; }

/* ── Mapa ────────────────────────────────────────────────────────────── */

.mapa {
  position: relative;
  aspect-ratio: 16 / 9;
  border: var(--border-width) solid var(--border-hairline);
  background: var(--surface-muted);
  overflow: hidden;
}
.mapa iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  /* En gris para que no compita con el azul de marca; recupera color al pasar
     el cursor. */
  filter: grayscale(1) contrast(1.04);
  transition: filter var(--dur-slow) var(--ease-out);
}
.mapa:hover iframe { filter: none; }

/* ── Carrusel de casos ───────────────────────────────────────────────── */

.carrusel-caja { position: relative; }
.carrusel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(260px, calc(25% - 2px));
  gap: 2px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-block-end: var(--space-2);
}
.carrusel::-webkit-scrollbar { display: none; }
.carrusel > * { scroll-snap-align: start; }
/* La serie de mentoplastia es 16:9: caben tres por pantalla, no cuatro. */
.carrusel--wide { grid-auto-columns: minmax(300px, calc(33.333% - 2px)); }

.carrusel-nav { display: flex; gap: var(--space-2); }
.carrusel-boton {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  cursor: pointer;
  transition: var(--transition-base);
}
.carrusel-boton:hover { border-color: var(--brand-blue); }
.carrusel-boton:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.carrusel-boton[disabled] { opacity: 0.35; cursor: default; }
.carrusel-boton--prev img { transform: rotate(180deg); }

/* ── Currículum: bloques en dos columnas asimétricas ─────────────────────
   Antes eran tres columnas iguales y la rejilla igualaba alturas: Formación
   dejaba 294 px de hueco y Membresías 233. Ahora cada bloque es una fila
   (rótulo a la izquierda, lista a la derecha) y no sobra nada. */
.cv-bloque {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: var(--space-7);
  padding-block: var(--space-7);
  border-block-start: var(--border-width) solid var(--nude-200);
}
/* El rótulo de cada bloque también sube: a 12 px se perdía. */
.cv-bloque > .eyebrow { font-size: 0.9375rem; letter-spacing: 0.12em; }
.cv-bloque:first-of-type { border-block-start: 0; }

/* ── Responsive ──────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .split, .split--text-heavy, .campaign-hero__grid { grid-template-columns: minmax(0, 1fr); }
  .editorial { grid-template-columns: minmax(0, 1fr); }
  .toc { display: none; }
  .card-grid, .card-grid--two { grid-template-columns: minmax(0, 1fr); }
  .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-row { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 680px) {
  /* Botón del menú más discreto en celular. */
  .menu-toggle { width: 40px; height: 40px; }
  .menu-toggle .icon { width: 17px; height: 17px; }
  .site-header__social > a .icon { width: 17px; height: 17px; }
  .site-header__logo { height: 24px; }

  /* Hero en móvil: la foto es apaisada y la pantalla vertical, así que el
     recorte lateral es enorme. Se encuadra sobre el rostro para que quede
     centrado y grande, como en la referencia. */
  .hero--editorial .hero__media img { object-position: 38% 42%; }
  /* El hero baja a 44px, la galería a dos columnas, el letrero a 28px. */
  .hero-title { font-size: 2.75rem; }
  .hero--editorial .hero-title { font-size: clamp(2.25rem, 11vw, 3.25rem); max-width: 11ch; }
  .display { font-size: 2.25rem; }
  .h2 { font-size: 1.75rem; }
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .marquee__track span { font-size: 1.75rem; }
  .campaign-title { font-size: 2.5rem; }
  .band { padding-block: var(--section-y-tight); }
  .site-footer__grid { grid-template-columns: minmax(0, 1fr); }
  .gallery--wide { grid-template-columns: minmax(0, 1fr); }
  /* En móvil se reduce a círculo: el texto estorba sobre el contenido. */
}

@media (max-width: 900px) {
  .cv-bloque { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .carrusel { grid-auto-columns: minmax(240px, calc(50% - 2px)); }
}


@media (prefers-reduced-motion: reduce) {
  .marquee__track,
  .hero__media img { animation: none; }
  .reveal,
  .reveal-hijos > * { opacity: 1; transform: none; }
  .carrusel { scroll-behavior: auto; }
  * { transition-duration: 1ms !important; }
}
