/* T309 Recuperación 12B -- lector real de revista, tema oscuro monocromo
   extraído literalmente del visor legacy real (visor-revista/{numero}/,
   <style> inline). Variables, medidas, tipografías y comportamiento visual
   reproducidos tal cual; solo el prefijo `.cv-lector-body`/`.cv-lector-root`
   sustituye a `html, body` (aquí conviven con el resto del sitio a través
   de base_lector.html.twig, un documento propio sin cabecera/pie). */
:root {
  --stage-0: #060606;
  --stage-1: #121212;
  --stage-2: #1c1c1c;
  --ink: #f4f4f2;
  --ink-dim: #8f8f8a;
  --gold: #ffffff;
  --gold-dim: rgba(255, 255, 255, 0.55);
  --gold-soft: rgba(255, 255, 255, 0.1);
  --gold-bright: #ffffff;
  --page-bg: #fff;
  --shadow-color: 0deg 0% 0%;
  --serif: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
  --display: Didot, "Big Caslon", Georgia, "Iowan Old Style", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
}

.cv-lector-root, .cv-lector-root * { box-sizing: border-box; }
html:has(.cv-lector-body), .cv-lector-body { margin: 0; padding: 0; height: 100%; background: var(--stage-0); overflow-x: hidden; }
.cv-lector-body {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  color: var(--ink);
  font-family: var(--sans);
  background:
    radial-gradient(ellipse 90% 65% at 50% 8%, var(--stage-2), transparent 68%),
    radial-gradient(ellipse 120% 90% at 50% 100%, hsl(var(--shadow-color) / 0.5), transparent 60%),
    var(--stage-0);
  position: relative;
}
.cv-lector-body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.05; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.6rem clamp(0.8rem, 3vw, 2.2rem) 0.55rem; flex: 0 0 auto; flex-wrap: wrap;
  border-bottom: 1px solid var(--gold-soft); position: relative; z-index: 10;
}
.brand { display: flex; align-items: center; }
.brand img { height: clamp(22px, 3.4vw, 34px); width: auto; filter: invert(1); display: block; }
.topbar-right { display: flex; align-items: center; gap: 0.6rem; }
.chipBtn {
  display: flex; align-items: center; gap: 0.4rem;
  background: transparent; border: 1px solid var(--gold-soft); color: var(--gold);
  font-family: var(--sans); font-size: 0.63rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.5rem 0.95rem; border-radius: 2px; cursor: pointer;
  transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
  position: relative;
}
.chipBtn:hover { background: var(--gold-soft); border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold-soft); }
.chipBtn svg { width: 0.9rem; height: 0.9rem; }
.chipBtn.active { background: var(--gold-soft); border-color: var(--gold); color: var(--gold-bright); }
.issue-tag {
  font-family: var(--sans); font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-dim); text-align: right; white-space: nowrap; margin-left: 0.5rem;
  padding-left: 1rem; border-left: 1px solid var(--gold-soft);
}
.issue-tag em { display: block; font-style: normal; font-family: var(--serif); color: var(--gold); font-size: 0.85rem; letter-spacing: 0.04em; margin-top: 0.2rem; }

.sharePanel {
  position: absolute; top: calc(100% + 0.5rem); right: 0;
  background: var(--stage-2); border: 1px solid rgba(244,244,242,0.4); border-radius: 10px;
  padding: 0.7rem; display: none; flex-direction: column; gap: 0.4rem; width: 220px;
  box-shadow: 0 16px 40px rgba(0,0,0,0.65), 0 0 0 6px rgba(0,0,0,0.35); z-index: 30;
}
.sharePanel.open { display: flex; }
.sharePanel a, .sharePanel button {
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--ink); text-decoration: none; font-size: 0.78rem;
  background: rgba(0,0,0,0.5); border: none; padding: 0.45rem 0.5rem; border-radius: 6px;
  cursor: pointer; text-align: left; font-family: var(--sans);
}
.sharePanel a:hover, .sharePanel button:hover { background: var(--gold-soft); }
.sharePanel svg { width: 1rem; height: 1rem; flex: 0 0 auto; color: var(--gold); }

.stage-wrap { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; padding: 0.15rem 0.2rem; min-height: 0; position: relative; z-index: 2; }
.reader { display: flex; align-items: center; height: 100%; width: 100%; justify-content: center; position: relative; }

