/* ==========================================================================
   BASE — primitivas compartidas por todas las pantallas
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400..700&display=swap');

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-100);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
button { cursor: pointer; }

/* ---- Tipografía utilitaria: solo 3 tamaños ---- */
.label {
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--ink-45);
}
.display { font-size: var(--text-display); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--ink-100); }
.body-strong { font-size: var(--text-body); font-weight: var(--weight-medium); color: var(--ink-100); }
.body-muted { font-size: var(--text-body); font-weight: var(--weight-regular); color: var(--ink-70); }
.body-faint { font-size: var(--text-body); font-weight: var(--weight-regular); color: var(--ink-45); }

/* ---- Layout shell ---- */
.shell { min-height: 100%; display: flex; flex-direction: column; }
.topnav {
  height: var(--nav-h);
  flex: 0 0 auto;
  display: grid;
  /* minmax(0,1fr), no 1fr a secas: un 1fr normal no se encoge por debajo
     del ancho de su contenido — con la hamburguesa añadida a la 1ª
     columna (antes solo la marca) y la 3ª vacía en casi todas las
     páginas, en ventanas estrechas el grid entero se quedaba más ancho
     que el viewport (la pastilla "simulación" central acababa empujada
     fuera, con scroll horizontal) y todo lo demás de la página se leía
     descentrado. Con minmax(0,1fr) esas columnas sí pueden encogerse. */
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-4);
  padding: 0 var(--space-6);
  background: var(--bg-raised);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 40;
}
/* Una sola voz tipográfica para el lockup: todo en mayúscula, mismo peso. */
.topnav .brand {
  justify-self: start;
  /* ~15% menos que --weight-bold (680 → 580) — un pelín menos grueso, no
     un cambio de voz tipográfica. */
  font-weight: 580;
  font-size: var(--text-body);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  text-decoration: none;
  color: var(--ink-100);
}
.topnav .brand:hover { color: var(--cyan-ink); }
.topnav .proto-pill { justify-self: center; }
/* Configuración / Fuentes: transversales, no al mismo nivel que Oportunidades
   (esa ya es el espacio por defecto al que lleva el logo) — por eso van
   agrupadas aparte, con icono, a la derecha. */
