/* ═══════════════════════════════════════════════════════════════════════════
   Aimee — con el estilo de Arc (uiarc.dev)
   Los tokens (color, tipo, radios, sombras, temas) son los de Arc y vienen de
   `arc-foundation.css`, que se carga antes. Aimee no usa sus componentes React:
   reestiliza su propio HTML con esos tokens y con las reglas de Arc.
   - Superficies planas sobre un borde de 1px. Sin cristal, sin blur y sin
     degradados de adorno.
   - Sombra solo en lo que flota (diálogos, menús, la tarjeta del mapa):
     `--shadow-floating`.
   - Pesos 400 y 500. Sin mayúsculas forzadas ni `text-shadow`.
   - El acento solo en lo activo, lo elegido o el dato que importa, y el
     estado (`--success`, `--warning`, `--danger`) solo para estados de verdad.
   - El foco: ningún anillo con el ratón; con teclado, el de Arc.

   TODO VIVE BAJO `#aimee`. Para poder meter Aimee dentro de otro sistema sin que
   su CSS toque nada de fuera, cada selector empieza por `#aimee`, cada id por
   `aimee-` y cada @keyframes por `aimee-`. Lo que antes iba en `:root`, `html` o
   `body` (los tokens, el tema, el fondo, el layout de página) va ahora en el
   propio contenedor. Una regla nueva sigue el mismo patrón.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Tokens: alias sobre Arc ─────────────────────────────────────────────────
   Los valores los pone `arc-foundation.css` (se carga antes). Aquí solo se
   traducen los nombres de siempre de Aimee a los papeles de Arc, para que las
   miles de reglas de abajo cambien de piel sin reescribirse. Una regla nueva
   usa directamente los tokens de Arc (`--background`, `--foreground`,
   `--text-secondary`, `--surface-muted`, `--radius-*`, `--shadow-floating`…).

   `--surface`, `--border`, `--border-strong`, `--accent`, `--danger`,
   `--success` y `--warning` se llaman igual en Arc y NO se redefinen, salvo
   `--surface`: en Aimee es el gris de los hovers y la burbuja del usuario, que
   en Arc es `--surface-muted` (su `--surface` es blanco).
   El acento es el azul de Arc (`data-accent="blue"` en el HTML) y el tema, el
   claro. Los valores oscuros llegan solos con `data-theme="dark"`.
   ──────────────────────────────────────────────────────────────────────────── */
#aimee {
    /* Superficies */
    --bg:             var(--background);
    --bg2:            color-mix(in oklab, var(--surface-muted) 50%, var(--background));
    --surface:        var(--surface-muted);
    --surface-2:      color-mix(in oklab, var(--surface-muted), var(--foreground) 4%);
    --surface-3:      color-mix(in oklab, var(--surface-muted), var(--foreground) 8%);

    /* Texto */
    --text:           var(--foreground);
    --text-mid:       var(--text-secondary);
    --text-dim:       var(--text-muted);

    /* Acento */
    --accent-hover:   var(--accent-strong);
    --accent-soft:    var(--accent-subtle);
    --on-accent:      var(--accent-foreground);
    /* «Hay un skill que puede atender esto». Ámbar de la familia de Arc: no
       puede confundirse con el foco, que usa el acento. */
    --dorado:         var(--tone-amber);
    --dorado-soft:    color-mix(in oklab, var(--tone-amber) 14%, transparent);

    /* Par de inversión (botones sólidos) */
    --ink:            var(--foreground);
    --on-ink:         var(--background);
    --ink-soft:       color-mix(in oklab, var(--foreground) 16%, transparent);

    /* Semánticos: solo sus tintes; los colores son los de Arc */
    --danger-soft:    color-mix(in oklab, var(--danger) 10%, transparent);
    --success-soft:   color-mix(in oklab, var(--success) 14%, transparent);

    /* Gráficas (Highcharts), con los colores de las gráficas de Arc
       (line-chart y bar-chart de uiarc.dev):
       - series de una gráfica: la primera en el acento y las demás en gris,
         `--foreground` al 46 % y al 26 % sobre la superficie;
       - categorías (un pie, o más de tres series): `--series-1..4`, la paleta
         categórica de la foundation;
       - barras de una sola serie: el acento al 62 % sobre la superficie, y en
         pleno la que se señala;
       - rejilla en `--border`, eje en `--border-strong` y rótulos en `--text-muted`.
       app.js los lee y los pasa a rgb antes de dárselos a Highcharts. */
    --chart-1:        var(--accent);
    --chart-2:        color-mix(in oklab, var(--foreground) 46%, var(--surface));
    --chart-3:        color-mix(in oklab, var(--foreground) 26%, var(--surface));
    --chart-4:        var(--series-2);
    --chart-5:        var(--series-3);
    --chart-bar:      color-mix(in oklab, var(--accent) 62%, var(--surface));
    --chart-grid:     var(--border);
    --chart-axis:     var(--border-strong);
    --chart-label:    var(--text-muted);
    --chart-tooltip-bg:   var(--surface-raised);
    --chart-tooltip-text: var(--foreground);

    /* Las tres familias de capacidades del grafo de dispositivos (rosa vieja,
       aguamarina y azul celeste). Paleta medida para contraste y daltonismo:
       no se cambia por la de Arc sin volver a validarla. */
    --cap-own:        #B25C74;
    --cap-protocol:   #2FB89C;
    --cap-igniter:    #1A5FBF;

    /* Forma de onda de las notas de voz */

    --overlay:        oklch(0% 0 0 / .32);

    /* Radios. Los grandes son los de Arc; los dos pequeños quedan para piezas
       dentro de otra (concéntricos: el de dentro = el de fuera − el padding). */
    --r-xs:   8px;
    --r-sm:  12px;
    --r-md:  var(--radius-control);
    --r-lg:  var(--radius-panel);
    --r-xl:  var(--radius-surface);
    --r-pill: var(--radius-pill);

    /* Única sombra permitida: capas flotantes */
    --shadow-pop: var(--shadow-floating);

    /* Tipografía de Arc. `--font-display` (Geist) y `--font-body` (Inter) los
       define la foundation y leen estos dos ganchos: aquí solo se dice qué
       familia cargó la página (Google Fonts, 400 y 500) y su respaldo.
       Geist solo para lo de 30px o más; Inter para todo lo demás. */
    --font-geist: 'Geist', 'Geist Variable', system-ui, -apple-system;
    --font-inter: 'Inter', 'Inter Variable', system-ui, -apple-system;
    --font:      var(--font-body);
    --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;

    --sidebar-w: 300px;

    /* Alias de compatibilidad */
    --blue:      var(--accent);
    --blue-dim:  var(--accent-soft);
    --blue-glow: transparent;
    --user-bg:   var(--surface);
}

#aimee[data-theme="dark"] {
    /* Arc aclara las barras en oscuro para que se lean sobre la superficie. */
    --chart-bar:      color-mix(in oklab, var(--accent) 76%, var(--surface));
    --cap-own:        #B85471;
    --cap-protocol:   #2AB79B;
    --cap-igniter:    #4A86E0;
    --overlay:        oklch(0% 0 0 / .6);
}

/* ── Base ────────────────────────────────────────────────────────────────── */
/* `:where()` deja este reset en especificidad 0, la que tenía el `*` pelado. Con
   `#aimee *` (1,0,0) pisaría el margin y el padding de MapLibre y Highcharts, que
   pintan dentro de Aimee y antes le ganaban. */
:where(#aimee *) { margin: 0; padding: 0; box-sizing: border-box; }

/* Arc: solo pesos 400 y 500, también en lo que pinta el markdown. Especificidad
   baja (`:where`) para que cualquier regla propia le gane. */
:where(#aimee) :where(strong, b, th, h1, h2, h3, h4, h5, h6) { font-weight: 500; }
:where(#aimee) { letter-spacing: var(--tracking-body); line-height: var(--leading-body); }

/* Arc: Geist para los titulares y las cifras de 30px o más, con su tracking y
   su interlineado. Lo de menos de 30px sigue en Inter. */
#aimee :is(#aimee-welcome h1, .hero-title, .gm-big, .clima-temp strong) {
    font-family: var(--font-display);
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-display);
}

/* Arc: las cifras que cambian o se alinean en columna, con números tabulares. */
#aimee :is(.kpi-valor, .hero-kpi-value, .cost-row-value, .gm-big, .fc-big, .dv-codigo,
           .clima-temp, .msg-time, .timestamp, .bubble td, .gm-bar-lbl, .agenda-dia-num) {
    font-variant-numeric: tabular-nums;
}

/* Arc: toda animación tiene su rama de movimiento reducido. Una sola regla para
   todas, en vez de una por componente (las de abajo siguen y no estorban). */
@media (prefers-reduced-motion: reduce) {
    #aimee *, #aimee *::before, #aimee *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* EL SISTEMA NO SE MUEVE EN HORIZONTAL. NUNCA.
   No es solo una preferencia: en un móvil un desplazamiento lateral accidental
   deja el composer y los botones fuera de la vista y no hay forma obvia de
   volver. Se cierra en la raíz, y cada contenedor que sí necesite desplazarse de
   lado —un bloque de código, una tabla— lo hace dentro de sus propios límites. */
#aimee {
    background: var(--bg);
    overflow-x: hidden;
    max-width: 100%;
}

#aimee {
    color: var(--text);
    font-family: var(--font);
    /* `dvh` encima de `vh`, y en el móvil la diferencia es todo: `100vh` mide la
       ventana COMO SI la barra del navegador no estuviera, así que el alto real
       se queda corto justo lo que mide esa barra y el composer —que va al final
       de la columna— cae por debajo del pliegue. `dvh` sigue al viewport de
       verdad, y también cuando sube el teclado. `vh` se deja como respaldo para
       navegadores sin `dvh`. */
    height: 100vh;
    height: 100dvh;
    display: flex;
    flex-direction: row;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
}

/* El tema Aurora pintaba dos capas de gradiente aquí. Se anulan. */
#aimee::before,
#aimee::after { content: none; }

/* ── Sidebar toggle ──────────────────────────────────────────────────────── */
#aimee .sidebar-toggle {
    position: fixed;
    top: 12px; left: 12px;
    width: 34px; height: 34px;
    border-radius: var(--r-sm);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    z-index: 300;
    transition: background .15s, color .15s, border-color .15s;
    flex-shrink: 0;
}
#aimee .sidebar-toggle:hover { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
#aimee .sidebar-toggle svg { width: 16px; height: 16px; }

/* ── Acciones de la aplicación (esquina superior derecha) ────────────────────
   Simétricas al botón del historial: misma altura, mismo z-index, la otra
   esquina. Van fijas al viewport y no dentro del sidebar porque no dependen de
   la conversación ni de que el historial esté abierto. */
#aimee .top-actions {
    position: fixed;
    top: 12px; right: 12px;
    z-index: 300;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Sueltos ahí arriba tienen que ser el MISMO botón que el del historial, no un
   primo parecido. La piel va entera aquí —borde, centrado, cursor, transición—
   en vez de heredarla a medias de la cabecera del sidebar, que es de donde
   venían: el de los tres puntos no estaba en aquella lista y se quedaba sin
   borde propio, sin centrar y enseñando el resalte del navegador al pulsarlo. */
#aimee .top-actions > button {
    width: 34px; height: 34px;
    border-radius: var(--r-sm);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s, border-color .15s;
    flex-shrink: 0;
}
#aimee .top-actions > button:hover {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border-strong);
}
#aimee .top-actions > button svg { width: 16px; height: 16px; }

/* El botón de los tres puntos solo existe en móvil.
   Se escribe `.top-actions > .top-actions-toggle` y no `.top-actions-toggle` a
   secas porque la piel de arriba (`.top-actions > button`) ya trae `display:
   grid` y le ganaría por especificidad: el botón se colaba en escritorio. */
#aimee .top-actions > .top-actions-toggle { display: none; }

/* ── Las acciones plegadas (móvil) ───────────────────────────────────────────
   Tres botones a la derecha más el del historial a la izquierda no caben en un
   teléfono: con el historial abierto —que ahí ocupa 300px— se montaban encima.
   Se pliegan detrás de los tres puntos y bajan en columna al abrirlos.

   `column-reverse` deja los tres puntos ARRIBA aunque vayan los últimos en el
   HTML, que es donde tienen que estar: fijos en su sitio, con el resto
   descolgándose por debajo. */
@media (max-width: 720px) {
    #aimee .top-actions {
        flex-direction: column-reverse;
        align-items: flex-end;
        gap: 6px;
    }
    #aimee .top-actions > .top-actions-toggle { display: grid; }
    #aimee .top-actions > button:not(.top-actions-toggle) { display: none; }
    #aimee .top-actions.open > button { display: grid; }
    /* Abierto se marca exactamente igual que al pasar por encima: mismo fondo y
       mismo borde. Así el botón nunca cambia de forma, solo de tono. */
    #aimee .top-actions.open .top-actions-toggle {
        background: var(--surface);
        border-color: var(--border-strong);
        color: var(--text);
    }
}

/* ── Overlay móvil ───────────────────────────────────────────────────────── */
#aimee .sidebar-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--overlay);
    z-index: 99;
}
#aimee .sidebar-overlay.visible { display: block; }

/* ── Sidebar ─────────────────────────────────────────────────────────────── */
#aimee .sidebar {
    width: 0;
    min-width: 0;
    background: var(--bg2);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: width .25s ease, min-width .25s ease;
    flex-shrink: 0;
    z-index: 100;
}
#aimee .sidebar.open {
    width: var(--sidebar-w);
    min-width: var(--sidebar-w);
}

#aimee .sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 14px 12px 14px 52px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
#aimee .sidebar-label {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
    white-space: nowrap;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Botones de cabecera del sidebar — misma piel para todos */
#aimee .session-btn,
#aimee .new-chat-btn,
#aimee .selection-toggle-btn {
    width: 26px; height: 26px;
    border-radius: var(--r-xs);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s, border-color .15s;
    flex-shrink: 0;
}
#aimee .session-btn:hover,
#aimee .new-chat-btn:hover,
#aimee .selection-toggle-btn:hover {
    background: var(--surface-2);
    color: var(--text);
    border-color: var(--border-strong);
}
#aimee .session-btn svg,
#aimee .new-chat-btn svg,
#aimee .selection-toggle-btn svg { width: 13px; height: 13px; }

/* Campana tachada cuando los avisos están silenciados, y apagada de color para
   que se note de un vistazo que ahí no va a sonar nada. */
#aimee .notify-btn .icon-bell-off { display: none; }
#aimee .notify-btn.is-muted .icon-bell     { display: none; }
#aimee .notify-btn.is-muted .icon-bell-off { display: block; }
#aimee .notify-btn.is-muted { opacity: .55; }

/* ── Lista de conversaciones ─────────────────────────────────────────────── */
#aimee .conversations-list {
    flex: 1;
    overflow-y: auto;
    padding: 6px;
}
#aimee .conversations-list::-webkit-scrollbar { width: 3px; }
#aimee .conversations-list::-webkit-scrollbar-track { background: transparent; }
#aimee .conversations-list::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

#aimee .conv-item {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    background: none;
    border: none;
    border-radius: var(--r-sm);
    padding: 8px 9px;
    transition: background .15s;
    margin-bottom: 2px;
}
#aimee .conv-item:hover   { background: var(--surface); }
#aimee .conv-item.active  { background: var(--surface-2); }
#aimee .conv-item.checked { background: var(--surface-2); }

#aimee .conv-checkbox {
    width: 15px; height: 15px;
    flex-shrink: 0;
    accent-color: var(--accent);
    cursor: pointer;
    display: none;
}
#aimee .conv-checkbox.visible { display: block; }

#aimee .conv-item-body {
    flex: 1;
    min-width: 0;
    text-align: left;
    cursor: pointer;
}

#aimee .conv-title {
    font-size: var(--text-sm);
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-bottom: 2px;
}
#aimee .conv-item.active .conv-title { color: var(--text); font-weight: 500; }

#aimee .conv-date { font-size: var(--text-xs); color: var(--text-dim); }

/* ── Sin leer ────────────────────────────────────────────────────────────────
   Rojo y con la cifra: en una lista de catorce conversaciones, un punto sin
   número no dice si te has perdido un mensaje o quince. Tabular para que no
   baile al pasar de 9 a 10, y `min-width` para que el globo sea redondo con una
   cifra y ovalado con tres, en vez de estrecharse. */
#aimee .conv-badge {
    flex-shrink: 0;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--danger);
    color: #FFFFFF;
    font-size: var(--text-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 18px;
    text-align: center;
}
/* Una conversación con algo sin leer se lee antes que las demás. */
#aimee .conv-item.has-unread .conv-title { font-weight: 500; }

/* El mismo aviso, pero sobre el botón que abre el historial: es lo único
   visible cuando el sidebar está cerrado. Se ancla contra `.sidebar-toggle`,
   que ya es `position: fixed`. */
#aimee .toggle-badge {
    position: absolute;
    top: -5px; right: -5px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--danger);
    border: 2px solid var(--bg);
    color: #FFFFFF;
    font-size: var(--text-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 12px;
    text-align: center;
    pointer-events: none;
}
#aimee .toggle-badge[hidden] { display: none; }

/* En oscuro, --danger es un coral claro pensado para texto sobre fondo negro.
   Como relleno con letra blanca se queda en 2.8:1, que no se lee. Se invierte:
   letra casi negra sobre el coral, y sube a 6.7:1. */
#aimee[data-theme="dark"] .conv-badge,
#aimee[data-theme="dark"] .toggle-badge { color: #1C0F0D; }

#aimee .conv-delete {
    width: 22px; height: 22px;
    border-radius: var(--r-xs);
    border: none;
    background: none;
    color: transparent;
    cursor: pointer;
    display: grid; place-items: center;
    flex-shrink: 0;
    transition: background .15s, color .15s;
    padding: 0;
}
#aimee .conv-item:hover .conv-delete { color: var(--text-dim); }
#aimee .conv-delete:hover { background: var(--danger-soft); color: var(--danger) !important; }
#aimee .conv-delete svg { width: 13px; height: 13px; }

#aimee .selection-toggle-btn.active {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--on-ink);
}

/* ── Pie del sidebar ─────────────────────────────────────────────────────── */
#aimee .sidebar-footer {
    padding: 10px;
    border-top: 1px solid var(--border);
    display: none;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}
#aimee .sidebar-footer.visible { display: flex; }

#aimee .select-all-label {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1;
    cursor: pointer;
    font-size: var(--text-xs);
    color: var(--text-mid);
    user-select: none;
}
#aimee .select-all-label:hover { color: var(--text); }
#aimee .select-all-label input[type="checkbox"] {
    width: 14px; height: 14px;
    accent-color: var(--accent);
    cursor: pointer;
    flex-shrink: 0;
}

#aimee .sidebar-footer-btn {
    padding: 7px 12px;
    border-radius: var(--r-xs);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--danger);
    font-size: var(--text-xs);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s, border-color .15s;
    white-space: nowrap;
}
#aimee .sidebar-footer-btn:hover { background: var(--danger-soft); border-color: var(--danger); }
#aimee .sidebar-footer-btn:disabled { opacity: .35; cursor: not-allowed; pointer-events: none; }

/* ── Sesión (pie del sidebar) ────────────────────────────────────────────────
   Siempre visible y siempre abajo: `margin-top: auto` la empuja al fondo aunque
   haya dos conversaciones, para que no quede flotando a media altura. */
#aimee .sidebar-session {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}
#aimee .sidebar-session-who {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
/* El nombre puede ser largo y el sidebar es estrecho: se recorta antes que
   ensanchar nada o empujar el botón fuera. */
#aimee .sidebar-session-name {
    font-size: var(--text-sm);
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#aimee .sidebar-session-name:empty::before {
    content: '—';
    color: var(--text-dim);
}

#aimee .sidebar-empty {
    font-size: var(--text-sm);
    color: var(--text-dim);
    text-align: center;
    padding: 24px 12px;
    line-height: 1.6;
}

/* ── Tooltip ─────────────────────────────────────────────────────────────── */
#aimee .tooltip-popup {
    position: fixed;
    /* Aparcado arriba a la izquierda hasta que el JS lo coloque. Sin esto se
       queda al final del flujo, 10px por debajo del pliegue: invisible, pero es
       la clase de resto que se vuelve un fallo el día que alguien cambie un
       `overflow`. */
    top: 0; left: 0;
    background: var(--ink);
    border: none;
    color: var(--on-ink);
    font-size: var(--text-xs);
    font-family: var(--font);
    font-weight: 500;
    padding: 5px 10px;
    border-radius: var(--r-xs);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity .12s, visibility .12s;
    z-index: 9999;
}
#aimee .tooltip-popup.visible { opacity: 1; visibility: visible; }

/* ── Diálogo de confirmación ─────────────────────────────────────────────── */
#aimee .confirm-overlay {
    position: fixed;
    inset: 0;
    background: var(--overlay);
    z-index: 500;
    display: none;
    align-items: center;
    justify-content: center;
}
#aimee .confirm-overlay.visible { display: flex; }

#aimee .confirm-dialog {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 24px;
    width: 100%;
    max-width: 340px;
    margin: 0 16px;
    box-shadow: var(--shadow-pop);
    animation: aimee-fadeIn .15s ease;
}

#aimee .confirm-message {
    font-size: var(--text-sm);
    color: var(--text);
    line-height: 1.5;
    margin-bottom: 20px;
}

#aimee .confirm-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

#aimee .confirm-btn {
    padding: 9px 16px;
    border-radius: var(--r-xs);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    font-size: var(--text-sm);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .confirm-btn:hover { background: var(--surface); color: var(--text); }
#aimee .confirm-btn.danger { border-color: var(--danger); background: var(--danger); color: #FFFFFF; }
#aimee .confirm-btn.danger:hover { background: var(--danger); opacity: .88; }

/* ── Área de chat ────────────────────────────────────────────────────────── */
#aimee .chat-area {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    position: relative;
    background: var(--bg);
}

/* El glow superior desaparece en el tema plano. */
#aimee .chat-area::before { content: none; }

/* ── Bienvenida ──────────────────────────────────────────────────────────── */
#aimee #aimee-welcome {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px 20px;
    text-align: center;
    animation: aimee-fadeIn .5s ease;
    overflow-y: auto;
    position: relative;
    z-index: 1;
}
#aimee #aimee-welcome h1 {
    font-size: clamp(var(--text-3xl), 4.4vw, var(--text-4xl));
    /* Light: el saludo cambia en cada recarga (saludos.js) y con 600 se leía
       como un titular. Inter se carga con el peso 300. */
    font-weight: 300;
    color: var(--text);
    margin-bottom: 32px;
    letter-spacing: -.03em;
    line-height: 1.1;
    /* Un poco menos ancho que el input (.input-inner, 690px): las frases largas
       no se salen de los márgenes. saludos.js baja el tamaño hasta que quepan en
       una línea y, si ni así, las parte en dos líneas equilibradas. */
    width: 100%;
    max-width: 620px;
    text-wrap: balance;
}
#aimee #aimee-welcome h1 span { color: var(--text-mid); }
/* Aimee, el personaje, donde antes iba el orbe de Lottie. */
#aimee .aimee-welcome { width: 180px; height: 180px; margin: 0 auto 8px; }
#aimee .aimee-welcome > .aimee-bot,
#aimee .aimee-dock-slot > .aimee-bot { width: 100%; height: 100%; }

/* En el chat Aimee no se va: flota arriba en el centro, con su nombre debajo,
   y los mensajes pasan por detrás (como Muse). Solo ella recibe el puntero;
   el resto del dock deja pasar los clics al hilo. */
