* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  height: 100%;
  overflow: hidden;
  /* Evita que el swipe horizontal de dos dedos (trackpad) dispare atrás/adelante del
     navegador. Al hacer pinch-zoom en el PDF, el componente horizontal del gesto se
     interpretaba como swipe-atrás y te sacaba del libro a la biblioteca. El botón atrás y
     el logo→biblioteca siguen funcionando; solo se desactiva la navegación por GESTO. */
  overscroll-behavior-x: none;
  font-family: var(--font-ui);
  font-size: var(--font-size-base);
  background: var(--surface-0);
  color: var(--text);
  transition: background var(--transition-normal), color var(--transition-normal);
}

/* ============ SIDEBAR ============ */
.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--sidebar-width);
  height: 100%;
  background: var(--surface-1);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  z-index: 100;
  transform: translateX(-100%);
  /* Los paneles que ENTRAN en pantalla usan la curva de salida suave (--transition-panel):
     arrancan rápido y frenan largo. Con la curva simétrica anterior el drawer parecía
     arrastrarse. El lector (.reader-main) usa la MISMA curva y duración, si no el empuje
     del contenido y el panel van desacompasados. */
  transition: transform var(--transition-panel);
}

.sidebar.open {
  transform: translateX(0);
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Misma altura que la cabecera del lector y la del agente (borde inferior alineado). */
  height: var(--header-height);
  flex-shrink: 0;
  box-sizing: border-box;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
}

.sidebar-header h2 {
  font-size: 16px;
  font-weight: 600;
}

/* Tabs (v2: más limpias) */
.sidebar-tabs {
  display: flex;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border-soft);
}

.tab-btn {
  flex: 1 0 auto;
  white-space: nowrap;
  padding: 12px 10px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-soft);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.tab-btn:hover {
  color: var(--text);
}

.tab-btn.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

.tab-content {
  display: none;
  flex: 1;
  overflow-y: auto;
  padding: 12px;
}

.tab-content.active {
  display: block;
}

.sidebar-footer {
  flex: none;
  border-top: 1px solid var(--border);
  padding: 8px;
}
.sidebar-footer-btn {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 12px; border: none; border-radius: var(--r-sm); background: none;
  color: var(--text-soft); font-size: 14px; text-align: left; cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.sidebar-footer-btn:hover { background: var(--surface-3); color: var(--text); }

/* ============ BUTTONS ============ */
.icon-btn {
  background: none;
  border: none;
  color: var(--text-soft);
  font-size: 18px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.icon-btn:hover {
  background: var(--surface-3);
  color: var(--text);
}

.icon-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Botón-marca (logo → volver a la biblioteca): teñido de acento como identidad,
   igual que el logo coloreado de Play Books entre iconos neutros. Mantiene el
   emerald también en hover (solo cambia el fondo). */
.icon-btn.brand-btn, .icon-btn.brand-btn:hover { color: var(--accent); }
/* El botón de marca lleva el imagotipo completo (tile + página + cinta), no un
   glyph de línea: no hereda currentColor, sus colores vienen de --logo-*. */
.icon-btn.brand-btn .brand-mark { display: block; }

.primary-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 12px 24px;
  border-radius: 8px;
  font-size: 16px;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.primary-btn:hover {
  background: var(--accent-hover);
}

/* ============ FILTROS DE PANTALLA (brillo / luz nocturna, tipo Play Books) ============ */
/* Overlays a pantalla completa que NO capturan eventos. Brillo = capa negra que atenúa;
   luz nocturna = capa ámbar en `multiply` que entibia y recorta la luz azul. La web no
   puede tocar el brillo/temperatura reales del dispositivo, así que se emula en pantalla. */
.screen-filter {
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 9000;
  transition: opacity 0.15s var(--ease);
}
#screen-dim { background: #000; z-index: 9001; }
#night-warm { background: #ff8a2b; mix-blend-mode: multiply; }

/* Controles deslizantes con icono + valor (brillo, luz nocturna). */
.slider-control { display: flex; align-items: center; gap: 10px; }
.slider-control input[type="range"] { flex: 1; min-width: 0; }
.slider-ico { color: var(--text-faint); flex: 0 0 auto; display: inline-flex; }
.slider-value { min-width: 42px; text-align: right; font-size: 14px; color: var(--text-soft); }

/* ============ EMPTY STATES ============ */
.empty-state {
  color: var(--text-faint);
  text-align: center;
  padding: 24px;
  font-size: 14px;
}

/* ============ TOC (v3: jerarquía por grupos, estilo Notion) ============
   Antes era una lista plana donde la única señal de jerarquía era la sangría: parecía un
   listado de ficheros. Ahora hay tres niveles de lectura — cabecera de grupo (entrada con
   subentradas), capítulo y subcapítulo — y AIRE entre grupos, que es lo que deja escanear
   el índice de un vistazo. La estructura del DOM no cambia (todo siguen siendo <a>): el
   marcado de la sección actual, la atenuación por relevancia y los tests siguen igual. */
.toc-list a {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 12px;
  color: var(--text);
  text-decoration: none;
  border-radius: var(--r-sm);
  font-size: 14px;
  line-height: 1.45;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.toc-list a:hover {
  background: var(--surface-3);
}

/* Entrada que ABRE grupo (tiene subentradas): hace de título de sección. */
.toc-list a.has-sub {
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Aire entre grupos: el primer capítulo de nivel 1 después de un bloque de subentradas
   abre grupo nuevo. Es la separación que hace legible un índice largo. */
.toc-list a.subitem + a:not(.subitem) { margin-top: var(--s-4); }

.toc-list a.subitem {
  padding-left: 22px;
  font-size: 13px;
  color: var(--text-soft);
}

/* Punto guía en vez de sangría a secas: marca el nivel sin dibujar una línea vertical
   (las barras laterales están proscritas, ver DESIGN.md §1.6). */
.toc-list a.subitem .toc-label::before {
  content: '';
  display: inline-block;
  width: 4px; height: 4px;
  margin-right: 9px;
  vertical-align: middle;
  border-radius: 50%;
  background: var(--text-faint);
  opacity: 0.65;
}
.toc-list a.subitem.current .toc-label::before { background: currentColor; opacity: 1; }

/* Entrada escalonada del índice al abrir el panel (F4). Solo las primeras entradas: más
   allá el retardo acumulado se percibe como lentitud, no como cuidado. El resto aparece
   ya colocado, que es lo correcto —el ojo está arriba—. */
.sidebar.open .toc-list a { animation: toc-in 0.22s var(--ease-out-soft) both; }
@keyframes toc-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }
.sidebar.open .toc-list a:nth-child(1)  { animation-delay: 0ms; }
.sidebar.open .toc-list a:nth-child(2)  { animation-delay: 14ms; }
.sidebar.open .toc-list a:nth-child(3)  { animation-delay: 28ms; }
.sidebar.open .toc-list a:nth-child(4)  { animation-delay: 42ms; }
.sidebar.open .toc-list a:nth-child(5)  { animation-delay: 56ms; }
.sidebar.open .toc-list a:nth-child(6)  { animation-delay: 70ms; }
.sidebar.open .toc-list a:nth-child(7)  { animation-delay: 84ms; }
.sidebar.open .toc-list a:nth-child(8)  { animation-delay: 98ms; }
.sidebar.open .toc-list a:nth-child(n+9) { animation-delay: 112ms; }

/* Sección que se está leyendo: fondo suave y texto de acento, sin barra lateral. */
.toc-list a.current {
  background: var(--accent-soft);
  color: var(--accent-hover);
  font-weight: 600;
}
.toc-list a.current .toc-page { color: var(--accent-hover); }

/* Etiqueta flexible + número de página anclado a la derecha, como un índice impreso.
   El número no se encoge ni se parte aunque el título sea larguísimo. */
.toc-label { flex: 1; min-width: 0; }
.toc-page {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--text-faint);
}

/* ============ BÚSQUEDA (v2) ============ */
.search-box { padding: 12px; }
.search-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  transition: border-color var(--transition-fast);
}
.search-input:focus {
  outline: none;
  border-color: var(--accent);
}
.search-count { color: var(--text-faint); font-size: 12px; padding: 8px 12px; }
.search-results { display: flex; flex-direction: column; }
.search-hit {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px 12px;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: none;
  color: var(--text);
  cursor: pointer;
  font: inherit;
  transition: background var(--transition-fast);
}
.search-hit:hover { background: var(--surface-3); }
.search-hit-ctx { display: block; font-size: 13px; line-height: 1.5; }
.search-hit-ctx mark { background: var(--accent); color: var(--on-accent); border-radius: 3px; padding: 1px 3px; }
.search-hit-meta { display: block; margin-top: 4px; font-size: 11px; color: var(--text-faint); }

/* ============ BOOKMARKS (v2) ============ */
.bookmark-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--transition-fast);
}

.bookmark-item:hover {
  background: var(--surface-3);
}

.bookmark-item .bookmark-info {
  flex: 1;
  min-width: 0;
}

.bookmark-item .bookmark-title {
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bookmark-item .bookmark-chapter {
  font-size: 11px;
  color: var(--text-faint);
}

.bookmark-item .bookmark-page {
  font-size: 11px;
  color: var(--text-soft);
  margin-top: 2px;
}

.bookmark-item .bookmark-delete {
  background: none;
  border: none;
  color: var(--text-faint);
  cursor: pointer;
  padding: 4px;
  font-size: 14px;
}

.bookmark-item .bookmark-delete:hover {
  color: #e53935;
}

/* ============ HIGHLIGHTS LIST (v2) ============ */
.highlights-header {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.export-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 8px 14px;
  border-radius: var(--r-sm);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.export-btn:hover:not(:disabled) {
  background: var(--accent-hover);
}

.export-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

/* El color del subrayado se lleva en el propio fondo de la ficha (--hl-color lo pone
   renderHighlights), como una marca de rotulador: dice de qué color es sin recurrir a
   una barra lateral. */
.highlight-item {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--hl-color, var(--surface-2)) 16%, transparent);
  margin-bottom: 10px;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.highlight-item:hover {
  background: color-mix(in srgb, var(--hl-color, var(--surface-2)) 30%, transparent);
}

.highlight-item .highlight-text {
  font-size: 13px;
  font-style: italic;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.highlight-item .highlight-meta {
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 6px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.highlight-item .highlight-meta > span { margin-right: auto; }

.highlight-item .highlight-share,
.highlight-item .highlight-delete {
  background: none;
  border: none;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 12px;
  display: inline-flex;
  align-items: center;
}

.highlight-item .highlight-share:hover { color: var(--accent); }
.highlight-item .highlight-delete:hover {
  color: #e53935;
}

/* ============ SETTINGS (v2) ============ */
.settings-group {
  margin-bottom: 24px;
}

.settings-group label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-soft);
  margin-bottom: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.theme-selector {
  display: flex;
  gap: 10px;
}

/* Control segmentado Páginas/Scroll (modo de lectura). */
.reading-mode-selector { display: flex; gap: 10px; }
.reading-mode-btn {
  flex: 1;
  padding: 10px 12px;
  border: 2px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}
.reading-mode-btn:hover { border-color: var(--accent); }
.reading-mode-btn.active { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }

.theme-btn {
  width: 44px;
  height: 44px;
  border: 2px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  font-size: 20px;
  cursor: pointer;
  transition: border-color var(--transition-fast), transform var(--transition-fast);
}

.theme-btn:hover {
  transform: scale(1.05);
}

.theme-btn.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

.font-size-control {
  display: flex;
  align-items: center;
  gap: 12px;
}

.font-size-control span {
  min-width: 44px;
  text-align: center;
  font-size: 14px;
  font-weight: 500;
}

select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font-size: 14px;
  transition: border-color var(--transition-fast);
}
select:focus {
  outline: none;
  border-color: var(--accent);
}

.column-width-control,
.line-height-control {
  display: flex;
  align-items: center;
  gap: 12px;
}

input[type="range"] {
  flex: 1;
  accent-color: var(--accent);
}

.column-width-control span,
.line-height-control span {
  min-width: 48px;
  text-align: center;
  font-size: 13px;
  color: var(--text-soft);
}

/* ============ READER MAIN ============ */
.reader-main {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin-left: 0;
  /* `margin` y no `margin-left`: el panel del agente empuja por la DERECHA y sin esto
     ese lado saltaba de golpe mientras el panel se deslizaba. */
  transition: margin var(--transition-panel);
}

/* ============ READER HEADER ============ */
.reader-header {
  height: var(--header-height);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 12px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
  flex-shrink: 0;
}

/* Título del libro: centrado en la cabecera (estilo Apple Books/Kindle), con
   presencia tipográfica y truncado elegante. Al ir en position:absolute no
   "empuja" el layout, así que las dos islas de iconos quedan balanceadas a los
   lados y el hueco central se llena con el título en vez de aire. */
.reader-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Ancho limitado a lo que queda libre entre las dos islas de iconos, para que el
     título centrado NUNCA se solape con ellas (crítico en móvil). */
  max-width: min(calc(100% - 260px), 460px);
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;   /* no interfiere con los clics de los iconos */
}

.header-actions {
  display: flex;
  gap: 4px;
  margin-left: auto;      /* empuja las acciones a la derecha (el título ya no ocupa flujo) */
}

/* ============ READER VIEWPORT ============ */
.reader-viewport {
  flex: 1;
  overflow: hidden;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-0);
}
/* Con un libro abierto, el fondo del viewport iguala al de la página (--page-bg, fijado
   por epub-reader según el tema). Así, al arrastrar para pasar página, el hueco que se
   revela no muestra una franja de otro color. */
body.reading .reader-viewport { background: var(--page-bg, var(--surface-0)); }

/* Salvo cuando la página se dibuja como HOJA: entonces el viewport es el "escritorio"
   sobre el que reposa (el mismo color, un punto más oscuro). La condición la decide
   `sizeContainer()` en js/epub-reader.js poniendo `.has-desk` cuando hay margen lateral
   de sobra; con poco margen el gris no se lee como escritorio sino como una franja rara
   pegada al borde. Ver --desk en themes.css. */
body.reading .reader-viewport:has(> .epub-container.has-desk) { background: var(--desk); }
/* Modo scroll: el contenido crece en vertical y se desplaza; alineamos arriba y dejamos
   que epub.js gestione el scroll interno (no centramos ni ocultamos el desborde). */
body.scroll-mode .reader-viewport { align-items: stretch; justify-content: flex-start; }

/* ============ READER FOOTER (v2) ============ */
.reader-footer {
  height: var(--footer-height);
  display: flex;
  align-items: center;
  padding: 0 20px;
  gap: 20px;
  border-top: 1px solid var(--border-soft);
  background: var(--surface-1);
  flex-shrink: 0;
}

.nav-btn {
  background: none;
  border: none;
  color: var(--text);
  font-size: 18px;
  cursor: pointer;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  transition: background var(--transition-fast);
}

.nav-btn:hover {
  background: var(--surface-3);
}

/* Pie del lector: info (página · % · tiempo restante) sobre una barra clicable. */
.progress-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.progress-info {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  font-size: 12px;
  line-height: 1;
  color: var(--text-faint);
}
.progress-info > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Capítulo actual: la información primaria del pie (lo que un lector quiere saber es
   dónde está, no qué número de localización lleva). Lo rellena markCurrentToc() en
   app.js reusando la sección que ya calcula para marcar el índice. Sin índice queda
   vacío y el bloque de cifras se va solo a la izquierda. */
.progress-chapter {
  flex: 1;
  min-width: 0;
  color: var(--text-soft);
  font-weight: 500;
}

/* Cifras: página · % · tiempo restante, en un solo bloque atenuado y con cifras de
   ancho fijo para que no bailen al avanzar. El separador es CSS (no texto) para no
   meter cadenas nuevas al i18n, y salta las piezas vacías. */
.progress-meta {
  flex: none;
  display: inline-flex;
  align-items: baseline;
  font-variant-numeric: tabular-nums;
}
.progress-meta > span:not(:empty) + span:not(:empty)::before {
  content: '·';
  margin: 0 6px;
  color: var(--text-faint);
  opacity: 0.7;
}

.progress-container {
  height: 3px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  position: relative;
  cursor: pointer;
}
/* Zona de pulsación más alta que los 6px visibles: es más fácil acertar el salto
   (el clic sobre el pseudo-elemento se atribuye al contenedor). */
.progress-container::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: -8px; bottom: -8px;
}

.progress-bar {
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
  width: 0%;
  transition: width var(--transition-fast);
  pointer-events: none;
}

/* Arrastre estilo Play Books. `touch-action: none` es lo que impide que el gesto
   horizontal lo robe el scroll de la página en móvil. */
.progress-container { touch-action: none; }
.progress-container:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Pulgar: colgado del extremo de la barra, así sigue su anchura sin que JS tenga que
   posicionarlo. Solo aparece al enfocar o arrastrar, para no ensuciar la barra fina. */
