/**
 * Media Hub NewsAI - el asistente que ve el lector.
 *
 * @copyright  (C) 2026 Bruno Invernizzi. All rights reserved.
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

/*
 * ESTA HOJA HABLABA UN IDIOMA PROPIO.
 *
 * Primero tuvo dos bloques `:root` con su paleta —#0d6efd, #1f2933 y un juego
 * oscuro aparte—. Esos se fueron en la fase 13: escribir en `:root` desde un
 * widget incrustado es escribir en el ámbito global del sitio del cliente, y
 * además esos colores nunca habían pasado por una medición de contraste.
 *
 * Lo que quedó fue un PUENTE: `--newsmind-chat-bg` y sus siete hermanos dejaron
 * de tener valor propio y pasaron a ser alias de los tokens verificados. Fue lo
 * correcto entonces —cambió el origen de los valores sin tocar una sola regla,
 * que es como se arregla algo que está en producción— y quedó anotado como
 * deuda: dos nombres para la misma cosa.
 *
 * Esta etapa paga esa deuda en el archivo que más se ve. Treinta y tres usos del
 * puente pasan a `--nm-*` directo. No es cosmética de nombres: mientras el
 * puente existiera, cualquiera que leyera esta hoja tenía que saltar a tokens.css
 * para averiguar de qué color estaba hablando, y una hoja que no se puede leer
 * sola es una hoja donde el próximo color a mano entra sin que nadie lo note.
 *
 * También se va el último color escrito a mano, `#dc2626`, que era el rojo de
 * error. Tenía el mismo defecto que tenía la PWA: en el modo oscuro del lector
 * quedaba rojo oscuro sobre fondo oscuro, que es exactamente donde un aviso de
 * error deja de avisar. `--nm-error` está medido en los dos modos.
 *
 * Lo que NO se toca acá, a propósito: el alto mínimo del registro y el blanco
 * táctil de los pulgares del voto. Son de la etapa 5, van con los estados de
 * carga, y adelantarlos sería mezclar dos revisiones en un mismo cambio.
 */

.newsmind-chat {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    color: var(--nm-text);
    background-color: var(--nm-surface);
    border: var(--nm-border-width) solid var(--nm-border);
    border-radius: var(--nm-radius-lg);
    box-shadow: var(--nm-shadow-lg);
}

/* ==========================================================================
   CABECERA

   Va rellena con el color de marca del medio. `--nm-brand` es lo que el medio
   configuró en Apariencia y `--nm-brand-contrast` la tinta que se midió contra
   ese relleno: usar uno sin el otro es como se llega a un titular ilegible
   sobre el color corporativo.
   ========================================================================== */

.newsmind-chat__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--nm-space-2);
    padding: var(--nm-space-3) var(--nm-space-4);
    background-color: var(--nm-brand);
    color: var(--nm-brand-contrast);
}

/* ==========================================================================
   LA CONVERSACIÓN
   ========================================================================== */

.newsmind-chat__log {
    flex: 1 1 auto;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: var(--nm-space-3);
    padding: var(--nm-space-4);

    /*
     * 15rem, no 240px, y la diferencia importa.
     *
     * Los dos valen lo mismo con la letra por omisión. Pero un lector que
     * agranda el texto del navegador —porque ve poco, que es de quien estamos
     * hablando— con `px` recibe la misma caja con letra más grande: menos
     * renglones visibles y más desplazamiento. Con `rem` la caja crece con la
     * letra y sigue mostrando lo mismo.
     */
    min-block-size: 15rem;
}

.newsmind-chat__bubble {
    max-width: 85%;
    padding: var(--nm-space-2) var(--nm-space-3);
    border-radius: var(--nm-radius-lg);
    line-height: var(--nm-leading-normal);
}

.newsmind-chat__bubble--user {
    align-self: flex-end;
    background-color: var(--nm-brand);
    color: var(--nm-brand-contrast);
}

/*
 * LA BURBUJA DEL ASISTENTE NO SE DEFINE ACÁ.
 *
 * Acá hubo una regla con fondo `--nm-bg` y borde, que fue la respuesta a un
 * `color-mix` sin medir del 6% de la tinta sobre transparente. V-4 la dejó sin
 * efecto: la respuesta del asistente ya no es una caja, es texto. La única
 * definición vive en el bloque «BURBUJA ASIMÉTRICA — V-4», más abajo en esta
 * misma hoja.
 *
 * La nota queda porque el hueco pregunta solo: el lector que busque el fondo de
 * la respuesta acá arriba tiene que enterarse de que ya no hay fondo, y no
 * agregarlo de vuelta.
 */

/*
 * Justificado, como una columna de diario.
 *
 * `text-wrap: pretty` va junto y no es adorno: justificar sin él deja ríos de
 * espacio en las líneas con pocas palabras, y en una columna angosta eso se ve
 * enseguida. `pretty` reparte el corte mirando el párrafo entero en vez de
 * línea por línea, que es justamente lo que hace falta acá.
 *
 * `hyphens: auto` ayuda a lo mismo en castellano, donde las palabras son
 * largas: sin partir, una palabra que no entra se lleva todo el hueco a la
 * línea anterior.
 */
.newsmind-chat__text {
    text-align: justify;
    text-wrap: pretty;
    hyphens: auto;
}

.newsmind-chat__text > p {
    margin: 0 0 var(--nm-space-2);
}

