/* ══════════════════════════════════════════════════════════════════
   CLÍNICA DEL LAGO · Odontología, Puerto Varas — demo CristalWeb
   Demo sin encargo. Construida el 02-09-2026, subida de nivel el
   08-09-2026: se le agregaron la banda de cifras, la sección de
   mitades, dos clips de fondo y cinco fotos. La identidad —el trío,
   la paleta y el tono— no se tocó: son decisiones ya tomadas.

   Segunda pasada del 08-09-2026:
   · Botón flotante de WhatsApp al número DE LA CLÍNICA, escrito en el
     HTML y visible por defecto (el JS sólo lo aparta sobre la portada).
   · El mosaico pasó de tres columnas a CUATRO. Con seis piezas y las
     celdas 1 y 6 a `span 2` son ocho celdas: en tres columnas quedaba
     un hueco blanco al final —se veía en la página— y en cuatro cierra
     exacto en dos filas.
   · Cinco fotos cambiadas (tajo, telón de especialidades y tres del
     mosaico): las tres primeras no tenían procedencia anotada, y en las
     dos del mosaico había una marca de fabricante grabada en el sillón
     y dos diplomas con texto legible. Ninguna decisión de identidad se
     tocó en esta pasada.

   Revisión del 09-09-2026 (tercera pasada, medida sobre la página viva):
   · Las seis fichas del tratamiento NO estaban centradas: la lista lleva
     la clase .ancho, pero `.etapas { margin: 0 }` viene después en el
     archivo y pisaba el `margin-inline: auto`. Medido en la captura de
     1440: la grilla iba de x 0 a x 1140 y el título de arriba de 150 a
     1290. Corregido con `margin-block: 0`.
   · Los enlaces del nav pasan a 44 px de alto (estaban en 36).
   · `p { text-wrap: pretty }` y `svg, video { max-width: 100% }`, que
     faltaban de la base canónica.
   ------------------------------------------------------------------
   DIRECCIÓN: «NUDE Y PORCELANA». Arena cálida y un bronce apagado: la
   paleta de la piel, no la del diente. Es deliberado — la clínica hace
   ortodoncia Y armonización facial, y el celeste clínico de rigor
   habla sólo de la mitad del negocio.

   Deslinde escrito con las diez dentales del registro:
     48-vivesmile (sin acento), 53-innovadent (porcelana y acero frío),
     75-brand (menta), 84-martinez-satta (jade), 67-patagonia (azul de
     noche), 51-centro-dental-aleman (verde quirúrgico), 57-msalud
     (granate), 61-praxis (ciruela), 78-auralafken (rosa viejo),
     45-urgencia-dental (grafito y coral). Ninguna es cálida-arena y
     ninguna usa bronce. Con la 172 (dental-araucaria, ortodoncia con
     brackets) el deslinde además es de CONTENIDO: allá el tratamiento
     se cuenta con aparatos fijos, acá con alineadores y con las horas
     de uso como eje.

   TRÍO
     Display · Quattrocento — serif clásica y cálida, nueva en el
       registro. Da calma sin ponerse solemne.
     Cuerpo  · Jost — segunda aparición (49-gruas-del-sur). Geométrica
       y silenciosa, aguanta bien el aire.
     Dato    · Fragment Mono — cuarta aparición. Lleva las cifras del
       tratamiento y los rótulos del esquema.

   ESCENA: la herradura del alineador baja inclinada y se posa en 0,9 s;
     después una línea de brillo bronce la recorre en 1,2 s y vuelve
     cada 8 s. Es el ÚNICO bucle infinito de la página. El objeto es la
     pregunta —una placa que se pone y se saca— y va en su propia zona,
     a la derecha, sin pelear con el clip.

   CLIPS: dos, ambos 720p sin audio y sin pista de sonido.
     · video/port.mp4  · 9,0 s · 1,7 MB — un box de atención vacío, la
       cámara se desplaza. El sujeto es el mismo que la foto de
       portada, así que el fundido de 1,4 s no cambia de tema.
     · video/cita.mp4  · 6,4 s · 0,95 MB — modelos de yeso sobre la
       mesa. Es el objeto del que habla la frase, y su color es el de
       la paleta: arena y bronce, no el celeste clínico de rigor.
     Los dos van con la foto de base debajo y sin atributo poster: el
     <img> hermano NO se va, así que si el autoplay se bloquea nunca
     queda un rectángulo negro.
   ══════════════════════════════════════════════════════════════════ */

