/* ===========================================================================
   Roel Tobias Portrait Studio — editorial cálido

   Tres voces y nada más. El logotipo del Brand Book firma la casa. La grotesca
   (Archivo) organiza: versales anchas, rótulos, números de sección, datos. La
   serif en cursiva fina (Newsreader) solo habla en las frases que importan, una
   por pantalla. Todo lo demás es papel, aire y foto.

   El papel es un blanco templado, no blanco de pantalla: un estudio de retrato
   de familia no se vende en una sala de operaciones. El oro aparece en el
   logotipo, en los filetes y sobre el carbón, nunca como texto en claro.
   =========================================================================== */

/* Archivo variable, subset latin: 35 KB para todos los pesos. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('../fonts/archivo-latin.woff2') format('woff2');
  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;
}

/* Un solo corte de la serif: cursiva de 300. Es voz de acento, no de cuerpo,
   así que 25 KB compran todas las frases del sitio. */
@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/newsreader-italic-latin.woff2') format('woff2');
  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;
}

/* Los dos colores de marca salen del Brand Book (RTPS-NewWebLogo): el oro del
   logotipo y el carbón de su fondo. Los grises son neutros derivados del
   carbón; no hay ningún color inventado fuera de esos dos.

   El oro NO se usa para texto sobre papel claro: da 2,1:1 de contraste, muy
   por debajo del 4,5:1 exigible. Sobre el carbón sube a 6:1 y ahí sí es texto.
   En claro queda para filetes, subrayados y estados de foco. */
:root {
  --oro: #cea647;
  --tinta: #2d2d2d;

  --papel: #f7f5f2;
  --papel-hondo: #edeae5;
  --tinta-70: #575757;
  --tinta-45: #6e6e6e;
  --linea: #dedbd5;
  --linea-fuerte: #bdb9b1;
  --verde: #1fa855; /* solo el icono de WhatsApp: es señal, no decoración */

  /* El contorno del foco es un token porque cambia de superficie. Escrito a
     pelo como `--tinta`, sobre el pie —que es carbón— daba 1:1 y desaparecía:
     quien navega con teclado perdía el rastro en los trece enlaces del pie. Las
     superficies oscuras lo redefinen más abajo. */
  --foco: var(--tinta);

  /* El único color que no sale del Brand Book, y sale de él igual: es el oro
     bajado a tierra. 6,9:1 sobre papel, así que es texto legal, no un aviso
     decorativo. Solo lo usan los errores del formulario, y nunca solo: siempre
     acompañado de un texto que dice qué pasó. */
  --alerta: #8f3a1e;

  --sans: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;

  --bordes: clamp(20px, 5vw, 80px);
  --aire: clamp(72px, 10vw, 152px);

  /* Las dos curvas de la casa. Ya estaban repetidas a mano por todo el archivo;
     nombrarlas aquí hace que el movimiento sea una decisión y no una
     coincidencia. Las de fábrica no sirven: `ease-out` de serie es tan suave
     que un gesto de 200 ms parece que duda, y `ease-in` arranca lento justo en
     el instante que el ojo está mirando, así que en esta hoja no aparece nunca.

     --salida: para lo que entra o sale. Arranca seco y frena largo.
     --cruce:  para lo que se mueve dentro de la pantalla sin irse (el aspa del
               menú, la cortina). Acelera y frena por igual, como una puerta. */
  --salida: cubic-bezier(0.22, 1, 0.36, 1);
  --cruce: cubic-bezier(0.76, 0, 0.24, 1);
}

*, *::before, *::after { box-sizing: border-box; }
/* El aire de arriba al saltar a un ancla. La cabecera es pegajosa y mide 84 px:
   sin esto, «How it works» o «Book» en la página de Navidad aterrizaban con el
   titular debajo de ella, cortado. Lenis lo lee también (resta el
   `scroll-padding-top` de la raíz), así que vale para el salto interpolado del
   escritorio y para el nativo del teléfono, y para los enlaces del pie que
   llevan a una tarjeta de Sesiones. */
html {
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
  scroll-padding-top: calc(84px + clamp(16px, 2.4vw, 32px));
}

body {
  margin: 0;
  background: var(--papel);
  color: var(--tinta);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

/* `hidden` gana siempre. La regla de fábrica del navegador es la más débil de
   todas y cualquier `display` de un componente la pisa: así los filtros de
   Sesiones marcaban las tarjetas como ocultas y `.sesion { display: flex }` las
   seguía enseñando todas. Elegir un tipo de sesión no hacía nada. */
[hidden] { display: none !important; }

/* Dos correcciones de táctil que solo tienen sentido juntas y solo ahora que
   todo lo pulsable se hunde al tocarlo:

   · El recuadro gris que iOS y Android pintan encima al tocar es el sustituto
     de fábrica de un estado de pulsación. Estorba cuando ya hay uno: se ven las
     dos cosas, la del sistema y la de la casa, y la de la casa pierde. Se quita
     porque hay algo mejor en su lugar, nunca para dejar el toque sin respuesta.

   · `manipulation` renuncia al doble toque para ampliar sobre botones y
     enlaces, que es lo que obliga al navegador a esperar ~300 ms por si llega
     un segundo toque. Sin esa espera el hundido sale bajo el dedo, no después. */
a, button {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
ul { margin: 0; padding: 0; list-style: none; }
p { margin: 0; text-wrap: pretty; }

h1, h2, h3 {
  margin: 0;
  font-weight: 600;
  line-height: 1.14;
  text-wrap: balance;
}

/* El énfasis dentro de un titular de grotesca se pasa a la cursiva de verdad:
   Archivo no tiene itálica y el navegador la falsifica inclinando la recta, que
   es justo el detalle que delata una plantilla. El 1.06em compensa la altura de
   x menor de la serif para que las dos voces se lean del mismo tamaño. */
h1 em, h2 em, h3 em, p em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: 1.06em;
  letter-spacing: 0;
}
.frase em { font-family: inherit; font-weight: inherit; font-size: inherit; }

:focus-visible { outline: 2px solid var(--foco); outline-offset: 3px; }

/* Las cuatro superficies de carbón del sitio. El foco se invierte sobre ellas
   —papel sobre carbón son 12,7:1— porque el contorno tiene que verse igual de
   bien en las dos mitades del sitio. Va sobre el contenedor y no sobre cada
   enlace: así lo hereda cualquier cosa pulsable que se añada después. */
.pie, .galeria, .panel, .sesion--destacada, .sesion--contrast,
.lounge, .sala { --foco: var(--papel); }

.saltar {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--tinta); color: var(--papel);
  padding: 12px 20px; font-size: 13px; font-weight: 600;
}
.saltar:focus { left: 12px; top: 12px; }

/* --- Piezas ---------------------------------------------------------------- */

/* La cursiva es la única voz que no grita: se usa en frase completa. */
.frase {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  letter-spacing: -0.005em;
  line-height: 1.1;
  text-wrap: balance;
}

.rotulo {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--tinta-45);
}

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 16px 30px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid var(--tinta);
  background: var(--tinta);
  color: var(--papel);
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease,
              transform 0.14s var(--salida);
}

/* El hundido al pulsar es la única respuesta que existe en un teléfono: allí no
   hay cursor que cambie ni fondo que se invierta, y sin esto tocar un botón no
   produce absolutamente nada hasta que la página siguiente carga. 0.97 no se ve
   —se siente—, que es exactamente lo que tiene que pasar. Va en el mismo sitio
   para todo lo que se pulsa, porque un botón que responde y otro que no delatan
   que los hizo gente distinta. */
.boton:active { transform: scale(0.97); }

.boton--linea { background: transparent; color: var(--tinta); border-color: var(--linea-fuerte); }

/* Los estados de hover se sirven solo a quien tiene cursor. Una pantalla táctil
   dispara `:hover` al tocar y lo deja pegado hasta que se toca otra cosa: el
   botón se queda invertido después de pulsarlo, como si estuviera roto. */
@media (hover: hover) and (pointer: fine) {
  .boton:hover { background: transparent; color: var(--tinta); }
  .boton--linea:hover { background: var(--tinta); color: var(--papel); border-color: var(--tinta); }
}

/* Enlace de texto: la línea crece desde la izquierda al pasar por encima. */
.enlace-sub {
  display: inline-block;
  position: relative;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 6px;
}
.enlace-sub::after {
  content: '';
  position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--linea-fuerte);
}
.enlace-sub::before {
  content: '';
  position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--oro);
  transform: scaleX(0); transform-origin: left;
  /* 200 ms y no 350: un subrayado que persigue al cursor tiene que llegar antes
     que el ojo, y a 350 ms se le ve venir. La curva fuerte hace el resto. */
  transition: transform 0.2s var(--salida);
  z-index: 1;
}
@media (hover: hover) and (pointer: fine) {
  .enlace-sub:hover::before { transform: scaleX(1); }
}

/* El verde solo vive aquí: es señal de canal, no color de marca. */
.wa-icono { color: var(--verde); flex: none; display: block; }

/* Marco de foto: el zoom es de medio punto y lento. Sugiere que la imagen
   está viva sin convertir la página en un carrusel. */
.marco { overflow: hidden; background: var(--papel-hondo); }
.marco img { width: 100%; transition: transform 0.9s var(--salida); }
/* El zoom es de cursor y de nadie más. En táctil se quedaba encendido después
   de tocar la foto y ya no se apagaba: la imagen quedaba ampliada sin que nadie
   lo hubiera pedido, que es el fallo que más se nota de todos. */
@media (hover: hover) and (pointer: fine) {
  a:hover .marco img, .marco:hover img { transform: scale(1.035); }
}

/* --- Cabecera -------------------------------------------------------------- */
.cabecera {
  position: sticky; top: 0; z-index: 120;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 20px var(--bordes);
  background: var(--papel);
  border-bottom: 1px solid transparent;
  /* Solo el filete se anima. Antes se animaba también el `padding`, que es
     cálculo de maquetación durante 300 ms de una cabecera pegajosa —y encima
     cambiaba su alto, que es lo único que no debe moverse mientras alguien
     lee—. El compactado ahora lo hace el logotipo con un `transform`, que no
     toca la maquetación y se lee igual de bien. */
  transition: border-color 0.3s ease;
}
.cabecera[data-fija='true'] { border-bottom-color: var(--linea); }

