/* Estilos de la app. Todos los colores vienen de styles/tokens.css. */

* { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }

html, body {
  height: 100%;
  overflow: hidden;
}

body {
  font-family: var(--font-body);
  background: var(--void);
  color: var(--text);
  position: relative;
}

/* ── COSMIC BACKGROUND ── */
.bg-canvas {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.bg-canvas::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--bg-wash);
}
.bg-canvas::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: var(--stars-opacity);
  background-image:
    radial-gradient(1.5px 1.5px at 15% 20%, rgb(255 255 255 / 0.6) 0%, transparent 100%),
    radial-gradient(1px 1px at 35% 60%, rgb(255 255 255 / 0.4) 0%, transparent 100%),
    radial-gradient(2px 2px at 65% 15%, rgb(var(--lilac-rgb) / 0.5) 0%, transparent 100%),
    radial-gradient(1px 1px at 80% 40%, rgb(255 255 255 / 0.3) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 90% 70%, rgb(255 255 255 / 0.5) 0%, transparent 100%),
    radial-gradient(1px 1px at 45% 85%, rgb(var(--lilac-rgb) / 0.4) 0%, transparent 100%),
    radial-gradient(2px 2px at 10% 75%, rgb(var(--gold-rgb) / 0.3) 0%, transparent 100%),
    radial-gradient(1px 1px at 55% 35%, rgb(255 255 255 / 0.35) 0%, transparent 100%),
    radial-gradient(1.5px 1.5px at 25% 45%, rgb(255 255 255 / 0.45) 0%, transparent 100%),
    radial-gradient(1px 1px at 70% 90%, rgb(var(--lilac-rgb) / 0.3) 0%, transparent 100%);
}

/* Floating orbs */
.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  animation: float 8s ease-in-out infinite;
  opacity: var(--orbs-opacity);
  pointer-events: none;
}
.orb-1 { width:300px; height:300px; background:rgb(var(--purple-rgb) / 0.2); top:-80px; left:-80px; animation-delay:0s; }
.orb-2 { width:200px; height:200px; background:rgb(var(--violet-rgb) / 0.15); bottom:20%; right:-60px; animation-delay:3s; }
.orb-3 { width:150px; height:150px; background:rgb(var(--amber-rgb) / 0.12); bottom:10%; left:20%; animation-delay:5s; }
@keyframes float {
  0%,100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-20px) scale(1.05); }
}

/* Decorative lines */
.deco-lines {
  position: absolute;
  inset: 0;
  opacity: var(--grid-opacity);
  background-image:
    linear-gradient(90deg, rgb(var(--lilac-rgb) / 0.03) 1px, transparent 1px),
    linear-gradient(0deg, rgb(var(--lilac-rgb) / 0.03) 1px, transparent 1px);
  background-size: 60px 60px;
}

/* ── LAYOUT ── */
.app-wrapper {
  position: relative;
  z-index: 1;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── LOS ICONOS ──
   Dibujados en el pliego del index.html. Un solo grosor de trazo para
   todos: es lo que hace que parezcan de la misma mano. */
.ico-pliego { position: absolute; width: 0; height: 0; overflow: hidden; }
.ico {
  width: 20px;
  height: 20px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}
.ico-sm { width: 15px; height: 15px; stroke-width: 1.6; }
.ico-lg { width: 26px; height: 26px; stroke-width: 1.25; }

/* ── CABECERA ──
   Un ex libris: la etiqueta que alguien pega dentro de su libro.
   «Ex libris» arriba en versalitas, el nombre debajo, y un filete de
   latón que los separa del resto de la página. */
.app-header {
  padding: env(safe-area-inset-top, 0) 0 0;
  background: rgb(var(--void-rgb) / 0.92);
  backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.header-inner {
  padding: 15px 18px 0;
}
.header-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.brand-mark {
  font-size: 9px;
  line-height: 1;
  color: var(--gold);
  letter-spacing: 3px;
  text-transform: uppercase;
  margin-bottom: 5px;
}
.brand-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: var(--display-weight);
  color: var(--text);
  letter-spacing: var(--display-spacing);
  text-transform: var(--display-transform);
  line-height: 1;
}

/* El folio: el recuento donde va el número de página de un libro. */
.header-folio {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 11px;
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 0.4px;
}
.folio-rule {
  flex: 1;
  height: 1px;
  margin-right: 5px;
  background: var(--rule-line);
}
.folio-num { color: var(--lilac); font-variant-numeric: tabular-nums; }
.folio-sep { color: var(--border-strong); }

/* ── NAVEGACIÓN ──
   El activo se marca con un filete de latón bajo el icono, como la
   pestaña de un archivador. Sin fondo, sin brillo, sin cápsula. */
.nav-bar {
  display: flex;
  padding: 0 8px;
  margin-top: 10px;
}
.nav-item {
  flex: 1;
  padding: 9px 2px 9px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  color: var(--muted);
  border-bottom: 1.5px solid transparent;
  transition: color 0.2s, border-color 0.2s;
  position: relative;
}
.nav-item.active { color: var(--gold); border-bottom-color: var(--gold); }
.nav-icon { width: 21px; height: 21px; }
.nav-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: var(--label-spacing);
  font-weight: 500;
}

