/*
  Layout y componentes — Fase 1 (menu superior + header de la galeria).
  Mobile-first: las reglas base son para movil; @media agrega/ajusta para pantallas mas grandes.
*/

/* Oculta visualmente sin ocultar de lectores de pantalla ni buscadores —
   usado para encabezados semanticos que no tienen lugar visual propio
   (Fase 7, ej. el <h2> de la seccion Galeria: el nombre de la seccion ya
   se lee en el boton de navegacion activo, no hace falta repetirlo en
   pantalla, pero la jerarquia h1->h2->h3 debe existir igual). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Menu superior (sticky) ---------- */

/* El <h1> del sitio (unico, SEO/accesibilidad — Fase 7) envuelve el link de
   marca sin generar su propia caja: hereda el tamano/margen por defecto del
   navegador para <h1> si no se neutraliza, así que se anula por completo y
   se deja que .marca (el <a> de adentro) siga controlando toda la
   apariencia, exactamente como antes de agregar el <h1>. */
.marca-h1 {
  display: contents;
}

.menu-superior {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.4rem;
  min-height: var(--alto-menu);
  padding: 0.5rem 1.1rem;
  background: var(--color-fondo);
  border-bottom: 1px solid var(--color-linea);
}

.marca {
  font-family: var(--font-titulo);
  font-weight: 700;
  /* 2.1rem=33.6px en movil (Fase 7, 2026-08-18, pedido explicito: el nombre
     como pieza mas grande de la franja superior — el pedido original era
     40px/2.5rem, pero a ese tamano "Elena Climent" no cabe junto al toggle
     ES/EN y el icono de Instagram en la misma linea en pantallas de 360-375px
     de ancho, medido en el navegador real: se desbordaba y el toggle/IG
     saltaban a su propia fila. 2.1rem es el valor mas grande que sigue
     entrando con margen en ambos anchos). Desktop se queda con su 2rem
     original (ver @media 1024px), pensado para convivir con el resto del
     menu en una sola fila mas larga. */
  font-size: 2.1rem;
  text-decoration: none;
  white-space: nowrap;
  margin-right: 0.15rem;
}

/* Secciones (Galeria/Trayectoria), chips de filtro y el boton de orden
   comparten tamano/forma — misma altura, mismo padding, mismo radio — para
   verse como una sola familia de controles. Los chips rompen el color a
   proposito (ver mas abajo) para distinguirse como "filtros", no por tamano. */
/* Altura exacta del buscador (no un padding que "por casualidad" cuadre —
   ver Fase 3, quedo 7px corto una vez por lo mismo): un numero fijo,
   compartido literalmente por los cuatro controles. */
.menu-secciones button,
.chip-filtro,
.boton-orden,
.menu-buscador input[type="search"],
.toggle-idioma,
.boton-icono {
  height: var(--alto-boton);
}

/* Una sola talla de fuente para todo el menu excepto la marca (incluye el
   texto "Ordenar:" y el toggle de idioma. Todos los botones del sitio
   comparten esta misma familia de tamano, para verse como un solo sistema).
   0.9rem en movil (2026-08-18, pedido explicito "dos puntos mas grandes" —
   antes 0.78rem); desktop se queda en el 0.78rem original (ver @media
   1024px). El buscador NO esta en este grupo — tiene su propia regla mas
   abajo, por un motivo tecnico aparte (ver comentario ahi). */
.menu-secciones button,
.chip-filtro,
.boton-orden,
.etiqueta-ordenar-por,
.toggle-idioma {
  font-size: 0.9rem;
}

.menu-secciones button,
.chip-filtro,
.boton-orden {
  font-family: var(--font-titulo);
  font-weight: 700;
  white-space: nowrap;
  /* padding-top:2px + padding-bottom:0, con altura fija (--alto-boton) y
     centrado por flexbox, baja el texto exactamente 1px dentro del boton
     (la mitad del padding "de mas" que se le resta al area de centrado
     arriba, ver el mismo truco en chip-filtro/toggle-idioma). */
  padding: 2px 0.175rem 0;
  letter-spacing: 0.03em;
  border-radius: var(--radio-chip);
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Galeria/Trayectoria (no chips ni el boton de orden, que comparten la
   regla de arriba): 3px extra de padding horizontal por lado (6px en
   total) sobre el valor base — pedido explicito 2026-08-18. */
.menu-secciones button {
  padding-left: calc(0.175rem + 3px);
  padding-right: calc(0.175rem + 3px);
}

/* El boton de orden no forma parte del rediseno de color de 2026-08-17
   (nav/chips/idioma/"Mas sobre mi") — se queda con su look original. */
.boton-orden {
  border-color: var(--color-linea);
  background: none;
  color: var(--color-texto);
}

.boton-orden:hover {
  background: var(--color-fondo-elevado);
}

.menu-secciones {
  display: flex;
  gap: 0.175rem;
}

/* Galeria/Trayectoria: inactivo = gris casi invisible, activo (la seccion
   que se esta mostrando) = acento salvia claro, hover = un peldano mas
   claro que el inactivo. Sin borde en ningun estado (el foco de teclado lo
   sigue marcando :focus-visible, eso no se toca). */
.menu-secciones button {
  background: var(--color-boton-inactivo);
  color: var(--color-texto);
}

.menu-secciones button[aria-current="true"] {
  background: var(--color-acento);
  color: var(--color-acento-texto);
}

.menu-secciones button:not([aria-current="true"]):hover {
  background: var(--color-boton-hover);
}

/* La "unidad" completa del menu — secciones, filtros, orden y buscador —
   como un solo grupo, para poder centrarla entera en el menu superior. */
.unidad-menu {
  order: 6;
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  gap: 0.325rem;
  min-width: 0;
}

.separador-menu {
  flex-shrink: 0;
  width: 1px;
  height: 1.4rem;
  background: var(--color-linea);
}

/* order:2 lo empata con .menu-buscador (tambien order:2): como el
   separador va antes en el DOM, el empate lo deja justo delante del
   buscador, que es donde tiene que estar. Selector por id (no mas
   ".unidad-menu > .separador-menu" — cambiado 2026-08-18 al agregar
   #fila-secundaria-menu, ver mas abajo): un id no depende de que el
   elemento sea hijo DIRECTO de nada en particular, asi que sigue
   funcionando sin importar cuanto anidamiento haya alrededor. */
#separador-buscador {
  order: 2;
}

/* Envuelve filtros+orden+buscador+slideshow (ver index.html). Invisible
   por defecto (display:contents — sin caja propia, sus hijos se comportan
   como si fueran hijos directos de .unidad-menu, exactamente igual que
   antes de que este wrapper existiera): asi movil y el desktop de siempre
   quedan intactos sin tocar ninguna de sus reglas. Solo se activa de
   verdad — con su propia fila, ver .grid-template-rows de mas abajo — en
   el layout intermedio nuevo de 1024-1279px (pedido explicito 2026-08-18:
   evitar que los filtros se aprieten contra el resto del menu al achicar
   la ventana antes de llegar a movil). */
#fila-secundaria-menu {
  display: contents;
}

