/* ============================================================
   Meridian : COMPOSANTS ET PAGES. Les jetons (couleurs, type, espacement,
   rayons, ombres, mouvement, polices) vivent dans tokens.css, miroir du
   dossier `Meridian Design System/` ; ce fichier n'a AUCUN :root, aucune
   couleur ni aucun rayon en dur (tests/test_design_system.py).

   Regles du DS (readme.md, palette « Ardoise & sauge », accent jaune) :
   blancs neutres et encres ardoise ; UNE COULEUR, UN SENS (jaune = l'IA,
   vert du logo = pret/obtenu, cuivre = attention, rouge = destructeur
   seulement, gris = dormant, rose = rencontre prise, bleu acier = gagne) ;
   action primaire ardoise, or du logo sur l'ardoise ; rayons 8 px panneaux/tables/champs, 10 px
   cartes d'agents, 9 px boutons, 6 px etiquettes, pilules pour les barres ;
   aucune ombre au repos ; contenu dense en tables « Outlook ».

   Table des matieres :
     1. Base (html, liens, focus, selection)
     2. Coquille (barre laterale, selecteur de client, en-tete, colonne)
     3. Typographie de page, fiche de compte, grille de criteres
     4. Composants (champs, boutons, pastilles, badges, cartes, dialogue,
        note, tables Outlook)
     5. Pages (tableau de bord, chat, notifications, pipelines, espace
        Pipeline, agents, onboarding, admin, journal IA, consignes)
     6. Mobile (en-tete, tiroir, cibles 44 px, tables empilees)
     7. Utilitaires (toujours en dernier : la cascade doit leur donner
        le dernier mot)
   ============================================================ */

* { box-sizing: border-box; }

html, body { margin: 0; height: 100%; }
/* Un saut d'ancre (#agent-scribe, #consignes, #label...) s'arrete SOUS la
   barre de titre collante au lieu de cacher le titre vise derriere elle. */
[id] { scroll-margin-top: calc(var(--top-h) + var(--sp-4)); }

body {
  font: var(--text-body-md);
  color: var(--text-body);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  letter-spacing: -.004em;
}

a { color: var(--blue-strong); text-decoration: none; }
a:hover { color: var(--blue); text-decoration: underline; }

:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* Sur les surfaces sombres (barre laterale, en-tete mobile), l'anneau d'or
   se fondrait dans le fond : il passe a l'or clair (0.3.25). */
.sb :focus-visible, .mhead :focus-visible { outline-color: var(--blue-bright); }
::selection { background: var(--blue-tint-2); }

/* ============================================================
   Coquille applicative : sidebar + colonne principale
   ============================================================ */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
  background: var(--paper);
}

/* --- Sidebar --- */
.sb {
  position: sticky; top: 0; align-self: start;
  height: 100vh;
  /* Deux etages (demande Marek, 2026-10-12) : le menu (.sb__defile) defile
     seul, le pied (.sb__foot : le client et « Se deconnecter ») reste fixe en
     bas. Avant, toute la barre defilait, pied compris, et sur un ecran court
     le nom du client et la deconnexion sortaient de l'ecran. */
  overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--blue-deep);
  color: var(--white);
  padding: 0 0 var(--sp-5); /* Shell.jsx : 20 px en haut (sur le menu), 14 px de cote */
}
.sb__defile {
  flex: 1 1 auto; min-height: 0;
  /* Un ecran court (1280x720) et une barre d'operateur (Administration,
     Journal IA, Incidents, Signaler) : le menu defile seul plutot que de
     pousser toute la page a defiler (2026-10-06), comme le tiroir mobile. */
  overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
  /* Sans barre de defilement visible (demande Marek, 2026-10-07) : des que
     le menu depassait la hauteur de l'ecran, ses 15 px se prenaient dans
     les 236 de la barre, et « Demander a Erikia » passait sur deux lignes.
     Il defile toujours, a la molette, au pave tactile et au doigt. */
  scrollbar-width: none;
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--sp-5) 14px var(--sp-3);
}
.sb__defile::-webkit-scrollbar { display: none; }
.sb__brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-2) var(--sp-4);
  color: var(--white); text-decoration: none;
}
/* Le logo garde son blanc au survol (demande Marek, 2026-10-11) : la regle
   globale `a:hover` (bleu) l'emportait sur `.sb__brand` et recolorait le mot. */
.sb__brand:hover { color: var(--white); text-decoration: none; }
.sb__version {
  margin-left: auto; font: var(--text-data); font-size: var(--fs-11);
  color: var(--nav-fg-dim); border: 1px solid var(--line-on-dark);
  border-radius: var(--r-tag); padding: 1px 7px; white-space: nowrap;
}
/* Le mot-symbole porte le nom : plus de <b> a cote. Il est large (le
   rapport du cadre serre est de 4), d'ou `width: auto`. 20 px de cadre
   donnent une capitale de 17 px, celle du mot d'avant. */
.sb__brand > img { height: 21px; width: auto; flex: none; }
.sb__brand-icone { display: none; }
.sb__brand-icone svg { width: 28px; height: 28px; }
.sb__grp {
  font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--nav-fg-dim); padding: var(--sp-4) var(--sp-2) var(--sp-1);
}
.nav {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px var(--sp-3); border-radius: var(--r-sm);
  color: var(--nav-fg); cursor: pointer; text-decoration: none;
  font: var(--text-label); font-size: var(--fs-14);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.nav:hover { background: var(--nav-bg-hover); color: var(--white); text-decoration: none; }
.nav.active { background: var(--nav-bg-active); color: var(--white); }
.nav svg { width: 18px; height: 18px; flex: none; }
/* Le logo de « Demander a Erikia » est un aplat : a 18px il pese plus que
   les icones au trait. 10 % plus petit (demande Marek, 2026-10-02), recentre
   par sa marge pour que les libelles restent alignes. */
.nav svg.logo-demander { width: 16.2px; height: 16.2px; margin: 0 0.9px; }
.nav__label { flex: 1; }
/* Pastille de compte dans la nav (Shell.jsx) : or clair sur noir, encre
   --sur-clair, chiffres tabulaires. */
.nav__badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-pill);
  background: var(--blue-bright); color: var(--sur-clair);
  font: 700 var(--fs-11)/1 var(--font-mono);
}
.sb__foot {
  /* Hors de la zone defilante : toujours en bas, son filet est la ligne ou
     commence le defilement du menu (2026-10-12). */
  flex: none; margin: 0 14px;
  /* Colonne depuis l'auth : le selecteur/l'identite au-dessus, le bouton de
     deconnexion en dessous, pleine largeur. */
  display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-2) var(--sp-1);
  border-top: 1px solid var(--line-on-dark);
}
.sb__ava {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  background: var(--blue-bright); color: var(--sur-clair);
  display: flex; align-items: center; justify-content: center;
  font: 600 var(--fs-13) var(--font-display);
}
.sb__foot .col span { font-size: var(--fs-13); color: var(--white); font-weight: 600; }

/* --- Selecteur de client (pied de barre) ---
   <details> natif : fonctionne sans JavaScript. Desktop : le pied est colle en
   bas (flex + margin-top:auto), le menu s'ouvre donc vers le HAUT. Mobile : la
   barre devient horizontale et le pied passe a droite, le menu s'ouvre vers le
   BAS, aligne a droite. */
.sb__foot { position: relative; }
.orgpick { width: 100%; }
.orgpick__summary {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; cursor: pointer; list-style: none;
  border-radius: var(--r-sm); padding: var(--sp-1);
  text-decoration: none;
  transition: background var(--t-fast) var(--ease);
}
.orgpick__summary::-webkit-details-marker { display: none; }
/* Variante non interactive (compte regulier : un seul client). */
.orgpick__summary--fixe { cursor: default; }
.orgpick__summary:hover { background: var(--nav-bg-hover); }
.orgpick__summary .col { min-width: 0; }
.orgpick__summary .col span {
  font-size: var(--fs-13); color: var(--white); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: block; max-width: 140px;
}
.orgpick__chev {
  margin-left: auto; color: var(--nav-fg-dim);
  font-size: 9px; transition: transform var(--t-fast) var(--ease);
}
.orgpick[open] .orgpick__chev { transform: rotate(180deg); }
.orgpick__menu {
  position: absolute; bottom: 100%; left: 0; right: 0;
  margin-bottom: var(--sp-2); padding: var(--sp-1);
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); box-shadow: var(--shadow-menu);
  z-index: 60;
}
.orgpick__menu form { margin: 0; }
.orgpick__item {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; padding: var(--sp-2); border: 0; background: none;
  border-radius: var(--r-sm); cursor: pointer; text-align: left;
  font: var(--text-body-md); color: var(--ink); text-decoration: none;
}
.orgpick__item:hover { background: var(--paper); }
.orgpick__item[aria-current="true"] { font-weight: 600; }
.orgpick__ava {
  width: 22px; height: 22px; font-size: var(--fs-12);
  background: var(--blue-tint); color: var(--blue-strong);
}
.orgpick__check { margin-left: auto; color: var(--blue); }
.orgpick__item--add {
  border-top: 1px solid var(--line); border-radius: 0;
  margin-top: var(--sp-1); padding-top: var(--sp-2);
  color: var(--blue-strong); font-weight: 600;
}

/* La page /client (chemin sans JavaScript et sans liste sous la main). Une
   rangee = le formulaire de bascule, puis « Reprendre l'onboarding » quand
   l'onboarding du client n'est pas fini (2026-10-23). */
.client-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0; }
.client-row__form { flex: 1 1 16rem; min-width: 0; margin: 0; }
.client-row__reprise { flex: none; margin-right: var(--sp-3); }
.client-row__btn {
  display: flex; align-items: center; gap: var(--sp-3);
  width: 100%; padding: var(--sp-3); border: 0; background: none;
  border-radius: var(--r-sm); cursor: pointer; text-align: left;
  font: var(--text-body-md); color: var(--ink);
}
.client-row__btn:hover { background: var(--paper); }
.client-row.is-current .client-row__btn { background: var(--blue-tint); }
.client-row__ava { background: var(--blue-tint-2); color: var(--blue-deep); }
.client-row__col { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
.client-row__check { margin-left: auto; color: var(--blue); font-weight: 700; }
.sb__foot small { color: var(--nav-fg-dim); font-size: var(--fs-12); }

/* --- Colonne principale --- */
.main { display: flex; flex-direction: column; min-width: 0; }
.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 16px var(--sp-10);
  background: var(--topbar-bg);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line);
  min-height: var(--top-h); /* 80 px : titre 20 px, sous-titre 13 px dessous, 16 px de marge (jeton du DS) */
}
/* Titre puis sous-titre sur sa propre ligne (demande de Marek, 2026-09-11 :
   le kit les mettait cote a cote). Un sous-titre trop long passe a la ligne
   au lieu d'etre tronque. */
.top__titles { min-width: 0; }
.top h1 {
  font: 600 var(--fs-20)/1.2 var(--font-display); margin: 0;
  color: var(--ink); letter-spacing: var(--track-title);
}
.top__sub { color: var(--ink-3); font-size: var(--fs-13); line-height: var(--lh-snug); margin: 4px 0 0; }
.top__sp { flex: 1; }
/* TOUTES les pages ont la meme largeur (demande Marek, 2026-09-25) :
   Agents et Pipeline etaient pleine largeur, Reglages, Profil, Aide et les
   autres se serraient dans 920 px. Deux gabarits de page pour un seul
   produit, et le regard devait se reajuster a chaque navigation. */
.scroll { flex: 1; padding: var(--sp-8) var(--sp-10); }

/* petits utilitaires */
[hidden] { display: none !important; }
.col { display: flex; flex-direction: column; }
.row { display: flex; align-items: center; gap: var(--sp-3); }
.row-split { display: flex; justify-content: space-between; gap: var(--sp-3); }
.row-split--top { align-items: flex-start; }
.row-split--base { align-items: baseline; }
.row--tight { gap: var(--sp-2); }
.row--base { align-items: baseline; }
.row--end { align-items: flex-end; }
.row--wrap { flex-wrap: wrap; }
.muted { color: var(--ink-3); }
.small { font-size: var(--fs-13); }
.caps { font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--ink-title); }
.tight { margin: 6px 0; padding-left: 18px; }

/* ============================================================
   Typographie de page
   ============================================================ */
h1 {
  font: var(--text-display); font-size: var(--fs-28);
  letter-spacing: var(--track-display); margin: 0 0 var(--sp-2); color: var(--ink);
}
h2 {
  font: var(--text-caps);
  letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--ink-title); margin: var(--sp-8) 0 var(--sp-3); font-weight: 600;
}
h3 { font: var(--text-title); font-size: var(--fs-16); margin: 0 0 var(--sp-2); }
.lede { color: var(--ink-2); font-size: var(--fs-16); margin: 0 0 var(--sp-4); line-height: var(--lh-body); max-width: 68ch; }
.section-hint { color: var(--ink-3); font-size: var(--fs-13); margin: 0 0 var(--sp-4); }

/* Listes explicatives (accueil, aide) : numeros discrets, respiration entre
   les items, largeur de lecture bornee. */
.steps-list {
  margin: 0; padding-left: var(--sp-5);
  color: var(--ink-2); font-size: var(--fs-14); line-height: var(--lh-body);
  max-width: 68ch;
}
.steps-list > li { margin-bottom: var(--sp-3); padding-left: var(--sp-1); }
.steps-list > li:last-child { margin-bottom: 0; }
.steps-list > li::marker { color: var(--ink-4); font-weight: 600; }

.help-list {
  margin: 0; padding-left: var(--sp-5);
  color: var(--ink-2); font-size: var(--fs-14); line-height: var(--lh-body);
  max-width: 68ch;
}
.help-list > li { margin-bottom: var(--sp-2); }
.help-list > li:last-child { margin-bottom: 0; }

/* ---- Onboarding en etapes -------------------------------------------------
   Sans JavaScript, .ob-form--stepped n'est jamais pose : les fieldsets
   s'affichent a la suite et le formulaire reste utilisable tel quel. */
fieldset.ob-step { border: 0; margin: 0; padding: 0; min-width: 0; }
.ob-form--stepped .ob-step { display: none; }
.ob-form--stepped .ob-step.is-active { display: block; }

/* Les champs de l'onboarding font TROIS lignes, grandissent jusqu'a SIX, puis
   defilent (demande Marek, 2026-09-04). Le pre-remplissage y ecrit des
   suggestions longues : sur une seule ligne, elles etaient illisibles et
   impossibles a faire defiler (overflow: clip sur un <input>). Restent d'une
   ligne, et ce sont les seules : les noms, les adresses web, l'objet d'un
   courriel.

   La borne haute vit ICI et pas dans le script : sans JavaScript, le champ
   s'ouvre a trois lignes et defile au-dela, ce qui reste utilisable.
   onboarding.js ne fait qu'ajuster la hauteur entre les deux bornes. */
/* `.txt-auto` porte la meme regle HORS de l'onboarding : le champ de
   precisions de la page de revue et les reponses aux questions la reclamaient,
   et le selecteur borne a `.ob-step` les laissait de cote (2026-09-04). */
.ob-step textarea, textarea.txt-auto {
  /* Une ligne = la hauteur de ligne du champ LUI-MEME (1em = sa fonte, pas
     celle du fieldset), plus ses rembourrages et ses bordures (border-box). */
  --ob-ligne: calc(var(--lh-body) * 1em);
  --ob-chrome: calc(2 * var(--sp-2) + 2px);
  min-height: calc(3 * var(--ob-ligne) + var(--ob-chrome));
  max-height: calc(6 * var(--ob-ligne) + var(--ob-chrome));
  overflow-y: auto;
}

.ob-steps {
  display: flex; flex-wrap: wrap; gap: var(--sp-1);
  list-style: none; margin: 0 0 var(--sp-6); padding: 0;
  counter-reset: obstep;
}
.ob-steps li {
  counter-increment: obstep;
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--ink-3);
  cursor: pointer; user-select: none;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.ob-steps li::before {
  content: counter(obstep);
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; flex: none;
  border-radius: 50%; border: 1px solid var(--line-strong);
  font-size: var(--fs-12); font-weight: 600; font-variant-numeric: tabular-nums;
}
.ob-steps li:hover { background: var(--paper-4); color: var(--ink-2); }
.ob-steps li.is-active { background: var(--blue-tint); color: var(--blue-strong); font-weight: 600; }
.ob-steps li.is-active::before { border-color: var(--blue); background: var(--blue); color: var(--white); }
.ob-steps li.is-done { color: var(--ink-2); }
.ob-steps li.is-done::before {
  content: "✓"; border-color: var(--ok); background: var(--ok-tint); color: var(--ok);
}

/* La barre reste accessible sur les etapes longues (l'etape « Vos clients »
   fait plus de deux ecrans). Fond pleine largeur pour que le contenu passe
   dessous sans transparence. */
.ob-nav {
  position: sticky; bottom: 0; z-index: 2;
  margin: var(--sp-6) calc(-1 * var(--sp-10)) 0;
  padding: var(--sp-4) var(--sp-10);
  background: var(--paper);
  border-top: 1px solid var(--line);
}
.ob-nav #ob-note { margin-left: auto; }
@media (max-width: 900px) {
  .ob-nav { margin-left: calc(-1 * var(--sp-5)); margin-right: calc(-1 * var(--sp-5)); padding-left: var(--sp-5); padding-right: var(--sp-5); }
}
/* Les marges negatives doivent SUIVRE le padding horizontal du parent
   (.scroll) a chaque palier, sinon l'onboarding fait defiler tout l'ecran
   de 2x4px — deja mordu deux fois. Paliers actuels : sp-4 sous 820,
   sp-3 sous 560. */
@media (max-width: 820px) {
  .ob-nav { margin-left: calc(-1 * var(--sp-4)); margin-right: calc(-1 * var(--sp-4)); padding-left: var(--sp-4); padding-right: var(--sp-4); }
}
@media (max-width: 560px) {
  .ob-nav { margin-left: calc(-1 * var(--sp-3)); margin-right: calc(-1 * var(--sp-3)); padding-left: var(--sp-3); padding-right: var(--sp-3); }
}

/* Barre d'actions collante d'un formulaire long (0.3.36), taillee sur .ob-nav :
   Enregistrer reste a portee de clic depuis n'importe quel champ, y compris au
   bas des « Reglages avances ». Memes marges negatives, meme piege : elles
   doivent SUIVRE le padding horizontal de .scroll a chaque palier. */
.form-sticky {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  margin: var(--sp-6) calc(-1 * var(--sp-10)) 0;
  padding: var(--sp-4) var(--sp-10);
  background: var(--paper);
  border-top: 1px solid var(--line);
}
@media (max-width: 900px) {
  .form-sticky { margin-left: calc(-1 * var(--sp-5)); margin-right: calc(-1 * var(--sp-5)); padding-left: var(--sp-5); padding-right: var(--sp-5); }
}
@media (max-width: 820px) {
  /* Plus de reserve a droite depuis 0.3.48 : la pastille passe AU-DESSUS de la
     barre, elle ne la recouvre plus. Et les 64 px d'avant n'en protegeaient
     qu'un tiers, la pastille faisant environ 200 px de large. */
  .form-sticky {
    margin-left: calc(-1 * var(--sp-4)); margin-right: calc(-1 * var(--sp-4));
    padding-left: var(--sp-4); padding-right: var(--sp-4);
  }
}
@media (max-width: 560px) {
  .form-sticky {
    margin-left: calc(-1 * var(--sp-3)); margin-right: calc(-1 * var(--sp-3));
    padding-left: var(--sp-3); padding-right: var(--sp-3);
  }
}

/* Etat vide : ce qu'il n'y a pas encore, et EXACTEMENT un geste pour y
   remedier. Jamais deux liens noyes dans une phrase. */