/* ── SCROLL AREA ── */
.scroll-area {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 80px;
}
.scroll-area::-webkit-scrollbar { display: none; }

/* ── VIEWS ── */
.view { display: none; padding: 16px; }
.view.active { display: block; }

/* ── EL TITULILLO ──
   Antes esto era «✦ SECCIÓN ✦» centrado entre dos filetes, y la hoja
   de un libro llegaba a tener OCHO seguidos bajando por la pantalla:
   ocho estrellitas idénticas, ocho rayas simétricas. Un adorno que se
   repite ocho veces deja de adornar y pasa a ser papel pintado.

   Ahora es el titulillo de un libro: el rótulo pegado al margen
   izquierdo y un filete que corre hasta el borde derecho. Marca dónde
   empieza algo sin pedir su turno. */
.section-heading {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 26px 0 12px;
}
.section-heading::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--rule-line);
}
.section-heading-text {
  font-size: 10px;
  letter-spacing: var(--label-spacing);
  color: var(--lilac);
  text-transform: uppercase;
  white-space: nowrap;
}

/* ── EL LOMO ──
   Hasta ahora un libro sin portada era una letra dentro de una caja
   redondeada, igual que un chip, igual que un botón, igual que todo lo
   demás. En una app que trata de libros, los libros no tenían cuerpo.

   Esto es un lomo: tela, dos filetes arriba y abajo, el título
   estampado en vertical y el canto de las hojas asomando por la
   derecha. La tela sale del género —siempre la misma para el mismo
   género— y TODO lo demás sale de tokens, porque la encuadernación es
   parte del tema: Máquina no tiene ni tela ni pan de oro, y en
   Pergamino los lomos van sobre papel claro y no pueden ser negros. */
.lomo {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--lomo-luz), var(--tela, var(--tela-1));
  border-radius: var(--lomo-radio);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / .3);
}
/* Los dos filetes: en un lomo entelado enmarcan el rótulo. */
.lomo::before,
.lomo::after {
  content: '';
  position: absolute;
  left: 12%;
  right: 22%;
  height: 1px;
  background: var(--lomo-filete);
  opacity: .6;
}
.lomo::before { top: 13%; }
.lomo::after { bottom: 13%; }
/* El canto: las hojas que asoman por el lado abierto. */
.lomo-canto {
  position: absolute;
  top: 2px; bottom: 2px; right: 0;
  width: 4px;
  background: repeating-linear-gradient(180deg,
    var(--lomo-canto) 0 1px,
    transparent 1px 2px);
  opacity: .55;
}
.lomo-txt {
  position: absolute;
  inset: 19% 30% 19% 10%;
  display: block;
  font-family: var(--font-display);
  font-size: 7.5px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: .3px;
  color: var(--lomo-filete);
  writing-mode: vertical-rl;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* En los sitios pequeños el título no cabe: queda la tela y el filete,
   que ya distinguen un libro de otro. */
.lomo-mini .lomo-txt { display: none; }
.lomo-mini::before { top: 16%; }
.lomo-mini::after { bottom: 16%; }

/* ── LEYENDO AHORA ──
   Lo de hoy, encima del plan del año. No es una tarjeta con marco:
   sería una caja compitiendo con la mascota justo encima y con los
   meses justo debajo. Es una balda más —el mismo filete y la misma
   letra que los meses—, así que se lee como parte de la misma
   estantería y no como un cartel pegado.

   La portada es alta y estrecha como en el resto de la app: un libro
   se reconoce por el lomo antes que por el título. */
.ahora { margin-bottom: 22px; }
.ahora-titulo {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: var(--display-weight);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 8px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border-soft);
}
.ahora-libro { display: flex; gap: 12px; align-items: flex-start; }
.ahora-libro + .ahora-libro { margin-top: 16px; }
.ahora-cover {
  width: 34px; height: 52px; flex-shrink: 0;
  border-radius: 1px; overflow: hidden; cursor: pointer;
  box-shadow: 0 2px 8px rgb(0 0 0 / .5);
}
.ahora-cover img { width: 100%; height: 100%; object-fit: cover; }
.ahora-txt { flex: 1; min-width: 0; }
.ahora-book-title {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 15px; line-height: 1.3;
  cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ahora-book-author { font-size: 12px; color: var(--muted); margin-top: 1px; }
/* La fila de progreso ya trae su margen de arriba; aquí sobra la
   mitad porque el autor va justo encima. */
.ahora-txt .progress-row { margin-top: 6px; }

/* ── EL AÑO ──
   Los tres años son tres pestañas de un archivador, no tres botones
   con degradado. El activo se marca abajo, en latón, igual que la
   navegación y los filtros: una sola señal en toda la app. */
.year-row {
  display: flex;
  gap: 22px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border-soft);
}
.year-btn {
  padding: 8px 2px 8px;
  border-bottom: 1.5px solid transparent;
  margin-bottom: -1px;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: var(--display-weight);
  color: var(--muted);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: color 0.2s, border-color 0.2s;
}
.year-btn.active { color: var(--gold); border-bottom-color: var(--gold); }

