/* Base común de la demo: tokens, tipografía, cabecera, botones, cargador,
   cursor y pie. Medidas tomadas de luxury-places.ch (10-nov-2026): fondo
   #f0f0f0, Poppins 200 en mayúsculas con 0.02em, menú a 12 px, botones negros
   de radio 2 px y la curva cubic-bezier(.6, 0, .3, 1) en todas las
   transiciones. */

:root {
  --fondo: #f0f0f0;
  --tinta: #000;
  --gris: #666;
  /* #9a9a9a daba 2.5:1 sobre el fondo (placeholders, filtros inactivos). */
  --gris-claro: #858585;
  --linea: rgba(0, 0, 0, .14);
  --blanco: #fff;
  --curva: cubic-bezier(.6, 0, .3, 1);
  --margen: 16px;
  --hueco: clamp(24px, 5.5vw, 72px);
  --alto: 100vh;
  --barra: 0px;
}
/* Alto de pantalla con las barras del navegador escondidas (lvh), no el que
   cambia mientras se esconden (dvh). Medido el 13-nov-2026 en Safari de iOS
   26: con dvh, al bajar la barra se recoge, la ventana pasa de 714 a 754 px y
   toda la página crecía 537 px a media lectura (secciones de 3 a 6 pantallas).
   --barra es lo que tapa la barra cuando está a la vista: lo que va pegado
   abajo de una sección a pantalla completa se sube eso. */
@supports (height: 100lvh) { :root { --alto: 100lvh; --barra: calc(100lvh - 100svh); } }

* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--fondo); }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
body {
  background: var(--fondo); color: var(--tinta);
  font-family: "Poppins", system-ui, sans-serif; font-size: 16px; line-height: 1.5;
  -webkit-font-smoothing: antialiased; overflow-x: clip;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }
button { -webkit-tap-highlight-color: transparent; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }

.contenedor { padding-left: var(--margen); padding-right: var(--margen); }
.texto-xs { font-size: 12px; line-height: 1.66; text-transform: uppercase; letter-spacing: .01em; }
.titulo-xl {
  font-weight: 200; font-size: clamp(38px, 6.05vw, 118px); line-height: 1.1;
  letter-spacing: .02em; text-transform: uppercase;
}
.titulo-l {
  font-weight: 200; font-size: clamp(30px, 3.85vw, 74px); line-height: 1.1;
  letter-spacing: .02em; text-transform: uppercase;
}
.titulo-m {
  font-weight: 300; font-size: clamp(22px, 2.45vw, 34px); line-height: 1.2;
  letter-spacing: .02em; text-transform: uppercase;
}

