/* =========================================================================
   Casa Lavalle — mosaico.css
   Piezas compartidas por /galeria y /proyectos: el mosaico de filas
   justificadas y el lightbox. Se carga después de styles.css y antes del CSS
   de cada página (que solo aporta su cabecera y su ritmo vertical).
   Mobile-first: base = 0–767px, md = 768px, xl = 1280px.
   ========================================================================= */

/* ---------- Utilidades ---------- */
/* Texto solo para lectores de pantalla (estados de filtro, aria-live). */
.u-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Mosaico ----------
   Filas justificadas. mosaico.js agrupa las figuras en .mosaico__row; dentro de
   cada fila el flex-grow de cada figura es su relación de aspecto y el
   flex-basis es 0, así que el ancho de cada foto queda proporcional a su ratio
   y TODAS terminan a la misma altura:

     ancho_i  = libre * r_i / Σr        (libre = fila - gaps)
     alto_i   = ancho_i / r_i = libre / Σr   → idéntico para toda la fila

   De ahí salen las dos cosas que se pidieron a la vez: la fila cierra al ras en
   ambos márgenes (simétrico) y ninguna foto se recorta (tamaño original). Por
   eso la imagen va con height:auto y sin object-fit: el alto lo determina el
   ancho que reparte el flex. */
.mosaico__grid {
  display: flex;
  flex-direction: column;
  gap: clamp(9px, 1.5vw, 16px);
}

/* Las filas justificadas son el sistema en TODOS los anchos (2026-07-21). En
   móvil son filas de dos, emparejadas por orientación desde mosaico.js, así que
   las dos fotos salen del mismo ancho y a la misma altura: las columnas quedan
   alineadas y la fila cierra al ras en ambos márgenes, igual que en desktop.

   Antes el móvil usaba mampostería (`columns: 2`): nada se recortaba, pero las
   fotos no se alineaban entre columnas, el fondo del mosaico quedaba
   desnivelado —157px en /galeria, la franja blanca delante del footer— y el
   orden curado se leía hacia abajo por la columna izquierda y luego por la
   derecha, en vez de en renglones. */
.mosaico__row {
  display: flex;
  gap: clamp(9px, 1.5vw, 16px);
}

.mosaico__fig {
  margin: 0;
  overflow: hidden;
  border-radius: 6px;
  /* --r lo escribe mosaico.js con el ratio real de cada foto. Se multiplica por
     10 porque flexbox solo reparte TODO el espacio libre cuando la suma de los
     flex-grow de la fila llega a 1: una fila con un solo vertical (r = 0.667)
     se quedaba al 67% del ancho y dejaba un hueco al margen. Escalar no altera
     las proporciones, que es lo único que importa una vez pasado ese umbral. */
  flex: calc(var(--r, 1) * 10) 1 0;
  min-width: 0;
}
.mosaico__link {
  display: block;
  cursor: zoom-in;
}
.mosaico__img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 0.8s var(--ease-out);
  will-change: transform;
}

/* Sin JS no hay filas: la lista plana cae a un wrap simple para que el mosaico
   siga siendo navegable. */
html:not(.js) .mosaico__grid { flex-direction: row; flex-wrap: wrap; }
html:not(.js) .mosaico__fig { flex: 0 1 calc(50% - 8px); }   /* la mitad del gap máximo */

/* Hover sereno, coherente con el teaser de la landing (solo pointer). */
@media (hover: hover) {
  .mosaico__fig:hover .mosaico__img { transform: scale(1.04); }
}

/* ---------- Lightbox ----------
   Foto ampliada sobre fondo oscuro. Cerrado por defecto; mosaico.js alterna
   .is-open. La transición es un fade simple (la puerta del Hero sigue siendo
   el único momento orquestado del sitio). */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;                     /* sobre nav (120) y page-cover (200) */
  display: flex;
  align-items: center;
  justify-content: center;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out), visibility 0s linear 0.3s;
}
.lightbox.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s var(--ease-out);
}

.lightbox__scrim {
  position: absolute;
  inset: 0;
  background: rgba(16, 16, 16, 0.94);
}

.lightbox__stage {
  position: relative;
  margin: 0;
  /* Aire para que los controles nunca se encimen a la foto. */
  width: min(100% - 32px, 1200px);
  height: calc(100% - 128px);
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: pan-y;              /* swipe horizontal propio */
}
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 4px;
  user-select: none;
  -webkit-user-drag: none;
}

/* Controles: trazo fino marfil, targets de 48px. */
.lightbox__btn {
  position: absolute;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  cursor: pointer;
  color: var(--marfil);
  transition: color 0.3s var(--ease-out);
}
.lightbox__btn:hover { color: var(--bronce-anzures); }
.lightbox__btn svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lightbox__btn--close { top: 12px; right: 12px; }
.lightbox__btn--prev { left: 4px; top: 50%; transform: translateY(-50%); }
.lightbox__btn--next { right: 4px; top: 50%; transform: translateY(-50%); }

.lightbox__count {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  color: rgba(247, 244, 239, 0.7);
}

/* Scroll lock mientras el lightbox está abierto (mosaico.js). */
html.lb-open, html.lb-open body { overflow: hidden; }

/* =========================================================================
   md — @media (min-width: 768px)
   ========================================================================= */
@media (min-width: 768px) {
  /* El cap en --page-max (1280px) no es estético sino de nitidez: con él las
     filas reparten alturas de ~340-450px, y como la fuente más angosta de la
     selección son los retratos de 845px, TODA foto se dibuja por encima de 2x.
     Sin el cap, en pantallas anchas las tomas de 1280px se verían suaves. */
  .mosaico__grid {
    max-width: var(--page-max);
    margin-inline: auto;
  }

  .lightbox__btn--prev { left: 16px; }
  .lightbox__btn--next { right: 16px; }
  .lightbox__btn--close { top: 20px; right: 20px; }
}