/* Filtros/orden viven dentro del menu (nunca se ocultan con el scroll — el
   menu esta fuera de #galeria, ver mostrarSeccion() en interfaz.js), por eso
   hay que esconder este grupo a mano en Trayectoria (donde no aplican). */
.grupo-filtros {
  display: flex;
  align-items: center;
  gap: 0.325rem;
  min-width: 0;
}

.chips-filtros {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.175rem;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.chips-filtros::-webkit-scrollbar {
  display: none;
}

/* Chips: inactivo = gris casi invisible (a proposito); activo (filtro
   encendido) = azul dedicado (distinto del verde de nav/idioma, para que
   los filtros se distingan como su propia familia); hover = un peldano
   mas claro, SOLO en chips inactivos. Sin borde. Bold (2026-08-18 — antes
   regular a proposito, para distinguirse del resto de la familia de
   botones solo por tipo de letra; revertido a pedido explicito, ahora
   coinciden en peso con el resto). */
.chip-filtro {
  flex-shrink: 0;
  font-weight: 700;
  background: var(--color-boton-inactivo);
  color: var(--color-texto-tenue);
}

.chip-filtro[aria-pressed="true"] {
  background: var(--color-acento-filtros);
  color: var(--color-acento-filtros-texto);
}

/* Antes el hover ganaba tambien sobre un chip activo (mismo truco que
   .boton-trayectoria) — eso causaba el bug reportado: al hacer clic para
   encender un filtro, el puntero se quedaba "hovering" y el chip se veia
   gris (color de hover) en vez de azul hasta que el mouse se movia fuera.
   Excluyendo [aria-pressed="true"] aqui, igual que ya hacia el nav
   (.menu-secciones button:not([aria-current="true"]):hover), el chip pasa
   a azul en el instante del clic, sin esperar a que el puntero se mueva. */
.chip-filtro:not([aria-pressed="true"]):hover {
  background: var(--color-boton-hover);
  color: var(--color-texto);
}

/* Dropdown de ordenamiento: desactivado en movil (queda el orden aleatorio). */
.orden-wrapper {
  position: relative;
  flex-shrink: 0;
  display: none;
  align-items: center;
  gap: 0.4rem;
}

/* "Aleatorio"/"Fecha"/etc. dentro del boton de orden: peso regular, a
   pedido explicito (igual que los chips), a diferencia de "Orden:" de al
   lado que se queda en bold. */
#etiqueta-orden {
  font-weight: 400;
}

.etiqueta-ordenar-por {
  font-family: var(--font-cuerpo);
  /* Mismo tamano en px que el resto del menu, pero en peso regular se veia
     "mas chico" — en una fuente manuscrita el trazo delgado engana el ojo.
     Bold para que iguale de verdad al resto. */
  font-weight: 700;
  color: var(--color-texto-tenue);
  white-space: nowrap;
}

.lista-orden {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  /* Antes 10rem fijo: con justify-content:space-between (ver .lista-orden li)
     ese ancho forzaba el hueco entre el texto y la flecha. Sin min-width, el
     dropdown se achica al contenido real (el criterio mas largo, "Alfabetico"). */
  list-style: none;
  margin: 0;
  padding: 0.35rem;
  background: var(--color-fondo-elevado);
  border: 1px solid var(--color-linea);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  z-index: 95;
}

.lista-orden li {
  font-family: var(--font-titulo);
  font-size: 0.85rem;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  display: flex;
  align-items: center;
  /* flex-start (no space-between): la flecha va pegada al texto, no
     empujada al otro extremo del dropdown — eso es lo que lo compactaba. */
  justify-content: flex-start;
  gap: 0.2rem;
  cursor: pointer;
  color: var(--color-texto);
}

.lista-orden li:hover,
.lista-orden li[aria-selected="true"] {
  background: var(--color-fondo);
}

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

.flecha-orden {
  font-size: 0.75rem;
}

/* Rediseno movil (Fase 7, 2026-08-18, a pedido explicito con wireframe): una
   sola franja con Galeria/Trayectoria a la izquierda, el buscador
   expandiendose al resto del ancho, y el boton "Filtros" (azul, mismo acento
   que los chips activos) a la derecha, que despliega los chips en un panel
   flotante (ver .grupo-filtros/.chips-filtros/.chip-filtro mas abajo e
   inicializarFiltrosMovil en galeria.js). Reemplaza el diseno anterior de 3
   filas apiladas (secciones / chips / buscador). En desktop se recupera el
   layout original de una sola fila con filtros siempre inline (ver @media
   1024px: ahi .abierto deja de ser relevante porque #boton-filtros esta
   oculto y nadie la agrega/quita). */
.unidad-menu {
  flex-wrap: nowrap;
  position: relative; /* ancla el panel de .grupo-filtros */
}

.menu-secciones {
  order: 0;
  flex-shrink: 0;
}

.menu-buscador {
  order: 2;
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
}

.boton-filtros {
  order: 4;
  flex-shrink: 0;
  height: var(--alto-boton);
  padding: 2px 0.7rem 0;
  font-family: var(--font-titulo);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  white-space: nowrap;
  border: none;
  border-radius: var(--radio-chip);
  background: var(--color-acento-filtros);
  color: var(--color-acento-filtros-texto);
}

.boton-filtros:hover {
  filter: brightness(1.15);
}

/* Panel desplegable de filtros: mismo patron visual que .lista-orden /
   .panel-slideshow (fondo elevado, borde, sombra, misma familia de
   desplegables), pero con los chips apilados en columna (ver
   .chips-filtros/.chip-filtro mas abajo) en vez de un listado de opciones
   unica. Cerrado por defecto (display:none); .abierto lo muestra (mas
   especificidad que el display:none de aca, gana siempre que este presente
   — ver inicializarFiltrosMovil en galeria.js). */
.grupo-filtros {
  order: 5;
  display: none;
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  flex-basis: auto;
  flex-direction: column;
  align-items: stretch;
  gap: 0.3rem;
  max-height: 60vh;
  overflow-y: auto;
  /* Ancho justo al del nombre de grupo mas largo (pedido explicito
     2026-08-18, "Loving Solitude" es el mas largo hoy) en vez de un
     min-width fijo — max-content fuerza el shrink-to-fit sobre el ancho
     "natural" de los chips (el width:100% de .chip-filtro se ignora para
     este calculo, como exige la spec para evitar un ciclo — el ancho real
     de cada chip se resuelve DESPUES, estirado por align-items:stretch al
     ancho ya resuelto del panel). El tope evita que un nombre larguisimo
     futuro desborde en una pantalla angosta. */
  width: max-content;
  max-width: calc(100vw - 2.2rem);
  padding: 0.5rem;
  background: var(--color-fondo-elevado);
  border: 1px solid var(--color-linea);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  z-index: 95;
}

.grupo-filtros.abierto {
  display: flex;
}

.chips-filtros {
  flex-direction: column;
  align-items: stretch;
  overflow-x: visible;
  gap: 0.3rem;
}

.chip-filtro {
  width: 100%;
  justify-content: flex-start;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* Despues del buscador (order:2) en la fila de .unidad-menu — sin esto cae
   en el order:0 por defecto y salta antes que secciones/chips/orden, pese a
   venir despues en el HTML (el orden visual de flex lo decide "order", no
   la posicion en el DOM). Da lo mismo en movil (esta oculto, ver mas abajo). */
#control-slideshow {
  order: 3;
  position: relative;
  display: none;
  align-items: center;
}

