/* ==========================================================================
   Calpe Place — sistema de diseño
   Estructura y ritmo adaptados de la maqueta de referencia (Luxury Places):
   cabecera fina, hero centrado con trío de fotos, bandas de tipo a sangre,
   carril de fichas, bloque de servicios numerado, panel oscuro, panorámica y
   pie oscuro.

   Lo que NO se copia de la referencia: su registro. El cliente pidió por
   escrito «asequible y bonito, cercano — NO lujo frío» (PRODUCT.md). Así que
   el negro y el casi-blanco se sustituyen por el crema y el teal de marca, el
   interletrado se afloja, y los titulares largos van en caja normal — las
   mayúsculas se reservan para etiquetas, navegación y botones.

   Estático puro: sin librerías, sin build. Ver DESIGN.md.
   ========================================================================== */

/* -------------------------------------------------------------- Fuentes -- */
/* VARIANTE TIPOGRÁFICA — Fraunces (voz) + Onest (lectura y oficio).
   Noto Sans es la tipografía de apoyo del kit, pero es la letra de recambio de
   Google: se diseñó para cubrir todos los alfabetos con la mínima personalidad
   posible, y es literalmente lo que pinta el navegador cuando no carga nada.
   De ahí la sensación de plantilla. Aquí la voz pasa a una serif cálida y el
   oficio a una grotesca legible. El wordmark sigue siendo imagen, nunca webfont.

   Dos archivos variables, servidos por tramo con unicode-range: el español
   solo baja `latin` (Fraunces 67 KB + Onest 32 KB). El cirílico de la versión
   RU no se descarga hasta que hace falta. */

/* Fraunces — titulares. Variable opsz 9-144 × wght 300-700 (OFL). */
@font-face{
  font-family:"Fraunces";
  src:url("../fonts/fraunces-latin.woff2") format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Fraunces";
  src:url("../fonts/fraunces-latin-ext.woff2") format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap;
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* Onest — cuerpo, etiquetas, navegación y datos. Variable wght 300-700 (OFL).
   Se eligió con el ruso en la mano: está dibujada para latín Y cirílico por el
   mismo diseñador, así que la versión RU no cambia de voz. Fraunces no lleva
   cirílico: en /ru/ los titulares caen a Onest, y es la caída correcta. */
@font-face{
  font-family:"Onest";
  src:url("../fonts/onest-latin.woff2") format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Onest";
  src:url("../fonts/onest-latin-ext.woff2") format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap;
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:"Onest";
  src:url("../fonts/onest-cyrillic.woff2") format("woff2");
  font-weight:300 700;font-style:normal;font-display:swap;
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

/* --------------------------------------------------------------- Tokens -- */
:root{
  /* Marca (brand_color.pdf del cliente) */
  --teal:#00A2B0;
  --cream:#F5E7D3;
  --aqua:#D9EEF1;
  /* Derivados para contraste AA — el kit no traía un oscuro apto */
  --teal-700:#046E79;
  --teal-800:#06515A;
  --ink:#22333B;
  --ink-soft:#5A6C74;

  /* Superficies */
  --paper:#FBF7F0;          /* fondo de página: crema muy suave, nunca blanco */
  --paper-2:#F5EFE4;        /* alternancia sutil */
  --on-deep:#F3E9DA;
  --on-deep-soft:#A9C4CA;
  --line:rgba(34,51,59,.14);
  --line-soft:rgba(34,51,59,.08);
  --veil:6,45,50;           /* velo sobre foto, en canales */
  --on-photo:#FFF8EE;
  --photo:255,248,238;

  --err-bg:#F7DCD4;
  --err-fg:#7A2E16;

  /* Tema por bloque: cada sección redefine estas cuatro y todo lo hereda. */
  --bg:var(--paper);
  --fg:var(--ink);
  --fg-soft:var(--ink-soft);
  --rule:var(--line);

  --font:"Onest",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  /* La voz. Georgia de respaldo porque es la serif de pantalla que hay en todas
     partes: si Fraunces tarda, el titular no salta de serif a sans. */
  --font-voz:"Fraunces",Georgia,"Times New Roman",serif;

  /* Escala tipográfica sobre un ancho de referencia de 1800 px */
  --t-display:clamp(1.9rem,3.6vw,3.4rem);   /* h1 del hero, en versal */
  --t-h1:clamp(1.75rem,3vw,2.75rem);
  --t-h2:clamp(1.4rem,2.1vw,2.125rem);
  --t-h3:clamp(1.15rem,1.5vw,1.4rem);
  --t-body:clamp(.9375rem,.4vw + .75rem,1.0625rem);
  --t-lead:clamp(1rem,1vw + .5rem,1.1875rem);
  --t-card:clamp(.95rem,1.05vw,1.0625rem);
  --t-meta:.8125rem;
  --t-label:.6875rem;       /* etiquetas en versal con mucho tracking */
  --t-micro:.625rem;

  /* Tracking. La referencia llega a .34em; aquí se afloja para no enfriar.
     La versal de una serif necesita menos aire que la de una sans —los remates
     ya separan—, así que el display baja de .08 a .05em. Las etiquetas siguen
     en Onest y conservan su receta. */
  --tr-display:.05em;
  --tr-label:.2em;
  --tr-btn:.16em;

  /* Espaciado: 7 pasos, misma referencia de 1800 px */
  --sp-xxs:clamp(1rem,2.22vw,2rem);
  --sp-xs:clamp(1rem,2.78vw,2.5rem);
  --sp-sm:clamp(1.5rem,3.33vw,3rem);
  --sp-md:clamp(2.5rem,5.56vw,5rem);
  --sp-lg:clamp(3.5rem,8.33vw,7.5rem);
  --sp-xl:clamp(5rem,11.11vw,10rem);

  --r:2px;
  --container:100rem;
  --container-prose:60rem;
  --gutter:clamp(1.25rem,3.4vw,3rem);
  --header-h:68px;
  --bookbar-h:4.5rem;

  /* Una sola curva en todo el sitio. */
  --ease:cubic-bezier(.6,0,.3,1);
}

/* ---------------------------------------------------------------- Reset -- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0}
html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--header-h) + 1rem);
}
body{
  font-family:var(--font);
  font-size:var(--t-body);
  font-weight:400;
  line-height:1.6;
  color:var(--fg);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,picture,svg,video{display:block;max-width:100%}
img{height:auto}
button,input,select,textarea{font:inherit;color:inherit}
a{color:inherit;text-decoration:none}
ul,ol{list-style:none;padding:0}
/* Los titulares son la voz. Peso 400, no 300: en Fraunces el peso ligero
   adelgaza los finos hasta el registro de revista de moda —lujo frío, justo lo
   que el cliente descartó por escrito—, mientras que en 400 la letra tiene el
   cuerpo cálido de una serif antigua. El interletrado se cierra porque una
   serif ya viene ajustada de origen. */
h1,h2,h3,h4{
  font-family:var(--font-voz);
  font-weight:400;line-height:1.14;letter-spacing:-.015em;text-wrap:balance;
  font-optical-sizing:auto;   /* Fraunces afina los remates según el tamaño */
}

::selection{background:var(--teal-800);color:var(--paper)}
:focus-visible{outline:2px solid var(--teal);outline-offset:3px;border-radius:var(--r)}

.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--ink);color:var(--paper);padding:.85rem 1.25rem}
.skip:focus{left:.75rem;top:.75rem}
.sr{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* -------------------------------------------------------- Contenedores -- */
.wrap{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
.wrap--prose{max-width:var(--container-prose)}

/* Tema por bloque */
.on-deep{--bg:var(--teal-800);--fg:var(--on-deep);--fg-soft:var(--on-deep-soft);--rule:rgba(243,233,218,.2)}
.on-cream{--bg:var(--cream);--fg:var(--ink);--fg-soft:var(--ink-soft);--rule:rgba(34,51,59,.16)}
.on-aqua{--bg:var(--aqua);--fg:var(--ink);--fg-soft:var(--ink-soft);--rule:rgba(34,51,59,.14)}
.on-paper2{--bg:var(--paper-2)}
[class*="on-"]{background:var(--bg);color:var(--fg)}

/* ------------------------------------------------- Piezas de tipografía -- */
/* La versalita con tracking es el hilo que cose toda la maqueta: etiqueta de
   sección, dato de ficha, navegación y botón usan la misma receta. */
.label{
  display:inline-block;font-size:var(--t-label);font-weight:500;
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--teal-700);
}
.on-deep .label{color:var(--aqua)}
.label--c{display:block;text-align:center}

.meta{
  display:flex;flex-wrap:wrap;gap:.35rem 1.15rem;
  font-size:var(--t-label);letter-spacing:.1em;text-transform:uppercase;
  color:var(--fg-soft);font-variant-numeric:tabular-nums;
}

.lead{font-size:var(--t-lead);font-weight:400;line-height:1.62;color:var(--fg-soft)}

/* -------------------------------------------------------------- Botones -- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  padding:13px 26px;border:1px solid transparent;border-radius:var(--r);
  background:var(--teal-800);color:var(--paper);
  font-size:var(--t-label);font-weight:500;letter-spacing:var(--tr-btn);text-transform:uppercase;
  cursor:pointer;text-align:center;
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease);
}
.btn svg{width:15px;height:15px;flex:none;transition:transform .3s var(--ease)}
.btn--ghost{background:transparent;color:var(--fg);border-color:var(--rule);padding:12px 25px}
.btn--light{background:var(--cream);color:var(--teal-800)}
.btn--sm{padding:10px 20px}
@media (hover:hover) and (pointer:fine){
  .btn:hover{background:var(--teal);color:#062E33}
  .btn:hover svg{transform:translateX(3px)}
  .btn--ghost:hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
  .btn--light:hover{background:var(--aqua)}
}
/* El relleno solo da 45,6 px de alto y el fantasma 44: justo en el filo del
   mínimo táctil de Apple, y por debajo en cuanto la etiqueta baja de línea.
   En el dedo se nota; con ratón no cambia nada, por eso va acotado. */
@media (width <= 48rem){
  .btn{min-height:48px}
}

.arrow{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:var(--t-label);font-weight:500;letter-spacing:var(--tr-btn);text-transform:uppercase;
  color:var(--fg);padding-bottom:.4rem;border-bottom:1px solid var(--teal);
  transition:gap .3s var(--ease);
}
@media (hover:hover) and (pointer:fine){.arrow:hover{gap:.9rem}}

/* ------------------------------------------------------------ Cabecera -- */
/* Barra que se encoge a píldora flotante al bajar 100 px. Es el patrón del
   `resizable-navbar` de Aceternity, portado a CSS/JS puro: aquí no hay React ni
   librería de animación, y el markup de las 30 páginas no se toca ni una línea
   —cada pieza del componente ya tenía su equivalente en esta cabecera.

   Sobre la paleta: la píldora es blanca y el hover gris, que son los colores del
   componente original, no los de la marca. Es una decisión tomada a sabiendas.
   Para devolverlo al registro crema/teal bastan dos valores: el `background` de
   `.is-float .header__in` y el de `.nav__pill`. */
.header{
  position:sticky;top:0;z-index:40;
  /* Transparente a propósito: lo que se ve es la píldora de dentro y el
     contenido pasando por debajo. La altura mínima se queda fija para que al
     encogerse la píldora la página no dé un salto. */
  background:transparent;border-bottom:0;
  min-height:var(--header-h);
}
.header__in{
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-xs);
  min-height:var(--header-h);
  /* El original anima con muelle (stiffness 200, damping 50). Ese ratio de
     amortiguación es 1,77: sobreamortiguado, no rebota. Una curva de salida lo
     reproduce igual y sin pagar una librería de física. */
  transition:width .5s cubic-bezier(.2,.8,.2,1),min-width .5s cubic-bezier(.2,.8,.2,1),
             min-height .5s cubic-bezier(.2,.8,.2,1),padding .5s cubic-bezier(.2,.8,.2,1),
             gap .5s cubic-bezier(.2,.8,.2,1),
             transform .5s cubic-bezier(.2,.8,.2,1),border-radius .5s cubic-bezier(.2,.8,.2,1),
             background-color .5s cubic-bezier(.2,.8,.2,1),box-shadow .5s cubic-bezier(.2,.8,.2,1);
}
/* Píldora flotante. Medidas y sombra multicapa calcadas del componente. */
/* Las medidas salen de medir, no de copiar: con los 800 px del original el
   contenido de esta cabecera no cabía —el wordmark es mucho más ancho que el
   logotipo cuadrado de la maqueta— y el botón se salía 43 px por la derecha.
   860 px y un hueco de 1rem dejan holgura de sobra. */
