/* Estilos de componentes (se añadirán en fases posteriores) */

/* ---- NAVBAR ---- */
#navbar {
  position: fixed;
  inset-inline: 0;
  top: var(--space-4);
  z-index: var(--z-navbar);
  display: flex;
  justify-content: center;
  padding-inline: var(--container-pad);
  transition: transform var(--transition-base), opacity var(--transition-base);
}

/* La barra del home nace ESCONDIDA sobre la portada y el JS la muestra al
   salir de ella (se desliza hacia arriba). Va condicionada a html.js: sin
   JavaScript la clase queda inerte y la barra se ve siempre. En las demás
   páginas nunca lleva esta clase, así que aparecen con la barra normal. */
html.js #navbar.navbar--oculto {
  transform: translateY(-200%);
  opacity: 0;
  pointer-events: none;
}

/* La barra es siempre muy translúcida: nunca toma un fondo propio.
   Es su contenido (enlaces, logo, hamburguesa) el que cambia de tono
   según el fondo que tenga debajo (ver navbar--tinta más abajo) */
.navbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  max-width: var(--container-max);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-pill);
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow:
    var(--shadow-glass),
    inset 0 1px 1px rgba(255, 255, 255, 0.28);
  transition: padding var(--transition-base), border-color var(--transition-base);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .navbar__inner {
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    backdrop-filter: blur(24px) saturate(170%);
  }
}

.navbar__logo {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 1.35rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #F7F7DF;
}

.navbar__logo-img {
  width: auto;
  height: 28px;
  /* Halo sutil para que el logo blanco no se pierda sobre el gris medio de
     la transición del home (en tinta el filtro se reemplaza por el oscuro) */
  filter: drop-shadow(0 1px 5px rgba(0, 0, 0, 0.45));
  transition: height var(--transition-base), filter var(--transition-base);
}

.navbar__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-6);
}

.navbar__links a {
  font-size: var(--fs-small);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #D4D4D4;
  /* Sombra sutil en modo claro: mantiene legibles los enlaces mientras el
     degradado del hero del home pasa por gris medio bajo la barra. Se anula
     en modo tinta (sobre blanco no debe verse). */
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
  transition: color var(--transition-fast), font-size var(--transition-base);
}

/* Sobre el navbar oscuro el hover aclara a crema (el rojo no contrastaría) */
.navbar__links a:hover,
.navbar__links a:focus-visible {
  color: #F7F7DF;
}

/* Botón hamburguesa (solo visible en móvil) */
.navbar__toggle {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
}

.navbar__toggle-linea {
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #F7F7DF;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

/* Las tres líneas se convierten en una X al abrir el menú */
#navbar.menu-abierto .navbar__toggle-linea:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

#navbar.menu-abierto .navbar__toggle-linea:nth-child(2) {
  opacity: 0;
}

#navbar.menu-abierto .navbar__toggle-linea:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ---- NAVBAR EN MÓVIL: solo logo + hamburguesa; menú desplegable ---- */
@media (max-width: 768px) {
  .navbar__inner {
    flex-wrap: nowrap;
    padding: var(--space-2) var(--space-4);
  }

  .navbar__logo-img {
    height: 24px;
  }

  #navbar.navbar--compacto .navbar__logo-img {
    height: 20px;
  }

  .navbar__toggle {
    display: inline-flex;
  }

  /* El menú se despliega bajo la barra en un panel con EL MISMO vidrio
     translúcido de la barra superior: idéntico degradado, borde y brillo.
     Su contenido cambia de tono con navbar--tinta, igual que la barra.
     (Sin backdrop-filter el vidrio no puede desenfocar lo de atrás, así
     que el respaldo es el panel oscuro sólido de siempre) */
  .navbar__nav {
    position: absolute;
    top: calc(100% + var(--space-2));
    left: var(--container-pad);
    right: var(--container-pad);
    padding: var(--space-2);
    border-radius: var(--radius-lg);
    background: rgba(23, 23, 23, 0.90);
    border: 1px solid rgba(255, 255, 255, 0.22);
    box-shadow:
      var(--shadow-glass),
      inset 0 1px 1px rgba(255, 255, 255, 0.28);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    pointer-events: none;
    transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s;
  }

  @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    /* La receta EXACTA del vidrio de la barra. Para que el desenfoque
       funcione de verdad, main.js saca este panel de .navbar__inner en
       móvil: un backdrop-filter anidado dentro de otro no puede
       desenfocar la página (el navegador limita el muestreo al vidrio
       ancestro, y el panel se veía transparente sin esmerilado) */
    .navbar__nav {
      background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03));
      -webkit-backdrop-filter: blur(24px) saturate(170%);
      backdrop-filter: blur(24px) saturate(170%);
    }
  }

  #navbar.menu-abierto .navbar__nav {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
  }

  .navbar__links {
    flex-direction: column;
    gap: 0;
  }

  .navbar__links a {
    display: block;
    padding: var(--space-3);
    text-align: center;
    font-size: 0.8rem;
  }
}

/* Sobre los tramos claros del recorrido la barra sigue igual de translúcida:
   solo el contenido pasa a gris para leerse (el logo se tiñe con un filtro:
   el PNG es monocromo claro, brightness(0) + invert lo lleva al gris) */
#navbar.navbar--tinta .navbar__inner {
  border-color: rgba(23, 23, 23, 0.10);
  box-shadow:
    0 8px 32px rgba(23, 23, 23, 0.08),
    inset 0 1px 1px rgba(255, 255, 255, 0.35);
}

#navbar.navbar--tinta .navbar__links a {
  color: #565650;
  text-shadow: none; /* sobre blanco no lleva sombra */
}

#navbar.navbar--tinta .navbar__links a:hover,
#navbar.navbar--tinta .navbar__links a:focus-visible {
  color: var(--color-primary);
}

#navbar.navbar--tinta .navbar__logo-img {
  filter: brightness(0) invert(0.34);
}

#navbar.navbar--tinta .navbar__toggle-linea {
  background: #565650;
}

/* En móvil el panel comparte el vidrio de la barra: en modo tinta su
   borde y brillo pasan al tono claro, igual que la barra. Los enlaces
   siguen la misma tinta que la barra SOLO cuando el vidrio de verdad
   desenfoca; sobre el panel oscuro de respaldo se quedan claros */
@media (max-width: 768px) {
  #navbar.navbar--tinta .navbar__links a {
    color: #D4D4D4;
  }

  #navbar.navbar--tinta .navbar__links a:hover,
  #navbar.navbar--tinta .navbar__links a:focus-visible {
    color: #F7F7DF;
  }

  @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    #navbar.navbar--tinta .navbar__nav {
      border-color: rgba(23, 23, 23, 0.10);
      box-shadow:
        0 8px 32px rgba(23, 23, 23, 0.08),
        inset 0 1px 1px rgba(255, 255, 255, 0.35);
    }

    #navbar.navbar--tinta .navbar__links a {
      color: #565650;
    }

    #navbar.navbar--tinta .navbar__links a:hover,
    #navbar.navbar--tinta .navbar__links a:focus-visible {
      color: var(--color-primary);
    }
  }
}

/* ---- SUBMENÚS DESPLEGABLES (Servicios y Proyectos) ----
   El panel comparte el vidrio de la barra principal y aparece justo
   debajo de ella, centrado bajo su enlace, con fundido + deslizamiento */
.navbar__item {
  position: relative;
}

/* Puente invisible que cubre el hueco entre la barra y el panel:
   sin él, el menú se cerraría al cruzar el mouse por ese espacio */
.navbar__item::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 240px;
  height: var(--space-4);
}

.navbar__submenu {
  position: absolute;
  top: calc(100% + var(--space-4));
  left: 50%;
  min-width: 240px;
  padding: var(--space-2);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow:
    var(--shadow-glass),
    inset 0 1px 1px rgba(255, 255, 255, 0.28);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -10px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .navbar__submenu {
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    backdrop-filter: blur(24px) saturate(170%);
  }
}

/* Apertura sin JavaScript (el panel sigue dentro del item): hover/foco */
.navbar__item:hover > .navbar__submenu,
.navbar__item:focus-within > .navbar__submenu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

/* Con JavaScript el panel se saca de la barra (para que su vidrio
   desenfoque de verdad) y main.js gobierna la apertura con esta clase */