.newsmind-chat__text > p:last-child {
    margin-bottom: 0;
}

/* ==========================================================================
   CITAS
   ========================================================================== */

/*
 * ACÁ ESTABA `.newsmind-chat__marker`, Y NO LO DIBUJABA NADIE.
 *
 * Era el apuntado que marca de qué nota salió cada frase de la respuesta. Cuando
 * se escribió, este archivo era el único que sabía dibujar una cita; después
 * llegó `cite.css` con `.nm-cite__marker`, el guión pasó a usar ese, y esta
 * regla se quedó — sin errores, sin síntoma, y ganándole en especificidad a
 * nada.
 *
 * Se va porque una regla muerta no es sólo peso: el que la lee cree que el
 * apuntado se estiliza acá, la edita, y no pasa nada. Perder una tarde así es
 * más caro que las trece líneas que ahorra.
 *
 * El apuntado vive en `cite.css`. Ahí, y en un solo sitio.
 */

/* ---------- Fuentes: el hallazgo V-06, por fin ----------
 *
 * Este bloque no tenía NINGUNA regla para sus enlaces. Los `<a>` heredaban el
 * color de la plantilla del medio, y en Radio Gabal eso es #ffa621: 1,96:1 sobre
 * blanco. El mínimo legible es 4,5. Las citas estuvieron ilegibles durante meses
 * y el rediseño entero nació de ahí.
 *
 * El sistema de diseño definió `--nm-cite` —petróleo, 7,38:1— y lo llamó «la
 * promesa del producto: responde sólo con lo publicado y lo demuestra, así que
 * su aspecto no puede quedar a merced del CSS ajeno». Ese token se escribió, se
 * verificó, se documentó… y se usó únicamente en el panel de administración,
 * donde no hay citas. Décima vez que algo correcto no llega a destino.
 *
 * La cita es lo ÚNICO que el color de marca no puede pintar. Un medio puede
 * teñir botones y cabeceras; no puede teñir la prueba de que la respuesta es
 * verdadera, porque entonces deja de leerse.
 */
/* Sólo separa; no decora.
   El filo petróleo y la sangría los pone cada ficha (.nm-cite). Tenerlos también
   acá dibujaba una segunda regla vertical envolviendo a las de adentro, y
   empujaba el bloque entero hacia la derecha sin motivo. Es lo que queda de
   cuando este contenedor era el que daba el estilo, antes de que existiera el
   componente. */
.newsmind-chat__sources {
    margin-top: var(--nm-space-3);
    padding-top: var(--nm-space-2);
    border-top: var(--nm-border-width) solid var(--nm-border);
    font-size: var(--nm-text-sm);
    color: var(--nm-text-secondary);
}

/* Lo mismo con `.newsmind-chat__sources-label`: el rótulo «Fuente» lo pone hoy
   cada ficha, con `.nm-cite__label`. El de acá encabezaba la lista entera cuando
   la lista era una lista y no un conjunto de fichas. */

.newsmind-chat__sources ol {
    margin: 0;
    padding-left: var(--nm-space-6);
}

/* Acá había un parche que forzaba color y subrayado a TODO enlace dentro del
   bloque de fuentes. Se escribió antes de que existiera cite.css, cuando el
   problema era que los enlaces heredaban el color de la plantilla.

   Ahora estorba: con especificidad (0,2,1) le ganaba a `a.nm-cite__title`
   (0,1,1) y dejaba el título de cada ficha subrayado y en petróleo, cuando el
   componente lo quiere oscuro y limpio, y reserva el petróleo para el apuntado.

   Un parche que sobrevive a su causa se convierte en la causa siguiente. El
   blindaje ahora lo da el componente, que fija su color explícitamente. */

/* ==========================================================================
   VOTO
   ========================================================================== */

.newsmind-chat__rating {
    margin-top: var(--nm-space-2);
    display: flex;
    gap: var(--nm-space-1);
    align-items: center;
    font-size: var(--nm-text-sm);
    color: var(--nm-text-muted);
}

/*
 * LOS PULGARES: 44×44, QUE ES LO QUE MIDE UN DEDO.
 *
 * Tenían `padding: .1rem .4rem` — unos 24 píxeles de alto, la mitad del mínimo.
 * Lo señaló la auditoría y el propio sistema de diseño lo dejó escrito con
 * nombre y apellido: «los botones de valoración usan `padding: .1rem .4rem`, muy
 * por debajo de 44 px. Se corrige». Se escribió, se documentó, y se quedó ahí
 * quince versiones.
 *
 * El tamaño va en `min-*` y no en `padding` a propósito: el relleno depende del
 * cuerpo de letra, así que un medio que agrande la tipografía cambiaría el
 * blanco táctil sin querer. El mínimo es el mínimo pase lo que pase con la
 * letra, y el contenido se centra dentro.
 */
.newsmind-chat__rate {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: var(--nm-touch);
    min-block-size: var(--nm-touch);
    padding: 0 var(--nm-space-2);
    border: var(--nm-border-width) solid var(--nm-border);
    background: transparent;
    color: inherit;
    border-radius: var(--nm-radius-sm);
    cursor: pointer;
    font-size: .9rem;
    line-height: 1.4;
}

.newsmind-chat__rate:disabled {
    opacity: .4;
    cursor: default;
}

/* ==========================================================================
   ESTADOS
   ========================================================================== */