.header.is-float .header__in{
  width:46%;min-width:940px;min-height:56px;
  gap:1rem;
  padding-inline:1rem;
  border-radius:9999px;
  background:rgba(255,255,255,.8);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:0 0 24px rgba(34,42,53,.06),0 1px 1px rgba(0,0,0,.05),
             0 0 0 1px rgba(34,42,53,.04),0 0 4px rgba(34,42,53,.08),
             0 16px 68px rgba(47,48,55,.05),0 1px 0 rgba(255,255,255,.1) inset;
  transform:translateY(20px);
}
@media (prefers-reduced-motion:reduce){
  .header__in{transition:none}
}
.header__logo{
  display:block;width:clamp(104px,9.5vw,138px);flex:none;
  transition:width .5s cubic-bezier(.2,.8,.2,1);
}
.header__logo img{width:100%;display:block}
/* Al encogerse la barra el wordmark encoge con ella. A 138 px de ancho mide 55
   de alto y llenaba de borde a borde una píldora de 56: por eso se veía
   desproporcionado. A 100 px se queda en 42 y deja los mismos ~7 px de aire
   arriba y abajo que tiene el botón. */
.header.is-float .header__logo{width:100px}

.nav{display:flex;align-items:center;gap:.25rem;position:relative}
/* Registro del componente de referencia: caja normal en vez de versal, gris
   medio y peso 500. El subrayado teal se retira porque aquí la señal de hover
   pasa a ser la pastilla que sigue al ratón. */