.vide { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
/* La phrase d'etat vide d'une liste (conventions-interface.md §8) : la cause,
   puis l'action, en gris, toujours le meme balisage. */
p.vide { display: block; margin: var(--sp-2) 0 var(--sp-4); color: var(--ink-3); font-size: var(--fs-14); }

/* Mention accolee a un titre de section (« facultatif ») : elle dit qu'on peut
   passer son chemin sans rien casser. */
.h2-note {
  margin-left: var(--sp-2); padding: 2px 8px; border-radius: var(--r-tag);
  background: var(--paper-3); color: var(--ink-3);
  font: var(--text-label); font-size: var(--fs-12); font-weight: 600;
  text-transform: none; letter-spacing: 0; vertical-align: 2px;
}

/* Une case ou un bouton radio et son libelle (conventions-interface.md §7) :
   un seul balisage, <label class="choix"><input> <span>Libelle</span></label>.
   Les variantes de page (pastille de jalon, ligne du menu des cohortes...)
   gardent leur classe a cote et precisent la mise en page. */
.choix { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
.choix input { width: auto; margin: 0; flex: none; }


/* ---- Fiche de compte ------------------------------------------------------
   Trois cartes cote a cote, volontairement distinctes : un representant doit
   voir d'un coup d'oeil ce qui est SOURCE, ce qui est SUPPOSE, et ce qui reste
   a verifier. Les melanger reviendrait a lui faire repeter au telephone une
   hypothese comme si c'etait un fait. */
.bv-brief__cols {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-3);
}
@media (max-width: 1100px) {
  .bv-brief__cols { grid-template-columns: 1fr; }
}
.bv-brief__card {
  border: 1px solid var(--line); border-radius: var(--r-xs);
  padding: var(--sp-4) var(--sp-5); background: var(--white);
}
/* L'en-tête porte la couleur : point + titre caps. Vert = sourcé,
   vert = supposé (la voix de l'IA), ambre = à vérifier. Le point est la
   pastille nommée .bvx-dot--*, la même clé que les badges de stade (0.4.24) :
   une seule table de couleurs pour tout le produit. */
.bv-brief__card .block-title { display: flex; align-items: center; gap: 7px; }
.bv-brief__card--facts .block-title { color: var(--ok); }
.bv-brief__card--guess .block-title { color: var(--blue-strong); }
.bv-brief__card--verify .block-title { color: var(--warn); }
.bv-brief__card ul { margin: var(--sp-2) 0 0; padding-left: var(--sp-4); }

/* Paires libellé/valeur de la fiche (Besoin probable, Hypothèse...). */
/* Le bloc « Brief » du kit (Profil.jsx) : une boite blanche a rangees
   libelle / valeur, filets --paper-3, libelles en --ink-lbl. */
.bv-kv {
  display: grid; grid-template-columns: 150px 1fr; gap: 0 14px;
  margin: var(--sp-3) 0; font-size: var(--fs-14); line-height: 1.55;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-xs);
}
.bv-kv dt {
  color: var(--ink-lbl); font-weight: 500; font-size: var(--fs-13);
  padding: var(--row-pad-y) 0 var(--row-pad-y) var(--row-pad-x); border-bottom: 1px solid var(--paper-3);
}
.bv-kv dd { margin: 0; padding: var(--row-pad-y) var(--row-pad-x) var(--row-pad-y) 0; border-bottom: 1px solid var(--paper-3); }
.bv-kv dt:last-of-type, .bv-kv dd:last-of-type { border-bottom: 0; }
.bv-kv__action { font-weight: 600; }
@media (max-width: 700px) {
  .bv-kv { grid-template-columns: 1fr; gap: 0; }
  .bv-kv dt { border-bottom: 0; padding: var(--row-pad-y) var(--row-pad-x) 0; }
  .bv-kv dd { padding: var(--sp-1) var(--row-pad-x) var(--row-pad-y); }
}

/* Grille de critères : 2 colonnes, coche ronde mono. */
.crit-grid {
  list-style: none; margin: var(--sp-2) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--sp-6);
  overflow-wrap: anywhere;
}
@media (max-width: 900px) { .crit-grid { grid-template-columns: 1fr; } }
.crit-grid li {
  display: flex; align-items: baseline; gap: var(--sp-2); line-height: 1.5;
  padding: var(--sp-2) 0; border-bottom: 1px solid var(--paper-3);
}
/* Le libellé (et sa preuve, et son lien) peut rétrécir sous sa largeur de
   contenu : sans ça, un mot long pousse la grille hors de l'écran. */
.crit-grid li > span { min-width: 0; }
.crit-mark {
  flex: none; width: 18px; height: 18px; display: inline-flex;
  align-items: center; justify-content: center; border-radius: 50%;
  font: 700 11px/1 var(--font-mono);
  background: var(--paper-3); color: var(--ink-3);
}
.crit-mark--ok { background: var(--ok-tint); color: var(--ok); }
.crit-mark--warn { background: var(--warn-tint); color: var(--warn); }
.crit-mark--muted { background: var(--paper-3); color: var(--ink-3); }
/* Les points d'un critère : « 5/5 » obtenu, « 0/5 » manqué. Le pointage se lit
   d'un coup d'oeil, c'est ce qui rend la pondération enfin visible. */
.crit-pts {
  flex: none; min-width: 38px; padding: 1px 5px; display: inline-flex;
  align-items: center; justify-content: center; border-radius: var(--r-tag);
  font: 700 var(--fs-12)/1.4 var(--font-mono); font-variant-numeric: tabular-nums;
  background: var(--paper-3); color: var(--ink-3);
}
.crit-pts--ok { background: var(--ok-tint); color: var(--ok); }
.crit-pts--warn { background: var(--warn-tint); color: var(--warn); }
.crit-pts--muted { background: var(--paper-3); color: var(--ink-3); }

/* Dans la carte « Grille de l'Analyste » (0.4.25), un critere prend toute la
   largeur en TROIS colonnes : les points, le critere, la preuve. En deux
   colonnes serrees, la preuve se lisait comme la suite du libelle. */
.crit-grid--rangees {
  display: block; margin: 0;
}
.crit-grid--rangees li {
  display: grid; grid-template-columns: 54px minmax(140px, 1fr) minmax(0, 1.4fr);
  gap: var(--sp-3); align-items: baseline;
  padding: var(--row-pad-y) var(--row-pad-x); border-bottom: 1px solid var(--paper-3);
}
.crit-libelle { font-size: var(--fs-14); font-weight: 600; color: var(--ink); }
.crit-preuve { font-size: var(--fs-13); line-height: var(--lh-body); color: var(--ink-3); }
@media (max-width: 820px) {
  .crit-grid--rangees li { grid-template-columns: 54px minmax(0, 1fr); }
  .crit-preuve { grid-column: 2; }
}

/* L'editeur de grille (page Profil) : un libellé, des points, rien d'autre. */
.crit-edit__list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.crit-edit__row { display: flex; gap: var(--sp-2); align-items: center; margin-bottom: 6px; }
/* La regle generique `input[type=...]` pose width:100% et vit PLUS BAS dans la
   feuille : a specificite egale elle gagnerait. D'ou le type ET la classe. */
.crit-edit__row input[type="text"] { flex: 1 1 auto; min-width: 0; width: auto; }
.crit-edit__row input[type="number"].crit-edit__pts {
  flex: none; width: 5rem; text-align: right; font-variant-numeric: tabular-nums;
}
.crit-edit__row.is-neuf input[type="text"] { border-color: var(--warn); }
/* Les outils du profil : un nom, puis ce qu'il dit de l'entreprise. Pas
   .crit-edit__row : cette classe-la designe les lignes de la grille pointee
   (profil.js et ses tests les comptent). */
.pf-outil { display: flex; gap: var(--sp-2); align-items: center; margin-bottom: 6px; }
.pf-outil input[type="text"] { flex: 1 1 auto; min-width: 0; width: auto; }
.pf-outil select { flex: none; width: auto; max-width: 15rem; }
/* Les listes du profil et de la voix, une case par entree
   (_liste_entrees.html, 2026-10-07) : un fieldset sans cadre, sa legende
   habillee comme un libelle, les cases empilees. */
.pf-liste { border: 0; padding: 0; min-width: 0; }
.pf-liste legend {
  padding: 0; font: var(--text-label); color: var(--ink-2);
  margin-bottom: var(--sp-1);
}
.pf-liste__cases { list-style: none; margin: 0; padding: 0; }
.pf-liste__cases li { margin-bottom: 6px; }
.crit-edit__foot {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-3);
  margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line);
}
.crit-edit__total {
  font: 700 var(--fs-14)/1 var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--ok);
}
.crit-edit__total.is-faux { color: var(--warn); }
@media (max-width: 640px) {
  .crit-edit__row { flex-wrap: wrap; }
  .crit-edit__row input[type="text"] { flex: 1 1 100%; }
  .crit-edit__row input[type="number"].crit-edit__pts { width: 4.5rem; }
  .pf-outil { flex-wrap: wrap; }
  .pf-outil select { flex: 1 1 100%; max-width: none; }
}

/* Glossaire terme / definition : le terme porte, la definition explique. */
.help-dl { margin: 0; max-width: 68ch; }
.help-dl dt {
  font-size: var(--fs-14); font-weight: 600; color: var(--ink);
  margin-top: var(--sp-4);
}
.help-dl dt:first-child { margin-top: 0; }
.help-dl dd {
  margin: var(--sp-1) 0 0; padding-left: var(--sp-3);
  border-left: 2px solid var(--line);
  color: var(--ink-2); font-size: var(--fs-13); line-height: var(--lh-body);
  /* Une route, un courriel, un identifiant sont des jetons SANS espace : le
     detail d'un incident poussait la page a 683 px sur mobile (2026-10-06). */
  overflow-wrap: anywhere;
}

/* ============================================================
   Formulaires
   ============================================================ */
form { margin-top: var(--sp-2); }
.field { margin: var(--sp-4) 0; }
label {
  display: block; font: var(--text-label); color: var(--ink-2);
  margin-bottom: var(--sp-1);
}
/* Un groupe de champs du meme genre (cases, presences web, lignes CAB,
   conventions-interface.md §7) : un fieldset sans cadre, sa legende habillee
   comme un libelle. */
fieldset.field { border: 0; padding: 0; min-width: 0; }
fieldset.field > legend { padding: 0; font: var(--text-label); color: var(--ink-2); margin-bottom: var(--sp-1); }
/* email et date manquaient a la liste (0.3.25) : le champ Courriel de /admin
   et le filtre de date du journal sortaient en champ natif de 24 px. Puis
   search (0.4.24, banc mobile) : la recherche du pipeline sortait a 21 px. */
input[type=text], input[type=url], input[type=email], input[type=date],
input[type=search], input[type=number], input[type=file], textarea, select {
  width: 100%; height: var(--control-h); padding: 0 var(--sp-3);
  font: var(--text-body-md); color: var(--ink);
  background: var(--white); border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
/* Le selecteur de fichier natif est le seul controle que le navigateur dessine
   lui-meme, libelle compris (en anglais selon la langue du navigateur). On le
   recouvre. `.filepick.is-enhanced` n'est pose que par documents.js : sans
   JavaScript, l'input natif reste visible et cliquable. */
input[type=file] { padding: 0; line-height: var(--control-h); cursor: pointer; }
input[type=file]::file-selector-button {
  height: 100%; margin-right: var(--sp-3); padding: 0 var(--sp-3);
  font: var(--text-label); color: var(--ink-2); cursor: pointer;
  background: var(--paper); border: 0;
  border-right: 1px solid var(--line-strong);
  border-radius: var(--r-xs) 0 0 var(--r-xs);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
input[type=file]:hover::file-selector-button { background: var(--paper-3); color: var(--ink); }

.filepick { position: relative; }
.filepick__btn, .filepick__name { display: none; }
.filepick.is-enhanced {
  display: flex; align-items: center; height: var(--control-h);
  background: var(--white); border: 1px solid var(--line-strong);
  border-radius: var(--r-xs); overflow: hidden; cursor: pointer;
  transition: border-color var(--t-fast) var(--ease);
}
.filepick.is-enhanced:hover { border-color: var(--ink-4); }
.filepick.is-enhanced:focus-within { outline: 2px solid var(--focus-ring); border-color: var(--blue); }
.filepick.is-enhanced input[type=file] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; cursor: pointer;
}
.filepick.is-enhanced .filepick__btn {
  display: block; flex: none; align-self: stretch;
  padding: 0 var(--sp-3); line-height: calc(var(--control-h) - 2px);
  font: var(--text-label); color: var(--ink-2);
  background: var(--paper); border-right: 1px solid var(--line-strong);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.filepick.is-enhanced:hover .filepick__btn { background: var(--paper-3); color: var(--ink); }
.filepick.is-enhanced .filepick__name {
  display: block; min-width: 0; padding: 0 var(--sp-3);
  font: var(--text-body-md); color: var(--ink-4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.filepick.is-enhanced .filepick__name.has-file { color: var(--ink); }
textarea { height: auto; min-height: 80px; padding: var(--sp-2) var(--sp-3); resize: vertical; line-height: var(--lh-body); }
/* Texte de substitution en --ink-3 (0.3.25) : --ink-4 sur blanc tombait
   sous le contraste minimal pour un texte qui donne l'exemple attendu. */
input::placeholder, textarea::placeholder { color: var(--ink-3); }
input:hover, textarea:hover, select:hover { border-color: var(--ink-4); }
input:focus, textarea:focus, select:focus {
  outline: 2px solid var(--focus-ring); outline-offset: 0;
  border-color: var(--blue);
}
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235F6B71' stroke-width='2.5'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; padding-right: 30px;
}
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
@media (max-width: 700px) { .grid-2 { grid-template-columns: 1fr; } }

/* ============================================================
   Boutons (Button.jsx). Noms canoniques : .btn, .btn-ghost, .btn-soft,
   .btn-ai, .btn-danger, .btn-sm, .btn-lg. Les alias .mds-btn* restent
   definis (scripts, prudence) mais aucun gabarit ne les emploie.
   ============================================================ */
.btn, .mds-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: var(--control-h); padding: 0 var(--sp-4);
  border-radius: var(--r-sm); border: 1px solid transparent;
  font: var(--text-label); font-size: var(--fs-13); font-weight: 600;
  background: var(--primary); color: var(--white); cursor: pointer; white-space: nowrap;
  text-decoration: none;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.btn:hover, .mds-btn:hover { background: var(--primary-hover); color: var(--white); text-decoration: none; }
.btn:active, .mds-btn:active { transform: translateY(1px); }
/* Desactive (0.3.25) : l'attribut `disabled` bloque deja le clic ; garder le
   curseur, c'est laisser le pointeur DIRE que le bouton est indisponible.
   `pointer-events: none` supprimait ce retour. */
.btn[disabled], .mds-btn[disabled] { opacity: .45; cursor: not-allowed; }

/* Bouton occupe : distinct de « desactive ». Un agent tourne (jusqu'a 90 s pour
   une etude), donc le bouton doit rester lisible et montrer qu'il travaille,
   pas paraitre indisponible. Le point qui pulse est le seul signal de vie. */
.is-busy { opacity: .8 !important; cursor: progress; }
.is-busy::after {
  content: ""; display: inline-block; width: 6px; height: 6px;
  margin-left: 8px; vertical-align: middle;
  background: currentColor; border-radius: 50%;
  animation: busy-dot 1s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .is-busy::after { animation: none; opacity: .7; }
}
.btn-ghost, .mds-btn--secondary {
  background: var(--white); border-color: var(--line-strong); color: var(--ink);
}
.btn-ghost:hover, .mds-btn--secondary:hover { background: var(--white); border-color: var(--ink-4); color: var(--ink); }
/* Tertiaire (« Copier », « Réécrire ») : fond gris chaud, sans bordure. */
.btn-soft, .mds-btn--soft { background: var(--paper-3); border-color: transparent; color: var(--ink-2); }
.btn-soft:hover, .mds-btn--soft:hover { background: var(--line); border-color: transparent; color: var(--ink); }
.btn-ai, .mds-btn--ai { background: var(--surface-ai); border-color: var(--blue-line); color: var(--blue-strong); }
.btn-ai:hover, .mds-btn--ai:hover { background: var(--blue-tint-2); color: var(--blue-strong); }
.btn-danger, .mds-btn--danger { background: var(--danger); color: var(--white); }
.btn-danger:hover, .mds-btn--danger:hover { background: var(--danger-hover); color: var(--white); }
.btn-sm, .mds-btn--sm { height: var(--control-h-sm); padding: 0 var(--sp-3); font-size: var(--fs-13); }
.btn-lg, .mds-btn--lg { height: var(--control-h-lg); padding: 0 var(--sp-5); font-size: var(--fs-16); }
.actions { margin-top: var(--sp-8); display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }
.actions .muted { font-size: var(--fs-13); }

/* Le point « Meridian » (en-tete de la fenetre de discussion) */
.mds-ask__dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--blue); box-shadow: 0 0 0 3px var(--blue-tint-2);
}


/* ============================================================
   Deux familles de petits controles, et rien d'autre (0.3.25)

   PASTILLE (rayon --r-pill, caps ou label en --fs-12) :
     - cliquable, 32 px de haut (44 sur mobile) : .mini-btn, .bvx-chip
     - statique, 22 px de haut : .mds-badge, .bvx-stage
   ONGLET (controle segmente : une piste --paper-4, l'actif en blanc ombre) :
     - .pv-tab, .pv-ct-chip (choisir un contact = changer le contenu affiche,
       c'est structurellement un onglet, pas une pastille)

   Memes hauteurs, memes rayons, memes tailles de texte a l'interieur d'une
   famille. Les noms de classes n'ont pas change ; seules les regles ont
   converge, pour que deux choses qui font pareil aient l'air pareil.
   ============================================================ */

/* petit bouton texte (app .mini-btn) */
.mini-btn {
  display: inline-flex; align-items: center; gap: 5px; min-height: 32px;
  font: var(--text-label); font-size: var(--fs-12); font-weight: 600;
  color: var(--blue-strong); background: var(--surface-ai);
  border: 1px solid var(--blue-line); cursor: pointer;
  padding: 4px var(--sp-3); border-radius: var(--r-sm);
  text-decoration: none; transition: background var(--t-fast) var(--ease);
}
.mini-btn:hover { background: var(--blue-tint-2); color: var(--blue-strong); text-decoration: none; }
.mini-btn[disabled] { opacity: .5; cursor: not-allowed; }
/* Les variantes du petit bouton (conventions-interface.md §1) : --primary
   conclut une modification en ligne (Enregistrer, Repondre, Ajouter) ;
   --danger retire ou supprime, toujours confirme (forms.js). */
.mini-btn--danger { color: var(--danger); background: var(--white); border-color: var(--line-strong); }
.mini-btn--danger:hover { background: var(--danger-tint); border-color: var(--danger); color: var(--danger); }

/* ============================================================
   Surfaces : cartes, blocs, pastilles, tags
   ============================================================ */
.card, .block, .mds-card {
  background: var(--surface-card); border: 1px solid var(--line);
  border-radius: var(--r-xs); box-shadow: var(--shadow-card);
}
.card { padding: var(--sp-5) var(--sp-6); margin: var(--sp-4) 0; }
.block { padding: var(--sp-4) var(--sp-5); margin: var(--sp-3) 0; }
.mds-card--ai, .card.ai { background: var(--surface-ai); border-color: var(--blue-line); box-shadow: none; }
/* Cartes a filet de sens (UNE COULEUR, UN SENS) : ambre = a regarder, rouge =
   irreversible, vert = ce qu'Erikia propose. */
.card--warn { border-color: var(--warn); background: var(--warn-tint); }
.card--danger { border-color: var(--danger); }
.card--ai-line { border-color: var(--blue); }
.block-title {
  font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--ink-title); margin-bottom: var(--sp-2); font-weight: 600;
}
/* Le contenu des agents est rendu en HTML depuis le 2026-08-21 (filtre
   `markdown`) : plus de pre-wrap, qui doublerait les sauts de ligne du
   <p>. .prose donne le rythme vertical de ce contenu. */
.analysis { line-height: var(--lh-body); }

.prose > *:first-child { margin-top: 0; }
.prose > *:last-child { margin-bottom: 0; }
.prose p { margin: 0 0 var(--sp-3); line-height: var(--lh-body); }
.prose h2 { font-size: var(--fs-18); margin: var(--sp-5) 0 var(--sp-2); }
.prose h3 { font-size: var(--fs-16); margin: var(--sp-5) 0 var(--sp-2); }
/* h4+ : les agents descendent rarement plus bas ; on garde une hiérarchie
   lisible plutôt que quatre tailles qui se ressemblent. */