.navBtn {
  position: fixed; top: 50%; transform: translateY(-50%); z-index: 20;
  width: 2.5rem; height: 2.5rem; border-radius: 50%;
  border: 1px solid var(--gold-soft); background: hsl(var(--shadow-color) / 0.3); color: var(--gold);
  font-family: var(--serif); font-size: 1.2rem; line-height: 1; display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
  opacity: 0.55; backdrop-filter: blur(3px);
}
.navBtn:hover:not(:disabled) {
  background: var(--gold-soft); border-color: var(--gold); opacity: 1; color: var(--gold-bright);
  box-shadow: 0 0 0 5px var(--gold-soft);
}
.navBtn:disabled { opacity: 0.12; cursor: default; }
.navBtn:focus-visible, .zone:focus-visible, .chipBtn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.navBtnPrev { left: 0.4rem; }
.navBtnNext { right: 0.4rem; }

.stage3d { position: relative; perspective: 3400px; height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; min-width: 0; }
.book {
  position: relative;
  height: 88%;
  aspect-ratio: 0.708;
  max-width: 92%;
  box-shadow: 0 22px 34px hsl(var(--shadow-color) / 0.22), 0 4px 10px hsl(var(--shadow-color) / 0.14);
}
.half { position: absolute; top: 0; bottom: 0; width: 50%; background: var(--page-bg); overflow: hidden; }
.halfLeft { left: 0; border-radius: 3px 0 0 3px; }
.halfRight { left: 50%; border-radius: 0 3px 3px 0; }
.half.blank { background: transparent; }
.half img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; -webkit-user-drag: none; }
.spineShade {
  position: absolute; inset: 0; pointer-events: none; z-index: 3;
  background: linear-gradient(90deg, rgba(0,0,0,0.09) 0%, transparent 4%, transparent 96%, rgba(0,0,0,0.09) 100%);
}
.book.single { aspect-ratio: 0.708; }
.book.single .halfLeft, .book.single .spineShade { display: none; }
.book.single .halfRight { left: 0; width: 100%; border-radius: 3px; }

/* T309 Recuperación 21 -- hallazgo de José: slot vacío fantasma a la
   izquierda de la portada. Causa raíz: .book.single (el único estado que
   colapsa realmente el diseño a una columna) solo lo activa el interruptor
   global de modo página-única/doble del usuario -- nunca el hecho de que
   el spread actual (la portada, o la última página si el total es impar)
   no tenga página izquierda real. .half.blank solo ocultaba el fondo, no
   el hueco de 50% de ancho que seguía reservado dentro de la caja ancha
   de modo doble. Se añade .book.lone, aplicada por JS solo cuando el
   spread mostrado no tiene página izquierda (independiente del modo
   global), con el mismo colapso visual que .single -- el modo doble
   genuino de las páginas interiores con 2 páginas reales no se toca. */
.book.lone { aspect-ratio: 0.708; }
.book.lone .halfLeft, .book.lone .spineShade { display: none; }
.book.lone .halfRight { left: 0; width: 100%; border-radius: 3px; }

/* T309 Recuperación 36 -- hallazgo de Codex: el rectángulo fuente real
   (Lorelize/PDF) mide solo unos 7px de alto, insuficiente para usarlo de
   forma fiable con el cursor. left/top ahora los coloca el JS en el
   CENTRO real del dato impreso (no la esquina), por eso el
   translate(-50%,-50%): el área interactiva puede crecer alrededor de
   ese punto sin desplazarlo nunca. El propio JS
   (calcularAreasTactilesSeguras) ya calcula width/height ampliados en %
   respetando un mínimo en píxeles reales y sin invadir al hotspot
   vecino, así que aquí no hace falta duplicar esa lógica con
   min-width/min-height -- solo centrar. */
.cv-revista-hotspot {
  position: absolute; transform: translate(-50%, -50%);
  border-radius: 4px; cursor: pointer; z-index: 6;
  outline-offset: 2px; -webkit-tap-highlight-color: rgba(255,255,255,0.2);
}
.cv-revista-hotspot:hover, .cv-revista-hotspot:focus-visible { outline: 2px solid var(--gold); }

.zones { position: absolute; inset: 0; display: flex; z-index: 5; }
.zone { flex: 1; cursor: pointer; display: flex; align-items: center; background: transparent; border: none; padding: 0; }
.zone .chev {
  opacity: 0; color: var(--ink); background: hsl(0 0% 0% / 0.28); backdrop-filter: blur(2px);
  width: 1.9rem; height: 1.9rem; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 1rem; transition: opacity 0.15s ease;
}
.zone.zoneLeft { justify-content: flex-start; padding-left: 0.5rem; }
.zone.zoneRight { justify-content: flex-end; padding-right: 0.5rem; }
.zone:hover .chev { opacity: 0.85; }
.zone:disabled { cursor: default; }