/*
 * EL ERROR, CON EL ROJO DEL SISTEMA.
 *
 * Era `color-mix(in srgb, #dc2626 12%, transparent)` para el fondo y `#dc2626`
 * pelado para el texto. Los dos valores eran el último color escrito a mano de
 * esta hoja y ninguno tenía versión oscura: sobre `--nm-surface` en modo oscuro
 * —#111A2B— ese rojo da 3,3:1, por debajo del mínimo, en el único mensaje que el
 * lector necesita leer sí o sí.
 *
 * `--nm-error-soft` y `--nm-error-on-soft` son la pareja medida: fondo y tinta
 * pensados el uno para el otro, con su juego oscuro. No hace falta calcular nada
 * acá porque ya está calculado allá, que es la diferencia entre tener un sistema
 * y tener una paleta.
 */
/* El borde va completo y no sólo `border-color`: la clase de error se AÑADE a la
   del papel que tocara —`--assistant` la trae, otro papel no— así que fijar sólo
   el color deja el aviso sin filo cuando el error no viene del asistente. */
.newsmind-chat__bubble--error {
    background-color: var(--nm-error-soft);
    border: var(--nm-border-width) solid var(--nm-error);
    color: var(--nm-error-on-soft);
}

.newsmind-chat__status {
    padding: 0 var(--nm-space-3) var(--nm-space-2);
    font-size: var(--nm-text-sm);
    color: var(--nm-text-muted);
    min-height: 1.2em;
}

.newsmind-chat__status--error {
    color: var(--nm-error);
    font-weight: var(--nm-weight-medium);
}

/* «Está tardando más de lo normal» no es un error: es una espera larga. Ámbar y
   no rojo, porque el rojo dice «se rompió» y lo que hay que decir es «esperá». */
.newsmind-chat__status--warn {
    color: var(--nm-warning);
    font-weight: var(--nm-weight-medium);
}

/*
 * MIENTRAS SE ESPERA.
 *
 * `is-busy` se ponía desde el primer día y NINGUNA regla lo leía: una señal que
 * se emite y nadie escucha. Ahora hace dos cosas, las dos pequeñas y las dos
 * reales — apagar lo que no responde y decir con el cursor que el widget está
 * ocupado. Un control que se ve activo y no hace nada es peor que uno apagado,
 * porque el lector lo pulsa dos veces y concluye que está roto.
 */
.newsmind-chat.is-busy .newsmind-chat__form {
    cursor: progress;
}

.newsmind-chat__suggestion:disabled {
    opacity: .5;
    cursor: default;
}

/* ==========================================================================
   SUGERENCIAS
   ========================================================================== */

.newsmind-chat__suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--nm-space-1);
    padding: 0 var(--nm-space-3) var(--nm-space-2);
}

.newsmind-chat__suggestion {
    display: inline-flex;
    align-items: center;
    min-block-size: var(--nm-touch);
    border: var(--nm-border-width) solid var(--nm-border);
    background: transparent;
    color: inherit;
    border-radius: var(--nm-radius-full);
    padding: var(--nm-space-1) var(--nm-space-3);
    font: inherit;
    font-size: var(--nm-text-sm);
    text-align: left;
    cursor: pointer;
}

.newsmind-chat__suggestion:hover,
.newsmind-chat__suggestion:focus-visible {
    border-color: var(--nm-brand);
}

/* ==========================================================================
   WIDGET FLOTANTE
   ========================================================================== */

/*
 * Cuatro esquinas y un desplazamiento configurable — hallazgo V-05.
 *
 * En Radio Gabal el botón flotante se superpone con el widget de accesibilidad
 * de la plantilla. La primera reacción fue subir el z-index, y estaba mal: el
 * problema no es quién queda encima, es que los dos ocupan el mismo lugar.
 * Ganar la pelea de apilamiento sólo decide cuál de los dos queda inutilizable.
 *
 * Lo que resuelve es poder MOVER el chat, y para eso hace falta más que elegir
 * esquina: el widget ajeno suele estar en la misma. Con un desplazamiento
 * propio, el asistente se corre lo justo para convivir con él en vez de pelear.
 *
 * Los valores por omisión son los de antes, así que un sitio que no configure
 * nada no ve ningún cambio.
 */
.newsmind-chat--floating {
    position: fixed;

    /* `--nm-chat-z` no está declarado en ninguna parte, y es a propósito: sólo
       lo escribe el guión, en el elemento, cuando mide que la plantilla del
       medio apila más alto que nuestro valor. Sin guión —o con una plantilla
       normal— manda el token del sistema. */
    z-index: var(--nm-chat-z, var(--nm-z-widget));
    /* 26rem y no 24: con 24 las tres pestañas entraban por quince píxeles
       —medido—, y un medio con un nombre de pestaña más largo las desbordaba.
       El tope por ancho de pantalla no cambia, así que en un teléfono se ve
       igual que antes. */
    inline-size: min(26rem, calc(100vw - 2rem));
    max-height: min(34rem, calc(100vh - 6rem));

    --nm-chat-x: var(--nm-space-4);
    --nm-chat-y: var(--nm-space-4);

    /* Para que el ancho se anime entre el panel y la etiqueta cerrada. Ver el
       bloque «CERRADO SE ADAPTA A SU CONTENIDO», más abajo. */
    interpolate-size: allow-keywords;
    transition: inline-size var(--nm-motion-expand);
}