.nav__link{
  font-size:.875rem;font-weight:500;color:#525252;
  padding:.5rem 1rem;position:relative;z-index:20;
  transition:color .2s var(--ease);
}
.nav__link[aria-current="page"]{color:#171717}
@media (hover:hover) and (pointer:fine){
  .nav__link:hover{color:#171717}
}
/* La pastilla es el `layoutId="hovered"` del original: un solo elemento que se
   mueve y se reescala entre enlaces en vez de un fondo por enlace. La inyecta
   el JS, de modo que ninguna de las 30 páginas cambia de markup. */
.nav__pill{
  position:absolute;top:0;left:0;height:100%;width:0;
  border-radius:9999px;background:#f5f5f5;
  opacity:0;pointer-events:none;z-index:0;
  transition:transform .25s var(--ease),width .25s var(--ease),opacity .2s var(--ease);
}
.nav__pill.is-on{opacity:1}
/* Con seis enlaces el interlineado horizontal se aprieta un punto al flotar;
   la pastilla se reajusta sola porque el JS lee el ancho en cada hover. */
.header.is-float .nav__link{padding-inline:.75rem}
@media (prefers-reduced-motion:reduce){
  .nav__pill{transition:opacity .2s var(--ease)}
}

.header__tools{display:flex;align-items:center;gap:.85rem}
.lang{
  display:inline-flex;align-items:center;gap:.3rem;
  font-size:.875rem;font-weight:500;color:#525252;
}
/* Selector de idioma (14 sep 2026): el idioma actual en negrita y sin enlace,
   los demás como enlace a la misma página traducida. */
.lang a{color:inherit;padding:.2rem .15rem}
.lang a:hover{color:#171717}
.lang [aria-current]{color:#171717;font-weight:700}
/* En móvil la cabecera esconde .lang: el selector vive en el menú. */
.drawer__lang{
  display:flex;align-items:center;gap:.5rem;
  padding:.35rem 0;border-bottom:1px solid var(--line-soft);
  font-size:1rem;font-weight:500;color:#525252;
}
.drawer .drawer__lang a{
  border:0;font-size:inherit;color:inherit;
  padding:.6rem .5rem;
}
.drawer__lang [aria-current]{color:#171717;font-weight:700}
/* El CTA pasa a la variante `dark` del `NavbarButton`: negro, esquina blanda y
   ese medio píxel de elevación al pasar el ratón. Va después de `.btn:hover`
   a propósito —misma especificidad, gana el último— para que no le entre el
   teal de la marca. */
/* Redondeo completo, no los 6 px del componente original. Con una píldora de
   9999 px alrededor, un rectángulo pegado al borde curvo se lee como un error:
   dos formas concéntricas se leen como una decisión. */
.header__cta{
  padding:.5rem 1.15rem;border-radius:9999px;
  background:#000;color:#fff;
  font-size:.875rem;font-weight:700;letter-spacing:0;text-transform:none;
  box-shadow:0 0 24px rgba(34,42,53,.06),0 1px 1px rgba(0,0,0,.05),
             0 0 0 1px rgba(34,42,53,.04),0 0 4px rgba(34,42,53,.08),
             0 16px 68px rgba(47,48,55,.05),0 1px 0 rgba(255,255,255,.1) inset;
  transition:transform .2s var(--ease),background .2s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .header__cta:hover{background:#171717;color:#fff;transform:translateY(-2px)}
}
@media (prefers-reduced-motion:reduce){
  .header__cta:hover{transform:none}
}
.burger{
  display:none;width:44px;height:44px;align-items:center;justify-content:center;
  background:none;border:0;cursor:pointer;color:var(--ink);
}
.burger span,.burger span::before,.burger span::after{
  display:block;width:20px;height:1.5px;background:currentColor;
  transition:transform .35s var(--ease),opacity .2s;
}
.burger span{position:relative}
.burger span::before,.burger span::after{content:"";position:absolute;left:0}
.burger span::before{top:-6px}
.burger span::after{top:6px}
.burger[aria-expanded="true"] span{background:transparent}
.burger[aria-expanded="true"] span::before{transform:translateY(6px) rotate(45deg)}
.burger[aria-expanded="true"] span::after{transform:translateY(-6px) rotate(-45deg)}

/* Panel del `MobileNavMenu`. Deja de deslizarse desde detrás de la cabecera —ya
   no hay cabecera opaca que lo tape— y entra fundiéndose, como el original. */
.drawer{
  position:fixed;left:0;right:0;top:var(--header-h);z-index:39;
  background:#fff;
  display:grid;gap:.25rem;padding:var(--sp-xs) var(--gutter) var(--sp-sm);
  box-shadow:0 0 24px rgba(34,42,53,.06),0 1px 1px rgba(0,0,0,.05),
             0 0 0 1px rgba(34,42,53,.04),0 0 4px rgba(34,42,53,.08),
             0 16px 68px rgba(47,48,55,.05),0 1px 0 rgba(255,255,255,.1) inset;
  opacity:0;transform:translateY(-8px);visibility:hidden;
  transition:opacity .25s var(--ease),transform .25s var(--ease),visibility .25s;
}
.drawer.is-open{opacity:1;transform:translateY(0);visibility:visible}
/* Con la cabecera flotando, el panel se alinea con la píldora: mismo 90 % de
   ancho, mismos 20 px de caída y esquina redondeada. */
.header.is-float + .drawer{
  left:5%;right:5%;top:calc(var(--header-h) + 20px);
  border-radius:8px;padding-inline:1rem;
}
.drawer a{
  color:#525252;font-size:var(--t-h3);font-weight:400;
  padding:.65rem 0;border-bottom:1px solid var(--line-soft);
}
.drawer .btn{
  margin-top:var(--sp-xxs);
  background:#000;color:#fff;border-radius:6px;
  letter-spacing:0;text-transform:none;font-size:.875rem;font-weight:700;
}
@media (hover:hover) and (pointer:fine){
  .drawer a:hover{color:#171717}
  .drawer .btn:hover{background:#171717;color:#fff}
}
@media (prefers-reduced-motion:reduce){
  .drawer{transition:opacity .25s var(--ease),visibility .25s;transform:none}
  .drawer.is-open{transform:none}
}

@media (width <= 64rem){
  .nav,.header__tools .lang{display:none}
  .header__cta{display:none}
  .burger{display:flex}
  /* Variante móvil de la píldora: el componente la lleva al 90 % y le quita casi
     todo el redondeo. Sin `min-width`, que los 800 px del escritorio se saldrían
     de pantalla. */
  .header.is-float .header__in{
    width:90%;min-width:0;padding-inline:12px;border-radius:4px;
    /* .8 de blanco basta en escritorio, donde la píldora cae sobre el centro
       de la foto. En vertical el recorte cambia y acaba sobre el mar: el
       blur tiñe el cristal de azul y el logotipo turquesa se pierde encima.
       A .94 el tinte ya no llega a comprometerlo, y el efecto se conserva. */
    background:rgba(255,255,255,.94);
  }
  /* La barra del iPhone se come el borde de arriba en cuanto hay muesca. */
  .header{padding-top:env(safe-area-inset-top,0px)}
  /* El wordmark encogido mide 42 px de alto y es el enlace a la portada: se le
     da caja hasta los 44 sin tocar el dibujo, que sigue igual de grande. */
  .header__logo{display:flex;align-items:center;min-height:44px}
  /* La cabecera es `sticky`, así que en vertical se comía sus 68 px de alto
     antes de que empezara la foto: la píldora quedaba apoyada sobre una franja
     crema vacía en vez de superpuesta al hero, que es como está diseñada. El
     margen negativo devuelve la escena al borde superior; el texto no se tapa
     porque `.hero-par__texto` ya reserva `--header-h` de padding. */
  .hero-par{margin-top:calc(var(--header-h) * -1)}
}

/* ================================================================ HERO ==
   Titular corto centrado y dos acciones, sobre la escena de Calpe. Nada más:
   la foto es el argumento y el texto solo la estorbaba.
   ========================================================================== */
/* Se acorta a propósito: lo que viene debajo es el trío, y tiene que asomar
   en la primera pantalla para que se entienda que hay algo que abrir. */
.hero{padding-block:clamp(2rem,4.5vw,4.5rem) 0}
/* El titular va en Onest, no en Fraunces, y en caja normal. La versión anterior
   —tres líneas de versal serif con tracking— era el elemento que más tapaba la
   foto, que es lo primero que entra y lo mejor que tiene la portada. Ahora es
   una línea, y todo el peso visual se lo queda la bahía. */
.hero h1{
  margin-inline:auto;text-align:center;
  font-family:var(--font);
  font-size:var(--t-display);font-weight:400;line-height:1.16;
  letter-spacing:-.015em;text-wrap:balance;
}
.hero__actions{display:flex;flex-wrap:wrap;justify-content:center;gap:.75rem;margin-top:var(--sp-xs)}

@media (width <= 48rem){
  /* Los dos CTA se dimensionaban cada uno por su contenido: 249 y 228 px
     medidos en un iPhone 15 Pro. Apilados y centrados el escalón se ve, y se
     lee como descuido. Mismo ancho para los dos y tope para que no crucen la
     pantalla de lado a lado en los móviles grandes. */
  .hero__actions{flex-direction:column;align-items:center}
  .hero__actions .btn{width:100%;max-width:20rem}
}

/* ------------------------------------------------ Hero · escena de Calpe -- */
/* Tres planos de una misma foto que se separan al bajar. El recorrido es el
   alto del track menos la pantalla: 80vh de scroll para 100svh de escena.

   Geometría: cada capa es más alta que el escenario y asoma por arriba y por
   abajo (`top:-18%; height:136%`). Ese margen es el que consume el
   desplazamiento — la capa de delante llega a subir un 15% de su propio alto
   y aun así no destapa el borde inferior. Lo que queda al filo lo cubre el
   degradado de salida. Si se suben los valores de hero-parallax.js hay que
   subir también este 136%.

   Las tres capas comparten PROPORCIÓN, así que object-fit:cover las recorta
   igual y siguen cuadrando al píxel aunque tengan distinta resolución. */
.hero-par{position:relative}
.hero-par__track{height:180vh}
.hero-par__stage{
  position:sticky;top:0;height:100svh;overflow:hidden;
  background:var(--teal-800);
}
.hero-par__layers{position:absolute;inset:0}
.hero-par__layer{position:absolute;left:0;width:100%;top:-18%;height:136%}
.hero-par__layer img{width:100%;height:100%;object-fit:cover;display:block}
/* Las capas de foto son decorado: no pueden atrapar el ratón. La 4 va por
   delante del titular a propósito, y sin esto se comía los clics del botón
   principal — el botón se veía, pero no se podía pulsar. */
.hero-par__layer:not(.hero-par__texto){pointer-events:none}

/* El orden manda la profundidad: el velo va sobre el paisaje pero bajo el
   titular, y el primer plano por delante de todo — como en el recurso
   original, donde la capa 4 pasa por delante del título. Que los tejados
   rocen los botones es lo que mete el texto DENTRO de la escena. */
.hero-par__layer[data-capa="1"]{z-index:1}
.hero-par__layer[data-capa="2"]{z-index:2}
.hero-par__velo{position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(var(--veil),.34) 0%,rgba(var(--veil),.14) 18%,
    rgba(var(--veil),.48) 52%,rgba(var(--veil),.56) 78%,rgba(var(--veil),.26) 100%);
}
.hero-par__layer[data-capa="4"]{z-index:5}

/* El bloque de texto va POR DELANTE del primer plano, en todas las ventanas.
   Antes iba detras (z-index 4) para que los tejados rozaran el titular, y solo
   se adelantaba por debajo de 800 px de alto de ventana. Medida la capa 4 sobre
   el CTA en reposo: alfa 0 a 860 px de alto, .017 a 800, .05 a 760, .136 a 700
   y .189 a 663. Con ese ultimo velo el fondo del boton deja de ser crema
   (245,231,211) y se vuelve gris verdoso (199,205,198): sigue pasando AA, pero
   pierde su color y ya no se distingue del boton fantasma de al lado. El umbral
   tampoco protegia de verdad — en ventanas altas el velo es flojo pero se ve.
   El roce de los tejados es el precio, y es barato: `hero-parallax.js` sube el
   texto un -24% contra el -15% de la capa 4 y lo apaga al 55% del recorrido,
   asi que el titular se marcha ANTES de que el primer plano llegue a su altura.
   Lo que se recupera es la jerarquia de la llamada a la accion, que es para lo
   que esta la portada.
   `.hero-par__fade` tambien es 6 y va detras en el HTML, asi que sigue tapando
   el texto por abajo cuando la escena entrega al escenario de tipos. */
.hero-par__texto{z-index:6}

/* El titular no es una capa de imagen: no tiene que tapar nada, así que no
   necesita el sobrealto. Se sienta por encima del centro para dejar que el
   primer plano entre por debajo. */
.hero-par__texto{
  top:0;height:100%;display:flex;align-items:center;justify-content:center;
  /* El bloque se sienta por encima del centro para que los botones queden por
     ENCIMA de donde el primer plano empieza a hacerse opaco. Que los tejados
     rocen el titular mete el texto dentro de la escena; que tapen la llamada a
     la acción es otra cosa.

     El número sale de una cuenta, no del ojo: la capa 4 empieza a aparecer en
     el 58% de SU imagen, y como la capa mide un 136% del escenario y arranca
     en -18%, eso cae en el 61% de la pantalla (-18 + 0,58 × 136). Con 30svh
     abajo, el borde inferior del botón queda por encima de esa línea desde
     ~800 px de alto de ventana. Si se toca AGUA en hero_capas.py, este número
     se recalcula. */
  padding-top:calc(var(--header-h) + var(--sp-sm));padding-bottom:30svh;
  --fg:var(--on-photo);--fg-soft:rgba(var(--photo),.88);--rule:rgba(var(--photo),.42);
  color:var(--fg);
}
/* Velo propio, pegado al texto y no a la pantalla. El velo general no basta
   aquí: en escritorio el titular cae justo sobre la bahía y los edificios
   blancos, que es lo más claro de la foto, y en móvil sobre mar abierto, que
   es de los más oscuros. Un velo plano que valga para la bahía ensucia el
   resto de la escena. Este viaja con el titular —comparte capa— así que sigue
   cubriéndolo mientras sube. */
.hero-par__texto{
  background:radial-gradient(115% 52% at 50% 44%,
    rgba(var(--veil),.62) 0%,rgba(var(--veil),.44) 42%,
    rgba(var(--veil),.14) 72%,rgba(var(--veil),0) 100%);
}
.hero-par__texto .hero{padding-block:0}
.hero-par__texto .btn--ghost{color:var(--on-photo);border-color:rgba(var(--photo),.5)}

/* Entrega a la sección de abajo: la escena se disuelve en el papel en vez de
   cortarse con una línea recta. También es lo que tapa el filo de la capa de
   delante cuando ha subido del todo. */
.hero-par__fade{
  position:absolute;left:0;right:0;bottom:0;height:24svh;z-index:6;pointer-events:none;
  background:linear-gradient(180deg,rgba(251,247,240,0),var(--paper) 92%);
}

/* Se promete al compositor solo mientras la escena ronda la pantalla, igual
   que el escenario de tipos — y solo las dos capas que de verdad recorren
   distancia. Promocionar las cuatro son cuatro texturas del tamaño de la
   pantalla en memoria de GPU a la vez; con eso llegué a colgar el
   renderizador tres veces seguidas mientras probaba. La capa 1 apenas se
   mueve (un 3%) y va a 1100 px, y el titular es texto: ninguna lo necesita. */
.hero-par.is-near .hero-par__layer[data-capa="2"],
.hero-par.is-near .hero-par__layer[data-capa="4"]{will-change:transform}

/* En móvil no se promociona nada: es donde la memoria de GPU escasea y donde
   un hero en blanco haría más daño. */
@media (max-width:47.99rem){
  .hero-par.is-near .hero-par__layer{will-change:auto}
}

@media (max-width:47.99rem){
  /* En móvil el recorrido se acorta: la escena es vertical y hay menos sitio
     donde separar los planos antes de que canse. En svh y no en vh porque el
     stage mide 100svh: con el track en vh las dos medidas dejan de cuadrar en
     cuanto iOS colapsa la barra de Safari, y el hero pega un salto. */
  .hero-par__track{height:130svh}
  .hero-par__texto{padding-bottom:16svh}
}

/* Sin movimiento: las tres capas en reposo recomponen la foto entera, así que
   no hay nada que apagar — solo se quita el recorrido muerto del track. */
@media (prefers-reduced-motion:reduce){
  .hero-par__track{height:auto}
  .hero-par__stage{position:relative}
}

/* -------------------------------------------------------------- Sección -- */
.sec{padding-block:var(--sp-lg)}
.sec--tight{padding-block:var(--sp-md)}
.sec__head{margin-bottom:var(--sp-sm)}
.sec__head--c{text-align:center}
.sec__head h2{
  font-size:var(--t-h2);margin-top:.75rem;
  letter-spacing:-.01em;
}
.sec__head--c h2{margin-inline:auto;max-width:22ch}
.sec__head .lead{margin-top:var(--sp-xxs);max-width:60ch}
.sec__head--c .lead{margin-inline:auto}
.sec__cta{display:flex;justify-content:center;margin-top:var(--sp-xs)}
.sec__after{
  display:flex;flex-wrap:wrap;gap:var(--sp-xs);align-items:center;
  justify-content:space-between;margin-top:var(--sp-sm);
}

/* ============================================= TIPOS · ESCENARIO DE ZOOM ==
   Arranca como el trío de siempre. Al bajar, el marco central se abre hasta
   ocupar la pantalla y las laterales se van hacia fuera; después el recorrido
   pasa por los tres tipos con fundido cruzado.

   ⚠️ El aviso de DESIGN.md sigue en pie y aquí se cumple al pie de la letra:
   NO se anima ni una propiedad de layout. El marco central mide siempre el
   escenario entero y lo único que cambia es su clip-path; las laterales se van
   con translate y las fotos hacen zoom con scale. Las tres son propiedades
   compuestas: el layout no se rehace en ningún frame y el alto del documento
   no se mueve ni un píxel mientras bajas. El JS solo escribe --p y opacidades.
   ========================================================================== */
/* Probado el 20 ago 2026 y descartado: declarar `--p` con `@property` como
   `<number>` no cambia nada. Medido a 4x de freno, 150 fotogramas x 3: el
   recálculo de estilo pasó de 145 a 153 ms, o sea nada. No merece la línea. */
.zoom{
  --p:0;              /* apertura del marco: 0 en reposo, 1 a pantalla completa */
  --cx:22%;           /* recorte lateral en reposo → 56% de ancho */
  /* El superior tiene que dejar pasar la cabecera pegajosa: con menos, el
     borde de arriba de la foto en reposo se mete debajo y parece cortada. */
  --ct:12%;
  --cb:20%;
  --track:460svh;     /* recorrido: abrir el marco + los tres tipos */
  position:relative;
}
.zoom__track{height:var(--track)}
.zoom__stage{
  position:sticky;top:0;overflow:hidden;background:var(--paper);
  height:100vh;height:100svh;
}

/* Laterales: se van hacia fuera y se apagan según se abre la central. */
.zoom__side{
  position:absolute;top:46%;z-index:1;margin:0;   /* centro del marco en reposo */
  width:clamp(7rem,15vw,15.5rem);aspect-ratio:3/4;
  overflow:hidden;border-radius:var(--r);background:var(--line-soft);
  transform:translate3d(var(--sx,0),-50%,0);
  opacity:calc(1 - var(--p) * 2);
}
.zoom__side img{width:100%;height:100%;object-fit:cover;object-position:var(--pos,50% 50%)}
.zoom__side--l{left:var(--gutter);--sx:calc(var(--p) * -165%)}
.zoom__side--r{right:var(--gutter);--sx:calc(var(--p) * 165%)}

/* El marco: ocupa el escenario entero desde el primer frame. Lo que se abre
   es el recorte, así que crecer no le cuesta al layout nada. */
/* El `- 1px * var(--p)` de cada lado no es maquillaje: con el marco abierto del
   todo, el borde del recorte caía JUSTO sobre el borde de la pantalla, y el
   navegador dibuja ahí una raya de un píxel suavizada —la costura del clip—
   que en un móvil, sobre foto oscura, se ve como una línea clara pegada al
   canto. Sacando el recorte 1 px fuera de la caja, la costura cae fuera de la
   pantalla y no hay nada que ver. El radio también se va a cero al abrirse:
   una foto a sangre no lleva esquinas redondeadas, y esas esquinas eran el
   otro sitio donde asomaba la costura. */
.zoom__core{
  position:absolute;inset:0;z-index:2;
  clip-path:inset(
    calc(var(--ct) * (1 - var(--p)) - 1px * var(--p))
    calc(var(--cx) * (1 - var(--p)) - 1px * var(--p))
    calc(var(--cb) * (1 - var(--p)) - 1px * var(--p))
    calc(var(--cx) * (1 - var(--p)) - 1px * var(--p))
    round calc(var(--r) * (1 - var(--p))));
}
.zoom__slide{position:absolute;inset:0;display:block;opacity:0}
.zoom__slide:first-child{opacity:1}   /* lo que se ve antes de que el JS tome el mando */
/* El <picture> solo está para servir la foto de móvil; que no se interponga
   entre el slide y la <img>, o el height:100% de abajo se quedaría sin contra
   qué medirse. */
.zoom__slide picture{display:contents}
.zoom__slide img{
  width:100%;height:100%;object-fit:cover;object-position:var(--pos,50% 50%);
  transform:scale(calc(1 + var(--p) * .18));
}
/* Velo: flojo mientras la foto es pequeña, entero cuando el rótulo cae encima.
   Los tramos son los mismos que valida DESIGN.md — el rótulo aterriza sobre
   agua de piscina y césped al sol, de los fondos más claros que hay. */
.zoom__slide::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(var(--veil),.5) 0%,rgba(var(--veil),.08) 30%,
    rgba(var(--veil),.08) 46%,rgba(var(--veil),.52) 80%,rgba(var(--veil),.82) 100%);
  opacity:calc(.28 + var(--p) * .72);
}

/* Rótulo del tipo: solo cuando la foto ya manda en la pantalla. */
.zoom__cap{
  position:absolute;left:var(--gutter);right:var(--gutter);z-index:1;
  bottom:calc(clamp(1.25rem,2.6vw,2.25rem) + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;gap:.4rem;color:var(--on-photo);
  opacity:calc((var(--p) - .82) * 5.6);
  /* Las fotos se funden; los rótulos NO. Dos textos al 50% en el mismo sitio
     se leen como un fallo de pintado, así que se relevan: el saliente se va en
     180 ms y el entrante espera a que se haya ido. */
  transition:opacity .22s var(--ease) .2s;
}
.zoom__slide[inert] .zoom__cap{opacity:0;transition:opacity .18s var(--ease) 0s}
.zoom__kind{font-family:var(--font-voz);font-size:var(--t-h2);font-weight:400;letter-spacing:-.015em;line-height:1.12;max-width:18ch}
.zoom__n{
  font-size:var(--t-label);letter-spacing:.14em;text-transform:uppercase;
  color:rgba(var(--photo),.85);font-variant-numeric:tabular-nums;
}

/* Rótulo de reposo: dice qué son las tres fotos y se apaga al abrirse. */
.zoom__hint{
  position:absolute;left:50%;bottom:clamp(1.5rem,4vh,3rem);z-index:3;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:.5rem;
  font-size:var(--t-label);font-weight:500;letter-spacing:var(--tr-label);
  text-transform:uppercase;color:var(--fg-soft);white-space:nowrap;
  opacity:calc(1 - var(--p) * 2.6);
}
.zoom__hint svg{width:13px;height:13px;flex:none}

.zoom__pager{
  position:absolute;right:var(--gutter);z-index:3;
  bottom:calc(clamp(1.25rem,2.6vw,2.25rem) + env(safe-area-inset-bottom,0px));
  display:flex;align-items:center;gap:.7rem;
  font-size:var(--t-label);letter-spacing:var(--tr-label);color:var(--on-photo);
  font-variant-numeric:tabular-nums;
  opacity:calc((var(--p) - .82) * 5.6);
}
.zoom__bars{display:flex;gap:.3rem}
.zoom__bars i{display:block;width:20px;height:2px;background:rgba(var(--photo),.38);transition:background .4s var(--ease)}
.zoom__bars i.is-on{background:var(--on-photo)}

/* La pastilla sigue al cursor y aparece justo debajo. Es solo el rótulo: el
   clic lo recoge el propio tipo, que ocupa la pantalla entera. */
.zoom__pill{
  position:fixed;left:0;top:0;z-index:45;pointer-events:none;
  display:inline-flex;align-items:center;gap:.55rem;
  padding:11px 20px;border-radius:var(--r);
  background:rgba(var(--photo),.94);color:var(--teal-800);
  font-size:var(--t-label);font-weight:500;letter-spacing:var(--tr-btn);
  text-transform:uppercase;white-space:nowrap;
  transform:translate3d(var(--mx,50vw),var(--my,50vh),0) translate(-50%,18px);
  opacity:0;transition:opacity .35s var(--ease);
}
.zoom__pill svg{width:15px;height:15px;flex:none}
.zoom.is-live.is-hover .zoom__pill{opacity:1}

/* Mientras el escenario está en pantalla, sus tres capas se prometen al
   compositor. Fuera de pantalla se sueltan: dejarlas promovidas todo el rato
   es memoria de GPU regalada. */
/* El marco NO se promete: `clip-path` no es una propiedad que el compositor
   sepa animar, así que el navegador repinta su capa entera en cada fotograma
   pase lo que pase. Prometerla no ahorra ni un repintado y sí reserva memoria
   de GPU. Lo que sí baja el coste de ese repintado es que la foto de dentro
   sea la de 1200 px y no la de 2000 (ver tools/gen_tipos_m.py). */
.zoom.is-near .zoom__side{will-change:transform,opacity}
.zoom.is-near .zoom__slide img{will-change:transform}

/* El `--track` baja mucho al estrechar. En escritorio 460svh se recorren con
   la rueda sin pensar; con el dedo son casi cinco gestos, y main.js reparte el
   recorrido por porcentaje (ABRE .22, MESETA .58), así que lo que se acorta es
   la meseta inmóvil, no la animación. Medido en un iPhone 15 Pro: la sección
   pasa de 3,9 pantallas a 2,3 y el efecto se ve entero igual. */
@media (width <= 64rem){
  .zoom{--cx:12%;--ct:10%;--cb:26%;--track:300svh}
  .zoom__side{width:clamp(5rem,20vw,9rem);top:42%}
  .zoom__side--l{left:calc(var(--gutter) * -.35)}
  .zoom__side--r{right:calc(var(--gutter) * -.35)}
}
/* El trío en reposo estaba descuadrado en vertical y solo en vertical. Medido
   con --p a 0: en 1440 la central es 3,7 veces la lateral y las laterales se
   ven ENTERAS; en un iPhone 15 Pro la central se comía el 84% del ancho, su
   borde caía DENTRO de las laterales y las tapaba a la mitad —de 80 px se
   veían 38—, así que la relación real era de 8,7 a 1. De ahí que la del medio
   pareciera enorme y las de los lados dos rendijas.
   Se recomponen las tres para que quepan de verdad: central al 54% del ancho,
   laterales al 17,8% (en escritorio son el 15%, o sea que aquí pesan algo más)
   y un hueco de unos 10 px entre cada par. Quedan en 3:1 y sin solaparse.
   La central también se centra en vertical (--ct y --cb iguales) porque al
   estrecharla la composición se quedaba escorada hacia arriba.
   NADA de esto sale de aquí: el escritorio y el portátil de 1024 conservan sus
   propios valores, que ya estaban bien. */
@media (width <= 48rem){
  /* 19 ago 2026 — el trío en reposo seguía descuadrado, pero al revés que la
     vez anterior: con --ct y --cb al 28% la central se quedaba en el 44% del
     alto del escenario y sobraban dos bandas de crema de más de 200 px arriba
     y abajo. En escritorio esa misma foto ocupa el 68%. Sube al 62% —el 60%
     de ancho por el 62% de alto— y el reposo vuelve a leerse como una
     composición y no como una foto perdida en mitad de la pantalla. El
     recorte de abajo se deja algo mayor que el de arriba porque el rótulo y
     el paginador viven ahí. */
  .zoom{--cx:22%;--ct:16%;--cb:22%;--track:230svh}
  /* Más verticales que en escritorio (allí van a 3/4): en una pantalla alta y
     estrecha una lateral apaisada se lee como un recorte, no como una foto.
     El alto es además lo único que queda por repartir —a lo ancho las tres ya
     llenan la pantalla de borde a borde—, así que la central crece hacia
     abajo hasta el 44% del escenario en vez de quedarse en un tercio con
     medio escenario de crema vacía alrededor.
     A 3/5 quedaban tan estrechas que parecían sellos pegados al borde; 3/4.4
     las deja verticales sin llegar a rendija. Reparto a 390 px: la central va
     del 22% al 78% (86-304 px), la lateral del 11 al 73, así que quedan 11 px
     de margen contra el borde de la pantalla y 13 px de hueco con la central.
     Ese margen es lo que las hace parecer fotos puestas ahí y no fotos que se
     salen: pegadas al borde se leían como recortadas. */
  .zoom__side{width:clamp(4rem,16vw,8rem);aspect-ratio:3/4.4;top:46%}
  .zoom__side--l{left:calc(var(--gutter) * .55)}
  .zoom__side--r{right:calc(var(--gutter) * .55)}
  .zoom__kind{font-size:var(--t-h3);max-width:14ch}
  /* El punto de interés se mueve al cambiar de recorte: en apaisado el toldo de
     la terraza queda fuera y en vertical se come la mitad de arriba. `--pos-m`
     es el foco solo para vertical; el de escritorio no se toca. Va en el HTML,
     junto a la foto, igual que `--pos`: es un dato de la imagen, no del CSS. */
  .zoom__slide img,.zoom__side img{object-position:var(--pos-m,var(--pos,50% 50%))}
}

/* Sin ratón no hay nada que seguir: la pastilla se planta abajo y se queda.
   Sigue siendo `fixed`: en `absolute` se anclaría a la sección entera —300svh
   de recorrido— y acabaría al final del track, fuera de la pantalla. */
/* Sin ratón la pastilla no tiene nada que seguir, y plantada sobre el rótulo
   quedaba un botón por ENCIMA del título que lo justifica —lo primero que se
   lee es la llamada y después de qué—. Además dice lo mismo que el `.zoom__n`
   que ya lleva el rótulo debajo, y la diapositiva entera es el enlace: en el
   dedo se puede pulsar en cualquier sitio. Se retira; el rótulo se queda solo,
   que es lo que se lee bien en vertical. */
@media (pointer:coarse),(hover:none){
  .zoom__pill{display:none}
}

/* ---- Sin JS o con movimiento reducido: las tres bandas de toda la vida ----
   Aquí «reducir» no es una versión lenta del zoom: un zoom ligado al scroll
   no tiene versión suave. Lo honesto es entregar el mismo contenido quieto,
   que es exactamente lo que era esta sección antes. */
.no-js .zoom__track,.zoom--flat .zoom__track{height:auto}
.no-js .zoom__stage,.zoom--flat .zoom__stage{position:static;height:auto;overflow:visible}
.no-js .zoom__side,.zoom--flat .zoom__side,
.no-js .zoom__hint,.zoom--flat .zoom__hint,
.no-js .zoom__pager,.zoom--flat .zoom__pager,
.no-js .zoom__pill,.zoom--flat .zoom__pill{display:none}
.no-js .zoom__core,.zoom--flat .zoom__core{
  position:static;clip-path:none;display:flex;flex-direction:column;gap:8px;
}
.no-js .zoom__slide,.zoom--flat .zoom__slide{
  position:relative;inset:auto;opacity:1;height:clamp(15rem,34vw,26.25rem);
}
.no-js .zoom__slide img,.zoom--flat .zoom__slide img{transform:none}
.no-js .zoom__slide::after,.zoom--flat .zoom__slide::after{opacity:1}
.no-js .zoom__cap,.zoom--flat .zoom__cap{opacity:1}

@media (hover:hover) and (pointer:fine){
  .zoom--flat .zoom__slide:hover .zoom__kind{
    text-decoration:underline;text-underline-offset:.24em;text-decoration-thickness:1px;
  }
}

/* ------------------------------------------------------ Flechas de paso -- */
/* Vienen del carril de fichas que hubo aquí; ahora las hereda el coverflow. */
.rail__btn{
  width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--rule);border-radius:var(--r);background:transparent;
  color:var(--fg);cursor:pointer;
  transition:background .3s var(--ease),color .3s var(--ease),border-color .3s var(--ease),opacity .3s var(--ease);
}
.rail__btn svg{width:17px;height:17px}
.rail__btn:disabled{opacity:.3;cursor:default}
@media (hover:hover) and (pointer:fine){
  .rail__btn:not(:disabled):hover{background:var(--ink);color:var(--paper);border-color:var(--ink)}
}

/* ====================================================== COVERFLOW DE CASAS ==
   Doce casas en fila girando en profundidad, la centrada de frente y su ficha
   debajo. La geometría —cuánto gira y cuánto se aleja cada una— la calcula
   js/coverflow.js fotograma a fotograma; aquí solo está el escenario.

   Lo que se cambió del componente de origen, que venía en lenguaje de app:
   las esquinas bajan de 16 px a los 2 px de la casa, la sombra deja de ser
   negra y solo la lleva la centrada, y las de los lados se apagan con un velo
   del color del papel en vez de con opacidad —bajar la opacidad sobre crema
   no aleja la foto, la agrisa, porque se ve el fondo a través de ella.
   ========================================================================== */
.cover{position:relative;margin-top:var(--sp-sm)}

/* Las de los extremos se comen el borde del contenedor y se cortan en seco,
   que es lo que delata que aquello está recortado. Dos degradados del color
   del papel por encima las dejan irse en vez de terminarse. Van aquí y no como
   `mask` sobre el marco a propósito: una máscara en un ancestro puede aplanar
   el preserve-3d de la escena, y entonces no hay carrusel que valga. */
.cover__marco::before,.cover__marco::after{
  content:"";position:absolute;top:0;bottom:0;width:11%;
  z-index:150;pointer-events:none;
}
.cover__marco::before{left:0;background:linear-gradient(to right,var(--bg),transparent)}
.cover__marco::after{right:0;background:linear-gradient(to left,var(--bg),transparent)}

.cover__marco{
  position:relative;
  /* De aquí sale todo lo demás: el paso, el fondo y la perspectiva se miden en
     anchos de tarjeta, así que el rastrillo escala solo. */
  --cover-carta:clamp(11.5rem,17vw,16.25rem);
  perspective:calc(var(--cover-carta) * 3);
  overflow:hidden;
  /* Aire arriba y abajo para que el recorte no corte la sombra de la centrada. */
  padding-block:var(--sp-xxs);
  cursor:grab;
  /* El gesto horizontal es nuestro; el vertical se lo queda la página. */
  touch-action:pan-y;
}
.cover__marco:active{cursor:grabbing}

.cover__escena{position:relative;height:calc(var(--cover-carta) * 1.25);transform-style:preserve-3d}

.cover__card{
  position:absolute;left:50%;top:0;
  width:var(--cover-carta);aspect-ratio:4/5;
  overflow:hidden;border-radius:var(--r);background:var(--line-soft);
  -webkit-user-select:none;user-select:none;
  transition:box-shadow .5s var(--ease);
}
/* Doce tarjetas prometidas al compositor son doce capas de GPU residentes todo
   el rato, y en un teléfono eso se paga aunque el carrusel esté a tres
   pantallas de distancia. Se prometen solo mientras ronda la pantalla, igual
   que hace el escenario de tipos; la clase la pone js/coverflow.js. */
.cover.is-near .cover__card{will-change:transform}
.cover__card img{display:block;width:100%;height:100%;object-fit:cover;pointer-events:none}
.cover__velo{position:absolute;inset:0;background:var(--bg);opacity:0;pointer-events:none}
/* Muy baja y tintada de tinta, no negra: la profundidad ya la da la
   perspectiva y la sombra solo tiene que despegar la casa que importa. */
.cover__card.is-centro{box-shadow:0 18px 44px -20px rgba(34,51,59,.5)}

/* ---------------------------------------------------- Ficha de la casa -- */
.cover__ficha{
  max-width:34rem;margin:var(--sp-xs) auto 0;text-align:center;
}
.cover__datos{justify-content:center;min-height:calc(2 * 1.6em)}
.cover__nombre{
  font-family:var(--font-voz);font-size:var(--t-h3);font-weight:400;
  line-height:1.35;letter-spacing:0;margin-top:.15rem;
}
.cover__resumen{
  font-size:var(--t-meta);color:var(--fg-soft);margin-top:.4rem;
  min-height:calc(2 * 1.6em);
}
.cover__pie{
  display:flex;justify-content:center;align-items:baseline;gap:1.4rem;
  max-width:24rem;margin:.9rem auto 0;padding-top:.75rem;
  border-top:1px solid var(--rule);
}
.cover__zona{
  font-size:var(--t-label);letter-spacing:var(--tr-label);
  text-transform:uppercase;color:var(--fg-soft);
}
.cover__cta{
  font-size:var(--t-meta);letter-spacing:.04em;color:var(--fg);white-space:nowrap;
  text-decoration:underline;text-underline-offset:.26em;text-decoration-thickness:1px;
  text-decoration-color:var(--rule);transition:text-decoration-color .3s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .cover__cta:hover{text-decoration-color:currentColor}
}
/* Al cambiar de casa el texto entra, no salta. La clase la pone y la quita el
   JS; el reflow forzado que hay allí es lo que deja reiniciar la animación. */
.cover__ficha.is-nueva{animation:coverEntra .45s var(--ease) both}
@keyframes coverEntra{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

.cover__nav{
  display:flex;justify-content:center;align-items:center;gap:1.1rem;
  margin-top:var(--sp-xs);
}
/* Doce puntos serían confeti; un contador dice lo mismo y ocupa una línea. */
.cover__cuenta{
  font-size:var(--t-label);letter-spacing:var(--tr-label);color:var(--fg-soft);
  font-variant-numeric:tabular-nums;
}

/* 19 ago 2026 — en móvil esto no se leía como un coverflow. La tarjeta al 62%
   del ancho, con el paso que salía del `hueco` de coverflow.js, dejaba a las
   vecinas casi fuera de pantalla: de cada una asomaban 16vw, o sea una cuarta
   parte de la foto, y lo que se veía era una foto grande con dos rendijas.
   En escritorio la misma tarjeta ocupa el 17% del ancho y se ven cinco casas.
   Al 52%, y con las vecinas solapadas (`hueco` negativo en coverflow.js), se
   ve media casa girada a cada lado. La perspectiva se aleja un poco —de 3 a
   3,6 anchos— porque el borde cercano de la vecina se estiraba tanto que se
   veía MÁS ALTA que la del centro. */
@media (width <= 48rem){
  .cover__marco{--cover-carta:52vw;perspective:calc(var(--cover-carta) * 3.6)}
  /* Más ancho el degradado: con la vecina asomando el doble, el corte contra
     el borde de la pantalla se nota justo el doble. */
  .cover__marco::before,.cover__marco::after{width:18%}
  .cover__ficha{padding-inline:var(--gutter)}
}

@media (prefers-reduced-motion:reduce){
  .cover__ficha.is-nueva{animation:none}
}

/* Sin JS no hay quien calcule el giro, así que las doce se ponen en fila y se
   recorren de lado. Siguen estando las doce fotos y los doce enlaces. */
.no-js .cover__marco{overflow-x:auto;cursor:auto;perspective:none}
.no-js .cover__escena{
  display:flex;gap:clamp(1rem,1.7vw,1.5rem);height:auto;transform-style:flat;
}
.no-js .cover__card{position:static;flex:0 0 auto}
.no-js .cover__velo,.no-js .cover__ficha,.no-js .cover__nav{display:none}
.no-js .cover__marco::before,.no-js .cover__marco::after{display:none}

/* -------------------------------------------------------- Ficha de casa -- */
/* Sin fondo, sin borde, sin sombra: foto y texto sobre el papel. Los datos van
   ARRIBA del título, como en la referencia: es lo que hace que se comparen. */
.home{display:flex;flex-direction:column;gap:.85rem;color:inherit}
.home__media{
  position:relative;overflow:hidden;border-radius:var(--r);
  aspect-ratio:4/3;background:var(--line-soft);
}
.home__media img{width:100%;height:100%;object-fit:cover;transition:transform .8s var(--ease)}
/* Dos líneas reservadas para los datos: unas casas traen tres y otras cinco, y
   sin esto los títulos de dos tarjetas vecinas arrancan a alturas distintas. */
.home .meta{min-height:calc(2 * 1.6em)}
.home__title{font-size:var(--t-card);font-weight:400;line-height:1.45;letter-spacing:0;text-wrap:pretty}
.home__place{font-size:var(--t-meta);color:var(--fg-soft)}
.home__foot{
  display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  margin-top:auto;padding-top:.75rem;border-top:1px solid var(--rule);
}
.home__zone{font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft)}
.home__price{font-size:var(--t-meta);letter-spacing:.04em;color:var(--fg);white-space:nowrap;font-variant-numeric:tabular-nums}
@media (hover:hover) and (pointer:fine){
  .home:hover .home__media img{transform:scale(1.045)}
  .home:hover .home__title{text-decoration:underline;text-underline-offset:.26em;text-decoration-thickness:1px}
}
/* Propiedad publicada de la que aún no hay datos: se enseña y se declara el
   estado. Un enlace que no lleva a ningún sitio es peor que un aviso. */
.home.is-soon{cursor:default}
.home.is-soon .home__media img{filter:grayscale(.4);opacity:.72}
.home.is-soon .home__title{color:var(--fg-soft)}
@media (hover:hover) and (pointer:fine){
  .home.is-soon:hover .home__media img{transform:none}
  .home.is-soon:hover .home__title{text-decoration:none}
}

/* Rejilla del listado: 3 columnas, mismo componente de ficha. */
.homes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-sm) clamp(1rem,1.7vw,1.5rem)}
@media (width <= 64rem){.homes{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (width <= 36rem){.homes{grid-template-columns:1fr}}

/* ============================================================= SERVICIOS ==
   Dos columnas: lista numerada a la izquierda, mosaico de tres fotos a la
   derecha. La numeración 01-05 es de la referencia y aquí sirve para ordenar
   lo que de verdad diferencia al negocio.
   ========================================================================== */
.svcs{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(2rem,4.5vw,4rem);align-items:center;
}
.svcs__txt{display:flex;flex-direction:column;gap:var(--sp-xs);max-width:34rem}
/* Rejilla, no flex: el número va arriba a la derecha y la explicación debajo a
   todo el ancho. En flex con `flex-basis:100%` el párrafo se encogía y se
   colaba en la misma línea que el rótulo. */
.svc-list{border-top:1px solid var(--rule)}
.svc-list li{
  display:grid;grid-template-columns:1fr auto;gap:.35rem 1rem;
  padding-block:1rem;border-bottom:1px solid var(--rule);
}
.svc-list b{grid-column:1;font-size:var(--t-meta);font-weight:400;letter-spacing:.1em;text-transform:uppercase}
.svc-list span{
  grid-column:2;grid-row:1;align-self:start;
  font-size:var(--t-micro);letter-spacing:.1em;color:var(--teal-700);
  font-variant-numeric:tabular-nums;
}
.svc-list p{grid-column:1 / -1;font-size:var(--t-meta);color:var(--fg-soft);line-height:1.7;max-width:52ch}
.svcs__grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  grid-template-rows:1fr 1fr;gap:clamp(.75rem,1.1vw,1rem);
  aspect-ratio:1/1;
}
.svcs__grid figure{margin:0;overflow:hidden;border-radius:var(--r);background:var(--line-soft)}
.svcs__grid figure:first-child{grid-row:span 2}
.svcs__grid img{width:100%;height:100%;object-fit:cover}
@media (width <= 64rem){
  .svcs{grid-template-columns:1fr}
  .svcs__grid{aspect-ratio:16/10}
}

/* ============================================================ NOSOTROS ==
   «Con quién estás trabajando». Partido tomado de una tarjeta editorial
   (emerald-ui, MIT) y pasado al sistema de aquí: retrato vertical, nombre
   grande en Fraunces que se monta sobre el borde de la foto, botón redondo
   con flecha y entrada escalonada con el `data-reveal` de siempre.
   Se usa en la portada (#nosotros) y en /nosotros/. Una sola tarjeta: Katya
   es la única cara de la empresa (21 sep 2026).
   Sin retrato todavía: `.team__ph` pinta las iniciales sobre crema.
   ========================================================================== */
.team{display:grid;gap:var(--sp-lg);max-width:60rem;margin-inline:auto}
.team__card{
  display:grid;align-items:center;
  grid-template-columns:clamp(14rem,26vw,22.5rem) minmax(0,1fr);
}
.team__role{grid-column:1/-1;margin-bottom:1rem}

.team__media{position:relative;aspect-ratio:4/5;overflow:hidden;background:var(--cream)}
/* Sombra al pie solo sobre foto: encima del crema del hueco ensucia. */
.team__media:has(img)::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(34,51,59,.2),transparent 45%);
}
.team__media img{width:100%;height:100%;object-fit:cover;transition:transform .6s var(--ease)}
.team__media:hover img{transform:scale(1.05)}
.team__ph{
  position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.9rem;
  font-family:var(--font-voz);font-size:clamp(3rem,6vw,5rem);font-weight:300;letter-spacing:.02em;color:var(--teal-700);
}
.team__ph small{font-family:var(--font);font-size:var(--t-label);font-weight:500;letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ink-soft)}

/* El bloque de texto se come 2rem de la foto: es lo que da el aire de revista. */
.team__info{position:relative;z-index:2;display:flex;flex-direction:column;gap:var(--sp-sm);margin-left:-2rem}
.team__name{font-family:var(--font-voz);font-size:clamp(2.2rem,4.6vw,4rem);font-weight:300;line-height:1.08;letter-spacing:-.02em}
.team__name b{display:block;font-weight:400}
.team__row{display:flex;align-items:flex-start;gap:var(--sp-xs)}
.team__bio{max-width:38ch;font-size:var(--t-meta);line-height:1.8;color:var(--fg-soft)}

.team__go{
  flex:none;display:grid;place-items:center;width:4.5rem;height:4.5rem;border-radius:50%;
  border:1px solid var(--rule);color:var(--fg);
  transition:background .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease),transform .3s var(--ease);
}
.team__go svg{width:20px;height:20px;transition:transform .3s var(--ease)}
.team__go:hover,.team__go:focus-visible{background:var(--teal);border-color:var(--teal);color:var(--on-photo);transform:scale(1.06)}
.team__go:hover svg,.team__go:focus-visible svg{transform:rotate(-45deg)}