.navbar__submenu.es-abierto {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

/* Los enlaces del panel usan el mismo gris de la barra */
.navbar__submenu a {
  display: block;
  padding: var(--space-2) var(--space-4);
  white-space: nowrap;
  text-align: left;
  color: #565650;
  transition: color var(--transition-fast);
}

/* Igual que el menú principal: el hover solo cambia el color de la letra
   (a vino), sin pintar ningún recuadro gris de fondo */
.navbar__submenu a:hover,
.navbar__submenu a:focus-visible {
  color: var(--color-primary);
}

#navbar.navbar--tinta .navbar__submenu {
  border-color: rgba(23, 23, 23, 0.10);
  box-shadow:
    0 8px 32px rgba(23, 23, 23, 0.08),
    inset 0 1px 1px rgba(255, 255, 255, 0.35);
}

/* En móvil no hay hover: el menú hamburguesa muestra solo las secciones */
@media (max-width: 768px) {
  .navbar__item::after,
  .navbar__submenu {
    display: none;
  }
}

/* Al bajar por la página, la barra se compacta (más delgada, letras más pequeñas) */
#navbar.navbar--compacto .navbar__inner {
  padding: var(--space-1) var(--space-4);
}

#navbar.navbar--compacto .navbar__links a {
  font-size: 0.72rem;
}

#navbar.navbar--compacto .navbar__logo-img {
  height: 21px;
}

/* ---- HERO ----
   Blanco, como el resto del sitio (2026-07-19: la portada con el logo y
   el hero oscuro se retiraron a pedido; el modo oscuro con el gradiente
   vivo quedó reservado al CTA del formulario). El título abre la página
   abajo a la izquierda, en tinta */
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: flex-end;
  background-color: var(--color-bg);
  overflow: hidden;
}

.hero__content {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: flex-start;
  padding-bottom: clamp(3rem, 10vh, 6rem);
}

.hero__title {
  font-family: var(--font-hero);
  font-size: var(--fs-hero);
  font-weight: var(--fw-bold);
  color: var(--color-ink);
  text-align: left;
  max-width: 900px;
  text-wrap: balance;
  animation: hero-entrada 0.9s ease 0.2s both;
}

/* Títulos de un solo tono: los acentos heredan el color del titular
   (negro sobre blanco; crema en el CTA oscuro) */
.hero__acento,
.hero__acento--vivo,
.acento-vivo,
.texto-acento {
  color: inherit;
}

@keyframes hero-entrada {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ---- BASE DE SECCIONES ---- */
section[id] {
  scroll-margin-top: 6.5rem; /* evita que el navbar fijo tape los títulos al navegar */
}

.nosotros,
.servicios,
.proyectos,
.contacto {
  position: relative;
  padding-block: var(--espacio-seccion);
  background-color: var(--color-bg);
}

/* Cada sección abre con una línea separadora fina al ancho del
   contenido, al estilo editorial de las referencias del rediseño */
.servicios > .container,
.proyectos > .container,
.nosotros > .container,
.contacto > .container,
.seccion > .container {
  border-top: 1px solid var(--color-border);
  padding-top: clamp(2.5rem, 6vh, 4rem);
}

/* Etiqueta pequeña sobre los títulos de sección: gris discreto,
   como los rótulos laterales de las referencias */
.eyebrow {
  display: block;
  font-size: 0.75rem;
  font-weight: var(--fw-regular);
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
}

.eyebrow--centrado {
  text-align: center;
}

/* Cabecera común de sección, con aire generoso antes del contenido */
.seccion__cabecera {
  max-width: 720px;
  margin-bottom: clamp(3rem, 8vh, 5rem);
}

.seccion__cabecera h2 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-4);
}

.seccion__cabecera p {
  color: var(--color-text-muted);
}

/* ---- SERVICIOS (portafolios) ---- */
.servicios__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--space-5);
}

.servicio {
  position: relative;
  padding: var(--space-6) var(--space-5);
}

/* En tarjetas de método/servicio, el ícono se ubica en la esquina superior derecha */
.servicio .icono-caja {
  position: absolute;
  top: var(--space-5);
  right: var(--space-5);
  margin-bottom: 0;
}

.servicio__numero {
  display: block;
  font-family: var(--font-hero);
  font-size: 1.75rem;
  color: var(--color-primary);
  margin-bottom: var(--space-3);
}

.servicio__titulo {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-3);
}

.servicio__texto {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  line-height: var(--lh-base);
}

/* El antiguo "liquid glass" cede su lugar a un marco de línea delgada
   gris apenas notoria sobre blanco: sin desenfoque, sin sombras, sin
   esquinas redondeadas (rediseño minimalista) */
.glass-card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 0;
  transition: border-color var(--transition-base);
}

.glass-card:hover {
  border-color: rgba(23, 23, 23, 0.30);
}

/* Aparición suave al hacer scroll (solo si hay JavaScript disponible) */
html.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

html.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* Imágenes provisionales (se reemplazarán por fotos reales):
   bloques grises neutros, como la imaginería en escala de grises
   de las referencias del rediseño */
.placeholder {
  width: 100%;
  border-radius: 0;
}

.placeholder--retrato {
  aspect-ratio: 4 / 5;
  background: linear-gradient(160deg, #F0F0EE 0%, #D9D9D6 100%);
}

.placeholder--espacio {
  aspect-ratio: 4 / 3;
  background: linear-gradient(200deg, #EDEDEA 0%, #CFCFCB 100%);
}

.placeholder--residencial {
  aspect-ratio: 16 / 10;
  background: linear-gradient(145deg, #EFEFED 0%, #D4D4D0 100%);
}

.placeholder--comercial {
  aspect-ratio: 16 / 10;
  background: linear-gradient(215deg, #F1F1EF 0%, #CBCBC7 100%);
}

.placeholder__nota {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

/* ---- NOSOTROS ---- */
.nosotros__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6);
  align-items: center;
}

.nosotros__galeria {
  display: grid;
  gap: var(--space-4);
}

.nosotros__card {
  overflow: hidden;
}

.nosotros__texto {
  padding: clamp(var(--space-5), 4vw, var(--space-7));
}

.nosotros__texto h2 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-4);
  color: var(--color-ink);
}

.nosotros__texto p {
  color: var(--color-text-muted);
}

.nosotros__texto p + p {
  margin-top: var(--space-3);
}

@media (max-width: 860px) {
  .nosotros__grid {
    grid-template-columns: 1fr;
  }
}

/* Convicciones y cierre, debajo de la presentación. Reutilizan el patrón
   de tarjetas .servicios__grid para no alargar la sección en un muro de texto */
.nosotros__convicciones {
  margin-top: clamp(3rem, 8vh, 5rem);
}

.nosotros__lema {
  margin-bottom: var(--space-5);
  color: var(--color-text-muted);
}

.nosotros__cierre {
  margin-top: clamp(3rem, 8vh, 5rem);
  max-width: 64ch;
  color: var(--color-text-muted);
}

.nosotros__cierre p + p {
  margin-top: var(--space-4);
}

/* ---- PROYECTOS ---- */
/* Filtros como fila de texto plano: el activo se subraya en tinta
   (anula el marco que .glass-card le pondría al contenedor) */
.filtros {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  padding: 0;
  border: none;
  background: transparent;
  margin-bottom: var(--space-6);
}

.filtro {
  padding: var(--space-1) 0;
  border: none;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: var(--transition-fast);
}

.filtro:hover {
  color: var(--color-ink);
}

.filtro.is-active {
  background: transparent;
  color: var(--color-ink);
  border-bottom-color: var(--color-ink);
}

/* Carrusel: las tarjetas viajan en horizontal para acortar el scroll
   vertical. En escritorio se ven 4 por pantalla, en móvil 1 (con gesto
   de arrastre además de las flechas). El botón "Ver todos los proyectos"
   despliega la cuadrícula completa (modo expandido, más abajo) */
.carrusel {
  position: relative;
}

.proyectos__grid {
  --carrusel-vista: 2; /* piezas visibles por pantalla: la imagen manda */
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none; /* el desplazamiento vive en las flechas y el gesto */
  padding-block: var(--space-2); /* aire para la sombra de las tarjetas */
}

.proyectos__grid::-webkit-scrollbar {
  display: none;
}

@media (max-width: 860px) {
  .proyectos__grid {
    --carrusel-vista: 1;
  }
}

.carrusel__flecha {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  cursor: pointer;
  transition: opacity var(--transition-fast), border-color var(--transition-fast);
}

.carrusel__flecha--prev {
  left: calc(-1 * var(--space-2));
}

.carrusel__flecha--next {
  right: calc(-1 * var(--space-2));
}

.carrusel__flecha:hover:not(:disabled),
.carrusel__flecha:focus-visible:not(:disabled) {
  border-color: rgba(23, 23, 23, 0.40);
}

.carrusel__flecha:disabled {
  opacity: 0;
  pointer-events: none;
}

.carrusel__flecha svg {
  width: 20px;
  height: 20px;
}

.proyectos__acciones {
  display: flex;
  justify-content: center;
  margin-top: var(--space-5);
}

.proyectos__desplegar {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: 0;
  background: var(--color-bg);
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: var(--transition-fast);
}

.proyectos__desplegar:hover,
.proyectos__desplegar:focus-visible {
  color: var(--color-ink);
  border-color: rgba(23, 23, 23, 0.40);
}

.proyectos__desplegar svg {
  width: 16px;
  height: 16px;
  transition: transform var(--transition-base);
}

/* Modo expandido: la pista deja de desplazarse y se envuelve como cuadrícula */
.proyectos__galeria--expandida .proyectos__grid {
  flex-wrap: wrap;
  overflow: visible;
  scroll-snap-type: none;
}

.proyectos__galeria--expandida .carrusel__flecha {
  display: none;
}

.proyectos__galeria--expandida .proyectos__desplegar svg {
  transform: rotate(180deg);
}

/* Cada proyecto ES su imagen: la foto ocupa toda la pieza y el texto se
   superpone en el borde inferior izquierdo, sobre un velo degradado que
   garantiza la lectura sobre cualquier fotografía. En reposo el título va
   pequeño para no tapar la imagen; al pasar el mouse crece y aparece la
   descripción. */
.proyecto {
  position: relative;
  flex: 0 0 calc((100% - (var(--carrusel-vista) - 1) * var(--space-4)) / var(--carrusel-vista));
  aspect-ratio: 4 / 3;
  scroll-snap-align: start;
  overflow: hidden;
  background-color: #E4E4E1; /* color de espera mientras carga la foto */
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.proyecto[hidden] {
  display: none;
}

.proyecto--oculto {
  opacity: 0;
  transform: scale(0.96);
}

/* La imagen llena la pieza. aspect-ratio:auto anula la proporción propia
   del placeholder; object-fit sirve cuando se reemplacen por <img> reales */
.proyecto__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  object-fit: cover;
  border-radius: 0;
  transition: transform 0.6s ease;
}

/* Velo que sube desde abajo: sombra sobre la que se apoya el texto */
.proyecto::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.92;
  background: linear-gradient(to top,
    rgba(10, 10, 10, 0.80) 0%,
    rgba(10, 10, 10, 0.40) 30%,
    rgba(10, 10, 10, 0) 62%);
  transition: opacity var(--transition-base);
  pointer-events: none;
}

