/* ARTE[FACTO] — sitio estático
   Diseño: Ana Cantello (Figma "ArteFacto Web", página "Opción [Final]").

   El diseño está construido sobre una grilla de 12 columnas: canvas de 1440px,
   márgenes laterales de 60px, gutter de 32px (columna = 80,667px). Todas las
   posiciones del Figma caen exactas en esa grilla, así que acá se reproduce con
   CSS Grid nativo.

   --u equivale a 1 píxel del diseño: escala proporcional hasta 1440px y se
   detiene ahí (arriba de 1440 el canvas queda centrado). Con eso, cualquier
   medida del Figma se escribe como calc(N * var(--u)).
   ========================================================================== */

/* ── Tokens ────────────────────────────────────────────────────────────────── */
:root {
  --canvas: 1440;
  --u: calc(min(100vw, 1440px) / var(--canvas));
  --ancho-max: 1440px;
  --margen: calc(60 * var(--u));
  --gutter: calc(32 * var(--u));

  --fondo: #fbf8f9;
  --fondo-banda: #eceae3;
  --amarillo: #f1d40d;
  --tinta: #000000;
  --acento: #e94e24;
  /* La línea debajo de los artistas: negro al 10%, como en el diseño. */
  --linea-tenue: rgba(0, 0, 0, 0.1);

  /* Opacidades del diseño para texto secundario.
     OJO: con estos valores el contraste queda por debajo del 4.5:1 que pide
     WCAG AA para texto normal (medido sobre --fondo: 0.5 -> 4.0:1,
     0.6 -> 2.3:1, 0.7 -> 3.0:1). Están así por fidelidad al Figma; subirlas a
     ~0.82 cumple AA y es un cambio de una línea. Ver nota en el README. */
  /* [PROYECTO] y [ARTISTAS]: negro al 40%, indicación de Ana. Igual en desktop
     y en mobile. */
  --op-rotulo: 0.4;
  --op-origen: 0.5;
  --op-lugar: 0.7;
  --op-credito: 0.5;

  --sans: "tt-commons-pro", system-ui, -apple-system, "Segoe UI", sans-serif;
  --display: "tiffin-latin-variable", system-ui, sans-serif;

  /* Escala tipográfica: mínimo a 375px, máximo = valor del Figma a 1440px. */
  --fs-titulo: clamp(2rem, 4.24vw, 3.8125rem);          /* 32 → 61 */
  --fs-pregunta: clamp(2rem, 5.35vw, 4.8125rem);        /* 32 → 77 */
  --fs-respuesta: clamp(1.1875rem, 2.36vw, 2.125rem);   /* 19 → 34 */
  --fs-entrada: clamp(1.1875rem, 1.74vw, 1.5625rem);    /* 19 → 25 */
  --fs-cuerpo: clamp(1rem, 1.39vw, 1.25rem);            /* 16 → 20 */
  --fs-nombre: clamp(1.125rem, 1.74vw, 1.5625rem);      /* 18 → 25 */
  --fs-pie-obra: clamp(0.8125rem, 1.11vw, 1rem);        /* 13 → 16 */
  --fs-rotulo: clamp(0.9375rem, 1.39vw, 1.25rem);       /* 15 → 20 */
  --fs-tienda: clamp(1.75rem, 3.19vw, 2.875rem);        /* 28 → 46 */
  --fs-menor: clamp(0.875rem, 1.18vw, 1.0625rem);       /* 14 → 17 */
  --fs-menu: clamp(2rem, 3.47vw, 3.125rem);             /* 32 → 50 */
  /* El bloque de contacto del menú va a la mitad del tamaño que tenía (38 → 19 y
     30 → 15), pero SÓLO de tablet para arriba: en mobile el tamaño original ya
     estaba aprobado y se restaura en el bloque <768px. */
  --fs-menu-titulo: clamp(1rem, 1.32vw, 1.1875rem);     /* 16 → 19 */
  --fs-menu-dato: clamp(0.8125rem, 1.04vw, 0.9375rem);  /* 13 → 15 */
  --fs-menu-credito: clamp(0.75rem, 0.97vw, 0.875rem);  /* 12 → 14 */

  /* GSAP power3.out / power2.out como cubic-bezier equivalentes. */
  --ease-salida: cubic-bezier(0.215, 0.61, 0.355, 1);
  --ease-suave: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  /* El easing que pidió Ana para el menú. */
  --ease-menu: cubic-bezier(0.16, 1, 0.3, 1);
  /* Suave en los dos extremos, para la subida larga del logo. */
  --ease-logo: cubic-bezier(0.65, 0, 0.35, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* Al llegar por un ancla del menú, deja aire arriba del título en vez de
   pegarlo al borde de la pantalla. */
:target,
#arriba,
#proyecto,
#artistas,
#tienda {
  scroll-margin-top: calc(120 * var(--u));
}

body {
  margin: 0;
  background: var(--fondo);
  color: var(--tinta);
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--fs-cuerpo);
  line-height: 1.42;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, figure { margin: 0; }
img, svg { display: block; max-width: 100%; }
strong { font-weight: 600; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 3px;
}

/* ── Utilidades ───────────────────────────────────────────────────────────── */
.u-solo-lectores {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.u-saltar {
  position: absolute;
  top: 0; left: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--tinta);
  color: var(--fondo);
  font-size: 1rem;
  text-decoration: none;
  transform: translateY(-120%);
  transition: transform 0.2s var(--ease-salida);
}
.u-saltar:focus { transform: translateY(0); }

/* ── Grilla de 12 columnas ────────────────────────────────────────────────── */
.reja {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding-inline: var(--margen);
}

/* ── Riel derecho: menú + marca vertical ──────────────────────────────────── */
/* Figma nodo 161:3947: el bloque va @1360,45 con 248px entre el ícono y la
   marca. Acá va fixed para que el menú siga alcanzable en una página de
   ~5000px de alto. */
/* Queda FUERA del contenedor: pegado al borde derecho del viewport, no alineado
   al canvas de 1440. Y en la misma posición exacta que la × del menú, así el
   ícono se transforma en su lugar. */
.riel {
  position: fixed;
  top: calc(70 * var(--u));
  right: calc(60 * var(--u));
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(248 * var(--u));
}

.riel__menu {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;   /* área táctil mínima */
  margin: -10px;               /* sin desplazar el ícono de 24px del diseño */
  padding: 0;
  border: 0;
  background: none;
  color: #131313;
  cursor: pointer;
}
.riel__menu svg { width: 24px; height: 24px; }

/* La marca lleva al tope de la página. */
.riel__marca {
  font-size: calc(17 * var(--u));
  font-weight: 500;
  writing-mode: vertical-rl;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: color 0.3s var(--ease-suave);
}
.riel__marca:hover,
.riel__marca:focus-visible { color: var(--acento); }

/* ── Menú ─────────────────────────────────────────────────────────────────── */
/* Panel "Navegación" del Figma (nodo 135:3173): 705px anclado a la derecha,
   fondo amarillo. La × cae en x=1356, exactamente donde está la hamburguesa. */
/* Capa para cerrar haciendo clic fuera del panel. Sin color: no se ve. Sólo
   recibe clics cuando el menú está abierto, así el resto del tiempo no estorba. */
.menu__fondo {
  position: fixed;
  inset: 0;
  z-index: 29;
  pointer-events: none;
}
.tiene-menu-abierto .menu__fondo { pointer-events: auto; }

/* El panel entra deslizándose desde el costado derecho y sale más rápido.
   Cerrado queda con visibility hidden y pointer-events none para no interferir
   con la navegación. */
.menu {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 30;
  width: min(calc(705 * var(--u)), 100%);
  background: var(--amarillo);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(100%);
  visibility: hidden;
  pointer-events: none;
  transition:
    transform 0.4s var(--ease-menu),
    visibility 0s linear 0.4s;
}

/* Apertura un 25% más lenta que la especificación original (0.55s → 0.69s).
   El cierre sigue en 0.4s, que Ana pidió más rápido que la apertura. */
.menu.esta-abierto {
  transform: translateX(0);
  visibility: visible;
  pointer-events: auto;
  transition:
    transform 0.69s var(--ease-menu),
    visibility 0s;
}

/* Entrada en cascada del contenido: cada ítem lleva su índice en --i. */
.menu__item {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.5s var(--ease-menu),
    transform 0.5s var(--ease-menu);
  transition-delay: 0s;
}
/* El stagger se mantiene en los 0.05s que pidió Ana; lo que se escaló es el
   fundido y el retraso inicial, para acompañar la apertura más lenta. */
.menu.esta-abierto .menu__item {
  opacity: var(--op-final, 1);
  transform: translateY(0);
  transition-delay: calc(0.19s + var(--i, 0) * 0.05s);
}

.menu__cerrar {
  position: absolute;
  top: calc(70 * var(--u));
  right: calc(60 * var(--u));
  display: grid;
  place-items: center;
  width: 44px; height: 44px;   /* área táctil mínima */
  margin: -10px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--tinta);
  cursor: pointer;
}
.menu__cerrar svg { width: 24px; height: 24px; }