.prose h4, .prose h5, .prose h6 {
  font-size: var(--fs-14); margin: var(--sp-4) 0 var(--sp-1);
  color: var(--ink-2); text-transform: none; letter-spacing: 0;
}
.prose ul, .prose ol { margin: 0 0 var(--sp-3); padding-left: 1.35em; }
.prose li { margin: 0 0 var(--sp-1); line-height: var(--lh-body); }
.prose li::marker { color: var(--ink-4); }
.prose code {
  font-family: var(--font-code); font-size: 0.92em;
  background: var(--paper-3); border-radius: var(--r-xs); padding: 1px 5px;
}
.prose strong { font-weight: 600; }
.prose a { color: var(--blue-strong); text-decoration: underline; }

/* Pastille statique (.mds-badge, et .bvx-stage depuis 0.3.25 :
   le stade d'une entreprise etait un rectangle de 10 px a coins carres, la
   seule pastille de l'interface qui ne ressemblait pas aux autres). Les
   variantes de couleur .bvx-stage--* vivent avec le reste du pipeline ;
   .pill--ready et .pill--muted, que plus aucun gabarit ne rendait, ont été
   retirées en 0.3.35 pour qu'elles ne redivergent jamais des .bvx-stage--*.
   .pill elle-meme est partie le 2026-10-02 avec l'historique du profil,
   son dernier lecteur. */
.mds-badge, .bvx-stage {
  display: inline-flex; align-items: center; gap: 5px; height: 22px;
  padding: 0 10px; border-radius: var(--r-tag);
  font: var(--text-caps);
  letter-spacing: var(--track-caps); text-transform: uppercase;
  background: var(--blue-tint); color: var(--blue-strong);
  white-space: nowrap;
}
.mds-badge--neutral { background: var(--paper-3); color: var(--ink-2); }
.mds-badge--ok { background: var(--ok-tint); color: var(--ok); }
.mds-badge--warn { background: var(--warn-tint); color: var(--warn); }
.mds-badge--danger { background: var(--danger-tint); color: var(--danger); }
.mds-badge--muted { background: var(--paper-3); color: var(--ink-3); }

/* Tag (app .tag) */
.tag {
  display: inline-flex; align-items: center; height: 26px; padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-tag); /* pilule (DS) */
  background: var(--white); font-size: var(--fs-13); color: var(--ink-2);
}

/* Dialogue modal (mds) */
.mds-scrim {
  position: fixed; inset: 0; z-index: 80;
  background: var(--scrim);
  display: flex; align-items: center; justify-content: center; padding: var(--sp-6);
}
.mds-dialog {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); box-shadow: var(--shadow-overlay);
  max-width: 480px; width: 100%;
  animation: mds-pop var(--t-med) var(--ease);
  /* Rien ne bornait la hauteur : la fenetre de suivi (six jalons, deux menus,
     une zone de notes, trois gestes) sortait de l'ecran a 844 px de haut. */
  display: flex; flex-direction: column; max-height: 100%; min-height: 0;
}
.mds-dialog__body { overflow-y: auto; min-height: 0; }
.mds-dialog__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) 0; font: var(--text-title); font-size: var(--fs-18);
}
/* La croix « Fermer », en haut a droite de tout dialogue (conventions-
   interface.md §9) : elle fait ce que fait Echap, rien de plus. */
.mds-dialog__fermer {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; margin: -6px -8px 0 0; padding: 0;
  border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink-3); cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.mds-dialog__fermer:hover { background: var(--paper-row-hover); color: var(--ink); }
.mds-dialog__body { padding: var(--sp-3) var(--sp-5) var(--sp-4); color: var(--ink-2); font-size: var(--fs-14); }
.mds-dialog__body textarea { margin-top: var(--sp-2); }
.mds-dialog__foot {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--line);
  background: var(--paper); border-radius: 0 0 var(--r-xs) var(--r-xs);
}

/* Ligne de note / info (app .note-line) */
.note-line {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0;
  background: var(--surface-ai); border: 1px solid var(--blue-line);
  border-radius: var(--r-xs); font-size: var(--fs-14); color: var(--blue-strong);
}
.note-line a { color: inherit; font-weight: 600; text-decoration: underline; }
.note-line--warn { background: var(--warn-tint); border-color: var(--warn-tint); color: var(--warn); }
.note-line--danger { background: var(--danger-tint); border-color: var(--danger-tint); color: var(--danger); }

/* Lien d'evitement : hors ecran jusqu'au premier Tab, bien visible ensuite. */
.skip {
  position: absolute; left: var(--sp-3); top: -80px; z-index: 200;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm);
  background: var(--blue-strong); color: var(--white); text-decoration: none;
  font-size: var(--fs-14); font-weight: 600;
}
.skip:focus { top: var(--sp-3); }
/* Le conteneur de contenu ne recoit le focus que par ce lien : pas d'anneau. */
.scroll:focus { outline: none; }

/* Retour arriere des pages filles : meme forme partout (_retour.html). Depuis
   la maquette 0.4.25, c'est une pastille doree et non un lien gris : sur une
   page dense, le seul chemin de sortie doit se voir sans etre cherche. */
.retour {
  display: inline-flex; align-items: center; gap: 7px;
  height: var(--control-h-sm); margin-bottom: var(--sp-3); padding: 0 var(--sp-3);
  border: 1px solid var(--blue-line); border-radius: var(--r-sm);
  background: var(--surface-ai); white-space: nowrap;
  font: 600 var(--fs-13)/1 var(--font-sans); color: var(--blue-strong); text-decoration: none;
  transition: background var(--t-fast) var(--ease);
}
.retour:hover { background: var(--blue-tint-2); color: var(--blue-strong); text-decoration: none; }

/* ============================================================
   Tableau de bord
   ============================================================ */
.dash-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: var(--sp-6); flex-wrap: wrap; margin: var(--sp-2) 0 var(--sp-8);
}
.dash-hello {
  margin: 0; font: var(--text-display); font-size: var(--fs-36);
  letter-spacing: var(--track-display); text-transform: none; color: var(--ink);
}
.dash-status {
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-xs);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-5);
  box-shadow: var(--shadow-card);
}
.dash-status__dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.dash-status__dot--live { background: var(--blue); box-shadow: 0 0 0 4px var(--blue-tint-2); animation: pulse 1.8s var(--ease) infinite; }
.dash-status__dot--wip { background: var(--warn); box-shadow: 0 0 0 4px var(--warn-tint); }
.dash-status__dot--ok { background: var(--ok); box-shadow: 0 0 0 4px var(--ok-tint); }
.dash-status__dot--ready { background: var(--blue); box-shadow: 0 0 0 4px var(--blue-tint-2); }
.dash-status__txts { display: flex; flex-direction: column; gap: 1px; margin-right: var(--sp-2); }
.dash-status__txt { color: var(--ink); font-size: var(--fs-14); font-weight: 600; }
.dash-status__hint { color: var(--ink-3); font-size: var(--fs-12); }
/* Les gestes de l'encadre (2026-10-13, demande Marek) : sur ordinateur, dans
   la rangee, comme avant (`display: contents`) ; sur un telephone, les deux
   boutons cote a cote SOUS le statut, a parts egales (la rangee repliait un
   bouton par ligne). Un libelle long passe sur deux lignes dans son bouton
   plutot que d'elargir l'encadre. */
.dash-status__gestes { display: contents; }
@media (max-width: 820px) {
  .dash-status { width: 100%; }
  .dash-status__gestes { display: flex; flex: 1 1 100%; gap: var(--sp-2); }
  .dash-status__gestes .btn {
    flex: 1 1 0; min-width: 0; height: auto; min-height: var(--control-h);
    padding: 6px var(--sp-3); white-space: normal; line-height: 1.25; text-align: center;
  }
}

.dash-block { margin-bottom: var(--sp-5); }
.dash-block__title {
  font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase;
  font-size: var(--fs-12); color: var(--ink-title); margin: 0 0 var(--sp-3);
}
/* --- Table « Outlook » (DS : DataTable.jsx, guidelines/table-outlook.html) ---
   Tout contenu dense vit dans une table alignee : en-tete en capitales sur
   --paper-head, rangees egales de --row-h, filets --paper-3, chiffres a droite
   en mono (.num), survol --paper-row-hover, ellipse plutot que debordement,
   .table-scroll en filet de securite. `.calls-table` (tableau de bord) et
   `.jia` (journal IA, admin) sont deux noms historiques de la MEME table ;
   sous 820 px, `table.t-cartes` empile les rangees en cartes (section Mobile).
   JAMAIS de min-width sur une table : le banc mobile signale tout conteneur
   qui defile. La hauteur d'une cellule est un minimum : un contact sur deux
   lignes ou un groupe de boutons de jalon tient dans sa rangee. */
.table-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-xs);
}
.calls-table, .jia { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.calls-table th, .jia th {
  text-align: left; font: var(--text-th); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-lbl); background: var(--paper-head);
  padding: var(--row-pad-y) var(--row-pad-x); border-bottom: 1px solid var(--line); white-space: nowrap;
}
.calls-table td, .jia td {
  height: var(--row-h); padding: 0 var(--row-pad-x);
  border-bottom: 1px solid var(--paper-3); vertical-align: middle;
}
.calls-table tbody tr, .jia tbody tr { transition: background var(--t-fast) var(--ease); }
.calls-table tbody tr:hover, .jia tbody tr:hover { background: var(--paper-row-hover); }
.calls-table tr:last-child td, .jia tr:last-child td { border-bottom: 0; }
.calls-table th.num, .jia th.num { text-align: right; }
.calls-table td.num, .jia td.num {
  text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.calls-co { font-weight: 600; }

/* --- Cockpit de vente : jalons, cascade, signaux ------------------------- */
.dash-block__count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 7px; margin-left: var(--sp-1);
  border-radius: var(--r-tag); background: var(--blue-tint);
  color: var(--blue-strong); font-size: var(--fs-12); font-weight: 600;
  letter-spacing: 0; vertical-align: 1px;
}
.dash-block__hint { margin: calc(-1 * var(--sp-2)) 0 var(--sp-3); }

/* Les quatre listes d'entreprises (2026-10-02), en 2 x 2 ; une colonne sous
   820 px. Une rangee par entreprise : le nom et pourquoi elle est la, a
   gauche ; son statut a droite. Filets --paper-3 comme la table Outlook. */
.dash-listes {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-4); margin-bottom: var(--sp-5);
}
.dash-listes > .dash-liste { margin: 0; }
.dash-liste__items { list-style: none; margin: 0; padding: 0; }
.dash-liste__item {
  display: flex; align-items: center; gap: var(--sp-3);
  border-top: 1px solid var(--paper-3);
}
.dash-liste__lien {
  flex: 1; min-width: 0; min-height: 44px; padding: var(--sp-2) 0;
  display: flex; flex-direction: column; justify-content: center;
  color: var(--ink); text-decoration: none;
}
.dash-liste__lien:hover .dash-liste__nom { color: var(--blue-strong); text-decoration: underline; }
.dash-liste__nom, .dash-liste__meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-liste__nom { font-weight: 600; font-size: var(--fs-14); }
.dash-liste__meta { font-size: var(--fs-12); color: var(--ink-lbl); }
.dash-liste__item > .bvx-stage { flex: none; }
.dash-liste__pied { margin: var(--sp-2) 0 0; }
@media (max-width: 820px) {
  .dash-listes { grid-template-columns: minmax(0, 1fr); }
}

/* Jalons : un bouton de jalon est un GESTE À POSER, pas un résultat obtenu
   (0.3.35). Tous gris au repos, tous sans bordure. Au survol, un cran de
   gris plus foncé, le même pour les six (0.5.5, demande Marek : le survol
   teinté par jalon « fait jaune dans tous les cas », trois teintes pâles sur
   six tiraient vers le jaune) ; la couleur ne dit plus ce que le clic va
   produire, le libellé le dit. Une fois posé, `.is-done` passe au noir avec
   sa coche. Plus de jalons « plausibles » teintés selon le statut non plus
   (0.4.126, retirés à la demande de Marek le 2026-10-07) : aucune couleur au
   repos. */
.ct-btn {
  white-space: nowrap; border-color: transparent; border-radius: var(--r-sm);
  color: var(--ink-3); background: var(--paper-3);
}
.ct-btn:hover { color: var(--ink); background: var(--paper-4); border-color: transparent; }
/* Posé : noir avec sa coche. Il se clique (2026-10-07) : la fenêtre propose
   de le retirer, pour un jalon posé par erreur. */
.ct-btn.is-done {
  background: var(--primary); border-color: var(--primary); color: var(--white);
  opacity: 1; cursor: pointer;
}
.ct-btn.is-done:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--white); }
.ct-btn.is-done::before { content: "✓ "; }

/* Toast partage (toast.js) : « Enregistré », en bas au centre, meme forme sur
   toutes les pages. Couche 90 (conventions-interface.md §9) : AU-DESSUS de
   tout, pastille (50), tiroir mobile (58/60), fenetre Erikia (70/79) et
   modal (80) compris ; un retour declenche depuis un dialogue ou pendant que
   la fenetre Erikia est ouverte restait invisible sous eux. Sur mobile, empile
   AU-DESSUS de la pastille (44 px + 14 de marge) plutot qu'a cote. */
.toast-zone {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  z-index: 90; display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  max-width: calc(100vw - 40px); pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: var(--sp-4);
  min-height: var(--control-h-lg); padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-sm); background: var(--ink); color: var(--white);
  font: var(--text-label); font-size: var(--fs-13); font-weight: 600;
  box-shadow: var(--shadow-overlay);
  animation: mds-pop var(--t-med) var(--ease);
}
.toast__undo {
  border: none; background: none; cursor: pointer; padding: 0 var(--sp-1);
  min-height: 32px; font: inherit; color: var(--blue-bright);
  text-decoration: underline; text-underline-offset: 2px;
}
.toast__undo:hover { color: var(--white); }
.toast :focus-visible { outline-color: var(--blue-bright); } /* fond sombre */
.toast__undo[disabled] { opacity: .45; cursor: not-allowed; }
@media (max-width: 820px) {
  .toast-zone {
    left: 14px; right: 14px; transform: none; align-items: stretch; max-width: none;
    bottom: calc(14px + 44px + 14px + env(safe-area-inset-bottom));
  }
  .toast { justify-content: space-between; }
  .toast__undo { min-height: 44px; padding: 0 var(--sp-3); }
}
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* --- Les chiffres, tous pipelines : anneau + trois jauges ----------------
   Marques fines, une seule teinte (or) du plus pale au plus fonce ; le
   texte reste en encre, jamais dans la couleur de la serie. */
.dash-charts {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-6);
  align-items: center; margin-bottom: var(--sp-5);
}
.donut-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); }
.donut { position: relative; width: 168px; height: 168px; }
.donut svg { display: block; width: 100%; height: 100%; }
.donut__centre {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; pointer-events: none;
}
.donut__num { font: 600 var(--fs-36)/1 var(--font-sans); color: var(--ink); }
.donut__lbl { font: var(--text-label); color: var(--ink-3); margin-top: 4px; }
.donut__legende { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.donut__key { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-13); color: var(--ink-2); }
.donut__key b { color: var(--ink); font-weight: 600; }
/* « À contacter N » mène à la chip du pipeline : un lien discret, souligné
   au survol. En ligne dans son span : texte courant, pas une cible isolée. */
.donut__lien { color: inherit; text-decoration: none; }
.donut__lien:hover { color: var(--blue-strong); text-decoration: underline; }
.donut__swatch { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
/* « À contacter » prend le vert de son statut (0.5.5) ; le reste de
   l'anneau, les contactées, reste neutre. */
.donut__swatch--a { background: var(--ok); }
.donut__swatch--c { background: var(--paper-4); }
/* Les jauges tiennent sur UNE rangee, qu'il y en ait une, deux, trois ou
   quatre (demande Marek, 2026-10-07) : une colonne egale par jauge. Avant,
   trois colonnes fixes renvoyaient « Gagnees » seule sous les autres. */
.kpis { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--sp-4); }
.kpi {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-xs);
  padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0;
}
.kpi__lbl { font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--ink-title); }
.kpi__val { font: 600 var(--fs-28)/1.05 var(--font-sans); color: var(--ink); }
/* La piste est un pas plus pale du meme degrade ; sous 2 %, le remplissage
   garde 2 % de largeur : un faible taux doit rester visible (la valeur
   exacte est ecrite juste au-dessus). */
.kpi__track { display: block; height: 6px; border-radius: var(--r-pill); background: var(--blue-tint); overflow: hidden; }
.kpi__fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--blue); transition: width .6s var(--ease); }
.kpi__fill--win { background: var(--ok); }
.kpi__sub { font-size: var(--fs-12); color: var(--ink-3); }
/* Ecran de bureau etroit : a cote de l'anneau, quatre jauges n'auraient
   plus que 105 px a 1024 et « Rencontres » deborderait. L'anneau passe
   au-dessus, couche a cote de sa legende ; les jauges gardent leur rangee. */
@media (min-width: 821px) and (max-width: 1180px) {
  .dash-charts { grid-template-columns: minmax(0, 1fr); }
  .donut-wrap { flex-direction: row; justify-content: center; gap: var(--sp-6); }
  .donut__legende { align-items: flex-start; }
}
@media (max-width: 820px) {
  .dash-charts { grid-template-columns: 1fr; }
  .kpis { grid-auto-flow: row; grid-template-columns: 1fr; }
}

/* Ce qu'Erikia a appris : une carte CARREE par note (demande Marek,
   2026-10-12 : « sinon je veux juste un carre »), crayon et poubelle en haut
   a droite, le texte coupe en fondu ; « Lire la suite » deplie la carte (un
   <details> natif, sans JavaScript ; notes.js le cache quand tout tient),
   les autres de la rangee gardent leur carre (`align-items: start`). Une
   carte en modification prend toute la largeur. `min-height: 0` : sans lui,
   le contenu d'une boite a ratio l'etire au lieu de deborder ; depliee, elle
   retrouve `min-height: auto` et garde le ratio : au moins un carre, plus
   haute si le texte le demande (sans ratio, une note courte RAPETISSAIT). */
.notes {
  list-style: none; margin: 0; padding: 0; display: grid; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--sp-3);
}
.note {
  display: flex; flex-direction: column; gap: var(--sp-2);
  aspect-ratio: 1 / 1; min-height: 0; overflow: hidden;
  background: var(--paper); border: 1px solid var(--line); border-left: 3px solid var(--line-strong);
  border-radius: var(--r-xs); padding: var(--sp-3) var(--sp-4);
}
.note--icp { border-left-color: var(--blue); }
.note--agent { border-left-color: var(--ok); }
.note:has(.note__plus[open]) { min-height: auto; overflow: visible; }
.note--modification { aspect-ratio: auto; overflow: visible; grid-column: 1 / -1; }
.note__tete { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2); }
.note__lbl { font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--ink-title); padding-top: 6px; }
.note__gestes { display: inline-flex; flex: none; gap: 2px; margin: 0 calc(-1 * var(--sp-2)) 0 0; }
.note__gestes form { margin: 0; display: inline-flex; }
.note__geste {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--ink-3); cursor: pointer;
}
.note__geste:hover { background: var(--paper-row-hover); color: var(--ink); text-decoration: none; }
.note__geste svg { width: 16px; height: 16px; }
.note__geste--danger:hover { background: var(--danger-tint); color: var(--danger); }
.note__txt {
  flex: 1 1 auto; min-height: 0; overflow: hidden; margin: 0;
  font-size: var(--fs-14); color: var(--ink); line-height: var(--lh-snug); white-space: pre-line;
  -webkit-mask-image: linear-gradient(to bottom, black calc(100% - 2.5em), transparent);
  mask-image: linear-gradient(to bottom, black calc(100% - 2.5em), transparent);
}
.note:has(.note__plus[open]) .note__txt { overflow: visible; -webkit-mask-image: none; mask-image: none; }
.note__pied { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); flex: none; }
.note__plus summary {
  list-style: none; cursor: pointer; font-size: var(--fs-13); font-weight: 600; color: var(--ink-2);
}
.note__plus summary::-webkit-details-marker { display: none; }
.note__plus summary:hover { color: var(--ink); text-decoration: underline; }
.note__plus[open] .note__ouvrir, .note__plus:not([open]) .note__fermer { display: none; }
.note__date { font-size: var(--fs-12); color: var(--ink-4); font-variant-numeric: tabular-nums; margin-left: auto; }
/* Les groupes de « Ce qu'Erikia a appris » (2026-10-13, demande Marek :
   « groupees par etape ») : dans la carte, un titre par etape, numerote
   comme la page Prospection, puis sa grille de carres. */