/* Separador entre buscador y slideshow (2026-08-18, pedido explicito) —
   mismo order que #control-slideshow: al venir antes en el DOM, el empate
   lo deja justo delante (identico patron al separador suelto de mas
   arriba, que empata con .menu-buscador). Oculto en movil junto con el
   resto de .separador-menu (ver mas abajo), visible en desktop. */
#separador-slideshow {
  order: 3;
}

#boton-slideshow {
  /* El icono (22.88px de ancho, ver #boton-slideshow svg) no entra comodo en
     los 30px de .boton-icono (pensados para el cuadrado de Instagram) — se
     ensancha el boton para que le quede un margen parejo alrededor. */
  width: 36px;
}

#boton-slideshow:disabled {
  opacity: 0.35;
  cursor: default;
}

#boton-slideshow:disabled:hover {
  background: none;
}

/* Panel con el slider de segundos — oculto por defecto, aparece debajo del
   boton de slideshow al presionarlo (mismo patron que .lista-orden), y se
   vuelve a ocultar al arrancar el show (no queda visible al salir). */
.panel-slideshow {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.65rem;
  background: var(--color-fondo-elevado);
  border: 1px solid var(--color-linea);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  white-space: nowrap;
  z-index: 95;
}

/* Slider "delicado": una linea fina y un circulo, sin tramo relleno de color
   (a diferencia del accent-color por defecto de Chrome, que pinta el tramo
   recorrido) — se pide expresamente sin relleno. */
.slider-slideshow {
  -webkit-appearance: none;
  appearance: none;
  width: 4.5rem;
  height: 0.7rem;
  background: transparent;
  cursor: pointer;
}

.slider-slideshow::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--color-texto-tenue);
}

.slider-slideshow::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 0.65rem;
  height: 0.65rem;
  margin-top: -0.32rem;
  border-radius: 50%;
  background: var(--color-acento);
}

.slider-slideshow::-moz-range-track {
  height: 1px;
  background: var(--color-texto-tenue);
}

.slider-slideshow::-moz-range-progress {
  background: transparent;
}

.slider-slideshow::-moz-range-thumb {
  width: 0.65rem;
  height: 0.65rem;
  border: none;
  border-radius: 50%;
  background: var(--color-acento);
}

.etiqueta-segundos-slideshow {
  font-size: 0.75rem;
  color: var(--color-texto-tenue);
}

/* Boton "Slideshow" — misma familia visual que el toggle de idioma (mismo
   fondo/hover), pero mas chico, a pedido explicito ("pequeno boton"). */
.boton-iniciar-slideshow {
  font-family: var(--font-titulo);
  font-weight: 700;
  font-size: 0.72rem;
  background: var(--color-boton-inactivo);
  border: none;
  border-radius: var(--radio-chip);
  padding: 0.3rem 0.55rem;
  letter-spacing: 0.03em;
  color: var(--color-texto);
}

.boton-iniciar-slideshow:hover {
  background: var(--color-boton-hover);
}

.menu-buscador input[type="search"] {
  width: 100%;
  font-family: var(--font-cuerpo);
  /* 16px (1rem) en movil, no el 0.9rem del resto del menu: es el minimo que
     evita que iOS/Android hagan zoom automatico de TODA la pagina al
     enfocar un campo de texto con letra mas chica (pedido explicito
     2026-08-18, bug reportado: "zoom a la pagina" al tocar el buscador —
     comportamiento del propio sistema operativo, no del sitio). Desktop
     vuelve al 0.78rem compartido con el resto del menu (ver @media 1024px),
     donde este problema no existe. */
  font-size: 1rem;
  /* <input> no hereda line-height igual que un <button> (queda "normal" en
     vez de heredar el 1.5 del body) — sin esto queda unos px mas bajo que
     los botones de al lado, rompiendo la altura uniforme. */
  line-height: 1.5;
  background: var(--color-boton-inactivo);
  border: none;
  border-radius: var(--radio-chip);
  padding: 0 1.775rem 0 0.575rem;
  color: var(--color-texto);
}

/* "Activo" en un campo de texto es cuando tiene el foco (no hay estado
   :active util aqui) — se llena de azul y el texto pasa a blanco/bold para
   que se lea bien encima. Sin outline: el cambio de relleno ya comunica el
   foco, no hace falta el anillo (el resto de los controles si lo conservan,
   ver :focus-visible en theme.css — este input queda como unica excepcion). */
.menu-buscador input[type="search"]:focus {
  background: var(--color-acento-filtros);
  color: var(--color-blanco);
  font-weight: 700;
  outline: none;
}

.menu-buscador input[type="search"]::placeholder {
  color: var(--color-texto-tenue);
}

/* Boton nativo de limpiar de Chrome/Edge (::-webkit-search-cancel-button) se
   oculta: usamos nuestro propio boton para que se vea igual en todos lados. */
.menu-buscador input[type="search"]::-webkit-search-cancel-button {
  display: none;
}

.boton-limpiar-busqueda {
  position: absolute;
  right: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  background: none;
  border: none;
  border-radius: var(--radio-chip);
  color: var(--color-texto-tenue);
  font-size: 0.8rem;
}

.boton-limpiar-busqueda:hover {
  background: var(--color-fondo);
  color: var(--color-texto);
}

/* En movil cada fila ya distingue los grupos por si sola; los separadores
   verticales solo suman cuando todo cabe en una sola fila (desktop). */
.separador-menu {
  display: none;
}

.menu-herramientas {
  order: 4;
  display: flex;
  align-items: center;
  gap: 0.15rem;
  flex-shrink: 0;
  margin-left: auto;
}

.boton-icono {
  display: grid;
  place-items: center;
  width: var(--alto-boton);
  border-radius: var(--radio-chip);
  background: none;
  border: none;
  color: var(--color-texto);
}

.boton-icono:hover {
  background: var(--color-fondo-elevado);
}

.boton-icono svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* slideshow.svg no es cuadrado (viewBox ~96x84) — con el height:1.1rem fijo
   de arriba se veria levemente aplastado; height:auto lo deja calcularse
   solo a partir del viewBox, manteniendo su proporcion real. Ancho 30% mas
   grande que el resto de los iconos (1.1rem -> 1.43rem), a pedido. */
#boton-slideshow svg {
  width: 1.43rem;
  height: auto;
}

/* Indicador de idioma activo (2026-08-18, tercera version — primero un
   gradiente deslizante, despues la palabra activa en verde, ambos
   descartados a pedido del usuario): el boton es fondo solido; la PALABRA
   del idioma activo dentro del texto fijo "ES/EN" (envuelta en dos <span>,
   ver index.html) pasa a blanco — ej. con "en" activo, "ES/" queda en el
   gris de los chips inactivos y "EN" en blanco. Sin borde en ningun
   estado. */
