﻿/* ===================================================================================================
   assets/css/assistant-ia.css — LE CHAT de l'assistant IA (dock du panneau + fenêtre agrandie)

   Ce fichier porte TOUT l'habillage du chat. Avant lui, le composant était habillé à deux endroits —
   `assets/css/assistantia.css` et un bloc de 137 lignes de `assets/css/Dashboard/dashboard-onglets.css` —
   d'où des règles qui se cherchaient, et un commentaire dans ce dernier expliquant qu'une règle avait
   dû déménager parce que le chat sortait de son scope en plein écran.

   REGLE DE PARTAGE, à tenir :
     - `dashboard-onglets.css` ne dit QUE la place du dock dans la chaîne flex du panneau ;
     - sa hauteur, son intérieur et son habillage vivent ICI ;
     - `assistant-bulle.css` ne porte QUE la bulle flottante (position, couche 1030, glisser-déposer).

   🛑 A DECLARER A TROIS ENDROITS, et le JS à deux seulement :
        Views/Shared/_Layout.cshtml            (tous les écrans)
        Views/Dashboard/Index.cshtml           (le dashboard a son propre layout, qui ne mentionne
                                                jamais l'assistant : oublier ce site laisse le dock nu
                                                sur le dashboard)
        Views/Shared/Assistant/_PanneauAssistant.cshtml, bloc `@if (overlay)`
                                               (hors dashboard, aucune feuille du panneau n'est dans
                                                le head ; panneau-assistant.js les y déplace après
                                                injection)
      Oublier la ligne du bloc `overlay` donne un dock nu HORS DASHBOARD UNIQUEMENT — le défaut
      classique de ce partial, et il ne se signale pas.

   Aucun `!important`, aucune règle globale, aucun `z-index` près de `.modal` (un test l'interdit).
   =================================================================================================== */


/* ---------------------------------------------------------------------------------------------------
   1. JETONS

   🛑 Les couleurs d'IDENTITE viennent du THEME, les couleurs d'ETAT sont LITTERALES. Ce n'est pas une
   incohérence, c'est la seule règle qui tienne :

     - Le thème par défaut porte `--bs-primary: #2e3862` et `--bs-main: #ff6136`, à quelques unités du
       navy et de l'orange de la maquette Ingeneo. L'écart est imperceptible, et le chat suit alors la
       personnalisation de l'abonné — ce que la norme front exige.

     - Pour les états, c'est l'inverse. Dans ce même thème, `--bs-warning-bg-subtle` (#ffe6df) et
       `--bs-danger-bg-subtle` (#ffcfd5) sont DEUX ROSES QUASI INDISCERNABLES, et chaque abonné peut
       avoir son propre couple. Habiller « hors périmètre » avec le jeton « warning » du thème
       reproduirait donc EXACTEMENT le défaut que cette refonte corrige : un encadré rose qu'on ne
       distingue pas d'une erreur. L'ambre, le rouge d'échec et le vert « en ligne » sont donc écrits
       ici, en dur, et c'est une exception assumée à la règle « aucune couleur en dur ».

   ⚠️ CONTRASTE AA : trois couleurs de la maquette échouent sur fond blanc et ne sont pas reprises
   telles quelles — `#A2AAC0` (2,30:1) et `#8A93AD` (3,06:1) pour le texte, blanc sur `#EE5A24`
   (3,43:1) pour le chiffre du badge. L'horodatage et la ligne d'aide prennent donc `#5B6480`
   (5,83:1) ; `#8A93AD` ne sert plus qu'au PLACEHOLDER, que WCAG exempte ; et le chiffre du badge est
   rendu décoratif (aria-hidden) avec le compte repris en visually-hidden.

   Un bloc `:root` serait une règle globale, interdite : les jetons sont portés par les trois racines
   du composant, ce qui les déclare une seule fois sans rien laisser fuir.
   --------------------------------------------------------------------------------------------------- */
.ia-dock,
.ia-fenetre,
/* 🛑 `.ia-historique` DOIT figurer ici : la fenêtre d'historique est relogée sous `<body>` (le dock et le
   panneau portent un `overflow: hidden` qui la découperait), elle n'est donc descendante ni du dock ni de
   la fenêtre agrandie. Sans cette ligne, tous les jetons ci-dessous y seraient indéfinis et son contenu
   sortirait sans couleurs — silencieusement, puisqu'une variable absente ne produit aucune erreur. */