#aimee .aimee-dock {
    position: absolute;
    top: 4px; left: 50%;
    transform: translateX(-50%);
    z-index: 5;
    display: flex;
    flex-direction: column;
    align-items: center;
    pointer-events: none;
}
#aimee .aimee-dock[hidden] { display: none; }
#aimee .aimee-dock-slot { width: 72px; height: 72px; pointer-events: auto; }
#aimee .aimee-dock-slot .aimee-glow { filter: blur(14px); }
#aimee .aimee-dock-name {
    margin-top: -12px;
    padding: 3px 11px;
    border-radius: var(--r-pill);
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--foreground);
    background: var(--surface-raised);
    border: 1px solid var(--border);
    animation: aimee-fadeIn .4s ease .45s both;
}

/* ── Mensajes ────────────────────────────────────────────────────────────── */
#aimee #aimee-messages {
    flex: 1;
    overflow-y: auto;
    /* UN CHAT NO SE DESPLAZA EN HORIZONTAL, nunca.
       `overflow-y: auto` con el eje X en `visible` hace que el navegador
       convierta la X en `auto` por especificación: cualquier hijo que se pasara
       de ancho —un hash largo medía 1121px, medido— dejaba el hilo entero
       desplazable de lado. Se cierra la X aquí como última red, y aparte se
       arregla la causa: que el contenido quepa (ver .bubble más abajo). */
    overflow-x: hidden;
    overscroll-behavior-y: contain;
    padding: 96px 0 20px;   /* deja sitio a Aimee en el dock */
    position: relative;
    z-index: 1;
    scroll-behavior: smooth;
    display: none;
}
#aimee #aimee-messages::-webkit-scrollbar { width: 4px; }
#aimee #aimee-messages::-webkit-scrollbar-track { background: transparent; }
#aimee #aimee-messages::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

/* ── Input ───────────────────────────────────────────────────────────────── */
#aimee .input-wrap {
    width: 100%;
    padding: 14px 24px 0;
    position: relative;
    z-index: 2;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    background: var(--bg);
    border-top: 1px solid var(--border);
}

#aimee .input-inner { width: 100%; max-width: 890px; }

#aimee .input-box {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 60px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    padding: 10px 10px 10px 20px;
    transition: border-color .15s, box-shadow .15s, background .15s;
}
#aimee .input-box:focus-within {
    background: var(--bg);
    border-color: var(--border-strong);
}

/* Mientras Aimee responde el foco no se pinta de azul. El campo sigue
   aceptando texto, pero deja de aparentar que el envío está disponible. */
#aimee .input-box.is-thinking:focus-within {
    border-color: var(--border-strong);
    box-shadow: none;
}

/* ── El aviso del precog ─────────────────────────────────────────────────────
   Mientras se escribe, si Aimee reconoce un skill que puede atender la frase, el
   canto de arriba del campo se pone dorado. Solo el de arriba: es un aviso, no un
   estado, y pintar el borde entero competiría con el foco.

   El `:focus-within` se repite a propósito. El foco reescribe `border-color` de las
   cuatro caras, así que sin volver a poner el dorado aquí el aviso se apagaría justo
   al escribir, que es la única vez que se puede ver. Lo mismo con la variante sobre
   foto, que además cambia el color de foco a `--ink`.

   Nada de sombras en el texto: el aviso vive en el borde de la caja. */
#aimee .input-box.skill-a-la-vista,
#aimee .input-box.skill-a-la-vista:focus-within {
    border-top-color: var(--dorado);
}


/* ── El chat fijado a un especialista ────────────────────────────────────────
   Las CUATRO caras en verde, y ahí está la diferencia con el aviso del precog de
   arriba, que sólo pinta el canto superior. Aquel es un aviso —dura lo que dura una
   frase a medio escribir— y este es un ESTADO: mientras esté encendido, lo que se
   escriba no va al chat de siempre, va a otro modelo. Un estado que cambia a dónde
   van tus preguntas tiene que rodear la caja, no asomar por un lado.

   `--success` y no un verde suelto: es el único verde del sistema y ya significa
   "esto está activo y funcionando" en el resto de la interfaz.

   El `:focus-within` se repite por lo mismo que en el aviso del precog: el foco
   reescribe `border-color` de las cuatro caras, así que sin volver a ponerlo aquí el
   borde se apagaría justo al escribir, que es cuando más falta hace verlo. Y la
   variante sobre foto va aparte porque allí el foco es `--ink`, no el acento.

   Nada de sombras en el texto: el estado vive en el borde de la caja. */
#aimee .input-box.especialista-fijado,
#aimee .input-box.especialista-fijado:focus-within {
    border-color: var(--success);
}

/* Si además hay un skill a la vista, el canto de arriba sigue siendo dorado: son
   dos cosas distintas —a dónde va la pregunta y qué se ha reconocido escribiendo— y
   taparlas la una con la otra perdería información. El dorado va después en el
   fichero, así que gana en el canto superior por orden de cascada; se repite aquí
   para que la intención quede escrita y no dependa de dónde esté cada bloque. */
#aimee .input-box.especialista-fijado.skill-a-la-vista,
#aimee .input-box.especialista-fijado.skill-a-la-vista:focus-within {
    border-top-color: var(--dorado);
}

/* El orbe de Aimee dentro del input. En reposo va desaturado; mientras Aimee
   consulta la API recupera su color y la animación se reanuda. */
#aimee .aimee-logo {
    width: 26px; height: 26px;
    flex-shrink: 0;
    display: grid; place-items: center;
    /* El orbe es pastel claro: sobre fondo claro hay que oscurecerlo para que
       se vea, sobre fondo oscuro ya destaca por sí solo. */
    filter: grayscale(1) brightness(.72);
    transition: filter .3s ease;
}
#aimee[data-theme="dark"] .aimee-logo { filter: grayscale(1) opacity(.8); }

#aimee .aimee-logo.is-thinking,
#aimee[data-theme="dark"] .aimee-logo.is-thinking { filter: none; }
#aimee .aimee-logo svg { width: 100%; height: 100%; display: block; }

#aimee textarea {
    flex: 1;
    background: none;
    border: none;
    outline: none;
    resize: none;
    color: var(--text);
    font-family: var(--font);
    font-size: var(--text-base);
    line-height: 1.5;
    max-height: 120px;
    min-height: 24px;
}
#aimee textarea::placeholder { color: var(--text-dim); }

#aimee .input-actions { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }

#aimee .icon-btn {
    width: 36px; height: 36px;
    border-radius: var(--r-pill);
    border: none;
    background: none;
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s;
}
#aimee .icon-btn:hover { background: var(--surface-2); color: var(--text); }
#aimee .icon-btn svg { width: 18px; height: 18px; }

/* ── Botón de micrófono ──────────────────────────────────────────────────── */
#aimee .mic-btn {
    width: 36px; height: 36px;
    border-radius: var(--r-pill);
    border: none;
    background: none;
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s;
    position: relative;
    flex-shrink: 0;
}
#aimee .mic-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
#aimee .mic-btn svg { width: 18px; height: 18px; }
#aimee .mic-btn:disabled { color: var(--text-dim); opacity: .45; cursor: not-allowed; }

#aimee .mic-btn.processing {
    color: var(--accent);
    opacity: .7;
    pointer-events: none;
}

#aimee .send-btn {
    width: 36px; height: 36px;
    border-radius: var(--r-pill);
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    cursor: pointer;
    display: grid; place-items: center;
    border: 1px solid transparent;
    transition: background .15s, color .15s, border-color .15s, transform .1s;
    flex-shrink: 0;
}
#aimee .send-btn:hover:not(:disabled) { background: var(--accent-hover); }
#aimee .send-btn:active:not(:disabled) { transform: scale(.94); }

/* Mientras Aimee responde: gris y sin clic. El relleno apenas separa del input
   (1.2:1), así que el borde es lo que mantiene el círculo legible. */
#aimee .send-btn:disabled {
    background: var(--surface-3);
    border-color: var(--border-strong);
    color: var(--text-dim);
    cursor: not-allowed;
}
#aimee .send-btn svg { width: 16px; height: 16px; }

/* ── Sugerencias ─────────────────────────────────────────────────────────── */
#aimee .suggestions {
    display: flex;
    gap: 8px;
    margin-top: 18px;
    flex-wrap: wrap;
    justify-content: center;
}
#aimee .suggestion {
    padding: 9px 16px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-mid);
    cursor: pointer;
    transition: background .15s, color .15s;
    white-space: nowrap;
}
#aimee .suggestion:hover { background: var(--surface-2); color: var(--text); }

/* ── Disclaimer ──────────────────────────────────────────────────────────── */
/* Ocupa todo el ancho con un margen lateral que escala con la pantalla.
   Sin max-width: así el texto usa las líneas que quepan y el footer no crece
   de alto innecesariamente en pantallas anchas. */
/* El aviso legal, plegado tras su palabra. Desplegado son 74px en un móvil —el
   9% de la pantalla— y se lee una vez en la vida; el composer necesita ese sitio
   más que él. Se pliega en las dos plataformas: en escritorio también era un
   muro de texto de 8px que nadie leía. */
#aimee .disclaimer-wrap {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
}
#aimee .disclaimer-toggle {
    border: none;
    background: none;
    padding: 6px 12px 8px;
    font-family: inherit;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
    cursor: pointer;
    transition: color .15s;
}
#aimee .disclaimer-toggle:hover { color: var(--text-mid); }
/* Abierto se distingue, para que se vea que ESO es lo que se cierra. */
#aimee .disclaimer-toggle[aria-expanded="true"] { color: var(--text-mid); }

#aimee .disclaimer[hidden] { display: none; }

#aimee .disclaimer {
    font-size: var(--text-xs);
    color: var(--text-dim);
    text-align: center;
    width: 100%;
    padding: 8px clamp(16px, 4vw, 72px) 10px;
    margin: 0;
    line-height: 1.5;
    text-wrap: pretty;
}

/* ── Mensajes de chat ────────────────────────────────────────────────────── */
#aimee .timestamp {
    text-align: center;
    font-size: var(--text-xs);
    color: var(--text-dim);
    padding: 20px 0 12px;
}
#aimee .msg {
    /* El margen lateral del hilo, en un solo sitio: lo usan el relleno de aquí y
       el tope del mapa, que tienen que cuadrar. Antes eran dos constantes
       sueltas y bastaba tocar una para descuadrar el margen derecho. */
    --msg-pad: 28px;
    padding: 6px var(--msg-pad);
    display: flex;
    animation: aimee-fadeIn .25s ease;
    /* 960 y no 760: Aimee contesta con tablas y fichas, y necesita sitio. Va a la par
       con `.input-inner` (890px): el hilo útil (960 − 2×28) y la caja de escribir
       quedan alineados igual que antes con 760/690. */
    max-width: 960px;
    margin: 0 auto;
    width: 100%;
}
#aimee .msg.user { justify-content: flex-end; }
#aimee .msg.assistant { justify-content: flex-start; }

#aimee .bubble {
    max-width: 520px;
    font-size: var(--text-base);
    line-height: 1.65;
    /* `anywhere` y no `break-word`: la diferencia está en el tamaño mínimo que
       el navegador calcula para la caja. Con `break-word` el mínimo sigue siendo
       la palabra más larga, así que un token de 60 caracteres ensancha la
       burbuja igual; con `anywhere` puede partir y la burbuja respeta su ancho.
       Solo parte cuando no hay otra opción: el texto normal sigue cortando por
       espacios. */
    overflow-wrap: anywhere;
}

#aimee .msg.user .bubble {
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: var(--r-lg);
    padding: 12px 18px;
    color: var(--text);
}
/* Las respuestas de Aimee van sin burbuja, como en el chat de Arc (blocks/ai-chat): texto sobre el fondo, sin
   borde ni relleno. Solo la pregunta de la persona lleva globo. Las gráficas (`.chart-bubble`) y los mapas
   (`.map-bubble`) conservan su caja: lo que se mira es la gráfica, y sin marco se pierde. */
#aimee .msg.assistant .bubble:not(.chart-bubble) {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
    color: var(--text);
}

/* Listas dentro de burbujas */
#aimee .bubble ul,
#aimee .bubble ol {
    margin: 8px 0;
    padding-left: 24px;
}
#aimee .bubble ul ul,
#aimee .bubble ol ol,
#aimee .bubble ul ol,
#aimee .bubble ol ul { margin: 4px 0; }

#aimee .bubble li { margin: 4px 0; padding-left: 4px; }
#aimee .bubble p  { margin: 8px 0; }
#aimee .bubble p:first-child { margin-top: 0; }
#aimee .bubble p:last-child  { margin-bottom: 0; }

/* ── Enlaces dentro de la burbuja ────────────────────────────────────────────
   Hasta aquí no había ni una regla para `a` dentro del chat, así que las citas
   de una investigación —«[1]» con su enlace— salían con el azul, el morado de
   visitado y el subrayado que pone el navegador cuando nadie dice otra cosa: lo
   único de la pantalla que no pertenecía al sistema.

   Ahora cada enlace es una pastilla que dice DE DÓNDE sale el dato: el número
   de la cita y el dominio. El dominio es lo que se recorta cuando no cabe, y no
   el número, porque el número es la referencia y el dominio es el detalle; la
   URL entera sigue en el `title`. */
#aimee .bubble a {
    color: var(--accent);
    text-decoration: none;
}
#aimee .bubble a:hover { text-decoration: underline; }

#aimee .bubble a.cita {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    max-width: 220px;
    padding: 0 8px;
    margin: 0 1px;
    /* La pastilla es una caja dentro de un párrafo, y sin esto se sienta sobre
       la línea base en vez de cruzarla: el texto de alrededor queda un pelo
       alto. Los dos píxeles son la mitad del padding vertical efectivo. */
    vertical-align: -2px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    background: var(--bg);
    color: var(--text-mid);
    font-size: .84em;
    font-weight: 500;
    line-height: 1.75;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    transition: background .15s, border-color .15s, color .15s;
}
#aimee .bubble a.cita:hover {
    background: var(--surface);
    border-color: var(--accent);
    color: var(--accent);
    text-decoration: none;
}

/* Cuando el badge lleva dominio, el número es una referencia de dos o tres
   caracteres y no se recorta nunca. Cuando va solo, es el texto del enlace y
   entonces sí: es lo único que hay que encoger. */
#aimee .bubble a.cita .cita-num {
    flex: none;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}
#aimee .bubble a.cita .cita-num:only-child { flex: 0 1 auto; }

/* El punto medio es decoración, no contenido: por eso va en un `::after` y no
   en el HTML. El `:not(:last-child)` es lo que impide que quede un separador
   colgando cuando el badge no lleva dominio detrás. */
#aimee .bubble a.cita .cita-num:not(:last-child)::after {
    content: "·";
    margin-left: 5px;
    color: var(--text-dim);
    font-weight: 400;
}

/* El `min-width: 0` es lo que hace que la truncación funcione: sin él un hijo
   de flex no baja de su tamaño de contenido y el `ellipsis` no llega a pintarse
   nunca, por mucho `overflow: hidden` que lleve el padre. */
#aimee .bubble a.cita .cita-host {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 500;
}

/* Indicador de skill ejecutada — barra de acento a la izquierda.
   Usa --accent y no un tercer color: el sistema es monocromo + un acento. */
#aimee .msg.assistant .bubble.skill-response {
    border-left: 2px solid var(--accent);
    padding-left: 14px;
}

/* Mensaje de progreso mientras la investigación corre */
/* Animation removed - no pulsing effect */
#aimee .msg.progress-message .bubble {
    /* No animation */
}

/* ── Indicador de modo ───────────────────────────────────────────────────── */
#aimee .mode-indicator {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    margin-bottom: 8px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-mid);
    width: fit-content;
}

/* El indicador con un especialista fijado. Mismo componente que los modos de
   investigación y organización —incluido su × para quitarlo— teñido de verde para
   que la burbuja y el borde de la caja se lean como una sola cosa. Si fueran de
   colores distintos habría que aprender que van juntos. */
#aimee .mode-indicator.es-especialista {
    border-color: color-mix(in srgb, var(--success) 45%, var(--border));
    color: var(--success);
    background: color-mix(in srgb, var(--success) 8%, var(--surface));
}
#aimee .mode-indicator.es-especialista .mode-indicator-close { color: var(--success); }
#aimee .mode-indicator.es-especialista .mode-indicator-close:hover {
    background: color-mix(in srgb, var(--success) 14%, transparent);
    color: var(--success);
}

/* El nombre del especialista con inicial mayúscula: «Especialista Astrolle». Va en el
   CSS y no en las cadenas de los idiomas porque el adaptador llega en minúscula desde
   el backend —es un slug, `^[a-z0-9][a-z0-9_-]*$`— y así vale igual para «specialist
   {adapter}» en inglés. Acotado a `.es-especialista` a propósito: `.mode-indicator-text`
   lo comparten investigación y organización, y ahí convertiría «Modo investigación» en
   «Modo Investigación». */
#aimee .mode-indicator.es-especialista .mode-indicator-text { text-transform: capitalize; }

/* Sin color-mix se pierde el tinte del fondo, no la información: el canto y el
   texto siguen en verde. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
    #aimee .mode-indicator.es-especialista {
        border-color: var(--success);
        background: var(--surface);
    }
}

#aimee .mode-indicator-text { user-select: none; }

#aimee .mode-indicator-close {
    background: none;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    padding: 0;
    width: 16px;
    height: 16px;
    display: grid;
    place-items: center;
    border-radius: var(--r-xs);
    transition: background .15s, color .15s;
}
#aimee .mode-indicator-close svg { width: 11px; height: 11px; }
#aimee .mode-indicator-close:hover { background: var(--surface-2); color: var(--text); }

/* ── Menú de modos ───────────────────────────────────────────────────────── */
#aimee .mode-menu {
    position: absolute;
    bottom: 100%;
    left: 20px;
    width: fit-content;
    margin-bottom: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 6px;
    box-shadow: var(--shadow-pop);
    z-index: 100;
    animation: aimee-slideUpFade .2s ease-out;
}

@keyframes aimee-slideUpFade {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

#aimee .mode-menu-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    cursor: pointer;
    border-radius: var(--r-xs);
    transition: background .15s, color .15s;
    color: var(--text-mid);
    font-size: var(--text-sm);
    font-weight: 500;
    user-select: none;
}
#aimee .mode-menu-option:hover { background: var(--surface); color: var(--text); }
#aimee .mode-menu-option.mode-menu-option-selected { background: var(--surface-2); color: var(--text); }
#aimee .mode-menu-option svg { flex-shrink: 0; opacity: .7; }
#aimee .mode-menu-option:hover svg { opacity: 1; }
#aimee .mode-menu-option.mode-menu-option-selected svg { opacity: 1; }

/* ── Marcas de tiempo y acciones por mensaje ─────────────────────────────── */
#aimee .msg-time {
    font-size: var(--text-xs);
    color: var(--text-dim);
    margin-top: 4px;
    user-select: none;
}
#aimee .msg.user .msg-time { text-align: right; }
#aimee .msg.assistant .msg-time { text-align: left; }

#aimee .action-btn {
    width: 28px; height: 28px;
    border-radius: var(--r-xs);
    border: none;
    background: none;
    color: var(--text-dim);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s;
}
#aimee .action-btn:hover { background: var(--surface-2); color: var(--text); }
#aimee .action-btn svg { width: 15px; height: 15px; }

/* ── Código markdown ─────────────────────────────────────────────────────── */
#aimee .bubble pre {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 14px 16px;
    margin: 10px 0 4px;
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: 1.6;
    color: var(--text);
}
#aimee .bubble code {
    background: var(--surface);
    border: 1px solid var(--border);
    padding: 2px 6px;
    border-radius: var(--r-xs);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--text);
    /* Un identificador o un hash no tienen espacios por donde partir, y era el
       peor infractor: 1121px de ancho en una pantalla de 393. */
    overflow-wrap: anywhere;
    word-break: break-all;
}
#aimee .bubble pre code { background: none; border: none; padding: 0; font-size: inherit; }

/* ── Tablas markdown ─────────────────────────────────────────────────────── */
/* El contenedor `.tabla` lo pone el renderer de marked (`configurarMarked`). Él es
   quien se desplaza y lleva el borde; la tabla sigue siendo una tabla de verdad y
   por eso sus filas estiran a todo el ancho.

   Una tabla de cinco columnas no cabe en un teléfono, y sin contenerla era ella la
   que arrastraba el hilo entero de lado. Hace falta el `nowrap`: sin él las celdas
   se comprimen hasta partir «Organización» en cuatro líneas —medido— y queda
   ilegible en vez de desplazable. */
#aimee .bubble .tabla {
    max-width: 100%;
    /* Los dos ejes por separado y NUNCA el atajo `overflow`: el atajo escribe los
       dos, así que un `overflow: hidden` puesto después para redondear las esquinas
       anulaba el `auto` y la tabla se quedaba cortada sin poder desplazarla.
       Redondear no necesita el atajo: cualquier `overflow` distinto de `visible`
       ya recorta contra el `border-radius`. */
    overflow-x: auto;
    overflow-y: hidden;
    margin: 12px 0;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
}
#aimee .bubble table {
    width: 100%;
    white-space: nowrap;
    border-collapse: collapse;
    font-size: var(--text-sm);
}

/* La tabla es lo único que se desplaza dentro de un mensaje y el gesto no se
   adivina, así que la barra va siempre visible y fina, como la del hilo. Se
   pinta solo con `::-webkit-scrollbar` y SIN `scrollbar-width`: cuando están
   las dos, Chrome hace caso a la estándar y en macOS eso devuelve la barra
   flotante que se esconde sola, que es justo lo que no sirve aquí. */
#aimee .bubble .tabla::-webkit-scrollbar { height: 6px; }
#aimee .bubble .tabla::-webkit-scrollbar-track { background: transparent; }
#aimee .bubble .tabla::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: var(--r-pill);
}

#aimee .bubble thead { background: var(--surface); }
#aimee .bubble th {
    color: var(--text);
    padding: 10px 14px;
    text-align: left;
    font-weight: 500;
    font-size: var(--text-sm);
    border-bottom: 1px solid var(--border);
}
#aimee .bubble td {
    padding: 10px 14px;
    color: var(--text-mid);
    border-bottom: 1px solid var(--border);
}
#aimee .bubble tbody tr:last-child td { border-bottom: none; }
#aimee .bubble tbody tr:hover { background: var(--surface); }

/* Ficha técnica: una tabla de dos columnas (un cliente, un contacto…). Sin la
   cabecera «Campo | Detalle», que en una ficha no dice nada; la etiqueta en tono
   apagado y el valor en tinta, que es lo que se lee. */
#aimee .bubble .ficha thead { display: none; }
#aimee .bubble .ficha td:first-child { width: 38%; color: var(--text-mid); font-size: var(--text-sm); }
#aimee .bubble .ficha td:last-child { color: var(--text); font-weight: 500; white-space: normal; }
#aimee .bubble .ficha tbody tr:hover { background: none; }
/* El título de la ficha es el nombre del registro: pesa más que un h3 corriente. */
/* `inherit` y no `var(--text)`: con el tema oscuro sobre el fondo claro, --text es
   blanco y el nombre desaparecía sobre la burbuja clara. */
#aimee .bubble h3:has(+ .ficha) { font-size: var(--text-lg); color: inherit; margin: 4px 0 8px; }

/* Etiqueta de estado de un registro (etapa, activo, clasificación, tags). La pone
   `rellenar_variables` en talk/astrolle_mcp.py, nunca el modelo. Junto al título de
   una ficha o dentro de una celda: por eso alineada al centro de la línea y sin crecer
   con el h3. Activo en verde, inactivo apagado; el resto, en el acento. */