/* Rejilla de 3 filas (categoría · título · descripción). La última fila se
   colapsa a 0fr cuando la descripción está oculta: así no ocupa espacio y
   todos los títulos quedan alineados a la misma altura entre piezas,
   independientemente de lo largo que sea cada descripción. */
.proyecto__info {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-rows: auto auto 1fr;
  padding: var(--space-4);
  text-align: left;
  color: #FFFFFF;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.6);
  transition: grid-template-rows var(--transition-base);
}

.proyecto__categoria {
  display: inline-block;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
  font-weight: var(--fw-regular);
  margin-bottom: var(--space-2);
}

/* Tamaño de partida (y definitivo en pantallas táctiles, donde no hay hover) */
.proyecto__nombre {
  font-size: 1.35rem;
  line-height: 1.2;
  color: #FFFFFF;
  margin-bottom: 0;
  transition: font-size var(--transition-base);
}

/* El espacio sobre la descripción va como padding (no margin) para que se
   recorte junto con ella cuando la fila se colapsa a 0fr */
.proyecto__meta {
  overflow: hidden;
  min-height: 0;
  padding-top: var(--space-2);
  font-size: var(--fs-small);
  color: rgba(255, 255, 255, 0.88);
  transition: opacity 0.3s ease, padding-top var(--transition-base);
}

/* En pantallas con cursor: título pequeñito en reposo; al pasar el mouse
   la imagen se acerca, el velo se intensifica, el título crece y se
   revela la descripción */
@media (hover: hover) {
  .proyecto__nombre {
    font-size: 1rem;
  }

  /* En reposo la fila de la descripción mide 0: los títulos se alinean */
  .proyecto__info {
    grid-template-rows: auto auto 0fr;
  }

  .proyecto__meta {
    opacity: 0;
    padding-top: 0; /* el padding no lo recorta la fila: se anula aparte */
  }

  .proyecto:hover .proyecto__info,
  .proyecto:focus-within .proyecto__info {
    grid-template-rows: auto auto 1fr;
  }

  .proyecto:hover .proyecto__img,
  .proyecto:focus-within .proyecto__img {
    transform: scale(1.06);
  }

  .proyecto:hover::after,
  .proyecto:focus-within::after {
    opacity: 1;
  }

  .proyecto:hover .proyecto__nombre,
  .proyecto:focus-within .proyecto__nombre {
    font-size: 1.65rem;
  }

  .proyecto:hover .proyecto__meta,
  .proyecto:focus-within .proyecto__meta {
    opacity: 1;
    padding-top: var(--space-2);
  }
}

@media (prefers-reduced-motion: reduce) {
  .proyecto__img,
  .proyecto__nombre,
  .proyecto__meta,
  .proyecto::after {
    transition: none;
  }
}

/* ---- CTA DEL FORMULARIO: DONDE ARRANCA LA ZONA OSCURA ----
   (2026-07-19) El modo oscuro con el gradiente vivo quedó reservado a
   los CTA de contacto: la sección de contacto del index y la sección
   .seccion--cta de los portafolios. Ambas llevan data-shader-host (ahí
   monta shader-bg.js el fondo dinámico); este degradado es el respaldo
   sin WebGL. El texto pasa a claro y los marcos a línea blanca tenue.
   Desde el 2026-07-21 la zona oscura no termina aquí: el mismo fondo
   dinámico sigue por detrás del footer hasta el final (ver .footer) */
.contacto,
.seccion.seccion--cta {
  background-color: #121212;
  background-image:
    radial-gradient(ellipse 900px 650px at 15% 10%, rgba(71, 22, 14, 0.55), transparent 60%),
    radial-gradient(ellipse 750px 700px at 85% 85%, rgba(86, 105, 81, 0.30), transparent 65%),
    radial-gradient(ellipse 800px 600px at 80% 15%, rgba(212, 212, 212, 0.10), transparent 60%);
  overflow: hidden;
}

/* Con el fondo dinámico montado, el CTA suelta el recorte: su caja de
   shader se estira por debajo del footer (ver .fondo-shader) y no debe
   quedar cortada en el borde de la sección. El recorte lo hace ahora la
   propia caja del fondo */
html.shader-activo .contacto,
html.shader-activo .seccion.seccion--cta {
  overflow: visible;
}

.contacto > .container,
.seccion--cta > .container {
  position: relative; /* por encima del fondo dinámico */
  z-index: 1;
  border-top-color: rgba(255, 255, 255, 0.16);
}

.contacto .eyebrow,
.seccion--cta .eyebrow {
  color: #D4D4D4;
}

.contacto .glass-card,
.seccion--cta .glass-card {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.20);
}

.seccion--cta .destacado h3 {
  color: #F7F7DF;
}

.seccion--cta .destacado p {
  color: #D4D4D4;
}

/* Formulario sobre el fondo oscuro: letras claras */
.contacto .form__campo label,
.seccion--cta .form__campo label {
  color: #D4D4D4;
}

.contacto .form__campo input,
.contacto .form__campo textarea,
.seccion--cta .form__campo input,
.seccion--cta .form__campo textarea {
  color: #F7F7DF;
  border-bottom-color: rgba(247, 247, 223, 0.30);
}

.contacto .form__campo input:focus,
.contacto .form__campo textarea:focus,
.seccion--cta .form__campo input:focus,
.seccion--cta .form__campo textarea:focus {
  border-bottom-color: #F7F7DF;
  background-color: rgba(247, 247, 223, 0.06);
}

.contacto .form__gracias,
.seccion--cta .form__gracias,
.seccion--cta .destacado .form__gracias {
  color: #F7F7DF;
}

.contacto .form__error,
.seccion--cta .form__error {
  color: #D4D4D4;
}

.contacto .form__error a,
.seccion--cta .form__error a {
  color: #F7F7DF;
}

.contacto__cabecera {
  text-align: center;
  margin-bottom: clamp(3rem, 8vh, 5rem);
}

/* La frase es la única voz de la sección, en claro sobre la noche */
.contacto__frase {
  font-family: var(--font-hero);
  font-size: var(--fs-h1);
  color: #F7F7DF;
  text-wrap: balance;
}

.contacto__inner {
  display: flex;
  justify-content: center;
}

.contacto__panel {
  width: 100%;
  max-width: 640px;
  padding: clamp(var(--space-5), 5vw, var(--space-7));
}

.form {
  display: grid;
  gap: var(--space-5);
}