.ia-historique,
.ia-bulle-badge {
    --ia-navy: var(--bs-primary, #2B3566);
    --ia-navy-rgb: var(--bs-primary-rgb, 43, 53, 102);
    --ia-accent: var(--bs-main, #EE5A24);

    --ia-tint: #EEF1FA;
    --ia-fond-fil: #F8F9FC;
    --ia-bord: #E6E9F2;
    --ia-bord-fort: #CFD5E6;

    --ia-texte: #1c2138;
    --ia-texte-2: #5B6480;
    --ia-placeholder: #8A93AD;

    --ia-ambre-fond: #FDF6E7;
    --ia-ambre-bord: #F2E3BD;
    --ia-ambre-texte: #6B5518;

    --ia-erreur: #C0392B;
    --ia-erreur-bord: #F0B7AE;
    --ia-en-ligne: #1F9D55;
    --ia-hors-ligne: #98A0B8;

    --ia-r-sm: 7px;
    --ia-r-md: 9px;
    --ia-r-lg: 12px;
}


/* ---------------------------------------------------------------------------------------------------
   2. LE DOCK — géométrie

   🛑 `flex: 0 0 auto` et une `height` explicite, et surtout PAS de `max-height` en pourcentage.
   L'ancienne bande était en `flex: 0 1 auto; min-height: 120px; max-height: 55%`, ce qui produisait
   deux défauts muets dès qu'on veut une hauteur réglée par l'utilisateur :
     - le plancher de 120 px empêchait le dock replié de descendre à 52 px (on cherche un padding) ;
     - le plafond de 55 % rognait SILENCIEUSEMENT la hauteur relue du stockage, d'où une restitution
       « qui marche une fois sur deux » — elle marche sous le seuil, pas au-dessus.
   Le plafond est désormais l'affaire du JS, qui borne la valeur avant de l'écrire (même principe que
   `borner()` dans dashboard-assistant-resize.js).

   ⚠️ `flex-shrink: 0` n'est pas cosmétique : le corps à onglets est en `flex: 1 1 auto`, et avec un
   shrink à 1 les deux se partageraient la compression — c'est le défaut « écrasé à 0 px par la chaîne
   flex » que l'ancien `min-height` servait justement à empêcher. `min-height: 52px` reste en ceinture.
   --------------------------------------------------------------------------------------------------- */
.ia-dock {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: var(--ia-dock-hauteur, 320px);
    min-height: 52px;
    max-height: 100%;
    background: #fff;
    border-top: 1px solid var(--ia-bord-fort);
    box-shadow: 0 -10px 22px -16px rgba(var(--ia-navy-rgb), .55);
    color: var(--ia-texte);
    overflow: hidden;
    transition: height .18s ease;
}

/* Etat replié : 52 px = 8 de poignée + 44 de rangée.

   🛑 DEUX classes dans le sélecteur, pour l'emporter sur la règle de base SANS `!important`
   (spécificité 0,2,0 contre 0,1,0) — patron déjà employé par `.dashboard-assistant.dashboard-assistant--drag`.

   ⚠️ Ne pas confondre ce repli-ci avec celui de la BARRE du panneau : ce sont deux états imbriqués,
   deux clés de stockage, et le même mot « replié ». Quand la barre est repliée, le dock n'est même pas
   affiché (cf. `dashboard-onglets.css`). */
.ia-dock.ia-dock--replie {
    height: 52px;
}

/* Pendant le glisser, la transition rendrait le geste élastique et inutilisable. */
.ia-dock.ia-dock--drag {
    transition: none;
}

.ia-dock.ia-dock--replie .ia-dock-corps {
    display: none;
}

.ia-dock:not(.ia-dock--replie) .ia-dock-replie {
    display: none;
}

.ia-dock-corps {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}


/* --- Poignée de redimensionnement ------------------------------------------------------------------

   🛑 La classe s'appelle `ia-dock-poignee` et NON `dashboard-assistant-poignee` : cette dernière est
   déjà prise par la poignée de LARGEUR du panneau, que `dashboard-assistant-resize.js` câble par un
   `querySelector` (donc le PREMIER trouvé). Réutiliser son nom ferait voler le geste de largeur par
   la poignée du dock.

   ⚠️ `touch-action: none` est obligatoire : sans lui, le navigateur interprète le geste comme un
   défilement et émet un `pointercancel` au premier pixel — le drag ne démarre jamais.

   La poignée est EN FLUX (elle occupe ses 8 px) et non en position absolue débordante : le panneau
   porte `overflow: hidden`, qui clipperait une poignée sortant de son cadre. */
.ia-dock-poignee {
    flex: 0 0 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--ia-fond-fil);
    border-bottom: 1px solid var(--ia-bord);
    cursor: row-resize;
    touch-action: none;
}

.ia-dock-poignee-trait {
    width: 34px;
    height: 3px;
    border-radius: 2px;
    background: #C2C9DC;
}

.ia-dock-poignee:hover .ia-dock-poignee-trait,
.ia-dock-poignee:focus-visible .ia-dock-poignee-trait {
    background: var(--ia-navy);
}

.ia-dock-poignee:focus-visible {
    outline: 2px solid var(--ia-navy);
    outline-offset: -2px;
}


/* --- Rangée repliée (44 px) ------------------------------------------------------------------------
   Un clic dans le champ déploie le dock à sa dernière hauteur. C'est un vrai `<button>` et non un
   `<input readonly>` : c'est sémantiquement un déclencheur, et le clavier fonctionne sans rien écrire. */
.ia-dock-replie {
    flex: 0 0 44px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 10px;
}

.ia-dock-amorce {
    flex: 1 1 auto;
    min-width: 0;
    height: 30px;
    display: flex;
    align-items: center;
    padding: 0 10px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: 15px;
    background: var(--ia-fond-fil);
    color: var(--ia-placeholder);
    font-size: 11.5px;
    text-align: left;
    cursor: text;
}

.ia-dock-amorce:hover {
    border-color: var(--ia-navy);
    background: #fff;
}


/* --- Avatar ----------------------------------------------------------------------------------------
   🛑 Cibler `> i` ET `> svg` : lucide-init.js remplace le `<i>` par un `<svg>` et lui RETIRE son
   `data-lucide` (sa parade anti-boucle). Une règle accrochée à cet attribut serait donc MORTE dès que
   l'icône existe réellement — le `> i` couvre le battement avant rendu, le `> svg` l'état final. */
.ia-avatar {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: var(--bs-info);
    color: #fff;
}

    .ia-avatar > i,
    .ia-avatar > svg {
        width: 17px;
        height: 17px;
        margin-bottom: 2px;
    }

.ia-avatar--msg {
    width: 22px;
    height: 22px;
    margin-top: 2px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: var(--ia-r-sm);
    background: #fff;
    color: var(--ia-navy);
}

    .ia-avatar--msg > i,
    .ia-avatar--msg > svg {
        width: 12px;
        height: 12px;
    }


/* --- Entête du dock : identité, statut, quatre actions --------------------------------------------- */
.ia-tete {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 8px 0 10px;
    height: 40px;
}

.ia-tete-identite {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.ia-tete-nom {
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ia-statut {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 10px;
    color: var(--ia-texte-2);
}

.ia-statut-point {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ia-en-ligne);
}

/* Service indisponible : le point passe au gris et la saisie est verrouillée. L'état est porté par la
   RACINE, donc un seul attribut décrit toute la surface. */
.ia-dock[data-ia-etat="indisponible"] .ia-statut-point,
.ia-fenetre[data-ia-etat="indisponible"] .ia-statut-point {
    background: var(--ia-hors-ligne);
}

.ia-tete-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 1px;
}

/* Cible de 32 px minimum, exigence d'accessibilité du dock (le carré visible est plus petit). */
.ia-btn-icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--ia-r-sm);
    background: none;
    color: var(--ia-texte-2);
}

    .ia-btn-icone > i,
    .ia-btn-icone > svg {
        width: 15px;
        height: 15px;
    }

    .ia-btn-icone:hover {
        background: var(--ia-tint);
        color: var(--ia-navy);
    }


