/* Tipografías auto-alojadas (sin enlazar a Google Fonts: cero dependencias
   de terceros en el frontend público). */
@font-face {
  font-family: 'Passion One';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/passion-one-regular.woff2') format('woff2');
}

@font-face {
  font-family: 'Passion One';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/passion-one-bold.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-medium.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-semibold.woff2') format('woff2');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/inter-bold.woff2') format('woff2');
}

:root {
  --color-primario: #8d48a0;
  --color-primario-oscuro: #5b2d68;
  --color-fondo-hero: #fcf2ff;
  --color-blanco: #ffffff;
  --color-error: #b3261e;

  --fuente-titular: 'Passion One', Georgia, serif;
  --fuente-base: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  --nav-alto: clamp(72px, 9vw, 106px);
  --radio-boton: 999px;
  --ancho-maximo: 1280px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--fuente-base);
  color: var(--color-primario-oscuro);
}

/* Los elementos de formulario (button, input, textarea...) no heredan la
   tipografía del body por defecto — el navegador les aplica la suya
   propia (Arial en la mayoría). Sin esto, un botón que solo lleva un
   icono y ningún .boton explícito (como los de cerrar/hamburguesa) se
   queda con esa fuente por defecto en vez de Inter. */
button,
input,
textarea,
select {
  font-family: inherit;
}

img {
  max-width: 100%;
  display: block;
}

.contenedor {
  width: 100%;
  max-width: var(--ancho-maximo);
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 64px);
}

/* -------------------- Menú fijo -------------------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--nav-alto);
  background: var(--color-blanco);
}

.nav .contenedor {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
}

.nav__logo {
  position: relative;
  z-index: 1;
  display: block;
  width: clamp(56px, 8vw, 96px);
  height: clamp(56px, 8vw, 96px);
  border-radius: 0 0 40% 40%;
  overflow: hidden;
  flex-shrink: 0;
}

.nav__logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nav__enlaces {
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 36px);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__enlaces a {
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 16px;
  color: var(--color-primario);
  text-decoration: none;
  padding: 10px;
  border-radius: 10px;
  transition: background-color 0.25s ease;
}

.nav__enlaces a:focus-visible {
  background: var(--color-fondo-hero);
}

@media (hover: hover) {
  .nav__enlaces a:hover {
    background: var(--color-fondo-hero);
  }
}

.nav__derecha {
  display: flex;
  align-items: center;
  gap: 24px;
}

/* Solo tiene sentido dentro del menú a pantalla completa de móvil (ver
   media query más abajo), donde se le da su posición y tamaño reales. */
.nav__decoracion {
  display: none;
}

.nav__hamburguesa {
  display: none;
  position: relative;
  /* Por encima del panel del menú a pantalla completa (ver .nav__derecha
     en el media query de móvil), para que el aspa se vea siempre por
     delante aunque los dos sean descendientes del mismo <header>. */
  z-index: 2;
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
}

.nav__hamburguesa svg {
  width: 28px;
  height: 28px;
  color: var(--color-primario);
}

/* Las tres líneas pivotan sobre el centro del viewBox (12,12): las de
   arriba y abajo se deslizan hacia el medio y giran 45°/-45° para formar
   el aspa, y la del medio simplemente se desvanece. */
.nav__hamburguesa-linea {
  transform-origin: 12px 12px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

/* El orden de las funciones importa: CSS aplica la de más a la derecha
   primero. Con "translateY() rotate()" la línea rotaba ANTES de
   desplazarse (alrededor de un origen todavía descentrado) y el aspa
   salía torcida; así, primero se desplaza al centro y luego gira sobre
   ese mismo punto. */
.nav[data-menu-abierto='true'] .nav__hamburguesa-linea--arriba {
  transform: rotate(45deg) translateY(6px);
}

.nav[data-menu-abierto='true'] .nav__hamburguesa-linea--medio {
  opacity: 0;
}

.nav[data-menu-abierto='true'] .nav__hamburguesa-linea--abajo {
  transform: rotate(-45deg) translateY(-6px);
}

/* -------------------- Página legal (política de privacidad) -------------------- */
/* Página propia, no una sección de inicio.php: por eso necesita su propio
   padding-top para no quedar tapada por el .nav fijo (ver .hero, que
   resuelve lo mismo para la portada). */

.legal {
  padding-top: calc(var(--nav-alto) + clamp(32px, 8vw, 72px));
  padding-bottom: clamp(64px, 10vw, 120px);
}

.legal__contenido {
  max-width: 1200px;
}

.legal__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 1.4px;
  color: var(--color-primario);
}

.legal__eyebrow img {
  width: 6px;
  height: 6px;
}

.legal__titular {
  margin: 0 0 8px;
  font-family: var(--fuente-titular);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1;
  font-size: clamp(2.25rem, 1.9rem + 1.5vw, 3.25rem);
  color: var(--color-primario-oscuro);
}

.legal__titular span {
  color: var(--color-primario);
}

.legal__actualizado {
  margin: 0 0 32px;
  font-family: var(--fuente-base);
  font-size: 14px;
  color: var(--color-primario-oscuro);
  opacity: 0.75;
}

.legal__aviso-pendiente {
  margin: 0 0 40px;
  padding: 16px 20px;
  border-radius: 12px;
  background: var(--color-fondo-hero);
  border: 1px solid var(--color-primario);
  font-family: var(--fuente-base);
  font-size: 15px;
  line-height: 1.6;
  color: var(--color-primario-oscuro);
}

.legal h2 {
  margin: 40px 0 12px;
  font-family: var(--fuente-titular);
  font-weight: 700;
  font-size: clamp(1.375rem, 1.25rem + 0.5vw, 1.75rem);
  color: var(--color-primario-oscuro);
}

.legal h3 {
  margin: 24px 0 8px;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 17px;
  color: var(--color-primario-oscuro);
}

/* Tabla de dos columnas clave/valor (§2 datos del responsable): la primera
   columna hace de etiqueta, sin necesitar un <thead> como la de cookies. */
