﻿/* =================================================================================================
   El chat, un solo juego de estilos (B5 de «un solo chat, responsivo»).

   B2, B3 y B4 dejaron el **marcado** en un sitio; el aspecto seguía escrito dos veces —`app.css` y
   `mobile.css` declaraban los mismos 56 selectores con valores distintos—, que es la misma trampa un piso
   más abajo: nadie se entera de que divergieron hasta que el usuario compara los dos aparatos.

   Cómo se reparte:

   - **La base es la variante de puntero y pantalla ancha** (el escritorio de hoy). Es la que tiene más
     reglas estructurales y la que sirve de punto de partida razonable si una superficie nueva no dice nada.
   - **`@media (max-width: 720px)` es la variante táctil**: turnos como burbujas, altura de dedo en todo lo
     pulsable, y los dos paneles —ajustes e histórico— como **hoja inferior** en vez de anclados. Esa
     colocación es una diferencia **real** y por eso sobrevive: una hoja se alcanza con el pulgar y un panel
     anclado no.

   El corte por **ancho** y no por «es la PWA» es deliberado: el escritorio en una ventana estrecha quiere lo
   mismo que un teléfono, y un teléfono apaisado grande quiere lo de la base.

   **El acento se pide por variable**, `--chat-accent`. Es la única diferencia de color con motivo: en el
   escritorio es el terracota de Claude —la pestaña de Claude se distingue del resto de la aplicación— y en el
   móvil es el color del **contexto**, que es como el teléfono dice en qué proyecto estás. Cada superficie la
   fija donde monta el chat; aquí solo se consume.
   ================================================================================================= */

:root {
    --cc-accent: #d97757;      /* terracota de Claude */
    --cc-accent-soft: #e8a48d;
    --chat-accent: var(--cc-accent);
}

/* --- El armazón ---------------------------------------------------------------------------------- */

.cc { display: flex; flex-direction: column; height: 100%; min-height: 0; gap: .5rem; }

/* El registro se lleva el alto sobrante y **desplaza él**: si desplazara el contenedor entero, el cuadro de
   escritura se iría fuera de la pantalla en cuanto la conversación creciera. */
/* **`scrollbar-gutter: stable`** (0.27.81, temblor del chat). El registro crece mientras llega la respuesta, así
   que cruza una y otra vez el umbral de «necesita barra»: cada aparición y desaparición de la barra estrecha el
   contenido unos 15 px y **reflúa el texto en horizontal**. Es un temblor lateral que no viene de ninguna
   animación, y por eso sobrevivió al arreglo de la estrella. Con el hueco reservado siempre, la barra aparece
   sobre un espacio que ya estaba. */
/* **`overflow-anchor: none`** (0.27.128). El registro lo desplaza la aplicación —`contextaraChat.scrollToEnd`, al
   fondo mientras el turno llega—, y el navegador hace **lo mismo por su cuenta**: el anclaje de scroll de Chromium
   corrige `scrollTop` cuando cambia algo por encima del ancla, que durante un turno pasa en cada bloque que se
   consolida y en cada racha de herramientas que se colapsa. Dos correcciones sobre el mismo valor, calculadas en
   momentos distintos, se ven como un tirón. Con el anclaje apagado manda una sola. */
.cc-log {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-gutter: stable; overflow-anchor: none;
    display: flex; flex-direction: column; gap: .5rem;
}
.cc-compose { flex: 0 0 auto; display: flex; flex-direction: column; gap: .4rem; }

.cc-head { display: flex; align-items: baseline; gap: .8rem; }
.cc-brand {
    display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
    font-family: Georgia, "Times New Roman", serif; font-size: .9rem; color: var(--text);
}
.cc-ver { font-family: inherit; font-size: .68rem; color: var(--muted); font-weight: normal; }
/* La ruta del workspace en la cabecera, **en una línea y recortada con elipsis** (usuario, 2026-08-17: *«la ruta
   en el chat se expande rompiendo el layout, agrega un elipsis»*).

   Tenía `overflow-wrap: anywhere`, y de ahí salía el defecto: con esa propiedad el **min-content** del elemento
   pasa a ser **un carácter**, así que un flex item que puede encogerse se encoge hasta una columna de letras y
   estira la barra a doscientos píxeles de alto —`d:\Co` / `ntext` / `ara\C`…—. Y en `.cc-head` compite por el
   ancho con el título (`flex: 1 1 auto`) y con los medidores (`nowrap`), así que la ruta era justo la que perdía.

   `nowrap` + `overflow: hidden` + `text-overflow: ellipsis` la dejan en una línea y con `…` al final; `min-width: 0`
   es lo que **permite** encogerse por debajo del min-content —sin él, `nowrap` haría que la ruta entera empujara
   la barra y volvería el desbordamiento por el otro lado—, y `min-width` en `ch` le pone un suelo para que no se
   evapore hasta la nada. La ruta completa sigue en el `title`: recortar no pierde información. */