/* Entrada: el texto llega de lado, hacia la foto. Va antes del bloque de
   Revelado, así que `.is-in` (misma especificidad, más abajo) lo deja en su sitio. */
.team__info[data-reveal]{transform:translateX(24px)}

.team__quote{
  margin-top:var(--sp-lg);text-align:center;
  font-family:var(--font-voz);font-size:var(--t-h2);font-weight:300;line-height:1.3;letter-spacing:-.01em;
}
.team__quote b{font-weight:400;color:var(--teal-700)}

.team__stats{display:flex;flex-wrap:wrap;gap:var(--sp-xxs) var(--sp-md)}
.team__stat{display:flex;flex-direction:column;gap:.35rem}
.team__stat b{font-family:var(--font-voz);font-size:clamp(2rem,3.4vw,3rem);font-weight:400;letter-spacing:-.02em;color:var(--teal-700)}
.team__stat span{font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft)}

@media (width <= 48rem){
  .team__card{grid-template-columns:minmax(0,1fr)}
  .team__media{max-width:22rem}
  .team__info{margin:1.5rem 0 0;align-items:flex-start;text-align:left}
  .team__info[data-reveal]{transform:translateY(12px)}
}
@media (prefers-reduced-motion:reduce){
  .team__info[data-reveal]{transform:none}
  .team__media:hover img{transform:none}
}