/* El contenido arranca a 80px del borde del panel y hay 120px arriba y abajo;
   entre los dos bloques el diseño deja 355px, que acá resuelve space-between. */
.menu__interior {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: calc(80 * var(--u));
  padding: calc(120 * var(--u)) calc(60 * var(--u)) calc(120 * var(--u)) calc(80 * var(--u));
}

.menu__lista,
.menu__contacto {
  margin: 0;
  padding: 0;
  list-style: none;
}

.menu__lista {
  display: grid;
  gap: calc(50 * var(--u));
}
.menu__lista a {
  display: inline-block;
  font-size: var(--fs-menu);
  line-height: 1.1;
  text-decoration: none;
  transition: color 0.3s var(--ease-suave);
}
.menu__lista a:hover,
.menu__lista a:focus-visible { color: var(--acento); }

/* Las separaciones del bloque también van a la mitad: con el texto a mitad de
   tamaño y los huecos de antes, el bloque quedaba desarmado. */
.menu__pie { display: grid; gap: calc(13 * var(--u)); }

.menu__titulo {
  font-size: var(--fs-menu-titulo);
  font-weight: 400;
  line-height: 1.1;
}

.menu__contacto {
  display: grid;
  gap: calc(4 * var(--u));
  font-size: var(--fs-menu-dato);
  line-height: 1.15;
}
.menu__contacto a { text-decoration: underline; }