.cc-where {
    color: var(--muted); font-size: .75rem;
    flex: 0 1 auto; min-width: 6ch;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cc-meta { color: var(--muted); font-size: .72rem; white-space: nowrap; display: flex; gap: .6rem; margin-left: auto; }
.cc-unavailable { padding: .5rem 0; }
/* La franja de solo lectura, **en el sitio del cuadro de escribir** (0.27.84): ocupa exactamente lo que ocupaba
   lo que no se puede usar, así que el panel no da un salto al aparecer ni al irse. En ambar y no en rojo —no ha
   fallado nada— y con su salida a la derecha, que es donde estan los botones del compositor. */
.cc-readonly {
    display: flex; align-items: center; gap: .6rem; margin: 0;
    padding: .5rem .6rem; font-size: .78rem; color: var(--text);
    background: rgba(240, 180, 41, .08); border-top: 1px solid rgba(240, 180, 41, .35);
}
.cc-readonly > span { flex: 1 1 auto; }
.cc-toggle { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer; user-select: none; }
.cc-toggle input { margin: 0; cursor: pointer; }
.cc-link {
    background: none; border: 0; padding: 0; font: inherit; font-size: .72rem;
    color: var(--chat-accent); cursor: pointer; text-decoration: underline;
}
/* Pastilla que avisa de que a la sesión se le pasó el estado del Context. */
.cc-badge {
    font-size: .66rem; color: var(--chat-accent); border: 1px solid var(--chat-accent);
    border-radius: 999px; padding: .05rem .45rem; white-space: nowrap;
}

/* El asterisco de Claude. Baila mientras piensa —gira y late a la vez— y está quieto el resto del tiempo.

   **Hueco fijo y estrella flotando dentro** (usuario, 2026-08-13: *«el giro de la estrella en el chat no está
   centrado y es rectangular, eso causa movimiento como temblor en el chat; deja un espacio fijo y algo
   flotante»*).

   El defecto y su causa, que se ven en una sola medida: la caja del glifo era **27,72 × 19,81** —rectangular,
   porque la dibujaba el propio carácter— y `transform-origin` cae en el centro de **esa** caja, que no es el
   centro de la tinta. Girar así no hace girar la estrella: la hace **orbitar**, y a 1,4 s por vuelta eso se lee
   como un temblor. Y como la caja la decidía el glifo, cualquier cambio de fuente o de zoom movía además lo que
   tiene al lado.

   La solución son las dos piezas que pidió, y hacen falta las dos:

     · `.cc-star-slot` reserva un **cuadrado fijo**, y es lo único que ocupa sitio en la línea. No se anima, así
       que nada de lo que hay alrededor se mueve nunca.
     · `.cc-star` va **fuera del flujo** (`position: absolute`) y centrada con `inset: 0` + flex. Al ser la caja
       cuadrada y la tinta estar centrada en ella, el origen del giro **es** el centro visual: gira en su sitio.

   Cuadrado y no `width: auto`: un hueco que dependa del glifo vuelve a ser rectangular en cuanto cambie la
   fuente, y con él vuelve el temblor. */
.cc-star-slot {
    display: inline-flex; position: relative; flex: none;
    /* **En `rem` y no en `em`**, y eso lo destapó el usuario mirando la de arriba: en `em` el hueco depende de la
       letra de quien lo contiene, y las dos estrellas viven en sitios con tamaños distintos —`.cc-brand` está a
       .9rem—. Un «espacio fijo» que cambia con el rótulo que tiene al lado no es fijo. */
    width: 1.25rem; height: 1.25rem; vertical-align: middle;
}

/* **La estrella es un trazo propio y ya no un carácter** (0.27.128, usuario: *«aún después de varios intentos de
   corrección, el chat tiene temblor»*).

   Lo que quedaba temblando era esto, y es medible: con el hueco de 20 px y el `✳` a 16 px en `system-ui`, la tinta
   del glifo va de (3,89 · 4) a (16,89 · 17) —centro (10,39 · 10,5)—, mientras que el origen del giro es el centro
   de la caja, (10 · 10). Rasterizando el giro, el centro de la tinta describe un círculo de **0,52 px de radio**:
   la estrella no giraba sobre sí misma, **orbitaba** un circulito de 1 px cada 1,4 s, y era el único elemento de
   la pantalla en movimiento.

   0.27.71 arregló la **caja** (cuadrada y fuera del flujo, para que nada de al lado reflúa) y aquí se arregla la
   **tinta**, que es lo que ninguna regla de CSS puede centrar: dónde cae depende de la fuente que resuelva el
   sistema, del tamaño y del zoom. Un SVG se dibuja alrededor de (12 · 12) de su `viewBox`, así que el radio de la
   órbita es **cero por construcción**. Ver `FileIcons.Asterisk`.

   Por eso ya no hay `font-family` ni `font-size` aquí: no queda ningún carácter que componer. */
.cc-star {
    color: var(--chat-accent);
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
}
.cc-star svg { display: block; width: 100%; height: 100%; }

/* **`will-change: transform` es el arreglo del temblor que quedaba** (0.27.135; usuario, 2026-08-19: *«el temblor
   persiste»*, con un vídeo de 42 s).

   **Lo que el vídeo demostró, y no era lo que se había arreglado.** Midiendo el centroide de la tinta del
   asterisco fotograma a fotograma: **no se mueve** —desvío medio de 0,38 px, que es ruido de compresión—, así que
   la órbita de 0.27.128 está cerrada de verdad. Lo que oscila es **el área**: entre fotogramas consecutivos la
   tinta pasa de 35 a 58 píxeles. El asterisco no se desplaza: **hierve en su sitio**, y eso es lo que el ojo lee
   como temblor.

   **La causa es la rasterización, no la geometría.** Cada brazo mide 2 de las 24 unidades del `viewBox`, o sea
   unos 2 px en pantalla. Al girar, los brazos cruzan la rejilla de píxeles en ángulos distintos y el navegador
   **vuelve a rasterizar el dibujo en cada fotograma**: el suavizado reparte la tinta de otra forma, así que cada
   brazo se engorda, se adelgaza y a veces casi desaparece. Medido en un banco propio, girando el mismo SVG en 36
   ángulos, el área oscila un **7,8 %** con el brazo a 1,7 unidades y un **3,0 %** a 2,0.

   **Y por eso la cura es una capa de composición.** Con `will-change: transform` el navegador rasteriza el SVG
   **una vez** y luego rota la textura en la GPU: el dibujo deja de recalcularse por ángulo, y el hervor desaparece
   por construcción —no por ajuste—. Es la misma familia de razones por las que `transform` era la vía barata para
   el giro; lo que faltaba era decirle que la capa merece existir.

   **Va en `.is-thinking` y no en `.cc-star`**: una capa permanente por cada asterisco quieto es memoria de GPU a
   cambio de nada, y `will-change` sobre algo que no se anima es justo lo que la propiedad advierte de no hacer. */
.cc-star.is-thinking {
    animation: cc-spin 1.4s linear infinite, cc-pulse 1.4s ease-in-out infinite;
    will-change: transform;
}
@keyframes cc-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes cc-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }

/* **Con la preferencia puesta pierde el latido, no el giro** (usuario, 2026-08-17: *«el ✳ en el chat y en el
   título ya no gira; ¿hay alguna forma de hacerlos girar que no sea costosa?»*).

   Este es el bloque que lo paró. En 0.27.95 (M3) se escribió `animation: none`, y con eso la estrella se queda
   quieta en **cualquier máquina que tenga desactivados los efectos de animación de Windows** —Accesibilidad ▸
   Efectos visuales ▸ Efectos de animación—: WebView2 traduce ese interruptor a `prefers-reduced-motion: reduce`,
   y el resultado no fue «menos movimiento», fue **ninguno**. En una la estrella gira y en la otra no, con el
   mismo binario, y eso se lee como un defecto porque lo es.

   El error de M3 fue confundir dos cosas. Lo que sobraba era la **segunda** animación —el latido de `opacity`
   corriendo horas seguidas en paralelo—; el giro no sobra: es la **única** señal de que el turno sigue vivo, y
   una señal de estado no es decoración. La preferencia pide reducir el movimiento **no esencial**, no apagar el
   indicador que dice si la aplicación está trabajando o colgada.

   Así que aquí se reduce de verdad: **se queda el giro y se va el latido**. Es la mitad de los fotogramas y
   ningún cambio de coste —`transform` lo resuelve el compositor en la GPU, sin recalcular disposición ni
   repintar—, que es también la respuesta a «¿y un GIF?»: un GIF sería **más** caro (decodificar y rasterizar
   cada fotograma en el hilo principal) y encima no heredaría el color del acento. */
@media (prefers-reduced-motion: reduce) {
    .cc-star.is-thinking { animation: cc-spin 1.4s linear infinite; }
}