/* El logotipo del Brand Book, no una marca compuesta con tipografía: la
   didona del logo es la firma de la casa y ninguna fuente web la sustituye. */
.marca { display: flex; align-items: center; flex: none; }
.marca__logo {
  height: clamp(24px, 2.3vw, 31px); width: auto;
  /* Se encoge desde su borde izquierdo, que es donde está anclada la marca:
     escalando desde el centro, el logotipo se despegaría del margen. */
  transform-origin: left center;
  transition: transform 0.3s var(--salida);
}
.cabecera[data-fija='true'] .marca__logo { transform: scale(0.88); }
.marca__logo--menu { height: 24px; }

.navegacion { display: flex; align-items: center; gap: clamp(16px, 2.4vw, 34px); }
.navegacion__lista { display: flex; gap: clamp(16px, 2vw, 30px); }
.navegacion__lista a {
  position: relative;
  font-size: 12px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  padding-bottom: 4px;
  white-space: nowrap;
}
.navegacion__lista a::after {
  content: '';
  position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: var(--tinta);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.18s var(--salida);
}
/* La página en la que se está va marcada siempre, con cursor o sin él: es
   información, no un efecto. Por eso sale del bloque de hover — si compartieran
   regla, gatear el hover se habría llevado por delante el indicador. */
.navegacion__lista a[aria-current='page']::after { transform: scaleX(1); }
@media (hover: hover) and (pointer: fine) {
  .navegacion__lista a:hover::after { transform: scaleX(1); }
}

/* Selector de idioma: dos enlaces reales, no un interruptor de adorno.
   Cada uno lleva a la misma página en el otro idioma. */
.idioma {
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
  padding-left: clamp(0px, 1.4vw, 14px);
  border-left: 1px solid var(--linea);
}
.idioma a { color: var(--tinta-45); transition: color 0.2s ease; }
.idioma a[aria-current='true'] { color: var(--tinta); text-decoration: underline; text-underline-offset: 4px; }
.idioma span { color: var(--linea-fuerte); }
@media (hover: hover) and (pointer: fine) {
  .idioma a:hover { color: var(--tinta); }
}

.boton-wa {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 11px 18px;
  border: 1px solid var(--linea-fuerte);
  transition: border-color 0.25s ease, background-color 0.25s ease,
              transform 0.14s var(--salida);
}
.boton-wa:active { transform: scale(0.97); }
@media (hover: hover) and (pointer: fine) {
  .boton-wa:hover { border-color: var(--tinta); background: rgba(38, 32, 28, 0.04); }
}

/* Dos líneas que se cruzan. El giro sale del centro del botón, así que las
   líneas se juntan primero y giran después: ese medio tiempo es lo que hace
   que se lea como un gesto y no como un cambio de icono. */
.menu-boton {
  display: none;
  position: relative;
  width: 30px; height: 22px;
  background: none; border: 0; padding: 0; cursor: pointer; color: inherit;
  transition: transform 0.14s var(--salida);
}
/* Más hundido que un botón normal (0.9 y no 0.97) porque el blanco es de 30 px:
   a esa escala el 3 % no se ve. El hundido es proporcional al tamaño, no una
   constante. */
.menu-boton:active { transform: scale(0.9); }
.menu-boton__linea {
  position: absolute; left: 3px; right: 3px;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.45s var(--cruce);
}
.menu-boton__linea:nth-child(1) { top: 6px; }
.menu-boton__linea:nth-child(2) { top: 14px; }
.menu-boton[aria-expanded='true'] .menu-boton__linea:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.menu-boton[aria-expanded='true'] .menu-boton__linea:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

/* --- Hero: texto a la izquierda, retrato sangrando a la derecha ------------ */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  gap: clamp(32px, 5vw, 76px);
  align-items: center;
  padding: clamp(24px, 4vw, 56px) 0 var(--aire) var(--bordes);
}
.hero__texto { display: flex; flex-direction: column; gap: 26px; max-width: 33rem; }
.hero__titulo { display: flex; flex-direction: column; gap: 18px; }
.hero__kicker {
  font-size: clamp(10px, 1vw, 12px);
  font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--tinta-45);
}
.hero__frase { font-size: clamp(42px, 6.4vw, 88px); }
.hero__frase em { font-style: italic; }
.hero__entrada { color: var(--tinta-70); font-size: 17px; max-width: 40ch; }
.hero__acciones { display: flex; flex-wrap: wrap; gap: 12px; }

/* La montura de carbón. El retrato del hero está tirado sobre fondo claro de
   estudio y se colocaba directamente sobre el papel: dos blancos casi del mismo
   valor, así que la fotografía no tenía borde y se derramaba en la página justo
   en la pantalla que decide si alguien sigue bajando. Montada sobre carbón
   recupera su masa y los blancos por fin se leen como luz — que es exactamente
   por lo que la galería, la única superficie oscura del sitio, funciona.
   El carbón sale del Brand Book y ya vive en la galería y en el pie: no entra
   ningún color nuevo.

   Va como `border` y no como `padding` a propósito: `overflow: hidden` recorta
   en la caja de relleno, así que el zoom lento de la foto pintaría por encima
   de un relleno y se comería la montura. Sobre el borde no puede pintar.

   Abierta por la derecha: la lámina sigue sangrando fuera de la página, que es
   la composición que ya tenía. */
.hero__foto {
  overflow: hidden;
  border: clamp(12px, 1.5vw, 24px) solid var(--tinta);
  border-right: 0;
}

/* --- La vida del hero -------------------------------------------------------
   Va en CSS y no en GSAP a propósito: las librerías se piden después del
   `load`, así que una entrada hecha con ellas llegaría tarde —o no llegaría—
   justo en lo primero que se ve. Estas animaciones corren desde el primer
   fotograma que pinta el navegador.

   La foto NO se desvanece al entrar. Es el elemento del LCP y animar su
   opacidad retrasaría la medición; lo único que se le toca es el `transform`,
   que no cambia cuándo se considera pintada. */
.hero__zoom {
  height: 100%;
  animation: hero-respira 26s var(--salida) both;
}
@keyframes hero-respira {
  0%   { transform: scale(1.1); }
  12%  { transform: scale(1.005); }
  100% { transform: scale(1.06); }
}

/* El texto sí entra, escalonado, detrás de la foto. */
.hero__kicker,
.hero__frase,
.hero__entrada,
.hero__acciones,
.hero__pista {
  animation: hero-entra 1s var(--salida) both;
}
.hero__kicker   { animation-delay: 0.08s; }
.hero__frase    { animation-delay: 0.20s; }
.hero__entrada  { animation-delay: 0.42s; }
.hero__acciones { animation-delay: 0.56s; }
.hero__pista    { animation-delay: 0.90s; }
@keyframes hero-entra {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

/* Indicador de scroll: un punto que recorre un riel, en bucle. Es la única
   pieza de la página que se mueve sola sin que nadie haga nada, y está ahí
   para decir que abajo hay más. */
.hero__pista {
  display: flex; align-items: center; gap: 14px;
  margin-top: 10px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--tinta-45);
}
.hero__pista__riel {
  position: relative;
  width: 62px; height: 1px;
  background: var(--linea-fuerte);
  overflow: hidden;
}
.hero__pista__riel i {
  position: absolute; inset: 0 auto 0 0;
  width: 22px;
  background: var(--oro);
  animation: hero-riel 2.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
@keyframes hero-riel {
  0%   { transform: translateX(-100%); }
  60%  { transform: translateX(280%); }
  100% { transform: translateX(280%); }
}
/* La foto se sirve ya recortada a 4:5, que es la proporción del marco en
   escritorio: aquí `cover` no recorta nada y el encuadre lo decide el archivo,
   no el navegador. El object-position solo entra en juego en la banda de
   tableta, donde el marco pasa a 5:4 (ver más abajo). */
.hero__foto img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 30%; }

/* --- Credenciales: una tira de datos, separada por filetes ----------------- */
.datos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--tinta);
  border-bottom: 1px solid var(--linea);
  margin: 0 var(--bordes) var(--aire);
}
.datos__celda { padding: 26px clamp(16px, 2.4vw, 36px) 26px 0; }
.datos__celda + .datos__celda { border-left: 1px solid var(--linea); padding-left: clamp(16px, 2.4vw, 36px); }
.datos__cifra {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(28px, 2.8vw, 40px); line-height: 1.05;
}
.datos__pie { color: var(--tinta-70); font-size: 14px; margin-top: 8px; max-width: 26ch; }

/* --- Encabezado de sección: número, rótulo y filete ------------------------ */
.seccion { padding: 0 var(--bordes) var(--aire); }

.seccion__encabezado {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  align-items: end;
  gap: clamp(24px, 4vw, 64px);
  border-top: 1px solid var(--tinta);
  padding-top: 18px;
  margin-bottom: clamp(32px, 4vw, 60px);
}
.seccion__marca { display: flex; align-items: baseline; gap: 14px; margin-bottom: 20px; }
.seccion__numero { font-size: 11px; font-weight: 600; letter-spacing: 0.14em; color: var(--tinta); }
/* Peso 500 y no 600: al lado de la cursiva del hero, la grotesca en negrita
   grande se lee como anuncio. Aligerada, ordena sin levantar la voz. */
.seccion__titulo { font-size: clamp(30px, 3.6vw, 52px); font-weight: 500; letter-spacing: -0.03em; max-width: 20ch; }
.seccion__nota { color: var(--tinta-70); max-width: 44ch; font-size: 16px; }
.seccion__cola { display: flex; justify-content: flex-end; margin-top: clamp(26px, 3vw, 44px); }

/* --- Índice de sesiones de la portada -------------------------------------- */
.indice { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.4vw, 38px); }
/* La tarjeta entera es el enlace, así que la que se hunde es la tarjeta entera.
   0.985 y no 0.97: cuanto más grande la superficie, menos hay que moverla para
   que el gesto se lea; a tamaño de tarjeta, un 3 % ya parece un tropiezo. */