/* --- Bandeau de contexte ---------------------------------------------------------------------------
   Pastilles dossier / exercice / écran. Elles RAPPELLENT à l'utilisateur sur quoi il travaille et ne
   prétendent RIEN de plus : contrairement à la maquette, aucune mention « ce contexte est transmis à
   l'assistant » — ce serait faux, `PoserQuestion(string message)` n'envoie que le message. */
.ia-contexte {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0 10px 7px;
    overflow: hidden;
}

.ia-ctx {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 20px;
    max-width: 46%;
    padding: 0 7px;
    border: 1px solid var(--ia-bord);
    border-radius: 10px;
    background: #F2F4FA;
    color: #3d4560;
    font-size: 10px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

    .ia-ctx > i,
    .ia-ctx > svg {
        flex: 0 0 auto;
        width: 10px;
        height: 10px;
    }

.ia-ctx--discret {
    font-weight: 500;
    color: var(--ia-texte-2);
}


/* ---------------------------------------------------------------------------------------------------
   3. LE FIL
   --------------------------------------------------------------------------------------------------- */
.ia-fil {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    background: var(--ia-fond-fil);
    border-top: 1px solid var(--ia-bord);
    scrollbar-width: thin;
}

.ia-fil-colonne {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px;
}

/* Séparateur de jour. */
.ia-jour {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .4px;
    text-transform: uppercase;
    color: var(--ia-texte-2);
}

    .ia-jour::before,
    .ia-jour::after {
        content: "";
        flex: 1 1 auto;
        height: 1px;
        background: var(--ia-bord);
    }

/* Bouton « nouveau message » : il n'apparaît que si l'utilisateur avait remonté le fil, auquel cas on
   ne le recolle PAS en bas de force — on lui propose d'y aller. */
.ia-fil-nouveau {
    position: sticky;
    bottom: 6px;
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 10px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: 13px;
    background: #fff;
    box-shadow: 0 2px 8px -4px rgba(var(--ia-navy-rgb), .5);
    color: var(--ia-navy);
    font-size: 11px;
    font-weight: 600;
}

    .ia-fil-nouveau > i,
    .ia-fil-nouveau > svg {
        width: 12px;
        height: 12px;
    }

/* 🛑 La règle `[hidden]` est écrite EXPLICITEMENT : le `display` posé ci-dessus écraserait sinon le
   `display: none` que l'agent utilisateur applique à l'attribut, et le bouton resterait affiché en
   permanence. Même parade que la pastille de comptage de la bulle. */
.ia-fil-nouveau[hidden] {
    display: none;
}


/* --- Message de l'utilisateur : bulle navy à droite ------------------------------------------------ */
.ia-msg {
    display: flex;
    flex-direction: column;
}

.ia-msg--user {
    align-items: flex-end;
}

.ia-bulle {
    max-width: 80%;
    padding: 8px 10px;
    border: 1px solid transparent;
    border-radius: var(--ia-r-lg) var(--ia-r-lg) 4px var(--ia-r-lg);
    background: var(--ia-navy);
    color: #fff;
    font-size: 12px;
    line-height: 1.5;
    overflow-wrap: break-word;
}

/* Echec d'envoi : la question RESTE dans le fil, bordée de rouge, et peut être renvoyée. Rien n'est
   perdu — c'est tout l'intérêt de ne pas la retirer à la première erreur. */
.ia-msg--echec .ia-bulle {
    background: #fff;
    border-color: var(--ia-erreur-bord);
    color: #3d4560;
}

.ia-msg-echec {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 4px;
    font-size: 10.5px;
}

.ia-msg-echec-texte {
    color: var(--ia-erreur);
}

.ia-msg-echec[hidden] {
    display: none;
}


/* --- Réponse de l'assistant : HORS bulle, en carte pleine largeur ---------------------------------- */
.ia-msg--assistant {
    flex-direction: row;
    gap: 7px;
}

.ia-msg-corps {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.ia-carte {
    padding: 9px 10px;
    border: 1px solid var(--ia-bord);
    border-radius: var(--ia-r-md);
    background: #fff;
}

/* Horodatage : UNE SEULE FOIS par message, en bas à droite du bloc.
   ⚠️ `#5B6480` et non le `#A2AAC0` de la maquette, qui échoue au contraste AA (2,30:1). */
.ia-msg-pied {
    display: flex;
    align-items: center;
    gap: 2px;
}

.ia-msg-heure {
    margin-left: auto;
    font-size: 10px;
    color: var(--ia-texte-2);
}

/* Actions par message. Seul « Copier » est rendu : « Ouvrir l'écran concerné » et « Utile / A
   améliorer » n'ont aujourd'hui ni donnée ni point d'entrée serveur, et un bouton inerte est pire
   qu'un bouton absent.
   ⚠️ Pas de menu déroulant ici : le fil, le dock et le panneau portent chacun un `overflow: hidden`,
   soit TROIS clippings successifs — un `.dropdown-menu` s'ouvrirait (classe posée, événement émis) et
   resterait invisible. */
.ia-msg-action {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 6px;
    border: 1px solid transparent;
    border-radius: 5px;
    background: none;
    color: var(--ia-texte-2);
    font-size: 10.5px;
    font-weight: 500;
}

    .ia-msg-action > i,
    .ia-msg-action > svg {
        width: 12px;
        height: 12px;
    }

    .ia-msg-action:hover {
        background: var(--ia-tint);
        color: var(--ia-navy);
    }

/* Suggestions de suite, et suggestions d'accueil : même jeton visuel. */
.ia-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.ia-suggestion {
    padding: 4px 8px;
    border: 1px solid #DDE3F5;
    border-radius: 12px;
    background: #fff;
    color: var(--ia-navy);
    font-size: 10.5px;
    font-weight: 600;
    text-align: left;
}

    .ia-suggestion:hover {
        border-color: var(--ia-navy);
        background: var(--ia-tint);
    }

.ia-suggestions[hidden] {
    display: none;
}


/* ---------------------------------------------------------------------------------------------------
   4. RENDU DE LA REPONSE — habillage de la sortie Markdig

   Le serveur rend du HTML produit par Markdig avec `UseAdvancedExtensions()`. Tout le rendu structuré
   de la maquette (titre, étapes numérotées, pastille de chemin de menu, tableau, encadré) s'obtient
   donc EN CSS SEUL sur ce HTML, sans toucher au serveur.

   Ce qui n'est PAS atteignable ainsi, et il faut le savoir : le titre si l'assistant n'émet aucun
   `hN` ; la pastille s'il écrit le chemin en gras (`strong` sert à tout, l'habiller en pastille
   défigurerait les emphases) ; l'encadré s'il n'écrit pas de citation ; les étapes s'il écrit « 1. »
   au fil d'un paragraphe. Réécrire ce HTML en JS par expression régulière est proscrit — norme front,
   et risqué sur du contenu produit par un modèle.
   --------------------------------------------------------------------------------------------------- */
.ia-md {
    font-size: 12px;
    line-height: 1.55;
    color: #2c3350;
    overflow-wrap: break-word;
}

    .ia-md > :first-child {
        margin-top: 0;
    }

    .ia-md > :last-child {
        margin-bottom: 0;
    }

    .ia-md p {
        margin: 0 0 .5rem;
    }

    .ia-md h1,
    .ia-md h2,
    .ia-md h3,
    .ia-md h4,
    .ia-md h5,
    .ia-md h6 {
        margin: .5rem 0 .25rem;
        font-size: 12.5px;
        font-weight: 600;
        line-height: 1.3;
        color: var(--ia-texte);
    }

/* Etapes numérotées : puce ronde teintée, à la place du numéro nu. */
    .ia-md ol {
        counter-reset: ia-etape;
        list-style: none;
        margin: 0 0 .5rem;
        padding-left: 0;
    }

        .ia-md ol > li {
            counter-increment: ia-etape;
            position: relative;
            margin-bottom: .375rem;
            padding-left: 1.6em;
        }

            .ia-md ol > li::before {
                content: counter(ia-etape);
                position: absolute;
                top: .1em;
                left: 0;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                width: 1.15rem;
                height: 1.15rem;
                border-radius: 50%;
                background: var(--ia-tint);
                color: var(--ia-navy);
                font-size: 9.5px;
                font-weight: 700;
            }

    .ia-md ul {
        list-style: none;
        margin: 0 0 .5rem;
        padding-left: 0;
    }

        .ia-md ul > li {
            position: relative;
            margin-bottom: .25rem;
            padding-left: 1.6em;
        }

            .ia-md ul > li::before {
                content: "";
                position: absolute;
                top: .55em;
                left: .45em;
                width: 4px;
                height: 4px;
                border-radius: 50%;
                background: var(--ia-navy);
            }

/* Pastille de chemin de menu.
   🛑 `:not(pre) > code` et non `code` : sans cette garde, les BLOCS de code deviennent eux aussi des
   pastilles, ce qui les rend illisibles. */
    .ia-md :not(pre) > code {
        padding: 1px 5px;
        border: 1px solid #DDE3F5;
        border-radius: 4px;
        background: var(--ia-tint);
        color: var(--ia-navy);
        font-family: inherit;
        font-size: .95em;
        font-weight: 600;
        white-space: nowrap;
    }

    .ia-md pre {
        margin: 0 0 .5rem;
        padding: .5rem;
        border: 1px solid var(--ia-bord);
        border-radius: var(--ia-r-sm);
        background: var(--ia-fond-fil);
        overflow-x: auto;
    }

/* Tableaux.
   🛑 `table-layout: fixed` et `word-break` sont OBLIGATOIRES, pas cosmétiques : le panneau fait 340 px
   et Markdig rend les tables sans aucune classe (`UseAdvancedExtensions` n'inclut pas `UseBootstrap`).
   Sans ces deux règles, une table un peu large déborde et sort une barre de défilement horizontale —
   le défaut déjà corrigé une fois sur les bulles de ce chat. */
    .ia-md table {
        width: 100%;
        table-layout: fixed;
        margin: 0 0 .5rem;
        border: 1px solid var(--ia-bord);
        border-radius: var(--ia-r-sm);
        border-collapse: collapse;
        font-size: 11.5px;
    }

    .ia-md th,
    .ia-md td {
        padding: .25rem .4rem;
        border: 1px solid var(--ia-bord);
        text-align: left;
        word-break: break-word;
    }

    .ia-md thead th {
        background: var(--ia-fond-fil);
        color: var(--ia-texte-2);
        font-weight: 700;
    }

/* Encadré d'information. */
    .ia-md blockquote {
        margin: .5rem 0;
        padding: .4rem .6rem;
        border: 1px solid var(--ia-bord);
        border-left: 3px solid var(--ia-bord-fort);
        border-radius: var(--ia-r-sm);
        background: var(--ia-fond-fil);
        color: var(--ia-texte-2);
        font-size: 11.5px;
    }

    .ia-md a {
        color: var(--ia-navy);
        text-decoration: underline;
    }

    .ia-md a:hover {
        color: var(--ia-accent);
    }

    .ia-md img {
        max-width: 100%;
    }


/* ---------------------------------------------------------------------------------------------------
   5. LES CINQ ETATS

   Ils sont EXCLUSIFS, donc portés par un attribut (`data-ia-etat`) sur la racine et non par N classes
   cumulables : la combinaison impossible devient non représentable.

   ⚠️ Le masquage se fait par l'attribut `hidden` ou par cet attribut d'état, JAMAIS en surchargeant un
   utilitaire d'affichage de Bootstrap (`d-flex`, `d-none`…) : ceux-ci sont en `!important` et aucune
   règle de ce fichier ne peut les battre — or ce fichier n'a pas le droit d'en écrire.
   --------------------------------------------------------------------------------------------------- */

/* --- Accueil --------------------------------------------------------------------------------------- */
.ia-accueil {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.ia-accueil-titre {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
}

.ia-accueil-texte {
    margin: 0;
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--ia-texte-2);
}

.ia-accueil[hidden] {
    display: none;
}


/* --- Réponse en cours -----------------------------------------------------------------------------
   Trois points + un squelette de lignes FIXE. Le squelette est honnête comme indicateur d'attente : il
   annonce qu'un paragraphe se prépare. Il serait malhonnête en simulation de flux (lignes qui
   apparaissent une par une, curseur de frappe, pourcentage) — il n'y a AUCUN streaming : le serveur
   interroge l'API par sondage (20 essais de 1,5 s) et rend la réponse en un seul bloc. */
.ia-attente {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ia-attente-ligne {
    display: flex;
    align-items: center;
    gap: 7px;
}

.ia-attente-points {
    display: flex;
    align-items: center;
    gap: 4px;
}

    .ia-attente-points > span {
        width: 5px;
        height: 5px;
        border-radius: 50%;
        background: var(--ia-navy);
        animation: ia-attente-pulse 1.2s ease-in-out infinite;
    }

    .ia-attente-points > span:nth-child(2) {
        animation-delay: .15s;
    }

    .ia-attente-points > span:nth-child(3) {
        animation-delay: .3s;
    }

@keyframes ia-attente-pulse {
    0%, 100% { opacity: .25; }
    50%      { opacity: .85; }
}

.ia-attente-legende {
    font-size: 11px;
    color: var(--ia-texte-2);
}

.ia-squelette {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding-left: 29px;
}

.ia-squelette-ligne {
    height: 9px;
    border-radius: 4px;
    background: var(--ia-bord);
}

    .ia-squelette-ligne:nth-child(2) { width: 82%; }
    .ia-squelette-ligne:nth-child(3) { width: 54%; }

/* Le libellé dit « Arrêter d'attendre » et non « Arrêter » : le clic abandonne l'attente côté client,
   il n'annule PAS le traitement côté serveur — la question est déjà partie, et la réponse pourra même
   réapparaître au prochain chargement de la conversation. Le bouton ne doit pas promettre l'inverse. */
.ia-arreter {
    height: 22px;
    padding: 0 8px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: var(--ia-r-sm);
    background: #fff;
    color: var(--ia-navy);
    font-size: 10.5px;
    font-weight: 600;
}

.ia-arreter[hidden] {
    display: none;
}


/* --- Encadrés d'état : hors périmètre (ambre) et service indisponible (gris) ------------------------
   La distinction se fait d'abord par la FORME — icône, bordure, actions en ligne, absence d'avatar —
   et seulement ensuite par la teinte : c'est ce qui la rend robuste à tous les thèmes et aux
   daltonismes. */
.ia-encadre {
    display: flex;
    gap: 8px;
    padding: 10px 11px;
    border: 1px solid var(--ia-bord);
    border-radius: var(--ia-r-md);
    background: var(--ia-fond-fil);
}

    .ia-encadre > i,
    .ia-encadre > svg {
        flex: 0 0 auto;
        margin-top: 1px;
        width: 14px;
        height: 14px;
    }

.ia-encadre-corps {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.ia-encadre-texte {
    font-size: 11.5px;
    line-height: 1.55;
}

.ia-encadre-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.ia-btn-doux {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 10px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: var(--ia-r-sm);
    background: #fff;
    color: var(--ia-navy);
    font-size: 11.5px;
    font-weight: 600;
}

    .ia-btn-doux > i,
    .ia-btn-doux > svg {
        width: 12px;
        height: 12px;
    }

/* Hors périmètre : AMBRE, et surtout pas rouge. L'utilisateur n'a rien cassé — sa question ne relève
   simplement pas du logiciel. C'est le défaut principal que cette refonte corrige : les trois états
   « hors périmètre », « saisie vide » et « service indisponible » partageaient la même bulle rouge. */
.ia-encadre--ambre {
    border-color: var(--ia-ambre-bord);
    background: var(--ia-ambre-fond);
    color: var(--ia-ambre-texte);
}

    .ia-encadre--ambre > i,
    .ia-encadre--ambre > svg {
        color: #B7791F;
    }

    .ia-encadre--ambre .ia-btn-doux {
        border-color: #E3D6AB;
        color: var(--ia-ambre-texte);
    }

/* Service indisponible : gris, neutre, avec « Réessayer ». L'historique reste consultable. */
.ia-encadre--gris {
    color: #4a5578;
}

    .ia-encadre--gris > i,
    .ia-encadre--gris > svg {
        color: var(--ia-texte-2);
    }

.ia-encadre[hidden] {
    display: none;
}


/* ---------------------------------------------------------------------------------------------------
   6. LE COMPOSER
   --------------------------------------------------------------------------------------------------- */
.ia-composer {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 8px 10px 9px;
    background: #fff;
    border-top: 1px solid var(--ia-bord);
}

.ia-composer-boite {
    display: flex;
    align-items: flex-end;
    gap: 7px;
    padding: 7px 7px 7px 10px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: var(--ia-r-md);
    background: #fff;
}

    .ia-composer-boite:focus-within {
        border-color: var(--ia-navy);
        box-shadow: 0 0 0 3px rgba(var(--ia-navy-rgb), .1);
    }

/* 🛑 Ni `height` ni `min-height` FIXE : ce champ grandit avec son contenu, et le JS pose sa hauteur en
   mesurant le contenu. L'ancienne bande imposait `height: 28px; min-height: 28px` — avec une hauteur
   figée, un champ multiligne ne peut jamais grandir, et l'auto-agrandissement passe pour cassé alors
   que le script est correct. */
.ia-composer-saisie {
    flex: 1 1 auto;
    min-width: 0;
    /* 🛑 Plancher d'UNE LIGNE, et ce n'est pas décoratif : la hauteur du champ est mesurée en script
       (`ajusterHauteurSaisie`) et écrite en style inline. Une mesure prise sur un élément sans mise en
       page rend 0, et un `height: 0px` inline escamote le champ — invisible, incliquable, donc plus aucun
       `input` pour le recalculer : le chat cesse d'accepter la moindre frappe. `min-height` l'emportant
       sur `height`, cette ligne rend ce blocage impossible quelle que soit la valeur écrite. */
    min-height: 1.5em;
    max-height: 7.5em;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ia-texte);
    font-family: inherit;
    font-size: 12px;
    line-height: 1.5;
    resize: none;
    overflow-y: auto;
    margin-bottom: 8px;
}

    .ia-composer-saisie:focus {
        outline: none;
    }

    .ia-composer-saisie::placeholder {
        color: var(--ia-placeholder);
    }

    .ia-composer-saisie:disabled {
        background: none;
        color: var(--ia-texte-2);
    }

.ia-envoyer {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: var(--ia-navy);
    color: #fff;
}

    .ia-envoyer > i,
    .ia-envoyer > svg {
        width: 15px;
        height: 15px;
    }

    .ia-envoyer:disabled {
        background: var(--ia-bord-fort);
        color: #fff;
    }

    .ia-envoyer[hidden] {
        display: none;
    }

/* ⚠️ `#5B6480` et non `#A2AAC0` : cette ligne d'aide est du texte, elle doit passer l'AA. */
.ia-composer-aide {
    margin: 0;
    font-size: 9.5px;
    color: var(--ia-texte-2);
}

/* Saisie verrouillée quand le service est indisponible. */
.ia-dock[data-ia-etat="indisponible"] .ia-composer-boite,
.ia-fenetre[data-ia-etat="indisponible"] .ia-composer-boite {
    background: var(--ia-fond-fil);
}


/* ---------------------------------------------------------------------------------------------------
   7. LA FENETRE AGRANDIE — vraie modale Bootstrap 5

   🛑 Aucun `z-index` ici, et surtout pas sur `.modal` ni `.modal-backdrop` : le socle est seul
   propriétaire des couches, et un test unitaire refuse qu'un CSS d'écran en décide. La modale se
   range donc d'elle-même à 1055, au-dessus de son voile (1050) et du panneau (1035) — lequel se
   retrouve grisé pendant la lecture, ce qui est le comportement voulu.

   🛑 Le squelette est déclaré dans le partial du panneau (seule source présente sur les deux
   surfaces, le layout du dashboard ne mentionnant jamais l'assistant) MAIS il est RELOGE SOUS `body`
   avant toute ouverture. Ce n'est pas une précaution de style : l'hôte du panneau porte en permanence
   un `transform` (même ouvert, `translateX(0)` n'est pas `none`), un `z-index: 1035` et un
   `visibility: hidden` à l'état fermé. Une modale laissée dedans serait (1) enfermée dans les 340 px
   du tiroir, (2) plafonnée à 1035 donc SOUS SON PROPRE VOILE — page et modale grisées, tous les
   boutons inertes —, et (3) escamotée si l'utilisateur ferme le panneau, en laissant le voile seul à
   l'écran. Le piège de focus de Bootstrap ne fonctionnerait pas non plus.
   --------------------------------------------------------------------------------------------------- */

.ia-fenetre .ia-fenetre-contenu {
    flex-direction: row;
    height: min(704px, 88vh);
    border: 0;
    border-radius: 14px;
    overflow: hidden;
}

/* --- Rail des conversations ------------------------------------------------------------------------ */
.ia-rail {
    flex: 0 0 234px;
    display: flex;
    flex-direction: column;
    background: var(--ia-fond-fil);
    border-right: 1px solid #E9ECF4;
}

.ia-rail-nouvelle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 34px;
    margin: 14px 12px 10px;
    border: 1px solid var(--ia-bord-fort);
    border-radius: 8px;
    background: #fff;
    color: var(--ia-navy);
    font-size: 12.5px;
    font-weight: 600;
}

    .ia-rail-nouvelle > i,
    .ia-rail-nouvelle > svg {
        width: 15px;
        height: 15px;
    }

    .ia-rail-nouvelle:hover {
        border-color: var(--ia-navy);
        background: var(--ia-tint);
    }

.ia-rail-titre {
    margin: 0;
    padding: 4px 16px 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--ia-texte-2);
}

.ia-rail-liste {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 8px;
    overflow-y: auto;
    scrollbar-width: thin;
}

.ia-rail-vide {
    padding: 4px 8px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--ia-texte-2);
}

