/* ============================================================
   TECPORT RAG — Componentes (CSS plano, sin frameworks)
   Los colores, tipografías, radios, sombras y safe-areas viven
   en tokens.css (cargado antes): este archivo solo consume
   var(--token) y NO define colores en crudo, para que el theme
   sea portable tal cual a la app Android/iOS.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Hanken+Grotesk:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400;1,500&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;1,8..60,400&family=JetBrains+Mono:wght@400;500;600&display=swap');
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; padding: 0; }
body {
  font-family: var(--ui);
  background: var(--bg);
  background-image: var(--bg-grad);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
  /* Móvil: sin rebote del documento al hacer overscroll ni flash al tocar */
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
}
::selection { background: rgba(31,111,199,.25); }

/* Táctil: elimina el retraso de doble-tap-zoom en todos los controles */
button, [role="button"], input, textarea, a { touch-action: manipulation; }

/* Accesibilidad: anillo de foco visible solo al navegar con teclado */
:focus-visible { outline: 2px solid var(--blue-bright); outline-offset: 2px; }

/* scrollbars */
*::-webkit-scrollbar { width: 11px; height: 11px; }
*::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border-radius: 20px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-faint); background-clip: padding-box; }
*::-webkit-scrollbar-track { background: transparent; }

.theme-fade, .theme-fade * {
  transition: background-color .35s var(--ease), color .35s var(--ease),
              border-color .35s var(--ease), box-shadow .35s var(--ease);
}

/* keyframes */
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.6); opacity: .35; } }
@keyframes fadeup { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes stripe { to { background-position: 40px 0; } }
@keyframes blink { 0%,80%,100% { opacity: .25; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
@keyframes rowin { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* 100dvh sigue la altura visible REAL en móvil (barras del navegador /
   teclado en pantalla); 100vh queda como respaldo para motores antiguos. */
.app { display: flex; height: 100vh; height: 100dvh; overflow: hidden; }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--app); }

/* ============================ SIDEBAR ============================ */
.sb {
  width: 274px; flex: none; display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--sidebar) 0%, var(--sidebar-2) 100%);
  color: var(--sidebar-tx); padding: 16px 14px; gap: var(--sb-gap);
  transition: width .38s var(--ease), padding .38s var(--ease);
  overflow: hidden; border-right: 1px solid var(--sidebar-border);
}
.sb--collapsed { width: 80px; padding: 16px 12px; overflow: visible; /* deja salir los tooltips */ }
.sb__label { transition: opacity .2s var(--ease); white-space: nowrap; }
.sb--collapsed .sb__label { opacity: 0; pointer-events: none; width: 0; }

/* ---------- PRIMITIVA de icon-button ----------
   Misma área de impacto, radio y tamaño de glifo para TODO control del sidebar.
   La usan el toggle de colapso y (vía sus reglas .sb--collapsed) el logo,
   "Nueva conversación", "Documentos" y el avatar. */
.sb-iconbtn {
  flex: none; width: var(--sb-btn-size); height: var(--sb-btn-size);
  border-radius: var(--sb-btn-radius); border: 1px solid var(--sidebar-line);
  background: var(--sidebar-soft); color: var(--sidebar-tx);
  display: grid; place-items: center; cursor: pointer;
  transition: background .18s, border-color .18s, color .18s;
}
.sb-iconbtn svg { width: var(--sb-btn-icon); height: var(--sb-btn-icon); }
.sb-iconbtn:hover               { background: var(--sb-hover); }
.sb-iconbtn:active              { background: var(--sb-active); }
.sb-iconbtn.is-active,
.sb-iconbtn[aria-current="page"]{ background: var(--sb-active); border-color: var(--sidebar-border); }

/* Foco-visible homogéneo (anillo) para cualquier control enfocable del sidebar */
.sb :focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--sidebar), 0 0 0 4px var(--sb-focus);
}

/* ---------- regiones flexbox: grupo superior (.sb__nav crece) e inferior anclado ---------- */
.sb__top  { display: flex; align-items: center; gap: var(--sb-gap); min-height: var(--sb-btn-size); }
.sb__nav  { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--sb-gap); }
.sb__foot { display: flex; flex-direction: column; gap: 10px; }
.sb__divider { height: 1px; border: 0; margin: 0; background: var(--sb-divider); }

/* ---------- marca: branding NO interactivo (sin chrome de botón) ---------- */
.sb__brand { flex: 1; min-width: 0; display: flex; align-items: center; }
.sb__logo-plaque {
  display: inline-flex; background: var(--sidebar-plaque); border-radius: 12px; padding: 9px 13px;
  max-width: 100%;
}
.sb__logo-plaque img { height: 26px; display: block; width: auto; }
.sb__icon { width: var(--sb-btn-size); height: var(--sb-btn-size); border-radius: var(--sb-btn-radius); display: none; }
.sb--collapsed .sb__logo-plaque { display: none; }
.sb--collapsed .sb__icon { display: block; }
.sb--collapsed .sb__top { flex-direction: column; gap: var(--sb-gap); align-items: center; }
.sb--collapsed .sb__brand { flex: none; justify-content: center; }

.sb__new {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px; border: 1px solid rgba(255,255,255,.16); cursor: pointer;
  border-radius: var(--sb-btn-radius); color: #fff; font: 600 14px/1 var(--ui); letter-spacing: .2px;
  background: var(--sidebar-cta);
  box-shadow: 0 6px 18px rgba(8,24,56,.5), inset 0 1px 0 rgba(255,255,255,.18);
  transition: transform .15s, box-shadow .2s, border-color .2s, filter .2s;
}
.sb__new:hover { transform: translateY(-1px); filter: brightness(1.07); box-shadow: 0 10px 24px rgba(8,24,56,.6), inset 0 1px 0 rgba(255,255,255,.22); border-color: rgba(255,255,255,.28); }
/* Colapsado: cada control adopta la primitiva (cuadrado de --sb-btn-size,
   mismo radio, glifo de --sb-btn-icon) centrado en el mismo eje vertical. */
.sb--collapsed .sb__new { width: var(--sb-btn-size); height: var(--sb-btn-size); padding: 0; margin: 0 auto; justify-content: center; gap: 0; }

.sb__section {
  display: flex; align-items: center; gap: 7px; padding: 0 6px;
  font: 700 11px/1 var(--ui); letter-spacing: 1.4px; text-transform: uppercase; color: var(--sidebar-tx-dim);
}
.sb--collapsed .sb__section { justify-content: center; gap: 0; }