:root {
  --porcelana: #F7F4F0;
  --arena:     #EBE4DA;
  --tinta:     #221E1B;
  --medio:     #5C544B;   /* 6,7:1 sobre porcelana */
  --bronce:    #8A5A2B;   /* texto y relleno — 5,6:1 sobre porcelana */
  --bronce-o:  #6E4620;   /* hover */
  --bronce-l:  #D9A96F;   /* sobre tinta */
  --linea:     rgba(34,30,27,.16);

  --display: 'Quattrocento', Georgia, serif;
  --cuerpo:  'Jost', 'Segoe UI', system-ui, sans-serif;
  --mono:    'Fragment Mono', 'Consolas', ui-monospace, monospace;

  --p--1: clamp(.8rem, .77rem + .12vw, .88rem);
  --p-0:  clamp(1rem, .96rem + .2vw, 1.1rem);
  --p-1:  clamp(1.15rem, 1.08rem + .3vw, 1.35rem);
  --p-2:  clamp(1.4rem, 1.25rem + .7vw, 1.9rem);
  --p-3:  clamp(1.8rem, 1.5rem + 1.4vw, 2.7rem);
  --p-4:  clamp(2.2rem, 1.6rem + 2.7vw, 4rem);

  --aire:  clamp(4rem, 2.4rem + 5.5vw, 7.5rem);
  --ancho: min(100% - 2.5rem, 1140px);
  --salida: cubic-bezier(.16, 1, .3, 1);
  --sale-2: cubic-bezier(.2, 0, 0, 1);   /* objetos grandes que llegan */
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body { margin: 0; background: var(--porcelana); color: var(--tinta); font-family: var(--cuerpo); font-size: var(--p-0); line-height: 1.68; }
img, svg, video { max-width: 100%; }
img { height: auto; }
p { text-wrap: pretty; }   /* mata las viudas de una línea, gratis */
a { color: var(--bronce); }
:focus-visible { outline: 3px solid var(--bronce); outline-offset: 2px; }
.ancho { width: var(--ancho); margin-inline: auto; }
h1, h2, h3 { font-family: var(--display); font-weight: 700; line-height: 1.2; margin: 0; }
.mono { font-family: var(--mono); }

.rotulo { font-family: var(--mono); font-size: var(--p--1); letter-spacing: .14em; text-transform: uppercase; color: var(--bronce); margin: 0 0 .8rem; }
.rotulo--claro { color: var(--bronce-l); }
.titulo { font-size: var(--p-3); max-width: 24ch; margin-bottom: 1rem; }
.titulo--claro { color: var(--porcelana); }
.entradilla { max-width: 58ch; color: var(--medio); font-size: var(--p-1); margin: 0 0 2rem; }
.entradilla b { color: var(--tinta); font-weight: 700; }
.nota { margin-top: 1.6rem; font-size: var(--p--1); color: var(--medio); max-width: 64ch; }
.sobre { font-family: var(--mono); font-size: var(--p--1); letter-spacing: .12em; text-transform: uppercase; color: var(--bronce); margin: 0 0 1rem; }

/* ── Dato de ejemplo ───────────────────────────────────────────── */
.ej { position: relative; border: 1px dashed rgba(138,90,43,.5); border-radius: 3px; }
.ej::after {
  content: attr(data-ejemplo); position: absolute; top: -.62rem; right: .6rem;
  font-family: var(--mono); font-size: .62rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--bronce); background: var(--porcelana); padding: 0 .35rem;
}

/* ── Botones ───────────────────────────────────────────────────── */
.boton {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: .85rem 1.7rem;
  border: 1px solid var(--bronce); border-radius: 999px;
  background: var(--bronce); color: #FFFFFF;
  font-family: var(--cuerpo); font-size: var(--p-0); font-weight: 500;
  letter-spacing: .02em; text-decoration: none; cursor: pointer;
  transition: transform .16s ease-out, background-color .16s;
}
.boton:hover { background: var(--bronce-o); transform: translateY(-2px); }
.boton:active { transform: translateY(0); }
.boton--linea { background: transparent; color: var(--bronce); }
.boton--linea:hover { background: rgba(138,90,43,.09); }
.boton--chico { min-height: 40px; padding: .5rem 1.1rem; font-size: var(--p--1); }

/* ── Propuesta ─────────────────────────────────────────────────── */
.propuesta { background: var(--tinta); color: var(--porcelana); padding: .85rem clamp(1.2rem, 5vw, 3rem); border-bottom: 3px solid var(--bronce); }
.propuesta__que { margin: 0 0 .3rem; font-size: var(--p--1); font-family: var(--mono); }
.propuesta__que b { color: var(--bronce-l); }
.propuesta__gancho { margin: 0; font-size: var(--p--1); color: #BFB8B0; max-width: 96ch; line-height: 1.5; }

/* ── Cabecera ──────────────────────────────────────────────────── */
.cab { position: sticky; top: 0; z-index: 40; display: flex; align-items: center; gap: 1rem; padding: .75rem clamp(1rem, 4vw, 2.4rem); background: rgba(247,244,240,.94); border-bottom: 1px solid var(--linea); transition: box-shadow .2s, background-color .2s; }
.cab--flota { box-shadow: 0 6px 22px -16px rgba(34,30,27,.8); background: rgba(247,244,240,.99); }
.cab__marca { display: flex; align-items: center; gap: .7rem; text-decoration: none; color: var(--tinta); }
/* La onda del lago, dibujada con un borde curvo. Cero bytes. */
.onda { width: 26px; height: 18px; flex: none; border-bottom: 2px solid var(--bronce); border-radius: 0 0 50% 50% / 0 0 100% 100%; position: relative; }
.onda::after { content: ""; position: absolute; left: 3px; right: 3px; bottom: 5px; height: 8px; border-bottom: 2px solid rgba(138,90,43,.45); border-radius: 0 0 50% 50% / 0 0 100% 100%; }
.cab__nombre { font-family: var(--display); font-size: var(--p-1); line-height: 1; }
.cab__sub { display: block; font-family: var(--mono); font-size: .58rem; letter-spacing: .1em; text-transform: uppercase; color: var(--bronce); margin-top: .3rem; font-weight: 400; }
.cab__nav { display: flex; gap: 1.2rem; margin-left: auto; overflow-x: auto; }
/* 44 px también acá: sobre 1040 px el nav se ve, y hay tablets táctiles de
   ese ancho. Con `padding: .4rem 0` el blanco de toque quedaba en 36 px. */
.cab__nav a { display: inline-flex; align-items: center; min-height: 44px; color: var(--medio); text-decoration: none; font-size: var(--p--1); white-space: nowrap; padding: .4rem 0; border-bottom: 2px solid transparent; }
.cab__nav a:hover { color: var(--bronce); border-bottom-color: var(--bronce); }
.cab__cta { margin-left: .4rem; }
@media (max-width: 1040px) { .cab__nav { display: none; } .cab__cta { margin-left: auto; } }

/* ── Portada ───────────────────────────────────────────────────── */
.portada { position: relative; isolation: isolate; min-height: min(84vh, 720px); display: flex; flex-direction: column; justify-content: center; padding: var(--aire) 0; overflow: hidden; }
.portada__foto { position: absolute; inset: 0; z-index: -1; }
/* La foto y el clip comparten selector: misma máscara, mismo recorte y
   mismo encuadre escritos UNA vez. Con reglas separadas se descuadran
   apenas se toca una. */
.portada__foto img, .portada__video {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 74% 46%;
  /* Espejo. La foto y el clip traen su masa oscura —el sillón— en el
     tercio IZQUIERDO, que es justo el que la máscara borra: sin esto
     la portada queda blanca sobre blanca y se ve plana. Va en el
     selector compartido para que foto y clip volteen juntos. */
  transform: scaleX(-1);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 26%, rgba(0,0,0,.2) 42%, rgba(0,0,0,.7) 60%, #000 76%, #000 100%);
          mask-image: linear-gradient(90deg, transparent 0%, transparent 26%, rgba(0,0,0,.2) 42%, rgba(0,0,0,.7) 60%, #000 76%, #000 100%);
}
/* Velo entero en rgba y terminando en alfa 0. */
.portada__foto::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg,
      rgba(247,244,240,1) 0%, rgba(247,244,240,1) 30%,
      rgba(247,244,240,.74) 46%, rgba(247,244,240,.32) 64%,
      rgba(247,244,240,.08) 82%, rgba(247,244,240,0) 96%);
}
.portada__texto { width: var(--ancho); margin-inline: auto; }
.portada__titulo { font-size: var(--p-4); max-width: 15ch; }
.portada__titulo span { display: block; }
.portada__bajada { max-width: 46ch; color: var(--medio); font-size: var(--p-1); margin: 1.4rem 0 2rem; }
.acciones { display: flex; flex-wrap: wrap; gap: .8rem; }