.toggle-idioma {
  font-family: var(--font-titulo);
  background: var(--color-boton-inactivo);
  color: var(--color-texto-tenue); /* mismo gris que un chip de filtro inactivo, pedido explicito */
  border: none;
  border-radius: var(--radio-chip);
  /* +6px de ancho total (3px por lado) y 15px mas separado del icono de
     Instagram (ver .menu-herramientas) — ambos pedidos explicitos. */
  padding: 2px calc(0.25rem + 3px) 0;
  margin-right: 15px;
  /* 10px mas hacia la derecha (2026-08-18, pedido explicito aparte):
     position:relative + right:-10px desplaza SOLO este boton, sin afectar
     el flujo (el icono de Instagram no se mueve ni el resto del menu se
     recalcula) — probado antes con margin-left, que no funcionaba: el
     grupo entero (.menu-herramientas) queda pegado al borde derecho del
     menu via margin-left:auto/justify-self:end, asi que cualquier margen
     agregado ADENTRO del grupo solo se "traga" ese espacio en vez de
     mover nada (el grupo crece hacia la izquierda, el boton no se mueve). */
  position: relative;
  right: -10px;
  letter-spacing: 0.03em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@media (prefers-reduced-motion: no-preference) {
  .idioma-es,
  .idioma-en {
    transition: color 0.3s ease;
  }
}

.toggle-idioma[data-idioma="es"] .idioma-es,
.toggle-idioma[data-idioma="en"] .idioma-en {
  color: var(--color-blanco);
}

.toggle-idioma:hover {
  background: var(--color-boton-hover);
}

.toggle-idioma:active {
  filter: brightness(0.85);
}


/* ---------- Layout intermedio (1024-1479px) ---------- */
/* Entre el layout movil (<1024px) y el desktop de "una sola fila" (arriba
   de 1480px, ver el proximo bloque — el punto de quiebre se SUBIO de
   1024px a 1280px (primera version), despues a 2241px (el usuario midio
   en Photoshop el ancho de ventana donde el layout de una fila todavia se
   veia bien), y por ultimo a 1280+200=1480px (mismo dia: "no quedo bien,
   usemos tu medida anterior [1280px] pero sumale 200px") — en ningun caso
   se toco ninguna declaracion del bloque de una fila, solo el numero del
   media query) hay una franja donde esa sola fila se aprieta demasiado:
   los chips de filtro son el UNICO elemento pensado para encogerse ahi
   (ver comentario del proximo bloque), asi que absorben el 100% de
   cualquier reduccion de ancho — medido en el navegador: se encogen 1px
   por cada 1px que se achica la ventana, sin ningun margen, desde el
   primer momento. El usuario reporto sentir los filtros "a punto de ser
   ocultados" al achicar la ventana (2026-08-18).

   Este bloque agrega una fila intermedia en su lugar: linea 1 = marca +
   Galeria/Trayectoria + ES/EN + Instagram (igual que siempre); linea 2 =
   filtros + orden + buscador + slideshow, en su mismo orden relativo,
   alineados a la izquierda con la marca, mas abajo (offset vertical
   afinado varias veces el mismo dia — ver margin-top en
   #fila-secundaria-menu mas abajo para el valor final y su historial).

   MUY IMPORTANTE (pedido explicito): este layout no debe afectar ni al
   movil (<1024px) ni al desktop de una sola fila (1480px+) — por eso NO
   reutiliza ni modifica ninguna regla existente de esos dos, declara sus
   propios valores aunque eso implique repetir varias declaraciones ya
   escritas mas abajo para 1480px+. Pieza clave: #fila-secundaria-menu (ver
   index.html) es display:contents en todos los demas anchos (invisible,
   sus hijos se comportan como si fueran hijos directos de .unidad-menu,
   exactamente igual que antes de que este wrapper existiera) — aca pasa a
   ser una caja real con su propia fila del grid (grid-row:2, grid-column:
   1/-1: arranca en la misma columna que la marca). .unidad-menu tambien
   pasa a ser display:contents, para "soltar" tanto .menu-secciones (que
   sube a la fila 1) como #fila-secundaria-menu. */
@media (min-width: 1024px) and (max-width: 1479px) {
  :root {
    --alto-boton: 30px;
  }
  .menu-superior {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1rem;
    row-gap: 30px;
    padding: 0.5rem 2rem;
  }
  .marca {
    grid-row: 1;
    grid-column: 1;
    justify-self: start;
    font-size: 2rem;
    margin-right: 0;
  }
  .unidad-menu {
    display: contents;
  }
  .menu-secciones {
    grid-row: 1;
    grid-column: 2;
    flex-shrink: 0;
  }
  .menu-secciones button,
  .chip-filtro,
  .boton-orden {
    padding: 2px 0.275rem 0;
  }
  .menu-secciones button {
    padding-left: calc(0.275rem + 3px);
    padding-right: calc(0.275rem + 3px);
  }
  .menu-secciones button,
  .chip-filtro,
  .boton-orden,
  .etiqueta-ordenar-por,
  .toggle-idioma,
  .menu-buscador input[type="search"] {
    font-size: 0.78rem;
  }
  .menu-herramientas {
    grid-row: 1;
    grid-column: 3;
    justify-self: end;
    margin-left: 0;
    gap: 0.2rem;
  }

  /* Fila 2: filtros + orden + buscador + slideshow, alineados a la
     izquierda con la marca (columna 1). row-gap:30px (arriba) ubica la
     fila en el grid, y margin-top negativo la sube desde ahi (pedido
     explicito 2026-08-18, tres vueltas el mismo dia: "sube 38px" -> "quedo
     demasiado arriba, bajala 25px" (-38+25=-13) -> "sube 20px mas"
     (-13-20=-33px)) — no se puede lograr con un row-gap negativo (gap no
     admite valores negativos: se ignora como invalido y el navegador cae
     de vuelta al gap de 0.5rem/8px de la regla base de movil, error real
     que se encontro probando en el navegador). El margen negativo, en
     cambio, si se puede — desplaza la caja sin tocar el tamano de la
     pista del grid. */
  #fila-secundaria-menu {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 0.425rem;
    grid-row: 2;
    grid-column: 1 / -1;
    /* align-self:start (no el align-items:center heredado del grid): con
       centrado, un margin-top negativo interactua con el calculo de
       centrado y el resultado queda impreciso (probado: pedia -38px y
       solo subia 34px). Con "start", el margen negativo desplaza la caja
       de forma directa y predecible desde el borde superior de la pista. */
    align-self: start;
    margin-top: -33px;
  }
  /* Reset a orden natural del DOM (filtros, buscador, slideshow — ya en ese
     orden en index.html): las reglas base/movil les dan order:2/3/4/5,
     pensados para cuando su contenedor flex era .unidad-menu (ver
     comentarios ahi) — dentro de #fila-secundaria-menu esos valores darian
     una secuencia distinta (buscador antes que filtros). */
  #grupo-filtros,
  #separador-buscador,
  .menu-buscador,
  #boton-filtros,
  #separador-slideshow,
  #control-slideshow {
    order: 0;
  }
  .grupo-filtros {
    display: flex;
    position: static;
    flex-direction: row;
    align-items: center;
    gap: 0.425rem;
    max-height: none;
    overflow-y: visible;
    width: auto;
    max-width: none;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
  /* Sin la barra vertical antes del primer chip ("Recientes" — pedido
     explicito 2026-08-18, solo en este layout). El otro separador de
     #grupo-filtros (entre los chips y "Ordenar:") se queda igual. */
  #grupo-filtros > .separador-menu:first-child {
    display: none;
  }
  .chips-filtros {
    flex-direction: row;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .chip-filtro {
    width: auto;
    justify-content: center;
  }
  .boton-filtros {
    display: none;
  }
  .separador-menu {
    display: block;
  }
  .orden-wrapper {
    display: flex;
  }
  /* El buscador se expande para llenar el espacio libre (pedido explicito
     2026-08-18) — como es el unico elemento de la fila con flex-grow, el
     slideshow (que viene justo despues en el orden) queda empujado al
     borde derecho de la fila sin necesidad de nada mas. min-width:0 evita
     que su "ancho minimo de contenido" le impida encogerse si la fila
     llegara a apretarse. */
  .menu-buscador {
    flex: 1 1 auto;
    min-width: 0;
  }
  .menu-buscador input[type="search"] {
    width: 100%;
  }
  #control-slideshow {
    display: flex;
  }
}