/* ── EL MES ──
   Antes cada mes llevaba un cuadradito de color con un emoji dentro:
   doce colores distintos bajando por la pantalla, ninguno diciendo
   nada. Ahora el mes es la etiqueta de una balda —el nombre a la
   izquierda, el filete, y cuántos van a la derecha— y los libros
   cuelgan debajo. */
.month-group { margin-bottom: 30px; }
.month-label {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 4px;
}
.month-name-text {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: var(--display-weight);
  color: var(--text);
  letter-spacing: 0.2px;
}
.month-name-text::after {
  content: '';
  display: none;
}
.month-label .month-rule {
  flex: 1;
  height: 1px;
  align-self: center;
  background: var(--rule-line);
}
.month-progress {
  font-size: 10px;
  color: var(--muted);
  letter-spacing: var(--label-spacing);
  font-variant-numeric: tabular-nums;
}

/* ── UN LIBRO EN EL PLAN ──
   Ya no es una tarjeta. Antes todo era una tarjeta —el libro, el
   filtro, el botón, el aviso— con el mismo borde y el mismo radio, y
   una pantalla entera de cajas idénticas no tiene jerarquía: tiene
   relleno. Un libro es ahora una ENTRADA DE CATÁLOGO: el lomo, el
   texto, y un filete que la separa de la siguiente. */
.book-card {
  display: flex;
  gap: 14px;
  align-items: stretch;
  padding: 13px 4px;
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  position: relative;
  transition: opacity 0.2s;
}
.book-card:active { opacity: .6; }
.book-card.read { opacity: 0.48; }
/* Leído: un sello en el margen, no una medalla verde encima. */
.book-card-read-badge {
  position: absolute;
  top: 15px;
  right: 2px;
  font-size: 11px;
  color: var(--success);
  line-height: 1;
}
.book-card-cover {
  width: 32px;
  height: 62px;
  flex-shrink: 0;
  align-self: flex-start;
  position: relative;
  overflow: hidden;
  border-radius: 1px;
  box-shadow: 0 2px 8px rgb(0 0 0 / .5);
}
.book-card-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.book-card-body {
  flex: 1;
  padding: 1px 18px 0 0;
  min-width: 0;
}
.book-card-role {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: var(--label-spacing);
  font-weight: 600;
  margin-bottom: 4px;
}
/* El rol no es un estado: ⚡ Corto no es "éxito", es el libro breve
   del mes. Por eso lleva acento propio y sigue al tema, en vez de
   tomar prestado el verde semántico. */
.role-anchor { color: var(--role-anchor); }
.role-short { color: var(--role-short); }
.book-card-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: var(--display-weight);
  line-height: 1.22;
  margin-bottom: 3px;
  color: var(--text);
}
/* El autor en cursiva, como en la ficha de una biblioteca. */
.book-card-author {
  font-size: 12px;
  font-style: italic;
  color: var(--muted);
  margin-bottom: 7px;
}
.book-card-tags {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: baseline;
}
/* Un dato al margen, no una pastilla. Las cápsulas con borde estaban
   por todas partes y todas pesaban lo mismo que el título del libro. */
.tag {
  font-size: 10px;
  color: var(--muted);
  letter-spacing: .2px;
}
.tag + .tag::before {
  content: '·';
  margin-right: 8px;
  color: var(--border-strong);
}
.tag-pages { color: var(--muted); }

/* ── LIBRARY VIEW ── */
.search-wrap {
  position: relative;
  margin-bottom: 12px;
}
.search-wrap input {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  padding: 10px 4px 10px 28px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text);
  outline: none;
  transition: border-color 0.2s;
  backdrop-filter: blur(10px);
}
.search-wrap input::placeholder { color: var(--muted); }
.search-wrap input:focus { border-bottom-color: var(--gold); }
.search-icon {
  position: absolute;
  left: 2px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}
.search-icon .ico { width: 17px; height: 17px; }
.filter-scroll {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin-bottom: 14px;
  padding-bottom: 2px;
}
.filter-scroll::-webkit-scrollbar { display: none; }
/* Un filtro es una PALABRA que se puede pulsar, no una cápsula. El
   activo se subraya en latón: la misma marca que la pestaña de arriba,
   así se aprende una sola vez. */