/* ── Escena de portada · la placa que se posa ──────────────────────
   movimiento-web, ficha «Dental», escalón 1. Es la misma herradura del
   mapa de placas de más abajo, en grande: el mismo dibujo dice las dos
   cosas. z-index -1 y después de la foto en el HTML: pinta sobre la
   foto y su velo, y siempre por debajo del texto.
   La perspectiva va en el PADRE, que es donde sirve. */
.escena { position: absolute; z-index: -1; pointer-events: none; }
.escena--placa { top: 20%; right: 7%; width: min(36%, 380px); perspective: 600px; }
.escena__svg { display: block; width: 100%; height: auto; }

.escena__herradura {
  fill: var(--porcelana); fill-opacity: .6;
  stroke: var(--bronce); stroke-width: 1.5; stroke-linejoin: round;
}
.escena__cortes path { stroke: var(--bronce); stroke-width: 1; opacity: .45; fill: none; }

/* Llegada: baja inclinada y se endereza al posarse. */
@keyframes placa-baja {
  from { transform: translateY(-30px) rotateX(40deg); opacity: 0; }
  25%  { opacity: 1; }
  to   { transform: translateY(0) rotateX(0deg); opacity: 1; }
}
.js .escena__svg { animation: placa-baja .9s var(--sale-2) .3s both; }

/* El brillo recorre la herradura y vuelve cada 8 s. Se mueve con
   TRANSFORM, no con background-position: al vivir dentro del SVG y
   estar recortado por un clipPath no hace falta la excepción del
   gradiente que usa la 03. Recorre en 1,2 s (el 15 % del ciclo) y el
   resto del tiempo está fuera del cuadro. */
@keyframes brillo-recorre {
  0%   { transform: translateX(0); }
  15%  { transform: translateX(360px); }
  100% { transform: translateX(360px); }
}
.escena__brillo { transform: translateX(360px); }
.js .escena__brillo { animation: brillo-recorre 8s linear 1.2s infinite; }

/* A 375 px la herradura baja al pie de la portada. NO al 55 % que pedía
   el prompt: medido, a ese ancho se mete detrás de los dos botones —que
   llegan a x 208— y un arco bronce debajo de un botón bronce se ve
   sucio. Con 42 % el dibujo arranca en x 223 y queda libre.
   El titular termina en y 554; la escena empieza en 791. */
@media (max-width: 760px) {
  /* CORREGIDO EL 09-09-2026. El cálculo de arriba sólo vale a 375 px, que
     es donde los dos botones NO caben en una línea y el segundo baja. Entre
     ~420 y 760 px los dos caben juntos, llegan a x 403 (medido a 485) y la
     herradura arrancaba en x 266: el arco bronce cruzaba por dentro de
     «Pedir evaluación», justo lo que este comentario decía que había que
     evitar. Ahora la escena tiene FRANJA PROPIA bajo los botones: la
     portada reserva abajo 34vw + 2,5rem y el dibujo ocupa 36vw × 0,85 más
     su margen, así que a cualquier ancho de la franja queda aire entre el
     botón y el arco. */
  .portada { padding-bottom: calc(34vw + 2.5rem); }
  .escena--placa { top: auto; bottom: 1.25rem; right: 4%; width: 36%; }
  /* El texto pasó de estar AL LADO de la foto a estar ENCIMA: la
     máscara y el velo rotan a vertical o el titular queda sobre la
     zona nítida. El sujeto del clip (el sillón) vive en el centro
     del cuadro, así que basta rotar; no hace falta recomponer. */
  .portada { min-height: 0; padding-top: 1.5rem; }
  .portada__foto img, .portada__video {
    object-position: 50% 46%;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.45) 36%, #000 66%);
            mask-image: linear-gradient(180deg, transparent 0%, rgba(0,0,0,.45) 36%, #000 66%);
  }
  .portada__foto::after {
    background: linear-gradient(180deg,
        rgba(247,244,240,1) 0%, rgba(247,244,240,.94) 34%,
        rgba(247,244,240,.6) 66%, rgba(247,244,240,.18) 100%);
  }
}

