/* Frontend del asistente — Fase 2, rediseñado para acercarlo a la estética de
   los chats de IA actuales (Claude, ChatGPT): superficies con sombra suave en
   vez de bordes duros, radios grandes, compositor único tipo pill con íconos
   en línea, selector de modo segmentado. Ver el contrato de dirección al
   principio de index.html. Sigue siendo una herramienta interna de uso
   intensivo: legibilidad larga y procedencia visible no se negocian por
   estética — ver PRODUCT.md. */

:root {
  --papel:      #f6f5f2;
  --superficie: #ffffff;
  --superficie-hundida: #edeeec;   /* fondo recesado: track del selector, chips, hover de íconos */

  /* Navy y cian exactos del logo de Cinestar Software (medidos del PNG, no
     aproximados a ojo: #001a54 y #00dcf9). El navy hace de tinta Y de acento
     por defecto — el logo tampoco distingue "texto" de "color de marca", es
     el mismo azul para todo. El cian es la chispa: en el logo es solo el
     punto sobre la "i", una pincelada chica sobre un fondo dominado por navy
     — acá se usa igual de poco, y SOLO sobre navy o teal (el punto en el
     selector de modo activo): sobre los fondos claros de la app mide ~1.6:1
     de contraste (medido), casi invisible como texto o como trazo fino. */
  --tinta:      #001a54;
  --tinta-suave:#5a6b7a;
  --chispa:     #00dcf9;
  --linea:      #d8dee3;
  --linea-fina: #e7ebee;

  /* confianza — el eje de color con significado */
  --validado:   #1b6b4a;
  --borrador:   #b26a00;
  --obsoleto:   #a32b2b;

  /* modo Carga (Fase 3.5): no el cian puro de arriba (ver nota de contraste),
     sino un teal más oscuro derivado del mismo matiz — mismo hue que la
     chispa de marca, pero con luminosidad suficiente para llevar texto
     blanco encima (5.9:1 medido) y para leerse como texto sobre el fondo
     pálido de este modo (5.4:1). Es la única razón por la que no es el
     #00dcf9 exacto: si lo fuera, "botón de Carga con texto blanco" o "aviso
     de Carga con este color de texto" quedarían casi ilegibles. */
  --carga:        #046e86;
  --carga-suave:  #eaf7fa;
  --carga-borde:  #a3d9e6;

  /* Eje de color del modo ACTIVO. Todo lo que usa `--acento` en vez de
     `--tinta` directamente (burbuja del usuario, pastilla del selector,
     botón de enviar, foco de teclado) cambia de navy a teal solo con
     reasignar esta variable — es lo que hace que Carga se sienta una
     pantalla distinta y no un detalle de color suelto. */
  --acento: var(--tinta);

  --sans: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: Consolas, "Cascadia Mono", "SF Mono", Menlo, monospace;

  /* Medida de línea compartida por todo lo que se alinea con el hilo de
     mensajes (mensajes, compositor, avisos, pista) — un solo número, no un
     "68ch" repetido siete veces por el archivo. */
  --medida: 72ch;

  /* Separación fija entre el contenido y el borde de la ventana, la misma en
     el header, el hilo y el compositor — antes cada uno la fijaba por su
     cuenta (algunos con padding, otros restándola del max-width) y quedaban
     ligeramente desalineados entre sí. Se achica en pantallas angostas. */
  --gutter: 24px;

  /* Radios: escala chica→pill, la señal más directa de "interfaz de chat de
     IA actual" frente a los 2–4px de la versión anterior. */
  --radio-sm: 8px;
  --radio-md: 12px;
  --radio-lg: 18px;
  --radio-pill: 999px;

  /* Sombras con un tinte de tinta, no negro puro: una elevación de marca en
     vez de la sombra gris genérica de cualquier framework. */
  --sombra-sm: 0 1px 2px rgba(0, 26, 84, .06);
  --sombra-md: 0 1px 2px rgba(0, 26, 84, .04), 0 8px 20px rgba(0, 26, 84, .07);
  --sombra-lg: 0 2px 6px rgba(0, 26, 84, .06), 0 16px 36px rgba(0, 26, 84, .12);
}

