/* Visor: índice lateral con efecto lupa + foto grande, sobre el mismo papel crema. */

html.viewer-open { overflow: hidden; }

.viewer {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: none;
  background: var(--paper);
  opacity: 0;
  transition: opacity .35s var(--ease);
}
.viewer.is-open {
  display: block;
  opacity: 1;
}

/* --- Índice lateral ------------------------------------------------------ */

.viewer__rail {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: clamp(172px, 14vw, 200px);
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
  cursor: default;
  z-index: 2;
}

.viewer__track {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  will-change: transform;
}

/* Todas del mismo ancho y alineadas: la curva la dibuja el efecto lupa que
   aplica el JS en cada cuadro (por eso aquí no hay transición: el movimiento
   ya viene animado desde el bucle). */
.viewer__thumb {
  display: block;
  width: var(--w, 86px);
  height: var(--h, 64px);
  margin: 0 0 12px;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: var(--paper-2);
  cursor: pointer;
  opacity: .34;
  /* El índice es navegación: se queda redondeado aunque la web vaya en recto */
  border-radius: 6px;
  transform-origin: left center;
  will-change: transform;
}
.viewer__thumb img { width: 100%; height: 100%; object-fit: cover; }

/* --- Escenario ----------------------------------------------------------- */

.viewer__stage {
  position: absolute;
  inset: 0;
  left: clamp(172px, 14vw, 200px);
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: clamp(10px, 1.6vh, 22px);
  padding: clamp(14px, 2.4vh, 30px) clamp(16px, 3vw, 56px);
  padding-top: max(env(safe-area-inset-top), clamp(14px, 2.4vh, 30px));
  text-align: center;
}

.viewer__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  text-transform: uppercase;
  letter-spacing: -.01em;
  font-size: clamp(.95rem, 1.8vw, 1.35rem);
  min-height: 1.2em;
}

.viewer__frame {
  position: relative;
  min-height: 0;
  will-change: transform;
}

/* Absolutas y con object-fit: así la foto nunca decide el alto de la caja
   (si lo decidiera, se saldría por abajo) y el fundido entre las dos capas
   ocurre exactamente en el mismo sitio. */
.viewer__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  /* La que sale se va deprisa… */
  transition: opacity .26s var(--ease);
}
/* …y la que entra llega un poco después: el cruce pasa por el papel en vez de
   superponer dos fotos de proporciones distintas. */
.viewer__img.is-front { opacity: 1; transition: opacity .5s var(--ease) .14s; }

.viewer__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 3vw, 40px);
  padding-bottom: max(env(safe-area-inset-bottom), 4px);
}

.viewer__act {
  border: 0;
  background: transparent;
  padding: 6px 2px;
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 108%;
  text-transform: uppercase;
  font-size: clamp(.95rem, 1.65vw, 1.22rem);
  letter-spacing: -.01em;
  color: var(--ink);
  cursor: pointer;
  transition: color .2s var(--ease), transform .2s var(--ease);
}
.viewer__act:hover { color: var(--accent); transform: translateY(-1px); }
.viewer__count { min-width: 5ch; }

/* --- Ficha técnica ------------------------------------------------------- */