.rg-groupe {
  display: flex; align-items: center; gap: var(--sp-2);
  margin: var(--sp-5) 0 var(--sp-3); font: var(--text-title); font-size: var(--fs-16);
  letter-spacing: 0; text-transform: none; color: var(--ink);
}
.rg-groupe:first-child { margin-top: 0; }
.rg-groupe .bvx-rank { width: 24px; height: 24px; font-size: var(--fs-13); }

/* Commentaire global. */
.commentaire { margin: 0; }
.commentaire textarea { width: 100%; box-sizing: border-box; margin: 0 0 var(--sp-3); }
.commentaire__foot { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.commentaire__retour {
  margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--surface-ai); border: 1px solid var(--blue-line); border-radius: var(--r-xs);
  color: var(--blue-strong); font-size: var(--fs-14);
}
.commentaire__resume { margin: 0; font-weight: 600; }
.commentaire__liste { margin: var(--sp-2) 0 0; padding-left: 1.2em; }

/* ============================================================
   Demander à Meridian : conversations + fil de chat
   ============================================================ */
.chat-layout {
  /* minmax(0, 260px) et non 260px : un element de grille garde `min-width:
     auto` (= min-content), donc la colonne debordait PAR-DESSUS le fil des
     qu'un titre etait long, malgre l'ellipsis pose plus bas. Meme raison pour
     les `min-width: 0` de .chat-side et .chat-item : l'ellipsis d'un enfant ne
     s'applique que si TOUTE la chaine de parents accepte de retrecir. */
  display: grid; grid-template-columns: minmax(0, var(--colonne-w)) minmax(0, 1fr);
  gap: var(--sp-5) var(--colonne-ecart); align-items: start; margin-bottom: var(--sp-3);
}
@media (max-width: 900px) {
  .chat-layout { grid-template-columns: 1fr; }
  /* Sur mobile, le FIL d'abord : la liste des conversations empilait
     au-dessus et il fallait tout defiler avant d'atteindre les messages. */
  .chat-side { order: 2; }
}
.chat-side { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.chat-new { justify-content: center; width: 100%; }
/* La liste vit dans sa propre carte (maquette 0.4.34), comme le rail de la
   page d'entreprise : un titre en capitales dessus, les fils dedans. */
.chat-side__bloc { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.chat-side__tete { display: flex; align-items: baseline; gap: var(--sp-2); }
.chat-side__tete .num { font-size: var(--fs-12); color: var(--ink-4); }
.chat-side__liste {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); padding: 5px; min-width: 0;
}
.chat-side__vide {
  margin: 0; padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-12); line-height: var(--lh-snug); color: var(--ink-lbl);
}
.chat-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.chat-item {
  position: relative; display: flex; align-items: center; min-width: 0;
  border-radius: var(--r-sm);
  transition: background var(--t-fast) var(--ease);
}
.chat-item:hover { background: var(--paper-3); }
.chat-item.is-active { background: var(--blue-tint); }
.chat-item__link {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px;
  padding: var(--sp-2) var(--sp-3); text-decoration: none; color: inherit;
}
.chat-item__link:hover { text-decoration: none; color: inherit; }
.chat-item__title {
  font-size: var(--fs-13); font-weight: 500; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-item.is-active .chat-item__title { color: var(--blue-strong); }
.chat-item__date {
  font-size: var(--fs-12); color: var(--ink-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-item__edit {
  font-size: var(--fs-13); height: 26px; padding: 0 var(--sp-2);
  border-radius: var(--r-xs); width: 100%;
}
/* Renommer / supprimer un fil : reveles au survol, mais aussi au clavier
   (:focus-within) et toujours la ou il n'y a pas de survol (0.3.25). */
.chat-item__actions {
  display: none; align-items: center; gap: 2px; padding-right: var(--sp-2); flex: none;
}
.chat-item:hover .chat-item__actions, .chat-item:focus-within .chat-item__actions,
.chat-item.is-active .chat-item__actions { display: inline-flex; }
@media (hover: none) { .chat-item__actions { display: inline-flex; } }
.chat-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: var(--r-sm);
  border: none; background: transparent; color: var(--ink-4); cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.chat-iconbtn:hover { background: var(--white); color: var(--blue-strong); }
.chat-iconbtn--danger:hover { color: var(--danger); }

/* `margin: 0` : .card pose une marge haute de var(--sp-4) que le bouton
   « Nouvelle conversation » n'a pas, donc la carte commencait 16 px plus bas
   que la colonne (demande Marek, 2026-09-09).
   La hauteur suit la fenetre au lieu d'un 62vh fixe qui laissait un vide sous
   la carte : en sont retires l'en-tete colle (56 px, DS), le padding de
   .scroll (2 x var(--sp-8)) et la marge basse de .chat-layout. Le plancher
   garde la carte utilisable sur un ecran court. Les 164 px sont mesures dans
   Chromium (tests/test_chat_page_web.py), pas devines. */
.chat-card {
  padding: 0; margin: 0; display: flex; flex-direction: column;
  height: calc(100vh - 164px); min-height: 420px;
}
/* Le titre du fil : meme trait que la zone de saisie, en miroir. `flex: none`
   sinon il se ferait comprimer par le fil. Tronque, parce qu'un titre
   automatique monte a 60 caracteres et ne doit pas elargir la carte. Les
   proprietes de `h2` (petites capitales de section) sont toutes reprises :
   ici c'est un vrai titre, pas une etiquette. */
.chat-card__head {
  flex: none; display: flex; align-items: baseline; gap: var(--sp-3);
  border-bottom: 1px solid var(--line); background: var(--paper-head);
  padding: 12px var(--row-pad-x);
}
.chat-card__compte {
  flex: none; margin-left: auto; font-size: var(--fs-12);
  color: var(--ink-lbl); white-space: nowrap;
}
.chat-card__title {
  font: var(--text-title); font-size: var(--fs-15); font-weight: 600;
  letter-spacing: normal; text-transform: none; color: var(--ink); margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-log { flex: 1; overflow-y: auto; padding: var(--sp-5) var(--row-pad-x); }
/* L'accueil : qui parle, ce qu'il voit, et trois questions d'un clic. */
.chat-accueil { display: flex; flex-direction: column; gap: var(--sp-4); max-width: 640px; }
.chat-accueil__mot { display: flex; gap: var(--sp-3); align-items: flex-start; }
.chat-accueil__texte {
  margin: 0; font-size: var(--fs-14); line-height: var(--lh-body); color: var(--ink-2);
}
/* La pastille d'Erikia : sa tete, en or, la voix d'Erikia dans tout le
   produit (plus d'etoile IA depuis le 2026-10-02). */
.chat-avatar {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--blue-tint); border: 1px solid var(--blue-line);
  color: var(--blue-strong);
  display: inline-flex; align-items: center; justify-content: center;
}
.chat-accueil__exemples {
  display: flex; flex-wrap: wrap; gap: 6px; padding-left: calc(28px + var(--sp-3));
}
/* Un exemple est une PASTILLE cliquable, memes cotes que .bvx-chip. */
.chat-exemple {
  display: inline-flex; align-items: center; min-height: 32px;
  padding: 6px var(--sp-3); cursor: pointer; text-align: left;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--white); color: var(--ink-2);
  font: 500 var(--fs-12)/1.3 var(--font-sans);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.chat-exemple:hover {
  border-color: var(--blue-line); background: var(--blue-tint); color: var(--blue-strong);
}
/* La saisie, sur fond creuse : elle se detache du fil sans trait dur. */
.chat-form {
  display: flex; gap: var(--sp-2); align-items: flex-end;
  border-top: 1px solid var(--line); background: var(--paper-inset);
  padding: var(--sp-3) var(--row-pad-x) var(--sp-2); margin: 0;
}
.chat-form textarea {
  flex: 1; min-width: 0; margin: 0; resize: none;
  min-height: var(--control-h); max-height: 160px;
  padding: 9px var(--sp-3); line-height: 1.45;
}
.chat-form__pied {
  display: flex; flex-direction: column; gap: 2px;
  padding: 0 var(--row-pad-x) var(--sp-3); background: var(--paper-inset);
  border-radius: 0 0 var(--r-xs) var(--r-xs);
}
.chat-form__aide {
  margin: 0; font-size: var(--fs-12); line-height: var(--lh-snug); color: var(--ink-lbl);
}
.chat-msg {
  max-width: 85%; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm);
  margin: var(--sp-2) 0; white-space: pre-wrap; line-height: var(--lh-body);
  font-size: var(--fs-14);
}
.chat-bot { background: var(--surface-ai); border: 1px solid var(--blue-line); color: var(--ink); border-bottom-left-radius: var(--r-xs); }
/* Liens des reponses : Meridian pointe vers les pages de l'app (briefings,
   reglages...). Soulignement discret pour dire « cliquez-moi » sans crier. */
.chat-bot a {
  color: var(--blue-strong); font-weight: 600;
  text-decoration: underline; text-decoration-color: var(--blue-line);
  text-underline-offset: 2px;
}
.chat-bot a:hover { text-decoration-color: var(--blue-strong); }
.chat-user { background: var(--blue-deep); color: var(--white); margin-left: auto; border-bottom-right-radius: var(--r-xs); }
.chat-wait { color: var(--ink-3); font-style: italic; background: transparent; border: none; }

/* --- Meridian partout : bouton flottant + fenetre de discussion --------------
   Couches : sous le tiroir mobile (58/60) pour ne jamais flotter par-dessus le
   voile de navigation, sous le modal (80).

   `--fab-bottom` est la hauteur d'une barre d'actions collante quand la page en
   porte une (.form-sticky, .ob-nav) : la pastille passe AU-DESSUS au lieu de la
   recouvrir, en gardant exactement la meme respiration qu'ailleurs. La valeur
   est MESUREE par meridian_widget.js, parce que la barre passe sur deux lignes
   des que son texte d'appui ne tient plus, et sur mobile a coup sur. Elle vaut
   0 par defaut : sans JavaScript, la pastille se pose exactement ou avant. */
.mw-fab-wrap {
  position: fixed; right: 20px; bottom: calc(var(--fab-gap) + var(--fab-bottom)); z-index: 50;
  display: inline-flex; align-items: center; gap: 4px;
}
.mw-fab {
  height: var(--fab-h); padding: 0 var(--sp-4) 0 var(--sp-3); border-radius: var(--r-sm); cursor: pointer;
  background: var(--white); color: var(--blue-strong); border: 1px solid var(--blue-line);
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font: var(--text-label); font-size: var(--fs-14); font-weight: 600;
  box-shadow: var(--shadow-raised);
  /* La hauteur vit dans un jeton : la fenetre de discussion s'en sert pour se
     poser juste au-dessus, au lieu du 84px en dur d'avant. */
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.mw-fab svg { color: var(--blue); flex: none; }
.mw-fab svg.logo-demander { width: 16.2px; height: 16.2px; }
.mw-fab:hover { transform: translateY(-1px); box-shadow: var(--shadow-overlay); background: var(--blue-tint); }
.mw-fab:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.mw-panel {
  position: fixed; right: 20px; z-index: 79;
  bottom: calc(var(--fab-gap) + var(--fab-h) + var(--fab-gap) + var(--fab-bottom));
  width: 400px; max-width: calc(100vw - 40px); height: min(640px, 80vh);
  display: flex; flex-direction: column;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); box-shadow: var(--shadow-overlay);
  animation: mds-pop var(--t-med) var(--ease);
}
.mw-panel__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line);
  background: var(--paper); border-radius: var(--r-xs) var(--r-xs) 0 0;
}
.mw-panel__title { display: inline-flex; align-items: center; gap: var(--sp-2); font-weight: 600; color: var(--ink); }
.mw-panel__actions { display: inline-flex; align-items: center; gap: var(--sp-2); }
.mw-panel__close {
  border: none; background: none; cursor: pointer; font-size: 22px; line-height: 1;
  color: var(--ink-3); width: 32px; height: 32px; border-radius: var(--r-sm);
}
.mw-panel__close:hover { background: var(--paper-3); color: var(--ink); }
.mw-panel__log { flex: 1; overflow-y: auto; padding: var(--sp-4); }
.mw-panel__form { margin: 0; }
@media (max-width: 820px) {
  /* Plein ecran : au-dessus de l'en-tete mobile (55), sous le tiroir (58/60). */
  .mw-panel { inset: 0; width: auto; max-width: none; height: auto; border-radius: 0; z-index: 70; }
  .mw-panel__head { border-radius: 0; padding-top: max(var(--sp-3), env(safe-area-inset-top)); }
  .mw-panel__form { padding-bottom: max(var(--sp-4), env(safe-area-inset-bottom)); }
  body.mw-ouvert .mw-fab-wrap { display: none; }
  body.mw-ouvert { overflow: hidden; }
  .mw-fab-wrap { right: 14px; bottom: calc(max(14px, env(safe-area-inset-bottom)) + var(--fab-bottom)); }
}
@media (prefers-reduced-motion: reduce) {
  .mw-panel { animation: none; }
  .mw-fab { transition: none; }
}

/* ============================================================
   Notifications : credit, pastille de la barre, petite fenetre
   ============================================================ */
.sb__credit {
  font-size: 11px; color: var(--nav-fg-dim); letter-spacing: .01em;
  padding: 0 var(--sp-2) var(--sp-3); margin-top: calc(-1 * var(--sp-3));
}
/* Le bouton Notifications ressemble aux liens de navigation. */
.sb-notif { width: 100%; border: 0; background: none; text-align: left; font-family: inherit; }
.sb-notif[aria-expanded="true"] { background: var(--nav-bg-active); color: var(--white); }

.notif-panel {
  position: fixed; left: calc(var(--sidebar-w) + 12px); top: var(--top-h); z-index: 79;
  width: 380px; max-width: calc(100vw - var(--sidebar-w) - 24px); max-height: 70vh;
  display: flex; flex-direction: column;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); box-shadow: var(--shadow-overlay);
  animation: mds-pop var(--t-med) var(--ease);
}
.notif-panel__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line);
}
.notif-panel__title { font-weight: 600; color: var(--ink); }
.notif-panel__actions { display: inline-flex; align-items: center; gap: var(--sp-2); }
.notif-liste { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; }
.notif-item {
  display: flex; gap: var(--sp-3); width: 100%; text-align: left;
  border: 0; background: none; padding: var(--sp-3) var(--sp-4); border-radius: 0;
  min-height: var(--row-h); border-bottom: 1px solid var(--paper-3);
  cursor: pointer; font: inherit; color: var(--ink);
  transition: background var(--t-fast) var(--ease);
}
.notif-item:hover { background: var(--paper-row-hover); }
.notif-item.is-nonlue { background: var(--paper); }
.notif-item.is-nonlue:hover { background: var(--paper-3); }
.notif-item__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--blue); flex: none; margin-top: 6px; }
.notif-item.is-lue .notif-item__dot { background: var(--line-mute); }
.notif-item__body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.notif-item__titre { font-weight: 600; font-size: var(--fs-14); line-height: 1.3; }
.notif-item.is-lue .notif-item__titre { font-weight: 500; color: var(--ink-2); }
.notif-item__msg { font-size: var(--fs-13); color: var(--ink-2); line-height: 1.45; }
.notif-item__date { font-size: var(--fs-12); color: var(--ink-lbl); margin-top: 2px; }
.notif-panel__vide { margin: 0; padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--ink-3); font-size: var(--fs-13); }
.notif-panel__foot {
  padding: var(--sp-2) var(--sp-4); border-top: 1px solid var(--line);
  font-size: var(--fs-12); color: var(--ink-lbl); background: var(--paper);
  border-radius: 0 0 var(--r-xs) var(--r-xs);
}
@media (max-width: 820px) {
  /* Plein ecran, au-dessus du tiroir (60) et de l'en-tete (55), sous le modal (80). */
  .notif-panel { inset: 0; left: 0; top: 0; width: auto; max-width: none; max-height: none; border-radius: 0; z-index: 70; }
  .notif-panel__head { padding-top: max(var(--sp-3), env(safe-area-inset-top)); }
  .notif-panel__foot { border-radius: 0; padding-bottom: max(var(--sp-2), env(safe-area-inset-bottom)); }
}
@media (prefers-reduced-motion: reduce) { .notif-panel { animation: none; } }

/* Une note en modification (le crayon, `?modifier=<id>`). */
.note__form { display: flex; flex-direction: column; gap: var(--sp-2); width: 100%; }
.note__form textarea {
  min-width: 0; font: inherit; font-size: var(--fs-14);
  padding: var(--sp-2); border: 1px solid var(--line); border-radius: var(--r-xs);
}
.note__actions { display: flex; gap: var(--sp-2); }

/* Page de rétroaction */
.fb-card { margin-bottom: var(--sp-4); }
.fb-card__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--sp-4); margin-bottom: var(--sp-3);
  padding-bottom: var(--sp-3); border-bottom: 1px solid var(--line);
}
.fb-card__name { font-size: var(--fs-16); font-weight: 600; }
.fb-card__sub { color: var(--ink-3); font-size: var(--fs-13); margin-top: 2px; }
.fb-contacted {
  display: inline-flex; align-items: center; gap: var(--sp-2); flex: none;
  font-size: var(--fs-13); color: var(--ink-2); margin: 0;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-tag);
  padding: 6px var(--sp-4); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.fb-contacted:hover { border-color: var(--blue-line); }
.fb-contacted input { width: auto; margin: 0; accent-color: var(--blue); }
.fb-contacted:has(input:checked) { background: var(--blue-tint); border-color: var(--blue-line); color: var(--blue-strong); }


/* ============================================================
   Viewer de briefing
   ============================================================ */
/* Master-détail : liste d'entreprises (gauche) + panneau de détail (droite).
   Tout texte de l'espace peut se couper n'importe où : une URL de 120
   caractères dans un courriel, une adresse de 70, un nom d'entreprise à mot
   unique ne doivent jamais élargir la page (mordu sur mobile le 2026-09-01 :
   le banc ne mesurait que le panneau actif). overflow-wrap est hérité : une
   règle couvre toute la grille. */
/* Les pages a deux colonnes (Pipeline, page d'entreprise, Profils,
   Reglages, Administration, Demander a Erikia) partagent les memes mesures
   (demande Marek, 2026-10-09) : une colonne de 288 px, puis le meme ecart
   qu'entre la barre laterale et cette colonne (le --sp-10 de .scroll), un
   filet de 1 px en son milieu. Le filet vit sur la zone de contenu : il
   part de la ligne sous le titre de la page et descend jusqu'en bas. Un
   message de confirmation pleine largeur, au-dessus de la grille, passe
   par-dessus (positionne, il se peint apres). Sous 900 px, tout s'empile
   et le filet disparait. */
.scroll { --colonne-w: 288px; --colonne-ecart: var(--sp-10); }
.bvx { display: grid; grid-template-columns: var(--colonne-w) 1fr; gap: var(--sp-6) var(--colonne-ecart); align-items: start; overflow-wrap: anywhere; }
.scroll:has(> .bvx, > .chat-layout) { position: relative; }
.scroll:has(> .bvx, > .chat-layout)::before {
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(var(--sp-10) + var(--colonne-w) + var(--colonne-ecart) / 2); width: 1px;
  background: var(--line-strong); pointer-events: none;
}
.scroll > .note-line { position: relative; }
/* Les deux colonnes commencent a la meme hauteur (demande Marek, 2026-10-12) :
   le premier element de chaque colonne, et le titre ou le bloc qui ouvre ce
   premier element, n'ont pas de marge haute. Les marges par defaut d'un
   formulaire (8 px), d'une carte (16 px) et d'un titre de section (32 px)
   decalaient la colonne de droite (Criteres de qualification : 40 px) ou de
   gauche (Pipeline). Le retour d'un telephone, cache sur ordinateur, ne
   compte pas : c'est l'element qui le suit qui ouvre la colonne. Un champ
   cache non plus (le formulaire des criteres s'ouvre sur lineage_id, son
   titre vient apres). Garde-fou : verif_mobile.py --alignement. */
.bvx > * > :is(:first-child, .bvx-retour + *),
.bvx > * > :is(:first-child, .bvx-retour + *) > :nth-child(1 of :not([type="hidden"])) { margin-top: 0; }
@media (max-width: 900px) {
  .bvx { grid-template-columns: 1fr; }
  .scroll:has(> .bvx, > .chat-layout)::before { content: none; }
}
/* La barre « Enregistrer » deborde de 40 px pour toucher le bord de la
   page ; dans la colonne de droite (Profils, Reglages), les 24 px d'ecart
   ne suffisaient pas et elle recouvrait la colonne de gauche (demande
   Marek, 2026-10-09). Elle part donc du bord de sa colonne. */