/* Tras enviarse, el formulario se oculta y queda solo el agradecimiento
   (sin esta regla, el display de arriba anularía el atributo hidden) */
.form[hidden] {
  display: none;
}

.form__campo {
  display: grid;
  gap: var(--space-2);
}

.form__campo label {
  font-size: var(--fs-small);
  font-weight: var(--fw-bold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.form__campo input,
.form__campo textarea {
  width: 100%;
  padding: var(--space-2) var(--space-1);
  border: none;
  border-bottom: 1px solid var(--color-border);
  background: transparent;
  color: var(--color-ink);
  transition: border-color var(--transition-base), background-color var(--transition-base);
  resize: vertical;
}

.form__campo input:focus,
.form__campo textarea:focus {
  outline: none;
  border-bottom-color: var(--color-primary);
  background-color: rgba(71, 22, 14, 0.05);
}

/* Botón primario: rojo vino del sistema de diseño con un volumen
   sutil de botón físico — luz arriba, sombra corta abajo — sin brillos.
   Al pasar el mouse se levanta apenas; al presionar, se asienta */
.btn--primario {
  background-color: var(--color-primary);
  background-image: linear-gradient(180deg,
    rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 45%, rgba(0, 0, 0, 0.16));
  color: #FFFFFF;
  justify-self: center;
  min-width: 220px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -2px 0 rgba(0, 0, 0, 0.20),
    0 2px 4px rgba(23, 23, 23, 0.18),
    0 8px 18px rgba(71, 22, 14, 0.22);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
              background-color var(--transition-fast);
}

.btn--primario:hover,
.btn--primario:focus-visible {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.26),
    inset 0 -2px 0 rgba(0, 0, 0, 0.20),
    0 4px 8px rgba(23, 23, 23, 0.20),
    0 12px 24px rgba(71, 22, 14, 0.26);
}

.btn--primario:active {
  transform: translateY(0);
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.25),
    0 1px 2px rgba(23, 23, 23, 0.18);
}

/* Confirmación y aviso de error del envío: tipografía oscura por defecto
   (fondos claros); dentro de la sección oscura de contacto pasan a claro */
.form__gracias {
  text-align: center;
  color: var(--color-primary);
  font-weight: var(--fw-bold);
}

/* Dentro del CTA (destacado) la regla ".destacado p" no debe apagarlo */
.destacado .form__gracias {
  color: var(--color-primary);
}

/* Aviso si el servicio de envío falla: ofrece el correo directo */
.form__error {
  margin-top: var(--space-4);
  text-align: center;
  font-size: var(--fs-small);
  color: var(--color-text-muted);
}

.form__error a {
  color: var(--color-primary);
  font-weight: var(--fw-bold);
  text-decoration: underline;
}

/* ---- PÁGINAS DE PORTAFOLIO (ej. Acabados VIS) ---- */

/* Hero simple de portafolios de diseño (arquitectónico / interior):
   una sola pantalla y título contenido, como el de la escena VIS */
.hero--portafolio .hero__title {
  font-size: clamp(1.5rem, 2.4vw, 2.3rem);
}

.hero--portafolio .hero__bajada {
  font-size: var(--fs-small);
  max-width: 440px;
}


/* Hero de páginas interiores con recorrido largo de scroll:
   el contenido queda fijo (sticky) mientras las axonometrías se arman */
.hero--sub {
  display: block;
  /* El anclaje (sticky) dura exactamente hasta que termina la transición
     de color: después el contenido se suelta y sube con el scroll normal.
     overflow visible es OBLIGATORIO: el overflow:hidden heredado de .hero
     rompe position:sticky (el recorte lo hace .hero__pegajoso) */
  overflow: visible;
  min-height: 190vh;
}

.hero__pegajoso {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

.hero--sub .hero__content {
  padding-bottom: clamp(2.5rem, 8vh, 5rem);
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: var(--space-5);
  align-items: end; /* título y texto anclados abajo a la izquierda */
}

/* En páginas de portafolio el título cede el protagonismo a las axonometrías:
   más pequeño, contenido, en la esquina inferior izquierda */
.hero--sub .hero__title {
  font-size: clamp(1.5rem, 2.4vw, 2.3rem);
}

.hero--sub .hero__bajada {
  font-size: var(--fs-small);
  max-width: 440px;
  margin-top: var(--space-3);
}

.hero__isos {
  align-self: center; /* las axonometrías quedan centradas verticalmente */
}

/* Partes del título que se revelan por separado al scrollear (una por línea) */
.hero__parte {
  display: block;
}

/* ---- ESCENA VIS (2026-07-19: simplificada a flujo normal) ----
   Sin anclajes ni columnas fijas: primero el título, después la pila de
   axonometrías —cada pieza se "recolecta" con el avance del scroll
   (main.js pinta opacidad y encaje directo desde la posición)— y luego
   los bloques de contenido. Todo sobre blanco */
.escena-vis {
  position: relative;
  background-color: var(--color-bg);
}

/* Estado inicial de las piezas: invisibles solo si hay JavaScript
   (main.js las va encajando con el scroll); sin él, se ven completas */
html.js .escena-vis .hero__iso {
  opacity: 0;
  will-change: opacity, transform;
}

/* Intro: un bloque normal que abre la página bajo el navbar */
.vis-intro {
  padding-top: clamp(7rem, 18vh, 10rem);
  padding-bottom: var(--space-6);
}

/* Bloques de contenido a media pantalla (Método, Tranquilidad, Proceso).
   En escritorio cada bloque ocupa exactamente una pantalla: el contenido
   se centra verticalmente y las tarjetas usan la versión compacta de abajo */
.vis-bloque {
  padding-block: var(--space-6);
  /* Línea separadora fina entre bloques, como en el resto del sitio */
  border-top: 1px solid var(--color-border);
}

@media (min-width: 861px) {
  .vis-bloque {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* El padding superior reserva la franja del navbar fijo para que el
       eyebrow no quede debajo de él en pantallas de poca altura */
    padding-top: 5.5rem;
    padding-bottom: var(--space-4);
  }
}

.escena-vis .hero__title {
  font-size: clamp(1.5rem, 2.4vw, 2.3rem);
}

.escena-vis .hero__bajada {
  font-size: var(--fs-small);
  max-width: 440px;
  margin-top: var(--space-3);
}

/* Recuadros adaptados al ancho de media pantalla, en versión ultra-compacta
   (la mitad de alto): filas delgadas y tipografía contenida para que cada
   bloque completo quepa en una sola pantalla incluso en portátiles bajos */
.escena-vis__flujo .seccion__cabecera {
  margin-bottom: var(--space-3);
}

.escena-vis__flujo .seccion__cabecera h2 {
  font-size: clamp(1.2rem, 1.7vw, 1.5rem);
  margin-bottom: var(--space-2);
}

.escena-vis__flujo .seccion__cabecera p {
  font-size: 0.85rem;
}

.escena-vis__flujo .servicios__grid {
  grid-template-columns: 1fr;
  gap: var(--space-2);
}

/* Tarjetas de método como filas: número | título y texto | ícono */
.escena-vis__flujo .servicio {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "numero titulo icono"
    "numero texto  icono";
  column-gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-3);
}

.escena-vis__flujo .servicio__numero {
  grid-area: numero;
  font-size: 1rem;
  min-width: 1.6rem;
  margin-bottom: 0;
}

.escena-vis__flujo .servicio__titulo {
  grid-area: titulo;
  font-size: 0.95rem;
  margin-bottom: 1px;
  align-self: end;
}

.escena-vis__flujo .servicio__texto {
  grid-area: texto;
  font-size: 0.8rem;
  align-self: start;
}

.escena-vis__flujo .servicio .icono-caja {
  grid-area: icono;
  position: static;
  width: 30px;
  height: 30px;
  margin-bottom: 0;
}

.escena-vis__flujo .servicio .icono-caja svg {
  width: 16px;
  height: 16px;
}

/* Dudas en una sola fila: pregunta | respuesta */
.escena-vis__flujo .dudas {
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.escena-vis__flujo .duda {
  grid-template-columns: 1fr 1.2fr;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-3);
}

.escena-vis__flujo .duda__pregunta {
  font-size: 0.8rem;
  border-right: 1px solid var(--color-border);
  border-bottom: none;
  padding-right: var(--space-3);
  padding-bottom: 0;
}

.escena-vis__flujo .duda__icono {
  width: 30px;
  height: 30px;
}

.escena-vis__flujo .duda__icono svg {
  width: 16px;
  height: 16px;
}

.escena-vis__flujo .duda__respuesta {
  font-size: 0.8rem;
}