.viewer__info {
  position: absolute;
  right: clamp(16px, 3vw, 56px);
  bottom: clamp(64px, 9vh, 96px);
  z-index: 3;
  max-width: min(340px, 70vw);
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--card) 94%, transparent);
  backdrop-filter: blur(14px);
  box-shadow: var(--sh-2);
  text-align: left;
  animation: infoIn .3s var(--ease);
}
@keyframes infoIn { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
.viewer__info p { margin: 0 0 6px; font-size: .88rem; }
.viewer__info p:last-child { margin: 0; color: var(--muted); }
.viewer__info-title:empty { display: none; }
.viewer__info-exif { line-height: 1.7; }
.viewer__info-tags {
  margin-top: 10px !important;
  font-size: .82rem;
  color: var(--ink-soft) !important;
  text-transform: lowercase;
}

/* --- Móvil: el índice pasa abajo, en horizontal -------------------------- */

@media (max-width: 859px) {
  .viewer__rail {
    left: 0; right: 0; top: auto;
    bottom: max(env(safe-area-inset-bottom), 8px);
    width: 100%;
    /* Alto suficiente para la miniatura + lo que la lupa la levanta y agranda,
       o se vería cortada por arriba */
    height: 104px;
  }
  .viewer__track { top: auto; bottom: 0; left: 0; width: max-content; display: flex; align-items: flex-end; }
  .viewer__thumb {
    margin: 0 10px 0 0;
    width: 64px;
    height: 64px;
    border-radius: 9px;
    transform-origin: center bottom;   /* en móvil la lupa crece hacia arriba */
  }

  .viewer__stage {
    left: 0;
    grid-template-rows: auto minmax(0, 1fr) auto;
    padding-bottom: calc(120px + env(safe-area-inset-bottom));
  }
  .viewer__info { bottom: 200px; right: 16px; left: 16px; max-width: none; }
}

/* --- Foto sola, sin nada alrededor --------------------------------------- */

.viewer__frame { cursor: zoom-in; }

.viewer__solo {
  position: absolute;
  inset: max(env(safe-area-inset-top), 14px) 14px auto 14px;
  z-index: 5;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.viewer.is-solo .viewer__solo { display: flex; animation: infoIn .3s var(--ease); }

.viewer__encuadre {
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: var(--r-pill);
}

/* --- Cristal --------------------------------------------------------------
   Lo que flota sobre la foto no es una caja opaca: deja pasar la imagen
   desenfocada y saturada, con un filo claro arriba y sombra por debajo para
   que se lea como un vidrio con canto y no como un rectángulo translúcido.
   El tinte sale de --card, así que con la paleta oscura el cristal se oscurece
   solo en vez de quedarse en una pastilla blanca. */
.viewer__encuadre,
.viewer__ico--salir,
.viewer.is-solo.is-fill.is-movible .viewer__solo::after {
  /* El tinte no baja de aquí: por debajo, sobre una foto oscura los iconos
     dejan de leerse. Aun al 72 % se ve la imagen moverse por detrás. */
  background:
    linear-gradient(
      color-mix(in srgb, var(--card) 72%, transparent),
      color-mix(in srgb, var(--card) 54%, transparent)
    );
  backdrop-filter: blur(22px) saturate(190%);
  -webkit-backdrop-filter: blur(22px) saturate(190%);
  border: 1px solid color-mix(in srgb, var(--card) 60%, transparent);
  box-shadow:
    /* filo de luz en el borde superior y base algo más densa */
    0  1px 0 color-mix(in srgb, var(--card) 75%, transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink)   7%, transparent) inset,
    /* la sombra separa el cristal de la foto */
    0 10px 30px color-mix(in srgb, var(--ink) 17%, transparent),
    0  2px  8px color-mix(in srgb, var(--ink) 10%, transparent);
}

.viewer__ico {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.viewer__ico svg { width: 21px; height: 21px; }
.viewer__ico:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); }
/* El activo no es un adhesivo opaco: deja intuir la foto por debajo, pero
   con tinta suficiente para que el icono se lea sobre cualquier imagen. */
.viewer__ico.is-on {
  background: color-mix(in srgb, var(--ink) 86%, transparent);
  color: var(--paper);
  box-shadow: 0 1px 6px color-mix(in srgb, var(--ink) 28%, transparent);
}
.viewer__ico:active { transform: scale(.93); }

.viewer__ico--salir { position: absolute; right: 0; }

/* En modo solo desaparece todo lo demás y la foto se queda con la pantalla */
.viewer.is-solo .viewer__rail,
.viewer.is-solo .viewer__title,
.viewer.is-solo .viewer__bar {
  opacity: 0;
  pointer-events: none;
}
.viewer.is-solo .viewer__stage {
  left: 0;
  padding: 0;
  gap: 0;
  grid-template-rows: 0 minmax(0, 1fr) 0;
}
.viewer.is-solo .viewer__frame {
  transform: none !important;
  cursor: zoom-out;
}
/* Encuadre 1: la foto entera, con aire alrededor */
.viewer.is-solo .viewer__img {
  padding: clamp(14px, 3.5vw, 60px);
  padding-top: max(env(safe-area-inset-top), clamp(14px, 3.5vw, 60px));
  padding-bottom: max(env(safe-area-inset-bottom), clamp(14px, 3.5vw, 60px));
}
/* Encuadre 2: llena la pantalla aunque tenga que recortar */
.viewer.is-solo.is-fill .viewer__img {
  padding: 0;
  object-fit: cover;
  object-position: 50% 50%;
}

/* Si sobra foto fuera del encuadre, se puede arrastrar para recorrerla */
.viewer.is-solo.is-fill.is-movible .viewer__frame { cursor: grab; touch-action: none; }
.viewer.is-solo.is-fill.is-moviendo .viewer__frame { cursor: grabbing; }
/* Mientras se arrastra, la foto sigue al dedo sin suavizado */
.viewer.is-moviendo .viewer__img { transition: none; }

/* Pista discreta: aparece unos segundos al llenar la pantalla y se va sola */
.viewer.is-solo.is-fill.is-movible .viewer__solo::after {
  content: attr(data-pista);
  position: absolute;
  left: 50%;
  top: calc(100% + 14px);
  transform: translateX(-50%);
  padding: 7px 14px;
  border-radius: var(--r-pill);
  font-size: .78rem;
  color: var(--ink-soft);
  white-space: nowrap;
  pointer-events: none;
  animation: pista 4s var(--ease) forwards;
}
@keyframes pista {
  0%   { opacity: 0; transform: translate(-50%, -6px) }
  12%  { opacity: 1; transform: translate(-50%, 0) }
  72%  { opacity: 1 }
  100% { opacity: 0 }
}

.viewer__rail, .viewer__title, .viewer__bar { transition: opacity .3s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .viewer__frame { transform: none !important; }
}