.chip {
  flex-shrink: 0;
  padding: 6px 2px 5px;
  /* Algunos `.chip` son <button>, y un botón sin fondo declarado se
     pinta BLANCO: es el color que trae el navegador de fábrica. Antes
     no se veía porque `.chip` traía su propio relleno. */
  background: transparent;
  border: none;
  border-bottom: 1.5px solid transparent;
  font-size: 11px;
  cursor: pointer;
  color: var(--muted);
  white-space: nowrap;
  transition: color 0.2s, border-color 0.2s;
  letter-spacing: 0.2px;
}
.chip.active { color: var(--gold); border-bottom-color: var(--gold); }
.filter-scroll { gap: 16px; }

/* ── LA ESTANTERÍA ──
   La misma entrada de catálogo que en el plan, con el lomo más alto:
   aquí el libro es lo que se busca, no lo que está programado. */
.lib-card {
  padding: 12px 4px;
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  gap: 14px;
  cursor: pointer;
  transition: opacity 0.15s;
}
.lib-card:active { opacity: .6; }
.lib-cover {
  width: 30px;
  height: 66px;
  overflow: hidden;
  flex-shrink: 0;
  border-radius: 1px;
  box-shadow: 0 2px 8px rgb(0 0 0 / .5);
}
.lib-cover img { width:100%; height:100%; object-fit:cover; }
.lib-info { flex:1; min-width:0; padding-top: 1px; }
.lib-title {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: var(--display-weight);
  line-height: 1.24;
  margin-bottom: 2px;
  color: var(--text);
}
.lib-author { font-size: 12px; font-style: italic; color: var(--muted); margin-bottom: 7px; }
.lib-footer { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.status-dot {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
}
.status-read-dot { background: var(--success); }
.status-reading-dot { background: var(--violet); }
.status-pending-dot { background: var(--amber); }
.status-text { font-size: 10px; color: var(--muted); }
.lib-year { font-size: 10px; color: rgb(var(--lilac-rgb) / 0.3); }

/* ── TRACKER VIEW ── */
/* La única placa de la pantalla: tapa, filete de latón arriba y
   sombra debajo. Es lo que justifica que las demás cosas NO la lleven. */
.tracker-orb-card {
  background: var(--dusk);
  border: var(--card-border);
  border-top: 1px solid rgb(var(--gold-rgb) / .4);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  padding: 24px 20px 20px;
  margin-bottom: 4px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.orb-ring-wrap {
  position: relative;
  width: 110px;
  height: 110px;
  margin: 0 auto 16px;
}
.orb-ring { transform: rotate(-90deg); }
.orb-ring-bg { fill:none; stroke: rgb(var(--lilac-rgb) / 0.12); stroke-width: 4; }
.orb-ring-fill {
  fill: none;
  stroke: url(#goldGradient);
  stroke-width: 4;
  stroke-linecap: butt;
  transition: stroke-dashoffset 0.6s cubic-bezier(0.4,0,0.2,1);
}
.orb-center {
  position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%);
  text-align:center;
}
.orb-pct {
  font-family: var(--font-display); font-size:30px; font-weight: var(--display-weight);
  color: var(--gold); line-height:1; font-variant-numeric: tabular-nums;
}
.orb-sublabel { font-size:8px; color:var(--muted); text-transform:uppercase; letter-spacing: var(--label-spacing); margin-top: 3px; }
.tracker-stats {
  display: flex;
  justify-content: center;
  gap: 28px;
}
.tstat { text-align:center; }
.tstat-num {
  font-family: var(--font-display); font-size:22px; font-weight: var(--display-weight);
  color: var(--text); line-height:1; font-variant-numeric: tabular-nums;
}
.tstat-label { font-size:8px; color:var(--muted); text-transform:uppercase; letter-spacing: var(--label-spacing); margin-top: 4px; }

/* Tracker card */
.tracker-card {
  padding: 16px 4px;
  border-bottom: 1px solid var(--border-soft);
}
.tracker-card-header {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
  align-items: flex-start;
}
.tracker-card-cover {
  width: 28px;
  height: 58px;
  border-radius: 1px;
  overflow: hidden;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgb(0 0 0 / .5);
}
.tracker-card-cover img { width:100%; height:100%; object-fit:cover; }
.tracker-card-info { flex:1; min-width:0; }
.tracker-card-title {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-size: 16px;
  line-height: 1.3;
  margin-bottom: 2px;
  color: var(--text);
}
.tracker-card-author { font-size: 12px; font-style: italic; color: var(--muted); }
.read-btn {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  flex-shrink: 0;
  transition: all 0.2s;
  color: var(--muted);
}
.read-btn.done {
  background: linear-gradient(135deg, var(--success), var(--success-deep));
  border-color: transparent;
  color: white;
}
.stars-row { display:flex; gap:6px; margin-bottom:10px; }
.star {
  font-size: 22px;
  cursor: pointer;
  color: rgb(var(--gold-rgb) / 0.2);
  transition: color 0.15s, transform 0.1s;
  -webkit-user-select: none;
  user-select: none;
}
.star.on { color: var(--gold); text-shadow: 0 0 10px rgb(var(--gold-rgb) / 0.5); }
.star:active { transform: scale(1.3); }
.review-txt {
  width: 100%;
  background: rgb(var(--lilac-rgb) / 0.05);
  border: var(--hairline);
  border-radius: var(--chip-radius);
  padding: 8px 10px;
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--text);
  resize: none;
  outline: none;
  min-height: 52px;
  transition: border-color 0.2s;
}
.review-txt::placeholder { color: var(--muted); }
.review-txt:focus { border-color: var(--violet); }

/* ── LA RACHA  ·  historia #68 ──
   Apagada cuando no hay racha, cálida cuando la hay, y con un borde
   de aviso cuando hoy todavía no cuenta. Nada de rojo ni de alarmas:
   la racha tiene que dar ganas, no ansiedad. */
.streak-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  margin-bottom: 16px;
  border-radius: var(--card-radius);
  border: var(--card-border);
  background: var(--card-bg);
}
.streak-card.viva {
  border-color: rgb(var(--amber-rgb) / 0.45);
  background: linear-gradient(135deg, rgb(var(--amber-rgb) / 0.10), transparent 70%);
}
.streak-card.en-peligro { border-style: dashed; }
.streak-flame {
  font-size: 30px;
  line-height: 1;
  flex: none;
  filter: grayscale(1);
  opacity: 0.35;
}
.streak-card.viva .streak-flame { filter: none; opacity: 1; }
.streak-body { flex: 1; min-width: 0; }
.streak-num {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1;
  color: var(--gold);
}
.streak-line { font-size: 12px; color: var(--text); margin-top: 4px; }
.streak-best { font-size: 11px; color: var(--muted); margin-top: 3px; }
.streak-freeze {
  font-size: 11px;
  color: var(--lilac);
  margin-top: 6px;
}
.streak-freeze-left { font-size: 10px; color: var(--muted); margin-top: 4px; opacity: 0.8; }