/* Reasigna el eje de color y el fondo de toda la pantalla. Nada más que esta
   regla necesita saber que existe el modo Carga: cada elemento que ya usa
   `var(--acento)` o hereda el fondo del body lo sigue automáticamente. */
body[data-modo="carga"] {
  --acento: var(--carga);
  background: var(--carga-suave);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  display: flex;
  flex-direction: column;
  background: var(--papel);
  color: var(--tinta);
  font: 15px/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.oculto {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Superficies del navegador que ningún componente "dibuja" pero que igual
   llevan la marca: selección de texto y cursor de escritura. */
::selection { background: var(--acento); color: #fff; }

/* --- barra superior ------------------------------------------------------ */

.barra {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  padding: 12px var(--gutter);
  background: var(--superficie);
  border-bottom: 1px solid var(--linea-fina);
  transition: background-color .15s ease, border-color .15s ease;
}

/* El logo trae su propio nombre ("cinestar software") escrito adentro de la
   imagen — repetirlo en texto al lado sería redundante. Lo que hace falta
   decir acá es qué ES esta pantalla puntual, así que el h1 pasa a ser una
   leyenda chica y neutra, separada del logo por una línea vertical fina (el
   patrón común de "marca de un tercero + nombre del producto interno" que
   usan paneles admin de cualquier proveedor). */
.marca {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo { display: block; height: 24px; width: auto; }

.barra h1 {
  margin: 0;
  padding-left: 12px;
  border-left: 1px solid var(--linea);
  font-size: 13px;
  font-weight: 500;
  color: var(--tinta-suave);
  letter-spacing: -0.01em;
}

.estado {
  margin: 0 0 0 auto;
  font-size: 13px;
  color: var(--tinta-suave);
}

.estado.caido { color: var(--obsoleto); }

/* Quién está logueado + cerrar sesión (LOGIN-USUARIOS.md). Va después de
   `.estado`, que ya tiene el margin-left:auto que empuja todo el bloque
   derecho del header — este solo necesita alinearse en la misma fila. */
.sesion {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 16px;
  padding-left: 16px;
  border-left: 1px solid var(--linea);
}

.sesion-usuario {
  font-size: 13px;
  font-weight: 600;
  color: var(--tinta);
}

.sesion button {
  flex: none;
  font: inherit;
  font-size: 12.5px;
  background: none;
  border: 1px solid var(--linea);
  border-radius: var(--radio-pill);
  color: var(--tinta-suave);
  padding: 4px 12px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}

.sesion button:hover { border-color: var(--tinta); color: var(--tinta); }

/* Selector conversar/carga, como un control segmentado: una pastilla que
   desliza detrás del texto en vez de dos botones con una línea divisoria en
   el medio. Es la decisión más importante de la barra — en "carga" el agente
   puede escribir en la base — así que quien lo usa tiene que ver siempre, de
   un vistazo, en cuál de los dos está parado; la pastilla en movimiento hace
   ese cambio más notorio que un simple cambio de color de fondo. Un rol
   "consulta" (LOGIN-USUARIOS.md) no lo ve nunca — `display:flex` le gana a
   `hidden` si no se lo dice explícito, mismo motivo que en `.lector`. */
.modos[hidden] { display: none; }

.modos {
  position: relative;
  display: flex;
  gap: 2px;
  background: var(--superficie-hundida);
  border-radius: var(--radio-pill);
  padding: 3px;
}

.modos-indicador {
  position: absolute;
  top: 3px; bottom: 3px; left: 3px;
  width: calc(50% - 3px);
  border-radius: var(--radio-pill);
  background: var(--acento);
  box-shadow: var(--sombra-sm);
  transform: translateX(0%);
  transition: transform .25s cubic-bezier(.4, 0, .2, 1), background-color .2s ease;
}

body[data-modo="carga"] .modos-indicador { transform: translateX(100%); }

.modo-boton {
  position: relative;
  z-index: 1;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  background: none;
  color: var(--tinta-suave);
  border: none;
  border-radius: var(--radio-pill);
  padding: 7px 16px;
  cursor: pointer;
  transition: color .2s ease;
}

.modo-boton[aria-pressed="true"] { color: #fff; }

/* El cian de marca puro (fuera del logo mismo) vive en dos lugares, y en los
   dos es el mismo punto de 5px que cita directo el punto sobre la "i" del
   logo: acá, y en el botón de dictado mientras escucha (más abajo). Los dos
   comparten el motivo — se pone solo donde hay un fondo oscuro para que se
   vea (navy o teal — contraste medido, no a ojo: 9.9:1 y 3.5:1
   respectivamente), que es justo el fondo que trae la pastilla debajo. */
.modo-boton[aria-pressed="true"]::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--chispa);
  margin-right: 6px;
  vertical-align: middle;
}

.modo-boton:disabled { opacity: 0.6; cursor: default; }

/* En modo carga el fondo entero de la barra se tiñe — no solo el selector —
   para que la señal de "acá se puede escribir en la base" no dependa de
   fijarse en un solo elemento chico. */
body[data-modo="carga"] .barra {
  background: var(--carga-suave);
  border-bottom-color: var(--carga-borde);
}

/* Aviso persistente, solo en modo carga — a propósito asimétrico: Conversar
   es el estado neutro/por-defecto y no necesita explicarse cada vez; Carga sí,
   porque ahí el agente puede escribir en la base y esta conversación además
   es independiente de la otra (cambiar de modo no mezcla los hilos). Flota
   como una tarjeta en vez de ocupar todo el ancho como una barra más: separa
   visualmente "aviso" de "estructura fija de la pantalla". */
.aviso-modo {
  flex: none;
  margin: 12px var(--gutter) 0;
  padding: 10px 16px;
  border-radius: var(--radio-md);
  background: var(--carga-suave);
  border: 1px solid var(--carga-borde);
  color: var(--carga);
  font-size: 13px;
}

.aviso-modo strong { font-weight: 600; }

/* --- estructura ---------------------------------------------------------- */

.taller {
  flex: 1;
  display: flex;
  min-height: 0;
}

.conversacion {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  position: relative;   /* ancla a .zona-soltar, el overlay de arrastrar y soltar */
}

.hilo {
  flex: 1;
  overflow-y: auto;
  padding: 32px var(--gutter) 12px;
  scrollbar-width: thin;
  scrollbar-color: var(--linea) transparent;
}

.hilo > * {
  max-width: var(--medida);
  margin-inline: auto;
}

/* Scrollbars temáticas: sin esto, el navegador dibuja la suya (gris genérico
   de sistema) sobre una interfaz que redefinió todo lo demás — el tipo de
   detalle que delata una pantalla "vestida" en vez de diseñada entera. */
.hilo::-webkit-scrollbar, .lector-cuerpo::-webkit-scrollbar { width: 10px; }
.hilo::-webkit-scrollbar-track, .lector-cuerpo::-webkit-scrollbar-track { background: transparent; }
.hilo::-webkit-scrollbar-thumb, .lector-cuerpo::-webkit-scrollbar-thumb {
  background: var(--linea);
  border-radius: var(--radio-pill);
  border: 3px solid transparent;
  background-clip: padding-box;
}
.hilo::-webkit-scrollbar-thumb:hover, .lector-cuerpo::-webkit-scrollbar-thumb:hover { background: var(--tinta-suave); }

/* --- pantalla de arranque ------------------------------------------------ */

.arranque { padding: 24px 0 8px; }

.arranque-texto {
  margin: 0 0 12px;
  color: var(--tinta-suave);
  max-width: 58ch;
}

.ejemplos {
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.ejemplos button {
  border: 1px solid var(--linea);
  background: var(--superficie);
  color: var(--acento);
  font: inherit;
  font-size: 14px;
  text-align: left;
  padding: 10px 16px;
  border-radius: var(--radio-md);
  cursor: pointer;
  box-shadow: var(--sombra-sm);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.ejemplos button:hover {
  border-color: var(--acento);
  box-shadow: var(--sombra-md);
  transform: translateY(-1px);
}

.arranque-carga-pista {
  display: inline-block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--carga);
}

/* --- mensajes ------------------------------------------------------------ */
/* Usuario y asistente se diferencian por alineación, no solo por color: el
   usuario habla en una burbuja compacta a la derecha, como en cualquier chat;
   el asistente responde a la izquierda, sin caja, porque sus respuestas
   traen tablas y bloques de código que se leen mal encajonados en un ancho
   de burbuja angosto. */

.mensaje {
  display: flex;
  flex-direction: column;
  margin-bottom: 28px;
}

.mensaje.usuario  { align-items: flex-end; }
.mensaje.asistente { align-items: stretch; }

.quien {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: 6px;
}

.mensaje.usuario .texto {
  max-width: 80%;
  background: var(--acento);
  color: #fff;
  border-radius: var(--radio-lg) var(--radio-lg) var(--radio-sm) var(--radio-lg);
  padding: 12px 16px;
  white-space: pre-wrap;
  box-shadow: var(--sombra-sm);
}

.texto > *:first-child { margin-top: 0; }
.texto > *:last-child  { margin-bottom: 0; }
.texto p  { margin: 0 0 12px; }
.texto ul, .texto ol { margin: 0 0 12px; padding-left: 22px; }
.texto li { margin-bottom: 4px; }
.texto strong { font-weight: 600; }

.texto code {
  font: 0.9em var(--mono);
  background: var(--superficie-hundida);
  padding: 1px 5px;
  border-radius: 6px;
}

.texto pre {
  margin: 0 0 12px;
  padding: 13px 15px;
  background: var(--tinta);
  color: #e6edf3;
  border-radius: var(--radio-md);
  overflow-x: auto;
}

.texto pre code {
  background: none;
  padding: 0;
  color: inherit;
  font-size: 13px;
}

/* Cursor de escritura en vivo: se agrega al final del texto que ya llegó por
   streaming, y se saca en cuanto llega el evento "final". `--acento`, no
   `--chispa`: el cian de marca mide ~1.6:1 de contraste contra el fondo claro
   de acá (medido) — ilegible como trazo fino. La chispa solo funciona sobre
   navy/teal, donde sí se usa (ver el punto en `.modo-boton` activo). */
.cursor {
  display: inline-block;
  width: 2px;
  height: 1.1em;
  margin-left: 1px;
  border-radius: 1px;
  background: var(--acento);
  vertical-align: text-bottom;
  animation: parpadeo 0.9s step-end infinite;
}

@keyframes parpadeo {
  0%, 49%  { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* Cada mensaje nuevo entra con un fade + slide corto — un solo momento
   orquestado por mensaje, no una animación en cada elemento suelto de adentro. */
.mensaje {
  animation: aparecer 0.22s ease-out both;
}

@keyframes aparecer {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* un id de ficha citado en el medio del texto: se abre sin salir del hilo.
   Azul fijo a propósito, no `--acento`: una ficha es el mismo objeto la mires
   desde Conversar o desde Carga, así que su color de "es un link" no tiene
   por qué cambiar con el modo — a diferencia de la burbuja o el cursor. */
button.cita {
  font: 0.85em var(--mono);
  background: var(--superficie-hundida);
  border: none;
  color: var(--tinta);
  padding: 2px 7px;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color .15s ease;
}

button.cita:hover { background: var(--linea-fina); }

/* --- las fichas usadas en cada respuesta --------------------------------- */

.fuentes {
  margin-top: 16px;
  border-top: 1px solid var(--linea-fina);
  padding-top: 12px;
}

.fuentes-titulo {
  font-size: 12px;
  color: var(--tinta-suave);
  margin-bottom: 8px;
}

.fuente {
  display: flex;
  align-items: baseline;
  gap: 9px;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 13.5px;
  background: var(--superficie);
  border: 1px solid var(--linea-fina);
  border-left: 3px solid var(--linea);
  border-radius: 0 var(--radio-md) var(--radio-md) 0;
  padding: 9px 13px;
  margin-bottom: 6px;
  cursor: pointer;
  transition: border-color .15s ease, box-shadow .15s ease;
}

/* Esta regla lateral es el ÚNICO lugar de la interfaz que la usa, y es a
   propósito: mapea el campo `confianza` de la ficha a un canal visual. Si el
   mismo device aparece también en avisos y errores, deja de significar algo.
   Ver los avisos más abajo: llevan borde completo justamente por esto. */
.fuente:hover { border-color: var(--linea); border-left-color: currentColor; box-shadow: var(--sombra-sm); }
.fuente.validado { border-left-color: var(--validado); }
.fuente.borrador { border-left-color: var(--borrador); }
.fuente.obsoleto { border-left-color: var(--obsoleto); }

.fuente-id {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--tinta);
  flex: none;
}

.fuente-titulo {
  color: var(--tinta-suave);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Qué escribió el agente en la base durante este turno. Es un recibo, no una
   ficha: borde completo, para no gastar acá la regla lateral que en la tira de
   fuentes significa una cosa puntual (el campo `confianza`). */
.escrituras {
  margin-top: 14px;
  font-size: 13.5px;
  border: 1px solid #e3cfa4;
  background: #fdf6e9;
  padding: 11px 14px;
  border-radius: var(--radio-md);
}

.escrituras p { margin: 0 0 4px; }
.escrituras p:last-child { margin-bottom: 0; }
.escrituras button.cita { background: #f5ead4; }

/* --- estado de espera ---------------------------------------------------- */

/* Indicador de "trabajando": un solo elemento que se reutiliza durante todo
   el turno, no solo antes del primer texto. Reaparece cada vez que el agente
   pide una herramienta a mitad de una respuesta ya empezada — antes eso
   dejaba la pantalla quieta entre el texto que ya llegó y el que sigue, sin
   ninguna señal de que el turno sigue vivo. */
.pensando {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--tinta-suave);
  font-size: 14px;
  margin-bottom: 28px;
}

.spinner {
  flex: none;
  width: 15px; height: 15px;
  border-radius: 50%;
  border: 2px solid var(--linea);
  border-top-color: var(--acento);   /* navy o teal según el modo, como el cursor */
  animation: girar 0.7s linear infinite;
}

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

.error {
  border: 1px solid #e6bcbc;
  background: #fbeeee;
  padding: 11px 14px;
  border-radius: var(--radio-md);
  font-size: 14px;
  margin-bottom: 28px;
}

/* --- subir un documento (solo modo carga) -------------------------------- */

/* Overlay de arrastrar-y-soltar. `pointer-events: none` es a propósito: sin
   eso, mover el mouse sobre el texto del overlay dispara su propio
   dragleave/dragenter y el overlay parpadea — dejarlo "transparente" al mouse
   hace que los eventos de arrastre los siga recibiendo `.conversacion`, un
   solo listener, sin lógica de conteo de profundidad. Inset en vez de
   edge-to-edge: se lee como una tarjeta flotando sobre el hilo, no como un
   marco pegado a los bordes de la ventana. */
.zona-soltar {
  position: absolute;
  inset: var(--gutter);
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--carga-suave);
  border: 2px dashed var(--carga);
  border-radius: var(--radio-lg);
  color: var(--carga);
  font-size: 15px;
  font-weight: 600;
  pointer-events: none;
}

.zona-soltar[hidden] { display: none; }

/* `display: flex` le gana a `hidden`, mismo motivo que `.lector` más abajo. */
.archivo-elegido[hidden] { display: none; }

/* Contenedor de la lista de archivos elegidos — hasta MAX_ARCHIVOS filas
   (`.archivo-item`), cada una con su propio botón de quitar. Los errores de
   validación (formato, tamaño, tope de cantidad) ya no viven acá: van al
   aviso aparte `#archivo-error` (`.aviso-chico`, compartido con el de
   dictado) para no clavar la lista de archivos ya elegidos cada vez que uno
   nuevo se rechaza. */
.archivo-elegido {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: var(--medida);
  width: calc(100% - 2 * var(--gutter));
  margin: 0 auto 10px;
  padding: 9px 14px;
  background: var(--carga-suave);
  border: 1px solid var(--carga-borde);
  border-radius: var(--radio-md);
  font-size: 13px;
  color: var(--carga);
  box-shadow: var(--sombra-sm);
}

.archivo-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.archivo-item span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Miniatura de vista previa — solo en archivos que son imagen (ver
   pintarArchivosElegidos en chat.js). Confirma de un vistazo que se
   seleccionó la captura correcta, algo que el nombre del archivo solo
   ("Screenshot_2026...png") no garantiza. */
.archivo-item img {
  flex: none;
  width: 28px;
  height: 28px;
  object-fit: cover;
  border-radius: var(--radio-sm);
}

/* Botón de cerrar/quitar: un ícono circular, no un link subrayado — mismo
   lenguaje que los íconos del compositor de abajo. */
.archivo-elegido button {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  transition: background-color .15s ease;
}

.archivo-elegido button:hover { background: rgba(0, 0, 0, .08); }
.archivo-elegido button svg { width: 14px; height: 14px; }

/* Aviso chico y transitorio, compartido por el dictado (#mic-error) y la
   validación de archivos (#archivo-error): mismo lenguaje que el resto de
   los estados de error de la app, en un formato que se auto-oculta solo. */
.aviso-chico {
  max-width: var(--medida);
  width: calc(100% - 2 * var(--gutter));
  margin: 8px auto 0;
  padding: 9px 14px;
  border-radius: var(--radio-md);
  background: #fbeeee;
  border: 1px solid #e6bcbc;
  color: var(--obsoleto);
  font-size: 12.5px;
  box-shadow: var(--sombra-sm);
}

.aviso-chico[hidden] { display: none; }

/* --- compositor ------------------------------------------------------------
   Una sola superficie tipo pill —no una fila de botones sueltos— con los
   íconos de adjuntar, dictar y enviar adentro, junto al textarea: el patrón
   que comparten los chats de IA actuales. Adjuntar y dictar son íconos
   discretos (grises, sin fondo) porque son acciones secundarias; enviar es el
   único círculo con color sólido, porque es la acción primaria del turno. */

.redaccion {
  flex: none;
  max-width: var(--medida);
  width: calc(100% - 2 * var(--gutter));
  margin: 0 auto;
  padding-top: 14px;
}

.compositor {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--radio-lg);
  padding: 6px 6px 6px 16px;
  box-shadow: var(--sombra-md);
  transition: border-color .15s ease, box-shadow .15s ease;
}

.compositor:focus-within {
  border-color: var(--acento);
  box-shadow: var(--sombra-lg);
}

body[data-modo="carga"] .compositor { border-color: var(--carga-borde); }

.compositor textarea {
  flex: 1;
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 10px 6px;
  resize: none;
  max-height: 40vh;
  outline: none;
  caret-color: var(--acento);
}

.compositor textarea::placeholder { color: var(--tinta-suave); opacity: .75; }
.compositor textarea:focus-visible { outline: none; }   /* la pill entera ya marca el foco */

/* `display: inline-flex` le gana a `hidden` si no se lo dice explícito —
   adjuntar y dictar arrancan `hidden` (uno hasta que el modo sea carga, el
   otro hasta confirmar que el navegador soporta dictado), mismo motivo que
   `.lector`/`.modos` más arriba. */
.icono-boton[hidden] { display: none; }

/* Íconos secundarios (adjuntar, dictar): círculo transparente, se tiñe recién
   al pasar el mouse — no compiten con el botón de enviar por atención. */
.icono-boton {
  position: relative;   /* ancla el anillo de "escuchando" */
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  margin-bottom: 1px;
  border-radius: 50%;
  background: none;
  border: none;
  color: var(--tinta-suave);
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}

.icono-boton svg { width: 19px; height: 19px; }

.icono-boton:hover { background: var(--superficie-hundida); color: var(--acento); }
.icono-boton:disabled { opacity: .4; cursor: default; background: none; color: var(--tinta-suave); }

.icono-boton:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--superficie), 0 0 0 4px var(--acento);
}

/* Dictado activo: mismo tratamiento de fondo sólido + punto cian que el
   selector de modo (ver el comentario de `.modo-boton[aria-pressed="true"]`
   más arriba) más un anillo que pulsa una vez y se desvanece — la única
   animación de "algo está pasando ahora mismo" de todo el compositor. */
/* `:hover` sola empataría en especificidad con `[aria-pressed="true"]` y, por
   orden de aparición, se comería el color de "escuchando" apenas el mouse
   queda encima — justo el estado en que más importa que no cambie. */
.icono-boton[aria-pressed="true"],
.icono-boton[aria-pressed="true"]:hover {
  background: var(--acento);
  color: #fff;
}

.icono-boton[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--acento);
  opacity: .6;
  animation: pulso-mic 1.6s ease-out infinite;
}

@keyframes pulso-mic {
  from { transform: scale(.85); opacity: .6; }
  to   { transform: scale(1.35); opacity: 0; }
}

/* Enviar: la única acción primaria del compositor, así que es el único
   círculo con color sólido — apagado (gris) mientras no hay nada que mandar,
   con el color de acento en cuanto hay texto o un archivo listo. */
.icono-boton-enviar {
  background: var(--linea);
  color: var(--tinta-suave);
}

.icono-boton-enviar.listo { background: var(--acento); color: #fff; }
.icono-boton-enviar.listo:hover { background: var(--acento); filter: brightness(1.08); color: #fff; }
.icono-boton-enviar:disabled { opacity: .5; background: var(--linea); color: var(--tinta-suave); }

.pista {
  flex: none;
  max-width: var(--medida);
  width: calc(100% - 2 * var(--gutter));
  margin: 8px auto 0;
  padding-bottom: 14px;
  font-size: 12px;
  color: var(--tinta-suave);
}

/* Foco de teclado de todo lo que no sea el compositor (que ya marca su propio
   foco como una sola pieza) o un objeto-ficha (ver más abajo, foco fijo). */
.ejemplos button:focus-visible,
.archivo-elegido button:focus-visible,
.modo-boton:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 2px;
}

/* Elementos de ficha (link, chip de fuente, botón del lector): foco azul fijo,
   mismo motivo que `.fuente-id` más arriba — son el mismo objeto sin importar
   el modo desde el que se los mire. */
.fuente:focus-visible,
button.cita:focus-visible,
.lector-barra button:focus-visible {
  outline: 2px solid var(--tinta);
  outline-offset: 2px;
}

/* --- lector de fichas ---------------------------------------------------- */

/* `display: flex` le gana a `hidden`, así que hay que decirlo explícito. */
.lector[hidden] { display: none; }

.lector {
  flex: none;
  width: min(46ch, 46vw);
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  box-shadow: -8px 0 28px rgba(0, 26, 84, .07);
  min-height: 0;
}

.lector-barra {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--linea-fina);
}

.lector-id {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--tinta);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lector-barra button {
  flex: none;
  font: inherit;
  font-size: 13px;
  background: none;
  border: 1px solid var(--linea);
  border-radius: var(--radio-pill);
  color: var(--tinta-suave);
  padding: 4px 14px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}

.lector-barra button:hover { border-color: var(--tinta); color: var(--tinta); }

.lector-cuerpo {
  flex: 1;
  overflow-y: auto;
  padding: 20px 22px 40px;
  font-size: 14.5px;
  scrollbar-width: thin;
  scrollbar-color: var(--linea) transparent;
}

.lector-cuerpo h2 {
  margin: 0 0 6px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
}

/* Insignia de confianza como pastilla rellena, no texto con marco — el mismo
   dato de siempre, en el lenguaje de "badge" que ya usa el resto del
   rediseño en vez de un contorno aislado. */
.sello {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .01em;
  padding: 3px 11px;
  border-radius: var(--radio-pill);
  margin-bottom: 14px;
}

.sello.validado { background: #e3f2ea; color: var(--validado); }
.sello.borrador { background: #fdf1de; color: var(--borrador); }
.sello.obsoleto { background: #fbe9e9; color: var(--obsoleto); }

/* Va inmediatamente debajo del sello de confianza, que ya lleva el color y el
   borde. Encajonarlo otra vez era repetir el mismo dato dos veces seguidas. */
.aviso-borrador {
  font-size: 13px;
  line-height: 1.5;
  color: var(--tinta-suave);
  max-width: 46ch;
  margin: 10px 0 16px;
}

.datos {
  margin: 0 0 20px;
  font-size: 13px;
  color: var(--tinta-suave);
  background: var(--papel);
  border-radius: var(--radio-md);
  padding: 12px 15px;
}

.datos div { margin-bottom: 4px; }
.datos div:last-child { margin-bottom: 0; }
.datos dfn { font-style: normal; color: var(--tinta); }

.lector-cuerpo h3 {
  margin: 24px 0 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--tinta);
}

.lector-cuerpo p { margin: 0 0 11px; }
.lector-cuerpo ul, .lector-cuerpo ol { margin: 0 0 11px; padding-left: 21px; }
.lector-cuerpo li { margin-bottom: 3px; }

.lector-cuerpo code {
  font: 0.9em var(--mono);
  background: var(--superficie-hundida);
  padding: 1px 5px;
  border-radius: 6px;
}

.lector-cuerpo pre {
  margin: 0 0 11px;
  padding: 12px 14px;
  background: var(--tinta);
  color: #e6edf3;
  border-radius: var(--radio-md);
  overflow-x: auto;
}

.lector-cuerpo pre code { background: none; padding: 0; color: inherit; font-size: 12.5px; }

.lector-cuerpo table {
  border-collapse: collapse;
  width: 100%;
  font-size: 13px;
  margin: 0 0 11px;
}

.lector-cuerpo th, .lector-cuerpo td {
  border: 1px solid var(--linea-fina);
  padding: 6px 9px;
  text-align: left;
  vertical-align: top;
}

.lector-cuerpo th { background: var(--papel); font-weight: 600; }

/* Los bloques de comentario HTML (HISTORIAL, PENDIENTE DE CONFIRMAR) son parte
   del método de captura, no ruido: se muestran, distinguidos del contenido. */
.anotacion {
  font-size: 13px;
  color: var(--tinta-suave);
  background: var(--papel);
  border: 1px dashed var(--linea);
  border-radius: var(--radio-md);
  padding: 10px 13px;
  margin: 0 0 11px;
  white-space: pre-wrap;
}

/* --- angosto: el lector pasa a taparlo todo ------------------------------ */

@media (max-width: 860px) {
  .lector {
    position: fixed;
    inset: 0;
    width: auto;
    z-index: 10;
  }
}

/* --- angosto: el header no entra en una fila si trae los tres bloques ---- */

@media (max-width: 480px) {
  :root { --gutter: 16px; }

  /* El nombre de la pantalla ("Base de conocimiento") es redundante con el
     logo cuando el espacio es tan poco — se saca, no se envuelve, para que
     el selector de modo (lo que de verdad importa mirar) no compita por
     lugar en la misma fila. */
  .barra h1 { display: none; }

  /* El contador de fichas/modelo y el bloque de sesión pasan a su propia
     fila, alineados a la izquierda como todo lo demás — a la derecha de una
     fila angosta quedaban apretados contra el borde. */
  .estado {
    flex-basis: 100%;
    margin-left: 0;
    order: 3;
  }

  .sesion {
    margin-left: auto;
    padding-left: 0;
    border-left: none;
    order: 4;
  }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}