/* En pantallas angostas la duda vuelve a apilarse */
@media (max-width: 720px) {
  .escena-vis__flujo .duda {
    grid-template-columns: 1fr;
    gap: var(--space-2) var(--space-3);
  }

  .escena-vis__flujo .duda__pregunta {
    grid-column: 1 / -1;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    padding-right: 0;
    padding-bottom: var(--space-2);
  }
}

/* Fases condensadas: número | ícono | título y texto corridos en una línea */
.escena-vis__flujo .fases {
  gap: var(--space-2);
}

.escena-vis__flujo .fase {
  padding: var(--space-2) var(--space-3);
  gap: var(--space-2);
}

.escena-vis__flujo .fase__numero {
  font-size: 0.95rem;
  min-width: 1.6rem;
}

.escena-vis__flujo .fase__icono {
  width: 28px;
  height: 28px;
}

.escena-vis__flujo .fase__icono svg {
  width: 15px;
  height: 15px;
}

.escena-vis__flujo .fase__titulo {
  display: inline;
  font-size: 0.85rem;
  margin: 0;
}

.escena-vis__flujo .fase__titulo::after {
  content: ".";
}

.escena-vis__flujo .fase__texto {
  display: inline;
  font-size: 0.8rem;
}

/* Las imágenes que viven dentro del flujo mantienen una altura contenida
   y el antes/después va lado a lado, para no romper "un bloque = una pantalla" */
.escena-vis__flujo .media-opcional img {
  max-height: 20vh;
  width: 100%;
  object-fit: cover;
}

.escena-vis__flujo .medios-grid {
  grid-template-columns: 1fr 1fr;
}

/* La pila de axonometrías: un bloque normal en el flujo. Cada pieza la
   pinta main.js según el avance del scroll (se recolectan de abajo
   hacia arriba: planta → obra blanca → carpinterías) */
.hero__isos {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-block: var(--space-6);
}

.hero__iso {
  max-height: 38vh;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

/* Las piezas se solapan como en una axonometría explotada real:
   las esquinas transparentes de los isométricos lo permiten sin chocar */
.hero__iso + .hero__iso {
  margin-top: -8vh;
}

@media (max-width: 860px) {
  .hero__iso {
    max-height: 24vh;
  }

  .hero__iso + .hero__iso {
    margin-top: -5vh;
  }
}

/* Los heroes ahora son blancos: el eyebrow "claro" vuelve al gris
   normal y la bajada usa el texto secundario del sistema */
.eyebrow--claro {
  color: var(--color-text-muted);
}

.hero__bajada {
  color: var(--color-text-muted);
  max-width: 560px;
  margin-top: var(--space-5);
}

/* Sección genérica de página interior */
.seccion {
  position: relative;
  padding-block: var(--espacio-seccion);
  background-color: var(--color-bg);
}

/* Iconografía decorativa fuera: en el rediseño minimalista los íconos
   solo se conservan donde son estrictamente funcionales (flechas del
   carrusel, redes del footer, WhatsApp). Las cajitas ilustrativas de
   método, dudas y fases desaparecen sin tocar el HTML */
.icono-caja {
  display: none;
}

/* Dudas frecuentes: pregunta del cliente → respuesta de Aviva */
.dudas {
  display: grid;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.duda {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: var(--space-5);
  align-items: center;
  padding: var(--space-5);
}

.duda__icono {
  margin-bottom: 0;
}

.duda__pregunta {
  font-style: italic;
  color: var(--color-text-muted);
  border-right: 1px solid var(--color-border);
  padding-right: var(--space-4);
}

.duda__respuesta {
  color: var(--color-ink);
  font-size: var(--fs-small);
}

@media (max-width: 720px) {
  .duda {
    grid-template-columns: 1fr;
  }

  .duda__pregunta {
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    padding-right: 0;
    padding-bottom: var(--space-3);
  }

  .duda__icono {
    justify-self: start;
  }
}

/* Bloques de imagen opcionales: se ocultan solos si el archivo aún no existe */
.media-opcional {
  overflow: hidden;
  margin-top: var(--space-5);
  padding: var(--space-3);
}

.media-opcional img {
  width: 100%;
  border-radius: 0;
}

.media-etiqueta {
  font-size: 0.75rem;
  font-weight: var(--fw-bold);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: var(--space-1) var(--space-2) var(--space-2);
}

.media-nota {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  padding: var(--space-2);
}

.medios-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--space-4);
}

.medios-grid .media-opcional {
  margin-top: var(--space-4);
}

/* Las seis fases */
.fases {
  display: grid;
  gap: var(--space-4);
  counter-reset: fase;
}

.fase {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-4) var(--space-5);
}

.fase__icono {
  margin-bottom: 0;
}

.fase__numero {
  font-family: var(--font-hero);
  font-size: 1.5rem;
  color: var(--color-primary);
  line-height: 1;
  min-width: 2.5rem;
}

.fase__titulo {
  font-size: 1.1rem;
  margin-bottom: var(--space-1);
}

.fase__texto {
  color: var(--color-text-muted);
  font-size: var(--fs-small);
}

/* Modalidades de contratación. Los documentos de presupuesto van "montados"
   sobre la tarjeta: sobresalen por el canto superior (como en el portafolio
   impreso), así que la rejilla reserva ese espacio arriba y entre filas.
   Documentos y tarjetas van en versión contenida para que la sección
   completa quepa en una pantalla */
.modalidades {
  --doc-saliente: 5.5rem; /* cuánto asoma el documento por encima de la tarjeta */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: calc(var(--doc-saliente) + var(--space-4)) var(--space-5);
  padding-top: var(--doc-saliente);
  margin-bottom: var(--space-5);
}

.modalidad {
  padding: var(--space-4);
  overflow: visible;
}

.modalidad__titulo {
  font-size: var(--fs-h3);
  margin-bottom: var(--space-3);
}

.modalidad__lista {
  display: grid;
  gap: var(--space-2);
}

.modalidad__lista li {
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding-block: var(--space-2);
}

/* Cada renglón se separa con la misma línea fina del sistema;
   los íconos de chulito eran decorativos y salen del rediseño */
.modalidad__lista li + li {
  border-top: 1px solid var(--color-border);
}

.modalidad__lista li > svg {
  display: none;
}

.modalidad__lista strong {
  color: var(--color-ink);
}

.modalidad__doc {
  /* El PNG trae márgenes transparentes con la sombra ya horneada (~19% por
     lado), por eso el ancho se ve algo mayor de lo que ocupa el papel */
  width: min(60%, 230px);
  /* Sube el documento por encima del borde superior de la tarjeta:
     el saliente + el padding propio de la tarjeta */
  margin: calc(-1 * (var(--doc-saliente) + var(--space-4))) auto var(--space-2);
  padding: 0;
  border: none;
  box-shadow: none;
  background: none;
  overflow: visible;
}

.modalidad__doc img {
  display: block;
  width: 100%;
  border-radius: 0;
  box-shadow: none;
}

/* En pantallas angostas el documento asoma un poco menos */
@media (max-width: 720px) {
  .modalidades {
    --doc-saliente: 4.5rem;
  }
}

/* Bloque destacado (frases fuertes y CTA) */
.destacado {
  padding: clamp(var(--space-4), 3.5vw, var(--space-6));
  text-align: center;
}

.destacado h3 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-3);
}

.destacado p {
  color: var(--color-text-muted);
  max-width: 640px;
  margin-inline: auto;
}

.destacado__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* Botón de WhatsApp: verde con el mismo volumen sutil del primario */
.btn--whatsapp {
  background-color: #25D366;
  background-image: linear-gradient(180deg,
    rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 45%, rgba(0, 0, 0, 0.14));
  color: #fff;
  border-radius: var(--radius-pill);   /* redondeado, igual que el menú y "Escríbenos" */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.30),
    inset 0 -2px 0 rgba(0, 0, 0, 0.18),
    0 2px 4px rgba(23, 23, 23, 0.16),
    0 8px 18px rgba(37, 211, 102, 0.24);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.btn--whatsapp:hover,
.btn--whatsapp:focus-visible {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -2px 0 rgba(0, 0, 0, 0.18),
    0 4px 8px rgba(23, 23, 23, 0.18),
    0 12px 24px rgba(37, 211, 102, 0.28);
}

.btn--whatsapp:active {
  transform: translateY(0);
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.22),
    0 1px 2px rgba(23, 23, 23, 0.16);
}

/* ---- Botón de vidrio esmerilado con interior retroiluminado (2026-07-21) ----
   Vive SOBRE el fondo texturizado del CTA oscuro (data-shader-host): el
   glassmorphism necesita textura detrás para leerse (sobre un plano no se
   nota). La superficie de vidrio es la capa ::before, con backdrop-filter;
   los destellos cálidos que siembra js/aviva-buttons.js van DETRÁS del
   vidrio (z-index:-1 en el contexto aislado del botón), así la luz naranja
   "atraviesa" el esmerilado. El texto va encima, en .btn__label. */
