/* ===========================================================================
   SOMA — el sitio
   Los tokens están en tokens.css. Acá van sólo composición y movimiento.
   ========================================================================= */
html{ scroll-behavior: smooth; }
html, body{ height: 100%; }
body{ overflow-x: hidden; background: var(--tinta); }
body[data-fase="cargando"]{ overflow: hidden; }

@property --revelado{ syntax: '<percentage>'; initial-value: 0%; inherits: true; }
/* inherits:true no es opcional: la transición vive en el contenedor y la
   máscara la consume un hijo. Con false el hijo lee el valor inicial y no se
   mueve nunca — se ve como un problema de repintado y no lo es. */

/* ===== REVELADOS ==========================================================
   El motor está en soma.js. Acá sólo el gesto.

   Todo el estado oculto cuelga de `.con-js`, que pone un script mínimo en el
   <head>. Si el JavaScript no carga, falla o lo bloquea una extensión, el sitio
   se ve entero y quieto en vez de quedarse sin fotos ni titulares. Un revelado
   roto no deja una animación fea: deja la página vacía. */
[data-revelar]{ }

/* Texto: cada línea sube desde debajo de su propio recorte. El escalonado es
   corto —70ms— porque con más se lee como una lista que aparece, no como un
   párrafo que entra. */
[data-revelar="lineas"] .linea,
[data-revelar="parrafo"] .linea{ display: block; overflow: hidden; }
.con-js [data-revelar="lineas"] .linea > span,
.con-js [data-revelar="parrafo"] .linea > span{
  display: block;
  transform: translateY(112%);
  transition: transform var(--t-revelar) var(--curva-fina);
  transition-delay: calc(var(--i, 0) * 70ms + var(--retraso, 0ms));
}
[data-revelar="lineas"].visible .linea > span,
[data-revelar="parrafo"].visible .linea > span{ transform: none; }

/* Imagen: el recorte se abre y la foto, adentro, vuelve de una escala mayor a
   la suya. Las dos duraciones son distintas a propósito: si coinciden, el
   gesto se lee como un bloque que crece. Desfasadas, la foto se asienta.

   EL RECORTE VA EN LA IMAGEN, NO EN LA FIGURA, y no es un detalle de estilo:
   IntersectionObserver considera que un elemento con `clip-path` que lo deja en
   área cero NO está intersectando. Con el recorte en la figura —que es el
   elemento observado— se arma un bloqueo circular: está oculta, así que el
   observador no dispara; como no dispara, nunca se le pone .visible; como no
   se le pone, nunca se desclipea. Resultado: NINGUNA foto del sitio aparece
   jamás. Medido: con recorte en la figura, isIntersecting false y ratio 0;
   moviéndolo a la imagen, true y 0,669 en el mismo scroll. */
/* scale y translate van separados, y no por prolijidad. Antes los dos vivían en
   `transform`, que tiene la transición de 2,1s del revelado: cada cambio de
   --py —o sea cada cuadro de scroll— se animaba con 2,1s de retraso y el
   parallax llegaba tarde. Con desplazamientos de 16-26px casi no se notaba; con
   el parallax fuerte del pórtico la foto se sentía como goma. Ahora la escala
   lleva la transición y el desplazamiento sigue al scroll al instante. */
.con-js [data-revelar="imagen"] img{
  clip-path: inset(0 0 100% 0);
  scale: 1.16;
  translate: 0 var(--py, 0px);
  transition: clip-path 1.45s var(--curva-fina), scale 2.1s var(--curva-fina);
  transition-delay: var(--retraso, 0ms);
}
[data-revelar="imagen"].visible img{
  clip-path: inset(0 0 0 0);
  scale: 1;
}
/* El fundido con subida va en la FIGURA, además del recorte en la imagen. Esa
   capa de más es exactamente lo que hacía que las de Residencias se vieran
   mejor: ahí la tarjeta entera llevaba un `subir` encima del recorte, y en las
   otras secciones la figura tenía sólo el recorte. Ahora es una sola regla y
   todas las fotos del sitio entran igual.
   La opacidad no interfiere con IntersectionObserver —sólo el recorte lo hace—
   así que esto es seguro donde el clip-path no lo era. */