.menu__credito {
  font-size: var(--fs-menu-credito);
  line-height: 1.15;
  opacity: var(--op-credito);
  --op-final: var(--op-credito);
}

/* El crédito enlaza al Behance de Ana. Se mantiene sin subrayado, como el
   diseño, y se revela como link al pasar el cursor. */
.menu__credito a,
.pie__credito a { text-decoration: none; }

.menu__contacto a:hover,
.menu__contacto a:focus-visible,
.menu__credito a:hover,
.menu__credito a:focus-visible {
  color: var(--acento);
}

/* ── Portada ──────────────────────────────────────────────────────────────── */
.portada { padding-top: calc(150 * var(--u)); }

.portada__logo,
.portada__bajada { grid-column: 1 / -1; }

/* El logo mide 695 de los 1320 del área de contenido. */
.portada__logo svg { width: 52.65%; height: auto; }

.portada__bajada {
  margin-top: calc(30 * var(--u));
  font-size: var(--fs-titulo);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

/* El logo NO va recortado: arranca abajo en la pantalla, entero y visible, y
   sube hasta su lugar (ver el bloque de animación). La bajada sí usa máscara. */
.portada__bajada { overflow: hidden; }
.portada__logo svg,
.portada__bajada > span { display: block; }

/* ── Collage ──────────────────────────────────────────────────────────────── */
.collage { margin-top: calc(64 * var(--u)); }

.collage__caja {
  position: relative;
  max-width: var(--ancho-max);
  margin-inline: auto;
  aspect-ratio: 1440 / 1389;
}

/* Sin overflow:hidden: el parallax mueve la obra completa (flota), no la imagen
   dentro de un marco recortado. */
.collage__obra { position: absolute; }
.collage__obra picture { display: block; }
.collage__obra img { width: 100%; height: auto; }

/* ── [proyecto] ───────────────────────────────────────────────────────────── */
/* Sube 202px para solaparse con el final del collage, como en el diseño. */
.proyecto { margin-top: calc(-202 * var(--u)); }

.rotulo {
  font-size: var(--fs-rotulo);
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  opacity: var(--op-rotulo);
  --op-final: var(--op-rotulo);
}

.proyecto > .rotulo { grid-column: 5 / span 7; }

.proyecto__cuerpo {
  grid-column: 5 / span 7;
  margin-top: calc(20 * var(--u));
  display: grid;
  gap: calc(15 * var(--u));
  /* 17px en desktop y no 20. Se midió el borde derecho de las 16 líneas de los 5
     párrafos en la columna real de 757px, probando de 17 a 20px:
       20px → hueco promedio 36px, peor línea 154px, 3 líneas con más de 60px
       17px → hueco promedio 23px, peor línea  81px, 1 línea
     No baja de forma progresiva: 19px y 18,5px quedan PEOR que 20 (47 y 55 de
     promedio), porque el resultado depende de dónde caen los cortes y no del
     tamaño. Tampoco ayuda text-wrap: pretty (39px), y balance es inservible en
     párrafos (130px): está pensado para títulos.
     En mobile se midió aparte, en las columnas reales de dos teléfonos (320px en
     un Galaxy S22 y 353px en un Motorola Edge 50 Neo). Ahí el mínimo va en 16,5px
     y no en 16:
       320px → hueco promedio 23,5px contra 24,9
       353px → hueco promedio 29,4px contra 33,2, y peor línea 72px contra 74
     Subir a 17px es el PEOR de todos en los tres anchos (hasta 122px de hueco),
     así que el ajuste va para abajo, no para arriba.
     Desktop no cambia: a 1440px el término en vw ya da 17px. */
  font-size: clamp(1.03125rem, 1.18vw, 1.0625rem);
}

.proyecto__entrada {
  font-size: var(--fs-entrada);
  line-height: 1.35;
}
/* La primera frase lleva sangría, pero NO va en un bloque aparte: antes estaba
   alineada a la derecha en su propio span y en mobile se partía en dos, dejando
   "galería" sola en una línea. Con text-indent es un párrafo único que fluye.
   Como el partidor de líneas convierte cada línea en su propio bloque, y
   text-indent se hereda, hay que anularlo en todas menos la primera; si no, la
   sangría se aplicaría a cada línea. */
.proyecto__entrada { text-indent: 15%; }
.proyecto__entrada .linea:not(:first-child) { text-indent: 0; }

.proyecto__direccion {
  margin-top: calc(5 * var(--u));
  font-weight: 500;
  line-height: 1.45;
}

/* ── Banda de la pregunta ─────────────────────────────────────────────────── */
.pregunta {
  margin-top: calc(126 * var(--u));
  padding-block: calc(60 * var(--u)) calc(90 * var(--u));
  background: var(--fondo-banda);
}

.pregunta__texto {
  grid-column: 4 / span 8;
  font-family: var(--display);
  font-weight: 300;
  font-size: var(--fs-pregunta);
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-align: right;
}

.pregunta__respuesta {
  grid-column: 5 / span 7;
  margin-top: calc(35 * var(--u));
  font-size: var(--fs-respuesta);
  text-align: right;
}

/* ── [Artistas] ───────────────────────────────────────────────────────────── */
.artistas { margin-top: calc(100 * var(--u)); }

/* El rótulo arranca en la columna 2, como en el diseño. */
.rotulo--artistas { grid-column: 2 / span 4; }

.artistas__tabs {
  grid-column: 1 / -1;
  margin-top: calc(40 * var(--u));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(40 * var(--u)) calc(40 * var(--u));
}

.artistas__tab {
  position: relative;
  padding: 0;
  border: 0;
  background: none;
  color: var(--tinta);
  font-family: inherit;
  font-size: var(--fs-nombre);
  font-weight: 500;
  line-height: 1.15;
  cursor: pointer;
  transition: color 0.3s var(--ease-suave);
}
.artistas__tab:hover { color: var(--acento); }

.artistas__tab[aria-selected="true"] { color: var(--acento); }

/* El punto del diseño: 6px, a 13px del borde derecho del nombre. */
.artistas__tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  right: calc(10 * var(--u));
  bottom: calc(-11 * var(--u));
  width: calc(6 * var(--u));
  height: calc(6 * var(--u));
  border-radius: 50%;
  background: var(--acento);
}