.topnav .secondary-nav { justify-self: end; display: flex; gap: var(--space-5); }
.topnav .secondary-nav a {
  display: inline-flex; align-items: center; gap: 6px;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  color: var(--ink-45);
  padding: var(--space-2) 0;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.topnav .secondary-nav a svg { width: 13px; height: 13px; flex: none; }
.topnav .secondary-nav a:hover { color: var(--ink-100); }
.topnav .secondary-nav a.active { color: var(--ink-100); border-bottom-color: var(--cyan); }

/* ==========================================================================
   VARIANTE EXPERIMENTAL — menú hamburguesa + barra lateral (ver
   initSideNav() en js/app.js). Mueve Cómo funciona/Configuración/Fuentes
   (antes sueltos aquí a la derecha) y el filtro de Oportunidades a un
   panel único — así que la fila de enlaces de siempre se oculta, no se
   borra: para revertir basta con quitar este display:none.
   ========================================================================== */
.topnav .secondary-nav { display: none; }
.topnav-left, .topnav .brand { justify-self: start; }
.topnav-left { display: flex; align-items: center; gap: var(--space-3); min-width: 0; overflow: hidden; }
/* La cabecera entera sube por encima del panel (ver .side-nav/-overlay más
   abajo, que ahora empiezan en top:var(--nav-h) en vez de 0) — así la
   hamburguesa/X nunca queda tapada por el panel que ella misma abre. */
.topnav { z-index: 97; }
.hamburger-btn {
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex: none; position: relative;
  background: none; border: none; border-radius: var(--radius-sm);
  color: var(--ink-70); cursor: pointer; padding: 0;
}
.hamburger-btn:hover { background: var(--ink-06); color: var(--ink-100); }
/* 3 barras independientes (no un SVG fijo): al abrir, las de fuera rotan
   45°/-45° hasta cruzarse en una X y la del medio se desvanece — el propio
   botón hace de cierre, no hace falta un ✕ aparte dentro del panel. Un
   pelín más grandes y más separadas que el icono de antes (18px/6px de
   separación → 22px/7px). */
.hamburger-btn .bar {
  position: absolute; left: 7px; width: 22px; height: 2px; background: currentColor;
  border-radius: 1px; transition: transform .25s ease, opacity .2s ease, top .25s ease;
}
.hamburger-btn .bar:nth-child(1) { top: 11px; }
.hamburger-btn .bar:nth-child(2) { top: 18px; }
.hamburger-btn .bar:nth-child(3) { top: 25px; }
.hamburger-btn.open .bar:nth-child(1) { top: 18px; transform: rotate(45deg); }
.hamburger-btn.open .bar:nth-child(2) { opacity: 0; }
.hamburger-btn.open .bar:nth-child(3) { top: 18px; transform: rotate(-45deg); }

.side-nav-overlay {
  position: fixed; top: var(--nav-h); left: 0; right: 0; bottom: 0; background: rgba(15, 22, 32, 0.45);
  z-index: 90; opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.side-nav-overlay.open { opacity: 1; pointer-events: auto; }

.side-nav {
  position: fixed; top: var(--nav-h); left: 0; bottom: 0; width: 300px; max-width: 85vw;
  /* Chispa de transparencia (antes sólido #1B2E3D) + el mismo desenfoque de
     cristal que el resto de piezas oscuras de este experimento. Subida de
     nuevo a petición del usuario: 0.95 → 0.90 → 0.70. */
  background: rgba(27, 46, 61, 0.70);
  backdrop-filter: blur(16px) saturate(1.15); -webkit-backdrop-filter: blur(16px) saturate(1.15);
  z-index: 91; display: flex; flex-direction: column;
  padding: var(--space-5); overflow-y: auto;
  box-shadow: 12px 0 32px -8px rgba(15, 22, 32, 0.35);
  transform: translateX(-100%); transition: transform .25s ease;
  /* Mismo truco de siempre: estos tokens invertidos hacen que .filter-option,
     .label, .body-faint… que vivan dentro ya salgan legibles sin tocarlos. */
  --ink-100: #fff; --ink-70: rgba(255, 255, 255, 0.85); --ink-45: rgba(255, 255, 255, 0.65);
  --line: rgba(255, 255, 255, 0.14); --line-strong: rgba(255, 255, 255, 0.24);
  --bg: rgba(255, 255, 255, 0.07); --bg-raised: rgba(255, 255, 255, 0.1); --bg-sunken: rgba(255, 255, 255, 0.07);
  --ink-06: rgba(255, 255, 255, 0.08);
}
.side-nav.open { transform: translateX(0); }
.side-nav-section { padding-bottom: var(--space-4); margin-bottom: var(--space-4); border-bottom: 1px solid rgba(255, 255, 255, 0.14); }
.side-nav-section .side-nav-title { font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: rgba(255, 255, 255, 0.55); margin-bottom: var(--space-3); }
.side-nav-links { display: flex; flex-direction: column; gap: 2px; }
.side-nav-links a {
  display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3);
  border-radius: var(--radius-sm); text-decoration: none; font-weight: var(--weight-medium);
  color: rgba(255, 255, 255, 0.8); white-space: nowrap;
}
.side-nav-links a svg { width: 16px; height: 16px; flex: none; }
.side-nav-links a:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }
.side-nav-links a.active { background: rgba(11, 165, 184, 0.22); color: #7FE3F0; }
/* Fila de Oportunidades + su botón "+" cuadrado propio, pegado a la derecha
   de esa misma pastilla — para crear una oportunidad sin tener que entrar
   primero. La fila entera se comporta como el resto de .side-nav-links a
   (mismo padding/radio/hover), solo que repartido en dos zonas clicables. */
.side-nav-link-row { display: flex; align-items: center; border-radius: var(--radius-sm); }
.side-nav-link-row:hover, .side-nav-link-row.active { background: rgba(11, 165, 184, 0.22); }
.side-nav-link-row .side-nav-link-main {
  display: flex; align-items: center; gap: var(--space-3); flex: 1; min-width: 0;
  padding: var(--space-3); border-radius: 0; color: rgba(255, 255, 255, 0.8); text-decoration: none; font-weight: var(--weight-medium);
}
.side-nav-link-row.active .side-nav-link-main { color: #7FE3F0; }
.side-nav-link-row .side-nav-link-main svg { width: 16px; height: 16px; flex: none; }
.side-nav-add-btn {
  flex: none; width: 28px; height: 28px; margin-right: var(--space-3);
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm); background: var(--orange); color: #fff;
  font-size: 18px; line-height: 1; text-decoration: none;
}
.side-nav-add-btn:hover { background: var(--orange-ink); color: #fff; }
.topnav .proto-pill {
  font-size: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--coral-ink);
  background: var(--coral-wash);
  border: 1px solid var(--coral-wash-strong);
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  white-space: nowrap;
}
/* Pastilla puramente decorativa: en vez de dejar que su columna "auto" del
   grid fuerce la cabecera (y con ella toda la página) por encima del ancho
   de pantallas estrechas, se quita de en medio ahí. */
@media (max-width: 560px) { .topnav .proto-pill { display: none; } }

main {
  flex: 1;
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-6);
  padding-bottom: calc(var(--dock-h-collapsed) + var(--space-8));
  min-width: 0;
}