#aimee .bubble .pastilla {
    display: inline-block;
    padding: 0 9px;
    margin: 0 2px;
    vertical-align: middle;
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    color: var(--accent);
    font-size: var(--text-xs);
    font-weight: 500;
    line-height: 1.8;
    white-space: nowrap;
}
#aimee .bubble .pastilla[data-tono="si"] { background: var(--success-soft); color: var(--success); }
#aimee .bubble .pastilla[data-tono="no"] { background: var(--surface); color: var(--text-dim); }

/* Miniatura de un dato con imagen (opción de un maestro, cápsula). La pone
   `rellenar_variables` en talk/astrolle_mcp.py junto al nombre, nunca el modelo; al
   pulsarla abre la imagen entera. Pequeña y en línea: cabe en una lista o en una celda. */
/* GIF de reacción (talk/skills/giphy.py): llega como mensaje propio después del texto y va fuera de la burbuja
   (`separarTarjetas`), sin burbuja vacía ni botón de copiar. Alto fijo para que el hilo no salte al cargar. */
#aimee .msg-content:has(> .tarjetas-fuera .aimee-gif) > .bubble,
#aimee .msg-content:has(> .tarjetas-fuera .aimee-gif) > .msg-actions { display: none; }
/* Y el mensaje al que sigue un GIF (un saludo, una broma, «nada pendiente»), tampoco: no suelen ser para copiar
   (pedido del usuario). En vivo lo marca `con_gif` desde que llega; al recargar el historial, el GIF de al lado.
   Con un tablero de KPIs (la celebración de metas) sí se deja: ahí hay datos. */
#aimee .msg.assistant.con-gif:not(:has(.kpis)) .msg-actions,
#aimee .msg.assistant:has(+ .msg.assistant .aimee-gif):not(:has(.kpis)) .msg-actions { display: none; }
#aimee img.aimee-gif, #aimee .aimee-gif img { display: block; height: 160px; width: auto; max-width: 100%; border-radius: var(--r-sm); }
/* Un sticker (preguntas triviales: «¿me amas?») trae fondo transparente: sin esquinas, y un poco más pequeño. */
#aimee .gif[data-sticker] img.aimee-gif { height: 140px; border-radius: 0; }
/* Los GIFs guardados en el historial antes de quitar el enlace a GIPHY lo llevan
   en su HTML: se anula aquí para que tampoco abran GIPHY. */
#aimee a.aimee-gif { display: inline-block; line-height: 0; pointer-events: none; cursor: default; }
#aimee .bubble .dato-imagen { display: inline-block; vertical-align: middle; margin: 2px 4px; line-height: 0; }
/* En una lista, la miniatura flota a la izquierda y el texto va a su derecha aunque ocupe
   varias líneas: en línea con el texto, cada miniatura caía en una columna distinta según lo
   largo del nombre (problems/1.png del MCP). Sin viñeta: la imagen hace de viñeta. */
#aimee .bubble li:has(.dato-imagen) { display: flow-root; list-style: none; margin: 0 0 10px -1.1em; }
#aimee .bubble li .dato-imagen { float: left; margin: 0 12px 0 0; }
#aimee .bubble .dato-imagen img {
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: var(--r-sm);
    border: 1px solid var(--surface);
}

/* Un teléfono, como en un input de teléfono: bandera, separador y número. Lo monta
   `conTelefonos` en app.js y abre WhatsApp. Cifras tabulares para que los grupos
   se lean alineados.
   NADA de colores del tema: con el tema oscuro sobre el fondo claro, `--bg` es negro y
   la caja salía negra con letra oscura encima. Fondo transparente y borde sacado del
   color del texto de la burbuja: se ve igual de bien en cualquier tema. */
#aimee .bubble a.tel {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 1px 10px 1px 8px;
    margin: 0 1px;
    vertical-align: middle;
    border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 1.7;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color .15s;
}
#aimee .bubble a.tel:hover { border-color: var(--success); text-decoration: none; }
#aimee .bubble a.tel .tel-bandera {
    padding-right: 7px;
    border-right: 1px solid color-mix(in srgb, currentColor 18%, transparent);
    font-size: 1.05em;
    line-height: 1;
}

/* ── Encabezados markdown ────────────────────────────────────────────────── */
#aimee .bubble h1 {
    font-size: var(--text-lg);
    font-weight: 500;
    color: var(--text);
    margin: 14px 0 8px 0;
    line-height: 1.4;
    letter-spacing: -.01em;
}
#aimee .bubble h2 {
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--text);
    margin: 12px 0 6px 0;
    line-height: 1.4;
    letter-spacing: -.01em;
}
#aimee .bubble h3 {
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--text-mid);
    margin: 10px 0 6px 0;
    line-height: 1.4;
}
#aimee .bubble h4, #aimee .bubble h5, #aimee .bubble h6 {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-mid);
    margin: 8px 0 4px 0;
    line-height: 1.4;
}

/* ── Widget interactivo ──────────────────────────────────────────────────── */
#aimee .ask-widget {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: 16px;
    max-width: 420px;
}
#aimee .ask-titulo { font-size: var(--text-sm); color: var(--text); margin-bottom: 12px; line-height: 1.5; font-weight: 500; }
#aimee .ask-options { display: flex; flex-direction: column; gap: 6px; }
#aimee .ask-option {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    cursor: pointer;
    transition: background .15s, border-color .15s;
    text-align: left;
}
#aimee .ask-option:hover { background: var(--surface-2); }
#aimee .ask-option.selected { border-color: var(--accent); background: var(--accent-soft); }
#aimee .ask-option-label { font-size: var(--text-sm); color: var(--text); font-weight: 500; }
#aimee .ask-option-sub   { font-size: var(--text-xs); color: var(--text-dim); }
#aimee .ask-input-row { display: flex; gap: 8px; margin-top: 4px; }
#aimee .ask-input {
    flex: 1;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 10px 12px;
    color: var(--text);
    font-size: var(--text-sm);
    font-family: inherit;
    outline: none;
    transition: border-color .15s, box-shadow .15s, background .15s;
}
#aimee .ask-input:focus { background: var(--bg); border-color: var(--border-strong); }
#aimee .ask-submit {
    background: var(--accent);
    color: var(--on-accent);
    border: none;
    border-radius: var(--r-sm);
    padding: 10px 16px;
    font-size: var(--text-sm);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s;
}
#aimee .ask-submit:hover { background: var(--accent-hover); }
#aimee .ask-cancel {
    font-size: var(--text-xs);
    color: var(--text-dim);
    background: none;
    border: none;
    cursor: pointer;
    margin-top: 10px;
    padding: 0;
    font-family: inherit;
}
#aimee .ask-cancel:hover { color: var(--text); }
#aimee .ask-widget.done { opacity: .5; pointer-events: none; }

/* ── Aprobación: el «needs-input» del agent-status de Arc ──────────────────────
   Lo que Aimee propone y espera que digas sí o no, en una píldora y no en una
   caja: orbe con su anillo, la pregunta, los segundos si se activa sola y los dos
   botones dentro. Trasladado de `agent-status.module.css` (Arc, Pro): 38 px por
   dentro de un borde de 1, radio 20, orbe de 24 y botones de 30 con radio 15,
   concéntricos con la píldora. */
#aimee .ask-widget.ask-status {
    background: none; border: 0; border-radius: 0; padding: 0;
    max-width: 100%;
    align-self: flex-start;
}
#aimee .ask-status-pill {
    /* Se parte sola, sin container query: con `container-type` el widget no
       tiene ancho propio y, dentro de la burbuja, se aplastaba a una palabra
       por línea. Ahora va en una fila mientras quepa, y si no, los botones
       bajan a la segunda y la pregunta no se corta. */
    display: inline-flex; flex-wrap: wrap; align-items: center; column-gap: 8px;
    max-width: 100%; min-height: 40px; box-sizing: border-box;
    padding: 0 4px 0 7px;
    border: 1px solid var(--border); border-radius: 20px;
    background: var(--surface);
    font-size: var(--text-sm); line-height: 20px; color: var(--foreground);
}
/* El icono de lo que se aprueba, pegado a la pregunta (6 px, como el labelIcon de Arc). */
#aimee .ask-status-icon {
    flex: none; width: 16px; height: 16px; margin-right: -2px;
    stroke: var(--text-secondary); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
#aimee .ask-status-label { flex: 1 1 10em; min-width: 0; padding-block: 9px; }
#aimee .ask-status-timer { flex: none; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
#aimee .ask-acciones { display: flex; flex: none; align-items: center; gap: 4px; margin-left: auto; padding-block: 4px; }
#aimee .ask-descartar, #aimee .ask-aprobar {
    height: 30px; padding: 0 12px; border-radius: 15px;
    font: inherit; font-weight: 500; cursor: pointer; white-space: nowrap;
    transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
/* El que no se puede deshacer va en el acento y el otro queda discreto: la
   diferencia de peso es la que evita que se apruebe un envío por inercia. */
#aimee .ask-aprobar { background: var(--accent); color: var(--accent-foreground); border: 1px solid var(--accent); }
#aimee .ask-aprobar:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
#aimee .ask-descartar { background: var(--surface); color: var(--foreground); border: 1px solid var(--border); }
#aimee .ask-descartar:hover { background: var(--surface-muted); }

/* El orbe: anillo de fondo, el arco que se vacía con la cuenta atrás, el punto de
   acento que pide atención (un solo «ping») y los glifos del final. */
#aimee .ask-status-orb { position: relative; display: grid; flex: none; width: 24px; height: 24px; place-items: center; }
#aimee .ask-status-orb > svg:first-child { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; stroke-width: 1.5; }
#aimee .ask-status-track { stroke: var(--border); }
#aimee .ask-status-arc {
    stroke: var(--accent); stroke-linecap: round; opacity: 0;
    stroke-dasharray: 100; stroke-dashoffset: 0;
    transform: rotate(-90deg); transform-origin: 12px 12px;
}
#aimee .ask-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); position: relative; }
#aimee .ask-status-dot::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--accent);
    animation: aimee-ask-ping .9s var(--ease-standard) .1s 1 both;
}
#aimee .ask-status-check, #aimee .ask-status-stop { display: none; }
#aimee .ask-status-check { position: absolute; width: 14px; height: 14px; stroke: var(--success); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
#aimee .ask-status-stop { width: 8px; height: 8px; border-radius: 2px; background: var(--text-secondary); }

/* Se activa sola: el arco se vacía en el mismo plazo que cuenta el servidor. El
   desfase negativo lo pone en su punto si el mensaje llegó con retraso. */
#aimee .ask-status.contando .ask-status-arc {
    opacity: 1;
    animation: aimee-ask-vaciar var(--cuenta, 10s) linear var(--cuenta-desde, 0s) forwards;
}

/* Resuelta. Aprobada: el anillo se cierra en verde y sale el check. Descartada:
   el cuadrito gris. Activándose sola: el anillo gira y la frase brilla. */
#aimee .ask-status.done { opacity: 1; pointer-events: none; }
#aimee .ask-status.done .ask-acciones { display: none; }
#aimee .ask-status.done .ask-status-label { flex: 0 1 auto; }
#aimee .ask-status.done .ask-status-pill { padding-right: 14px; }
#aimee .ask-status.done[data-state="needs-input"] { opacity: .5; }
#aimee .ask-status:is([data-state="done"], [data-state="stopped"]) .ask-status-dot { display: none; }
#aimee .ask-status[data-state="done"] .ask-status-track { stroke: var(--success); }
#aimee .ask-status[data-state="done"] .ask-status-check { display: block; }
#aimee .ask-status[data-state="stopped"] .ask-status-stop { display: block; }
#aimee .ask-status[data-state="stopped"] .ask-status-label { color: var(--text-secondary); }
#aimee .ask-status[data-state="working"] .ask-status-dot { display: none; }
#aimee .ask-status[data-state="working"] .ask-status-arc {
    opacity: 1; stroke: var(--foreground); stroke-dasharray: 25 75; stroke-dashoffset: 0;
    animation: aimee-ask-girar .9s linear infinite;
}
#aimee .ask-status[data-state="working"] .ask-status-label {
    --shimmer-base: color-mix(in oklab, var(--foreground) 50%, var(--surface));
    color: transparent;
    background-image: linear-gradient(90deg, var(--shimmer-base) 0%, var(--shimmer-base) 38%, var(--foreground) 50%, var(--shimmer-base) 62%, var(--shimmer-base) 100%);
    background-size: 300% 100%; -webkit-background-clip: text; background-clip: text;
    animation: aimee-ask-shimmer 2.4s var(--ease-in-out) infinite;
}

/* El detalle va primero y es el mensaje de Aimee: la misma burbuja que sus respuestas
   (`.msg.assistant .bubble`), y la píldora debajo (pedido del usuario: primero el
   mensaje, luego la confirmación). Es lo que se revisa antes de decir sí. pre-line
   porque llega con saltos de línea del backend (destinatario, asunto, texto). Un
   correo largo rueda en vez de empujar la píldora fuera de la vista. */
#aimee .ask-detalle {
    white-space: pre-line; overflow-wrap: anywhere;
    max-width: 520px; max-height: 260px; overflow-y: auto; margin: 0 0 10px;
    padding: 16px 20px; border: 1px solid var(--border); border-radius: var(--r-lg);
    background: var(--bg); color: var(--text);
    font-size: var(--text-base); line-height: 1.65;
}
#aimee .ask-status-aviso { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

@keyframes aimee-ask-vaciar { to { stroke-dashoffset: 100; } }
@keyframes aimee-ask-girar { to { transform: rotate(270deg); } }
@keyframes aimee-ask-ping { from { opacity: .4; transform: scale(1); } to { opacity: 0; transform: scale(2.6); } }
@keyframes aimee-ask-shimmer { 0% { background-position: 100% 0; } 72%, 100% { background-position: 0% 0; } }

/* Sin movimiento para quien lo ha pedido. Los segundos siguen a la vista. */
@media (prefers-reduced-motion: reduce) {
    #aimee .ask-status.contando .ask-status-arc,
    #aimee .ask-status[data-state="working"] .ask-status-arc { animation: none; }
    #aimee .ask-status-dot::after { display: none; }
    #aimee .ask-status[data-state="working"] .ask-status-label { animation: none; background: none; color: var(--foreground); }
}

/* ── Respuestas HTML ─────────────────────────────────────────────────────── */
#aimee .bubble.html-response { padding: 0; overflow: hidden; background: transparent; border: none; }
#aimee .html-response .html-body {
    padding: 14px 16px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    color: var(--text);
}
#aimee .html-response table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
#aimee .html-response th {
    background: var(--surface);
    color: var(--text);
    padding: 8px 12px;
    text-align: left;
    font-weight: 500;
    font-size: var(--text-xs);
    border-bottom: 1px solid var(--border);
}
#aimee .html-response td { padding: 8px 12px; border-bottom: 1px solid var(--border); color: var(--text-mid); vertical-align: top; }
#aimee .html-response tr:last-child td { border-bottom: none; }
#aimee .html-response tr:hover td { background: var(--surface); }
#aimee .html-response ul, #aimee .html-response ol { margin: 8px 0; padding-left: 20px; }
#aimee .html-response li { padding: 4px 0; color: var(--text-mid); }
#aimee .html-response h3, #aimee .html-response h4 { color: var(--text); margin: 0 0 10px; font-size: var(--text-sm); font-weight: 500; }
#aimee .html-response p { margin: 6px 0; }

/* ── Botón de abrir reporte ──────────────────────────────────────────────── */
#aimee .report-open-btn {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: 4px; padding: 8px 14px;
    background: var(--ink);
    color: var(--on-ink);
    border: none;
    border-radius: var(--r-xs);
    font-size: var(--text-sm);
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: opacity .15s;
}
#aimee .report-open-btn:hover { opacity: .85; }

/* ── Lottie ──────────────────────────────────────────────────────────────── */
/* El orbe conserva su color original: es la única pieza de marca con color
   propio y funciona como punto focal de la bienvenida. */
#aimee .lottie-loading { width: 60px; height: 30px; }

/* Lo que Aimee va diciendo mientras piensa (mostrarEstado en app.js): una línea
   pequeña junto a los puntos, que no compite con la respuesta. Hereda el color de
   la burbuja y solo lo apaga, así vale con fondo y sin él. */
#aimee #aimee-typing .bubble { display: flex; align-items: center; gap: 10px; }
#aimee #aimee-typing .lottie-loading { flex: none; }
#aimee .typing-status {
    font-size: var(--text-sm);
    font-style: italic;
    opacity: 0;
    transition: opacity .25s ease;
}
#aimee .typing-status.visible { opacity: .6; }

/* Las respuestas ya no llevan avatar: el mensaje arranca en el margen. */
/* Aimee tiene más sitio que el usuario: el 70 % del hilo, y nunca menos de los 560px
   de antes (en una ventana estrecha el 70 % sería MENOS). La burbuja llena ese
   ancho; la del usuario se queda en sus 520px. */
#aimee .msg.assistant > div { display: flex; align-items: flex-start; max-width: max(70%, 560px); }
/* Solo en escritorio: por debajo de 900px mandan los topes de móvil de siempre. */
@media (min-width: 901px) {
    #aimee .msg.assistant .bubble { max-width: none; }
}
/* TRANSFERENCIA — `min-width: 0` NO es decorativo, y quitarlo rompe el margen
   derecho del móvil. Un hijo flex no baja por defecto de su
   tamaño mínimo de contenido, y el mapa lo tiene grande sin que se note: su caja
   lleva `aspect-ratio: 16/10` con `min-height: 300px`, y eso IMPLICA un ancho
   mínimo de 480px (300 × 1.6). En un teléfono de 393px eso empujaba el mensaje a
   482px de ancho: quedaba con su margen a la izquierda y 103px por fuera a la
   derecha. Con `min-width: 0` el contenedor puede encogerse hasta el ancho real
   y el mapa se adapta; el `min-height` sigue mandando en el alto. */
#aimee .msg-content { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#aimee .msg-actions { display: flex; gap: 4px; margin-top: 6px; padding-left: 4px; margin-bottom: 4px; }

#aimee .typing-dots { display: flex; gap: 5px; align-items: center; padding: 10px 0; }
#aimee .typing-dots span { width: 6px; height: 6px; border-radius: var(--r-pill); background: var(--text-dim); animation: aimee-bounce 1.2s infinite; }
#aimee .typing-dots span:nth-child(2) { animation-delay: .2s; }
#aimee .typing-dots span:nth-child(3) { animation-delay: .4s; }

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

#aimee .error-text { color: var(--danger); font-size: var(--text-sm); padding: 6px 0; }

/* ── Nota de voz ─────────────────────────────────────────────────────────────
   Reproductor propio: píldora con play, forma de onda y duración. Sustituye al
   <audio controls> nativo, que el navegador dibujaba a su manera. */

/* Columna: píldora + transcripción + hora, alineada a la derecha como el resto
   de los mensajes del usuario. */
#aimee .voice-msg {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    max-width: 340px;
    min-width: 0;
}

/* La burbuja, como la del voice-recorder de Arc: la tuya va en tinta (fondo
   `--foreground`, letra `--background`), 44 px de alto con radio 22, play de 32 en
   el color contrario, barras de 3 px y la duración en cifras tabulares. */
#aimee .audio-bubble {
    display: flex; align-items: center; gap: 10px;
    max-width: 100%; height: 44px; box-sizing: border-box;
    padding: 6px 14px 6px 6px;
    border-radius: 22px;
    background: var(--foreground); color: var(--background);
}

/* El <audio> es solo el motor de reproducción: nunca se ve. */
#aimee .audio-bubble audio { display: none; }

#aimee .voice-play {
    display: grid; place-items: center; flex: none;
    width: 32px; height: 32px; padding: 0;
    border: 0; border-radius: 50%;
    background: var(--background); color: var(--foreground);
    cursor: pointer;
    transition: scale var(--duration-fast) var(--ease-standard);
}
#aimee .voice-play:active { scale: .92; }
#aimee .voice-play svg { width: 14px; height: 14px; }
/* El icono de play se ve centrado si se desplaza un pelo a la derecha */
#aimee .voice-play .icon-play { margin-left: 2px; }

/* En un hilo estrecho las barras adelgazan en vez de empujar la duración fuera. */
#aimee .voice-wave {
    display: flex; align-items: center; gap: 2px;
    flex: 0 1 auto; min-width: 0; height: 22px;
    overflow: hidden; cursor: pointer; outline: none;
    touch-action: none;
}

/* --h (0..1) lo fija el JS con los picos reales del audio. Las que faltan por
   sonar, al 28 % del color; las ya sonadas, enteras. */
#aimee .voice-bar {
    /* `width` además de la base: sin él, el ancho natural de la burbuja cuenta
       cada barra (vacía) como 0 y salen de 1,5 px. */
    flex: 0 1 3px; width: 3px; min-width: 1.5px;
    height: max(12%, calc(var(--h, .2) * 100%));
    border-radius: 2px;
    background: color-mix(in oklab, currentColor 28%, transparent);
}
#aimee .voice-bar.is-played { background: currentColor; }

#aimee .voice-time {
    flex: none; min-width: 3.4ch;
    font-size: var(--text-xs); font-variant-numeric: tabular-nums;
    opacity: .8; text-align: right; user-select: none;
}

/* ── La grabadora: el composer del voice-recorder de Arc ─────────────────────
   Tapa el .input-box mientras se graba o se revisa una nota: papelera, la
   cápsula (grabando: punto rojo, cronómetro y onda en vivo; revisión: play,
   barras y duración) y el botón que hace avanzar la nota (parar, enviar), en el
   acento. El rojo queda solo en el punto de «grabando». */
#aimee .voz {
    position: absolute; inset: -1px; z-index: 5;
    display: flex; align-items: center; gap: 8px;
    padding: 0 7px 0 8px;
    border: 1px solid var(--border-strong); border-radius: inherit;
    background: var(--surface);
}
#aimee .voz-descartar, #aimee .voz-principal {
    display: grid; place-items: center; flex: none;
    padding: 0; border: 0; border-radius: 50%; cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
#aimee .voz-descartar { width: 36px; height: 36px; background: transparent; color: var(--text-secondary); }
#aimee .voz-descartar:hover { background: var(--surface-muted); color: var(--danger); }
#aimee .voz-principal { width: 44px; height: 44px; background: var(--accent); color: var(--accent-foreground); }
#aimee .voz-principal:hover { background: var(--accent-strong); }
#aimee .voz-descartar svg, #aimee .voz-principal svg { width: 18px; height: 18px; }
#aimee .voz-principal svg { stroke-width: 2; }

#aimee .voz-capsula {
    display: flex; align-items: center; gap: 10px;
    flex: 1; min-width: 0; height: 44px; box-sizing: border-box;
    padding: 0 14px 0 8px; border-radius: 999px;
    background: var(--surface-muted); color: var(--foreground);
}
#aimee .voz-capsula[data-fase="grabando"] {
    padding-left: 16px;
    background: color-mix(in oklab, var(--accent) 7%, var(--surface-muted));
}
#aimee .voz-punto { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--danger); animation: aimee-voz-rec 1.2s ease-in-out infinite; }
#aimee .voz-reloj { flex: none; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
#aimee .voz-onda { display: block; flex: 1; min-width: 0; height: 28px; color: var(--foreground); }

/* En revisión, la cápsula lleva la misma píldora de reproducción que irá al hilo,
   pero sin su fondo de tinta y con las barras repartidas a todo el ancho. */
#aimee .voz-capsula .audio-bubble { flex: 1; height: auto; padding: 0; background: none; color: inherit; border-radius: 0; }
#aimee .voz-capsula .voice-play { background: var(--foreground); color: var(--background); }
#aimee .voz-capsula .voice-wave { flex: 1; height: 24px; justify-content: space-between; }
#aimee .voz-capsula .voice-bar { flex: 1 1 0; max-width: 3px; }
#aimee .voz-capsula .voice-time { font-size: var(--text-sm); opacity: 1; }