/* Líneas que suben desde una máscara al entrar. */
.revela .linea { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.revela .linea > span { display: inline-block; transform: translateY(110%); transition: transform 1.2s var(--curva); }
.revela .linea:nth-child(2) > span { transition-delay: .08s; }
.revela .linea:nth-child(3) > span { transition-delay: .16s; }
.revela.visible .linea > span { transform: none; }

/* Títulos que entran letra por letra (home.js las separa). La línea ya no se
   mueve entera: cada letra sube desde la máscara con un retraso escalonado. */
.revela.letras .linea > span { transform: none; transition: none; }
.letras .palabra { display: inline-block; white-space: nowrap; }
.letras .letra {
  display: inline-block; transform: translateY(108%) rotate(4deg); transform-origin: 0 100%; opacity: 0;
  transition: transform 1.1s var(--curva), opacity .7s var(--curva);
  transition-delay: calc(var(--i) * 26ms);
}
.letras.visible .letra { transform: none; opacity: 1; }

/* Botones */
.boton {
  display: inline-flex; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 2px;
  background: var(--tinta); color: var(--blanco);
  font-size: 12px; line-height: 1.66; text-transform: uppercase; white-space: nowrap;
  transition: background-color .5s var(--curva), color .5s var(--curva);
}
.boton:hover { background: #2b2b2b; }
.boton-extra { color: var(--gris); }
.boton--claro { background: var(--blanco); color: var(--tinta); }
.boton--claro:hover { background: #e6e6e6; }
.boton .flecha { width: 12px; height: 12px; }

/* Cruz fina de los costados (marca de retícula). */
.cruz { position: relative; width: 14px; height: 14px; opacity: .35; flex: none; }
.cruz::before, .cruz::after { content: ""; position: absolute; background: currentColor; }
.cruz::before { left: 0; right: 0; top: 50%; height: 1px; }
.cruz::after { top: 0; bottom: 0; left: 50%; width: 1px; }

/* Cabecera */
.cabecera {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: start;
  padding: 24px var(--margen) 0; color: var(--tinta);
  transition: transform .8s var(--curva), color .5s var(--curva);
  pointer-events: none;
}
.cabecera > * { pointer-events: auto; }
.cabecera.oculta { transform: translateY(-140%); }
/* Al volver a aparecer sobre fondo claro lleva el gris de la página, para no
   encimarse con lo que pasa debajo; sobre fotos queda transparente. */
.cabecera { padding-bottom: 14px; }
.cabecera::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: var(--fondo);
  opacity: 0; transition: opacity .5s var(--curva);
}
.cabecera.con-fondo::before { opacity: 1; }
.cabecera.clara { color: var(--blanco); }
/* Blanca sobre fotos claras (el cielo rosa de «Del terreno a la casa» daba
   1.25:1): una sombra suave que no se nota sobre lo oscuro. */
.cabecera.clara .menu, .cabecera.clara .idioma { text-shadow: 0 1px 2px rgba(0,0,0,.3), 0 0 14px rgba(0,0,0,.35); }
.cabecera.clara .cabecera-marca { filter: drop-shadow(0 0 8px rgba(0,0,0,.35)); }
.menu { display: flex; flex-wrap: wrap; align-items: center; }
.menu li { display: flex; align-items: center; }
.menu li + li::before {
  content: ""; width: 3px; height: 3px; border-radius: 50%; background: currentColor;
  opacity: .35; margin: 0 8px;
}
.menu a { font-size: 12px; line-height: 1.66; text-transform: uppercase; transition: opacity .4s var(--curva); }
.menu a:hover { opacity: .55; }
.menu--der { justify-content: flex-end; }
.cabecera-logo { display: block; padding: 14px; margin: -22px -14px -14px; }
/* La máscara va en un hijo: si fuera el propio enlace, sus huecos
   transparentes dejaban pasar el clic a lo de abajo (en la ficha, a la mitad
   de la galería, que avanzaba la foto en vez de ir al inicio). Así el enlace
   ocupa todo su recuadro, con 14 px de margen para atinarle. */
.cabecera-marca {
  display: block; width: 52px; height: 52px;
  background: currentColor;
  -webkit-mask: url(../media/marca/marca.png) center / contain no-repeat;
  mask: url(../media/marca/marca.png) center / contain no-repeat;
}
.idioma button { font-size: 12px; line-height: 1.66; text-transform: uppercase; opacity: .4; transition: opacity .4s var(--curva); }
.idioma button[aria-pressed="true"] { opacity: 1; }
.idioma button:hover { opacity: 1; }
.idioma-sep { opacity: .35; margin: 0 4px; font-size: 12px; }

/* Cargador: la marca con un aro que se dibuja; al terminar se abre un
   círculo desde el centro. Solo la primera visita de la sesión. */
@property --abre { syntax: "<length>"; inherits: false; initial-value: 0px; }
.cargador {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background: var(--fondo);
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent var(--abre), #000 calc(var(--abre) + 1px));
  mask: radial-gradient(circle at 50% 50%, transparent var(--abre), #000 calc(var(--abre) + 1px));
  transition: --abre 1.4s var(--curva), opacity .6s ease-out 1s;
}
.cargador.fuera { --abre: 120vmax; opacity: 0; pointer-events: none; }
.cargador-logo { position: relative; width: 112px; height: 112px; }
.cargador-aro { position: absolute; inset: 0; transform: rotate(-90deg); overflow: visible; }
.cargador-aro circle {
  fill: none; stroke: var(--tinta); stroke-width: 1; vector-effect: non-scaling-stroke;
  stroke-dasharray: 316; stroke-dashoffset: 316;
  animation: aro 1.6s var(--curva) forwards;
}
@keyframes aro { to { stroke-dashoffset: 0; } }
.cargador-marca {
  position: absolute; inset: 22%; background: var(--tinta);
  -webkit-mask: url(../media/marca/marca.png) center / contain no-repeat;
  mask: url(../media/marca/marca.png) center / contain no-repeat;
  opacity: 0; animation: aparece .6s ease-out .2s forwards;
}
@keyframes aparece { to { opacity: 1; } }
.sin-cargador .cargador { display: none; }

/* La página entra desenfocada y se aclara, como en la referencia. */
.pagina { transition: filter 1.4s var(--curva), opacity 1.4s var(--curva); }
html:not(.lista) .pagina { filter: blur(14px); opacity: .5; }

/* Cursor propio (solo con ratón). El aro y el punto se mezclan en
   «diferencia» con lo que tienen debajo: negros sobre el gris claro, blancos
   sobre el negro e invertidos sobre las fotos. Para que la mezcla vea la
   página, la capa fija que los lleva no puede vivir dentro de otro contexto
   de apilamiento: por eso el contenedor no se posiciona. */
.cursor { display: none; }
@media (hover: hover) and (pointer: fine) { .cursor { display: block; } }
.cursor-marca, .cursor-capa { position: fixed; left: 0; top: 0; z-index: 90; pointer-events: none; }
.cursor-marca { mix-blend-mode: difference; }
.cursor-aro {
  /* 64 px (antes 150: Mario lo sintió demasiado grande, 13-nov-2026). */
  position: absolute; width: 64px; height: 64px; margin: -32px 0 0 -32px; border-radius: 50%;
  border: 1px solid #fff; opacity: .7;
  transition: transform .6s var(--curva), opacity .4s var(--curva);
}
.cursor-punto {
  position: absolute; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; border-radius: 50%;
  background: #fff; transition: transform .4s var(--curva), opacity .4s var(--curva);
}
.cursor-boton {
  position: absolute; transform: translate(-50%, -50%) scale(.6); opacity: 0;
  transition: transform .5s var(--curva), opacity .3s var(--curva), background-color .4s var(--curva), color .4s var(--curva);
}
.cursor.boton-activo .cursor-boton { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.cursor.boton-activo .cursor-aro, .cursor.boton-activo .cursor-punto { opacity: 0; transform: scale(.4); }
/* Al presionar (por ejemplo, para arrastrar el carrusel) se encoge un poco. */
.cursor.presionado .cursor-aro { transform: scale(.82); }
.cursor.boton-activo.presionado .cursor-boton { transform: translate(-50%, -50%) scale(.88); }
.con-cursor, .con-cursor a, .con-cursor button { cursor: none; }
/* Sobre las mitades de la galería: una flecha fina dentro del aro, que se
   achica, en lugar del botón con texto. Vive en la capa en «diferencia»:
   blanca sobre las fotos. */
.cursor-flecha {
  position: absolute; width: 26px; height: 26px; margin: -13px 0 0 -13px; color: #fff;
  opacity: 0; transform: scale(.5); transition: opacity .3s var(--curva), transform .5s var(--curva);
}
.cursor.flecha-activa .cursor-flecha { opacity: 1; transform: none; }
.cursor.flecha-activa.flecha-izq .cursor-flecha { transform: scaleX(-1); }
.cursor.flecha-activa .cursor-aro { transform: scale(1.05); opacity: .9; }
.cursor.flecha-activa .cursor-punto { opacity: 0; transform: scale(.4); }
.cursor.flecha-activa.presionado .cursor-aro { transform: scale(.9); }

/* Pie */
.pie {
  position: relative; min-height: var(--alto); display: grid;
  grid-template-rows: auto 1fr auto; padding: 24px var(--margen); gap: 24px;
}
.pie-arriba { display: grid; grid-template-columns: 1fr auto 1fr; }
.pie-centro { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px; }
.pie-logo {
  display: block; width: clamp(220px, 26vw, 380px); aspect-ratio: 2434 / 807; background: var(--tinta);
  -webkit-mask: url(../media/marca/logotipo.png) center / contain no-repeat;
  mask: url(../media/marca/logotipo.png) center / contain no-repeat;
}
.pie-lema { margin-top: 18px; text-align: center; color: var(--gris); }
.redes { display: flex; gap: 6px; }
.redes a {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 2px; background: var(--blanco);
  transition: background-color .4s var(--curva);
}
.redes a:hover { background: #e2e2e2; }
.redes svg { width: 13px; height: 13px; }
.pie-contacto { justify-self: end; }
.pie-abajo { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 24px; color: var(--gris); }

/* El botón «Menú» solo existe en celular; ahí el menú de la izquierda pasa a
   un panel a pantalla completa debajo del logo y los controles. */
.menu .menu-boton-li { display: none; }
.menu-boton { font-size: 12px; line-height: 1.66; text-transform: uppercase; }

@media (max-width: 760px) {
  .cabecera { grid-template-columns: auto 1fr; }
  .cabecera-logo { justify-self: start; }
  .cabecera-marca { width: 44px; height: 44px; }
  .menu .menu-boton-li { display: flex; }
  .menu-panel {
    position: fixed; inset: 0; z-index: -1; display: flex; align-items: center;
    padding: 0 var(--margen); background: var(--fondo); color: var(--tinta);
    opacity: 0; visibility: hidden; transition: opacity .5s var(--curva), visibility 0s linear .5s;
  }
  .menu-panel .menu { flex-direction: column; align-items: flex-start; gap: 6px; }
  .menu-panel .menu li + li::before { display: none; }
  .menu-panel .menu a { font-size: 34px; font-weight: 200; line-height: 1.3; letter-spacing: .02em; }
  .menu-panel .menu a[aria-current] { opacity: .45; }
  .cabecera.menu-abierto { color: var(--tinta); transform: none; }
  .cabecera.menu-abierto .menu-panel { opacity: 1; visibility: visible; transition: opacity .5s var(--curva); }
  .pie { grid-template-rows: 1fr auto; }
  .pie-arriba { display: none; }
  .pie-centro { grid-template-columns: 1fr; justify-items: center; align-content: center; }
  .pie-contacto { justify-self: center; }
  .redes { order: 3; }
  .pie-abajo { flex-direction: column; align-items: center; text-align: center; gap: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .revela .linea > span, .pagina, .cabecera, .letras .letra, .servicios li > span, .servicios li::before, .servicios li::after { transition: none; }
  .cargador { display: none; }
  html:not(.lista) .pagina { filter: none; opacity: 1; }
}

/* Entradas suaves al aparecer en pantalla. */
.aparece { opacity: 0; transform: translateY(26px); transition: opacity 1.2s var(--curva), transform 1.2s var(--curva); }
.aparece.visible { opacity: 1; transform: none; }
.aparece-foto { clip-path: inset(14% 0 0 0); transition: clip-path 1.5s var(--curva); }
.aparece-foto img { transform: scale(1.12); transition: transform 1.8s var(--curva); }
.aparece-foto.visible { clip-path: inset(0 0 0 0); }
.aparece-foto.visible img { transform: none; }
.pie-mapa { transition: color .4s var(--curva); }
.pie-mapa:hover { color: var(--tinta); }
@media (prefers-reduced-motion: reduce) {
  .aparece, .aparece-foto, .aparece-foto img { transition: none; opacity: 1; transform: none; clip-path: none; }
}

/* Texto que leen los lectores de pantalla y no se ve (p. ej. «m² construidos»
   junto a un número que ya lleva su ícono). */
.solo-lector { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Con el dedo, los enlaces de texto de 12 px quedaban en 20 px de alto (ES y
   EN en 13 × 20): se amplía el área que recibe el toque con relleno y margen
   negativo, sin mover nada de lugar. */
@media (pointer: coarse) {
  .menu a, .idioma button, .menu-boton, .migas a, .pie-mapa { padding-block: 12px; margin-block: -12px; }
  .idioma button { padding-inline: 8px; margin-inline: -8px; position: relative; }
  .idioma button[aria-pressed="false"] { z-index: 1; }
  .redes a { width: 40px; height: 40px; }
}

/* Flecha junto al nombre de un proyecto que se abre en Instagram o Facebook
   (los que no tienen ficha propia): avisa antes de salir del sitio. */
.externo { color: var(--gris-claro); font-weight: 300; }