.progress-bar { position: relative; }
.progress-bar::after {
  content: '';
  position: absolute;
  top: 50%; right: -6px;
  width: 12px; height: 12px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity var(--transition-fast), transform var(--transition-fast);
}
.progress-container.dragging .progress-bar::after,
.progress-container:focus-visible .progress-bar::after { opacity: 1; transform: scale(1); }
/* Durante el arrastre la anchura sigue al dedo: la transición la haría ir a rastras. */
.progress-container.dragging .progress-bar { transition: none; }

.progress-bubble {
  position: absolute;
  bottom: 18px;
  transform: translateX(-50%);
  display: none;
  flex-direction: column;
  gap: 2px;
  max-width: min(240px, 70vw);
  padding: 6px 10px;
  border-radius: var(--r-sm);
  background: var(--surface-1);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18));
  font-size: 12px;
  line-height: 1.3;
  color: var(--text);
  pointer-events: none;
  white-space: nowrap;
  z-index: 5;
}
.progress-bubble.visible { display: flex; }
.progress-bubble strong { font-weight: 600; }
.progress-bubble span {
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============ ZOOM DE IMÁGENES (lightbox) ============ */
.img-zoom {
  position: fixed; inset: 0; z-index: 400;
  display: none; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.92);
  touch-action: none; overflow: hidden; overscroll-behavior: contain;
}
.img-zoom-img {
  max-width: 100%; max-height: 100%;
  transform-origin: center center; will-change: transform;
  user-select: none; -webkit-user-select: none; -webkit-user-drag: none;
}
.img-zoom-close {
  position: absolute; z-index: 1;
  top: calc(12px + env(safe-area-inset-top)); right: calc(12px + env(safe-area-inset-right));
  width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, 0.5); color: #fff;
}
.img-zoom-close:hover { background: rgba(0, 0, 0, 0.75); }

/* ============ EPUB CONTAINER ============ */
.epub-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

/* La página como objeto (F1). Solo en pantallas anchas: es donde `sizeContainer()`
   (js/epub-reader.js) limita el contenedor al "ancho de columna" y sobra escritorio a los
   lados. Por debajo de 1000px la página va a sangre y una tarjeta solo robaría línea de
   lectura. El umbral debe seguir al `vw > 1000` de sizeContainer: si cambia allí, cambia aquí.
   El fondo va en el CONTENEDOR (no en el viewport) porque el swipe lo traslada: la hoja se
   mueve entera y lo que asoma detrás es el escritorio, como al pasar página de verdad.
   Ojo: NADA aquí puede cambiar el tamaño del área de lectura. Un inset vertical (padding en
   el viewport) parece inofensivo y repagina el EPUB entero: la página que anuncia la burbuja
   de la barra deja de ser la página a la que se salta (progress-scrub.spec) y, de paso, el
   PDF se re-ajusta. Por eso el respiro es solo lateral —el que sizeContainer ya deja— y aquí
   únicamente se pinta: fondo, radio y sombra. */
@media (min-width: 1001px) {
  body.reading:not(.scroll-mode) .epub-container.has-desk {
    background: var(--page-bg, var(--surface-0));
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-2);
  }
  /* En inmersivo la hoja ocupa todo: sin cromo alrededor, el marco sobra. */
  body.reading.immersive:not(.scroll-mode) .epub-container { border-radius: 0; box-shadow: none; }
}

/* Entrada de capítulo (F4). La dispara fadeChapterIn() en js/epub-reader.js al
   renderizarse una sección nueva; ahí están las exclusiones (giro de pantalla, swipe). */
.epub-container.chapter-in { animation: chapter-in var(--dur-chapter) var(--ease-out-soft); }
@keyframes chapter-in { from { opacity: 0.35; } to { opacity: 1; } }

/* En PAGINADO la vista debe llenar el viewport (altura fija). En SCROLL debe conservar
   su altura de contenido (la que epub.js pone inline, p. ej. 1229px) para que el
   contenedor de epub.js (overflow:auto) tenga algo que desplazar; por eso gateamos estas
   alturas fijas a :not(.scroll-mode). */
body:not(.scroll-mode) .epub-container > div {
  height: 100% !important;
}

.epub-container iframe {
  border: none !important;
}

body:not(.scroll-mode) .epub-container .epub-view {
  overflow: hidden !important;
  height: 100% !important;
}

/* ============ PDF CONTAINER (zoom fluido) ============ */
/* El contenedor es el área de SCROLL (paneo nativo, 1 dedo). Dentro, #pdf-zoom-layer
   agrupa las páginas y es lo que escalamos EN VIVO durante el pinch (2 dedos, por JS).
   El zoom "horneado" vive en el layout: cada .pdf-page es una caja de tamaño fit·zoom y
   su .pdf-scaler escala el contenido — así el scroll nativo abarca el contenido ampliado
   y la selección de texto sigue funcionando. */
.pdf-container {
  width: 100%;
  height: 100%;
  overflow: auto;
  position: relative;
  padding: 20px;
  background: var(--surface-3);
  touch-action: pan-x pan-y;      /* 1 dedo = scroll/selección nativos; pinch lo gestiona el JS */
  overscroll-behavior: contain;   /* al panear a zoom>1, el rebote en el borde no navega ni mueve el body */
  -webkit-overflow-scrolling: touch;
}

#pdf-zoom-layer {
  display: flex;
  flex-direction: column;
  align-items: safe center;       /* centra horizontalmente */
  justify-content: safe center;   /* centra verticalmente si la página cabe (paginado) */
  min-height: 100%;
}
/* El hueco entre páginas escala CON el zoom. Durante el pinch se escala el layer entero
   (gaps incluidos); si al hornear el gap se quedara fijo, el contenido de arriba mediría
   distinto que en el preview y la vista pegaba un salto al soltar los dedos. */
.pdf-container.pdf-scroll #pdf-zoom-layer {
  justify-content: flex-start;
  gap: calc(12px * var(--pdf-zoom, 1));
}

.pdf-page {
  position: relative;
  flex: none;
  box-shadow: 0 2px 8px var(--shadow);
  /* Grupo de mezcla acotado a la página: el tinte de papel y los subrayados (ambos con
     mix-blend-mode) se mezclan con el papel y entre sí, nunca con el fondo de la app que
     hay detrás ni con la sombra de la caja. */
  isolation: isolate;
}

/* ---- Papel del PDF: tinte y modo noche (ADR-026) --------------------------
   Una sola palanca: `data-pdf-paper` en <html>, que resuelve settings.js. TODO el pintado
   es CSS → el cambio es instantáneo, no vuelve a pdf.js y no re-rasteriza nada (respeta
   ADR-019/025: el zoom sigue siendo compositor puro).

   Son DOS mecanismos distintos bajo el mismo control, y no es un capricho:
   - Tintes claros → capa en `multiply`. Multiplicar solo puede OSCURECER, que es justo lo
     que hace falta: papel blanco × crema = crema, y la tinta (ya negra) no se mueve.
   - Noche → `invert`. Un tinte NO sirve: multiplicar por negro deja la página entera en
     negro, tinta incluida. Por eso «Noche» no es un color más de la paleta.

   Lo que el agente de visión captura (capturePageImage / captureRegionImage) lee el canvas
   directamente, así que sigue viendo la página REAL, sin teñir ni invertir. Es la ventaja
   de hacer esto en CSS y no al rasterizar. */
:root { --pdf-paper-tint: transparent; }
[data-pdf-paper="cream"] { --pdf-paper-tint: #f6ecd8; }
[data-pdf-paper="sepia"] { --pdf-paper-tint: #eadcc0; }
[data-pdf-paper="grey"]  { --pdf-paper-tint: #dcdcda; }
/* "white" y "auto"→claro no llevan tinte: el papel del PDF ya es blanco. */

/* El tinte es un ::after del wrapper: no añade DOM por página ni toca el render. Va por
   encima del canvas (base Y parche de detalle, ambos dentro del .pdf-scaler) y por DEBAJO
   de los subrayados (.pdf-hl-layer, z-index 2), que deben teñirse como la tinta y no
   quedar "bajo el papel". Solo se pinta cuando hay tinte: si no, ni se crea la capa. */
.pdf-page::after {
  content: '';
  display: none;
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--pdf-paper-tint);
  mix-blend-mode: multiply;
}
[data-pdf-paper="cream"] .pdf-page::after,
[data-pdf-paper="sepia"] .pdf-page::after,
[data-pdf-paper="grey"] .pdf-page::after { display: block; }

/* Noche: invertir los canvas. El `hue-rotate` devuelve el tono a los colores (sin él, un
   diagrama azul sale naranja). Coge base y parche de detalle a la vez, y deja fuera la capa
   de texto y los subrayados, que viven fuera del .pdf-scaler.
   El `contrast(0.88)` final evita el par negro puro / blanco puro: deja el papel en gris muy
   oscuro y la tinta en hueso. Invertir a pelo es más agresivo de lo que parece en una sesión
   larga, que es justo cuando se usa este modo. */
[data-pdf-paper="night"] .pdf-scaler canvas {
  filter: invert(1) hue-rotate(180deg) contrast(0.88);
}
/* Con el papel ya en negro, `multiply` haría desaparecer los subrayados (color × negro =
   negro). En noche el blend se invierte a `screen`: el color ilumina el papel oscuro y la
   tinta, ahora blanca, sigue legible por encima. */
[data-pdf-paper="night"] .pdf-hl-group {
  mix-blend-mode: screen;
  opacity: 0.3;
}

/* Contenido de la página (canvas + capa de texto) a tamaño fit; se escala al zoom actual. */
.pdf-scaler {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}
.pdf-scaler canvas, #pdf-canvas { display: block; }

/* Parche de detalle: solo el trozo visible, rasterizado a la resolución exacta del zoom y
   superpuesto al canvas base (que NUNCA se retira → nada de huecos en blanco). Posición y
   tamaño en unidades fit, puestos por JS, así escala con el .pdf-scaler como todo lo demás.
   Va encima del base y DEBAJO de la capa de texto, que debe seguir seleccionable. */
.pdf-scaler canvas.pdf-detail {
  position: absolute;
  pointer-events: none;
}

/* Flash al saltar a una página desde una cita del agente (señala el destino). */
@keyframes pdfCiteFlash {
  0%, 100% { box-shadow: 0 2px 8px var(--shadow); }
  20%, 60% { box-shadow: 0 0 0 3px var(--accent), 0 2px 12px var(--shadow); }
}
.pdf-page.pdf-cite-flash { animation: pdfCiteFlash 1.5s var(--ease); }

/* Resaltado transitorio del TROZO citado (cuando sí localizamos el pasaje en la página). */
.pdf-cite-layer { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.pdf-cite-hl {
  position: absolute;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0.35;
  mix-blend-mode: multiply;
  animation: pdfCiteHlIn 0.18s var(--ease);
}
@keyframes pdfCiteHlIn { from { opacity: 0; } to { opacity: 0.35; } }

/* pdf.js selectable text layer overlaid on the canvas */
.textLayer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  line-height: 1;
  text-align: initial;
  opacity: 1;
  forced-color-adjust: none;
  transform-origin: 0 0;
}

.textLayer span,
.textLayer br {
  position: absolute;
  white-space: pre;
  color: transparent;
  cursor: text;
  transform-origin: 0% 0%;
}

.textLayer ::selection {
  background: rgba(79, 140, 255, 0.35);
}

/* PDF3 · Overlay de subrayados: rectángulos (coords fraccionales → px) sobre el canvas.
   Multiply para que se vea como un marcador sobre el texto. No captura eventos: la capa de
   texto de encima sigue siendo seleccionable. */
.pdf-hl-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Por ENCIMA del .pdf-scaler (canvas) pase lo que pase con el orden del DOM: en modo
     scroll el subrayado se crea sobre el placeholder ANTES de que el observer perezoso
     añada el scaler, así que sin z-index el canvas opaco lo tapaba. */
  z-index: 2;
}

/* Un subrayado = un GRUPO. El blend/opacidad se aplican UNA sola vez al grupo (que crea su
   propio contexto de composición): así los rects de líneas contiguas —que se solapan un poco
   por el alto de línea— se funden en un color sólido uniforme antes de mezclarse, sin las
   bandas más oscuras que salían al multiplicar dos veces en cada solape. */
.pdf-hl-group {
  position: absolute;
  inset: 0;
  mix-blend-mode: multiply;
  opacity: 0.4;
}
/* Rects individuales: color sólido, SIN blend ni opacidad propios (los pone el grupo). */
.pdf-hl {
  position: absolute;
  border-radius: 2px;
}

/* ============ AI PANEL ============ */
:root { --ai-panel-width: 380px; }

/* --kb-inset = alto del teclado virtual (lo publica `initKeyboardInset` en ai/panel.js a
   partir de visualViewport). El panel es `fixed`: sin esto, en iOS el teclado NO encoge el
   viewport de layout y el composer queda debajo del teclado — escribías a ciegas. */
#ai-panel {
  position: fixed;
  top: 0;
  right: 0;
  width: var(--ai-panel-width);
  height: calc(100% - var(--kb-inset, 0px));
  background: var(--surface-1);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  z-index: 100;
  transform: translateX(100%);
  transition: transform var(--transition-panel);
}

body.ai-open #ai-panel { transform: translateX(0); }
body.ai-open .reader-main { margin-right: var(--ai-panel-width); }

/* En escritorio, abrir la barra lateral izquierda EMPUJA el contenido (el texto
   se re-pagina al nuevo ancho), igual que el panel del agente a la derecha —al
   estilo de NotebookLM. En tablet/móvil se superpone como drawer (media query
   de abajo lo revierte a margin 0). */
body:has(#sidebar.open) .reader-main { margin-left: var(--sidebar-width); }

/* En la biblioteca, las sidebars de la vista de libro nunca deben verse (van por encima
   de la estantería). El id en el selector gana en especificidad a .open/.ai-open. */
body.in-library #sidebar { transform: translateX(-100%); }
body.in-library #ai-panel { transform: translateX(100%); }

/* ---- Tiradores para redimensionar los paneles (solo escritorio) ----
   Ambos paneles EMPUJAN el lector con un margen = su anchura (variable CSS). Arrastrar
   el tirador actualiza esa variable y el texto reflowea. En móvil (drawer/overlay) se
   ocultan. */
.panel-resizer {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 10px;
  z-index: 110;
  cursor: col-resize;
  touch-action: none;
}
.ai-resizer { left: -5px; }          /* borde interior del panel del agente (izquierda) */
.sidebar-resizer { right: -5px; }    /* borde interior de la sidebar (derecha) */
.panel-resizer::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 50%;
  width: 2px;
  transform: translateX(-50%);
  background: transparent;
  transition: background var(--transition-fast);
}
.panel-resizer:hover::before,
body.resizing-panel .panel-resizer::before { background: var(--accent); }
/* Durante el arrastre: sin selección de texto, cursor global y sin transición de márgenes
   (para que el texto siga el tirador sin retardo). */
body.resizing-panel { cursor: col-resize; user-select: none; }
body.resizing-panel #ai-panel,
body.resizing-panel #sidebar,
body.resizing-panel .reader-main { transition: none !important; }
@media (max-width: 1023px) { .panel-resizer { display: none; } }

/* Toolbar único del panel: una sola fila con el selector de conversación + perfil +
   acciones + ajustes/cerrar. Sustituye a la antigua .ai-header ("Agente"). */
/* Tirador del bottom-sheet: SOLO existe en móvil (sus estilos viven en la media query de
   <768px). Sin esta línea el <button> se colaba en escritorio con el estilo por defecto del
   navegador —un rectángulo de 379×4px con borde `2px outset`— y se veía como dos rayas
   sueltas encima de la barra del panel. */
.ai-sheet-grab { display: none; }

.ai-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  box-sizing: border-box;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-soft);
}
/* ⚙ (y ✕ a su lado) quedan a la derecha aunque el grupo de conversación esté oculto. */
.ai-toolbar-cfg { margin-left: auto; }


/* Coach mark de una sola vez que señala el botón de Flashcards. */
.ai-coachmark {
  position: fixed; z-index: 400; max-width: 260px;
  display: flex; align-items: flex-start; gap: 8px;
  background: var(--accent); color: var(--on-accent);
  border-radius: var(--r-md); padding: 10px 12px;
  font-size: 13px; line-height: 1.4; box-shadow: var(--shadow-3);
  opacity: 0; transform: translateY(-4px); transition: opacity var(--transition-fast), transform var(--transition-fast);
  pointer-events: none;   /* no intercepta clics; solo su ✕ es interactivo */
}
.ai-coachmark .ai-coachmark-x { pointer-events: auto; }
.ai-coachmark.is-in { opacity: 1; transform: translateY(0); }
.ai-coachmark b { font-weight: 700; }
.ai-coachmark::before {
  content: ''; position: absolute; top: -6px; left: var(--arrow-x, 130px);
  width: 12px; height: 12px; background: var(--accent);
  transform: translateX(-50%) rotate(45deg);
}
.ai-coachmark-x {
  flex: none; background: rgba(255,255,255,0.2); border: none; color: var(--on-accent);
  width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center;
  justify-content: center; cursor: pointer; position: relative;
}
.ai-coachmark-x:hover { background: rgba(255,255,255,0.35); }