/* ── CIFRAS ────────────────────────────────────────────────────────
   Banda oscura entre la portada y la pieza firma. Lleva telón propio
   —el segundo de la página, otra foto— para que la banda oscura tenga
   imagen, como todas las demás oscuras de esta página.
   Contraste medido con .js quitado: la porcelana #F7F4F0 sobre el
   tinta #221E1B da 15,4:1, y el gris claro #C9C2BA sobre el mismo
   fondo da 9,7:1. El telón al 10 % no mueve el fondo lo suficiente
   para bajar de AAA. */
.cifras { padding: calc(var(--aire) * .72) 0; background: var(--tinta); color: var(--porcelana); }
.telon--cifras img { opacity: .10; object-position: 50% 55%; }
.cifras__lista {
  list-style: none; margin-block: 0; padding: 0;
  display: grid; gap: 1.6rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.cifras__lista li { border-top: 1px solid rgba(217,169,111,.32); padding-top: .9rem; }
/* El número hueco: relleno del propio fondo y contorno bronce. Se lee
   como grabado y no como texto — por eso el dato de verdad va en el
   <span> de al lado, que sí es texto normal y sí pasa AA. */
.cifras__lista b {
  display: block; font-family: var(--display); font-size: clamp(3rem, 2rem + 4vw, 5rem);
  line-height: 1; color: var(--tinta); font-weight: 700;
  -webkit-text-stroke: 1.5px rgba(217,169,111,.85);
  font-variant-numeric: tabular-nums; margin-bottom: .5rem;
}
/* La herida rompe el patrón: relleno sólido, sin contorno. Ese
   contraste es lo que dirige la vista al 0. */
.cifras__herida b { color: var(--bronce-l); -webkit-text-stroke: 0; }
.cifras__lista span { display: block; font-size: var(--p--1); color: #C9C2BA; line-height: 1.5; }
.cifras__herida span { color: var(--porcelana); }

/* ── PIEZA FIRMA · el mapa del tratamiento ─────────────────────── */
.mapa { padding: var(--aire) 0; }
.placas { display: block; width: 100%; height: auto; margin: 1rem 0 .6rem; background: var(--arena); border-radius: 8px; padding: 0; }
.placas__eje { stroke: rgba(34,30,27,.2); stroke-width: 1.5; }
.arc { fill: none; stroke: var(--bronce); stroke-width: 3; stroke-linecap: round; }
.placas__g text { font-family: var(--mono); font-size: 12px; fill: var(--medio); text-anchor: middle; }
.placas__g--ctrl .arc { stroke-width: 4; }
.pt { fill: var(--bronce); }
.placas__g--fin .arc { stroke: var(--tinta); stroke-width: 4; }
.placas__rot { font-family: var(--mono); font-size: 11px; fill: var(--medio); letter-spacing: .08em; text-transform: uppercase; }
.placas__rot--der { text-anchor: end; }
.placas__pie { margin: 0 0 2.5rem; font-family: var(--mono); font-size: var(--p--1); color: var(--medio); display: flex; align-items: center; gap: .5rem; }
.pt-leyenda { width: 10px; height: 10px; border-radius: 50%; background: var(--bronce); display: inline-block; flex: none; }

/* margin-BLOCK, no `margin: 0`: esta lista lleva además la clase .ancho, y
   un `margin: 0` escrito después pisa el `margin-inline: auto` que la
   centra. Con `margin: 0` las seis fichas arrancaban pegadas al borde
   izquierdo de la ventana mientras el título de arriba seguía en la
   retícula —medido: la grilla iba de x 0 a x 1140 en vez de 150 a 1290—.
   Es el mismo motivo por el que .cifras__lista usa margin-block. */
.etapas { list-style: none; margin-block: 0; padding: 0; display: grid; gap: 1.2rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.etapa { background: var(--arena); border-radius: 8px; padding: 1.4rem; }
.etapa__n { margin: 0 0 .5rem; font-family: var(--mono); font-size: var(--p-2); color: var(--bronce); }
.etapa h3 { font-size: var(--p-1); margin-bottom: .5rem; }
.etapa p { margin: 0; font-size: var(--p--1); color: var(--medio); }
.etapa__d { margin-top: .9rem !important; display: inline-block; font-family: var(--mono); color: var(--bronce) !important; padding: .4rem .7rem; }
.etapa__d.ej::after { background: var(--arena); }
/* La etapa de las 22 horas es la que decide el tratamiento: se destaca
   invirtiendo el bloque, no agregando un segundo color. */
.etapa--clave { background: var(--tinta); }
.etapa--clave h3 { color: var(--porcelana); }
.etapa--clave p { color: #BFB8B0; }
.etapa--clave .etapa__n, .etapa--clave .etapa__d { color: var(--bronce-l) !important; }
.etapa--clave .etapa__d { border: 1px solid rgba(217,169,111,.4); border-radius: 3px; }

/* ── Tajo ──────────────────────────────────────────────────────── */
.tajo { position: relative; margin: 0; isolation: isolate; min-height: min(52vh, 420px); display: flex; align-items: flex-end; overflow: hidden; }
.tajo img { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; object-fit: cover; object-position: 50% 42%; }
.tajo::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(0deg, rgba(34,30,27,.94) 0%, rgba(34,30,27,.78) 34%, rgba(34,30,27,.32) 62%, rgba(34,30,27,0) 92%); }
.tajo__txt { width: var(--ancho); margin-inline: auto; padding: 2.5rem 0; }
.tajo__txt h2 { font-size: var(--p-3); max-width: 22ch; color: var(--porcelana); }
.tajo__txt p { max-width: 48ch; color: #CFC8C0; margin: .9rem 0 0; }

/* ── Armonización ──────────────────────────────────────────────── */
.armonia { padding: var(--aire) 0; background: var(--arena); }
.arm { display: grid; gap: 1.2rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.arm__c { background: var(--porcelana); border-radius: 8px; padding: 1.4rem; border-top: 3px solid var(--bronce); }
.arm__c--no { border-top-color: var(--linea); }
.arm__r { margin: 0 0 .8rem; font-family: var(--mono); font-size: var(--p--1); letter-spacing: .12em; text-transform: uppercase; color: var(--bronce); }
.arm__c--no .arm__r { color: var(--medio); }
.arm__c ul { margin: 0; padding-left: 1.1rem; }
.arm__c li { font-size: var(--p--1); color: var(--medio); margin-bottom: .45rem; }

/* ── Especialidades, con telón ─────────────────────────────────── */
.espec { padding: var(--aire) 0; }
.con-telon { position: relative; isolation: isolate; overflow: hidden; }
.telon { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
/* Foto NÍTIDA al 15%: telón, no aura. Cero desenfoque. */
.telon img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 44%; opacity: .15;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 74%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 74%, transparent 100%);
}
/* minmax de 280 y no de 230: con 230 caben cuatro columnas y las seis
   especialidades quedan 4 + 2, con dos huecos a la derecha de la
   segunda fila. Con 280 caben tres y quedan 3 + 3, que es lo que se
   lee como una lista completa. */
.esp { list-style: none; margin: 0; padding: 1.6rem; display: grid; gap: 1.4rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.esp h3 { font-size: var(--p-1); margin-bottom: .3rem; color: var(--bronce); }
.esp p { margin: 0; font-size: var(--p--1); color: var(--medio); }

/* ── Cita ──────────────────────────────────────────────────────── */
.cita { position: relative; margin: 0; isolation: isolate; min-height: min(48vh, 380px); display: grid; place-items: center; overflow: hidden; }
.cita img, .cita__video { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }
.cita::after { content: ""; position: absolute; inset: 0; z-index: -1; background: rgba(34,30,27,.76); }
.cita__txt { margin: 0; width: var(--ancho); padding: 3rem 0; }
.cita__txt p { font-family: var(--display); font-size: var(--p-3); color: var(--porcelana); max-width: 24ch; margin: 0 auto; text-align: center; line-height: 1.3; }

/* ── Mosaico ───────────────────────────────────────────────────────
   CUATRO columnas, no tres. Con seis piezas y las celdas 1 y 6 a
   `span 2` son ocho celdas: en tres columnas eso deja un hueco blanco
   al final de la tercera fila —se veía— y en cuatro cierra exacto en
   dos filas de cuatro. El ritmo queda [1 1][2][3] / [4][5][6 6]. */
.mos { padding: var(--aire) 0; }
.mos__grilla { display: grid; gap: 4px; grid-template-columns: repeat(4, 1fr); width: var(--ancho); margin: 2rem auto 0; border-radius: 8px; overflow: hidden; }
.mos__p { margin: 0; overflow: hidden; }
.mos__p:nth-child(1), .mos__p:nth-child(6) { grid-column: span 2; }
.mos__p img { display: block; width: 100%; height: 100%; aspect-ratio: 3 / 2; object-fit: cover; filter: saturate(.94); transition: transform .5s var(--salida), filter .5s var(--salida); }
.mos__p:hover img { transform: scale(1.05); filter: saturate(1); }
/* A dos columnas la retícula sigue cerrando: [1 1] / [2][3] / [4][5] / [6 6] */
@media (max-width: 900px) { .mos__grilla { grid-template-columns: repeat(2, 1fr); } }

/* ── Mitades · qué llevar ──────────────────────────────────────────
   Media foto y medio texto. La foto NO termina en filo recto: se apaga
   contra el fondo con mask-image, que es lo que un ::after no puede
   hacer sin dejar el corte. Cero desenfoque: la foto va a foco
   completo del lado libre.
   Contraste medido: porcelana #F7F4F0 sobre tinta #221E1B, 15,4:1;
   la lista en #C9C2BA sobre el mismo fondo, 9,7:1. */
.mit { background: var(--tinta); color: var(--porcelana); display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; overflow: hidden; }
.mit__foto { margin: 0; position: relative; min-height: clamp(300px, 34vw, 540px); }
.mit__foto img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 52% 50%;
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 58%, rgba(0,0,0,.55) 84%, transparent 100%);
          mask-image: linear-gradient(90deg, #000 0%, #000 58%, rgba(0,0,0,.55) 84%, transparent 100%);
}
.mit__txt { display: flex; align-items: center; padding: var(--aire) 0; }
.mit__caja { width: min(100% - 2.5rem, 36rem); margin-inline: auto; }
.mit__lista { list-style: none; margin: 1.4rem 0 0; padding: 0; }
.mit__lista li { position: relative; padding: 0 0 .9rem 1.6rem; font-size: var(--p--1); color: #C9C2BA; line-height: 1.6; }
/* El bullet dibujado: un cuadrado de 7 px girado — la placa vista de
   canto. Nunca el list-style por defecto. */
.mit__lista li::before {
  content: ""; position: absolute; left: 0; top: .5rem;
  width: 7px; height: 7px; background: var(--bronce-l); transform: rotate(45deg);
}
.mit__lista b { color: var(--porcelana); font-weight: 700; }
.mit__cierre { margin: 1.4rem 0 0; font-size: var(--p--1); color: var(--bronce-l); border-left: 3px solid rgba(217,169,111,.4); padding-left: .9rem; }
@media (max-width: 860px) {
  .mit { grid-template-columns: 1fr; }
  .mit__foto { min-height: clamp(240px, 52vw, 340px); }
  .mit__foto img {
    object-position: 50% 46%;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 58%, rgba(0,0,0,.55) 86%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 0%, #000 58%, rgba(0,0,0,.55) 86%, transparent 100%);
  }
  .mit__txt { padding-top: 1.5rem; }
}

/* ── Evaluación ────────────────────────────────────────────────── */
.evalua { padding: var(--aire) 0; background: var(--arena); }
.evalua__cols { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); align-items: start; }
.datos { margin: 0; display: grid; }
.datos > div { display: grid; grid-template-columns: 10rem 1fr; gap: .6rem; padding: .75rem .6rem; border-bottom: 1px solid var(--linea); }
.datos dt { font-family: var(--mono); font-size: var(--p--1); letter-spacing: .06em; text-transform: uppercase; color: var(--medio); }
.datos dd { margin: 0; }
.datos .ej::after { background: var(--arena); }
@media (max-width: 480px) { .datos > div { grid-template-columns: 1fr; } }

.pedir { background: var(--porcelana); border: 1px solid var(--linea); border-radius: 10px; padding: clamp(1.2rem, 3vw, 2rem); }
.pedir__t { font-size: var(--p-2); margin-bottom: 1rem; }
.form { display: grid; gap: .9rem; }
.form label { display: grid; gap: .3rem; font-family: var(--mono); font-size: var(--p--1); letter-spacing: .04em; text-transform: uppercase; color: var(--medio); }
.form input, .form select {
  font-family: var(--cuerpo); font-size: var(--p-0);
  padding: .7rem .8rem; min-height: 46px;
  border: 1px solid rgba(34,30,27,.24); border-radius: 6px;
  background: #FCFAF7; color: var(--tinta); text-transform: none;
}
.form input:focus-visible, .form select:focus-visible { border-color: var(--bronce); }
.form__salida { font-family: var(--mono); font-size: var(--p--1); background: var(--arena); border-left: 3px solid var(--bronce); border-radius: 0 6px 6px 0; padding: .7rem .8rem; margin: .2rem 0 0; white-space: pre-wrap; color: var(--medio); }
.form__salida:empty { display: none; }
.form__acciones { display: flex; flex-wrap: wrap; gap: .7rem; }
.form__sinjs { margin: 1rem 0 0; font-size: var(--p--1); color: var(--medio); }

/* ── Para el dueño ─────────────────────────────────────────────── */
.dueno { padding: var(--aire) 0; background: var(--tinta); color: var(--porcelana); }
.dueno__cols { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-top: 1rem; }
.dueno__cols h3 { font-size: var(--p-1); color: var(--bronce-l); margin-bottom: .5rem; }
.dueno__cols p { margin: 0; color: #BFB8B0; font-size: var(--p--1); }
.dueno__cols b { color: var(--porcelana); }
.dueno__cierre { display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 2.5rem 0 0; }
.flecha { color: var(--bronce-l); text-decoration: none; font-weight: 500; border-bottom: 1px solid rgba(217,169,111,.4); padding-bottom: .15rem; }
.flecha:hover { border-bottom-color: var(--bronce-l); }

/* ── Pie ───────────────────────────────────────────────────────── */
/* El padding de abajo deja sitio al botón flotante de WhatsApp: 56 px
   de botón más el margen, para que nunca tape la última línea legal. */
.pie { background: #1B1815; color: #8E877F; padding: 2rem clamp(1.2rem, 5vw, 3rem) 6rem; }
.pie p { margin: 0; font-size: var(--p--1); max-width: 92ch; }

/* ── WHATSAPP FLOTANTE ─────────────────────────────────────────────
   Botón fijo abajo a la derecha. 56 px de alto: por encima de los 44
   del mínimo táctil. El verde de WhatsApp va a propósito —se reconoce
   sin leerlo, y eso es lo que hace que se toque— y es el único color
   de la página que no sale de la paleta: es una marca, no un adorno.

   La dirección del truco importa: el botón se ve SIEMPRE por defecto y
   el JS sólo lo aparta mientras el visitante está en la portada, para
   no tapar el titular. Si el script no arranca, o si rescate.js quita
   la clase .js, el botón queda visible, que es el estado que vende.

   Contraste medido: #07310F sobre #25D366 da 7,3:1 — AA de sobra para
   un rótulo de 700 en .95rem. El icono va incrustado en el HTML porque
   la CSP de esta página no deja pedir nada a un tercero. */
.wapp {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right, 0px));
  bottom: max(1rem, env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: inline-flex; align-items: center; gap: .55rem;
  height: 56px; padding: 0 1.15rem 0 1rem;
  border-radius: 999px;
  background: #25D366; color: #07310F;
  text-decoration: none;
  font-family: var(--cuerpo); font-size: .95rem; font-weight: 700; line-height: 1;
  box-shadow: 0 6px 18px rgba(0,0,0,.3), 0 2px 6px rgba(0,0,0,.2);
  transition: opacity .28s ease, transform .28s ease, box-shadow .18s ease;
}
.wapp__i { width: 26px; height: 26px; flex: none; fill: currentColor; }
.wapp:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0,0,0,.34), 0 2px 6px rgba(0,0,0,.2); }
.wapp:focus-visible { outline: 3px solid var(--tinta); outline-offset: 3px; }
/* Apartado mientras se mira la portada. No se usa `hidden` ni
   display:none: sigue en el flujo y vuelve con un fundido. */
.wapp--arriba { opacity: 0; transform: translateY(14px) scale(.94); pointer-events: none; }
/* Bajo 520 px queda el círculo y el rótulo se esconde sin salir del
   DOM: el lector de pantalla sigue leyendo el aria-label del enlace. */
@media (max-width: 520px) {
  .wapp { width: 56px; padding: 0; justify-content: center; gap: 0; }
  .wapp__t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}

/* ══ Animación ═════════════════════════════════════════════════
   Números de movimiento-web (reglas atómicas): la OPACIDAD salta corta
   —0,3 s— y es el TRANSFORM el que dura, 0,6 s con la curva de salida. */
.js .rev { opacity: 0; transform: translateY(22px); }
.js .rev.ok {
  opacity: 1; transform: none;
  transition: opacity .3s ease-out, transform .6s var(--salida);
}
.js .portada__texto > * { animation: entra .8s var(--salida) both; }
.js .sobre           { animation-delay: .05s; }
.js .portada__titulo { animation-delay: .14s; }
.js .portada__bajada { animation-delay: .26s; }
.js .acciones        { animation-delay: .36s; }
@keyframes entra { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }

/* ── Las doce placas: BARRIDO, no cascada (regla 4) ────────────────
   Con más de nueve piezas la cascada deja de leerse como un grupo y se
   vuelve una fila de tics: la regla manda barrido. El clip-path corre
   sobre el SVG entero en 0,8 s, y el observer va sobre el CONTENEDOR
   —un elemento recortado a área cero jamás dispara IntersectionObserver
   y se bloquearía solo—. */
@keyframes placas-barre {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}
.js .mapa .ancho.rev .placas { clip-path: inset(0 100% 0 0); }
.js .mapa .ancho.rev.ok .placas { animation: placas-barre .8s var(--salida) both; }

/* Los controles entran 200 ms después de que el barrido termina, sólo
   con opacidad: son marcas sobre el dibujo, no piezas que llegan. */
@keyframes ctrl-aparece { from { opacity: 0; } to { opacity: 1; } }
.js .mapa .ancho.rev .placas .pt,
.js .mapa .ancho.rev .placas__pie { opacity: 0; }
.js .mapa .ancho.rev.ok .placas .pt,
.js .mapa .ancho.rev.ok .placas__pie { animation: ctrl-aparece .4s ease-out 1s both; }

/* ── Cascada de hijos (regla 4) ────────────────────────────────────
   El CONTENEDOR se neutraliza y animan los hijos. Si no se neutraliza,
   contenedor e hijos bajan a la vez y el grupo entero se desplaza el
   doble. El índice va por nth-child en el CSS y NUNCA en un
   style="--i:3": la CSP de esta página no admite estilo en línea y lo
   bloquearía sin un solo error visible. */
.js .cascada.rev { opacity: 1; transform: none; transition: none; }
.js .cascada.rev > * { opacity: 0; transform: translateY(26px); }
.js .cascada.rev.ok > * {
  opacity: 1; transform: none;
  transition: opacity .3s ease-out, transform .6s var(--salida);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.cascada > :nth-child(1) { --i: 0; }
.cascada > :nth-child(2) { --i: 1; }
.cascada > :nth-child(3) { --i: 2; }
.cascada > :nth-child(4) { --i: 3; }
.cascada > :nth-child(5) { --i: 4; }
.cascada > :nth-child(6) { --i: 5; }
.cascada > :nth-child(7) { --i: 6; }
.cascada > :nth-child(8) { --i: 7; }

@media (prefers-reduced-motion: reduce) {
  .js .portada__texto > * { animation: none; opacity: 1; transform: none; }
  .mos__p:hover img { transform: none; }
  .boton:hover { transform: none; }
  /* Los reveals NO se desplazan, pero SÍ siguen fundiendo: un fundido
     no es movimiento, un salto de 22 px sí. Apagar los dos deja la
     página muerta, que es justo lo que la regla de la casa prohíbe. */
  .js .rev, .js .cascada.rev > * { transform: none; }
  /* La secuencia entera, sin barrido, y los controles puestos. */
  .js .mapa .ancho.rev .placas { clip-path: none; }
  .js .mapa .ancho.rev.ok .placas { animation: none; }
  .js .mapa .ancho.rev .placas .pt,
  .js .mapa .ancho.rev .placas__pie { opacity: 1; }
  .js .mapa .ancho.rev.ok .placas .pt,
  .js .mapa .ancho.rev.ok .placas__pie { animation: none; }
  /* Arco puesto, sin brillo. */
  .js .escena__svg { animation: none; }
  .js .escena__brillo { animation: none; }
  /* Del botón flotante se apaga el desplazamiento, no el fundido: la
     opacidad es lo que dice si está o no está. */
  .wapp:hover { transform: none; }
  .wapp--arriba { transform: none; }
}
/* ── Blancos de toque ──────────────────────────────────────────────
   Regla de la casa: nada que se toque puede medir menos de 44 px de
   alto. Los enlaces sueltos —el teléfono dentro de la ficha de datos
   y las flechas del cierre— quedaban en 23 y 30 px medidos sobre la
   página a 375 px. Se les da caja propia sin cambiar cómo se ven. */
.datos dd a,
.flecha {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
/* La marca de la cabecera también es un enlace: 44 px mínimos. */
.cab__marca { min-height: 44px; }
/* El botón chico de la cabecera es el CTA principal en teléfono:
   en móvil sube a 44 px como todo lo demás que se toca. */
@media (max-width: 1060px) { .boton--chico { min-height: 44px; } }

/* ══════════════════════════════════════════════════════════════════
   VIDEO DE FONDO
   La foto sigue siendo la base y el clip se funde encima cuando puede
   reproducirse. Si el visitante pidió menos movimiento o ahorra datos,
   main.js no lo pide y no se descarga ni un byte. El arranque en
   opacidad 0 con 1,4 s de fundido es lo que hace que el clip «cobre
   vida»: con 0,3 s se ve el salto y con 2,5 s se ve lento.
   Presupuesto: portada 1,7 MB · banda 0,95 MB, 720p sin audio.
   ══════════════════════════════════════════════════════════════════ */
.portada__video, .cita__video {
  position: absolute; inset: 0; opacity: 0;
  transition: opacity 1.4s ease; pointer-events: none;
}
.portada__video.video--ver, .cita__video.video--ver { opacity: 1; }

/* ══ El difuminado al scroll ═══════════════════════════════════════
   Lo que una demo corriente resuelve con GSAP + ScrollTrigger, 70 KB
   de librería y una petición a un CDN que esta CSP bloquearía. Acá son
   doce líneas que corren en el compositor y sencillamente no existen
   donde el navegador no las soporta.
   El filter va en el CONTENEDOR (.portada__foto), nunca en el <video>,
   y el scale(1.06) acompaña al blur para que el desenfoque no deje ver
   el filo transparente de la caja.
   Fondo claro → blur corto y opacidad: la foto se disuelve hacia la
   porcelana, que es lo que hay debajo. En el teléfono no corre. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 761px) {
    .portada__foto {
      animation: portada-se-va linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 88vh;
    }
    .cita {
      animation: cita-enfoca linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 95%;
    }
  }
}
@keyframes portada-se-va { to { filter: blur(7px); transform: scale(1.06); opacity: .5; } }
@keyframes cita-enfoca   { from { filter: blur(9px); } to { filter: blur(0); } }

/* ── MAPA DE UBICACION ──────────────────────────────────────────────
   Imagen propia con mosaicos de OpenStreetMap pegados: la CSP prohibe
   pedir nada a un tercero, asi que un iframe de Google Maps quedaria en
   blanco SIN dar un solo error. El "Como llegar" si es un enlace, y un
   enlace no lo bloquea nada.
   Los colores salen de currentColor a proposito: asi el bloque se adapta
   a la paleta de cada demo sin conocerla y sin chocar con ella.
   La atribucion a OpenStreetMap la exige su licencia (ODbL). */
.mapa-sec { padding: clamp(2.5rem, 6vw, 4.5rem) 0; }
.mapa { margin: 1.4rem 0 0; border: 1px solid; border-color: color-mix(in srgb, currentColor 22%, transparent); border-radius: 10px; overflow: hidden; }
@supports not (color: color-mix(in srgb, red 50%, blue)) { .mapa { border-color: rgba(128, 128, 128, .35); } }
.mapa img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; }
.mapa__pie {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1rem;
  padding: .75rem .9rem;
  font-size: .86em; line-height: 1.45;
  border-top: 1px solid; border-top-color: color-mix(in srgb, currentColor 22%, transparent);
}
@supports not (color: color-mix(in srgb, red 50%, blue)) { .mapa__pie { border-top-color: rgba(128, 128, 128, .35); } }
.mapa__pie b { font-weight: 700; }
.mapa__ir { color: inherit; font-weight: 700; text-decoration: underline; min-height: 44px; display: inline-flex; align-items: center; }
.mapa__cred { width: 100%; font-size: .84em; opacity: .8; }
.mapa__cred a { color: inherit; }
/* ── BOTON FLOTANTE DE CONTACTO ─────────────────────────────────────
   56 px de alto, por encima del minimo tactil de 44. Los colores de
   marca van a proposito: se reconocen sin leerlos, y eso es lo que hace
   que se toquen. Se ve SIEMPRE por defecto; el JS solo lo aparta sobre
   la portada. Al reves, un fallo del script se llevaria el CTA principal. */
.flota {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right, 0px));
  bottom: max(1rem, env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: inline-flex; align-items: center; gap: .55rem;
  height: 56px; padding: 0 1.15rem 0 1rem;
  border-radius: 999px;
  text-decoration: none;
  font-family: var(--cuerpo, system-ui, sans-serif);
  font-size: .95rem; font-weight: 700; line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .26), 0 2px 6px rgba(0, 0, 0, .16);
  transition: opacity .28s ease, transform .28s ease, box-shadow .18s ease;
}
.flota--wa { background: #25D366; color: #07310F; }
.flota--ig { background: linear-gradient(120deg, #F9CE34 4%, #EE2A7B 48%, #6228D7 96%); color: #FFFFFF; }
.flota__i { width: 26px; height: 26px; fill: currentColor; flex: none; }
.flota:hover, .flota:focus-visible { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(0, 0, 0, .3); }
.js .flota--arriba { opacity: 0; transform: translateY(14px) scale(.94); pointer-events: none; }

@media (max-width: 520px) {
  .flota { width: 56px; padding: 0; justify-content: center; }
  .flota__t { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
@media (prefers-reduced-motion: reduce) {
  .flota { transition: opacity .28s ease; }
  .flota:hover, .flota:focus-visible { transform: none; }
  .js .flota--arriba { transform: none; }
}