.legal__tabla--datos td:first-child {
  width: 40%;
  font-weight: 700;
  color: var(--color-primario);
}

@media (max-width: 599px) {
  .legal__tabla--datos td:first-child {
    width: auto;
    padding-bottom: 0;
  }

  /* La primera columna YA es la etiqueta (p. ej. "NIF/CIF"): sin esto, el
     ::before genérico de .legal__tabla (más abajo en el fichero, misma
     especificidad) la repetiría delante de sí misma — de ahí el selector
     compuesto, para ganar por especificidad y no depender del orden. */
  .legal__tabla.legal__tabla--datos td::before {
    content: none;
  }
}

.legal p,
.legal li {
  font-family: var(--fuente-base);
  font-size: 16px;
  line-height: 1.62;
  color: var(--color-primario-oscuro);
}

.legal ul {
  margin: 0 0 16px;
  padding-left: 1.25em;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.legal a {
  color: var(--color-primario);
}

.legal__tabla {
  width: 100%;
  margin: 0 0 16px;
  border-collapse: collapse;
  font-family: var(--fuente-base);
  font-size: 15px;
  color: var(--color-primario-oscuro);
}

.legal__tabla th,
.legal__tabla td {
  padding: 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--color-fondo-hero);
}

.legal__tabla th {
  font-weight: 700;
  color: var(--color-primario);
}

@media (max-width: 599px) {
  /* La tabla no cabe en una pantalla estrecha con las 4 columnas en fila:
     se convierte en una lista de fichas, una por cookie, con la etiqueta de
     columna delante de cada dato (misma tabla, solo cambia cómo se ve). */
  .legal__tabla,
  .legal__tabla thead,
  .legal__tabla tbody,
  .legal__tabla th,
  .legal__tabla td,
  .legal__tabla tr {
    display: block;
  }

  .legal__tabla thead {
    display: none;
  }

  .legal__tabla tr {
    padding: 12px 0;
    border-bottom: 1px solid var(--color-fondo-hero);
  }

  .legal__tabla td {
    padding: 4px 0;
    border: none;
  }

  .legal__tabla td::before {
    content: attr(data-etiqueta) ': ';
    font-weight: 700;
    color: var(--color-primario);
  }
}

/* -------------------- Botones -------------------- */

.boton {
  font-family: var(--fuente-base);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.16px;
  padding: 18px 32px;
  border-radius: var(--radio-boton);
  border: none;
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.boton--primario {
  background: var(--color-primario);
  color: var(--color-blanco);
}

.boton--primario:focus-visible {
  background: var(--color-primario-oscuro);
}

.boton--fantasma {
  background: transparent;
  color: var(--color-primario);
  border: 1.5px solid var(--color-primario);
}

.boton--fantasma:focus-visible {
  background: var(--color-primario);
  color: var(--color-blanco);
}

/* Para usar sobre fondos de color (morado), en vez del morado sobre blanco
   de .boton--primario. */
.boton--claro {
  background: var(--color-blanco);
  color: var(--color-primario);
  text-decoration: none;
  display: inline-flex;
}

.boton--claro:focus-visible {
  background: var(--color-fondo-hero);
}

/* Los ":hover" van aparte, detrás de "(hover: hover)": en touch, el propio
   navegador simula el hover al tocar y se queda pegado hasta el toque
   siguiente, así que en móvil no se aplican — solo en dispositivos con un
   puntero real (ratón, trackpad). El foco por teclado (:focus-visible, más
   arriba) no depende de esto y sigue activo siempre. */
@media (hover: hover) {
  /* Un poco más oscuro al pasar el ratón, no un cambio brusco de color —
     reutiliza el morado oscuro que ya existe como token, en vez de inventar
     uno nuevo solo para el hover. */
  .boton--primario:hover {
    background: var(--color-primario-oscuro);
  }

  /* El botón de contorno se rellena con su propio color al hover, y el
     texto pasa a blanco para que se siga leyendo encima. */
  .boton--fantasma:hover {
    background: var(--color-primario);
    color: var(--color-blanco);
  }

  .boton--claro:hover {
    background: var(--color-fondo-hero);
  }
}

/* -------------------- Hero -------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--color-fondo-hero);
  padding-top: calc(var(--nav-alto) + clamp(32px, 8vw, 96px));
  min-height: 100vh;
  /* 100dvh evita el salto al aparecer/ocultarse la barra del navegador en
     móvil; los navegadores que no la soportan se quedan con el 100vh de
     arriba. */
  min-height: 100dvh;
}

.hero__contenido {
  position: relative;
  z-index: 1;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  text-align: center;
}

.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 1.6px;
  color: var(--color-primario);
}

.hero__eyebrow img {
  width: 6px;
  height: 6px;
}

.hero__titular {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1;
  /* Interpola 50px en el diseño móvil (375px) a 80px en el de escritorio
     (a partir de ~1280px), según los dos frames de Figma. */
  font-size: clamp(3.125rem, 2.35rem + 3.32vw, 5rem);
  color: var(--color-primario-oscuro);
}

.hero__titular-linea {
  display: block;
}

.hero__titular-linea--acento {
  color: var(--color-primario);
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: center;
}

/* Solo "Descubre más": el resto de .boton--fantasma del sitio (filtros de
   categoría, Instagram, panel admin) sigue con fondo transparente. */
.hero__ctas .boton--fantasma {
  background: var(--color-blanco);
}

.hero__imagen {
  /* Pegada al borde inferior del hero, no centrada con el texto — así es
     como está compuesta en el diseño (no forma parte del bloque centrado). */
  position: absolute;
  z-index: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  /* Medido directamente sobre el frame de Figma: el cuerpo de la tarta
     ocupa ~31% del ancho de la ventana (no del contenedor). Por vw en vez
     de por alto, para que el tamaño responda al ancho como en el diseño;
     el tope en px evita que crezca sin límite en monitores muy anchos. */
  width: min(31vw, 500px);
  height: auto;
  margin: 0;
  overflow: hidden;
  aspect-ratio: 941 / 971;
  /* Alto suficiente para no recortar la imagen (a su ancho máximo hacen
     falta ~52vh); solo actúa de tope de seguridad en ventanas muy bajas. */
  max-height: 58vh;
}