@media (min-width: 901px) {
  .bvx-detail .form-sticky { margin-left: 0; padding-left: 0; }
}
.bvx-list {
  position: sticky; top: calc(var(--top-h) + 12px); display: flex; flex-direction: column;
  gap: var(--sp-2); max-height: calc(100vh - var(--top-h) - 32px); min-width: 0;
}
.bvx-filter { flex: none; }
/* Point de couleur : il dit la nature d'un bloc (fait sourcé, supposition,
   chose à vérifier) avec les mêmes clés que les pastilles de stade. */
.bvx-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--line-mute); }
/* Même clé, même couleur que la pastille de stade ci-dessous (0.3.35). */
.bvx-dot--ready { background: var(--ok); }
.bvx-dot--info { background: var(--blue); }
.bvx-dot--ok { background: var(--ok); }
.bvx-dot--warn { background: var(--warn); }
.bvx-dot--muted { background: var(--line-mute); }
.bvx-dot--danger { background: var(--danger); }
.bvx-dot--violet { background: var(--violet); }
.bvx-dot--azur { background: var(--azur); }
.bvx-fit {
  flex: none; text-align: right; font: 600 var(--fs-13)/1 var(--font-mono);
  font-variant-numeric: tabular-nums; color: var(--ink-3); white-space: nowrap;
}
.bvx-fit--hi { color: var(--ok); }
.bvx-fit--lo { color: var(--warn); }

/* --- Le pipeline unique (/pipeline, maquette Claude Design de Marek,
   0.4.24) : le rail de selection a gauche, la table « Outlook » triable a
   droite. Les composants sont ceux du produit (.bvx-chip, .calls-table,
   .bvx-stage, .btn) ; ces classes ne posent que la disposition. --- */
.pg-rail { gap: var(--sp-5); }
.pg-bloc { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.pg-hint { margin: 0; font-size: var(--fs-12); line-height: var(--lh-snug); color: var(--ink-lbl); }

/* Le declencheur d'un menu (cohortes, tri). Rendu masque : le script le
   revele et replie le panneau, donc sans JavaScript le panneau reste en
   clair et le bouton n'apparait jamais. */
.pg-declencheur {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: var(--control-h); padding: 0 var(--sp-3);
  appearance: none; border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--white); color: var(--ink-2);
  font: 600 var(--fs-13)/1 var(--font-sans); cursor: pointer; white-space: nowrap;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.pg-declencheur:hover { border-color: var(--ink-4); }
.pg-declencheur[aria-expanded="true"] { background: var(--paper-3); border-color: var(--ink-4); }
.pg-declencheur__txt { flex: 1; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pg-chevron { flex: none; font-size: var(--fs-11); color: var(--ink-4); }
.pg-declencheur[aria-expanded="true"] .pg-chevron { transform: rotate(180deg); }
.pg-cohortes { position: relative; }
.pg-cohortes .pg-declencheur { width: 100%; }
.pg-menu { display: flex; flex-direction: column; gap: 1px; }
/* La liste des cohortes DEFILE, le bouton « Appliquer » reste dessous. Une
   mission par jour fait une cohorte de plus : passe une vingtaine, le menu
   flottant depassait le bas de l'ecran et rien ne permettait d'y descendre
   (constate par Marek le 2026-09-26). `min-height: 0` est ce qui autorise un
   enfant de colonne flex a retrecir sous son contenu — sans lui, `overflow`
   n'a rien a faire deborder. */
.pg-menu__liste {
  display: flex; flex-direction: column; gap: 1px;
  min-height: 0; overflow-y: auto; overscroll-behavior: contain;
}
/* Flottant SEULEMENT quand le script a pris la main (le declencheur est
   revele) : sans lui, le menu vit dans le flux et reste utilisable — et, dans
   le flux, la liste n'a aucune raison d'etre bornee. */
.pg-declencheur:not([hidden]) + .pg-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-xs);
  box-shadow: var(--shadow-menu); padding: 5px;
  max-height: min(60vh, 420px);
}
.pg-coche {
  display: flex; align-items: center; gap: var(--sp-2); min-height: 40px;
  padding: 0 var(--sp-2); border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--ink); cursor: pointer;
}
.pg-coche:hover { background: var(--paper-row-hover); }
.pg-coche__nom { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pg-coche .num { font-family: var(--font-mono); font-size: var(--fs-12); color: var(--ink-4); }
.pg-appliquer { align-self: flex-start; margin-top: var(--sp-2); }
.pg-export { padding-top: var(--sp-2); border-top: 1px solid var(--line); }
.pg-export__btn { justify-content: center; }
.bvx-chip__n { font: 500 var(--fs-12)/1 var(--font-mono); color: var(--ink-4); }
.bvx-chip.is-active .bvx-chip__n { color: var(--white); opacity: .7; }

/* La barre au-dessus de la table : ce que la selection montre, et le tri. */
.pg-corps { display: flex; flex-direction: column; gap: var(--sp-3); }
.pg-barre { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.pg-barre__txt { color: var(--ink-lbl); font-size: var(--fs-13); }
.pg-tri { position: relative; margin-left: auto; }
/* Sur ordinateur, les en-tetes de colonnes trient deja : le menu « Trier »
   les doublait (demande Marek, 2026-10-12). Il reste sur un telephone, ou la
   table devient des cartes sans en-tetes. */
@media (min-width: 821px) { .pg-tri { display: none; } }
.pg-tri__btn { height: var(--control-h-sm); font-size: var(--fs-12); }
.pg-menu--droite { left: auto; }
.pg-declencheur:not([hidden]) + .pg-menu--droite { left: auto; right: 0; min-width: 230px; }
.pg-option {
  display: flex; align-items: center; gap: var(--sp-2); min-height: 32px;
  padding: 0 var(--sp-2); border-radius: var(--r-sm);
  font: 500 var(--fs-13)/1.3 var(--font-sans); color: var(--ink); text-decoration: none;
}
.pg-option:hover { background: var(--paper-row-hover); text-decoration: none; color: var(--ink); }
.pg-option.is-active { font-weight: 600; color: var(--blue-strong); }
.pg-option__marque { margin-left: auto; width: 14px; text-align: right; color: var(--blue-strong); }

/* La table. En-tetes cliquables (une colonne triee porte sa fleche), etoile
   des favorites en tete de rangee, colonnes secondaires retirees quand la
   fenetre se serre : le nom garde la place qu'il lui faut. */
.pg-th {
  display: inline-flex; align-items: center; gap: 4px;
  color: inherit; font: inherit; letter-spacing: inherit; text-decoration: none;
}
.pg-th:hover { color: var(--ink-2); text-decoration: none; }
.pg-fleche { font: 500 9px/1 var(--font-mono); }
.pg-table th.num .pg-th { justify-content: flex-end; }
.pg-th-fav, .pg-td-fav { width: 26px; padding-right: 0; }
.pg-fav { display: flex; }
.pg-etoile {
  appearance: none; border: none; background: none; padding: 0; cursor: pointer;
  font-size: var(--fs-16); line-height: 1; color: var(--line-strong);
  transition: color var(--t-fast) var(--ease);
}
.pg-etoile:hover { color: var(--ink-4); }
.pg-etoile.is-on, .pg-etoile.is-on:hover { color: var(--blue-deep); }
.pg-td-nom { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
.pg-nom { display: block; font-weight: 600; color: var(--ink); text-decoration: none; }
.pg-nom:hover { color: var(--blue-strong); text-decoration: underline; }
.pg-sous { display: block; margin-top: 2px; font-size: var(--fs-12); color: var(--ink-lbl); }
.pg-td-sec, .pg-td-coh { color: var(--ink-3); }
.pg-td-coh { font-size: var(--fs-12); color: var(--ink-lbl); }
.pg-table { table-layout: fixed; }
.pg-table td { overflow: hidden; }
.pg-table tbody tr { cursor: pointer; }
/* Largeurs recalculees au plancher de 12 px (2026-09-11) : a 10 px, la
   pastille « A CONTACTER » et l'en-tete « SCORE » tenaient dans 112 et 78 px ;
   au plancher ils y etaient rognes. Fixe 460 px + 45 % = la table entiere
   (« Taille » remplace « Emp. » le 2026-10-02 : 80 px au lieu de 66). */
.pg-table th:nth-child(1) { width: 36px; }
.pg-table th:nth-child(2) { width: 23%; }
/* 172 px depuis « Rencontre prévue » (0.4.125) : la pastille la plus longue
   etait rognee a 144 px. */
.pg-table th:nth-child(3) { width: 172px; }
.pg-table th:nth-child(4) { width: 11%; }
.pg-table th:nth-child(5) { width: 80px; }
.pg-table th:nth-child(6) { width: 11%; }
.pg-table th:nth-child(7) { width: 108px; }
.pg-table th:nth-child(8) { width: 92px; }
.pg-nom, .pg-sous, .pg-td-sec, .pg-td-coh {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Les colonnes secondaires et le complement de la sous-ligne s'echangent :
   l'un ou l'autre, jamais les deux. Le seuil est passe de 1180 a 1500 px avec
   le plancher de 12 px (2026-09-11) : a huit colonnes, un portable de 1440 px
   ne laissait plus que six caracteres a « Secteur » et a « Marche ». Sous le
   seuil, Marche et Cohorte reviennent dans la sous-ligne et les colonnes qui
   restent reprennent la place. */
.pg-plus { display: none; }
@media (max-width: 1500px) {
  .pg-opt { display: none; }
  .pg-plus { display: inline; }
  .pg-table th:nth-child(2) { width: auto; }
  .pg-table th:nth-child(4) { width: 24%; }
}
.pg-vide__titre { font: 600 var(--fs-16)/1.3 var(--font-display); color: var(--ink); }

/* --- La page d'entreprise (/entreprises/{id}, 0.4.18 ; maquette Claude
   Design 0.4.25) : a gauche une carte de navigation (Brief et ses trois vues,
   Communications et Rencontre par contact), a droite la carte d'identite puis
   la section choisie. Tout le contenu est en CARTES : un en-tete en capitales
   sur --paper-head, puis des rangees a filets --paper-3, comme la table du
   pipeline. Ces classes ne posent que la disposition : les pastilles, les
   boutons et les scores restent .bvx-stage, .btn, .bvx-fit. --- */
.pe-rail { gap: var(--sp-3); }
/* La colonne collante ne rogne plus ses cartes (demande Marek, 2026-10-09).
   Colonne flex limitee a la hauteur de l'ecran : une carte en overflow
   hidden se laissait ecraser et coupait sa derniere entree (« Voix et
   messages ») pendant que la suivante debordait sous l'ecran. Les cartes
   gardent leur hauteur ; une colonne plus haute que l'ecran defile seule,
   sans barre visible, comme la barre laterale. Un anneau de focus collant
   au bord serait coupe : il passe a l'interieur.
   SANS `overscroll-behavior: contain` (2026-10-11, « on n'arrive pas a
   defiler le menu de gauche ») : sa hauteur suppose la colonne deja collee
   sous l'en-tete, mais avant que la page defile elle commence plus bas
   (sous « Retour au pipeline » sur une entreprise), et son bas sortait de
   l'ecran. Le confinement retenait la molette dans la colonne : la page ne
   defilait pas, la colonne ne se collait jamais, et « Exporter PDF » ou les
   derniers contacts restaient hors d'atteinte. Arrivee au bout, la molette
   passe maintenant a la page. */
.pe-rail { overflow-y: auto; scrollbar-width: none; }
.pe-rail::-webkit-scrollbar { display: none; }
.pe-rail > * { flex-shrink: 0; }
.pe-rail :focus-visible { outline-offset: -2px; }
.pe-carte {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); overflow: hidden; min-width: 0;
}
.pe-carte__tete {
  padding: var(--row-pad-y) var(--row-pad-x); background: var(--paper-head);
  border-bottom: 1px solid var(--line);
  font: var(--text-th); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-lbl);
}
/* Un en-tete qui porte aussi le score : le titre a gauche, le reste pousse a
   droite. `baseline` aligne le chiffre mono sur les capitales. */
.pe-carte__tete--barre {
  display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap;
}
.pe-carte__tete--barre > :first-child { margin-right: auto; }
.pe-carte__note { font-size: var(--fs-12); text-transform: none; letter-spacing: 0; }
.pe-carte__corps { padding: var(--sp-4) var(--row-pad-x); }
.pe-carte__pied {
  margin: 0; padding: var(--row-pad-y) var(--row-pad-x);
  font-size: var(--fs-12); line-height: var(--lh-snug); color: var(--ink-lbl);
}
/* Une carte de prose sans en-tete (« ou en est-elle ») : le texte respire.
   L'Apercu et la Strategie d'approche ont repris le bandeau gris des autres
   cartes le 2026-10-11 (demande Marek). */
.pe-carte--texte .pe-carte__corps { padding: var(--sp-2) var(--sp-5) var(--sp-4); }
/* La carte « ou en est-elle » n'a pas d'en-tete : ses paragraphes portent la
   respiration de la carte, pas la leur. */
.pe-carte__corps--etat { padding-top: var(--sp-4); }
.pe-carte__corps--etat > :first-child { margin-top: 0; }
.pe-carte__corps--etat > :last-child { margin-bottom: 0; }
/* Les autres participants de la rencontre (2026-10-07) : une case par
   contact, sous le choix du contact principal. L'etiquette entiere est la
   cible tactile. */
.pe-participants {
  margin: 0 0 var(--sp-3); padding: 0; border: 0;
  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); align-items: center;
}
.pe-participants > legend { padding: 0; margin-bottom: var(--sp-1); }
.pe-participants__choix {
  display: inline-flex; align-items: center; gap: var(--sp-2); min-height: 44px;
  font-size: var(--fs-14); cursor: pointer;
}
/* Les elements d'information (2026-10-07) : replies sous leur decompte par
   entreprise.js ; un fondu sur le papier de la carte dit qu'il y a une suite. */
.pe-elements .bv-brief__cols { margin: 0; }
.pe-elements__corps.est-replie { max-height: 220px; overflow: hidden; position: relative; }
.pe-elements__corps.est-replie::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 64px;
  background: linear-gradient(to bottom, transparent, var(--white)); pointer-events: none;
}
.pe-elements__bascule { margin-top: var(--sp-3); }
/* Dans une carte, la liste libelle/valeur perd son propre cadre : la carte le
   porte deja. Le dernier filet tombe aussi, sinon il double la bordure. */
.pe-carte > .pe-kv { margin: 0; border: 0; border-radius: 0; }

/* Le menu de la colonne : trois cartes (Brief, Communications, Plus) depuis
   le 2026-10-02, chacune son en-tete ; les liens sont des rangees
   cliquables pleine largeur. */
.pe-menu { display: block; padding: 5px; }
.pe-lien {
  display: flex; align-items: center; gap: var(--sp-2); min-height: 40px;
  padding: 0 var(--sp-3); border-radius: var(--r-sm);
  font: 600 var(--fs-13)/1.3 var(--font-sans); color: var(--ink); text-decoration: none;
}
.pe-lien:hover { background: var(--paper-row-hover); text-decoration: none; color: var(--ink); }
.pe-lien.is-active { background: var(--blue-tint); color: var(--blue-strong); }
.pe-lien--inerte { color: var(--ink-4); cursor: default; font-weight: 400; }
.pe-lien--inerte:hover { background: transparent; color: var(--ink-4); }
/* Un contact tient sur deux lignes : son nom, son titre dessous. */
.pe-lien--ct { padding-top: 5px; padding-bottom: 5px; }
.pe-lien__nom {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pe-lien__titre {
  font-weight: 400; font-size: var(--fs-12); color: var(--ink-lbl);
  overflow: hidden; text-overflow: ellipsis;
}
/* Le compte des incidents non vus, au bout de l'onglet (page Administration). */
.pe-lien__pastille { margin-left: auto; }
.pe-lien .num { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-12); color: var(--ink-4); }
/* Les favoris (2026-10-11, demande Marek) : une etoile en haut a droite de
   la carte de l'entreprise, grise au repos, noire une fois posee. */
.pe-etoile-form { position: absolute; top: var(--sp-3); right: var(--sp-3); margin: 0; }
.pe-etoile {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; appearance: none; cursor: pointer;
  border: 0; border-radius: var(--r-sm); background: transparent;
  color: var(--ink-4); font: 400 var(--fs-22)/1 var(--font-sans);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.pe-etoile:hover { background: var(--paper-row-hover); color: var(--ink-3); }
.pe-etoile.is-on, .pe-etoile.is-on:hover { color: var(--ink); }

/* Les onglets des Reglages (2026-10-02) : la colonne de la page d'entreprise.
   Les cartes de l'onglet s'espacent par le `gap` du corps, pas par leur
   propre marge (elle doublait l'ecart et decalait le haut). */
.rg-corps > .card, .pf-corps > .card { margin: 0; }
/* Le titre qui ouvre l'onglet n'a pas de marge haute : la regle generale
   « Les deux colonnes commencent a la meme hauteur » s'en charge. */
/* Le menu « Quel profil » du Profil : le choix, et son bouton sans JavaScript. */
.pf-profils { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-3); }
/* La liste et ses trois gestes sur UNE rangee (demande Marek, 2026-10-09) :
   la liste prend la place qui reste et coupe un nom trop long. */
.pf-rangee { display: flex; align-items: center; gap: 4px; }
.pf-choix { display: flex; align-items: center; gap: var(--sp-2); margin: 0; flex: 1; min-width: 0; }
.pf-choix select {
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pf-icone-form { display: flex; margin: 0; }
.pf-icone {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--control-h); height: var(--control-h); padding: 0;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--white); color: var(--ink-3); cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease);
}
.pf-icone svg { width: 16px; height: 16px; }
.pf-icone:hover { background: var(--paper-row-hover); color: var(--ink); }
.pf-icone--danger:hover { background: var(--danger-tint); border-color: var(--danger); color: var(--danger); }
/* Ajouter est le geste principal de la rangee : en noir, comme l'ancien
   bouton « Ajouter un profil ». */
.pf-icone--ajouter { background: var(--primary); border-color: var(--primary); color: var(--white); }
.pf-icone--ajouter:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: var(--white); }
.pf-icone:disabled, .pf-icone:disabled:hover {
  background: var(--white); border-color: var(--line); color: var(--ink-3);
  opacity: .4; cursor: not-allowed;
}
.pf-renommer { display: grid; gap: var(--sp-2); margin: 0; }
.pf-renommer__actions { display: flex; gap: 6px; }
/* « Ce qu'Erikia aimerait savoir » : en tete de la colonne, seule dans sa
   carte (demande Marek, 2026-10-09), en jaune. Le compte des questions en
   pastille, comme le badge des notifications ; le meme compte s'affiche
   a cote de « Profils » dans la barre laterale. */
.pf-questions__lien { background: var(--blue-tint-2); color: var(--ink); }
.pf-questions__lien:hover { background: var(--blue-light); color: var(--ink); }
.pf-questions__lien.is-active { background: var(--blue-bright); color: var(--sur-clair); }
.pf-questions__texte { flex: 1; min-width: 0; }
.pf-questions__n {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 7px; border-radius: var(--r-tag);
  background: var(--blue-deep); color: var(--blue-bright);
  font-size: var(--fs-12); font-weight: 700;
}
/* Le crayon d'un bloc « Ce qu'Erikia comprend... » (2026-10-11, demande
   Marek) : en haut a droite de la carte ; le texte lui laisse sa place. */
.pf-texte { position: relative; }
.pf-texte:not(.pf-texte--edition) { padding-right: 56px; }
.pf-crayon {
  position: absolute; top: var(--sp-2); right: var(--sp-2);
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--r-sm); color: var(--ink-3);
}
.pf-crayon:hover { background: var(--paper-row-hover); color: var(--ink); text-decoration: none; }
.pf-crayon svg { width: 16px; height: 16px; }
/* La carte des clients en modification : un client par groupe, sous un
   filet. Le filet vit sur l'enveloppe : celui d'un <fieldset> passe a travers
   sa legende. */