#aimee .voz-aviso { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

@keyframes aimee-voz-rec { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
    #aimee .voz-punto { animation: none; }
    #aimee .voice-play, #aimee .voz-descartar, #aimee .voz-principal { transition: none; }
}

/* Transcripción: pie suelto bajo la píldora, sin fondo ni borde */
#aimee .audio-transcription {
    font-size: var(--text-xs);
    color: var(--text-dim);
    line-height: 1.4;
    text-align: right;
    padding: 0 4px;
}
#aimee .audio-transcription.is-pending { font-style: italic; opacity: .75; }
#aimee .audio-transcription.is-error { color: var(--danger); }
#aimee .audio-transcription svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 4px; }

/* ── Modal de identificación de usuario ──────────────────────────────────── */
#aimee .user-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--overlay);
    z-index: 999;
    align-items: center;
    justify-content: center;
    /* Hueco para que el modal no se pegue a los bordes, y scroll de reserva: en
       apaisado con el teclado abierto puede no caber ni la cabecera con el pie,
       y entonces el scroll de dentro no basta. */
    padding: 16px;
    overflow-y: auto;
}
#aimee .user-modal-overlay.visible { display: flex; }

/* SEIS campos con etiqueta y pista no caben en un móvil. Antes el modal no tenía
   `max-height` y sí `overflow: hidden`, dentro de un overlay fijo sin scroll: el
   pie se quedaba fuera de pantalla y el botón de continuar era INALCANZABLE.
   Nadie podía iniciar sesión desde el teléfono.

   Ahora es una columna de tres piezas: cabecera y pie quedan quietos y solo
   scrollan los campos. El botón siempre está a la vista, que es la razón de
   elegir esto en vez de scrollar el modal entero: si scrolla todo, el botón
   vuelve a poder estar fuera de pantalla y el usuario tiene que descubrir que
   hay que bajar. */
#aimee .user-modal {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-pop);
    width: min(90vw, 420px);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* `vh` primero como respaldo y `dvh` encima: en el móvil `vh` cuenta la
       barra del navegador como si no estuviera, así que el modal se pasa de
       alto justo lo que mide esa barra. `dvh` sigue al viewport de verdad, y
       también cuando sube el teclado. */
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px);
}

#aimee .user-modal-header {
    padding: 28px 28px 20px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
#aimee .user-modal-header h2 {
    font-size: var(--text-xl);
    font-weight: 500;
    color: var(--text);
    margin-bottom: 8px;
    letter-spacing: -.02em;
}
#aimee .user-modal-header p { font-size: var(--text-sm); color: var(--text-mid); }

#aimee .user-modal-body {
    padding: 24px 28px;
    display: flex;
    flex-direction: column;
    gap: 18px;
    /* Lo único que scrolla. `min-height: 0` es imprescindible: sin él, un hijo
       flex no baja de su tamaño natural y el contenedor crece en vez de
       desbordar, que es como estaba. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}
#aimee .user-modal-body::-webkit-scrollbar { width: 4px; }
#aimee .user-modal-body::-webkit-scrollbar-track { background: transparent; }
#aimee .user-modal-body::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

#aimee .user-input-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
#aimee .user-input-group label {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text);
}
/* La piel de los campos se comparte con la hoja de acciones, que además de
   inputs tiene un select de códigos de país y un textarea. */
#aimee .user-input-group input,
#aimee .user-input-group select,
#aimee .user-input-group textarea {
    width: 100%;
    padding: 11px 14px;
    border: 1px solid var(--border);
    border-radius: var(--r-xs);
    background: var(--surface);
    font-family: var(--font);
    font-size: var(--text-base);
    color: var(--text);
    transition: border-color .15s, box-shadow .15s, background .15s;
    outline: none;
}
#aimee .user-input-group input:focus,
#aimee .user-input-group select:focus,
#aimee .user-input-group textarea:focus {
    background: var(--bg);
    border-color: var(--border-strong);
}
#aimee .user-input-group input.has-error,
#aimee .user-input-group select.has-error,
#aimee .user-input-group textarea.has-error { border-color: var(--danger); box-shadow: 0 0 0 2px var(--danger-soft); }
#aimee .user-input-group input::placeholder,
#aimee .user-input-group textarea::placeholder { color: var(--text-dim); }

/* Texto de ayuda bajo cada campo */
#aimee .field-hint {
    color: var(--text-dim);
    font-size: var(--text-xs);
    line-height: 1.4;
}

/* Quieto abajo, y con borde: cuando los campos scrollan por debajo, el borde es
   lo que dice que hay más contenido en vez de parecer un corte. */
#aimee .user-modal-footer {
    padding: 16px 28px 20px;
    border-top: 1px solid var(--border);
    background: var(--bg);
    flex-shrink: 0;
}

/* En un teléfono, 28px de margen a cada lado se comen el ancho y el titular de
   24px se come el alto. Apretados, entran dos campos más sin scrollar. */
@media (max-width: 520px) {
    #aimee .user-modal-overlay { padding: 10px; }
    #aimee .user-modal {
        width: 100%;
        max-height: calc(100vh - 20px);
        max-height: calc(100dvh - 20px);
    }
    #aimee .user-modal-header { padding: 20px 18px 14px; }
    #aimee .user-modal-header h2 { font-size: var(--text-xl); margin-bottom: 4px; }
    #aimee .user-modal-header p { font-size: var(--text-sm); }
    #aimee .user-modal-body { padding: 16px 18px; gap: 14px; }
    #aimee .user-modal-footer { padding: 12px 18px 14px; }
}

#aimee .user-modal-btn {
    width: 100%;
    padding: 13px 24px;
    border: none;
    border-radius: var(--r-xs);
    background: var(--ink);
    color: var(--on-ink);
    font-family: var(--font);
    font-size: var(--text-base);
    font-weight: 500;
    cursor: pointer;
    transition: opacity .15s;
}
#aimee .user-modal-btn:hover { opacity: .88; }
#aimee .user-modal-btn:active { opacity: 1; }
#aimee .user-modal-btn:disabled { opacity: .4; cursor: not-allowed; }

/* ── Modal de inicialización del agente ──────────────────────────────────── */
#aimee .init-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--overlay);
    z-index: 10000;
    align-items: center;
    justify-content: center;
}
#aimee .init-modal-overlay.visible { display: flex; }

#aimee .init-modal {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: 40px;
    max-width: 500px;
    width: 90%;
    box-shadow: var(--shadow-pop);
    text-align: center;
}

#aimee .init-animation { width: 110px; height: 110px; margin: 0 auto 24px; }

#aimee .init-modal h2 {
    font-size: var(--text-xl);
    font-weight: 500;
    color: var(--text);
    margin-bottom: 12px;
    letter-spacing: -.02em;
}
#aimee .init-modal p { font-size: var(--text-base); color: var(--text-mid); margin-bottom: 28px; }

#aimee .init-checklist {
    list-style: none;
    text-align: left;
    margin-bottom: 20px;
}
#aimee .init-checklist li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    margin-bottom: 8px;
    font-size: var(--text-sm);
    color: var(--text-mid);
    transition: background .25s, border-color .25s, color .25s;
}
#aimee .init-checklist li.init-complete {
    background: var(--bg);
    border-color: var(--border);
    color: var(--text);
}
#aimee .init-checklist li.init-error {
    background: var(--danger-soft);
    border-color: var(--danger);
    color: var(--danger);
}

#aimee .init-icon {
    min-width: 20px;
    display: grid;
    place-items: center;
    color: var(--text-dim);
    flex-shrink: 0;
}
#aimee .init-icon svg { width: 16px; height: 16px; }
#aimee .init-complete .init-icon { color: var(--success); }
#aimee .init-error .init-icon { color: var(--danger); }

#aimee .init-error {
    background: var(--danger-soft);
    border: 1px solid var(--danger);
    border-radius: var(--r-sm);
    padding: 14px 16px;
    margin-top: 20px;
    color: var(--danger);
    font-size: var(--text-sm);
}

/* ── Animaciones base ────────────────────────────────────────────────────── */
@keyframes aimee-fadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes aimee-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
    /* EL DOCUMENTO NO SE DESPLAZA. Solo #aimee-messages.
       `overflow: hidden` en el body NO basta en iOS: Safari sigue permitiendo el
       rebote elástico de la página, y al arrastrar se lleva el composer fuera de
       la pantalla. `position: fixed` sí lo impide, y es el bloqueo de toda la
       vida para esto. El alto va explícito en `dvh` porque con `top: 0` y
       `bottom: 0` el navegador usaría el viewport GRANDE —el de la barra
       escondida— y volveríamos a tener el composer bajo el pliegue.
       Los elementos `position: fixed` de dentro (sidebar, botones de arriba)
       siguen anclados al viewport: un body fijo no crea bloque contenedor para
       ellos, solo lo harían un transform o un filter. */
    #aimee { overflow: hidden; }
    #aimee {
        display: block;
        position: fixed;
        top: 0; left: 0; right: 0;
        height: 100dvh;
        overflow: hidden;
    }

    #aimee .sidebar {
        position: fixed;
        left: 0; top: 0;
        /* ALTURA EXPLÍCITA, no `bottom: 0`. Un elemento fijo en iOS se coloca
           contra el viewport GRANDE —el de la barra del navegador escondida—, así
           que `bottom: 0` caía por debajo de lo visible y el bloque de SESIÓN con
           su botón quedaba fuera de la pantalla, inalcanzable. */
        height: 100vh;
        height: 100dvh;
        width: min(82vw, 320px) !important;
        max-width: 320px;
        min-width: 0 !important;
        transform: translateX(-105%);
        transition: transform .28s ease;
        z-index: 250;
    }
    #aimee .sidebar.open {
        width: min(82vw, 320px) !important;
        min-width: 0 !important;
        transform: translateX(0);
    }

    #aimee .sidebar-overlay.visible { display: block; z-index: 220; }

    #aimee .chat-area {
        /* `100%` y no `100vw`: `100vw` no descuenta la barra de desplazamiento,
           así que en cuanto aparece una el área de chat se pasa de ancho y
           reaparece el desplazamiento lateral que este cambio viene a quitar. */
        width: 100%;
        min-width: 0;
        height: 100vh;
        height: 100dvh;
        margin-left: 0 !important;
    }

    #aimee #aimee-messages { padding-left: 0; padding-right: 0; }

    #aimee .msg { --msg-pad: 16px; }
    #aimee .msg.assistant > div { max-width: calc(100vw - 2 * var(--msg-pad)); }

    #aimee .bubble { max-width: min(520px, calc(100vw - 92px)); }

    #aimee .input-wrap {
        padding-left: 14px;
        padding-right: 14px;
        /* Sin esto el composer queda debajo de la barra de inicio del iPhone y
           el último trozo no se puede ni tocar. */
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    /* El padding lateral ya lo resuelve el clamp() de .disclaimer */
    #aimee .disclaimer { font-size: var(--text-xs); }
}

@media (max-width: 520px) {
    #aimee #aimee-welcome { padding-left: 14px; padding-right: 14px; }

    #aimee .aimee-welcome { width: 150px; height: 150px; }

    #aimee #aimee-welcome h1 { font-size: var(--text-2xl); margin-bottom: 24px; }

    #aimee .input-box { min-height: 56px; padding: 9px 9px 9px 16px; }

    #aimee .suggestions { gap: 8px; }
    #aimee .suggestion { font-size: var(--text-xs); padding: 8px 12px; }

    #aimee .aimee-logo { width: 22px; height: 22px; }

    #aimee .icon-btn,
    #aimee .mic-btn,
    #aimee .send-btn { width: 32px; height: 32px; }

    /* 14px y no 10: es el mismo margen que usa `.input-wrap`, así las burbujas
       quedan alineadas con el borde del composer en vez de 4px por fuera. Con 10
       las de la derecha se leían pegadas al borde de la pantalla. */
    #aimee .msg { --msg-pad: 14px; }

    #aimee .msg.assistant > div { max-width: calc(100vw - 2 * var(--msg-pad)); }

    #aimee .bubble { max-width: calc(100vw - 72px); font-size: var(--text-sm); }
}

/* Token #grafo: en las sugerencias y en el mensaje enviado.
   Usa el color de acento para que se lea como una mencion, igual que en otros
   chats, y no como texto normal. */
#aimee .graph-mention {
    color: var(--accent);
    font-weight: 500;
    background: var(--accent-soft);
    padding: 1px 4px;
    border-radius: 4px;
}
/* Dentro de la burbuja el comando va SOLO en negrita: sin fondo, sin color y sin
   sigilo. Ahí ya no es sintaxis que haya que reconocer para escribirla —eso pasó al
   enviar—, es una palabra más de una frase que se está leyendo. El fondo blanco al
   18% venía de cuando la burbuja del usuario era oscura y hoy no se ve. */
#aimee .bubble .graph-mention {
    background: none;
    padding: 0;
    border-radius: 0;
    color: inherit;
    font-weight: 500;
}

/* ── Resaltado del #grafo DENTRO del campo de texto ───────────────────────────
   Un <textarea> no puede pintar texto de dos colores, asi que se usa la tecnica
   del espejo: un div identico debajo que si lleva marcado, y el textarea encima
   con el texto transparente y solo el cursor visible.

   Lo critico es que la tipografia y el espaciado del espejo sean EXACTAMENTE los
   del textarea (font, size, line-height, white-space): cualquier diferencia
   desalinea el resaltado respecto a lo que se escribe. */
#aimee .ta-wrap {
    flex: 1;
    position: relative;
    display: flex;
    min-width: 0;          /* sin esto el flex no deja encogerse y desborda */
    /* CRITICO: el texto a la izquierda, en los dos.
       #aimee-welcome lleva `text-align: center` y lo heredaba todo lo de dentro, incluido
       el input. Con texto centrado la linea se recoloca en CADA pulsacion, y el
       espejo (un div) y el textarea no resuelven ese centrado de forma identica, asi
       que el resaltado se iba separando de lo que se escribia. Solo pasaba en el
       saludo: el input del chat ya estaba alineado a la izquierda.
       Alinear los dos a la izquierda elimina la causa y deja los dos inputs iguales. */
    text-align: left;
}
#aimee .ta-wrap textarea {
    position: relative;
    z-index: 1;
    width: 100%;
    text-align: left;       /* que no vuelva a heredar el center de #aimee-welcome */
    background: transparent;
    color: transparent;                 /* el texto lo pinta el espejo */
    -webkit-text-fill-color: transparent;
    caret-color: var(--text);           /* pero el cursor tiene que verse */
}
#aimee .ta-wrap textarea::placeholder {
    color: var(--text-dim);
    -webkit-text-fill-color: var(--text-dim);
}
/* Semitransparente para que el texto del espejo se lea a traves de la seleccion */
#aimee .ta-wrap textarea::selection { background: var(--accent-soft); }

#aimee .ta-mirror {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;               /* el textarea sigue recibiendo los clics */
    overflow: hidden;
    color: var(--text);
    /* Clon exacto de las reglas de `textarea` */
    font-family: var(--font);
    font-size: var(--text-base);
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    border: none;
    padding: 0;
    margin: 0;
    text-align: left;       /* idem: el espejo tampoco debe centrar */
}
/* Dentro del input SOLO puede cambiar el color. Ni fondo, ni padding, ni negrita:
   cualquier cosa que altere el ancho de los caracteres desplaza el espejo respecto
   al textarea y el resaltado deja de cuadrar con lo que se escribe. La negrita es
   el error clasico aqui. */
#aimee .ta-mirror .graph-mention {
    background: none;
    padding: 0;
    border-radius: 0;
    font-weight: inherit;
    letter-spacing: inherit;
    color: var(--accent);
}

/* Nombre del skill al lado del alias en las sugerencias del @ */
#aimee .mention-detail { color: var(--text-dim); font-size: var(--text-xs); margin-left: 6px; }
/* El menú del @ lista todos los skills y las acciones propias: si no caben, se desplaza. */
#aimee .mode-menu:has(.mention-menu-option) { max-height: min(55vh, 420px); overflow-y: auto; }

/* ── Gráficas (Highcharts) ────────────────────────────────────────────────────
   La burbuja de una gráfica es más ancha que la de texto y sin fondo de color: lo
   que se mira es la gráfica, no el globo que la envuelve. Los colores los pone JS
   desde los tokens del tema, aquí solo va la caja. */
#aimee .chart-bubble {
    width: min(560px, calc(100vw - 92px));
    max-width: none;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 10px;
}
#aimee .chart-box {
    width: 100%;
    height: 300px;
}

#aimee .chart-error {
    padding: 24px 12px;
    text-align: center;
    font-size: var(--text-sm);
    color: var(--text-dim);
}

@media (max-width: 520px) {
    #aimee .chart-bubble { width: calc(100vw - 40px); }
    #aimee .chart-box { height: 240px; }
}
/* Una barra dividida (el split-bar de Arc, `comoBarraDividida` en app.js) mide lo que pide su gráfica, no 300 px. */
#aimee .chart-box.chart-box--dividida { height: auto; }

/* ── Globo de ayuda de las acciones personalizadas ────────────────────────────
   Flota sobre el composer mientras hay una acción propia escrita, con lo que esa
   acción espera recibir. Semitransparente y sin fondo sólido a propósito: informa
   sin tapar el chat ni pedir que lo cierres. */
#aimee .own-hint {
    display: none;
    position: fixed;
    z-index: 300;             /* sobre el composer (2), bajo la hoja de acciones (520) */
    max-width: min(90vw, 460px);
    padding: 8px 14px;
    border-radius: var(--r-pill);
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text-mid);
    font-size: var(--text-xs);
    line-height: 1.4;
    pointer-events: none;     /* es un aviso, no algo con lo que interactuar */
    animation: aimee-slideUpFade .2s ease-out;
}
#aimee .own-hint.visible { display: block; }
#aimee .own-hint b { color: var(--text); font-weight: 500; }

/* Sin color-mix, el fondo queda opaco pero legible: se pierde la transparencia,
   no la información. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
    #aimee .own-hint { background: var(--surface); }
}

/* ── Panel de informes (canvas) ───────────────────────────────────────────────
   Hermano de .chat-area dentro del flex de body: al mostrarse, el chat se estrecha
   y el informe entra al lado. En móvil pasa a pantalla completa. */

#aimee .canvas-panel {
    display: none;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    background: var(--bg2);
    border-left: 1px solid var(--border);
}
/* 1.7 contra el flex:1 del chat: reparte en 37/63, la proporción del diseño. El
   chat sigue siendo usable porque su .input-inner ya tiene su propio máximo. */
#aimee .canvas-panel.open {
    display: flex;
    flex: 1.7 1 0;
    animation: aimee-fadeIn .2s ease;
}

#aimee .canvas-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
    flex-shrink: 0;
}
#aimee .canvas-close {
    width: 30px; height: 30px;
    flex-shrink: 0;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .canvas-close:hover { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
#aimee .canvas-close svg { width: 15px; height: 15px; }

#aimee .canvas-titles { min-width: 0; }
#aimee .canvas-title {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#aimee .canvas-sub { font-size: var(--text-xs); color: var(--text-dim); }

#aimee .canvas-body {
    flex: 1;
    overflow-y: auto;
    padding: 20px;
}
#aimee .canvas-body::-webkit-scrollbar { width: 4px; }
#aimee .canvas-body::-webkit-scrollbar-track { background: transparent; }
#aimee .canvas-body::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

/* Tarjeta que queda en la burbuja del chat: es lo que reabre el panel cuando se
   ha cerrado, y lo que se ve del informe al releer la conversación. */
#aimee .canvas-card {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    margin-top: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg);
    font-family: var(--font);
    text-align: left;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
#aimee .canvas-card:hover { background: var(--surface); border-color: var(--border-strong); }
#aimee .canvas-card-icon {
    width: 34px; height: 34px;
    flex-shrink: 0;
    border-radius: var(--r-xs);
    background: var(--accent-soft);
    color: var(--accent);
    display: grid; place-items: center;
}
#aimee .canvas-card-icon svg { width: 17px; height: 17px; }
#aimee .canvas-card-text { min-width: 0; }
#aimee .canvas-card-title { font-size: var(--text-sm); font-weight: 500; color: var(--text); }
#aimee .canvas-card-sub   { font-size: var(--text-xs); color: var(--text-dim); }

@media (max-width: 900px) {
    /* Pantalla completa, con la X arriba a la izquierda para volver al chat. El
       z-index queda por encima del sidebar (250) y por debajo de la hoja de
       acciones (520), que puede abrirse estando el informe delante. */
    #aimee .canvas-panel.open {
        position: fixed;
        inset: 0;
        z-index: 400;
        flex: none;
        border-left: none;
    }
    #aimee .canvas-body { padding: 14px; }
}

/* ── Informe "Buenos días" (clases gm-*) ─────────────────────────────────────
   Las produce la plantilla del skill (talk/skills/domains/good_morning). Viven
   aquí y no en el HTML del informe porque sanitizeHtml() borra los bloques \3c style>
   de todo lo que manda Aimee —y porque así el informe hereda los tokens y funciona
   en tema claro y oscuro sin duplicar ni un color. */

#aimee .gm-dash { display: flex; flex-direction: column; gap: 14px; }

#aimee .gm-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
#aimee .gm-eyebrow { font-size: var(--text-xs); color: var(--text-dim); }
#aimee .gm-title {
    font-size: var(--text-xl);
    font-weight: 500;
    color: var(--text);
    letter-spacing: -.02em;
}
#aimee .gm-date { font-size: var(--text-xs); color: var(--text-dim); }

#aimee .gm-row { display: grid; gap: 12px; }
#aimee .gm-row-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#aimee .gm-row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

#aimee .gm-card {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 16px;
    min-width: 0;
}
/* Una sola tarjeta con el acento: la del titular. Con dos ya no hay titular.
   Arc: el acento va en la cifra, con su tinte suave detrás; nunca de relleno. */
#aimee .gm-card-accent {
    background: var(--accent-subtle);
    border-color: transparent;
}
#aimee .gm-card-accent .gm-big { color: var(--accent-strong); }

#aimee .gm-label {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text);
}
#aimee .gm-sub { font-size: var(--text-xs); color: var(--text-dim); margin-top: 2px; }
#aimee .gm-big {
    font-size: var(--text-3xl);
    font-weight: 500;
    color: var(--text);
    letter-spacing: -.03em;
    line-height: 1.1;
    margin-top: 10px;
}

#aimee .gm-delta {
    display: inline-block;
    margin-top: 10px;
    padding: 3px 8px;
    border-radius: var(--r-pill);
    font-size: var(--text-xs);
    font-weight: 500;
    background: var(--surface);
    color: var(--text-mid);
}
#aimee .gm-up   { color: var(--success); background: var(--success-soft); }
#aimee .gm-down { color: var(--danger);  background: var(--danger-soft); }
#aimee .gm-flat { color: var(--text-dim); background: var(--surface); }

/* Barras de la semana. El alto de cada barra lo pone el skill en línea, porque es
   dato; todo lo demás es piel y vive aquí. */
#aimee .gm-bars {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 6px;
    margin-top: 14px;
    min-height: 130px;
}
#aimee .gm-bar-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    flex: 1;
    min-width: 0;
}
#aimee .gm-bar-val { font-size: var(--text-xs); color: var(--text-dim); }
#aimee .gm-bar {
    width: 100%;
    max-width: 34px;
    border-radius: var(--r-xs) var(--r-xs) 0 0;
    background: var(--surface-3);
}
#aimee .gm-bar-today { background: var(--accent); }
#aimee .gm-bar-lbl { font-size: var(--text-xs); font-weight: 500; color: var(--text-dim); }