.newsmind-chat--floating.newsmind-chat--bottom-right { right: var(--nm-chat-x); bottom: var(--nm-chat-y); }
.newsmind-chat--floating.newsmind-chat--bottom-left  { left:  var(--nm-chat-x); bottom: var(--nm-chat-y); }
.newsmind-chat--floating.newsmind-chat--top-right    { right: var(--nm-chat-x); top:    var(--nm-chat-y); }
.newsmind-chat--floating.newsmind-chat--top-left     { left:  var(--nm-chat-x); top:    var(--nm-chat-y); }

/*
 * CERRADO ES «TODO MENOS LA CABECERA», NO «ESTAS CUATRO COSAS».
 *
 * Era una lista escrita a mano: registro, formulario, estado y sugerencias. La
 * F2 agregó tres bloques —la portada, los enlaces rápidos y las pestañas— y
 * ninguno entró en la lista, así que el widget cerrado los mostraba igual.
 *
 * El resultado en producción: parecía desplegado y no se podía minimizar, el
 * campo no aparecía —ése SÍ estaba en la lista y se ocultaba bien— y ningún
 * enlace hacía nada, porque rellenaban un campo oculto.
 *
 * Es el patrón de siempre: una enumeración a la que un elemento nuevo no se
 * suma, y nada lo avisa. La forma correcta es la inversa —esconder todo salvo
 * lo que tiene que verse—, porque así el bloque que se escriba mañana ya está
 * cubierto sin que nadie se acuerde de nada.
 *
 * La cabecera se queda porque ES el botón que abre.
 */
.newsmind-chat--floating:not(.is-open) > *:not(.newsmind-chat__header) {
    display: none;
}

/* ==========================================================================
   CERRADO SE ADAPTA A SU CONTENIDO

   El widget tenía el mismo ancho abierto que cerrado, así que la barra azul
   ocupaba media pantalla del móvil para decir una palabra. Cerrado no es un
   panel: es una etiqueta.

   `fit-content` la ajusta al nombre que el medio haya puesto —«Gaby» o
   «Asistente de Radio Gabal de Balcarce»—, sin número escrito en ningún sitio.

   `interpolate-size` hace que el cambio de ancho se anime en vez de saltar.
   Es de Chrome y Edge; donde no está, el ancho cambia de golpe, que es
   exactamente lo que pasaba antes. Mejora progresiva, sin nada que romper.
   ========================================================================== */

/*
 * Cerrado NO lleva borde.
 *
 * `.newsmind-chat` pone un filo de un píxel para separar el panel de la página,
 * y en el panel está bien. Pero cerrado el widget es un botón de un solo color
 * con sombra propia, y ese filo gris alrededor del azul se lee como una costura,
 * no como un límite.
 *
 * Se quita sólo en el estado cerrado. Abierto, el filo sigue haciendo su
 * trabajo: la superficie del panel es casi del tono de la página y la sombra
 * sola no alcanza a despegarla.
 */
.newsmind-chat--floating:not(.is-open) {
    border: 0;
    inline-size: fit-content;
    max-inline-size: calc(100vw - (2 * var(--nm-chat-x)));
}

/* La equis: sólo con el widget abierto. Cerrado no hay nada que cerrar, y una
   equis que no hace nada es peor que ninguna. */
.newsmind-chat--floating:not(.is-open) .newsmind-chat__close {
    display: none;
}

.newsmind-chat__close {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    inline-size: var(--nm-touch);
    min-block-size: var(--nm-touch);
    border: 0;
    border-radius: 50%;
    padding: 0;
    margin-inline-end: var(--nm-space-1);
    background: none;
    color: inherit;
    cursor: pointer;
    transition: background-color var(--nm-transition-fast);
}

.newsmind-chat__close:hover {
    background-color: color-mix(in oklab, currentColor 18%, transparent);
}

/* El control más pulsado del producto: es el que abre el asistente. No tenía
   relleno ninguno, así que medía lo que midiera su icono —22 píxeles— y el que
   fallaba el toque le daba a la cabecera, que no hace nada. */
/*
 * El nombre del medio es lo único que se lee con el widget cerrado, y medía lo
 * mismo que un pie de foto. Sube a `--nm-text-lg` con peso semibold: es la
 * identidad del asistente, y cerrado es TODO el asistente.
 *
 * No pasa a la serif de titulares a propósito. Esa está reservada al saludo de
 * la portada y al título de la página; usarla también acá le quitaría al saludo
 * lo que lo hace leerse como el titular de un medio.
 */
.newsmind-chat__toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--nm-space-2);
    font-size: var(--nm-text-lg);
    font-weight: var(--nm-weight-semibold);
    min-block-size: var(--nm-touch);
    padding-inline: var(--nm-space-1);
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
    text-align: left;
}

/*
 * ÚNICO FOCO DEL ARCHIVO QUE NO USA `--nm-focus-border`, Y ES A PROPÓSITO.
 *
 * Este botón vive DENTRO de la cabecera, que va rellena con el color de marca
 * del medio. El anillo de foco del sistema es azul; sobre una cabecera azul —o
 * sobre cualquier marca cercana— desaparece, justo en el control que sólo se
 * usa con el teclado.
 *
 * `currentcolor` acá es `--nm-brand-contrast`: la tinta que ya se midió contra
 * ese relleno. Con cualquier marca que el medio configure, el anillo se ve.
 */