.crossfade { transition: opacity 0.5s ease; }
.crossfade.hidden { opacity: 0; }

/* T309 Recuperación 24 -- efecto real de "pase de página" (leaf flip),
   portado literalmente del visor legacy real (visor-revista/{numero}/,
   <script> inline: runLeafAnimation(), FLIP_MS=1360, easeInOutSine()).
   Cada .leaf es una hoja física ocupando exactamente el hueco de la mitad
   que gira (misma caja que .halfLeft/.halfRight), oculta (visibility:
   hidden) salvo mientras dura el volteo (.leaf.flipping). .face.front
   muestra la página que se está abandonando, .face.back (pre-rotada 180°)
   la página que queda al posarse en el otro lado; .foldShade es la sombra
   de pliegue junto al lomo y .sheen el brillo de papel, ambas con opacidad
   accionada por la fase de curvatura (Math.sin) igual que el legacy. Solo
   se usa en modo doble genuino -- portada/última página suelta y modo
   página única siguen con el crossfade .crossfade de arriba, que es el
   propio fallback diseñado por el legacy, no un error. */
.leaf {
  position: absolute; top: 0; bottom: 0; width: 50%;
  transform-style: preserve-3d;
  pointer-events: none;
  visibility: hidden;
  z-index: 9;
}
.leaf.flipping { visibility: visible; }
.leafRight { left: 50%; transform-origin: left center; }
.leafLeft { left: 0; transform-origin: right center; }
.leaf .face {
  position: absolute; inset: 0; overflow: hidden;
  background: var(--page-bg); backface-visibility: hidden;
}
.leaf .face img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; -webkit-user-drag: none; }
.leaf .face.back { transform: rotateY(180deg); }
.leaf .foldShade {
  position: absolute; inset: 0; pointer-events: none; opacity: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(0,0,0,0.35) 0%, transparent 30%);
}
.leafLeft .foldShade { background: linear-gradient(270deg, rgba(0,0,0,0.35) 0%, transparent 30%); }
.leaf .sheen {
  position: absolute; inset: 0; pointer-events: none; opacity: 0; z-index: 2;
  mix-blend-mode: soft-light;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,0.55) 50%, transparent 80%);
}
.book.single .leaf, .book.lone .leaf { display: none; }
@media (prefers-reduced-motion: reduce) {
  /* El propio JS (movimientoReducidoActivo()) evita entrar en el volteo
     de hoja cuando el usuario pide movimiento reducido y usa el crossfade
     corto de siempre en su lugar; esta regla es una red de seguridad a
     nivel CSS por si un .leaf quedara con una transición aplicada. */
  .leaf, .leaf .face, .leaf .foldShade, .leaf .sheen { transition: none !important; }
}

.counter-wrap {
  flex: 0 0 auto; display: flex; justify-content: center; align-items: center; gap: 0.5rem;
  padding: 0.5rem 0 0.7rem; border-top: 1px solid var(--gold-soft); margin-top: 0.2rem;
  position: relative; z-index: 2;
}
.counter {
  font-variant-numeric: tabular-nums; font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-dim); display: flex; align-items: center; gap: 0.7rem;
}
.counter .num { font-family: var(--serif); font-size: 0.82rem; letter-spacing: 0.02em; color: var(--ink); text-transform: none; }
.counter .track { width: 130px; height: 1px; background: var(--gold-soft); position: relative; overflow: hidden; }
.counter .track b { position: absolute; inset: 0 auto 0 0; background: var(--gold); transition: width 0.35s ease; }