.artistas__paneles {
  grid-column: 1 / -1;
  margin-top: calc(61 * var(--u));
  padding-top: calc(20 * var(--u));
  border-top: 1px solid var(--linea-tenue);
  transition: height 0.45s var(--ease-suave);
}

/* Red de seguridad, sólo mientras el alto está animado: así nada puede
   desbordar y pisar las secciones siguientes, y en reposo tampoco se recorta
   nada. */
.artistas__paneles.esta-animando { overflow: hidden; }

.artista {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
}
/* Sin JS se ven las seis fichas. Con JS, sólo la activa: se oculta por CSS
   antes del primer pintado y site.js además maneja el atributo hidden. */
.js .artista:not(.esta-activa) { display: none; }
.artista[hidden] { display: none; }

.artista__ficha { grid-column: 1 / span 4; }
.obra--centro   { grid-column: 5 / span 4; }
.obra--derecha  { grid-column: 9 / span 3; }

.artista__origen {
  line-height: 1.45;
  opacity: var(--op-origen);
}

.artista__bio { margin-top: calc(24 * var(--u)); }

.obra--izquierda { margin-top: calc(50 * var(--u)); }

/* ── Obras ────────────────────────────────────────────────────────────────── */
.obra > picture {
  display: block;
  overflow: hidden;   /* contiene el zoom del hover dentro del marco */
}
.obra img {
  width: 100%;
  height: auto;
  transition: transform 0.4s var(--ease-suave);
}
.obra > picture:hover img { transform: scale(1.05); }