.newsmind-chat__toggle:focus-visible {
    outline: var(--nm-border-width-accent) solid currentcolor;
    outline-offset: 2px;
}

/*
 * TEXTO PARA QUIEN NO VE LA PANTALLA.
 *
 * Se llamaba `.visually-hidden`, a secas. Ese nombre es de Bootstrap y de media
 * plantilla de Joomla, así que esta hoja lo estaba REDEFINIENDO para toda la
 * página del medio — el mismo pecado que los dos `:root` que se borraron en la
 * fase 13, sólo que con una clase en vez de con variables.
 *
 * Y el riesgo va en los dos sentidos: si un día el medio deja de traer la suya,
 * el rótulo del campo aparece escrito encima del chat; si el medio la trae y
 * gana por orden de carga, el nuestro puede no esconderse. Con nombre propio, el
 * widget no depende de nadie ni le pisa nada.
 *
 * LA MISMA UTILIDAD ESTABA ESCRITA TRES VECES, CON DOS NOMBRES Y TRES CUERPOS.
 * Ésta usaba `!important` y el `clip` obsoleto; la de los módulos se llamaba
 * `.newsmind-offscreen` y usaba `clip-path`; la del panel, un tercer híbrido. No
 * es un problema teórico de duplicación: es la prueba de que ya se había ido
 * separando sola. Ahora las tres son idénticas —`clip-path`, propiedades
 * lógicas— y `check-frontend-tokens.py` falla si vuelven a diferir.
 *
 * El `!important` se fue con el nombre viejo: estaba para ganarle a la clase de
 * Bootstrap con la que competía. Con `nm-` delante ya no compite con nada, y un
 * `!important` que sobrevive a su motivo es el estorbo siguiente.
 */
.nm-visually-hidden {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   FORMULARIO
   ========================================================================== */

/* ==========================================================================
   EL CAMPO ES UNA PÍLDORA, Y EL BOTÓN VA DENTRO

   Antes eran dos cajas separadas en una fila: un rectángulo con borde y, al
   lado, un botón azul que decía «Enviar». Funciona y se ve de 2014.

   Lo que cambia no es el radio. Es QUIÉN es el control: ahora el formulario
   entero es el campo —lleva el borde, el fondo y el foco— y el input de dentro
   no tiene nada propio. El botón es un círculo apoyado en el borde interior.
   Una sola forma en vez de dos, que es lo que hace que se lea como un buscador
   y no como un formulario.

   El foco tampoco lo dibuja el navegador (regla 15b.9): va en el formulario con
   `:focus-within`, porque el elemento que se ve enfocado tiene que ser el que
   el lector percibe como el control.
   ========================================================================== */

.newsmind-chat__form {
    display: flex;
    align-items: center;
    gap: var(--nm-space-2);
    margin: var(--nm-space-3);
    padding: var(--nm-space-1) var(--nm-space-1) var(--nm-space-1) var(--nm-space-4);
    border: var(--nm-border-width) solid var(--nm-border-control);
    border-radius: var(--nm-radius-full);
    background-color: var(--nm-surface);
    box-shadow: var(--nm-shadow-sm);
    transition: border-color var(--nm-transition-fast),
                box-shadow var(--nm-transition-fast);
}

.newsmind-chat__form:focus-within {
    border-color: var(--nm-accent);
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--nm-accent) 28%, transparent);
}

/*
 * EL INPUT NO DIBUJA NADA — Y HACE FALTA UN SELECTOR DE DOS CLASES PARA ELLO.
 *
 * Con `.newsmind-chat__input` a secas —especificidad (0,1,0)— la plantilla del
 * medio ganaba. Medido en la página de Radio Gabal, sobre el campo real:
 *
 *     border: 1px solid rgb(231, 231, 231)
 *     background-color: rgb(255, 255, 255)
 *     padding: 10px
 *
 * Es decir: dentro de la píldora se dibujaba **otro** campo rectangular, que es
 * lo que se veía. Las plantillas de Joomla estilan los formularios con reglas
 * del tipo `.uk-input` o `.form-control input` —(0,1,1) o más—, y ahí una sola
 * clase nuestra no alcanza.
 *
 * Con `.newsmind-chat .newsmind-chat__input` —(0,2,0)— sí: probado en la misma
 * página inyectando las tres especificidades, y (0,2,0) fue la primera que
 * apagó el borde, el fondo y el relleno.
 *
 * No lleva `!important`, y no es purismo: `!important` no se puede deshacer
 * desde fuera, y un medio con una marca propia tiene derecho a ajustar su campo
 * desde su hoja. Lo que hay que ganarle es al estilo POR OMISIÓN de su
 * plantilla, no a su intención.
 *
 * `@layer` no servía acá: las reglas sin capa le ganan siempre a las que están
 * en una capa, así que meter nuestra hoja en una capa habría empeorado esto.
 */
.newsmind-chat .newsmind-chat__input {
    flex: 1 1 auto;
    min-inline-size: 0;
    min-block-size: var(--nm-touch);
    border: 0;
    border-radius: 0;
    padding: 0;
    background: none;
    box-shadow: none;
    color: var(--nm-text);
    font: inherit;
}

.newsmind-chat__input::placeholder {
    color: var(--nm-text-muted);
}

/* Y el foco no se dibuja acá tampoco: lo dibuja la píldora de alrededor. */
.newsmind-chat__input:focus,
.newsmind-chat__input:focus-visible {
    outline: none;
}

