
/* font-display:block (et non swap) : le texte n'est JAMAIS rendu dans une police
   de secours puis remplacé — ce remplacement (« FOUT » / font swap) faisait
   rapetisser les lettres une fraction de seconde à chaque navigation. La police
   est locale (48 Ko), donc l'attente est imperceptible ; elle est en plus
   préchargée en priorité (voir <link rel=preload> dans le gabarit). */
@font-face { font-family:'InterDovada'; src:url('inter-var.woff2') format('woff2');
             font-weight:100 900; font-display:block; }
/* Barre de défilement TOUJOURS réservée : sans ça, une page courte (sans barre)
   et une page longue (avec barre) décalent le contenu centré de ~15 px — la page
   semble « vibrer » d'un écran à l'autre (« layout shift » / scrollbar jump). */
html { scrollbar-gutter:stable; overflow-y:scroll; }
/* CONTRASTE : les gris sont volontairement soutenus. Un texte secondaire doit
   rester LISIBLE sur un écran de portable en salle de réunion — pas décoratif. */
:root {
  color-scheme: light dark;
  --fond:#f3f2ec; --carte:#fbfaf5; --texte:#1b1c1e; --discret:#4a4a50;
  --faible:#5c5c63; --tres-faible:#6e6e76; --bord:#ddd9cb; --bord-fin:#e7e3d6;
  --vert:#1a7f5a; --vert-fond:#e6f2e7; --vert-texte:#14563e;
  --jaune:#7a5c00; --jaune-fond:#fdf3d0; --jaune-bord:#e0c876;
  --rouge:#a3241d; --inverse:#1b1c1e; --sur-inverse:#f3f2ec;
  /* Le ruban d'explication d'une option : BLANC, pour se détacher du crème de
     la liste déroulante (choix produit — le gris y est déjà la couleur par
     défaut). En sombre, « blanc » devient la surface la plus claire du thème :
     un vrai blanc y brûlerait l'écran. */
  --ruban:#ffffff;
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
  --fond:#1e1e20; --carte:#26262a; --texte:#f2f2f4; --discret:#c2c2c9;
  --faible:#b0b0b8; --tres-faible:#9a9aa2; --bord:#3d3d44; --bord-fin:#33333a;
  --vert:#6fd0a0; --vert-fond:#1d3527; --vert-texte:#a8e5c4;
  --jaune:#f0d47e; --jaune-fond:#3a2f12; --jaune-bord:#6b5722;
  --rouge:#ff9aa0; --inverse:#f2f2f4; --sur-inverse:#1b1c1e; --ruban:#31313a;
} }
:root[data-theme="dark"] {
  --fond:#1e1e20; --carte:#26262a; --texte:#f2f2f4; --discret:#c2c2c9;
  --faible:#b0b0b8; --tres-faible:#9a9aa2; --bord:#3d3d44; --bord-fin:#33333a;
  --vert:#6fd0a0; --vert-fond:#1d3527; --vert-texte:#a8e5c4;
  --jaune:#f0d47e; --jaune-fond:#3a2f12; --jaune-bord:#6b5722;
  --rouge:#ff9aa0; --inverse:#f2f2f4; --sur-inverse:#1b1c1e; --ruban:#31313a;
}
* { box-sizing:border-box; }
body { margin:0; background:var(--fond); color:var(--texte); font-weight:300;
       font-family:'InterDovada', -apple-system, 'Segoe UI', system-ui, sans-serif;
       font-synthesis:none; -webkit-font-smoothing:antialiased; }
a { color:inherit; text-decoration:none; }

/* Bande de navigation générale — surface claire, séparée du contenu de page */
/* Le contenu est CENTRÉ dans une colonne de largeur fixe (comme la page de base) :
   sur un grand écran il ne s'étale pas d'un bord à l'autre. Le bandeau garde son
   fond pleine largeur mais son contenu s'aligne sur la même colonne. */
/* LE BANDEAU RESTE À L'ÉCRAN (demande produit) : la marque, le tableau de bord
   et le passage d'un agent à l'autre doivent être atteignables à tout moment,
   sans remonter. `z-index` AU-DESSUS de l'en-tête collant du tableau (30),
   sinon les colonnes CONSTAT|CORRECTION|… lui passeraient par-dessus. */
.bandeau { background:var(--carte); border-bottom:0.5px solid var(--bord);
           position:sticky; top:0; z-index:60; }

/* Les onglets sont CENTRÉS dans le bandeau : la marque et les actions occupent
   chacune une moitié de l'espace restant, quelle que soit leur largeur. */
.bandeau-int { max-width:none; margin:0 auto; padding:13px clamp(20px, 2.5vw, 48px);
               display:flex; align-items:center; gap:14px; }
/* LE RUBAN S'ALIGNE SUR LE CONTENU (demande produit 2026-08-12). Le rectangle
   des pages est plafonné à 1776 px et centré ; sans cette règle, « DOVADA
   ACCOUNTING » et les boutons EN / thème restaient collés aux bords de
   l'écran, en porte-à-faux de ~65 px avec le contenu juste en dessous. Deux
   axes verticaux différents sur la même page, ça se voit tout de suite.
   Même plafond, même centrage, même garde `echo-scinde` que `main`. */
body:not(.echo-scinde) .bandeau-int { max-width:1776px; }
.marque { font-size:13px; letter-spacing:.04em; font-weight:400; flex:1;
          display:inline-flex; align-items:center; gap:9px; }
/* LOGO DOVADA — fichier statique (mis en cache par le navigateur), jamais un
   CDN : les pages tournent en local chez le client. Le tracé d'origine est
   dessiné point par point (60 Ko) ; les points ALIGNÉS ont été retirés, la
   forme est identique.
   Le logo est NOIR : en thème sombre on l'inverse plutôt que de servir deux
   fichiers — un seul fichier, donc jamais deux versions qui divergent. */
.logo-dovada { display:block; flex:0 0 auto; }
/* Le logo garde SES couleurs : noir sur clair, blanc sur sombre. Le teindre en
   vert en faisait un élément d'interface parmi d'autres — c'est une marque. */
.logo-attente svg { width:72px; height:72px; color:var(--texte); }
/* CHARGEMENT = IDÉE 1.2 AVEC REPOS (demande produit, 2026-08-08) : une copie
   exacte tourne par-dessus le logo, ET l'ensemble tourne sur lui-même — les
   DEUX au même rythme, sinon la superposition se désynchronise. Le rythme :
   le logo a une symétrie de 180° (sa 2e pièce est la 1re tournée d'un
   demi-tour), donc chaque DEMI-tour re-forme exactement le logo d'origine.
   Un cycle = 2,5 s : repos complet sur le logo aligné (0 → 22 %, le temps que
   l'œil le voie), puis demi-tour qui part lentement, accélère, et ralentit en
   arrivant (ease-in-out). Centre de rotation : celui du dessin (499.4/503.9),
   via transform-box:view-box — le centre de la boîte du groupe bougerait avec
   la copie. Le viewBox du SVG animé est un CARRÉ couvrant tout le cercle
   balayé — un cadre taillé sur le logo immobile couperait la rotation. */
.logo-attente .logo-tout, .logo-attente .logo-copie {
          transform-box:view-box; transform-origin:499.4px 503.9px;
          animation:tourne-repos 2.5s ease-in-out infinite; }
@keyframes tourne-repos { 0%, 22% { transform:rotate(0deg); }
                          100%    { transform:rotate(180deg); } }
/* Le bouton LOGO TEST porte l'habit d'un agent SELECTIONNE (demande produit) :
   pilule verte, texte creme, aucun bord ni fond de bouton natif qui deborde. */
button.onglet { background:var(--vert); color:#fbfaf5; border:none;
                cursor:pointer; font-family:inherit; }
button.onglet:hover { color:#fbfaf5; }
/* Respect du réglage système « réduire les animations » : on n'impose jamais
   du mouvement à quelqu'un qui a demandé de ne pas en avoir. */
@media (prefers-reduced-motion: reduce) {
  .logo-attente .logo-tout, .logo-attente .logo-copie { animation:none; } }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .logo-dovada {
          filter:invert(1); } }
:root[data-theme="dark"] .logo-dovada { filter:invert(1); }
:root[data-theme="light"] .logo-dovada { filter:none; }
.onglets { display:flex; gap:2px; flex:0 0 auto; border:0.5px solid var(--bord);
           border-radius:999px; padding:3px; }
.onglet { font-size:11px; letter-spacing:.09em; padding:6px 13px; border-radius:999px;
          color:var(--discret); white-space:nowrap; }