.obra__pie {
  margin-top: calc(15 * var(--u));
  display: grid;
  font-size: var(--fs-pie-obra);
  line-height: 1.4;
  text-align: right;
}
.obra__titulo { font-weight: 600; }

/* ── Banda de la tienda ───────────────────────────────────────────────────── */
.tienda {
  margin-top: calc(144 * var(--u));
  /* La banda mide 395 en el diseño, con el contenido centrado vertical. */
  min-height: calc(395 * var(--u));
  padding: calc(60 * var(--u)) var(--margen);
  background: var(--amarillo);
  display: grid;
  align-content: center;
  justify-items: center;
  text-align: center;
}

.tienda__titulo {
  font-size: var(--fs-tienda);
  font-weight: 500;
  line-height: 1.15;
}

.tienda__bajada {
  max-width: calc(870 * var(--u));
  margin-top: calc(9 * var(--u));
}

.tienda__boton {
  margin-top: calc(30 * var(--u));
  padding: calc(10 * var(--u));
  min-width: calc(225 * var(--u));
  display: grid;
  place-items: center;
  border: 1px solid var(--tinta);
  font-size: var(--fs-menor);
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color 0.3s var(--ease-suave), color 0.3s var(--ease-suave);
}
/* Hover en rojo, igual que los links (indicación de Ana). */
.tienda__boton:hover,
.tienda__boton:focus-visible {
  color: var(--acento);
  border-color: var(--acento);
}

/* ── Página de error (404.html) ───────────────────────────────────────────── */
/* Sin diseño propio de Ana: se arma sólo con sus elementos — el fondo, el logo,
   la escala tipográfica de la portada y su recurso de los corchetes. */
.error {
  min-height: 100svh;
  align-content: start;
  padding-top: calc(150 * var(--u));
}

.error__logo,
.error__rotulo,
.error__mensaje,
.error > p { grid-column: 1 / -1; }

.error__logo { margin: 0; }
.error__logo img { width: 52.65%; height: auto; }

.error__rotulo { margin-top: calc(60 * var(--u)); }