.stepBtn {
  width: 1.7rem; height: 1.7rem; border-radius: 50%; border: 1px solid var(--gold-soft);
  background: transparent; color: var(--ink-dim); cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.stepBtn svg { width: 14px; height: 14px; }
.stepBtn:hover:not(:disabled) { background: rgba(244,244,242,0.08); color: var(--ink); }
.stepBtn:disabled { opacity: 0.3; cursor: default; }

.zoomOverlay {
  position: fixed; inset: 0; background: hsl(0 0% 0% / 0.88); z-index: 50; display: none; flex-direction: column;
}
.zoomOverlay.open { display: flex; }
.zoomTopbar { display: flex; justify-content: flex-end; padding: 0.9rem 1.1rem; flex: 0 0 auto; }
.zoomClose {
  width: 2.2rem; height: 2.2rem; border-radius: 50%; border: 1px solid rgba(244,244,242,0.3);
  background: transparent; color: var(--ink); font-size: 1.15rem; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.zoomClose:hover { background: rgba(244,244,242,0.12); }
.zoomScroll { flex: 1 1 auto; overflow: auto; cursor: grab; display: flex; }
.zoomScroll.dragging { cursor: grabbing; }
.zoomInner { margin: auto; display: flex; flex-shrink: 0; transition: width 0.28s ease; }
.zoomInner .half { position: static; width: 50%; }
.zoomInner.single .half { width: 100%; }
.zoomInner img { display: block; width: 100%; height: auto; user-select: none; -webkit-user-drag: none; }
.zoomControls {
  display: flex; justify-content: center; align-items: center; gap: 0.9rem; padding: 0.7rem 0 1.1rem; flex: 0 0 auto;
}
.zoomStep {
  width: 2.6rem; height: 2.6rem; border-radius: 50%;
  background: rgba(244,244,242,0.08); border: 1px solid rgba(244,244,242,0.28); color: var(--ink);
  font-size: 1.2rem; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.zoomStep:hover:not(:disabled) { background: rgba(244,244,242,0.2); }
.zoomStep:disabled { opacity: 0.3; cursor: default; }
.zoomPct {
  font-variant-numeric: tabular-nums; font-size: 0.75rem; color: rgba(244,244,242,0.75);
  min-width: 3.4em; text-align: center; letter-spacing: 0.04em;
}

.thumbsOverlay {
  position: fixed; inset: 0; background: hsl(0 0% 0% / 0.92); z-index: 50; display: none; flex-direction: column;
}
.thumbsOverlay.open { display: flex; }
.thumbsTopbar {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0.9rem 1.1rem; flex: 0 0 auto; gap: 1rem;
}
.jumpForm { display: flex; align-items: center; gap: 0.6rem; }
.jumpForm label { font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-dim); }
.jumpForm input {
  width: 4.2rem; background: rgba(244,244,242,0.08); border: 1px solid rgba(244,244,242,0.28);
  border-radius: 4px; color: var(--ink); font-size: 0.85rem; padding: 0.35rem 0.5rem;
  font-variant-numeric: tabular-nums;
}
.jumpForm input:focus { outline: 1px solid var(--ink); }
.jumpForm .chipBtn { padding: 0.4rem 0.85rem; }
.thumbsGrid {
  flex: 1 1 auto; overflow: auto; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 1.1rem; padding: 0.5rem 1.4rem 2rem;
}
.thumbCard {
  cursor: pointer; border: 1px solid rgba(244,244,242,0.18); border-radius: 3px; overflow: hidden;
  background: var(--page-bg); transition: border-color 0.15s ease, transform 0.15s ease;
}
.thumbCard:hover { border-color: rgba(244,244,242,0.6); transform: translateY(-2px); }
.thumbCard img { display: block; width: 100%; height: auto; }
.thumbCard .thumbNum {
  font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-dim);
  text-align: center; padding: 0.35rem 0;
}

.badge-note {
  position: fixed; bottom: 0.9rem; left: 0.9rem; font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold-dim); background: transparent; border: 1px solid var(--gold-soft);
  padding: 0.32rem 0.6rem; border-radius: 2px; opacity: 0.7; z-index: 2; pointer-events: none;
}
@media (max-width: 720px) { .badge-note { display: none; } }
@media (prefers-reduced-motion: reduce) { .crossfade { transition: none !important; } }

.loadingOverlay {
  position: fixed; inset: 0; z-index: 9998; background: var(--stage-0);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem;
}
.loadingOverlay.hidden { display: none; }
.loadingSpinner {
  width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid rgba(244,244,242,0.2); border-top-color: var(--ink);
  animation: loadingSpin 0.9s linear infinite;
}
@keyframes loadingSpin { to { transform: rotate(360deg); } }
.loadingText { font-family: var(--sans); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-dim); }
@media (prefers-reduced-motion: reduce) { .loadingSpinner { animation: none; } }

@media (max-width: 720px) {
  .book { height: 82%; max-width: 96%; }
  .navBtn { width: 2.1rem; height: 2.1rem; font-size: 1rem; }
  .counter .track { width: 70px; }
  .issue-tag { display: none; }
}