/* ---- Migas / cabecera de página ---- */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-5); margin-bottom: var(--space-6); flex-wrap: wrap; }
.crumb { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--ink-45); margin-bottom: var(--space-2); }
.crumb a { text-decoration: none; color: var(--ink-45); }
.crumb a:hover { color: var(--cyan-ink); }
.crumb .sep { opacity: .5; }
.page-head h1 { margin: 0; }
.page-head .meta-row { display: flex; gap: var(--space-4); margin-top: var(--space-2); flex-wrap: wrap; }
/* Enlace dentro de un párrafo de intro sin caja (Fuentes, Cómo funciona…) —
   compartida porque ya la usa más de una página. */
/* Azul propio, no --cyan-ink: sobre blanco el cian de siempre se lee
   demasiado saturado para un enlace de línea de texto suelta. */
.page-head-link { color: #2E5A6B; }
.page-head-link:hover { color: #1F3F4C; }

/* ---- Tarjetas ---- */
.card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.card-pad { padding: var(--space-5); }
.card-flat { background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius-md); }

/* ---- tira de veredicto: usada tanto para el veredicto global (informe.html)
   como para el veredicto de un ámbito concreto (ambito.html) — compartida
   aquí para que las dos no diverjan. ---- */
.verdict-strip { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; padding: var(--space-4) var(--space-5); background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius-lg); }
.verdict-strip .big { font-size: var(--text-display); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; }

.grid { display: grid; gap: var(--space-4); }
.grid-6 { grid-template-columns: repeat(6, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 1000px) { .grid-6 { grid-template-columns: repeat(2, 1fr); } .grid-3 { grid-template-columns: 1fr; } .grid-2 { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .grid-6 { grid-template-columns: 1fr; } }

/* ---- Badges / chips ---- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  font-weight: var(--weight-medium);
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.chip-favorable { background: var(--verdict-favorable-wash); color: var(--green-ink); border-color: var(--green-wash-strong); }
.chip-favorable .chip-dot { background: var(--verdict-favorable); }
.chip-mixto { background: var(--verdict-mixto-wash); color: var(--ink-70); border-color: var(--ink-12); }
.chip-mixto .chip-dot { background: var(--ink-45); }
.chip-debil { background: var(--verdict-debil-wash); color: var(--coral-ink); border-color: var(--coral-wash-strong); }
.chip-debil .chip-dot { background: var(--verdict-debil); }
.chip-critico { background: var(--verdict-critico-wash); color: var(--orange-ink); border-color: var(--orange-wash-strong); }
.chip-critico .chip-dot { background: var(--orange); }
.chip-neutral { background: var(--ink-06); color: var(--ink-70); }

/* ---- Confianza (barra de fiabilidad del dato) ---- */
.confidence { display: flex; align-items: center; gap: var(--space-2); }
.confidence .track { width: 54px; height: 4px; border-radius: 2px; background: var(--ink-12); overflow: hidden; }
.confidence .fill { height: 100%; background: var(--cyan); border-radius: 2px; }
.confidence .pct { font-size: var(--text-label); font-variant-numeric: tabular-nums; color: var(--ink-45); }

/* ---- Botones ---- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  border-radius: var(--radius-sm); border: 1px solid var(--line-strong);
  background: var(--bg-raised); padding: var(--space-2) var(--space-4);
  font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label);
  font-weight: var(--weight-medium); color: var(--ink-70);
  text-decoration: none; /* un <a class="btn"> no debe heredar el subrayado por defecto del link */
}
.btn:hover { border-color: var(--ink-25); color: var(--ink-100); }
.btn-primary { background: var(--orange); border-color: var(--orange); color: #fff; }
.btn-primary:hover { background: var(--orange-ink); border-color: var(--orange-ink); color: #fff; }
.btn-accent { background: var(--cyan); border-color: var(--cyan); color: #fff; }
.btn-accent:hover { background: var(--cyan-ink); border-color: var(--cyan-ink); }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--ink-06); }
.btn-sm { padding: 4px var(--space-3); }
.icon-btn { width: 32px; height: 32px; padding: 0; justify-content: center; border-radius: 50%; }

/* ---- Tabla densa (capa "motor") ---- */
table.dense { width: 100%; border-collapse: collapse; font-size: var(--text-body); }
table.dense th {
  text-align: left; font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label);
  color: var(--ink-45); font-weight: var(--weight-medium); padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line-strong); white-space: nowrap; position: sticky; top: 0;
  /* Un tono más gris que las celdas de cuerpo (--bg-raised, siempre blanco),
     como la fila de cabecera de un Excel. */
  background: var(--bg-sunken);
}
table.dense td { background: var(--bg-raised); }
table.dense td { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--line); vertical-align: top; }
table.dense tbody tr:hover { background: var(--ink-06); }
.table-scroll { overflow-x: auto; border-radius: var(--radius-md); border: 1px solid var(--line); }
.table-scroll table.dense { border: none; }
.table-scroll table.dense th:first-child, .table-scroll table.dense td:first-child { position: sticky; left: 0; background: inherit; }