/* ----------------------------------------------------------- Panorámica -- */
.pano{position:relative;height:clamp(16rem,38vw,35rem);overflow:hidden}
.pano img{width:100%;height:100%;object-fit:cover;object-position:50% 58%}
/* El pie cae sobre roca clara: una sombra de texto no basta, hace falta velo. */
.pano::after{
  content:"";position:absolute;inset:auto 0 0 0;height:40%;pointer-events:none;
  background:linear-gradient(0deg,rgba(var(--veil),.72),rgba(var(--veil),.28) 46%,rgba(var(--veil),0));
}
.pano__cap{
  position:absolute;z-index:1;left:var(--gutter);bottom:clamp(1.1rem,2.2vw,1.75rem);
  color:var(--on-photo);font-size:var(--t-label);letter-spacing:var(--tr-label);
  text-transform:uppercase;
}

/* =================================================================== FAQ ==
   Ocupa el sitio del «Journal» de la maqueta: foto grande a la izquierda y
   lista a la derecha. Aquí no hay blog, y las preguntas frecuentes son
   contenido real que además alimenta el schema FAQPage.
   ========================================================================== */
/* La foto se estira a lo que mida la lista en vez de imponer su proporción: con
   `aspect-ratio:4/5` fijo sobraban 300 px de hueco a la derecha de las
   preguntas. El mínimo evita que se aplaste si algún día quedan dos preguntas. */