.ia-conv {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 10px;
    border: 0;
    border-radius: 8px;
    background: none;
    text-align: left;
}

    .ia-conv:hover {
        background: #fff;
    }

.ia-conv--active {
    background: var(--ia-tint);
}

.ia-conv-titre {
    font-size: 12.5px;
    color: #3d4560;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ia-conv--active .ia-conv-titre {
    font-weight: 600;
    color: var(--ia-texte);
}

.ia-conv-date {
    font-size: 10.5px;
    color: var(--ia-texte-2);
}

.ia-rail-pied {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 10px 12px;
    border-top: 1px solid #E9ECF4;
}

.ia-rail-lien {
    display: flex;
    align-items: center;
    gap: 7px;
    background: none;
    border: 0;
    padding: 0;
    color: var(--ia-navy);
    font-size: 12px;
    font-weight: 500;
    text-align: left;
    text-decoration: none;
}

    .ia-rail-lien > i,
    .ia-rail-lien > svg {
        flex: 0 0 auto;
        width: 14px;
        height: 14px;
    }

    .ia-rail-lien:hover {
        color: var(--ia-accent);
    }


/* --- Colonne de conversation ----------------------------------------------------------------------- */
.ia-fenetre-conversation {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.ia-fenetre-tete {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 12px 16px 10px 18px;
    border-bottom: 1px solid var(--ia-bord);
}

.ia-fenetre-tete-ligne {
    display: flex;
    align-items: center;
    gap: 10px;
}

.ia-fenetre .ia-avatar {
    width: 30px;
    height: 30px;
    border-radius: var(--ia-r-md);
}

    .ia-fenetre .ia-avatar > i,
    .ia-fenetre .ia-avatar > svg {
        width: 17px;
        height: 17px;
    }

.ia-fenetre .ia-tete-nom {
    font-size: 14.5px;
    padding-bottom: 2px;
}

.ia-fenetre .ia-statut {
    font-size: 11px;
}

.ia-btn-texte {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 9px;
    border: 1px solid var(--ia-bord);
    border-radius: var(--ia-r-sm);
    background: #fff;
    color: #4a5578;
    font-size: 12px;
    font-weight: 500;
}

    .ia-btn-texte > i,
    .ia-btn-texte > svg {
        width: 15px;
        height: 15px;
    }

    .ia-btn-texte:hover {
        border-color: var(--ia-navy);
        color: var(--ia-navy);
    }

/* Pastilles de contexte : un peu plus grandes qu'au dock, la place le permet. */
.ia-fenetre .ia-contexte {
    padding: 0;
}

.ia-fenetre .ia-ctx {
    height: 24px;
    max-width: none;
    padding: 0 9px;
    border-radius: 12px;
    font-size: 11.5px;
}

    .ia-fenetre .ia-ctx > i,
    .ia-fenetre .ia-ctx > svg {
        width: 11px;
        height: 11px;
    }

/* 🛑 LA colonne de lecture bornée à 640 px et centrée : c'est le point clé de la fenêtre agrandie.
   Sans elle, le texte s'étale sur 860 px et devient pénible à lire — le défaut du plein écran
   précédent. Le fil et le composer partagent la même contrainte, pour qu'ils restent alignés. */
.ia-fenetre .ia-fil {
    background: #fff;
    border-top: 0;
    padding: 20px 0 6px;
}

.ia-fenetre .ia-fil-colonne {
    max-width: 640px;
    margin-inline: auto;
    gap: 18px;
    padding: 0 24px;
}

.ia-fenetre .ia-composer {
    padding: 10px 0 14px;
    border-top: 0;
}

.ia-fenetre .ia-composer-interieur {
    width: 100%;
    max-width: 640px;
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

/* Les différences dock / fenêtre sont TOUTES de taille et d'espacement, jamais de structure : c'est ce
   qui permet de déplacer le même nœud de fil d'une surface à l'autre sans le re-rendre, et donc de ne
   perdre ni un message en échec, ni une réponse interrompue. */
.ia-fenetre .ia-bulle {
    max-width: 74%;
    padding: 10px 13px;
    border-radius: 14px 14px 5px 14px;
    font-size: 13.5px;
}

.ia-fenetre .ia-md {
    font-size: 13.5px;
    line-height: 1.6;
}

    .ia-fenetre .ia-md h1,
    .ia-fenetre .ia-md h2,
    .ia-fenetre .ia-md h3,
    .ia-fenetre .ia-md h4 {
        font-size: 14px;
    }

    .ia-fenetre .ia-md table {
        font-size: 12.5px;
    }

    .ia-fenetre .ia-md ol > li::before {
        width: 1.35rem;
        height: 1.35rem;
        font-size: 11px;
    }

.ia-fenetre .ia-carte {
    padding: 0;
    border: 0;
    background: none;
}

.ia-fenetre .ia-msg--assistant {
    gap: 11px;
}

.ia-fenetre .ia-avatar--msg {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: var(--ia-fond-fil);
}

    .ia-fenetre .ia-avatar--msg > i,
    .ia-fenetre .ia-avatar--msg > svg {
        width: 14px;
        height: 14px;
    }

.ia-fenetre .ia-msg-action {
    padding: 4px 7px;
    font-size: 11.5px;
}

.ia-fenetre .ia-msg-heure {
    font-size: 11px;
}

.ia-fenetre .ia-suggestion {
    padding: 5px 10px;
    border-radius: 14px;
    font-size: 12px;
}

.ia-fenetre .ia-envoyer {
    width: auto;
    height: 34px;
    padding: 0 13px;
    border-radius: var(--ia-r-md);
    font-size: 13px;
    font-weight: 600;
}

.ia-fenetre .ia-composer-saisie {
    font-size: 13.5px;
    max-height: 9em;
}

.ia-fenetre .ia-composer-aide {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
}

.ia-fenetre-avertissement {
    margin-left: auto;
}


/* ---------------------------------------------------------------------------------------------------
   8. BADGE « MESSAGE NON LU »

   Deux porteurs, parce que la poignée du panneau n'est pas la même selon la surface : la bulle
   flottante `#assistantToggleBtn` HORS dashboard (elle est rendue par `_Layout`, que le dashboard
   n'utilise pas), et la zone du picto de l'entête du panneau SUR le dashboard.

   🛑 Une classe DISTINCTE de `.assistant-button-bulle`, qui compte les éléments des WIDGETS et a déjà
   DEUX écrivains (le chargement paresseux du panneau et le script des bulles de comptage). Un
   troisième écrivain sur le même nœud produirait un défaut intermittent : le badge de l'assistant
   serait écrasé — ou masqué — dès la première mutation d'un widget, c'est-à-dire à l'ouverture du
   panneau ou 50 ms après n'importe quel rechargement. Symptôme « le badge disparaît tout seul »,
   impossible à reproduire de façon fiable.

   Le badge de l'assistant est ORANGE, la pastille des widgets reste ROUGE : le rouge appartient aux
   alertes métier. Et il se place en BAS à droite, la pastille de comptage occupant déjà le haut.
   --------------------------------------------------------------------------------------------------- */
.ia-bulle-badge {
    position: absolute;
    right: -4px;
    bottom: -4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border: 2px solid #fff;
    border-radius: 9px;
    background: var(--ia-accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    /* Sans quoi le badge intercepterait le clic d'ouverture du panneau ET le glisser de la bulle. */
    pointer-events: none;
    animation: ia-badge-apparait .2s ease-out;
}

/* 🛑 Ecrit explicitement : le `display` ci-dessus écraserait le `display: none` que l'agent
   utilisateur applique à l'attribut, et un badge sans compte resterait affiché à vide. */
.ia-bulle-badge[hidden] {
    display: none;
}

@keyframes ia-badge-apparait {
    from { opacity: 0; transform: scale(.5); }
    to   { opacity: 1; transform: scale(1); }
}


/* ---------------------------------------------------------------------------------------------------
   9. RESPONSIVE ET PREFERENCES SYSTEME
   --------------------------------------------------------------------------------------------------- */

/* Sous 992 px, le panneau passe pleine largeur SOUS le contenu, en hauteur libre (`height: auto`, corps
   en `overflow: visible`). Une hauteur de dock figée n'y a donc plus de sens, et la poignée n'aurait
   rien à régler : elle est neutralisée, exactement comme l'est déjà celle de la largeur du panneau. */
@media (max-width: 991.98px) {
    .ia-dock {
        height: auto;
        max-height: none;
    }

    .ia-dock:not(.ia-dock--replie) .ia-fil {
        max-height: 50vh;
    }

    .ia-dock-poignee {
        display: none;
    }
}

@media (max-width: 575.98px) {
    .ia-fenetre .ia-rail {
        display: none;
    }

    .ia-fenetre .ia-fenetre-contenu {
        height: min(704px, 92vh);
    }
}

/* Réglage système « réduire les animations » : plus aucun mouvement, ni sur la hauteur du dock, ni sur
   les points d'attente, ni sur l'apparition du badge. */
@media (prefers-reduced-motion: reduce) {
    .ia-dock {
        transition: none;
    }

    .ia-attente-points > span,
    .ia-bulle-badge {
        animation: none;
    }
}

/* ===================================================================================================
   Fenêtre d'historique — ouverte par le bouton horloge de l'entête du dock
   ===================================================================================================

   Petite fenêtre affichée À GAUCHE du panneau, ne portant que les conversations archivées.

   🛑 Elle est relogée sous `<body>` par `assistant-ia.dock.js` : le fil, le dock ET le panneau portent
   chacun un `overflow: hidden`, qui la découperait intégralement. Deux conséquences à connaître :

   1. Le positionnement se fait en `position: fixed`, ce qui ne fonctionne QUE hors du panneau — celui-ci
      porte un `transform` même ouvert (`translateX(0)` n'est pas `none`), donc il établirait un bloc
      conteneur et « fixed » y serait relatif au panneau, puis clippé par son `overflow`.
   2. Les jetons de couleur du composant sont scopés : `.ia-historique` est déclarée dans leur bloc, en
      tête de cette feuille. Ne pas l'en retirer.

   💡 L'ancrage horizontal reste du CSS et non du JavaScript : `dashboard-assistant-resize.js` reflète la
   largeur du panneau sur `:root`, donc `right` la suit à la poignée. L'ancrage vertical est le BAS de la
   fenêtre, et non le haut : le dock occupe le bas du panneau, la fenêtre apparaît donc à côté de lui —
   et l'on n'a pas à connaître la hauteur de l'entête de page, qui varie d'une surface à l'autre.

   Couche 1040 : au-dessus de l'hôte du panneau (1035), sous le voile des modales (1050). Aucune règle
   ne nomme `.modal` ni `.modal-backdrop` — un test du dépôt l'interdit. */
.ia-historique {
    position: fixed;
    right: calc(var(--tg-assistant-largeur, 295px) + 12px);
    bottom: 16px;
    z-index: 1040;
    display: flex;
    flex-direction: column;
    width: 264px;
    max-height: min(60vh, 420px);
    padding: 8px;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .16);
}

/* Le reboot Bootstrap 5 déclare `[hidden] { display: none !important }`, donc le `display: flex`
   ci-dessus ne peut pas rouvrir une fenêtre fermée. La règle est écrite quand même : elle rend la
   dépendance explicite, et le piège inverse a déjà été payé sur `.ia-bulle-badge`. */
.ia-historique[hidden] {
    display: none;
}

.ia-historique-tete {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 2px 8px;
    border-bottom: 1px solid var(--bs-border-color);
}

.ia-historique-titre {
    flex: 1 1 auto;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ia-navy);
}

.ia-historique-liste {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* 🛑 `overflow-x: hidden` explicitement : CSS calcule en `auto` le `visible` d'un axe dès que l'autre
       vaut `auto`, donc un `overflow-y` seul autoriserait AUSSI une barre horizontale — sur 264 px, un
       titre de conversation la déclencherait au premier caractère de trop. */
    overflow-y: auto;
    overflow-x: hidden;
    padding: 6px 0;
}

.ia-historique-pied {
    padding-top: 6px;
    border-top: 1px solid var(--bs-border-color);
}

/* Sous cette largeur, le panneau passe pleine largeur SOUS le contenu : la largeur reflétée sur `:root`
   ne décrit plus une colonne de droite, et s'en servir placerait la fenêtre hors de l'écran. On l'ancre
   alors au bord du viewport. */
@media (max-width: 991.98px) {
    .ia-historique {
        right: 12px;
        left: 12px;
        width: auto;
    }
}