/* ---- score pill numérico (-3..+3) ---- */
.score {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; height: 22px; padding: 0 6px; border-radius: 999px;
  font-size: var(--text-label); font-weight: var(--weight-bold); font-variant-numeric: tabular-nums;
}
.score-pos { background: var(--cyan-wash); color: var(--cyan-ink); }
.score-neg { background: var(--coral-wash); color: var(--coral-ink); }
.score-zero { background: var(--ink-06); color: var(--ink-45); }

/* ---- Fuente / cita ---- */
.source-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--text-label); color: var(--cyan-ink); background: var(--cyan-wash);
  padding: 1px 8px; border-radius: 999px; text-decoration: none; border: 1px solid transparent;
}
.source-tag:hover { border-color: var(--cyan-wash-strong); }
.flag-warn { color: var(--orange-ink); }

/* ---- Placeholder visual (foto / mapa / plano) ---- */
.visual-ph {
  position: relative; border-radius: var(--radius-md); overflow: hidden;
  background: var(--bg-image-wash); border: 1px solid var(--line);
  display: flex; align-items: flex-end; min-height: 120px;
}
.visual-ph::before {
  content: attr(data-label);
  font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label);
  color: var(--ink-45); background: rgba(255,255,255,.72); backdrop-filter: blur(2px);
  padding: 4px 10px; margin: var(--space-2); border-radius: 999px;
}

/* ---- Slider / ecualizador ---- */
.fader-col { display: flex; flex-direction: column; align-items: center; width: 100%; gap: var(--space-2); }
.fader-track-wrap { height: 160px; display: flex; align-items: center; justify-content: center; }
.fader-track-wrap input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 140px; height: 4px; background: var(--ink-12); border-radius: 2px;
  transform: rotate(-90deg); margin: 0;
}
.fader-track-wrap input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%;
  background: var(--bg-raised); border: 3px solid var(--cyan); box-shadow: 0 1px 3px rgba(0,0,0,.2); cursor: grab;
}
.fader-track-wrap input[type=range]::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%; background: var(--bg-raised); border: 3px solid var(--cyan); cursor: grab;
}
.fader-value { font-variant-numeric: tabular-nums; font-size: var(--text-label); color: var(--ink-70); font-weight: var(--weight-medium); }

input[type=range].inline-slider {
  -webkit-appearance: none; appearance: none; width: 100%; height: 4px; background: var(--ink-12); border-radius: 2px;
}
input[type=range].inline-slider::-webkit-slider-thumb {
  -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--bg-raised); border: 3px solid var(--cyan); cursor: grab; margin-top: -1px;
}
input[type=range].inline-slider::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: var(--bg-raised); border: 3px solid var(--cyan); cursor: grab; }