.faq{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(2rem,4.5vw,3.5rem);margin-top:var(--sp-sm);align-items:stretch;
}
.faq__media{
  position:relative;overflow:hidden;border-radius:var(--r);
  min-height:clamp(16rem,26vw,24rem);background:var(--line-soft);
}
.faq__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.faq__list{border-top:1px solid var(--rule)}
.faq details{border-bottom:1px solid var(--rule)}
.faq summary{
  display:flex;align-items:center;justify-content:space-between;gap:1.5rem;
  padding-block:1.15rem;cursor:pointer;list-style:none;
  font-size:var(--t-card);font-weight:400;line-height:1.4;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary svg{width:18px;height:18px;flex:none;color:var(--teal-700);transition:transform .4s var(--ease)}
.faq details[open] summary svg{transform:rotate(45deg)}
.faq__a{padding-bottom:1.15rem;max-width:64ch;color:var(--fg-soft);font-size:var(--t-meta);line-height:1.75}
@media (hover:hover) and (pointer:fine){.faq summary:hover{color:var(--teal-700)}}
@media (width <= 64rem){
  .faq{grid-template-columns:1fr}
  .faq__media{min-height:0;aspect-ratio:16/9}
  .faq__media img{position:static}
}

/* ------------------------------------------------------------- Contacto -- */
.close-cta{
  display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);
  gap:var(--sp-sm);align-items:end;
}
.close-cta h2{font-size:var(--t-h2);margin-top:.75rem}
.close-cta p{margin-top:var(--sp-xxs);color:var(--fg-soft);max-width:46ch}
.close-cta__a{display:flex;flex-wrap:wrap;gap:.75rem;justify-content:flex-end}
@media (width <= 64rem){
  .close-cta{grid-template-columns:1fr}
  .close-cta__a{justify-content:flex-start}
}

/* --------------------------------------------------------------- Footer -- */
.foot{padding-block:var(--sp-md) var(--sp-sm)}
/* Cinco columnas desde que la compraventa es un silo propio: marca, alquiler,
   venta, sitio y contacto. */
.foot__top{display:grid;grid-template-columns:1.3fr 1fr 1fr 1fr 1.1fr;gap:var(--sp-sm) var(--sp-xs)}
.foot__brand{display:flex;flex-direction:column;gap:.9rem;max-width:24rem}
/* El wordmark es tinta oscura con el isotipo en teal: sobre el campo teal del
   pie desaparece. Se pasa a plano en crema, que es la versión de marca para
   fondo oscuro. */