/* El botón: un círculo del tamaño del dedo, no un rectángulo con una palabra. */
.newsmind-chat__send {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    inline-size: var(--nm-touch);
    min-block-size: var(--nm-touch);
    border: 0;
    border-radius: 50%;
    padding: 0;
    background-color: var(--nm-brand);
    color: var(--nm-brand-contrast);
    cursor: pointer;
    transition: background-color var(--nm-transition-fast),
                transform var(--nm-transition-fast);
}

.newsmind-chat__send:hover:not([disabled]) {
    transform: scale(1.06);
}

.newsmind-chat__send[disabled] {
    opacity: .6;
    cursor: not-allowed;
}

/* El anillo del sistema para todo lo que no está sobre la marca. Antes cada
   control repetía `2px solid var(--newsmind-chat-accent)`: el acento de marca
   como anillo de foco significa que un medio con marca clara se queda sin foco
   visible, porque el acento se eligió para RELLENAR, no para señalar. */
.newsmind-chat__rate:focus-visible,
.newsmind-chat__input:focus-visible,
.newsmind-chat__send:focus-visible {
    outline: var(--nm-border-width-accent) solid var(--nm-focus-border);
    outline-offset: 2px;
}

/* ==========================================================================
   ESCRIBIENDO…
   ========================================================================== */

.newsmind-chat__typing {
    display: inline-flex;
    gap: 4px;
}

.newsmind-chat__typing span {
    width: 6px;
    height: 6px;
    border-radius: var(--nm-radius-full);
    background-color: currentcolor;
    animation: newsmind-bounce var(--nm-motion-typing) infinite;
}

.newsmind-chat__typing span:nth-child(2) { animation-delay: .15s; }
.newsmind-chat__typing span:nth-child(3) { animation-delay: .3s; }