/* ==========================================================================
   AGENTE CONVERSACIONAL — dock contextual (uno por pantalla) y global
   ========================================================================== */
.chat-dock {
  position: sticky;
  bottom: 0;
  left: 0; right: 0;
  z-index: 30;
  background: var(--bg-raised);
  border-top: 1px solid var(--line-strong);
  box-shadow: var(--shadow-dock);
}
.chat-dock .dock-bar {
  max-width: var(--content-max); margin: 0 auto; padding: 0 var(--space-6);
  min-height: var(--dock-h-collapsed);
  display: flex; align-items: center; gap: var(--space-3);
}
/* Avatar: una nube de color en movimiento — da a entender "esto es la IA"
   sin depender de una etiqueta. Respeta prefers-reduced-motion. */
.chat-dock .dock-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  position: relative; overflow: hidden; background: var(--bg-sunken);
}
.chat-dock .dock-avatar::before, .chat-dock .dock-avatar::after {
  content: ''; position: absolute; inset: -20%; border-radius: 50%; filter: blur(2.5px); opacity: .95;
}
.chat-dock .dock-avatar::before { background: radial-gradient(circle at 30% 30%, var(--cyan), transparent 60%); animation: dock-cloud-a 2.6s ease-in-out infinite; }
.chat-dock .dock-avatar::after { background: radial-gradient(circle at 70% 70%, var(--coral), transparent 60%); animation: dock-cloud-b 3.1s ease-in-out infinite; }
@keyframes dock-cloud-a { 0%, 100% { transform: translate(-10%,-10%) scale(.9); } 50% { transform: translate(24%,18%) scale(1.3); } }
@keyframes dock-cloud-b { 0%, 100% { transform: translate(12%,12%) scale(1.25); } 50% { transform: translate(-22%,-16%) scale(.85); } }
@media (prefers-reduced-motion: reduce) { .chat-dock .dock-avatar::before, .chat-dock .dock-avatar::after { animation: none; } }

/* El campo ya no es solo una línea: es una caja (dock-input-box) con la
   fila de escritura arriba y las pastillas de sugerencia dentro, debajo,
   separadas por un filete — así se leen como parte del campo, no como
   un menú aparte que aparece al expandir. */
.chat-dock .dock-ask-form { flex: 1; min-width: 0; display: flex; align-items: center; }
.chat-dock .dock-input-box {
  flex: 1; min-width: 0; border: 1px solid var(--line-strong); border-radius: var(--radius-md);
  background: var(--bg-sunken); padding: var(--space-2) var(--space-3);
}
.chat-dock .dock-input-box:focus-within { border-color: var(--cyan); }
.chat-dock .dock-input-row { display: flex; align-items: center; gap: var(--space-3); }
.chat-dock .dock-ask-input {
  flex: 1; min-width: 0; border: none; border-radius: 0;
  padding: var(--space-1) 2px; background: transparent; font-size: var(--text-body);
  color: var(--ink-100);
}
.chat-dock .dock-ask-input::placeholder { color: var(--ink-45); font-weight: var(--weight-regular); }
.chat-dock .dock-ask-input:focus { outline: none; }
.chat-dock .dock-suggestions {
  display: flex; gap: var(--space-2); flex-wrap: wrap;
  margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px solid var(--line);
}
.dock-suggestion {
  font-size: var(--text-label); color: var(--ink-70); background: var(--bg-raised);
  border: 1px solid transparent; border-radius: 999px; padding: 4px 12px;
}
.dock-suggestion:hover { border-color: var(--line-strong); color: var(--ink-100); }

/* El cuerpo está siempre presente en el flujo; es el hilo (no el dock
   entero) el que crece. Sin alto tope ni scroll interno — antes el hilo
   cortaba el último globo a media frase al llegar a su tope de 3x; ahora,
   abierto, crece todo lo que haga falta para que se vea entero (JS pone
   la clase .open en cuanto hay mensajes, via setThreadOpen()). El botón es
   de COLAPSAR (dock-thread-toggle), no de cerrar: nunca vacía el hilo, así
   que al volver a abrirlo aparece la misma conversación, no una en blanco;
   la flecha gira 180° según el estado para indicar qué pasa al pulsar. */