@media (min-width: 1480px) {
  /* Punto de quiebre subido de 640px a 1024px (2026-08-17), de 1024px a
     1280px, de 1280px a 2241px, y por ultimo de vuelta a 1280+200=1480px
     (2026-08-18, ver el bloque de arriba — nunca se toco ninguna
     declaracion de ESTE bloque, solo el numero del media query cada vez):
     a 640px el contenido fijo (marca + secciones + "Orden:" + buscador de
     14rem + herramientas) ya no cabe aunque los chips se encojan a 0 —
     medido con el navegador real, el buscador y "Orden:" se salian de
     .unidad-menu e invadian visualmente la columna de herramientas (el
     toggle ES/EN quedaba tapado/desalineado). Por debajo de este punto el
     menu usa el layout intermedio de arriba (1024-1479px) o el apilado de
     movil (<1024px).

     Tres columnas: marca | la unidad completa (secciones + filtros + orden +
     buscador) | herramientas. La columna del medio es minmax(0, 1fr) — NO
     minmax(0, auto): con "auto" el navegador sigue sizeando la pista a su
     ancho de contenido completo y el menu se desborda (lo confirme
     midiendolo); con "1fr" la pista participa de verdad en el reparto de
     espacio y se achica cuando hace falta — son los chips (con su propio
     scroll horizontal, ver .chips-filtros) los que ceden, no la fila entera.
     Las columnas laterales quedan "auto" (a su contenido) en vez de 1fr/1fr:
     ya no es un centrado matematico perfecto (marca y herramientas no miden
     exactamente lo mismo), pero es la combinacion que no desborda. */
  /* Movil usa 40px (minimo tactil para el dedo, pedido explicito 2026-08-18
     — ver el valor base en theme.css); desktop, con mouse de precision,
     vuelve al tamano original de 30px. */
  :root {
    --alto-boton: 30px;
  }
  .menu-superior {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1rem;
    padding: 0.5rem 2rem;
  }
  .marca {
    grid-column: 1;
    justify-self: start;
    font-size: 2rem;
    margin-right: 0;
  }
  .unidad-menu {
    grid-column: 2;
    /* justify-self NO — con "center" (o cualquier valor que no sea el
       "stretch" por defecto) el item de grid se dimensiona a su contenido
       maximo e ignora el ancho real de la pista, y minmax(0,1fr) deja de
       servir de nada (lo confirme midiendolo: se desbordaba igual). Con el
       "stretch" por defecto el contenedor SI queda del ancho real de la
       pista; ahora alineamos su CONTENIDO (la "botonera") a la izquierda
       con justify-content. */
    justify-content: flex-start;
    /* 35px totales desde el borde derecho de "Elena Climent" (45px original,
       movida 10px a la izquierda dos veces a pedido): el grid ya pone 1rem
       (16px) de column-gap entre las columnas 1 y 2, este margen cubre el
       resto (25-16=9px). */
    margin-left: 9px;
    order: initial;
    flex: initial;
    flex-wrap: nowrap;
    min-width: 0;
    gap: 0.425rem;
  }
  .menu-secciones {
    flex-basis: auto;
    /* Los chips son el unico elemento pensado para encogerse (ver
       .chips-filtros mas abajo). Sin esto, el encogimiento por flexbox se
       reparte tambien aqui y en el buscador segun su "hypothetical size"
       (el ancho SIN encoger de los chips, que es enorme) — medido en el
       navegador: el buscador quedaba a 121px de sus 224px fijos y su
       input se salia encima del toggle de idioma. */
    flex-shrink: 0;
  }
  .menu-secciones button,
  .chip-filtro,
  .boton-orden {
    padding: 2px 0.275rem 0;
  }
  /* Mismos +3px por lado que en movil (ver regla base) sobre el valor de
     padding horizontal propio de desktop. */
  .menu-secciones button {
    padding-left: calc(0.275rem + 3px);
    padding-right: calc(0.275rem + 3px);
  }
  /* El bump de "dos puntos" (0.78rem -> 0.9rem) y el fix de zoom del
     buscador (-> 1rem) son especificos de movil — desktop vuelve al 0.78rem
     unico original compartido por todo el menu, buscador incluido (ver
     comentarios en las reglas base de mas arriba). */
  .menu-secciones button,
  .chip-filtro,
  .boton-orden,
  .etiqueta-ordenar-por,
  .toggle-idioma,
  .menu-buscador input[type="search"] {
    font-size: 0.78rem;
  }
  /* Filtros vuelve a ser una fila inline siempre visible (no un panel
     desplegable — #boton-filtros esta oculto abajo, asi que .abierto nunca
     se agrega en desktop de todas formas, pero se revierte el resto de la
     apariencia de "panel flotante" explicitamente). order:1 (bug corregido
     2026-08-18): la base movil le puso order:5 para que el panel flotante
     no interfiera en el flujo de la franja inferior, pero ese valor se
     quedaba pegado en desktop tambien — los filtros aparecian despues del
     buscador y el slideshow en vez de justo despues de Galeria/Trayectoria,
     como siempre fue. */
  .grupo-filtros {
    order: 1;
    display: flex;
    position: static;
    flex-basis: auto;
    flex-direction: row;
    align-items: center;
    gap: 0.425rem;
    max-height: none;
    overflow-y: visible;
    min-width: 0;
    /* Revierte el width:max-content/max-width del panel movil (arriba) — en
       desktop es una fila inline normal, su ancho lo decide el flexbox de
       .unidad-menu como siempre (los chips se encogen con su propio scroll
       horizontal, ver .chips-filtros). */
    width: auto;
    max-width: none;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }
  .chips-filtros {
    flex-direction: row;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .chip-filtro {
    width: auto;
    justify-content: center;
  }
  .boton-filtros {
    display: none;
  }
  .separador-menu {
    display: block;
  }
  .orden-wrapper {
    display: flex;
  }
  .menu-buscador {
    /* flex-grow:0 explicito (bug corregido 2026-08-18): la base movil pone
       flex:1 1 auto para que el buscador se expanda en la franja inferior;
       ese flex-grow:1 se quedaba pegado en desktop porque este bloque solo
       reseteaba flex-basis/flex-shrink, nunca flex-grow — el buscador
       terminaba creciendo para llenar toda la columna 2 del grid y
       empujaba el slideshow hasta pegarlo con ES/EN, que es el bug que
       reporto el usuario. */
    flex: 0 0 auto;
  }
  .menu-buscador input[type="search"] {
    /* 60% de 224px (14rem, el ancho anterior) = 134.4px, redondeado a un
       numero entero en px (no rem, para no reintroducir una fraccion). */
    width: 134px;
  }
  .menu-herramientas {
    grid-column: 3;
    justify-self: end;
    order: initial;
    margin-left: 0;
    gap: 0.2rem;
  }
  #control-slideshow {
    display: flex;
  }
}