/* Listas: agenda, canales y avisos */
#aimee .gm-list, #aimee .gm-meters, #aimee .gm-alerts {
    list-style: none;
    display: flex;
    flex-direction: column;
    margin-top: 12px;
}
#aimee .gm-list { gap: 2px; }
#aimee .gm-meters { gap: 12px; }
#aimee .gm-alerts { gap: 8px; }

#aimee .gm-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
}
#aimee .gm-item:last-child { border-bottom: none; }
#aimee .gm-hora {
    flex-shrink: 0;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text);
}
#aimee .gm-item-body { display: flex; flex-direction: column; flex: 1; min-width: 0; }
#aimee .gm-item-title {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
}
#aimee .gm-item-sub { font-size: var(--text-xs); color: var(--text-dim); }

#aimee .gm-chip {
    flex-shrink: 0;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-mid);
    background: var(--surface);
    border-radius: var(--r-pill);
    padding: 3px 8px;
}

#aimee .gm-meter { display: flex; flex-direction: column; gap: 6px; }
#aimee .gm-meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
#aimee .gm-track {
    height: 6px;
    border-radius: var(--r-pill);
    background: var(--surface-2);
    overflow: hidden;
}
#aimee .gm-fill {
    display: block;
    height: 100%;
    border-radius: var(--r-pill);
    background: var(--accent);
}

/* Avisos: el color va en el borde izquierdo, no en el fondo. Un fondo teñido a
   ancho completo compite con las tarjetas y se lee como error. */
#aimee .gm-alert {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border-radius: var(--r-xs);
    background: var(--bg2);
    border-left: 3px solid var(--border-strong);
}
#aimee .gm-alert-ok   { border-left-color: var(--success); }
#aimee .gm-alert-warn { border-left-color: var(--warning); }
#aimee .gm-alert-info { border-left-color: var(--accent); }

#aimee .gm-foot { font-size: var(--text-xs); color: var(--text-dim); text-align: center; padding-top: 4px; }

/* El informe cabe en una columna cuando el panel es estrecho: en móvil, y también
   en escritorio si la ventana no da para tres tarjetas. */
@media (max-width: 1200px) {
    #aimee .gm-row-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
    #aimee .gm-row-2, #aimee .gm-row-3 { grid-template-columns: minmax(0, 1fr); }
    #aimee .gm-big { font-size: var(--text-2xl); }
    #aimee .gm-title { font-size: var(--text-lg); }
}

/* ── Hoja de acciones (el "+" del composer) ──────────────────────────────────
   Una sola capa para las dos pantallas. En escritorio es un popover que el JS
   ancla sobre el .input-box activo (por eso la posición no está aquí); a partir
   de 900px se convierte en hoja inferior, con el mismo gesto y la misma duración
   que el drawer del sidebar. */

/* El "+" ya aporta su propio aire por la izquierda: sin esto, el orbe más el
   botón más los 20px de padding empujan demasiado el texto hacia el centro. */
#aimee .input-box:has(.sheet-btn) { padding-left: 14px; }

#aimee .sheet-btn { flex-shrink: 0; }
#aimee .sheet-btn[aria-expanded="true"] { background: var(--surface-2); color: var(--text); }

#aimee .sheet-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--overlay);
    /* Por encima del sidebar (250) y del composer, por debajo del modal de
       usuario (999) y de los tooltips (9999). */
    z-index: 520;
}
#aimee .sheet-overlay.visible { display: block; }

#aimee .action-sheet {
    position: fixed;
    width: min(92vw, 380px);
    /* `dvh` y no `vh`: con `vh` el panel se mide contra el viewport grande y sus
       botones de abajo se quedaban fuera de la pantalla en el móvil. */
    max-height: 82vh;
    max-height: 82dvh;
    overflow-y: auto;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-pop);
    padding: 8px;
    animation: aimee-slideUpFade .2s ease-out;
}

#aimee .sheet-grabber { display: none; }

#aimee .sheet-header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 8px 10px;
}
#aimee .sheet-title {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-dim);
}
#aimee .sheet-back {
    width: 24px; height: 24px;
    border: none;
    background: none;
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    border-radius: var(--r-xs);
    transition: background .15s, color .15s;
    flex-shrink: 0;
}
#aimee .sheet-back:hover { background: var(--surface); color: var(--text); }
#aimee .sheet-back svg { width: 16px; height: 16px; }

/* ── Lista de acciones ───────────────────────────────────────────────────── */
#aimee .sheet-list { display: flex; flex-direction: column; gap: 2px; }

/* Mismas métricas que .mode-menu-option: los dos son filas de un menú que sale
   del composer y deben leerse igual. */
#aimee .sheet-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 12px;
    border: none;
    background: none;
    text-align: left;
    font-family: var(--font);
    cursor: pointer;
    border-radius: var(--r-xs);
    color: var(--text-mid);
    transition: background .15s, color .15s;
}
#aimee .sheet-item:hover { background: var(--surface); color: var(--text); }
#aimee .sheet-item svg { width: 18px; height: 18px; flex-shrink: 0; opacity: .7; }
#aimee .sheet-item:hover svg { opacity: 1; }

#aimee .sheet-item-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
#aimee .sheet-item-label { font-size: var(--text-sm); font-weight: 500; color: var(--text); }
#aimee .sheet-item-sub   { font-size: var(--text-xs); color: var(--text-dim); }

#aimee .sheet-item.disabled { opacity: .5; pointer-events: none; }
#aimee .sheet-badge {
    flex-shrink: 0;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
    background: var(--surface-2);
    padding: 3px 7px;
    border-radius: var(--r-pill);
}

/* Sección de acciones propias de la empresa, separada del catálogo común por una
   línea y su título: son cosas de otra naturaleza y conviene que se note. */
#aimee .sheet-section {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
}
#aimee .sheet-section-title {
    padding: 0 12px 6px;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
}

/* ── Formulario ──────────────────────────────────────────────────────────── */
#aimee .sheet-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 4px 12px 12px;
}
#aimee .sheet-row { display: flex; gap: 10px; }
#aimee .sheet-row > * { flex: 1; min-width: 0; }

/* El prefijo es corto y el número largo: repartir la fila a partes iguales deja
   el select con aire de sobra y el teléfono apretado.
   Dos clases en el selector a propósito: `.user-input-group select` fija
   width:100% y con una sola clase gana ella, que es lo que dejaba al select
   ocupando la fila entera y el campo del número fuera de la vista. */
#aimee .sheet-row .sheet-country {
    flex: 0 0 100px;
    width: 100px;
    padding-left: 10px;
    padding-right: 4px;
}

/* Etiqueta a la izquierda y el interruptor de destino a la derecha, en la misma
   línea que la etiqueta para no robarle alto al formulario. */
#aimee .sheet-field-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
#aimee .sheet-toggle { width: 28px; height: 28px; }
#aimee .sheet-toggle svg { width: 16px; height: 16px; }
#aimee .sheet-toggle.is-active { background: var(--accent-soft); color: var(--accent); }
#aimee .sheet-toggle.is-active:hover { background: var(--accent-soft); color: var(--accent-hover); }

#aimee .sheet-form textarea { resize: vertical; min-height: 76px; line-height: 1.5; }

#aimee .sheet-error { color: var(--danger); font-size: var(--text-xs); line-height: 1.4; }

#aimee .sheet-actions { display: flex; gap: 10px; align-items: center; }
#aimee .sheet-actions .user-modal-btn { flex: 1; }
#aimee .sheet-cancel {
    padding: 13px 18px;
    border: 1px solid var(--border);
    border-radius: var(--r-xs);
    background: none;
    color: var(--text-mid);
    font-family: var(--font);
    font-size: var(--text-base);
    font-weight: 500;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .sheet-cancel:hover { background: var(--surface); color: var(--text); border-color: var(--border-strong); }

/* ── Hoja inferior en móvil ──────────────────────────────────────────────── */
@keyframes aimee-sheetUp {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

@media (max-width: 900px) {
    #aimee .action-sheet {
        /* !important porque el anclaje de escritorio deja top/left en línea, y
           un estilo en línea gana a la media query. El JS también los limpia al
           reposicionar, esto es el cinturón. */
        left: 0 !important;
        top: auto !important;
        right: 0;
        bottom: 0;
        width: 100%;
        max-width: none;
        max-height: 88vh;
        max-height: 88dvh;
        border-radius: var(--r-lg) var(--r-lg) 0 0;
        border-bottom: none;
        padding: 4px 8px calc(12px + env(safe-area-inset-bottom));
        /* Animación y no transición: el panel entra en el mismo fotograma en que
           el overlay pasa de display:none a block, y una transición ahí no
           arranca. Misma duración que el drawer del sidebar. */
        animation: aimee-sheetUp .28s ease-out;
    }

    #aimee .sheet-grabber {
        display: block;
        width: 36px; height: 4px;
        margin: 8px auto 4px;
        border-radius: var(--r-pill);
        background: var(--surface-3);
    }
}

/* Marca de que Aimee guardó ese mensaje en su memoria episódica.
   Arriba a la derecha de la burbuja, en el color atenuado: es un dato SOBRE el
   mensaje, no parte de lo que dice, y en la esquina no se mezcla con la lectura. */
#aimee .msg .bubble { position: relative; }

/* El hueco de la esquina se reserva solo en las burbujas que llevan marca: si no,
   la primera línea del texto pasa por debajo del icono. */
#aimee .bubble.con-memoria { padding-right: 34px; }

#aimee .memoria-badge {
    position: absolute;
    top: 10px;
    right: 12px;
    display: inline-flex;
    color: var(--text-dim);
    cursor: default;
}
/* 16px y no 8. Medido renderizando el icono a tamaño real: por debajo de 15px los
   pliegues y el cerebelo se empastan y vuelve a parecer una nube. A 16 se reconoce
   y sigue siendo más pequeño que la altura de una mayúscula del texto. */
#aimee .memoria-badge svg { width: 16px; height: 16px; }
#aimee .memoria-badge:hover { color: var(--accent); }

/* Pie de una respuesta de especialista: de dónde salió y lo que tardó.

   Debajo del texto y no en la esquina como la marca de memoria, porque no es un
   icono: es una línea que se lee. Un punto por encima de la hora del mensaje (10px)
   y en el mismo --text-dim: se tiene que poder leer sin competir con la respuesta,
   porque el dato importa cuando se busca, no mientras se lee.

   Sin sombra de texto, como todo en este producto. */
#aimee .especialista-pie {
    margin-top: 6px;
    font-size: var(--text-xs);
    color: var(--text-dim);
    cursor: default;
    user-select: none;
}

/* La misma inicial mayúscula que la burbuja, para no dejar dos grafías del mismo
   nombre a la vista en la misma pantalla. En un span y no en el pie entero porque el
   pie lleva también el tiempo, y `capitalize` sobre todo el nodo tocaría su unidad:
   «13,4 s» se leería «13,4 S». */
#aimee .especialista-pie-etiqueta { text-transform: capitalize; }

/* La respuesta que llegó con el chat fijado a un especialista y NO la escribió él.
   En ámbar y no en rojo: no es un error —la respuesta es válida, la ha dado el chat
   de siempre— es una advertencia sobre su procedencia. Rojo diría "algo ha fallado",
   y lo que hay que decir es "esto no es lo que crees que estás leyendo". */
#aimee .especialista-pie.es-fallback { color: var(--warning); }

/* Acción propia nombrada por Aimee dentro de un mensaje: es pulsable y al pulsarla
   se escribe en el composer. Se pinta como una píldora y no como un enlace para
   que se lea como algo que se usa, no como algo que lleva a otro sitio. */
#aimee .accion-chip {
    display: inline-block;
    padding: 1px 8px;
    margin: 0 1px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    background: var(--bg);
    color: var(--accent);
    font-family: var(--font);
    font-size: .92em;
    font-weight: 500;
    line-height: 1.5;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}
#aimee .accion-chip:hover {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--accent-hover);
}
#aimee .accion-chip:active { background: var(--surface-2); }

/* El botón de acciones con una acción escrita en el composer: el "+" pasa a rayo.
   Se pinta con el acento porque el cambio de icono solo no se nota lo suficiente
   como para explicar que el siguiente mensaje va a ir a esa acción y no al chat. */
#aimee .sheet-btn.tiene-accion {
    color: var(--accent);
    background: var(--accent-soft);
}
#aimee .sheet-btn.tiene-accion:hover {
    color: var(--accent-hover);
    background: var(--accent-soft);
}

/* ── Mapa ────────────────────────────────────────────────────────────────────
   Lo pinta MapLibre a partir de un FeatureCollection de GeoJSON. El mapa ocupa
   la burbuja entera y encima van tres cosas flotando: las chinchetas, el botón
   de ampliar y la tarjeta del sitio seleccionado.

   El mapa se lleva su propio bloque de estilos y no hereda de `.bubble` porque
   dentro no hay texto: hay un lienzo. Bordes redondeados con `overflow: hidden`
   para que el lienzo no se salga por las esquinas. */
/* Ocupa el ancho entero de la conversación, no el de una burbuja de texto.
   `.msg-content` ya es `flex: 1`, así que basta con soltar el `max-width: 520px`
   que hereda de `.bubble`: el ancho lo acaba marcando `.msg` (760px menos sus
   28px de margen a cada lado). Un mapa se lee por lo que abarca; encogerlo al
   ancho de un párrafo desperdicia justo lo que lo hace útil. */
/* El mapa va siempre en claro (estilo `positron`, `estiloMapa` en app.js): lo pidió el usuario (2026-11-05). Aimee ya
   usa el tema claro de Arc, así que su caja, la tarjeta y los botones toman los tokens de siempre. */
#aimee .map-bubble,
#aimee .map-overlay-caja,
#aimee .map-full {
    color: var(--text);
}
#aimee .map-bubble {
    padding: 0 !important;
    overflow: hidden;
    background: var(--surface) !important;
    border: 1px solid var(--border) !important;
    /* Suelta el tope de lectura de `.bubble` (520px) y a la vez pone uno que el
       contenido no pueda saltarse. Contra el VIEWPORT y no contra el padre:
       `max-width: 100%` es inútil aquí —probado— porque el porcentaje se
       resuelve contra un padre que, cuando falla el ancho mínimo, ya viene
       reventado. La pantalla, en cambio, no miente. */
    max-width: calc(100vw - 2 * var(--msg-pad));
    width: 100%;
}

/* El tope real de una respuesta no está en `.bubble` sino en
   `.msg.assistant > div { max-width: 560px }`, que es lo que mantiene el texto
   en un ancho de lectura cómodo. Para el texto está bien; para un mapa no, y
   soltarlo solo en `.map-bubble` no servía de nada porque el que ataba era el
   contenedor. `:has()` lo levanta ÚNICAMENTE cuando ese contenedor lleva un
   mapa dentro, sin tocar el resto de mensajes. */
#aimee .msg.assistant > div:has(.map-bubble) { max-width: none; }

/* TARJETAS — `{{tarjetas:reports}}` en una respuesta de Astrolle (la pinta `_tarjetas` en
   talk/astrolle_mcp.py; app.js la saca de la burbuja con `colocarTarjetas`). El texto queda en la
   burbuja y las tarjetas debajo, FUERA, a todo el ancho del hilo, como el mapa.
   Diseño de tarjeta con imagen a sangre (como en el producto: NX01_mcp/problems/2.png): la imagen
   cubre la tarjeta y un degradado oscuro sube desde abajo para que el título, en blanco, se lea sobre
   cualquier foto. Sin descripción: la cuenta Aimee si se la preguntan. Colores fijos y no del tema: con `var(--bg)` el pie salía
   negro con letras negras (problems/3.png). Sin imagen, un degradado con la inicial.
   SIEMPRE 3 por fila, también en móvil: lo que se encoge es la tarjeta y su texto, no el número de
   columnas. `.tarjetas-fuera` es un contenedor (`container-type`) y los tamaños van en `cqw` (% de su
   ancho) con `clamp()`: a 900px de hilo el título mide 16px; a 360px (móvil), 10px. */
#aimee .msg.assistant > div:has(.tarjetas) { max-width: none; }
#aimee .msg.assistant > div:has(.organigrama) { max-width: none; }
#aimee .tarjetas-fuera { width: 100%; max-width: calc(100vw - 2 * var(--msg-pad)); margin: 10px 0 2px; container-type: inline-size; }
#aimee .tarjetas {
    display: grid;
    /* `minmax(0, 1fr)` y no `1fr`: con `1fr` una columna no baja del ancho propio de su contenido. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: clamp(6px, 1.8cqw, 16px);
}
#aimee .tarjeta {
    /* Un hijo de grid no baja de su ancho mínimo de contenido (el ancho propio de la imagen, 413px):
       sin esto, en un móvil empujaba el hilo entero más ancho que la pantalla. */
    min-width: 0;
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: clamp(8px, 2.2cqw, 20px);
    background: var(--foreground);
    transition: border-color var(--duration-fast) var(--ease-standard);
}
/* Cuadritos pastel (desde 2026-10-15): sin imagen, el color va por orden en la lista (`_tarjetas` en
   talk/astrolle_mcp.py da `data-tono` 0–11 de 5 en 5: dos vecinas nunca se parecen) y el código va detrás del
   nombre entre paréntesis. Tinta oscura
   sobre pastel: contraste de más de 12:1 en los doce. Las tarjetas guardadas antes (con imagen y sin `data-tono`)
   siguen con el estilo de arriba. */
/* 2 por fila en tamaño celular y 3 cuando hay más ancho, nunca más: lo decide el ancho del hilo (`.tarjetas-fuera`
   es un contenedor), no el de la ventana. Con 3 forzadas, a 280px los títulos se cortaban («ENFERME…»). */
#aimee .tarjetas:has(.tarjeta[data-tono]) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@container (min-width: 480px) {
    #aimee .tarjetas:has(.tarjeta[data-tono]) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Tan altas como el título más un 10% encima (porcentaje del ancho, como todo padding en CSS): el cuerpo vuelve
   al flujo en vez de ir anclado abajo de un cuadro fijo. */
#aimee .tarjeta[data-tono] { aspect-ratio: auto; background: var(--tarjeta-pastel); border: 1px solid color-mix(in oklab, var(--tarjeta-pastel), var(--foreground) 8%); }
#aimee .tarjeta[data-tono] .tarjeta-cuerpo { position: static; padding-top: 10%; }
#aimee .tarjeta[data-tono]:hover { border-color: color-mix(in oklab, var(--tarjeta-pastel), var(--foreground) 22%); }
#aimee .tarjeta[data-tono] .tarjeta-titulo { color: var(--foreground); font-size: clamp(var(--text-xs), 1.6cqw, var(--text-sm)); -webkit-line-clamp: 4; }
#aimee .tarjeta-codigo-texto { font-weight: 500; opacity: .62; white-space: nowrap; }
#aimee .tarjeta[data-tono="0"]  { --tarjeta-pastel: #FAD4D4; } /* rosa */
#aimee .tarjeta[data-tono="1"]  { --tarjeta-pastel: #FBE0C8; } /* melocotón */
#aimee .tarjeta[data-tono="2"]  { --tarjeta-pastel: #FCEFC4; } /* vainilla */
#aimee .tarjeta[data-tono="3"]  { --tarjeta-pastel: #E4F2C8; } /* lima */
#aimee .tarjeta[data-tono="4"]  { --tarjeta-pastel: #CDEFD8; } /* menta */
#aimee .tarjeta[data-tono="5"]  { --tarjeta-pastel: #C8EDEA; } /* aguamarina */
#aimee .tarjeta[data-tono="6"]  { --tarjeta-pastel: #CBE6F7; } /* cielo */
#aimee .tarjeta[data-tono="7"]  { --tarjeta-pastel: #D3DDFA; } /* pervinca */
#aimee .tarjeta[data-tono="8"]  { --tarjeta-pastel: #E0D4F7; } /* lavanda */
#aimee .tarjeta[data-tono="9"]  { --tarjeta-pastel: #F1D2F0; } /* orquídea */
#aimee .tarjeta[data-tono="10"] { --tarjeta-pastel: #F7D3E3; } /* chicle */
#aimee .tarjeta[data-tono="11"] { --tarjeta-pastel: #E3E0D8; } /* arena */
/* KPIs de Glup (`{{kpis:kpis}}`, talk/astrolle_mcp.py:_kpis), con la forma del Metric card de Arc (uiarc.dev,
   `metric-card`): superficie con borde, radio de superficie, 24px de relleno y la sombra en reposo. Arriba el
   nombre y, a la derecha, el cambio en una píldora; 32px más abajo la cifra en Geist (como el AnimatedCounter de
   Arc) y debajo el contexto en gris suave.
   Dos diferencias a propósito con Arc:
   - la píldora del cambio va neutra: si subir es bueno depende del KPI;
   - el resultado (cumplida, no cumplida, error) va en su insignia de estado, con el tinte suave de Arc.
   2 por fila en celular y 3 con más ancho, como las tarjetas. */
#aimee .msg.assistant > div:has(.kpis) { max-width: none; }
#aimee .kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
@container (min-width: 480px) { #aimee .kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
#aimee .kpi {
    --kpi-color: var(--text-muted);
    min-width: 0; display: flex; flex-direction: column;
    padding: var(--space-6);
    border: 1px solid var(--border); border-radius: var(--radius-surface);
    /* `--surface-raised` y no `--surface`: en Aimee `--surface` es el gris de los hovers; el blanco de Arc es este. */
    background: var(--surface-raised); box-shadow: var(--shadow-resting); color: var(--foreground);
}
#aimee .kpi[data-resultado="achieved"]     { --kpi-color: var(--success); }
#aimee .kpi[data-resultado="not_achieved"] { --kpi-color: var(--danger); }
#aimee .kpi[data-resultado="error"],
#aimee .kpi[data-resultado="timeout"]      { --kpi-color: var(--warning); }
#aimee .kpi-arriba {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    margin-bottom: var(--space-8);
    /* El alto de la píldora aunque no haya cambio: así la cifra cae a la misma altura en todas las tarjetas. */
    min-height: calc(var(--text-sm) * var(--leading-body) + 8px);
}
#aimee .kpi-nombre { min-width: 0; color: var(--text-secondary); font-size: var(--text-sm); overflow-wrap: anywhere; }
#aimee .kpi-tendencia {
    display: inline-flex; flex: 0 0 auto; padding: 3px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-pill);
    color: var(--text-secondary); font-size: var(--text-sm); white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Los KPIs guardados antes en el historial llevan la flecha dentro de la cifra: ahí va pequeña y sin píldora. */
#aimee .kpi-valor .kpi-tendencia {
    padding: 0; border: 0; font-family: var(--font-body); font-size: var(--text-sm);
    letter-spacing: var(--tracking-body); vertical-align: middle;
}
#aimee .kpi > .kpi-nombre { margin-bottom: var(--space-8); }
#aimee .kpi-valor {
    color: var(--foreground); font-family: var(--font-display); font-size: var(--text-3xl); font-weight: 500;
    letter-spacing: var(--tracking-display); line-height: 1; font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
#aimee .kpi-estado {
    align-self: flex-start; margin-top: var(--space-4); padding: 2px 8px; border-radius: var(--radius-pill);
    font-size: var(--text-xs); font-weight: 500;
    color: var(--kpi-color); background: color-mix(in oklab, var(--kpi-color) 11%, transparent);
}
#aimee .kpi-pie { margin-top: var(--space-4); color: var(--text-muted); font-size: var(--text-sm); line-height: var(--leading-body); }
#aimee .kpi-estado + .kpi-pie { margin-top: var(--space-2); }
/* Cumplió la meta pero cambió mucho (`check_data` de glups.kpis): ámbar, como «revisar», no rojo. */
#aimee .kpi-aviso { margin-top: var(--space-2); color: var(--warning); font-size: var(--text-sm); }
/* En un hilo estrecho, como Arc por debajo de 380px: menos relleno, la fila de arriba puede partirse y la cifra baja
   un paso para que quepan dos por fila. */