.error__mensaje {
  margin-top: calc(20 * var(--u));
  font-size: var(--fs-titulo);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.error__volver {
  display: inline-block;
  margin-top: calc(40 * var(--u));
  font-size: var(--fs-respuesta);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  transition: color 0.3s var(--ease-suave);
}
.error__volver:hover,
.error__volver:focus-visible { color: var(--acento); }

@media (max-width: 767px) {
  .error { padding-top: 72px; }
  .error__logo img { width: 100%; }
}

/* ── Pie ──────────────────────────────────────────────────────────────────── */
.pie {
  display: flex;
  flex-wrap: wrap;
  gap: calc(40 * var(--u));
  justify-content: space-between;
  align-items: flex-start;
  max-width: var(--ancho-max);
  margin-inline: auto;
  padding: calc(80 * var(--u)) var(--margen);
}

.pie__marca img { width: calc(193 * var(--u)); height: auto; }

.pie__bajada {
  margin-top: calc(15 * var(--u));
  font-size: calc(18 * var(--u));
  font-weight: 600;
}

.pie__datos {
  display: grid;
  gap: calc(7 * var(--u));
  font-size: var(--fs-menor);
  text-align: right;
}
.pie__datos a { text-decoration: none; }
/* Hover en rojo, como el resto de los links (indicación de Ana). */
.pie__datos a:hover,
.pie__datos a:focus-visible {
  color: var(--acento);
  text-decoration: underline;
}
.pie__lugar { opacity: var(--op-lugar); }
/* Mismo tamaño que el crédito del menú: comparten el token para que no puedan
   volver a desincronizarse. */
.pie__credito {
  font-size: var(--fs-menu-credito);
  opacity: var(--op-credito);
}

/* ══ Animaciones ══════════════════════════════════════════════════════════════
   Especificación de Ana: reveal/mask-up en la portada, fade+scale de entrada y
   parallax suave en el collage, mask reveal en cascada en los textos, y entrada
   escalonada en las fichas de artista. */

/* ── Reveal de portada al cargar ───────────────────────────────────────────────
   El logo arranca ABAJO en la pantalla, entero y visible, y sube suavemente
   hasta su posición: el mismo efecto que la palabra "Photography" en
   brand.squarespace.com/photography, que recorre ~44% del alto del viewport.
   Por eso el desplazamiento va en vh y no en % de su propia altura: con % sólo
   subiría 119px, que es su alto, y el gesto se pierde.
   Se queda abajo 0.5s y recién entonces sube, en 1.4s y con un easing suave en
   los dos extremos, para que no dé un tirón al arrancar ni al llegar. */
.portada__logo svg {
  transform: translateY(66vh);
  transition: transform 1.4s var(--ease-logo) 0.5s;
}
.esta-cargado .portada__logo svg { transform: translateY(0); }

/* El logo entra como "ARTE[]" y se completa mientras sube: el corchete de cierre
   se corre hacia la derecha y FACTO aparece con un fundido.
   Los 339px del desplazamiento son unidades del viewBox del SVG, no píxeles de
   pantalla: dentro de un SVG los transform en px se aplican en su sistema de
   coordenadas, así que el gesto escala solo en desktop, tablet y mobile sin
   necesidad de un valor por breakpoint.
   El estado inicial va detrás de .js para que sin JS el logo se vea completo. */
.js .logo__facto { opacity: 0; }
.js .logo__cierra { transform: translateX(-339px); }

/* Los tiempos caen dentro de la subida del logo (0.5s → 1.9s): el corchete abre
   entre 0.7s y 1.5s, y FACTO aparece entre 1.0s y 1.7s, cerrando justo antes de
   que el logo llegue arriba. */
.logo__facto { transition: opacity 0.7s var(--ease-suave) 1s; }
.logo__cierra { transition: transform 0.8s var(--ease-logo) 0.7s; }

.esta-cargado .logo__facto { opacity: 1; }
.esta-cargado .logo__cierra { transform: translateX(0); }

/* La bajada entra con máscara, y recién cuando el logo ya llegó: primero se
   lee ARTE[FACTO] y después "Galería de Arte". */
.portada__bajada > span {
  transform: translateY(100%);
  transition: transform 0.9s var(--ease-salida);
}
.esta-cargado .portada__bajada > span {
  transform: translateY(0);
  transition-delay: 1.7s;
}

/* ── Reveal por líneas ────────────────────────────────────────────────────────
   Mismo efecto que los textos de brand.squarespace.com/photography. Se leyeron
   los parámetros de su bundle: parte el texto en líneas con SplitText en modo
   máscara, cada línea entra desde abajo detrás de un recorte, con duración 0.8s,
   power3.out, stagger de 0.08s por línea y SIN cambio de opacidad.
   El partidor de líneas está en site.js: acá sólo viven los estados. */
.linea {
  display: block;
  overflow: hidden;
  overflow: clip;
  /* Aire para los descendentes sin alterar la métrica del párrafo: con
     line-height ajustado (la pregunta va en 1.1) el recorte los comería. */
  padding-bottom: 0.15em;
  margin-bottom: -0.15em;
}
.linea > span {
  display: block;
  /* 120% y no 100%: tiene que despejar también el padding de arriba. */
  transform: translateY(120%);
  transition: transform 0.8s var(--ease-salida);
}
.texto-lineas.esta-visible .linea > span {
  transform: translateY(0);
  transition-delay: calc(var(--l, 0) * 0.08s);
}

/* Entrada por scroll. */
.js .aparece {
  opacity: 0;
  transform: translateY(30px);
  transition:
    opacity 0.8s var(--ease-salida) var(--retraso, 0s),
    transform 0.8s var(--ease-salida) var(--retraso, 0s);
}
/* Termina en --op-final y no en 1: si no, la aparición le gana por
   especificidad a los elementos que tienen una opacidad propia (los rótulos al
   40%, el crédito al 50%) y los deja al 100%. */
.js .aparece.esta-visible {
  opacity: var(--op-final, 1);
  transform: translateY(0);
}

/* Las obras entran de abajo hacia arriba y quedan flotando suavemente, igual
   que el logo y las líneas de texto.
   Hay tres capas de transform, una por elemento, para que no se pisen:
     figure  → la entrada
     picture → el parallax (lo aplica el JS)
     img     → el flote continuo
   Sin eso, las tres animaciones competirían por la misma propiedad. */
/* Cada obra entra de abajo hacia arriba con su propia transición. El scroll
   dispara el turno de cada una (ver site.js), pero la animación es propia: así
   aparecen DE A UNA y en orden, y no todas juntas avanzando a la par. */
.js .collage__obra {
  opacity: 0;
  transform: translateY(48px);
  /* 0.85s y no 1s: con 1s la primera obra recién estaba presente a los 3.7s y
     quedaba demasiado fondo en blanco después de "Galería de Arte". */
  transition:
    opacity 0.85s var(--ease-salida),
    transform 0.85s var(--ease-salida);
}
.js .collage__obra.esta-visible {
  opacity: 1;
  transform: translateY(0);
}

.collage__obra,
.collage__obra picture { will-change: transform; }

@keyframes flotar {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-18px); }
}