.btn--vidrio {
  position: relative;
  isolation: isolate;         /* contexto propio: el destello vive en z-index:-1 */
  overflow: hidden;
  min-width: 220px;
  justify-self: center;       /* centra el "Enviar mensaje" dentro del formulario (grid) */
  border-radius: var(--radius-pill);  /* redondeado, como el menú */
  color: #FFF3E9;             /* texto claro cálido, legible sobre el vidrio */
  background: transparent;    /* el "vidrio" lo pinta ::before */
  /* Halo naranja permanente: el botón "alumbra" (como el verde del WhatsApp) */
  box-shadow:
    0 8px 20px rgba(232, 133, 60, 0.34),
    0 2px 6px rgba(0, 0, 0, 0.28);
  transition: box-shadow 0.3s ease, transform var(--transition-fast);
}

/* Superficie de vidrio con la MISMA estética del menú (navbar__inner):
   translúcida y esmerilada. Detrás va el destello naranja; encima, el texto. */
.btn--vidrio::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.04));
  border: 1px solid rgba(255, 255, 255, 0.24);
  -webkit-backdrop-filter: blur(24px) saturate(170%);
  backdrop-filter: blur(24px) saturate(170%);
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.30);
  transition: background 0.3s ease, border-color 0.3s ease;
  pointer-events: none;
}

.btn--vidrio:hover,
.btn--vidrio:focus-visible {
  transform: translateY(-1px);
  box-shadow:
    0 12px 30px rgba(232, 133, 60, 0.52),   /* alumbra más al pasar el mouse */
    0 3px 8px rgba(0, 0, 0, 0.32);
}

.btn--vidrio:hover::before,
.btn--vidrio:focus-visible::before {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.20), rgba(255, 255, 255, 0.06));
  border-color: rgba(255, 224, 200, 0.45);
}

.btn--vidrio:active {
  transform: translateY(0);
}

/* Destello: círculo cálido borroso DETRÁS del vidrio (z-index:-1). El JS lo
   coloca en la posición del cursor; se enciende y se apaga. Ya viene
   suave (blur propio), así que se lee como luz difusa aunque el
   backdrop-filter no lo reprocese. */
.btn__glow {
  position: absolute;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 999px;
  transform: translate(-50%, -50%);
  filter: blur(16px);
  pointer-events: none;
  z-index: -1;                /* detrás de la superficie de vidrio (::before) */
  opacity: 0;
  transition: opacity 0.3s ease;
}
.btn__glow.is-in  { opacity: 0.85; }
.btn__glow.is-out { opacity: 0; transition-duration: 1.2s; }

/* El texto por encima del vidrio y del destello */
.btn__label {
  position: relative;
  z-index: 1;
}

/* Con "reducir movimiento" no hay destellos (respaldo; el JS tampoco los crea) */
@media (prefers-reduced-motion: reduce) {
  .btn__glow { display: none; }
}

/* Formulario que se despliega dentro del CTA al presionar "Escríbenos".
   Vive sobre el tramo claro del recorrido, así que usa la tipografía
   oscura por defecto del formulario (la variante de letras claras
   solo aplica dentro de la sección oscura .contacto del index) */
.cta-formulario {
  max-width: 560px;
  margin: var(--space-6) auto 0;
  text-align: left;
  animation: cta-form-entra 0.45s ease;
}

@keyframes cta-form-entra {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cta-formulario {
    animation: none;
  }
}

/* Planes: Esencial / Comfort / Premium */
.planes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--space-5);
}

.plan {
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
}

/* El nombre del paquete queda ANCLADO en pantalla mientras se recorre
   su lista: una pastilla redondeada con el mismo vidrio de la barra
   superior (degradado translúcido, borde tinta y desenfoque), que se
   despega y viaja bajo la barra fija hasta que su tarjeta termina */
.plan__nombre {
  position: sticky;
  top: 5.5rem; /* justo debajo de la barra de navegación fija */
  z-index: 2;
  align-self: flex-start;
  font-size: var(--fs-small);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.25));
  border: 1px solid rgba(23, 23, 23, 0.10);
  box-shadow:
    0 8px 32px rgba(23, 23, 23, 0.08),
    inset 0 1px 1px rgba(255, 255, 255, 0.35);
  margin-bottom: var(--space-4);
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .plan__nombre {
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03));
    -webkit-backdrop-filter: blur(24px) saturate(170%);
    backdrop-filter: blur(24px) saturate(170%);
  }
}

/* La lista de características es una <table> semántica (categoría → valor):
   así buscadores e IA la leen como una ficha clave-valor real. Conserva
   EXACTAMENTE el aspecto anterior reutilizando el mismo modelo de caja
   —la tabla actúa como grid y cada fila como flex—. Los roles ARIA del
   HTML restituyen la semántica de tabla que el cambio de display quitaría
   a los lectores de pantalla. */
.plan__lista {
  display: grid;
  gap: var(--space-1);
  flex-grow: 1;
  width: 100%;
}

.plan__lista tbody {
  display: contents;
}

/* Cada renglón en una sola línea (categoría | valor) para que las tres
   tarjetas completas quepan en una pantalla sin scrollear */
.plan__lista tr {
  font-size: var(--fs-small);
  color: var(--color-ink);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--color-border);
}

.plan__cat {
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: var(--fw-regular); /* neutraliza el negrita por defecto de <th> */
  text-align: left;               /* neutraliza el centrado por defecto de <th> */
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Chulito verde para lo incluido, equis roja para lo que no */
.plan__valor {
  position: relative;
  margin-left: auto;
  text-align: right;
  padding-left: 1.4rem;
}

.plan__valor::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: #566951;
  font-weight: var(--fw-bold);
}

.plan__no {
  opacity: 0.55;
}

.plan__no .plan__valor {
  font-style: italic;
}

.plan__no .plan__valor::before {
  content: "✕";
  color: #47160E;
}

.plan__precio {
  margin-top: var(--space-3);
  font-family: var(--font-hero);
  font-size: 1.5rem;
  color: var(--color-ink);
}

.plan__precio small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: var(--fw-regular);
  color: var(--color-text-muted);
}

.planes__nota {
  margin-top: var(--space-3);
  font-size: var(--fs-small);
  color: var(--color-text-muted);
  text-align: center;
}

/* Enlace desde la tarjeta de servicio hacia su portafolio: etiqueta
   subrayada al estilo editorial de las referencias */
.servicio__enlace {
  display: inline-block;
  margin-top: var(--space-5);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-ink);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--color-ink);
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.servicio__enlace:hover,
.servicio__enlace:focus-visible {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}

/* ---- FONDO DINÁMICO (shader WebGL, ver js/shader-bg.js) ----
   Vive DENTRO del CTA del formulario de cada página (el elemento con
   data-shader-host, donde arranca la zona oscura): llena su caja y
   se va con ella al scrollear. Carga él mismo el degradado oscuro de
   respaldo por si WebGL no está disponible.
   Desde el 2026-07-21 se estira hacia abajo el alto del footer
   (--alto-footer, que publica main.js) para pasar por detrás de él:
   así el CTA y el footer comparten UN SOLO degradado vivo, sin
   costura. El recorte lo hace esta caja, no la sección */
.fondo-shader {
  position: absolute;
  inset: 0;
  bottom: calc(-1 * var(--alto-footer, 0px));
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
  will-change: opacity;
  background-color: #121212;
  background-image:
    radial-gradient(ellipse 900px 650px at 12% 8%, rgba(71, 22, 14, 0.65), transparent 60%),
    radial-gradient(ellipse 750px 750px at 88% 12%, rgba(86, 105, 81, 0.40), transparent 65%),
    radial-gradient(ellipse 800px 900px at 95% 88%, rgba(212, 212, 212, 0.16), transparent 60%),
    radial-gradient(ellipse 1000px 700px at 22% 78%, rgba(247, 247, 223, 0.10), transparent 55%);
}

/* Con el fondo dinámico montado, el anfitrión suelta su degradado
   propio: si lo conservara, al desvanecer el fondo reaparecería el
   oscuro de atrás en lugar del blanco */
html.shader-activo [data-shader-host] {
  background-color: transparent;
  background-image: none;
}

.fondo-shader__lienzo {
  position: absolute;
  inset: 0;
}

.fondo-shader__lienzo canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.fondo-shader__orbe-capa {
  position: absolute;
  inset: 0;
  overflow: hidden;
  mix-blend-mode: overlay;
  isolation: isolate;
  transition: opacity 0.4s ease;
}