.chat-dock .dock-body { max-width: var(--content-max); margin: 0 auto; padding: 0 var(--space-6); position: relative; }
.chat-dock .dock-thread {
  max-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: var(--space-3);
}
.chat-dock .dock-thread.open { max-height: none; }
.chat-dock .dock-thread.open:has(.chat-msg) { padding: var(--space-5) var(--space-8) var(--space-3) 0; }
.dock-thread-toggle {
  position: absolute; top: var(--space-2); right: var(--space-6); z-index: 1;
  width: 26px; height: 26px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-sunken); color: var(--ink-45);
}
.dock-thread-toggle:hover { background: var(--bg-raised); color: var(--ink-100); }
.dock-thread-toggle svg { width: 15px; height: 15px; transition: transform .2s ease; }
.dock-thread-toggle:not(.open) svg { transform: rotate(180deg); }
.chat-msg { display: flex; gap: var(--space-3); max-width: 640px; }
/* 6px, no 2px: con el texto a 18px (ver experiment-glass.css) una bola de
   22px centrada por top necesita bajar un poco más para alinear con el
   centro óptico de la primera línea, no con el borde superior del bloque. */
.chat-msg .who { width: 22px; height: 22px; border-radius: 50%; flex: none; margin-top: 6px; }
.chat-msg.agent .who { background: conic-gradient(from 210deg, var(--cyan), var(--coral)); }
/* El usuario escribe de izquierda a derecha: su propio texto va a la
   izquierda (orden de lectura natural, "esto lo digo yo"), y la respuesta
   del agente a la derecha — al revés del chat-a-la-WhatsApp de siempre,
   a propósito. */
.chat-msg.agent { margin-left: auto; flex-direction: row-reverse; }
.chat-msg.user .who { background: var(--ink-25); }
.chat-msg .bubble { padding: var(--space-1) 0; font-size: var(--text-body); color: var(--ink-100); }
.chat-msg.user .bubble { background: #F3EBDC; color: var(--ink-100); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); }
/* El agente también lleva su propio bocadillo ahora — un tono neutro y
   discreto (no compite con el crema del usuario), para que ambos lados de
   la conversación se lean como mensajes y no uno de ellos como texto suelto. */
.chat-msg.agent .bubble { background: var(--ink-06); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); }

/* ---- utilidades ---- */
.row { display: flex; align-items: center; }
.row-between { display: flex; align-items: center; justify-content: space-between; }
.gap-2 { gap: var(--space-2); } .gap-3 { gap: var(--space-3); } .gap-4 { gap: var(--space-4); } .gap-5 { gap: var(--space-5); }
.stack-2 > * + * { margin-top: var(--space-2); } .stack-3 > * + * { margin-top: var(--space-3); } .stack-4 > * + * { margin-top: var(--space-4); }
.hr { border: none; border-top: 1px solid var(--line); margin: var(--space-5) 0; }
.section-title { text-transform: uppercase; letter-spacing: var(--tracking-label); font-size: var(--text-label); color: var(--ink-45); font-weight: var(--weight-medium); margin-bottom: var(--space-3); }
[hidden] { display: none !important; }

/* ==========================================================================
   MAPA — compartido entre el mapa pequeño del informe (.map-card) y el
   grande de Ámbito · Ubicación (.map-card.big). Ver js/app.js wireMapCard().
   ========================================================================== */
.map-card { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; background: var(--bg-raised); min-height: 220px; }
.map-card.big { min-height: 460px; }
.map-tabs-row { display: flex; align-items: center; border-bottom: 1px solid var(--line); }
.map-tabs { display: flex; gap: 2px; padding: var(--space-2); overflow-x: auto; flex: 1; min-width: 0; }
.map-expand-link { flex: none; display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin-right: var(--space-2); border-radius: var(--radius-sm); color: var(--ink-45); }
.map-expand-link:hover { background: var(--ink-06); color: var(--ink-100); }
.map-expand-link svg { width: 14px; height: 14px; }
.map-tab {
  flex: none; border: none; background: none; padding: 6px 10px; border-radius: var(--radius-sm);
  font-size: var(--text-label); text-transform: uppercase; letter-spacing: var(--tracking-label);
  font-weight: var(--weight-medium); color: var(--ink-45); white-space: nowrap;
}
.map-tab:hover { background: var(--ink-06); color: var(--ink-100); }
.map-tab.active { background: var(--cyan-wash); color: var(--cyan-ink); }
.map-frame-wrap { flex: 1; position: relative; min-height: 180px; }
.map-frame-wrap iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: none; }