@keyframes newsmind-bounce {
    0%, 60%, 100% { transform: translateY(0); opacity: .5; }
    30% { transform: translateY(-4px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .newsmind-chat__typing span {
        animation: none;
    }
}

/* El icono del botón que abre el chat flotante. El mismo dibujo que el módulo de
   relacionadas: es la misma cosa —acá se pregunta— y verla igual en los dos
   sitios es lo que hace que el lector la reconozca sin leer.

   `currentColor` y `flex: none`, como el resto de los iconos del sitio. */
.newsmind-chat__icon {
    flex: none;
    inline-size: 1.375rem;
    block-size: 1.375rem;
    color: currentcolor;
}


/* ==========================================================================
   LA PORTADA — F2

   El campo es el mismo elemento en los dos estados. Lo único que cambia es lo
   que tiene alrededor: en `empty` el registro mide cero y el campo queda debajo
   del saludo; en `chat` se ocultan saludo, enlaces y pestañas y el mismo campo
   queda al pie. Sin duplicar el input no hay foco que rescatar ni recorrido de
   tabulador que cambie.
   ========================================================================== */

/*
 * SIN `:empty`. La pseudoclase exige que el elemento no tenga NI UN NODO
 * dentro, y los saltos de línea de la plantilla ya son nodos de texto. Así que
 * `:empty` no llegaba a coincidir nunca y el registro seguía midiendo 240 px de
 * nada en la pantalla inicial.
 *
 * El estado lo dice mejor: en `empty` no hay conversación, punto.
 */
.newsmind-chat[data-state="empty"] .newsmind-chat__log {
    display: none;
}

/*
 * EL FLOTANTE ABIERTO SE DESPLAZA, NO SE CORTA.
 *
 * La caja está limitada a 504 px con `overflow: hidden`. Con la portada dentro
 * el contenido pasó a medir 827, y lo que sobra en una columna flexible
 * desbordada **se va por arriba**: la cabecera quedaba en `top: -303` y el
 * saludo en `-235`. No es que no se dibujaran; estaban fuera de la caja.
 *
 * Un contenido que no entra tiene que poder alcanzarse, no desaparecer en
 * silencio. La cabecera se queda pegada porque es el botón que cierra: sin
 * ella, desplazarse hacia abajo dejaría al lector sin forma de salir.
 */
.newsmind-chat--floating.is-open {
    overflow-y: auto;
}

.newsmind-chat--floating .newsmind-chat__header {
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
}

/*
 * Y la portada, más compacta donde hay 400 px de ancho y medio alto de
 * pantalla. Es la misma portada, no otra: el saludo baja un escalón de la
 * escala tipográfica y la lista de sugerencias se desplaza dentro de sí misma
 * en vez de empujar al resto fuera.
 */
.newsmind-chat--floating .newsmind-chat__home {
    padding-block: var(--nm-space-4) var(--nm-space-2);
}

.newsmind-chat--floating .newsmind-chat__greeting {
    font-size: var(--nm-text-xl);
}

/*
 * Acá el panel de sugerencias tenía `max-block-size: 8rem` y su propio
 * desplazamiento. Salió a pedido, y con razón: son cinco títulos, y una lista
 * corta con barra propia dentro de un panel que YA se desplaza entero obliga a
 * elegir cuál de los dos mover. El flotante abierto se desplaza como una sola
 * pieza —`.newsmind-chat--floating.is-open`, más arriba—, y eso alcanza.
 */
.newsmind-chat[data-state="chat"] [data-newsmind-home] {
    display: none;
}

.newsmind-chat__home {
    text-align: center;
    padding-block: var(--nm-space-8) var(--nm-space-4);
}

/*
 * El saludo, en serif. Es el sitio uno de dos donde vive `--nm-font-display`.
 *
 * `text-wrap: balance` reparte los renglones en vez de dejar una palabra
 * colgando: en un saludo de dos líneas eso es la diferencia entre un titular y
 * un párrafo mal cortado. Donde no está soportado, no pasa nada.
 */
.newsmind-chat__greeting {
    margin: 0 0 var(--nm-space-2);
    font-family: var(--nm-font-display);
    font-size: var(--nm-text-2xl);
    font-weight: var(--nm-weight-normal);
    line-height: var(--nm-leading-tight);
    color: var(--nm-text);
    text-wrap: balance;
}

.newsmind-chat__intro {
    margin: 0 auto;
    max-inline-size: 46ch;
    font-size: var(--nm-text-md);
    line-height: var(--nm-leading-relaxed);
    color: var(--nm-text-secondary);
    text-wrap: pretty;
}

/* ---------- Pestañas de sugerencias ---------- */

.newsmind-chat__tabs {
    margin-block-start: var(--nm-space-6);
}

/*
 * «Sugerencias»: un rótulo de sección, no un título.
 *
 * Va en el cuerpo y no en la serif de titulares: la serif está reservada al
 * saludo y al título de la página —es lo que hace que el saludo se lea como el
 * titular de un medio—, y gastarla acá le quita ese peso. Versalitas, tamaño
 * chico y tinta apagada: dice qué es lo que sigue y no compite con nada.
 */
.newsmind-chat__tabstitle {
    margin: 0 0 var(--nm-space-2);
    font-size: var(--nm-text-sm);
    font-weight: var(--nm-weight-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nm-text-muted);
    text-align: center;
}

/*
 * LAS TRES PESTAÑAS, EN UNA SOLA LÍNEA — Y SI NO ENTRAN, SE DESPLAZAN.
 *
 * Con `flex-wrap: wrap` la tercera caía al renglón de abajo y quedaba centrada
 * ella sola, que se lee como un error de maquetado y no como una pestaña.
 *
 * Medido en la página real, con el panel abierto a 396 px de ancho:
 *
 *     «Esta semana» 107 px · «En desarrollo» 110 px · «Lo más preguntado» 151 px
 *     con las separaciones, 376 px de los 379 disponibles
 *
 * O sea que entraban por tres píxeles. Tres. Cualquier medio con un nombre de
 * pestaña más largo, o una columna un poco más angosta, las partía.
 *
 * Tres cosas, en orden de preferencia:
 *
 * 1. `nowrap`, que es el pedido: nunca en dos renglones.
 * 2. Menos relleno lateral en cada pestaña, que devuelve 24 px sin tocar la
 *    tipografía del sistema.
 * 3. Y si aun así no entran —un teléfono de 360 px no puede con 350 px de
 *    pestañas—, la fila se desplaza en horizontal. Desplazarse es peor que
 *    verlo todo y mejor que partirlo: la pestaña sigue siendo una pestaña.
 *
 * `justify-content: center` sale: con desplazamiento, centrar deja la primera
 * cortada por la izquierda cuando la fila desborda.
 */
.newsmind-chat__tablist {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--nm-space-1);
    overflow-x: auto;
    scrollbar-width: thin;

    /* Que el desplazamiento no se lleve el filo inferior. */
    border-block-end: var(--nm-border-width) solid var(--nm-border);
    margin-block-end: var(--nm-space-3);
}

.newsmind-chat__tab {
    flex: 0 0 auto;
    min-block-size: 44px;
    padding-inline: var(--nm-space-2);
    white-space: nowrap;
    border: 0;
    border-block-end: var(--nm-border-width-accent) solid transparent;
    background: none;
    font: inherit;
    font-size: var(--nm-text-base);
    font-weight: var(--nm-weight-medium);
    color: var(--nm-text-muted);
    cursor: pointer;
    transition: color var(--nm-transition-fast),
                border-block-end-color var(--nm-transition-fast);
}

.newsmind-chat__tab[aria-selected="true"] {
    color: var(--nm-text);
    border-block-end-color: var(--nm-accent);
}

.newsmind-chat__tabpanel {
    display: grid;
    gap: var(--nm-space-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * El título de la página del asistente: el segundo y último sitio del serif.
 *
 * El plan decía «el h1 del panel», pero el panel de administración no tiene
 * `<h1>` propio: el título lo dibuja la barra de herramientas de Joomla, fuera
 * de `.newsmind-wrapper`. El `<h1>` que sí existe y sí es nuestro es éste, el de
 * la página del asistente, justo encima del saludo.
 *
 * Y queda mejor donde está: el serif dice «esto lo escribe un medio», y eso no
 * tiene nada que hacer en una pantalla de administración.
 */
.newsmind-assistant__title {
    font-family: var(--nm-font-display);
    font-weight: var(--nm-weight-normal);
    line-height: var(--nm-leading-tight);
    color: var(--nm-text);
    text-wrap: balance;
}

/* ==========================================================================
   BURBUJA ASIMÉTRICA — V-4

   El lector conserva su píldora: lo que escribió es suyo y se distingue de un
   vistazo. La respuesta deja de ser una burbuja y pasa a ser texto.

   Una respuesta del asistente no es un mensaje de chat: es un párrafo con
   fuentes que se lee entero. Encerrarlo en una caja gris al 70 % del ancho lo
   hace parecer una conversación de mensajería, y además obliga a medir su
   contraste contra el fondo de la burbuja en vez de contra la superficie, que
   es un par más que verificar por cada modo.
   ========================================================================== */

/*
 * Sin fondo y sin borde a propósito: el contraste del texto se mide contra la
 * SUPERFICIE del chat, que es un par ya anotado en tokens.css, y no contra un
 * tono de burbuja que habría que verificar aparte en claro y en oscuro.
 */
.newsmind-chat__bubble--assistant {
    align-self: stretch;
    max-inline-size: none;
    padding-inline: 0;
    border: 0;
    background: none;
    font-size: var(--nm-text-md);
    line-height: var(--nm-leading-relaxed);
    color: var(--nm-text);
}

/* ==========================================================================
   LOS ENLACES RÁPIDOS, CON SU FLECHA

   Eran tres textos subrayados. El subrayado es lo que se usa cuando no hay otra
   señal de que algo se pulsa; con la flecha delante ya la hay, y el subrayado
   pasa a ser ruido — tres subrayados seguidos en una fila corta se leen como un
   error de maquetado.

   Al pasar el puntero cambia el COLOR y no aparece subrayado: son tres enlaces
   en una fila de una línea, y el subrayado que entra y sale desplaza el texto lo
   justo para que se note. El cambio de color señala igual sin mover nada.

   Siguen a 24 px con separación, que es la excepción 2.5.8 para enlaces de
   texto en línea. La flecha no los convierte en botones.
   ========================================================================== */

.newsmind-chat__quicklink {
    display: inline-flex;
    align-items: center;
    gap: var(--nm-space-1);
    min-block-size: 24px;
    padding: var(--nm-space-1) var(--nm-space-1);
    border: 0;
    background: none;
    font: inherit;
    font-size: var(--nm-text-base);
    font-weight: var(--nm-weight-medium);
    color: var(--nm-accent);
    cursor: pointer;
    text-decoration: none;
    transition: color var(--nm-transition-fast);
}

.newsmind-chat__quicklink:hover {
    color: var(--nm-text);
}

.newsmind-chat__quicklink-icon {
    flex: 0 0 auto;
}

/*
 * La fila: 24 px de alto, no 44.
 *
 * Es la excepción 2.5.8 que el sistema ya tiene escrita: el mínimo de 44 px es
 * para controles, y un enlace de texto en línea con otros enlaces de texto está
 * exceptuado siempre que haya separación suficiente alrededor. A 44 serían tres
 * botones grandes compitiendo con el campo, que es justo lo que no tiene que
 * pasar en la pantalla inicial. La flecha no los convierte en botones.
 */
.newsmind-chat__quick {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--nm-space-2);
    margin-block-start: var(--nm-space-3);
}

/* Sin separador entre un enlace y otro: la flecha de cada uno ya marca dónde
   empieza. Acá hubo un punto medio con `content: "·" / ""` —la barra silencia el
   punto para el lector de pantalla—, y con la flecha delante eran dos marcas
   para lo mismo. Se queda anotado porque esa sintaxis es la que reemplaza al
   `speak: never` que nunca tuvo soporte, y hace falta la próxima vez. */

/* ==========================================================================
   SEGUIR PREGUNTANDO — debajo de cada respuesta

   Otras notas del archivo sobre el mismo tema, para que el lector siga tirando
   del hilo en vez de quedarse con una respuesta y cerrar.

   Va DESPUÉS de las fuentes y de los pulgares, y eso es deliberado: primero la
   respuesta, después de dónde salió, después valorarla, y al final por dónde
   seguir. Ofrecer el siguiente paso antes de mostrar la prueba invertiría lo
   que el producto promete.

   Se separa con un filo superior y un rótulo apagado porque no es parte de la
   respuesta: es una oferta. Un bloque de tres títulos sin separación se lee
   como si el asistente siguiera hablando.
   ========================================================================== */

.newsmind-chat__followup {
    margin-block-start: var(--nm-space-4);
    padding-block-start: var(--nm-space-3);
    border-block-start: var(--nm-border-width) solid var(--nm-border);
}

.newsmind-chat__followup-title {
    margin: 0 0 var(--nm-space-2);
    font-size: var(--nm-text-sm);
    font-weight: var(--nm-weight-semibold);
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--nm-text-muted);
}

.newsmind-chat__followup-list {
    display: grid;
    gap: var(--nm-space-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Los títulos de las notas NO se justifican: son de una o dos líneas y
   justificar dos líneas sueltas deja un hueco en medio de la primera. */
.newsmind-chat__followup .newsmind-chat__suggestion {
    text-align: left;
    text-wrap: pretty;
    hyphens: manual;
}

/* ==========================================================================
   LA PESTAÑA VACÍA

   No es un error ni un aviso: es una explicación. Así que se lee como texto
   secundario y no como una alerta — el medio no hizo nada mal, esa lista
   todavía no tiene con qué llenarse.
   ========================================================================== */

.newsmind-chat__tabempty {
    padding: var(--nm-space-3) var(--nm-space-2);
    color: var(--nm-text-muted);
    font-size: var(--nm-text-base);
    line-height: var(--nm-leading-normal);
    text-align: center;
    text-wrap: pretty;
}