/* ---------- Header de la galeria (foto + intro) ---------- */

/* Movil (Fase 7, 2026-08-18, pedido explicito con wireframe): layout
   editorial — la foto flota a la izquierda (float + shape-outside, para que
   el texto abrace el circulo de verdad, no solo su caja cuadrada) y el
   texto ocupa lo que queda a la derecha durante el alto de la foto, y sigue
   a ancho completo por debajo una vez que la supera. display:flow-root (no
   un clearfix con ::after) contiene el float sin agregar ningun elemento
   fantasma — importante porque desktop reemplaza esto por flex (ver @media
   1024px) y un ::after ahi se colaria como item de flex de mas. Texto
   alineado a la izquierda (antes centrado) — legible junto al float y
   pedido explicito aparte. */
.header-galeria {
  display: flow-root;
  text-align: left;
  /* Padding horizontal y max-width igualados a los de .mosaico (misma
     progresion por breakpoint) para que la foto quede alineada con el
     borde izquierdo del mosaico en cualquier ancho de pantalla. */
  padding: 2.5rem 1rem;
  max-width: 92rem;
  margin: 0 auto;
}

.header-galeria .texto-columna > * {
  margin: 0;
}

/* La mascara circular vive en el contenedor (tamano/posicion fijos); la
   img adentro es la que crece en hover — asi el circulo nunca cambia de
   tamano, solo se ve mas "acercada" la foto dentro de el. shape-outside
   necesita el mismo circulo que el recorte visual (border-radius) para que
   el texto abrace el borde real, no la caja cuadrada del float. */
.header-galeria .foto-perfil-mascara {
  float: left;
  shape-outside: circle(50%);
  /* 175px = 140px +25% (pedido explicito 2026-08-18). */
  width: 175px;
  height: 175px;
  margin: 0 1.25rem 0.75rem 0;
  border-radius: 50%;
  overflow: hidden;
}

.header-galeria .foto-perfil {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Mismo tamano y line-height que el texto corrido de Trayectoria
   (.trayectoria-texto p, 1.2rem/1.3 — pedido explicito 2026-08-18: se
   habian quedado distintos desde el rediseno del header movil, cuando este
   bajo a 1.05rem para caber mejor junto a la foto flotante). Line-height
   ajustado de 1.4 a 1.3 en ambos (mas apretado, pedido explicito aparte). */
.header-galeria .texto-intro {
  font-size: 1.2rem;
  line-height: 1.3;
  color: var(--color-texto);
}

/* Mismo punto de quiebre que .mosaico para su padding horizontal, y mismo
   valor (1.5rem), asi el borde izquierdo se mantiene alineado. */
@media (min-width: 640px) {
  .header-galeria {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }
}

/* 1024px: por debajo, la columna de texto no tiene ancho suficiente para
   igualar la altura de la foto sin verse mal (probado con la version real);
   se queda en el layout editorial de foto flotante (ver mas arriba). Aca
   se reemplaza flow-root+float por flex fila — display:flex explicito
   porque la base movil ya no lo trae (ver comentario en .header-galeria de
   mas arriba), y float/shape-outside/margin de la foto se resetean porque
   un flex item no los necesita (los maneja el propio flex). */
@media (min-width: 1024px) {
  .header-galeria {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    text-align: left;
    gap: 2rem;
    padding-top: 3.5rem;
    padding-bottom: 3.5rem;
    padding-left: 2rem;
    padding-right: 2rem;
  }

  .header-galeria .foto-perfil-mascara {
    float: none;
    shape-outside: none;
    margin: 0;
    /* 280px = 224px +25% (pedido explicito 2026-08-18). */
    width: 280px;
    height: 280px;
    flex-shrink: 0;
  }

  /* Zoom en hover — solo con mouse real (@media hover:hover, no un ancho de
     pantalla: un touchscreen a 1024px+ tampoco tiene puntero real). Se
     probo una version tactil (mantener el dedo presionado, Fase 7
     2026-08-18) pero se revirtio de inmediato (mismo dia): en el telefono
     real, mantener el dedo ~1s sobre la foto disparaba el dialogo nativo
     del sistema (menu de guardar/copiar imagen), un conflicto de gestos
     que no vale la pena — el zoom queda exclusivo de desktop otra vez. La
     mascara (arriba) no cambia; solo la img crece adentro, recortada por su
     overflow. El punto de interes (la cara de Elena) no esta en el centro
     geometrico de la foto original (800x800): midiendo pixel a pixel, la
     cara cae en ~(405,305), es decir ~50.6%/38.1% del ancho/alto —
     practicamente centrada en X, mas arriba del centro en Y. Para que quede
     CENTRADA en el circulo una vez zoomeada (no solo anclada en su lugar),
     el escalado se combina con un translate: con transform-origin en el
     centro (default), "scale(2) translate(dx,dy)" mueve ese punto a
     (0.5-dx_frac)*2 de offset respecto al centro — despejando, dx/dy =
     0.5 - posicion_relativa del punto de interes. Version anterior
     (10%,18%) partia de una estimacion visual a ojo que resulto imprecisa
     (el usuario mostro una captura con la cara corrida a la derecha); esta
     usa medicion real sobre la imagen. */
  .header-galeria .foto-perfil {
    transition: transform 5s ease;
  }

  @media (hover: hover) and (pointer: fine) {
    .header-galeria .foto-perfil-mascara:hover .foto-perfil {
      transform: scale(2) translate(0%, 12%);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .header-galeria .foto-perfil {
      transition: none;
    }
  }

  .header-galeria .texto-columna {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1;
  }

  .header-galeria .texto-intro {
    /* Ancho acotado para que el bloque de texto (a 1.4 de line-height)
       cierre en 8 lineas, igualando la altura de la foto (224px). */
    max-width: 680px;
  }
}

/* ---------- Mosaico (masonry) — Fase 2 ---------- */

.mosaico {
  --grid-cols: 2;
  --grid-gap: 8px;
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), 1fr);
  grid-auto-rows: 1px;
  gap: var(--grid-gap);
  padding: 0 1rem 3rem;
  max-width: 92rem;
  margin: 0 auto;
  /* El masonry coloca las obras en posiciones visuales que no siguen el orden
     del DOM; esto hace que teclado/lectores de pantalla las recorran en el
     orden VISUAL correcto. Sin soporte, cae al orden del DOM (aceptable). */
  reading-flow: grid-rows;
}

@media (min-width: 640px) {
  .mosaico {
    --grid-cols: 3;
    --grid-gap: 12px;
    padding: 0 1.5rem 4rem;
  }
}