.sb__hist { flex: 1; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; overflow-x: hidden; margin: 0 -4px; padding: 0 4px; }
.hist {
  position: relative; display: flex; align-items: stretch; gap: 9px; padding: 9px 28px 9px 10px; border-radius: 10px; cursor: pointer;
  border: 1px solid transparent; background: transparent; text-align: left; color: var(--sidebar-tx);
  transition: background .18s, border-color .18s;
}
.hist:hover { background: var(--sidebar-soft); }
.hist--active { background: var(--sidebar-active); border-color: var(--sidebar-line); }
.hist__bar { width: 3px; border-radius: 3px; background: var(--orange); flex: none; opacity: 0; transition: opacity .18s; }
.hist--active .hist__bar { opacity: 1; }
.hist__body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.hist__title { font: 600 13px/1.3 var(--ui); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hist__time { font: 500 11px/1 var(--ui); color: var(--sidebar-tx-dim); }
.hist__del {
  position: absolute; top: 50%; right: 7px; transform: translateY(-50%);
  width: 22px; height: 22px; border: none; background: transparent; color: var(--sidebar-tx-dim);
  cursor: pointer; border-radius: 6px; font-size: 16px; line-height: 1; display: grid; place-items: center;
  opacity: 0; padding: 0; transition: opacity .15s, background .15s, color .15s;
}
.hist:hover .hist__del { opacity: 1; }
.hist__del:hover { background: rgba(237,125,34,.18); color: var(--orange-soft); }
/* Al colapsar ocultamos el historial completo (los títulos no caben);
   ya no se generan los puntos "·" que antes lo representaban. */
.sb--collapsed .sb__section,
.sb--collapsed .sb__hist { display: none; }

.sb__empty { padding: 16px 10px; text-align: center; color: var(--sidebar-tx-dim); font: 500 12px/1.5 var(--ui); }
.sb--collapsed .sb__empty { display: none; }

.sb__docs {
  display: flex; align-items: center; gap: 9px; padding: 11px 12px; cursor: pointer;
  border-radius: var(--sb-btn-radius); border: 1px solid var(--sidebar-line); background: var(--sidebar-soft);
  color: var(--sidebar-tx); font: 600 13px/1 var(--ui); text-align: left;
  transition: background .18s, border-color .18s, color .18s;
}
.sb__docs:hover  { background: var(--sb-hover); color: var(--sidebar-tx); }
.sb__docs:active { background: var(--sb-active); }
.sb__docs.is-active,
.sb__docs[aria-current="page"] { background: var(--sb-active); border-color: var(--sidebar-border); }
.sb__docs svg { flex: none; width: var(--sb-btn-icon); height: var(--sb-btn-icon); }
.sb__docs-count {
  margin-left: auto; flex: none; min-width: 22px; padding: 3px 7px; border-radius: 999px; text-align: center;
  font: 700 11px/1.2 var(--ui); color: #fff; background: rgba(237,125,34,.85);
}
.sb--collapsed .sb__docs { width: var(--sb-btn-size); height: var(--sb-btn-size); padding: 0; margin: 0 auto; justify-content: center; gap: 0; }
/* El badge de contador lleva margin-left:auto; aunque .sb__label lo deja a
   ancho 0, ese margen automático seguiría absorbiendo el hueco y descentraría
   el glifo. Lo sacamos del flujo flex para que justify-content:center mande. */
.sb--collapsed .sb__docs-count { display: none; }

.sb__user {
  display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 12px;
  background: var(--sidebar-card); border: 1px solid var(--sidebar-line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
}
.sb--collapsed .sb__user { width: var(--sb-btn-size); padding: 4px 0; margin: 0 auto; justify-content: center; gap: 0; border-color: transparent; background: transparent; box-shadow: none; }
.sb__avatar {
  width: var(--sb-btn-size); height: var(--sb-btn-size); flex: none; border-radius: var(--sb-btn-radius); display: grid; place-items: center;
  font: 700 13px/1 var(--ui); color: var(--user-tx); background: var(--sb-avatar-bg);
  box-shadow: inset 0 0 0 1px var(--sidebar-line);
}
.sb__userinfo { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.sb__userinfo strong { font: 700 13px/1.2 var(--ui); color: var(--sidebar-tx); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb__userinfo em { font: 500 11px/1.3 var(--ui); font-style: normal; color: var(--sidebar-tx-dim); }
.sb__gear { background: none; border: none; color: var(--sidebar-tx-dim); cursor: pointer; padding: 4px; border-radius: 7px; flex: none; transition: background .18s, color .18s; }
.sb__gear:hover  { color: var(--sidebar-tx); background: var(--sb-hover); }
.sb__gear:active { background: var(--sb-active); }

/* ---------- tooltips en modo colapsado (las etiquetas de texto están ocultas) ---------- */
.sb-tip { position: relative; }
.sb--collapsed .sb-tip::after {
  content: attr(data-tip);
  position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%) scale(.96);
  transform-origin: left center;
  background: var(--sb-tip-bg); color: var(--sb-tip-tx);
  padding: 6px 10px; border-radius: 8px; font: 600 12px/1 var(--ui); white-space: nowrap;
  box-shadow: var(--shadow-md); opacity: 0; pointer-events: none;
  transition: opacity .14s var(--ease), transform .14s var(--ease); z-index: 80;
}
.sb--collapsed .sb-tip:hover::after,
.sb--collapsed .sb-tip:focus-visible::after { opacity: 1; transform: translateY(-50%) scale(1); }

/* ---------- ayuda contextual (regla: nada de párrafos largos en los modales) ----------
   Trigger discreto (icono "?"). El texto explicativo largo vive dentro de .tp-help__pop
   y sólo aparece flotando al pasar el mouse o enfocar con teclado. Reutilizable en
   cualquier modal/encabezado: <span class="tp-help" tabindex="0">?<span class="tp-help__pop">…</span></span> */
.tp-help { position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; flex: none; cursor: help;
  border: 1px solid var(--border-2); background: var(--surface-2); color: var(--text-3);
  font: 700 11px/1 var(--ui); vertical-align: middle; outline: none; }
.tp-help:hover, .tp-help:focus-visible { color: var(--text); border-color: var(--sb-focus, var(--border)); }
.tp-help:focus-visible { box-shadow: 0 0 0 3px var(--sb-focus, rgba(31,111,199,.4)); }
.tp-help__pop {
  /* Por encima del overlay de diálogos (.tp-dlg-overlay = --z-float + 10): el "?" vive
     sobre todo dentro de modales y su popover no puede quedar debajo del cromado.
     Dentro de un diálogo, ui_dialog.js además lo reposiciona en fixed (anti-clipping). */
  position: absolute; top: calc(100% + 8px); left: 0; z-index: calc(var(--z-float) + 40);
  width: max-content; max-width: min(320px, 74vw);
  background: var(--surface); color: var(--text-2); text-align: left;
  border: 1px solid var(--border-2); border-radius: var(--r-md, 10px);
  padding: 9px 11px; font: 500 12px/1.5 var(--ui);
  box-shadow: var(--shadow-md); opacity: 0; pointer-events: none;
  transform: translateY(-3px) scale(.98); transform-origin: top left;
  transition: opacity .14s var(--ease), transform .14s var(--ease); }
.tp-help__pop b { color: var(--text); font-weight: 700; }
/* Triggers fuera de diálogos: los muestra el CSS con :hover/:focus (posición absolute).
   Los que están dentro de un diálogo llevan .tp-help--managed y los controla ui_dialog.js
   por JS (clase .is-open + position:fixed), evitando el salto de layout del modal. */
.tp-help:not(.tp-help--managed):hover .tp-help__pop,
.tp-help:not(.tp-help--managed):focus-visible .tp-help__pop,
.tp-help:not(.tp-help--managed):focus-within .tp-help__pop,
.tp-help__pop.is-open {
  opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
/* Si el icono está cerca del borde derecho, anclar el popover a la derecha */
.tp-help--right .tp-help__pop { left: auto; right: 0; transform-origin: top right; }

/* ============================ HEADER ============================ */
.hd {
  /* La cabecera absorbe el notch/status bar: crece con la safe-area superior */
  height: calc(66px + var(--safe-top)); flex: none; display: flex; align-items: center; gap: 18px;
  padding: var(--safe-top) calc(22px + var(--safe-right)) 0 calc(22px + var(--safe-left));
  background: var(--surface); border-bottom: 1px solid var(--border);
}
/* Botón hamburguesa: sólo visible en móvil (ver bloque responsive) */
.hd__menu {
  display: none; flex: none; width: 38px; height: 38px; border-radius: 10px;
  border: 1px solid var(--border-2); background: var(--surface-2); color: var(--text-2);
  place-items: center; cursor: pointer; transition: background .2s;
}
.hd__menu:hover { background: var(--surface-3); }

/* Capa oscura del cajón del sidebar en móvil (oculta por defecto) */
.sb-backdrop {
  position: fixed; inset: 0; z-index: 55; background: rgba(8,16,32,.5);
  opacity: 0; pointer-events: none; transition: opacity .3s var(--ease);
  -webkit-backdrop-filter: blur(1px); backdrop-filter: blur(1px);
}
.sb-backdrop.is-open { opacity: 1; pointer-events: auto; }

.hd__id { display: flex; align-items: center; gap: 11px; flex: none; }
.hd__dot { width: 11px; height: 11px; border-radius: 50%; background: var(--blue-bright); box-shadow: 0 0 0 4px rgba(61,139,224,.18); flex: none; }
.hd__dot.is-off { background: var(--danger); box-shadow: 0 0 0 4px var(--danger-bg-hov); }
.hd__titles { display: flex; flex-direction: column; gap: 2px; line-height: 1.15; white-space: nowrap; }
.hd__titles strong { font: 800 16px/1.1 var(--ui); color: var(--text); letter-spacing: -.2px; white-space: nowrap; }
.hd__titles em { font: 600 11.5px/1.1 var(--ui); font-style: normal; color: var(--text-3); white-space: nowrap; }

/* ── Estado unificado (zona izquierda): punto de conexión; hover/focus despliega
      el panel con "Conectado" + contadores de documentos y vectores. Los IDs
      #stat-docs/#stat-vectors son nodos VIVOS que updateStatus() refresca. ── */
.hd__status {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px; cursor: default; flex: none;
}
.hd__status:hover, .hd__status:focus-visible { background: var(--surface-2); }
.hd__status.stat--ok .hd__dot { background: var(--ok); box-shadow: 0 0 0 4px var(--ok-bg); }
.hd__status.stat--off .hd__dot { background: var(--danger); box-shadow: 0 0 0 4px var(--danger-bg-hov); }
.hd__status-panel {
  position: absolute; top: calc(100% + 10px); left: -6px; z-index: 70;
  display: none; flex-direction: column; gap: 8px; min-width: 195px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 12px;
  box-shadow: var(--shadow-lg); padding: 12px 14px;
  font: 600 12.5px/1 var(--ui); color: var(--text-2); white-space: nowrap;
}
/* Puente invisible sobre el hueco entre el punto y el panel: el hover no se corta. */
.hd__status-panel::before { content: ""; position: absolute; top: -12px; left: 0; right: 0; height: 12px; }
.hd__status:hover .hd__status-panel,
.hd__status:focus-visible .hd__status-panel,
.hd__status:focus-within .hd__status-panel { display: flex; }
.hd__status-panel > b { font: 800 13px/1 var(--ui); }
.hd__status.stat--ok .hd__status-panel > b { color: var(--ok); }
.hd__status.stat--off .hd__status-panel > b { color: var(--danger); }
.hd__status-row { display: flex; align-items: center; gap: 7px; }
.hd__status-row b { color: var(--text); font-weight: 800; margin-left: auto; }
.hd__status-row svg { color: var(--text-3); flex: none; }

/* ── Navegación core (zona central): pestañas Troubleshooting / Documentos ── */
.hd__nav { flex: 1; display: flex; justify-content: center; gap: 10px; min-width: 0; }

.hd__actions { display: flex; align-items: center; gap: 12px; }

/* Botones del header HOMOGENEIZADOS: pestañas centrales, disparador del menú de
   gestión y Detener comparten box-model; el tinte es semántico vía tokens. */
.hd__tab, .hd-menu__btn, .hd__stop {
  display: inline-flex; align-items: center; gap: 8px; padding: 9px 15px; border-radius: 999px; cursor: pointer;
  font: 600 12.5px/1 var(--ui); border: 1px solid transparent; transition: background .2s, border-color .2s, color .2s;
}
.hd__tab svg, .hd-menu__btn svg, .hd__stop svg { flex: none; }
.hd__tab:disabled, .hd-menu__btn:disabled { cursor: default; opacity: .5; }

/* default → pestañas de navegación */
.hd__tab { color: var(--btn-tx); background: var(--btn-bg); border-color: var(--btn-bd); }
.hd__tab:hover:not(:disabled) { background: var(--btn-bg-hov); }

/* ── Dropdown "Gestión de índice" (zona derecha, solo developer) ── */
.hd-menu { position: relative; }
/* El gestor de opciones (kebab) sólo existe en móvil; en escritorio los botones van inline. */
.hd-menu--more { display: none; }
.hd-menu__btn { color: var(--btn-tx); background: var(--btn-bg); border-color: var(--btn-bd); }
.hd-menu__btn:hover { background: var(--btn-bg-hov); }
.hd-menu.is-open .hd-menu__btn { background: var(--btn-bg-hov); border-color: var(--border-2); }
.hd-menu__caret { transition: transform .2s var(--ease); }
.hd-menu.is-open .hd-menu__caret { transform: rotate(180deg); }
.hd-menu__panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 70;
  display: none; min-width: 236px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: 12px;
  box-shadow: var(--shadow-lg);
}
.hd-menu.is-open .hd-menu__panel { display: block; }
.hd-menu__item {
  display: flex; width: 100%; align-items: center; gap: 9px; padding: 10px 11px; border-radius: 8px;
  font: 600 13px/1.2 var(--ui); color: var(--text-2); background: none; border: none;
  cursor: pointer; text-align: left; transition: background .15s, color .15s;
}
.hd-menu__item:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.hd-menu__item:disabled { cursor: default; opacity: .55; }
.hd-menu__item svg { flex: none; }
/* Estado "ocupado" (Sincronizando…/Backfill…): mismo tinte azul que antes. */
.hd-menu__item.is-on { color: var(--link); background: rgba(31,111,199,.1); }
[data-theme="dark"] .hd-menu__item.is-on { color: var(--blue-bright); background: rgba(61,139,224,.14); }
/* Tintes semánticos: Reindexar (warn) y Vaciar índice (danger, destructivo). */
.hd-menu__item--warn { color: var(--btn-warn-tx); }
.hd-menu__item--warn:hover:not(:disabled) { background: var(--btn-warn-bg); color: var(--btn-warn-tx); }
.hd-menu__item--danger { color: var(--danger); }
.hd-menu__item--danger:hover:not(:disabled) { background: var(--danger-bg); color: var(--danger); }
.hd-menu__sep { height: 1px; background: var(--border); margin: 6px 4px; }

/* danger → Detener (con estados de parada suave/dura) */
.hd__stop { color: var(--danger); background: var(--danger-bg); border-color: var(--danger-bd); transition: background .2s, transform .15s; }
.hd__stop:hover { background: var(--danger-bg-hov); transform: translateY(-1px); }
.hd__stop.is-stopping {
  color: var(--text-3); background: var(--surface-2); border-color: var(--border);
  cursor: default; pointer-events: none;
}
/* Segunda etapa: hard stop ARMADO tras el primer clic (corte inmediato al volver a pulsar). */
.hd__stop.is-hard {
  color: #fff; background: var(--danger-solid); border-color: var(--danger-solid);
  animation: hardpulse 1.1s ease-in-out infinite;
}
.hd__stop.is-hard:hover { background: var(--danger-solid-hov); transform: translateY(-1px); }
@keyframes hardpulse { 0%,100% { box-shadow: 0 0 0 0 rgba(192,57,43,.45); } 50% { box-shadow: 0 0 0 5px rgba(192,57,43,0); } }

.hd__theme { border: none; background: none; cursor: pointer; padding: 0; }
.hd__theme-track {
  width: 52px; height: 28px; border-radius: 999px; background: var(--toggle-track); border: 1px solid var(--border-2);
  display: flex; align-items: center; padding: 3px; transition: background .3s, border-color .3s;
}
.hd__theme-knob {
  width: 22px; height: 22px; border-radius: 50%; background: var(--toggle-knob); color: var(--toggle-icon);
  display: grid; place-items: center; box-shadow: 0 2px 5px rgba(0,0,0,.25);
  transform: translateX(0); transition: transform .32s var(--ease), color .3s, background .3s;
}
[data-theme="dark"] .hd__theme-knob { transform: translateX(24px); }

/* ===== Botón de tema FLOTANTE global (theme.js) — visible en TODA sección ===== */
.tp-theme-fab {
  position: fixed;
  right: calc(16px + var(--safe-right));
  bottom: calc(16px + var(--safe-bottom));
  z-index: var(--z-float, 3000);
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: var(--surface); color: var(--toggle-icon);
  border: 1px solid var(--border-2); box-shadow: var(--shadow-md);
  transition: background .25s, color .3s, border-color .3s, transform .15s var(--ease);
}
.tp-theme-fab:hover { background: var(--surface-2); transform: translateY(-1px); }
.tp-theme-fab:active { transform: translateY(0); }
.tp-theme-fab:focus-visible { outline: 2px solid var(--sb-focus); outline-offset: 2px; }
/* Cada sección con header propio ya trae su toggle de tema (chat #btn-theme,
   overlay TS #ts2-theme, y el cromado común de admin/aprendizaje/próximamente) →
   se oculta el FAB en esas vistas para no duplicar el botón de tema. En el chat,
   además, taparía el botón de enviar del composer. */
body.tp-agent .tp-theme-fab,
body[data-tp-view="troubleshooting"] .tp-theme-fab,
body[data-tp-view="admin"] .tp-theme-fab,
body[data-tp-view="learning"] .tp-theme-fab,
body[data-tp-view="soon"] .tp-theme-fab { display: none; }

/* ===== Cesta de cotización: FAB flotante (quote_cart.js) =====
   Apilado 12px SOBRE el FAB de tema (44px de alto) con las mismas safe-areas.
   Lo enciende el JS con .is-on (capacidad + vista partes o piezas pendientes);
   se oculta en las mismas vistas que el FAB de tema para no tapar composers. */
.tp-quote-fab {
  position: fixed;
  right: calc(16px + var(--safe-right));
  bottom: calc(16px + 44px + 12px + var(--safe-bottom));
  z-index: var(--z-float, 3000);
  width: 44px; height: 44px; border-radius: 50%;
  display: none; place-items: center; cursor: pointer;
  background: var(--navy); color: #fff;
  border: 1px solid var(--navy-700, var(--navy)); box-shadow: var(--shadow-md);
  transition: background .25s, transform .15s var(--ease);
}
.tp-quote-fab.is-on { display: grid; }
.tp-quote-fab:hover { background: var(--navy-700, var(--navy)); transform: translateY(-1px); }
.tp-quote-fab:active { transform: translateY(0); }
.tp-quote-fab:focus-visible { outline: 2px solid var(--sb-focus); outline-offset: 2px; }
body.tp-agent .tp-quote-fab,
body[data-tp-view="troubleshooting"] .tp-quote-fab,
body[data-tp-view="admin"] .tp-quote-fab,
body[data-tp-view="learning"] .tp-quote-fab,
body[data-tp-view="soon"] .tp-quote-fab { display: none; }
/* Excepción: en el chat (agente) el FAB SÍ aparece si hay ítems en la cesta, para poder
   abrirla tras agregar una pieza desde la ficha flotante. (Mayor especificidad que el hide.) */
body.tp-agent .tp-quote-fab.is-on { display: grid; }
.tp-quote-fab__badge {
  position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px;
  border-radius: 999px; padding: 0 4px; display: grid; place-items: center;
  background: var(--orange); color: #fff; font: 700 11px/1 var(--ui);
  border: 2px solid var(--bg); box-sizing: content-box;
}
@keyframes tpq-pulse { 0% { transform: scale(1); } 35% { transform: scale(1.14); } 100% { transform: scale(1); } }
.tp-quote-fab.is-pulse { animation: tpq-pulse .35s var(--ease); }

/* ===== Cesta de cotización: modal (.tp-dlg--quote) ===== */
.tp-dlg--quote { max-width: min(560px, calc(100vw - 24px)); }
.tpq { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.tpq-head { display: flex; align-items: center; gap: 8px; }
.tpq-head__lead { font: 600 12.5px/1.4 var(--ui); color: var(--text-2); flex: 1; }
.tpq-notice {
  padding: 9px 12px; border-radius: var(--r-sm);
  background: var(--warn-bg); color: var(--warn);
  border: 1px solid var(--warn-bd);
  font: 500 12.5px/1.5 var(--ui);
}
.tpq-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: min(44vh, 380px); overflow: auto; min-height: 0;
}
.tpq-empty { padding: 18px 10px; text-align: center; color: var(--text-3); font: 500 13px/1.5 var(--ui); }
.tpq-item {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-2);
}
.tpq-item__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tpq-item__pn { font: 600 12.5px/1.3 var(--mono); color: var(--text); word-break: break-all; }
.tpq-item__desc {
  font: 500 12px/1.35 var(--ui); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tpq-item__unit { font: 500 11.5px/1 var(--ui); color: var(--text-3); margin-left: 4px; }
.tpq-step { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.tpq-step__btn {
  width: 26px; height: 26px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text-2);
  font: 700 14px/1 var(--ui); display: grid; place-items: center;
}
.tpq-step__btn:hover { background: var(--surface-3); color: var(--text); }
.tpq-step__val {
  width: 48px; height: 26px; text-align: center; border-radius: var(--r-sm);
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text);
  font: 600 12.5px/1 var(--ui); -moz-appearance: textfield;
}
.tpq-step__val::-webkit-outer-spin-button, .tpq-step__val::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tpq-item__rm {
  flex: none; width: 26px; height: 26px; border-radius: 50%; cursor: pointer;
  border: 1px solid transparent; background: transparent; color: var(--text-3);
  font: 400 16px/1 var(--ui); display: grid; place-items: center;
}
.tpq-item__rm:hover { color: var(--danger); border-color: var(--danger-bd); background: var(--danger-bg); }
.tpq-notes { resize: vertical; }
.tpq-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  padding-top: 4px; border-top: 1px solid var(--hairline, var(--border));
}
.tpq-foot__status { flex: 1 1 auto; font: 600 12.5px/1.4 var(--ui); color: var(--text-2); }
/* «Vaciar cesta»: acción destructiva discreta, alineada a la izquierda del pie. */
.tpq-clear { color: #d6453d; border-color: transparent; background: transparent; }
.tpq-clear:hover:not(:disabled) { background: rgba(214, 69, 61, .1); }
.tpq-clear:disabled { opacity: .45; cursor: default; }

/* Agrupación por conglomerado de máquina (familia · modelo · versión · serial). */
.tpq-group { display: flex; flex-direction: column; gap: 6px; }
.tpq-group + .tpq-group { margin-top: 8px; }
.tpq-group__h {
  font: 700 11px/1.3 var(--ui); text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-2); padding: 2px 2px 4px; border-bottom: 1px solid var(--hairline, var(--border));
}
/* Chip de contexto por línea (kit / posición en plano / serial de la pieza). */
.tpq-item__ctx { font: 600 10.5px/1.3 var(--ui); color: var(--primary);
  background: color-mix(in srgb, var(--primary) 12%, transparent); border-radius: 999px;
  padding: 1px 7px; margin-top: 2px; align-self: flex-start; }
/* Serial de la MÁQUINA, destacado en el encabezado de grupo. */
.tpq-serial { display: inline-block; font: 700 10px/1.3 var(--mono, monospace);
  text-transform: none; letter-spacing: 0; color: var(--primary-tx, #fff);
  background: var(--primary); border-radius: 4px; padding: 1px 7px; margin-left: 6px;
  vertical-align: middle; }

/* Diálogo «¿Para qué máquina…?»: atribución de máquina al agregar a la cesta. */
.tpq-pick__sub { margin: 0 0 10px; font: 400 13px/1.45 var(--ui); color: var(--text-2); }
.tpq-pick__list { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow: auto; }
.tpq-mach { display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  width: 100%; padding: 9px 12px; text-align: left; cursor: pointer;
  background: var(--surface-2, var(--surface)); color: var(--text);
  border: 1px solid var(--hairline, var(--border)); border-radius: 8px; }
.tpq-mach:hover { border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 7%, var(--surface)); }
.tpq-mach__label { font: 600 13px/1.35 var(--ui); }
.tpq-mach__alias { font: 400 12px/1.35 var(--ui); color: var(--text-2); }
.tpq-mach__tags { display: flex; align-items: center; gap: 6px; }
.tpq-mach__tags .tpq-serial { margin-left: 0; }
.tpq-mach__warn { font: 600 10.5px/1.3 var(--ui); color: var(--warn, #b45309);
  background: color-mix(in srgb, var(--warn, #b45309) 12%, transparent);
  border-radius: 999px; padding: 1px 7px; }

/* Línea de KIT: colapsable dentro de la cesta. */
.tpq-item--kit { display: block; padding: 0; overflow: hidden; }
.tpqk { width: 100%; }
.tpqk__sum { display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: pointer;
  list-style: none; }
.tpqk__sum::-webkit-details-marker { display: none; }
.tpqk__badge { flex: none; font: 800 9.5px/1.4 var(--ui); letter-spacing: .05em; color: var(--primary-tx, #fff);
  background: var(--primary); border-radius: 4px; padding: 2px 6px; }
/* Distintivo del PLAN de mantenimiento: la misma línea colapsable que un kit, pero es un
   servicio calculado hasta un horizonte de horas, no un kit del catálogo. Se separa por color
   para que en la cesta no se confundan dos cosas que se cotizan distinto. */
.tpqk__badge--plan { background: var(--accent, #2f6df6); color: #fff; }
.tpqk__name { font: 700 12.5px/1.3 var(--ui); color: var(--text); flex: 1; min-width: 0; }
.tpqk__pn { font: 600 11px/1.2 var(--mono); color: var(--text-3); }
.tpqk__meta { font: 600 11.5px/1.3 var(--ui); color: var(--text-3); white-space: nowrap; }
.tpqk__body { padding: 4px 10px 10px; border-top: 1px solid var(--hairline, var(--border));
  display: flex; flex-direction: column; gap: 8px; }
.tpqk__ctl { display: flex; align-items: center; gap: 10px; font: 600 12px/1.3 var(--ui); color: var(--text-2); }
.tpqk__tbl { width: 100%; border-collapse: collapse; font: 500 12px/1.4 var(--ui); }
.tpqk__tbl td { padding: 4px 6px; border-bottom: 1px solid var(--hairline); vertical-align: top; }
.tpqk__tbl .tpqk-pn { font-family: var(--mono); color: var(--text); white-space: nowrap; }
.tpqk__tbl .tpqk-qty { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text-2); }

/* Filas de encabezado de grupo en la bandeja del receptor. */
.tpqi-table .tpqi-grouprow td { background: var(--surface-2); font: 700 11px/1.3 var(--ui);
  text-transform: uppercase; letter-spacing: .03em; color: var(--text-2); }

/* Móvil: objetivos táctiles ≥ --tap y filas a dos líneas si hace falta */
@media (max-width: 640px) {
  .tpq-item { flex-wrap: wrap; }
  .tpq-item__info { flex-basis: 100%; }
  .tpq-step__btn { width: var(--tap, 44px); height: 38px; }
  .tpq-step__val { height: 38px; width: 56px; }
  .tpq-item__rm { width: 38px; height: 38px; }
}

/* ===== Campana del hub: ventana unificada (.tp-dlg--notify) =====
   Una sección por origen (cotizaciones, garantías) con su cabecera. Toma prestado el idioma visual
   de la bandeja de cotizaciones —misma fila, mismo hover— a propósito: son la misma pregunta hecha
   sobre dos módulos, y dos aspectos distintos las harían parecer dos pantallas. */
.tp-dlg--notify { max-width: min(680px, calc(100vw - 24px)); }
.tpn { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.tpn-body { min-height: 120px; max-height: min(60vh, 520px); overflow: auto; }
.tpn-group + .tpn-group { margin-top: 14px; }
.tpn-group__h {
  margin: 0 0 6px; font: 700 11px/1.4 var(--ui); text-transform: uppercase; letter-spacing: .5px;
  color: var(--text-3);
}
.tpn-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 12px; margin-bottom: 6px; border: 1px solid var(--border);
  border-radius: var(--r-sm); background: var(--surface-2); cursor: pointer;
  transition: background .12s, border-color .12s;
}
.tpn-row:hover { background: var(--surface-3); border-color: var(--border-2); }
.tpn-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tpn-row__title { font: 700 13px/1.35 var(--ui); color: var(--text); }
.tpn-row__meta {
  font: 500 12px/1.35 var(--ui); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* El asomo del último mensaje. A una línea: la ventana es para decidir a cuál entrar, no para
   leerlos aquí. */
.tpn-row__prev {
  font: 400 12px/1.35 var(--ui); color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tpn-row__n {
  flex: none; min-width: 20px; padding: 1px 7px; border-radius: 999px;
  background: var(--orange); color: #fff; font: 700 11px/1.6 var(--ui); text-align: center;
}
.tpn-row__d { flex: none; font: 500 11px/1.3 var(--ui); color: var(--text-3); white-space: nowrap; }

/* El interruptor de los avisos al teléfono, arriba del todo y separado por una línea: no es una
   notificación más, es el ajuste que decide si las demás llegan al bolsillo. Cuando está encendido
   se tiñe con los tokens `--ok` (los mismos de `.tpqi-status.is-done`) — es el único estado en el
   que la app puede prometer algo con la pantalla apagada, y conviene que se vea de un vistazo. */
.tpn-push {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-2);
}
.tpn-push.is-on { background: var(--ok-bg); border-color: var(--ok-bd); }
.tpn-push.is-on .tpn-push__t { color: var(--ok); }
.tpn-push[hidden] { display: none; }
.tpn-push__txt { flex: 1; min-width: 160px; display: flex; flex-direction: column; gap: 2px; }
.tpn-push__t { font: 700 13px/1.35 var(--ui); color: var(--text); }
.tpn-push__m { font: 400 12px/1.4 var(--ui); color: var(--text-2); }
.tpn-push__acts { flex: none; display: flex; align-items: center; gap: 6px; }
.tpn-push__btn, .tpn-push__test {
  flex: none; padding: 6px 12px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--border-2); background: var(--surface);
  font: 600 12px/1.4 var(--ui); color: var(--text);
  transition: background .12s, border-color .12s;
}
.tpn-push__btn:hover, .tpn-push__test:hover { background: var(--surface-3); border-color: var(--text-3); }
.tpn-push__btn:disabled, .tpn-push__test:disabled { opacity: .55; cursor: default; }
.tpn-push__btn[hidden], .tpn-push__test[hidden] { display: none; }

/* ===== Cotizaciones: campana del hub + bandeja (.tp-dlg--qinbox) ===== */
.hub-bell { position: relative; }
.hub-bell__badge {
  position: absolute; top: 2px; right: 2px; min-width: 16px; height: 16px;
  border-radius: 999px; padding: 0 4px; display: grid; place-items: center;
  background: var(--orange); color: #fff; font: 700 10px/1 var(--ui);
  border: 2px solid var(--bg); box-sizing: content-box; pointer-events: none;
}
/* `display: grid` gana al `[hidden] { display: none }` del navegador, así que sin esto el badge
   seguía pintándose con un «0» encima de la campana cuando no había nada sin leer. Venía de antes,
   pero ahora la campana la ve todo el mundo y el cero estaría en todas las pantallas. */
.hub-bell__badge[hidden] { display: none; }
.tp-dlg--qinbox { max-width: min(640px, calc(100vw - 24px)); }
.tpqi { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.tpqi-head { display: flex; align-items: center; gap: 8px; }
.tpqi-head__lead { flex: 1; }
.tpqi-body { min-height: 120px; }
.tpqi-list { display: flex; flex-direction: column; gap: 6px; max-height: min(52vh, 460px); overflow: auto; }
.tpqi-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-2); cursor: pointer; transition: background .12s, border-color .12s;
}
.tpqi-row:hover { background: var(--surface-3); border-color: var(--border-2); }
.tpqi-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tpqi-row__title { font: 600 13px/1.35 var(--ui); color: var(--text); }
.tpqi-row.is-unread .tpqi-row__title { font-weight: 800; }
.tpqi-row.is-unread::before {
  content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--orange);
}
.tpqi-row__meta { font: 500 12px/1.35 var(--ui); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpqi-status {
  flex: none; padding: 3px 9px; border-radius: 999px; font: 700 11px/1.2 var(--ui);
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text-2);
}
.tpqi-status.is-new  { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn); }
.tpqi-status.is-done { background: var(--ok-bg); border-color: var(--ok-bd); color: var(--ok); }
.tpqi-detail { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.tpqi-detail__bar { display: flex; align-items: center; gap: 10px; }
.tpqi-detail__title { flex: 1; font: 700 13.5px/1.35 var(--ui); color: var(--text); min-width: 0; }
.tpqi-detail__meta { font: 500 12.5px/1.5 var(--ui); color: var(--text-2); }
.tpqi-detail__meta a { color: var(--link); }
.tpqi-detail__items { max-height: min(42vh, 360px); }
.tpqi-table { width: 100%; border-collapse: collapse; font: 500 12.5px/1.4 var(--ui); }
.tpqi-table th {
  position: sticky; top: 0; text-align: left; padding: 7px 10px; font: 700 11.5px/1.2 var(--ui);
  color: var(--text-3); background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.tpqi-table td { padding: 7px 10px; border-bottom: 1px solid var(--hairline); color: var(--text); vertical-align: top; }
.tpqi-pn { font: 600 12px/1.3 var(--mono); word-break: break-all; }
.tpqi-num, .tpqi-table th.tpqi-num, .tpqi-table td.tpqi-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tpqi-detail__notes {
  padding: 9px 12px; border-radius: var(--r-sm); background: var(--surface-2);
  border: 1px solid var(--border); font: 500 12.5px/1.5 var(--ui); color: var(--text-2);
}

/* ============================ SYNC BAR ============================ */
.syncbar {
  flex: none; display: none; align-items: center; gap: 12px; padding: 9px 22px;
  background: var(--surface-2); border-bottom: 1px solid var(--border); font: 600 12px/1 var(--ui); color: var(--text-2);
  flex-wrap: wrap; row-gap: 7px;
}
.syncbar.is-active { display: flex; }
/* Sub-progreso del archivo actual (páginas → embeddings → Pinecone) */
.syncbar__sub { display: inline-flex; align-items: center; gap: 8px; }
.syncbar__stage { color: var(--text-2); font-weight: 700; white-space: nowrap; }
[data-theme="dark"] .syncbar__stage { color: var(--orange); }
.syncbar__subtrack { flex: none; width: 130px; height: 5px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.syncbar__subfill {
  display: block; height: 100%; width: 0%; border-radius: 999px;
  background: linear-gradient(90deg, var(--orange) 0%, var(--orange-soft) 100%);
  transition: width .35s var(--ease);
}
.syncbar__tag { display: inline-flex; align-items: center; gap: 6px; color: var(--link); font-weight: 700; white-space: nowrap; }
[data-theme="dark"] .syncbar__tag { color: var(--blue-bright); }
.syncbar__track { flex: none; width: 220px; height: 7px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.syncbar__fill {
  height: 100%; border-radius: 999px; position: relative; overflow: hidden; width: 0%;
  background: linear-gradient(90deg, var(--blue) 0%, var(--orange) 130%);
  transition: width .6s var(--ease);
}
.syncbar__stripes {
  position: absolute; inset: 0;
  background-image: linear-gradient(115deg, rgba(255,255,255,.35) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.35) 50%, rgba(255,255,255,.35) 75%, transparent 75%);
  background-size: 20px 20px; animation: stripe .7s linear infinite;
}
.syncbar__pct { font-weight: 800; color: var(--text); }
.syncbar__meta { color: var(--text-3); }
.syncbar__file {
  display: inline-flex; align-items: center; gap: 6px; color: var(--text-3); margin-left: auto;
  max-width: 360px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ============================ THREAD ============================ */
.scroll { flex: 1; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.thread {
  max-width: 1100px; margin: 0 auto; display: flex; flex-direction: column; gap: 24px;
  /* max() protege el contenido del notch lateral en apaisado */
  padding: 30px max(34px, var(--safe-right)) 44px max(34px, var(--safe-left));
  transition: max-width .4s var(--ease);
}
.thread:has(.row__main.is-reader) { max-width: min(1720px, calc(100vw - 150px)); }

.row { display: flex; gap: 13px; animation: rowin .35s var(--ease) both; }
.row--user { justify-content: flex-end; }
.row--ai { align-items: flex-start; }
.row__main { min-width: 0; display: flex; flex-direction: column; gap: 14px; max-width: 770px; }
.row__main.is-reader { max-width: 100%; flex: 1; }
/* TroubleShooting: contenedor horizontal propio, a pantalla casi completa e
   INDEPENDIENTE del lector. El bloque ocupa el ancho visible disponible con el
   mismo valor esté el lector abierto o cerrado, así abrir/cerrar "Abrir en lector"
   no cambia su ancho. Estas reglas vienen DESPUÉS de `.thread:has(.row__main.is-reader)`
   y `.row__main.is-reader`, así que ganan por orden de fuente en ambos estados.
   La vista ampliada de los pasos la decide el viewport (>820px), no el ancho del
   contenedor — ver `.ts-inchat` en troubleshooting.css. En móvil (≤820px) el calc()
   deja el bloque a ancho de pantalla y los pasos bajan a 1 columna. Las burbujas de
   texto siguen acotadas (`.bubble--ai` max-width 770px), no se estiran. */
.thread:has(.ts-inchat) { max-width: min(2040px, calc(100vw - 48px)); }
.row__main:has(.ts-inchat) { max-width: 100%; flex: 1; }

.ava { flex: none; width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font: 800 12px/1 var(--ui); }
.ava--ai { overflow: hidden; box-shadow: 0 0 0 1px var(--border-2), var(--shadow-sm); background: var(--navy); }
.ava--ai img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ava--user { background: var(--surface-3); color: var(--text-2); border: 1px solid var(--border-2); }

.row__meta { display: flex; align-items: center; gap: 10px; padding-left: 2px; }
.row__name { font: 700 12.5px/1 var(--ui); color: var(--text-2); }
.row__flag {
  display: inline-flex; align-items: center; gap: 5px; font: 700 10.5px/1 var(--ui); letter-spacing: .3px;
  color: var(--orange); background: rgba(237,125,34,.12); border: 1px solid rgba(237,125,34,.28);
  padding: 4px 8px; border-radius: 999px; text-transform: uppercase;
}
.row__readbtn {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font: 700 11.5px/1 var(--ui); color: var(--link); background: var(--cite-bg);
  border: 1px solid rgba(31,111,199,.25); padding: 6px 11px; border-radius: 999px; transition: background .18s, transform .15s;
}
[data-theme="dark"] .row__readbtn { color: var(--blue-bright); border-color: rgba(61,139,224,.4); }
.row__readbtn:hover { background: var(--cite-hover); transform: translateY(-1px); }

/* burbujas */
.bubble { padding: 15px 19px 16px; border-radius: 16px; font-size: 15px; line-height: 1.66; }
.bubble--ai {
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  border-top-left-radius: 5px; box-shadow: var(--shadow-sm); max-width: 770px;
}
.bubble--user {
  background: var(--user-grad); color: var(--user-tx); border-top-right-radius: 5px;
  max-width: 560px; box-shadow: 0 6px 16px rgba(20,58,94,.28); font-weight: 500;
  white-space: pre-wrap; word-wrap: break-word;
}
.bubble--typing { display: inline-flex; gap: 5px; padding: 16px 18px; width: max-content; }
.bubble--typing span { width: 8px; height: 8px; border-radius: 50%; background: var(--text-3); animation: blink 1.2s infinite; }
.bubble--typing span:nth-child(2) { animation-delay: .18s; }
.bubble--typing span:nth-child(3) { animation-delay: .36s; }

/* ---------- indicador de etapas progresivas (barra horizontal) ---------- */
.bubble--progress { padding: 15px 18px 14px; width: min(340px, 78vw); max-width: 100%; }

/* fila de píldoras: una por etapa, se rellenan de izquierda a derecha */
.progress-bar { display: flex; gap: 6px; }
.pseg {
  flex: 1; height: 6px; border-radius: 999px;
  background: var(--border-2);
  transition: background-color .35s var(--ease), box-shadow .35s var(--ease);
}
.pseg.is-pending { background: var(--border-2); }
.pseg.is-done    { background: var(--blue); }
/* segmento activo: relleno azul con un brillo (shimmer) que recorre la píldora */
.pseg.is-active {
  background-image: linear-gradient(90deg, var(--navy) 0%, var(--blue-bright) 50%, var(--navy) 100%);
  background-size: 200% 100%;
  box-shadow: 0 0 0 1px rgba(61,139,224,.18);
  animation: pseg-shimmer 1.1s linear infinite;
}
@keyframes pseg-shimmer { to { background-position: -200% 0; } }

/* una sola línea de texto con la fase actual; recorta el desbordamiento para el swap */
.progress-phase {
  position: relative; overflow: hidden;
  height: 1.3em; margin-top: 11px;
}
.pphase-text {
  position: absolute; left: 0; top: 0; white-space: nowrap;
  color: var(--blue); font: 600 14px/1.3 var(--ui);
  transform: translateY(0); opacity: 1;
  transition: transform .42s var(--ease), opacity .42s var(--ease);
}
/* entrante: arranca abajo y sube a su sitio al quitar la clase */
.pphase-text.is-entering { transform: translateY(110%); opacity: 0; }
/* saliente: sube y se desvanece */
.pphase-text.is-leaving  { transform: translateY(-110%); opacity: 0; }

@keyframes spin { to { transform: rotate(360deg); } }

/* nota sutil de baja confianza, DEBAJO de la respuesta */
.lowconf-note {
  display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 2px;
  padding: 9px 13px; border-radius: 10px; border-left: 3px solid var(--orange);
  background: rgba(237,125,34,.07); color: var(--text-3);
  font: 500 12.5px/1.45 var(--ui);
}
.lowconf-note svg { flex: none; margin-top: 1px; color: var(--orange); }

/* mensaje de sistema (notificación) */
.bubble--note {
  border-left: 4px solid var(--orange); background: rgba(237,125,34,.07);
}

/* sugerencias de la bienvenida (rellenan el campo de consulta al pulsarlas) */
.welcome-suggest { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.ws-chip {
  padding: 8px 13px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-2); background: var(--surface-2); color: var(--text-2);
  font: 600 12.5px/1 var(--ui); transition: border-color .15s, color .15s, background .15s;
}
.ws-chip:hover { border-color: var(--blue); color: var(--link); background: var(--cite-bg); }
[data-theme="dark"] .ws-chip:hover { color: var(--blue-bright); }

/* ============================ BLOQUES / MARKDOWN ============================ */
.bubble p, .reader__pages p { margin: 0 0 12px; }
.bubble p:last-child, .reader__pages p:last-child { margin-bottom: 0; }
.bubble strong { font-weight: 700; color: var(--heading); }
.bubble em { font-style: italic; color: var(--text-2); }

.bubble h3, .bubble h4, .bubble h5,
.reader__pages h3, .reader__pages h4, .reader__pages h5 {
  margin: 20px 0 10px; font: 800 14.5px/1.3 var(--ui); color: var(--heading); letter-spacing: -.1px;
  display: flex; align-items: center; gap: 9px;
}
.bubble h3::before, .bubble h4::before, .bubble h5::before,
.reader__pages h3::before, .reader__pages h4::before, .reader__pages h5::before {
  content: ""; width: 5px; height: 16px; border-radius: 3px; background: var(--orange); flex: none;
}
.bubble h3:first-child, .bubble h4:first-child, .bubble h5:first-child, .bubble p:first-child { margin-top: 0; }

.bubble ul, .bubble ol, .reader__pages ul, .reader__pages ol {
  margin: 0 0 14px; padding-left: 4px; display: flex; flex-direction: column; gap: 9px; list-style: none; counter-reset: ol;
}
.bubble ul li, .bubble ol li, .reader__pages ul li, .reader__pages ol li { position: relative; padding-left: 26px; line-height: 1.6; }
.bubble ul li::before, .reader__pages ul li::before {
  content: ""; position: absolute; left: 7px; top: 9px; width: 7px; height: 7px; border-radius: 50%; background: var(--blue);
}
.bubble ol li, .reader__pages ol li { counter-increment: ol; }
.bubble ol li::before, .reader__pages ol li::before {
  content: counter(ol); position: absolute; left: 0; top: 1px; width: 19px; height: 19px; border-radius: 6px;
  background: var(--navy); color: #fff; font: 700 11px/19px var(--ui); text-align: center;
}
[data-theme="dark"] .bubble ol li::before, [data-theme="dark"] .reader__pages ol li::before { background: var(--blue); }

.bubble blockquote, .reader__pages blockquote {
  margin: 16px 0; padding: 11px 15px; border-left: 4px solid var(--orange);
  background: rgba(237,125,34,.07); color: var(--text-2); border-radius: 0 var(--r-md) var(--r-md) 0;
}

.bubble code, .reader__pages code {
  font: 600 .86em/1.3 var(--mono); background: var(--code-bg); color: var(--code-tx);
  border: 1px solid var(--code-bd); padding: 1px 7px; border-radius: 6px; white-space: nowrap;
}
.code-block {
  margin: 14px 0; padding: 12px 14px; background: var(--code-bg); border: 1px solid var(--code-bd);
  border-radius: var(--r-md); overflow-x: auto;
}
.code-block code {
  display: block; background: transparent; border: none; padding: 0; white-space: pre;
  font: 500 13px/1.55 var(--mono); color: var(--code-tx);
}

/* citas inline (pill) — clases mantenidas por compatibilidad con app.js */
.citation-link, .citation-text {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: baseline; margin: 0 1px;
  font: 600 11px/1 var(--ui); color: var(--cite-tx-strong); background: var(--cite-bg);
  border: 1px solid var(--cite-bd); padding: 2px 8px; border-radius: 999px;
  transition: background .15s; white-space: nowrap; max-width: 100%;
}
.citation-link { cursor: pointer; }
.citation-link:hover { background: var(--cite-hover); }
.citation-text { cursor: default; color: var(--cite-tx); }

/* Tag de repuesto (nº de parte del catálogo) inline → abre la ficha flotante. */
.part-tag {
  display: inline-flex; align-items: center; vertical-align: baseline; cursor: pointer;
  font: 700 12px/1.2 var(--mono, ui-monospace, monospace); color: var(--primary-tx, #fff);
  background: var(--primary); border: 1px solid var(--primary); border-radius: 6px;
  padding: 1px 6px; margin: 0 1px; white-space: nowrap; transition: filter .15s;
}
.part-tag:hover { filter: brightness(1.08); }
/* Tag de una pieza cuya referencia CONSULTADA era antigua (alias): tinte de aviso. */
.part-tag--alias { background: var(--warn, #b8860b); border-color: var(--warn, #b8860b); }

/* Nota discreta bajo la respuesta: «referencia antigua → nº Tecport actual». */
.alias-note { margin: 8px 0 2px; display: flex; flex-direction: column; gap: 4px; }
.alias-note__row { display: flex; align-items: flex-start; gap: 6px; font: 500 12.5px/1.4 var(--ui);
  color: var(--text-2); background: var(--warn-bg); border: 1px solid var(--warn-bd);
  border-radius: var(--r-sm, 8px); padding: 6px 10px; }
.alias-note__ico { color: var(--warn); flex: none; }
.alias-note__cur { cursor: pointer; text-decoration: underline dotted; }
.alias-note__cur:hover { color: var(--primary); }

/* Ventana flotante con la ficha de un repuesto. Por encima del chat. */
.part-pop {
  position: fixed; z-index: calc(var(--z-float, 3000) + 25); width: 300px; max-width: calc(100vw - 16px);
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--r-md, 12px);
  box-shadow: var(--shadow-lg); overflow: hidden; font: 500 13px/1.45 var(--ui); color: var(--text);
}
.part-pop__head { display: flex; align-items: center; gap: 8px; padding: 9px 12px;
  border-bottom: 1px solid var(--hairline); background: var(--surface-2); }
.part-pop__pn { font: 700 13px/1.2 var(--mono, ui-monospace, monospace); color: var(--heading); flex: 1; word-break: break-all; }
.part-pop__close { flex: none; width: 24px; height: 24px; border: 0; background: transparent;
  color: var(--text-2); font-size: 18px; line-height: 1; cursor: pointer; border-radius: 6px; }
.part-pop__close:hover { background: var(--surface); }
.part-pop__body { padding: 10px 12px; max-height: 50vh; overflow: auto; }
.part-pop__dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; margin: 0; }
.part-pop__dl dt { font-weight: 700; color: var(--text-2); }
.part-pop__dl dd { margin: 0; color: var(--text); word-break: break-word; }
.part-pop__note { color: var(--text-3); font-size: 12px; }
.part-pop__note + .part-pop__note, .part-pop__dl + .part-pop__note { margin-top: 8px; }
/* Aviso de referencia antigua dentro de la ficha. */
.part-pop__warn { color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-bd);
  border-radius: var(--r-sm, 8px); padding: 6px 9px; font-size: 12px; margin-bottom: 8px; }
/* Botón «Agregar a cotización» de la ficha flotante del chat. */
.part-pop__cart { margin-top: 10px; width: 100%; display: inline-flex; align-items: center; justify-content: center;
  gap: 7px; padding: 8px 12px; border: 1px solid var(--primary); border-radius: var(--r-sm, 8px);
  background: var(--primary); color: var(--primary-tx, #fff); font: 700 12.5px/1 var(--ui); cursor: pointer;
  transition: filter .15s; }
.part-pop__cart:hover { filter: brightness(1.08); }
.part-pop__cart svg { flex: none; }

/* ============================ RECOMENDACIÓN IA ============================ */
.ai-suggestion {
  margin: 4px 0 0; border-radius: 14px; padding: 14px 16px; background: rgba(237,125,34,.07);
  border: 1px solid rgba(237,125,34,.32); border-left: 4px solid var(--orange);
}
.ai-suggestion-header { display: flex; align-items: center; gap: 10px; }
.ai-suggestion-badge { font: 800 10px/1 var(--ui); color: #fff; background: var(--orange); padding: 5px 7px; border-radius: 6px; letter-spacing: .5px; }
.ai-suggestion-title { font: 800 13.5px/1 var(--ui); color: var(--heading); }
.ai-suggestion-body { margin: 11px 0 0; font-size: 14px; line-height: 1.62; color: var(--text); }
.ai-suggestion-body p:last-child { margin-bottom: 0; }
.ai-suggestion-footer { margin: 10px 0 0; font: italic 400 11.5px/1.55 var(--ui); color: var(--text-3); border-top: 1px dashed var(--border-2); padding-top: 9px; }
.ai-suggestion-footer strong { font-style: normal; color: var(--text-2); font-weight: 600; }
.ai-suggestion.forming { opacity: .75; }
.ai-suggestion.forming .ai-suggestion-title::after { content: " · preparando…"; color: var(--text-3); font-weight: 400; font-style: italic; }

/* ============================ FUENTES ============================ */
.source-section { margin-top: 4px; }
.source-title { display: flex; align-items: center; gap: 8px; font: 800 11px/1 var(--ui); letter-spacing: 1.2px; text-transform: uppercase; color: var(--text-3); margin-bottom: 12px; }
.source-title svg { color: var(--text-3); }
.source-title .src-count { font-size: 11px; color: var(--link); background: var(--cite-bg); padding: 3px 8px; border-radius: 999px; letter-spacing: 0; }
.source-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 14px; }
.source-card {
  display: flex; gap: 13px; padding: 13px; text-align: left; cursor: pointer; border-radius: 13px;
  background: var(--surface); border: 1px solid var(--border); transition: transform .16s, box-shadow .2s, border-color .2s;
  position: relative; overflow: hidden;
}
.source-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--blue); }
.source-thumb-wrap {
  flex: none; width: 72px; height: 92px; border-radius: 8px; position: relative; overflow: hidden;
  background: #fff; border: 1px solid var(--border-2); box-shadow: var(--shadow-sm);
}
[data-theme="dark"] .source-thumb-wrap { background: #cdd6df; }
.source-thumbnail { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .35s ease; }
.source-card.has-preview:hover .source-thumbnail { transform: scale(1.06); }
.thumb__corner { position: absolute; right: 4px; bottom: 4px; font: 800 7px/1 var(--ui); color: #fff; background: var(--orange); padding: 2px 4px; border-radius: 3px; letter-spacing: .5px; }
.source-thumb-overlay {
  position: absolute; inset: 0; display: grid; place-items: center; color: #fff; opacity: 0;
  background: linear-gradient(135deg, rgba(31,111,199,.55) 0%, rgba(20,58,94,.6) 100%); transition: opacity .25s ease;
}
.source-card.has-preview:hover .source-thumb-overlay { opacity: 1; }
.source-info { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.source-file { font: 700 13px/1.3 var(--ui); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.source-meta { font: 600 11.5px/1.3 var(--ui); color: var(--text-3); }
.source-meta .src-kind { color: var(--link); }
.source-rel { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
.source-score-bar { flex: 1; height: 5px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.source-score-bar span { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--blue), var(--orange)); }
.source-pct { font: 800 11px/1 var(--ui); color: var(--text-2); }
.source-hint { font: 700 11px/1 var(--ui); color: var(--link); margin-top: 3px; }
.source-snippets { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.source-snippet { font: 400 11px/1.45 var(--ui); color: var(--text-3); font-style: italic; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Tarjeta de fuente que es un PLANO de despiece: distintivo naranja. */
.source-card.is-diagram { border-color: var(--orange); }
.source-card.is-diagram .thumb__corner { background: var(--blue); }

/* ===================== PLANO DE DESPIECE (bloque dedicado) ===================== */
.diagram-section { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--orange); border-radius: 14px; background: var(--cite-bg); }
.diagram-title { display: flex; align-items: center; gap: 8px; font: 800 11px/1 var(--ui); letter-spacing: 1.2px; text-transform: uppercase; color: var(--text-2); margin-bottom: 12px; }
.diagram-title svg { color: var(--orange); }
.diagram-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.diagram-card { display: flex; flex-direction: column; gap: 8px; cursor: pointer; border-radius: 12px; overflow: hidden; background: var(--surface); border: 1px solid var(--border); transition: transform .16s, box-shadow .2s, border-color .2s; }
.diagram-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--orange); }
.diagram-thumb-wrap { position: relative; width: 100%; aspect-ratio: 4 / 3; background: #fff; overflow: hidden; }
[data-theme="dark"] .diagram-thumb-wrap { background: #cdd6df; }
.diagram-thumbnail { width: 100%; height: 100%; object-fit: contain; display: block; transition: transform .35s ease; }
.diagram-card:hover .diagram-thumbnail { transform: scale(1.04); }
.diagram-thumb-overlay { position: absolute; inset: 0; display: grid; place-items: center; color: #fff; opacity: 0; background: linear-gradient(135deg, rgba(231,124,38,.5) 0%, rgba(20,58,94,.6) 100%); transition: opacity .25s ease; }
.diagram-card:hover .diagram-thumb-overlay { opacity: 1; }
.diagram-info { padding: 0 10px 10px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.diagram-label { font: 700 12.5px/1.3 var(--ui); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diagram-meta { font: 600 11px/1.3 var(--ui); color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (hover: none) {
  .diagram-card:hover .diagram-thumb-overlay { opacity: 0; }
  .diagram-card:hover .diagram-thumbnail { transform: none; }
}

/* ============================ LECTOR DOBLE PÁGINA ============================ */
.reader { border-radius: 16px; overflow: hidden; box-shadow: var(--shadow-lg); border: 1px solid var(--border); }
.reader:focus { outline: none; }
.reader__bar {
  display: flex; align-items: center; gap: 12px; padding: 11px 16px;
  background: var(--reader-bar); color: var(--reader-bar-tx);
}
[data-theme="dark"] .reader__bar { border-bottom: 1px solid var(--border); }
.reader__lead { display: inline-flex; align-items: center; gap: 8px; font: 800 13.5px/1 var(--ui); }
.reader__sub { font: 600 12px/1 var(--ui); color: rgba(255,255,255,.62); }
[data-theme="dark"] .reader__sub { color: var(--text-3); }
.reader__spacer { flex: 1; }
.reader__fs { display: flex; gap: 4px; }
.reader__fs button {
  width: 30px; height: 28px; border-radius: 7px; border: 1px solid rgba(255,255,255,.2);
  background: rgba(255,255,255,.08); color: var(--reader-bar-tx); cursor: pointer; font: 700 12px/1 var(--ui);
}
.reader__fs button:hover { background: rgba(255,255,255,.2); }
[data-theme="dark"] .reader__fs button { border-color: var(--border-2); background: var(--surface-2); }
.reader__close {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font: 700 12px/1 var(--ui);
  color: var(--reader-close-tx); background: var(--reader-close-bg); border: none; padding: 8px 13px; border-radius: 999px; transition: transform .15s;
}
.reader__close:hover { transform: translateY(-1px); }

.reader__spread {
  position: relative; background: var(--paper);
  background-image: radial-gradient(circle at 50% 0, var(--paper-2), var(--paper) 70%);
  padding: 44px clamp(40px, 4.5vw, 76px) 54px; overflow: hidden;
  /* La altura la fija JS (paginateReader) al espacio vertical visible. */
}
/* Ventana de recorte: muestra sólo el pliego actual; las columnas que no
   caben quedan a la derecha y se llega a ellas pasando de página. */
.reader__viewport {
  position: relative; z-index: 2; height: 100%; overflow: hidden;
  /* Canalón invisible: una franja transparente al centro deja ver el papel del pliego
     (detrás del viewport) en reposo, pero recorta el texto que se desliza por el centro
     al pasar de página → ya no se "atraviesa" la lomera. Sin tinte ⇒ sin banda visible. */
  --reader-gutter: clamp(54px, 6.5vw, 112px);
  -webkit-mask: linear-gradient(90deg, #000 calc(50% - var(--reader-gutter)/2 - 7px), transparent calc(50% - var(--reader-gutter)/2), transparent calc(50% + var(--reader-gutter)/2), #000 calc(50% + var(--reader-gutter)/2 + 7px));
          mask: linear-gradient(90deg, #000 calc(50% - var(--reader-gutter)/2 - 7px), transparent calc(50% - var(--reader-gutter)/2), transparent calc(50% + var(--reader-gutter)/2), #000 calc(50% + var(--reader-gutter)/2 + 7px));
}
.reader__pages {
  column-count: 2; column-gap: clamp(64px, 7vw, 120px); column-rule: 0; column-fill: auto;
  height: 100%; will-change: transform; transition: transform .5s cubic-bezier(.22,.61,.36,1);
  color: var(--paper-tx); font-family: var(--serif);
  font-size: calc(16px * var(--fs, 1)); line-height: 1.72; letter-spacing: .1px;
}
.reader__pages p { margin-bottom: 14px; text-align: justify; hyphens: auto; }
.reader__pages h3, .reader__pages h4, .reader__pages h5 { font-family: var(--ui); font-size: calc(15px * var(--fs,1)); margin-top: 22px; break-after: avoid; }
.reader__pages h3:first-child, .reader__pages h4:first-child, .reader__pages h5:first-child, .reader__pages p:first-child { margin-top: 0; }
.reader__pages ul, .reader__pages ol { gap: 10px; margin-bottom: 16px; }
.reader__pages li { break-inside: avoid; }
.reader__pages .ai-suggestion, .reader__pages blockquote { break-inside: avoid; }
.reader__pages .citation-link, .reader__pages .citation-text { font-family: var(--ui); }
.reader__pages code { font-family: var(--mono); }

/* Lomera: sombra sutil de encuadernación sobre el canalón (no sobre el texto). */
.reader__spine {
  position: absolute; top: 24px; bottom: 24px; left: 50%; width: clamp(60px, 7vw, 120px); transform: translateX(-50%);
  background: var(--spine); z-index: 4; pointer-events: none;
}
.reader__spine::before, .reader__spine::after { content: ""; position: absolute; top: 0; bottom: 0; width: 1px; background: var(--paper-line); }
.reader__spine::before { left: 28px; } .reader__spine::after { right: 28px; }

.reader__wm { position: absolute; right: 26px; bottom: 18px; z-index: 1; pointer-events: none; opacity: var(--watermark); }
.reader__wm img { width: 150px; height: 150px; }
.reader__folio { position: absolute; bottom: 18px; z-index: 3; font: 600 11px/1 var(--serif); color: var(--text-faint); letter-spacing: 2px; }
.reader__folio--l { left: 0; right: 50%; text-align: center; }
.reader__folio--r { right: 0; left: 50%; text-align: center; }

/* Contador de páginas en la barra del lector */
.reader__pageinfo { font: 700 12px/1 var(--ui); color: rgba(255,255,255,.85); white-space: nowrap; }
[data-theme="dark"] .reader__pageinfo { color: var(--text-2); }

/* Flechas de paso de página (sobre los bordes del pliego) */
.reader__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 42px; height: 42px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-size: 24px; line-height: 1; display: grid; place-items: center; padding: 0 0 3px;
  box-shadow: var(--shadow-md); opacity: .88;
  transition: opacity .2s, transform .15s, background .2s;
}
.reader__nav:hover { opacity: 1; background: var(--surface-2); transform: translateY(-50%) scale(1.06); }
.reader__nav--prev { left: 12px; }
.reader__nav--next { right: 12px; }
.reader__nav:disabled { opacity: 0; pointer-events: none; }
@media (hover: none) { .reader__nav:hover { transform: translateY(-50%); } }

/* ============================ COMPOSER ============================ */
.composer {
  flex: none; background: var(--app); border-top: 1px solid var(--border);
  /* La safe-area inferior mantiene el composer por encima de la barra de gestos */
  padding: 14px max(34px, var(--safe-right)) calc(20px + var(--safe-bottom)) max(34px, var(--safe-left));
}
.composer__box {
  max-width: 1032px; margin: 0 auto; display: flex; align-items: flex-end; gap: 8px; padding: 8px 8px 8px 12px;
  background: var(--surface); border: 1.5px solid var(--border-2); border-radius: 18px; box-shadow: var(--shadow-sm);
  transition: border-color .2s, box-shadow .2s;
}
.composer__box:focus-within { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(31,111,199,.12); }
.composer__box textarea {
  flex: 1; resize: none; border: none; outline: none; background: none; color: var(--text);
  font: 500 15px/1.5 var(--ui); padding: 9px 4px; max-height: 160px;
}
.composer__box textarea::placeholder { color: var(--text-faint); }
.composer__tool { flex: none; width: 38px; height: 38px; border-radius: 11px; border: none; background: none; color: var(--text-3); cursor: pointer; display: grid; place-items: center; transition: background .15s, color .15s; }
.composer__tool:hover { background: var(--surface-3); color: var(--text); }
/* Nueva conversación desde el composer: sólo tiene sentido en móvil,
   donde el sidebar (y su botón "Nueva conversación") vive en el cajón. */
.composer__new { display: none; }
@media (max-width: 820px) {
  .composer__new { display: grid; }
}
/* Menú "+" del composer y su panel: sólo móvil (en escritorio los tools y los
   controles de respuesta van inline). */
.composer__more { display: none; }
.composer__menu { display: none; }
.composer__send {
  flex: none; width: 40px; height: 40px; border-radius: 12px; border: none; cursor: pointer; display: grid; place-items: center;
  background: var(--surface-3); color: var(--text-faint); transition: all .2s var(--ease);
}
.composer__send.is-ready { background: linear-gradient(135deg, var(--blue) 0%, #144a7d 100%); color: #fff; box-shadow: 0 5px 14px rgba(31,111,199,.4); }
.composer__send.is-ready:hover { transform: translateY(-1px) scale(1.03); }
.composer__hint { max-width: 1032px; margin: 9px auto 0; text-align: center; font: 500 11.5px/1 var(--ui); color: var(--text-faint); }
.composer__hint b { color: var(--text-3); font-weight: 700; }
.composer__box.is-dragover { border-color: var(--blue); box-shadow: 0 0 0 4px rgba(31,111,199,.18); }

/* previsualización de imagen adjunta */
.composer__attach {
  max-width: 1032px; margin: 0 auto 8px; display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; background: var(--surface); border: 1.5px solid var(--border-2); border-radius: 14px;
}
/* El atributo `hidden` debe ganar a `display:flex`: sin esto, la barra de
   previsualización se mostraba vacía (sin imagen) aunque no hubiera adjunto. */
.composer__attach[hidden] { display: none; }
.composer__attach img { width: 44px; height: 44px; object-fit: cover; border-radius: 8px; border: 1px solid var(--border-2); }
.composer__attach-name { flex: 1; font: 500 13px var(--ui); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.composer__attach-remove {
  flex: none; width: 26px; height: 26px; border-radius: 8px; border: none; cursor: pointer;
  background: var(--surface-3); color: var(--text-3); font-size: 18px; line-height: 1; display: grid; place-items: center;
}
.composer__attach-remove:hover { background: rgba(237,125,34,.14); color: var(--orange); }

/* controles de modo de respuesta (rápido/estándar/profundo) + slider de extensión */
.composer__controls {
  max-width: 1032px; margin: 0 auto 8px; display: flex; align-items: center;
  justify-content: space-between; gap: 12px;
}
.composer__modes {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--surface); border: 1.5px solid var(--border-2); border-radius: 12px;
}
.mode-btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border: none;
  border-radius: 9px; background: none; color: var(--text-3); font: 600 12px var(--ui);
  cursor: pointer; transition: background .15s, color .15s, box-shadow .15s;
}
.mode-btn:hover { background: var(--surface-3); color: var(--text); }
.mode-btn.is-active {
  background: linear-gradient(135deg, var(--blue) 0%, #144a7d 100%); color: #fff;
  box-shadow: 0 2px 8px rgba(31,111,199,.35);
}
.composer__length { display: inline-flex; align-items: center; gap: 9px; }
.length-name { font: 600 11.5px var(--ui); color: var(--text-3); min-width: 48px; text-align: right; }
#length-slider {
  -webkit-appearance: none; appearance: none; width: 110px; height: 4px; border-radius: 2px;
  background: var(--border-2); outline: none; cursor: pointer;
}
#length-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 14px; height: 14px; border-radius: 50%;
  background: var(--blue); border: 2px solid var(--surface); box-shadow: 0 1px 4px rgba(15,28,45,.25);
}
#length-slider::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%; background: var(--blue);
  border: 2px solid var(--surface); box-shadow: 0 1px 4px rgba(15,28,45,.25);
}

/* ============================ TOASTS ============================ */
/* Los toasts son avisos transitorios: SIEMPRE topmost. A z-index 1000 los tapaban las
   vistas de sección (.adm--page / #tp-parts = --z-view: 1000, insertadas después en el
   DOM) y los diálogos (--z-float + 10); por eso "no salían" en Flota/Manual/carrito. */
.toast-stack {
  position: fixed; top: calc(82px + var(--safe-top)); right: calc(18px + var(--safe-right)); z-index: calc(var(--z-float, 3000) + 40);
  display: flex; flex-direction: column; gap: 10px; max-width: min(380px, calc(100vw - 36px));
  pointer-events: none;
}
.toast {
  pointer-events: auto; display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; border-radius: 12px; background: var(--surface);
  border: 1px solid var(--border-2); border-left: 4px solid var(--blue);
  box-shadow: var(--shadow-md, 0 10px 30px rgba(0,0,0,.18));
  font: 500 13.5px/1.45 var(--ui); color: var(--text);
  /* VISIBLE por defecto: la opacidad NUNCA depende de la animación de entrada.
     Antes: nacía con opacity:0 y un rAF añadía .is-in; si el navegador no entrega
     frames (página estática, ventana ocluida, headless), el rAF/animación no corre y
     el toast quedaba montado pero transparente — "solo salía la primera vez". El
     keyframe solo anima el deslizamiento; sin frames, el toast igual se ve. */
  opacity: 1; transform: none;
  animation: toastIn .22s var(--ease);
  transition: opacity .22s var(--ease), transform .22s var(--ease);
}
@keyframes toastIn { from { transform: translateX(16px); } to { transform: none; } }
/* .is-in queda como no-op de compatibilidad (app.js aún la añade vía rAF; ya no hace falta). */
.toast.is-out { opacity: 0; transform: translateX(16px); }
.toast__ico { flex: none; width: 18px; height: 18px; margin-top: 1px; color: var(--blue); }
.toast__msg { flex: 1; }
.toast__close {
  flex: none; border: none; background: none; cursor: pointer; color: var(--text-faint);
  font-size: 16px; line-height: 1; padding: 0 2px; align-self: flex-start;
}
.toast__close:hover { color: var(--text); }
.toast--error   { border-left-color: var(--danger); }
.toast--error   .toast__ico { color: var(--danger); }
.toast--success { border-left-color: var(--ok); }
.toast--success .toast__ico { color: var(--ok); }
/* Confirmación de la cesta: tarjeta blanca con acentos azul de marca; el elemento agregado
   se resalta en azul (--blue) como "detalle" de la empresa. */
.toast--cart { border-left-color: var(--blue); }
.toast--cart .toast__ico { color: var(--blue); }
.toast--cart .tpq-toast__t { display: block; font-weight: 600; color: var(--text); }
.toast--cart .tpq-toast__d { display: block; margin-top: 2px; font-weight: 700; color: var(--blue); font-size: 12.5px; overflow-wrap: anywhere; }
.toast--info    { border-left-color: var(--blue); }
.toast--info    .toast__ico { color: var(--blue); }

/* imagen dentro de la burbuja del usuario */
.bubble__image { display: block; max-width: 320px; max-height: 280px; width: auto; border-radius: 10px; margin-bottom: 6px; }
.bubble__text { white-space: pre-wrap; word-wrap: break-word; }

/* ============================ LIGHTBOX ============================ */
.lightbox {
  /* Por encima del visor TS (--z-view), del modal admin (--z-dialog) y de cualquier
     overlay flotante: el lightbox es modal y siempre debe quedar al frente. */
  position: fixed; inset: 0; z-index: calc(var(--z-float, 3000) + 20); background: rgba(8,18,30,.62); backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px); display: none; align-items: center; justify-content: center;
  padding: calc(20px + var(--safe-top)) max(30px, var(--safe-right)) calc(20px + var(--safe-bottom)) max(30px, var(--safe-left));
}
.lightbox.active { display: flex; animation: fadeup .2s ease both; }
.lightbox-content {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 14px;
  width: min(92vw, 1100px); max-height: 92dvh;
}
.lightbox-close {
  position: absolute; top: -6px; right: -6px; width: 38px; height: 38px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2); cursor: pointer;
  display: grid; place-items: center; font-size: 22px; line-height: 1; z-index: 10; transition: background .2s;
}
.lightbox-close:hover { background: var(--surface-3); }
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%); width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2); cursor: pointer;
  display: grid; place-items: center; font-size: 20px; z-index: 10; transition: background .2s;
}
.lightbox-nav:hover { background: var(--surface-3); transform: translateY(-50%) scale(1.05); }
.lightbox-prev { left: -10px; } .lightbox-next { right: -10px; }
.lightbox-stage {
  position: relative; width: 100%; flex: 1; min-height: 320px; max-height: 78dvh;
  display: flex; align-items: center; justify-content: center; border-radius: var(--r-md);
  background: var(--surface); border: 1px solid var(--border); overflow: auto; box-shadow: var(--shadow-lg);
}
.lightbox-stage img {
  max-width: 100%; max-height: 78dvh; width: auto; height: auto; object-fit: contain;
  border-radius: var(--r-sm); cursor: zoom-in; display: block;
}
.lightbox-stage.zoomed {
  /* En zoom abandonamos el centrado flex (corta las zonas superiores e impide
     scrollear hacia ellas) y pasamos a layout en bloque totalmente desplazable. */
  display: block; overflow: auto; cursor: grab;
}
.lightbox-stage.zoomed img {
  max-width: none; max-height: none; width: auto; height: auto;
  margin: 0 auto; display: block; cursor: grab;
}
.lightbox-stage.zoomed.is-panning, .lightbox-stage.zoomed.is-panning img { cursor: grabbing; }
.lightbox-loader, .lightbox-error {
  display: none; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  color: var(--text-2); padding: 32px; text-align: center;
}
.lightbox-stage[data-state="loading"] .lightbox-loader { display: flex; }
.lightbox-stage[data-state="loading"] img, .lightbox-stage[data-state="loading"] .lightbox-error { display: none; }
.lightbox-stage[data-state="loaded"] img { display: block; }
.lightbox-stage[data-state="loaded"] .lightbox-loader, .lightbox-stage[data-state="loaded"] .lightbox-error { display: none; }
.lightbox-stage[data-state="error"] .lightbox-error { display: flex; }
.lightbox-stage[data-state="error"] img, .lightbox-stage[data-state="error"] .lightbox-loader { display: none; }
.loader-spinner { width: 42px; height: 42px; border: 3px solid var(--border-2); border-top-color: var(--blue); border-radius: 50%; animation: spin .9s linear infinite; }
.lightbox-error p { font-size: 14px; color: var(--text); }
.lightbox-error a { color: var(--link); text-decoration: none; border-bottom: 1px solid var(--cite-bd); }
.lightbox-caption { text-align: center; width: 100%; }
.lightbox-caption h4 { margin: 0; font: 800 16px/1.25 var(--ui); color: var(--text); }
.lightbox-caption p { margin: 4px 0 0; font: 600 12.5px/1.4 var(--ui); color: var(--text-3); }
.lightbox-action {
  display: inline-block; margin-top: 10px; color: var(--link); font: 700 12px/1 var(--ui); text-decoration: none;
  border: 1px solid var(--cite-bd); padding: 7px 13px; border-radius: 999px; transition: background .2s;
}
.lightbox-action:hover { background: var(--cite-bg); }

/* ============================ CHIP DE TABLA (colapsada) ============================ */
.table-chip {
  display: inline-flex; align-items: center; gap: 11px; margin: 12px 0;
  padding: 10px 12px; max-width: 100%; text-align: left; cursor: pointer;
  background: linear-gradient(180deg, rgba(237,125,34,.10), rgba(237,125,34,.05));
  border: 1.5px solid rgba(237,125,34,.45); border-left: 4px solid var(--orange);
  border-radius: var(--r-md); color: var(--text); font: inherit;
  transition: transform .15s var(--ease), box-shadow .2s var(--ease), background .2s;
}
.table-chip:hover { transform: translateY(-1px); box-shadow: var(--shadow-md);
  background: linear-gradient(180deg, rgba(237,125,34,.16), rgba(237,125,34,.08)); }
.table-chip__ico { display: grid; place-items: center; width: 30px; height: 30px; flex: 0 0 auto;
  border-radius: 9px; background: var(--orange); color: #fff; }
.table-chip__main { display: flex; flex-direction: column; gap: 1px; line-height: 1.2; }
.table-chip__label { font: 800 13px/1.2 var(--ui); color: var(--text); }
.table-chip__dims { font: 600 11.5px/1.2 var(--ui); color: var(--text-3); }
.table-chip__cta { display: inline-flex; align-items: center; gap: 5px; margin-left: auto;
  font: 800 11.5px/1 var(--ui); color: #fff; background: var(--orange);
  padding: 7px 11px; border-radius: 999px; white-space: nowrap; }
.table-chip:hover .table-chip__cta { background: var(--orange-deep); }

/* ============================ MODAL DE TABLA (ventana flotante) ============================ */
.table-modal {
  position: fixed; inset: 0; z-index: 70; display: none; align-items: center; justify-content: center;
  padding: calc(20px + var(--safe-top)) max(30px, var(--safe-right)) calc(20px + var(--safe-bottom)) max(30px, var(--safe-left));
  background: rgba(8,18,30,.62); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.table-modal.active { display: flex; animation: fadeup .2s ease both; }
.table-modal__panel {
  display: flex; flex-direction: column; width: min(94vw, 1000px); max-height: 88dvh;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.table-modal__bar {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.table-modal__title { display: inline-flex; align-items: center; gap: 8px; color: var(--orange);
  font: 800 15px/1 var(--ui); }
.table-modal__dims { font: 600 12px/1 var(--ui); color: var(--text-3); }
.table-modal__spacer { flex: 1; }
.table-modal__close {
  width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-2); cursor: pointer; font-size: 21px; line-height: 1;
  display: grid; place-items: center; transition: background .2s;
}
.table-modal__close:hover { background: var(--surface-3); }
.table-modal__body { padding: 18px; overflow: auto; }

/* Tabla bien renderizada (dentro del modal) */
.rag-table { border-collapse: collapse; width: 100%; font: 500 13.5px/1.5 var(--ui); color: var(--text); }
.rag-table th, .rag-table td { border: 1px solid var(--border-2); padding: 9px 13px; vertical-align: top; }
.rag-table thead th {
  background: var(--navy); color: #fff; font-weight: 700; text-align: left; position: sticky; top: 0;
}
.rag-table tbody tr:nth-child(even) { background: var(--surface-2); }
.rag-table tbody tr:hover { background: var(--cite-bg); }
.rag-table code { font: 600 .86em/1.3 var(--mono); background: var(--code-bg); color: var(--code-tx); padding: 1px 5px; border-radius: 5px; }

/* ============================ PANEL DE DOCUMENTOS INDEXADOS ============================ */
/* (El botón Documentos del header usa .hd__tab, homogeneizado en el bloque HEADER.) */

.docs-modal {
  position: fixed; inset: 0; z-index: 70; display: none; align-items: center; justify-content: center;
  padding: calc(20px + var(--safe-top)) max(30px, var(--safe-right)) calc(20px + var(--safe-bottom)) max(30px, var(--safe-left));
  background: rgba(8,18,30,.62); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.docs-modal.active { display: flex; animation: fadeup .2s ease both; }
.docs-modal__panel {
  display: flex; flex-direction: column; width: min(94vw, 880px); max-height: 86dvh;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.docs-modal__bar {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.docs-modal__title { display: inline-flex; align-items: center; gap: 8px; color: var(--orange); font: 800 15px/1 var(--ui); }
.docs-modal__meta { font: 600 12px/1 var(--ui); color: var(--text-3); }
.docs-modal__spacer { flex: 1; }
.docs-modal__refresh, .docs-modal__close {
  width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-2); cursor: pointer; line-height: 1;
  display: grid; place-items: center; transition: background .2s;
}
.docs-modal__close { font-size: 21px; }
.docs-modal__refresh:hover, .docs-modal__close:hover { background: var(--surface-3); }
.docs-modal__refresh.is-spinning svg { animation: spin 1s linear infinite; }

.docs-modal__summary {
  display: flex; flex-wrap: wrap; gap: 8px; padding: 13px 16px;
  border-bottom: 1px solid var(--border); background: var(--surface);
}
.docs-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 999px; cursor: pointer;
  font: 600 12px/1 var(--ui); color: var(--text-2); background: var(--surface-2);
  border: 1px solid var(--border-2); transition: background .2s, border-color .2s, color .2s;
}
.docs-chip b { font-weight: 800; color: var(--text); }
.docs-chip:hover { background: var(--surface-3); }
.docs-chip.is-active { border-color: var(--orange); color: var(--orange); background: rgba(237,125,34,.08); }
.docs-chip.is-active b { color: var(--orange); }

.docs-modal__body { flex: 1; overflow: auto; padding: 6px 0; }
.docs-empty { padding: 28px 20px; text-align: center; font: 600 13px/1.5 var(--ui); color: var(--text-3); }
.docs-row {
  display: flex; align-items: center; gap: 12px; padding: 9px 18px;
  border-bottom: 1px solid var(--border); font: 500 13px/1.4 var(--ui); color: var(--text);
}
.docs-row:last-child { border-bottom: none; }
.docs-row:hover { background: var(--surface-2); }
.docs-row__name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.docs-row__vec, .docs-row__size { flex: none; font: 600 11.5px/1 var(--ui); color: var(--text-3); white-space: nowrap; }
.docs-badge {
  flex: none; padding: 4px 10px; border-radius: 999px; white-space: nowrap;
  font: 700 11px/1.2 var(--ui); border: 1px solid transparent;
}
.docs-badge.is-indexed  { color: #1d7a3e; background: rgba(34,160,84,.12);  border-color: rgba(34,160,84,.3); }
.docs-badge.is-pending  { color: #8a6d1a; background: rgba(220,170,40,.13); border-color: rgba(220,170,40,.35); }
.docs-badge.is-modified { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-bd); }
.docs-badge.is-outdated { color: #7a4ec2; background: rgba(140,90,220,.12); border-color: rgba(140,90,220,.3); }
.docs-badge.is-orphan   { color: #b03434; background: rgba(214,69,69,.1);   border-color: rgba(214,69,69,.3); }
.docs-badge.is-indexing { color: var(--orange); background: rgba(237,125,34,.1); border-color: rgba(237,125,34,.35); animation: blink 1.2s infinite; }
[data-theme="dark"] .docs-badge.is-indexed  { color: #5fd68f; }
[data-theme="dark"] .docs-badge.is-pending  { color: #e8c558; }
[data-theme="dark"] .docs-badge.is-modified { color: #f0a35e; }
[data-theme="dark"] .docs-badge.is-outdated { color: #b696ec; }
[data-theme="dark"] .docs-badge.is-orphan   { color: #ec8484; }

.docs-modal__foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 11px 16px;
  border-top: 1px solid var(--border); background: var(--surface-2);
  font: 600 11px/1.4 var(--ui); color: var(--text-3);
}
.docs-foot__warn { color: var(--warn); }
.docs-foot__ver { margin-left: auto; font-family: var(--mono); font-weight: 500; }

/* ============================ RESPONSIVE ============================ */
/* ── Anchos medios: las etiquetas de los botones de acción no caben y se
      cortaban contra el borde derecho; quedan sólo los iconos (el title
      de cada botón sigue explicando su función al pasar el cursor). ── */
@media (max-width: 1380px) {
  .hd { gap: 12px; }
  .hd__actions { gap: 8px; flex: none; }
  .hd__tab span, .hd-menu__btn > span, .hd__stop span { display: none; }
  .hd__tab, .hd-menu__btn, .hd__stop {
    padding: 9px 11px; min-width: 40px; min-height: 40px; justify-content: center;
  }
  /* Los ítems DENTRO del panel del menú conservan sus etiquetas (el panel tiene ancho). */
}

@media (max-width: 1080px) {
  .thread, .composer__box, .composer__hint, .composer__controls { max-width: 100%; }
  .reader__pages { column-gap: 48px; }
  .reader__spread { padding: 32px 34px 44px; }
}
/* ── Tablet / iPad portrait: el lector pasa a una sola página pero sigue
      siendo cómodo de leer (tipografía de lectura, ancho contenido). ── */
@media (max-width: 820px) {
  .reader__pages { column-count: 1; column-gap: 0; }
  .reader__viewport { -webkit-mask: none; mask: none; }
  .reader__spine, .reader__folio--l, .reader__folio--r { display: none; }
  .reader__spread { padding: 30px clamp(22px, 5vw, 44px) 40px; }
  .reader__nav { width: 36px; height: 36px; font-size: 20px; }
  .reader__nav--prev { left: 6px; }
  .reader__nav--next { right: 6px; }

  /* El botón hamburguesa aparece y abre el cajón */
  .hd__menu { display: grid; }
  .hd { gap: 12px; padding: 0 14px; }
  /* La navegación central (flex:1) mantiene las acciones a la derecha; el estado
     unificado (punto + hover) es diminuto y sigue visible. */
  .hd__actions { margin-left: auto; }

  /* ── El sidebar se convierte en un cajón deslizable (off-canvas) ── */
  .sb {
    position: fixed; top: 0; left: 0; height: 100dvh; z-index: 60;
    width: min(86vw, 300px);
    /* El cajón cubre el borde izquierdo: respeta notch y barra de gestos */
    padding: calc(16px + var(--safe-top)) 14px calc(16px + var(--safe-bottom)) calc(14px + var(--safe-left));
    transform: translateX(-100%);
    transition: transform .32s var(--ease);
    box-shadow: 8px 0 40px rgba(0,0,0,.4);
  }
  .sb.sb--open { transform: translateX(0); }

  /* En móvil ignoramos el modo "colapsado" de escritorio: el cajón
     siempre muestra el contenido completo cuando está abierto. */
  .sb.sb--collapsed { width: min(86vw, 300px); padding: 16px 14px; }
  .sb--collapsed .sb__label { opacity: 1; pointer-events: auto; width: auto; }
  .sb--collapsed .sb__logo-plaque { display: inline-flex; }
  .sb--collapsed .sb__icon { display: none; }
  .sb--collapsed .sb__top { flex-direction: row; gap: 8px; align-items: center; }
  .sb--collapsed .sb__brand { flex: 1; justify-content: flex-start; }
  .sb--collapsed .sb__new { width: auto; height: auto; margin: 0; justify-content: flex-start; gap: 10px; padding: 12px 14px; }
  .sb--collapsed .sb__docs { width: auto; height: auto; margin: 0; justify-content: flex-start; gap: 9px; padding: 11px 12px; }
  .sb--collapsed .sb__docs-count { display: inline-block; }
  .sb--collapsed .sb__section,
  .sb--collapsed .sb__hist { display: flex; }
  .sb--collapsed .sb__user {
    width: auto; margin: 0; justify-content: flex-start; gap: 10px; padding: 10px;
    background: var(--sidebar-card); border-color: var(--sidebar-line); box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
  }
  /* El cajón muestra etiquetas: los tooltips de modo colapsado sobran aquí */
  .sb--collapsed .sb-tip::after { display: none; }
}

/* ── Teléfonos: compactamos cabecera y composer; ocultamos las etiquetas
      de los botones de acción dejando sólo los iconos. ── */
@media (max-width: 600px) {
  .hd {
    height: calc(58px + var(--safe-top)); gap: 8px;
    padding: var(--safe-top) calc(10px + var(--safe-right)) 0 calc(10px + var(--safe-left));
  }
  .hd__titles em { display: none; }
  .hd__actions { gap: 8px; }
  .hd__tab span, .hd-menu__btn > span, .hd__stop span { display: none; }
  /* Solo iconos, pero con objetivo táctil suficiente (~40px) */
  .hd__tab, .hd-menu__btn, .hd__stop {
    padding: 9px 11px; min-width: 40px; min-height: 40px; justify-content: center;
  }
  /* El panel del menú se ancla al borde para no salirse de la pantalla. */
  .hd-menu__panel { right: -8px; }

  /* Gestor de opciones (kebab): en móvil colapsa nav + índice + idioma + tema en un
     único menú para no encimar botones sobre el título. Se ocultan los inline (el
     kebab delega en ellos por JS). !important porque #index-menu tiene display inline
     fijado por el gating de rol. El panel del kebab conserva sus etiquetas visibles. */
  .hd-menu--more { display: block; }
  .hd__nav,
  #index-menu,
  #btn-lang,
  /* Detener pasa al menú ⋮ (kebab); no debe quedar suelto en el header. */
  .hd__stop,
  .hd__theme { display: none !important; }

  .composer { padding: 10px 12px calc(14px + var(--safe-bottom)); }
  .composer__hint { display: none; }
  /* 16px evita el autozoom de iOS al enfocar el campo de texto */
  .composer__box textarea { font-size: 16px; }
  .composer__tool, .composer__send { width: var(--tap); height: var(--tap); }

  /* Lightbox: controles dentro de la pantalla y alcanzables con el pulgar */
  .lightbox-prev { left: 2px; } .lightbox-next { right: 2px; }
  .lightbox-close { top: 0; right: 0; }
  .toast-stack { left: max(18px, var(--safe-left)); }
  /* Composer más bajo y despejado: las herramientas sueltas del textbox se agrupan
     en un único menú "+" (btn-composer-more) que despliega un panel flotante con las
     acciones + tema + controles de respuesta. La barra queda [+] [texto] [enviar]. */
  .composer { position: relative; }
  #btn-new-chat-2, #btn-attach, #btn-parts-search, #btn-attach-2 { display: none; }
  .composer__more { display: grid; }
  .composer__more.is-open { color: var(--text); background: var(--surface-3); }
  .composer__more svg { transition: transform .15s var(--ease); }
  .composer__more.is-open svg { transform: rotate(45deg); }

  /* Panel del menú "+" flotando sobre la caja */
  .composer__menu {
    position: absolute; left: max(12px, var(--safe-left)); right: max(12px, var(--safe-right));
    bottom: calc(100% - 6px); z-index: 60; margin: 0;
    flex-direction: column; gap: 4px; padding: 8px;
    background: var(--surface); border: 1px solid var(--border-2);
    border-radius: 14px; box-shadow: var(--shadow-lg);
  }
  .composer__menu.is-open { display: flex; }
  .composer__menu-actions { display: flex; flex-direction: column; gap: 2px; }
  .composer__menu-item {
    display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
    padding: 11px 12px; border: none; border-radius: 10px; cursor: pointer;
    background: none; color: var(--text-2); font: 600 14px/1 var(--ui);
  }
  .composer__menu-item svg { flex: none; color: var(--text-3); }
  .composer__menu-item:hover, .composer__menu-item:active { background: var(--surface-3); color: var(--text); }
  /* Controles de respuesta reubicados dentro del panel: fila estática y visible */
  .composer__menu .composer__controls {
    position: static; display: flex; margin: 4px 2px 2px; padding: 8px 4px 2px;
    gap: 10px; background: none; border: none; box-shadow: none; border-radius: 0;
    border-top: 1px solid var(--hairline);
  }
  .mode-btn span { display: none; }
  .mode-btn { padding: 6px 10px; }
  #length-slider { width: 78px; }
  .length-name { min-width: 40px; font-size: 11px; }
  .thread { padding: 18px 14px 28px; gap: 18px; }

  /* El lector queda deshabilitado por JS en móvil; este respaldo evita
     cualquier desbordamiento si alguna fila quedara en modo lector. */
  .reader__spread { padding: 22px 18px 30px; }
  .reader__bar { flex-wrap: wrap; gap: 8px; padding: 10px 12px; }
  .reader__sub { display: none; }
}

/* ── Diálogo de archivo pesado (pausa de ingesta) ── */
.heavy-overlay {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15,28,45,.45); backdrop-filter: blur(2px);
}
.heavy-dialog {
  width: min(440px, 92vw);
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 22px 22px 18px; font-family: var(--ui);
}
.heavy-title {
  font-weight: 700; font-size: 1.05rem; color: var(--navy);
  margin-bottom: 10px;
}
.heavy-body p { color: var(--text-2); font-size: .92rem; line-height: 1.45; margin: 8px 0 0; }
.heavy-file {
  font-family: var(--mono); font-size: .82rem;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 7px 10px; word-break: break-word;
}
.heavy-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }
.heavy-btn {
  width: 100%; padding: 10px 14px; border-radius: var(--r-sm);
  font-family: var(--ui); font-size: .9rem; font-weight: 600;
  cursor: pointer; border: 1px solid var(--border-2);
  background: var(--surface-2); color: var(--text);
  transition: filter .15s var(--ease), background .15s var(--ease);
}
.heavy-btn:hover { filter: brightness(.97); }
.heavy-proceed { background: var(--navy); border-color: var(--navy); color: #fff; }
.heavy-stop { background: transparent; color: var(--danger); border-color: var(--danger-bd); }

/* ============================ CATÁLOGO EN EL CHAT ============================ */
/* Línea de transparencia: el catálogo SQL de partes fue consultado. */
.catalog-badge {
  display: flex; align-items: center; gap: 7px; margin: 10px 0 2px;
  color: var(--text-3); font: 600 11.5px/1.4 var(--ui);
}
.catalog-badge svg { flex: none; opacity: .75; }
.catalog-badge__btn {
  border: 1px solid var(--border-2); background: var(--surface-2); color: var(--link);
  font: 700 11px/1 var(--ui); padding: 4px 9px; border-radius: 999px; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.catalog-badge__btn:hover { border-color: var(--blue); background: var(--cite-bg); }

/* CTA de fallback: ofrecer el buscador del catálogo cuando no hubo respuesta. */
.parts-cta {
  margin: 12px 0 2px; padding: 12px 14px; border-radius: 12px;
  border: 1px dashed var(--border-2); background: var(--surface-2);
}
.parts-cta__hint { color: var(--text-2); font: 500 12.5px/1.5 var(--ui); margin-bottom: 9px; }
.parts-cta__btn { display: inline-flex; align-items: center; gap: 7px; }

/* Modal del buscador de partes (overlay propio, sobre el chat). */
.parts-modal__overlay {
  position: fixed; inset: 0; z-index: calc(var(--z-float, 3000) + 20);
  display: grid; place-items: start center; padding: 9vh 12px 12px;
  background: rgba(10, 22, 36, .45); backdrop-filter: blur(2px);
}
.parts-modal {
  width: 560px; max-width: 100%; max-height: 78vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--r-md, 12px);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.parts-modal__head {
  display: flex; align-items: center; gap: 8px; padding: 12px 14px;
  border-bottom: 1px solid var(--hairline); background: var(--surface-2);
}
.parts-modal__title { display: inline-flex; align-items: center; gap: 8px; flex: 1;
  font: 800 13.5px/1.2 var(--ui); color: var(--heading); }
.parts-modal__close { flex: none; width: 26px; height: 26px; border: 0; background: transparent;
  color: var(--text-2); font-size: 20px; line-height: 1; cursor: pointer; border-radius: 6px; }
.parts-modal__close:hover { background: var(--surface); }
.parts-modal__input {
  margin: 12px 14px 4px; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--border-2); background: var(--surface); color: var(--text);
  font: 500 14px/1.3 var(--ui); outline: none;
}
.parts-modal__input:focus { border-color: var(--blue); }
.parts-modal__hint { margin: 0 14px 8px; color: var(--text-3); font: 500 11.5px/1.4 var(--ui); }
.parts-modal__results { overflow: auto; padding: 0 8px 10px; display: flex; flex-direction: column; gap: 2px; }
.parts-modal__note { color: var(--text-3); font: 500 12.5px/1.5 var(--ui); padding: 10px 8px; }
.parts-modal__row {
  display: flex; align-items: baseline; gap: 12px; text-align: left; width: 100%;
  border: 0; background: transparent; padding: 9px 10px; border-radius: 9px; cursor: pointer;
  transition: background .12s;
}
.parts-modal__row:hover { background: var(--surface-2); }
.parts-modal__pn { flex: none; font: 700 12.5px/1.2 var(--mono, ui-monospace, monospace); color: var(--link); }
.parts-modal__desc { color: var(--text-2); font: 500 12.5px/1.4 var(--ui); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================ KITS EN EL CHAT ============================ */
.kits-inchat { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.kits-inchat__title {
  display: flex; align-items: center; gap: 8px; font: 800 11px/1 var(--ui);
  letter-spacing: 1.2px; text-transform: uppercase; color: var(--text-3); margin-bottom: 2px;
}
.kits-inchat__title .src-count { font-size: 11px; color: var(--link); background: var(--cite-bg);
  padding: 3px 8px; border-radius: 999px; letter-spacing: 0; }
.kit-card { border: 1px solid var(--border); border-radius: 12px; background: var(--surface); overflow: hidden; }
.kit-card__head {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; cursor: pointer;
  border: 0; background: transparent; padding: 10px 13px; flex-wrap: wrap;
}
.kit-card__head:hover { background: var(--surface-2); }
.kit-card__name { font: 700 13px/1.3 var(--ui); color: var(--heading); }
.kit-card__chips { display: inline-flex; gap: 5px; flex-wrap: wrap; }
.kit-chip {
  font: 700 10.5px/1 var(--ui); color: var(--cite-tx-strong); background: var(--cite-bg);
  border: 1px solid var(--cite-bd); padding: 3px 8px; border-radius: 999px; white-space: nowrap;
}
.kit-card__pn { font: 700 11.5px/1.2 var(--mono, ui-monospace, monospace); color: var(--text-2); }
.kit-card__count { margin-left: auto; font: 600 11.5px/1 var(--ui); color: var(--text-3); white-space: nowrap; }
.kit-card__toggle { color: var(--text-3); font-size: 12px; transition: transform .18s var(--ease); }
.kit-card__head.is-open .kit-card__toggle { transform: rotate(180deg); }
.kit-card__body { padding: 2px 13px 12px; border-top: 1px solid var(--hairline); }
.kit-card__desc { color: var(--text-2); font: 500 12.5px/1.5 var(--ui); margin: 9px 0 2px; }
.kit-card__table { width: 100%; border-collapse: collapse; margin-top: 8px; font: 500 12.5px/1.45 var(--ui); }
.kit-card__table th {
  text-align: left; font: 700 10.5px/1.2 var(--ui); letter-spacing: .6px; text-transform: uppercase;
  color: var(--text-3); padding: 6px 8px; border-bottom: 1px solid var(--border-2);
}
.kit-card__table td { padding: 7px 8px; border-bottom: 1px solid var(--hairline); color: var(--text-2); vertical-align: top; }
.kit-card__table tr:last-child td { border-bottom: 0; }

/* ============================ TÁCTIL (sin puntero con hover) ============================
   En pantallas táctiles no existe hover: lo que en escritorio se revela al
   pasar el ratón debe estar siempre visible, y las micro-elevaciones de
   hover se desactivan para que nada "salte" al tocar. */
@media (hover: none) {
  .hist__del { opacity: 1; }
  .source-card:hover, .sb__new:hover, .row__readbtn:hover, .table-chip:hover,
  .hd__stop:hover, .composer__send.is-ready:hover { transform: none; }
  .source-card.has-preview:hover .source-thumb-overlay { opacity: 0; }
  .source-card.has-preview:hover .source-thumbnail { transform: none; }
  *::-webkit-scrollbar { width: 4px; height: 4px; }
}

/* Respeto a la preferencia del sistema de reducir movimiento */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ═══════════════════════ TPDialog (ventanas flotantes) ═══════════════════════
   Reemplazo tokenizado de prompt/confirm/alert. Markup en js/ui_dialog.js. */
.tp-dlg-overlay {
  position: fixed; inset: 0; z-index: calc(var(--z-float, 3000) + 10); display: none;
  align-items: center; justify-content: center; background: rgba(8, 16, 28, .5);
  backdrop-filter: blur(2px);
  padding: calc(16px + var(--safe-top)) max(12px, var(--safe-right)) calc(16px + var(--safe-bottom)) max(12px, var(--safe-left));
}
.tp-dlg-overlay.is-open { display: flex; animation: tpDlgFade .15s ease both; }
@keyframes tpDlgFade { from { opacity: 0; } to { opacity: 1; } }
.tp-dlg {
  position: relative;
  width: 100%; max-width: 440px; max-height: 100%; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg); padding: 20px 22px;
  font: 500 14px/1.5 var(--ui); color: var(--text);
  animation: tpDlgUp .18s var(--ease, ease) both;
}
@keyframes tpDlgUp { from { transform: translateY(10px) scale(.98); opacity: 0; } to { transform: none; opacity: 1; } }
/* «×» de cierre en la esquina superior derecha (todas las ventanas TPDialog). */
.tp-dlg__close {
  position: absolute; top: 10px; right: 12px; z-index: 1;
  width: 30px; height: 30px; padding: 0; border: 0; border-radius: 8px;
  background: transparent; color: var(--text-3); cursor: pointer;
  font: 400 22px/1 var(--ui); display: flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.tp-dlg__close:hover { background: var(--surface-3); color: var(--text); }
.tp-dlg__title { font: 800 17px/1.25 var(--ui); color: var(--heading); margin-bottom: 6px; padding-right: 28px; }
.tp-dlg__msg { color: var(--text-2); margin-bottom: 14px; white-space: pre-line; }
.tp-dlg__body { display: flex; flex-direction: column; gap: 12px; }
.tp-dlg__field { display: flex; flex-direction: column; gap: 5px; }
.tp-dlg__label { font: 700 12px/1.2 var(--ui); color: var(--text-2); }
.tp-dlg__req { color: var(--danger); }
/* Contrapartida del «*»: marca explícita de campo prescindible. Deliberadamente tenue — es una
   aclaración, no un aviso; solo se pone donde la duda es real. */
.tp-dlg__opt { font-weight: 500; color: var(--text-3); text-transform: none; }
.tp-dlg__hint { font: 500 11.5px/1.35 var(--ui); color: var(--text-3); }
/* Aviso leve dentro de un campo (p. ej. un valor fuera del catálogo): informa sin bloquear, así
   que usa el color de advertencia y NO el de error, que aquí significaría "no puedes guardar". */
.tp-dlg__hint--warn { color: var(--warn); font-weight: 600; }
.tp-dlg__field[hidden] { display: none; }
.tp-dlg__input {
  width: 100%; min-height: 40px; padding: 9px 12px; font: 500 14px/1.4 var(--ui); color: var(--text);
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: var(--r-sm);
  transition: border-color .15s, box-shadow .15s;
}
textarea.tp-dlg__input { resize: vertical; min-height: 72px; }
.tp-dlg__input:focus { outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent); }
.tp-dlg__input.is-invalid { border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 18%, transparent); }
/* Grupo de checkboxes (field.type = multiselect) */
.tp-dlg__multi { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px 12px;
  padding: 8px; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); }
.tp-dlg__multi.is-invalid { border-color: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 18%, transparent); }
.tp-dlg__chk { display: flex; align-items: center; gap: 7px; font: 500 12.5px/1.3 var(--ui); color: var(--text-1); cursor: pointer; }
.tp-dlg__chk input { flex: none; width: 15px; height: 15px; accent-color: var(--primary); cursor: pointer; }
/* Casilla SUELTA (field.type = checkbox): su etiqueta va al lado, no encima, y se le da el mismo
   alto de toque que a un input para que no quede como un renglón perdido entre dos campos. */
.tp-dlg__field--check { gap: 4px; }
.tp-dlg__chkline {
  display: flex; align-items: center; gap: 9px; min-height: 34px; cursor: pointer;
  font: 600 13px/1.35 var(--ui); color: var(--text);
}
.tp-dlg__chkline input { flex: none; width: 16px; height: 16px; accent-color: var(--primary); cursor: pointer; }
.tp-dlg__actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.tp-dlg__btn {
  min-height: 40px; padding: 9px 18px; border-radius: var(--r-sm); cursor: pointer;
  font: 700 13.5px/1 var(--ui); color: var(--text); background: var(--surface-2);
  border: 1px solid var(--border-2); transition: background .15s, filter .15s;
}
.tp-dlg__btn:hover { background: var(--surface-3); }
.tp-dlg__btn--primary { color: var(--primary-tx); background: var(--primary); border-color: transparent; }
.tp-dlg__btn--primary:hover { filter: brightness(1.08); background: var(--primary); }
.tp-dlg__btn--danger { color: #fff; background: var(--danger); border-color: transparent; }
.tp-dlg__btn--danger:hover { filter: brightness(1.06); background: var(--danger); }

/* ── Selector de idioma (TPLang, ventana TPDialog.custom) ── */
.tp-dlg__langs { display: flex; flex-direction: column; gap: 8px; }
.tp-dlg__langopt {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  min-height: 44px; padding: 10px 14px; cursor: pointer;
  font: 600 14px/1.2 var(--ui); color: var(--text); text-align: left;
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: var(--r-sm);
  transition: background .15s, border-color .15s;
}
.tp-dlg__langopt:hover { background: var(--surface-3); }
.tp-dlg__langopt.is-current {
  border-color: var(--primary); color: var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, var(--surface-2));
}
.tp-dlg__langchk { font-weight: 800; }

/* ── Refuerzo positivo: pulgares sobre imágenes de referencia + guardar validada ── */
.src-thumbs { display: flex; gap: 6px; margin-top: 6px; }
.src-thumb {
  cursor: pointer; line-height: 1; padding: 2px 6px; border-radius: 7px;
  border: 1px solid var(--border-2); background: var(--surface-2);
  font-size: 13px; opacity: .65; transition: opacity .15s, background .15s, transform .1s;
}
.src-thumb:hover { opacity: 1; transform: translateY(-1px); }
.src-thumb-up.is-active { opacity: 1; background: color-mix(in srgb, var(--primary) 18%, var(--surface-2)); border-color: var(--primary); }
.src-thumb-down.is-active { opacity: 1; background: color-mix(in srgb, var(--danger) 16%, var(--surface-2)); border-color: var(--danger); }
.source-reinforce-actions { margin-top: 10px; }
.source-validate-btn {
  cursor: pointer; font: 600 12px/1 var(--ui); padding: 7px 12px; border-radius: 8px;
  color: var(--primary-tx); background: var(--primary); border: 1px solid transparent;
}
.source-validate-btn:hover { filter: brightness(1.07); }

/* ════════════════════ Barra de FASES (primitiva compartida) ════════════════════
   Un documento que avanza por etapas —una orden de compra, un reclamo de garantía— se lee de un
   vistazo en horizontal: cada tramo apunta al siguiente para que se entienda como un avance y no
   como una lista de opciones. Los recorridos van en el color de marca; el actual, con relieve;
   los pendientes, apagados.

   Nació en Producción como `.po-phases` y se promovió aquí al necesitarla Garantías: dos copias
   del mismo galón acabarían divergiendo. Quien la use declara sus fases UNA vez (id, label, hint)
   y de esa tabla salen la barra, los filtros y los botones de avance.

   El color y su texto salen SIEMPRE de la pareja --primary / --primary-tx: en tema oscuro el
   primario es casi blanco, así que fijar el texto a blanco lo dejaría ilegible. */
.tp-phases { display: flex; flex-wrap: wrap; gap: 3px; margin: 0 0 18px; }

.tp-phase { position: relative; display: flex; align-items: center; gap: 8px;
    padding: 9px 26px 9px 16px; background: var(--surface-2); color: var(--text-3);
    font: 600 12.5px/1.2 var(--ui); cursor: default; user-select: none;
    /* La punta a la derecha y la muesca a la izquierda encajan un tramo con el siguiente. */
    clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%, 12px 50%); }
.tp-phase:first-child { padding-left: 16px;
    clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%); }
.tp-phase:not(:first-child) { padding-left: 26px; margin-left: -3px; }

.tp-phase.is-done { background: var(--primary); color: var(--primary-tx); }
/* La fase ACTUAL es la que más se busca de un vistazo: mismo azul, pero con relieve. */
.tp-phase.is-now { background: var(--primary); color: var(--primary-tx);
    box-shadow: inset 0 0 0 2px var(--surface); }
.tp-phase__n { display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: 999px; flex: none;
    background: rgba(127, 127, 127, .28); font-size: 11px; }
.tp-phase.is-done .tp-phase__n, .tp-phase.is-now .tp-phase__n {
    background: rgba(127, 127, 127, .35); }

/* Fin de trayecto que NO es el previsto (orden cancelada, reclamo rechazado o anulado): un solo
   tramo en rojo, sin galón, porque ya no hay avance que representar. */
.tp-phase--cancel { background: var(--danger-bg); color: var(--danger);
    box-shadow: inset 0 0 0 1px var(--danger-bd); }
.tp-phases--off .tp-phase { clip-path: none; padding: 9px 16px; border-radius: var(--r-sm); }

/* Globo explicativo. Aparece con retardo para que pasar el ratón por encima de camino no lo
   dispare, y se pinta sobre el tramo, no dentro, para que no deforme la geometría. */
.tp-phase::after { content: attr(data-hint); position: absolute; left: 0; top: calc(100% + 8px);
    z-index: 40; width: max-content; max-width: 320px; padding: 9px 12px;
    border-radius: var(--r-md); border: 1px solid var(--border-2);
    background: var(--surface-3); color: var(--text);
    font: 500 12px/1.5 var(--ui); text-align: left; white-space: normal;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .22);
    opacity: 0; visibility: hidden; transform: translateY(-4px);
    transition: opacity .13s ease, transform .13s ease, visibility 0s linear .45s;
    pointer-events: none; }
.tp-phase:hover::after { opacity: 1; visibility: visible; transform: translateY(0);
    transition-delay: .45s, .45s, 0s; }
/* Los últimos tramos abren el globo hacia la izquierda para no salirse del panel. */
.tp-phase:nth-last-child(-n+2)::after { left: auto; right: 0; }

/* Variante COMPACTA: la misma barra dentro de una fila de listado o de una tarjeta, donde solo
   interesa por dónde va y no cómo se llama cada tramo. */
.tp-phases--mini { gap: 2px; margin: 0; }
.tp-phases--mini .tp-phase { padding: 3px 12px 3px 8px; font-size: 0; gap: 0;
    clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 0 100%, 6px 50%); }
.tp-phases--mini .tp-phase:first-child { padding-left: 8px;
    clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 0 100%); }
.tp-phases--mini .tp-phase:not(:first-child) { padding-left: 14px; margin-left: -2px; }
.tp-phases--mini .tp-phase__n, .tp-phases--mini .tp-phase__t { display: none; }

@media (max-width: 720px) {
    /* Sin espacio para las puntas, los tramos pasan a bloques apilados legibles. */
    .tp-phase, .tp-phase:first-child { clip-path: none; padding: 8px 12px;
        border-radius: var(--r-sm); }
    .tp-phase:not(:first-child) { padding-left: 12px; margin-left: 0; }
}

/* ════════════════ Buscador de nº de parte (TPPartPicker) ════════════════
   Desplegable flotante compartido por todo el portal. Es `position: fixed` a propósito: los
   diálogos (.tp-dlg) tienen overflow-y y recortarían un desplegable en flujo, y por eso también
   se apila por encima de --z-float. Las filas son de dos líneas —número arriba, descripción
   debajo— que es justo lo que un <datalist> nativo no sabe pintar. */
.tp-pick {
    position: fixed; z-index: calc(var(--z-float, 3000) + 15);
    display: flex; flex-direction: column; gap: 1px; padding: 4px;
    max-height: 260px; min-width: 220px; max-width: min(460px, 92vw); overflow: auto;
    border: 1px solid var(--border); border-radius: var(--r-md);
    background: var(--surface); box-shadow: var(--shadow-lg);
}
.tp-pick__opt {
    display: flex; flex-direction: column; gap: 2px; width: 100%;
    padding: 7px 10px; border: none; border-radius: var(--r-sm);
    background: transparent; cursor: pointer; text-align: left;
    font: 500 12.5px/1.35 var(--ui); color: var(--text);
}
.tp-pick__opt:hover, .tp-pick__opt.is-active { background: var(--surface-2); }
.tp-pick__pn { font-family: var(--mono); font-size: 12px; letter-spacing: -.2px; }
.tp-pick__lbl { font-weight: 400; font-size: 11px; color: var(--text-3); }
/* Pista de procedencia («Boom · 2 u»): dice POR QUÉ esa pieza sale sugerida. */
.tp-pick__hint { font-weight: 600; font-size: 10.5px; color: var(--text-faint); }
.tp-pick__empty { padding: 8px 10px; font: 400 11.5px/1.4 var(--ui); color: var(--text-3); }
.tp-pick__add {
    display: flex; align-items: center; gap: 6px; width: 100%;
    margin-top: 2px; padding: 8px 10px; border: none; border-top: 1px solid var(--border);
    border-radius: 0 0 var(--r-sm) var(--r-sm); background: transparent; cursor: pointer;
    font: 600 12px/1.35 var(--ui); color: var(--primary); text-align: left;
}
.tp-pick__add:hover, .tp-pick__add.is-active { background: var(--surface-2); }

/* Variante para buscar NOMBRES y no números de parte (el cliente final en Flota). Dos cambios:
   el nombre va en la fuente de interfaz —en monoespaciada un nombre de empresa se lee como un
   código— y el panel enseña OCHO filas antes de hacer scroll. El alto base (260px) está
   calibrado para ocho filas de UNA línea; aquí casi todas llevan la segunda («empresa del
   portal») y solo cabrían cinco: 8 × 47,7px de fila + 7px de huecos + 10px de cromo ≈ 400px.
   El tope en vh es para que en una pantalla baja el panel no se salga por abajo. */
.tp-pick--names { max-height: min(400px, 60vh); }
.tp-pick--names .tp-pick__pn {
    font-family: var(--ui); font-size: 12.5px; letter-spacing: 0;
}