@container (max-width: 480px) {
    #aimee .kpi { padding: var(--space-4); }
    #aimee .kpi-arriba { align-items: flex-start; flex-wrap: wrap; margin-bottom: var(--space-6); }
    #aimee .kpi-valor { font-size: var(--text-2xl); }
}
/* Clima de una unidad productiva (`{{clima:units}}`, talk/astrolle_mcp.py:_clima), como la referencia que pidió el
   usuario (dribbble 21615833): de día azul con ondas, de noche azul noche con luna y estrellas; con lluvia o nubes, un
   azul más gris. Texto blanco sobre fondo propio y sin `text-shadow`: los azules son lo bastante oscuros para leerlo. */
#aimee .msg.assistant > div:has(.clima) { max-width: none; }
#aimee .clima { display: grid; gap: 12px; max-width: 560px; }
#aimee .clima-tarjeta {
    --clima-fondo: linear-gradient(120deg, #0A7FC8 0%, #1C62C4 100%);
    position: relative; overflow: hidden; isolation: isolate;
    display: flex; align-items: stretch; gap: 16px; padding: 14px 18px 16px;
    border-radius: 14px; color: #fff; background: var(--clima-fondo);
    box-shadow: 0 10px 24px -12px rgba(16, 60, 120, .55);
}
#aimee .clima-tarjeta[data-cielo="nube"],
#aimee .clima-tarjeta[data-cielo="niebla"] { --clima-fondo: linear-gradient(120deg, #3F74A8 0%, #35598F 100%); }
#aimee .clima-tarjeta[data-cielo="lluvia"],
#aimee .clima-tarjeta[data-cielo="llovizna"],
#aimee .clima-tarjeta[data-cielo="tormenta"] { --clima-fondo: linear-gradient(120deg, #3A6390 0%, #2B4A78 100%); }
#aimee .clima-tarjeta[data-momento="noche"] { --clima-fondo: linear-gradient(120deg, #1A5A82 0%, #0D3656 100%); }
/* Las ondas: anillos concéntricos que salen de la esquina de arriba a la derecha y respiran despacio. */
#aimee .clima-tarjeta::before {
    content: ""; position: absolute; z-index: -1; width: 420px; height: 420px; right: -150px; top: -190px;
    border-radius: 50%; pointer-events: none;
    background: repeating-radial-gradient(circle, rgba(255, 255, 255, .09) 0 34px, rgba(255, 255, 255, .03) 34px 68px);
    animation: aimee-clima-ondas 7s ease-in-out infinite alternate;
}
/* De noche, la luna asoma arriba y hay estrellas sueltas. */
#aimee .clima-tarjeta[data-momento="noche"]::after {
    content: ""; position: absolute; z-index: -1; width: 64px; height: 64px; right: 120px; top: -26px;
    border-radius: 50%; background: transparent; box-shadow: -18px 14px 0 0 #FCE7A0; /* la sombra desplazada es la luna creciente */
    pointer-events: none;
}
#aimee .clima-tarjeta[data-momento="noche"]::before {
    background:
        radial-gradient(circle at 20% 60%, rgba(255, 255, 255, .7) 0 1.5px, transparent 2px),
        radial-gradient(circle at 48% 80%, rgba(255, 255, 255, .5) 0 1.2px, transparent 1.7px),
        radial-gradient(circle at 34% 44%, rgba(255, 255, 255, .6) 0 1px, transparent 1.5px),
        repeating-radial-gradient(circle, rgba(255, 255, 255, .06) 0 34px, rgba(255, 255, 255, .02) 34px 68px);
}
@keyframes aimee-clima-ondas { from { transform: scale(.94); } to { transform: scale(1.06); } }
#aimee .clima-ahora { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
#aimee .clima-lugar {
    align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
    padding: 3px 10px 3px 7px; border-radius: var(--radius-pill); background: rgba(6, 30, 60, .32);
    font-size: var(--text-sm); font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
#aimee .clima-lugar svg { width: 14px; height: 14px; flex: none; }
#aimee .clima-fila { display: flex; align-items: center; gap: clamp(12px, 3cqw, 26px); flex-wrap: wrap; }
#aimee .clima-cielo { display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: var(--text-sm); }
#aimee .clima-cielo span::first-letter { text-transform: uppercase; }
#aimee .clima-icono { width: 46px; height: 46px; }
#aimee .clima-temp { display: flex; flex-direction: column; align-items: center; line-height: 1; }
#aimee .clima-temp strong { font-size: clamp(var(--text-3xl), 10cqw, var(--text-4xl)); font-weight: 200; letter-spacing: -1px; }
#aimee .clima-rango { font-size: var(--text-sm); margin-top: 6px; opacity: .92; }
#aimee .clima-extra { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; font-size: var(--text-sm); }
#aimee .clima-pastilla { padding: 2px 10px; border-radius: var(--radius-pill); background: #E9F7FF; color: #0B4F86; font-weight: 500; }
#aimee .clima-manana {
    flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    padding-left: 16px; border-left: 1px solid rgba(255, 255, 255, .7); font-size: var(--text-sm); min-width: 92px;
}
#aimee .clima-manana .clima-icono { width: 38px; height: 38px; }
#aimee .clima-manana .clima-rango { margin-top: 0; }
#aimee .clima-manana small { font-size: var(--text-xs); opacity: .9; }
/* En un celular, mañana baja debajo de lo de ahora, con la raya arriba. */
@container (max-width: 420px) {
    #aimee .clima-tarjeta { flex-direction: column; gap: 10px; }
    #aimee .clima-manana { flex-direction: row; gap: 10px; padding: 8px 0 0; border-left: 0; border-top: 1px solid rgba(255, 255, 255, .6); }
}
@media (prefers-reduced-motion: reduce) { #aimee .clima-tarjeta::before { animation: none; } }
/* Organigrama de la empresa (`{{organigrama:companies}}`, talk/astrolle_mcp.py:_organigrama): árbol de arriba abajo
   con conectores en CSS. Lo ancho (muchos procesos) se desplaza en horizontal en vez de apretarse. */
#aimee .tarjetas-fuera:has(.organigrama) { --org-linea: var(--border-strong); }
#aimee .organigrama { overflow-x: auto; padding: 4px 2px 10px; }
/* `margin: auto` y no `justify-content: center`: centrado con flex, lo que desborda por la izquierda queda fuera del
   scroll y no se puede ver. Así, si cabe se centra, y si no, empieza en el borde y se desplaza. */
#aimee .org-arbol { width: max-content; margin: 0 auto 18px; }
#aimee .org-rama { display: flex; justify-content: center; position: relative; margin: 0; padding: 18px 0 0; list-style: none; }
#aimee .org-arbol > .org-rama { padding-top: 0; }
#aimee .org-item { position: relative; display: flex; flex-direction: column; align-items: center; padding: 18px 6px 0; }
#aimee .org-item::before, #aimee .org-item::after {
    content: ''; position: absolute; top: 0; right: 50%; width: 50%; height: 18px; border-top: 2px solid var(--org-linea);
}
#aimee .org-item::after { right: auto; left: 50%; border-left: 2px solid var(--org-linea); }
#aimee .org-item:only-child::before, #aimee .org-item:only-child::after { display: none; }
#aimee .org-item:only-child { padding-top: 0; }
#aimee .org-item:first-child::before, #aimee .org-item:last-child::after { border: 0 none; }
#aimee .org-item:last-child::before { border-right: 2px solid var(--org-linea); border-radius: 0 8px 0 0; }
#aimee .org-item:first-child::after { border-radius: 8px 0 0 0; }
/* Los hijos de un grupo (procesos, unidades) bajan en filas dentro del ancho del hilo: uno al lado del otro, 8
   procesos medían más de 2000px y la empresa quedaba fuera de la vista. Un solo conector baja al bloque. */
#aimee .org-grupo + .org-rama {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 200px)); justify-content: center; gap: 8px;
    max-width: calc(50cqw - 24px);
}
#aimee .org-item:only-child > .org-grupo + .org-rama { max-width: calc(100cqw - 24px); }
#aimee .org-grupo + .org-rama > .org-item { padding: 0; }
#aimee .org-grupo + .org-rama > .org-item > .org-nodo { max-width: none; width: 100%; height: 100%; box-sizing: border-box; }
#aimee .org-grupo + .org-rama > .org-item::before, #aimee .org-grupo + .org-rama > .org-item::after { display: none; }
#aimee .org-rama .org-rama::before {
    content: ''; position: absolute; top: 0; left: 50%; height: 18px; border-left: 2px solid var(--org-linea);
}
#aimee .org-nodo {
    min-width: 120px; max-width: 220px; padding: 8px 12px; border-radius: var(--r-sm); background: var(--surface-raised);
    border: 1px solid var(--border); color: var(--foreground); font-size: var(--text-sm); font-weight: 500; line-height: 1.25;
}
#aimee .org-empresa { background: var(--foreground); border-color: var(--foreground); color: var(--background); font-size: var(--text-sm); }
#aimee .org-grupo { background: var(--surface-muted); color: var(--foreground); font-size: var(--text-xs); }
#aimee .org-nota { display: block; margin-top: 2px; font-weight: 400; font-size: var(--text-xs); opacity: .8; }
#aimee .org-hojas { margin: 6px 0 0; padding: 6px 0 0; list-style: none; border-top: 1px solid var(--border-subtle); text-align: left; }
#aimee .org-hojas li { font-weight: 400; font-size: var(--text-xs); color: var(--text-secondary); padding: 1px 0 1px 10px; position: relative; }
#aimee .org-hojas li::before { content: '•'; position: absolute; left: 0; color: var(--text-muted); }
#aimee .org-sueltos { display: flex; justify-content: center; }
#aimee .org-sueltos .org-nodo { background: transparent; border: 1px dashed var(--org-linea); box-shadow: none; }
#aimee .tarjeta-portada { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
/* Anclada arriba: los banners «R0x» llevan su título arriba (miden de 1,15 a 1,78). */
#aimee .tarjeta-portada img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; margin: 0; border-radius: 0; transition: transform .35s ease; }
#aimee .tarjeta:hover .tarjeta-portada img { transform: scale(1.03); }
/* El oscurecimiento: transparente arriba, casi negro abajo, donde va el texto. */
#aimee .tarjeta-portada::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Más denso en la franja del texto: los banners con texto propio (SPO248) competían con el título. */
    background: linear-gradient(to top, rgba(8, 12, 20, .95) 0%, rgba(8, 12, 20, .82) 32%, rgba(8, 12, 20, .35) 58%, rgba(8, 12, 20, 0) 80%);
    pointer-events: none;
}
/* Mensajes guardados antes de que la tarjeta dejara de llevar la descripción: el historial guarda el
   HTML ya pintado, así que la traen. Se oculta para que se vean como las nuevas. */
#aimee .tarjeta-texto { display: none; }
#aimee .tarjeta-inicial { font-size: clamp(22px, 6cqw, 56px); font-weight: 500; color: rgba(255, 255, 255, .35); margin-bottom: 25%; }
#aimee .tarjeta-codigo {
    position: absolute;
    top: clamp(5px, 1.3cqw, 12px);
    left: clamp(5px, 1.3cqw, 12px);
    z-index: 2;
    padding: clamp(1px, .2cqw, 2px) clamp(4px, 1.1cqw, 10px);
    border-radius: clamp(3px, .7cqw, 6px);
    background: #FBC02D;
    color: #1F1A12;
    font-size: clamp(8px, 1.35cqw, 12px);
    font-weight: 500;
    letter-spacing: .02em;
    line-height: 1.6;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
#aimee .tarjeta-cuerpo {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    padding: clamp(6px, 1.8cqw, 16px) clamp(7px, 1.8cqw, 16px) clamp(6px, 1.6cqw, 14px);
    display: flex;
    flex-direction: column;
    gap: 4px;
}
#aimee .tarjeta-titulo {
    margin: 0;
    font-size: clamp(var(--text-xs), 1.8cqw, var(--text-base));
    font-weight: 500;
    line-height: 1.25;
    color: #FFFFFF;
    /* Un nombre largo en una tarjeta de móvil (~110px) no se come la imagen: 3 líneas y «…». */
    /* Y una palabra larga sola («ENFERMEDADES» a 320px) parte en vez de cortarse. */
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Altura por proporción y no fija: a 704px de ancho, 380px de alto dejaban una
   franja apaisada. El `min-height` evita que en un móvil estrecho se quede en
   una tira, y el `max-height` que en un monitor ancho se coma la pantalla. */
#aimee .map-box {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    min-height: 300px;
    max-height: 520px;
    /* OJO al combinar estas dos: `aspect-ratio` con un `min-height` definido
       TRANSFIERE un ancho mínimo al otro eje —300px × 1.6 = 480px— y ese 480 se
       propaga hacia arriba como ancho mínimo de contenido de toda la rama. En un
       teléfono de 393px reventaba la burbuja hasta 482px: margen a la izquierda
       y nada a la derecha. Quien lo corta es el `min-width: 0` de `.msg-content`
       (buscar «TRANSFERENCIA» ahí); poner `min-width: 0` AQUÍ no sirve, está
       medido. Si algún día se toca el `min-height`, ese es el número que manda. */
    background: var(--surface-2);
}
#aimee .map-box .maplibregl-canvas { outline: none; }

/* MapLibre pintaría sus propios controles dentro del lienzo; se apagan porque
   los nuestros ya están, y su esquina inferior es donde vive la tarjeta. */
#aimee .map-box .maplibregl-ctrl-bottom-left,
#aimee .map-box .maplibregl-ctrl-bottom-right,
#aimee .map-box .maplibregl-ctrl-top-right { display: none; }

/* La atribución, obligatoria, va DEBAJO del mapa y no dentro: en una esquina la
   tapaba la tarjeta, y su control ocupa 44px —medido— que ahí no sobran. */
#aimee .map-attrib {
    padding: 4px 10px 5px;
    font-size: var(--text-xs);
    line-height: 1.3;
    color: var(--text-dim);
    text-align: right;
    background: var(--surface);
}
#aimee .map-attrib a { color: inherit; text-decoration: none; }
#aimee .map-attrib a:hover { text-decoration: underline; }

/* ── Chinchetas ──────────────────────────────────────────────────────────── */
#aimee .map-pin {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    cursor: pointer;
    user-select: none;
}
#aimee .map-pin-dot {
    width: 20px; height: 20px;
    border-radius: 6px;
    background: var(--accent);
    color: #FFFFFF;
    display: grid; place-items: center;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .45);
    transition: transform .15s;
}
#aimee .map-pin-dot svg { width: 12px; height: 12px; }
#aimee .map-pin:hover .map-pin-dot { transform: scale(1.12); }
#aimee .map-pin-label {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--accent);
    text-shadow: 0 1px 3px var(--bg), 0 0 6px var(--bg);
    white-space: nowrap;
    max-width: 130px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* El seleccionado no es una chincheta más grande: es otra cosa. Píldora oscura
   con la nota, que es el dato por el que se elige un sitio. */
#aimee .map-pin.is-active .map-pin-dot {
    width: auto; height: 22px;
    padding: 0 9px;
    border-radius: var(--radius-pill);
    background: var(--ink);
    color: var(--on-ink);
    display: flex; align-items: center; gap: 4px;
    font-size: var(--text-xs); font-weight: 500;
}
#aimee .map-pin.is-active .map-pin-dot svg { width: 11px; height: 11px; }
#aimee .map-pin.is-active .map-pin-label {
    color: var(--text);
    font-weight: 500;
    font-size: var(--text-xs);
}

/* ── Controles del mapa ──────────────────────────────────────────────────────
   Juntos en un grupo y no colocados a mano uno por uno: así añadir un tercero
   no obliga a recalcular la posición de los otros dos. */
#aimee .map-controles {
    position: absolute;
    top: 10px; right: 10px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
}
#aimee .map-controles-fila {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Acercar y alejar, apilados como es costumbre en un mapa. Comparten la piel de
   la `i` para que los cuatro controles se lean como un mismo juego. */
#aimee .map-zoom {
    display: flex;
    flex-direction: column;
    border-radius: var(--radius-pill);
    overflow: hidden;
    background: var(--surface-raised);
    color: var(--foreground);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-raised);
}
#aimee .map-zoom button {
    width: 28px; height: 28px;
    border: none;
    background: none;
    color: var(--foreground);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background var(--duration-fast) var(--ease-standard);
}
#aimee .map-zoom button + button { box-shadow: inset 0 1px 0 var(--border); }
#aimee .map-zoom button:hover:not(:disabled) { background: var(--surface-muted); }
/* En el tope no se puede acercar más: el botón lo dice en vez de no responder. */
#aimee .map-zoom button:disabled { opacity: .35; cursor: not-allowed; }
#aimee .map-zoom svg { width: 14px; height: 14px; }

/* La `i` enciende y apaga la tarjeta de información. Redonda y sin texto: es un
   interruptor, no una acción con nombre. */
#aimee .map-info {
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--surface-raised);
    color: var(--foreground);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-raised);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
#aimee .map-info:hover { background: var(--surface-muted); }
#aimee .map-info svg { width: 14px; height: 14px; }

/* Apagada se ve apagada: si no se distinguiera, quien no encuentre la tarjeta
   no sabría que hay un interruptor puesto y pensaría que está roto. */
#aimee .map-info.is-off {
    background: var(--surface);
    color: var(--text-dim);
    box-shadow: inset 0 0 0 1px var(--border-strong);
}

#aimee .map-expand {
    display: flex; align-items: center; gap: 6px;
    padding: 6px 11px;
    border-radius: var(--radius-pill);
    background: var(--surface-raised);
    color: var(--foreground);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-raised);
    font: inherit;
    font-size: var(--text-xs);
    font-weight: 500;
    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-standard);
}
#aimee .map-expand:hover { background: var(--surface-muted); }
#aimee .map-expand svg { width: 12px; height: 12px; }

/* ── Tarjeta del sitio ───────────────────────────────────────────────────── */
/* Oculta de verdad: `[hidden]` por sí solo no gana al `display: flex` de aquí
   abajo, y la tarjeta se quedaba puesta con el interruptor apagado. */
#aimee .map-card[hidden] { display: none; }

#aimee .map-card {
    position: absolute;
    left: 10px; right: 10px; bottom: 10px;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px;
    border-radius: 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-floating);
}

/* Sin foto: un glifo de la categoría sobre un cuadro tintado. Antes que traer
   imágenes de un tercero —y con ellas sus peticiones y su rastreo—, se dibuja. */
#aimee .map-card-thumb {
    flex: none;
    width: 62px; height: 62px;
    border-radius: 10px;
    background: var(--accent-soft);
    color: var(--accent);
    display: grid; place-items: center;
}
#aimee .map-card-thumb svg { width: 24px; height: 24px; }
/* Una zona no es un sitio: se distingue en la miniatura sin necesidad de leer. */
#aimee .map-card-thumb.is-area {
    background: var(--surface-2);
    color: var(--text-mid);
}

#aimee .map-card-body { flex: 1; min-width: 0; }
#aimee .map-card-title {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Las propiedades vienen de datos del cliente: pueden ser dos o veinte, y no se
   sabe cuáles. Se pintan como celdas que fluyen y saltan de línea, en vez de
   filas fijas: así dos no dejan un hueco y veinte no rompen la tarjeta.

   `max-height` con scroll y no recorte: si alguien manda veinte propiedades es
   porque las veinte importan, y esconderlas sin decirlo es peor que tener que
   desplazar. El tope evita que la tarjeta se coma el mapa. */
#aimee .map-card-props {
    display: flex;
    flex-wrap: wrap;
    gap: 3px 10px;
    margin-top: 4px;
    max-height: 66px;
    overflow-y: auto;
    overscroll-behavior: contain;   /* al llegar al final no arrastra el chat */
}
#aimee .map-card-props::-webkit-scrollbar { width: 3px; }
#aimee .map-card-props::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: var(--r-pill); }

#aimee .map-card-prop {
    font-size: var(--text-xs);
    color: var(--text);
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* La etiqueta en apagado y el valor en normal: se distingue el dato del rótulo
   sin necesidad de dos puntos ni de columnas. */
#aimee .map-card-prop i {
    font-style: normal;
    color: var(--text-dim);
    margin-right: 4px;
}

/* La nota va con su estrella y sin rótulo: "Rating 4.3" sobra cuando la
   estrella ya lo dice. Es una de las tres claves fijas del mapa. */
#aimee .map-card-prop.is-rating {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-weight: 500;
}
#aimee .map-card-prop.is-rating svg { width: 11px; height: 11px; }

/* Un booleano no se lee como "true": se lee como la etiqueta, encendida o no. */
#aimee .map-card-prop.is-si { color: var(--success); font-weight: 500; }
#aimee .map-card-prop.is-no { color: var(--text-dim); }
#aimee[data-theme="dark"] .map-card-prop.is-si { color: #4ade80; }

/* Navegar entre sitios sin tener que acertarle a una chincheta de 20px. */
#aimee .map-card-nav {
    flex: none;
    display: flex;
    gap: 4px;
}
#aimee .map-card-nav button {
    width: 26px; height: 26px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .map-card-nav button:hover {
    background: var(--surface-2);
    color: var(--text);
    border-color: var(--border-strong);
}
#aimee .map-card-nav svg { width: 13px; height: 13px; }

@media (max-width: 520px) {
    #aimee .map-card-thumb { width: 48px; height: 48px; }
}

/* ── Mapa ampliado ───────────────────────────────────────────────────────────
   Ampliar no saca al usuario del chat: monta una capa encima. `z-index` por
   debajo del modal de sesión (999) y del diálogo de confirmación (500), que son
   los que sí deben poder aparecer sobre esto. */
#aimee .map-overlay {
    position: fixed;
    inset: 0;
    z-index: 400;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: var(--overlay);
    animation: aimee-fadeIn .15s ease;
}

/* Casi toda la pantalla, pero no toda: el borde de fondo visible es lo que
   dice que hay un chat debajo y que esto se cierra. */
#aimee .map-overlay-caja {
    display: flex;
    flex-direction: column;
    width: min(1100px, 100%);
    height: min(760px, 100%);
    border-radius: 16px;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-pop, 0 18px 50px rgba(0, 0, 0, .35));
}

#aimee .map-overlay-barra {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
#aimee .map-overlay-titulo {
    flex: 1;
    min-width: 0;
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#aimee .map-overlay-cerrar {
    flex: none;
    width: 30px; height: 30px;
    border-radius: var(--r-sm);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-mid);
    cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .map-overlay-cerrar:hover {
    background: var(--surface-2);
    color: var(--text);
    border-color: var(--border-strong);
}
#aimee .map-overlay-cerrar svg { width: 15px; height: 15px; }

/* Aquí el mapa llena lo que queda: hay que anular la proporción y los topes que
   `.map-box` trae para la burbuja, o limitarían el alto en vez de llenarlo. */
#aimee .map-overlay .map-box {
    flex: 1;
    height: auto;
    aspect-ratio: auto;
    min-height: 0;
    max-height: none;
    border-radius: 0;
}
/* Ya estás en el mapa ampliado: el botón de ampliar no tiene a dónde llevarte. */
#aimee .map-overlay .map-expand { display: none; }
/* Y la tarjeta se centra y se acota: estirada de lado a lado en un monitor
   quedaría una franja de 1100px con un nombre dentro. */
#aimee .map-overlay .map-card {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(560px, calc(100% - 24px));
    bottom: 16px;
}
#aimee .map-overlay .map-card-props { max-height: 140px; }
/* La línea de atribución no debe encogerse cuando el mapa se estira. */
#aimee .map-overlay .map-attrib { flex-shrink: 0; }

@media (max-width: 720px) {
    #aimee .map-overlay { padding: 0; }
    #aimee .map-overlay-caja { border-radius: 0; border: none; height: 100%; }
}