/* --- La última fila del registro: el asterisco, el coste del turno y la hora ----------------------- */

/* **Una fila, no dos** (usuario, 2026-08-17). El asterisco de «está respondiendo» a la izquierda y, a la derecha,
   lo que se sabe del último turno: cuánto costó —duración y tokens, que antes vivía arriba en `.cc-meta`— y
   cuándo fue.

   Que sea **una sola fila con altura mínima fija** es lo que arregló el temblor de 0.27.81 y hay que conservarlo:
   al terminar un turno se va el asterisco y aparece la hora, justo en el punto donde está la vista pegada al
   fondo. Con dos filas independientes eso es una que muere y otra que nace —el registro salta—; con una fila de
   altura reservada es un cambio de contenido, y nada se mueve.

   `.cc-entry` **no** interviene aquí: esto no es un turno de la conversación, así que no hereda ni su relleno ni
   su `flex-direction: column`. Era eso lo que obligaba antes a escribir `.cc-entry.cc-thinking` para ganarle la
   especificidad —ver 0.27.71—, y con la fila propia el problema desaparece en vez de contrarrestarse. */
.cc-foot {
    display: flex; flex-direction: row; align-items: center; justify-content: flex-start;
    gap: .5rem; min-height: 1.25rem;
}
.cc-foot .cc-star-slot { opacity: .9; }

/* El coste y la hora del último turno, **al pie, a la derecha y en letra pequeña**: son referencias que se
   consultan al volver a una pestaña, no algo que compita con la conversación. Por eso el gris apagado y sin
   rótulos —los explican los `title`—.

   `margin-left: auto` los empuja a la derecha **dentro** de la fila, así que la hora sigue cayendo exactamente
   donde caía cuando tenía fila propia; el asterisco no la mueve porque su hueco es de ancho fijo (1,25 rem).

   Las cifras van en `tabular-nums` porque cambian en cada turno: sin ancho fijo, «569,5 s» y «48,9k» bailan de
   sitio con cada dígito nuevo. */
.cc-stamp {
    margin-left: auto; display: flex; align-items: baseline; gap: .6rem;
    min-width: 0; overflow: hidden;
    text-align: right; font-size: .68rem; color: var(--muted);
    padding: .15rem .1rem .1rem; font-variant-numeric: tabular-nums;
}
.cc-stamp > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- Los turnos ---------------------------------------------------------------------------------- */

.cc-entry { display: flex; flex-direction: column; gap: .15rem; font-size: .85rem; }
.cc-entry .cc-text { overflow-wrap: anywhere; }
/* Los enlaces de una respuesta, en **celeste** y no en el acento del chat: el terracota de Claude sobre fondo
   oscuro se lee casi como el texto normal, y un enlace tiene que verse que es un enlace sin pasar el raton por
   encima —en un telefono no hay raton que pasar—. */