.ai-config {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.ai-config label {
  display: block;
  font-size: 12px;
  color: var(--text-soft);
  margin: 8px 0 4px;
}
.ai-config input,
.ai-config select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-0);
  color: var(--text);
  font-size: 13px;
}
.ai-save { width: 100%; margin-top: 12px; padding: 8px; font-size: 14px; }
.ai-privacy {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 12px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-faint);
}
.ai-privacy .icon { flex: none; margin-top: 1px; }

.ai-status {
  padding: 10px 18px;
  font-size: 13px;
  color: var(--text-faint);
  border-bottom: 1px solid var(--border-soft);
}

/* Chip del perfil de agente activo (P1): clicable, abre Ajustes → Perfiles. Vive en la
   fila de la barra de conversación (ver panel-template.js), así que no lleva márgenes
   propios y encoge con ellipsis para no empujar al selector de conversación. */
.ai-profile-chip {
  flex: 0 1 auto; min-width: 0;
  display: flex; align-items: center; gap: 6px;
  margin: 0; padding: 7px 12px;
  max-width: 45%;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-2);
  font-size: 13px; color: var(--text-soft); cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}
.ai-profile-chip:hover { border-color: var(--accent); color: var(--text); }
.ai-profile-chip .icon { flex: none; color: var(--accent); }
.ai-profile-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ai-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.ai-msg { display: flex; }
.ai-msg-user { justify-content: flex-end; }
.ai-bubble {
  font-size: var(--fs-md);
  line-height: 1.6;
  white-space: normal;
  word-wrap: break-word;
}
/* Usuario: burbuja de acento, alineada a la derecha */
.ai-msg-user .ai-bubble {
  max-width: 85%;
  padding: 10px 16px;
  border-radius: var(--r-lg) var(--r-lg) var(--r-sm) var(--r-lg);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-1);
}
/* Agente: bloque de texto limpio (estilo NotebookLM), sin caja */
.ai-msg-assistant { width: 100%; }
.ai-msg-assistant .ai-bubble { width: 100%; color: var(--text); }