/* ── ¿CUÁL PRIMERO?  ·  historia #60 ── */
.duel-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  margin-bottom: 6px;
  text-align: left;
  background: transparent;
  border: var(--hairline);
  border-radius: var(--ctl-radius);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.duel-pick.on {
  border-color: var(--violet);
  background: rgb(var(--purple-rgb) / 0.18);
}
.duel-cover {
  flex: none;
  width: 30px;
  height: 44px;
  object-fit: cover;
  border-radius: 4px;
  background: rgb(var(--lilac-rgb) / 0.08);
}
.duel-info { flex: 1; min-width: 0; display: block; }
.duel-title {
  display: block;
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.duel-meta {
  display: block;
  font-size: 10px;
  color: var(--muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.duel-check { flex: none; color: var(--violet); font-size: 14px; width: 14px; }

.duel-verdict {
  font-family: var(--font-display);
  font-size: 17px;
  line-height: 1.4;
  color: var(--gold);
  margin-bottom: 14px;
}
.duel-reasons {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: 12px;
  line-height: 1.65;
  color: var(--text);
}
.duel-reasons li { margin-bottom: 3px; }
.duel-against {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: var(--ctl-radius);
  border: var(--hairline);
  background: transparent;
}
.duel-against-title {
  font-size: 11px;
  color: var(--muted);
  text-transform: var(--label-transform);
  letter-spacing: var(--label-spacing);
}
.duel-against .duel-reasons { color: var(--muted); }

/* El empate reñido: los dos lados, uno al lado del otro */
.duel-sides { display: grid; gap: 10px; }
.duel-side {
  padding: 12px;
  border-radius: var(--card-radius);
  border: var(--hairline);
}
.duel-side-title {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--text);
  margin-bottom: 4px;
}
.duel-side-none { font-size: 11px; color: var(--muted); margin: 6px 0; }

/* ── LOS HUECOS DEL PLAN  ·  historia #65 ──
   Un mes vacío tiene que verse, pero no puede competir con los meses
   que sí tienen libros: por eso va en trazo discontinuo y apagado.
   Se lee como «aquí falta algo», no como «aquí hay algo». */
.month-gap {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  margin-bottom: 14px;
  border-radius: var(--card-radius);
  border: 1px dashed var(--border);
  background: transparent;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.month-gap:hover { border-color: var(--violet); background: rgb(var(--lilac-rgb) / 0.05); }
/* El mes vacío: el signo de sumar en el margen, donde iría el lomo. */
.gap-rune {
  width: 32px;
  display: grid;
  place-items: center;
  color: var(--muted-soft);
  flex: none;
}
.gap-text { flex: 1; min-width: 0; }
.gap-month {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--muted);
  letter-spacing: var(--display-spacing);
}
.gap-hint { font-size: 11px; color: var(--muted); opacity: 0.8; margin-top: 2px; }
.gap-add {
  font-size: 20px;
  color: var(--violet);
  flex: none;
  line-height: 1;
}

/* El de un mes que ya tiene libros: más callado todavía */
.gap-inline {
  display: block;
  width: 100%;
  margin: -4px 0 14px;
  padding: 8px 12px;
  font-size: 11px;
  text-align: left;
  color: var(--muted);
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--ctl-radius);
  cursor: pointer;
}
.gap-inline:hover { color: var(--lilac); border-color: var(--violet); }

/* ── TU GUSTO, EN UNA FRASE  ·  historia #62 ──
   Va arriba del todo y con aire: es lo que hace auditable al motor.
   Si dice que te encanta la poesía y es mentira, quieres verlo tú. */
.taste-line {
  font-family: var(--font-display);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  padding: 12px 14px;
  margin-bottom: 16px;
  border-radius: var(--card-radius);
  border: var(--hairline);
  background: rgb(var(--lilac-rgb) / 0.06);
}

/* ── PRIVADA O PÚBLICA  ·  historia #28 ──
   Apagado es el estado normal, y se nota: gris, sin brillo, sin
   reclamar nada. El encendido sí canta —porque publicar es lo que
   conviene ver de un vistazo, no lo que conviene que pase de largo. */
.privacy-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 10px 0 16px;
}
.privacy-row.privacy-off { opacity: 0.45; }
/* El texto del interruptor: ocupa lo que queda y se parte si hace falta. */
.privacy-copy { flex: 1; min-width: 0; }
.privacy-switch {
  flex: none;
  width: 44px;
  height: 26px;
  padding: 3px;
  border-radius: var(--pill-radius);
  border: var(--hairline);
  background: rgb(var(--lilac-rgb) / 0.08);
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.privacy-switch:disabled { cursor: default; }
.privacy-switch.on {
  background: rgb(var(--success-rgb) / 0.35);
  border-color: rgb(var(--success-rgb) / 0.6);
}
.privacy-knob {
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--muted);
  transition: transform 0.2s, background 0.2s;
}
.privacy-switch.on .privacy-knob {
  transform: translateX(18px);
  background: var(--success);
}
.privacy-title { font-size: 12px; color: var(--text); }
.privacy-hint { font-size: 11px; color: var(--muted); margin-top: 2px; }