.fondo-shader__orbe {
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background:
    radial-gradient(ellipse 25% 28% at 35% 35%, rgba(38, 48, 36, 0.55), transparent 60%),
    radial-gradient(ellipse 40% 45% at 35% 35%, rgba(86, 105, 81, 0.85), rgba(86, 105, 81, 0) 70%);
  animation: orbe-deriva 25s ease-in-out infinite;
  will-change: transform, opacity;
  backface-visibility: hidden;
}

@keyframes orbe-deriva {
  0%   { transform: translate(0%, 0%) scale(1); opacity: 0; }
  8%   { transform: translate(1%, 1%) scale(1.02); opacity: 0.85; }
  22%  { transform: translate(8%, 3%) scale(1.15); opacity: 0.95; }
  40%  { transform: translate(20%, 13%) scale(0.95); opacity: 0.75; }
  55%  { transform: translate(27%, 20%) scale(1.10); opacity: 0.85; }
  70%  { transform: translate(13%, 16%) scale(0.85); opacity: 0.45; }
  78%  { transform: translate(6%, 9%) scale(0.80); opacity: 0; }
  100% { transform: translate(0%, 0%) scale(1); opacity: 0; }
}

.fondo-shader__velo {
  position: absolute;
  inset: 0;
  background-color: rgba(15, 15, 15, 0.25);
}

.fondo-shader__grano {
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch' seed='5'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-repeat: repeat;
  background-size: 180px 180px;
  mix-blend-mode: overlay;
  opacity: 0.16;
}

/* ---- FOOTER: cierra la zona oscura que abre el CTA de contacto ----
   Todas las páginas terminan igual: CTA oscuro + footer. El footer no
   pinta fondo propio: se apoya sobre el fondo dinámico del CTA, que se
   estira por detrás de él (ver .fondo-shader). El negro plano queda
   como respaldo para cuando no hay JS y el degradado vivo no se monta.
   La línea blanca tenue mantiene la separación editorial de siempre */
.footer {
  position: relative;
  z-index: 1; /* por encima de la caja del fondo, que viene de la sección anterior */
  padding-block: var(--space-7);
  background: #121212;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

html.shader-activo .footer {
  background: transparent;
}

.footer__inner {
  display: grid;
  gap: var(--space-4);
  justify-items: center;
  text-align: center;
}

.footer__social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5);
}

/* Sobre el negro, el texto secundario es gris claro y el hover sube al
   crema (el vino de marca no tiene contraste suficiente en oscuro) */
.footer__red {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-small);
  color: #D4D4D4;
  transition: color var(--transition-fast);
}

.footer__red:hover,
.footer__red:focus-visible {
  color: #F7F7DF;
}

.footer__copy {
  font-size: var(--fs-small);
  color: #8A8A85;
}

/* ---- BOTÓN FLOTANTE DE WHATSAPP ---- */
.fab-whatsapp {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: var(--z-fab);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 45px;
  height: 45px;
  border-radius: var(--radius-pill);
  background: #25D366;
  color: #fff;
  box-shadow: 0 8px 24px rgba(37, 211, 102, 0.40);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.fab-whatsapp svg {
  width: 22px;
  height: 22px;
}

.fab-whatsapp:hover,
.fab-whatsapp:focus-visible {
  transform: scale(1.08);
  box-shadow: 0 10px 28px rgba(37, 211, 102, 0.55);
}

/* ---- BARRA DE SCROLL MÍNIMA ----
   La barra nativa (con su pista que ocupa pantalla) se oculta y un
   pulgar flotante la reemplaza: aparece al scrollear y se desvanece
   al quedar quieto (lo crea y lo mueve js/main.js). Solo cuando hay
   JavaScript: sin él, la barra nativa sigue en su sitio. */
html.js {
  scrollbar-width: none; /* Firefox */
}

html.js::-webkit-scrollbar {
  display: none; /* Chrome / Edge / Safari (solo la del documento) */
}

.scroll-pulgar {
  position: fixed;
  top: 0;
  right: 0;
  width: 14px; /* zona de agarre generosa; la barrita visible es el ::before */
  z-index: 1200;
  opacity: 0;
  transition: opacity 0.4s ease;
  cursor: grab;
  touch-action: none;
}

.scroll-pulgar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 4px;
  width: 5px;
  border-radius: var(--radius-pill);
  /* Gris medio translúcido: se lee sobre los tramos oscuros y claros */
  background: rgba(120, 120, 120, 0.55);
  transition: width 0.2s ease, background-color 0.2s ease;
}

.scroll-pulgar:hover::before,
.scroll-pulgar.es-arrastrado::before {
  width: 8px;
  background: rgba(120, 120, 120, 0.75);
}

.scroll-pulgar.es-visible {
  opacity: 1;
}

.scroll-pulgar.es-arrastrado {
  cursor: grabbing;
}

/* ============================================================
   PÁGINAS DE PROYECTO (ej. proyecto-mirador-del-rio.html)
   Añadido el 2026-07-21 junto con la primera ficha de proyecto real.
   ============================================================ */

/* ---- Tarjeta de proyecto enlazada (solo la obra con página propia) ----
   La capa .proyecto__enlace cubre toda la pieza: cualquier clic navega.
   Los demás proyectos son provisionales y no llevan enlace. */
.proyecto--enlazado {
  cursor: pointer;
}

.proyecto__enlace {
  position: absolute;
  inset: 0;
  z-index: 4; /* sobre el velo (1), la info (2) y la flecha (2) */
}

/* Foto de portada de la tarjeta: cubre el degradado de respaldo (z-index 0,
   bajo el velo). Con el mouse se acerca, igual que la galería. */
.proyecto__foto {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s ease;
}

@media (hover: hover) {
  .proyecto--enlazado:hover .proyecto__foto,
  .proyecto--enlazado:focus-within .proyecto__foto {
    transform: scale(1.06);
  }
}

/* Distintivo permanente de "esto se puede abrir": flecha arriba a la derecha */
.proyecto__flecha {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  color: #FFFFFF;
  background: rgba(10, 10, 10, 0.30);
  border: 1px solid rgba(255, 255, 255, 0.55);
  transition: background-color var(--transition-base), transform var(--transition-base);
}

.proyecto__flecha svg {
  width: 18px;
  height: 18px;
}

.proyecto--enlazado:hover .proyecto__flecha,
.proyecto--enlazado:focus-within .proyecto__flecha {
  background: rgba(10, 10, 10, 0.55);
  transform: translate(2px, -2px);
}

/* ---- Hero de la página de proyecto ----
   Título grande (--fs-hero, como el hero de inicio), pero sin ocupar la
   pantalla entera: el contenido de abajo empieza a verse enseguida. */
.hero--proyecto {
  min-height: auto;
  padding-top: clamp(7rem, 16vh, 10rem);
  padding-bottom: clamp(2.5rem, 7vh, 4.5rem);
}

/* Enlace "‹ Proyectos" que abre el hero, discreto y en tinta */
.volver {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin-bottom: var(--space-4);
  font-size: var(--fs-small);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  transition: color var(--transition-fast);
}

.volver:hover,
.volver:focus-visible {
  color: var(--color-ink);
}

.volver svg {
  width: 16px;
  height: 16px;
}

.hero__subtitulo {
  margin-top: var(--space-3);
  font-size: var(--fs-h3, 1.2rem);
  color: var(--color-text-muted);
}

/* ---- Intro del proyecto: ficha de datos + texto ----
   Dos columnas en escritorio (datos a la izquierda, relato a la derecha),
   apiladas en móvil. */
.proyecto-intro {
  display: grid;
  grid-template-columns: minmax(220px, 300px) 1fr;
  gap: clamp(var(--space-5), 6vw, var(--space-7));
  align-items: start;
}

@media (max-width: 820px) {
  .proyecto-intro {
    grid-template-columns: 1fr;
    gap: var(--space-5);
  }
}

/* Ficha: pares dato/valor separados por línea fina, estilo editorial */
.ficha {
  display: grid;
  gap: 0;
}