.pf-client { min-width: 0; }
.pf-client + .pf-client { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.pf-client__champs { border: 0; margin: 0; padding: 0; min-width: 0; }
.pf-client__nom { padding: 0; margin-bottom: var(--sp-2); font-weight: 600; color: var(--ink); }
.pf-client__retirer { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-13); color: var(--ink-2); }
.pf-client__etiquette { font-weight: 600; color: var(--ink-2); }
@media (max-width: 820px) {
  .pf-crayon { width: 44px; height: 44px; top: var(--sp-1); right: var(--sp-1); }
  .pf-client__retirer { min-height: 44px; }
}
/* Profil > Votre voix (2026-10-13, demande Marek) : la voix en lecture, comme
   les autres blocs « Ce qu'Erikia comprend... » : des etiquettes en petite
   capitale, les termes en pastilles ; sous un filet, la boite « Completer
   avec Erikia ». Les piliers en modification : un formulaire par pilier,
   sous un filet, et « Annuler » apres le dernier. */
.pf-voix { display: grid; gap: var(--sp-3); margin: 0; }
.pf-voix dt {
  margin-bottom: 4px; font: var(--text-caps); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-title);
}
.pf-voix dd { margin: 0; font-size: var(--fs-14); line-height: var(--lh-body); color: var(--ink); overflow-wrap: anywhere; }
.pf-voix__bloc { white-space: pre-line; }
.pf-voix__termes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.pf-voix__termes li {
  padding: 2px var(--sp-2); border: 1px solid var(--line); border-radius: var(--r-tag);
  background: var(--paper); font-size: var(--fs-13);
}
.pf-voix__erikia { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.pf-piliers { margin: 0; padding-left: 1.2em; }
.pf-pilier-lu + .pf-pilier-lu { margin-top: var(--sp-3); }
.pf-pilier + .pf-pilier, .pf-pilier + .actions { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--line); }

/* « Avec qui » de la section Rencontre : le contact se choisit ici. */
.pe-qui { display: flex; flex-direction: column; gap: var(--sp-2); }

.pe-corps { min-width: 0; display: flex; flex-direction: column; gap: var(--sp-4); }
/* La carte d'identite : le nom en grand, l'etat, la segmentation, les liens,
   puis les deux gestes qui mettent des agents au travail. */
.pe-identite {
  position: relative;
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-4);
}
/* La place de l'etoile, en haut a droite. */
.pe-identite > .pe-titre { padding-right: 44px; }
/* « Suivre la relation » (2026-10-11) : le titre et les six jalons, dans la
   rangee des gestes de la carte, a la place de « Recommencer ». */
.pe-suivre { display: flex; align-items: center; flex-wrap: wrap; gap: 6px var(--sp-2); }
.pe-suivre__titre {
  font: var(--text-caps); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-title); font-weight: 600;
}
/* Le formulaire de suivi sans JavaScript, dans la carte : la carte porte
   deja ses marges. */
.pe-identite > .pe-suivi__form { padding: var(--sp-3) 0 0; }
/* `h2` est un titre de SECTION en capitales 11 px dans tout le produit : ici
   c'est un nom propre, il reprend la casse et l'echelle d'affichage. */
.pe-nom {
  font: 600 var(--fs-28)/1.1 var(--font-display); letter-spacing: var(--track-display);
  text-transform: none; color: var(--ink); margin: 0;
}
/* Le nom et sa cohorte sur la meme ligne ; la pastille passe dessous quand
   le nom est long. */
.pe-titre { display: flex; align-items: center; gap: var(--sp-2) var(--sp-3); flex-wrap: wrap; }
.pe-titre .pe-nom { min-width: 0; }
.pe-cohorte { text-decoration: none; }
.pe-cohorte:hover { text-decoration: underline; }
.pe-score { display: inline-flex; align-items: baseline; gap: 6px; }
.pe-meta { margin: 0; font-size: var(--fs-13); line-height: var(--lh-body); color: var(--ink-3); }
.pe-liens { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin: 0; font-size: var(--fs-13); }
.pe-liens a { overflow-wrap: anywhere; }
.pe-point { color: var(--line-mute); }
.pe-gestes {
  display: flex; align-items: center; gap: 6px var(--sp-3); flex-wrap: wrap;
  padding-top: var(--sp-3); border-top: 1px solid var(--paper-3);
}
.pe-essais { margin: 0; }
/* La fiche de strategie modifiable (0.4.19) : ses champs en deux colonnes. */
.pe-strategie__grille { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin-top: var(--sp-3); }
/* La strategie se deplie (2026-10-11) : le bouton est le <summary>, sans
   triangle. */
.pe-strategie__bascule { list-style: none; width: fit-content; }
.pe-strategie__bascule::-webkit-details-marker { display: none; }
.pe-strategie__plus[open] > .pe-strategie__bascule { display: none; }
.pe-champ { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pe-champ textarea {
  width: 100%; font: inherit; font-size: var(--fs-13); line-height: var(--lh-body);
  padding: var(--sp-2); border: 1px solid var(--line); border-radius: var(--r-xs); resize: vertical;
}
/* La sequence des canaux (2026-10-09) : une phrase qui se lit d'une traite. */
.pe-champ--large { grid-column: 1 / -1; }
@media (max-width: 700px) { .pe-strategie__grille { grid-template-columns: 1fr; } }

/* Filtres par statut (pastilles cliquables, memes cotes que .mini-btn),
   badges de stade (pastille statique, regle de base avec .pill) et barre
   d'actions */
.bvx-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.bvx-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px;
  appearance: none; border: 1px solid var(--line-strong); background: var(--white);
  border-radius: var(--r-sm); padding: 0 var(--sp-3); font: var(--text-label);
  font-size: var(--fs-12); color: var(--ink-2); cursor: pointer; text-decoration: none;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.bvx-chip:hover { border-color: var(--ink-4); color: var(--ink-2); text-decoration: none; }
.bvx-chip.is-active { background: var(--primary); border-color: var(--primary); color: var(--white); }
/* Dans une table dense, la pastille descend a 20 px et 10 px de caractere :
   la rangee garde sa hauteur, la couleur garde son sens. */
.bvx-stage--sm { height: 24px; padding: 0 9px; font-size: var(--fs-12); }
.bvx-stage--ready, .bvx-stage--ok { background: var(--ok-tint); color: var(--ok); }
.bvx-stage--info { background: var(--blue-tint); color: var(--blue-strong); }
.bvx-stage--warn { background: var(--warn-tint); color: var(--warn); }
.bvx-stage--muted { background: var(--paper-3); color: var(--ink-3); }
.bvx-stage--danger { background: var(--danger-tint); color: var(--danger); }
.bvx-stage--violet { background: var(--violet-tint); color: var(--violet); }
.bvx-stage--azur { background: var(--azur-tint); color: var(--azur); }
.mini-btn--primary { background: var(--primary); border-color: var(--primary); color: var(--white); }
.mini-btn--primary:hover { background: var(--primary-hover); color: var(--white); }
/* Bandeau « les agents travaillent » d'une fiche du Pipeline : le travail
   part dans la file, la page reste ouverte, et on peut la quitter. */
.pv-travail {
  margin: var(--sp-3) 0; padding: var(--sp-3) var(--sp-4);
  background: var(--surface-ai); border: 1px solid var(--blue-line);
  border-radius: var(--r-xs); flex-wrap: wrap;
}
.pv-travail__txt { font-weight: 600; color: var(--blue-strong); }
/* Un export n'est pas une action d'agent : il reste discret, et centre sur la
   ligne du titre (la rangee est en `align-items: baseline`). */

.bvx-detail { min-width: 0; }
.bvx-note { font-size: var(--fs-14); line-height: var(--lh-body); margin: var(--sp-2) 0; }

/* Rang au podium (dans les sous-liens de contact de la page d'entreprise). */
.bvx-rank {
  background: var(--primary); color: var(--white); width: 20px; height: 20px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; font: 700 11px/1 var(--font-mono);
  /* Poppins pose ses chiffres un demi-pixel trop haut dans une ligne de
     hauteur 1 : un pixel de retrait en tete (boite border-box) les recentre. */
  padding-top: 1px;
}
.bvx-contact { display: none; }
.bvx-contact.is-active { display: block; }
.bvx-ct-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-4); flex-wrap: wrap; margin-bottom: var(--sp-2); }
.bvx-ct-head > div { min-width: 0; }
/* La relance à générer : un encadré en pointillé, vide jusqu'au clic. */
.bv-draft--a-venir { border-style: dashed; }
/* Sections « Ce qu'on sait », critères, sources... : toujours dépliées
   (plus de <details> repliable), un titre en capitales suffit. */
.bv-know__title {
  font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--ink-title); margin: var(--sp-3) 0 var(--sp-1); font-weight: 600;
}
/* Ce que l'Investigateur a trouve sur le contact : en tete de la section,
   deplie, sur la surface de la voix de l'IA (2026-10-02). */
.pe-recherche { margin: var(--sp-2) 0 var(--sp-3); }
.pe-recherche > .bv-know__title { margin-top: 0; }
/* Repliee a trois lignes (entreprise.js) ; la derniere finit sur des points
   de suspension. Les titres et paragraphes du portrait passent en ligne pour
   que les trois lignes soient du texte, pas un intertitre et deux marges. */
.pe-recherche__texte.est-replie {
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}
.pe-recherche__texte.est-replie > * { display: inline; margin: 0; font-size: inherit; }
.pe-recherche__texte.est-replie > * + *::before { content: " "; }
.pe-recherche__bascule { margin-top: var(--sp-2); }
/* Chaque communication sur fond BLANC (demande Marek, 2026-09-01) : sur la
   couleur de la page, les encadrés se lisaient comme des trous. */
.bv-draft {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); padding: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0;
}
.bv-draft .subject { font-weight: 600; }
.bv-draft .body { white-space: pre-wrap; margin-top: 6px; font-size: var(--fs-14); line-height: var(--lh-body); }

/* --- Chaque ebauche a l'air de ce qu'elle est (2026-10-11, demande Marek) ---
   Le courriel comme un vrai message (en-tete De / A / Objet, puis le corps),
   le script d'appel en etapes numerotees, le message LinkedIn en bulle. */
.courriel { margin-top: var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-xs); overflow: hidden; }
.courriel__entete {
  margin: 0; padding: var(--sp-2) var(--sp-4);
  background: var(--paper-head); border-bottom: 1px solid var(--line); font-size: var(--fs-13);
}
.courriel__ligne { display: flex; gap: var(--sp-3); padding: 3px 0; }
.courriel__ligne dt { flex: none; width: 52px; color: var(--ink-lbl); font-weight: 600; }
.courriel__ligne dd { margin: 0; min-width: 0; overflow-wrap: anywhere; color: var(--ink); }
.bv-draft .courriel__corps { margin: 0; padding: var(--sp-4); }
.script { list-style: none; margin: var(--sp-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.script__etape {
  display: flex; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--paper-head); border: 1px solid var(--line); border-radius: var(--r-xs);
}
.script__num {
  flex: none; width: 28px; height: 28px; padding-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill); background: var(--blue-deep); color: var(--white);
  font: 700 var(--fs-13)/1 var(--font-mono);
}
.script__contenu { flex: 1; min-width: 0; }
.script__titre {
  margin-bottom: 4px; font: var(--text-caps); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-title); font-weight: 600;
}
.script__texte { margin: 0; font-size: var(--fs-14); line-height: var(--lh-body); }
.script__points { margin: 0; padding-left: var(--sp-5); font-size: var(--fs-14); line-height: var(--lh-body); }
.script__points li + li { margin-top: 4px; }
.linkedin { display: flex; justify-content: flex-end; align-items: flex-end; gap: var(--sp-2); margin-top: var(--sp-3); }
/* Pleine largeur (demande Marek, 2026-10-11) : la bulle occupe la carte,
   l'avatar a sa droite ; « A ... » reste aligne a droite au-dessus. */
.linkedin__fil { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.linkedin__a { text-align: right; }
/* Le gris des etapes du script d'appel (demande Marek, 2026-10-12) : la
   bulle etait doree, elle se lisait comme un bouton. */
.bv-draft .linkedin__bulle {
  margin: 0; padding: var(--sp-3) var(--sp-4);
  background: var(--paper-head); border: 1px solid var(--line);
  border-radius: var(--r-track) var(--r-track) var(--r-xs) var(--r-track);
}
.linkedin__avatar {
  flex: none; width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill); background: var(--blue-deep); color: var(--white);
  font: 600 var(--fs-13)/1 var(--font-display);
}
.bv-draft-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.bv-actions { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.dlabel { font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--ink-title); font-weight: 600; }
.estatus { font-weight: 600; }
.estatus.ok { color: var(--ok); }
.estatus.warn { color: var(--warn); }
.estatus.bad { color: var(--danger); }
.fb-status { min-width: 70px; font-size: var(--fs-12); }

/* --- Suivi de la relation (0.4.27) : l'encadre en tete de la page
   d'entreprise. Six jalons ; cliquer l'un d'eux ouvre la fenetre, qui EST le
   formulaire ci-dessous, deplace par entreprise.js. Sans JavaScript, les
   boutons restent caches et le formulaire s'affiche deplie dans la carte :
   d'ou les deux mises en page dans le meme bloc. --- */
.pe-suivi__jalons { display: flex; flex-wrap: wrap; gap: 6px; }
/* Un jalon deja pose chez au moins un contact se porte en noir avec sa
   coche (recapitulatif), mais il reste CLIQUABLE : on peut vouloir le poser
   chez un autre interlocuteur. `.ct-btn.is-done` coupe les evenements de
   pointeur pour le tableau de bord, ou le bouton est le geste lui-meme. */
.pe-suivi__jalons .ct-btn.is-done { pointer-events: auto; cursor: pointer; }
.pe-suivi__form {
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-4) var(--row-pad-x);
  border-top: 1px solid var(--paper-3);
}
/* Dans la fenetre, le formulaire porte deja la respiration du dialogue. */
.mds-dialog__body > .pe-suivi__form { padding: 0; border-top: 0; }
.pe-suivi__legende {
  display: block; margin-bottom: 5px;
  font: var(--text-th); letter-spacing: var(--track-caps);
  text-transform: uppercase; color: var(--ink-lbl);
}
.pe-suivi__groupe { margin: 0; padding: 0; border: 0; }
.pe-suivi__choix { display: flex; flex-wrap: wrap; gap: 6px; }
.pe-suivi__radio {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--control-h); padding: 0 var(--sp-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--ink-2); cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.pe-suivi__radio:hover { background: var(--paper-row-hover); }
.pe-suivi__radio:has(input:checked) {
  background: var(--primary); border-color: var(--primary); color: var(--white);
}
/* Deja pose pour le contact choisi : la fenetre le dit, sans l'interdire
   (le service est idempotent, reposer un jalon est un no-op). */