.indice__pieza {
  display: flex; flex-direction: column;
  transition: transform 0.16s var(--salida);
}
.indice__pieza:active { transform: scale(0.985); }
.indice__pieza img { aspect-ratio: 4 / 5; object-fit: cover; }
.indice__pie {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  border-top: 1px solid var(--linea); margin-top: 18px; padding-top: 14px;
}
.indice__titulo { font-size: 15px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; }
.indice__orden { font-size: 11px; font-weight: 600; color: var(--tinta-45); letter-spacing: 0.1em; }
.indice__texto { color: var(--tinta-70); font-size: 15px; margin-top: 10px; }
.indice__precio { font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; margin-top: 12px; }

/* --- Banda de foto a sangre: una pausa, sin texto encima ------------------- */
/* El margen va completo, no solo el de abajo: <figure> trae de fábrica
   `margin: 1em 40px` y ese margen lateral impedía que la banda fuese a sangre. */
.banda-foto { margin: 0 0 var(--aire); }
.banda-foto img { width: 100%; aspect-ratio: 21 / 9; object-fit: cover; object-position: 50% 32%; }
.banda-foto figcaption {
  padding: 12px var(--bordes) 0;
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tinta-45);
}

/* --- Panel a pantalla completa: la foto se queda, el contenido la tapa ------
   El parallax de verdad: la foto ocupa la pantalla entera y se queda quieta
   mientras la sección siguiente sube por encima y la cubre.

   Se hace con `position: sticky` y no con la receta clásica de `perspective`
   en el <body>: esa obliga a mover el scroll del documento al body, y un
   ancestro con perspective crea un bloque contenedor que rompe la cabecera
   sticky y el menú móvil `fixed`. Tampoco con `background-attachment: fixed`,
   que iOS ignora desde hace años. Con sticky el resultado es el mismo y
   funciona en todos los navegadores.

   La clave es que el panel mide más que la pantalla: esos 70vh de diferencia
   son el recorrido durante el cual la foto se queda clavada. */
.panel {
  position: relative;
  /* svh y no vh: en iOS la barra de direcciones se encoge al bajar y con `vh`
     el panel cambia de alto a mitad del recorrido, dando un salto. */
  height: 170vh;
  height: 170svh;
  margin-bottom: var(--aire);
}
.panel__fondo {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  display: grid;
  place-items: center;
}
/* El 30 % horizontal está medido sobre la foto que hay hoy, y lo decide el
   móvil: el panel es tan alto y tan estrecho que enseña apenas el 31 % del
   ancho de una foto 3:2. Centrado, esa franja arrancaba en el 34,6 % y dejaba
   al padre —cuya cara va del 23 % al 39 %— fuera por la izquierda; con el 30 %
   arranca en el 20,8 % y entran las dos caras, la suya y la del niño, que
   termina en el 50 %. En escritorio la franja visible es el 87 % del ancho, así
   que este número mueve la foto unos 25 px y no se nota.

   El 40 % vertical no llega a actuar en ningún ancho de uso real: a esas
   proporciones `cover` escala por altura y solo recorta a los lados. Se deja
   por si alguna vez el panel se mira en una ventana apaisada y baja. */
.panel__fondo img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 30% 40%;
}
/* El velo se calcula para el peor caso, no para el mejor: la frase va en blanco
   y estas fotos tienen zonas claras —una camisa, un fondo de papel— donde el
   texto desaparecería con un velo de cortesía. */
.panel__velo {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(18,16,14,0.62) 0%, rgba(18,16,14,0.48) 45%, rgba(18,16,14,0.66) 100%);
}
/* El ancho va en rem y no en ch: `ch` se resuelve contra el tamaño de fuente
   del propio elemento —16 px aquí—, así que 22ch dejaban una columna de 240 px
   y la frase caía a una palabra por línea. */
.panel__texto {
  position: relative;
  text-align: center;
  color: #fff;
  padding: 0 var(--bordes);
  width: 100%;
  max-width: 56rem;
}
.panel__texto .rotulo { color: rgba(255,255,255,0.72); margin-bottom: 26px; }
.panel__frase { font-size: clamp(32px, 5vw, 76px); color: #fff; }
.panel__firma {
  margin-top: 30px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
  color: rgba(255,255,255,0.78);
}

/* Lo que viene detrás de un panel tiene que ser opaco y estar por encima: es
   lo que produce el tapado. Sin esto, el contenido pasaría por debajo. */
.tras-panel {
  position: relative;
  z-index: 2;
  background: var(--papel);
}

/* --- Manifiesto: la frase de la casa sobre papel hondo --------------------- */
.manifiesto {
  background: var(--papel-hondo);
  padding: clamp(64px, 8vw, 120px) var(--bordes);
  margin-bottom: var(--aire);
  text-align: center;
}
.manifiesto blockquote {
  margin: 0 auto;
  max-width: 20ch;
  font-size: clamp(30px, 4.4vw, 64px);
}
.manifiesto__firma { margin-top: 30px; font-size: 11px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--tinta-70); }

/* --- Bloque de dos columnas con foto (eventos y estudio) ------------------- */
.duo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 4.5vw, 76px);
  align-items: center;
}
/* `.duo__foto` es la foto de la sección de eventos de la portada. Estuvo sin
   uso del 22 de agosto al 30 de septiembre de 2026, mientras no hubo una foto
   de evento de Roel; volvió con la del baby shower. */
