/* ==========================================================================
   LeadSync - Configuracion
   La modal de Configuracion con sus secciones, la Ayuda, los avisos del bot y la
   pestana de Memoria.

   OJO CON EL ORDEN: estos ficheros se enlazan en index.html en un orden concreto y
   ese orden ES la cascada. Mover un enlace de sitio cambia que regla gana entre dos
   de la misma especificidad. Si anades uno nuevo, ponlo donde le toque, no al final.
   ========================================================================== */

/* --- Modal de Configuración con secciones (item 8) ------------------------- */

/* La modal crece a lo ancho: el panel izquierdo necesita sitio y así el derecho no
   estrangula los textos de ayuda. */

/* `.modal-card` fija width:420px y se declara MÁS ABAJO, así que con la misma
   especificidad ganaría por orden: hay que calificar con .modal-card (como .starred-modal). */
.modal-card.settings-modal {
  width: min(96vw, 860px);
  max-width: 860px;
}
.modal-card.settings-modal .modal-body {
  padding: 0;
  overflow: hidden;
}
.settings-shell {
  display: grid;
  grid-template-columns: 226px 1fr;

  /* La fila se acota EXPLÍCITAMENTE. Con el `auto` implícito se dimensiona al contenido,
     así que crecía más que el shell y el max-height solo la RECORTABA: por eso "Usuarios"
     salía partido en b_10.png (item 48) en vez de aparecer un scroll. */
  grid-template-rows: minmax(0, 1fr);
  min-height: 62vh;
  max-height: 72vh;
}

/* Y cada panel scrollea por su cuenta. `min-height: 0` es la otra mitad: un hijo de grid
   arranca en min-height:auto, que le impide encogerse por debajo de su contenido. */
.settings-rail,
.settings-pane {
  min-height: 0;
  overflow-y: auto;
}
.settings-rail {
  border-right: 1px solid var(--border);
  background: var(--bg);
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.settings-rail .seg-control { margin-bottom: 8px; }
.rail-group {
  margin: 0 0 8px 0;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 7px;
}
.rail-group:first-child { margin-top: 2px; }
.rail-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  border: none;
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  color: var(--text);
  font: inherit;
  transition: background-color .12s ease;
}
.rail-item:hover { background: var(--bg-hover); }
.rail-item[aria-selected="true"] {
  background: var(--accent-dim);
  color: var(--accent-strong);
  font-weight: 600;
}
.rail-item .ic {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
}
.rail-lbl {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-tag {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--warn-bg);
  color: var(--warn);
  border: 1px solid var(--warn);
}
/* SIN RELLENO ARRIBA: lo pone la cabecera pegajosa. Un `position: sticky` con `top: 0` se
   pega al borde del RELLENO del scrollport, no al del contenedor, asi que con 18px aqui la
   barra se quedaba 18px mas abajo y el contenido se veia pasar por ese hueco.

   Y EL RELLENO LATERAL ES UNA VARIABLE porque la barra lo compensa con un margen negativo:
   son el mismo numero escrito dos veces, y en cuanto uno cambio -la regla de movil lo bajaba
   a 14px- la barra dejo de llegar a los bordes. Un hecho, un sitio. */
.settings-pane {
  --pane-pad: 22px;
  padding: 0 var(--pane-pad) 24px;
}
/* LA CABECERA DEL APARTADO SE QUEDA PEGADA ARRIBA, y con ella el boton de guardar.
   Estaba al final del panel y habia que bajar a buscarlo: "se me olvido 3 veces y nunca se
   guardo nada". Un boton que hay que ir a buscar se olvida.
   El fondo es OPACO a proposito: el panel scrollea por debajo. */
.settings-pane .pane-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  /* De borde a borde: el relleno lateral del panel se compensa con margen negativo, y el de
     arriba lo pone esta barra (el panel ya no lo lleva). */
  margin: 0 calc(-1 * var(--pane-pad));
  padding: 18px var(--pane-pad) 10px;
  background: var(--bg-panel);
}

/* Las acciones del apartado, a la derecha del titulo. */
.pane-acciones {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}
/* "Sin guardar" se DICE, no se deja al color de un boton: un boton encendido no explica QUE
   esta pendiente. */