.con-js [data-revelar="imagen"]{
  opacity: 0; transform: translateY(22px);
  transition: opacity .9s var(--curva-fina), transform 1.1s var(--curva-fina);
  transition-delay: var(--retraso, 0ms);
}
[data-revelar="imagen"].visible{ opacity: 1; transform: none; }

/* Aparición simple, para lo que no es ni línea ni foto */
.con-js [data-revelar="subir"]{
  opacity: 0; transform: translateY(22px);
  transition: opacity .9s var(--curva-fina), transform 1.1s var(--curva-fina);
  transition-delay: var(--retraso, 0ms);
}
[data-revelar="subir"].visible{ opacity: 1; transform: none; }

/* Filete que se dibuja. Cuesta una línea y ordena una sección entera. */
[data-revelar="filete"]{
  height: 1px; background: var(--linea); border: 0; margin: 0;
  transform-origin: left;
}
.con-js [data-revelar="filete"]{
  transform: scaleX(0);
  transition: transform 1.5s var(--curva-fina);
  transition-delay: var(--retraso, 0ms);
}
[data-revelar="filete"].visible{ transform: scaleX(1); }

/* ===== HERO ================================================================ */
.fondo{ position: fixed; inset: 0; z-index: 0; overflow: hidden; }
/* Pasado el hero, la capa deja de existir para el navegador. Antes quedaba
   fija detrás de las nueve secciones esperando que cada una la tapara con su
   fondo; alcanzaba con que una no lo hiciera —"Un umbral"— para que la villa
   reapareciera en el medio del sitio. Así no depende de ninguna sección.
   visibility y no display: al volver a subir aparece sin recalcular layout. */
.fondo[data-pasado="si"]{ visibility: hidden; }
.fondo img{ width: 100%; height: 100%; object-fit: cover; }
.fondo__borrosa{ position: absolute; inset: 0; opacity: 1; transition: opacity 1.2s var(--curva-suave); }
.fondo__borrosa img{ filter: blur(30px) saturate(.9); transform: scale(1.1); }
body[data-fase="listo"] .fondo__borrosa,
body[data-fase="revelando"] .fondo__borrosa{ opacity: 0; }

/* La foto se apaga a medida que sube la sección siguiente. Además de ser el
   gesto buscado, es lo que sostiene al header: el crema gana contraste al
   bajar en vez de tener que saltar a una barra opaca a mitad del hero. */
.fondo__oscurecer{ position: absolute; inset: 0; background: var(--tinta);
  opacity: calc(var(--oscuro, 0) * .74); }

/* Velo superior. No es decorativo: sin él el header en crema mide 2,60–3,14:1;
   con él, 4,58–5,29:1. Si alguna vez se saca, el header vuelve a tinta. */
.fondo__velo{
  position: absolute; inset: 0; opacity: 0;
  background: linear-gradient(180deg, rgba(24,24,8,.34) 0%, rgba(24,24,8,.06) 34%, rgba(24,24,8,0) 52%);
  transition: opacity .9s var(--curva);
}
/* Refuerzo lateral: el cielo NO es parejo en horizontal. Bajo el nav mide
   #7D8B9B pero bajo el selector de idioma, pegado al borde, #AFBDCA — ahí el
   crema se quedaba en 3,27 mientras el nav llegaba a 5,29. Subir el velo
   general lo arreglaba oscureciendo la foto entera por una esquina. */