@media (min-width: 1024px) {
  .mosaico {
    --grid-cols: 4;
    padding: 0 2rem 4rem;
  }
}

@media (min-width: 1400px) {
  .mosaico {
    --grid-cols: 5;
  }
}

.obra {
  position: relative;
  overflow: hidden;
  margin: 0;
  background: var(--color-fondo);
  cursor: pointer;
}

/* Marca de "ya vista" (Fase 4) — durante la sesion actual, no persiste entre
   visitas. Icono de ojo (sitio/img/eye.svg, ya blanco) abajo a la derecha,
   con sombra para que se lea encima de cualquier obra, clara u oscura. */
.obra.vista::after {
  content: "";
  position: absolute;
  right: 18px;
  bottom: 12px;
  width: 20px;
  height: 20px;
  background-image: url("../img/eye.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.8));
  pointer-events: none;
}

/* Hover en desktop (Fase 4): oscurece la imagen y muestra ficha (titulo,
   tecnica, anio, medidas) encima. Solo con hover "de verdad" (mouse fino) —
   sin esto, un tap en movil deja el estado :hover "pegado" hasta el proximo
   toque en otro lado, que es justo lo que CLAUDE.md pide evitar ("en movil
   no hay hover"). */
.obra-ficha-hover {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0;
  padding: 1rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease;
}

/* Titulo y lineas comparten fuente/tamano/color — lo unico que los distingue
   es el peso (pedido explicito). Cuatro lineas: titulo, tecnica, medidas, anio. */
.obra-ficha-hover-titulo,
.obra-ficha-hover-linea {
  font-family: var(--font-titulo);
  font-size: 0.85rem;
  line-height: 1.25;
  color: var(--color-texto);
}

.obra-ficha-hover-titulo {
  font-weight: 700;
}

.obra-ficha-hover-linea {
  font-weight: 400;
}

@media (hover: hover) and (pointer: fine) {
  .obra img {
    transition: filter 200ms ease, opacity 500ms ease-out;
  }
  .obra:hover img {
    filter: brightness(0.4);
  }
  .obra:hover .obra-ficha-hover {
    opacity: 1;
  }
}

.obra img {
  /* Variable (no numero suelto): asi el JS del reacomodo animado (Fase 3) puede
     leerla y combinarla con su propio translate sin duplicar el valor a mano. */
  --escala-thumb: 0.968;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  border-radius: 9px;
  opacity: 0;
  transform: scale(var(--escala-thumb));
  /* Mismos valores que la fase 2 del fundido dirigido por JS (galeria.js,
     DURACION_ENTRADA_MS) para que se sientan como un solo sistema — este es
     el fallback/base; galeria.js pisa esto por inline style con su propio
     escalon cuando corresponde. */
  transition: opacity 500ms ease-out;
}

.obra img.cargada {
  opacity: 1;
}

/* Oculta por filtro/busqueda (distinto del atributo [hidden], que es para
   secciones enteras). display:none saca al elemento del grid sin dejar hueco. */
.obra.oculta {
  display: none;
}

/* Imagen que falla al cargar: placeholder discreto con el titulo, no el icono roto. */
.obra.error-carga img {
  display: none;
}

.obra.error-carga::after {
  content: attr(data-titulo);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.75rem;
  text-align: center;
  font-size: 0.8rem;
  color: var(--color-texto-tenue);
}

/* Aparicion suave al entrar en viewport (mejora progresiva, CSS puro). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .obra {
      animation: aparecer-obra linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 25%;
    }

    @keyframes aparecer-obra {
      from {
        opacity: 0;
        transform: translateY(12px);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
  }
}

/* ---------- Seccion Trayectoria — Fase 5 ---------- */

#trayectoria {
  padding: 3rem 1.25rem 4rem;
  /* Mas ancha que antes (42rem): el cuerpo de texto usa el mismo tamano que
     el intro del header (1.2rem, ver mas abajo) — una columna angosta con
     letra grande se ve desbalanceada. */
  max-width: 50rem;
  margin: 0 auto;
}

#trayectoria h2 {
  font-family: var(--font-titulo);
  font-weight: 700;
  font-size: 1.6rem;
  margin: 0 0 2.5rem;
}

.trayectoria-apartado {
  margin: 0 0 3rem;
}

.trayectoria-apartado h3 {
  font-family: var(--font-titulo);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--color-acento);
  margin: 0 0 1.25rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-linea);
}

/* Mismo estilo que .texto-intro del header (pedido explicito) — el unico
   color distinto en toda la seccion es el de los links, mas abajo. */
.trayectoria-texto p,
.trayectoria-item p,
.bibliografia-item {
  font-size: 1.2rem;
  line-height: 1.3;
  color: var(--color-texto);
  margin: 0 0 1rem;
  /* Las URLs largas de Prensa/Bibliografia (texto plano enlazado, ver
     enlazarURLs en interfaz.js) no tienen espacios para partir en un salto
     de linea normal — sin esto desbordan el ancho en movil. */
  overflow-wrap: break-word;
}

.trayectoria-texto p:last-child,
.trayectoria-item p:last-child {
  margin-bottom: 0;
}

.trayectoria-item {
  margin: 0 0 1.5rem;
}

.trayectoria-item:last-child {
  margin-bottom: 0;
}

.trayectoria-item h4 {
  font-family: var(--font-titulo);
  font-weight: 700;
  font-size: 0.95rem;
  margin: 0 0 0.35rem;
}

.bibliografia-item:last-child {
  margin-bottom: 0;
}

/* Enlaces dentro del contenido de Trayectoria (Prensa, Bibliografia, y las
   URLs sueltas de Arte Publico) — el subrayado los distingue del texto
   plano sin depender solo del color (accesibilidad). */
.trayectoria-texto a,
.trayectoria-item a,
.bibliografia-item a {
  color: var(--color-acento);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.trayectoria-texto a:hover,
.trayectoria-item a:hover,
.bibliografia-item a:hover {
  color: var(--color-texto);
}

[hidden] {
  display: none !important;
}

/* ---------- Visor expandido — Fase 4 ---------- */

.visor {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 3.5rem 1rem 1.5rem;
  background: rgba(8, 8, 8, 0.94);
  cursor: pointer;
  opacity: 1;
  transition: opacity 220ms ease, display 220ms allow-discrete;
}

.visor[hidden] {
  opacity: 0;
}

@starting-style {
  .visor:not([hidden]) {
    opacity: 0;
  }
}

body.visor-abierto {
  overflow: hidden;
}

.visor-marco {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  max-width: 100%;
  max-height: 100%;
  cursor: default;
}

.visor-media {
  position: relative;
  display: grid;
  place-items: center;
  max-width: min(92vw, 1400px);
  max-height: 68vh;
}

/* width/height:100% (no auto/auto): el contenedor ya llega con su tamano
   final fijado por JS (tamanoContenido() en galeria.js, a partir de
   thumb_w/thumb_h) ANTES de que la imagen cargue — asi la imagen simplemente
   llena esa caja ya correcta desde el primer instante, sin depender de su
   propio tamano intrinseco (que mientras carga es 0, o el de reemplazo por
   defecto de la spec CSS). object-fit:contain queda como red de seguridad
   ante cualquier desajuste minimo de redondeo. El <iframe> recibe su propio
   ancho/alto por JS (dimensionarIframe) con mayor especificidad (estilo
   inline), asi que esta regla no lo afecta en la practica. */
.visor-media img,
.visor-media iframe {
  max-width: min(92vw, 1400px);
  max-height: 68vh;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 4px;
}

.visor-imagen {
  position: relative;
}

/* Un <iframe> no tiene tamano/proporcion intrinseca real (a diferencia de
   una <img>) — ni los atributos width/height HTML ni aspect-ratio resultan
   confiables dentro de este grid (probado: sin tamano fijo cae al default
   del navegador ~300x150, o a 0x0 con aspect-ratio + auto en este layout).
   Por eso el tamano se calcula y fija por JS (dimensionarIframe en
   galeria.js), igual que el ancho de la ficha. */
.visor-iframe {
  border: none;
}

.visor-play-video {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.55);
  color: var(--color-blanco);
  font-size: 1.4rem;
  display: grid;
  place-items: center;
  cursor: pointer;
}