.hero__imagen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* -------------------- Testimonios -------------------- */

.testimonios {
  position: relative;
  overflow: hidden;
  border-left: 80px solid var(--color-primario);
  padding: clamp(64px, 10vw, 120px) clamp(24px, 6vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.testimonios__fondo {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.testimonios__fondo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

.testimonios__capa {
  position: absolute;
  inset: 0;
  /* La foto ya llega con el oscurecido aplicado; esta capa solo refuerza
     un poco el contraste para que el texto blanco se lea bien encima. */
  background: rgba(20, 20, 20, 0.25);
}

.testimonios__pista {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 900px;
  min-height: clamp(220px, 28vw, 300px);
}

.testimonio {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  margin: 0;
  color: var(--color-blanco);
  opacity: 0;

  /* Cuatro testimonios repartidos a partes iguales en un ciclo de 24s: cada
     uno entra con fundido desde la derecha, se para en el centro, y sale
     con fundido hacia la izquierda (§ petición del cliente). Los cuatro
     comparten la misma animación, desfasados un cuarto del ciclo cada uno.
     Si se añade o se quita un testimonio, hay que recalcular a mano: la
     duración (6s × nº de testimonios), el "animation-delay" de cada
     :nth-child (6s × su posición) y los porcentajes del @keyframes de
     abajo (12%/87%/100% de lo que le toque a cada uno, en % del ciclo
     completo) — si no, dos testimonios pueden acabar compartiendo el mismo
     delay y solaparse, como pasó al añadir el cuarto. */
  animation: testimonio-ciclo 24s ease-in-out infinite;
}

.testimonio:nth-child(1) {
  animation-delay: 0s;
}

.testimonio:nth-child(2) {
  animation-delay: 6s;
}

.testimonio:nth-child(3) {
  animation-delay: 12s;
}

.testimonio:nth-child(4) {
  animation-delay: 18s;
}

@keyframes testimonio-ciclo {
  0% {
    opacity: 0;
    transform: translateX(48px);
  }
  3% {
    opacity: 1;
    transform: translateX(0);
  }
  22% {
    opacity: 1;
    transform: translateX(0);
  }
  25%,
  100% {
    opacity: 0;
    transform: translateX(-48px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .testimonio {
    animation: none;
    opacity: 0;
  }

  /* Sin animación, se muestra solo el primero para que la sección no quede
     vacía a quien tiene activado "reducir movimiento" en su sistema. */
  .testimonio:first-child {
    opacity: 1;
    position: relative;
  }
}

.testimonio__texto {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 400;
  line-height: 1.15;
  font-size: clamp(1.875rem, 1.357rem + 2.21vw, 3.125rem);
}

.testimonio__autor {
  margin-top: 10px;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 16px;
  font-style: normal;
}

/* -------------------- Galería -------------------- */

.galeria {
  padding: clamp(64px, 10vw, 140px) 0;
}

.galeria__cabecera {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  margin-bottom: clamp(32px, 6vw, 56px);
}

.galeria__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 1.4px;
  color: var(--color-primario);
}

.galeria__eyebrow img {
  width: 6px;
  height: 6px;
}

.galeria__titular {
  margin: 0 0 16px;
  font-family: var(--fuente-titular);
  font-weight: 700;
  line-height: 1;
  font-size: clamp(3.125rem, 2.35rem + 3.32vw, 5rem);
  color: var(--color-primario-oscuro);
}

.galeria__titular-acento {
  color: var(--color-primario);
}

.galeria__descripcion {
  margin: 0;
  font-family: var(--fuente-base);
  font-size: 16px;
  line-height: 1.62;
  color: var(--color-primario-oscuro);
  max-width: 55ch;
}

.galeria__instagram {
  width: 100%;
  gap: 12px;
}

/* El icono usa fill="currentColor" para heredar el color del botón (ver
   .boton--fantasma:hover), pero al ser un descendiente necesita su propia
   transición de "color" para que el cambio se vea con el mismo fundido que
   el resto de botones, en vez de saltar de golpe. */
.galeria__instagram svg {
  transition: color 0.25s ease;
}

/* -------------------- Filtros -------------------- */

.galeria__filtros {
  position: relative;
  margin: 0 0 clamp(32px, 5vw, 48px);
}

.galeria__filtros-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  background: var(--color-fondo-hero);
  border: none;
  border-radius: 200px;
  padding: 24px;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 18px;
  color: var(--color-primario-oscuro);
  cursor: pointer;
}

.galeria__filtros-flecha {
  width: 13px;
  height: 13px;
  transform: rotate(-135deg);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

.galeria__filtros[data-abierto="true"] .galeria__filtros-flecha {
  transform: rotate(45deg);
}

.galeria__filtros-lista {
  display: none;
  flex-direction: column;
  list-style: none;
  margin: 0;
  padding: 8px;
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  background: var(--color-blanco);
  border-radius: 20px;
  box-shadow: 0 8px 24px rgba(91, 45, 104, 0.15);
  z-index: 5;
}

.galeria__filtros[data-abierto="true"] .galeria__filtros-lista {
  display: flex;
}

.filtro {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: 12px;
  padding: 14px 16px;
  font-family: var(--fuente-base);
  font-size: 16px;
  font-weight: 400;
  color: var(--color-primario-oscuro);
  cursor: pointer;
  /* "font-weight" no se puede animar con fluidez entre pesos estáticos
     (Inter está autoalojada en ficheros fijos, no como fuente variable):
     el cambio se notaría de golpe a mitad de transición. En su lugar se
     engrosa el trazo del texto, que sí es una propiedad continua. */
  -webkit-text-stroke: 0px currentColor;
  transition: background-color 0.25s ease, -webkit-text-stroke-width 0.25s ease;
}

.filtro:focus-visible {
  background: var(--color-fondo-hero);
  -webkit-text-stroke-width: 0.5px;
}

@media (hover: hover) {
  .filtro:hover {
    background: var(--color-fondo-hero);
    -webkit-text-stroke-width: 0.5px;
  }
}

.filtro[aria-pressed="true"] {
  font-weight: 700;
  background: var(--color-fondo-hero);
}

/* -------------------- Rejilla de imágenes -------------------- */

.galeria__rejilla {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  transition: opacity 0.18s ease;
}

.galeria__rejilla[data-transicion="true"] {
  opacity: 0;
}

.galeria__tarjeta {
  position: relative;
  display: block;
  margin: 0;
  padding: 0;
  border: none;
  border-radius: 14px;
  overflow: hidden;
  background: #e9c9ba;
  aspect-ratio: 310 / 451;
  cursor: pointer;
  font: inherit;
  animation: galeria-tarjeta-entrada 0.35s ease both;
}

.galeria__tarjeta img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s ease;
}

.galeria__tarjeta:focus-visible img {
  transform: scale(1.08);
}

/* La tarjeta ya recorta con overflow:hidden, así que el zoom de la imagen
   se queda dentro del contenedor sin agrandar la tarjeta en sí. */
@media (hover: hover) {
  .galeria__tarjeta:hover img {
    transform: scale(1.08);
  }
}

/* Tarjeta de descripción de categoría: ocupa el primer hueco de la
   rejilla en vez de una foto, con texto fijo (§ no depende de las
   imágenes que haya). Cursor "default": a diferencia de las fotos, no
   abre nada al pulsarla. */
.galeria__tarjeta--info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 16px;
  padding: 24px;
  background: var(--color-primario);
  cursor: default;
}

.galeria__tarjeta-info-titulo {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--color-blanco);
}

.galeria__tarjeta-info-raya {
  width: 32px;
  height: 2px;
  background: var(--color-blanco);
}

.galeria__tarjeta-info-descripcion {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.35;
  color: var(--color-blanco);
}

/* En móvil no seguimos la proporción fija de las fotos (310/451): con
   solo texto queda muchísimo hueco vacío, así que la altura la marca el
   propio contenido, más baja que una foto (a petición del cliente). */
@media (max-width: 767px) {
  .galeria__tarjeta--info {
    aspect-ratio: auto;
  }
}

/* El fundido de entrada termina fijando "transform" en su último
   fotograma (fill-mode "both"), lo que pisaría el translateY(59px) fijo
   del escalonado de escritorio si ambos usaran "transform" por separado.
   Por eso el desplazamiento final se lee de --tarjeta-y (0 por defecto,
   59px en las columnas escalonadas) en vez de fijarse en otra regla. */
@keyframes galeria-tarjeta-entrada {
  from {
    opacity: 0;
    transform: translateY(calc(var(--tarjeta-y, 0px) + 10px));
  }
  to {
    opacity: 1;
    transform: translateY(var(--tarjeta-y, 0px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .galeria__rejilla {
    transition: none;
  }

  .galeria__tarjeta {
    animation: none;
  }

  .galeria__tarjeta img {
    transition: none;
  }
}

/* Las 2 primeras fotos ocupan el ancho completo en móvil; el resto va en
   parejas — así lo pide el cliente para esta vista. */
.galeria__tarjeta:nth-child(1),
.galeria__tarjeta:nth-child(2) {
  grid-column: 1 / -1;
}

.galeria__vacio,
.galeria__error {
  font-family: var(--fuente-base);
  color: var(--color-primario-oscuro);
  text-align: center;
  padding: 40px 0;
}

.galeria__cargar-mas {
  display: block;
  margin: clamp(32px, 6vw, 56px) auto 0;
}

/* -------------------- Lightbox -------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* display:flex de arriba gana por origen de cascada (autor vence a UA)
   aunque el atributo "hidden" tenga la misma especificidad; hay que
   apagarlo aquí a mano o el popup no se ocultaría nunca. */
.lightbox[hidden] {
  display: none;
}

.lightbox__fondo {
  position: absolute;
  inset: 0;
  background: rgba(91, 45, 104, 0.6);
}

.lightbox__contenido {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 400px;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--color-blanco);
  border-radius: 30px;
  padding: 81px 19px 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.lightbox__cerrar {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  border: none;
  background: none;
  color: var(--color-primario-oscuro);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

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

.lightbox__imagen-contenedor {
  /* aspect-ratio se fija por JS con el ancho/alto real de cada foto, para
     que el hueco sea vertical, horizontal o cuadrado según la imagen. Sin
     "width: 100%" aquí: así el tamaño lo marcan la proporción real y estos
     topes, no un ancho forzado. */
  width: 100%;
  max-width: 297px;
  max-height: 60vh;
  border-radius: 14px;
  overflow: hidden;
  /* Con texto debajo el pop-up puede no caber en pantalla: las piezas no se
     encogen, es el propio pop-up el que hace scroll. */
  flex-shrink: 0;
}

.lightbox__imagen {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.lightbox__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: 100%;
}

.lightbox__flecha {
  display: none;
  border: none;
  background: none;
  color: var(--color-primario-oscuro);
  cursor: pointer;
  padding: 8px;
  flex-shrink: 0;
}

.lightbox__flecha svg {
  width: 24px;
  height: 24px;
}

.lightbox__puntos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
}

.lightbox__punto {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: var(--color-fondo-hero);
  cursor: pointer;
}

.lightbox__punto[aria-current="true"] {
  background: var(--color-primario);
}

/* Texto del producto (título, descripción, precio): en móvil va debajo de la
   foto y de los puntos, y el pop-up hace scroll si no cabe. */
.lightbox__info {
  order: 3;
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  max-width: 292px;
  margin-top: 13px;
  flex-shrink: 0;
  color: var(--color-primario-oscuro);
  overflow-wrap: anywhere;
}

.lightbox__nav {
  order: 2;
  flex-shrink: 0;
  /* Separaciones del diseño móvil (foto → puntos 49px, puntos → texto 33px),
     que suman a los 20px de gap del contenedor. */
  margin-top: 29px;
}

.lightbox__info [hidden] {
  display: none;
}

.lightbox__titulo,
.lightbox__precio {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.62;
}

.lightbox__descripcion {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.62;
  /* Respeta los saltos de línea que escribe el administrador (párrafos). */
  white-space: pre-line;
}

@media (min-width: 768px) {
  .lightbox__contenido {
    display: grid;
    grid-template-columns: minmax(0, 530fr) minmax(0, 489fr);
    grid-template-areas:
      'imagen info'
      'nav nav';
    column-gap: clamp(24px, 4.7vw, 61px);
    row-gap: 57px;
    align-items: start;
    max-width: 1300px;
    padding: 79px clamp(32px, 8.5vw, 110px) 46px;
  }

  .lightbox__cerrar {
    top: 41px;
    right: 45px;
    width: 50px;
    height: 50px;
  }

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

  .lightbox__imagen-contenedor {
    grid-area: imagen;
    justify-self: center;
    width: auto;
    max-width: 100%;
    max-height: min(605px, 65vh);
  }

  .lightbox__info {
    grid-area: info;
    margin-top: 0;
    max-width: none;
    /* 183px del diseño menos los 79px de arriba de la foto. */
    padding-top: 104px;
  }

  .lightbox__nav {
    grid-area: nav;
    margin-top: 0;
    justify-self: center;
    max-width: 744px;
    justify-content: space-between;
  }

  .lightbox__flecha {
    display: flex;
  }
}

/* -------------------- Sobre mí -------------------- */

.sobre-mi {
  background: var(--color-primario);
  padding: clamp(64px, 10vw, 140px) 0;
  overflow: hidden;
}

.sobre-mi__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(40px, 8vw, 64px);
}

.sobre-mi__texto {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  width: 100%;
  color: var(--color-blanco);
}

.sobre-mi__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 1.4px;
}

.sobre-mi__eyebrow img {
  width: 6px;
  height: 6px;
}

.sobre-mi__titular {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 400;
  text-transform: uppercase;
  /* Un valor fijo, no proporcional al tamaño de letra: en el diseño el
     interlineado es igual de apretado (40px) tanto en el titular de 50px
     móvil como en el de 60px escritorio. */
  line-height: 40px;
  font-size: clamp(3.125rem, 2.866rem + 1.105vw, 3.75rem);
}

.sobre-mi__parrafos {
  display: flex;
  flex-direction: column;
  gap: 24px;
  margin: 0;
  font-family: var(--fuente-base);
  font-size: 16px;
  line-height: 1.62;
}

.sobre-mi__parrafos p {
  margin: 0;
}

.sobre-mi__fotos {
  position: relative;
  width: 100%;
  aspect-ratio: 595 / 564;
}

.sobre-mi__foto {
  position: absolute;
  border-radius: 30px;
  overflow: hidden;
}

.sobre-mi__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Las dos fotos están posicionadas en porcentajes del contenedor (no en
   píxeles fijos), porque en el diseño la composición guarda exactamente
   la misma proporción en móvil y en escritorio — solo cambia el tamaño
   del conjunto, nunca la disposición relativa. */
.sobre-mi__foto--grande {
  top: 0;
  right: 0;
  width: 79.33%;
  height: 100%;
}

.sobre-mi__foto--pequena {
  top: 32.09%;
  left: 0;
  width: 50.42%;
  aspect-ratio: 1 / 1;
  z-index: 1;
  box-shadow: 10px 24px 34px rgba(34, 17, 39, 0.6);
}

.sobre-mi__visita {
  margin-top: clamp(64px, 10vw, 140px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  text-align: center;
  color: var(--color-blanco);
}

.sobre-mi__visita-titular {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 1;
  font-size: clamp(3.125rem, 2.35rem + 3.32vw, 5rem);
}

.sobre-mi__visita-direccion {
  margin: 0;
  font-family: var(--fuente-base);
  font-size: 16px;
  line-height: 1.62;
}

.sobre-mi__mapa {
  width: 100%;
  max-width: 1298px;
  aspect-ratio: 341 / 322;
  border-radius: 30px;
  overflow: hidden;
}

.sobre-mi__mapa iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

@media (min-width: 768px) {
  .sobre-mi__eyebrow {
    font-size: 16px;
    letter-spacing: 1.6px;
  }

  .sobre-mi__intro {
    flex-direction: row-reverse;
    align-items: center;
    justify-content: center;
    gap: clamp(40px, 5vw, 71px);
  }

  .sobre-mi__texto {
    flex: 1 1 640px;
  }

  .sobre-mi__fotos {
    flex: 1 1 595px;
    max-width: 595px;
  }

  .sobre-mi__mapa {
    aspect-ratio: 1298 / 566;
  }
}

/* -------------------- Contacto -------------------- */

.contacto {
  padding: clamp(64px, 10vw, 140px) 0;
}

.contacto__grid {
  display: flex;
  flex-direction: column;
  gap: clamp(48px, 8vw, 80px);
}

.contacto__info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  color: var(--color-primario-oscuro);
}

.contacto__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 1.4px;
  color: var(--color-primario);
}

.contacto__eyebrow img {
  width: 6px;
  height: 6px;
}

.contacto__titular {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 700;
  line-height: 1;
  font-size: clamp(3.125rem, 2.35rem + 3.32vw, 5rem);
  color: var(--color-primario-oscuro);
}

.contacto__pasos {
  list-style: decimal;
  margin: 0;
  padding: 0;
  padding-left: 1.5em;
  display: flex;
  flex-direction: column;
  gap: 24px;
  font-family: var(--fuente-titular);
  font-weight: 400;
  font-size: clamp(1.5625rem, 1.433rem + 0.5525vw, 1.875rem);
  color: var(--color-primario-oscuro);
}

/* El número (marcador de lista) solo se genera en elementos con
   "display: list-item" — por eso el flex de cada paso va en un div
   envolvente dentro del <li>, no en el <li> mismo (eso apagaría el "1.",
   "2.", "3." por completo). */
.contacto__paso {
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.contacto__pasos li::marker {
  font-family: var(--fuente-titular);
  color: var(--color-primario-oscuro);
}

.contacto__paso-titulo {
  margin: 0;
  line-height: 40px;
}

.contacto__paso-descripcion {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.62;
}

/* -------------------- Formulario -------------------- */

.contacto__formulario-envoltorio {
  width: 100%;
}

.contacto__formulario {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.campo {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.campo label {
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 14px;
  line-height: 1.62;
  color: var(--color-primario-oscuro);
}

.campo input,
.campo textarea {
  width: 100%;
  background: #f3f3f3;
  border: none;
  border-bottom: 1px solid var(--color-primario);
  border-radius: 0;
  padding: 0 12px;
  height: 46px;
  font-family: var(--fuente-base);
  font-size: 16px;
  color: var(--color-primario-oscuro);
  outline-offset: 2px;
}

.campo textarea {
  height: 112px;
  padding-top: 12px;
  padding-bottom: 12px;
  resize: vertical;
}

.campo input:focus-visible,
.campo textarea:focus-visible {
  outline: 2px solid var(--color-primario);
}

.campo--error input,
.campo--error textarea {
  border-bottom-color: var(--color-error);
}

.campo__error {
  margin: 0;
  min-height: 1.2em;
  font-family: var(--fuente-base);
  font-size: 14px;
  color: var(--color-error);
}

/* Campo de imagen: el <input type="file"> nativo se oculta (sigue siendo
   accesible y enfocable por teclado) y su <label> hace de botón. */
.campo__etiqueta {
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 14px;
  line-height: 1.62;
  color: var(--color-primario-oscuro);
}

.archivo {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.archivo__estado {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
}

.campo .archivo__input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.campo label.archivo__boton {
  gap: 8px;
  padding: 12px 24px;
  font-size: 16px;
  font-weight: 600;
  line-height: normal;
  color: var(--color-primario);
}

.archivo__boton svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.archivo__input:focus-visible + .archivo__boton {
  outline: 2px solid var(--color-primario);
  outline-offset: 2px;
}

@media (hover: hover) {
  .campo label.archivo__boton:hover {
    background: var(--color-primario);
    color: var(--color-blanco);
  }
}

.archivo__nombre {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--fuente-base);
  font-style: italic;
  font-size: 15px;
  color: #858585;
}

.archivo__quitar {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: #f3f3f3;
  color: var(--color-primario-oscuro);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.archivo__quitar:focus-visible {
  outline: 2px solid var(--color-primario);
  outline-offset: 2px;
}

.campo__ayuda {
  margin: 0;
  font-family: var(--fuente-base);
  font-size: 13px;
  color: var(--color-primario-oscuro);
  opacity: 0.75;
}

.campo--consentimiento {
  flex-direction: row;
  flex-wrap: wrap;
}

.contacto__consentimiento {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--fuente-base);
  font-size: 14px;
  color: var(--color-primario-oscuro);
  cursor: pointer;
}

.contacto__consentimiento input {
  width: 18px;
  height: 18px;
  accent-color: var(--color-primario);
  cursor: pointer;
}

.campo--consentimiento .campo__error {
  width: 100%;
}

.contacto__enviar {
  align-self: flex-start;
  /* Tono cálido específico de este botón en el diseño, distinto del
     blanco puro que usan el resto de .boton--primario del sitio. */
  color: #fbf6ef;
}

.contacto__enviar:disabled {
  opacity: 0.6;
  cursor: progress;
}

/* -------------------- Popup de confirmación -------------------- */

.contacto-popup {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* display:flex de arriba gana por origen de cascada (autor vence a UA)
   aunque el atributo "hidden" tenga la misma especificidad; hay que
   apagarlo aquí a mano o el popup no se ocultaría nunca (mismo caso que
   .lightbox[hidden]). */
.contacto-popup[hidden] {
  display: none;
}

.contacto-popup__fondo {
  position: absolute;
  inset: 0;
  background: rgba(91, 45, 104, 0.6);
}

.contacto-popup__contenido {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  background: var(--color-blanco);
  border-radius: 24px;
  padding: clamp(32px, 6vw, 48px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.contacto-popup__cerrar {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  border: none;
  background: none;
  color: var(--color-primario-oscuro);
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.contacto-popup__cerrar svg {
  width: 22px;
  height: 22px;
}

.contacto-popup__titulo {
  margin: 0;
  font-family: var(--fuente-titular);
  font-weight: 700;
  font-size: clamp(1.875rem, 1.6rem + 1.5vw, 2.5rem);
  color: var(--color-primario-oscuro);
}

.contacto-popup__texto {
  margin: 0;
  font-family: var(--fuente-base);
  font-size: 16px;
  line-height: 1.62;
  color: var(--color-primario-oscuro);
}

@media (min-width: 768px) {
  .contacto__grid {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
  }

  .contacto__info {
    flex: 1 1 640px;
    max-width: 640px;
  }

  .contacto__eyebrow {
    font-size: 16px;
    letter-spacing: 1.6px;
  }

  .contacto__formulario-envoltorio {
    flex: 1 1 529px;
    max-width: 529px;
  }

  .campo label {
    font-size: 16px;
  }

  .campo {
    gap: 19px;
  }

  .contacto__formulario {
    gap: 14px;
  }
}

/* Más aire arriba y abajo en tablet/móvil (<1100px) en los módulos con
   franjas de color — 150px fijos, a petición del cliente, en vez del
   clamp fluido (más ajustado) que se usa a partir de escritorio. */
@media (max-width: 1099px) {
  .testimonios {
    padding-top: 150px;
    padding-bottom: 150px;
  }

  .galeria {
    padding-top: 150px;
    padding-bottom: 150px;
  }

  .sobre-mi {
    padding-top: 150px;
    padding-bottom: 150px;
  }

  .contacto {
    padding-top: 150px;
    padding-bottom: 150px;
  }
}

/* -------------------- Footer -------------------- */

.footer {
  background: var(--color-primario-oscuro);
  padding: clamp(40px, 8vw, 72px) 0;
}

.footer__top {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
}

.footer__marca {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

/* Cuadrado, no la proporción 199.566×147.731 del badge exterior del
   Figma: esa forma es solo el fondo alrededor del logo, y el archivo real
   (logo.webp) es cuadrado (400×400) — con la proporción del badge,
   object-fit: cover lo recortaba por arriba y por abajo. Mismo patrón que
   .nav__logo. */
.footer__logo {
  display: block;
  width: clamp(96px, 14vw, 140px);
  height: clamp(96px, 14vw, 140px);
  border-radius: 0 0 40% 40%;
  overflow: hidden;
}

.footer__logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.footer__nombre {
  margin: 0;
  text-align: center;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.25;
  color: var(--color-blanco);
}

.footer__copyright {
  margin: 0;
  text-align: center;
  font-family: var(--fuente-base);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-blanco);
}

.footer__columna {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  text-align: center;
}

.footer__titulo-columna {
  margin: 0;
  font-family: var(--fuente-base);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.4;
  color: #fbf6ef;
}

.footer__columna a,
.footer__columna span {
  font-family: var(--fuente-base);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-blanco);
  text-decoration: none;
}

.footer__columna a:focus-visible {
  text-decoration: underline;
}

@media (hover: hover) {
  .footer__columna a:hover {
    text-decoration: underline;
  }
}

@media (min-width: 768px) {
  .footer__top {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: clamp(24px, 4vw, 64px);
  }

  .footer__marca {
    align-items: flex-start;
  }

  .footer__nombre,
  .footer__copyright {
    text-align: left;
  }

  .footer__columna {
    align-items: flex-start;
    gap: 12px;
    text-align: left;
  }
}

/* -------------------- WhatsApp flotante -------------------- */

.whatsapp-flotante {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 999px;
  background: var(--color-primario-oscuro);
  color: var(--color-blanco);
  transition: background-color 0.25s ease, transform 0.25s ease;
}

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

@media (hover: hover) {
  /* Ya parte del morado más oscuro de los dos tokens (--color-primario-
     -oscuro), así que el hover necesita un tercer tono, más oscuro
     todavía — no hay ningún token para eso, de ahí el hexadecimal suelto. */
  .whatsapp-flotante:hover {
    background: #3d1f47;
    transform: scale(1.06);
  }
}

@media (min-width: 768px) {
  .whatsapp-flotante {
    right: 32px;
    bottom: 32px;
    width: 88px;
    height: 88px;
  }

  .whatsapp-flotante svg {
    width: 34px;
    height: 34px;
  }
}

/* -------------------- Menú móvil -------------------- */

@media (max-width: 767px) {
  /* En el diseño móvil el nav mide más (126px) que en escritorio (106px);
     no es un típico "encoge en móvil", así que se fija aparte del clamp. */
  :root {
    --nav-alto: 126px;
  }

  /* Más grande que en escritorio (era el mismo clamp de 56-96px), pero sin
     tocar --nav-alto: la barra ya mide 126px, así que hay margen de sobra
     para agrandar el logo sin que la barra tenga que crecer con él. */
  .nav__logo {
    width: 104px;
    height: 104px;
  }

  .nav__hamburguesa {
    display: block;
    /* La caja del botón ya queda tan pegada al borde como el logo al suyo
       (mismo padding del contenedor), pero el icono no "rellena" su propia
       caja como sí hace el logo (es un trazo fino con aire alrededor,
       dentro además del padding del botón), así que ópticamente parece
       más pegado. Este margen extra lo compensa. */
    margin-right: 12px;
  }

  .hero__eyebrow {
    font-size: 14px;
    letter-spacing: 1.4px;
  }

  .hero__ctas {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }

  /* Medido sobre el frame móvil de Figma: el cuerpo de la tarta ocupa ~84%
     del ancho de pantalla (recorte propio en vertical, 504×788). */
  .hero__imagen {
    width: min(84vw, 480px);
    height: auto;
    /* La foto correcta para este hueco es la ancha (643×716) que ya usa
       escritorio, recortada aparte para móvil — no la vertical (504×788),
       que es la del menú a pantalla completa (ver .nav__decoracion). */
    aspect-ratio: 700 / 716;
    max-height: 55vh;
  }

  .testimonios {
    border-left: none;
    border-top: 20px solid var(--color-primario);
    padding-left: 20px;
    padding-right: 20px;
  }

  .testimonio__autor {
    margin-top: 40px;
  }

  /* Al menos el doble que en el clamp base: separación de "Cuéntame tu
     idea" a la foto, y de la foto al bloque "Visita el obrador". */
  .sobre-mi__intro {
    gap: clamp(80px, 16vw, 128px);
  }

  .sobre-mi__visita {
    margin-top: clamp(128px, 20vw, 280px);
  }

  /* El menú ocupa toda la pantalla (100dvh, no solo un desplegable bajo la
     barra), con el logo y el aspa de la cabecera siempre visibles encima
     (ver z-index de .nav__hamburguesa/.nav__logo más arriba). */
  .nav__derecha {
    position: fixed;
    inset: 0;
    height: 100dvh;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 40px;
    background: var(--color-blanco);
    overflow-y: auto;
    padding: calc(var(--nav-alto) + 80px) clamp(20px, 6vw, 64px) 40px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s;
  }

  .nav__enlaces {
    flex-direction: column;
    align-items: flex-start;
    gap: 40px;
  }

  .nav__enlaces a {
    padding: 0;
    border-radius: 0;
    font-family: var(--fuente-titular);
    font-weight: 700;
    font-size: 40px;
    line-height: 1;
    color: var(--color-primario-oscuro);
    background: none;
  }

  /* Alterna oscuro/claro enlace a enlace, tal como está en el diseño. */
  .nav__enlaces li:nth-child(even) a {
    color: var(--color-primario);
  }

  .nav__derecha .boton--primario {
    margin: 0;
  }

  /* Fundido desde la izquierda hasta su posición final, en cascada: cada
     enlace (y el botón, al final) sale un poco después que el anterior.
     Con el menú cerrado ya están en su sitio pero invisibles y desplazados,
     listos para deslizarse en cuanto se abra. */
  .nav__enlaces a,
  .nav__derecha > .boton--primario {
    opacity: 0;
    transform: translateX(-32px);
    transition: opacity 0.4s ease, transform 0.4s ease;
  }

  .nav__enlaces li:nth-child(1) a {
    transition-delay: 0.08s;
  }

  .nav__enlaces li:nth-child(2) a {
    transition-delay: 0.16s;
  }

  .nav__enlaces li:nth-child(3) a {
    transition-delay: 0.24s;
  }

  .nav__enlaces li:nth-child(4) a {
    transition-delay: 0.32s;
  }

  .nav__derecha > .boton--primario {
    transition-delay: 0.4s;
  }

  /* Fuera del flujo (position: absolute) a propósito: así no cuenta para
     la altura del panel y los enlaces + el botón caben siempre en 100dvh,
     sin scroll. Esquina inferior derecha, por detrás del botón si hace
     falta (z-index negativo) — así lo ha pedido el cliente. */
  .nav__decoracion {
    display: block;
    position: absolute;
    top:50%;
    right: 0;
    bottom: 0;
    z-index: -1;
    width: min(92vw, 480px);
    pointer-events: none;
  }

  .nav__decoracion img {
    display: block;
    width: 100%;
    height: auto;
  }

  .nav[data-menu-abierto='true'] .nav__derecha {
    opacity: 1;
    visibility: visible;
  }

  .nav[data-menu-abierto='true'] .nav__enlaces a,
  .nav[data-menu-abierto='true'] .nav__derecha > .boton--primario {
    opacity: 1;
    transform: translateX(0);
  }
}

/* A partir de aquí hay hueco para que los filtros quepan en una fila y las
   fotos grandes de móvil dejen de tener sentido: cabecera en fila, filtros
   como píldoras siempre visibles, rejilla de 2 columnas sin fotos grandes.
   No hay diseño de Figma específico para este rango (768–1099px); es un
   punto intermedio razonable entre el móvil y el de escritorio (≥1100px). */
@media (min-width: 768px) {
  .galeria__cabecera {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .galeria__instagram {
    width: auto;
  }

  .galeria__filtros-toggle {
    display: none;
  }

  .galeria__filtros-lista {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    position: static;
    width: fit-content;
    margin: 0 auto;
    gap: clamp(20px, 4vw, 60px);
    padding: 24px clamp(24px, 5vw, 60px);
    background: var(--color-fondo-hero);
    border-radius: 200px;
    box-shadow: none;
  }

  .filtro {
    width: auto;
    padding: 0;
    border-radius: 0;
  }

  .filtro[aria-pressed="true"] {
    background: none;
  }

  .galeria__tarjeta:nth-child(1),
  .galeria__tarjeta:nth-child(2) {
    grid-column: auto;
  }
}

@media (min-width: 1100px) {
  .galeria__rejilla {
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    /* Reserva el hueco que ocupa visualmente el escalonado de abajo (ver
       nota siguiente), para que no se pise con lo que viene después. */
    padding-bottom: 59px;
  }

  /* El escalonado del diseño: la 2ª y 4ª columna de cada fila de 4 bajan
     59px respecto a la 1ª y 3ª. Con transform (vía --tarjeta-y, ver la
     animación de entrada más arriba) en vez de margin-top: un margin ahí
     infla la altura de toda la fila en el grid (afectando también a las
     columnas sin desplazar), que es justo lo que separaba verticalmente
     más que en horizontal. transform no participa en el cálculo del grid,
     así que el espaciado real se queda en los 24px del "gap" y el
     desplazamiento es solo visual. */
  .galeria__tarjeta:nth-child(4n + 2),
  .galeria__tarjeta:nth-child(4n) {
    --tarjeta-y: 59px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav__enlaces {
    transition: none;
  }

  .nav__hamburguesa-linea,
  .nav__derecha,
  .nav__enlaces a,
  .nav__derecha > .boton--primario {
    transition: none;
  }
}

/* -------------------- Animaciones al entrar en pantalla -------------------- */
/* Cada bloque entra una sola vez, la primera vez que cruza el viewport
   (assets/js/revelar.js, con IntersectionObserver — no vuelve a animarse
   si se sube y se baja otra vez). Los contenedores marcados
   ".reveal-grupo" reparten un pequeño retraso entre sus hijos directos
   ".reveal" para que entren en cascada en vez de todos a la vez. */
.reveal {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.reveal--izquierda {
  transform: translateX(-48px);
}

.reveal--derecha {
  transform: translateX(48px);
}

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

/* La foto del hero entra un poco después de que termine de aparecer el
   texto (ver el reveal-grupo de .hero__contenido), no a la vez. Se centra
   con left:50% + translateX(-50%) (ver .hero__imagen más arriba): el
   "transform" del reveal genérico no puede pisar ese translateX sin
   descentrarla, así que aquí se combinan los dos en una sola declaración
   en vez de usar los modificadores --izquierda/--derecha. */
.hero__imagen.reveal {
  transition-delay: 0.25s;
  transform: translateX(-50%) translateY(28px) scale(0.94);
}

.hero__imagen.reveal.reveal--visible {
  transform: translateX(-50%) translateY(0) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