/* La versión de una línea, para el tracker */
.privacy-mini {
  margin-top: 8px;
  font-size: 10px;
  padding: 3px 10px;
  border-radius: var(--pill-radius);
  border: var(--hairline);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.privacy-mini.on {
  color: var(--success);
  border-color: rgb(var(--success-rgb) / 0.5);
  background: rgb(var(--success-rgb) / 0.1);
}
.tag-public {
  color: var(--success);
  border-color: rgb(var(--success-rgb) / 0.5);
  background: rgb(var(--success-rgb) / 0.1);
}

/* ── AÑADIR ──
   Era un círculo morado que brillaba. Ahora es una placa: tapa, filete
   de latón y sombra. Un objeto sobre la mesa, no una luz. */
.fab {
  position: fixed;
  bottom: calc(22px + env(safe-area-inset-bottom, 0));
  right: 18px;
  width: 50px; height: 50px;
  border-radius: var(--ctl-radius);
  background: var(--fab-bg);
  color: var(--fab-color);
  border: 1px solid var(--fab-borde);
  cursor: pointer;
  box-shadow: 0 6px 20px rgb(0 0 0 / .55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  transition: transform 0.15s, background 0.15s;
}
.fab .ico { width: 22px; height: 22px; }

/* ── LOS ATAJOS DEL MARGEN · historias #57 y #157 ─────────────
   Tres cosas que se usan a menudo y estaban detrás de pantallas que se
   abren de vez en cuando: las estanterías, dónde sentarse a leer y
   dónde comprar el siguiente.

   MÁS PEQUEÑOS QUE EL «+», y a propósito. Añadir un libro es lo que se
   hace en esta app todos los días; salir a un café es lo que se hace
   de vez en cuando. Dos botones del mismo tamaño dirían que las tres
   cosas pesan lo mismo, y no es verdad. */
.atajos {
  position: fixed;
  /* EN COLUMNA SOBRE EL «+», Y A LA DERECHA.

     Primero estuvieron abajo a la izquierda, enfrente del «+». Pero
     ese lado es donde vive el dibujo del fondo —la lámpara, la pila de
     libros, el bote de las tijeras— y dos botones encima de eso se
     leen como parte de la ilustración y no como botones. La derecha
     está despejada.

     Así que se apilan sobre el botón de añadir: una sola columna, en
     el mismo eje, con el «+» abajo del todo porque es el que más se
     usa y el que cae más cerca del pulgar. */
  bottom: calc(84px + env(safe-area-inset-bottom, 0));
  right: 22px;
  display: flex; flex-direction: column; gap: 10px;
  z-index: 200;
}
.atajo-btn {
  width: 42px; height: 42px;
  border-radius: var(--ctl-radius);
  /* El MISMO fondo y borde que el «+», que es lo que los hace leerse
     como la misma familia de botones y no como parte del dibujo del
     fondo. Con el color de superficie se confundían con la ilustración
     de la mesa, que es exactamente la queja de partida: que estaba
     escondido. */
  background: var(--fab-bg);
  color: var(--fab-color);
  border: 1px solid var(--fab-borde);
  cursor: pointer;
  box-shadow: 0 5px 16px rgb(0 0 0 / .5);
  display: flex; align-items: center; justify-content: center;
}
.atajo-btn .ico { width: 20px; height: 20px; }
.atajo-btn:active { transform: translateY(1px); background: var(--purple); }
.fab:active { transform: translateY(1px); background: var(--purple); }

/* ── MODALS ── */
.overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / 0.7);
  z-index: 300;
  align-items: flex-end;
  backdrop-filter: blur(4px);
}
.overlay.open { display: flex; }
.sheet {
  background: var(--sheet-bg);
  border-radius: var(--sheet-radius);
  border-top: 1px solid rgb(var(--gold-rgb) / .25);
  padding: 16px 20px calc(36px + env(safe-area-inset-bottom,0));
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
}
.sheet-handle {
  width: 34px; height: 3px;
  background: var(--border-strong);
  border-radius: 2px;
  margin: 0 auto 16px;
}
/* El título de la hoja, con su filete debajo: es la portadilla. */
.sheet-title {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: var(--display-weight);
  color: var(--text);
  padding-bottom: 12px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--border);
  letter-spacing: 0.2px;
}