/* ---- proximidad gastronómica: tarjetas de contexto junto al mapa grande ---- */
.dining-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); margin-top: var(--space-4); }
@media (max-width: 700px) { .dining-grid { grid-template-columns: 1fr; } }
.dining-stat { background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius-md); padding: var(--space-4); }
.dining-stat .icon { width: 18px; height: 18px; color: var(--ink-45); flex: none; }
.dining-stat .n { font-size: var(--text-display); font-weight: var(--weight-bold); }
.dining-stat .k { font-size: var(--text-label); color: var(--ink-45); margin-top: 2px; }
.dining-stat .d { font-size: var(--text-label); color: var(--ink-45); margin-top: var(--space-2); }

/* ---- mosaico de fotos (Producto y room mix) ---- */
.photo-mosaic { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
.photo-mosaic.cols-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 700px) { .photo-mosaic, .photo-mosaic.cols-3 { grid-template-columns: repeat(2, 1fr); } }
.photo-mosaic figure { margin: 0; position: relative; border-radius: var(--radius-md); overflow: hidden; aspect-ratio: 4/3; background: var(--bg-sunken); }
.photo-mosaic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-mosaic figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: var(--space-2) var(--space-3);
  background: linear-gradient(transparent, rgba(15,22,32,.72)); color: #fff; font-size: var(--text-label);
}
.photo-mosaic figure { cursor: zoom-in; }

/* ---- lightbox / carrusel (abre al hacer clic en cualquier foto del mosaico) ---- */
.lightbox {
  display: none; position: fixed; inset: 0; z-index: 100; background: rgba(15,22,32,.92);
  align-items: center; justify-content: center;
}
.lightbox.open { display: flex; }
.lightbox figure { margin: 0; max-width: min(900px, 86vw); max-height: 82vh; }
.lightbox img { max-width: 100%; max-height: 72vh; display: block; border-radius: var(--radius-md); margin: 0 auto; }
.lightbox figcaption { color: #fff; text-align: center; margin-top: var(--space-3); font-size: var(--text-body); }
.lightbox-close {
  position: absolute; top: var(--space-5); right: var(--space-5); width: 36px; height: 36px; border-radius: 50%;
  border: none; background: rgba(255,255,255,.12); color: #fff; font-size: 16px;
}
.lightbox-close:hover { background: rgba(255,255,255,.22); }
.lightbox-nav {
  position: absolute; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; border-radius: 50%;
  border: none; background: rgba(255,255,255,.12); color: #fff; font-size: 22px; line-height: 1;
}
.lightbox-nav:hover { background: rgba(255,255,255,.22); }
.lightbox-nav.prev { left: var(--space-5); }
.lightbox-nav.next { right: var(--space-5); }

/* ==========================================================================
   INFORMACIÓN CUALITATIVA — una caja más, título dentro. Compartida entre
   el informe (todos los ámbitos) y cada ficha de ámbito (el suyo, fijo) —
   ver initQualCard() en js/app.js y docs/HANDOFF.md §8.
   ========================================================================== */
/* El color del delta sugerido (+/-) se lee vía estas dos variables, no
   directamente var(--green-ink)/var(--orange-ink) en el JS — así un tema
   oscuro (ver experiment-glass.css) puede redefinirlas a tonos más claros
   sin tocar qualDeltaColor() en js/app.js. Los -ink de siempre están
   pensados para texto sobre blanco; sobre fondo oscuro se leen casi negros. */
.qual-card { --qual-delta-pos: var(--green-ink); --qual-delta-neg: var(--orange-ink); }
.qual-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-2); flex-wrap: wrap; }
.qual-card-head-text { flex: 1; min-width: 240px; }
/* El título venía heredando .section-title (versalitas, pequeño, --ink-45)
   — se leía como una etiqueta más, no como el nombre de una sección. Al
   mismo estilo que el nombre de cada ámbito en su tarjeta (.body-strong):
   texto normal, negrita media, tinta oscura de verdad. */