.pane-sucio {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--warn);
}
.settings-pane .pane-head h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 650;
}
.settings-pane .pane-sub {
  margin: 5px 0 16px;
  color: var(--text-dim);
  font-size: 13px;
}
.settings-back { display: none; }
.cfg-field {
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.cfg-field:first-child {
  border-top: none;
  padding-top: 2px;
}
/* EL AJUSTE SE PARTE EN DOS CUANDO NO CABE EN UNA. Con la fila en una sola linea, el texto
   se quedaba en una columna de 80 px y caia una palabra por renglon; el control, entero al
   lado. En movil era ilegible y pasaba en TODOS los ajustes, no solo en el del modo.

   SIN MEDIA QUERY, a proposito: lo que decide no es el ancho de la PANTALLA sino el de la
   caja donde vive el ajuste -la modal, el panel, el chat-, y una media query no sabe de eso.
   Con `flex-wrap` y un suelo en el bloque de texto, el navegador reparte solo: mientras el
   texto tenga sus 260 px, control al lado; cuando no, el control baja a su propia linea. */
.cfg-field-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  row-gap: 10px;
}
.cfg-field-main {
  /* EL TEXTO TIENE UN MINIMO Y SOLO BAJA LO QUE NO CABE. Con `flex-basis: 260px` bajaban
     TODOS -hasta "Imagenes", que cabe de sobra con su interruptor al lado-, y la pantalla
     quedaba a dos filas por ajuste. Lo dijo el: *"es solo lo que no cabe, el texto debe
     tener un minimo de ancho, y si ese ancho rompe el espacio, entonces salta de linea"*.

     `flex: 1 1 auto` con `min-width` hace exactamente eso: mientras al texto le queden sus
     180 px, el control se queda al lado; cuando el control es tan ancho que no se los deja
     -un `select`, no un interruptor-, baja a su propia linea. */
  flex: 1 1 auto;
  min-width: 180px;
}
.cfg-field-name { font-weight: 600; }
.cfg-field-help {
  color: var(--text-dim);
  font-size: 12.5px;
  margin-top: 3px;
}
.cfg-sw { flex: 0 0 auto; }

/* --- Casilla dentro de un ajuste (item A76) -------------------------------
   No es el interruptor de .cfg-sw, que va a la derecha del titulo y vale para un si/no
   evidente. Esto es una ELECCION que necesita su frase al lado, asi que la casilla y el
   texto van juntos y en su propia linea. */
.cfg-check {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 8px;
  font-size: 13px;
  cursor: pointer;
}

.cfg-check input {
  width: auto;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Desactivada, el texto tambien se apaga: si no, parece que se puede pulsar. */
.cfg-check input:disabled { cursor: default; }
.cfg-check input:disabled + span { color: var(--text-dim); cursor: default; }

/* El motivo por el que algo NO se puede hacer se distingue del consejo de al lado: uno
   explica y el otro impide. */
.cfg-aviso {
  margin-top: 6px;
  padding: 7px 10px;
  border-radius: 8px;
  background: var(--warn-bg);
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent);
  color: var(--text);
}

/* item 59: píldora de estado de un ajuste que NO se decide aquí (el permiso de avisos lo
   da el navegador). Neutra por defecto, verde cuando está en orden y roja cuando bloquea. */
.cfg-state {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .3px;
  padding: 3px 9px;
  border-radius: 8px;
  background: var(--bg-hover);
  color: var(--text-dim);
}
.cfg-state.ok {
  background: var(--accent-dim);
  color: var(--author-bot);
}
.cfg-state.off { color: var(--danger); }

/* item 60: titularidad y condiciones de uso. Discreto en el inicio de sesión —tiene que
   estar, no tiene que gritar— y legible en la ventana de condiciones. */
.auth-legal {
  display: block;
  margin-top: 14px;
  font-size: 11px;
  color: var(--text-dim);
}
.legal-doc {
  max-height: 60vh;
  overflow-y: auto;
}
.legal-h {
  margin: 16px 0 4px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}
.legal-h:first-of-type { margin-top: 12px; }
.legal-foot {
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--text-dim);
}

/* Herencia global → personal: mientras manda el equipo, el bloque se ve pero no se toca. */
.cfg-inherit { transition: opacity .16s ease; }
.cfg-inherit.locked { opacity: .45; }
.modal-note {
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: 9px;
  font-size: 12.5px;
  line-height: 1.5;
  background: var(--info-bg);
  border: 1px solid var(--info-border);
  color: var(--text);
}