.foot__brand img{width:132px;filter:brightness(0) invert(1);opacity:.92}
.foot__brand p{font-size:var(--t-meta);line-height:1.75;color:var(--fg-soft)}
.foot__col{display:flex;flex-direction:column;gap:.7rem}
.foot h3{
  font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;
  font-weight:500;color:var(--fg-soft);margin-bottom:.3rem;
}
.foot a,.foot li{font-size:var(--t-meta);color:var(--fg-soft);font-weight:400}
.foot__contact li{display:flex;gap:.6rem;align-items:flex-start}
.foot__contact svg{width:14px;height:14px;flex:none;margin-top:.4rem;color:var(--teal)}
@media (hover:hover) and (pointer:fine){.foot a:hover{color:var(--on-deep)}}
.foot__bottom{
  display:flex;flex-wrap:wrap;gap:1rem;justify-content:space-between;align-items:center;
  margin-top:var(--sp-md);padding-top:var(--sp-xxs);border-top:1px solid var(--rule);
  font-size:var(--t-micro);letter-spacing:.1em;text-transform:uppercase;color:var(--fg-soft);
}
.foot__legal{display:flex;flex-wrap:wrap;gap:1rem}
.foot__legal a{font-size:var(--t-micro);letter-spacing:.1em;text-transform:uppercase}
@media (width <= 64rem){.foot__top{grid-template-columns:1fr 1fr}}
@media (width <= 36rem){.foot__top{grid-template-columns:1fr}}
/* Con el ratón, 21 px de alto y un `gap` de .7rem se aciertan sin pensar. Con
   el dedo son la mitad del mínimo de 44 pt, y el pie es donde están los enlaces
   legales y el teléfono. Se les da caja en vez de subirles el tipo: la escala
   del pie no cambia, solo el área que responde. El `gap` baja para compensar
   lo que crecen las filas. */
@media (width <= 64rem){
  .foot__col{gap:0}
  .foot__col a,.foot__contact a,.foot__legal a{
    display:inline-flex;align-items:center;min-height:44px;
  }
  .foot__contact li{align-items:center}
  .foot__contact svg{margin-top:0}
}

/* =========================================================== LISTADO ==== */
.page-head{padding-block:var(--sp-md) var(--sp-sm)}
.crumbs{font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft)}
.crumbs span{margin-inline:.5rem;opacity:.5}
.page-head h1{
  font-size:var(--t-h1);margin-top:.9rem;
  letter-spacing:-.015em;max-width:22ch;
}
.page-head h1 sup{font-size:.3em;font-weight:400;letter-spacing:.1em;vertical-align:super;color:var(--fg-soft);margin-left:.5em}
.page-head .lead{margin-top:var(--sp-xxs);max-width:60ch}

/* Rejilla y no flex: cada taxonomía en su fila. En una sola fila los dos grupos
   se juntaban y el rótulo «Zona» quedaba enterrado entre chips de tipo, que es
   justo lo que obliga a adivinar qué hace cada chip. */
.filters{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:.75rem 1.5rem;
  align-items:center;padding-block:var(--sp-xxs);border-block:1px solid var(--rule);
}
.filters__group{grid-column:1;display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}
.filters__label{
  font-size:var(--t-micro);letter-spacing:var(--tr-label);text-transform:uppercase;
  /* Mínimo, no fijo: «Tipo» y «Zona» caben en 3.5rem, pero «Municipio» del silo
     de venta se salía por encima del primer chip. Con min-width los listados de
     alquiler se pintan exactamente igual que antes. */
  color:var(--fg-soft);min-width:3.5rem;flex:none;
}
.chip{
  padding:.5rem 1rem;border:1px solid var(--rule);border-radius:var(--r);
  background:transparent;font-size:var(--t-label);letter-spacing:.08em;text-transform:uppercase;
  cursor:pointer;transition:background .3s var(--ease),border-color .3s var(--ease),color .3s var(--ease);
}
.chip[aria-pressed="true"]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
@media (hover:hover) and (pointer:fine){
  .chip:hover{background:var(--aqua);border-color:transparent}
  .chip[aria-pressed="true"]:hover{background:var(--teal-800)}
}
.filters__count{
  grid-column:2;grid-row:1;text-align:right;
  font-size:var(--t-label);letter-spacing:.08em;text-transform:uppercase;color:var(--fg-soft);
}
@media (width <= 48rem){
  .filters{grid-template-columns:1fr}
  .filters__count{grid-column:1;grid-row:auto;text-align:left}
  .filters__label{width:auto}
}
.filters__state{
  display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;
  font-size:var(--t-meta);color:var(--fg-soft);margin-top:var(--sp-xs);
}
.filters__state[hidden]{display:none}
.filters__clear{border:0;background:transparent;padding:0;font:inherit;color:var(--fg);text-decoration:underline;cursor:pointer}

.empty{padding:var(--sp-md) 0;border-top:1px solid var(--rule)}
.empty h3{font-size:var(--t-h3)}
.empty p{margin-top:.5rem;color:var(--fg-soft);max-width:48ch}
.empty .btn{margin-top:var(--sp-xs)}

/* ============================================================== FICHA ==== */
/* Mosaico de cinco fotos: una grande de 2x2 y cuatro a su derecha. El resto de
   la galería vive en el <dialog>, en lazy: no pesa hasta que alguien la abre. */
.gal{position:relative;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.5rem}
.gal figure{margin:0;overflow:hidden;border-radius:var(--r);background:var(--line-soft);aspect-ratio:4/3}
.gal img{width:100%;height:100%;object-fit:cover}
.gal__main{grid-column:span 2;grid-row:span 2;aspect-ratio:auto}
.gal__more{
  position:absolute;right:.9rem;bottom:.9rem;
  display:inline-flex;align-items:center;gap:.5rem;
  padding:11px 18px;border:0;border-radius:var(--r);cursor:pointer;
  background:var(--paper);color:var(--ink);font:inherit;
  font-size:var(--t-label);letter-spacing:var(--tr-btn);text-transform:uppercase;
  box-shadow:0 18px 40px -24px rgba(34,51,59,.45);
  transition:background .3s var(--ease),color .3s var(--ease);
}
.gal__more svg{width:16px;height:16px;flex:none}
@media (hover:hover) and (pointer:fine){.gal__more:hover{background:var(--ink);color:var(--paper)}}
@media (width <= 48rem){
  .gal{grid-template-columns:repeat(2,minmax(0,1fr))}
  .gal figure:nth-of-type(n+4){display:none}
}

.lightbox{
  width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;
  margin:0;padding:0;border:0;background:var(--paper);color:var(--ink);
}
.lightbox::backdrop{background:rgba(var(--veil),.82)}
.lightbox__bar{
  position:sticky;top:0;z-index:2;display:flex;align-items:center;
  justify-content:space-between;gap:1rem;height:62px;padding-inline:var(--gutter);
  background:var(--paper);border-bottom:1px solid var(--line);
}
.lightbox__bar p{font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft)}
.lightbox__close{
  display:grid;place-items:center;width:40px;height:40px;flex:none;
  border:1px solid var(--line);border-radius:var(--r);background:transparent;color:var(--ink);cursor:pointer;
}
.lightbox__close svg{width:17px;height:17px}
@media (hover:hover) and (pointer:fine){.lightbox__close:hover{background:var(--aqua)}}
.lightbox__body{height:calc(100dvh - 62px);overflow-y:auto;overscroll-behavior:contain}
.lightbox__grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;
  padding:var(--sp-xs) var(--gutter) var(--sp-md);
}
.lightbox__grid figure{margin:0;position:relative;overflow:hidden;border-radius:var(--r)}
.lightbox__grid img{width:100%;aspect-ratio:4/3;object-fit:cover}
/* Ninguna imagen lleva texto encima sin velo. */
.lightbox__grid figcaption{
  position:absolute;inset:auto 0 0 0;padding:.7rem .9rem;
  background:linear-gradient(0deg,rgba(var(--veil),.86),rgba(var(--veil),.35) 65%,transparent);
  color:var(--on-photo);font-size:var(--t-micro);letter-spacing:.04em;
}
@media (width <= 48rem){.lightbox__grid{grid-template-columns:1fr}}

.ficha__body{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,4fr);gap:var(--sp-sm) var(--sp-md);align-items:start}
.ficha__rail{position:sticky;top:calc(var(--header-h) + var(--sp-xxs))}
@media (width <= 64rem){
  /* minmax(0,1fr) y no 1fr: con el mínimo `auto`, la columna crece hasta el
     min-content de lo que lleva dentro y se sale del contenedor. */
  .ficha__body{grid-template-columns:minmax(0,1fr)}
  .ficha__rail{position:static}
}

/* min(Npx,100%) en vez de Npx a secas: así auto-fit puede bajar a una columna
   cuando no hay sitio, en vez de imponer dos y desbordar en móvil. */
.specs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(140px,100%),1fr));gap:0;margin-bottom:var(--sp-sm)}
.specs div{padding-block:1rem;border-top:1px solid var(--rule)}
.specs dt{font-size:var(--t-micro);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft)}
.specs dd{font-size:clamp(1.15rem,1.5vw,1.4rem);font-weight:400;margin-top:.4rem;letter-spacing:-.01em}

.prose h2,.prose h3{font-size:var(--t-h3);margin-top:var(--sp-sm)}
.prose h2:first-child{margin-top:0}
.prose p{max-width:66ch;margin-top:var(--sp-xxs)}

/* Texto corrido de las páginas legales: el reset quita viñetas y subrayados, y
   un aviso legal sin ellos se lee fatal. Solo aplica dentro de .prose. */
.prose ul{max-width:66ch;margin-top:var(--sp-xxs);padding-left:1.2em;list-style:disc}
.prose li{margin-top:.4rem}
.prose li::marker{color:var(--teal)}
.prose a{text-decoration:underline;text-underline-offset:.2em;color:var(--teal-700)}
/* Dato del cliente que aún no tenemos. Tiene que cantar: si algo así llega a
   producción es que se publicó sin revisar. */
.pte{background:#FFF3BF;color:#5C4600;padding:.05em .4em;border-radius:2px;font-size:.9em}

.amenities{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px,100%),1fr));gap:.25rem 1.5rem;margin-top:var(--sp-xs)}
.amenities li{display:flex;gap:.6rem;align-items:center;padding-block:.55rem;font-size:var(--t-meta);border-bottom:1px solid var(--line-soft)}
.amenities svg{width:14px;height:14px;color:var(--teal);flex:none}

.walk{margin-top:var(--sp-xs);border-top:1px solid var(--rule)}
.walk li{display:flex;justify-content:space-between;gap:1rem;padding-block:.85rem;border-bottom:1px solid var(--line-soft);font-size:var(--t-meta)}
.walk b{font-weight:400}
.walk span{color:var(--fg-soft);font-variant-numeric:tabular-nums}

.ficha__legal{margin-top:var(--sp-sm);padding-top:var(--sp-xxs);border-top:1px solid var(--rule);font-size:var(--t-meta);color:var(--fg-soft)}
.ficha__aviso{margin-top:var(--sp-xxs);padding:.7rem 1rem;border-left:3px solid var(--teal);background:var(--aqua);font-size:var(--t-meta)}

.book{padding:var(--sp-xs);border-radius:var(--r)}
.book__price{font-size:var(--t-h3);font-weight:500;letter-spacing:-.01em}
.book__unit{font-size:var(--t-body);color:var(--fg-soft)}
.book__note{font-size:var(--t-meta);color:var(--fg-soft);margin-top:.4rem}
.book form{margin-top:var(--sp-xs);display:grid;gap:.85rem}
.field label{display:block;font-size:var(--t-micro);letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--fg-soft);margin-bottom:.35rem}
.field input,.field select,.field textarea{
  width:100%;padding:12px 14px;background:var(--paper);color:var(--ink);
  border:0;border-bottom:1px solid var(--line);border-radius:var(--r);
}
.field textarea{min-height:92px;resize:vertical}
.field input::placeholder,.field textarea::placeholder{color:var(--ink-soft)}
.field--2{display:grid;grid-template-columns:1fr 1fr;gap:.85rem}
.book .btn{width:100%;margin-top:.4rem}
.book__alt{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-top:var(--sp-xxs);font-size:var(--t-meta);color:var(--fg-soft)}
.book__alt a{color:var(--fg);text-decoration:underline;text-underline-offset:.2em}