.qual-head-title {
  text-transform: none; letter-spacing: normal; font-size: var(--text-body);
  font-weight: var(--weight-medium); color: var(--ink-100);
}
.qual-card-head .btn { flex: none; }
.qual-entry { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) 0; border-bottom: 1px solid var(--line); }
.qual-entry:last-child { border-bottom: none; }
.qual-body { flex: 1; min-width: 0; }
.qual-top { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.qual-domain-tag { font-size: var(--text-label); color: var(--cyan-ink); background: var(--cyan-wash); padding: 2px 8px; border-radius: 999px; }
.qual-delta-wrap { display: flex; align-items: center; gap: var(--space-2); flex: none; }
.qual-delta { font-weight: var(--weight-bold); font-variant-numeric: tabular-nums; min-width: 40px; text-align: right; }
.qual-ai-tag { font-size: var(--text-label); color: var(--ink-45); white-space: nowrap; }
.qual-stepper { display: flex; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); overflow: hidden; }
.qual-stepper button { width: 22px; height: 22px; border: none; background: var(--bg-raised); color: var(--ink-70); }
.qual-stepper button:hover { background: var(--ink-06); }
.qual-form { display: none; margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--line); }
.qual-form.open { display: block; }
.qual-source-toggle { display: flex; gap: var(--space-2); margin-bottom: var(--space-3); }
.qual-source-toggle button { flex: none; }
.qual-source-toggle button.active { background: var(--cyan-wash); color: var(--cyan-ink); border-color: var(--cyan-wash-strong); }
.qual-form textarea { width: 100%; min-height: 80px; border: 1px solid var(--line-strong); border-radius: var(--radius-md); padding: var(--space-3); background: var(--bg); color: var(--ink-100); font-size: var(--text-body); font-family: inherit; resize: vertical; }
.qual-form textarea::placeholder { color: var(--ink-45); }
.qual-form select { border: 1px solid var(--line-strong); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); background: var(--bg); color: var(--ink-100); font-size: var(--text-body); text-transform: none; }
.qual-form-row { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-3); flex-wrap: wrap; }
/* Tarjeta de "falta información": un único campo y un único botón, sin
   selector de ámbito (ya está dicho en el título) — el botón va a la
   derecha, más alto que el resto para que se note que es la única acción. */
.qual-form-row-end { justify-content: flex-end; }
.qual-incorporate-btn { padding: var(--space-3) var(--space-5); }
/* El valor que propone la IA, dentro del propio formulario — mismo +/−
   que ya usa cada entrada de la lista (.qual-stepper/.qual-delta), para
   que el gesto de "ajusta el número" sea idéntico en los dos sitios. */
.qual-proposal { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px dashed var(--line); }
.qual-proposal-row { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-2); flex-wrap: wrap; }
/* Volver al paso 1 (editar el texto) no es una acción del mismo peso que
   "añadir a la lista" — un enlace de texto, no un botón. */
.qual-edit-link {
  background: none; border: none; padding: 0; margin-top: 4px;
  font-size: var(--text-label); color: var(--ink-45); cursor: pointer; text-decoration: underline;
}
.qual-edit-link:hover { color: var(--ink-100); }
/* "Cerrar" no manda nada, solo pliega el panel — no debe competir
   visualmente con "proponer valor" / "añadir a la lista", que sí son
   pasos de un proceso. Mismo .btn por debajo (hereda tamaño/posición),
   pero sin relleno ni mayúsculas: lee como indicador, no como botón. */
.qual-add-btn.is-close {
  background: none; border-color: transparent; color: var(--ink-45);
  text-transform: none; letter-spacing: normal; font-weight: var(--weight-regular);
}
.qual-add-btn.is-close:hover { color: var(--ink-100); background: none; }
.qual-proposal-row .qual-stepper { flex: none; }

/* ---- spinner — "procesando" genérico, usado en recalibración, propuesta
   de valor cualitativo y cualquier casilla/página todavía "generando…" ---- */
.spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--orange-wash-strong); border-top-color: var(--orange); border-radius: 50%; animation: spin .7s linear infinite; vertical-align: -1px; }
@keyframes spin { to { transform: rotate(360deg); } }
/* ---- celdas de veredicto/fuente mientras el agente todavía trabaja: no
   hay nada fiable que mostrar todavía, así que no fingimos una cifra.
   Usada en la tabla de oportunidades (portfolio.js) y en el veredicto
   global del informe mientras no hay ni un ámbito generado (informe.js). ---- */
.cell-generating { display: flex; align-items: center; gap: var(--space-2); color: var(--orange-ink); font-size: var(--text-label); }