/* Cambio de sección en escritorio: un matiz corto para que el ojo siga el cambio. */
@keyframes cfgSwap {
  from {
    opacity: 0;
    transform: translateY(5px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.settings-pane.swapping { animation: cfgSwap .16s ease; }

/* En móvil el detalle SUSTITUYE a la lista, así que entra y sale con movimiento: si
   apareciera de golpe no se vería de dónde salió. Animación CSS y no transición desde
   rAF: si el frame no llega a correr, una transición dejaría el panel invisible. */
@keyframes cfgPaneIn {
  from {
    opacity: 0;
    transform: translateX(26%);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes cfgPaneOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(26%);
  }
}
@keyframes cfgRailIn {
  from {
    opacity: 0;
    transform: translateX(-18%);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* item 77: navegación lista↔chat en móvil. El chat entra desde la derecha y sale por ahí
   mismo; la lista vuelve desde la izquierda. Los porcentajes son suaves a propósito: un
   100% se siente como un cambio de página y esto es una sola pantalla que se desplaza. */
@keyframes chatIn {
  from {
    opacity: 0;
    transform: translateX(22%);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes chatOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(22%);
  }
}
@keyframes listIn {
  from {
    opacity: 0;
    transform: translateX(-16%);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (max-width: 720px) {
  .modal-card.settings-modal { width: 96vw; }
  .settings-shell {
    grid-template-columns: 1fr;
    min-height: 60vh;
    overflow: hidden;
  }
  .settings-rail { border-right: none; }
  .settings-pane {
    display: none;
    /* SIN RELLENO ARRIBA, igual que en escritorio: aqui estaba el fallo. Se puso 16px y la
       cabecera pegajosa se quedaba 16px por debajo del borde, con el contenido pasando por
       el hueco. Lo lateral va por la variable para que la barra siga llegando a los bordes. */
    --pane-pad: 14px;
    padding: 0 var(--pane-pad) 20px;
  }
  .settings-shell.drill .settings-rail { display: none; }
  .settings-shell.drill .settings-pane {
    display: block;
    animation: cfgPaneIn .2s ease;
  }
  .settings-shell:not(.drill) .rail-item[aria-selected="true"] {
    background: none;
    color: inherit;
    font-weight: inherit;
  }
  .settings-shell.leaving .settings-pane { animation: cfgPaneOut .18s ease forwards; }
  .settings-rail.entering { animation: cfgRailIn .2s ease; }
  .settings-back {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    color: var(--accent-strong);
    cursor: pointer;
    /* El panel ya no lleva relleno arriba (lo pone la cabecera pegajosa), asi que este
       boton lo pone para si. */
    padding: 14px 0 10px;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
  }
  .settings-back .ic {
    width: 16px;
    height: 16px;
  }

  /* item 75: en móvil, estando en la LISTA no hay ninguna sección abierta, así que ninguna
     puede salir resaltada. En escritorio el resaltado sí dice algo —el panel de esa sección
     está a la vista, a la derecha—; aquí, al volver, señalaba "estás en Acerca de" cuando
     ya no estabas. Es el mismo fallo que el del ojito: un estado visual que sobrevive a la
     navegación que lo hizo falso.
     Se corrige en CSS y no tocando `actual` a propósito: el estado sigue siendo verdad
     (esa ES la última sección abierta y a la que se vuelve), lo único que no vale es
     PINTARLO cuando su panel no se ve. */

  /* Durante la salida el panel sigue montado: se le deja terminar antes de ocultarlo. */
}

/* Fila de ajuste con un botón a la derecha (item 36: horario de atención). */
.settings-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.settings-row > span:first-child {
  flex: 1;
  min-width: 0;
}

/* Editor del horario de atención. */
.hours-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.hours-label {
  flex: 1;
  min-width: 0;
}
.hours-sep {
  color: var(--text-dim);
  font-size: 13px;
}
.hours-preview {
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--info-bg);
  border: 1px solid var(--info-border);
  color: var(--text);
  font-size: 13px;
  line-height: 1.45;
}
.cfg-select {
  flex: 0 0 auto;
  min-width: 112px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text);
  font-size: 13px;
  outline: none;
  cursor: pointer;
  transition: border-color .15s ease;
}
.cfg-select:focus { border-color: var(--accent); }
.cfg-select option {
  background: var(--bg-panel);
  color: var(--text);
}

/* Instrucciones del bot (item 40): textos largos, así que el control va DEBAJO del rótulo
   y a todo el ancho, no a la derecha como los interruptores y los selects. Lo mismo vale
   para los campos de una línea de "Mi cuenta" (.cfg-input, item 58): comparten el aspecto
   para que el panel no tenga dos estilos de caja de texto. */
.cfg-textarea,
.cfg-input {
  display: block;
  width: 100%;
  margin-top: 10px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.5;

  /* Sin agarradera de redimensionar: el alto lo decide el diseño (rows), y arrastrarla
     descuadra el panel de configuración. */
  resize: none;
  outline: none;
  transition: border-color .15s ease;
}
.cfg-textarea:focus,
.cfg-input:focus {
  border-color: var(--accent);
}
.cfg-textarea::placeholder,
.cfg-input::placeholder {
  color: var(--text-dim);
}
.cfg-count-warn { color: var(--warn, #e0a33e); }

.cfg-bot-firma-campo:not([hidden]) {
  animation: cfgBotFirmaEntra 180ms ease-out;
}
@keyframes cfgBotFirmaEntra {
  from { opacity: 0; transform: translateY(-5px); }
}
/* Separa el interruptor de la explicación de arriba: sin margen quedaba pegado. */
.cfg-bot-firma-fila { margin-top: 14px; }
.cfg-bot-firma-campo .cfg-field-help { margin: 8px 0 5px; }
@media (prefers-reduced-motion: reduce) {
  .cfg-bot-firma-campo:not([hidden]) { animation: none; }
}
.cfg-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
@keyframes dirty-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* El plegable de "avanzado" comparte armazón con el de Odoo: mismo componente, un solo
   sitio donde tocarlo (mandato de componentes globales). */
.cfg-advanced {
  border-top: 1px solid var(--border);
  padding-top: 10px;
  margin-top: 14px;
}

/* item 66: los <details> de la consola abrían y cerraban de golpe. La animación de ENTRADA
   corre sola al aparecer los hijos; la de SALIDA la habilita wireDetails (ui.js), que
   retrasa el cierre real hasta que termina. Animación y no transición: si no llega a
   correr, el elemento queda en su estado natural en vez de a medias. */
.acc-anim[open] > :not(summary) { animation: acc-in .24s ease-out; }
.acc-anim.closing > :not(summary) { animation: acc-out .18s ease-in; }
@keyframes acc-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}
@keyframes acc-out {
  to {
    opacity: 0;
    transform: translateY(-6px);
  }
}

/* Quien pide menos movimiento se queda sin animación, pero el acordeón sigue funcionando. */
@media (prefers-reduced-motion: reduce) {
  .acc-anim[open] > :not(summary),
  .acc-anim.closing > :not(summary) {
    animation: none;
  }
}

/* --- Sección "Ayuda" de Configuración --- */

/* Es el único sitio de la consola que se LEE de arriba abajo, así que aquí manda la
   legibilidad: renglón más alto, ancho de línea acotado y nada de controles. */
.help-intro {
  margin: 0 0 14px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.6;
}
.help-search { margin-bottom: 12px; }
.help-search input {
  width: 100%;
  box-sizing: border-box;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
  color: var(--text);
  font-size: 13.5px;
  outline: none;
  transition: border-color .15s ease;
}
.help-search input:focus { border-color: var(--accent); }
.help-search input::-webkit-search-cancel-button { filter: invert(.5); }

/* La línea divisoria de antes la sustituye la TARJETA (ver más abajo, .help-item): con
   filas separadas por una raya, seis acordeones seguidos se leían como una lista. */

/* 12px POR LOS CUATRO LADOS. Los 2px de los costados venían de cuando esto era una lista
   plana, donde el aire lo ponía el ancho del panel; dentro de una tarjeta ese mismo valor
   deja el texto pegado al borde. Es el escalón de la escala que toca para una tarjeta. */
.help-item > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.help-item > summary::-webkit-details-marker { display: none; }
.help-item > summary:hover .help-t { color: var(--accent); }
.help-ic {
  flex: 0 0 auto;
  display: flex;
  color: var(--text-dim);
}
.help-ic .ic {
  width: 17px;
  height: 17px;
}
.help-head {
  flex: 1;
  min-width: 0;
}
.help-t {
  display: block;
  font-weight: 600;
  transition: color .12s ease;
}
.help-s {
  display: block;
  margin-top: 2px;
  color: var(--text-dim);
  font-size: 12.5px;
}

/* La flecha gira al abrir: es la señal de que ese renglón esconde algo, y girar cuesta
   menos de leer que cambiar el icono por otro. */
.help-chev {
  flex: 0 0 auto;
  display: flex;
  color: var(--text-dim);
  transition: transform .2s ease;
}
.help-chev .ic {
  width: 16px;
  height: 16px;
}
.help-item[open] > summary .help-chev { transform: rotate(180deg); }

/* El cuerpo arranca donde arranca el TÍTULO (12 de padding + 17 del icono + 12 del hueco
   = 41), no en el borde de la tarjeta: así el texto cuelga del nombre del tema en vez de
   flotar por debajo del icono. */
.help-body {
  padding: 0 12px 12px 41px;
  font-size: 13px;
  line-height: 1.6;
}
.help-body p {
  margin: 0 0 10px;
  color: var(--text-dim);
}
.help-body b {
  color: var(--text);
  font-weight: 600;
}
.help-body code {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 12px;
  background: var(--bg-hover);
  padding: 1px 5px;
  border-radius: 5px;
  color: var(--text);
}

/* Cada "cosa" y su explicación en dos columnas: el ojo baja por los nombres y solo lee
   la fila que buscaba. En móvil se apilan, que a 375px dos columnas dejan tres palabras. */
.help-def {
  display: grid;
  grid-template-columns: 148px 1fr;
  gap: 4px 12px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
}
.help-def:first-of-type { border-top: none; }
.help-def > b {
  color: var(--text);
  font-weight: 600;
}
.help-def > span { color: var(--text-dim); }
.help-def .rail-tag {
  margin-left: 4px;
  vertical-align: 1px;
}
.help-empty {
  margin: 18px 2px;
  color: var(--text-dim);
  font-size: 13px;
}

/* Filtrar cambia la lista entera, así que el resultado ENTRA en vez de aparecer de golpe:
   sin eso no se distingue "se filtró" de "no pasó nada". Animación y no transición, para
   que si no llega a correr la lista quede visible igualmente. */
.help-list.filtering { animation: helpFilter .16s ease-out; }
@keyframes helpFilter {
  from {
    opacity: .35;
    transform: translateY(3px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .help-list.filtering { animation: none; }
  .help-chev { transition: none; }
}
@media (max-width: 640px) {
  .help-def {
    grid-template-columns: 1fr;
    gap: 2px;
  }
  .help-body { padding-left: 12px; }
}

/* --- Notificaciones de acciones del bot (item 3) --- */

/* Campanita con contador. */
.notif-btn { position: relative; }

/* ROJO y no verde (decisión del 11-08): el verde es el color de la marca y está por
   todos lados —el badge de no leídos, los botones—, así que un contador verde sobre un
   icono verde no destaca. El rojo de aviso contrasta con TODO lo demás de la consola, y
   además es lo que ya usa el favicon con no leídos: mismo significado, mismo color. */
.notif-count {
  position: absolute;
  top: -3px;
  right: -5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  box-sizing: border-box;
  border-radius: 999px;
  background: var(--info);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  pointer-events: none;
}

/* Campanita en la lista: notificaciones del bot pendientes (≠ no leídos). Mismo AZUL que el
   contador de la campanita del rail: son la misma cosa contada en dos sitios, y el icono de la
   campana es intuitivo y se distingue inmediatamente del círculo rojo de mensajes sin leer.

   Es un botón y no un adorno: lleva a las notificaciones de ese chat, que es donde se
   revisan y donde dejan de estar pendientes. */
.notif-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: var(--info);
  background: none;
  border: 0;
  padding: 0;
  flex: 0 0 auto;
  cursor: pointer;
  border-radius: 4px;
  line-height: 0;
  position: relative;
  transition: color .15s ease, background .15s ease, filter .15s ease;
}

.notif-dot .ic {
  width: 14px;
  height: 14px;
  display: block;
}

/* Área de pulsación amplia para accesibilidad (WCAG 2.2) */
.notif-dot::before {
  content: "";
  position: absolute;
  inset: -4px;
}

.notif-dot:hover,
.notif-dot:focus-visible {
  background: var(--info-bg);
  filter: brightness(1.2);
}

/* La (i) de la cabecera de la bandeja: abre la leyenda de los colores. Va pegada al título
   y no al borde: explica ESE título, no la bandeja entera. */
.notif-info-btn {
  background: none;
  border: 0;
  padding: 2px;
  margin-right: auto;
  display: inline-flex;
  align-items: center;
  color: var(--text-dim);
  cursor: pointer;
  border-radius: 6px;
  line-height: 0;
}

.notif-info-btn:hover,
.notif-info-btn:focus-visible { color: var(--text); background: var(--bg-hover); }
.notif-info-btn svg { width: 15px; height: 15px; }

/* La leyenda de los indicadores. Se despliega bajo la cabecera de la bandeja. */
/* ES UN POPOVER, no un bloque que se despliega dentro de la bandeja.

   Lo pediste asi explicitamente y la primera version salio acordeon: se abria EN SITIO y
   empujaba la lista hacia abajo, o sea que consultar que significa un color te movia justo lo
   que estabas mirando. Un popover sale encima, se lee, se cierra, y no ha movido nada.

   Cuelga del <body> (lo hace notifications.js) y se coloca con positionFloating, como el
   resto de flotantes de la consola. De ahi el `position: fixed`: dentro del panel heredaria
   su recorte y su ancho — es el mismo motivo por el que los menus de openMenu viven fuera, y
   lo vigila check-menus-fijos.py. */
.notif-leyenda {
  position: fixed;
  /* POR ENCIMA DE LA BANDEJA (que va en 260). Con 80 el popover salia DETRAS del panel del
     que cuelga: se abria y no se veia, que es peor que no abrirse. */
  z-index: 280;
  width: min(340px, calc(100vw - 24px));
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 32px var(--shadow);
  background: var(--bg-elev);
  display: grid;
  gap: 10px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-dim);
  animation: leyenda-entra 180ms ease-out;
}

.notif-leyenda.cerrando { animation: leyenda-sale 160ms ease-in forwards; }

.notif-leyenda b { color: var(--text); font-weight: 600; }

/* La muestra se alinea con la PRIMERA línea del texto, no con el centro del párrafo: con
   tres líneas, centrada, el circulito acababa a la altura de la segunda. */
.notif-leyenda-fila {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 8px;
  align-items: start;
}

.notif-leyenda-fila > :first-child { margin-top: 1px; justify-self: center; }
/* En la leyenda es una muestra, no un botón: ni se pulsa ni necesita área de pulsación. */
.notif-leyenda .notif-dot { cursor: default; pointer-events: none; }
.notif-leyenda .notif-dot::before { content: none; }

/* El verde de "cuántas hay": el mismo del contador de los filtros. */
/* La muestra del recuento SIN circulo, porque es justo lo que explica: un numero pelado no
   pide nada. Se llamaba `.leyenda-verde` cuando era una pastilla verde. */
.leyenda-cuenta {
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 700;
  min-width: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

@keyframes leyenda-entra {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

@keyframes leyenda-sale {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(-6px); }
}

/* Quien pide menos movimiento ve el cambio, no el desplazamiento. */
@media (prefers-reduced-motion: reduce) {
  .notif-leyenda { animation: none; }
  .notif-leyenda.cerrando { animation: none; }
}

/* Bandeja global bajo la campanita. */
.notif-panel {
  position: fixed;
  z-index: 260;
  width: 340px;
  max-width: calc(100vw - 16px);
  max-height: 60vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 10px 30px var(--shadow);
  animation: menuIn .13s ease;
}
.notif-panel-head {
  display: flex;
  align-items: center;
  /* EL BOTON DE LA LEYENDA VA CON SU ROTULO, NO PEGADO A EL. Con `space-between` a secas, la
     interrogacion quedaba lamiendo la "s" de "Notificaciones" —se lee como parte de la
     palabra— y todo el hueco se iba al otro lado. El separador se pone con `gap`, y a
     "Marcar todas leidas" se le manda al extremo con su propio `margin-left: auto`: asi cada
     cosa esta donde tiene que estar y no donde la deje el reparto. */
  gap: 6px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  font-size: 13px;
}
.notif-panel-head .link-btn { margin-left: auto; }

/* "3 de 15" (item B25): va PEGADO AL TITULO, no al otro extremo, porque explica el
   numero que se acaba de mirar en la campanita. En gris y mas pequeno que el rotulo: es
   una aclaracion, no un segundo titulo. */
.notif-panel-conteo {
  font-weight: 500;
  font-size: 11.5px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.notif-panel-list {
  overflow-y: auto;
  padding: 4px;
  /* Las filas de aviso van pegadas entre si (se separan por su propio relleno), asi que el
     componente de lista partida no tiene que anadir hueco: solo la raya del acordeon.
     Se declara igualmente para que el contrato de `listapartida.css` este dicho aqui y no
     se herede por accidente de otro sitio (item B76). */
  --lp-gap: 0px;
}

/* Fila de notificación (bandeja y pestaña). */
.notif-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 10px;
  border-radius: 8px;

  /* Sin este margen, dos filas resaltadas seguidas se ven como un solo bloque de color. */
  margin-bottom: 4px;
}
.notif-row:last-child { margin-bottom: 0; }
.notif-panel .notif-row { cursor: pointer; }
.notif-panel .notif-row:hover { background: var(--bg-hover); }

/* item 12: en la pestaña del chat, la fila con ancla lleva a su burbuja. */
.notif-row.linkable { cursor: pointer; }
.notif-row.linkable:hover { background: var(--bg-hover); }
.notif-row.unread { background: var(--accent-dim); }

/* Un color por TIPO de notificación (item 29): distinguirlas de un vistazo, sin tener que
   leer el texto de cada una. El icono va en un círculo teñido de su propio color. */
/* EL ICONO VA DEL COLOR QUE DICE LA LEYENDA, y no de uno propio por cada tipo.

   Tenia seis: naranja para transferencia, ambar para espera, lila para vinculo, turquesa
   para memoria... Seis colores que no significaban nada fuera de esta lista y que ademas
   CHOCABAN con los tres que la leyenda explica. Lo dijo asi: *"eso de los 3 colores es un
   poco confuso en notificaciones, creo que es mejor que si es azul, en notificaciones el
   icono y su circulo sea azul, o sea que sea de su color correspondiente, para que se
   entienda que ok este es azul, lo hizo el bot"*.

   Tiene razon: el color tiene que querer decir lo MISMO en toda la consola. Aqui todo lo que
   se lista es algo que hizo el bot o el sistema, y eso en LeadSync es azul —el mismo del
   cuadrado de la lista de chats y del contador de la campanita—. Lo que distingue un tipo de
   otro es el ICONO y el texto, que es para lo que sirven.

   Las dos que significan "alguien esta esperando a una persona" si se salen, porque eso no es
   informacion, es trabajo pendiente: llevan el mismo rojo que los mensajes sin leer. */
.notif-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  color: var(--info);
  background: color-mix(in srgb, currentColor 16%, transparent);
}
.notif-ic .ic {
  width: 15px;
  height: 15px;
}
.notif-ic.k-transferencia,
.notif-ic.k-espera { color: var(--notif); }

/* Barra de filtros por tipo: reusa el chip de la lista de chats (.filter-tab). */
.notif-filters { padding: 2px 2px 8px; }
.notif-panel .notif-filters { padding: 6px 6px 8px; }
.notif-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.notif-chat {
  font-weight: 600;
  font-size: 12.5px;
}
.notif-text {
  font-size: 12.5px;
  color: var(--text);
  overflow-wrap: anywhere;
}
.notif-time {
  font-size: 11px;
  color: var(--text-dim);
}

/* --- Pestaña Memoria (item 23) --- */
.mem-add.ses-nota {
  margin-top: 0;
  margin-bottom: 14px;
}
.mem-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mem-row {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--bg-panel);
  min-width: 0;
  transition: border-color .16s ease, background-color .16s ease;
}
.mem-row:hover { border-color: var(--accent); }
.mem-open {
  display: block;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.mem-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.mem-open[hidden] { display: none; }
.mem-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 10;
  overflow: hidden;
  line-height: 1.45;
  font-size: 13px;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.mem-text b { font-weight: 700; color: var(--text); }
.mem-text i { font-style: italic; }
.mem-text s { text-decoration: line-through; }
.mem-text code { font-family: var(--font-mono); font-size: .9em; padding: 1px 4px; border-radius: 4px; background: var(--bg-elev); }
.mem-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-dim);
}
.mem-by {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 600;
  padding: 2px 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-elev);
}
.mem-by.bot { color: var(--accent); }
.mem-by .ic {
  width: 12px;
  height: 12px;
}
.mem-actions {
  margin-left: auto;
  display: inline-flex;
  gap: 2px;
}
.mem-actions .icon-btn {
  width: 26px;
  height: 26px;
}
.mem-actions .ic {
  width: 14px;
  height: 14px;
}
.mem-carrusel { width: 100%; }
.mem-detalle { padding: 2px; }
.mem-detail-editor.ses-nota {
  margin: 14px 0;
}
.mem-jump { width: 100%; justify-content: center; }
.mem-no-origin { color: var(--text-dim); font-size: 12px; }
@media (prefers-reduced-motion: reduce) {
  .mem-row { transition: none; }
}

/* Memoria apartada (item 40): sigue ahí y se puede leer y reactivar, pero el bot no la
   usa. Se apaga sin esconderla — tacharla la haría ilegible, y el punto es poder leerla. */
.mem-off {
  opacity: .55;
  border-style: dashed;
}
.mem-off .mem-text {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.mem-off-tag {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 7px;
  font-size: 10.5px;
  text-transform: lowercase;
}

/* Numerito de la pestaña Notificaciones del panel.

   LLEVA PASTILLA PORQUE CUENTA LO NO LEIDO, no el total: ahi la pastilla dice la verdad. Y va
   AZUL y no verde porque lo que cuenta son acciones del BOT, que es el azul de toda la
   consola — el mismo del cuadrado de la lista y del contador de la campanita. En verde, el
   mismo dato tenia un color distinto segun donde se mirara. */
.tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  margin-left: 4px;
  border-radius: 999px;
  background: var(--info);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  vertical-align: middle;
}

/* 12px entre acciones: son un grupo de controles relacionados, no bloques distintos. Con
   16px se leían como cuatro islas sueltas y en móvil con 8px se tocaban entre sí (b_23);
   el mismo valor en las dos pantallas es lo que las hace consistentes. */
.chat-header-actions {
  /* La separación entre acciones, en un solo sitio: la consume el `gap` de aquí abajo y el
     SUELO de la caja (layout/chat.css), que cuenta los dos botones fijos con su hueco. */
  --gap-acciones: 12px;

  display: flex;
  align-items: center;
  gap: var(--gap-acciones);

  /* PEGADAS A LA DERECHA. Sin esto los botones se apilaban al principio de su caja y,
     cuando la caja era más ancha que ellos —el caso de "Mensajes guardados", que esconde
     casi todos—, quedaba un hueco grande entre el último botón y el borde. Se veía como
     si faltara algo ahí. */
  justify-content: flex-end;

  /* AQUÍ NO VA EL `min-width`. Estaba puesto a 0 y, como esta hoja se carga DESPUÉS que
     layout/chat.css, ganaba por orden y anulaba el suelo que impide que se recorten el
     panel y los tres puntos. Es el mismo tropiezo que ya avisa el comentario de
     badges.css: un hecho declarado en dos sitios acaba en dos verdades. El reparto de la
     cabecera se toca en layout/chat.css, que es donde vive. */
}

/* La usa overflowbar.js para sacar algo de la barra. `display: none` y no `visibility`:
   tiene que dejar de OCUPAR, que es de lo que va todo esto. */
.of-oculto { display: none !important; }

/* "Ver más" — la puerta a la ficha de Odoo, las notificaciones y la memoria del cliente.
   Estaba en gris sobre gris, con un contorno que casi no se distinguía del fondo de su
   contenedor: siendo la entrada a media consola, tiene que verse. Va con el color de
   acento —el mismo que ya manda en el resto de la interfaz, así resalta sin inventarse un
   color nuevo—: contorno en reposo, y RELLENO al pasar por encima y mientras el panel está
   abierto, que es un estado y no un hover. */
.ghost-btn {
  background: transparent;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

/* El texto sobre el acento va con --on-accent, el token que el tema ya define para eso
   (en claro es blanco; en oscuro, casi negro, que es lo que se lee sobre este verde). */
.ghost-btn:hover,
.ghost-btn.active {
  background: var(--accent);
  color: var(--on-accent);
}
.ghost-btn .ic {
  width: 16px;
  height: 16px;
}
.bot-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  color: var(--text-dim);
}
.bot-toggle input { display: none; }
.slider {
  width: 38px;
  height: 20px;
  background: var(--bg-hover);
  border-radius: 20px;
  position: relative;
  transition: background-color .15s ease;

  /* Nunca encoger: junto a una etiqueta larga (los switches de configuración) el flex
     lo estrujaba y el knob, que viaja 18px, se salía del carril. */
  flex: 0 0 auto;
}
.slider::before {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-dim);
  top: 2px;
  left: 2px;
  transition: transform .15s ease, background-color .15s ease;
}
.bot-toggle input:checked + .slider { background: var(--accent-dim); }

/* EN ASISTENCIA EL INTERRUPTOR SE TINE DE AZUL (revision del 09-09). Encendido y modo son
   dos ejes: el interruptor dice si el bot participa, el color en que modo lo hace. Sin esto
   habria que leer el desplegable del menu para saberlo, y el interruptor mentiria por
   omision - se veria igual redactando sugerencias que respondiendo solo.

   El azul es el MISMO --modo-asistencia que usan el punto del menu, el distintivo de la
   lista y el borde del selector (item A4): una excepcion de color aqui rompe la leyenda que
   esos tres construyen. */
.bot-toggle.modo-asistencia input:checked + .slider {
  background: color-mix(in srgb, var(--modo-asistencia) 30%, transparent);
}
.bot-toggle.modo-asistencia input:checked + .slider::before {
  background: var(--modo-asistencia);
}
.bot-toggle.modo-entrenamiento input:checked + .slider {
  background: color-mix(in srgb, var(--modo-entrenamiento) 30%, transparent);
}
.bot-toggle.modo-entrenamiento input:checked + .slider::before {
  background: var(--modo-entrenamiento);
}
.bot-toggle input:checked + .slider::before {
  transform: translateX(18px);
  background: var(--accent);
}

/* item 5, estado B: switch activo pero en amarillo cuando el bot no está disponible. */
/* AMARILLO = "encendido, pero con un matiz". Son dos situaciones distintas y el color es
   el mismo a propósito, porque para quien atiende significan lo mismo: el bot está puesto
   pero no está contestando como siempre.
     · bot-unavailable → activo y la IA no responde (item 5).
     · bot-esperando   → activo y gestionando una espera a persona. Antes este caso salía
       APAGADO, que era falso: el bot sigue al mando ahí. Es el mismo amarillo del badge
       "Esperando humano", así que la cabecera dice una sola cosa en dos sitios. */
.bot-toggle.bot-unavailable input:checked + .slider,
.bot-toggle.bot-esperando input:checked + .slider { background: var(--warn-bg); }
.bot-toggle.bot-unavailable input:checked + .slider::before,
.bot-toggle.bot-esperando input:checked + .slider::before { background: var(--warn); }