/* Ritmos distintos por obra, con retrasos negativos para que arranquen
   desfasadas y no se muevan todas juntas. */
.collage__obra.esta-visible img {
  animation: flotar var(--flote, 7s) ease-in-out var(--flote-retraso, 0s) infinite;
}
.collage__obra:nth-child(1) img { --flote: 6.5s; --flote-retraso: 0s; }
.collage__obra:nth-child(2) img { --flote: 8.5s; --flote-retraso: -1.4s; }
.collage__obra:nth-child(3) img { --flote: 7.2s; --flote-retraso: -3.1s; }
.collage__obra:nth-child(4) img { --flote: 9s;   --flote-retraso: -0.6s; }
.collage__obra:nth-child(5) img { --flote: 6.8s; --flote-retraso: -2.5s; }
.collage__obra:nth-child(6) img { --flote: 8s;   --flote-retraso: -4.2s; }

/* Cross-fade al cambiar de artista: el JS pone esta-saliendo para el fundido de
   salida y esta-entrando para arrancar en 0; al quitarla, vuelve a 1. */
.artista { transition: opacity 0.35s var(--ease-suave); }
.artista.esta-saliendo,
.artista.esta-entrando { opacity: 0; }

/* Red de seguridad: si site.js no se ejecutó, nada puede quedar invisible. */
.sin-js .aparece,
.sin-js .collage__obra {
  opacity: 1 !important;
  transform: none !important;
}
.sin-js .portada__logo svg,
.sin-js .portada__bajada > span { transform: none !important; }
/* Sin JS el logo tiene que leerse completo: FACTO visible y el corchete en su
   lugar. */
.sin-js .logo__facto { opacity: 1 !important; }
.sin-js .logo__cierra { transform: none !important; }
.sin-js .artista { display: grid !important; }
.sin-js .artistas__paneles { height: auto !important; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  .js .aparece,
  .js .collage__obra {
    opacity: 1;
    transform: none;
  }
  .portada__logo svg,
  .portada__bajada > span { transform: none; }
  /* Con movimiento reducido el logo aparece completo, sin la apertura. */
  .js .logo__facto { opacity: 1; }
  .js .logo__cierra { transform: none; }
  .obra > picture:hover img { transform: none; }
}

/* ══ Tablet: 768–1199px ═══════════════════════════════════════════════════════
   Según la especificación: 8 columnas, márgenes 24px, gutter 16px. */
@media (max-width: 1199px) {
  :root {
    --u: 0.78px;
    --margen: 24px;
    --gutter: 16px;
  }

  .reja,
  .artista { grid-template-columns: repeat(8, minmax(0, 1fr)); }

  .riel { right: var(--margen); }

  .portada { padding-top: calc(90 * var(--u)); }
  .portada__logo svg { width: 78%; }

  /* Sin espacio para el solapamiento del collage con el texto. */
  .proyecto { margin-top: calc(80 * var(--u)); }
  .proyecto > .rotulo,
  .proyecto__cuerpo { grid-column: 1 / -1; }

  .pregunta__texto,
  .pregunta__respuesta { grid-column: 1 / -1; }

  .rotulo--artistas { grid-column: 1 / span 4; }

  /* El collage abandona las posiciones absolutas del diseño de escritorio: a
     este ancho las obras quedarían de ~100px. Pasa a una grilla escalonada, que
     conserva la sensación de flotar y las deja mirables.
     minmax(0, 1fr) es imprescindible: con 1fr las columnas no pueden bajar del
     min-content de las imágenes y la caja se desborda del viewport. */
  .collage__caja {
    aspect-ratio: auto;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--gutter);
    align-items: start;
    padding-inline: var(--margen);
  }
  .collage__obra {
    position: static;
    min-width: 0;
    width: auto !important;
    left: auto !important;
    top: auto !important;
  }
  .collage__obra:nth-child(3n + 2) { margin-top: 12%; }
  .collage__obra:nth-child(3n + 3) { margin-top: 5%; }

  /* Las obras pasan a dos por fila. display:contents saca a la ficha de la
     ecuación para que sus hijos participen de la grilla de .artista. */
  .artista__ficha { display: contents; }
  .artista__origen,
  .artista__bio { grid-column: 1 / -1; }
  .obra--izquierda { grid-column: 1 / span 4; margin-top: calc(40 * var(--u)); }
  .obra--centro    { grid-column: 5 / span 4; margin-top: calc(40 * var(--u)); }
  .obra--derecha   { grid-column: 1 / span 4; margin-top: calc(40 * var(--u)); }
}