/* ── Comprobando mensajes nuevos ─────────────────────────────────────────────
   Aparece al entrar en un chat con mensajes sin leer y se va cuando terminan de
   bajar. Lleva la cifra de lo que queda, que es la misma que va bajando en el
   globo del sidebar: así se ve que está avanzando y no colgado.

   Va abajo y no arriba: arriba está la píldora del protocolo, y dos avisos
   apilados en la misma esquina se estorban. */
#aimee .checking-new {
    position: absolute;
    bottom: 96px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 240;
    display: flex;
    align-items: center;
    gap: 8px;
    width: max-content;
    max-width: min(420px, calc(100% - 40px));
    padding: 6px 14px;
    border-radius: var(--radius-pill);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    color: var(--text-mid);
    font-size: var(--text-xs);
    line-height: 1.4;
    box-shadow: var(--shadow-pop, 0 4px 16px rgba(0, 0, 0, .12));
    animation: aimee-checking-in .2s ease;
}
@keyframes aimee-checking-in {
    from { opacity: 0; transform: translate(-50%, 6px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

#aimee .checking-dot {
    flex: none;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: var(--accent);
    animation: aimee-protocol-pulse 1.2s ease-in-out infinite;
}

/* La cifra que queda, en el mismo rojo que el globo del sidebar: es el mismo
   número, y verlo bajar en los dos sitios es lo que cuenta que va avanzando. */
#aimee .checking-count {
    flex: none;
    min-width: 17px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--danger);
    color: #FFFFFF;
    font-size: var(--text-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 17px;
    text-align: center;
}
#aimee[data-theme="dark"] .checking-count { color: #1C0F0D; }

@media (prefers-reduced-motion: reduce) {
    #aimee .checking-new { animation: none; }
    #aimee .checking-dot { animation: none; }
}

/* ── Indicador de protocolo activo ──────────────────────────────────────────
   Se pinta mientras un protocolo está en marcha y desaparece al cerrarse.

   Es una píldora pequeña y siempre centrada al viewport, no una barra: informa
   de que algo está pasando, no alarma. Quien tiene que alarmarse es el mensaje
   del protocolo, no un adorno de la interfaz. Por eso el acento de color vive
   en el punto y en el borde, y el texto usa el color normal de la interfaz:
   así se lee bien en claro y en oscuro.

   Va arriba, dentro del hueco de 52px que #aimee-messages ya reserva. De colocarla se
   encarga .chat-top-stack, justo debajo: se posiciona contra .chat-area y no
   contra el viewport, así queda centrada sobre la conversación y no se descuadra
   cuando el historial está abierto y empuja el chat a la derecha. */

/* La pila de lo que flota arriba del chat: el indicador de protocolo y, debajo,
   la agenda de la semana. Los dos querían el mismo `top:14px` centrado, y en vez
   de que cada uno mida al otro los coloca la pila. Cuando el protocolo está
   oculto (`display:none`, que es como lo apaga app.js) no aporta altura y la
   agenda queda exactamente donde estaba el banner.

   `left:0; right:0` en vez de centrar la propia pila: así el ancho de referencia
   sigue siendo el de .chat-area, que es contra el que están calculados los
   `max-width` de los hijos. Y no captura el ratón —solo lo hacen ellos—, porque
   una franja invisible de lado a lado del chat se comería los clics en los
   mensajes de debajo. */
#aimee .chat-top-stack {
    position: absolute;
    top: 14px;
    left: 0;
    right: 0;
    z-index: 250;                                  /* por debajo de .sidebar-toggle (300) */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}
#aimee .chat-top-stack > * { pointer-events: auto; }

/* La holgura simétrica tiene que librar a los dos lados: el botón del historial
   llega hasta x=46, y las acciones de la derecha ocupan 12+34*3+6*2 = 126px.
   Manda el lado ancho, así que se reservan 260px repartidos. Es la misma cifra
   que usa .agenda-bar, por la misma razón. */
#aimee .protocol-banner {
    display: flex;
    align-items: center;
    gap: 8px;
    width: max-content;
    max-width: min(460px, calc(100% - 260px));
    padding: 6px 14px;
    border-radius: var(--radius-pill);
    background: var(--surface);
    border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent);
    color: var(--text);
    font-size: var(--text-sm);
    line-height: 1.4;
}

#aimee .protocol-banner strong { font-weight: 500; }

/* Un nombre largo se recorta antes que ensanchar la píldora. */
#aimee .protocol-text {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* El punto late para que se note que hay algo vivo, no un cartel olvidado, y
   es lo único que distingue un estado de otro. */
#aimee .protocol-dot {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    transition: background .25s ease;
}

#aimee .protocol-dot-active { animation: aimee-protocol-pulse 1.8s ease-in-out infinite; }

@keyframes aimee-protocol-pulse {
    0%, 100% { opacity: 1;  box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 45%, transparent); }
    50%      { opacity: .55; box-shadow: 0 0 0 6px transparent; }
}

/* Un protocolo crítico se distingue, pero sin gritar: cambia el acento, nunca
   la legibilidad del texto. El aviso de verdad va en el mensaje. */
#aimee .protocol-banner.is-critical { border-color: color-mix(in oklab, var(--warning) 45%, transparent); }
#aimee .protocol-banner.is-critical .protocol-dot-active {
    background: var(--warning);
    animation-name: aimee-protocol-pulse-alt;
}
@keyframes aimee-protocol-pulse-alt {
    0%, 100% { opacity: 1;  box-shadow: 0 0 0 0 color-mix(in oklab, var(--warning) 45%, transparent); }
    50%      { opacity: .55; box-shadow: 0 0 0 6px transparent; }
}

/* Verde y más rápido: algo acaba de ponerse en marcha. Va después de la regla
   crítica para ganarle: la recarga se ve igual en cualquier protocolo. */
#aimee .protocol-dot-reload {
    background: var(--success);
    animation: aimee-protocol-pulse-go 1.1s ease-in-out infinite;
}
@keyframes aimee-protocol-pulse-go {
    0%, 100% { opacity: 1;  box-shadow: 0 0 0 0 color-mix(in oklab, var(--success) 50%, transparent); }
    50%      { opacity: .55; box-shadow: 0 0 0 7px transparent; }
}

/* En móvil las tres acciones se pliegan en un solo botón, así que la derecha
   pasa a ocupar 46px igual que el botón del historial. Con eso basta la holgura
   de 120px de siempre y la píldora se queda arriba, sin tener que bajarse ni
   robarle sitio a los mensajes. */
@media (max-width: 720px) {
    #aimee .protocol-banner { max-width: calc(100% - 120px); }
}

/* Respeta a quien haya pedido menos movimiento. */
@media (prefers-reduced-motion: reduce) {
    #aimee .protocol-dot-active,
    #aimee .protocol-dot-reload { animation: none; }
}

/* ── Agenda de la semana ─────────────────────────────────────────────────────
   Los próximos siete días en una píldora, con un punto en los que tienen algo
   agendado. Al pulsar un día la píldora crece hacia abajo y enseña qué hay.

   Solo aparece si esta persona tiene algo: una barra permanentemente vacía sería
   un mueble. Quien decide eso es agenda.js poniendo/quitando el `hidden`.
   ────────────────────────────────────────────────────────────────────────── */
#aimee .agenda-bar[hidden] { display: none; }

#aimee .agenda-bar {
    display: flex;
    flex-direction: column;
    width: max-content;
    max-width: min(460px, calc(100% - 260px));     /* misma reserva que el banner */
    border-radius: var(--r-lg);
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    overflow: hidden;
    animation: aimee-slideUpFade .2s ease-out;
}

/* Los siete días. `tablist` y no una lista porque cada día ABRE un panel: es lo
   que un lector de pantalla espera de una pestaña, no de un elemento de lista. */
#aimee .agenda-dias {
    display: flex;
    gap: 2px;
    padding: 5px;
}

#aimee .agenda-dia {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 34px;
    padding: 5px 4px 4px;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: none;
    color: var(--text-dim);
    font-family: inherit;
    font-size: var(--text-xs);
    line-height: 1;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
#aimee .agenda-dia:hover { background: var(--surface-2); color: var(--text); }
#aimee .agenda-dia[aria-expanded="true"] {
    background: var(--surface-2);
    border-color: var(--border-strong);
    color: var(--text);
}

/* La inicial del día. Va en mayúscula desde CSS y no desde JS: `toLocaleDateString`
   devuelve minúscula en unos idiomas y mayúscula en otros, y aquí se quieren las
   siete iguales sin tener que saber en cuál estamos. */
#aimee .agenda-dia-letra { text-transform: uppercase; }

#aimee .agenda-dia-num {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-mid);
}
#aimee .agenda-dia:hover .agenda-dia-num,
#aimee .agenda-dia[aria-expanded="true"] .agenda-dia-num { color: var(--text); }

/* Hoy, marcado por el número y no por el fondo: el fondo ya significa "abierto",
   y dos cosas distintas con la misma señal no se distinguen. */
#aimee .agenda-dia.es-hoy .agenda-dia-num {
    color: var(--accent);
    font-weight: 500;
}

/* El puntico. Es lo único que dice si ese día hay algo, así que ocupa sitio
   siempre —en blanco cuando no hay nada— para que los siete días queden a la
   misma altura y la fila no baile al recargar. */
#aimee .agenda-punto {
    width: 5px;
    height: 5px;
    margin-top: 1px;
    border-radius: 50%;
    background: none;
}
#aimee .agenda-dia.tiene .agenda-punto { background: var(--accent); }

/* ── Plegada ───────────────────────────────────────────────────────────────
   Solo la palabra, arriba del todo. Es el estado de quien no quiere la agenda
   encima de la conversación pero tampoco quiere perderla: sigue estando, ocupa
   una línea de 11px y vuelve entera de un clic. */
#aimee .agenda-bar.es-minima { border-radius: var(--r-pill); }

#aimee .agenda-abrir {
    padding: 3px 12px 4px;
    border: none;
    background: none;
    color: var(--text-mid);
    font-family: inherit;
    font-size: var(--text-xs);
    line-height: 1.5;
    cursor: pointer;
    transition: color .15s;
}
#aimee .agenda-abrir:hover { color: var(--text); }

/* El botón de plegar, al final de la fila de días. Separado por una raya para
   que se lea como "esto no es un día más". */
#aimee .agenda-minimizar {
    display: grid;
    place-items: center;
    width: 22px;
    align-self: stretch;
    margin-left: 2px;
    padding: 0 2px;
    border: none;
    border-left: 1px solid var(--border);
    background: none;
    color: var(--text-dim);
    cursor: pointer;
    transition: color .15s;
}
#aimee .agenda-minimizar svg { width: 13px; height: 13px; }
#aimee .agenda-minimizar:hover { color: var(--text); }

/* ── El día desplegado ─────────────────────────────────────────────────────
   Crece hacia abajo dentro de la misma píldora. Se acota él mismo porque
   .chat-area es `overflow:hidden`: sin tope, un día con quince cosas se saldría
   por debajo del chat y lo que sobra no se vería ni se podría alcanzar. */
#aimee .agenda-panel[hidden] { display: none; }

#aimee .agenda-panel {
    max-height: min(46vh, 320px);
    overflow-y: auto;
    padding: 4px 6px 6px;
    border-top: 1px solid var(--border);
}

#aimee .agenda-vacio {
    padding: 8px 6px;
    color: var(--text-dim);
    font-size: var(--text-xs);
}

#aimee .agenda-tarea {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 6px;
    border-radius: var(--r-sm);
}
#aimee .agenda-tarea + .agenda-tarea { border-top: 1px solid var(--border); }

#aimee .agenda-hora {
    flex: none;
    min-width: 38px;
    padding-top: 1px;
    color: var(--text);
    font-size: var(--text-xs);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* El texto lo redacta el servidor (`summary`), así que aquí puede venir largo.
   Se deja envolver en vez de recortarlo: es la información, no un adorno. */
#aimee .agenda-texto {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--text-mid);
    font-size: var(--text-xs);
    line-height: 1.35;
    overflow-wrap: anywhere;
}

/* Lo periódico se distingue de lo de una vez: si no, cancelar "las 9:00 del
   lunes" parecería quitar solo ese lunes cuando quita la serie entera. */
#aimee .agenda-repite {
    display: block;
    margin-top: 1px;
    color: var(--text-dim);
    font-size: var(--text-xs);
}

#aimee .agenda-cancelar {
    flex: none;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border: 1px solid transparent;
    border-radius: var(--r-xs);
    background: none;
    color: var(--text-dim);
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
/* Un pelín más que la equis que había antes: la papelera tiene tres trazos y a
   12px se emborronaba hasta parecer una mancha. */
#aimee .agenda-cancelar svg { width: 14px; height: 14px; }
#aimee .agenda-cancelar:hover {
    background: var(--danger-soft);
    border-color: var(--danger);
    color: var(--danger);
}
#aimee .agenda-cancelar[disabled] { opacity: .5; cursor: default; }

#aimee .agenda-error {
    margin: 4px 6px 2px;
    color: var(--danger);
    font-size: var(--text-xs);
    line-height: 1.35;
}

/* En móvil las acciones de arriba se pliegan en un botón, así que hace falta
   menos hueco a los lados. Mismo criterio y misma cifra que .protocol-banner. */
@media (max-width: 720px) {
    #aimee .agenda-bar { max-width: calc(100% - 120px); }
    #aimee .agenda-dia { min-width: 30px; padding-left: 2px; padding-right: 2px; }
}

@media (prefers-reduced-motion: reduce) {
    #aimee .agenda-bar { animation: none; }
}

/* ── Mis dispositivos ────────────────────────────────────────────────────────
   El grafo de los aparatos de una persona, dentro del panel de informes. Los
   aparatos son personales —cuelgan del uuid, no del cliente—, y el dibujo dice
   justo eso: tú en el centro y lo tuyo colgando de ti.

   Los colores salen de los tokens semánticos que ya existen. Un aparato callado
   no es un error del sistema sino un aviso —puede ser una batería agotada—, y un
   revocado no es ninguna de las dos cosas: es historia, y se pinta apagado.
   ──────────────────────────────────────────────────────────────────────────── */
#aimee .dv { display: flex; flex-direction: column; gap: 20px; }

#aimee .dv-grafo {
    width: 100%;
    height: auto;
    max-height: 340px;
    overflow: visible;
}

/* ── Zoom del grafo ──
   Los botones van encima del dibujo y no debajo: al acercarte quieres seguir
   mirando el mismo sitio, y una barra fuera obligaría a bajar la vista. */
#aimee .dv-grafo-caja { position: relative; }

#aimee .dv-zoom {
    position: absolute;
    top: 4px;
    right: 4px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
#aimee .dv-zoom-btn {
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border-radius: var(--r-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-mid);
    font-size: var(--text-sm);
    line-height: 1;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
#aimee .dv-zoom-btn:hover { background: var(--surface-2); color: var(--text); }
#aimee .dv-zoom-btn.is-reset { font-size: var(--text-xs); }

/* El cursor es la única pista de que se puede arrastrar, y por eso solo aparece
   cuando de verdad hay algo fuera de cuadro. */
#aimee .dv-grafo.is-movible  { cursor: grab; }
#aimee .dv-grafo.is-moviendo { cursor: grabbing; }
/* Sin esto, arrastrar sobre el SVG selecciona los textos de las etiquetas y el
   gesto se convierte en un subrayado azul. */
#aimee .dv-grafo.is-movible { user-select: none; touch-action: none; }

#aimee .dv-arista {
    stroke: var(--border-strong);
    stroke-width: 1;
}

/* El halo es lo que da el estado a simple vista; el punto se queda del color del
   texto para que el grafo no parezca un semáforo. */
#aimee .dv-nodo .dv-halo,
#aimee .dv-centro .dv-halo { fill: var(--surface-2); }
#aimee .dv-nodo .dv-punto  { fill: var(--text-mid); }

#aimee .dv-nodo.is-activo   .dv-halo  { fill: color-mix(in srgb, var(--success) 26%, transparent); }
#aimee .dv-nodo.is-activo   .dv-punto { fill: var(--success); }
#aimee .dv-nodo.is-callado  .dv-halo  { fill: color-mix(in srgb, var(--warning) 26%, transparent); }
#aimee .dv-nodo.is-callado  .dv-punto { fill: var(--warning); }
#aimee .dv-nodo.is-revocado .dv-halo  { fill: transparent; }
#aimee .dv-nodo.is-revocado .dv-punto { fill: var(--text-dim); opacity: .5; }

#aimee .dv-centro .dv-punto { fill: var(--ink); }
#aimee .dv-yo {
    fill: var(--on-ink);
    font-size: var(--text-xs);
    font-weight: 500;
    text-anchor: middle;
}

/* ── La órbita de fuera: lo que es de la organización ──
   Sin línea al centro y con el punto más pequeño que el de un aparato: no cuelga
   de esta persona y no es suyo. La circunferencia de guía va muy tenue, solo para
   que se lea como un anillo y no como puntos sueltos. */
#aimee .dv-orbita {
    fill: none;
    stroke: var(--border);
    stroke-width: 1;
    stroke-dasharray: 2 6;
    opacity: .7;
}
#aimee .dv-cap.is-own      .dv-punto { fill: var(--cap-own); }
#aimee .dv-cap.is-protocol .dv-punto { fill: var(--cap-protocol); }
#aimee .dv-cap.is-igniter  .dv-punto { fill: var(--cap-igniter); }

/* El nombre va SIEMPRE escrito bajo el punto, y no es un adorno: el color solo no
   puede ser lo único que diga qué es cada cosa. */
#aimee .dv-cap-etiqueta {
    fill: var(--text-dim);
    font-size: var(--text-xs);
    font-weight: 500;
    text-anchor: middle;
}

#aimee .dv-etiqueta {
    fill: var(--text);
    font-size: var(--text-xs);
    font-weight: 500;
    text-anchor: middle;
}
#aimee .dv-visto {
    fill: var(--text-dim);
    font-size: var(--text-xs);
    text-anchor: middle;
}

/* ── Resumen y lista ── */
#aimee .dv-resumen { display: flex; flex-wrap: wrap; gap: 8px; }
#aimee .dv-chip {
    padding: 5px 12px;
    border-radius: var(--r-pill);
    background: var(--surface);
    border: 1px solid var(--border);
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-mid);
}
#aimee .dv-chip.is-activo   { color: var(--success); border-color: color-mix(in srgb, var(--success) 40%, transparent); }
#aimee .dv-chip.is-callado  { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 40%, transparent); }
#aimee .dv-chip.is-revocado { color: var(--text-dim); }

/* La leyenda de las capacidades. El punto de color delante repite exactamente el
   del grafo, que es lo que convierte la lista en una leyenda y no en tres chips
   más de colores. */
#aimee .dv-resumen.is-capacidades { margin-top: -2px; }
#aimee .dv-chip-cap { display: inline-flex; align-items: center; gap: 7px; }
#aimee .dv-chip-cap::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
#aimee .dv-chip-cap.is-own      { color: var(--cap-own);      border-color: color-mix(in srgb, var(--cap-own) 40%, transparent); }
#aimee .dv-chip-cap.is-protocol { color: var(--cap-protocol); border-color: color-mix(in srgb, var(--cap-protocol) 40%, transparent); }
#aimee .dv-chip-cap.is-igniter  { color: var(--cap-igniter);  border-color: color-mix(in srgb, var(--cap-igniter) 40%, transparent); }

#aimee .dv-lista { list-style: none; display: flex; flex-direction: column; }
#aimee .dv-fila { border-bottom: 1px solid var(--border); }
#aimee .dv-fila:last-child { border-bottom: none; }

/* La fila entera es el botón que abre el detalle: el objetivo de pulsación es
   toda la línea y no un icono de 16px, que en un móvil se falla. */
#aimee .dv-cabecera {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 0;
    background: none;
    border: none;
    font: inherit;
    font-size: var(--text-sm);
    color: inherit;
    text-align: left;
    cursor: pointer;
    /* El nombre manda y lo demás cede: un id largo no debe empujar la hora fuera */
    min-width: 0;
}
#aimee .dv-cabecera:hover .dv-nombre { color: var(--accent); }

#aimee .dv-flecha {
    width: 14px; height: 14px;
    flex-shrink: 0;
    color: var(--text-dim);
    transition: transform .18s ease;
}
#aimee .dv-fila.is-abierto .dv-flecha { transform: rotate(180deg); }

/* ── El detalle ──
   Lo que el aparato cuenta de sí mismo. Sangrado a la altura del nombre para que
   se lea como algo que cuelga de esa fila y no como una fila más. */
#aimee .dv-detalle {
    padding: 2px 0 16px 18px;
    animation: aimee-dvAbre .18s ease;
}
@keyframes aimee-dvAbre { from { opacity: 0; transform: translateY(-4px); } }

#aimee .dv-bloque-tit {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
    margin-bottom: 6px;
}

#aimee .dv-pares {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px;
    background: var(--surface);
    border-radius: var(--r-sm);
    margin-bottom: 8px;
}

/* La lectura es a lo que se viene: se separa del contexto con un filete de
   acento en vez de con más caja, que aquí sobraría. */
#aimee .dv-pares.is-lectura {
    border-left: 2px solid var(--accent);
    background: var(--surface-2);
}
#aimee .dv-pares.is-lectura dd { font-weight: 500; }
#aimee .dv-par {
    display: flex;
    gap: 12px;
    align-items: baseline;
    font-size: var(--text-xs);
}
#aimee .dv-par dt {
    color: var(--text-dim);
    flex-shrink: 0;
    min-width: 92px;
    /* Las claves las pone quien aprovisiona: pueden venir en cualquier idioma y
       con cualquier longitud, así que se dejan partir en vez de empujar el valor. */
    overflow-wrap: anywhere;
}
#aimee .dv-par dd {
    color: var(--text);
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
    /* Un objeto anidado llega con saltos de línea desde el JSON: se respetan. */
    white-space: pre-wrap;
    font-variant-numeric: tabular-nums;
}

#aimee .dv-sin-datos {
    font-size: var(--text-xs);
    color: var(--text-dim);
    padding: 10px 14px;
    background: var(--surface);
    border-radius: var(--r-sm);
}
/* Las variaciones: una gráfica por indicador, apiladas. Misma caja que el resto
   del detalle para que no parezcan un widget pegado de otro sitio. */
#aimee .dv-graficas {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 6px;
    background: var(--surface);
    border-radius: var(--r-sm);
    margin-bottom: 8px;
}
/* Alto fijo: lo pone también Highcharts al crearla, y aquí para que el hueco esté
   reservado antes de dibujar y la lista no dé un salto al terminar la petición. */
#aimee .dv-grafica { height: 190px; }

#aimee .dv-graficas .dv-sin-datos { background: none; padding: 6px 8px; }

#aimee .dv-id {
    margin-top: 8px;
    font-size: var(--text-xs);
    font-family: var(--font-mono);
    color: var(--text-dim);
    overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
    #aimee .dv-detalle { animation: none; }
    #aimee .dv-flecha { transition: none; }
}

#aimee .dv-bolita {
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--text-dim);
    flex-shrink: 0;
}
#aimee .dv-fila.is-activo   .dv-bolita { background: var(--success); }
#aimee .dv-fila.is-callado  .dv-bolita { background: var(--warning); }
#aimee .dv-fila.is-revocado .dv-bolita { background: var(--text-dim); opacity: .5; }

#aimee .dv-nombre {
    color: var(--text);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
#aimee .dv-tipo {
    color: var(--text-dim);
    font-size: var(--text-xs);
    white-space: nowrap;
}
#aimee .dv-cuando {
    margin-left: auto;
    color: var(--text-mid);
    font-size: var(--text-xs);
    white-space: nowrap;
    flex-shrink: 0;
}