/* Form */
.fg { margin-bottom: 14px; }
.flabel {
  display: block;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--muted);
  margin-bottom: 6px;
  font-weight: 500;
}
.finput, .fselect {
  width: 100%;
  padding: 11px 14px;
  background: rgb(var(--lilac-rgb) / 0.05);
  border: var(--hairline);
  border-radius: var(--ctl-radius);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text);
  outline: none;
  transition: border-color 0.2s;
  -webkit-appearance: none;
}
.finput::placeholder { color: var(--muted); }
.finput:focus, .fselect:focus { border-color: var(--violet); }
.fselect option { background: var(--deep); }
.frow { display: flex; gap: 10px; }
.frow .fg { flex: 1; }

.btn-magic {
  width: 100%;
  padding: 14px;
  background: var(--purple);
  color: var(--parchment);
  border: 1px solid rgb(var(--gold-rgb) / .3);
  border-radius: var(--ctl-radius);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: var(--display-weight);
  letter-spacing: 0.3px;
  cursor: pointer;
  margin-top: 8px;
  transition: transform 0.12s, filter 0.15s;
}
.btn-magic:active { transform: translateY(1px); filter: brightness(1.15); }
.btn-magic:has(.ico) { display: inline-flex; align-items: center; justify-content: center; gap: 9px; }
.btn-magic .ico { width: 17px; height: 17px; }

/* ── LA PORTADILLA ──
   El banner desenfocado ocupaba 160 px para enseñar la misma portada
   que ya salía debajo, y encima dejaba el libro en 60 px. Ahora el
   libro está de pie a tamaño de verdad y la ficha a su lado. */
.detail-portadilla {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  padding: 6px 20px 18px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.detail-libro {
  width: 78px;
  height: 118px;
  flex: none;
  border-radius: 1px;
  overflow: hidden;
  box-shadow: 0 8px 22px rgb(0 0 0 / .6);
}
.detail-libro img { width: 100%; height: 100%; object-fit: cover; display: block; }
.detail-ficha { flex: 1; min-width: 0; padding-top: 4px; }
.detail-cuerpo { padding: 0 20px; }
.detail-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: var(--display-weight);
  color: var(--text);
  line-height: 1.18;
  margin-bottom: 5px;
  letter-spacing: 0;
}
.detail-author { font-size: 13px; font-style: italic; color: var(--muted); margin-bottom: 12px; }
/* Cuatro datos sueltos separados por puntos, como el pie de imprenta.
   Cuatro cápsulas con borde pesaban lo mismo que el título. */
.detail-tags { font-size: 11px; color: var(--muted); line-height: 1.7; }
.detail-tag + .detail-tag::before { content: '·'; margin: 0 6px; color: var(--border-strong); }

.status-row { display:flex; gap:8px; }
.status-btn {
  flex:1; padding:9px 6px;
  border-radius: var(--ctl-radius);
  border: 1px solid var(--border);
  background: transparent;
  font-size:11.5px;
  color:var(--muted);
  cursor:pointer;
  text-align:center;
  transition: border-color .2s, color .2s;
}
.status-btn.s-read { border-color:rgb(var(--success-rgb) / .55); color:var(--success); }
.status-btn.s-reading { border-color:rgb(var(--gold-rgb) / .6); color:var(--gold); }