/* Chips de cita: pill sutil de acento (v2: más visible) */
.ai-cite {
  display: inline-flex;
  align-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  padding: 2px 8px;
  margin: 0 2px;
  cursor: pointer;
  vertical-align: baseline;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.ai-cite:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.ai-typing { color: var(--text-faint); font-style: italic; }
.ai-error { color: #e53935; }

.ai-composer {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
}
.ai-composer textarea {
  flex: 1;
  resize: none;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  transition: border-color var(--transition-fast);
}
.ai-composer textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.ai-send { padding: 8px 16px; font-size: 14px; align-self: stretch; }

/* Botonera del composer: "Ver" (visión) + Enviar, apiladas a la derecha del textarea. */
.ai-composer-btns { display: flex; flex-direction: column; gap: 6px; }
.ai-composer-btns .ai-send { flex: 1; }
/* Última fila: micro (cuadrado, solo icono) + Enviar, que se queda con el resto del ancho. */
.ai-composer-row { display: flex; gap: 6px; flex: 1; }
.ai-composer-row .ai-send { flex: 1; }
.ai-mic { padding: 6px 9px; justify-content: center; }
/* Grabando: mismo lenguaje que el micro de Feynman (acento sólido), más un latido suave
   que deja claro que el micro está ABIERTO aunque no haya texto en vivo (con el motor del
   proveedor la transcripción no llega hasta soltar). */
.ai-mic-on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  animation: ai-mic-pulse 1.6s ease-in-out infinite;
}
.ai-mic-on:hover { color: #fff; }
@keyframes ai-mic-pulse { 50% { opacity: 0.62; } }
@media (prefers-reduced-motion: reduce) { .ai-mic-on { animation: none; } }

/* ---- barra de grabación (patrón WhatsApp) ---- */
/* Ocupa el hueco del textarea mientras grabas, con su mismo alto para que el composer no dé
   un salto al entrar y salir. */
.mic-bar {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
}
.mic-bar[hidden] { display: none; }
textarea.is-recording { display: none; }

.mic-bar-cancel {
  display: none;              /* solo con el motor del proveedor (ver mic.js) */
  align-items: center;
  padding: 2px;
  border: 0;
  background: none;
  color: var(--text-soft);
  cursor: pointer;
}
.mic-bar.is-provider .mic-bar-cancel { display: inline-flex; }
.mic-bar-cancel:hover { color: #e53935; }

/* Punto latiendo: el "estoy grabando" de toda la vida. Rojo aunque el acento sea verde —
   grabando es grabando, y es el código de color que todo el mundo ya tiene aprendido. */
.mic-bar-dot {
  width: 9px;
  height: 9px;
  flex-shrink: 0;
  border-radius: 50%;
  background: #e53935;
  animation: mic-dot 1.3s ease-in-out infinite;
}
@keyframes mic-dot { 50% { opacity: 0.25; } }

.mic-bar-time {
  font-variant-numeric: tabular-nums;   /* que el ancho no baile al pasar de 0:09 a 0:10 */
  font-size: 13px;
  color: var(--text);
}

/* Vúmetro: se enciende de dentro afuera. Solo con el motor del proveedor, que es el único
   que da stream que medir. */
.mic-bar-level { display: none; align-items: center; gap: 2px; flex: 1; }
.mic-bar.is-provider .mic-bar-level { display: flex; }
.mic-bar-level i {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  transition: height 80ms linear, background-color 80ms linear;
}
.mic-bar-level i.on { height: 14px; background: var(--accent); }

.mic-bar-hint { font-size: 12px; color: var(--text-soft); white-space: nowrap; }
/* Con vúmetro el hueco se queda corto: la pista sobra, el medidor ya lo dice todo. */
.mic-bar.is-provider .mic-bar-hint { display: none; }

/* Parar: la acción principal mientras grabas, y por eso es lo único con acento en la barra.
   Va a la DERECHA (margin-left:auto), enfrente de la papelera: destructivo a un extremo,
   confirmar al otro. Antes esto solo estaba en el botón del micro, que queda fuera de donde
   miras porque la barra sustituye al textarea. */
.mic-bar-stop {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  transition: background var(--transition-fast);
}
.mic-bar-stop:hover { background: var(--accent-hover); }
.mic-bar-stop .icon { color: currentColor; }

@media (prefers-reduced-motion: reduce) {
  .mic-bar-dot { animation: none; }
  .mic-bar-level i { transition: none; }
}
.ai-see {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 10px;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-0);
  color: var(--text-soft);
  cursor: pointer;
}
.ai-see:hover { color: var(--accent); border-color: var(--accent); }

/* Tabs como segmented control (v2) */
.ai-tabs {
  display: flex;
  gap: 4px;
  margin: 12px 16px 0;
  padding: 4px;
  background: var(--surface-2);
  border-radius: var(--r-pill);
}
.ai-tab {
  flex: 1;
  padding: 8px 12px;
  background: none;
  border: none;
  border-radius: var(--r-pill);
  color: var(--text-soft);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.ai-tab:hover { color: var(--text); }
.ai-tab.active {
  color: var(--text);
  background: var(--surface-2);
  box-shadow: var(--shadow-1);
}

.ai-view { display: none; flex: 1; min-height: 0; flex-direction: column; }
.ai-view.active { display: flex; }
#ai-view-notebook { overflow-y: auto; padding: 12px 16px; }

/* ==== Studio: galería per-libro de artefactos (historial de resúmenes/mapas + flashcards) ==== */
#ai-view-studio { overflow-y: auto; padding: 14px 16px; }
.studio-book { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.studio-hint { font-size: 12px; color: var(--text-soft); margin: 2px 0 8px; line-height: 1.45; }
.studio-group { margin-bottom: 18px; }
.studio-group-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.studio-ico { display: inline-flex; color: var(--accent); flex: none; }
.studio-group-name { font-size: 14px; font-weight: 600; color: var(--text); flex: 1; min-width: 0; }
.studio-new {
  flex: none; display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  padding: 4px 10px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--accent); border-radius: 999px; background: transparent; color: var(--accent);
}
.studio-new:hover { background: var(--accent-soft); }
/* Tarjeta de artefacto: zona clicable (abrir) + botón borrar */
.studio-card {
  display: flex; align-items: stretch; gap: 4px; margin-bottom: 8px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-1);
  overflow: hidden;
}
.studio-card-main {
  flex: 1; min-width: 0; text-align: left; cursor: pointer;
  background: none; border: none; padding: 12px 14px; color: var(--text);
}
.studio-card-main:hover { background: var(--surface-3); }
.studio-del {
  flex: none; width: 40px; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-left: 1px solid var(--border); color: var(--text-soft); cursor: pointer;
}
.studio-del:hover { background: var(--surface-3); color: #dc2626; }
.studio-meta { font-size: 12.5px; color: var(--text-soft); margin: 0; line-height: 1.4; }
.studio-value { font-size: 12.5px; color: var(--text-soft); margin: 0; line-height: 1.45; }
/* Invitación (tipo sin artefactos aún) */
.studio-empty {
  flex-direction: column; align-items: flex-start; gap: 10px; padding: 12px 14px;
  background: var(--surface-0); border-style: dashed;
}
.studio-gen {
  padding: 6px 14px; font-size: 13px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--accent); border-radius: var(--r-sm);
  background: transparent; color: var(--accent); font-weight: 600;
}
.studio-gen:hover { background: var(--accent-soft); }
.studio-link { background: none; border: none; color: var(--accent); cursor: pointer; font: inherit; font-size: inherit; padding: 0 0 0 2px; }
/* Estados en curso / error, dentro del grupo del tipo */
.studio-running, .studio-error { flex-direction: column; align-items: stretch; gap: 8px; padding: 12px 14px; }
.studio-errmsg { color: #dc2626; }
.studio-progress { height: 5px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.studio-bar { height: 100%; background: var(--accent); border-radius: 999px; transition: width .3s ease; }

/* Acciones bajo una respuesta */
.ai-bubble-actions { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }
.ai-act {
  background: none; border: 1px solid var(--border); color: var(--text-soft);
  border-radius: 6px; font-size: 11px; padding: 3px 8px; cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.ai-act:hover:not(:disabled) { background: var(--surface-0); color: var(--text); }
.ai-act:disabled { opacity: 0.6; cursor: default; }
.ai-extract-status { font-size: 11px; color: var(--text-faint); align-self: center; }

/* Toggle de auto-libreta en el config */
.ai-check {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 13px; color: var(--text-soft); margin-top: 12px;
  text-transform: none; letter-spacing: 0; font-weight: 400;
}
.ai-check input { width: auto; }

/* Aviso de notas nuevas en la pestaña Libreta */
.ai-tab-unread::after {
  content: ''; display: inline-block; width: 7px; height: 7px; margin-left: 6px;
  border-radius: 50%; background: var(--accent); vertical-align: middle;
}

/* Atenuación de capítulos en el índice según el objetivo (E6.4) */
#toc-list a.ai-toc-low { opacity: 0.4; }
#toc-list a.ai-toc-mid { opacity: 0.7; }
#toc-list a.ai-toc-high { font-weight: 600; opacity: 1; }
#toc-list a.ai-toc-high::before {
  content: '★'; color: var(--accent); margin-right: 6px; font-size: 11px;
}
/* La marca de "estoy aquí" gana a la atenuación por objetivo: da igual lo poco que
   importe el capítulo para el objetivo, si es donde se lee tiene que verse. */
#toc-list a.current { opacity: 1; }

/* Markdown dentro de respuestas y notas */
.ai-bubble-text > :first-child, .ai-nb-note-text > :first-child { margin-top: 0; }
.ai-bubble-text > :last-child, .ai-nb-note-text > :last-child { margin-bottom: 0; }
.ai-bubble-text p, .ai-nb-note-text p { margin: 0 0 8px; }
.ai-md-h { font-size: 14px; font-weight: 700; margin: 12px 0 6px; line-height: 1.3; }
.ai-bubble-text ul, .ai-bubble-text ol,
.ai-nb-note-text ul, .ai-nb-note-text ol { margin: 0 0 8px; padding-left: 20px; }
.ai-bubble-text li, .ai-nb-note-text li { margin-bottom: 3px; }
.ai-bubble-text code, .ai-nb-note-text code {
  background: var(--surface-0); border-radius: 4px; padding: 1px 5px;
  font-size: 0.9em; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.ai-code {
  background: var(--surface-0); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; overflow-x: auto; margin: 0 0 8px;
}
.ai-code code { background: none; padding: 0; }
/* Cita: se distingue por superficie y color de texto, sin barra lateral. */
.ai-bubble-text blockquote, .ai-nb-note-text blockquote {
  margin: 0 0 8px; padding: 8px 12px; border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--text-soft); font-style: italic;
}
.ai-bubble-text hr, .ai-nb-note-text hr { border: none; border-top: 1px solid var(--border); margin: 10px 0; }
.ai-bubble-text a, .ai-nb-note-text a { color: var(--accent); }

/* Tablas del Markdown del agente. El panel es estrecho → el contenedor hace scroll
   horizontal en vez de desbordar; ver mdToHtml (js/ai/markdown.js). */
.ai-md-tablewrap { overflow-x: auto; margin: 0 0 8px; }
.ai-md-table { border-collapse: collapse; width: 100%; font-size: 13px; }
.ai-md-table th, .ai-md-table td {
  border: 1px solid var(--border); padding: 5px 9px; text-align: left; vertical-align: top;
}
.ai-md-table th { background: var(--surface-3); font-weight: 600; }
.ai-md-table tbody tr:nth-child(even) td { background: var(--surface-1); }

/* Libreta (v2) */
.ai-nb-goal {
  display: flex; flex-direction: column; gap: 4px;
  background: var(--surface-3); border-radius: var(--r-md); padding: 12px 14px;
  font-size: 14px; line-height: 1.5; margin-bottom: 8px;
}
.ai-nb-goal-label { display: block; font-size: 12px; color: var(--text-faint); margin-bottom: 4px; }
.ai-nb-goal-value { word-break: break-word; }
.ai-nb-tpl { font-size: 13px; color: var(--text-faint); margin-bottom: 18px; }
.ai-nb-field { margin-bottom: 18px; }
.ai-nb-field-label {
  font-size: 12px; font-weight: 600; color: var(--text-soft);
  text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 8px;
}
.ai-nb-note {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: var(--r-md); padding: 10px 12px; margin-bottom: 8px;
}
.ai-nb-note-text { flex: 1; font-size: 14px; line-height: 1.5; }
.ai-nb-note-tools { display: flex; gap: 4px; flex-shrink: 0; }
.ai-nb-edit, .ai-nb-del, .ai-nb-goto { background: none; border: none; color: var(--text-faint); cursor: pointer; font-size: 13px; padding: 4px 6px; border-radius: var(--r-sm); }
.ai-nb-edit:hover, .ai-nb-goto:hover { color: var(--accent); background: var(--surface-3); }
.ai-nb-del:hover { color: #e53935; background: var(--surface-3); }
.ai-nb-empty { font-size: 14px; color: var(--text-faint); margin-bottom: 8px; }

/* Editor de nota (editar/añadir) */
.ai-nb-editor { margin-bottom: 8px; }
.ai-nb-input {
  width: 100%; min-height: 72px; resize: vertical;
  border: 1px solid var(--accent); border-radius: var(--r-md); padding: 10px 12px;
  background: var(--surface-0); color: var(--text);
  font-family: inherit; font-size: 14px; line-height: 1.5;
}
.ai-nb-editor-actions { display: flex; gap: 8px; margin-top: 8px; }
.ai-nb-save, .ai-nb-cancel {
  border: 1px solid var(--border); border-radius: var(--r-sm); font-size: 13px; font-weight: 500;
  padding: 6px 14px; cursor: pointer;
}
.ai-nb-save { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.ai-nb-save:hover { background: var(--accent-hover); }
.ai-nb-cancel { background: none; color: var(--text-soft); }
.ai-nb-cancel:hover { background: var(--surface-3); color: var(--text); }
.ai-nb-add {
  background: none; border: 1px dashed var(--border); color: var(--text-faint);
  border-radius: var(--r-sm); font-size: 13px; padding: 6px 12px; cursor: pointer; width: 100%;
}
.ai-nb-add:hover { border-color: var(--accent); color: var(--accent); }

/* Onboarding modal */
.ai-onboarding {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
/* `display:flex` gana a [hidden] por especificidad; sin esto, minimizar la sesión de
   estudio (F2) dejaría el overlay tapando el libro al que se acaba de saltar. */
.ai-onboarding[hidden] { display: none; }
.ai-ob-card {
  position: relative;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 16px;
  padding: 32px; width: 100%; max-width: 560px; box-shadow: var(--shadow-3);
}
.ai-ob-close {
  position: absolute; top: 16px; right: 16px;
  width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; background: var(--surface-3); color: var(--text-soft);
  cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast);
}
.ai-ob-close:hover { background: var(--border); color: var(--text); }
.ai-ob-card h2 { font-size: 22px; font-weight: 700; margin-bottom: 8px; letter-spacing: -0.01em; }
.ai-ob-sub { color: var(--text-soft); font-size: 15px; margin-bottom: 20px; }
.ai-ob-back {
  background: none; border: none; color: var(--accent); cursor: pointer;
  font-size: 14px; font-weight: 500; margin-bottom: 16px; padding: 0;
}
.ai-ob-blocks, .ai-ob-templates { display: flex; flex-direction: column; gap: 12px; }
.ai-ob-block, .ai-ob-tpl {
  text-align: left; background: var(--surface-0); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 16px 18px; cursor: pointer; transition: border-color var(--transition-fast), background var(--transition-fast);
  display: flex; flex-direction: column; gap: 6px;
}
.ai-ob-block:hover, .ai-ob-tpl:hover { border-color: var(--accent); background: var(--surface-3); }
.ai-ob-block-label, .ai-ob-tpl-name { font-size: 16px; font-weight: 600; color: var(--text); }
.ai-ob-block-hint, .ai-ob-tpl-ideal { font-size: 13px; color: var(--text-soft); line-height: 1.4; }
.ai-ob-goal {
  width: 100%; border: 1px solid var(--border); border-radius: var(--r-md); padding: 12px;
  background: var(--surface-0); color: var(--text); font-family: inherit; font-size: 14px;
  resize: vertical; margin-bottom: 20px; transition: border-color var(--transition-fast);
}
.ai-ob-goal:focus { outline: none; border-color: var(--accent); }
.ai-ob-start { width: 100%; }
/* Opt-in del modo Artesano dentro de la Lectura Inmersiva. */
.ai-ob-check {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; color: var(--text-soft);
  margin: -8px 0 20px; cursor: pointer;
}
/* Atajo de baja fricción: "solo chatear" bajo la lista de objetivos. */
.ai-ob-quickchat {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  margin-top: 14px; padding: 12px; cursor: pointer;
  background: none; border: 1px dashed var(--border); border-radius: var(--r-md);
  color: var(--text-soft); font-size: 14px; font-family: inherit;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}
.ai-ob-quickchat:hover { border-color: var(--accent); color: var(--accent); }
.ai-ob-quickchat .icon { color: var(--accent); }

/* Aviso, tras la 1ª respuesta en chat libre, para activar un objetivo (sin perder el chat). */
.ai-objnudge {
  margin: 8px 0; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--accent-soft); border: 1px solid var(--border-soft);
  font-size: 13px; line-height: 1.45; color: var(--text);
  display: flex; flex-direction: column; gap: 10px;
}
.ai-objnudge b { font-weight: 700; }
.ai-objnudge-btns { display: flex; align-items: center; gap: 8px; }
.ai-objnudge-go {
  background: var(--accent); color: var(--on-accent); border: none; border-radius: var(--r-sm);
  padding: 7px 14px; font-size: 13px; font-weight: 600; cursor: pointer; font-family: inherit;
}
.ai-objnudge-go:hover { background: var(--accent-hover); }
.ai-objnudge-x {
  background: none; border: none; color: var(--text-soft); cursor: pointer;
  width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
}
.ai-objnudge-x:hover { background: var(--surface-3); color: var(--text); }
/* Conversación huérfana (plantilla eliminada tras consolidar a T1–T5). */
.ai-nb-orphan { text-align: center; color: var(--text-soft); font-size: 14px; padding: 24px 12px; }
.ai-nb-orphan p { margin-bottom: 14px; }

/* ---- Flashcards para Anki (modal, reusa el patrón del onboarding) ---- */
.fc-card { max-width: 640px; max-height: 90vh; overflow-y: auto; }

/* P13 · Resumen citado */
.sum-card { max-width: 680px; max-height: 90vh; overflow-y: auto; }
.sum-depth-hint { font-size: 12px; color: var(--text-soft); margin: 6px 0 2px; line-height: 1.45; }
/* Documento del resumen (markdown → HTML): portada, secciones por capítulo y cierre. */
.sum-doc { font-size: 15px; line-height: 1.65; color: var(--text); }
.sum-doc h1 { font-size: 20px; margin: 4px 0 10px; }
.sum-doc h2 {
  font-size: 15px; font-weight: 600; color: var(--text-soft);
  margin: 22px 0 8px; padding-bottom: 4px; border-bottom: 1px solid var(--border);
}
.sum-doc h1 + p {   /* TL;DR: primer párrafo tras el título → tarjeta destacada */
  font-size: 16px; background: var(--surface-2); border-radius: 12px;
  padding: 14px 16px; margin: 8px 0 4px;
}
.sum-doc p { margin: 8px 0; }
.sum-doc ul { margin: 6px 0; padding-left: 20px; }
.sum-doc li { margin-bottom: 8px; }

/* P14 · Mapa mental */
/* Setup/en curso: tarjeta cómoda como la del resumen. El resultado (SVG grande) la ensancha. */
.mm-card { max-width: 680px; max-height: 92vh; overflow: auto; }
.mm-card.mm-card--wide { max-width: 92vw; width: 900px; }
/* El mapa no tiene el texto de ayuda que en el resumen separa el select del botón: dale aire. */
.mm-card .ai-ob-start { margin-top: 20px; }
.mm-canvas { margin: 8px 0; border: 1px solid var(--border); border-radius: 12px; overflow: auto; background: #faf8f3; }
.mm-canvas svg { display: block; width: 100%; height: auto; }
.mm-cite:hover rect { stroke-width: 2.5; }

/* Trabajos de IA en segundo plano: vista "en curso", chip flotante y toast de aviso */
@keyframes ai-spin { to { transform: rotate(360deg); } }
.ai-run-status { font-size: 15px; color: var(--text); margin: 8px 0 18px; min-height: 1.4em; }
.ai-run-actions { display: flex; gap: 10px; align-items: center; }
.sum-resulthead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fc-txt-btn { background: none; border: none; color: var(--text-soft); font: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; padding: 4px 6px; border-radius: var(--r-md); }
.fc-txt-btn:hover { color: var(--accent); }

/* Chip flotante de progreso/reapertura (bajo el modal, sobre el lector) */
.ai-taskchip {
  position: fixed; right: 20px; bottom: 20px; z-index: 250;
  display: flex; align-items: center; gap: 9px;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--r-pill, 999px);
  padding: 9px 14px; box-shadow: var(--shadow, 0 6px 24px rgba(0,0,0,.14));
  font-size: 13px; font-weight: 600; color: var(--text); cursor: pointer; max-width: 260px;
}
.ai-taskchip.is-done { border-color: var(--accent); }
.ai-taskchip.is-error { border-color: #ef4444; }
.ai-taskchip-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-taskchip-spin {
  width: 15px; height: 15px; flex: none; border-radius: 50%;
  border: 2px solid var(--accent-soft, #cdefd8); border-top-color: var(--accent);
  animation: ai-spin .7s linear infinite;
}
.ai-taskchip-dot { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; flex: none; border-radius: 50%; background: var(--accent); color: var(--on-accent, #fff); font-weight: 700; font-size: 12px; }
.ai-taskchip.is-error .ai-taskchip-dot { background: #ef4444; }
.ai-taskchip-x { background: none; border: none; color: var(--text-faint, #999); cursor: pointer; padding: 0 0 0 2px; display: inline-flex; }
.ai-taskchip-x:hover { color: var(--text); }
/* Con el panel de IA abierto, aparta el chip a su izquierda para no tapar el input del chat. */
body.ai-open .ai-taskchip { right: calc(var(--ai-panel-width) + 20px); }
/* Chip de vuelta al repaso (F2): misma familia. Si hay un trabajo de IA en curso, su chip
   ya ocupa la esquina, así que este se apila encima en vez de taparlo. */
.ai-taskchip.is-study { border-color: var(--accent); }
body.has-taskchip .ai-taskchip.is-study { bottom: 74px; }
@media (max-width: 600px) { body.has-taskchip .ai-taskchip.is-study { bottom: 62px; } }

/* Toast de aviso (encima de todo) */
.ai-toast-host { position: fixed; left: 0; right: 0; bottom: 20px; z-index: 600; display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
.ai-toast {
  pointer-events: auto; display: flex; align-items: center; gap: 12px;
  background: #23232a; color: #fff; border-radius: var(--r-md, 10px); padding: 11px 12px 11px 16px;
  box-shadow: 0 8px 30px rgba(0,0,0,.28); font-size: 14px; max-width: min(92vw, 440px);
  opacity: 0; transform: translateY(12px); transition: opacity .2s var(--ease, ease), transform .2s var(--ease, ease);
}
.ai-toast.show { opacity: 1; transform: translateY(0); }
.ai-toast-msg { flex: 1; }
/* Éxito/error: un aro completo alrededor del toast, no una barra pegada al borde. */
.ai-toast--success { box-shadow: 0 8px 30px rgba(0,0,0,.28), inset 0 0 0 1px var(--accent); }
.ai-toast--error { box-shadow: 0 8px 30px rgba(0,0,0,.28), inset 0 0 0 1px #ef4444; }
.ai-toast-action { background: var(--accent); color: var(--on-accent, #fff); border: none; border-radius: var(--r-md, 8px); padding: 6px 12px; font: inherit; font-weight: 600; cursor: pointer; white-space: nowrap; }
.ai-toast-action:hover { background: var(--accent-hover); }
.ai-toast-close { background: none; border: none; color: rgba(255,255,255,.6); cursor: pointer; display: inline-flex; padding: 2px; }
.ai-toast-close:hover { color: #fff; }
@media (max-width: 600px) { .ai-taskchip, body.ai-open .ai-taskchip { right: 12px; bottom: 12px; } }
.fc-label { display: block; font-size: 13px; font-weight: 600; color: var(--text-soft); margin: 16px 0 6px; }
.fc-select {
  width: 100%; border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px;
  background: var(--surface-0); color: var(--text); font-family: inherit; font-size: 14px;
}
.fc-select:focus { outline: none; border-color: var(--accent); }

/* Desplegable propio del alcance (combobox con buscador) */
.fc-combo { position: relative; }
.fc-combo-btn {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px;
  background: var(--surface-0); color: var(--text); font-family: inherit; font-size: 14px; cursor: pointer;
}
.fc-combo-btn:hover { border-color: var(--accent); }
.fc-combo-btn[aria-expanded="true"] { border-color: var(--accent); }
.fc-combo-btn .icon { color: var(--text-soft); flex: none; }
.fc-combo-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
.fc-combo-pop {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 10;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--r-md);
  box-shadow: var(--shadow-3); padding: 6px; max-height: 300px; display: flex; flex-direction: column;
}
.fc-combo-pop[hidden] { display: none; }
.fc-combo-search {
  width: 100%; box-sizing: border-box; border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 8px 10px; background: var(--surface-0); color: var(--text); font-family: inherit; font-size: 14px;
  margin-bottom: 6px;
}
.fc-combo-search:focus { outline: none; border-color: var(--accent); }
.fc-combo-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; }
.fc-combo-list li {
  padding: 9px 10px; border-radius: var(--r-sm); cursor: pointer; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fc-combo-list li:hover { background: var(--surface-3); }
.fc-combo-list li.is-sel { color: var(--accent); font-weight: 600; }
.fc-combo-empty { color: var(--text-soft); cursor: default; }
.fc-combo-empty:hover { background: none; }
.fc-types { display: flex; gap: 10px; }
.fc-type {
  flex: 1; display: flex; gap: 10px; align-items: flex-start; cursor: pointer;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: var(--r-md); padding: 12px;
  transition: border-color var(--transition-fast);
}
.fc-type:has(input:checked) { border-color: var(--accent); background: var(--surface-3); }
.fc-type input { margin-top: 3px; accent-color: var(--accent); }
.fc-type b { display: block; font-size: 14px; }
.fc-type small { display: block; font-size: 12px; color: var(--text-soft); line-height: 1.35; margin-top: 2px; }
#fc-generate { width: 100%; margin-top: 20px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.fc-error { color: var(--danger, #e5484d); font-size: 13px; margin-top: 12px; }
/* Aviso de mazo ya existente para este alcance (P24 F4): casilla marcada por defecto. */
.fc-dup {
  display: flex; gap: 9px; align-items: flex-start; margin-top: 12px;
  font-size: 12.5px; line-height: 1.45; color: var(--text-soft); cursor: pointer;
}
.fc-dup input { margin-top: 2px; accent-color: var(--accent); flex: none; }
.fc-deck {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 10px 12px; margin-bottom: 8px;
}
.fc-deck-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fc-deck-name { font-size: 14px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-deck-meta { font-size: 12px; color: var(--text-soft); }
.fc-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.fc-item {
  display: flex; gap: 8px; align-items: flex-start;
  background: var(--surface-0); border: 1px solid var(--border); border-radius: var(--r-md); padding: 12px;
}
/* Suspendida: sigue en el mazo (y en el export a Anki) pero fuera de la rotación. Se
   apaga en vez de tacharse — el texto hay que poder leerlo para decidir si arreglarla. */
.fc-item.is-suspended { background: var(--surface-2); }
.fc-item.is-suspended .fc-item-fields { opacity: 0.5; }
.fc-item-fields { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.fc-front, .fc-back { font-size: 14px; line-height: 1.45; border-radius: var(--r-sm); padding: 2px 4px; }
.fc-front { font-weight: 600; }
.fc-back { color: var(--text-soft); }
.fc-front:focus, .fc-back:focus { outline: 1px solid var(--accent); background: var(--surface-0); }
.fc-back:empty::before { content: attr(data-ph); color: var(--text-faint); }
.fc-export { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.fc-export .primary-btn { display: inline-flex; align-items: center; gap: 8px; }
.fc-export .ai-ob-back { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 0; }
#fc-study small { font-weight: 700; opacity: .8; }
#fc-study[disabled] { opacity: .5; cursor: default; }
.fc-txt-btn { margin-bottom: 0; }
.fc-deck-study {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface-1);
  color: var(--text); padding: 6px 10px; font-size: 13px; font-weight: 600; cursor: pointer;
  font-family: inherit; white-space: nowrap;
}
.fc-deck-study:hover { border-color: var(--accent); color: var(--accent); }
.fc-deck-due {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--accent); color: var(--on-accent);
  font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center;
}

/* ---- Modo Estudiar (P10): sesión de repaso con repetición espaciada ---- */
.study-card {
  max-width: 680px; width: 100%; min-height: 460px; max-height: 92vh;
  display: flex; flex-direction: column;
}
.study-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; padding-right: 44px; }
.study-title { font-size: 15px; font-weight: 700; }
.study-left { font-size: 13px; color: var(--text-soft); }
/* Acciones sobre la tarjeta actual (editar/suspender/borrar) + deshacer: a la derecha
   del contador, pegadas al aspa. Discretas hasta que se pasa por encima: son el arreglo,
   no el camino principal. */
.study-tools { display: flex; gap: 2px; margin-left: auto; }
.study-tool { opacity: 0.55; }
.study-tool:hover { opacity: 1; }
.study-body {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; justify-content: center; gap: 14px;
  padding: 18px 4px; text-align: center;
}
.study-deckname {
  font-size: 12px; font-weight: 600; color: var(--text-soft); text-transform: uppercase;
  letter-spacing: 0.04em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.study-q, .study-a { font-size: 19px; line-height: 1.5; overflow-wrap: break-word; }
.study-q { font-weight: 600; }
.study-a { color: var(--text); border-top: 1px solid var(--border); padding-top: 16px; }
.study-a[hidden] { display: none; }
.study-cloze {
  background: var(--accent-soft); color: var(--accent);
  border-radius: var(--r-sm); padding: 0 6px; font-weight: 700;
}
.study-cloze.is-revealed { background: var(--accent-soft); }
.study-extra { font-size: 14px; color: var(--text-soft); margin-top: 12px; }
/* Aviso de leech: informativo, no alarmante — la acción está en la barra de arriba. */
.study-leech {
  display: flex; align-items: flex-start; gap: 8px; text-align: left;
  font-size: 12.5px; line-height: 1.45; color: var(--text-soft);
  background: var(--surface-3); border-radius: var(--r-sm); padding: 8px 10px;
}
.study-leech svg { flex: none; margin-top: 1px; }
/* Editor inline de la tarjeta: mismos campos que la vista de revisión. */
.study-edit { text-align: left; display: flex; flex-direction: column; gap: 4px; }
.study-edit .fc-label { margin-top: 8px; }
.study-editbar { display: flex; gap: 8px; justify-content: flex-end; }
.study-held { font-size: 13px; color: var(--text-soft); }
/* F3 · El pasaje del libro que respalda la tarjeta, para releerlo sin salir del repaso. */
.study-passage {
  margin: 16px 0 0; padding: 10px 14px;
  background: var(--surface-1); border-radius: var(--r-sm);
  font-size: 14px; line-height: 1.55; color: var(--text-soft); max-height: 30vh; overflow-y: auto;
}
.study-passage-ch { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; opacity: .7; margin-bottom: 4px; }
.study-foot { padding-top: 14px; }
.study-foot .study-flip {
  width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
}
.study-flip kbd {
  font-family: inherit; font-size: 11px; font-weight: 600; opacity: 0.75;
  border: 1px solid currentColor; border-radius: 4px; padding: 1px 6px;
}
.study-src {
  display: inline-flex; align-items: center; gap: 7px; margin: 0 auto 2px;   /* +8px del gap del pie */
  border: none; background: none; color: var(--accent); font-family: inherit;
  font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 8px; border-radius: var(--r-sm);
}
.study-src:hover { background: var(--accent-soft); }
.study-foot { display: flex; flex-direction: column; gap: 8px; }
.study-grades { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.study-grade {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-0);
  color: var(--text); padding: 10px 6px; cursor: pointer; font-family: inherit;
  font-size: 14px; font-weight: 600; transition: border-color var(--transition-fast);
}
.study-grade small { font-size: 11px; font-weight: 500; color: var(--text-soft); }
.study-grade.is-again:hover { border-color: var(--danger, #e5484d); color: var(--danger, #e5484d); }
.study-grade.is-hard:hover { border-color: #d97706; color: #d97706; }
.study-grade.is-good:hover, .study-grade.is-easy:hover { border-color: var(--accent); color: var(--accent); }
.study-end { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.study-end-icon {
  width: 72px; height: 72px; border-radius: 50%; background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.study-end h2 { font-size: 20px; }
.study-end p { font-size: 14px; color: var(--text-soft); max-width: 380px; }
.study-streak {
  margin-top: 6px; padding: 8px 16px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 14px;
}

/* Chip de la estantería: la cola diaria de repaso (bucle de retorno de P10). */
.lib-study-chip {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--accent); border-radius: 999px; background: var(--accent-soft);
  color: var(--accent); padding: 7px 14px; font-size: 13px; font-weight: 600;
  cursor: pointer; font-family: inherit; white-space: nowrap;
}
.lib-study-chip:hover { background: var(--accent); color: var(--on-accent); }

/* P12 · Selector de ámbito de repaso (Todo / estanterías) */
.lib-toolbar { position: relative; }
.lib-study-menu {
  position: absolute;
  z-index: 50;
  min-width: 240px; max-width: 320px;
  max-height: 60vh; overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-3);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.lib-study-sec {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-faint); padding: 8px 12px 4px;
}
.lib-study-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: 9px 12px; border: none; border-radius: 8px;
  background: none; color: var(--text); font: inherit; font-size: 14px;
  cursor: pointer; text-align: left;
}
.lib-study-opt:hover { background: var(--surface-3); }
.lib-study-opt-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-study-opt-n {
  flex: none; font-size: 12px; font-weight: 600; color: var(--accent);
  background: var(--accent-soft); border-radius: 999px; padding: 2px 9px;
}
/* Árbol: estantería = categoría padre (negrita); libro = hijo (sangrado, con guía). */
.lib-study-opt--shelf { font-weight: 600; }
.lib-study-opt--shelf .lib-study-opt-lbl::before { content: '▸ '; color: var(--text-faint); font-weight: 400; }
.lib-study-opt--book { padding-left: 30px; position: relative; color: var(--text-soft); }
.lib-study-opt--book .lib-study-opt-lbl::before { content: '└ '; color: var(--text-faint); }
.lib-study-opt--book .lib-study-opt-n { color: var(--text-soft); background: var(--surface-3); }

/* ============ AJUSTES GENERALES (overlay global) ============ */
/* Hogar de la config global de la app (agente + P1/P2/P3). Mismo patrón modal que
   el onboarding; settings de LECTURA siguen en la sidebar. */
.appset {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.appset-card {
  position: relative;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 16px;
  padding: 28px 30px; width: 100%; max-width: 640px; box-shadow: var(--shadow-3);
  /* Si la sección crece más que el viewport (p. ej. Agente en pantallas bajas), scroll
     interno: con el centrado flex, sin esto el TOPE de la tarjeta queda inalcanzable. */
  max-height: calc(100vh - 40px); overflow-y: auto;
}
.appset-close {
  position: absolute; top: 16px; right: 16px;
  width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; background: var(--surface-3); color: var(--text-soft);
  cursor: pointer; transition: background var(--transition-fast), color var(--transition-fast);
}
.appset-close:hover { background: var(--border); color: var(--text); }
.appset-h2 {
  display: flex; align-items: center; gap: 10px;
  font-size: 20px; font-weight: 700; margin-bottom: 20px; letter-spacing: -0.01em;
}
.appset-body { display: flex; gap: 24px; }
.appset-nav { flex: none; width: 160px; display: flex; flex-direction: column; gap: 6px; }
.appset-nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: none; border-radius: var(--r-sm); background: none;
  color: var(--text-soft); font-size: 14px; text-align: left; cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.appset-nav-item:hover { background: var(--surface-3); }
.appset-nav-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.appset-content { flex: 1; min-width: 0; }
.appset-section { display: flex; flex-direction: column; }
.appset-h3 { font-size: 18px; font-weight: 600; margin-bottom: 12px; }
.appset-label { display: block; font-size: 13px; color: var(--text-soft); margin: 12px 0 6px; font-weight: 500; }
.appset-input {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-0); color: var(--text); font-size: 14px;
  transition: border-color var(--transition-fast);
}
.appset-input:focus { outline: none; border-color: var(--accent); }
/* Fila del modelo: input + botón "Descubrir", y lista de chips clicables debajo. */
.appset-model-row { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; }
.appset-model-row .appset-input { flex: 1; }
.appset-discover {
  flex: none; padding: 0 14px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-3); color: var(--text); font-size: 13px; font-weight: 500; cursor: pointer;
  white-space: nowrap; transition: border-color var(--transition-fast), background var(--transition-fast);
}
.appset-discover:hover { border-color: var(--accent); }
.appset-discover:disabled { opacity: .6; cursor: default; }
.appset-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.appset-chip {
  padding: 5px 12px; border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-0); color: var(--text-soft); font-size: 13px; cursor: pointer;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
}
.appset-chip:hover { border-color: var(--accent); color: var(--text); }
.appset-chip.active { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.appset-model-hint { margin: 8px 0 0; font-size: 12px; color: var(--text-soft); line-height: 1.5; }
.appset-model-hint.is-error { color: var(--danger, #e5484d); }
.appset-model-manual { margin: 8px 0 0; font-size: 12px; }

.appset-check { display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 13px; color: var(--text-soft); }
.appset-save { width: 100%; margin-top: 16px; padding: 8px; font-size: 14px; }
.appset-saved { display: flex; align-items: center; gap: 5px; margin: 8px 0 0; font-size: 12px; color: var(--accent); }
/* `display:flex` de la regla de arriba gana al [hidden] de la hoja del navegador, así
   que el "Guardado" se veía siempre, desde el primer render. */
.appset-saved[hidden] { display: none; }
.appset-privacy {
  display: flex; align-items: flex-start; gap: 6px; margin: 14px 0 0;
  font-size: 11px; line-height: 1.5; color: var(--text-faint);
}
.appset-privacy .icon { flex: none; margin-top: 1px; }
.appset-muted { color: var(--text-soft); font-size: 13px; line-height: 1.6; margin-bottom: 10px; }
/* Salto entre la vista simple y la avanzada del Agente. Deliberadamente discreto:
   es una salida para quien la busca, no una invitación a configurar cosas. */
.appset-viewlink {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 16px;
  padding: 0; border: none; background: none; cursor: pointer;
  color: var(--text-soft); font-size: 12px; font-weight: 500;
}
.appset-viewlink:hover { color: var(--accent); }
.appset-viewlink .icon { color: currentColor; }
.appset-demo-on { display: flex; align-items: center; gap: 6px; color: var(--accent); }
.appset-demo-on .icon { flex: none; }
/* Alta/baja de un proveedor propio: aparece bajo la Base URL solo cuando hay algo
   que hacer con ella (guardarla con nombre, o quitarla de la lista). */
.appset-prov:not(:empty) { margin-top: 10px; }
.appset-prov .appset-muted { margin-bottom: 0; }
.appset-prov-on { display: flex; align-items: center; gap: 6px; color: var(--accent); margin-bottom: 8px; }
.appset-prov-on .icon { flex: none; }
.appset-soon { font-size: 12px; color: var(--text-faint); }
.appset-soon code { background: var(--surface-3); border-radius: 4px; padding: 1px 6px; }
.appset-err { margin: 10px 0 0; font-size: 12px; color: var(--danger, #e5484d); }

/* Sección Plantillas (P2) */
.appset-tpl-block { margin-top: 14px; }
.appset-tpl-block-h {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--text-soft);
  margin-bottom: 6px; text-transform: uppercase; letter-spacing: .02em;
}
.appset-tpl-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border: 1px solid var(--border); border-radius: 9px; margin-bottom: 6px;
}
.appset-tpl-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.appset-tpl-name { font-size: 14px; font-weight: 600; color: var(--text); }
.appset-tpl-ideal {
  font-size: 12px; color: var(--text-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.appset-tpl-acts { flex: none; display: flex; gap: 2px; }
.appset-tpl-tag {
  flex: none; font-size: 11px; color: var(--text-faint);
  background: var(--surface-3); border-radius: 5px; padding: 2px 7px;
}
.appset-tpl-fields { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.appset-tpl-field-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.appset-tpl-field-label { flex: 1; min-width: 140px; }
.appset-tpl-field-type { flex: none; width: 90px; }
.appset-tpl-field-fill { flex: none; width: 130px; }
.appset-tpl-addfield {
  margin-top: 10px; display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 1px dashed var(--border); border-radius: 8px;
  padding: 7px 12px; color: var(--text-soft); font-size: 13px; cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}
.appset-tpl-addfield:hover { border-color: var(--accent); color: var(--text); }
.appset-tpl-formacts { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.appset-tpl-cancel {
  background: none; border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 16px; color: var(--text-soft); font-size: 14px; cursor: pointer;
}
.appset-tpl-cancel:hover { background: var(--surface-3); color: var(--text); }

/* Sección Perfiles (P1) */
.appset-prof-active { font-size: 13px; color: var(--text-soft); margin: 4px 0 12px; }
.appset-tpl-row.is-active { border-color: var(--accent); }
.appset-prof-activate {
  flex: none; background: none; border: 1px solid var(--border); border-radius: 7px;
  padding: 4px 10px; color: var(--text-soft); font-size: 12px; cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.appset-prof-activate:hover { background: var(--surface-3); color: var(--text); }
.appset-tpl-row.is-active .appset-prof-activate { border-color: var(--accent); color: var(--accent); }

/* Sección Datos (P3) */
.appset-data-md {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-top: 8px;
}
.appset-data-msg { margin: 12px 0 0; font-size: 13px; color: var(--text-soft); line-height: 1.6; }
.appset-data-msg.is-error { color: var(--danger, #e5484d); }
.appset-data-msg .icon { vertical-align: -2px; color: var(--accent); }
.appset-data-reload {
  margin-left: 8px; background: none; border: 1px solid var(--border); border-radius: 6px;
  padding: 3px 10px; color: var(--accent); cursor: pointer; font-size: 12px;
}
.appset-data-reload:hover { background: var(--surface-3); }

@media (max-width: 560px) {
  .appset { padding: 0; align-items: flex-end; }
  .appset-card { max-width: 100%; border-radius: 16px 16px 0 0; max-height: 90vh; overflow-y: auto; }
  .appset-body { flex-direction: column; gap: 14px; }
  .appset-nav { width: 100%; flex-direction: row; flex-wrap: wrap; }
  .appset-nav-item { flex: 1; justify-content: center; }
}

/* ============ HIGHLIGHT TOOLTIP (v2) ============ */
/* Barra de selección de texto (estilo O'Reilly): preguntar al agente arriba;
   colores + nota + copiar abajo. */
/* La barra crece con el número de acciones y es `fixed`: sin un tope, en un móvil de
   375px se salía de la pantalla (447px ya antes de añadir "Con números"). Se acota al
   viewport y la fila de acciones envuelve. */
.sel-toolbar {
  position: fixed; z-index: 200;
  display: flex; flex-direction: column;
  max-width: calc(100vw - 20px);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-3);
  overflow: hidden;
}
.sel-ask {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px; border: none; background: none; cursor: pointer;
  color: var(--text); font-size: var(--fs-md); font-weight: 600; text-align: left;
  transition: background var(--transition-fast);
}
.sel-ask:hover { background: var(--surface-3); }
.sel-ask .icon { color: var(--accent); }
.sel-row {
  display: flex; align-items: stretch; gap: 0;
  flex-wrap: wrap;
  border-top: 1px solid var(--border-soft);
}
/* Al envolver, el separador vertical del primer botón de cada línea sobra; se sustituye
   por el horizontal de la propia línea. */
.sel-row > .sel-act { border-top: 1px solid transparent; }
.sel-colors { display: flex; align-items: center; gap: 8px; padding: 10px 14px; }
.highlight-color {
  width: 24px; height: 24px; border: 2px solid transparent; border-radius: 50%;
  cursor: pointer; padding: 0;
  transition: transform var(--transition-fast), border-color var(--transition-fast);
}
.highlight-color:hover { transform: scale(1.15); border-color: var(--text); }
.sel-act {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px; border: none; border-left: 1px solid var(--border-soft);
  background: none; cursor: pointer; color: var(--text); font-size: var(--fs-sm); font-weight: 500;
  transition: background var(--transition-fast);
}
.sel-act:hover { background: var(--surface-3); }
.sel-act .icon { color: var(--text-soft); }

/* Acciones rápidas: mismo peso visual que el resto de la barra, pero con el icono teñido
   de acento — son turnos del agente, no utilidades del subrayado. Cada botón ocupa la
   mitad para que se lean como un par y no como el principio de una lista larga. */
.sel-quick > .sel-act { flex: 1 1 0; justify-content: center; }
.sel-quick > .sel-act:first-child { border-left: none; }
.sel-quick .icon { color: var(--accent); }

/* Chip de referencia (pasaje adjunto) sobre el compositor del agente. */
.ai-ref {
  display: flex; align-items: center; gap: 10px;
  margin: 0 18px 10px; padding: 10px 12px;
  background: var(--accent-soft); border-radius: var(--r-md);
}
.ai-ref-ico { display: inline-flex; flex: 0 0 auto; color: var(--accent); }
.ai-ref-text {
  flex: 1; min-width: 0; font-size: var(--fs-sm); color: var(--text-soft); font-style: italic;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ai-ref-clear {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border: none; background: none; cursor: pointer;
  color: var(--text-faint); border-radius: 50%;
}
.ai-ref-clear:hover { color: var(--text); background: var(--surface-3); }

/* Nota personal bajo un subrayado en la lista. */
.highlight-note {
  display: flex; align-items: flex-start; gap: 6px; margin-top: 6px;
  font-size: 12px; color: var(--text-soft);
}
.highlight-note .icon { color: var(--text-faint); flex: 0 0 auto; margin-top: 1px; }

/* ============================================================================
   FOCO accesible (Fase 3): borde verde limpio, sin halo/glow. Coherente con la
   dirección "silenciosa y precisa": el foco es un borde de acento, no un resplandor.
   ========================================================================== */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
textarea:focus,
input:not([type="range"]):not([type="checkbox"]):focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: none;
}

/* ============================================================================
   TOOLTIPS (Fase 3) — componente CSS puro, sin JS. Cualquier elemento con
   [data-tip] muestra su texto debajo al hover/foco. Fondo charcoal fijo
   (#232A31) coherente en los tres temas, radio 8px, aparición con leve retardo.
   Se prefiere a `title` nativo (no estilable). Deja `aria-label` para a11y.
   ========================================================================== */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(-2px);
  background: #232a31;
  color: #f2f3f5;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  padding: 6px 9px;
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast), transform var(--transition-fast);
  z-index: 500;
}
[data-tip]:hover::after,
[data-tip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  transition-delay: 0.35s;
}
/* Anclajes para botones pegados a un borde (evita que el globo se salga). */
[data-tip][data-tip-align="left"]::after { left: 0; transform: translateX(0) translateY(-2px); }
[data-tip][data-tip-align="left"]:hover::after,
[data-tip][data-tip-align="left"]:focus-visible::after { transform: translateX(0) translateY(0); }
[data-tip][data-tip-align="right"]::after { left: auto; right: 0; transform: translateX(0) translateY(-2px); }
[data-tip][data-tip-align="right"]:hover::after,
[data-tip][data-tip-align="right"]:focus-visible::after { transform: translateX(0) translateY(0); }
/* En pantallas táctiles los tooltips estorban (no hay hover real): se ocultan. */
@media (hover: none) {
  [data-tip]::after { display: none; }
}

/* ============================================================================
   RESPONSIVE / MÓVIL (Fase 2) — FAB + drawers + bottom sheets + safe-areas
   ========================================================================== */

/* Altura real del viewport en móvil (barra de URL): dvh con fallback. */
@supports (height: 100dvh) {
  html, body { height: 100dvh; }
}

/* Backdrop de los drawers (solo activo en pantallas pequeñas) */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-normal);
}

/* FAB del agente (oculto por defecto; visible en móvil) */
.ai-fab {
  display: none;
  position: fixed;
  right: 16px;
  /* Por encima del footer del lector para no tapar la navegación. */
  bottom: calc(var(--footer-height) + 16px + env(safe-area-inset-bottom));
  z-index: 95;
  width: 56px;
  height: 56px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-size: 24px;
  cursor: pointer;
  box-shadow: var(--shadow-2);
  transition: transform var(--transition-normal), background var(--transition-fast);
}
.ai-fab:hover { background: var(--accent-hover); }

/* Aviso del agente cuando la respuesta llega con el panel cerrado: un punto sobre el
   punto de entrada VISIBLE (#ai-toggle en escritorio, .ai-fab en móvil; el oculto es
   display:none y no pinta nada). `ai-busy` = generando (pulso), `ai-unread` = listo. */
body.ai-busy #ai-toggle, body.ai-busy .ai-fab,
body.ai-unread #ai-toggle, body.ai-unread .ai-fab { position: relative; }
body.ai-busy #ai-toggle::after, body.ai-busy .ai-fab::after,
body.ai-unread #ai-toggle::after, body.ai-unread .ai-fab::after {
  content: ''; position: absolute; top: 6px; right: 6px;
  width: 9px; height: 9px; border-radius: 50%;
  border: 1.5px solid var(--surface-1); pointer-events: none;
}
/* Sobre el FAB (flotante sobre el fondo del lector) el punto es algo mayor. */
body.ai-busy .ai-fab::after, body.ai-unread .ai-fab::after {
  top: 5px; right: 5px; width: 14px; height: 14px; border: 2px solid var(--surface-0);
}
body.ai-unread #ai-toggle::after, body.ai-unread .ai-fab::after { background: #e5484d; }
body.ai-busy #ai-toggle::after, body.ai-busy .ai-fab::after {
  background: var(--accent); animation: ai-dot-pulse 1.2s ease-in-out infinite;
}
@keyframes ai-dot-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.65); } }

/* ---- Tablet y móvil (<1024): el agente se superpone, no empuja el lector ---- */
@media (max-width: 1023px) {
  body.ai-open .reader-main { margin-right: 0; }
  body:has(#sidebar.open) .reader-main { margin-left: 0; }   /* drawer overlay, no empuja */
  .sidebar { box-shadow: var(--shadow-3); }
  #ai-panel { width: min(440px, 100%); box-shadow: var(--shadow-3); }
  body.ai-open .scrim,
  body:has(#sidebar.open) .scrim { opacity: 1; pointer-events: auto; }
}

/* ---- Móvil (<768): bottom sheets, FAB, safe-areas ---- */
@media (max-width: 767px) {
  /* Cabecera/pie respetan el notch */
  .reader-header { padding-top: env(safe-area-inset-top); height: auto; min-height: var(--header-height); }
  .reader-footer { padding-bottom: env(safe-area-inset-bottom); height: auto; min-height: var(--footer-height); }

  /* El panel del agente se convierte en bottom sheet */
  #ai-panel {
    width: 100%;
    /* Dos alturas: media (se sigue viendo la página por encima) y completa. Ver
       `initSheetSnap` en ai/panel.js — el objetivo es que preguntar por una figura no
       implique perder de vista la figura. */
    /* Con el teclado abierto la hoja se apoya sobre él (bottom) y se recorta por arriba
       (min con el alto libre) para no salirse de la pantalla. */
    height: min(var(--ai-sheet-h, 92dvh), calc(100dvh - var(--kb-inset, 0px)));
    transition: transform var(--transition-normal), height var(--transition-normal);
    top: auto;
    bottom: var(--kb-inset, 0px);
    right: 0;
    border-left: none;
    border-top: 1px solid var(--border);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    transform: translateY(100%);
    padding-bottom: env(safe-area-inset-bottom);
  }
  body.ai-open #ai-panel { transform: translateY(0); }
  /* Teclado abierto: el hueco del home indicator lo tapa el propio teclado, y la altura
     debe seguirlo al instante (una transición aquí se ve como un salto tardío). */
  body.kb-open #ai-panel { padding-bottom: 0; transition: transform var(--transition-normal); }
  body.kb-open .ai-sheet-grab { display: none; }   /* con el teclado, cada píxel cuenta */
  /* Tirador del sheet: zona de toque generosa (44px de alto) con la barrita dentro. El área
     de toque es lo que hace usable el arrastre con el pulgar; la barrita sola sería un
     objetivo de 4px. */
  .ai-sheet-grab {
    display: block; flex-shrink: 0;
    width: 100%; height: 26px; padding: 0;
    border: none; background: none; cursor: grab;
    touch-action: none;                      /* el gesto es nuestro, no del scroll */
  }
  .ai-sheet-grab::before {
    content: '';
    display: block; width: 36px; height: 4px;
    margin: 9px auto 0;
    border-radius: 2px;
    background: var(--border);
  }
  body.sheet-dragging .ai-sheet-grab { cursor: grabbing; }
  body.sheet-dragging #ai-panel { transition: none; }

  /* Índice como drawer ancho */
  #sidebar { width: min(86%, 360px); }

  /* FAB visible; se oculta cuando el agente está abierto */
  .ai-fab { display: flex; align-items: center; justify-content: center; }
  body.ai-open .ai-fab { transform: scale(0); }
  /* En móvil el toggle del header sobra (está el FAB) */
  #ai-toggle { display: none; }

  /* Onboarding como bottom sheet */
  .ai-onboarding { padding: 0; align-items: flex-end; }
  .ai-ob-card {
    max-width: 100%;
    width: 100%;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    max-height: 92dvh;
    overflow-y: auto;
    padding: 24px 20px calc(24px + env(safe-area-inset-bottom));
  }
}

/* ---- Móvil en HORIZONTAL / pantallas muy bajas: comprimir el panel del agente ----
   El breakpoint de bottom-sheet es por ANCHO (<768), pero en horizontal el ancho supera ese
   umbral y el panel vuelve a drawer lateral con muy poca ALTURA. El "cromo" (línea de estado,
   chip de perfil, selector de conversación, pestañas y composer) se comía casi todo el alto y
   no cabían mensajes ("no se ve nada"). Recortamos ese cromo para devolverle altura a
   .ai-messages. Umbral 480px: no afecta a tablets en horizontal (iPad ≥768px de alto). */
@media (max-height: 480px) {
  #ai-panel { width: min(560px, 82%); }
  .ai-toolbar { padding: 6px 12px; }
  .ai-status { display: none; }              /* redundante con el selector de conversación */
  .ai-tabs { margin-top: 6px; }
  .ai-messages { padding-top: 8px; padding-bottom: 8px; gap: 8px; }
  .ai-composer { padding: 8px 12px; }
  .ai-composer textarea { min-height: 38px; }
}

/* ---- Táctil (móvil y TABLET): compactar el chrome del panel para dar alto al chat ----
   En vertical, un iPad no entra en el bottom-sheet (<768px de ancho) ni en la regla de
   horizontal (max-height 480), así que mostraba las filas completas (estado + selector +
   pestañas) y el chat quedaba en ~3 líneas. Aquí recortamos márgenes/paddings. El chip de
   perfil ya no ocupa fila propia (va en la barra de conversación, ver panel-template.js). */
@media (pointer: coarse) {
  .ai-status { padding: 6px 18px; font-size: 12px; }
  .ai-tabs { margin-top: 8px; }
  .ai-messages { padding: 12px 16px; }
  /* 16px exactos: por debajo de eso Safari iOS hace zoom al enfocar y descoloca el panel. */
  .ai-composer textarea { font-size: 16px; }
}
/* Estado EFÍMERO: en reposo es un readout técnico sin acción. Se colapsa cuando el espacio
   escasea —táctil o panel en modo hoja (ancho < 768, p. ej. una ventana estrecha de
   escritorio)— para dar todo el alto al chat. Los estados transitorios (leyendo/generando/
   error) quitan la clase 'idle' y reaparecen. */
@media (pointer: coarse), (max-width: 767px) {
  .ai-status.ai-status--idle { display: none; }
}

/* ============================================================================
   F3 · Pulido de componentes (estilo NotebookLM)
   ========================================================================== */

/* Cabecera del lector: translúcida sobre el contenido. El backdrop-filter crea un
   contexto de apilamiento propio, así que la elevamos (z-index) para que los tooltips
   de sus botones, que sobresalen hacia abajo, se pinten por encima del viewport
   (queda por debajo de scrim/sidebar/paneles, que van a 90+). */
.reader-header {
  position: relative;
  z-index: 40;
  background: color-mix(in srgb, var(--surface-1) 82%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border-soft);
}
.ai-status { border-bottom: 1px solid var(--border-soft); }

/* Botones unificados (Fase 3): radios a 8px, no píldora. La dirección es
   "herramienta de ingeniería" (Linear/GitHub/Warp), no iOS: esquinas contenidas,
   no cápsulas ni círculos. */
.primary-btn { border-radius: var(--r-sm); box-shadow: var(--shadow-1); }
.icon-btn { border-radius: var(--r-sm); width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; }
.nav-btn { border-radius: var(--r-sm); }

/* Barra de progreso más fina y redondeada (la zona de pulsación NO se encoge: la
   amplía .progress-container::before, que la extiende 8px arriba y abajo). */
.progress-container { height: 3px; border-radius: var(--r-pill); }
.progress-bar { border-radius: var(--r-pill); }

/* Composer: input redondeado y separación */
.ai-composer { border-top: 1px solid var(--border-soft); }
.ai-composer textarea { border-radius: var(--r-md); }

/* Libreta: etiqueta como "eyebrow" + notas como tarjetas suaves */
.ai-nb-field-label {
  font-size: var(--fs-xs);
  letter-spacing: 0.6px;
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: 8px;
}
/* INFO (IA) vs COGNICIÓN (tú): distintivo de quién rellena cada campo. */
.ai-nb-fill {
  font-size: 10px; font-weight: 700; letter-spacing: 0.3px; text-transform: none;
  padding: 1px 6px; border-radius: 999px; line-height: 1.5;
}
.ai-nb-fill.is-agent { background: var(--surface-2); color: var(--text-faint); }
.ai-nb-fill.is-user  { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.ai-nb-cog-hint {
  font-size: 12px; color: var(--text-faint); line-height: 1.5;
  margin: 2px 0 6px; font-style: italic;
}
.ai-nb-field.is-cognition {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-radius: var(--r-sm); padding: 8px 10px;
}
.ai-nb-note {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.ai-nb-goal {
  background: var(--accent-soft);
  border-radius: var(--r-md);
}
.ai-nb-goal-label { color: var(--accent); font-weight: 600; }

/* Estado "ocupado": shimmer sutil mientras el agente trabaja */
.ai-status--busy {
  background: linear-gradient(90deg, var(--text-faint) 25%, var(--text) 50%, var(--text-faint) 75%);
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: ai-shimmer 1.4s linear infinite;
}
@keyframes ai-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .ai-status--busy { animation: none; color: var(--text-soft); background: none; -webkit-text-fill-color: currentColor; }
}

/* Onboarding: tarjetas con un punto más de elevación */
.ai-ob-card { box-shadow: var(--shadow-3); }
.ai-ob-block, .ai-ob-tpl { transition: border-color var(--transition-fast), background var(--transition-fast), transform var(--transition-fast); }
.ai-ob-block:hover, .ai-ob-tpl:hover { background: var(--surface-1); transform: translateY(-1px); }

/* ============================================================================
   F4 · Modo lectura inmersivo
   ========================================================================== */
.reader-header, .reader-footer { transition: transform var(--transition-normal); }
/* Overlay de barras (estilo Play Books): cabecera y pie flotan (position:absolute)
   sobre un área de lectura que ocupa toda la altura, así ocultarlas/mostrarlas NO
   re-pagina el EPUB. Pero, como flotan, TAPAN la 1ª/última línea si no se ocultan —
   por eso el overlay solo se activa donde SÍ se ocultan:
     · MÓVIL (pointer coarse): siempre en lectura; se ocultan tocando el centro.
     · ESCRITORIO (pointer fine): SOLO en pantalla completa (`body.fs`), donde se
       auto-ocultan y reaparecen al mover el ratón.
   En ventana de escritorio las barras se quedan en el flujo normal (flex): el área
   de lectura se ajusta entre ellas y se ve TODO el texto sin gestos. */
@media (pointer: coarse) {
  body.reading .reader-header,
  body.reading .reader-footer { position: absolute; left: 0; right: 0; z-index: 60; }
  body.reading .reader-header { top: 0; }
  body.reading .reader-footer { bottom: 0; }
}
@media (pointer: fine) {
  body.reading.fs .reader-header,
  body.reading.fs .reader-footer { position: absolute; left: 0; right: 0; z-index: 60; }
  body.reading.fs .reader-header { top: 0; }
  body.reading.fs .reader-footer { bottom: 0; }
  /* En pantalla completa el área de lectura usa TODA la altura (sin reservar la franja de
     las barras): las barras están ocultas y son overlay. Al auto-revelarse (ratón al borde)
     tapan un instante la línea del borde, pero justo entonces vas a por la barra, no leyendo.
     Así se aprovecha la pantalla entera (antes se perdían ~104px arriba+abajo). */
}
/* Inmersivo = barras ocultas: se deslizan fuera (el área de lectura no cambia).
   Solo tiene efecto cuando las barras son overlay (móvil, o escritorio en `fs`). */
body.reading.immersive .reader-header { transform: translateY(-100%); }
body.reading.immersive .reader-footer { transform: translateY(100%); }
body.immersive .ai-fab { transform: scale(0); }

/* Móvil: al dibujar de borde a borde (fullscreen inmersivo + viewport-fit=cover), el
   área de lectura reserva el safe-area izquierdo/derecho (recorte de cámara en
   landscape). El fondo de página rellena esa franja (adiós al borde negro) y el texto
   queda inset, sin quedar bajo la cámara. En portrait los insets son 0 → sin efecto. */
@media (pointer: coarse) {
  body.reading .reader-viewport {
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
    /* Encogido suave al mostrar/ocultar barras (estilo Play Books, ver
       updateReaderScale). Solo transform: no re-pagina, el texto no se mueve. */
    transition: transform var(--transition-normal);
  }
  /* En modo scroll no encogemos el texto: cuando las barras overlay están visibles
     (no inmersivo) reservamos su alto para que la primera/última línea no queden
     ocultas mientras se hace scroll. */
  body.scroll-mode.reading:not(.immersive) .reader-viewport {
    padding-top: var(--header-height);
    padding-bottom: var(--footer-height);
  }
}

/* ============================================================================
   F5 · Sistema de iconos (SF Symbols) + refinado de controles estilo Apple
   ========================================================================== */

/* Glifo base: hereda el color del texto, alineado al texto que lo acompaña. */
.icon { display: inline-block; vertical-align: -0.18em; flex: 0 0 auto; }

/* Botones de icono: caja cuadrada, glifo centrado, pulsado sutil. */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-soft);
}
.icon-btn .icon { vertical-align: middle; }
.icon-btn:active:not(:disabled) { transform: scale(0.92); }
.icon-btn.is-active { color: var(--accent); }
/* Toggle en acento cuando su panel está abierto (afordancia de estado). */
body:has(#sidebar.open) #sidebar-toggle,
body.ai-open #ai-toggle { color: var(--accent); }

.nav-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; color: var(--text-soft);
}
.nav-btn:active { transform: scale(0.92); }

/* Botones con icono + texto (acciones, pestañas, volver, exportar). */
.ai-tab, .ai-act, .ai-ob-back, .export-btn,
.ai-nb-goal-label, .ai-extract-status {
  display: inline-flex; align-items: center; gap: 6px;
}
.ai-tab { justify-content: center; }
.export-btn { justify-content: center; }

/* Acento del lustre Apple: transiciones y pulsado en botones primarios/píldora. */
.primary-btn, .ai-act, .export-btn {
  transition: background var(--transition-fast), color var(--transition-fast),
              transform var(--transition-fast), box-shadow var(--transition-fast);
}
.primary-btn:active, .ai-act:active:not(:disabled),
.export-btn:active:not(:disabled) { transform: scale(0.97); }

/* Acciones bajo una respuesta: píldoras tenues con icono. */
.ai-act {
  border-radius: var(--r-pill);
  border-color: var(--border-soft);
  background: var(--surface-1);
  padding: 4px 11px 4px 9px;
  font-weight: 500;
}
.ai-act .icon { color: var(--text-faint); }
.ai-act:hover:not(:disabled) { background: var(--surface-3); color: var(--text); }

/* Selector de tema como muestras de color (estilo Apple Books). */
.theme-selector { gap: 12px; }
.theme-selector .theme-swatch {
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border); padding: 0; font-size: 0;
  box-shadow: var(--shadow-1);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.theme-selector .swatch-light  { background: #ffffff; }
.theme-selector .swatch-sepia  { background: #f3ead4; }
.theme-selector .swatch-dark   { background: #1c1c1e; }
.theme-selector .swatch-system { background: linear-gradient(110deg, #ffffff 0 50%, #1c1c1e 50% 100%); }
.theme-selector .theme-swatch:hover { transform: scale(1.08); }
.theme-selector .theme-swatch.active {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--surface-1), 0 0 0 4px var(--accent);
}

/* Papel del PDF: mismos swatches que el tema (misma gramática visual, mismo tamaño de
   toque), con la paleta de tintes real. "Noche" va aparte a propósito —no es un color
   más: invierte la tinta— y por eso se separa con un margen. */
.paper-selector { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.paper-selector .paper-swatch {
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border); padding: 0; font-size: 0;
  background: var(--surface-0);
  cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.paper-selector .swatch-auto  { background: linear-gradient(110deg, #ffffff 0 50%, #1c1c1e 50% 100%); }
.paper-selector .swatch-white { background: #ffffff; }
.paper-selector .swatch-cream { background: #f6ecd8; }
.paper-selector .swatch-paper-sepia { background: #eadcc0; }
.paper-selector .swatch-grey  { background: #dcdcda; }
.paper-selector .swatch-night { background: #14161a; margin-left: 6px; }
.paper-selector .paper-swatch:hover { transform: scale(1.08); }
.paper-selector .paper-swatch.active {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--surface-1), 0 0 0 4px var(--accent);
}

/* Nota bajo un control: explica una contrapartida sin robarle sitio a la etiqueta. */
.settings-hint {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-soft);
}

/* Onboarding: icono del bloque dentro de un disco de acento tenue. */
.ai-ob-block { position: relative; }
.ai-ob-block-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  margin-bottom: var(--s-2);
}

/* Botones de herramienta de la libreta: cuadrados de icono. */
.ai-nb-note-tools button,
.ai-nb-goto {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border: none; background: none;
  color: var(--text-faint); border-radius: var(--r-sm); cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.ai-nb-note-tools button:hover, .ai-nb-goto:hover {
  background: var(--surface-3); color: var(--text);
}
.ai-nb-del:hover { color: #ff3b30; }   /* systemRed */

/* "Volver" del onboarding como enlace de acento con chevron. */
.ai-ob-back { color: var(--accent); background: none; border: none;
  font-size: var(--fs-md); cursor: pointer; padding: 4px 2px; }
.ai-ob-back .icon { color: var(--accent); }

.ai-nb-goal-label .icon { color: var(--accent); }

/* ============================================================================
   F6 · Biblioteca — estilo Google Play Books (rail + orden/filtro + rejilla)
   ========================================================================== */

/* En la biblioteca se ocultan la cabecera del lector y el FAB del agente. */
body.in-library .reader-header { display: none; }
body.in-library .ai-fab { display: none; }

.library {
  position: absolute; inset: 0; z-index: 20;
  overflow: hidden; background: var(--surface-1);
}
.lib-layout { display: flex; height: 100%; }

/* ---- Rail izquierdo ---- */
.lib-rail {
  flex: 0 0 264px; width: 264px; height: 100%;
  display: flex; flex-direction: column;
  overflow-y: auto; border-right: 1px solid var(--border-soft);
  background: var(--surface-1);
  padding: calc(var(--s-4) + env(safe-area-inset-top)) var(--s-3) var(--s-5);
}
.lib-rail-item {
  display: flex; align-items: center; gap: var(--s-3); width: 100%;
  padding: 9px 12px; border: none; background: none; cursor: pointer;
  border-radius: var(--r-pill); color: var(--text); font-size: var(--fs-md);
  text-align: left; transition: background var(--transition-fast), color var(--transition-fast);
}
.lib-rail-item:hover { background: var(--surface-3); }
.lib-rail-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.lib-rail-item.active .lib-rail-ico .icon { color: var(--accent); }
.lib-rail-ico { display: inline-flex; flex: 0 0 auto; color: var(--text-soft); }
/* La marca ocupa la misma caja que las miniaturas de estantería para que la
   columna de iconos quede alineada. No se tiñe con el estado activo: es la
   marca, y cambiarle el color la desvirtúa. */
.lib-rail-mark { display: inline-flex; flex: 0 0 auto; width: 28px; height: 28px; }
.lib-rail-mark svg { display: block; }
.lib-rail-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lib-rail-count { color: var(--text-faint); font-size: var(--fs-sm); flex: 0 0 auto; }
.lib-rail-section {
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: var(--s-4) 12px var(--s-2);
}
.lib-rail-thumb {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 5px; overflow: hidden;
  background: var(--surface-3); display: inline-flex; align-items: center; justify-content: center;
}
.lib-rail-thumb img { width: 100%; height: 100%; object-fit: cover; }
.lib-rail-thumb-ph { color: var(--text-faint); display: inline-flex; }
.lib-rail-kebab {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%; color: var(--text-faint);
  opacity: 0; transition: opacity var(--transition-fast), background var(--transition-fast);
}
.lib-rail-shelf:hover .lib-rail-kebab { opacity: 1; }
.lib-rail-kebab:hover { background: var(--surface-2); color: var(--text); }
@media (hover: none) { .lib-rail-kebab { opacity: 1; } }
.lib-rail-create {
  display: inline-flex; align-items: center; gap: var(--s-3);
  margin: var(--s-3) 0 0; padding: 9px 12px; width: 100%;
  border: none; background: none; cursor: pointer;
  color: var(--accent); font-size: var(--fs-md); font-weight: 550;
}
.lib-rail-create .icon { color: var(--accent); }
.lib-rail-create:hover { text-decoration: underline; }
/* Los hijos del rail no se comprimen: con muchas estanterías el rail hace scroll,
   no encoge las filas. */
.lib-rail > * { flex: 0 0 auto; }
/* Ajustes generales: única puerta a la configuración desde la biblioteca (y la
   primera pantalla de quien no tiene libros), así que va anclado abajo, separado
   del resto y con caja propia — no como un enlace más de acción. */
.lib-rail-settings {
  margin-top: auto; padding-top: var(--s-3);
  border-top: 1px solid var(--border-soft); border-radius: 0;
  color: var(--text); font-weight: 500;
}
.lib-rail-settings .icon { color: var(--text-soft); }
.lib-rail-settings:hover { text-decoration: none; color: var(--accent); }
.lib-rail-settings:hover .icon { color: var(--accent); }

/* ---- Panel principal ---- */
.lib-main {
  flex: 1; min-width: 0; height: 100%; overflow-y: auto; background: var(--surface-0);
  padding: calc(var(--s-5) + env(safe-area-inset-top)) var(--s-6)
           calc(var(--s-8) + env(safe-area-inset-bottom));
}
.lib-h1 { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; margin-bottom: var(--s-4); }

/* ============ LIBRARY SECTIONS (estilo Stitch: "Reading Now", etc.) ============ */
.lib-section {
  margin-bottom: var(--s-6);
}
.lib-section-header {
  display: flex; align-items: baseline; gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.lib-section-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--text);
}
.lib-section-count {
  font-size: var(--fs-sm);
  color: var(--text-faint);
}

.lib-toolbar { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-5); }

/* Buscador de la estantería (filtra por título/autor) */
.lib-search-box {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-2); flex: 1 1 200px; max-width: 340px;
  transition: border-color var(--transition-fast);
}
.lib-search-box:focus-within { border-color: var(--accent); }
.lib-search-box .icon { color: var(--text-faint); flex: 0 0 auto; }
.lib-search-box:focus-within .icon { color: var(--accent); }
.lib-search {
  flex: 1; min-width: 0; border: none; background: none; outline: none;
  color: var(--text); font-size: var(--fs-sm); font-family: var(--font-ui);
}
.lib-search::placeholder { color: var(--text-faint); }
/* Oculta la cruz nativa de los input[type=search] (usamos el propio flujo). */
.lib-search::-webkit-search-cancel-button { -webkit-appearance: none; }

/* Desplegables (orden / progreso) */
.lib-dd { position: relative; }
.lib-dd-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px; border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--text); font-size: var(--fs-sm); font-weight: 550;
  cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast);
}
.lib-dd-btn:hover { background: var(--surface-3); }
.lib-dd.open .lib-dd-btn { border-color: var(--accent); color: var(--accent); }
.lib-dd.open .lib-dd-btn .icon { color: var(--accent); }

/* ============ PROGRESS FILTER TABS (estilo Stitch: All Books / Reading Now / To Read) ============ */
.lib-filters {
  display: flex; gap: 8px; margin-bottom: var(--s-4);
}
.lib-filter-btn {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--text-soft);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}
.lib-filter-btn:hover {
  background: var(--surface-3);
  color: var(--text);
}
.lib-filter-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.lib-dd-menu {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  min-width: 180px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-3); padding: 6px;
}
.lib-dd.open .lib-dd-menu { display: block; }
.lib-dd-opt {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; border: none; background: none; cursor: pointer;
  border-radius: var(--r-sm); color: var(--text); font-size: var(--fs-md); text-align: left;
}
.lib-dd-opt:hover { background: var(--surface-3); }
.lib-dd-opt.active { color: var(--accent); font-weight: 600; }
.lib-dd-check { width: 16px; flex: 0 0 auto; display: inline-flex; }
.lib-dd-check .icon { color: var(--accent); }

.lib-upload {
  display: inline-flex; align-items: center; gap: 6px; margin-left: auto;
  padding: 8px 16px; border: none; border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent); font-size: var(--fs-sm); font-weight: 600;
  cursor: pointer; box-shadow: var(--shadow-1);
  transition: background var(--transition-fast), transform var(--transition-fast);
}
.lib-upload:hover { background: var(--accent-hover); }
.lib-upload:active { transform: scale(0.97); }

/* ---- Rejilla de portadas (v2: más aire, sombras suaves) ---- */
.lib-grid {
  display: grid; gap: var(--s-6) var(--s-5);
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
.lib-card { cursor: pointer; }
.lib-cover {
  position: relative; aspect-ratio: 2 / 3; border-radius: var(--r-md);
  overflow: hidden; background: var(--surface-3); box-shadow: var(--shadow-1);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
.lib-card:hover .lib-cover { transform: translateY(-4px); box-shadow: var(--shadow-2); }
.lib-card:active .lib-cover { transform: scale(0.98); }
.lib-cover-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lib-cover-fallback {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, var(--accent), var(--accent-hover));
  color: #fff; font-size: 30px; font-weight: 700;
}
.lib-badge {
  position: absolute; top: 8px; left: 8px; width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-1);
}
/* Ficha fantasma: el libro está en la biblioteca pero su archivo no en este
   dispositivo. La portada se atenúa (sigue reconociéndose, no engaña con que
   está listo) y aparece la acción de traerlo. */
.lib-card.is-ghost .lib-cover-img,
.lib-card.is-ghost .lib-cover-fallback { opacity: 0.45; filter: saturate(0.6); }
.lib-card.is-ghost .lib-title, .lib-card.is-ghost .lib-author { color: var(--text-faint); }

.lib-dl {
  position: absolute; inset: auto 0 0 0; padding: 8px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.62), transparent);
}
.lib-dl-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border: none; border-radius: var(--r-pill); cursor: pointer;
  background: var(--accent); color: var(--on-accent);
  font-size: var(--fs-xs); font-weight: 600; box-shadow: var(--shadow-1);
  transition: background var(--transition-fast), transform var(--transition-fast);
}
.lib-dl-btn:hover { background: var(--accent-hover); }
.lib-dl-btn:active { transform: scale(0.96); }
.lib-dl-note {
  font-size: var(--fs-xs); font-weight: 600; color: #fff;
  padding: 4px 10px; border-radius: var(--r-pill); background: rgba(0, 0, 0, 0.45);
}
.lib-dl-lbl { font-size: var(--fs-xs); font-weight: 600; color: #fff; }
.lib-dl-bar {
  width: 100%; height: 4px; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.3); overflow: hidden;
}
.lib-dl-fill {
  display: block; height: 100%; width: 0;
  background: var(--accent); border-radius: inherit;
  transition: width var(--transition-normal);
}
.lib-card.is-transferring .lib-cover { transform: none; }

.lib-kebab {
  position: absolute; top: 6px; right: 6px;
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; cursor: pointer; color: #fff;
  background: rgba(0, 0, 0, 0.42); backdrop-filter: blur(4px);
  opacity: 0; transition: opacity var(--transition-fast);
}
.lib-card:hover .lib-kebab, .lib-kebab:focus-visible { opacity: 1; }
@media (hover: none) { .lib-kebab { opacity: 1; } }
.lib-progressbar { height: 3px; border-radius: var(--r-pill); background: var(--surface-3); margin: 12px 0 8px; overflow: hidden; }
.lib-progressbar span { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width var(--transition-normal); }
.lib-title {
  font-size: var(--fs-sm); font-weight: 600; line-height: 1.3; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.lib-author { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.lib-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-4); text-align: center; color: var(--text-soft); padding: 12vh var(--s-4);
}
.lib-empty-icon { color: var(--accent); opacity: 0.6; }
.lib-empty p { font-size: var(--fs-lg); margin-bottom: var(--s-2); }
/* El margin-left:auto que alinea el botón a la derecha en la barra de herramientas
   lo descolocaba aquí: dentro del estado vacío va centrado. */
.lib-empty .lib-upload { margin-left: 0; }
.lib-empty .lib-upload span { display: inline; }

/* Menú contextual (libro / estantería) */
.lib-menu {
  position: fixed; z-index: 200; min-width: 220px; display: none;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-3); padding: 6px;
}
.lib-menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: none; background: none; cursor: pointer;
  border-radius: var(--r-sm); color: var(--text); font-size: var(--fs-md); text-align: left;
}
.lib-menu-item:hover { background: var(--surface-3); }
.lib-menu-item .icon { color: var(--text-soft); flex: 0 0 auto; }
.lib-menu-item.danger, .lib-menu-item.danger .icon { color: #ff3b30; }
.lib-menu-check { width: 16px; display: inline-flex; flex: 0 0 auto; }
.lib-menu-check .icon { color: var(--accent); }
.lib-menu-sep { height: 1px; background: var(--border-soft); margin: 6px 4px; }
.lib-menu-label {
  font-size: var(--fs-xs); color: var(--text-faint); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 6px 10px 2px;
}
.lib-menu-empty { font-size: var(--fs-sm); color: var(--text-faint); padding: 4px 10px 8px; }

/* ---- Móvil: el rail pasa a tira horizontal de chips ---- */
@media (max-width: 767px) {
  .lib-layout { flex-direction: column; }
  .lib-rail {
    flex: 0 0 auto; width: 100%; height: auto; display: flex; gap: var(--s-2);
    flex-direction: row;   /* en escritorio el rail es columna */
    overflow-x: auto; overflow-y: hidden; border-right: none;
    border-bottom: 1px solid var(--border-soft); scrollbar-width: none;
    padding: calc(var(--s-3) + env(safe-area-inset-top)) var(--s-3) var(--s-3);
  }
  .lib-rail::-webkit-scrollbar { display: none; }
  .lib-rail-section { display: none; }
  .lib-rail-item {
    flex: 0 0 auto; width: auto; background: var(--surface-3);
    padding: 7px 12px; gap: var(--s-2);
  }
  .lib-rail-ico, .lib-rail-thumb, .lib-rail-mark { display: none; }
  .lib-rail-create { width: auto; flex: 0 0 auto; margin: 0; padding: 7px 12px; }
  .lib-rail-create span { display: none; }
  /* En la tira horizontal no hay "abajo": Ajustes vuelve a ser un chip más, pero
     conserva su etiqueta porque es la única entrada a la configuración. */
  .lib-rail-settings {
    margin: 0; padding: 7px 12px; border-top: none;
    border-radius: var(--r-pill); background: var(--surface-3);
  }
  .lib-rail-settings span { display: inline; }
  .lib-main { padding-left: var(--s-4); padding-right: var(--s-4); padding-top: var(--s-4); }
  .lib-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: var(--s-4) var(--s-3); }
  .lib-h1 { font-size: var(--fs-xl); }
  .lib-upload span { display: none; }
  .lib-upload { padding: 8px 12px; }
}

/* ============================================================================
   F7 · Selector de conversaciones (varias por libro) — v2
   ========================================================================== */
.ai-convobar { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; margin: 0; }
.ai-convo-btn {
  flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--text); font-size: var(--fs-sm); font-weight: 550;
  cursor: pointer; transition: background var(--transition-fast), border-color var(--transition-fast);
}
.ai-convo-btn:hover { background: var(--surface-3); }
.ai-convo-btn .icon:first-child { color: var(--accent); flex: 0 0 auto; }
.ai-convo-btn .icon:last-child { color: var(--text-faint); flex: 0 0 auto; }
.ai-convo-label { flex: 1; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ai-convo-menu { display: none; }
.ai-convo-item { align-items: flex-start; }
.ai-convo-item-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.ai-convo-item-name { font-weight: 600; }
.ai-convo-item-goal {
  font-size: var(--fs-xs); color: var(--text-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ai-convo-del {
  margin-left: auto; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 6px; color: var(--text-faint);
}
.ai-convo-del .icon { color: inherit; }
.ai-convo-del:hover { color: #ff3b30; background: var(--surface-3); }

/* Estado "sin conversación": invita a elegir objetivo (reabre el onboarding). */
.ai-convobar.no-convo .ai-convo-btn {
  border-style: dashed; border-color: var(--accent); color: var(--accent);
}
.ai-convobar.no-convo .ai-convo-btn .icon { color: var(--accent); }
.ai-convobar.no-convo .ai-convo-btn .icon:last-child { display: none; }

/* Botón de renombrar conversación en el menú. */
.ai-convo-rename {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 6px; color: var(--text-faint); margin-left: 4px;
}
.ai-convo-rename .icon { color: inherit; }
.ai-convo-rename:hover { color: var(--accent); background: var(--surface-3); }

/* ============================================================================
   Diálogos propios (alert/confirm/prompt) — reemplazan a los nativos del navegador.
   Modales sobrios y theme-aware; ver js/ui/dialog.js.
   ========================================================================== */
.dlg-overlay {
  position: fixed; inset: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(var(--shadow-color), 0.32);
  backdrop-filter: blur(2px);
}
.dlg-card {
  width: 100%; max-width: 420px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  padding: var(--s-5);
  animation: dlg-in 0.16s var(--ease);
}
@keyframes dlg-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
.dlg-title { font-size: var(--fs-lg); font-weight: 600; margin: 0 0 var(--s-2); }
.dlg-msg { font-size: var(--fs-md); color: var(--text-soft); line-height: 1.5; white-space: pre-wrap; }
.dlg-input {
  width: 100%; margin-top: var(--s-4);
  padding: 10px 12px; font: inherit; font-size: var(--fs-md);
  color: var(--text); background: var(--surface-0);
  border: 1px solid var(--border); border-radius: var(--r-sm);
}
.dlg-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.dlg-actions { display: flex; justify-content: flex-end; gap: var(--s-2); margin-top: var(--s-5); }
.dlg-btn {
  padding: 8px 16px; font: inherit; font-size: var(--fs-md); font-weight: 500;
  border-radius: var(--r-sm); border: 1px solid var(--border); cursor: pointer;
  background: var(--surface-0); color: var(--text);
  transition: background var(--transition-fast), border-color var(--transition-fast);
}
.dlg-cancel:hover { background: var(--surface-3); }
.dlg-ok { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.dlg-ok:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.dlg-ok:focus-visible, .dlg-cancel:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dlg-danger { background: #dc2626; border-color: #dc2626; color: #fff; }
.dlg-danger:hover { background: #b91c1c; border-color: #b91c1c; }

/* ==== Paywall Pro (ui/paywall.js) — misma familia visual que los diálogos ==== */
.pw-card { max-width: 460px; }
.pw-list { list-style: none; margin: var(--s-4) 0 0; padding: 0; display: grid; gap: 8px; }
.pw-feat {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-md); color: var(--text-soft);
}
.pw-feat svg { color: var(--accent); flex: none; }
.pw-feat-hot { color: var(--text); font-weight: 600; }
.pw-price { margin-top: var(--s-4); font-size: var(--fs-sm); color: var(--text-soft); }

/* ==== Ajustes → Licencia (MON2) ==== */
.appset-lic-state {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-md); font-weight: 600; margin-bottom: var(--s-2);
}
.appset-lic-state.is-pro { color: var(--accent); }
.appset-lic-mock { margin-top: var(--s-4); opacity: 0.8; }

/* ==== Badge de estado del sync (Fase 2) ==== */
#sync-badge {
  position: fixed;
  bottom: 14px;
  right: 14px;
  z-index: 900;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  background: var(--surface-2);
  color: var(--text-soft);
  border: 1px solid var(--border);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  pointer-events: none;
}
/* Cuando hay un chip de trabajo de IA (mismo rincón), sube el badge de sync para no solaparse. */
body.has-taskchip #sync-badge { bottom: 68px; }
/* Con el panel de IA abierto, el badge (fijo abajo-derecha) tapaba el botón "Ver" y el input
   del chat: apártalo a la izquierda del panel, igual que el task-chip. */
body.ai-open #sync-badge { right: calc(var(--ai-panel-width) + 14px); }
#sync-badge[data-state='error'] { color: #dc2626; border-color: #dc2626; }
#sync-badge[data-state='reconnect'] {
  color: var(--accent);
  border-color: var(--accent);
  cursor: pointer;
  pointer-events: auto;
}

/* ==== Historial de versiones — overlay dedicado (Fase 3: recuperación) ==== */
/* Overlay propio a pantalla completa (z sobre Ajustes) con UNA sola zona scrollable de
   altura completa: cabecera y buscador fijos, lista flex:1, pie fijo. Sin scroll anidado. */
.histov { z-index: 320; }
.histov-card {
  position: relative;
  display: flex; flex-direction: column;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 16px;
  width: 100%; max-width: 560px; height: 85vh; max-height: 85vh;
  box-shadow: var(--shadow-3); overflow: hidden;
}
.histov-head {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--border);
}
.histov-titles { flex: 1; min-width: 0; }
.histov-title {
  font-size: 17px; font-weight: 700; letter-spacing: -0.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.histov-sub { font-size: 12px; color: var(--text-soft); margin-top: 2px; }
.histov-back, .histov-close {
  flex: none; display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface-0); color: var(--text-soft);
  border-radius: var(--r-sm); transition: background var(--transition-fast), color var(--transition-fast);
}
.histov-back { padding: 6px 12px 6px 8px; font-size: 13px; }
.histov-close { width: 34px; height: 34px; justify-content: center; border-radius: 50%; }
.histov-back:hover, .histov-close:hover { background: var(--surface-3); color: var(--text); }
.histov-search-wrap { flex: none; padding: 12px 18px; border-bottom: 1px solid var(--border); }
.histov-search {
  width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-0); color: var(--text); font-size: 14px;
}
.histov-search:focus { border-color: var(--accent); outline: none; }
.histov-list {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px; padding: 14px 18px;
}
.histov-pad, .histov-empty { padding: 8px 2px; }
.histov-empty { text-align: center; padding: 32px 12px; }
.histov-book {
  text-align: left; padding: 12px 14px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-0); color: var(--text);
  display: flex; flex-direction: column; gap: 3px;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.histov-book:hover { border-color: var(--accent); background: var(--surface-3); }
.histov-book-title {
  font-size: 14px; font-weight: 500; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.histov-untitled { color: var(--text-soft); font-style: italic; font-weight: 400; }
.histov-book-id { font-family: ui-monospace, SFMono-Regular, monospace; font-size: 11px; color: var(--text-soft); }
.histov-ver {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-0);
}
.histov-ver-date { font-size: 13px; color: var(--text); }
.histov-ver-btn {
  flex: none; padding: 6px 14px; cursor: pointer;
  border: 1px solid var(--accent); border-radius: var(--r-sm);
  background: transparent; color: var(--accent); font-size: 13px; font-weight: 500;
}
.histov-ver-btn:hover { background: var(--accent-soft); }
.histov-ver-btn:disabled { opacity: 0.4; cursor: default; border-color: var(--border); color: var(--text-soft); background: transparent; }
.histov-foot { flex: none; padding: 10px 18px; border-top: 1px solid var(--border); font-size: 12px; margin: 0; }
@media (max-width: 600px) {
  .histov-card { max-width: 100%; height: 100%; max-height: 100%; border-radius: 0; }
}

/* ============ P18 · MODO FEYNMAN (explícamelo tú) ============ */
.fey-card { max-width: 620px; }
.fey-h2 { margin: 0 0 4px; font-size: 20px; }
.fey-hint { font-size: 13px; color: var(--text-soft); margin: 10px 0 0; }
.fey-chips { margin-top: 2px; }
.fey-chip {
  display: inline-block; margin: 4px 6px 0 0; padding: 4px 10px;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--text-soft);
  font-size: 12px; cursor: pointer;
}
.fey-chip:hover { background: var(--surface-3); color: var(--text); }

/* "Sugerir conceptos": acción discreta, no un botón de acento — la acción principal de la
   pantalla es Empezar, y esto solo alimenta el campo de arriba. */
.fey-suggest-btn {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; padding: 0;
  border: 0; background: none; color: var(--accent);
  font-size: 12px; cursor: pointer;
}
.fey-suggest-btn:hover:not(:disabled) { text-decoration: underline; }
.fey-suggest-btn:disabled { color: var(--text-faint); cursor: default; }

/* Progreso de ideas cubiertas. Es feedback SIN veredicto: dice cuánto llevas, no qué has
   hecho mal — el diagnóstico solo aparece si lo pides. */
.fey-progress { display: flex; align-items: center; gap: 10px; margin: 12px 0 16px; }
.fey-progress-bar { flex: 1; height: 6px; background: var(--surface-3); border-radius: var(--r-pill); overflow: hidden; }
.fey-progress-bar span { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width var(--transition-normal); }
.fey-progress-n { flex: none; font-size: 12px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* La intervención del tutor: una sola, destacada. Si pareciera un chat, el usuario
   respondería en corto; aquí queremos un párrafo suyo. */
.fey-say {
  padding: 14px 16px; margin-bottom: 14px;
  background: var(--accent-soft);
  border-radius: var(--r-md); font-size: 15px; line-height: 1.5;
}
.fey-input {
  width: 100%; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-1); color: var(--text);
  font: inherit; font-size: 15px; line-height: 1.5; resize: vertical;
}
.fey-input:focus { outline: none; border-color: var(--accent); }
.fey-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* El estado "grabando" lo pinta mic.js con .ai-mic-on (compartido con la barra del chat).
   Doble clase para ganarle a .appset-tpl-cancel sin recurrir a !important. */
.appset-tpl-cancel.ai-mic-on { background: var(--accent); color: #fff; }
/* La barra de grabación sustituye al textarea, y este es alto (rows=5): sin igualar la
   altura, el modal pegaba un salto al empezar a dictar. */
.ai-ob-body > .mic-bar { min-height: 132px; align-items: center; }
/* Selector de idioma del dictado: pegado al micro, porque es un ajuste DE ese botón.
   `width: auto` es obligatorio: el `select` global lleva `width: 100%` y aquí partía la
   fila de acciones en tres líneas. */
.fey-err-act {
  margin-left: 2px; padding: 0; border: 0; background: none; cursor: pointer;
  color: inherit; font: inherit; font-weight: 700; text-decoration: underline;
}
.fey-mic-lang {
  width: auto; flex: 0 0 auto; margin-left: -4px;
  padding: 6px 22px 6px 8px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-0); color: var(--text); font-size: 12px; font-weight: 600; cursor: pointer;
}

.fey-diag { margin-top: 8px; }
.fey-block { margin-bottom: 18px; }
.fey-block h4 { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--text-soft); }
.fey-block ul { margin: 0; padding-left: 20px; }
.fey-block li { margin-bottom: 6px; line-height: 1.5; }
.fey-ok li::marker { color: var(--accent); }
.fey-missing li::marker { color: var(--danger, #e5484d); }
.fey-wrong li::marker { color: #f5a524; }

/* ---- IA6 v2 · Selección de región sobre el PDF ---------------------------------------
   Capa fija sobre el hueco del lector mientras dura la selección. `touch-action: none` es
   obligatorio: sin él, el navegador se queda el gesto para hacer scroll y el arrastre no
   llega nunca a la capa. */
.region-overlay {
  position: fixed; z-index: 190;
  cursor: crosshair; touch-action: none;
  background: rgba(0, 0, 0, 0.12);
}
/* Con un marco dibujado, el atenuado se INVIERTE: lo que queda claro es exactamente lo que
   se va a mandar al modelo. Se consigue con una sombra enorme hacia fuera del marco, no con
   otra capa (que taparía el propio marco). */
.region-overlay:has(.region-box:not([hidden])) { background: transparent; }
.region-hint {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px 8px 16px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-pill); box-shadow: var(--shadow-3);
  font-size: var(--fs-sm); color: var(--text); white-space: nowrap;
}
.region-cancel {
  border: none; background: var(--surface-3); color: var(--text-soft);
  padding: 5px 12px; border-radius: var(--r-pill); font-size: var(--fs-xs); cursor: pointer;
}
.region-cancel:hover { color: var(--text); }

/* "Toda la página": el otro alcance de la misma acción. Se marca con acento tenue —no sólido—
   porque la acción principal aquí sigue siendo ARRASTRAR; esto es la alternativa, no el
   camino recomendado. */
.region-whole {
  border: none; background: var(--accent-soft); color: var(--accent-hover);
  padding: 5px 12px; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 600;
  cursor: pointer; transition: background var(--transition-fast);
}
.region-whole:hover { background: var(--accent); color: var(--on-accent); }
/* El recorte se ve a través del marco: el resto de la página queda atenuado por el overlay,
   así el usuario ve exactamente lo que va a mandar al modelo. */
.region-box {
  position: absolute; pointer-events: none;
  border: 2px solid var(--accent);
  border-radius: 2px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.38);
}
body.region-selecting { user-select: none; }

/* Zonas adjuntas al composer (multi-región): una miniatura por zona, con su × */
.ai-zones {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin: 0 18px 10px;
}
.ai-zone {
  position: relative; flex: 0 0 auto;
  width: 72px; height: 54px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  overflow: hidden; line-height: 0;
  background: var(--surface-3);
}
.ai-zone img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Rótulo corto y de UNA línea: el nombre largo ("Zona 2 · p. 4") es el que viaja al modelo,
   aquí solo hace falta distinguir una miniatura de otra. */
.ai-zone-label {
  position: absolute; left: 0; bottom: 0; right: 0;
  padding: 2px 4px; font-size: 10px; line-height: 1.3;
  background: rgba(0, 0, 0, 0.6); color: #fff; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ai-zone-x {
  position: absolute; top: 2px; right: 2px;
  width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, 0.6); color: #fff; padding: 0;
}
.ai-zone-add {
  display: inline-flex; align-items: center; gap: 6px;
  height: 54px; padding: 0 12px;
  border: 1px dashed var(--border); border-radius: var(--r-sm);
  background: none; color: var(--text-soft); font-size: var(--fs-xs); cursor: pointer;
}
.ai-zone-add:hover { color: var(--accent); border-color: var(--accent); }

/* Acciones sobre lo capturado: ocupan su propia línea bajo las miniaturas y reutilizan el
   aspecto de la barra de selección — es la misma idea (no empezar ante un campo vacío)
   aplicada a la imagen. */
.ai-zone-acts {
  flex: 1 0 100%;
  display: flex; flex-wrap: wrap; gap: 6px;
  margin-top: 2px;
}
.ai-zone-acts .sel-act {
  border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: 5px 12px; font-size: var(--fs-xs); gap: 6px;
}
.ai-zone-acts .sel-act .icon { color: var(--accent); }

/* ---- Fórmulas (MathML vía Temml) ---------------------------------------------------- */
.ai-math { font-size: 1.05em; }
/* En bloque: centrada y con scroll PROPIO. Una fórmula larga en un móvil de 390px no puede
   ensanchar la burbuja del chat ni el panel entero — que scrolle ella. */
.ai-math--block {
  display: block;
  margin: 12px 0;
  overflow-x: auto;
  overflow-y: hidden;
  text-align: center;
  padding-bottom: 2px;   /* sitio para la barra de scroll cuando aparece */
}
/* Hereda el color del texto: en tema oscuro la fórmula no puede quedarse en negro. */
.ai-math math { color: inherit; }
/* Antes de hidratar (o si Temml no llega) se ve el TeX ya legible, no `\cdot` crudo. */
.ai-math:not([data-math-done]) { font-family: var(--font-mono, monospace); font-size: 0.95em; }

/* ============================================================================
   Movimiento reducido (F4)
   Las animaciones nuevas son decorativas: con `prefers-reduced-motion` desaparecen
   sin dejar el elemento a medio camino (por eso se anula también el `both` del
   escalonado del índice, que si no lo dejaría en opacity:0 para siempre).
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .sidebar.open .toc-list a { animation: none; opacity: 1; transform: none; }
  .epub-container.chapter-in { animation: none; }
  .sidebar, #ai-panel, .reader-main { transition: none; }
}