#aimee .dv-fila.is-revocado .dv-nombre { text-decoration: line-through; color: var(--text-dim); }

/* ── Estados ── */
#aimee .dv-cargando,
#aimee .dv-vacio {
    padding: 40px 20px;
    text-align: center;
    color: var(--text-mid);
    font-size: var(--text-sm);
}
#aimee .dv-vacio-sub {
    margin-top: 8px;
    font-size: var(--text-xs);
    color: var(--text-dim);
}

/* ── Emparejar un aparato nuevo ──────────────────────────────────────────────
   El botón se gasta: al pulsarlo se convierte en el código. Por eso no hay
   estado "ya pedido" con el botón todavía a la vista — sería una invitación a
   pedir otro, y pedir otro invalida el anterior.
   ──────────────────────────────────────────────────────────────────────────── */
#aimee .dv-emparejar {
    margin-top: 24px;
    padding: 18px;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    text-align: center;
}

#aimee .dv-boton-codigo {
    padding: 10px 20px;
    border-radius: var(--r-pill);
    border: 1px solid transparent;
    background: var(--ink);
    color: var(--on-ink);
    font-family: inherit;
    font-size: var(--text-sm);
    font-weight: 500;
    cursor: pointer;
    transition: opacity .15s;
}
#aimee .dv-boton-codigo:hover:not(:disabled) { opacity: .84; }
#aimee .dv-boton-codigo:disabled {
    background: var(--surface-2);
    color: var(--text-dim);
    cursor: default;
}

#aimee .dv-codigo-tit {
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--text-dim);
    margin-bottom: 8px;
}
/* El código se teclea en otro aparato mirando esta pantalla: grande, en
   monoespaciada y separado, para no confundir un 0 con una O. */
#aimee .dv-codigo {
    font-family: var(--font-mono);
    font-size: var(--text-2xl);
    font-weight: 500;
    letter-spacing: .12em;
    color: var(--text);
    user-select: all;
}

#aimee .dv-emparejar-pie {
    margin-top: 10px;
    font-size: var(--text-xs);
    color: var(--text-dim);
}
#aimee .dv-emparejar-error {
    margin-top: 10px;
    font-size: var(--text-xs);
    color: var(--danger);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Facturas (fc-*) — la zona de arrastre y la tarjeta de una factura leída

   Dos bloques con destinos distintos:

     .fc-drop, .fc-esperando   viven en el chat, los pinta invoice.js
     .fc-card y lo de dentro   viven en el panel lateral, y el HTML lo manda el
                               backend (skills/domains/invoice/card.html). Por eso
                               los colores tienen que estar AQUÍ y no allí: el
                               frontend borra cualquier \3c style> que llegue en un
                               mensaje (sanitizeHtml, app.js:1907), y además así la
                               tarjeta funciona en tema claro y oscuro sin tocar
                               nada.

   Sin `text-shadow` en ningún sitio. El contraste lo dan el color y el fondo.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── La zona de arrastre ─────────────────────────────────────────────────── */

#aimee .fc-drop {
    position: absolute;
    inset: 0;
    z-index: 40;
    display: none;
    place-items: center;
    padding: 24px;
    /* El desenfoque es lo que hace legible el recuadro sobre lo que haya debajo
       —una conversación llena de texto o la foto de la bienvenida—, igual que en
       el resto del cristal de la aplicación. */
    background: var(--surface-raised);
}
#aimee .fc-drop.is-activa { display: grid; }

#aimee .fc-drop-caja {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 32px 40px;
    text-align: center;
    color: var(--accent);
    border: 2px dashed var(--accent);
    border-radius: var(--r-lg);
    /* Un pelo de fondo propio: sobre una foto clara el discontinuo solo se
       pierde. */
    background: var(--surface-raised);
}
#aimee .fc-drop-caja svg { width: 40px; height: 40px; }
#aimee .fc-drop-titulo { font-size: var(--text-lg); font-weight: 500; color: var(--text); }
#aimee .fc-drop-sub    { font-size: var(--text-sm); color: var(--text-dim); }

/* ── La espera ───────────────────────────────────────────────────────────── */
/* Tres puntos y no una barra de progreso: el servicio no manda progreso, así que
   una barra tendría que ser inventada, y una barra inventada que se queda a
   medias miente peor que un punto que late. */
#aimee .fc-puntos { display: inline-flex; gap: 3px; margin-left: 6px; }
#aimee .fc-puntos i {
    width: 4px; height: 4px;
    border-radius: 50%;
    background: currentColor;
    opacity: .35;
    animation: aimee-fc-latido 1.4s infinite;
}
#aimee .fc-puntos i:nth-child(2) { animation-delay: .2s; }
#aimee .fc-puntos i:nth-child(3) { animation-delay: .4s; }
@keyframes aimee-fc-latido {
    0%, 60%, 100% { opacity: .25; }
    30%           { opacity: .9; }
}
/* Quien haya pedido menos movimiento no lo quiere aquí tampoco, y la espera son
   minutos: tres puntos latiendo todo ese rato es mucho parpadeo. */
@media (prefers-reduced-motion: reduce) {
    #aimee .fc-puntos i { animation: none; opacity: .5; }
}

/* ── La tarjeta del panel ────────────────────────────────────────────────── */

#aimee .fc-card { display: flex; flex-direction: column; gap: 14px; }

#aimee .fc-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
#aimee .fc-head-main { min-width: 0; flex: 1 1 240px; }
#aimee .fc-head-side { text-align: right; min-width: 0; }
#aimee .fc-eyebrow { font-size: var(--text-xs); color: var(--text-dim); }
#aimee .fc-title {
    font-size: var(--text-xl);
    font-weight: 500;
    /* Un número de factura no tiene espacios donde partir, y lo ha leído un OCR:
       puede venir más largo de lo razonable. */
    overflow-wrap: anywhere;
}
#aimee .fc-fecha { font-size: var(--text-base); font-weight: 500; }
#aimee .fc-label { font-size: var(--text-xs); color: var(--text-dim); }

/* La nota de fiabilidad. Pequeña y en gris a propósito: acompaña al dato sin
   competir con él, porque va en TODAS las facturas y una nota permanente que
   grite deja de leerse a la tercera. */
#aimee .fc-nota {
    font-size: var(--text-xs);
    line-height: 1.45;
    color: var(--text-dim);
    margin-top: 4px;
}

/* ── El aviso fuerte: solo cuando las cifras no cuadran ──────────────────── */
/* Este SÍ tiene permiso para llamar la atención: sale en el 11 % de los casos, no
   en todos, y eso es lo que le deja seguir significando algo. */
#aimee .fc-aviso {
    padding: 12px 14px;
    border-radius: var(--r-sm);
    background: var(--danger-soft);
    border: 1px solid var(--danger);
}
#aimee .fc-aviso-titulo {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--danger);
    margin-bottom: 2px;
}
#aimee .fc-aviso-cuerpo { font-size: var(--text-sm); line-height: 1.5; }

/* El de las líneas, en cambio, es una nota: en escaneos densos salta casi
   siempre, y con el tono del aviso de arriba sería ruido constante. */
#aimee .fc-aviso-suave {
    font-size: var(--text-xs);
    line-height: 1.45;
    color: var(--warning);
    margin-bottom: 8px;
}

/* ── Cifras y bloques ───────────────────────────────────────────────────── */

#aimee .fc-row { display: grid; gap: 10px; min-width: 0; }
#aimee .fc-row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#aimee .fc-row-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

#aimee .fc-cifra, #aimee .fc-bloque {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 14px;
    min-width: 0;
}
/* Una sola cifra destacada: el total. Es la que se acierta el 90 % de las veces y
   la que se viene a mirar. Con dos destacadas ya no hay destacada. */
#aimee .fc-cifra-fuerte {
    background: var(--accent-subtle);
    border-color: transparent;
}
#aimee .fc-cifra-fuerte .fc-big   { color: var(--accent-strong); }

#aimee .fc-big { font-size: var(--text-xl); font-weight: 500; overflow-wrap: anywhere; }
#aimee .fc-med { font-size: var(--text-lg); font-weight: 550; overflow-wrap: anywhere; }

#aimee .fc-nombre {
    font-size: var(--text-sm);
    font-weight: 550;
    margin-top: 2px;
    overflow-wrap: anywhere;
}
#aimee .fc-dato {
    font-size: var(--text-xs);
    color: var(--text-dim);
    margin-top: 2px;
    overflow-wrap: anywhere;
}

/* Lo que el servicio no pudo leer. En gris y en cursiva para que se vea de un
   golpe que NO es un dato: la frase ya lo dice, pero la forma lo dice antes. */
#aimee .fc-nulo {
    font-style: italic;
    color: var(--text-dim);
    font-weight: 400;
}

/* ── Las líneas de detalle ──────────────────────────────────────────────── */

#aimee .fc-lineas { display: flex; flex-direction: column; }
#aimee .fc-linea {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 52px minmax(0, 84px) minmax(0, 92px);
    gap: 8px;
    padding: 8px 0;
    border-top: 1px solid var(--border);
    font-size: var(--text-sm);
    align-items: baseline;
}
#aimee .fc-linea-cab {
    border-top: none;
    font-size: var(--text-xs);
    color: var(--text-dim);
}
#aimee .fc-linea-desc  { min-width: 0; overflow-wrap: anywhere; }
#aimee .fc-linea-cant,
#aimee .fc-linea-precio,
#aimee .fc-linea-total { text-align: right; font-variant-numeric: tabular-nums; }
#aimee .fc-linea-total { font-weight: 550; }

/* La fila cuyo cantidad x precio no da su importe. Un borde lateral y nada más:
   marca sin gritar, porque puede haber quince marcadas en un tiquet térmico. */
#aimee .fc-linea-ojo {
    border-left: 2px solid var(--warning);
    padding-left: 8px;
}
#aimee .fc-marca {
    display: block;
    font-size: var(--text-xs);
    color: var(--warning);
    margin-top: 2px;
}

/* ── El pie ─────────────────────────────────────────────────────────────── */
/* La referencia del servicio vive aquí. Discreta pero SIEMPRE presente: es la
   única llave a los logs de NX01 Vision, y sin ella un "esto está mal" de la
   semana que viene no se puede diagnosticar. Seleccionable, que es justo lo que
   se hace con ella: copiarla. */
#aimee .fc-pie {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    font-size: var(--text-xs);
    color: var(--text-dim);
    border-top: 1px solid var(--border);
    padding-top: 10px;
}
#aimee .fc-pie-dato { user-select: all; overflow-wrap: anywhere; }

/* En móvil el panel es la pantalla entera y cuatro columnas no caben: las cifras
   pasan a una sola columna y la tabla suelta la de precio unitario, que es la
   menos fiable de las cuatro y por tanto la que menos se echa de menos. */
@media (max-width: 640px) {
    #aimee .fc-row-3, #aimee .fc-row-2 { grid-template-columns: minmax(0, 1fr); }
    #aimee .fc-linea { grid-template-columns: minmax(0, 1fr) 44px minmax(0, 84px); }
    #aimee .fc-linea-precio { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Maxipoderes (ig-*) — el círculo que cuenta hacia la próxima comprobación

   Mientras un igniter está en marcha, su mensaje lleva arriba a la derecha un
   círculo de 10×10 que se vacía. No es un "cargando" genérico: mide algo real,
   cuánto falta para que Aimee vuelva a mirar el log, y por eso su duración la
   manda el backend en `watcher_cada` (ver assets/js/ignition.js). Un indicador
   que gira a un ritmo inventado dice menos que no poner ninguno.

   Cuando llega [END] el círculo desaparece y el mensaje se queda como esté.

   Sin `text-shadow` en ningún sitio.
   ═══════════════════════════════════════════════════════════════════════════ */

/* La burbuja pasa a ser el marco del círculo. `relative` solo mientras vigila:
   así no se toca el posicionamiento de todas las demás burbujas del chat. */
#aimee .msg.ig-vigilando .bubble {
    position: relative;
    /* Sitio para el círculo, para que no se monte sobre la primera línea. */
    padding-right: 26px;
}

#aimee .ig-reloj {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 10px;
    height: 10px;
    display: block;
    /* Encima del texto, y sin capturar el ratón: es información, no un botón. */
    pointer-events: none;
}
#aimee .ig-reloj svg {
    width: 100%;
    height: 100%;
    /* El trazo de un SVG empieza a las 3 en punto; se gira para que empiece
       arriba, que es por donde una persona espera que arranque una cuenta. */
    transform: rotate(-90deg);
}

/* Blanco, no del color de acento: el círculo va DENTRO de la burbuja de Aimee, y
   ahí el azul se pierde contra el fondo. El blanco se lee sobre cualquiera de los
   dos temas y sobre la foto. */
#aimee .ig-reloj-fondo {
    fill: none;
    stroke: rgba(255, 255, 255, .25);
    stroke-width: 3;
}

#aimee .ig-reloj-aguja {
    fill: none;
    stroke: #FFFFFF;
    stroke-width: 3;
    stroke-linecap: round;
    /* El perímetro (2·π·8 ≈ 50.27) lo pone el JS en stroke-dasharray, porque el
       CSS no puede calcularlo. Aquí solo se anima el hueco.

       El DESFASE NEGATIVO es lo que hace que recargar la página no mienta: el JS
       calcula cuánto falta de verdad para la próxima comprobación y arranca la
       animación por ahí, en vez de empezarla de cero en cada recarga. */
    animation: aimee-ig-vaciar var(--ig-ciclo, 60s) linear infinite;
    animation-delay: var(--ig-desfase, 0s);
}

@keyframes aimee-ig-vaciar {
    from { stroke-dashoffset: 0; }
    to   { stroke-dashoffset: 50.27; }
}

/* Quien pidió menos movimiento no quiere un círculo girando durante minutos. Se
   queda a medias y quieto: sigue diciendo "esto está en marcha", que es lo que
   importa, sin animación. */
@media (prefers-reduced-motion: reduce) {
    #aimee .ig-reloj-aguja {
        animation: none;
        stroke-dashoffset: 25;
    }
}

/* ── La agenda de Aimee («muéstrame tu agenda», work_queue/consultar.py:_calendario) ─────────────────────
   El week-calendar de Arc (Pro) reducido a lo que se pide: hoy y los días siguientes en columnas, con la
   cabecera de Arc (día de la semana y número; hoy, en la píldora del acento) y un punto por tarea, en el
   orden de la hora. Al señalar un punto, o al tocarlo (foco), su ficha flota encima, como el popover de
   Arc. Los colores de los estados son los de la pantalla de la cola (work-queue.css); la cancelada, un
   aro vacío. Prefijo `su-agenda`: `.agenda-*` es la barra de agenda de agenda.js. Todo en CSS: el bloque llega como HTML del servidor y el chat no le engancha eventos. */
#aimee .msg.assistant > div:has(.su-agenda) { max-width: none; }
#aimee .su-agenda {
    --ag-blocked: var(--danger); --ag-waiting: #f48120; --ag-scheduled: #f3ad20;
    --ag-completed: var(--success); --ag-executing: var(--accent); --ag-neutral: var(--text-muted);
    display: grid; gap: var(--space-3);
}
#aimee[data-theme="dark"] .su-agenda { --ag-waiting: #ff9d50; --ag-scheduled: #ffcb62; }
#aimee .su-agenda [data-estado] { --ag: var(--ag-neutral); }
#aimee .su-agenda [data-estado="BLOCKED"], #aimee .su-agenda [data-estado="FAILED"] { --ag: var(--ag-blocked); }
#aimee .su-agenda [data-estado="WAITING_HUMAN"] { --ag: var(--ag-waiting); }
#aimee .su-agenda [data-estado="SCHEDULED"] { --ag: var(--ag-scheduled); }
#aimee .su-agenda [data-estado="COMPLETED"] { --ag: var(--ag-completed); }
#aimee .su-agenda [data-estado="EXECUTING"] { --ag: var(--ag-executing); }

#aimee .su-agenda-dias {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    border: 1px solid var(--border); border-radius: var(--radius-panel);
    /* `--surface-raised`: en Aimee `--surface` es el gris de los hovers; el blanco de Arc es este. */
    background: var(--surface-raised);
}
#aimee .su-agenda-dia { min-width: 0; display: flex; flex-direction: column; }
#aimee .su-agenda-dia + .su-agenda-dia { border-left: 1px solid var(--border-subtle); }
#aimee .su-agenda-cabeza {
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: var(--space-3) 0 var(--space-2); color: var(--text-secondary);
}
#aimee .su-agenda-semana { font-size: var(--text-xs); line-height: 1.2; }
#aimee .su-agenda-fecha {
    display: inline-grid; place-items: center; min-width: 32px; height: 32px; padding-inline: 6px;
    border-radius: var(--radius-pill); color: var(--foreground);
    font-size: var(--text-lg); font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums;
}
#aimee .su-agenda-dia[data-hoy] .su-agenda-cabeza { color: var(--foreground); }
#aimee .su-agenda-dia[data-hoy] .su-agenda-fecha { background: var(--accent); color: var(--accent-foreground); }
#aimee .su-agenda-puntos {
    flex: 1; display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start; gap: 8px;
    min-height: 56px; padding: var(--space-3) var(--space-3) var(--space-4);
    border-top: 1px solid var(--border-subtle);
}
#aimee .su-agenda-punto {
    position: relative; flex: none; width: 12px; height: 12px; border-radius: 50%;
    background: var(--ag); outline: none; cursor: default;
    transition: box-shadow var(--duration-fast) var(--ease-standard);
}
/* Más área que el punto, para el dedo. */
#aimee .su-agenda-punto::before { content: ""; position: absolute; inset: -6px; }
#aimee .su-agenda-punto[data-estado="CANCELLED"] { background: transparent; box-shadow: inset 0 0 0 1.5px var(--ag); }
#aimee .su-agenda-punto:hover, #aimee .su-agenda-punto:focus { box-shadow: 0 0 0 4px color-mix(in oklab, var(--ag) 24%, transparent); }
#aimee .su-agenda-punto[data-estado="CANCELLED"]:hover, #aimee .su-agenda-punto[data-estado="CANCELLED"]:focus {
    box-shadow: inset 0 0 0 1.5px var(--ag), 0 0 0 4px color-mix(in oklab, var(--ag) 24%, transparent);
}
#aimee .su-agenda-punto:focus-visible { box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 4px var(--accent); }

/* La ficha: el popover de Arc (superficie elevada, borde, radio y la sombra de lo que flota). Las dos
   primeras columnas la abren hacia la derecha y las dos últimas hacia la izquierda, para que no se salga
   del hilo. */
#aimee .su-agenda-info {
    --ag-x: -50%;
    position: absolute; bottom: calc(100% + 10px); left: 50%; z-index: 30;
    display: grid; gap: 2px; width: max-content; max-width: 220px;
    padding: 10px 12px; border: 1px solid var(--border); border-radius: 14px;
    background: var(--surface-raised); box-shadow: var(--shadow-floating);
    color: var(--text-secondary); font-size: var(--text-xs); line-height: 1.4; text-align: left;
    font-variant-numeric: tabular-nums; white-space: normal; overflow-wrap: break-word;
    opacity: 0; visibility: hidden; pointer-events: none; transform: translate(var(--ag-x), 4px);
    transition: opacity var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard),
                visibility 0s linear var(--duration-fast);
}
#aimee .su-agenda-dia:nth-child(-n+2) .su-agenda-info { left: -8px; --ag-x: 0%; }
#aimee .su-agenda-dia:nth-child(n+4) .su-agenda-info { left: auto; right: -8px; --ag-x: 0%; }
#aimee .su-agenda-punto:hover > .su-agenda-info, #aimee .su-agenda-punto:focus > .su-agenda-info {
    opacity: 1; visibility: visible; transform: translate(var(--ag-x), 0); transition-delay: 0s;
}
#aimee .su-agenda-info-titulo { margin-bottom: 2px; color: var(--foreground); font-size: var(--text-sm); font-weight: 500; }
#aimee .su-agenda-info-objetivo { color: var(--text-muted); }
#aimee .su-agenda-info-estado, #aimee .su-agenda-clave { display: inline-flex; align-items: center; gap: 6px; }
#aimee .su-agenda-info-estado::before, #aimee .su-agenda-clave::before {
    content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ag);
}
#aimee .su-agenda-info-estado[data-estado="CANCELLED"]::before, #aimee .su-agenda-clave[data-estado="CANCELLED"]::before {
    background: transparent; box-shadow: inset 0 0 0 1.5px var(--ag);
}
#aimee .su-agenda-leyenda { display: flex; flex-wrap: wrap; gap: 4px 14px; padding-inline: 2px; color: var(--text-secondary); font-size: var(--text-xs); }

/* Chips de siguiente paso (talk/siguientes.py): botones planos sobre un borde; el acento, solo al señalar o con teclado. */
#aimee .aimee-siguientes { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
#aimee .aimee-siguiente {
    padding: 4px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--background);
    color: var(--text-secondary);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: 400;
    line-height: 1.4;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s, color .15s;
}
#aimee .aimee-siguiente:hover { border-color: var(--accent); color: var(--foreground); }
#aimee .aimee-siguiente:focus { outline: none; }
#aimee .aimee-siguiente:focus-visible { color: var(--foreground); box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 4px var(--accent); }

/* Acciones de una respuesta, como el chat de Arc (blocks/ai-chat): copiar, reintentar, 👍 y 👎. Botones de 30 px,
   radio 10 px, en gris apagado; al señalar, la superficie muda. Se ven en la última respuesta y, en las demás, al
   pasar por encima o con el foco; en táctil, siempre. El reintento, solo en la última pregunta. */
#aimee .msg.assistant .msg-actions { gap: 0; height: 30px; align-items: center; margin: 2px 0 0 -6px; padding-left: 0;
    opacity: 0; transition: opacity var(--duration-fast, .15s) var(--ease-standard, ease); }
#aimee .msg.assistant:hover .msg-actions,
#aimee .msg.assistant:focus-within .msg-actions,
#aimee .msg.assistant:not(:has(~ .msg.user)) .msg-actions { opacity: 1; }
@media (hover: none) { #aimee .msg.assistant .msg-actions { opacity: 1; } }
#aimee .msg.assistant:has(~ .msg.user) .aimee-accion[data-accion="reintentar"] { display: none; }
#aimee .msg.assistant.progress-message .msg-actions { visibility: hidden; }
#aimee .aimee-accion { width: 30px; height: 30px; border-radius: 10px; color: var(--text-muted);
    transition: background-color var(--duration-fast, .15s) var(--ease-standard, ease),
                color var(--duration-fast, .15s) var(--ease-standard, ease), transform .1s ease; }
@media (hover: hover) and (pointer: fine) {
    #aimee .aimee-accion:hover { background: var(--surface-muted); color: var(--foreground); }
}
#aimee .aimee-accion:active { transform: scale(.96); }
#aimee .aimee-accion:focus { outline: none; }
#aimee .aimee-accion:focus-visible { box-shadow: 0 0 0 2px var(--surface-raised), 0 0 0 4px var(--accent); }
#aimee .aimee-accion[aria-pressed="true"] { color: var(--foreground); }
#aimee .aimee-accion[aria-pressed="true"] svg { fill: currentColor; }
#aimee .aimee-accion[data-estado="copiado"] { color: var(--success); }
#aimee .aimee-accion[data-estado="error"] { color: var(--danger); }
@media (prefers-reduced-motion: reduce) { #aimee .aimee-accion { transition: none; } #aimee .aimee-accion:active { transform: none; } }

/* «Pensó durante 2 s», encima de la respuesta (el «Thought for 2s» de Arc). */
#aimee .aimee-pensado { display: flex; min-height: 28px; align-items: center; color: var(--text-secondary);
    font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