.fondo__velo-lados{
  position: absolute; top: 0; left: 0; right: 0; height: 20svh; opacity: 0;
  background:
    linear-gradient(to right, rgba(24,24,8,.24) 0%, rgba(24,24,8,0) 30%),
    linear-gradient(to left,  rgba(24,24,8,.24) 0%, rgba(24,24,8,0) 30%);
  -webkit-mask-image: linear-gradient(180deg, #000 40%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 40%, transparent 100%);
  transition: opacity .9s var(--curva);
}
body[data-fase="listo"] .fondo__velo, body[data-fase="revelando"] .fondo__velo,
body[data-fase="listo"] .fondo__velo-lados, body[data-fase="revelando"] .fondo__velo-lados{ opacity: 1; }

/* El wordmark. Reposo al 21% de la altura: el medio exacto de la franja de
   cielo libre, porque el techo de la villa corta al 32,8%. Viaja con transform
   —nunca con top ni width— así el navegador interpola una matriz. */
.marca{
  position: fixed; left: 50%; top: 21%; z-index: 30;
  /* El ancho se rige por el ALTO de la pantalla, no por el ancho, porque el que
     aprieta es el eje vertical: el wordmark vive en la franja entre el header y
     el techo de la villa. Medido en 1512x860 —un MacBook Pro de 14"— esa franja
     es de 151px y el wordmark ocupaba 111: el 74%, con 19px de aire arriba y 21
     abajo. Con min(20vw, 27svh) queda en 232px de ancho y 78 de alto, o sea la
     mitad de la franja y ~36px de aire de cada lado.
     Y ojo: el techo cae al 29,9% de la PANTALLA, no al 32,8% que da el archivo.
     `object-fit: cover` recorta distinto según la proporción del monitor, así
     que medir sobre el archivo y no sobre el recorte lleva a error. */
  width: clamp(160px, min(20vw, 27svh), 300px); margin: 0;
  --viaje: 0; --salida: 0;
  /* La precarga a 1,30x. Sumado a la base más chica, el wordmark de entrada
     pasa de 462 a ~302px en un 14": un tercio menos. */
  transform: translate(-50%, calc(-50% + var(--viaje) * 29svh - var(--salida) * 34px))
             scale(calc(1 + var(--viaje) * .30));
  opacity: calc(1 - var(--salida));
  transition: transform 1.4s var(--curva-suave);
}
body[data-fase="cargando"] .marca{ --viaje: 1; }
.marca__caja{ position: relative; }
.marca img{ filter: brightness(0) invert(1) opacity(.94); width: 100%; }

/* El wordmark se escribe de izquierda a derecha, como tinta */
.marca__caja{ --revelado: 0%; transition: --revelado 1.5s var(--curva-suave); }
body[data-logo="si"] .marca__caja{ --revelado: 104%; }
.marca__caja > img{
  -webkit-mask-image: linear-gradient(90deg, #000 var(--revelado), transparent calc(var(--revelado) + 7%));
          mask-image: linear-gradient(90deg, #000 var(--revelado), transparent calc(var(--revelado) + 7%));
}

/* Flecha fina. La versión anterior era una línea de 1px al 50% de opacidad y
   pasaba desapercibida — que era exactamente el problema.
   --salida-cue la escribe el scroll. Antes la regla existía pero NADIE definía
   la variable, así que el indicador se quedaba en 0.5 para siempre, fijo abajo,
   durante todo el sitio. Se veía hasta en el pie. */
.scroll-cue{
  position: fixed; left: 50%; bottom: 26px; z-index: 30; color: var(--papel);
  --salida-cue: 0;
  transform: translateX(-50%) translateY(calc(var(--salida-cue) * 12px));
  pointer-events: none;
  /* Sin retraso acá. El elemento de afuera sólo responde al scroll y tiene que
     hacerlo YA: el retraso de 1s que necesita la aparición inicial también
     frenaba el desvanecido, y el indicador quedaba un segundo entero atrás del
     dedo. Dos responsabilidades distintas, dos elementos. */
  opacity: calc(1 - var(--salida-cue));
  transition: opacity .28s linear, transform .28s linear;
}
/* La aparición, con su retraso, vive adentro. */
.scroll-cue__in{ display: block; opacity: 0; transition: opacity .8s var(--curva) 1s; }
body[data-fase="listo"] .scroll-cue__in{ opacity: .85; }
.scroll-cue i{
  display: block; width: 1px; height: 54px; background: currentColor;
  margin: 0 auto; transform-origin: top;
  animation: cueLinea 2.4s var(--curva-fina) infinite;
}
/* La punta: dos trazos de 1px rotados. Un SVG para esto sería un archivo más
   y un pedido de red por una flecha de doce píxeles. */
.scroll-cue i::before, .scroll-cue i::after{
  content: ""; position: absolute; bottom: 0; width: 11px; height: 1px;
  background: currentColor; transform-origin: right center;
}
.scroll-cue i::before{ right: 0; transform: rotate(45deg); }
.scroll-cue i::after{ left: 0; transform-origin: left center; transform: rotate(-45deg); }
.scroll-cue i{ position: relative; }
@keyframes cueLinea{
  0%   { transform: translateY(-10px); opacity: 0 }
  28%  { opacity: 1 }
  72%  { transform: translateY(0);     opacity: 1 }
  100% { transform: translateY(9px);   opacity: 0 }
}

.espacio{ height: 100svh; position: relative; z-index: 1; }

/* ===== HEADER ============================================================== */
.hdr{
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  padding: clamp(18px, 2.4vw, 30px) var(--margen);
  color: var(--papel);
  opacity: 0; pointer-events: none;
  transition: padding .5s var(--curva), background-color .18s linear,
              box-shadow .18s linear, opacity .8s var(--curva);
}
body[data-fase="listo"] .hdr, body[data-fase="revelando"] .hdr{ opacity: 1; pointer-events: auto; }
/* La barra tiene que ser oscura: con el header en crema, una de papel sería
   crema sobre crema. En tinta el crema mide 16,17:1. Entra recién al final del
   hero, cuando la foto ya está oscurecida al 74% y el cambio no se lee. */
.hdr[data-fijo="si"]{
  padding-top: 10px; padding-bottom: 10px;
  background: var(--tinta); box-shadow: 0 1px 0 rgba(246,243,237,.12);
}
.hdr[data-fijo="si"] .hdr__marca img{ height: 32px; }
.hdr nav{ display: flex; align-items: center; justify-content: center; gap: clamp(10px, 2.2vw, 34px); }
.hdr nav a{
  color: inherit; text-decoration: none; flex: 0 0 auto; min-width: 92px;
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px;
  font-family: var(--sans); font-size: 12px; font-weight: 300;
  letter-spacing: .14em; text-transform: uppercase; position: relative;
}
/* El subrayado crece desde el centro. Es el mismo gesto que marca el idioma
   activo, así el header tiene un solo lenguaje de estado. */
.hdr nav a::after{
  content: ""; position: absolute; left: 22%; right: 22%; bottom: 10px; height: 1px;
  background: currentColor; transform: scaleX(0);
  transition: transform .4s var(--curva-fina);
}
.hdr nav a:hover::after{ transform: scaleX(1); }
.hdr__marca{ flex: 0 0 auto; margin: 0 clamp(8px, 2vw, 26px); display: flex; align-items: center; }
.hdr__marca img{ height: 46px; width: auto; transition: height .5s var(--curva);
  filter: brightness(0) invert(1) opacity(.94); }

/* El idioma va absoluto contra el borde, FUERA del grupo centrado: metido en el
   nav correría el eje y la simetría dejaría de ser exacta. */
.idioma{ position: absolute; right: var(--margen); top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; gap: 2px; }
/* El estado activo NO se marca con opacidad: sobre la foto, tinta o crema al
   45% se hunde a ~2:1 y al 70% sigue en 3,4:1. Ninguna translucidez sobre una
   imagen sobrevive. Los dos van a color pleno y el activo lleva la línea. */
.idioma button{ background: none; border: 0; cursor: pointer; color: inherit;
  font-family: var(--sans); font-size: 12px; font-weight: 300; letter-spacing: .14em;
  min-height: 44px; min-width: 44px; padding: 0 6px; position: relative; }
.idioma button::after{
  content: ""; position: absolute; left: 6px; right: 6px; bottom: 12px; height: 1px;
  background: currentColor; transform: scaleX(0);
  transition: transform .3s var(--curva-fina);
}
.idioma button[aria-pressed="true"]::after{ transform: scaleX(1); }
.idioma i{ width: 1px; height: 12px; background: currentColor; opacity: .35; }

.menu{ position: absolute; right: var(--margen); top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; display: none; place-items: center;
  background: none; border: 0; cursor: pointer; color: inherit; padding: 0; }
.menu i{ display: block; width: 22px; height: 1px; background: currentColor; position: relative;
  transition: transform .35s var(--curva-fina); }
.menu i::after{ content:""; position: absolute; left: 0; top: -6px; width: 22px; height: 1px;
  background: currentColor; transition: transform .35s var(--curva-fina); }
body[data-menu="abierto"] .menu i{ transform: rotate(45deg) translateY(-3px); }
body[data-menu="abierto"] .menu i::after{ transform: rotate(-90deg) translateY(6px); }

#panel-menu{
  position: fixed; inset: 0; z-index: 39; background: var(--tinta); color: var(--papel);
  display: grid; place-items: center; gap: 0;
}
/* El `hidden` del HTML pierde contra un display declarado con un selector de
   id: la hoja del navegador trae [hidden]{display:none} con especificidad casi
   nula. Sin esta línea el menú móvil se ve abierto en escritorio. */
#panel-menu[hidden]{ display: none; }
#panel-menu ul{ list-style: none; margin: 0; padding: 0; text-align: center; }
#panel-menu a{ color: inherit; text-decoration: none; font-family: var(--serif);
  font-size: clamp(2rem, 8vw, 3rem); line-height: 1.5; display: block; }

/* ===== CONTENIDO =========================================================== */
main{ position: relative; z-index: 2; }
/* scroll-margin-top: con un header fijo, saltar a un ancla deja el título
   debajo de la barra. Es el olvido más común de cualquier one-page. */
.seccion, .sangre{ scroll-margin-top: 76px; }
.seccion{ background: var(--papel); padding: var(--seccion) var(--margen); position: relative; }
.seccion--alt{ background: var(--papel-hondo); }
.seccion--oscura{ background: var(--tinta); color: var(--papel); }
.seccion--oscura .etiqueta{ color: rgba(246,243,237,.6); }
.seccion--oscura p{ color: rgba(246,243,237,.78); }

.limite{ max-width: var(--ancho-limite); margin: 0 auto; }
/* La foto se lleva más columna que el texto: el copy de estas secciones es
   corto y no necesita la mitad de la pantalla. --col se fija por variante
   porque las columnas de una grilla son posicionales y la figura no siempre
   cae en la misma: en Bienestar va primera en el HTML, en El proyecto va
   segunda, y en Arquitectura va segunda pero `order` la manda a la izquierda. */
.par{ display: grid; grid-template-columns: var(--col, 1.16fr .84fr);
  gap: clamp(30px, 4vw, 74px); align-items: center; }
.par--der{ --col: .84fr 1.16fr; }
.par--invertido{ --col: 1.16fr .84fr; }
.par--invertido > figure{ order: -1; }
.par__txt{ max-width: 32rem; }
.par--der .par__txt{ justify-self: end; }

figure{ margin: 0; overflow: hidden; }
figure img{ width: 100%; display: block; }

/* Manifiesto: casi todo aire. El texto es corto a propósito — es lo único que
   hay en la pantalla y tiene que poder leerse de una sola vez. */
.manifiesto{ text-align: center; padding: calc(var(--seccion) * 1.5) var(--margen); }
.manifiesto h2{ font-size: clamp(2rem, 4.6vw, 4rem); max-width: 20ch; margin: 0 auto; }
.manifiesto p{ margin: clamp(30px,4vw,52px) auto 0; color: var(--txt-suave); max-width: 44ch; }

/* Momento a sangre: una foto que ocupa todo y una sola línea encima. */
/* Fondo propio, opaco. Antes era transparente: mientras su foto se revelaba
   —recortada al 100% y con opacidad 0 durante un segundo y medio— la sección
   era un agujero y por ahí se veía la villa del hero, que sigue fija detrás.
   No era lentitud de carga: no había nada tapando. */
.sangre{ position: relative; min-height: 92svh; overflow: hidden; display: grid;
  background: var(--tinta); }
.sangre > *{ grid-area: 1 / 1; }
/* La imagen sale del flujo. `height:100%` en un ítem de grilla se resuelve
   contra su celda, pero la celda se dimensiona por el contenido: es circular y
   el navegador lo ignora, así que la figura seguía midiendo el alto natural del
   archivo —1440px sobre 1280 de ancho— y la sección quedaba en 1620 en vez de
   830. Absoluta, no dimensiona nada y el alto lo fija min-height. */
.sangre__velo, .sangre__oscuro{ position: absolute; inset: 0; }
/* Parallax fuerte: la foto mide un 50% más que su marco y se desplaza en
   sentido contrario al scroll, así que se mueve mucho más lento que la sección
   sin llegar a quedarse quieta. El 25% que sobra de cada lado cubre el máximo
   desplazamiento (±22% del alto de la sección): nunca asoma el borde. */
.sangre > figure{ position: absolute; left: 0; right: 0; top: -25%; height: 150%; }
/* Se apaga cuando sube la sección siguiente, con la misma rampa y el mismo
   tope que el hero: las dos fotos grandes del sitio se comportan igual. */
.sangre__oscuro{ background: var(--tinta); opacity: calc(var(--oscuro, 0) * .74); }
.sangre img{ width: 100%; height: 100%; object-fit: cover; }
.sangre__velo{ background: linear-gradient(180deg, rgba(24,24,8,.42), rgba(24,24,8,.12) 42%, rgba(24,24,8,.52)); }
.sangre__txt{ align-self: end; padding: 0 var(--margen) clamp(48px,8vh,92px); color: var(--papel); z-index: 2; }
.sangre__txt h2{ font-size: clamp(1.9rem, 4vw, 3.4rem); max-width: 18ch; }

/* Bienestar: la lista se escalona y cada ítem lleva su filete. */
.lista{ list-style: none; margin: clamp(28px,4vw,44px) 0 0; padding: 0; }
.lista li{ padding: clamp(18px,2vw,26px) 0; }
.lista li h3{ font-size: clamp(1.3rem, 2vw, 1.7rem); margin-bottom: .35em; }
.lista li p{ color: var(--txt-suave); margin: 0; }

/* Residencias: tres tipologías. Sin cifras: no existen y no se inventan. */
.tipos{ display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(24px,3vw,48px);
  margin-top: clamp(38px,5vw,70px); }
.tipos .tipo__txt{ margin-top: .7em; }
.tipos article h3{ font-size: clamp(1.35rem, 2.1vw, 1.85rem); margin: .35em 0 .4em; }
.tipos article p{ color: var(--txt-suave); font-size: .96rem; }
.tipos .num{ font-family: var(--sans); font-size: var(--etiqueta); letter-spacing: var(--tr-etiqueta);
  color: var(--oliva-txt); text-transform: uppercase; }

/* Identidad: un bloque rectangular, no un collage.
   Cuatro columnas por dos filas = ocho celdas. La primera foto ocupa 2x2 y las
   otras cuatro toman una celda cada una: el bloque cierra exacto en un
   rectángulo 2:1 sin huecos ni sobrantes.
   Las celdas chicas llevan aspect-ratio 1, así que la altura de fila es igual
   al ancho de columna y el `gap` es el MISMO en los dos ejes — que es lo que
   hace que se lea como una retícula y no como fotos apoyadas. Lo que no entra
   en su celda se recorta con object-fit, que para bodegones centrados no
   pierde nada. */
.identidad{
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(10px, 1.1vw, 18px);
  margin-top: clamp(38px,5vw,70px);
}
.identidad figure{ aspect-ratio: 1; margin: 0; overflow: hidden; }
.identidad figure img{ width: 100%; height: 100%; object-fit: cover; }
/* La grande TAMBIÉN lleva aspect-ratio 1, y es cuadrada por aritmética: dos
   columnas más un hueco miden lo mismo que dos filas más un hueco.
   Con `auto` su altura la definía la proporción del archivo (1000x1125), salía
   787 en vez de 699 y estiraba las filas: el hueco horizontal quedaba en 16,6px
   y el vertical en 61. La retícula se rompía justo en lo que la hace retícula. */
.identidad figure:nth-child(1){ grid-column: span 2; grid-row: span 2; aspect-ratio: 1; }

/* Cierre y firma */
/* Relleno asimétrico: menos abajo que arriba, porque el pie viene inmediatamente
   después y es del mismo color. Con 177px de cada lado más los 171 del pie, el
   bloque oscuro medía 811px sobre una pantalla de 860 — el 94%, una pantalla
   entera de negro. */
.cierre{ text-align: center;
  padding: clamp(88px, 9.5vw, 148px) var(--margen) clamp(64px, 6.5vw, 96px); }
.cierre__mono{ width: 78px; margin: 0 auto clamp(28px,4vw,44px);
  filter: brightness(0) invert(1) opacity(.9); }
.cierre h2{ font-size: clamp(1.8rem, 3.6vw, 3rem); max-width: 18ch; margin: 0 auto; }
.cierre .etiqueta{ display: block; margin-top: clamp(26px,3.4vw,40px); }

/* ===== PIE ================================================================
   Mismo negro que el cierre y que el header: el bloque oscuro del final es uno
   solo y el pie no se anuncia como una sección aparte.

   position:relative + z-index NO son decorativos acá. El pie estaba `static` y
   .fondo es `fixed` con z-index 0: un elemento posicionado pinta por encima del
   fondo de uno estático, aunque venga antes en el HTML. Resultado medido: al
   final del sitio, preguntando qué se pinta en el medio del pie, el navegador
   devolvía `DIV.fondo__velo`. El pie existía, tapado por la foto. */
.pie{
  position: relative; z-index: 3;
  background: var(--tinta); color: rgba(246,243,237,.62);
  padding: clamp(18px, 2vw, 26px) var(--margen) clamp(24px, 2.6vw, 34px);
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
}
.pie__caso{
  margin: 0; max-width: none;
  font-family: var(--sans); font-size: var(--etiqueta); font-weight: 400;
  letter-spacing: var(--tr-etiqueta); text-transform: uppercase; line-height: 1;
}
.pie__firma{
  display: inline-flex; align-items: center; gap: 14px;
  min-height: 44px; margin-right: -14px;  /* el relleno táctil no debe correr el borde */
  padding: 0 14px; text-decoration: none; color: inherit;
  transition: opacity .3s var(--curva-fina);
}
.pie__firma:hover{ opacity: .72; }
.pie__firma .etiqueta{ color: rgba(246,243,237,.5); }
.pie__firma img{ height: 22px; width: auto; filter: brightness(0) invert(1) opacity(.9); }

/* ===== MOBILE ==============================================================
   Se define acá y se dice: por debajo de 820px la tablet vertical queda
   adentro. Es una decisión, no un descuido. */
@media (max-width: 820px){
  .hdr nav > a{ display: none; }
  .idioma{ right: auto; left: var(--margen); }
  .menu{ display: grid; }
  .marca{ width: min(58vw, 250px); }
  .par{ grid-template-columns: 1fr; }
  .par--invertido > figure{ order: 0; }
  .par--der .par__txt{ justify-self: start; }
  .tipos{ grid-template-columns: 1fr; }
  .identidad{ grid-template-columns: repeat(2, 1fr); }
  .identidad figure:nth-child(1){ grid-column: span 2; grid-row: span 2; }
  .pie{ flex-direction: column; justify-content: center; gap: 14px; text-align: center; }
  .pie__firma{ margin-right: 0; }
}

/* Mismo trato que sin movimiento: el sitio armado, quieto. */
.sin-movimiento, .sin-movimiento *{ transition: none !important; animation: none !important; }
.sin-movimiento .fondo__borrosa{ display: none; }
.sin-movimiento .marca{ --viaje: 0 !important; }
.sin-movimiento .marca__caja{ --revelado: 104% !important; }
.sin-movimiento [data-revelar], .sin-movimiento [data-revelar] img{ opacity: 1 !important; transform: none !important; clip-path: none !important; scale: 1 !important; translate: none !important; }
.sin-movimiento [data-revelar] .linea > span{ transform: none !important; }
.sin-movimiento [data-revelar="filete"]{ transform: scaleX(1) !important; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  .fondo__borrosa{ display: none; }
  .marca{ --viaje: 0 !important; transition: none; }
  .marca__caja{ --revelado: 104% !important; }
  [data-revelar], [data-revelar] img{ opacity: 1 !important; transform: none !important; clip-path: none !important; scale: 1 !important; translate: none !important; }
  [data-revelar] .linea > span{ transform: none !important; }
  [data-revelar="filete"]{ transform: scaleX(1) !important; }
}