.cc-text.fv-markdown a, .cc-text.fv-markdown a:visited { color: #6cc4ff; }
/* **El relleno de la respuesta, a un tercio** (usuario, 2026-08-15: *«las respuestas del LLM en modo desktop
   tienen mucho margen interno, disminuyelo a 1/3»*).

   `.fv-markdown` nacio para el **visor de documentos**, donde un documento a pantalla completa agradece el aire
   (`.75rem 1.2rem` en `app.css`); la respuesta de un chat lo hereda por compartir la clase, y ahi ese aire es un
   marco de casi dos centimetros alrededor de cada turno en una ventana que no crece. Se acota **aqui y con dos
   clases**, no tocando `.fv-markdown`: el visor sigue con el suyo, que es el sitio donde estaba bien. */
.cc-text.fv-markdown { padding: .25rem .4rem; }

/* --- Copiar un bloque de codigo -------------------------------------------------------------------- */

/* El boton va **flotando sobre la esquina** del bloque y no en una fila propia: una fila por bloque, con quince
   bloques en un turno, seria una pantalla de botones. Discreto en reposo y con el glifo de siempre para copiar
   (el mismo ⧉ del resto de la aplicacion), asi no hace falta rotulo. */
.cc-copybox { position: relative; }
.cc-copy {
    position: absolute; top: .2rem; right: .2rem; z-index: 2;
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.7rem; height: 1.7rem; padding: 0; cursor: pointer;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 6px;
    color: var(--muted); font-size: .9rem; line-height: 1; opacity: .75;
}
.cc-copy::before { content: "⧉"; }
.cc-copy:hover { opacity: 1; color: var(--text); }
/* **Se dice que se copio.** Sin confirmacion no hay forma de saber si el toque acerto, y en un telefono menos:
   no hay puntero que cambie de forma ni foco que se vea. */
.cc-copy[data-state="ok"] { opacity: 1; color: #7bd88f; border-color: #7bd88f; }
.cc-copy[data-state="ok"]::before { content: "✓"; }
.cc-copy[data-state="fail"] { opacity: 1; color: #e08585; border-color: #e08585; }
.cc-copy[data-state="fail"]::before { content: "!"; }

/* El expansor del turno del usuario **no existe en pantalla ancha**: el recorte a tres lineas es de la variante
   tactil, y un boton que no recorta nada seria un boton que no hace nada. El marcado es el mismo en las dos
   superficies —una sola vista del registro— y quien decide es el CSS, como el resto de las diferencias. */
.cc-user-more { display: none; }
.cc-text pre { overflow-x: auto; background: #0b0e13; padding: .5rem; border-radius: 8px; }
/* Relleno **a la mitad**: en un chat el texto es lo que se lee, y el aire alrededor de cada turno se estaba
   comiendo líneas de conversación en una ventana que no crece. */
.cc-user .cc-text {
    background: rgba(217, 119, 87, .1); border-left: 2px solid var(--chat-accent);
    padding: .18rem .25rem; white-space: pre-wrap;
}
.cc-system .cc-text, .cc-tool .cc-text { color: var(--muted); font-size: .75rem; }
.cc-divider { color: var(--muted); font-size: .8rem; text-align: center; }
/* **La raya, en fila** (0.27.81): desde que puede llevar el enlace de «cargar más mensajes» son dos piezas, y
   `.cc-entry` las apila en columna —el enlace caería debajo del rótulo, que no es lo que se pidió—. Con
   `.cc-entry.cc-divider` y no `.cc-divider` a secas, que es la trampa documentada arriba para el asterisco: con la
   misma especificidad gana la regla de `.cc-entry`, que viene después en esta hoja. */
.cc-entry.cc-divider {
    flex-direction: row; align-items: baseline; justify-content: center; gap: 0;
}
.cc-hint { color: var(--muted); font-size: .9rem; padding: .6rem .2rem; }
.cc-entry.is-streaming .cc-text { white-space: pre-wrap; opacity: .85; }
.cc-error .cc-text { color: var(--danger, #e06c75); font-size: .8rem; white-space: pre-wrap; }
/* Separador entre la conversación retomada y lo que se escriba ahora. */
.cc-resume .cc-text {
    color: var(--chat-accent); font-size: .72rem; text-align: center;
    border-top: 1px dashed var(--border); padding-top: .5rem; margin-top: .3rem;
}
/* Historia trasladada de otro PC: atenuada, y bajo una raya que marca la costura. */
.cc-entry.is-dimmed { opacity: .45; }
.cc-relocated .cc-text {
    color: #dcc57f; font-size: .72rem; text-align: center; font-variant: small-caps; letter-spacing: .02em;
    border-top: 2px solid #6b5a2f; padding-top: .5rem; margin-top: .4rem;
}

/* La herramienta: **la cabecera en una línea** —etiqueta (READ, BASH…), comando, contador y chevrón— y el cuerpo
   **debajo** cuando se expande.

   El contenedor va en **columna**, y esto no es un detalle de estilo: cuando estaba en fila —heredado de cuando la
   herramienta era una etiqueta y un texto y nada más—, el cuerpo expandido entraba como un hermano más de la
   cabecera y se colocaba **a su derecha**, en una segunda columna. Es lo que se veía al expandir un comando. */
.cc-tool { flex-direction: column; align-items: stretch; gap: .15rem; }
.cc-tool .cc-label { flex: 0 0 auto; }
.cc-label { color: var(--chat-accent); font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; }
.cc-tool-head {
    display: flex; align-items: center; gap: .4rem; width: 100%;
    background: none; border: none; color: inherit; font: inherit;
    padding: .15rem 0; cursor: pointer; text-align: left;
}
.cc-tool-sum { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El contador de los que quedan detrás: de una racha de comandos se muestra **solo el último** con un «+3». */
.cc-tool-more {
    flex: 0 0 auto; font-size: .68rem; padding: 0 .3rem; border-radius: 999px;
    border: 1px solid var(--border); color: var(--muted);
}
.cc-tool-caret { flex: 0 0 auto; transition: transform .12s ease; }
.cc-tool-head.is-open .cc-tool-caret { transform: rotate(90deg); }
.cc-tool-body { white-space: pre-wrap; font-size: .8rem; opacity: .9; }

.cc-imgs { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .35rem; }
.cc-img { max-width: 100%; max-height: 22rem; border-radius: 8px; border: 1px solid var(--border); }

/* --- Las preguntas de Claude --------------------------------------------------------------------- */

/* Se destaca con el acento y un borde a la izquierda, como el turno del usuario pero al otro color: es un
   momento en el que la conversación **te toca a ti**, y tiene que distinguirse de un párrafo más de respuesta. */
.cc-ask {
    border-left: 2px solid var(--chat-accent); background: rgba(217, 119, 87, .07);
    padding: .25rem .3rem; display: flex; flex-direction: column; gap: .6rem;
}
.cc-ask-q { display: flex; flex-direction: column; gap: .25rem; }
.cc-ask-head {
    align-self: flex-start; font-size: .62rem; text-transform: uppercase; letter-spacing: .04em;
    color: var(--chat-accent); border: 1px solid var(--chat-accent); border-radius: .6rem; padding: 0 .35rem;
}
.cc-ask-text { font-size: .85rem; }
/* Las opciones a lo ancho y envolviendo: cuatro cortas caben en una fila, y una larga se lleva la suya. */
.cc-ask-opts { display: flex; flex-wrap: wrap; gap: .35rem; }
.cc-ask-opt {
    flex: 0 1 auto; max-width: 100%; text-align: left; cursor: pointer;
    display: flex; flex-direction: column; gap: .1rem;
    background: var(--panel-2); color: inherit;
    border: 1px solid var(--border); border-radius: .35rem; padding: .3rem .5rem;
}
.cc-ask-opt:hover { border-color: var(--chat-accent); }
.cc-ask-on { border-color: var(--chat-accent); background: rgba(217, 119, 87, .18); }
/* «Otra…»: punteada, para que se lea como la salida y no como una opción más de las que propuso el modelo.
   Sin ella, una pregunta cuya respuesta no está en la lista **no se podía contestar**. */
.cc-ask-other { border-style: dashed; color: var(--muted); }
.cc-ask-label { font-size: .8rem; }
.cc-ask-desc { font-size: .68rem; color: var(--muted); overflow-wrap: anywhere; }
/* Lo elegido, cuando ya se contestó: en el sitio que ocupaban los botones, para que la conversación se lea
   igual de arriba abajo. */
.cc-ask-picked { font-size: .8rem; color: var(--chat-accent); }
.cc-ask-otherbox { display: flex; gap: .4rem; align-items: center; }
.cc-ask-otherinput {
    flex: 1 1 auto; min-width: 0; font: inherit; font-size: .85rem;
    background: var(--panel); color: var(--text); border: 1px solid var(--chat-accent);
    border-radius: 8px; padding: .35rem .5rem;
}
.cc-ask-send {
    align-self: flex-start; cursor: pointer; font-size: .78rem; padding: .25rem .7rem;
    border: 1px solid var(--chat-accent); border-radius: .35rem;
    background: var(--chat-accent); color: #1b1e23;
}
.cc-ask-send:disabled { opacity: .45; cursor: default; }

/* --- El compositor ------------------------------------------------------------------------------- */

.cc-box { display: flex; flex-direction: column; gap: .4rem; }
.cc-input {
    width: 100%; resize: vertical; font: inherit; font-size: .85rem;
    background: #101317; color: var(--text); border: 1px solid var(--border);
    border-radius: .3rem; padding: .45rem .55rem;
}
.cc-input::placeholder { color: var(--muted); }
.cc-input:focus { outline: none; border-color: var(--chat-accent); }
/* **Centrado vertical y no al fondo**: la pastilla de ajustes y el círculo del medidor son más bajos que el clip
   y el botón de enviar, y con `flex-end` quedaban colgando del borde inferior, desalineados con ellos. */
.cc-actions { display: flex; align-items: center; gap: .7rem; }
.cc-ctrl { display: flex; flex-direction: column; gap: .15rem; color: var(--muted); font-size: .68rem; }
.cc-send { margin-left: auto; }
/* El botón de enviar dice «Enviar» donde hay ancho, y es una flecha donde no lo hay. */
.cc-btn-text { display: inline; }
.cc-btn-icon { display: none; }
.cc-primary { background: var(--chat-accent); border: 1px solid var(--chat-accent); color: #e6e6e6; }
.cc-primary:hover:not(:disabled) { background: #c96545; }
.cc-primary:disabled { opacity: .5; }
.cc-stop { border-color: var(--danger, #e06c75); color: var(--danger, #e06c75); }

/* Aviso de turno fallido con su reintento, encima del compositor. Discreto pero no escondido: es la acción que
   resuelve el caso más común —un error de API, un proceso caído—, no una alarma. */
.cc-retry {
    display: flex; align-items: center; gap: .5rem;
    margin: 0 0 .4rem; padding: .35rem .5rem;
    background: rgba(224, 82, 82, .10);
    border: 1px solid rgba(224, 82, 82, .35);
    border-radius: 6px;
    font-size: .8rem;
}
.cc-retry-text { color: #e05252; flex: 1 1 auto; min-width: 0; }
.cc-retry-btn {
    flex: 0 0 auto;
    padding: .18rem .55rem;
    background: transparent; border: 1px solid rgba(224, 82, 82, .55); border-radius: 5px;
    color: #e05252; cursor: pointer; font: inherit; font-size: .78rem;
}
.cc-retry-btn:hover { background: rgba(224, 82, 82, .18); }

.cc-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.cc-chip {
    display: inline-flex; align-items: center; gap: .25rem; background: var(--panel-2);
    border: 1px solid var(--border); border-radius: 999px; padding: .15rem .5rem; font-size: .78rem;
}
.cc-chip-x { background: none; border: none; color: var(--muted); cursor: pointer; font-size: .9rem; line-height: 1; }

/* La miniatura de una imagen adjunta. **Alta el doble que el botón de enviar** —que mide unas 2.1rem con su
   padding—, que es el tamaño en el que una captura de pantalla todavía se reconoce sin robarle sitio al cuadro
   de texto. El ancho es libre: recortar una captura apaisada a un cuadrado se lleva justo la parte que la
   distingue de la de al lado. */
.cc-chips { align-items: flex-start; }
.cc-thumb {
    position: relative; display: inline-flex; height: var(--cc-thumb-h, 4.2rem);
    border: 1px solid var(--border); border-radius: 6px; overflow: hidden; background: var(--panel-2);
}
.cc-thumb img { height: 100%; width: auto; max-width: 12rem; object-fit: cover; display: block; }
/* La aspa va **encima** y no al lado: fuera de la imagen empujaría la fila y dejaría la miniatura descolocada
   respecto a las pastillas de los adjuntos que no son imágenes. */
.cc-thumb-x {
    position: absolute; top: 0; right: 0;
    width: 1.25rem; height: 1.25rem; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .55); color: #e6e6e6; border-bottom-left-radius: 6px;
}
.cc-thumb-x:hover { background: rgba(0, 0, 0, .8); }
/* El clip: un botón con el 📎, no el `<input type=file>` nativo, que va oculto. */
.cc-attach {
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    width: 2rem; height: 2rem; border-radius: 6px; font-size: 1.05rem; color: var(--muted);
    border: 1px solid var(--border); background: var(--panel-2);
}
.cc-attach:hover { color: var(--text); border-color: var(--accent); }
/* El botón de apuntar una nota, a la derecha del clip (móvil). Mismo marco que el clip: son dos acciones del
   mismo rango sobre lo que se está escribiendo, y darle otra forma las jerarquizaría sin motivo. */
.cc-note {
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    width: 2rem; height: 2rem; border-radius: 6px; color: var(--muted);
    border: 1px solid var(--border); background: var(--panel-2);
}
.cc-note:hover { color: var(--text); border-color: var(--accent); }

/* **El popover de capturar del escritorio** (0.27.148). En el telefono la captura ocupa la pantalla porque no
   hay sitio para otra cosa; aqui el chat sigue a la vista, y lo que se apunta suele salir de lo que se esta
   leyendo. Se ancla al boton y se abre **hacia arriba**: debajo esta el borde de la ventana. */
.cc-capture { position: relative; display: inline-flex; }
.cc-note.is-on { color: var(--text); border-color: var(--accent); background: var(--panel); }

/* El velo cierra al pulsar fuera y **no pinta nada**: oscurecer el chat por apuntar una idea seria tratar un
   gesto de dos segundos como un modal. */
.cc-capture-veil { position: fixed; inset: 0; z-index: 40; }

.cc-capture-pop {
    position: absolute; bottom: calc(100% + .4rem); right: 0; z-index: 41;
    width: min(22rem, 60vw); padding: .6rem;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
    display: flex; flex-direction: column; gap: .5rem;
}

/* Los tres tipos con el mismo segmentado que los ajustes del chat, que es el control que esta fila ya usa. */
.cc-capture-kinds { display: flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.cc-capture-kinds .seg-item { flex: 1 1 0; }

.cc-capture-text {
    width: 100%; resize: vertical; min-height: 4rem;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border); border-radius: 6px; padding: .4rem .5rem;
    font: inherit; font-size: .85rem;
}
.cc-capture-text:focus { outline: none; border-color: var(--accent); }

.cc-capture-row { display: flex; align-items: center; gap: .4rem; min-width: 0; }
.cc-capture-label { color: var(--muted); font-size: .75rem; flex: 0 0 auto; }
.cc-capture-select {
    flex: 1 1 auto; min-width: 0;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border); border-radius: 6px; padding: .25rem .35rem; font-size: .8rem;
}
.cc-capture-none { color: var(--muted); font-size: .75rem; }

.cc-capture-acts { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.cc-capture-hint { color: var(--muted); font-size: .7rem; }

/* --- El medidor de contexto ---------------------------------------------------------------------- */

/* Tres niveles y no un degradado: lo que hay que saber es «vas bien», «ojo» y «ya toca abrir otro». */
.cc-meter { display: inline-block; width: 1.4rem; height: 1.4rem; flex: 0 0 auto; }
.cc-meter svg { width: 100%; height: 100%; display: block; }
.cc-meter-track { stroke: var(--border); }
.cc-meter-fill { transition: stroke-dasharray .35s ease, stroke .35s ease; }
.cc-meter.is-ok   .cc-meter-fill { stroke: #7bd88f; }
.cc-meter.is-high .cc-meter-fill { stroke: #d9a441; }
.cc-meter.is-full .cc-meter-fill { stroke: #e08585; }

/* --- Los ajustes: pastilla y panel ---------------------------------------------------------------- */

.cc-settings { position: relative; }
/* La pastilla dice el **permiso**, que es el ajuste con consecuencias: el modelo y el esfuerzo cambian lo que
   cuesta y lo que tarda, pero el permiso cambia lo que Claude puede hacerle a tu disco. */
.cc-pill {
    display: inline-flex; align-items: center; gap: .3rem; max-width: 100%; white-space: nowrap;
    background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); border-radius: 999px;
    font: inherit; font-size: .78rem; padding: .3rem .7rem; cursor: pointer;
}
.cc-pill.is-set { border-color: var(--chat-accent); color: var(--chat-accent); }
.cc-pill:disabled { opacity: .55; cursor: default; }

.cc-settings-back { position: fixed; inset: 0; z-index: 39; background: transparent; }
.cc-settings-panel {
    position: absolute; bottom: calc(100% + .5rem); left: 0; z-index: 40; width: 20rem; max-width: 80vw;
    background: var(--panel); border: 1px solid var(--border); border-radius: .5rem; padding: .8rem;
    display: flex; flex-direction: column; gap: .7rem; box-shadow: 0 .6rem 1.6rem rgba(0,0,0,.5);
}
.cc-settings-group { display: flex; flex-direction: column; gap: .35rem; }
.cc-settings-label { color: var(--muted); font-size: .74rem; }
/* Desplegable de los ajustes: se usa cuando hay más opciones de las que caben en el segmentado. Hereda el
   aspecto del panel para que el cambio de control no parezca un cambio de sitio. */
.cc-select {
    width: 100%; padding: .38rem .5rem; border: 1px solid var(--border); border-radius: 8px;
    background: var(--panel-2); color: var(--text); font: inherit; font-size: .78rem; cursor: pointer;
}
.cc-select:focus-visible { outline: 2px solid var(--accent, #d08770); outline-offset: 1px; }

/* El aviso del agente: se lee, no se ignora, pero no grita —es una advertencia, no un fallo—. */
.cc-settings-warning {
    margin: 0; padding: .4rem .5rem; border-radius: 6px; font-size: .72rem; line-height: 1.35;
    background: color-mix(in srgb, var(--warn, #d08770) 14%, transparent);
    color: var(--text); border: 1px solid color-mix(in srgb, var(--warn, #d08770) 40%, transparent);
}
/* La nota del control bloqueado: **informa, no advierte**. Nada va mal —el agente se eligió y el proceso
   arrancó—, así que no lleva el fondo del aviso: sería alarmar por el funcionamiento normal. */
.cc-settings-note { margin: .35rem 0 0; font-size: .7rem; line-height: 1.35; color: var(--muted); }

/* La espera de la oferta de agentes. **Ocupa alto** —una altura mínima parecida a la de los controles que
   sustituye— para que el panel no salte de tamaño cuando llega la lista. */
.cc-settings-loading {
    display: flex; align-items: center; gap: .5rem; min-height: 6rem;
    justify-content: center; font-size: .78rem; color: var(--muted);
}

/* **El anillo se define aquí y no se reutiliza `.nav-spinner`**, aunque sea el mismo dibujo: ese vive en
   `app.css`, que **solo carga el escritorio** —el móvil enlaza únicamente esta hoja—, y allí el giro habría
   salido invisible. La animación sí se comparte: es `cc-spin`, la de la estrella, ya declarada arriba. */
.cc-settings-loading .nav-spinner {
    width: 1rem; height: 1rem; flex: 0 0 auto; border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--text) 22%, transparent);
    border-top-color: var(--accent, #d08770);
    animation: cc-spin .7s linear infinite;
}

/* **Un solo «Aplicar»** para los tres: cambiarlos de uno en uno reiniciaba el CLI tres veces seguidas. */
.cc-settings-actions { display: flex; gap: .5rem; justify-content: flex-end; }
.cc-settings-apply { align-self: flex-end; }

/* Control segmentado (Modelo, Permisos): botones unidos en una fila, una sola elección. También se usa fuera
   del chat —«Cuentas de Claude», la bienvenida—, y por eso el acento vive en la raíz y no dentro de `.cc`. */
.seg { display: flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.seg-item {
    flex: 1 1 0; background: var(--panel-2); border: none; border-left: 1px solid var(--border);
    color: var(--text); font: inherit; font-size: .76rem; padding: .3rem .4rem; cursor: pointer;
    text-align: center; line-height: 1.15;
}
.seg-item:first-child { border-left: none; }
.seg-item:hover { background: var(--panel); }
/* El elegido va con el acento **y** con peso: solo color no basta para quien no distingue bien los tonos, y
   además el borde interior lo separa del resto de la tira. */
.seg-item.is-sel {
    background: var(--chat-accent); color: #e6e6e6; font-weight: 600;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25);
}
.seg-item.is-sel:hover { background: var(--chat-accent); }
/* Deshabilitado: se ve apagado y no responde al puntero. **El elegido se exceptúa a propósito** —conserva
   el acento entero— porque cuando la tira entera está bloqueada, lo único que hay que poder leer de un
   vistazo es cuál está en uso (decisión del usuario, 2026-09-05: «deshabilita destacando el actual»).
   Atenuarlo también dejaría la fila como un bloque gris del que no se saca ninguna información. */
.seg-item:disabled { opacity: .4; cursor: default; }
.seg-item:disabled:hover { background: var(--panel-2); }
.seg-item.is-sel:disabled { opacity: 1; }
.seg-item.is-sel:disabled:hover { background: var(--chat-accent); }

/* Deslizante segmentado (Esfuerzo): es ordinal, así que un rango con las marcas etiquetadas debajo. */
.seg-slider { display: flex; flex-direction: column; gap: .25rem; }
.seg-slider input[type=range] { width: 100%; accent-color: var(--chat-accent); margin: 0; }
.seg-ticks { display: flex; justify-content: space-between; gap: .15rem; }
.seg-tick { flex: 1 1 0; text-align: center; color: var(--muted); font-size: .62rem; }
.seg-tick.is-sel { color: var(--chat-accent); font-weight: 600; }

/* --- El histórico -------------------------------------------------------------------------------- */

.cc-history { position: relative; }
.cc-history-panel {
    position: absolute; top: calc(100% + .4rem); right: 0; z-index: 40; width: 22rem; max-width: 85vw;
    background: var(--panel); border: 1px solid var(--border); border-radius: .5rem; padding: .7rem;
    display: flex; flex-direction: column; gap: .4rem; max-height: 26rem; overflow-y: auto;
    box-shadow: 0 .6rem 1.6rem rgba(0,0,0,.5);
}
.cc-history-group-label { color: var(--muted); font-size: .72rem; }
.cc-history-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .2rem; }
.cc-history-item {
    display: flex; align-items: stretch; gap: .2rem;
    border: 1px solid transparent; border-radius: .35rem;
}
.cc-history-item:hover { border-color: var(--border); background: var(--panel-2); }
.cc-history-item.is-sel { border-color: var(--chat-accent); }
.cc-history-open {
    flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .05rem; text-align: left;
    background: none; border: none; color: var(--text); font: inherit; padding: .3rem .4rem; cursor: pointer;
}
.cc-history-name { font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-history-date { font-size: .68rem; color: var(--muted); }
/* Archivar vive en la **máquina dueña**: lo que se archive aquí desaparece también de la lista del otro
   aparato, y por eso el grupo dice cuántas hay en vez de esconderlas sin más. */
.cc-history-act {
    flex: 0 0 auto; background: none; border: none; color: var(--muted);
    font-size: .9rem; padding: 0 .45rem; cursor: pointer;
}
.cc-history-act:hover { color: var(--text); }
.cc-history-group {
    background: none; border: none; color: var(--muted); font: inherit; font-size: .74rem;
    padding: .3rem .1rem; text-align: left; cursor: pointer;
}
.cc-note { color: var(--muted); font-size: .78rem; margin: 0; }

/* =================================================================================================
   Táctil y estrecho. El corte es por **ancho**, no por «es la PWA»: el escritorio en una ventana estrecha
   quiere exactamente esto, y no hay motivo para negárselo.
   ================================================================================================= */
/* **La variante táctil vive en `chat-touch.css`** desde 0.26.28, y no aquí dentro de un `@media`.

   El motivo, en una línea: el corte por ancho es correcto para la aplicación de escritorio y **falso para la
   PWA**, que en un navegador de escritorio es ancha y se llevaba la variante de puntero —el usuario lo reportó
   como «la PWA conserva estilos viejos» (observación 15)—. Ahora el reparto lo hace el atributo `media` del
   `<link>`: el escritorio la carga con `(max-width: 720px)` y la PWA sin condición.

   Este archivo sigue siendo **la base**: la variante de puntero y pantalla ancha. */


/* --- La pregunta de Claude, como modal (segunda tanda del 2026-07-28) ------------------------------
   El registro se queda con el resumen —la pregunta y lo que se eligió— y las opciones viven aquí. Con las
   opciones dentro de la conversación había **dos cuadros de texto** en pantalla (el «Otra…» y el compositor) y
   al escribir se confundían. */
.cc-askmodal { max-width: 34rem; width: min(34rem, 92vw); display: flex; flex-direction: column; gap: .8rem; }

/* **El modal no puede pasar del alto de la ventana** (usuario, 2026-09-07: «hay que agregar un scroll a las
   preguntas de contextara y que no sobrepasen el alto del contenedor»). Sin tope, una tanda de tres o cuatro
   preguntas con sus descripciones crecía hacia arriba y hacia abajo a la vez —el modal está centrado—, así que
   se cortaban por los dos extremos y **los botones quedaban fuera de la pantalla**: no se podía ni contestar ni
   cancelar mientras la sesión esperaba. Es el mismo tope que ya tenía el ritual de cierre de una tarea, y por el
   mismo motivo.

   El desplazamiento va **en la lista de preguntas**, no en el modal entero: con el modal como contenedor
   desplazable, el título y los botones se irían con el resto y habría que bajar a buscar «Responder». Así el
   marco se queda quieto y solo se mueve lo que se lee. */
.cc-askmodal { max-height: 88vh; }
.cc-askmodal-list {
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    display: flex; flex-direction: column; gap: .8rem;
}

/* Título y botones no se encogen aunque la lista sea larga: los botones son la salida. */
.cc-askmodal .cx-modal-title,
.cc-askmodal .cx-modal-actions { flex: 0 0 auto; }

.cc-askmodal .cc-ask-q { gap: .4rem; }
.cc-askmodal .cc-ask-opts { flex-direction: column; align-items: stretch; }
.cc-askmodal .cc-ask-opt { text-align: left; }
/* El velo del modal de la pregunta tapa **de verdad**: mientras la sesión espera, el chat de debajo no se puede
   usar, y dejarlo a la vista y pulsable invitaba a escribir en el cuadro equivocado. */
.cc-askmodal-back { background: rgba(0, 0, 0, .55); }

/* En el registro, la pregunta viva es una línea: «esperando tu respuesta». Lo que hay que hacer está en el
   modal, y repetir las opciones aquí es lo que las duplicaba en pantalla. */
.cc-ask.is-waiting { border-color: var(--chat-accent); }
.cc-ask-waiting { font-size: .78rem; color: var(--chat-accent); }

/* **«· cargar más mensajes»**, en la raya de la conversación sembrada (0.27.81). Es un enlace y no un botón a la
   vista: vive dentro de una raya de una sola línea, y darle caja lo convertiría en la pieza más pesada de una
   franja que solo separa. Mientras trae, se deshabilita y lo dice — pulsarlo dos veces traería el mismo tramo. */
.cc-loadmore {
    background: none; border: none; padding: 0 0 0 .35rem; cursor: pointer;
    color: var(--chat-accent); font: inherit; font-size: inherit;
}
.cc-loadmore:hover:not(:disabled) { text-decoration: underline; }
.cc-loadmore:disabled { cursor: default; color: var(--muted); }

/* =================================================================================================
   LA VENTANA EXTERNA: el mismo chat, y el mismo armazón (usuario, 2026-08-25)
   =================================================================================================
   *«La ventana de chat externa tiene problema con el scroll: la parte inferior donde está el input y los
   botones debe quedar fija, ahora se desplaza con el scroll. También la cabecera debe quedar fija. El botón
   de conversaciones anteriores no funciona: abre el listado con problema de estilo y no se puede pinchar.»*

   **Las tres cosas son el mismo defecto, y no está en el chat.** `.cc` reparte su alto con `flex` y deja que
   desplace **solo** el registro (`.cc-log`), que es exactamente lo que el usuario pide; para eso necesita saber
   cuánto alto tiene, y lo pide en porcentaje (`height: 100%`). Dentro de la aplicación se lo da la rejilla del
   área de trabajo. En la ventana externa su padre es `.ventana-chat` dentro de `body`, y **ninguno de los dos
   tenía alto**: un porcentaje sobre un alto automático es alto automático, así que `.cc` crecía con la
   conversación, el registro no desplazaba nada y lo que desplazaba era **el documento entero** — cabecera y
   cuadro de escritura incluidos.

   Y de ahí sale también el listado inservible: `.cc-history-panel` se ancla a su botón, que en un documento de
   varias pantallas de alto está donde ya no se ve. El panel se abría fuera de la vista, cortado por el borde de
   la ventana; parecía un problema de estilos y era el mismo alto que falta.

   **Se arregla en el armazón y no tocando `.cc`**, que es la pieza que se comparte con la aplicación y con el
   móvil: lo que falta es el alto de la ventana, no una regla del chat. */
body.ventana-externa {
    /* `dvh` y no `vh`: la ventana externa puede acabar en un móvil, donde la barra del navegador se retrae y
       `vh` deja un trozo del cuadro de escritura debajo del borde.

       **Dividido por el zoom, igual que `.app-shell`** (usuario, 2026-08-25, al pedir el zoom de esta ventana).
       En Chromium el alto en unidades de viewport se mide **sin** escalar y después se multiplica por el `zoom`
       del elemento raíz, así que al ampliar el documento sobra por abajo y vuelve la barra de la página — con ella
       el defecto del scroll que se acaba de arreglar. `--vh-zoom` lo publica `contextaraSetZoom` **tras medirlo**,
       y vale 1 donde no hay que compensar. */
    height: calc(100dvh / var(--vh-zoom, 1));
    display: flex;
    /* El documento **no** desplaza: desplazar es del registro. Sin esto, un hijo que se pase de alto por un
       instante —una imagen que carga— devuelve la barra al documento y con ella el defecto. */
    overflow: hidden;
}

body.ventana-externa .ventana-chat {
    flex: 1 1 auto;
    min-width: 0;
    /* `min-height: 0` en toda la cadena: sin él, un hijo flexible se niega a encogerse por debajo de su
       contenido y el `overflow-y: auto` del registro nunca entra en juego. Es la trampa clásica de flexbox y la
       razón por la que hace falta repetirlo en cada eslabón. */
    min-height: 0;
    display: flex;
    padding: .6rem .8rem;
    box-sizing: border-box;
}

body.ventana-externa .ventana-chat > .cc {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* La ventana vacía —«esta conversación ya no está abierta»— se centra, que es lo único que puede hacer una
   ventana sin contenido. */
body.ventana-externa .ventana-vacia {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: .4rem;
}

/* =================================================================================================
   UBICARSE EN LOS PROMPTS: barra flotante y carril de puntos (usuario, 2026-08-25)
   =================================================================================================
   *«Barra horizontal flotante en la parte superior del chat que solo aparece cuando se hace scroll (aparece sobre
   el chat, no usa espacio vertical ni mueve elementos)… indicador a la izquierda con un punto por cada prompt.»*

   Las dos condiciones del pedido son de CSS y no de comportamiento: **flotan**. `.cc-logwrap` es el único
   elemento nuevo del armazón y solo existe para ser el marco de referencia de los dos flotantes; hereda el
   reparto de alto que antes tenía `.cc-log` directamente, así que el chat sigue distribuyéndose igual. */
.cc-logwrap { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* El registro deja sitio al carril a su izquierda. Es lo único que el armazón corre —medio centímetro, y solo en
   horizontal—: el pedido pide el indicador *a la izquierda del prompt*, así que ese sitio tiene que existir. La
   barra, en cambio, no corre nada: flota encima. */
.cc-logwrap > .cc-log { flex: 1 1 auto; min-height: 0; padding-left: .8rem; }

/* La barra. `is-on` la enciende el guion cuando hay algo por encima. */
.cc-sticky {
    position: absolute; top: 0; left: 0; right: 0; z-index: 30;
    display: flex; align-items: center; gap: .5rem;
    padding: .25rem .5rem;
    /* Translúcida y con desenfoque: tapa la línea que cruza, y a la vez se ve que hay conversación debajo — que
       es lo que dice que estás **sobre** el chat y no en una cabecera nueva. */
    background: color-mix(in srgb, var(--panel) 88%, transparent);
    backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--border);
    font-size: .76rem; color: var(--muted);
    /* Fuera de la vista y **sin recibir pulsaciones** mientras está apagada: una barra invisible que se come el
       clic del primer mensaje es peor que no tenerla. */
    opacity: 0; transform: translateY(-.4rem); pointer-events: none;
    transition: opacity .12s ease, transform .12s ease;
}

.cc-sticky.is-on { opacity: 1; transform: none; pointer-events: auto; }

/* La primera línea del prompt se lleva el ancho y se recorta: es una referencia, no el texto. */
.cc-sticky-text {
    flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    color: var(--text);
}

.cc-sticky-count { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

.cc-sticky-arrow {
    flex: 0 0 auto; background: none; border: 1px solid transparent; border-radius: .25rem;
    color: var(--muted); font: inherit; line-height: 1; padding: .1rem .3rem; cursor: pointer;
}
.cc-sticky-arrow:hover { color: var(--text); border-color: var(--border); background: var(--panel-2); }

/* El carril de puntos, pegado al borde izquierdo del registro. **Absoluto**: un carril en el flujo movería el
   texto de toda la conversación unos milímetros a la derecha, y el pedido dice que no mueva elementos. */
.cc-dots {
    position: absolute; left: 0; top: 0; bottom: 0; z-index: 20;
    width: .55rem;
    display: none; flex-direction: column; align-items: center; justify-content: center;
    /* El hueco entre puntos lo calcula el guion: depende de cuántos hay y de lo alto que sea el registro. */
    overflow: hidden;
}

/* Con un solo prompt no hay dónde ubicarse: el carril sobra y se calla. */
.cc-dots.is-on { display: flex; }

.cc-dot {
    flex: 0 0 auto; width: .3rem; height: .3rem; padding: 0;
    border: none; border-radius: 50%; cursor: pointer;
    background: var(--border);
    transition: background .12s ease, transform .12s ease;
}
.cc-dot:hover { background: var(--muted); transform: scale(1.6); }

/* Por dónde vas: los pasados encendidos a media luz, el actual con el color del chat y más grande. */
.cc-dot.is-past { background: var(--muted); }
.cc-dot.is-here { background: var(--chat-accent); transform: scale(1.8); }

/* En pantalla estrecha el carril se retira: el ancho es lo que falta ahí, y el dedo no acierta un punto de tres
   píxeles. La barra se queda, que es la mitad que sí sirve en un teléfono. */
@media (max-width: 640px) {
    .cc-dots { display: none !important; }
}

/* El control de zoom en la cabecera del chat, a la derecha del reloj. `.cc-head` alinea por la línea base —lo
   correcto para texto— y una caja con borde colgada de ahí queda un pelo alta: se centra ella sola. */
.cc-head .zoom-control { align-self: center; flex: 0 0 auto; }

/* La cola de turnos pendientes (0.27.276), encima del compositor: una fila por turno, con su ✕.

   **Discreta a propósito.** No es un aviso —nada va mal— y no puede competir con la respuesta que está
   llegando: fondo del panel, texto en una línea y del tamaño del cuerpo pequeño. Lo que sí destaca es la ✕,
   porque es lo único accionable de la fila.

   Y **no crece**: el texto se recorta en el marcado, así que tres pendientes largos siguen ocupando tres
   líneas y el cuadro de escribir no se va de la pantalla. */
.cc-queue { display: flex; flex-direction: column; gap: .2rem; margin-bottom: .35rem; }
.cc-queue-item {
    display: flex; align-items: center; gap: .4rem;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 6px;
    padding: .2rem .4rem; font-size: .78rem; color: var(--muted);
}
.cc-queue-mark { flex: 0 0 auto; opacity: .8; }
.cc-queue-text { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-queue-clips { flex: 0 0 auto; font-size: .72rem; }
.cc-queue-item .cc-chip-x { flex: 0 0 auto; }

/* Lo que quedó en cola mientras el agente trabaja (0.27.216): una pastilla discreta al lado del botón, no un
   aviso. Es información de estado, y el sitio donde se busca es justo donde se escribió. */
.cc-queued {
    align-self: center; margin-left: .5rem; padding: .1rem .45rem;
    border: 1px solid var(--border); border-radius: 999px;
    font-size: .68rem; color: var(--muted); white-space: nowrap;
}