/* ══ Mobile: < 768px ══════════════════════════════════════════════════════════
   Todo apilado en una columna, márgenes 20px. */
@media (max-width: 767px) {
  :root {
    --u: 0.66px;
    --margen: 20px;
    --gutter: 16px;
  }

  .reja,
  .artista { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* En mobile el riel pasa a ser una barra horizontal de 72px: la marca se
     endereza a la izquierda y la hamburguesa queda a la derecha
     (Figma nodo 181:4027). row-reverse deja el botón, que va primero en el
     HTML, en el extremo derecho. */
  .riel {
    top: 23px;
    left: 20px;
    right: 22px;
    flex-direction: row-reverse;
    justify-content: space-between;
    align-items: center;
    gap: 0;
  }
  /* En mobile la navegación queda sólo con la hamburguesa. */
  .riel__marca { display: none; }

  /* En mobile el bloque de contacto vuelve a su tamaño original: el achique del
     50% era sólo para desktop. */
  :root {
    --fs-menu-titulo: clamp(1.5rem, 2.64vw, 2.375rem);  /* 24 → 38 */
    --fs-menu-dato: clamp(1.125rem, 2.08vw, 1.875rem);  /* 18 → 30 */
  }
  .menu__pie { gap: calc(25 * var(--u)); }
  .menu__contacto { gap: calc(7 * var(--u)); }

  /* El panel ocupa todo el ancho y respeta el margen de mobile. */
  .menu__interior {
    padding: 80px var(--margen) 48px;
    gap: 48px;
  }
  .menu__cerrar {
    top: 16px;
    right: var(--margen);
  }

  /* Medidas del export de Ana: el logo arranca en y=150 y mide 310 de los 390
     de ancho, o sea que no llega al borde. */
  /* En su diseño mobile la entrada va al mismo cuerpo que el resto del texto,
     no más grande como en escritorio. Hereda de .proyecto__cuerpo en vez de usar
     --fs-cuerpo: si no, quedaba en 16px contra los 16,5 de los párrafos y la
     jerarquía salía al revés. */
  .proyecto__entrada { font-size: inherit; }

  .portada { padding-top: 150px; }
  .portada__logo svg { width: 94.6%; }
  .collage { margin-top: 74px; }
  .proyecto { margin-top: 102px; }

  /* Collage: Ana lo mantuvo disperso en mobile, no en grilla. Medidas tomadas de
     su export de 390px (design-files/mobile.png): la caja va de y=343 a y=1394,
     o sea 1051 de alto, y cada obra tiene su posición y su ancho propios.
     Los left/top/width vienen en el style inline de cada figura (los del diseño
     de escritorio), así que acá hay que ganarles con !important. */
  .collage__caja {
    display: block;
    aspect-ratio: 390 / 1051;
    padding-inline: 0;
  }
  .collage__obra {
    position: absolute;
    margin-top: 0 !important;
  }
  /* El orden en el HTML es: diz, pedro, mariana, julia, emilia, fernanda. */
  .collage__obra:nth-child(1) { left: 18.21% !important; top:  0%     !important; width: 29.49% !important; }
  .collage__obra:nth-child(2) { left: 63.59% !important; top: 45.48%  !important; width: 31.28% !important; }
  .collage__obra:nth-child(3) { left: 58.21% !important; top: 23.98%  !important; width: 29.23% !important; }
  .collage__obra:nth-child(4) { left:  5.13% !important; top: 21.03%  !important; width: 39.49% !important; }
  .collage__obra:nth-child(5) { left: 24.87% !important; top: 56.04%  !important; width: 29.49% !important; }
  .collage__obra:nth-child(6) { left:  5.13% !important; top: 77.83%  !important; width: 39.49% !important; }

  /* Todo apilado a una columna. */
  .obra--izquierda,
  .obra--centro,
  .obra--derecha {
    grid-column: 1 / -1;
    margin-top: 36px;
  }

  .artistas__tabs { gap: 20px 28px; }
  /* Área táctil de 44px en los nombres y el botón, como pide la especificación. */
  .artistas__tab {
    padding-block: 10px;
    min-height: 44px;
  }
  .artistas__tab[aria-selected="true"]::after { bottom: 4px; }

  .tienda__boton { min-height: 44px; }

  .pie { gap: 32px; }
  .pie__datos { text-align: left; }
}