.ficha__item {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.ficha__item:last-child {
  border-bottom: 1px solid var(--color-border);
}

.ficha__item dt {
  font-size: var(--fs-small);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.ficha__item dd {
  text-align: right;
  color: var(--color-ink);
  font-weight: var(--fw-bold);
}

.proyecto-descripcion h2 {
  margin-bottom: var(--space-4);
}

.proyecto-descripcion p + p {
  margin-top: var(--space-4);
}

.proyecto-descripcion p {
  color: var(--color-text-muted);
  max-width: 62ch;
}

/* ---- Galería por fases (cuadrícula estática) ----
   Cada fase de la obra es una sección con su título y, debajo, sus fotos
   en una cuadrícula que se acomoda en filas (sin movimiento). Clic en
   cualquier foto abre el lightbox y recorre TODAS las fases. Las <img>
   llevan img-opcional por si faltara un archivo.
   (Se llaman .etapa*, no .fase*, para no chocar con las fases del proceso
   de los portafolios, que ya usan .fase.) */
.etapas {
  display: grid;
  /* minmax(0, 1fr) evita que la cinta ancha (max-content) desborde la
     columna y provoque scroll horizontal en la página */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(var(--space-6), 9vh, var(--space-8));
}

/* Cada etapa se queda dentro de su columna aunque su cinta sea larguísima.
   (Se llama .etapa, no .fase, para no chocar con las fases del proceso de
   los portafolios, que ya usan .fase.) */
.etapa {
  min-width: 0;
}

/* Encabezado de cada etapa: número + título, con la línea fina editorial */
.etapa__cabecera {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.etapa__num {
  flex: none;
  white-space: nowrap; /* "Fase 5" nunca se parte en dos líneas */
  font-size: var(--fs-small);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.etapa__titulo {
  font-size: var(--fs-h3);
}

/* Bajo el título, las fotos de la fase en una cuadrícula que se acomoda
   en filas: caben todas a la vista, sin movimiento. Tantas columnas como
   quepan (mínimo 150px cada una). */
.etapa__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-2);
}

/* Proporción vertical 3:4 (las fotos verticales, 1500×2000, la llenan sin
   recortar; la única horizontal se recorta a los lados). Al pasar el mouse
   se acerca un poco dentro de su marco. */
.etapa__item {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  cursor: pointer;
  background-color: #E4E4E1; /* color de espera mientras carga */
}

.etapa__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}

@media (hover: hover) {
  .etapa__item:hover .etapa__foto,
  .etapa__item:focus-within .etapa__foto {
    transform: scale(1.05);
  }
}

/* Etapa aún sin fotos (p. ej. Diseño): solo el encabezado + una nota */
.etapa__nota {
  padding: var(--space-5);
  border: 1px dashed var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--fs-small);
  text-align: center;
}

/* ---- Planimetría: visor de PDF + descarga ---- */
.planos {
  display: grid;
  gap: var(--space-4);
  justify-items: center;
}

.planos__visor {
  width: 100%;
  aspect-ratio: 4 / 3;
  max-height: 80vh;
  border: 1px solid var(--color-border);
  background: #F4F4F2;
}

.planos__pdf {
  width: 100%;
  height: 100%;
  display: block;
}

.planos__fallback {
  display: grid;
  place-content: center;
  height: 100%;
  padding: var(--space-5);
  text-align: center;
  color: var(--color-text-muted);
}

.planos__fallback a {
  color: var(--color-primary);
  text-decoration: underline;
}

.planos__descarga {
  gap: var(--space-2);
}

/* ---- Lightbox: la foto de la galería a pantalla completa ----
   Lo monta js/main.js al hacer clic en un panel con imagen cargada. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1300; /* sobre navbar (1000), lightbox base (1100) y el pulgar de scroll (1200) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(10, 10, 10, 0.92);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-base), visibility var(--transition-base);
}

.lightbox.es-abierto {
  opacity: 1;
  visibility: visible;
}

/* Con el lightbox abierto, la barra y el botón flotante se esconden: si no,
   asoman a través del velo semitransparente y ensucian la vista completa */
.lightbox-activo #navbar,
.lightbox-activo .fab-whatsapp {
  opacity: 0;
  pointer-events: none;
}

.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.lightbox__cerrar {
  position: absolute;
  top: clamp(0.75rem, 3vw, 1.75rem);
  right: clamp(0.75rem, 3vw, 1.75rem);
  width: 46px;
  height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #FFFFFF;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.4);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.lightbox__cerrar:hover,
.lightbox__cerrar:focus-visible {
  background: rgba(255, 255, 255, 0.24);
}

.lightbox__cerrar svg {
  width: 22px;
  height: 22px;
}

/* Flechas anterior/siguiente y contador del lightbox (galería con varias
   fotos). Los monta js/main.js junto al lightbox. */
.lightbox__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 50px;
  height: 50px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #FFFFFF;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.4);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.lightbox__nav:hover,
.lightbox__nav:focus-visible {
  background: rgba(255, 255, 255, 0.24);
}

.lightbox__nav svg {
  width: 26px;
  height: 26px;
}

.lightbox__nav--prev { left: clamp(0.5rem, 3vw, 2rem); }
.lightbox__nav--next { right: clamp(0.5rem, 3vw, 2rem); }

.lightbox__contador {
  position: absolute;
  bottom: clamp(0.75rem, 3vw, 1.75rem);
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--fs-small);
  letter-spacing: 0.1em;
}

/* En pantallas angostas las flechas se recogen a las esquinas inferiores
   para no taparse con la foto */
@media (max-width: 600px) {
  .lightbox__nav {
    top: auto;
    bottom: clamp(0.75rem, 3vw, 1.75rem);
    transform: none;
  }
}

/* ============================================================
   PORTADA de la home + badge "Actualmente en curso"
   (repuestos/añadidos el 2026-07-22)
   ============================================================ */

/* ---- Portada: apertura del sitio con el logo sobre el fondo de marca ----
   Misma estética que el aviso en-construccion: negro con un respiro de
   oliva y del vino de marca. Una pantalla; debajo sigue el hero blanco. */
/* Fondo dinámico de APERTURA (solo home): el mismo shader de 3 colores del
   CTA, fijo detrás de la portada y el hero. main.js lo disuelve (opacity
   1→0) al hacer scroll: el oscuro se diluye poco a poco hasta dejar el
   sitio en blanco, sin banda ni "sombra mentirosa". El body es blanco, así
   que al desvanecerse queda blanco. */
.apertura {
  position: fixed;
  inset: 0;
  z-index: -1;          /* detrás del contenido; el body blanco queda atrás */
  pointer-events: none;
  will-change: opacity;
  /* Respaldo por si el shader no monta (WebGL off); con shader-activo el host
     se vuelve transparente y manda el .fondo-shader de adentro */
  background:
    radial-gradient(120% 90% at 15% 110%, rgba(86, 105, 81, 0.28) 0%, rgba(86, 105, 81, 0) 55%),
    radial-gradient(110% 80% at 90% -10%, rgba(71, 22, 14, 0.45) 0%, rgba(71, 22, 14, 0) 60%),
    linear-gradient(170deg, #121212 0%, #171717 100%);
}

/* En la apertura el shader NO se estira bajo el footer (eso es solo del CTA):
   llena el viewport fijo */
.apertura .fondo-shader {
  bottom: 0;
}

/* La portada y el hero del home van TRANSPARENTES para que se vea el fondo
   de apertura (que se disuelve al scrollear). Antes tenían un degradado
   estático que dejaba una banda oscura en la unión — retirado. */
.portada {
  position: relative;
  min-height: 100vh;
  display: grid;
  place-items: center;
  gap: clamp(1.75rem, 5vh, 3rem);
  text-align: center;
  padding: clamp(1.5rem, 6vw, 4rem);
  background: transparent;
}

.portada + .hero {
  background: transparent;
}

.portada__logo {
  width: min(380px, 72vw);
  height: auto;
  animation: portada-entrar 1.1s ease-out both;
}

/* Flecha suave que invita a bajar al sitio */
.portada__scroll {
  position: absolute;
  bottom: clamp(1.5rem, 5vh, 3rem);
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  color: rgba(247, 247, 223, 0.7);
  animation: portada-flecha 2s ease-in-out infinite;
  transition: color var(--transition-fast);
}
.portada__scroll:hover,
.portada__scroll:focus-visible { color: #F7F7DF; }
.portada__scroll svg { width: 30px; height: 30px; }

@keyframes portada-entrar {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes portada-flecha {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(6px); }
}
@media (prefers-reduced-motion: reduce) {
  .portada__logo { animation: none; }
  .portada__scroll { animation: none; }
}

/* ---- Badge "Actualmente en curso" con luz verde que late ---- */
.estado-obra {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: #FFFFFF;
  font-size: var(--fs-small);
  letter-spacing: 0.03em;
  color: var(--color-ink);
}

.estado-obra__luz {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #22C55E;
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.7);
  animation: latido-verde 1.8s ease-out infinite;
}

@keyframes latido-verde {
  0%   { box-shadow: 0 0 6px rgba(34, 197, 94, 0.7), 0 0 0 0 rgba(34, 197, 94, 0.55); }
  70%  { box-shadow: 0 0 6px rgba(34, 197, 94, 0.7), 0 0 0 8px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 6px rgba(34, 197, 94, 0.7), 0 0 0 0 rgba(34, 197, 94, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .estado-obra__luz { animation: none; }
}