.duo--invertido .duo__foto { order: 2; }
.duo__foto img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.duo__foto--ancha img { aspect-ratio: 3 / 2; }
.duo__texto { display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
.duo__titulo { font-size: clamp(28px, 3.4vw, 50px); max-width: 19ch; }
.duo__texto p { color: var(--tinta-70); max-width: 46ch; }
.duo__texto .ventajas { align-self: stretch; }

.ventajas { display: flex; flex-direction: column; }
.ventajas li {
  display: flex; gap: 16px; align-items: baseline;
  border-top: 1px solid var(--linea); padding: 15px 0; font-size: 15px;
}
.ventajas li:last-child { border-bottom: 1px solid var(--linea); }
.ventajas span { font-size: 11px; font-weight: 600; color: var(--tinta-45); letter-spacing: 0.1em; flex: none; }
/* Un elemento de la lista puede llevar a otra página (Contrast, en la portada):
   se subraya apagado para que se sepa que se pulsa sin gritarlo. */
.ventajas a {
  text-decoration: underline; text-decoration-color: var(--linea-fuerte);
  text-underline-offset: 4px; transition: text-decoration-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .ventajas a:hover { text-decoration-color: var(--oro); }
}
.duo__enlaces { display: flex; flex-wrap: wrap; gap: 12px 28px; }

/* --- La lámina de «Detrás de la cámara» y sus dos huecos --------------------
   El bloque de dos columnas normal no aguanta esta sección: la biografía pasó
   de un párrafo a cinco y, al lado de un 4:5, la columna de foto se quedaba a
   la mitad de alto que la de texto. En vez de recortar la biografía o estirar
   la foto, la lámina se queda clavada mientras el texto corre por debajo — que
   es además como se mira un retrato: quieto.

   La montura de carbón es la misma decisión que en el hero y por el mismo
   motivo: el retrato está tirado sobre fondo claro de estudio y, puesto
   directamente sobre el papel, no tiene borde y se derrama en la página.

   Va como `border` y no como `padding` porque `overflow: hidden` recorta en la
   caja de relleno: sobre un relleno el zoom lento de la foto pintaría encima de
   la montura, sobre el borde no puede. */
.duo--retrato {
  align-items: stretch;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
}
.duo--invertido .retrato__columna { order: 2; }
.retrato {
  position: sticky;
  /* La cabecera pegajosa mide 84 px (20 + 44 + 20): el retrato se detiene
     justo debajo, nunca detrás. */
  top: calc(84px + clamp(16px, 2vw, 28px));
  display: grid;
  grid-template-columns: minmax(0, 1.42fr) minmax(0, 1fr);
  grid-template-rows: 1fr 1fr;
  gap: clamp(10px, 1.1vw, 16px);
}
.retrato__principal {
  grid-row: 1 / span 2;
  border: clamp(10px, 1.1vw, 18px) solid var(--tinta);
}
.retrato__principal img {
  width: 100%; height: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
}
/* Las dos pequeñas no pueden decidir la altura de su fila: esa la pone el
   retrato grande, que ocupa las dos. Por eso la foto va en absoluto dentro de
   su celda y no aporta altura propia; si la aportara, la fila crecería con ella
   y la lámina dejaría de cuadrar con el retrato. */
.retrato__pieza { position: relative; overflow: hidden; background: var(--papel-hondo); min-height: 0; }
.retrato__pieza img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* --- Hueco de foto ----------------------------------------------------------
   Un marco declarado, no un espacio en blanco. Dice qué fotografía va ahí para
   que el cliente sepa exactamente qué mandar, y se lee como un hueco a
   propósito — nunca como una imagen que no cargó, que es lo que parecería un
   rectángulo vacío y mudo.

   El filete es de oro y el texto de carbón: el oro sobre el papel claro da
   2,1:1 y no puede escribirse con él, pero como filete no tiene que leerse. */
.hueco {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;
  padding: clamp(14px, 1.3vw, 20px);
  background: var(--papel-hondo);
  border: 1px solid var(--linea-fuerte);
}
.hueco::before {
  content: '';
  display: block;
  width: 34px; height: 2px;
  background: var(--oro);
  margin-bottom: auto;
}
.hueco p { font-size: 13px; line-height: 1.45; color: var(--tinta-70); }
/* Cada variante toma la proporción del marco que sustituye, para que la página
   no cambie de ritmo el día que llegue la fotografía. */
.hueco--sesion { aspect-ratio: 4 / 5; }
.hueco--ancho { aspect-ratio: 3 / 2; }

/* El retrato de Roel todavía no llegó y su celda es un hueco más, no una
   montura de carbón vacía: la montura existe para dar borde a una fotografía
   sobre papel claro, y sin nada dentro se leería como una imagen que falló. */
.retrato__principal.hueco { border: 1px solid var(--linea-fuerte); aspect-ratio: 4 / 5; }

/* --- Galería horizontal: la sala de proyección ------------------------------
   La única superficie de carbón de la portada, y la única tira que se recorre
   de lado.

   El recorrido lo lleva el navegador, no un script: el carril es un scroll
   horizontal nativo y se pasa con el dedo, con un gesto lateral de trackpad,
   arrastrando con el ratón o con las flechas del teclado. Antes el script
   clavaba la sección en pantalla y convertía el scroll vertical en avance
   horizontal; se retiró porque cobraba ocho fotos de peaje a quien solo
   quería seguir bajando. Ahora el scroll vertical hace lo que se espera de
   él: pasar a la sección siguiente. */
.galeria {
  background: var(--tinta);
  padding: clamp(48px, 7vw, 96px) 0;
  margin-bottom: var(--aire);
  overflow: hidden;
}
.galeria__encabezado {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 30px; flex-wrap: wrap;
  padding: 0 var(--bordes) clamp(28px, 3.5vw, 48px);
}
/* #a5a5a5 y no el #8f8f8f de antes: a 11 px con 0.22em de tracking, aquel daba
   4,26:1 sobre el carbón y se quedaba por debajo del 4,5 exigible. Este da
   5,59:1 y ya estaba en la paleta del pie, así que no entra un gris nuevo. */
.galeria__encabezado .rotulo { color: #a5a5a5; }
.galeria__encabezado .seccion__numero { color: var(--oro); }
.galeria__titulo { font-size: clamp(30px, 3.6vw, 52px); font-weight: 500; letter-spacing: -0.03em; color: var(--papel); max-width: 20ch; }
.galeria__nota { color: #b4b0aa; max-width: 40ch; font-size: 15px; }
.galeria__encabezado .enlace-sub { color: var(--papel); }
.galeria__encabezado .enlace-sub::after { background: #5a5a5a; }

/* El eje vertical va en `hidden` y no en `visible` a propósito: `visible` junto
   a un `overflow-x` se resuelve como `auto`, y bastaría un píxel de contenido
   asomando para que el carril se quedara con el scroll vertical del visitante
   —justo el gesto que tiene que llegar a la página—.

   `overscroll-behavior-x: contain` corta el encadenado solo en horizontal: al
   llegar al final del carril no se dispara el gesto de «atrás» del navegador.
   En vertical se deja encadenar, que es lo que permite pasar a la sección
   siguiente sin levantar el dedo. */
.galeria__carril {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.galeria__carril::-webkit-scrollbar { display: none; }
/* El anillo de foco se dibuja por dentro: el carril llega a los dos bordes de
   la pantalla y `.galeria` recorta, así que por fuera se perdería a los lados. */
.galeria__carril:focus-visible { outline-offset: -3px; }

/* Con ratón el carril también se arrastra. La clase la pone el script: si no
   corre no hay arrastre, y entonces el cursor no debe prometerlo. */
.galeria__carril--arrastrable { cursor: grab; }
.galeria__carril[data-arrastrando='true'] {
  cursor: grabbing;
  user-select: none;
  /* El imán tira hacia un lado mientras la mano tira hacia el otro. Se apaga
     durante el arrastre y vuelve al soltar, que es cuando sí se agradece. */
  scroll-snap-type: none;
}
.galeria__carril[data-arrastrando='true'] img { pointer-events: none; }

.galeria__pista {
  display: flex;
  gap: clamp(14px, 1.8vw, 30px);
  padding: 0 var(--bordes);
  width: max-content;
}
.galeria__pieza { margin: 0; flex: none; width: clamp(230px, 26vw, 400px); scroll-snap-align: center; }
.galeria__pieza--alta { width: clamp(200px, 21vw, 330px); }
.galeria__pieza img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.galeria__pieza--alta img { aspect-ratio: 4 / 5; }
.galeria__pieza figcaption {
  display: flex; justify-content: space-between; gap: 12px;
  border-top: 1px solid #4a4a4a; margin-top: 14px; padding-top: 11px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: #a5a5a5;
}
.galeria__pieza figcaption span:last-child { color: var(--oro); }

/* --- Rejilla de retratos verticales (portafolio de la portada) ------------- */
.rejilla-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(12px, 1.6vw, 26px); }
.rejilla-4 figure { margin: 0; }
.rejilla-4 img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.rejilla-4 figcaption {
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tinta-45); padding-top: 12px;
}

/* --- Cierre ---------------------------------------------------------------- */
.cierre {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: clamp(24px, 4vw, 60px); flex-wrap: wrap;
  border-top: 1px solid var(--tinta);
  padding: 26px var(--bordes) var(--aire);
}
.cierre__texto { flex: 1 1 30rem; max-width: 34ch; }
.cierre__texto h2 { font-size: clamp(30px, 4vw, 58px); }
.cierre__texto p { color: var(--tinta-70); margin-top: 14px; max-width: 42ch; }
.cierre__acciones { display: flex; gap: 12px; flex-wrap: wrap; }

/* --- Pie ------------------------------------------------------------------- */
.pie {
  background: var(--tinta);
  color: var(--papel);
  padding: clamp(52px, 6vw, 86px) var(--bordes) 34px;
  display: flex; flex-direction: column; gap: 52px;
}
.pie__rejilla { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 40px; }
/* Sobre el carbón el oro sí es texto: 6:1 de contraste. Aquí el logotipo va en
   su versión dorada, que es como se firma la marca. */
.pie__logo { height: 38px; width: auto; }
.pie address { font-style: normal; color: #a5a5a5; font-size: 15px; margin-top: 18px; line-height: 1.7; }
.pie address a { color: #a5a5a5; }
.pie__titulo {
  font-size: 10px; font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--oro); margin-bottom: 16px;
}
.pie__lista { display: flex; flex-direction: column; gap: 10px; font-size: 15px; }
.pie__lista a { color: #d6d4d0; }
/* Mismo cambio que el rótulo de la galería, y por lo mismo: 13 px de texto
   legal a 4,26:1 no cumplen. */
.pie__legal {
  border-top: 1px solid #444; padding-top: 22px; font-size: 13px; color: #a5a5a5;
  display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap;
}
.pie__legal a { color: #a5a5a5; }

/* El crédito de la casa. Va en la línea legal, que es su sitio: es un dato de
   quién hizo esto, no una oferta. Lo único que lo separa del texto de al lado
   es un subrayado apagado —el resto de enlaces de esta fila no lo llevan y no
   se distinguen del texto, que es un fallo que aquí no se repite. */
.pie__credito a {
  text-decoration: underline;
  text-decoration-color: #5a5a5a;
  text-underline-offset: 3px;
  transition: text-decoration-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .pie__credito a:hover { text-decoration-color: var(--oro); }
}

/* Los tres hovers del pie, juntos y solo para cursor. Son cambios de color sin
   movimiento, pero en táctil también se quedan encendidos: se toca un enlace,
   se vuelve atrás, y ese enlace sigue dorado como si estuviera seleccionado. */
@media (hover: hover) and (pointer: fine) {
  .pie address a:hover { color: var(--papel); }
  .pie__lista a:hover { color: var(--oro); }
  .pie__legal a:hover { color: var(--papel); }
}

/* --- Encabezado de página interior ----------------------------------------- */
.encabezado-pagina {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(24px, 5vw, 80px);
  align-items: end;
  padding: clamp(28px, 5vw, 76px) var(--bordes) clamp(30px, 4vw, 56px);
}
.encabezado-pagina .rotulo { margin-bottom: 18px; }
.encabezado-pagina h1 { font-size: clamp(38px, 5.6vw, 82px); }
.encabezado-pagina h1 em { font-style: italic; }
.encabezado-pagina p { color: var(--tinta-70); max-width: 46ch; }

/* --- Filtros: texto, no píldoras ------------------------------------------- */
.filtros {
  display: flex; gap: clamp(16px, 2vw, 28px); flex-wrap: wrap;
  padding: 0 var(--bordes) clamp(20px, 2.4vw, 32px);
  border-bottom: 1px solid var(--linea);
  margin-bottom: clamp(28px, 3.4vw, 46px);
}
.filtro {
  background: none; border: 0; padding: 0 0 5px; cursor: pointer;
  font-family: inherit; font-size: 11px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--tinta-45);
  border-bottom: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease,
              transform 0.14s var(--salida);
}
.filtro:active { transform: scale(0.95); }
.filtro[aria-pressed='true'] { color: var(--tinta); border-bottom-color: var(--oro); }
@media (hover: hover) and (pointer: fine) {
  .filtro:hover { color: var(--tinta); }
}

/* Lo que dice cada filtro del portafolio: cuánto cuesta esa sesión y dónde se
   reserva. Se pega al filete de los filtros para leerse como su respuesta. */
.filtros__destino {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 22px;
  padding: 0 var(--bordes);
  margin: calc(clamp(28px, 3.4vw, 46px) * -0.55) 0 clamp(28px, 3.4vw, 46px);
  color: var(--tinta-70); font-size: 15px;
}

/* --- Sesiones -------------------------------------------------------------- */
.rejilla-sesiones {
  display: grid; grid-template-columns: repeat(3, 1fr);
  /* `dense` para que la pieza de edición limitada rellene el hueco que deja la
     de Contrast, que ocupa dos columnas y no siempre cabe donde le toca. */
  grid-auto-flow: row dense;
  gap: clamp(30px, 3.4vw, 52px) clamp(16px, 2vw, 30px);
  padding: 0 var(--bordes) var(--aire);
}
.sesion { display: flex; flex-direction: column; }
.sesion img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.sesion__cuerpo { display: flex; flex-direction: column; gap: 12px; padding-top: 18px; flex: 1; }
.sesion__barra {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  border-top: 1px solid var(--linea); padding-top: 14px;
}
.sesion__titulo { font-size: 15px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; }
.sesion__orden { font-size: 11px; font-weight: 600; color: var(--tinta-45); letter-spacing: 0.1em; }
.sesion__texto { color: var(--tinta-70); font-size: 15px; flex: 1; }
.sesion__precio { font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tinta); }
.sesion .enlace-sub { align-self: flex-start; margin-top: 6px; }
.sesion__acciones { display: flex; flex-wrap: wrap; gap: 10px 26px; margin-top: 6px; }
.sesion__acciones .enlace-sub { margin-top: 0; }

/* La pieza de edición limitada es la única superficie oscura de la rejilla */
.sesion--destacada {
  background: var(--tinta); color: var(--papel);
  padding: clamp(26px, 2.6vw, 40px);
  justify-content: space-between; gap: 26px;
}
.sesion--destacada .rotulo { color: #a89c92; }
.sesion--destacada h2 { font-family: var(--serif); font-style: italic; font-weight: 300; font-size: clamp(28px, 2.4vw, 38px); margin-top: 14px; line-height: 1.1; }
.sesion--destacada p { color: #c4b8ae; font-size: 15px; margin-top: 14px; }
.sesion--destacada .boton { background: var(--papel); color: var(--tinta); border-color: var(--papel); align-self: flex-start; }
@media (hover: hover) and (pointer: fine) {
  .sesion--destacada .boton:hover { background: transparent; color: var(--papel); }
}

/* Contrast Studio Lounge: la única sesión que no pasa en el estudio sino
   dentro del evento del cliente, y la única con página propia. Va en carbón y
   a dos columnas, con foto, para que se lea como otra cosa y no como la décima
   tarjeta. Desde el 2026-09-30 las nueve sesiones cierran tres filas justas y
   la cuarta la reparten Contrast (dos columnas) y la edición limitada (una):
   por eso la limitada ya no se ensancha. */
.sesion--contrast {
  grid-column: span 2;
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  background: var(--tinta); color: var(--papel);
}
.sesion--contrast .marco { background: #3a3a3a; }
.sesion--contrast img { height: 100%; }
.sesion--contrast__texto {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
  gap: 16px; padding: clamp(24px, 3vw, 46px);
}
.sesion--contrast .rotulo { color: #a5a5a5; }
.sesion--contrast h2 {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(30px, 2.8vw, 44px); line-height: 1.05;
}
.sesion--contrast p { color: #c9c6c1; font-size: 15px; max-width: 40ch; }
/* El oro sí es texto aquí: sobre el carbón da 6:1. */
.sesion--contrast .sesion__precio { color: var(--oro); }
.sesion--contrast .boton { background: var(--papel); color: var(--tinta); border-color: var(--papel); }
@media (hover: hover) and (pointer: fine) {
  .sesion--contrast .boton:hover { background: transparent; color: var(--papel); }
}

/* --- Proceso --------------------------------------------------------------- */
.pasos { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(20px, 2.6vw, 40px); }
.paso { border-top: 1px solid var(--tinta); padding-top: 18px; }
.paso__numero {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: 30px; color: var(--tinta); line-height: 1;
}
.paso__titulo { font-size: 13px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; margin: 14px 0 10px; }
.paso p { color: var(--tinta-70); font-size: 15px; }

/* --- Precios ----------------------------------------------------------------
   Una tabla de verdad y no una rejilla de tarjetas: son diez filas de nombre y
   cifra, y quien llega preguntando cuánto cuesta lee de arriba abajo. Va bajo
   la nota de la sección, alineada con ella. La cifra en la cursiva de la casa,
   que es la voz de los datos (como las cifras de la portada). */
/* La tabla cae en la columna de la nota de arriba, con la misma rejilla que el
   encabezado de sección: así nombre y cifra quedan alineados con el texto que
   los explica y no flotan a media página. */
.precios__marco {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: clamp(24px, 4vw, 64px);
}
.precios { grid-column: 2; width: 100%; border-collapse: collapse; }
.precios th, .precios td { text-align: left; font-weight: 400; padding: 15px 0; border-top: 1px solid var(--linea); }
.precios thead th {
  font-size: 10px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--tinta-45); border-top-color: var(--tinta); padding: 14px 0;
}
.precios thead th:last-child, .precios td { text-align: right; }
.precios tbody th { font-size: 17px; padding-right: 20px; }
.precios td {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(22px, 2vw, 28px); line-height: 1.1; white-space: nowrap;
}
.precios tbody tr:last-child > * { border-bottom: 1px solid var(--linea); }
.precios a { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 4px; transition: text-decoration-color 0.2s ease; }
@media (hover: hover) and (pointer: fine) {
  .precios a:hover { text-decoration-color: var(--oro); }
}

/* --- Portafolio: mosaico por columnas --------------------------------------
   Va por columnas y no por filas: mezclar verticales 4:5 con apaisadas 3:2 en
   un grid deja huecos del alto de la pieza más grande. Con `columns` cada foto
   conserva su proporción y la pared queda cerrada. */
.mosaico {
  columns: 3;
  column-gap: clamp(12px, 1.6vw, 26px);
  padding: 0 var(--bordes) var(--aire);
}
.mosaico figure {
  margin: 0 0 clamp(20px, 2.4vw, 38px);
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}
.mosaico img { width: 100%; object-fit: cover; }
.mosaico:not(.mosaico--libre) img { aspect-ratio: 3 / 2; }
.mosaico figure.alto img { aspect-ratio: 4 / 5; }
.mosaico figcaption {
  display: flex; justify-content: space-between; gap: 12px;
  border-top: 1px solid var(--linea); margin-top: 12px; padding-top: 10px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tinta-45);
}

/* --- Contacto -------------------------------------------------------------- */
.contacto {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: clamp(36px, 5vw, 92px);
  padding: 0 var(--bordes) var(--aire);
}
.contacto__directo { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 38px; }

.separador { display: flex; align-items: center; gap: 18px; margin-bottom: 30px; }
.separador::before, .separador::after { content: ''; height: 1px; background: var(--linea); flex: 1; }
.separador span {
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--tinta-45);
}

.formulario { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.campo { display: flex; flex-direction: column; gap: 8px; }
.campo--ancho { grid-column: span 2; }
.campo label { font-size: 10px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--tinta-45); }
.campo input, .campo select, .campo textarea {
  font-family: inherit; font-size: 15px; color: var(--tinta);
  background: none; border: 0; border-bottom: 1px solid var(--linea-fuerte);
  padding: 10px 0; width: 100%; border-radius: 0;
}
.campo textarea { min-height: 92px; resize: vertical; }
.campo input::placeholder, .campo textarea::placeholder { color: var(--tinta-45); }
.campo input:focus, .campo select:focus, .campo textarea:focus {
  outline: 0; border-bottom-color: var(--oro); border-bottom-width: 2px; padding-bottom: 9px;
}
.formulario .boton { grid-column: 1 / -1; justify-self: start; margin-top: 10px; }

/* La línea que dice a dónde va lo que se escribe. Va pegada al botón, que es
   el momento en que la pregunta aparece, y no escondida en el pie. */
.formulario__nota { grid-column: 1 / -1; font-size: 13px; color: var(--tinta-45); }
.formulario__nota a { text-decoration: underline; text-underline-offset: 3px; }

/* --- Estados del formulario ------------------------------------------------
   El error no se dice solo con color: el filete se pone de alerta y además
   aparece una línea que nombra qué falta. Quien no distingue el rojo del gris
   lee lo mismo que los demás, y quien usa lector de pantalla lo oye porque el
   mensaje va enlazado con `aria-describedby`. */
.campo__error {
  font-size: 13px;
  color: var(--alerta);
  margin-top: 2px;
}
.campo__error[hidden] { display: none; }
.campo input[aria-invalid='true'],
.campo select[aria-invalid='true'],
.campo textarea[aria-invalid='true'] {
  border-bottom-color: var(--alerta);
  border-bottom-width: 2px;
  padding-bottom: 9px;
}

/* El aviso de después de enviar. Existe porque el envío abre WhatsApp en otra
   pestaña y hay un caso que antes no decía nada: si el navegador bloquea esa
   pestaña —en móvil pasa— la página se quedaba exactamente igual que antes de
   pulsar, sin error, sin confirmación y sin lead. Ahora ese caso tiene texto y
   un enlace que sí se puede tocar. */
.formulario__aviso {
  grid-column: 1 / -1;
  border-top: 1px solid var(--linea);
  padding-top: 16px;
  font-size: 15px;
  color: var(--tinta-70);
}
.formulario__aviso[hidden] { display: none; }
.formulario__aviso a { text-decoration: underline; text-underline-offset: 3px; }
.formulario__aviso--error { color: var(--alerta); border-top-color: var(--alerta); }

.contacto__panel { display: flex; flex-direction: column; gap: 30px; }
.contacto__panel img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.contacto__direccion {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(24px, 2.2vw, 32px); line-height: 1.2; margin-top: 12px;
}
.contacto__datos { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.dato { border-top: 1px solid var(--linea); padding-top: 14px; }
.dato__etiqueta { font-size: 10px; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; color: var(--tinta-45); margin-bottom: 6px; }
.dato__valor { font-size: 16px; font-weight: 500; }
@media (hover: hover) and (pointer: fine) {
  a.dato__valor:hover { color: var(--tinta-70); }
}
.mapa { width: 100%; height: 250px; border: 0; filter: grayscale(1) sepia(0.12) contrast(1.02); }

/* --- Campañas de temporada: la página de Navidad ---------------------------
   Una página de venta y no un catálogo: la primera pantalla dice qué es y dónde,
   la ficha dice cuánto y cuándo, y todo lo demás empuja hacia el formulario. El
   precio, la duración y las fechas no se escriben aquí: los pone Roel en la
   app y llegan por `campana.js`. Mientras no estén, la ficha dice «por
   anunciar», que es la verdad, y no un número verosímil. */
.temporada {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(28px, 5vw, 84px);
  align-items: end;
  padding: clamp(28px, 5vw, 76px) var(--bordes) clamp(30px, 4vw, 56px);
}
.temporada__texto { display: flex; flex-direction: column; gap: 22px; max-width: 36rem; }
.temporada__titulo { font-size: clamp(40px, 6vw, 88px); }
.temporada__titulo em { font-style: italic; }
.temporada__entrada { color: var(--tinta-70); font-size: 17px; max-width: 44ch; }
.temporada__acciones { display: flex; flex-wrap: wrap; gap: 12px; }
.hueco--temporada { aspect-ratio: 4 / 5; max-height: 72vh; }

.ficha-campana {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid var(--tinta);
  border-bottom: 1px solid var(--linea);
  margin: 0 var(--bordes) var(--aire);
}
.ficha-campana__celda { padding: 24px clamp(14px, 2vw, 30px) 24px 0; min-width: 0; }
.ficha-campana__celda + .ficha-campana__celda { border-left: 1px solid var(--linea); padding-left: clamp(14px, 2vw, 30px); }
.ficha-campana__valor {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(24px, 2.4vw, 34px); line-height: 1.12; margin-top: 10px;
  overflow-wrap: anywhere;
}
.ficha-campana__pie { color: var(--tinta-70); font-size: 13px; margin-top: 6px; }
/* Lo que todavía no se sabe se lee más bajo: es un aviso, no un dato. */
.ficha-campana__valor[data-pendiente] { color: var(--tinta-45); }

.incluye { color: var(--tinta-70); font-size: 17px; max-width: 58ch; white-space: pre-line; }

.pasos--tres { grid-template-columns: repeat(3, 1fr); }

.reservar { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(32px, 5vw, 92px); }
.reservar__lado { display: flex; flex-direction: column; gap: 18px; }
.reservar__lado h2 { font-size: clamp(32px, 3.8vw, 56px); }
.reservar__lado p { color: var(--tinta-70); max-width: 42ch; }
.reservar__pago { font-size: 13px; color: var(--tinta-45); }

/* El estado de la campaña —abierta, agotada, por abrir— va arriba del
   formulario y con palabras, no sólo con el botón gris. */
.reservar__estado {
  grid-column: 1 / -1;
  border-top: 1px solid var(--oro);
  padding-top: 14px;
  font-size: 15px;
  color: var(--tinta);
}
.reservar__estado:empty { display: none; }
.reservar__estado a { text-decoration: underline; text-underline-offset: 3px; }
.reservar__estado--error { border-top-color: var(--alerta); color: var(--alerta); }

.campo--casilla { grid-column: 1 / -1; flex-direction: row; align-items: flex-start; gap: 12px; }
.campo--casilla input { width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--tinta); flex: none; }
.campo--casilla label {
  font-size: 14px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--tinta-70);
}
.campo--casilla a { text-decoration: underline; text-underline-offset: 3px; color: var(--tinta); }

/* El campo trampa: fuera de la vista y del tabulador, pero en el formulario.
   Un robot que llena todo lo delata; una persona no lo ve nunca. */
.trampa { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.formulario .boton[disabled] { opacity: 0.45; cursor: not-allowed; transform: none; }
.formulario > .campo__error { grid-column: 1 / -1; margin-top: -14px; }

.preguntas { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(20px, 2.6vw, 40px); }
.pregunta { border-top: 1px solid var(--linea); padding-top: 18px; }
.pregunta h3 { font-size: 13px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; margin-bottom: 10px; }
.pregunta p { color: var(--tinta-70); font-size: 15px; }

/* La banda de la portada: la única superficie de carbón antes de la galería.
   Existe mientras dure la temporada y se quita entera cuando termine. */
.banda-temporada {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: clamp(24px, 4vw, 60px); flex-wrap: wrap;
  background: var(--tinta); color: var(--papel);
  margin: 0 var(--bordes) var(--aire);
  padding: clamp(28px, 4vw, 56px);
  --foco: var(--papel);
}
.banda-temporada .rotulo { color: #a89c92; }
.banda-temporada h2 { font-size: clamp(32px, 4vw, 58px); margin-top: 16px; max-width: 16ch; }
.banda-temporada p { color: #c4b8ae; margin-top: 14px; max-width: 44ch; }
.banda-temporada .boton { background: var(--papel); color: var(--tinta); border-color: var(--papel); }
@media (hover: hover) and (pointer: fine) {
  .banda-temporada .boton:hover { background: transparent; color: var(--papel); }
}

/* --- Contrast Studio Lounge ------------------------------------------------
   La única página del sitio que abre en carbón. Es una submarca y su idea es
   el contraste: un estudio de retrato montado dentro de un evento, y los
   retratos en blanco y negro. El papel vuelve en las secciones de lectura para
   que la página no sea un túnel oscuro, y el carbón regresa en la sala de fotos.

   La foto de la primera pantalla es el LCP: va precargada y nace visible. Lo
   que se anima en esta página empieza debajo del pliegue. */
.lounge {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: clamp(28px, 5vw, 84px);
  align-items: center;
  background: var(--tinta); color: var(--papel);
  padding: clamp(32px, 5vw, 80px) var(--bordes);
  margin-bottom: var(--aire);
}
.lounge__texto { display: flex; flex-direction: column; align-items: flex-start; gap: 26px; max-width: 38rem; }
.lounge__kicker {
  display: block; margin-bottom: 24px;
  font-family: var(--sans); font-style: normal;
  font-size: 11px; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
  color: #a5a5a5;
}
.lounge__titulo { font-size: clamp(46px, 6.6vw, 100px); font-weight: 500; letter-spacing: -0.035em; line-height: 0.98; }
/* La segunda voz del titular en oro: sobre el carbón es texto legal (6:1). */
.lounge__titulo em { color: var(--oro); display: block; }
.lounge__entrada { color: #c9c6c1; font-size: 17px; max-width: 46ch; }
.lounge__precio { font-family: var(--serif); font-style: italic; font-weight: 300; font-size: clamp(26px, 2.6vw, 36px); line-height: 1.05; }
.lounge__precio span {
  display: block; margin-bottom: 8px;
  font-family: var(--sans); font-style: normal;
  font-size: 11px; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; color: #a5a5a5;
}
.lounge__acciones { display: flex; flex-wrap: wrap; gap: 12px; }
.lounge .boton { background: var(--papel); color: var(--tinta); border-color: var(--papel); }
.lounge .boton--linea { background: transparent; color: var(--papel); border-color: #5a5a5a; }
@media (hover: hover) and (pointer: fine) {
  .lounge .boton:hover { background: transparent; color: var(--papel); }
  .lounge .boton--linea:hover { background: var(--papel); color: var(--tinta); border-color: var(--papel); }
}
.lounge__foto img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

/* La idea y el video, lado a lado. El video es vertical, como se grabó (9:16),
   y se mide por el alto de la pantalla menos la cabecera, el aire del salto y
   el pie: así cabe entero a la vista al llegar desde «Watch the video», sin
   desplazarse para ver el final de un clip de 52 segundos.

   El `height: auto` no es opcional. El <video> lleva `width` y `height` en el
   HTML para reservar su sitio, y sin él el navegador lo dibujaba con 1280 px de
   alto en una columna de 350: `cover` recortaba los costados y del rótulo del
   video solo se leía «RN YOUR EVE» (2026-10-01). */
.idea {
  display: grid;
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 92px);
  align-items: center;
}
.lounge-video {
  margin: 0;
  --ancho-video: min(100%, calc((100vh - 170px) * 9 / 16));
}
@supports (height: 100svh) {
  .lounge-video { --ancho-video: min(100%, calc((100svh - 170px) * 9 / 16)); }
}
.lounge-video video {
  display: block;
  width: var(--ancho-video);
  height: auto;
  aspect-ratio: 9 / 16;
  background: var(--tinta);
  object-fit: contain;
}
.lounge-video figcaption {
  width: var(--ancho-video); margin-top: 12px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tinta-45);
}
.idea__texto { display: flex; flex-direction: column; align-items: flex-start; gap: 22px; }
.idea__texto p { color: var(--tinta-70); max-width: 50ch; }
.idea__texto .duo__titulo { max-width: 16ch; }
.idea__texto .ventajas { align-self: stretch; max-width: 34rem; }

/* Para qué eventos: una lista numerada en tres columnas, con el mismo filete
   que las ventajas de la portada. */
.ocasiones {
  display: grid; grid-template-columns: repeat(3, 1fr);
  column-gap: clamp(20px, 3vw, 48px);
  border-bottom: 1px solid var(--linea);
}
.ocasiones li {
  display: flex; gap: 16px; align-items: baseline;
  border-top: 1px solid var(--linea); padding: 16px 0; font-size: 17px;
}
.ocasiones span { font-size: 11px; font-weight: 600; color: var(--tinta-45); letter-spacing: 0.1em; flex: none; }

/* La sala: la galería de Contrast, de vuelta en carbón. Cada foto en su
   proporción de origen, porque las tiras de fotomatón son la idea misma y
   recortadas a 4:5 dejarían de serlo. */
.sala {
  background: var(--tinta);
  padding: clamp(48px, 7vw, 96px) 0 clamp(20px, 3vw, 40px);
  margin-bottom: var(--aire);
}
.sala .mosaico { padding-bottom: 0; }
.sala .marco { background: #3a3a3a; }
/* Las columnas de la sala terminan parejas. Con fotos de cuatro proporciones
   que no se pueden partir, `columns` dejaba una columna una foto entera más
   corta: un rectángulo vacío al final de la galería, sobre todo en el
   teléfono. Ahora `interfaz.js` reparte las fotos en columnas explícitas según
   lo que dice cada <figure> (`data-col2`, `data-col3`: columna y posición),
   un reparto calculado para que sumen casi lo mismo, y la rejilla estira las
   filas de la columna más corta para alcanzar a la más alta. Lo que sobra son
   1 o 2 px por foto en el teléfono y unos 15 en escritorio, que `cover` absorbe
   sin que se note. Sin JS no hay clase y queda la galería por `columns`. */
.mosaico--libre.sala--repartida {
  columns: auto;
  display: flex;
  align-items: stretch;
  gap: clamp(12px, 1.6vw, 26px);
}
.sala__columna {
  flex: 1 1 0;
  min-width: 0;
  display: grid;
  align-content: stretch;
  row-gap: clamp(20px, 2.4vw, 38px);
}
.sala--repartida .sala__columna figure { margin: 0; display: grid; }
.sala__columna .marco { height: 100%; }
.sala__columna img { height: 100%; object-fit: cover; }

/* La sala no fuerza proporción: cada foto toma la suya de los `width` y
   `height` del HTML. Antes llevaba `aspect-ratio: auto`, que borra esa reserva
   de espacio: cada foto medía 0 px hasta cargar, las columnas se repartían con
   alturas que todavía no existían y al terminar de cargar quedaba un hueco
   vacío al final de una columna, que es lo que se veía en el teléfono. */

/* --- Blog ------------------------------------------------------------------
   Existe antes que su primer artículo, a pedido. Mientras esté vacío lo dice
   con palabras y manda a lo que sí hay, en vez de enseñar una rejilla vacía, y
   lleva `noindex` para que Google no guarde una página sin contenido. */
.blog-vacio {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(28px, 5vw, 84px);
  align-items: start;
  border-top: 1px solid var(--tinta);
  margin: 0 var(--bordes) var(--aire);
  padding-top: clamp(26px, 3.6vw, 48px);
}
.blog-vacio__aviso { display: flex; flex-direction: column; align-items: flex-start; gap: 20px; }
.blog-vacio__aviso h2 { font-size: clamp(32px, 4vw, 58px); max-width: 16ch; }
.blog-vacio__aviso p { color: var(--tinta-70); max-width: 46ch; }
.blog-vacio__acciones { display: flex; flex-wrap: wrap; gap: 12px 26px; margin-top: 6px; }
.autor {
  display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 20px; align-items: center;
  background: var(--papel-hondo); padding: 20px;
}
.autor img { width: 112px; aspect-ratio: 4 / 5; object-fit: cover; }
.autor .rotulo { margin-bottom: 8px; }
.autor__nombre { font-family: var(--serif); font-style: italic; font-weight: 300; font-size: 26px; line-height: 1.1; }
.autor p:last-child { color: var(--tinta-70); font-size: 14px; margin-top: 8px; }

/* --- 404 ------------------------------------------------------------------- */
.perdido {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 22px;
  padding: clamp(72px, 12vw, 180px) var(--bordes);
}
.perdido h1 { font-size: clamp(40px, 6vw, 88px); }
.perdido p { color: var(--tinta-70); max-width: 40ch; }
.perdido__acciones { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }

/* --- Páginas legales -------------------------------------------------------
   Términos y Aviso de privacidad. Son las dos únicas páginas del sitio que se
   leen de verdad —línea por línea, y a veces con un abogado al lado—, así que
   aquí manda la lectura y no la foto: una columna de 62 caracteres, un índice
   que se queda pegado al margen mientras se baja, y ni una animación de
   entrada. Un párrafo legal que aparece cuando entra en pantalla es un párrafo
   que alguien puede no llegar a ver, y eso en un contrato no se hace.

   El resumen en carbón de arriba no sustituye al texto: dice en cinco líneas
   lo que el cuerpo dice en cuarenta, para que nadie firme a ciegas. Por eso
   está marcado como <aside> y el propio recuadro avisa de que lo que obliga es
   lo de abajo. */
.legal {
  display: grid;
  grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 88px);
  align-items: start;
  padding: 0 var(--bordes) var(--aire);
}

/* El índice se queda a la vista todo el rato: son documentos de veinte
   apartados y la pregunta de quien los abre casi siempre es una sola. El
   `top` deja libre la altura de la cabecera fija. */
.legal__indice {
  position: sticky;
  top: 100px;
  border-top: 1px solid var(--tinta);
  padding-top: 16px;
  /* Diecinueve apartados no caben en una pantalla de laptop: sin este tope, el
     final del índice queda debajo del borde inferior y no hay forma de llegar a
     él, porque el bloque pegado no se desplaza con la página. */
  max-height: calc(100vh - 130px);
  overflow-y: auto;
  scrollbar-width: thin;
}
.legal__indice__titulo {
  font-size: 10px; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--tinta-45); margin-bottom: 16px;
}
.legal__indice ol { display: flex; flex-direction: column; gap: 11px; }
.legal__indice a {
  display: flex; gap: 10px; align-items: baseline;
  font-size: 14px; color: var(--tinta-70);
  transition: color 0.2s ease;
}
.legal__indice a span {
  font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
  color: var(--tinta-45); flex: none;
}
@media (hover: hover) and (pointer: fine) {
  .legal__indice a:hover { color: var(--tinta); }
}

.legal__cuerpo { max-width: 62ch; }

.legal__fecha {
  border-top: 1px solid var(--linea);
  padding-top: 14px; margin-bottom: clamp(30px, 4vw, 48px);
  font-size: 13px; color: var(--tinta-45);
}

.legal__resumen {
  background: var(--tinta); color: var(--papel);
  padding: clamp(26px, 3.4vw, 42px);
  margin-bottom: clamp(40px, 5vw, 68px);
}
.legal__resumen .rotulo { color: #a89c92; }
.legal__resumen h2 {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(24px, 2.2vw, 34px); line-height: 1.15; margin-top: 14px;
}
.legal__resumen ul { margin-top: 20px; display: flex; flex-direction: column; gap: 12px; }
.legal__resumen li { color: #c4b8ae; font-size: 15px; position: relative; padding-left: 22px; }
.legal__resumen li::before {
  content: ''; position: absolute; left: 0; top: 0.62em;
  width: 10px; height: 1px; background: var(--oro);
}
.legal__resumen p { color: #a89c92; font-size: 13px; margin-top: 22px; }

.legal__seccion { border-top: 1px solid var(--linea); padding-top: 20px; margin-bottom: clamp(34px, 4vw, 56px); }
.legal__seccion:last-of-type { margin-bottom: 0; }
.legal__marca { display: flex; align-items: baseline; gap: 14px; margin-bottom: 14px; }
.legal__numero { font-size: 11px; font-weight: 600; letter-spacing: 0.14em; color: var(--tinta); flex: none; }
.legal__seccion h2 { font-size: clamp(21px, 2.2vw, 28px); font-weight: 500; letter-spacing: -0.02em; }
.legal__seccion h3 {
  font-size: 12px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  margin-top: 28px;
}
.legal__seccion p { color: var(--tinta-70); margin-top: 14px; }
.legal__seccion strong { color: var(--tinta); font-weight: 600; }
.legal__seccion a {
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--linea-fuerte);
  transition: text-decoration-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .legal__seccion a:hover { text-decoration-color: var(--oro); }
}
.legal__seccion ul { margin-top: 14px; display: flex; flex-direction: column; gap: 11px; }
.legal__seccion li { color: var(--tinta-70); position: relative; padding-left: 22px; }
.legal__seccion li::before {
  content: ''; position: absolute; left: 0; top: 0.72em;
  width: 10px; height: 1px; background: var(--linea-fuerte);
}

/* La fila de contacto del final: quien llegó hasta abajo con una duda tiene
   aquí a quién preguntarle, sin volver a subir. */
.legal__contacto {
  border-top: 1px solid var(--tinta);
  margin-top: clamp(40px, 5vw, 64px); padding-top: 24px;
  display: flex; flex-wrap: wrap; gap: 16px 40px; align-items: baseline;
}
.legal__contacto p { color: var(--tinta-70); max-width: 40ch; }

/* --- Menú móvil ------------------------------------------------------------
   Se abre como una cortina: el papel baja cubriendo la pantalla y los enlaces
   entran detrás, uno detrás de otro.

   No se oculta con `display: none` —que no es animable y hacía que el menú
   apareciera de golpe— sino con `visibility` y un `clip-path` recogido. La
   visibilidad cambia sin transición al abrir y con el retardo entero al cerrar,
   así el panel sigue en pantalla mientras se recoge. Y `visibility: hidden`, a
   diferencia de `opacity: 0`, saca los enlaces del orden de tabulación: con el
   menú cerrado no se puede caer dentro con el teclado. */
.menu-movil {
  position: fixed; inset: 0; z-index: 100;
  background: var(--papel); color: var(--tinta);
  padding: clamp(88px, 15vh, 120px) var(--bordes) 40px;
  display: flex; flex-direction: column; gap: 36px; overflow-y: auto;

  visibility: hidden;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.66s var(--cruce), visibility 0s linear 0.66s;
}
.menu-movil[data-abierto='true'] {
  visibility: visible;
  clip-path: inset(0 0 0 0);
  transition: clip-path 0.66s var(--cruce), visibility 0s;
}


.menu-movil__lista { display: flex; flex-direction: column; }
.menu-movil__lista a {
  position: relative;
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(32px, 9vw, 46px);
  border-top: 1px solid var(--linea); padding: 16px 0;
}
.menu-movil__lista a:last-child { border-bottom: 1px solid var(--linea); }
/* Aquí el hundido no vale: escalar un texto de 46 px que además va recortado
   por su propio filete mueve el recorte y se ve el corte. Se atenúa, que es el
   equivalente para una fila de texto grande. */
.menu-movil__lista a { transition: opacity 0.14s var(--salida); }
.menu-movil__lista a:active { opacity: 0.5; }
.menu-movil__pie { margin-top: auto; display: flex; flex-direction: column; gap: 18px; }
.menu-movil__redes { display: flex; gap: 22px; font-size: 14px; color: var(--tinta-70); }
.menu-movil .idioma { border-left: 0; padding-left: 0; font-size: 12px; }

/* El contenido entra detrás de la cortina, no con ella: por eso los retardos
   arrancan pasada la mitad del recorrido del clip-path. */
.menu-movil__pie > * {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.45s ease, transform 0.55s var(--salida);
}
.menu-movil[data-abierto='true'] .menu-movil__pie > * {
  opacity: 1;
  transform: none;
}

/* Los enlaces no se desvanecen: suben desde detrás de su propio filete, como
   un cartel que se levanta. El recorte lo hace el <a> y el que se mueve es el
   <span> que el JS mete dentro. Si el JS no corre no hay span, no hay recorte
   y el enlace se ve tal cual: el menú sigue funcionando. */
.menu-movil__lista a { display: block; overflow: hidden; }
.menu-movil__lista a .linea {
  display: block;
  transform: translateY(115%);
  transition: transform 0.72s var(--salida);
}
.menu-movil[data-abierto='true'] .menu-movil__lista a .linea { transform: none; }

/* Este selector venía repetido —`.menu-movil … .menu-movil …`— y pedía una
   cortina dentro de otra cortina, que no existe: nunca aplicaba. El primer
   enlace subía sin esperar, y hasta el segundo pasaban 340 ms. El escalonado
   estaba escrito en cuatro tiempos y se veía en tres. */
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(1) .linea { transition-delay: 0.26s; }
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(2) .linea { transition-delay: 0.34s; }
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(3) .linea { transition-delay: 0.42s; }
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(4) .linea { transition-delay: 0.50s; }
/* El quinto (Navidad) entró sin retardo y subía antes que el primero; con
   Contrast ya son seis. Se escalonan igual, a 80 ms. */
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(5) .linea { transition-delay: 0.58s; }
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(6) .linea { transition-delay: 0.66s; }
.menu-movil[data-abierto='true'] .menu-movil__lista a:nth-child(7) .linea { transition-delay: 0.74s; }
.menu-movil[data-abierto='true'] .menu-movil__pie > *:nth-child(1) { transition-delay: 0.56s; }
.menu-movil[data-abierto='true'] .menu-movil__pie > *:nth-child(2) { transition-delay: 0.61s; }
.menu-movil[data-abierto='true'] .menu-movil__pie > *:nth-child(3) { transition-delay: 0.66s; }
.menu-movil[data-abierto='true'] .menu-movil__pie > *:nth-child(4) { transition-delay: 0.71s; }

/* Al cerrar no hay escalonado: el contenido se va de una vez y la cortina se
   recoge. Escalonar también la salida hace que el menú tarde en irse. */
.menu-movil:not([data-abierto='true']) .menu-movil__lista a,
.menu-movil:not([data-abierto='true']) .menu-movil__pie > * {
  transition-delay: 0s;
  transition-duration: 0.2s;
}

/* Cajas de una palabra, para que el titular pueda levantarse por partes. Las
   crea el script justo antes de animarlas: sin él, el titular es texto normal.
   El `vertical-align` evita que el recorte se coma las colas de la g y la j. */
.pal { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 0.06em; }
.pal > span { display: inline-block; }

/* --- Scroll interpolado (Lenis) ---------------------------------------------
   Las clases las pone la propia librería en <html> cuando arranca. Sin este
   bloque el scroll suave del navegador y el de Lenis se pelean, y los enlaces
   con almohadilla aterrizan en el sitio equivocado.

   Lo del iframe importa aquí: la página de contacto lleva el mapa incrustado,
   y mientras se desplaza tiene que dejar pasar la rueda en vez de tragársela. */
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-scrolling iframe { pointer-events: none; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }

/* --- Aparición al entrar en pantalla ---------------------------------------
   La clase la pone el JS: sin JS todo nace visible y nada depende del script. */
.anim [data-revelar] { opacity: 0; transform: translateY(18px); }
.anim [data-revelar].visible {
  opacity: 1; transform: none;
  transition: opacity 0.8s ease, transform 0.8s var(--salida);
}

/* --- Adaptación ------------------------------------------------------------ */

/* El menú de escritorio tiene seis enlaces desde que entró «Contrast Studio
   Lounge» (2026-09-30) y a espaciado completo pide 1330 px: por debajo, el
   nombre se partía en dos renglones y el logotipo se aplastaba hasta 35 px.
   Tres tramos medidos en el navegador, en inglés y en español:
   · 1400 px o más: como estaba.
   · 1101 a 1399: menos aire entre enlaces y WhatsApp solo con su icono (el
     verde y el `aria-label` lo siguen diciendo). Así cabe desde ~1060 px.
   · 1100 o menos: la hamburguesa, que antes entraba en 900. */
@media (max-width: 1399px) {
  .navegacion, .navegacion__lista { gap: 18px; }
  .navegacion__lista a { letter-spacing: 0.1em; }
  .boton-wa span { display: none; }
  .boton-wa { padding: 11px 12px; }
}

@media (max-width: 1100px) {
  .navegacion__lista { display: none; }
  .cabecera .idioma { border-left: 0; padding-left: 0; }
  .menu-boton { display: block; }
  .navegacion { gap: 14px; }
  .boton-wa span { display: inline; }
  .boton-wa { padding: 11px 18px; }
}

@media (max-width: 1100px) {
  .hero {
    grid-template-columns: 1fr;
    padding: 0 0 var(--aire);
    gap: 0;
  }
  /* En vertical la lámina ya no sangra por ningún lado: la montura se cierra
     por los cuatro costados y el retrato queda montado como una copia, no
     pegado al borde de la pantalla. */
  .hero__foto { order: -1; border-right-width: clamp(12px, 1.5vw, 24px); }
  /* Es la única banda donde el marco es más ancho que la foto y hay que
     recortar de verdad: de los 1175 px que se sirven solo se ven 752. El 25 %
     está medido sobre la foto que hay hoy —los cuatro de la familia caben
     entre el pelo del padre y la barbilla del bebé, y no sobra casi nada—.
     **Si cambia la foto del hero, este número se vuelve a medir**: con la
     anterior era el 52 %, y aplicado a esta decapitaría a los padres. */
  .hero__foto img { aspect-ratio: 5 / 4; object-position: 50% 25%; }
  .hero__texto { max-width: none; padding: clamp(28px, 5vw, 48px) var(--bordes) 0; }
  .duo, .contacto, .encabezado-pagina, .seccion__encabezado,
  .lounge, .idea, .blog-vacio { grid-template-columns: 1fr; }
  /* En vertical la foto de Contrast va primero, como la del hero de portada. */
  .lounge__foto { order: -1; }
  .precios__marco { grid-template-columns: 1fr; }
  .precios { grid-column: 1; }
  .lounge__foto img { aspect-ratio: 5 / 4; object-position: 50% 22%; }
  .ocasiones { grid-template-columns: repeat(2, 1fr); }
  /* El índice deja de ser columna y pasa a ser lo primero que se lee: en
     vertical, pegarlo arriba taparía el texto que quiere leerse. */
  .legal { grid-template-columns: 1fr; }
  .legal__indice { position: static; }
  .duo--invertido .duo__foto { order: 0; }
  .duo__foto img, .duo__foto--ancha img { aspect-ratio: 3 / 2; }

  /* Con una sola columna la lámina deja de estar clavada: clavada sin nada al
     lado no sujeta ningún texto, solo ocupa pantalla. Los dos huecos pasan
     debajo del retrato, en pareja. */
  .duo--invertido .retrato__columna { order: 0; }
  .retrato {
    position: static;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
  }
  .retrato__principal { grid-column: 1 / span 2; grid-row: auto; }
  .retrato__principal img, .retrato__principal.hueco { aspect-ratio: 3 / 2; }
  .retrato__pieza { aspect-ratio: 1 / 1; }
  .hueco { min-height: 200px; }
  .encabezado-pagina, .seccion__encabezado { align-items: start; }
  .rejilla-4, .rejilla-sesiones, .indice { grid-template-columns: repeat(2, 1fr); }
  .mosaico { columns: 2; }
  .pasos { grid-template-columns: repeat(2, 1fr); }
  .pie__rejilla { grid-template-columns: 1fr 1fr; }
  .banda-foto img { aspect-ratio: 16 / 9; }
}

@media (max-width: 900px) {
  .temporada, .reservar { grid-template-columns: 1fr; }
  .hueco--temporada { aspect-ratio: 3 / 2; max-height: none; }
  .ficha-campana { grid-template-columns: 1fr 1fr; }
  .ficha-campana__celda:nth-child(3) { border-left: 0; padding-left: 0; }
  .ficha-campana__celda:nth-child(n+3) { border-top: 1px solid var(--linea); }
  .preguntas, .pasos--tres { grid-template-columns: 1fr; }
  .datos { grid-template-columns: 1fr; }
  .datos__celda { padding: 20px 0; }
  .datos__celda + .datos__celda { border-left: 0; border-top: 1px solid var(--linea); padding-left: 0; }
  .datos__pie { max-width: none; }
}

@media (max-width: 640px) {
  .rejilla-4, .rejilla-sesiones, .indice, .pasos, .formulario, .pie__rejilla,
  .contacto__datos { grid-template-columns: 1fr; }
  /* En el teléfono el imán pasa a obligatorio: cada foto ocupa casi el ancho
     entero y media foto a la vista no es un encuadre, es un descuido. */
  .galeria__carril { scroll-snap-type: x mandatory; }
  .galeria__pieza { width: 78vw; }
  .galeria__pieza--alta { width: 66vw; }

  .mosaico { columns: 1; }
  /* En la sala de Contrast hay 22 fotos: en una columna serían un pasillo. A
     dos columnas se recorren y siguen leyéndose. */
  .mosaico--libre { columns: 2; column-gap: 10px; }
  .mosaico--libre figure { margin-bottom: 10px; }
  .mosaico--libre.sala--repartida { gap: 10px; }
  .sala__columna { row-gap: 10px; }
  .sesion--contrast { grid-column: auto; grid-template-columns: 1fr; }
  .retrato__pieza { aspect-ratio: 3 / 2; }
  .ocasiones { grid-template-columns: 1fr; }
  .lounge__foto img { aspect-ratio: 4 / 5; }
  .autor { grid-template-columns: 88px minmax(0, 1fr); }
  .autor img { width: 88px; }
  .precios tbody th { font-size: 15px; }
  .campo--ancho { grid-column: span 1; }
  /* En pareja quedarían dos columnas de 150 px y el texto que explica qué foto
     va en cada hueco caería a una palabra por línea. Apilados se lee. */
  .retrato { grid-template-columns: 1fr; }
  .retrato__principal { grid-column: 1; }
  .boton-wa span { display: none; }
  .boton-wa { padding: 11px 12px; }
  .contacto__directo .boton, .hero__acciones .boton { flex: 1 1 100%; }
  .hero__foto img { aspect-ratio: 4 / 5; }
  .banda-foto img { aspect-ratio: 4 / 3; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* El retardo se anula junto con la duración. Sin esto, el menú escalonado
     seguiría haciendo esperar tres cuartos de segundo a sus enlaces: la espera
     no es movimiento, pero se sufre igual. */
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
  }
  .anim [data-revelar] { opacity: 1; transform: none; }
  .hero__zoom, .hero__kicker, .hero__frase, .hero__entrada,
  .hero__acciones, .hero__pista { animation: none; opacity: 1; transform: none; }
  .hero__pista__riel i { animation: none; }
  .menu-movil, .menu-movil[data-abierto='true'] { clip-path: none; }
  .menu-movil__pie > * { opacity: 1; transform: none; }
  .menu-movil__lista a .linea { transform: none; }
}