.visor-play-video:hover {
  background: rgba(0, 0, 0, 0.7);
}

.visor-spinner {
  position: absolute;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  border: 3px solid var(--color-linea);
  border-top-color: var(--color-acento);
  animation: girar-spinner 800ms linear infinite;
}

@keyframes girar-spinner {
  to {
    transform: rotate(360deg);
  }
}

/* El ancho se fija por JS (sincronizarAnchoFicha en galeria.js) para que
   calce exacto con el ancho real de la imagen/iframe mostrado — asi el
   titulo+detalle entran en una sola linea en el caso normal. Si de todos
   modos no entra (imagen muy angosta + texto muy largo), el texto hace un
   salto de linea natural — nunca se trunca/recorta (pedido explicito). */
.visor-ficha {
  text-align: center;
  cursor: default;
}

.visor-ficha-linea {
  margin: 0;
}

/* Titulo y resto (tecnica/medidas/anio) comparten fuente/tamano/color, en
   una sola linea — lo unico que los distingue es el peso (pedido explicito). */
.visor-ficha-titulo,
.visor-ficha-detalle {
  font-family: var(--font-titulo);
  font-size: 0.85rem;
  color: var(--color-texto);
  /* Apretado en movil (2026-08-18: primero "mucho mas apretado" a 1.15,
     despues "un poco menos apretado, apenas un poco" a 1.25 — antes
     heredaba el 1.5 del body). Desktop vuelve al 1.5 original (ver @media
     1024px). */
  line-height: 1.25;
}

.visor-ficha-titulo {
  font-weight: 700;
  /* Movil: titulo en su propia linea (pedido explicito 2026-08-18) — el
     tamano de letra no cambia, solo el layout. Desktop vuelve a inline,
     una sola linea (ver @media 1024px). */
  display: block;
}

.visor-ficha-detalle {
  font-weight: 400;
  /* Segunda linea, cerca del titulo (ver arriba) — antes esta margen vivia
     en el wrapper .visor-ficha-detalle-fila (eliminado 2026-08-18: el
     compartir ahora tiene su PROPIA tercera linea, ver .visor-compartir
     mas abajo, asi que ya no hace falta envolver ficha+compartir juntos).
     0.12rem (subido de 0.05rem, mismo dia): "un poco menos apretado, apenas
     un poco". */
  display: block;
  margin-top: 0.12rem;
}

.visor-cerrar {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  border: none;
  background: var(--color-fondo-elevado);
  color: var(--color-texto);
  font-size: 1rem;
  display: grid;
  place-items: center;
  cursor: pointer;
  z-index: 1;
}

.visor-cerrar:hover {
  background: var(--color-boton-hover);
}

/* Icono de compartir (share.svg, ya blanco). En desktop va en linea al
   final de la ficha, separado ~15px de la ultima letra del texto (pedido
   explicito) — ver @media 1024px, que revierte el display:block/margin de
   aca. En movil es su PROPIA tercera linea, centrada (2026-08-18, pedido
   explicito: antes compartia la segunda linea con la ficha). 40px de
   ancho/alto en movil (2026-08-18: el icono anterior de 1.3rem/~21px
   quedaba por debajo del minimo tactil de 40-44px, y en la practica el
   dedo fallaba el boton y tocaba el fondo del visor en vez de compartir —
   de ahi el reporte de "no funciona"). En desktop, con mouse de precision,
   se queda en el tamano chico original. */
.visor-compartir {
  display: block;
  margin: 0.35rem auto 0;
  /* 3.25rem = 2.5rem (40px) +30% (pedido explicito 2026-08-18). */
  width: 3.25rem;
  height: 3.25rem;
  padding: 0.6rem;
  border: none;
  border-radius: 50%;
  background: none;
  cursor: pointer;
}

.visor-compartir img {
  width: 100%;
  height: 100%;
  display: block;
}

.visor-compartir:hover {
  background: var(--color-fondo-elevado);
}

/* Confirmacion de "copiado": circulo con el acento detras del icono, breve
   (ver setTimeout en compartirObraActual) — no se toca el <img> para no
   perder el icono al restaurar. */
.visor-compartir.copiado {
  background: var(--color-acento);
}

@media (min-width: 1024px) {
  .visor-ficha-titulo,
  .visor-ficha-detalle {
    font-size: 1rem;
    line-height: 1.5;
  }

  /* Vuelve a una sola linea (el layout de 3 lineas es especifico de movil,
     ver reglas base de mas arriba). */
  .visor-ficha-titulo,
  .visor-ficha-detalle {
    display: inline;
  }

  .visor-ficha-detalle {
    margin-top: 0;
  }

  /* Desktop usa mouse de precision — se queda con el icono chico original
     (el agrandado a 40px es especificamente para el dedo en movil, ver
     comentario en la regla base de .visor-compartir), en linea al final de
     la ficha (no en su propia linea — eso es especifico de movil). */
  .visor-compartir {
    display: inline-flex;
    vertical-align: middle;
    margin: 0 0 0 15px;
    width: 1.3rem;
    height: 1.3rem;
    padding: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .visor {
    transition: none;
  }
  .visor-spinner {
    animation-duration: 1600ms;
  }
}

/* ---------- Slideshow a pantalla completa — Fase 4 (desactivado en movil, ver galeria.js) ---------- */

.slideshow {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  background: #000;
  cursor: pointer;
  opacity: 1;
  transition: opacity 220ms ease, display 220ms allow-discrete;
}

.slideshow[hidden] {
  opacity: 0;
}

@starting-style {
  .slideshow:not([hidden]) {
    opacity: 0;
  }
}

.slideshow-imagen {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  opacity: 0;
}

.slideshow-imagen.visible {
  opacity: 1;
}

/* Fundido entre fotos (0.7s, pedido explicito) — sin reduced-motion no hay
   transition, asi que el cambio de opacidad es instantaneo (sin el hueco de
   700ms en negro que tendria una foto real animandose). */
@media (prefers-reduced-motion: no-preference) {
  .slideshow-imagen {
    transition: opacity 700ms ease;
  }
}

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