.btn-delete {
  width:100%; padding:12px;
  border-radius: var(--ctl-radius);
  border:1px solid rgb(var(--danger-rgb) / .2);
  background:transparent;
  color:rgb(var(--danger-rgb) / .7);
  font-family:'Inter',sans-serif;
  font-size:13px;
  cursor:pointer;
  margin-top:12px;
  transition:all 0.2s;
}

/* Empty */
.empty {
  text-align:center; padding:50px 20px;
  color:var(--muted);
}
.empty-rune { display: grid; place-items: center; margin-bottom: 12px; color: var(--muted-soft); }
.empty-rune .ico { width: 34px; height: 34px; stroke-width: 1.1; }
.empty-text { font-family: var(--font-display); font-size:15px; font-style:italic; }

/* Sparkle animation on load */
@keyframes sparkle {
  0%,100% { opacity:0.3; transform:scale(1); }
  50% { opacity:1; transform:scale(1.2); }
}
.sparkle { animation: sparkle 2s ease-in-out infinite; }
/* ── TU AÑO EN LIBROS  ·  historia #71 ──
   Una tarjeta grande cada vez, no seis números en fila. La nota de la
   historia pide cuidado visual real: si hay que entrecerrar los ojos
   para leerla, no se va a compartir. */
.year-picker { margin-bottom: 14px; }

.ycard {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 300px;
  padding: 28px 24px;
  border-radius: var(--card-radius);
  border: var(--card-border);
  background:
    radial-gradient(120% 90% at 15% 0%, rgb(var(--purple-rgb) / 0.30), transparent 60%),
    linear-gradient(160deg, rgb(var(--dusk-rgb) / 0.9), rgb(var(--deep-rgb) / 0.95));
  overflow: hidden;
  cursor: pointer;
  text-align: left;
}
.ycard::after {                       /* el mismo destello de las portadas */
  content: '✦';
  position: absolute;
  top: 14px; right: 18px;
  font-size: 26px;
  color: rgb(var(--gold-rgb) / 0.25);
}
.ycard-kicker {
  font-size: 11px;
  color: var(--lilac);
  text-transform: var(--label-transform);
  letter-spacing: var(--label-spacing);
  margin-bottom: 10px;
}
.ycard-title {
  font-family: var(--font-display);
  font-size: 40px;
  line-height: 1.1;
  color: var(--gold);
  text-wrap: balance;
}
.ycard-text { font-size: 14px; color: var(--text); margin-top: 10px; }
.ycard-portada .ycard-title,
.ycard-paginas .ycard-title { font-size: 56px; }
.ycard-mejor .ycard-title,
.ycard-largo .ycard-title,
.ycard-generos .ycard-title { font-size: 30px; }

.ycard-list {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  font-size: 12px;
  color: var(--muted);
}
.ycard-list li {
  display: flex;
  justify-content: space-between;
  padding: 5px 0;
  border-bottom: 1px solid rgb(var(--lilac-rgb) / 0.10);
}
.ycard-list li:last-child { border-bottom: none; }

.ydots { display: flex; justify-content: center; gap: 7px; margin: 14px 0 10px; }
.ydot {
  width: 7px; height: 7px;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: rgb(var(--lilac-rgb) / 0.25);
  cursor: pointer;
  transition: background 0.2s, transform 0.2s;
}
.ydot.on { background: var(--gold); transform: scale(1.3); }

/* El acceso, desde la tarjeta de la racha */
.streak-year {
  position: absolute;
  top: 12px; right: 14px;
  font-size: 10px;
  padding: 3px 9px;
  border-radius: var(--pill-radius);
  border: var(--hairline);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.streak-year:hover { color: var(--gold); border-color: rgb(var(--gold-rgb) / 0.5); }
.streak-card { position: relative; }

/* ── EL @USUARIO  ·  historia #44 ── */
.uname-field { position: relative; }
.uname-at {
  position: absolute;
  left: 12px; top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  font-size: 14px;
  pointer-events: none;
}
.uname-input { padding-left: 26px; }
.uname-status { font-size: 11px; color: var(--muted); margin-top: 6px; min-height: 15px; }
.uname-status.ok { color: var(--success); }
.uname-status.bad { color: var(--danger); }

/* ── PRESUMIR  ·  historias #90–#93 ──
   La vista previa a tamaño real no cabe en un móvil, así que se
   escala. Lo que se comparte son 1080×1920 de verdad. */
.share-preview {
  display: block;
  width: 100%;
  max-width: 300px;
  height: auto;
  margin: 14px auto 0;
  border-radius: var(--card-radius);
  border: var(--hairline);
  box-shadow: 0 12px 40px rgb(0 0 0 / 0.45);
}