.pe-suivi__radio.is-done { border-color: var(--blue-line); background: var(--blue-tint); }
.pe-suivi__radio.is-done > span::after { content: " ✓"; color: var(--blue-strong); }
.pe-suivi__paire { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.pe-suivi__note { resize: vertical; }
.pe-suivi__pied { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* Dans la fenetre, le pied reprend la forme de .mds-dialog__foot : les gestes
   a droite, « Annuler » en tete de file (insere par le script). */
.mds-dialog__body .pe-suivi__pied { justify-content: flex-end; }
/* « Generer une relance » (2026-10-12, demande Marek) : la fenetre reprend
   celle du suivi (.pe-suivi__legende, __radio, __pied), plus large pour
   lire un courriel envoye. Sans JavaScript, le formulaire est deplie sous
   les relances, tous les canaux avec lui. */
.pe-relance__scrim .mds-dialog { max-width: 640px; }
.pe-relances > .pe-relance__ouvrir { align-self: flex-start; margin-top: var(--sp-3); }
.pe-relance { display: flex; flex-direction: column; gap: var(--sp-4); margin-top: var(--sp-3); min-width: 0; }
.mds-dialog__body > .pe-relance { margin-top: 0; }
.pe-relance__canaux { border: 0; margin: 0; padding: 0; min-width: 0; }
.pe-relance__choix { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); }
.pe-relance__canal { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.pe-relance__canal[hidden] { display: none; }
.pe-relance__envoi { margin: 0; }
.pe-relance__envoi input { margin-bottom: 6px; }
@media (max-width: 700px) {
  .pe-suivi__paire { grid-template-columns: 1fr; }
}

.pv-meet-vide {
  background: var(--white); border: 1px dashed var(--line-mute);
  border-radius: var(--r-xs); padding: var(--sp-6); text-align: center;
}
.pv-meet-vide p { max-width: 52ch; margin-left: auto; margin-right: auto; }
/* Ce que le contact a répondu (phase 6) : la zone de texte de la section Rencontre. */
.pv-reponse { margin: 0 0 var(--sp-4); }
.pv-reponse__label { display: block; margin-bottom: var(--sp-1); }
.pv-reponse textarea { width: 100%; box-sizing: border-box; margin: 0; }
.pv-autre { margin-top: var(--sp-5); }
.pv-autre__form { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; margin: var(--sp-2) 0 0; }
.pv-autre__form input[type=text] { flex: 1 1 200px; min-width: 0; height: var(--control-h-sm); padding: 0 var(--sp-3); font-size: var(--fs-13); margin: 0; }
/* Pastille « ajoute a la main » d'un contact hors podium (sous-lien de la
   page d'entreprise ; le nom de classe date des puces de l'ancien espace). */
.pv-ct-chip__man {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--paper-3); color: var(--ink-2); font-weight: 700; font-size: var(--fs-12);
}
@media (max-width: 900px) {
  /* Le retour au flux DOIT vivre ici, APRES la regle .bvx-list de base :
     a specificite egale c'est l'ordre de source qui tranche, et un override
     media place AVANT la regle de base perd — la liste restait sticky sur
     mobile et flottait par-dessus la fiche en defilant (mordu le 2026-08-30). */
  .bvx-list { position: static; max-height: none; }
}

/* --- Un ecran a la fois sur un telephone (demande Marek, 2026-10-11 : « je
   veux pas le menu en haut des pages, ca fait des pages trop longues ») ---
   Les pages a menu (Pipeline, une entreprise, Profils, Reglages,
   Administration, Demander a Erikia) ne montrent plus, sous 900 px, le menu
   empile au-dessus du contenu : c'est le menu OU la section, comme sur un
   iPhone, avec un retour (.bvx-retour) vers le menu. Le serveur choisit
   l'ecran d'apres l'adresse (`bvx--menu` / `bvx--detail`) : rien ne depend
   de JavaScript. Sur l'ecran du menu, ce qui porte `.bvx-garde` reste
   visible et monte au-dessus du menu (la carte d'une entreprise et sa
   fenetre de suivi, une proposition de profil qui attend un accord) ;
   `.bvx-menu-seul` quitte l'ecran d'une section. Sur ordinateur, rien ne
   change : les deux sont cote a cote. */
.bvx-retour, .pg-voir { display: none; }
/* Le nom d'une entreprise peut etre un seul mot tres long : il se coupe en
   points de suspension plutot que de faire deborder la page. */
.bvx-retour { max-width: 100%; align-self: flex-start; justify-self: start; }
.bvx-retour__nom { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-card__head .bvx-retour { margin: 0; flex: none; }
@media (max-width: 900px) {
  .bvx-retour { display: inline-flex; }
  .retour.bvx-bureau-seul { display: none; }
  .bvx--menu > .bvx-detail { order: -1; }
  .bvx--menu > .bvx-detail > :not(.bvx-garde) { display: none; }
  .bvx--menu > .bvx-detail:not(:has(> .bvx-garde)) { display: none; }
  .bvx--detail > .bvx-list { display: none; }
  .bvx--detail .bvx-menu-seul { display: none; }
  /* L'ecran du menu n'a aucune section ouverte : aucune entree allumee
     (sur ordinateur, la section par defaut est a cote, et le reste). */
  .bvx--menu .pe-lien.is-active { background: transparent; color: var(--ink); }
  .bvx--menu .pe-lien.is-active:hover { background: var(--paper-row-hover); }
  .pg-voir { display: flex; justify-content: center; width: 100%; }
  .chat-layout--menu > .chat-card { display: none; }
  .chat-layout--detail > .chat-side { display: none; }
  /* minmax(0, 1fr) et non 1fr : le retour, le titre et le compte du fil
     tiennent sur une ligne, et la colonne doit pouvoir retrecir sous leur
     largeur minimale (le titre se coupe en points de suspension). */
  .chat-layout { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   Onboarding en cours (spinner)
   ============================================================ */
.status-line { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-16); }
.spinner {
  width: 18px; height: 18px; border: 3px solid var(--line-strong);
  border-top-color: var(--blue); border-radius: 50%;
  animation: spin .9s linear infinite;
}
.error { color: var(--danger); }

/* ============================================================
   Salle de veille (pipeline complet, thème clair)
   ============================================================ */
/* Le bandeau de mission (0.4.30) : il ne parait QUE pendant qu'il se passe
   quelque chose, et il porte tout ce qui concerne la mission en cours :
   l'etat, la progression, le temps restant, le temps ecoule et les deux
   gestes d'arret. Or pale : la couleur du travail des agents dans tout le
   produit (--surface-ai, comme le bandeau des pages d'entreprise). */
.ag-etat {
  display: flex; align-items: flex-start; gap: var(--sp-3); flex-wrap: wrap;
  background: var(--surface-ai); border: 1px solid var(--blue-line);
  border-radius: var(--r-xs); padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-5);
}
.ag-etat__point {
  width: 8px; height: 8px; border-radius: 50%; background: var(--blue);
  flex: none; margin-top: 6px; animation: pulse 1.4s var(--ease) infinite;
}
@media (prefers-reduced-motion: reduce) { .ag-etat__point { animation: none; } }
.ag-etat__corps { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.ag-etat__ligne { font-weight: 600; color: var(--blue-strong); font-size: var(--fs-13); }
.ag-etat__note { font-size: var(--fs-12); color: var(--ink-3); line-height: var(--lh-snug); }
/* La progression de la mission : la meme barre de 4 px que les agents, et le
   texte qui la dit en toutes lettres (« 4 sur 10 entreprises · environ
   12 min restantes »). */
.ag-etat__progres { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.ag-etat__barre {
  flex: 1 1 160px; min-width: 120px; height: 4px; background: var(--white);
  border-radius: var(--r-pill); overflow: hidden;
}
.ag-etat__rempli {
  display: block; height: 100%; width: 0; background: var(--blue);
  transition: width .6s var(--ease);
}
.ag-etat__eta {
  font: var(--text-data); font-size: var(--fs-12); color: var(--ink-2);
  white-space: nowrap;
}
.veille-meta {
  font-family: var(--font-mono); font-size: var(--fs-13); color: var(--ink-3);
  display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap;
}

/* -- Bandeau des agents : chaque agent apparait UNE fois ; les etapes
      automatiques (selection, verification, livraison) restent discretes. -- */
/* Une carte de communication qu'on vient de reecrire : le texte change sous
   les yeux, sans rechargement, donc il faut dire OU. Deux battements, puis
   plus rien. `prefers-reduced-motion` neutralise l'animation plus bas. */
.bv-draft.is-refait { animation: pulse .9s ease-out 2; }
@media (prefers-reduced-motion: reduce) { .bv-draft.is-refait { animation: none; } }
.bv-draft__travail { margin: var(--sp-3) 0 0; }


/* ============================================================
   Poste de pilotage : lancement + grille des carres d'agents
   ============================================================ */
.ag-launch { margin-bottom: var(--sp-5); }
.ag-launch__row { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }
.ag-launch__profil { display: flex; flex-direction: column; gap: 4px; margin: 0; min-width: 220px; }
.ag-launch__profil select { margin: 0; }
.ag-launch__cta { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; flex: 1; }
.ag-launch__cta:empty { display: none; }

/* Runs planifies */
.ag-plan { margin-bottom: var(--sp-5); }
.ag-plan__title {
  margin: 0 0 var(--sp-1); font: var(--text-title); font-size: var(--fs-18);
  letter-spacing: 0; text-transform: none; color: var(--ink);
}
.ag-plan__add { margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.ag-plan__list { list-style: none; margin: 0 0 var(--sp-3); padding: 0; }
.ag-plan__item {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  min-height: var(--row-h); padding: var(--sp-2) 0; border-top: 1px solid var(--paper-3);
}
.ag-plan__item:first-child { border-top: none; }
.ag-plan__item.is-off .ag-plan__when, .ag-plan__item.is-off .ag-plan__profil { color: var(--ink-4); }
.ag-plan__when { font-weight: 600; color: var(--ink); }
.ag-plan__profil { font-size: var(--fs-13); color: var(--ink-2); }
.ag-plan__next { flex: 1; min-width: 0; }
.ag-plan__actions { display: flex; gap: var(--sp-2); }
.ag-plan__actions form { margin: 0; }
.ag-plan__form { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: flex-end; margin: var(--sp-3) 0 0; }
.ag-plan__form label { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-13); color: var(--ink-2); margin: 0; }
.ag-plan__form input, .ag-plan__form select { margin: 0; width: auto; min-width: 90px; }

/* 360px et non 300 (demande Marek, 2026-09-03) : a 300, un ecran large posait
   les cinq carres cote a cote, chacun a sa largeur minimale, et le nom de
   l'agent passait sous sa pastille. A 360, on tombe a trois ou quatre colonnes
   et le contenu respire. */
/* Les cinq agents : une LISTE depuis 0.4.30 (maquette de Marek), plus cinq
   cartes a mini-terminal. C'est la table « Outlook » du produit (.calls-table)
   avec deux colonnes propres : ou en est l'agent, et le lien vers sa section
   des Reglages. La colonne de ce qu'il a produit est partie le 2026-10-02 :
   la progression prend sa place. */
.ag-liste {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xs); overflow: hidden; margin-bottom: var(--sp-5);
}
.ag-table { table-layout: fixed; }
.ag-table th:nth-child(1) { width: 30px; padding-right: 0; }
.ag-table th:nth-child(3) { width: 32%; }
.ag-table th:nth-child(4) { width: 118px; }
.ag-row__etat { padding-right: 0; }
.ag-row__point {
  display: block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--line-strong); margin: 0 auto;
}
.ag-row__nom { display: block; font-weight: 600; color: var(--ink); }
/* Le numero de l etape, puis son verbe a l infinitif ; le nom de code de
   l agent ne s affiche plus (2026-10-02). */
.ag-row__nom .bvx-rank { margin-right: var(--sp-2); vertical-align: 1px; }
/* Dessous, ce que fait l etape (la phrase des Reglages), alignee sur le verbe
   plutot que sur la pastille de rang (20px). Le nom et la phrase vivent dans
   UN bloc : en carte mobile, la cellule est un flex qui les aurait mis cote a
   cote. Sur deux a quatre lignes, la cellule respire au-dessus et dessous. */
@media (min-width: 821px) {
  .ag-table td.ag-row__etape { padding-top: var(--sp-3); padding-bottom: var(--sp-3); }
}
.ag-row__bloc { min-width: 0; }
.ag-row__role {
  display: block; margin-top: var(--sp-1); padding-left: calc(20px + var(--sp-2));
  font-size: var(--fs-13); color: var(--ink-3); line-height: var(--lh-snug);
}
/* Le flex vit DANS la cellule : une <td> en flex n'est plus une cellule de
   tableau, ne prend pas la hauteur de la rangee, et son filet se decale des
   que l'etape tient sur plusieurs lignes. `flex: 1` sert en carte mobile, ou
   la cellule devient un flex (libelle, puis ce bloc). */
.ag-row__prog { display: flex; flex: 1; align-items: center; gap: var(--sp-2); min-width: 0; }
.ag-row__barre {
  flex: 1; min-width: 60px; height: 4px; background: var(--paper-3);
  border-radius: var(--r-pill); overflow: hidden;
}
.ag-row__rempli {
  display: block; height: 100%; width: 0; background: var(--line-strong);
  transition: width .6s var(--ease);
}
.ag-row__pct { flex: none; min-width: 44px; text-align: right; color: var(--ink-3); }
/* Une couleur, un sens : gris en attente, or en cours, vert termine, ambre
   interrompu, rouge en echec. Memes cles que les pastilles de stade. */
.ag-row.running .ag-row__point { background: var(--blue); box-shadow: 0 0 0 4px var(--blue-tint-2); animation: pulse 1.8s var(--ease) infinite; }
.ag-row.running .ag-row__rempli { background: var(--blue); }
.ag-row.done .ag-row__point, .ag-row.done .ag-row__rempli { background: var(--ok); }
.ag-row.partial .ag-row__point, .ag-row.partial .ag-row__rempli { background: var(--warn); }
.ag-row.failed .ag-row__point, .ag-row.failed .ag-row__rempli { background: var(--danger); }
.ag-row.pending .ag-row__nom { color: var(--ink-2); }
@media (prefers-reduced-motion: reduce) { .ag-row.running .ag-row__point { animation: none; } }

.ag-config .field { margin-bottom: var(--sp-4); }
/* Deux fois le meme geste, donc la meme regle : un champ que Meridian a
   rempli (onboarding pre-rempli par le site) ou modifie (retouche du profil en
   attente d'accord) est surligne en or pale. */
[data-suggere="1"], [data-modifie="1"] { background: var(--blue-tint); border-color: var(--blue-line); }
.ob-legende { background: var(--blue-tint); border: 1px solid var(--blue-line); border-radius: var(--r-xs); padding: 0 4px; }
/* Les trois champs requis de l'onboarding portent « (requis) » dans leur libelle. */
.cab-ajouter { margin-top: 2px; }

/* Selecteur de modele : le select puis, sur « Autre », le champ libre. */
.modele-choix { display: flex; flex-direction: column; gap: var(--sp-2); }
.modele-choix__select { width: 100%; max-width: 100%; }
@media (max-width: 560px) {
  .ag-launch__profil { min-width: 0; width: 100%; }
  /* Empilee en carte, la rangee d'agent retrouve une largeur libre. */
  .ag-table { table-layout: auto; }
}

/* Les resultats par agent (.agent-hero, .agent-launch, .mission-tabs,
   .target-picker, .agent-list) ne sont plus rendus par aucun gabarit depuis
   que le travail des agents s'ouvre dans le Pipeline : regles retirees en 0.3.25.
   La rangee de pastilles des pages d'agent (.agent-rail, .agent-chip) est
   partie avec ces pages le 2026-10-02 : leur configuration vit dans
   Reglages > Agents. */

/* ============================================================
   Réduction de mouvement
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 1.5s; }
  .top { backdrop-filter: none; }
}

/* ============================================================
   Mobile : en-tete + tiroir de navigation (bascule CSS pure)

   La sidebar EXISTANTE devient le tiroir : elle garde sa mise en
   page verticale de bureau (libelles, groupes, selecteur de
   client, deconnexion) et coulisse depuis la gauche. La bascule
   est un checkbox cache (#mnav) + deux labels (burger, scrim) :
   tout fonctionne sans JavaScript, forms.js n'ajoute que la
   fermeture a Echap et au clic d'un lien.
   ============================================================ */

/* Bureau : rien de mobile n'existe. */
.mhead, .mnav-scrim { display: none; }

@media (max-width: 820px) {
  /* --- L'en-tete mobile ------------------------------------- */
  .mhead {
    position: sticky; top: 0; z-index: 55;
    display: flex; align-items: center; gap: var(--sp-2);
    background: var(--blue-deep); color: var(--white);
    padding: var(--sp-2) var(--sp-3);
    padding-top: calc(var(--sp-2) + env(safe-area-inset-top, 0px));
    padding-left: calc(var(--sp-3) + env(safe-area-inset-left, 0px));
    padding-right: calc(var(--sp-3) + env(safe-area-inset-right, 0px));
    min-height: 52px;
  }
  .mhead__burger {
    flex: none; width: 44px; height: 44px; border-radius: var(--r-sm);
    display: grid; place-items: center; color: var(--white); cursor: pointer;
    transition: background var(--t-fast) var(--ease);
  }
  .mhead__burger:active { background: var(--nav-bg-active); }
  .mhead__title {
    flex: 1; min-width: 0;
    font: 600 var(--fs-16)/1.25 var(--font-display); letter-spacing: -0.012em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .mhead__mark { flex: none; display: grid; place-items: center; width: 44px; height: 44px; }
  /* La cloche des notifications, a gauche du bouton menu : meme gabarit
     tactile que le burger, badge de non-lues dans le coin. */
  .mhead__notif {
    flex: none; position: relative; width: 44px; height: 44px;
    border: 0; border-radius: var(--r-sm); background: none; color: var(--white);
    display: grid; place-items: center; cursor: pointer; padding: 0;
    transition: background var(--t-fast) var(--ease);
  }
  .mhead__notif svg { width: 22px; height: 22px; }
  .mhead__notif:active, .mhead__notif[aria-expanded="true"] { background: var(--nav-bg-active); }
  .mhead__badge {
    position: absolute; top: 5px; right: 3px; min-width: 16px; height: 16px;
    padding: 0 4px; border-radius: var(--r-pill);
    background: var(--blue-bright); color: var(--sur-clair);
    font: 700 10px/16px var(--font-mono); font-variant-numeric: tabular-nums;
    text-align: center;
  }

  /* --- Le tiroir : la sidebar, en panneau coulissant ---------- */
  .app { grid-template-columns: 1fr; }
  .sb {
    position: fixed; inset: 0 auto 0 0; height: 100dvh;
    width: min(300px, 84vw); z-index: 60;
    transform: translateX(-105%);
    transition: transform 240ms var(--ease);
    box-shadow: var(--shadow-drawer);
    overflow: hidden; min-width: 0;
    padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
  }
  .mnav-toggle:checked ~ .app .sb { transform: none; }
  /* Cibles tactiles genereuses dans le tiroir. */
  .sb .nav { min-height: 48px; }

  .mnav-scrim {
    display: block; position: fixed; inset: 0; z-index: 58;
    background: var(--scrim);
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none;
    transition: opacity 200ms var(--ease);
  }
  .mnav-toggle:checked ~ .mnav-scrim { opacity: 1; pointer-events: auto; }
  /* Le fond ne defile pas sous le tiroir ouvert (CSS pur via :has). */
  body:has(.mnav-toggle:checked) { overflow: hidden; }

  /* --- La barre .top : le titre vit dans la mhead -------------- */
  .top { position: static; min-height: 0; padding: var(--sp-3) var(--sp-4); flex-wrap: wrap; }
  /* Sur mobile, c'est la mhead (52 px) qui reste collee en haut. */
  [id] { scroll-margin-top: calc(52px + var(--sp-3)); }
  .top__titles { display: none; }
  .mds-ask--input { flex: 1 1 100%; }
  .mds-ask--input input,
  .mds-ask--input:focus-within input { width: 100%; flex: 1; }
  /* En bas : la place de la pastille « Demander à Meridian » (fixe, bas
     droit), qui couvrait les boutons du dernier encadré. */
  .scroll { padding: var(--sp-5) var(--sp-4) calc(var(--sp-8) + 72px); }

  /* iOS zoome de force sur tout input sous 16px : on l'evite a la source. */
  input[type="text"], input[type="url"], input[type="number"],
  input[type="email"], input[type="password"], textarea, select {
    font-size: 16px;
  }
  /* Cibles tactiles (0.3.25) : 44 px pour tout ce qui se touche, les deux
     familles de petits controles comprises. Le banc verif_mobile.py mesure
     chaque element interactif et refuse tout ce qui passe dessous. */
  :root { --control-h: 44px; --control-h-sm: 44px; }
  .btn, .mini-btn, .bvx-chip, .chat-iconbtn,
  .retour, .fb-contacted { min-height: 44px; }
  .pf-icone { width: 44px; height: 44px; }
  .chat-iconbtn { min-width: 44px; }
  /* Ce que le banc a trouve sous 44 px : deconnexion, lignes du selecteur de
     client, fermeture des fenetres, crayon et poubelle d'une note d'Erikia,
     « Lire la suite » (la zone tactile deborde a marges negatives), selecteur de fichier
     (le champ vit DANS la bordure : +2 px pour qu'il fasse 44). */
  .sb__logout-btn, .orgpick__item { min-height: 44px; }
  .mw-panel__close { width: 44px; height: 44px; }
  .mds-dialog__fermer { width: 44px; height: 44px; margin: -12px -14px 0 0; }
  .note__geste { width: 44px; height: 44px; }
  .note__gestes { margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-3)) 0 0; }
  .note__plus summary { display: inline-flex; align-items: center; min-height: 44px; }
  .filepick.is-enhanced { height: calc(var(--control-h) + 2px); }
  .filepick.is-enhanced .filepick__btn { line-height: var(--control-h); }
}

@media (max-width: 560px) {
  .scroll { padding: var(--sp-4) var(--sp-3) calc(var(--sp-8) + 72px); }
  h1 { font-size: var(--fs-22); }
  .pg-coche, .pe-lien { min-height: 44px; }
  /* Site web et LinkedIn sont des elements d'une rangee flex, donc de vraies
     boites (et non du texte courant) : ils se touchent, ils font 44 px. */
  .pe-liens a, .pe-cohorte { display: inline-flex; align-items: center; min-height: 44px; }
  /* Empilee en carte, la colonne de l'etoile n'a plus de largeur imposee,
     et le nom de l'entreprise devient une vraie cible tactile. */
  .pg-table { table-layout: auto; }
  .pg-th-fav, .pg-td-fav { width: auto; }
  .pg-etoile { min-width: 44px; min-height: 44px; }
  .card { padding: var(--sp-4); }
}

@media (prefers-reduced-motion: reduce) {
  .sb, .mnav-scrim { transition: none; }
}

/* Tableaux larges : conteneur defilable SUR BUREAU seulement. Sur mobile,
   les tableaux marques data-label deviennent des cartes empilees (plus bas)
   et il n'y a plus rien a faire defiler. */

/* ============================================================
   Mobile : tableaux -> cartes empilees (pattern data-label)
   Chaque <td> porte data-label="Entete" ; sous 820px la ligne
   devient une carte et chaque cellule une paire libelle/valeur.
   ============================================================ */
@media (max-width: 820px) {
  table.t-cartes { display: block; }
  table.t-cartes thead { display: none; }
  table.t-cartes tbody { display: grid; gap: var(--sp-3); }
  table.t-cartes tr {
    /* border-box : en item de grille etire, le padding s'ajoutait a la
       largeur et la carte debordait de 7 px a 390 px. */
    display: block; box-sizing: border-box; min-width: 0; background: var(--white);
    border: 1px solid var(--line); border-radius: var(--r-xs);
    padding: var(--sp-4);
  }
  table.t-cartes td {
    display: flex; gap: var(--sp-3); align-items: baseline;
    padding: var(--sp-1) 0; border: none; height: auto;
    /* Un courriel ou une URL est un jeton SANS espace : sa largeur minimale
       est sa longueur entiere, et la carte ne peut pas descendre en dessous.
       Le banc mobile ne le voyait pas tant que le compte seme s'appelait
       « m@x.y » ; une adresse client reelle poussait la page a 394 px, a 390
       comme a 360 (largeur incompressible, pas un pourcentage). `anywhere`
       et non `break-word` : lui seul reduit AUSSI la largeur min-content. */
    min-width: 0; overflow-wrap: anywhere;
  }
  table.t-cartes td::before {
    content: attr(data-label);
    flex: none; width: 92px;
    font: var(--text-caps);
    letter-spacing: var(--track-caps); text-transform: uppercase;
    color: var(--ink-4);
  }
  table.t-cartes td:not([data-label])::before { content: none; }
  table.t-cartes td[data-label=""] { padding-top: var(--sp-2); }
  table.t-cartes td .btn, table.t-cartes td .mini-btn { width: 100%; justify-content: center; }
  /* Administration : en carte, les trois gestes s'empilent pleine largeur.
     En rangee, la cellule mesurait 538 px et poussait la PAGE hors de
     l'ecran — ici rien ne defile (voir la ligne suivante). */
  table.t-cartes td .adm-actions { flex: 1 1 100%; flex-direction: column; align-items: stretch; }
  table.t-cartes td .adm-actions form { flex-direction: column; align-items: stretch; }
  .table-scroll { overflow-x: visible; border: 0; background: none; border-radius: 0; }
}

/* Le pipeline en carte (demande Marek, 2026-10-07). Le patron libelle/valeur
   ci-dessus coincait le nom de l'entreprise dans une colonne de quelques
   lettres, a cote de sa sous-ligne (un mot par ligne), et ramenait
   Employes, Marche et Cohorte, que la sous-ligne porte deja. Ici, deux
   rangees sans etiquettes : l'etoile, le nom sur toute la largeur et le
   score ; puis le statut et le secteur, alignes sous le nom. */
@media (max-width: 820px) {
  table.t-cartes.pg-table tbody { gap: var(--sp-2); }
  table.t-cartes.pg-table tr {
    display: grid;
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    grid-template-areas:
      "fav nom nom score"
      ". statut sec sec";
    column-gap: var(--sp-2); row-gap: var(--sp-1);
    align-items: start;
    padding: var(--sp-3);
  }
  table.t-cartes.pg-table td { display: block; padding: 0; }
  table.t-cartes.pg-table td::before { content: none; }
  table.t-cartes.pg-table td.pg-opt { display: none; }
  .pg-table .pg-td-fav { grid-area: fav; }
  .pg-table .pg-td-nom { grid-area: nom; }
  .pg-table .pg-td-statut { grid-area: statut; }
  .pg-table .pg-td-secteur { grid-area: sec; font-size: var(--fs-12); }
  .pg-table .pg-td-score { grid-area: score; text-align: right; line-height: 44px; }
  .pg-nom, .pg-sous { white-space: normal; }
  /* Une premiere ligne de 44 px : l'etoile, le nom et le score s'y
     alignent, et le nom reste une vraie cible tactile. */
  .pg-nom { display: flex; align-items: center; min-height: 44px; }
  .pg-etoile { min-width: 44px; min-height: 44px; }
  .pg-sous { margin-top: 0; }
}


/* Administration : les gestes d'une ligne de compte, alignes a droite.
   Le menu deroulant d'organisation reste COLLE a son bouton (il ne veut rien
   dire seul) et ne prend que sa largeur : la regle globale `select {width:
   100%}` l'etirait sur toute la cellule et renvoyait les boutons sur trois
   lignes (signale par Marek, 2026-09-04). */
/* Depuis le 2026-10-12, les gestes d'un compte disent leur objet (« Réinitialiser
   le mot de passe », « Désactiver le compte », conventions-interface.md §3) :
   trop larges pour une rangee, ils s'empilent, et la colonne prend la largeur
   du plus long. */
.adm-actions {
  display: flex; flex-direction: column; gap: var(--sp-2);
  align-items: stretch; min-width: 11rem;
}
.adm-actions form { display: flex; gap: var(--sp-2); align-items: center; margin: 0; }
.adm-actions form > .btn { flex: 1; justify-content: center; }
/* Administration > Clients (2026-10-23) : la date de creation tient sur une ligne. */
.adm-date { white-space: nowrap; }
/* `nowrap` plutot qu'une compression : la cellule reclame sa largeur
   naturelle, et la mise en page automatique du tableau la prend sur la
   colonne Courriel, qui sait passer a la ligne. Avec `wrap`, la colonne
   gardait sa largeur et « Desactiver » tombait seul sur une deuxieme
   rangee. Si l'ecran ne suffit vraiment plus, .table-scroll defile. */
/* Un libelle long (« Réinitialiser le mot de passe ») passe sur deux lignes
   plutot que d'elargir la table au-dela de sa carte. */
.adm-actions .btn { white-space: normal; height: auto; min-height: var(--control-h-sm); line-height: 1.25; padding-top: 6px; padding-bottom: 6px; text-align: center; }
/* La page Administration (_administration.html) vit dans .bvx, qui coupe les
   mots n'importe ou : dans un tableau, les colonnes s'effondraient lettre par
   lettre (« L ir e », « Sup er adm in »). Ses tableaux reprennent la coupure
   normale ; les cellules longues (courriel, ou, message) portent .u-coupe.
   Les gestes d'Acces passent a la ligne plutot que de pousser le tableau hors
   de la carte : la colonne de l'onglet lui a pris 288 px. */
.adm-corps table { overflow-wrap: normal; }
.adm-corps .adm-actions { flex-wrap: wrap; }

/* --- Journal des appels IA -------------------------------------------------
   Un tableau dense : on lit d'abord QUI a parle et COMBIEN ca a coute, le
   detail se lit sur la page de l'appel. */
/* .jia : voir « Table Outlook » (regle partagee avec .calls-table). */
.jia--echec { background: var(--warn-tint); }
/* Etiquette « echec » du journal : un badge ambre (meme anatomie que .pill). */
.jia-tag {
  display: inline-flex; align-items: center; height: 22px; margin-left: var(--sp-2);
  padding: 0 10px; border-radius: var(--r-tag);
  font: var(--text-caps); letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--warn); background: var(--warn-tint); white-space: nowrap;
}
/* Les prompts sont longs et parfois tres larges : ils defilent dans leur
   propre boite, la page ne part jamais en travers. */