.form-msg{margin-top:.75rem;font-size:var(--t-meta);padding:.75rem 1rem;border-radius:var(--r);display:none}
.form-msg.is-on{display:block}
.form-msg--ok{background:var(--paper);color:var(--teal-800)}
.form-msg--err{background:var(--err-bg);color:var(--err-fg)}

/* Barra de reserva de móvil: a ≤64rem el rail deja de ser sticky y cae detrás
   de toda la prosa. Enlaza al #reservar del propio rail, así que funciona sin
   JS; el JS solo la esconde cuando el rail ya está a la vista. */
.bookbar{
  position:fixed;inset:auto 0 0 0;z-index:38;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  min-height:var(--bookbar-h);
  padding:.75rem var(--gutter);
  padding-bottom:max(.75rem,env(safe-area-inset-bottom));
  background:var(--paper);border-top:1px solid var(--line);
  box-shadow:0 -18px 40px -24px rgba(34,51,59,.4);
}
.bookbar__price{font-size:var(--t-meta);color:var(--ink-soft);white-space:nowrap}
.bookbar__price b{font-weight:400;color:var(--ink)}
.bookbar[hidden]{display:none}
@media (prefers-reduced-motion:no-preference){
  .bookbar{transition:transform .35s var(--ease)}
  .bookbar.is-off{transform:translateY(100%)}
}
@media (prefers-reduced-motion:reduce){.bookbar.is-off{display:none}}
@media (width > 64rem){.bookbar{display:none}}
@media (width <= 64rem){body:has(.bookbar) .foot{padding-bottom:calc(var(--sp-md) + var(--bookbar-h))}}

/* --------------------------------------------------------- Aviso demo ---- */
.demo-note{
  font-size:var(--t-micro);line-height:1.7;letter-spacing:.04em;color:var(--fg-soft);
  border:1px dashed var(--rule);padding:.75rem 1rem;border-radius:var(--r);
  display:block;max-width:62ch;
}
.demo-note b{font-weight:500;color:var(--fg);text-transform:uppercase;letter-spacing:.1em}

/* ------------------------------------------------------------ Revelado -- */
/* Fundido corto y un desplazamiento mínimo. La maqueta de referencia es
   estática; aquí solo se suaviza la entrada, no se coreografía nada. */
[data-reveal]{opacity:0;transform:translateY(12px)}
[data-reveal].is-in{
  opacity:1;transform:none;
  transition:opacity .8s var(--ease) var(--rd,0ms),transform .8s var(--ease) var(--rd,0ms);
}
/* Movimiento reducido no es lo mismo que nada de movimiento: se quita el
   desplazamiento y se conserva el fundido, que no marea a nadie. */
@media (prefers-reduced-motion:reduce){
  [data-reveal]{transform:none}
  [data-reveal].is-in{transition:opacity 350ms var(--ease)}
  *{scroll-behavior:auto !important}
}
/* Sin JS, todo visible. */
.no-js [data-reveal]{opacity:1;transform:none}

/* ========================================================== COMPRAVENTA ==
   Silo de venta. Reutiliza la rejilla `.homes`, los chips `.filters` y el
   contador del listado de alquiler: solo cambia la tarjeta, porque aquí lo que
   manda es el precio y no la disponibilidad.

   Las fotos del cliente aún no han llegado, así que el hueco de imagen está
   diseñado como marcador —silueta del tipo de propiedad sobre campo aqua— y no
   como una caja gris esperando una foto. Cuando entren las fotos se sustituye
   `.venta__media` por un <img> y el resto de la tarjeta no se toca.
   ========================================================================== */
.venta{
  display:flex;flex-direction:column;gap:.7rem;
  padding-bottom:var(--sp-xxs);border-bottom:1px solid var(--rule);
}
.venta__media{
  position:relative;display:grid;place-items:center;gap:.5rem;
  aspect-ratio:4/3;border-radius:var(--r);
  background:var(--aqua);color:var(--teal-700);
  border:1px dashed rgba(4,110,121,.28);
}
.venta__media svg{width:clamp(38px,4.5vw,54px);height:auto;opacity:.65}
.venta__ph{
  font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;
  color:var(--teal-700);opacity:.75;
}
/* Etiqueta de datos provisionales. Deliberadamente fea de ignorar: mientras esté,
   nadie debería tomar estos números por buenos. */
.venta__badge{
  position:absolute;top:.6rem;left:.6rem;
  font-size:var(--t-micro);letter-spacing:.1em;text-transform:uppercase;
  background:var(--err-bg);color:var(--err-fg);
  padding:.3rem .55rem;border-radius:var(--r);font-weight:500;
}
.venta__precio{
  font-family:var(--font-voz);font-size:var(--t-h3);font-weight:500;
  color:var(--fg);font-variant-numeric:tabular-nums;line-height:1;
}
.venta__title{font-family:var(--font-voz);font-size:var(--t-card);font-weight:400;line-height:1.3}
.venta__resumen{font-size:var(--t-meta);line-height:1.65;color:var(--fg-soft)}
.venta__foot{
  display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1rem;
  margin-top:auto;padding-top:.5rem;
}
.venta__zona{
  font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;
  color:var(--fg-soft);margin-right:auto;
}
.venta__foot .arrow{font-size:var(--t-micro)}
@media (hover:hover) and (pointer:fine){
  .venta:hover .venta__media{border-color:var(--teal);}
}

/* Al enlazar a la ficha, media y título son enlaces: heredan color y pierden el
   subrayado, como las tarjetas de alquiler. */
.venta__media,.venta__title a{color:inherit;text-decoration:none}
@media (hover:hover) and (pointer:fine){
  .venta__title a:hover{color:var(--teal-700)}
}

/* ------------------------------------------------------- Ficha de venta -- */
/* Dos columnas: el relato a la izquierda, los datos duros a la derecha en una
   columna pegajosa. Quien compra casa compara cifras, y las cifras tienen que
   seguirle mientras lee. */
.ficha-venta{
  display:grid;grid-template-columns:1.5fr 1fr;
  gap:var(--sp-sm) var(--sp-md);align-items:start;
  padding-bottom:var(--sp-lg);
}
.ficha-venta__precio{
  font-family:var(--font-voz);font-size:var(--t-h1);font-weight:500;
  color:var(--teal-800);font-variant-numeric:tabular-nums;
  margin-block:.4rem .6rem;line-height:1;
}
/* La galería de una propiedad en venta ocupa las dos columnas, igual que hacía el
   marcador al que sustituye. Sin esto cae en la columna de 1.5fr y el mosaico de
   5 fotos sale recortado por abajo. */
.ficha-venta > .gal{grid-column:1/-1}
.ficha-venta__media{
  grid-column:1/-1;
  display:grid;place-items:center;gap:.6rem;
  /* La proporción es la que tendrá la foto de portada cuando llegue. El tope de
     altura es para el estado actual: un marcador vacío de 580 px es un agujero
     en medio de la página. Al entrar las fotos, se quita el max-height. */
  aspect-ratio:16/7;max-height:300px;border-radius:var(--r);
  background:var(--aqua);color:var(--teal-700);
  border:1px dashed rgba(4,110,121,.28);
}
.ficha-venta__media svg{width:clamp(48px,5vw,68px);height:auto;opacity:.6}
.ficha-venta__txt p{margin-bottom:1rem;line-height:1.75;max-width:60ch}
.ficha-venta__txt p:last-child{margin-bottom:0}

.ficha-venta__datos{
  grid-row:span 2;position:sticky;top:calc(var(--header-h) + 2rem);
  background:var(--paper-2);border-radius:var(--r);padding:var(--sp-xxs);
}
.ficha-venta__datos h2,.ficha-venta__extras h2,.ficha-venta__cta h2{
  font-size:var(--t-label);letter-spacing:var(--tr-label);text-transform:uppercase;
  color:var(--fg-soft);font-weight:500;margin-bottom:.9rem;
}
.ficha-venta__datos dl{display:grid;gap:.55rem}
.ficha-venta__datos div{
  display:flex;justify-content:space-between;gap:1rem;
  padding-bottom:.55rem;border-bottom:1px solid var(--line-soft);
}
.ficha-venta__datos div:last-child{border-bottom:0;padding-bottom:0}
.ficha-venta__datos dt{font-size:var(--t-meta);color:var(--fg-soft)}
.ficha-venta__datos dd{
  font-size:var(--t-meta);font-weight:500;text-align:right;
  font-variant-numeric:tabular-nums;
}
.ficha-venta__extras ul{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem}
.ficha-venta__extras li{
  font-size:var(--t-meta);border:1px solid var(--rule);
  border-radius:9999px;padding:.35rem .85rem;color:var(--fg-soft);
}
.ficha-venta__cta{
  grid-column:1;border-top:1px solid var(--rule);padding-top:var(--sp-xs);
}
.ficha-venta__cta p{color:var(--fg-soft);line-height:1.7;max-width:52ch;margin-bottom:var(--sp-xs)}
.ficha-venta__acciones{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem 1.25rem}
@media (width <= 56rem){
  .ficha-venta{grid-template-columns:1fr}
  .ficha-venta__datos{grid-row:auto;position:static}
  .ficha-venta__cta{grid-column:1}
}

/* ------------------------------------------------------- Cómo trabajamos -- */
.venta-como{padding-block:var(--sp-lg) var(--sp-md)}
.venta-como h2{font-family:var(--font-voz);font-size:var(--t-h1);font-weight:400}
.venta-como .lead{margin-top:.75rem;max-width:56ch}
.pasos{
  list-style:none;margin-top:var(--sp-md);
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--sp-sm) var(--sp-xs);
}
.pasos li{display:grid;grid-template-columns:auto 1fr;gap:.4rem 1.1rem;align-items:start}
.pasos__n{
  grid-row:span 2;
  font-family:var(--font-voz);font-size:var(--t-h2);font-weight:300;
  color:var(--teal);line-height:1;font-variant-numeric:tabular-nums;
}
.pasos h3{font-size:var(--t-h3);font-weight:400;font-family:var(--font-voz)}
.pasos p{font-size:var(--t-meta);line-height:1.7;color:var(--fg-soft);max-width:46ch}
@media (width <= 48rem){.pasos{grid-template-columns:1fr}}

/* ------------------------------------------------------------ Vender -- */
.venta-vender{background:var(--bg);color:var(--fg);padding-block:var(--sp-lg)}
.venta-cta{
  display:grid;grid-template-columns:1.5fr 1fr;
  gap:var(--sp-sm) var(--sp-md);align-items:center;
}
.venta-cta h2{font-family:var(--font-voz);font-size:var(--t-h1);font-weight:400}
.venta-cta p{margin-top:.9rem;color:var(--fg-soft);line-height:1.7;max-width:52ch}
/* Ancho acotado: estirados a toda la columna, dos botones de dos palabras se
   convertían en barras de 550 px. */
.venta-cta__acciones{display:flex;flex-direction:column;gap:.75rem;max-width:20rem;margin-left:auto}
@media (width <= 56rem){
  .venta-cta{grid-template-columns:1fr}
  .venta-cta__acciones{flex-direction:row;flex-wrap:wrap}
}