.onglet:hover { color:var(--texte); }
.onglet.actif { background:var(--vert); color:#fbfaf5; }
.onglet.inactif { color:var(--tres-faible); }
.actions { flex:1; display:flex; gap:6px; align-items:center; justify-content:flex-end; }
/* LE BOUTON LOGO EST UN CERCLE (demande produit 2026-08-12) : le mot « LOGO »
   en toutes lettres occupait la place d'un onglet d'agent pour un bouton qui
   n'ouvre qu'un apercu d'animation. Il reprend la boite du bouton de theme
   (meme classe `.rond`, donc une seule definition a maintenir) et son image la
   taille du logo d'ALTO (15 px) — les deux logos du ruban se repondent.
   Le noir plein suit le meme raisonnement que pour ALTO : le fichier reste le
   favicon colore, seul l'affichage est ecrase, et s'inverse en theme sombre. */
.rond-logo { padding:0; background:var(--carte); cursor:pointer;
             font-family:inherit; }
.rond-logo img { height:15px; width:auto; display:block; filter:brightness(0); }
:root[data-theme="dark"] .rond-logo img { filter:brightness(0) invert(1); }
.rond { border:0.5px solid var(--bord); border-radius:999px; width:29px; height:29px;
        display:inline-flex; align-items:center; justify-content:center;
        color:var(--discret); font-size:13px; background:none; cursor:pointer;
        font-family:inherit; }
.pilule-lien { font-size:11px; letter-spacing:.08em; border:0.5px solid var(--bord);
               border-radius:999px; padding:6px 12px; color:var(--discret);
               background:none; cursor:pointer; font-family:inherit; }
.rond:hover, .pilule-lien:hover { color:var(--texte); }

main { max-width:none; margin:0 auto;
       padding:10px clamp(20px, 2.5vw, 48px) 48px; }
/* SUR GRAND ÉCRAN, LE CONTENU RESPIRE (demande produit 2026-08-12). Le
   rectangle occupait toute la largeur : à 1920 px, des tableaux de 1809 px
   fatiguent l'œil, qui doit balayer d'un bord à l'autre pour lire une ligne.
   Plafond à 1776 px, centré — soit ~7 % de moins et ~64 px de gris rendus de
   chaque côté. En dessous de ce seuil, RIEN ne change : les écrans normaux
   gardent exactement la mise en page d'avant.
   Uniquement quand ECHO est FERMÉ : en écran scindé, le volet gauche est déjà
   étroit et un second rétrécissement le rendrait illisible. */
body:not(.echo-scinde) main { max-width:1776px; }
.eyebrow { font-size:11px; letter-spacing:.16em; color:var(--faible); }

/* Titre-sélecteur : nu au repos, panneau au clic */
.sel { position:relative; display:inline-block; }
.sel-bouton { background:none; border:none; padding:0; margin:0; cursor:pointer;
              font-family:inherit; color:inherit; display:inline-flex;
              align-items:center; gap:10px; }
.titre-client { font-size:40px; font-weight:200; letter-spacing:-.02em; line-height:1.12; }
.titre-periode { font-size:24px; font-weight:200; color:var(--discret); }
.fleche { color:var(--tres-faible); font-size:.5em; line-height:1; }
.panneau { position:absolute; z-index:40; top:calc(100% + 6px); left:0; width:330px;
           background:var(--carte); border:0.5px solid var(--bord); border-radius:12px;
           padding:8px; box-shadow:0 10px 30px rgba(27,28,30,.10); display:none; }
.panneau.ouvert { display:block; }
.recherche { display:flex; align-items:center; gap:8px; border:0.5px solid var(--bord);
             border-radius:999px; padding:7px 13px; background:var(--fond); }
.recherche input { border:none; background:none; outline:none; font-family:inherit;
                   font-size:12px; color:var(--texte); width:100%; font-weight:300; }
.grp-panneau { font-size:9.5px; letter-spacing:.14em; color:var(--tres-faible);
               padding:10px 12px 5px; }
.opt-panneau { font-size:13px; padding:7px 12px; border-radius:8px; color:var(--discret);
               display:flex; justify-content:space-between; cursor:pointer; }
.opt-panneau:hover { background:var(--fond); color:var(--texte); }
.opt-panneau.choisi { background:var(--vert-fond); color:var(--texte); }
.ajouter { border-top:0.5px solid var(--bord-fin); margin-top:6px; padding:9px 12px 3px;
           font-size:12px; color:var(--vert); }

.stats { font-size:11.5px; color:var(--faible); }
/* Période et mesure sur la même ligne, séparées de 32 px : collés (13 px) les
   chiffres se lisaient comme la suite du titre ; à 48 px ils partaient trop
   loin. 32 px cale le début des chiffres sous le milieu du nom de client —
   repère visuel choisi à l'écran. */
.ligne-periode { display:flex; align-items:baseline; gap:32px; flex-wrap:wrap; }
.barre-actions { display:flex; align-items:center; gap:10px; padding:16px 0; }
.bouton-plein { font-size:11.5px; letter-spacing:.04em; background:var(--inverse);
                color:var(--sur-inverse); border:none; border-radius:999px;
                padding:11px 21px; cursor:pointer; font-family:inherit; }
.bouton-vide { font-size:11.5px; letter-spacing:.04em; border:0.5px solid var(--inverse);
               border-radius:999px; padding:11px 21px; background:none; color:inherit;
               cursor:pointer; font-family:inherit; }
.sous-onglets { margin-left:auto; display:flex; gap:22px; font-size:11px;
                letter-spacing:.12em; color:var(--discret); }
.sous-onglet.actif { color:var(--texte); border-bottom:1px solid var(--texte);
                     padding-bottom:3px; }

/* Une section à concilier = une bande de titre TEINTÉE (vert pâle) + son tableau.
   La bande porte la flèche d'état (repliée/dépliée), le titre, le compteur et
   l'approbation en lot. */
/* overflow:CLIP et non hidden : hidden fait de la boîte un contexte de
   défilement, ce qui empêche l'en-tête de colonnes (position:sticky) de rester
   collé au haut de l'écran (exigence produit). clip coupe les coins pareil. */
details.groupe { margin:16px 0 0; border:0.5px solid var(--bord); border-radius:12px;
                 overflow:clip; background:var(--carte); }
details.groupe > summary { list-style:none; cursor:pointer; background:var(--vert-fond);
                           border-bottom:0.5px solid var(--bord); padding:0; }
details.groupe > summary::-webkit-details-marker { display:none; }
.groupe-titre { display:flex; align-items:center; gap:11px; padding:13px 18px; }
.fleche-groupe { color:var(--vert); font-size:11px; width:14px; }
.fleche-groupe::before { content:'›'; display:inline-block;
             transition:transform .12s ease; }
details.groupe[open] .fleche-groupe::before { transform:rotate(90deg); }
.groupe-nom { font-size:13.5px; font-weight:400; }
.compteur { font-size:13px; letter-spacing:.01em; border:0.5px solid var(--bord);
            border-radius:999px; padding:5px 13px; color:var(--texte);
            background:var(--carte); white-space:nowrap; }
.bouton-lot { margin-left:auto; font-size:11.5px; background:var(--vert); color:#fbfaf5;
              border:none; border-radius:999px; padding:8px 16px; cursor:pointer;
              font-family:inherit; white-space:nowrap; }
.tableau { background:var(--carte); border:0.5px solid var(--bord); border-radius:12px;
           overflow:clip; }
details.groupe .tableau { border:none; border-radius:0; }
.rangee { display:grid; grid-template-columns:64px 1.05fr 1.05fr 1.1fr 128px;
          font-size:12.5px; line-height:1.65; border-bottom:0.5px solid var(--bord-fin); }
.rangee:last-child { border-bottom:none; }
/* En-tête de colonnes : MÊME taille et MÊME couleur que le titre de section. */
/* L'EN-TÊTE DE COLONNES RESTE À L'ÉCRAN (demande produit 2026-08-12). Dans un
   groupe long, on descend dans les lignes et on ne sait plus quelle colonne est
   CONSTAT, laquelle est RÉSOLUTION. L'en-tête se colle donc sous le ruban.
   `--ruban-haut` est MESURÉ au chargement et au défilement (police et zoom
   variables) — voir SCRIPT. `z-index:20` : au-dessus des lignes, sous le ruban
   (60) et sous la barre d'onglets d'ECHO (50).
   ⚠️ Le collage ne fonctionne QUE si aucun ancêtre ne rogne le débordement :
   `.tableau` porte `overflow:clip` pour ses coins arrondis, ce qui neutralisait
   silencieusement le `sticky`. Dans un groupe, les coins sont déjà droits — on
   y rend donc le débordement visible (règle juste en dessous). */
.entete-t { display:grid; grid-template-columns:64px 1.05fr 1.05fr 1.1fr 128px;
            font-size:13.5px; letter-spacing:.02em; color:var(--texte); font-weight:400;
            background:var(--fond); border-bottom:0.5px solid var(--bord);
            position:sticky; top:var(--ruban-haut, 56px); z-index:20; }
/* ÉCRAN SCINDÉ : l'en-tête se colle SOUS la barre d'onglets, pas sous le ruban.
   Collé au ruban seul, il glissait DERRIÈRE la barre d'onglets (qui est à
   z-index 50) et disparaissait au défilement — le défaut exact que le collage
   devait corriger, mais uniquement quand ALTO est ouvert. Les deux repères
   s'additionnent : hauteur du ruban + hauteur de la barre d'onglets. */
body.echo-scinde .entete-t {
            top:calc(var(--ruban-haut, 56px) + var(--echo-onglets-haut, 29px)); }
details.groupe .tableau { overflow:visible; }
.entete-t div, .rangee > div { padding:12px 14px; }
.entete-t div { padding-top:14px; padding-bottom:14px; }
.col-livres { border-left:2px solid var(--vert-fond); }
.conf { font-weight:400; font-size:13.5px; }
.conf.haute { color:var(--vert); } .conf.moyenne { color:var(--jaune); }
.conf.basse { color:var(--rouge); }
.montant { font-size:14px; font-weight:400; }
.ref { font-size:11.5px; letter-spacing:.04em; color:var(--tres-faible); }
.ref a { color:var(--vert); }
.ref a:hover { text-decoration:underline; }
.gris { color:var(--discret); font-size:12.5px; }
/* Les deux gestes ont EXACTEMENT la même bulle : seule la couleur les
   distingue (retour d'écran). « exécuter » plus large que « rejeter »
   laissait croire à deux niveaux d'importance différents ; ce sont deux
   décisions de même rang, l'une positive, l'autre négative. Les formulaires
   qui les portent doivent donc s'étirer aussi, sinon le bouton se règle sur la
   largeur de son propre texte. */
.col-action { display:flex; flex-direction:column; gap:9px; align-items:stretch; }
.col-action form { display:block; width:100%; }
/* Les deux gestes de FISCO sont les boutons les plus cliqués de l'écran : ils
   méritent une cible franche, pas la taille d'un lien secondaire. */
/* Un bouton ne se coupe JAMAIS en plein mot : « remettre à traiter » sortait
   tronqué en « remettre à trait… » (vu sur capture). Il passe sur deux
   lignes si la colonne est étroite — le texte prime sur la hauteur. */
.t-fisco .col-action .mini { font-size:13px; padding:9px 14px; width:100%;
               text-align:center; white-space:normal; line-height:1.35;
               overflow-wrap:break-word; }
.t-fisco .col-action .mini.ok { border-width:1px; font-weight:400; }
/* Ce qui manque pour pouvoir exécuter, écrit LÀ où le bouton devrait être.
   Un bouton absent sans explication se lit comme une panne. */
.manque-exec { line-height:1.4; text-align:left; }
/* «Créer un nouveau compte» : la MÊME grandeur que le reste de la carte —
   c'est un choix parmi les autres, pas une alerte. */
.creer-compte { display:flex; align-items:center; gap:7px; font-size:12px;
                margin-top:7px; cursor:pointer; }
/* CRÉER UN COMPTE SOI-MÊME — sur SA propre ligne, sous les propositions
   (maquette produit). Détaché par un filet : c'est une porte de sortie, pas une
   option de plus dans la liste. Deux champs seulement, parce que QuickBooks
   n'en exige pas plus : le nom et la catégorie. */
.creer-manuel { margin-top:11px; padding-top:10px;
                border-top:0.5px solid var(--bord-fin); }
.creer-manuel-t { margin-bottom:6px; }
/* UN CONSEIL, PAS UNE ALERTE. Ce bloc dit « tranchez celle-là d'abord » — rien
   n'est cassé. Il portait un « ⚠ » en tête de constat, ce qui faisait lire
   « encore un problème » à l'ouverture de la page ; il porte maintenant une
   ampoule, et il vit en tête de la colonne RÉSOLUTION, là où on décide.
   Teinte neutre : ni rouge ni jaune, sinon on retombe sur l'alerte. */
.conseil { display:flex; gap:7px; align-items:flex-start; font-size:11.5px;
           line-height:1.45; color:var(--vert-texte); background:var(--vert-fond);
           border:0.5px solid var(--vert-fond); border-radius:7px;
           padding:8px 10px; margin:0 0 9px; }
.conseil svg { color:var(--vert); }
/* BANDE DE PRÉCISION (S-6) : l'écran met en avant ce qui est devenu AUTOMATIQUE.
   Elle ne s'affiche QUE si quelque chose a été tranché — une rangée de zéros
   dirait « cet agent n'a rien fait », l'inverse du message. */
.bande-precision { display:flex; flex-wrap:wrap; align-items:flex-end; gap:26px;
             background:var(--carte); border:0.5px solid var(--bord);
             border-radius:9px; padding:14px 18px; margin:0 0 14px; }
.mesure-prec { display:flex; flex-direction:column; gap:2px; min-width:0; }
.mesure-prec b { font-size:21px; font-weight:400; line-height:1.1; }
.mesure-prec span { font-size:11.5px; color:var(--faible); }
/* Le taux est la seule mesure teintée : c'est la question que pose le CPA. */
.mesure-prec.taux b { color:var(--vert-texte); }
.precision-note { flex:1 1 100%; line-height:1.45; margin-top:2px; }
/* ── SCRIBE ────────────────────────────────────────────────────────────────
   Grille propre à l'agent : la pièce justificative doit être LISIBLE sans être
   ouverte, donc sa colonne prend l'espace libéré par la colonne de confiance
   (le niveau vit déjà dans le titre de section). Surcharge locale : la grille de
   Concilio n'est pas touchée. */
.t-scribe .entete-t, .t-scribe .rangee { grid-template-columns:470px 168px minmax(0,1fr) 116px; }
.t-memoire .entete-t, .t-memoire .rangee { grid-template-columns:1fr 1.2fr 1.5fr 130px 110px; }
/* La dernière colonne doit contenir « voir dans QuickBooks ↗ » EN ENTIER :
   trop étroite, le bouton était coupé par l'overflow du cadre. */
.t-historique .entete-t, .t-historique .rangee { grid-template-columns:1.3fr 120px 1.5fr 150px 205px; }
/* ── FISCO ─────────────────────────────────────────────────────────────────
   Agent d'AUDIT : pas de colonne gravité (elle vit dans la bande de section,
   même logique que la confiance chez Scribe) et pas de colonne d'action (il
   n'écrit rien). Les quatre colonnes portent donc du texte : la règle nommée,
   le constat, pourquoi c'est un problème, quoi faire. Surcharge locale : les
   grilles de Concilio et Scribe ne sont pas touchées. */
/* Carte de constat : le CONSTAT prime et occupe la colonne large ; la règle et
   son fondement vivent dans un « › Détails » replié (décision produit). */
/* Maquette produit du 2026-07-28 — QUATRE colonnes :
   CONSTAT (avant) | CORRECTION (l'action) | RÉSOLUTION (après) | ACTION.

   UNE SEULE définition de colonnes, reprise par l'en-tête, la rangée de tête ET
   toutes les sous-rangées. C'est ce qui rend le vis-à-vis AVANT/APRÈS
   rigoureusement parallèle : les deux tableaux sont deux cellules d'une même
   rangée de grille, pas deux piles indépendantes dans deux colonnes. */
.t-fisco { --cols:1.42fr 0.95fr 1.42fr 124px; }
/* Parenté DIRECTE (« > ») : « .t-fisco .entete-t » attrapait AUSSI les en-têtes
   des tableaux internes (transaction, R15). Ils héritaient donc des colonnes de
   la carte ET du collage en haut d'écran, et venaient se superposer au vrai
   en-tête au défilement. Un descendant lointain ne doit jamais hériter d'une
   règle de mise en page pensée pour le niveau au-dessus. */
.t-fisco > .entete-t, .t-fisco > .constat-bloc > .rangee, .t-fisco .sous-rangee,
.t-fisco details.det-txn > summary { display:grid;
               grid-template-columns:var(--cols); }
/* L'en-tête CONSTAT | CORRECTION | RÉSOLUTION | ACTION reste collé au haut de
   l'écran pendant qu'on parcourt sa section (exigence produit). Ne fonctionne
   que parce que les conteneurs sont en overflow:clip, pas hidden. Le z-index
   doit dépasser tout ce qui défile dessous : les tableaux internes ont un fond
   OPAQUE et passaient par-dessus. */
/* EN-TÊTE PLUS MINCE (demande produit) : 46 px mesurés, cible 80 % ≈ 37 px.
   Cette barre est COLLANTE — elle reste à l'écran pendant tout le défilement,
   donc chaque pixel qu'elle prend est un pixel de travail en moins, en
   permanence. Seul le padding vertical bouge : la police et l'alignement des
   colonnes restent ceux du reste de la plateforme. */
.t-fisco > .entete-t > div { padding-top:9.5px; padding-bottom:9.5px; }
/* Collé SOUS le bandeau, pas sous le haut de la fenêtre : à 0, cet en-tête
   glissait derrière la barre de navigation et devenait illisible. La hauteur du
   bandeau est MESURÉE au chargement (voir `page()`) plutôt qu'écrite en dur :
   elle change avec la langue, le zoom et la taille d'écran, et une valeur figée
   aurait dérivé en silence — mesuré 61 px, pas les 52 supposés. */
.t-fisco > .entete-t { position:sticky; top:var(--h-bandeau, 61px); z-index:30;
               box-shadow:0 1px 0 var(--bord); }
/* Ceinture et bretelles : aucun tableau interne ne colle ni ne remonte. */
.t-fisco-txn .entete-t, .t-fisco-r15 .entete-t { position:static; z-index:auto; }
/* Filets VERTICAUX entre les quatre colonnes. Posés sur les cellules de la
   grille (bordure gauche à partir de la 2e), donc alignés au pixel avec
   l'en-tête et toutes les sous-rangées — un séparateur dessiné à part finirait
   par se décaler. En clair, le trait est un cran plus soutenu que --bord-fin :
   il doit se voir sans découper la page. */
.t-fisco { --filet:#cfc9b6; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .t-fisco {
  --filet:#4a4a52; } }
:root[data-theme="dark"] .t-fisco { --filet:#4a4a52; }
/* Sur l'EN-TÊTE SEULEMENT : les filets séparent les TITRES les uns des autres,
   ils ne découpent pas la page en quatre colonnes verticales : des traits pleine
   hauteur cloisonnaient l'écran au lieu de l'organiser (décision produit). */
.t-fisco > .entete-t > div:not(:first-child) {
               border-left:1px solid var(--filet); }
/* Confirmation avant écriture en lot. <dialog> natif : aucune dépendance. */
dialog.dlg { border:0.5px solid var(--bord); border-radius:14px; padding:22px 24px;
             max-width:460px; background:var(--carte); color:var(--texte);
             box-shadow:0 18px 44px rgba(27,28,30,.22); }
dialog.dlg::backdrop { background:rgba(27,28,30,.34); }
.dlg-t { font-size:16px; font-weight:400; margin-bottom:9px; }
.dlg-c { font-size:13px; line-height:1.55; color:var(--discret); margin-bottom:18px; }
.dlg-b { display:flex; gap:8px; justify-content:flex-end; }
/* Voile d'exécution : l'écriture dure quelques secondes, et un écran figé sans
   signe de vie fait recliquer — donc réécrire. */
.exec-voile { display:none; position:fixed; inset:0; z-index:2000;
              background:rgba(27,28,30,.42); align-items:center;
              justify-content:center; }
.exec-voile.actif { display:flex; }
.exec-boite { background:var(--carte); border:0.5px solid var(--bord);
              border-radius:14px; padding:26px 30px; text-align:center;
              font-size:13px; color:var(--texte); }
.rouet { width:26px; height:26px; margin:0 auto 12px;
         border:2.5px solid var(--bord); border-top-color:var(--vert);
         border-radius:50%; animation:tourne .8s linear infinite; }
@keyframes tourne { to { transform:rotate(360deg); } }
/* « Workflow complété ! » — avec les liens vers chaque pièce écrite. */
.termine { border:0.5px solid var(--vert); background:var(--vert-fond);
           border-radius:12px; padding:15px 17px; margin:0 0 14px; }
.termine-t { font-size:14.5px; color:var(--vert-texte); margin-bottom:5px; }
/* Un lot qui a ÉCHOUÉ ne se déguise pas en succès (vu sur l'erreur 6000). */
.termine.echec { border-color:var(--rouge); background:var(--carte); }
.termine.echec .termine-t { color:var(--rouge); }
/* LA PREUVE PAR PIÈCE (M2) : après chaque écriture, Fisco RELIT la pièce dans
   QuickBooks et affiche ce qu'il y a trouvé — « ✓ vérifié : TPS 4,13 $ +
   TVQ 8,24 $, total inchangé 95,00 $ ». Deux écritures ont été déclarées
   réussies alors qu'elles étaient fausses ; « l'API a répondu 200 » ne se dit
   plus jamais « c'est corrigé ». */
.piece-verif { display:flex; flex-wrap:wrap; align-items:center; gap:8px;
               padding:5px 0; font-size:12.5px; }
.verif-ok { color:var(--vert-texte); }
.verif-ko { color:var(--rouge); font-weight:500; }
/* L'ARBRE DE DÉCISION R15 : le 2e niveau n'apparaît qu'après le 1er choix —
   présenter les cinq options d'un coup, c'est redemander au comptable le tri
   qu'on prétend lui enlever. */
/* Masqué par défaut : c'était l'ancien 2e niveau, révélé par le sélecteur
   « vente / pas une vente ». Ce sélecteur n'existe plus — le bloc `ouvert`
   (les trois barres de R15) est TOUJOURS visible. Sans cette règle, les barres
   étaient servies dans le HTML mais restaient invisibles à l'écran : les
   vérifications qui parsent le HTML sans appliquer le CSS ne l'ont pas vu. */
.arbre-n2 { display:none; margin-top:6px; }
.arbre-n2.ouvert { display:block; }
select.cbx-in { width:100%; cursor:pointer; }
textarea.note-r15 { width:100%; resize:vertical; font-family:inherit;
                    line-height:1.45; }
.t-fisco-r15.ecart .rangee > div:last-child { padding-bottom:10px; }
/* Légende des gestes : repliée par défaut, elle ne prend la place que si on
   la demande. Deux colonnes — le geste, ce qu'il fait vraiment. */
details.legende { margin:0 0 14px; }
.t-legende { border:0.5px solid var(--bord); border-radius:10px; overflow:clip;
             background:var(--carte); margin-top:8px; }
.t-legende .rangee { grid-template-columns:190px 1fr; font-size:12.5px; }
.t-legende .rangee > div { padding:10px 14px; }
/* Liens « aller au problème dans QuickBooks » pour les constats que Fisco ne
   peut pas exécuter : sans eux, l'écran dit « à faire dans QuickBooks » et
   laisse chercher — le travail qu'on prétend justement enlever. */
.liens-pieces { display:flex; flex-wrap:wrap; align-items:center; gap:6px;
                margin-top:8px; }
.liens-pieces .ref { flex:0 0 100%; }
/* Barre d'outils d'une section : « tout ouvrir/fermer » pour les Détails et
   pour les Justifications — la page se ramène à une vue simple en deux clics. */
/* LES BASCULES SONT DANS LA BANDE, plus sur une ligne blanche à elles. Cette
   ligne coûtait une bande de hauteur permanente pour deux boutons — du bruit
   pur. Dans le <summary>, elles ne coûtent RIEN, et elles s'effacent quand la
   section est repliée : proposer d'ouvrir les détails d'une section fermée
   n'aurait aucun sens. */
/* LES TROIS PASTILLES DE LA BANDE forment UNE famille, collées à droite :
   « Détails », « Justifications », « Exécuter le lot ». MÊME taille de texte et
   MÊME taille de bulle pour les trois — seule la couleur distingue l'action qui
   écrit. Des bulles de tailles différentes dans un même ruban donnent
   l'impression de trois éléments sans rapport. */
.actions-bande { display:inline-flex; gap:7px; align-items:center;
                 margin-left:auto; }
.outils-bande { display:inline-flex; gap:7px; align-items:center; }
details.groupe:not([open]) .outils-bande { display:none; }
/* `line-height` FIXE, sinon le contenu décide de la hauteur : le « ✓ » du
   bouton de lot étire sa ligne et le rendait 1 px plus haut que ses voisins
   (mesuré 33 px contre 32). Trois bulles qui ne s'alignent pas exactement se
   remarquent, même sans savoir pourquoi. */
.outils-bande button, .actions-bande .bouton-lot {
                 font-size:11.5px; letter-spacing:normal; line-height:1.3;
                 border-radius:999px; padding:8px 16px; cursor:pointer;
                 font-family:inherit; white-space:nowrap;
                 display:inline-flex; align-items:center; gap:6px; }
.outils-bande button { border:0.5px solid var(--bord); color:var(--discret);
                 background:var(--carte); }
.outils-bande button:hover { color:var(--texte); }
/* LE BOUTON DE LOT EST EN VIS-À-VIS DU BOUTON « exécuter » des cartes (demande
   produit) : même largeur (96 px) et même axe vertical, si bien que le geste de
   lot se lit comme la version « toute la section » du geste unitaire.
   MESURE QUI A IMPOSÉ CE CHOIX : le bouton faisait 139 px pour une colonne
   ACTION de 124 — le centrer tel quel l'aurait fait DÉBORDER de 8 px hors de la
   bande. On ne pousse donc pas le bouton vers la colonne : on lui donne la
   taille de la colonne, ce qui aligne les deux d'un coup.
   `margin-right:-4px` ramène la zone d'actions sur le padding des CELLULES
   (14 px) et non sur celui de la bande (18 px) : c'est l'axe des boutons
   « exécuter » qui fait référence, pas le bord de la bande. */
.actions-bande { margin-right:-4px; }
/* LARGEUR RENDUE AU TEXTE (demande produit, 2026-08-12). La contrainte à 96 px
   alignait le bouton sur la colonne ACTION, mais elle TRONQUAIT « Approuver le
   lot » / « Approve the batch ». Un bouton dont on ne lit pas l'intitulé ne
   s'aligne plus avec rien. Le bouton reprend donc la largeur de son écriture
   (`width:auto` + padding normal), avec un plancher à 96 px pour conserver
   l'axe vertical quand le libellé est court. */
.actions-bande .bouton-lot { margin-left:0; border:0.5px solid var(--vert);
                 width:auto; min-width:96px; padding-left:16px;
                 padding-right:16px; justify-content:center; }
/* LA JUSTIFICATION DE LA RÈGLE, une seule fois pour tout le groupe. Elle était
   répétée à l'identique sur chaque constat (quatre fois pour R2) : le même
   texte relu quatre fois n'apprend rien la deuxième. Fermée par défaut. */
.panneau-just { display:none; background:var(--carte); font-size:12px;
                 line-height:1.55; color:var(--discret);
                 border-bottom:0.5px solid var(--bord-fin); padding:13px 18px; }
.panneau-just.ouvert { display:block; }
.panneau-just .just-texte { margin-bottom:7px; }
.panneau-just .just-texte:last-child { margin-bottom:0; }
/* LA MÊME FLÈCHE QUE LES REPLIABLES qu'elles commandent : un bouton qui ouvre
   des « › » doit porter un « › ». Il pivote quand TOUT est ouvert. */
.fl-outil::before { content:'›'; display:inline-block; color:var(--tres-faible);
                 transition:transform .12s ease; }
.outils-bande button.ouvert .fl-outil::before { transform:rotate(90deg); }
/* La résolution R15 : les transactions qui expliquent l'écart.
   Colonnes recalibrées sur retour d'écran : la transaction se lit en une
   pile courte (lien / date / compte / côté), le MONTANT a la place de son plus
   large chiffre, et LA DÉCISION — la seule colonne où le comptable agit —
   prend tout le reste. */
/* Moitié / moitié : avec une colonne de montant étroite, « MONTANT (CAD) »
   se collait au bord droit et la transaction mangeait tout le reste. Deux
   moitiés égales posent le montant au centre du tableau, là où l'œil le
   cherche. */
.t-fisco-r15.ecart .entete-t, .t-fisco-r15.ecart .rangee {
               grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
/* La 3e colonne (VOTRE DÉCISION) n'existe plus dans la rangée du haut : le
   sélecteur passe SOUS la transaction, sur toute la largeur du tableau. Dans
   une colonne de ~370 px, trois colonnes ne tenaient pas — et élargir le
   tableau le faisait déborder sur les colonnes voisines de la carte. */
.t-fisco-r15.ecart .entete-t > div:nth-child(3) { display:none; }
/* Le montant se cale au DÉBUT de sa moitié — donc au centre du tableau, sous
   son en-tête — plutôt qu'au bord droit. */
.t-fisco-r15.ecart .montant { text-align:left; }
/* Le texte revient à la ligne AU MOT, jamais au caractère : sans ça
   « Subvention gouvernementale » descendait en colonne, une syllabe par ligne
   (vu sur capture). C'est le même réglage que « renvoyer à la ligne
   automatiquement » d'un tableur. */
.t-fisco-r15.ecart .rangee > div { overflow-wrap:break-word; word-break:normal;
               hyphens:none; min-width:0; }
.cell-txn, .cell-decision { display:flex; flex-direction:column; gap:3px;
               align-items:flex-start; }
.cell-decision { gap:6px; }
/* Le 2e niveau de l'arbre sort de la grille : il n'a aucune raison de
   s'aligner sur les colonnes du haut — ce ne sont pas les mêmes informations,
   et la zone de texte y était écrasée dans un couloir. */
/* CHAQUE TABLEAU DANS SA COLONNE : le tableau de l'écart appartient à
   RÉSOLUTION et n'en sort pas. Il avait été élargi sur trois colonnes pour
   donner de l'air au choix — mais déborder sur CORRECTION et ACTION casse la
   lecture en colonnes de toute la page. L'air se prend À L'INTÉRIEUR : la
   ligne du haut reste compacte, le choix s'étale dessous (voir .arbre-suite). */
/* LE CLIC NE PORTE QUE SUR LES TITRES. Le `summary` couvre toute la largeur :
   cliquer au-dessus de « Justification » — une zone vide, sans rien à lire —
   repliait les deux tableaux d'un coup (retour d'écran). Les cellules vides du
   titre ne captent plus rien. */
details.det-txn > summary { pointer-events:none; }
details.det-txn > summary > span { pointer-events:auto; }
details.det-txn > summary > span:empty { pointer-events:none; }
/* ── RÈGLE GÉNÉRALE : AUCUN TEXTE NE TOUCHE UNE BORDURE ────────────────────
   Posée en revue d'écran le 2026-08-08 après avoir vu « 1 200.00 $ » mordre le bord
   de sa cellule (mesuré : 3 px de DÉBORDEMENT). Elle vaut dans les deux sens,
   horizontal ET vertical, et pour toute bordure — cadre, filet, bord de
   colonne. Un chiffre collé au trait se lit comme une erreur de rendu, et sur
   un écran qu'on montre à un comptable, ça suffit à faire douter du reste.
   Deux conséquences tenues partout : une colonne se dimensionne sur son cas le
   PLUS LARGE (jamais sur le plus fréquent), et un montant ne se coupe jamais
   (`white-space:nowrap`) — mieux vaut une colonne large qu'un chiffre tronqué. */
.montant, .t-fisco-r15 .montant, .t-fisco-txn .montant { white-space:nowrap; }
/* DE L'AIR AVANT CHAQUE QUESTION DE L'ARBRE R15 (retour d'écran 2026-08-08) :
   le libellé « Catégorie » ou « Taxes » se collait à la barre intelligente du
   dessus, si bien que les questions se lisaient comme un seul pavé. Le libellé
   appartient à la barre qui le SUIT, pas à celle qui le précède : c'est
   l'espace au-dessus qui le dit. */
.rangee-choix { margin-top:16px; }
.rangee-choix:first-child { margin-top:0; }
.rangee-choix > .ref { margin-bottom:6px; }
/* La catégorie ne se demande qu'une fois le nom écrit — sans nom, la question
   n'a pas d'objet (décision produit). */
.rangee-cat { display:none; }
.rangee-cat.ouvert { display:block; }
/* Le rappel d'enregistrer, sous les barres : le comptable peut choisir sans
   rien enregistrer et croire que c'est fait. Un conseil, pas une alerte. */
.conseil-enregistrer { margin-top:14px; font-size:11.5px; line-height:1.45;
                color:var(--vert-texte); background:var(--vert-fond);
                border-radius:7px; padding:8px 11px; }
/* « Aucune taxe sur ce type de compte » : une EXPLICATION à la place d'une
   barre — pas une alerte, pas un champ. QuickBooks refuse tout code de taxe
   sur les comptes clients/fournisseurs (relevé en réel). */
.note-sans-taxe { line-height:1.5; }
/* DE L'AIR AU-DESSUS DE « VOTRE DÉCISION » (retour d'écran) : le bloc de choix
   démarrait à ras de la ligne de la transaction, si bien que la question et la
   donnée se lisaient comme un seul pavé. On respire avant de décider. */
.arbre-suite { padding:11px 10px 13px; background:var(--fond); }
.arbre-suite > .ref { margin-bottom:5px; }
.arbre-suite .arbre-n2 { max-width:520px; }
.select-arbre { width:100%; }
/* La décision déjà prise est du TEXTE, pas une pastille : `.drapeau` est ronde
   et faite pour un mot — autour d'une phrase de quatre lignes elle dessinait un
   grand ovale blanc au milieu du tableau. */
.decision-prise { display:flex; flex-direction:column; gap:3px;
               align-items:flex-start; }
.decision-libelle { font-size:12px; color:var(--texte); }
/* PAS D'HISTORIQUE EMPILÉ sur la carte d'un constat exécuté (décision produit,
   2026-08-10) : seul le DERNIER enregistrement s'affiche — l'état de la pièce.
   La chronologie complète vit au registre DOVADA, qui alimente le dossier de
   pré-clôture : c'est là qu'un vérificateur la cherche, pas sur l'écran de
   travail. */
/* Une carte = la rangée de tête + ses sous-rangées. Le trait de séparation
   appartient à la CARTE, pas à chaque rangée : sinon un trait coupait le
   constat de ses propres transactions. */
.t-fisco .constat-bloc { border-bottom:0.5px solid var(--bord-fin); }
.t-fisco .constat-bloc:last-child { border-bottom:none; }
.t-fisco .constat-bloc > .rangee { border-bottom:none; }
.t-fisco .sous-rangee > div { padding:0 14px 12px; min-width:0; }
.t-fisco .sous-rangee > div:empty { padding:0; }
/* Le détail d'UNE transaction : catégorie, montant, taxe. Replié par défaut —
   le comptable ouvre la pièce seulement quand il l'examine. Le résumé porte le
   même libellé dans les DEUX colonnes, et un seul clic ouvre les deux tableaux :
   ils ne peuvent donc jamais se retrouver désalignés. */
.t-fisco-txn { border:0.5px solid var(--bord); border-radius:8px;
               background:var(--fond); margin-top:2px; }
.t-fisco-txn .entete-t, .t-fisco-txn .rangee {
               grid-template-columns:minmax(0,1.15fr) 84px minmax(0,1.3fr);
               font-size:11.5px; }
.t-fisco-txn .entete-t div, .t-fisco-txn .rangee > div { padding:7px 9px; }
.t-fisco-txn .montant { text-align:right; white-space:nowrap; }
.t-fisco-txn .rangee:last-child > div:first-child { border-bottom-left-radius:8px; }
.t-fisco-txn .cbx { max-width:none; }
.t-fisco-txn .cbx-in { padding:5px 8px; background:var(--carte); color:var(--texte);
               border:0.5px solid var(--bord); border-radius:6px; font-size:11.5px; }
details.det-txn > summary { cursor:pointer; list-style:none; }
details.det-txn > summary::-webkit-details-marker { display:none; }
details.det-txn > summary > span { padding:2px 14px 4px; font-size:12px;
               color:var(--texte); min-width:0; }
details.det-txn > summary > span:not(:empty)::before { content:'›';
               color:var(--tres-faible); display:inline-block; width:.6em;
               margin-right:.4em; transition:transform .12s ease; }
details.det-txn[open] > summary > span:not(:empty)::before {
               transform:rotate(90deg); }
.lien-txn { text-align:right; padding-right:2px; margin-top:4px; font-size:11.5px; }
.lien-txn a { color:var(--vert-texte); text-decoration:none; }
.lien-txn a:hover { text-decoration:underline; }
/* L'ACTION concrète en tête de la colonne CORRECTION : c'est ce qu'on décide,
   donc c'est ce qu'on lit en premier. La justification se replie en dessous. */
.action-agent, .action-main { font-size:13px; line-height:1.45; }
.action-main { color:var(--texte); }

/* R15 : deux totaux face à face, même geste visuel que BANQUE ↔ LIVRES. */
.t-fisco-r15 { border:0.5px solid var(--bord); border-radius:10px; overflow:hidden;
               background:var(--fond); margin-top:2px; }
/* minmax(0,…) et non 1.4fr : sans le minimum à zéro, une colonne de grille
   refuse de descendre sous la largeur de son plus long mot, et l'en-tête
   « VENTES QUI ALIMENTENT LA DÉCLARATION » faisait déborder tout le tableau. */
/* RETOUR À 96px, ET LA MESURE DIT POURQUOI (2026-08-08) : à 82px, « 1 200.00 $ »
   dépassait de 3px hors de sa cellule — le seul montant de l'écran à toucher une
   bordure, relevé à l'oeil puis confirmé au pixel. 82px avait été calculé pour
   des montants SANS décimales ; un montant à cents (« 1 200.75 $ ») n'y entre
   pas. La colonne se dimensionne sur le cas le plus large, jamais sur le plus
   fréquent — sinon le débordement revient au premier chiffre irrégulier. */
.t-fisco-r15 .entete-t, .t-fisco-r15 .rangee {
               grid-template-columns:minmax(0,1fr) 96px minmax(0,1fr) 96px;
               font-size:11px; }
/* UN MOT NE SE COUPE JAMAIS EN PLEIN MILIEU. « DÉCLARATION » sortait
   « DÉCLARATI / ON » dans une colonne étroite : illisible, et pire qu'un mot
   qui dépasse. `overflow-wrap:normal` laisse le mot entier ; c'est la colonne
   qui s'adapte. */
.t-fisco-r15 .entete-t div, .t-fisco-r15 .rangee > div {
               overflow-wrap:normal; word-break:keep-all; hyphens:none; }
.t-fisco-r15 .entete-t div, .t-fisco-r15 .rangee > div { padding:6px 10px; }
.t-fisco-r15 .montant { text-align:right; white-space:nowrap;
               font-variant-numeric:tabular-nums; }
/* États d'un constat : discrets, ils informent sans crier. */
.drapeau.etat-resolu { border-color:var(--vert); background:var(--vert-fond);
                       color:var(--vert-texte); }
.drapeau.etat-rejete { border-color:var(--bord); background:var(--fond);
                       color:var(--discret); }
/* EXCEPTION DOCUMENTÉE : l'écart persiste PAR DÉCISION du comptable. Ni vert
   (rien n'est résolu) ni rouge (rien ne cloche) — un état neutre et assumé, qui
   ne promet aucune résolution future. */
.drapeau.etat-exception_documentee { border-color:var(--bord);
                       background:var(--carte); color:var(--texte); }
/* Les justifications se LISENT : interligne aéré et paragraphes de deux
   phrases. Un pavé serré de six lignes, personne ne le lit — et c'est
   justement le texte qui explique POURQUOI une correction est proposée. */
/* Avertissement de pièce délicate (payée, rattachée à un paiement) : il
   PRÉVIENT, il ne bloque pas — la correction reste sûre puisque le total ne
   bouge jamais. Discret mais visible avant le clic, pas après. */
.avert-piece { margin-top:7px; font-size:11.5px; line-height:1.5;
               color:var(--jaune); border-left:2px solid var(--jaune-bord);
               padding:2px 0 2px 9px; border-radius:0; }
/* Conflit entre deux corrections sur la MÊME ligne : plus grave qu'une pièce
   délicate — ici, exécuter les deux produirait une écriture fausse. */
.avert-piece.conflit { color:var(--rouge); border-left-color:var(--rouge); }
/* R10 — les fiches fournisseur à compléter. Deux champs LIBRES : ces numéros
   viennent de la facture papier, pas d'une liste du dossier. */
.t-fiches { border:0.5px solid var(--bord); border-radius:10px; overflow:clip;
            background:var(--fond); }
.t-fiches .entete-t, .t-fiches .rangee {
            grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) minmax(0,1fr);
            font-size:11.5px; }
.t-fiches .entete-t div, .t-fiches .rangee > div { padding:6px 10px; }
input.champ-num { font-family:var(--mono, inherit); letter-spacing:.02em; }
.just-texte { line-height:1.5; }
/* La NATURE de la dépense : ce qui répond à « cette dépense-CI porte-t-elle de
   la taxe ? ». Distincte du fondement de la règle, qui reste en dessous. */
.nature-bloc { margin-top:6px; padding:8px 10px; background:var(--carte);
               border:0.5px solid var(--bord); border-radius:8px; }
.nature-bloc + .nature-bloc { margin-top:8px; }
/* Bandeau de PORTÉE : ce que la page fait, et ce qu'elle ne fait PAS ENCORE.
   Un comptable qui cherche l'impôt sur le revenu doit le savoir tout de suite. */
.flash.portee { line-height:1.6; }
.just-texte + .just-texte { margin-top:8px; }
/* L'arbre R15 est ouvert par défaut : c'est LA question posée au comptable,
   la cacher derrière un repliable revenait à lui faire chercher son travail. */
details.det-txn.r15 > summary { font-weight:500; }
/* Onglet FONDEMENTS : la règle, les articles de loi (ELIADE), la question posée. */
.t-fondements { background:var(--carte); border:0.5px solid var(--bord);
                border-radius:12px; overflow:hidden; }
.t-fondements .entete-t, .t-fondements .rangee {
                grid-template-columns:230px 1.15fr 1.25fr; }
a.mini { display:inline-block; text-decoration:none; }
.t-memoire, .t-historique { background:var(--carte); border:0.5px solid var(--bord);
                            border-radius:12px; overflow:hidden; }
/* Le cadre de la pièce : mêmes dimensions pour un PDF embarqué (iframe, défilable)
   et pour un scan (img). Fond blanc dans les deux thèmes — une facture est un
   document papier, elle ne s'inverse pas en mode sombre. */
.apercu-piece { display:block; width:100%; height:318px; border:0.5px solid var(--bord);
                border-radius:7px; background:#fff; }
img.apercu-piece { object-fit:cover; object-position:top center; }
iframe.apercu-piece { color-scheme:light; }
.piece-lien { font-size:10.5px; color:var(--tres-faible); display:block; margin-top:7px; }
.etiq { font-size:10px; letter-spacing:.1em; color:var(--tres-faible); }
.val { font-size:12.5px; margin-top:3px; }
.sep-fin { border-top:0.5px solid var(--bord-fin); margin:12px 0; }
.taxe-just { font-size:11px; color:var(--vert-texte); background:var(--vert-fond);
             border-left:2px solid var(--vert); padding:9px 11px; margin-top:10px;
             line-height:1.6; }
.taxe-just a { color:inherit; text-decoration:underline; }
/* Deux niveaux de repli, même grammaire que les sections : une flèche, un mot.
   Au repos la ligne ne dit que « Détails » ; la source ne dit que « ↳ Source ». */
details.det > summary, details.det-src > summary { cursor:pointer; list-style:none;
             font-size:11.5px; color:var(--faible); }
details.det > summary::-webkit-details-marker,
details.det-src > summary::-webkit-details-marker { display:none; }
/* UNE SEULE FLÈCHE POUR TOUTE LA PLATEFORME (décision produit, 2026-08-04) :
   un chevron « › » à GAUCHE du titre, qui pivote vers le bas à l'ouverture.
   Un chevron qui tourne dit « ceci s'ouvre » mieux que deux glyphes différents,
   et il reste lisible à 11 px là où les anciens triangles bavaient. */
details.det > summary::before { content:'›'; color:var(--tres-faible);
             display:inline-block; width:.6em; margin-right:.4em;
             transition:transform .12s ease; }
details.det[open] > summary::before { transform:rotate(90deg); }
details.det > summary:hover, details.det-src > summary:hover { color:var(--texte); }
details.det-src { margin-top:7px; }
details.det-src > summary { color:var(--vert-texte); font-size:10.5px; }
details.det-src > summary::before { content:''; }
details.det-src > summary::after { content:' ›'; display:inline-block;
             transition:transform .12s ease; }
details.det-src[open] > summary::after { transform:rotate(90deg); }
details.det-src a { display:inline-block; margin-top:5px; font-size:10.5px; }
.drapeau { display:inline-block; font-size:10px; border-radius:999px; padding:3px 9px;
           margin:0 5px 5px 0; border:0.5px solid var(--jaune-bord);
           background:var(--jaune-fond); color:var(--jaune); }
select.champ-taxe, input.champ-motif { font-family:inherit; font-size:12px; font-weight:300;
                    padding:8px 11px; border:0.5px solid var(--bord); border-radius:6px;
                    background:var(--fond); color:var(--texte); width:100%; }
.t-scribe .cbx { max-width:none; }
.t-scribe .cbx-in { padding:8px 11px; background:var(--fond); color:var(--texte);
                    border:0.5px solid var(--bord); border-radius:6px; font-size:12.5px; }
.badge-corrige { display:inline-block; margin-top:5px; font-size:10px;
                 border:0.5px solid var(--jaune-bord); background:var(--jaune-fond);
                 color:var(--jaune); border-radius:999px; padding:3px 9px; }
/* « approuver » et « rejeter » ont la MÊME taille et leur mot est CENTRÉ
   (demande produit, 2026-08-12). Sans largeur commune, deux boutons empilés
   dans la colonne ACTION avaient des bords qui ne s'alignaient pas — le mot le
   plus long dictait sa largeur, et la paire se lisait de travers. `min-width`
   plutôt qu'une largeur fixe : l'anglais (« approve » / « reject ») et le
   français tiennent tous les deux, et un libellé plus long s'étendrait au lieu
   d'être tronqué (la leçon du bouton de lot, juste au-dessus). */
.mini { font-size:12px; border:0.5px solid var(--bord); background:none; color:inherit;
        border-radius:999px; padding:6px 15px; cursor:pointer; font-family:inherit;
        white-space:nowrap; min-width:104px; display:inline-flex;
        align-items:center; justify-content:center; text-align:center; }
.mini.ok { border-color:var(--vert); color:var(--vert); }
.mini.no { border-color:var(--bord); color:var(--discret); }
.mini:hover { background:var(--fond); }
.vide { padding:60px 20px; text-align:center; color:var(--discret); font-size:13.5px; }
.stats { font-size:13px; color:var(--discret); }
.eyebrow { color:var(--discret); }

/* ── Tableau de bord ─────────────────────────────────────────────────────── */
.tuiles { display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
          gap:14px; margin:20px 0 28px; }
.tuile { background:var(--carte); border:0.5px solid var(--bord); border-radius:12px;
         padding:18px 20px; }
.tuile-libelle { font-size:11px; letter-spacing:.13em; color:var(--discret); }
.tuile-valeur { font-size:34px; font-weight:200; letter-spacing:-.02em; margin:8px 0 2px;
                line-height:1.05; }
.tuile-detail { font-size:12px; color:var(--discret); }
.cartes { display:grid; grid-template-columns:repeat(auto-fit,minmax(270px,1fr)); gap:14px; }
.carte-agent { background:var(--carte); border:0.5px solid var(--bord); border-radius:12px;
               padding:20px 22px; display:flex; flex-direction:column; gap:2px; }
.carte-agent:hover { border-color:var(--vert); }
.carte-num { font-size:11px; letter-spacing:.14em; color:var(--tres-faible); }
.carte-nom { font-size:25px; font-weight:200; margin:5px 0 2px; }
.carte-sous { font-size:12.5px; color:var(--discret); }
.carte-mesures { margin-top:14px; padding-top:13px; border-top:0.5px solid var(--bord-fin);
                 display:flex; flex-direction:column; gap:6px; font-size:12.5px; }
.mesure { display:flex; justify-content:space-between; gap:10px; color:var(--discret); }
.mesure b { color:var(--texte); font-weight:400; }
.etiquette { display:inline-block; font-size:10.5px; letter-spacing:.06em; padding:3px 10px;
             border-radius:999px; border:0.5px solid var(--bord); color:var(--discret);
             align-self:flex-start; margin-top:10px; }
.etiquette.vif { background:var(--vert-fond); border-color:var(--vert-fond);
                 color:var(--vert-texte); }
details.corr summary { cursor:pointer; color:var(--vert); font-size:11px; margin-top:6px;
                       list-style:none; }
details.corr summary::-webkit-details-marker { display:none; }
details.corr form { margin-top:7px; display:flex; flex-direction:column; gap:6px; }
input[name=motif] { font-family:inherit; font-size:12px; font-weight:300; padding:6px 10px;
                    border:0.5px solid var(--bord); border-radius:6px; background:var(--fond);
                    color:var(--texte); }
.flash { background:var(--vert-fond); color:var(--vert-texte); border-radius:10px;
         padding:12px 16px; font-size:12.5px; margin:14px 0; }
.rapport-md { background:var(--carte); border:0.5px solid var(--bord); border-radius:12px;
              padding:20px 24px; font-size:13px; line-height:1.75; }
.rapport-md table { border-collapse:collapse; width:100%; font-size:12px; margin:10px 0; }
.rapport-md th, .rapport-md td { text-align:left; padding:7px 10px;
                                 border-bottom:0.5px solid var(--bord-fin); }
.rapport-md h1 { font-size:22px; font-weight:200; }
.rapport-md h2 { font-size:15px; font-weight:400; margin-top:22px; }
/* h3 : les constats d'un rapport d'audit. Sans cette règle, un « ### » de
   markdown s'affichait en clair dans la page (défaut vu le 2026-07-27). */
/* V9 — Filtres du rapport : le patron lit le sommaire, le technicien les
   transactions, le CPA les fondements. Multi-sélection, choix mémorisé. */
.filtres-rapport { display:flex; flex-wrap:wrap; align-items:center; gap:7px;
                   margin:0 0 14px; }
.filtres-rapport .chip { font-size:11.5px; letter-spacing:.02em; cursor:pointer;
                   border:0.5px solid var(--bord); border-radius:999px;
                   padding:5px 13px; background:var(--carte);
                   color:var(--tres-faible); font-family:inherit; }
.filtres-rapport .chip:hover { color:var(--texte); }
.filtres-rapport .chip.actif { background:var(--vert-fond); color:var(--vert-texte);
                   border-color:var(--vert); }
.filtres-rapport .raz { border-style:dashed; }
.rapport-md h3 { font-size:13.5px; font-weight:400; margin:18px 0 2px;
                 color:var(--texte); }
@media (max-width:900px) {
  .rangee, .entete-t { grid-template-columns:1fr; }
  .col-livres { border-left:none; border-top:2px solid var(--vert-fond); }
  .onglets { overflow-x:auto; }
}

 .cbx { position:relative; max-width:440px; }
 /* Le champ garde la couleur de la page : c'est l'encadré qui dit « on tape ici ».
    Aucune couleur en dur — sinon le champ devient illisible en mode sombre. */
 .cbx-in { width:100%; padding:8px 11px; font-size:13px; font-family:inherit;
           font-weight:inherit; color:var(--texte,#1f2933);
           background:var(--fond,#fff); border:1px solid var(--bord,#dde1e6);
           border-radius:8px; outline:none; }
 .cbx-in:focus { border-color:var(--vert,#1a7f5a);
                 box-shadow:0 0 0 3px var(--vert-fond,#e6f4ee); }
 .cbx-in::selection { background:var(--vert-fond,#e6f4ee); color:var(--texte,#1f2933); }
 /* La liste est une BOÎTE nette posée par-dessus la page : surface distincte,
    bordure franche, ombre portée. Elle ne pousse jamais le contenu.

    position:FIXED, et non absolute : en absolute, le moindre ancêtre en
    `overflow:hidden` (le cadre d'un groupe, un tableau à coins arrondis) COUPE
    la liste — elle disparaissait purement et simplement quand le champ était sur
    la dernière ligne d'un tableau. En fixed, la liste sort du flux et n'est
    clippée par personne ; sa position est calculée en JS à l'ouverture. */
 .cbx-liste { position:fixed; z-index:1000; margin:0;
              background:var(--carte,#fff); border:1px solid var(--bord,#dde1e6);
              border-radius:10px; max-height:270px; overflow:auto; display:none;
              box-shadow:0 10px 28px rgba(27,28,30,.16); }
 .cbx-liste .grp { font-size:11px; text-transform:uppercase; letter-spacing:.06em;
                   color:var(--discret,#7b8794); padding:9px 13px 5px;
                   background:var(--fond,#f7f8fa);
                   border-bottom:0.5px solid var(--bord-fin,#eceae1);
                   position:sticky; top:0; }
 /* Le logo DOVADA en tête des recommandés — à la place de l'étoile (demande
    produit) : les recommandations sont la signature de la maison.
    Le tracé est INTÉGRÉ (voir `logo_marque`) : sa largeur vient du viewBox, il
    prend la couleur du titre par `currentColor`, et aucun filtre d'inversion
    n'est nécessaire — en sombre, le titre s'éclaircit et le logo avec lui.
    TAILLE ET PLACE réglées à l'œil puis MESURÉES (retour d ecran) : un peu
    plus grand (14 px), et décalé à gauche pour se poser AU MILIEU de la marge
    qui précède le mot « Recommandés » — le `margin-left` négatif le sort du
    retrait du titre sans toucher au texte, qui reste aligné sur les options. */
 .cbx-liste .grp-logo { height:14px; width:auto; vertical-align:-3px;
                        margin-left:-6px; margin-right:7px; }
 /* Chaque choix respire : libellé complet sur 2 lignes au besoin, jamais
    tronqué ni coincé (retour d'usage sur les cellules étroites). */
 .cbx-liste .opt { padding:9px 14px; cursor:pointer; font-size:12.5px;
                   color:var(--texte,#1f2933); line-height:1.5;
                   white-space:normal; overflow-wrap:break-word;
                   border-bottom:0.5px solid var(--bord-fin,#eceae1); }
 .cbx-liste .opt:last-child { border-bottom:none; }
 .cbx-liste .opt:hover { background:var(--vert-fond,#e6f4ee); }
 .cbx-liste .opt.reco { font-weight:500; }
 .cbx-liste .vide-opt { padding:11px 13px; color:var(--discret,#7b8794); font-size:12.5px; }
 /* V8 — la flèche « pourquoi ce choix ? », tout à droite de l'option. Elle
    EXPLIQUE, elle ne choisit pas : son clic n'entraîne aucune sélection. */
 .cbx-liste .opt { display:flex; align-items:flex-start; gap:8px; }
 .cbx-liste .opt-lib { flex:1; min-width:0; }
 .cbx-liste .opt-just { flex:0 0 auto; color:var(--tres-faible,#8a8a92);
                        padding:0 2px; border-radius:4px; cursor:help;
                        font-size:11px; line-height:1.6; }
 .cbx-liste .opt-just:hover { color:var(--vert,#1a7f5a);
                              background:var(--vert-fond,#e6f4ee); }
 /* Le panneau s'ouvre À DROITE de la liste (à gauche s'il n'y a pas la place). */
 .cbx-just { position:fixed; z-index:1001; display:none; padding:13px 15px;
             background:var(--carte,#fff); border:1px solid var(--bord,#dde1e6);
             border-radius:10px; box-shadow:0 10px 28px rgba(27,28,30,.18);
             max-height:340px; overflow:auto; }
 .cbx-just-t { font-size:13px; font-weight:500; color:var(--texte,#1f2933);
               margin-bottom:7px; }
 .cbx-just-av { font-size:12px; line-height:1.5; color:var(--jaune,#7a5c00);
                background:var(--jaune-fond,#fdf3d0); border-radius:6px;
                padding:7px 9px; margin-bottom:8px; }
 .cbx-just-r { font-size:12.5px; line-height:1.55; color:var(--texte,#1f2933);
               margin-bottom:8px; }
 .cbx-just-b { font-size:12px; line-height:1.55; color:var(--discret,#4a4a50); }
 .cbx-just-s { display:inline-block; margin-top:9px; font-size:12px;
               color:var(--vert-texte,#14563e); text-decoration:underline; }
 /* ── MODE « DÉTAILS EN LIGNE » (demande produit, 2026-08-08) ─────────────────
    Le panneau latéral ci-dessus répond à « pourquoi cette valeur ? » d'un mot.
    Quand la question est « dans QUELLE SITUATION utiliserais-je ce compte pour
    CE dépôt ? », la réponse est un paragraphe, et elle doit se lire SOUS
    l'option, sans quitter la liste — c'est la conversation qu'on aurait eue
    avec un collègue, transposée dans la barre. Deux modes coexistent : une
    famille déclare le sien, les agents frères gardent la flèche latérale. */
 .cbx-liste .opt-neuf { color:var(--tres-faible,#8a8a92); font-weight:400;
                        margin-left:6px; }
 .cbx-liste .opt-details { flex:0 0 auto; font-family:inherit; font-size:11px;
                        line-height:1.3; border:0.5px solid var(--bord,#dde1e6);
                        border-radius:999px; padding:4px 11px; cursor:pointer;
                        background:var(--carte,#fff); color:var(--discret,#4a4a50);
                        display:inline-flex; align-items:center; gap:5px;
                        white-space:nowrap; }
 .cbx-liste .opt-details:hover { color:var(--texte,#1f2933);
                        border-color:var(--vert,#1a7f5a); }
 /* Même grammaire de flèche que partout ailleurs : un chevron qui pivote. */
 .cbx-liste .opt-details::before { content:'›'; display:inline-block;
                        transition:transform .12s ease; }
 .cbx-liste .opt-details.ouvert::before { transform:rotate(90deg); }
 /* LE RUBAN : blanc, pour se détacher du gris de la liste (choix produit).
    En sombre, « blanc » devient la surface la plus claire disponible — un vrai
    blanc y brûlerait l'écran. */
 .cbx-liste .opt-ruban { display:none; padding:10px 15px 13px; font-size:12px;
                        line-height:1.55; color:var(--texte,#1f2933);
                        background:var(--ruban,#ffffff);
                        border-bottom:0.5px solid var(--bord-fin,#eceae1); }
 .cbx-liste .opt-ruban.ouvert { display:block; }


/* La colonne de lecture d'ECHO NEO, reprise telle quelle : 740 px centres.
   Au-dela, l'oeil perd la ligne en revenant a la marge gauche. */
.echo { --echo-lecture:740px; --echo-controle:40px;
        display:grid; gap:0; background:var(--carte); overflow:hidden; }
/* Pas de bordure, pas de coins arrondis : le chat n'est pas une CARTE posee
   sur la page, il EST la page. Une carte dans une page qui a deja un ruban
   gris ajoute un second cadre pour rien — c'est le bruit que Sebastian
   pointait. Seul le panneau lateral garde un liseré, parce qu'il partage
   l'ecran avec autre chose. */
/* 🐛 `.echo` porte `overflow:hidden`. Un bouton pose dessus en `top:-40px`
   etait donc DECOUPE : present dans le document, invisible a l'ecran et
   inatteignable au clic — et `getBoundingClientRect()` le mesurait quand meme
   a la bonne place, ce qui m'a fait croire qu'il etait la.
   La bande du haut appartient donc a une ENVELOPPE, en dehors de la zone
   decoupee. Le repli de hauteur (150 -> 194) suit ces 44 px, sinon la page se
   remettrait a defiler. */
.echo-enveloppe { position:relative; padding-top:44px; }
.echo.pleine { grid-template-columns:270px 1fr;
               height:calc(100vh - var(--echo-tete, 194px)); min-height:420px; }
.echo.echo-vue-panneau { grid-template-columns:1fr; height:100%; }

/* ── La barre laterale, facon Claude/ChatGPT ────────────────────────────────
   Trois sections repliables (Projets / Clavardage / Corbeille), lignes d'UNE
   seule hauteur avec ellipse — la longueur visible depend de la largeur du
   ruban, jamais de la longueur du titre. Repliable en entier. */
.echo-cote { background:var(--fond); border-right:0.5px solid var(--bord);
             overflow-y:auto; overflow-x:hidden;
             min-height:0; padding:10px 8px; display:flex;
             flex-direction:column; gap:2px; }
/* 🐛 `grid-template-columns:0 1fr` etait FAUX. En repliant, `.echo-cote` passe
   en `display:none` : il ne reste qu'UN enfant, qui se place donc dans la
   PREMIERE colonne — celle de largeur ZERO. Le chat se retrouvait comprime a
   quelques pixels et le texte tombait a un mot par ligne. Une seule colonne
   quand il n'y a qu'un enfant. */
.echo.cote-repliee { grid-template-columns:1fr; }
.echo.cote-repliee .echo-cote { display:none; }
/* Le bouton de repli vit dans l'ENVELOPPE, au-dessus du ruban : hors de la
   barre il n'a plus rien à recouvrir, et hors de `.echo` il n'est plus
   découpé. Sa position ne dépend ni de ce que la barre contient, ni de son
   état — c'est l'enveloppe qui le porte, et elle ne bouge pas. */
.echo { position:relative; }
.echo-bascule-cote { position:absolute; left:0; top:4px; z-index:5;
    border:none; background:none; color:var(--faible); cursor:pointer;
    font-family:inherit; padding:5px; border-radius:8px; line-height:0; }
.echo-bascule-cote:hover { background:var(--fond); color:var(--texte); }
.echo-bascule-cote svg { width:20px; height:20px; display:block; }

/* Hauteur EXPLICITE : sans elle, le bouton se laissait écraser par ce qui
   l'entourait et le libellé se retrouvait coupé en deux. */
.echo-neuf { width:100%; height:34px; margin:0 0 10px; flex:none;
             border:0.5px solid var(--bord); border-radius:999px;
             background:var(--carte); color:var(--texte); padding:0 14px;
             font-size:12.5px; cursor:pointer; font-family:inherit;
             display:flex; align-items:center; gap:8px; white-space:nowrap;
             overflow:hidden; text-overflow:ellipsis; }
.echo-neuf:hover { background:var(--fond); filter:brightness(.97); }

.echo-section { margin-bottom:4px; }
.echo-section-tete { display:flex; align-items:center; gap:6px; padding:5px 6px;
    font-size:10.5px; letter-spacing:.14em; color:var(--tres-faible);
    text-transform:uppercase; cursor:pointer; border-radius:7px;
    user-select:none; }
.echo-section-tete:hover { color:var(--texte); }
.echo-section-tete .echo-fleche { font-size:9px; width:10px; flex:none;
    transition:transform .12s; }
.echo-section.repliee .echo-section-tete .echo-fleche { transform:rotate(-90deg); }
.echo-section.repliee .echo-section-corps { display:none; }
.echo-section-tete .plus { margin-left:auto; border:none; background:none;
    color:var(--faible); cursor:pointer; font-family:inherit;
    font-size:17px; font-weight:400; padding:0 6px; border-radius:6px;
    line-height:1; }
.echo-section-tete .plus:hover { color:var(--texte); background:var(--carte); }

/* Une ligne = UNE hauteur de ligne, quel que soit le titre. */
.echo-ligne { display:flex; align-items:center; gap:6px; padding:6px 8px;
    border-radius:7px; font-size:12.5px; color:var(--discret); cursor:pointer;
    line-height:1.35; }
.echo-ligne .titre { flex:1; min-width:0; white-space:nowrap; overflow:hidden;
    text-overflow:ellipsis; }
.echo-ligne:hover { background:var(--carte); color:var(--texte); }
.echo-ligne.actif { background:var(--carte); color:var(--texte); }
.echo-ligne .geste { border:none; background:none; color:var(--tres-faible);
    cursor:pointer; font-family:inherit; font-size:12px; padding:0 3px;
    border-radius:5px; line-height:1; flex:none; visibility:hidden; }
.echo-ligne:hover .geste { visibility:visible; }
.echo-ligne .geste:hover { color:var(--texte); }
.echo-projet > .echo-ligne { color:var(--texte); font-size:12px;
                             font-weight:600; letter-spacing:.01em; }
.echo-projet .echo-fleche { font-size:9px; width:10px; flex:none;
    color:var(--tres-faible); transition:transform .12s; }
.echo-projet.replie .echo-fleche { transform:rotate(-90deg); }
.echo-projet.replie .echo-projet-convs { display:none; }
.echo-projet-convs { padding-left:14px; }
.echo-cote .echo-vide-liste { font-size:11.5px; color:var(--tres-faible); padding:4px 8px;
                   font-style:italic; }

/* Le menu « ⋯ » d'une conversation : favori, deplacer, corbeille. En
   position:fixed parce que la barre laterale DEFILE — un menu absolu dans un
   conteneur qui defile se fait couper par l'overflow. */
.echo-menu { position:fixed; z-index:80; background:var(--carte);
    border:0.5px solid var(--bord); border-radius:10px; padding:4px;
    box-shadow:0 4px 18px rgba(0,0,0,.14); min-width:190px; max-width:240px; }
.echo-menu button { display:block; width:100%; text-align:left; border:none;
    background:none; font-family:inherit; font-size:12px; color:var(--texte);
    padding:7px 10px; border-radius:7px; cursor:pointer; white-space:nowrap;
    overflow:hidden; text-overflow:ellipsis; }
.echo-menu button:hover { background:var(--fond); }
.echo-menu .titre-menu { font-size:10px; letter-spacing:.12em;
    color:var(--tres-faible); text-transform:uppercase; padding:7px 10px 3px; }
.echo-menu .danger { color:#b4552d; }

/* 🐛 `min-height:0` N'EST PAS COSMETIQUE — mesure en navigateur le 2026-08-11.
   Un element de grille (comme de flex) porte `min-height:auto` : il REFUSE de
   descendre sous la hauteur de son contenu. Sans cette ligne, `.echo-corps`
   mesurait 1933 px dans une carte de 510 px : le fil ne scrollait JAMAIS
   (scrollHeight == clientHeight) et la zone de saisie se retrouvait a 2092 px,
   donc invisible, coupee par l'`overflow:hidden` de la carte. Le chat semblait
   n'avoir ni defilement ni champ de question des la premiere reponse longue. */
.echo-corps { display:flex; flex-direction:column; min-width:0; min-height:0;
              position:relative; }
.echo-fil { flex:1; min-height:0; overflow-y:auto; padding:22px 20px;
            scroll-behavior:smooth; }
.echo-fil-contenu { max-width:var(--echo-lecture); margin:0 auto;
                    display:flex; flex-direction:column; gap:14px; }

/* ── L'ETAT D'ACCUEIL, facon ChatGPT ────────────────────────────────────────
   Avant le premier message, le fil n'existe pas : la barre de question est AU
   CENTRE de l'ecran, salutation au-dessus, suggestions en dessous. Des que la
   conversation commence, la meme barre glisse en bas — c'est le MEME DOM, seul
   l'etat de la racine change. Deux compositeurs separes auraient diverge.

   🐛 `align-items:center` N'EST PAS DECORATIF. Sans lui, `.echo-bas-contenu`
   s'etire sur toute la largeur du conteneur flex (comportement par defaut
   `stretch`), puis `max-width` le rogne — et il reste COLLE A GAUCHE. Sur un
   ecran de 1920 le bloc de saisie se retrouvait dans le coin, avec 1100 px de
   vide a sa droite. `margin:0 auto` ne peut rien contre un etirement. */
.echo-corps.accueil .echo-fil { display:none; }
.echo-corps.accueil .echo-bas { border-top:none; background:none; flex:1;
    display:flex; flex-direction:column; justify-content:center;
    align-items:center; }
.echo-corps.accueil .echo-bas-contenu { width:100%; }
.echo-salutation { display:none; text-align:center; font-size:26px;
    font-weight:300; color:var(--texte); margin:0 0 28px; line-height:1.4;
    letter-spacing:-.01em; }
.echo-corps.accueil .echo-salutation { display:block; }
.echo-logo-accueil { display:none; text-align:center; margin:0 0 18px; }
.echo-logo-accueil img { height:44px; width:auto; opacity:.9; }
.echo-logo-accueil svg { width:52px; height:52px; color:var(--texte); }
.echo-corps.accueil .echo-logo-accueil { display:block; }

/* Les suggestions : meme largeur que la barre, alignees a gauche DANS cette
   colonne (comme ChatGPT) — centrer chaque ligne donnerait un bloc en sapin. */
.echo-sugg { display:none; margin-top:26px; }
.echo-corps.accueil .echo-sugg { display:block; }
.echo-sugg button { display:block; width:100%; text-align:left; border:none;
    background:none; font-family:inherit; font-size:13.5px; color:var(--faible);
    cursor:pointer; padding:11px 14px; line-height:1.5;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    border-radius:10px; }
.echo-sugg button:hover { color:var(--texte); background:var(--fond); }

/* Placement d'ECHO NEO : la question a DROITE, la reponse a GAUCHE. Le regard
   distingue qui parle a la position, sans lire l'etiquette. */
.echo-msg { margin:0; max-width:86%; }
.echo-msg.moi { align-self:flex-end; }
.echo-msg.agent { align-self:flex-start; max-width:100%; width:100%; }
.echo-msg .qui { font-size:10.5px; letter-spacing:.14em; color:var(--tres-faible);
                 text-transform:uppercase; margin-bottom:5px; }
.echo-msg.moi .qui { text-align:right; }
.echo-msg .texte { font-size:13.5px; line-height:1.72; white-space:pre-wrap;
                   word-wrap:break-word; overflow-wrap:anywhere; }
.echo-msg .texte b, .echo-msg .texte strong { font-weight:500; }
.echo-msg.moi .texte { background:var(--fond); border-radius:18px;
                       padding:10px 16px; display:inline-block; text-align:left; }
.echo-msg.agent .texte { padding:2px 0; }
.echo-fiabilite { font-size:11.5px; color:var(--faible); font-style:italic;
                  margin-top:9px; }
.echo-echec { border-left:2px solid #b4552d; padding-left:10px; margin-top:9px;
              font-size:12px; color:var(--discret); }

details.provenance { margin-top:10px; }
details.provenance > summary { font-size:11.5px; color:var(--faible);
    cursor:pointer; list-style:none; padding:4px 0; }
details.provenance > summary::-webkit-details-marker { display:none; }
details.provenance > summary:before { content:'▸ '; color:var(--tres-faible); }
details.provenance[open] > summary:before { content:'▾ '; }
details.provenance > summary:hover { color:var(--texte); }
.prov-section { margin:6px 0 10px; padding-left:14px; }
.prov-titre { font-size:10.5px; letter-spacing:.12em; color:var(--tres-faible);
              text-transform:uppercase; margin-bottom:4px; }
.prov-entree { font-size:12px; line-height:1.6; padding:2px 0; }
.prov-entree a { color:var(--texte); text-decoration:underline;
                 text-decoration-thickness:0.5px; text-underline-offset:2px; }
.prov-entree .gris { color:var(--faible); }
/* Les pictogrammes de provenance : dessines, pas des emojis. Ils heritent de
   la couleur du texte, donc ils suivent le theme sans une ligne de plus, et
   ils ont la MEME tete sur toutes les machines — un emoji est rendu par la
   police du systeme. */
.prov-picto { width:13px; height:13px; vertical-align:-2px; opacity:.75; }
details.provenance > summary .prov-picto { width:12px; height:12px; }

.echo-bas { padding:10px 20px 16px; background:var(--carte); flex:none; }
.echo-bas-contenu { max-width:var(--echo-lecture); margin:0 auto; }
/* ── La glissiere d'effort, facon Claude : 3 crans ──────────────────────────
   Le titre au-dessus NOMME le cran choisi (Réponse Instantanée / Réponse
   Standard / Analyse Approfondie) ; les extremites disent le compromis
   (Rapide ←→ Intelligent). DECISION SEBASTIAN (e), 2026-08-11. */
/* ── L'effort : un DEPLIANT, pas une glissiere posee en permanence ──────────
   Facon ChatGPT (« High ⌄ ») : au repos, un mot discret DANS la barre. Une
   glissiere toujours visible occupait le tiers de la hauteur du bloc de
   saisie pour un reglage qu'on change trois fois par mois — du bruit permanent
   pour un geste rare. Le panneau ne s'ouvre que si on le demande. */
.echo-effort { position:relative; user-select:none; flex:none; }
/* SANS CONTOUR au repos (demande de Sebastian) : c'est un réglage, pas une
   action. Un bouton cerclé appelle le clic ; « Corriger » en mérite un, le
   niveau d'effort non. On garde la HAUTEUR de 30 px pour que les deux restent
   alignés au pixel dans la barre — l'alignement ne dépend pas de la bordure. */
.echo-effort-bouton { display:inline-flex; align-items:center; gap:6px;
    height:30px; padding:0 10px; border:none; border-radius:999px;
    background:none; font-family:inherit; font-size:11.5px;
    color:var(--faible); cursor:pointer; white-space:nowrap; }
.echo-effort-bouton:hover { background:var(--fond); color:var(--texte); }
.echo-effort-bouton .chevron { font-size:8px; }
.echo-effort-nom { font:inherit; letter-spacing:inherit;
    color:inherit; }
.echo-effort-panneau { display:none; position:absolute; bottom:calc(100% + 6px);
    left:0; z-index:70; background:var(--carte); border:0.5px solid var(--bord);
    border-radius:12px; padding:5px; min-width:230px;
    box-shadow:0 4px 18px rgba(0,0,0,.13); }
.echo-effort.ouvert .echo-effort-panneau { display:block; }
.echo-effort-panneau button { display:block; width:100%; text-align:left;
    border:none; background:none; font-family:inherit; cursor:pointer;
    padding:8px 11px; border-radius:9px; color:var(--texte); font-size:12.5px; }
.echo-effort-panneau button:hover { background:var(--fond); }
.echo-effort-panneau button .quoi { display:block; font-size:11px;
    color:var(--tres-faible); margin-top:2px; }
.echo-effort-panneau button.actif { background:var(--fond); }
.echo-effort-panneau button.actif::after { content:' ✓'; color:var(--texte); }
/* La barre de saisie : UNE boite arrondie qui contient tout (texte, effort,
   envoyer), comme ChatGPT — au lieu de trois controles poses cote a cote. */
.echo-saisie { display:flex; flex-direction:column; gap:4px;
    border:0.5px solid var(--bord); border-radius:22px; background:var(--carte);
    padding:8px 8px 6px 14px; }
.echo-saisie:focus-within { border-color:var(--tres-faible); }
.echo-saisie textarea { resize:none; font-family:inherit; font-size:14px;
    line-height:21px; padding:5px 0; border:none; background:none;
    color:var(--texte); min-height:26px; max-height:180px; overflow-y:auto;
    width:100%; }
.echo-saisie textarea:focus { outline:none; }
.echo-saisie-pied { display:flex; align-items:center; gap:8px; }
.echo-saisie-pied .echo-mini { height:30px; padding:0 13px; font-size:11.5px;
    display:inline-flex; align-items:center; }
.echo-envoyer { border:none; border-radius:999px;
    background:var(--texte); color:var(--carte); font-family:inherit;
    font-size:15px; cursor:pointer; width:32px; height:32px; flex:none;
    line-height:1; }
/* L'effort se pose a DROITE, juste avant le bouton d'envoi : c'est le dernier
   reglage qu'on touche avant d'envoyer, il vit a cote de l'envoi. */
.echo-saisie-pied .echo-effort { margin-left:auto; }
.echo-effort-panneau { left:auto; right:0; }
.echo-envoyer:disabled { opacity:.35; cursor:default; }
.echo-outils { display:flex; gap:8px; align-items:center; margin-top:8px;
               flex-wrap:wrap; }
.echo-mini { border:0.5px solid var(--bord); border-radius:999px;
    background:var(--carte); color:var(--faible); font-family:inherit;
    font-size:11.5px; padding:5px 12px; cursor:pointer; }
.echo-mini:hover { color:var(--texte); }
.echo-dims { display:none; gap:6px; margin-top:8px; }
.echo-dims.actif { display:flex; flex-wrap:wrap; }
.echo-attente { font-size:12px; color:var(--faible); font-style:italic; }
/* L'attente : le logo DOVADA qui tourne, a la place des « … ». Trois points,
   c'est le chargement de n'importe quoi ; le logo dit QUI travaille. Meme
   fichier et meme rythme que le bouton « LOGO TEST » — une seule animation de
   marque, pas une deuxieme inventee pour le chat. */
.echo-attente-logo { display:inline-block; line-height:0; }
.echo-attente-logo svg { width:30px; height:30px; color:var(--texte); }
.echo-attente-logo .logo-tout, .echo-attente-logo .logo-copie {
    transform-box:view-box; transform-origin:499.4px 503.9px;
    animation:tourne-repos 2.5s ease-in-out infinite; }
@keyframes tourne-repos { 0%, 22% { transform:rotate(0deg); }
                          100%    { transform:rotate(180deg); } }
@media (prefers-reduced-motion: reduce) {
  .echo-attente-logo .logo-tout, .echo-attente-logo .logo-copie {
    animation:none; } }

/* Le bouton ECHO vit dans le RUBAN, a droite de LOGO TEST, avec le logo
   DOVADA — plus un bouton flottant qui recouvrait le contenu en bas a droite. */
.echo-lanceur { border:0.5px solid var(--bord); border-radius:999px;
    background:var(--carte); color:var(--texte); font-family:inherit;
    font-size:11px; letter-spacing:.09em; padding:0 14px; height:29px;
    cursor:pointer; display:inline-flex; align-items:center; gap:7px;
    vertical-align:middle; }
/* LOGO NOIR dans le bouton du ruban (demande produit 2026-08-12). Le fichier
   source est le favicon coloré ; `brightness(0)` l'écrase en noir plein sans
   toucher au fichier — le même SVG reste le favicon, coloré, dans l'onglet du
   navigateur. En thème sombre, le noir disparaîtrait sur le fond : on l'inverse
   en blanc, ce qui garde le même contraste. */
.echo-lanceur img { height:15px; width:auto; display:block; filter:brightness(0); }
:root[data-theme="dark"] .echo-lanceur img { filter:brightness(0) invert(1); }
.echo-lanceur:hover { background:var(--fond); }

/* ── LE PANNEAU « INFO » ─────────────────────────────────────────────────────
   Meme mecanique que le volet ECHO — meme ecran scindé, meme barre d'onglets,
   meme poignee. C'est un ONGLET DE PLUS dans le MEME volet, pas un second
   volet : deux panneaux qui se disputeraient la droite de l'ecran seraient
   ingerables sur un portable, et le patron VS Code veut un volet qui porte
   plusieurs onglets.

   LES FLECHES SUIVENT LA MEME RECETTE que celles des sections d'agent, sous un
   nom a nous (voir `.echo-info-fleche` plus bas) : meme chevron, meme rotation de
   90 degres, meme duree. C'est ce que la demande produit voulait dire par
   « meme principe que les fleches des Details ». */
/* LES TROIS BOUTONS DU RUBAN — LOGO, ECHO, INFO — ONT LA MEME TAILLE
   (demande produit 2026-08-12). Ils se suivent a l'oeil : des hauteurs
   differentes dans une meme rangee se lisent comme des natures d'objets
   differentes alors que ce sont des boutons. La reference est INFO.
   LOGO est depuis devenu un CERCLE de 29 px (classe `.rond` de ui.py) : meme
   hauteur, mais une pastille au lieu d'une etiquette — il n'ouvre qu'un
   apercu d'animation, il n'a pas a peser autant qu'ALTO.
   La hauteur est FIXEE plutot que laissee au contenu : le logo d'ECHO (une
   image de 15 px) etirait son bouton de deux pixels de plus que les autres,
   ce qui se voyait sans qu'on sache pourquoi. */
.info-lanceur { border:0.5px solid var(--bord);
    border-radius:999px; background:var(--carte); color:var(--texte);
    font-family:inherit; font-size:11px; letter-spacing:.09em;
    padding:0 14px; height:29px; cursor:pointer;
    display:inline-flex; align-items:center; gap:7px; vertical-align:middle; }
.info-lanceur:hover { background:var(--fond); }
/* Le « i » cercle, dessine en CSS : pas d'image a charger, il suit la couleur
   du texte donc il vit dans les deux themes sans retouche. */
.info-pastille { display:inline-flex; align-items:center; justify-content:center;
    width:14px; height:14px; border-radius:999px; border:1px solid currentColor;
    font-size:9.5px; font-style:italic; font-weight:600; line-height:1;
    letter-spacing:0; font-family:Georgia, serif; }

/* LE FOND BLANC EST LA SEPARATION. Chaque boite est posee sur `--carte` avec
   un interstice de 3 px : c'est le fond qui passe entre elles et leur donne
   l'air de flotter, exactement comme les cartes des pages d'agent. Un trait
   de bordure aurait donne un tableau ; un interstice donne des objets. */
.info-arbre { padding:12px; overflow:auto; height:100%; font-size:12.5px;
    line-height:1.5; background:var(--carte); }
.info-titre { background:var(--vert-texte); color:#fbfaf5; font-weight:500;
    padding:8px 12px; border-radius:9px; font-size:13px; margin-bottom:3px; }
/* DEUX TONS DE VERT, un par niveau. Les rubriques de tete (Introduction,
   Description Operationelle) sont plus soutenues que les etapes qu'elles
   contiennent : la hierarchie se lit AVANT d'avoir deplie quoi que ce soit.
   Le ton fonce est MELANGE a partir des deux verts du theme, jamais code en
   dur : il suit donc le theme clair comme le sombre.
   Surtout PAS `filter` sur la boite : un filtre s'applique a toute la
   descendance, et les etapes imbriquees auraient fonce avec leur parent —
   les deux niveaux seraient redevenus indiscernables. */
.info-bloc { border-radius:9px; overflow:clip; margin-bottom:3px;
    background:var(--vert-fond); }
.info-arbre > .info-bloc > summary {
    background:color-mix(in srgb, var(--vert-fond) 78%, var(--vert-texte)); }
.info-bloc > summary { list-style:none; cursor:pointer; background:var(--vert-fond);
    color:var(--vert-texte); font-weight:500; padding:8px 12px;
    display:flex; align-items:center; gap:8px; }
.info-bloc > summary::-webkit-details-marker { display:none; }
/* LA FLECHE : meme RECETTE que les sections d'agent, mais sous un nom a nous.
   Emprunter `.fleche-groupe` de la plateforme aurait marche a l'oeil et casse
   la regle du projet — un test dedie l'interdit, parce qu'une classe empruntee
   importe des styles etrangers dont le symptome n'a aucun rapport visible avec
   la cause (le chat s'etait retrouve hors de l'ecran a cause de `panneau`).
   On recopie donc les trois lignes qui comptent : le chevron en ::before,
   `display:inline-block` (un element inline non remplace NE PEUT PAS tourner),
   et la rotation a l'ouverture. */
.echo-info-fleche { color:var(--vert-texte); font-size:11px; width:11px;
    flex:none; }
.echo-info-fleche::before { content:'›'; display:inline-block;
    transition:transform .12s ease; }
details.info-bloc[open] > summary .echo-info-fleche::before { transform:rotate(90deg); }
.info-bloc > summary:hover { filter:brightness(0.97); }
/* Les ETAPES (C1..Cn) sont IMBRIQUEES dans « Description Operationnelle » :
   ce sont les temps d'un meme pipeline, pas des rubriques soeurs. Un ton plus
   clair et un retrait disent la subordination sans ajouter de trait. */
.info-sous { padding:3px 0 3px 0; background:var(--carte); }
.info-sous .info-bloc { background:var(--vert-fond); filter:none; }
.info-sous .info-bloc > summary { font-weight:400; padding:7px 12px; }
.info-corps { padding:9px 12px 11px 32px; background:var(--carte); }
.info-corps ul { margin:0; padding-left:16px; }
.info-corps li { margin:3px 0; color:var(--discret); }
.info-vide { color:var(--faible); font-style:italic; }

/* ── L'ECRAN SCINDE, facon VS Code ───────────────────────────────────────────
   Pas un tiroir qui RECOUVRE la page : deux volets qui se PARTAGENT l'ecran.
   Recouvrir obligeait a fermer ECHO pour relire la ligne dont on parlait —
   or la question porte presque toujours sur ce qu'on a sous les yeux.
   Le volet gauche retrecit par le `padding-right` du body : une seule
   propriete a poser, et TOUTE la page (bandeau compris) se recompose sans
   qu'aucun ecran d'agent n'ait a savoir qu'ECHO existe. */
body { --echo-largeur:40%; --echo-tiroir-haut:0px; --echo-onglets-haut:29px; }
/* Seul le CONTENU se pousse a gauche : le ruban DOVADA ACCOUNTING garde toute
   la largeur au-dessus du volet, comme la barre de menus de VS Code. */
body.echo-scinde main,
body.echo-scinde .echo-onglets-gauche { margin-right:var(--echo-largeur); }
/* La scission commence SOUS le ruban DOVADA ACCOUNTING, qui reste entier sur
   toute la largeur — comme la barre de menus de VS Code au-dessus des volets.
   La hauteur du ruban est posee par le script (elle depend de la police). */
.echo-tiroir { position:fixed; top:var(--echo-tiroir-haut); right:0; bottom:0;
    width:var(--echo-largeur); min-width:320px; max-width:80%;
    z-index:30; background:var(--carte);
    display:none; flex-direction:column; }
.echo-tiroir.ouvert { display:flex; }

/* La poignee : 8 px de prise, un trait de 1 px a l'oeil. Une poignee large
   d'un pixel se cherche a la souris ; large de huit, elle se trouve. */
.echo-poignee { position:absolute; left:-4px; top:0; bottom:0; width:8px;
    cursor:col-resize; z-index:2; }
.echo-poignee:hover, .echo-poignee.tire { background:var(--tres-faible); opacity:.35; }
body.echo-glisse { cursor:col-resize; user-select:none; }

/* Les onglets : le petit rectangle en haut a gauche de chaque volet.
   HAUTEUR : 29 px, exactement celle des boutons du ruban (LOGO, ALTO, INFO).
   Elle etait passee de 34 a 24 px pour gagner de la place sur un portable, mais
   24 px la rendait plus basse que les boutons qui la surplombent — deux rangees
   d'etiquettes de meme nature a deux hauteurs differentes. On garde donc le gain
   par rapport a l'origine (34 -> 29) tout en alignant la barre sur le ruban :
   une seule hauteur d'etiquette dans toute la plateforme. */
/* `stretch` et non `flex-end` : les onglets doivent REMPLIR la barre, comme
   ceux d'un navigateur. Aligne en bas, chacun se dimensionnait sur son texte —
   15 px de haut dans une barre de 29, trois pastilles flottantes au lieu
   d'onglets. */
.echo-onglets { display:flex; align-items:stretch; gap:0; background:var(--fond);
    border-bottom:0.5px solid var(--bord); min-height:var(--echo-onglets-haut);
    padding:0 0 0 12px; }
/* MEME ECRITURE que les boutons du ruban (11 px / .09em) : « CONCILIO » dans
   un onglet et « CONCILIO » dans le ruban sont la meme etiquette, elles ne
   doivent pas avoir deux tailles. La BARRE reste fine — c'est sa hauteur qui
   avait ete reduite, pas sa typographie. */
/* ONGLETS DE NAVIGATEUR (demande produit 2026-08-12, reference : Chrome).
   Coins arrondis EN HAUT seulement, base a plat : c'est ce qui fait lire une
   etiquette comme un onglet plutot que comme un bouton. L'onglet ACTIF prend
   la couleur du contenu qu'il ouvre, si bien qu'il parait s'y fondre — c'est
   le signal, pas un liseré. Le trait vertical qui separait les onglets
   disparait : deux formes arrondies posees cote a cote se separent d'elles
   memes, et le trait leur donnait l'air d'un tableau.
   Chaque onglet garde toute la hauteur de la barre : arrondir n'est pas
   retrecir, et la barre est deja alignee sur les boutons du ruban. */
.echo-onglet { display:flex; align-items:center; gap:6px; padding:0 13px;
    font-size:11px; letter-spacing:.09em; color:var(--faible);
    background:var(--fond); font-family:inherit;
    border-radius:9px 9px 0 0; margin-right:2px;
    border:0.5px solid var(--bord); border-bottom:none; }
.echo-onglet:hover { color:var(--discret); }
.echo-onglet.actif { background:var(--carte); color:var(--texte);
    box-shadow:none; }
/* PAS D'EVASEMENT A LA BASE — essaye le 2026-08-12, retire le jour meme.
   La courbe inversee de Chrome suppose que l'onglet actif se FOND dans un
   contenu de la meme couleur, juste en dessous, sans trait entre les deux.
   Ici la barre garde son filet inferieur : la courbe ne raccordait donc rien,
   elle posait deux pastilles claires de part et d'autre de l'onglet et coupait
   la ligne — deux taches, exactement ce que la forme devait eviter.
   L'onglet s'arrete net en bas, et le filet passe d'un bout a l'autre. */
.echo-onglet-nom { max-width:150px; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; outline:none; font:inherit; letter-spacing:inherit;
    color:inherit; }
.echo-onglet-nom[contenteditable=true] { background:var(--fond);
    border-radius:4px; padding:0 3px; }
.echo-onglet-fermer { border:none; background:none; color:var(--faible);
    font-size:12px; line-height:1; padding:0 0 0 6px; cursor:pointer;
    font-family:inherit; }
.echo-onglet-fermer:hover { color:var(--texte); }
.echo-tiroir-corps { position:relative; }
.echo-tab { height:100%; }
/* Le volet GAUCHE porte lui aussi son onglet — sinon un seul des deux volets
   a l'air d'etre « quelque part », et la scission ne se lit pas. */
.echo-onglets-gauche { display:none; }
/* LA BARRE D'ONGLETS RESTE COLLÉE SOUS LE RUBAN (demande produit 2026-08-12).
   Elle défilait avec la page : en descendant dans la liste d'un agent, on
   perdait de vue l'onglet actif et le bouton de fermeture d'ECHO — donc le
   moyen de revenir. Le volet DROIT est déjà fixe (`position:fixed`) ; le volet
   gauche prend le même repère, `--echo-tiroir-haut`, qui MESURE le bas du
   ruban à chaque défilement (police et zoom variables). `z-index:50` la place
   sous le ruban (60) et au-dessus du contenu : elle glisse dessous, jamais
   par-dessus. */
body.echo-scinde .echo-onglets-gauche { display:flex; position:sticky;
    top:var(--echo-tiroir-haut); z-index:50;
    /* MEME MARGE DE GAUCHE QUE LE CONTENU (demande produit 2026-08-12) :
       l'onglet « CONCILIO » demarrait au bord de l'ecran pendant que le titre
       du dossier et le tableau commencaient un demi-pouce plus loin. Deux
       alignements dans la meme colonne se voient tout de suite. On reprend
       telle quelle la formule de padding de `main` (ui.py) — si elle change
       la-bas, les deux bougent ensemble. */
    padding-left:clamp(20px, 2.5vw, 48px); }
/* LE TRAIT DE SEPARATION DES DEUX VOLETS commence SOUS les onglets (demande
   produit 2026-08-12). Porte par le volet entier, il traversait aussi la barre
   d'onglets et y laissait un petit trait vertical isole a gauche du premier
   onglet — une separation qui ne separait rien a cet endroit, puisque la barre
   est deja continue d'un volet a l'autre. Le trait appartient au CONTENU des
   deux volets, pas a leurs etiquettes. */
.echo-tiroir-corps { flex:1; min-height:0; border-left:0.5px solid var(--bord); }

@media (max-width:820px) {
  .echo.pleine { grid-template-columns:1fr; height:calc(100vh - 190px); }
  .echo-cote { display:none; }
  /* Sur mobile, le panneau prend TOUT l'ecran : deux volets sur 390 px de
     large ne laissent ni a l'agent ni au chat la place d'etre lisibles. */
  .echo-tiroir { width:100%; min-width:0; max-width:none; }
  .echo-poignee { display:none; }
  /* Sur mobile le volet prend TOUT : le contenu n'a plus a se pousser. */
  body.echo-scinde main { margin-right:0; }
  body.echo-scinde .echo-onglets-gauche { display:none; }
}

/* Bibliotheque de memoire */
.mem-ligne { display:grid; grid-template-columns:112px 1fr auto; gap:14px;
    padding:11px 16px; border-bottom:0.5px solid var(--bord-fin);
    font-size:12.5px; line-height:1.6; align-items:start; }
.mem-ligne:last-child { border-bottom:none; }
.mem-id { font-size:11.5px; color:var(--faible); letter-spacing:.04em; }
.mem-meta { font-size:11px; color:var(--tres-faible); margin-top:3px; }