.jia-pre {
  margin: 0; max-height: 480px; overflow: auto;
  white-space: pre-wrap; word-break: break-word;
  font-family: var(--font-code);
  font-size: var(--fs-13); line-height: 1.5; color: var(--ink-2);
}

/* ============================================================
   Deconnexion (pied de la barre laterale)
   ============================================================ */
.sb__logout { margin-top: var(--sp-2); }
.sb__logout-btn {
  width: 100%; background: none; border: 1px solid var(--line-on-dark);
  color: var(--nav-fg); border-radius: var(--r-sm);
  padding: 6px 10px; font: 500 12px var(--font-sans); cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.sb__logout-btn:hover { background: var(--nav-bg-hover); color: var(--white); }
.sb__logout-btn svg { display: none; }

/* ============================================================
   Barre laterale reduite aux icones (demandes de Marek, 2026-10-09).
   Bureau seulement : sous 821 px la barre est le tiroir mobile.
   La classe vit sur <html>, rendue par le serveur depuis le
   cookie meridian_sb (barre_laterale.js le pose) : aucun saut au
   chargement.

   La barre se referme SUR son contenu : chaque bloc garde sa largeur
   de barre large (208 px = 236 - 2 x 14) et sa mise en page, donc
   RIEN NE BOUGE VERTICALEMENT (demande Marek). On masque ce qui ne
   tient pas dans les 70 px, a la meme place ; chaque icone reste ou
   elle etait, centree dans la barre etroite. --sidebar-w change, et
   tout ce qui s'y aligne suit : la grille de .app, la fenetre des
   notifications, le bouton. Les libelles restent lus par les lecteurs
   d'ecran (opacite nulle) et passent en infobulle.
   ============================================================ */
/* La pastille ne compte pas dans la hauteur d'une entree, large ou
   reduite : avec elle, l'entree faisait 2 px de plus. */
.sb .nav { position: relative; }
.sb .nav__badge { position: absolute; right: var(--sp-3); top: 50%; transform: translateY(-50%); }
.sb-replier { display: none; }
@media (min-width: 821px) {
  /* Le bouton : un petit cercle de la couleur de la barre, a cheval sur
     son bord, EN HAUT, a la hauteur du titre de la page (demande Marek,
     2026-10-09). Essaye en bas en 0.4.156 : trop pres de « Se
     deconnecter », on risquait de cliquer l'un pour l'autre. Fixe : la
     barre defile et le couperait. */
  .sb-replier {
    position: fixed; z-index: 30; top: 17px; left: calc(var(--sidebar-w) - 13px);
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; padding: 0; border-radius: 50%;
    background: var(--blue-deep); color: var(--nav-fg);
    border: 1px solid var(--line-on-dark); box-shadow: var(--shadow-pill);
    cursor: pointer; transition: color var(--t-fast) var(--ease);
  }
  .sb-replier:hover { color: var(--white); }
  /* La barre, collante, forme son propre plan : la moitie du cercle qui
     depasse sur la page ne passe au-dessus du contenu (une barre
     « Enregistrer » collante, l'en-tete a 20) que si la barre est
     au-dessus. Les fenetres, messages et menus flottants restent plus
     haut (50 et plus). */
  .sb { z-index: 25; }
  /* Le contenu de la barre garde sa largeur de barre large (208 px =
     236 - 2 x 14), ouverte OU fermee. Pendant l'animation de la grille,
     la barre ne fait que glisser sur un contenu deja en place : avant, la
     devise et les libelles se recomposaient a chaque largeur
     intermediaire, sur plusieurs lignes, et le texte semblait apparaitre
     de haut en bas (demande Marek, 2026-10-09). */
  .sb__defile > *, .sb__foot { width: 208px; flex-shrink: 0; }
  .sb-replier svg { width: 14px; height: 14px; transition: transform var(--t-fast) var(--ease); }

  html.sb-replie { --sidebar-w: 70px; }
  html.sb-replie .sb-replier svg { transform: rotate(180deg); }
  /* Le haut : le logo rond a la place du mot-symbole, a la meme hauteur. */
  html.sb-replie .sb__brand { position: relative; }
  html.sb-replie .sb__brand > img, html.sb-replie .sb__version, html.sb-replie .sb__credit { visibility: hidden; }
  html.sb-replie .sb__brand-icone { display: flex; position: absolute; left: 7px; top: calc(var(--sp-2) + 3px); }
  /* Les titres de groupe deviennent un filet, a la meme place. */
  html.sb-replie .sb__grp { position: relative; color: transparent; }
  html.sb-replie .sb__grp::after {
    content: ""; position: absolute; left: 0; bottom: calc(var(--sp-1) + 6px);
    width: 42px; height: 1px; background: var(--line-on-dark);
  }
  /* Les entrees : l'icone seule, sa pastille au coin ; le fond actif ou
     de survol ne couvre que l'icone (42 px). */
  html.sb-replie .nav, html.sb-replie .nav:hover, html.sb-replie .nav.active,
  html.sb-replie .sb-notif[aria-expanded="true"] { background: transparent; }
  html.sb-replie .nav::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 42px;
    border-radius: var(--r-sm); transition: background var(--t-fast) var(--ease);
  }
  html.sb-replie .nav:hover::before { background: var(--nav-bg-hover); }
  html.sb-replie .nav.active::before,
  html.sb-replie .sb-notif[aria-expanded="true"]::before { background: var(--nav-bg-active); }
  html.sb-replie .nav > svg { position: relative; }
  html.sb-replie .nav__label { opacity: 0; }
  html.sb-replie .nav__badge {
    right: auto; left: 26px; top: 3px; transform: none;
    min-width: 16px; height: 16px; padding: 0 4px; font-size: 10px;
  }
  /* Le pied : l'avatar centre, le reste masque a la meme place. */
  html.sb-replie .sb__foot { border-top-color: transparent; }
  html.sb-replie .sb__foot::before {
    content: ""; position: absolute; top: -1px; left: 0;
    width: 42px; height: 1px; background: var(--line-on-dark);
  }
  html.sb-replie .orgpick__summary .col, html.sb-replie .orgpick__chev { opacity: 0; }
  html.sb-replie .orgpick__summary:hover { background: transparent; }
  html.sb-replie .orgpick__summary .sb__ava { transform: translateX(-6px); }
  html.sb-replie .orgpick__summary:hover .sb__ava { box-shadow: 0 0 0 3px var(--nav-bg-hover); }
  /* La barre coupe ce qui la depasse : le menu des clients s'ouvre a cote. */
  html.sb-replie .orgpick__menu {
    position: fixed; left: calc(var(--sidebar-w) + var(--sp-2)); right: auto;
    bottom: var(--sp-4); width: 260px; margin: 0;
  }
  html.sb-replie .sb__logout-btn { position: relative; border-color: transparent; }
  html.sb-replie .sb__logout-btn:hover { background: transparent; color: var(--white); }
  html.sb-replie .sb__logout-txt { opacity: 0; }
  html.sb-replie .sb__logout-btn svg {
    display: block; position: absolute; left: 3px; top: 50%; transform: translateY(-50%);
  }
}
@media (min-width: 821px) and (prefers-reduced-motion: no-preference) {
  .app { transition: grid-template-columns var(--t-med) var(--ease); }
}

/* Journal IA sur mobile : les prompts (pre/mono) se REPLIENT, jamais de
   defilement horizontal. */
@media (max-width: 820px) {
  pre, .jia-pre, code { white-space: pre-wrap; word-break: break-word; }
}


/* ============================================================
   6b. Les bulles d'Erikia (0.4.139 ; projecteur en 0.4.144, demande Marek,
   maquette a l'appui : « la page s'assombrit, seule la cible reste eclairee ;
   bulle sombre a cote »). Une visite guidee par page, une seule fois par
   compte (static/visite.js, services/visites.py).
   - .rp-voile : toute la page, transparent, absorbe les clics ;
   - .rp-trou : la decoupe posee sur la cible ; son ombre immense assombrit
     le reste, sa bordure doree et son halo eclairent la cible ;
   - .rp-bulle : sombre, a cote, la tete d'Erikia, les points de
     progression, « Passer » et « Suivant ».
   Positions posees par le script. z-index 73 a 75 : au-dessus de la barre
   laterale (60) et du bouton flottant (50), sous les panneaux ouverts (79)
   et les modales (80). Sous 820 px, la bulle devient une feuille.
   ============================================================ */
.rp-voile { position: fixed; inset: 0; z-index: 73; background: transparent; }
.rp-trou {
  position: fixed; z-index: 74; top: 0; left: 0; width: 0; height: 0;
  pointer-events: none;
  border: 2px solid var(--blue-bright); border-radius: var(--r-sm);
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--blue-bright) 30%, transparent),
    0 0 0 200vmax color-mix(in srgb, var(--blue-deep) 66%, transparent);
}
.rp-voile[hidden], .rp-trou[hidden], .rp-bulle[hidden] { display: none; }
.rp-bulle {
  --rp-fleche: 50%;
  position: fixed; z-index: 75; top: 0; left: 0;
  width: min(360px, calc(100vw - 2 * var(--sp-3)));
  background: var(--blue-deep); color: var(--white);
  border: 1px solid var(--line-on-dark); border-radius: var(--r-sm);
  box-shadow: var(--shadow-overlay);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
}
.rp-bulle__tete { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
/* La tete d'Erikia, en noir sur pastille d'or. */
.rp-bulle__avatar {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  background: var(--blue-bright); color: var(--blue-deep);
  display: inline-flex; align-items: center; justify-content: center;
}
.rp-bulle__nom { font-size: var(--fs-14); font-weight: 600; color: var(--blue-bright); }
/* La visite de l'application : « Page 2 sur 8 », discret, apres le nom. */
.rp-bulle__page { font-size: var(--fs-12); color: var(--nav-fg-dim); white-space: nowrap; }
.rp-bulle__page[hidden] { display: none; }
.rp-bulle__points { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; }
.rp-bulle__point {
  width: 6px; height: 6px; border-radius: 50%;
  background: color-mix(in srgb, var(--white) 28%, transparent);
}
.rp-bulle__point[data-actif] { background: var(--blue-bright); }
.rp-bulle__texte {
  margin: 0 0 var(--sp-4); font-size: var(--fs-14); line-height: var(--lh-body); color: var(--white);
}
.rp-bulle__pied { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.rp-bulle__compteur { font-size: var(--fs-12); color: var(--nav-fg-dim); white-space: nowrap; }
.rp-bulle__actions { display: flex; align-items: center; gap: var(--sp-2); }
.rp-bulle__passer, .rp-bulle__suivant {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 32px; border-radius: var(--r-sm); cursor: pointer;
  font: inherit; font-size: var(--fs-13); font-weight: 600; white-space: nowrap;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.rp-bulle__passer {
  padding: 0 var(--sp-3); background: transparent; color: var(--white);
  border: 1px solid color-mix(in srgb, var(--white) 45%, transparent);
}
.rp-bulle__passer:hover { background: color-mix(in srgb, var(--white) 10%, transparent); border-color: var(--white); }
.rp-bulle__suivant {
  padding: 0 var(--sp-4); background: var(--blue-bright); color: var(--blue-deep); border: 0;
}
.rp-bulle__suivant:hover { background: var(--blue-light); }
.rp-bulle :focus-visible { outline: 2px solid var(--blue-bright); outline-offset: 2px; }
/* La fleche : un carre tourne, meme fond et meme bordure que la bulle. */
.rp-bulle::before {
  content: ""; position: absolute; width: 12px; height: 12px; display: none;
  background: var(--blue-deep); border: 1px solid var(--line-on-dark);
  border-right: 0; border-bottom: 0; transform: rotate(45deg);
}
.rp-bulle[data-place="bas"]::before { display: block; top: -7px; left: calc(var(--rp-fleche) - 6px); }
.rp-bulle[data-place="haut"]::before {
  display: block; bottom: -7px; left: calc(var(--rp-fleche) - 6px); transform: rotate(225deg);
}
.rp-bulle[data-place="droite"]::before {
  display: block; left: -7px; top: calc(var(--rp-fleche) - 6px); transform: rotate(-45deg);
}
/* La cible : ses marges de defilement passent sous l'en-tete collant et
   au-dessus de la feuille basse. L'eclairage, c'est la decoupe. */
.rp-cible { scroll-margin-top: 96px; scroll-margin-bottom: 240px; }
@keyframes rp-apparait { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes rp-assombrit { from { opacity: 0; } to { opacity: 1; } }
/* En route vers sa cible, la bulle est invisible mais mesurable ; elle
   apparait posee, une fois la cible immobile (visite.js, 0.4.145). La
   decoupe glisse par le script, image par image : pas de transition CSS,
   qui trainait derriere une cible en plein defilement. */
.rp-bulle[data-en-route] { visibility: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .rp-bulle[data-pose] { animation: rp-apparait var(--t-med) var(--ease); }
  .rp-trou { animation: rp-assombrit var(--t-med) var(--ease); }
}
@media (max-width: 820px) {
  .rp-bulle {
    top: auto; left: var(--sp-3); right: var(--sp-3); width: auto;
    bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  }
  /* L'onboarding : en haut, sous l'en-tete mobile, au-dessus de la barre
     « Suivant » collee en bas du formulaire. */
  .rp-bulle[data-place="feuille-haut"] { top: calc(var(--control-h-lg) + var(--sp-2) * 3); bottom: auto; }
  .rp-bulle::before { display: none; }
  .rp-bulle__passer, .rp-bulle__suivant { min-height: 44px; }
}

/* ============================================================
   7. Utilitaires (0.3.25, echelle complete en 0.4.5). Ils remplacent TOUT
   style="" statique des gabarits (garde-fou : tests/test_design_system.py ;
   un style inline n'est tolere que si sa valeur vient du serveur ou d'un
   script, prefixe `width:`). En FIN de feuille expres : a specificite egale,
   c'est l'ordre de source qui tranche, et ces classes doivent avoir le
   dernier mot sur .card, .actions, .note-line, .section-hint, .field...
   ============================================================ */
/* Un texte pour les lecteurs d'ecran seulement : l'en-tete d'une colonne qui
   ne porte qu'une icone (l'etoile des favorites du pipeline). */
.u-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.u-m0 { margin: 0; }
.u-mt-0 { margin-top: 0; }
.u-mt-1 { margin-top: var(--sp-1); }
.u-mt-2 { margin-top: var(--sp-2); }
.u-mt-3 { margin-top: var(--sp-3); }
.u-mt-4 { margin-top: var(--sp-4); }
.u-mt-5 { margin-top: var(--sp-5); }
.u-mt-6 { margin-top: var(--sp-6); }
.u-mb-0 { margin-bottom: 0; }
.u-mb-2 { margin-bottom: var(--sp-2); }
.u-mb-3 { margin-bottom: var(--sp-3); }
.u-mb-4 { margin-bottom: var(--sp-4); }
.u-mb-5 { margin-bottom: var(--sp-5); }
.u-ml-2 { margin-left: var(--sp-2); }
.u-px-2 { padding-left: var(--sp-2); padding-right: var(--sp-2); }
.u-right { text-align: right; }
.u-min0 { min-width: 0; }
/* Une cellule qui porte un chemin ou un message technique (incidents) : un
   jeton sans espace coupe n'importe ou au lieu d'elargir tout le tableau. */
.u-coupe { overflow-wrap: anywhere; }
/* Un mot en ambre (« ecartee ») : attention, rien de casse (UNE COULEUR, UN SENS). */
.u-warn { color: var(--warn); }
.u-b { font-weight: 600; }
.u-fs-15 { font-size: var(--fs-15); }
.u-fs-16 { font-size: var(--fs-16); }
.u-flex-none { flex: none; }
/* Un jeton a copier d'un clic (mot de passe temporaire). */
.u-select-all { user-select: all; }
/* Un champ numérique court (seuil sur 100) : input[type=number] impose
   width: 100 % à spécificité (0,1,1), d'où le sélecteur qualifié. */
input.input--court { width: 5rem; }
/* Le sous-texte qui suit un contrôle : collé à lui, sans marge basse. */
.section-hint--suite { margin: var(--sp-2) 0 0; }
