/* Jarvis — interface, refonte de l'étape 37.

   « Ça fait très site de techno fait par des lycéens, pire qu'un Excel. »
   Le fond était solide, la surface non — et c'est elle que neuf personnes
   verront le 31.

   ── La charte ────────────────────────────────────────────────────────
   Le bleu est celui du LOGO, pas celui d'une maquette : #002687, lu dans
   `logo_blue_mountain.svg` sur norgayitservices.com (28 occurrences, couleur
   unique du fichier). Tout le reste en découle par teinte, à teinte constante
   (H 223°).

   L'ambre est réservé à ce qui APPELLE UNE ACTION : aperçu à confirmer, bouton
   d'ajout, manque signalé. S'il servait à décorer, il ne voudrait plus rien
   dire.

   ⚠️ Contrastes vérifiés, et c'est ce qui explique deux écarts avec la
   maquette : son ambre #E07A2F ne donne que 3,00:1 avec du blanc dessus
   (illisible en petit), et son gris #94A3B8 2,56:1 sur blanc. On garde l'ambre
   vif pour les FILETS, qui ne portent aucun texte, et on assombrit celui qui
   porte des lettres. `scripts/tests_interface.py` remesure tous les couples.

   ⚠️ Thème clair uniquement, assumé : la maquette validée est claire, et
   inventer une variante sombre non relue produirait exactement les contrastes
   qu'on vient de corriger. `color-scheme` l'annonce au navigateur pour qu'il
   n'inverse pas les contrôles de formulaire. */

:root {
  color-scheme: light;

  /* Bleu Norgay, exact */
  --marine:        #002687;
  --marine-clair:  #0031AD;   /* liens et accents — 10,3:1 sur blanc */
  --marine-pale:   #EAEFFB;
  --marine-trait:  #C9D3EC;   /* filets sur fond marine pâle (296 §6) */
  --carte-max:     min(720px, 92%);   /* le gabarit des cartes (296 §7) */
  --rail-doux:     #A8C0EA;   /* 7,0:1 sur le marine */
  --rail-titre:    #8FA8DC;   /* 5,4:1 sur le marine */

  /* Ce qui appelle une action */
  --ambre:         #A85513;   /* fonds portant du blanc — 5,3:1 */
  --ambre-vif:     #E07A2F;   /* filets et repères, jamais de texte dessus */
  --ambre-pale:    #FDF1E7;
  --ambre-encre:   #8F4A15;   /* texte sur ambre-pale — 6,0:1 */
  --ambre-trait:   #F0D6BC;

  --vert:          #256B54;
  --vert-pale:     #E8F3EF;

  /* Ce qui est en retard (étape 56). Le code couleur est celui de Laurent —
     vert fait / orange à faire / rouge en retard — parce que c'est celui de
     tous les CRM et que c'est lui qui vivra avec. L'orange est notre ambre,
     déjà réservé à ce qui appelle un geste depuis l'étape 37 : les deux
     conventions tombent juste.
     ⚠️ Mesuré : #A31621 sur #FCEBEC donne 6,77:1. Et la couleur ne porte
     JAMAIS l'information seule — chaque état garde son mot. */
  --rouge:         #A31621;
  --rouge-pale:    #FCEBEC;

  /* ⛔ **AUDIT 149 — SEPT VARIABLES ÉTAIENT EMPLOYÉES SANS EXISTER**, en
     trente-deux endroits, et sans valeur de repli : une propriété qui
     pointe une variable absente est simplement INVALIDE, donc transparente. Conséquences
     mesurées à l'écran : la **jauge de complétude était invisible** — les trois
     éléments présents dans le DOM, à la bonne géométrie, et peints en
     `rgba(0,0,0,0)` — c'est-à-dire l'élément-titre de l'étape 107 ; le survol
     d'un chiffre EFFAÇAIT sa tuile au lieu de l'éclairer ; et le badge
     « suspect » n'avait aucun fond, alors que 23 des 31 vignettes de Tamara le
     porteront demain.
     ⚠️ Ce ne sont pas des couleurs nouvelles : ce sont des ALIAS vers la
     palette qui existe. On ne redessine rien, on rend visible ce qui était
     déjà écrit. */
  --bleu:           #002687;   /* = --marine */
  --bleu-tres-pale: #EAEFFB;   /* = --marine-pale */
  --texte:          #152534;   /* = --encre */
  --texte-doux:     #4F5D70;   /* = --doux */
  --bordure:        #E2E8F0;   /* = --trait */
  --fond-doux:      #F4F7FA;   /* = --fond */

  --fond:          #F4F7FA;
  --surface:       #FFFFFF;
  --trait:         #E2E8F0;
  --encre:         #152534;
  --doux:          #4F5D70;   /* libellés — 6,6:1 sur blanc */
  --tres-doux:     #5F6E85;   /* le plus léger encore lisible — 4,8:1 sur le fond */

  --rayon:         14px;
  --ombre:         0 1px 2px rgb(0 38 135 / .06), 0 8px 24px rgb(0 38 135 / .07);
  --ombre-forte:   0 2px 4px rgb(0 38 135 / .10), 0 16px 40px rgb(0 38 135 / .14);
  --rail-largeur:  264px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Le curseur (étape 56) ───────────────────────────────────────────
   « Sur l'onglet compte, cela pourrait être moins perturbant de changer le
   type de curseur quand une action est possible. »

   ⚠️ **La main uniquement sur ce qui agit.** Une vignette entière qui a l'air
   cliquable alors que seul le bouton l'est, c'est une promesse que l'écran ne
   tient pas. La règle est posée ICI, pour tous les écrans à la fois : par
   défaut le curseur est celui du texte, et il devient une main sur ce qui
   répond au clic — et sur rien d'autre. */
a[href], button:not(:disabled), [role="button"]:not([aria-disabled="true"]),
summary, label[for], select, .jour, .onglet { cursor: pointer; }
button:disabled, [aria-disabled="true"] { cursor: default; }
[hidden] { display: none !important; }

html, body {
  height: 100%;
  background: var(--fond);
  color: var(--encre);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
        system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }

/* Le clavier doit voir où il est. Sans ce contour, une interface se pilote à
   l'aveugle dès qu'on lâche la souris. */
:focus-visible { outline: 2px solid var(--marine-clair); outline-offset: 2px; }

.mono {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .93em;
  letter-spacing: -.01em;
}

/* ── Connexion ─────────────────────────────────────────────────── */

/* ⚠️ L'écran de connexion porte DEUX blocs depuis l'étape 83 : la carte, et
   l'essai de son. En colonne, pour que l'essai reste sous la carte et sous le
   pouce en 390 px — c'est là qu'on le cherchera le 31 à 10 h 45. */
.ecran-connexion {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px;
  padding: 24px;
  background:
    radial-gradient(1200px 600px at 50% -10%, #E8EEFB 0%, var(--fond) 60%);
}

.carte {
  width: 100%; max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: 18px;
  padding: 28px 26px 24px;
  box-shadow: var(--ombre);
}
.carte label {
  display: block;
  margin: 16px 0 6px;
  font-size: 13px; font-weight: 600; color: var(--doux);
}
.carte input {
  width: 100%;
  padding: 11px 13px;
  background: var(--fond);
  border: 1px solid var(--trait);
  border-radius: 10px;
}
.carte input:focus { border-color: var(--marine-clair); background: var(--surface); }

/* Tester le son et le micro — sans se connecter (étape 83). Volontairement
   discret : ce n'est pas l'action principale de cet écran, c'est un geste
   d'avant-séance. Mais il est ATTEIGNABLE, pas caché derrière un lien de 11 px. */
.essai-son { width: 100%; max-width: 380px; text-align: center; }
.essai-son button {
  width: 100%;
  padding: 10px 13px;
  background: transparent;
  color: var(--marine);
  border: 1px solid var(--trait);
  border-radius: 10px;
  font-size: 14px; font-weight: 600;
  cursor: pointer;
}
.essai-son button:hover:not(:disabled) { border-color: var(--marine-clair); }
.essai-son button:disabled { opacity: .6; cursor: default; }
.essai-son .explication { margin: 8px 2px 0; font-size: 13px; min-height: 1.2em; }

#bouton-connexion {
  width: 100%;
  margin-top: 22px;
  padding: 12px;
  background: var(--marine); color: #fff;
  border: 0; border-radius: 11px;
  font-weight: 650;
}
#bouton-connexion:hover { background: var(--marine-clair); }
#bouton-connexion:disabled { opacity: .6; cursor: default; }

.erreur { color: #A31621; font-size: 14px; margin-top: 12px; }
/* ⛔ 296 §9 — l'erreur de connexion dans un ENCADRÉ, et la carte ne saute
   plus : elle est posée en haut (pas centrée), donc une erreur qui s'ajoute
   l'allonge vers le bas sans déplacer ce qu'on est en train de taper. */
.ecran-connexion { justify-content: flex-start; padding-top: max(24px, 12vh); }
.carte .erreur { background: #FDECEE; border: 1px solid #F3C4CA; border-left: 4px solid #A31621;
  border-radius: 10px; padding: 9px 12px; line-height: 1.45; color: #7A1018; }
/* Un œil pour voir le mot de passe qu'on tape. */
.mdp-champ { position: relative; }
.mdp-champ input { padding-right: 46px; }
.mdp-champ .oeil { position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; border: 0; background: transparent; border-radius: 8px;
  color: var(--doux); cursor: pointer; display: grid; place-items: center; }
.mdp-champ .oeil:hover { color: var(--marine); background: var(--fond); }
.mdp-champ .oeil svg { width: 20px; height: 20px; }
.activation-morte p { margin: 14px 0 0; line-height: 1.5; color: var(--doux); }
.activation-morte button { width: 100%; margin-top: 18px; padding: 12px; background: var(--marine);
  color: #fff; border: 0; border-radius: 11px; font-weight: 650; cursor: pointer; }

.marque { display: flex; align-items: center; gap: 11px; }
.marque .logo { width: 26px; height: 26px; flex: none; color: #fff; }
.marque b { font-size: 17px; letter-spacing: .2px; display: block; }
.marque span { display: block; font-size: 11.5px; color: var(--rail-doux); }
.marque.grande { margin-bottom: 6px; }
.marque.grande .logo { width: 40px; height: 40px; color: var(--marine); }
.marque.grande h1 { font-size: 25px; letter-spacing: -.02em; }
.sous-titre { font-size: 13px; color: var(--doux); }

/* ── La coque ──────────────────────────────────────────────────── */

.app {
  display: grid;
  grid-template-columns: var(--rail-largeur) 1fr;
  height: 100dvh;
  overflow: hidden;
}

/* ── Rail ──────────────────────────────────────────────────────── */

.rail {
  background: var(--marine); color: #fff;
  display: flex; flex-direction: column;
  padding: 18px 14px calc(14px + env(safe-area-inset-bottom));
  overflow-y: auto;
}
.rail .marque { padding: 4px 8px 14px; }
.fermer-rail {
  display: none;
  margin-left: auto;
  background: none; border: 0; color: var(--rail-doux);
  font-size: 26px; line-height: 1; padding: 0 4px;
}

.rail-titre {
  font-size: 11px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--rail-titre); padding: 14px 10px 8px; font-weight: 600;
}
.liste-jours { display: flex; flex-direction: column; }

.jour {
  display: block; width: 100%; text-align: left;
  background: none; border: 0;
  color: #DCE9F4;
  padding: 9px 10px; border-radius: 9px; margin-bottom: 2px;
  transition: background .12s;
}
.jour:hover { background: rgb(255 255 255 / .09); }
.jour.actif { background: rgb(255 255 255 / .15); }
.jour .d { font-weight: 600; font-size: 13.5px; color: #fff; display: block; }
.jour .r {
  font-size: 12px; color: var(--rail-doux); line-height: 1.4;
  margin-top: 2px; display: block;
}
.voir-plus {
  background: none; border: 0; color: var(--rail-doux);
  font-size: 12.5px; font-weight: 600;
  padding: 8px 10px; margin-top: 2px; border-radius: 9px; text-align: left;
}
.voir-plus:hover { background: rgb(255 255 255 / .09); color: #fff; }

.rail-bas {
  margin-top: auto; padding-top: 16px;
  border-top: 1px solid rgb(255 255 255 / .14);
}
.util { display: flex; align-items: center; gap: 10px; padding: 8px 10px; }
.util .qui { min-width: 0; }
/* ⛔ 297 §6.8 : le NOM COMPLET, jamais coupé de points de suspension. Un
   nom long passe à la ligne ; un nom amputé se lit comme une donnée fausse. */
.util b {
  font-size: 13.5px; color: #fff; display: block;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.25;
}
.util span { font-size: 11.5px; color: var(--rail-doux); }
.util button {
  margin-left: auto; background: none; border: 0; color: var(--rail-doux);
  padding: 7px; border-radius: 8px; display: grid; place-items: center;
}
.util button svg { width: 17px; height: 17px; }
.util button:hover { background: rgb(255 255 255 / .12); color: #fff; }

/* ⚠️ Le « ? » rejoint la roue dentée (étape 81). `margin-left: auto` est porté
   par le PREMIER bouton seulement : avec deux, chacun le prenant, ils se
   seraient repoussés aux deux bouts du rail. Le second se colle au premier, et
   la paire est poussée à droite comme l'était la roue seule. */
.util button + button { margin-left: 0; }
#bouton-aide {
  font-size: 15px; font-weight: 700; line-height: 1;
  width: 31px; height: 31px;      /* la même emprise que la roue, à l'œil */
}

/* Une phrase qu'on prononce, pas une consigne : elle se lit comme une citation
   et c'est ce qui la rend imitable. */
.explication.exemple {
  font-style: italic; color: var(--marine);
  border-left: 2px solid var(--ambre); padding-left: 10px; margin: 6px 0;
}

.pastille {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--ambre); color: #fff;
  display: grid; place-items: center;
  font-weight: 700; font-size: 12.5px; flex: none;
}
/* ⛔ 304 §12.1 — la bulle des initiales est un BOUTON : même dessin, et la
   main au survol seulement quand elle ouvre quelque chose. */
/* ⚠️ `.util button` (le « ? » et la roue) donne un fond transparent, une
   marge automatique et un rayon de 8 px : devenue bouton, la bulle les
   prenait et perdait son disque ambre (vu sur la capture du 9/10). La règle
   par l'identifiant, plus précise, lui rend son dessin. */
.util #initiales, .util #initiales:hover {
  border: 0; padding: 0; margin-left: 0; font-family: inherit;
  background: var(--ambre); color: #fff; border-radius: 50%;
}
#initiales:disabled { cursor: default; }
#chiffres-panneau .fiche-corps { padding: 14px 24px 22px; }
#initiales.pastille-cliquable { cursor: pointer; }
#initiales.pastille-cliquable:hover,
#initiales.pastille-cliquable:focus-visible {
  outline: 2px solid #fff; outline-offset: 2px;
}

.voile-rail { display: none; }

/* ── Colonne principale ────────────────────────────────────────── */

.principal { display: flex; flex-direction: column; overflow: hidden; min-width: 0; }

.onglets {
  display: flex; align-items: center; gap: 4px;
  padding: 0 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--trait);
  flex: none;
}
.onglet {
  background: none; border: 0;
  padding: 15px 13px 12px;
  font-weight: 600; font-size: 14.5px; color: var(--doux);
  border-bottom: 2.5px solid transparent;
}
.onglet:hover { color: var(--encre); }
.onglet.actif { color: var(--marine); border-bottom-color: var(--marine); }
/* ⛔ 304 §5 bis (0317) — le petit nombre : ce qui est pour moi, pas encore
   vu. Ambre, comme la pastille des initiales : du blanc dessus (5,3:1). */
.badge-nouveau {
  display: inline-block; min-width: 18px; height: 18px; margin-left: 6px;
  padding: 0 5px; border-radius: 9px; vertical-align: 1px;
  background: var(--ambre); color: #fff;
  font-size: 11.5px; font-weight: 700; line-height: 18px; text-align: center;
}
.demande.besoin-cree { border-left: 3px solid var(--ambre-vif); }

.burger {
  display: none;
  background: none; border: 0; color: var(--doux);
  padding: 9px; margin-right: 2px; border-radius: 9px;
}
.burger svg { width: 20px; height: 20px; display: block; }

.lien {
  margin-left: auto;
  background: none; border: 0;
  color: var(--tres-doux); font-size: 13px; font-weight: 600;
  padding: 8px 4px;
}
.lien:hover { color: var(--encre); }

.vue { flex: 1; overflow-y: auto; min-height: 0; }

/* ── Chat ──────────────────────────────────────────────────────── */

.fil {
  max-width: 760px; margin: 0 auto;
  padding: 24px 20px 8px;
}

.bulle {
  max-width: 82%;
  padding: 12px 16px;
  border-radius: 16px;
  margin-bottom: 13px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.bulle.jarvis {
  background: var(--surface);
  border: 1px solid var(--trait);
  border-bottom-left-radius: 5px;
  box-shadow: var(--ombre);
}
.bulle.moi {
  background: var(--marine); color: #fff;
  margin-left: auto;
  border-bottom-right-radius: 5px;
}
/* 297 §2 — un texte collé long : une ligne, et le texte entier derrière
   « Voir le texte ». Le texte déplié défile dans la bulle, il ne l'allonge
   pas sur dix écrans. */
.bulle.moi.colle { max-width: min(560px, 86%); }
.colle-titre { font-weight: 600; }
.colle-extrait { opacity: .85; margin-top: 2px; }
.colle-voir {
  margin-top: 8px; background: rgb(255 255 255 / .16); color: #fff;
  border: 1px solid rgb(255 255 255 / .35); border-radius: 8px;
  padding: 5px 10px; font: inherit; font-size: 13px; cursor: pointer;
}
.colle-tout {
  margin-top: 8px; max-height: 320px; overflow: auto; white-space: pre-wrap;
  font-size: 13px; line-height: 1.45; background: rgb(255 255 255 / .1);
  border-radius: 8px; padding: 8px 10px;
}
/* 296 §7 — le tableau qu'écrit le modèle, rendu en tableau. */
.tableau-bulle { border-collapse: collapse; margin: 6px 0; font-size: 13.5px;
                 white-space: normal; width: 100%; }
.tableau-bulle td { border-top: 1px solid var(--trait); padding: 5px 8px 5px 0;
                    vertical-align: top; overflow-wrap: anywhere; }
.tableau-bulle tr:first-child td { border-top: 0; }
/* 296 §7 — l'erreur : la troisième nature du gabarit, au filet rouge de la
   charte (le rose venait d'une palette à elle). */
.bulle.souci {
  background: var(--rouge-pale); border: 1px solid var(--rouge-pale);
  border-left: 3px solid var(--rouge); color: var(--rouge);
  border-bottom-left-radius: 5px;
}
/* 282 §0 — une ligne du produit, pas de Jarvis : centrée, sans bulle. */
.bulle.systeme {
  align-self: center; background: none; box-shadow: none; border: none;
  color: var(--texte-doux); font-size: .85rem; padding: 4px 8px;
}
/* Le fil d'avant, grisé : on le retrouve, on ne le confond pas avec le vif. */
.bulle.avant { opacity: .66; box-shadow: none; }

/* ⛔ L'heure d'un message rejoué — étape 265 §1.8. Discrète, en fin de
   bulle, et sur sa PROPRE ligne : collée au texte elle se lirait comme un
   mot de la phrase. */
.bulle-heure {
  display: block; margin-top: 3px;
  font-size: 11px; color: var(--tres-doux);
  font-variant-numeric: tabular-nums; text-align: right;
}

/* Une adresse dans une bulle : chasse fixe, arobase détachée. « Un seul F »
   doit se voir à l'œil — Laurent a dû le rattraper deux fois le premier jour. */
.courriel {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .93em;
  background: rgb(0 38 135 / .05);
  border-radius: 5px; padding: 1px 4px;
}
.bulle.moi .courriel { background: rgb(255 255 255 / .16); }
.courriel-at { color: var(--ambre-vif); font-weight: 700; padding: 0 1px; }

.sep {
  display: flex; align-items: center; gap: 12px;
  margin: 22px 0 16px;
  color: var(--tres-doux);
}
.sep::before, .sep::after { content: ''; flex: 1; height: 1px; background: var(--trait); }
.sep span {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em; font-weight: 600;
}

/* ⛔ 304 bis §2 — l'attente : un anneau qui tourne, aux couleurs de l'écran,
   et la phrase de l'étape à côté. ⚠️ Transparente pendant 300 ms : un « oui »
   rapide ne fait rien clignoter. */
.reflechit {
  display: flex; gap: 10px; align-items: center; width: fit-content;
  opacity: 0; transition: opacity .2s ease-out;
}
.reflechit.montree { opacity: 1; }
.attente-anneau {
  flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%;
  border: 2.5px solid var(--marine-pale);
  border-top-color: var(--marine);
  animation: tourner .9s linear infinite;
}
.attente-corps { display: flex; flex-direction: column; gap: 2px; }
.attente-texte { color: var(--texte-doux); font-style: italic; }
.attente-longue { color: var(--tres-doux); font-size: 12.5px; }
.attente-longue[hidden] { display: none; }
@keyframes tourner { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 60%, 100% { opacity: .3 } 30% { opacity: 1 } }
/* ⛔ 284 §1.4 — la ligne « Je regarde tes comptes… », dans la bulle
   d'attente ; la première phrase de la réponse la remplace. */
.reflechit.en-cours .attente-texte { color: var(--texte-doux); }

/* ⛔ 304 bis §2.4 — les blocs gris qui scintillent pendant un chargement. */
.squelette { display: grid; gap: 10px; padding: 4px 0; }
.squelette-cartes {
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.squelette-bloc {
  border-radius: 10px; min-height: 18px;
  background: linear-gradient(90deg, var(--trait) 0%, var(--fond) 45%,
                              var(--trait) 90%);
  background-size: 300% 100%;
  animation: scintiller 1.4s ease-in-out infinite;
}
.squelette-lignes .squelette-bloc { height: 22px; }
.squelette-lignes .squelette-bloc:nth-child(odd) { width: 82%; }
.squelette-cartes .squelette-bloc { height: 96px; }
@keyframes scintiller {
  0% { background-position: 100% 0; } 100% { background-position: 0 0; }
}

/* ⛔ 304 bis §2.4 — la roue d'un bouton qui court ; il ne se clique pas
   deux fois (la garde est dans `appeler`, le style ici). */
button.roue { position: relative; cursor: progress; }
button.roue::after {
  content: ''; display: inline-block; width: 11px; height: 11px;
  margin-left: 7px; vertical-align: -1px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: tourner .8s linear infinite;
}

/* ── La carte d'aperçu ─────────────────────────────────────────── */
/* L'aperçu ne se raconte plus, il se lit : un champ par ligne, la valeur à
   droite, l'email et le téléphone à chasse fixe. C'est l'objet que la fonction
   SQL rend depuis la migration 0014 — on a simplement cessé de le jeter. */

.apercu {
  background: var(--ambre-pale);
  border: 1px solid var(--ambre-trait);
  border-left: 3px solid var(--ambre-vif);
  border-radius: 12px;
  padding: 13px 16px;
  margin: 0 0 14px;
  /* ⛔ 296 §7 — UN GABARIT POUR TOUTES LES CARTES : la même largeur
     (deux coexistaient, 590 et 720 px), le même arrondi, et trois natures
     au filet — à confirmer (ambre), information (marine), erreur (rouge). */
  max-width: var(--carte-max);
}
/* ⛔ Un aperçu TRAITÉ s'éteint — audit de l'étape 149. Il ne disparaît pas :
   « Jarvis n'efface jamais rien » vaut aussi pour ce qui est à l'écran. Ce
   qu'il montrait reste lisible ; ce qui cesse, c'est de ressembler à une
   question vivante. */
.apercu.repondu { opacity: .62; }
.apercu.repondu h4 { color: var(--doux); }
.apercu.repondu .boutons { display: none; }
/* ⛔ 296 §7 — « traité » et « abandonné » se ressemblaient au point de se
   confondre. Traité : le vert de ce qui est fait, et la carte reste nette.
   Abandonné : un filet en pointillé sur le fond de page, et elle s'efface. */
.apercu.ecrit { opacity: 1; background: var(--vert-pale);
                border-color: var(--vert-pale); border-left-color: var(--vert); }
.apercu.ecrit h4 { color: var(--vert); }
.apercu.morte, .apercu.abandonne { background: var(--fond); opacity: .55;
                border-color: var(--trait); border-left: 3px dashed var(--tres-doux); }

.apercu h4 {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ambre-encre); margin-bottom: 9px; font-weight: 700;
}
.apercu dl {
  display: grid; grid-template-columns: auto 1fr;
  gap: 5px 14px; font-size: 14px;
  margin: 0;
}
.apercu dt { color: var(--doux); }
.apercu dd { font-weight: 600; overflow-wrap: anywhere; }
/* ⛔ Étape 263 §5 — « Modifier » rend les champs modifiables DANS la carte.
   La saisie occupe exactement la place de la valeur : la carte ne doit pas
   sauter sous les doigts au moment où on la corrige. */
.apercu-saisie {
  width: 100%;
  font: inherit;
  font-weight: 600;
  color: inherit;
  padding: 4px 6px;
  border: 1px solid var(--trait);
  border-radius: 6px;
  background: var(--fond);
}
/* ⚠️ La chasse fixe vient du `dd` par `font: inherit` — une seconde
   déclaration de la police serait une seconde vérité. */
/* ⛔ 289 §2 — un texte long se corrige sur au moins dix lignes, qui
   grandissent avec lui (app.js) ; les retours à la ligne restent. */
textarea.apercu-saisie {
  min-height: calc(10 * 1.5em + 10px);
  line-height: 1.5;
  resize: vertical;
  overflow: hidden;
  white-space: pre-wrap;
}
.apercu.edition { outline: 2px solid var(--ambre-vif); }
/* ⛔ 289 §2 — sur téléphone, une carte qui porte un texte long empile le
   libellé AU-DESSUS de la valeur : à 390 px la colonne des libellés prenait
   un tiers de la largeur, et un compte rendu se lisait quatre mots par
   ligne (capture du 01/10). */
@media (max-width: 640px) {
  .apercu dl:has(dd.texte-long) { grid-template-columns: 1fr; gap: 2px 0; }
  .apercu dl:has(dd.texte-long) dt { margin-top: 6px; }
}
.apercu .avant { color: var(--tres-doux); text-decoration: line-through; }
.apercu .fleche { color: var(--tres-doux); padding: 0 4px; }
.apercu .apres { color: var(--ambre-encre); }
.apercu .doutes {
  margin-top: 10px; font-size: 12.5px; color: var(--ambre-encre);
  background: #fff; border: 1px solid var(--ambre-trait);
  border-radius: 8px; padding: 8px 10px;
}
.apercu .boutons { display: flex; gap: 9px; margin-top: 13px; }

.bt {
  border: 0; border-radius: 9px;
  padding: 9px 15px;
  font-weight: 600; font-size: 13.5px;
}
/* ══ ⛔ 296 §6 — LE JEU DE PIÈCES ═══════════════════════════════════
   Trois boutons, un champ, et rien d'autre :
     · PRINCIPAL  le geste attendu de l'écran : marine plein (l'orange
                  servait aussi, pour « Confirmer » et « Relier ma boîte » :
                  deux couleurs pour la même chose) ;
     · DOUX       une amorce, un geste possible : marine sur marine pâle
                  (« Accepter », « Le signaler », « Oui, avec… », « Faire
                  avancer », « Son suivi ») — ils étaient au style brut du
                  navigateur, ou en lien souligné ;
     · DISCRET    le geste de retrait : du texte (« Refuser », « Non »).
   L'ambre ne sert plus qu'à ce qui alerte. */
.bt.principal-bt { background: var(--marine); color: #fff; }
.bt.principal-bt:hover { background: var(--marine-clair); }
.lien-jarvis, .lien-discret {
  background: var(--marine-pale); color: var(--marine);
  border: 0; border-radius: 8px; text-decoration: none;
  padding: 6px 11px; font-size: 12.5px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px;
}
.lien-jarvis:hover, .lien-discret:hover { background: #DCE5F8; color: var(--marine); }
:where(select, textarea,
       input:not([type="checkbox"]):not([type="radio"]):not([type="file"])
            :not([type="range"])) {
  border: 1px solid var(--trait); border-radius: 9px;
  background: var(--surface); padding: 7px 10px;
}
:where(select, textarea, input):focus-visible {
  outline: 2px solid var(--marine-clair); outline-offset: 1px;
}
.vivier-plus > summary {
  list-style: none; color: var(--marine); font-weight: 600; font-size: 13px;
  padding: 6px 0;
}
.vivier-plus > summary::-webkit-details-marker { display: none; }
.vivier-plus > summary::before { content: "▸ "; }
.vivier-plus[open] > summary::before { content: "▾ "; }
.bt.secondaire { background: #fff; color: var(--doux); border: 1px solid var(--trait); }
.bt.secondaire:hover { color: var(--encre); border-color: var(--tres-doux); }

/* ── Zone de saisie ────────────────────────────────────────────── */

.saisie-zone {
  flex: none;
  padding: 12px 20px calc(16px + env(safe-area-inset-bottom));
  background: var(--fond);
}
.saisie {
  max-width: 760px; margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: 15px;
  box-shadow: var(--ombre);
  display: flex; align-items: flex-end;
  gap: 6px; padding: 7px 8px;
}
.icone-bt {
  width: 38px; height: 38px; flex: none;
  border: 0; border-radius: 10px; background: none;
  color: var(--doux);
  display: grid; place-items: center;
}
.icone-bt svg { width: 19px; height: 19px; }
.icone-bt:hover { background: var(--marine-pale); color: var(--marine); }
.icone-bt.micro.ecoute { background: #A31621; color: #fff; animation: souffle 1.4s infinite; }
@keyframes souffle { 50% { opacity: .72 } }

/* Le haut-parleur : les ondes quand ça parle, la croix quand c'est coupé. */
.haut-parleur .barre { display: none; }
#bouton-son.coupe { color: var(--tres-doux); }
#bouton-son.coupe .haut-parleur .ondes { display: none; }
#bouton-son.coupe .haut-parleur .barre { display: inline; }

#champ {
  flex: 1;
  /* ⛔ **LE PLANCHER, ET IL EST MESURÉ** (étape 198 §1). Il valait `0` :
     n'importe quoi inséré dans la barre pouvait donc écraser le champ
     jusqu'à rien, et c'est arrivé — 8 px le 17/09, avec la phrase d'astuce
     des fichiers. La cause est corrigée (les pièces sont sorties de la
     rangée) ; ceci est la CEINTURE, pour ce qu'on insérera demain.
     ⚠️ **60 px et pas plus, parce que le téléphone est déjà juste** :
     mesuré le 17/09 contre la production, le champ fait **78 px en 390 px**
     de large (176 en 768, 472 en 1440). Un plancher au-dessus de 78 aurait
     débordé la barre sur un produit sain — et un plancher qui déborde
     pousse le bouton d'envoi dehors, c'est-à-dire échange une impasse
     contre une autre. */
  min-width: 60px;
  border: 0; outline: none; background: none;
  resize: none; max-height: 30dvh;
  padding: 9px 4px; line-height: 1.45;
}
.envoi {
  width: 38px; height: 38px; flex: none;
  background: var(--marine); color: #fff;
  border: 0; border-radius: 10px;
  display: grid; place-items: center;
}
.envoi svg { width: 18px; height: 18px; }
.envoi:hover { background: var(--marine-clair); }

.aide {
  max-width: 760px; margin: 8px auto 0;
  font-size: 11.5px; color: var(--tres-doux);
  display: flex; gap: 14px; flex-wrap: wrap;
}
.etat-micro {
  max-width: 760px; margin: 8px auto 0;
  font-size: 12.5px; color: var(--doux);
}

/* ── L'écoute permanente (étape 142) ───────────────────────────────
   ⛔ **Elle se voit, et elle ne ressemble pas au mode conversation.** Deux
   états différents ne doivent pas porter la même forme : la veille attend un
   mot, la conversation est en cours. Un liseré ambre — ce qui appelle un
   geste — contre le bleu de la conversation. */
.veille-barre {
  max-width: 760px; margin: 10px auto 0;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--ambre-pale); border: 1px solid var(--ambre-trait);
  border-left: 3px solid var(--ambre-vif);
  border-radius: 12px; padding: 8px 12px; font-size: 12.5px;
}
.veille-pastille {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--ambre-vif); animation: souffle 2.2s infinite;
}
.veille-etat { color: var(--ambre-encre); flex: 1; min-width: 0; }
#bouton-veille[aria-pressed="true"] {
  background: var(--ambre); color: #fff;
}

/* ⛔ **LE BIP DU RÉVEIL SE VOIT AUTANT QU'IL S'ENTEND.** Un son seul ne suffit
   pas : bureau bruyant, casque enlevé, poste muet. Le liseré passe au bleu de
   la conversation le temps d'un battement — la réponse est immédiate, avant
   même que le mode soit monté. */
.veille-barre.reveille {
  background: var(--marine-pale); border-color: var(--marine-clair);
  border-left-color: var(--marine); animation: reveil .45s ease-out;
}
.veille-barre.reveille .veille-etat { color: var(--marine); font-weight: 700; }
.veille-barre.reveille .veille-pastille { background: var(--marine); }
@keyframes reveil { from { transform: scale(.97); } to { transform: scale(1); } }

/* ── Le mode conversation (étape 141) ──────────────────────────────
   ⚠️ **La couleur ne porte JAMAIS l'état seule** — même règle que les
   pastilles d'agenda (étape 56). Chaque état porte son MOT, en clair, et la
   pastille ne fait que le redire à l'œil. Un daltonien lit « Je t'écoute ». */
.conversation-barre {
  max-width: 760px; margin: 10px auto 0;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--trait);
  border-left: 3px solid var(--tres-doux);
  border-radius: 12px; padding: 8px 12px;
  font-size: 13px; box-shadow: var(--ombre);
}
.conv-pastille {
  width: 10px; height: 10px; border-radius: 50%; flex: none;
  background: var(--tres-doux);
}
.conv-etat { font-weight: 700; color: var(--encre); }
.conv-note { color: var(--doux); font-size: 12px; flex: 1; min-width: 0; }
.conv-bt {
  border: 1px solid var(--trait); background: var(--surface);
  color: var(--doux); border-radius: 9px;
  padding: 4px 10px; font-size: 12px; flex: none;
}
.conv-bt:hover { color: var(--encre); border-color: var(--tres-doux); }

/* ÉCOUTE — le micro est ouvert. C'est l'état qu'il faut voir de loin. */
.conversation-barre[data-etat="ecoute"] { border-left-color: #A31621; }
.conversation-barre[data-etat="ecoute"] .conv-pastille {
  background: #A31621; animation: souffle 1.4s infinite;
}
/* RÉFLÉCHIT */
.conversation-barre[data-etat="reflechit"] { border-left-color: var(--ambre-vif); }
.conversation-barre[data-etat="reflechit"] .conv-pastille { background: var(--ambre); }
/* PARLE */
.conversation-barre[data-etat="parle"] { border-left-color: var(--marine-clair); }
.conversation-barre[data-etat="parle"] .conv-pastille { background: var(--marine-clair); }
/* EN PAUSE — le micro est fermé, et ça se voit. */
.conversation-barre[data-etat="pause"] { border-left-color: var(--tres-doux); }

#bouton-conversation[aria-pressed="true"] {
  background: var(--marine); color: #fff;
}

/* ⛔ **LE TEXTE MASQUÉ EST UNE AFFAIRE DE CSS, ET RIEN D'AUTRE** (étape 141).
   Ludovic : « voir défiler ce qu'il dit est agaçant ». Le fil continue de se
   remplir — masquer ne doit JAMAIS retenir un tour (découplage de l'étape
   132). C'est aussi ce qui rend la garantie prouvable : le texte est dans le
   DOM, il n'est simplement pas à l'écran, et il revient d'un clic. */
#vue-chat.texte-masque #fil > * { visibility: hidden; }
/* ⛔ **L'APERÇU NE SE MASQUE JAMAIS, ET C'EST LA GARANTIE CENTRALE DU
   PRODUIT.** Masquer le bavardage est une commodité ; masquer la carte
   « Aperçu — à confirmer » pendant qu'on accepte un « oui » dit à voix haute,
   c'est promettre *« je te montre ce que je vais écrire »* et ne rien montrer.
   Le masque est du confort ; le rituel n'en est pas. */
#vue-chat.texte-masque #fil > .apercu { visibility: visible; }
#vue-chat.texte-masque #fil { position: relative; }
#vue-chat.texte-masque #fil::after {
  content: "Le texte est masqué : tout reste écrit, « Afficher le texte » le montre.";
  visibility: visible;
  position: sticky; bottom: 0; display: block;
  text-align: center; color: var(--tres-doux); font-size: 12.5px;
  padding: 10px 16px;
}

/* ── Mes comptes ───────────────────────────────────────────────── */

.comptes { padding: 22px 20px 40px; max-width: 1400px; margin: 0 auto; }

.bandeau {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px; margin-bottom: 20px;
}
.stat {
  background: var(--surface); border: 1px solid var(--trait);
  border-radius: var(--rayon); padding: 14px 16px; box-shadow: var(--ombre);
}
.stat b { display: block; font-size: 26px; font-weight: 700; letter-spacing: -.5px; line-height: 1.15; }
.stat span { font-size: 12.5px; color: var(--doux); }
.stat.alerte b { color: var(--ambre); }
.stat.bien b { color: var(--vert); }

/* « Ce qui t'attend » — ce qu'il a lui-même programmé, avant ce qui manque. */
.agenda {
  background: var(--surface);
  border: 1px solid var(--trait); border-left: 3px solid var(--marine);
  border-radius: var(--rayon);
  padding: 15px 18px; margin-bottom: 22px;
  box-shadow: var(--ombre);
}
.agenda h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--marine); margin-bottom: 10px;
  display: flex; align-items: baseline; gap: 8px;
}
.agenda h3 .retard { text-transform: none; letter-spacing: 0; color: var(--ambre); }

/* ⛔ LE SEUL ROUGE DE CET ÉCRAN (étape 226 §1). Le filet est ambre VIF — il ne
   porte aucun texte, c'est la règle de contraste de l'étape 37 — et le titre
   est en `--ambre` (5,3:1 sur blanc). */
.agenda-retard { border-left-color: var(--ambre-vif); background: var(--ambre-pale); }
.agenda-retard h3 { color: var(--ambre-encre); }
.agenda-retard .action { border-top-color: var(--ambre-trait); }

/* ── Ce qui se replie ───────────────────────────────────────────────
   ⛔ **Replier n'est pas cacher** : le nombre reste à l'écran, toujours
   visible, et il EST la porte. Le pli est fermé par défaut ; il s'ouvre d'un
   clic ou d'une touche, et `<details>` s'en charge sans une ligne de JS. */
.pli {
  background: var(--surface);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  margin-bottom: 14px; box-shadow: var(--ombre);
  overflow: hidden;
}
.pli > .pli-tete {
  list-style: none; cursor: pointer;
  display: flex; align-items: baseline; gap: 10px;
  padding: 13px 18px 13px 16px;
  font-size: 14px; color: var(--encre);
}
.pli > .pli-tete::-webkit-details-marker { display: none; }
/* Le chevron, posé par la CSS : il tourne à l'ouverture, et il dit qu'il y a
   quelque chose derrière. */
.pli > .pli-tete::after {
  content: '\203A'; margin-left: auto; color: var(--doux);
  font-size: 20px; line-height: 1; transform: rotate(0deg);
  transition: transform .15s ease;
}
.pli[open] > .pli-tete::after { transform: rotate(90deg); }
.pli > .pli-tete:hover { background: var(--marine-pale); }
.pli > .pli-tete:focus-visible { outline: 2px solid var(--marine-clair); outline-offset: -2px; }
.pli-n {
  font-size: 17px; font-weight: 700; color: var(--marine);
  font-variant-numeric: tabular-nums;
}
.pli-quoi { color: var(--doux); }
/* ⛔ Le pli EST le cadre : la section qu'il porte perd le sien, sinon on
   dessine un cadre dans un cadre. Les quatre propriétés sont déclarées, et
   pas seulement le `padding` — `.dormants` et `.domaines` posent chacun un
   fond, une bordure et une marge, et une règle qui n'en neutralise qu'une
   laisse les trois autres. */
.pli > section {
  padding: 0 18px 16px; margin: 0;
  background: transparent; border: 0; border-radius: 0;
}
.pli > section > h3:first-child { margin-top: 4px; }
/* ⛔ Le troisième cas : rien à lister, quelque chose à DIRE. Pas de porte,
   pas de chevron — la phrase EST le contenu. */
.pli-phrase > .pli-tete { display: none; }
.pli-phrase > section { padding: 15px 18px; }
/* ⛔ Un pli qui porte une alarme la porte DANS SA TÊTE, donc lisible même
   refermé à la main. Filet ambre vif — il ne porte aucun texte. */
.pli-alarme { border-left: 3px solid var(--ambre-vif); }
.pli-rouge { color: var(--ambre-encre); font-weight: 600; }
/* La section d'un bloc de support dans un pli : le pli porte déjà le titre. */
.bloc-dans-pli { box-shadow: none; }
.action {
  display: flex; align-items: center; gap: 13px;
  padding: 9px 0; border-top: 1px solid var(--trait);
}
.action:first-of-type { border-top: 0; }
.date-carre {
  width: 44px; height: 46px; flex: none;
  border-radius: 10px; background: var(--marine-pale); color: var(--marine);
  display: grid; place-items: center; align-content: center; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.date-carre b { font-size: 16px; font-weight: 700; }
.date-carre span { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
.action.en-retard .date-carre { background: var(--ambre-pale); color: var(--ambre-encre); }
.action .quoi { min-width: 0; }
.action .quoi b { font-size: 14.5px; }
.action .quoi span { display: block; font-size: 12.5px; color: var(--doux); }
.action .gestes { margin-left: auto; display: flex; gap: 6px; flex: none; }
.reste-actions { margin-top: 9px; font-size: 12px; color: var(--tres-doux); }

/* ── La campagne (étape 48) ──────────────────────────────────────────
   L'ambre, parce que ce bloc appelle un geste — l'agenda, lui, reste marine :
   il rappelle ce qui est déjà décidé. Le filet vif ne porte aucun texte
   (3,00:1 sur blanc), le texte est en `--ambre-encre` sur `--ambre-pale`
   (6,0:1). Contrainte de l'étape 37, inchangée. */
.campagne {
  background: var(--ambre-pale);
  border: 1px solid var(--ambre-trait); border-left: 3px solid var(--ambre-vif);
  border-radius: var(--rayon);
  padding: 15px 18px; margin-bottom: 22px;
}
.campagne h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ambre-encre); margin-bottom: 4px;
}
.campagne .bilan { font-size: 13.5px; color: var(--encre); margin-bottom: 13px; }
.campagne .cartes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.carte-portee {
  background: var(--surface);
  border: 1px solid var(--ambre-trait); border-radius: 10px;
  padding: 12px 13px;
  display: flex; flex-direction: column; gap: 7px; min-width: 0;
}
.carte-portee .haut { display: flex; align-items: flex-start; gap: 8px; }
/* Même correctif qu'aux vignettes : sans marge, le badge se colle au nom. */
.carte-portee b { font-size: 14px; font-weight: 700; line-height: 1.3; flex: 1; min-width: 0; }
.carte-portee .manque { font-size: 12.5px; color: var(--ambre-encre); }
.carte-portee .demander { margin-top: auto; align-self: flex-start; }

/* ── Le « ? » qui replie (étape 52) ──────────────────────────────────
   Discret par défaut, lisible une fois ouvert. Le bouton fait 22 px : c'est le
   minimum pour être touché au pouce sans agrandir la cible au point de
   redevenir ce qu'on vient de retirer de l'écran. */
/* ⛔ **IL S'APPELAIT `.aide`, COMME LA BARRE SOUS LA SAISIE** (l. 532),
   qui n'a rien à voir. Trois effets, tous mesurés (étape 264 §6, le crible
   né de M3) : ce `display: block` écrasait le `flex` de la barre, dont les
   deux phrases s'empilaient au lieu d'être côte à côte ; et le
   `display: none` du téléphone (l. 1373), écrit pour la barre, rendait
   INVISIBLES tous les « ? » d'explication de chiffre sur mobile. */
.aide-enveloppe { display: block; }
.aide-bouton {
  width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--trait); border-radius: 50%;
  background: var(--surface); color: var(--doux);
  font-size: 12px; font-weight: 700; line-height: 1;
}
.aide-bouton:hover { border-color: var(--marine-clair); color: var(--marine-clair); }
.aide-bouton.ouvert { background: var(--marine); border-color: var(--marine); color: #fff; }
.aide-texte {
  margin-top: 8px; padding: 11px 13px;
  background: var(--fond); border-left: 2px solid var(--trait);
  border-radius: 0 8px 8px 0;
  font-size: 12.5px; line-height: 1.6; color: var(--doux);
}

/* ── Mon agenda (étape 49) ───────────────────────────────────────────
   Le marine, comme « ce qui t'attend » : l'agenda CONSTATE, il ne réclame
   rien. L'ambre reste réservé à ce qui appelle un geste — s'il servait ici,
   il ne voudrait plus rien dire ailleurs. */
.agenda-tete {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 6px;
}
.agenda-pilote { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bascule { display: inline-flex; background: var(--marine-pale); border-radius: 9px; padding: 2px; }
.bascule button {
  border: 0; background: none; color: var(--doux);
  font-size: 13px; font-weight: 600; padding: 6px 13px; border-radius: 7px;
}
.bascule button.actif { background: var(--surface); color: var(--marine); box-shadow: var(--ombre); }
.fleches { display: inline-flex; align-items: center; gap: 4px; }
.fleches button {
  border: 1px solid var(--trait); background: var(--surface); color: var(--doux);
  border-radius: 8px; padding: 6px 11px; font-size: 13px; font-weight: 600;
  line-height: 1.2;
}
.fleches button:hover { border-color: var(--marine-clair); color: var(--marine-clair); }
.agenda-periode { font-size: 13.5px; color: var(--doux); margin-bottom: 16px; }

.jour-agenda {
  background: var(--surface);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: 13px 16px; margin-bottom: 12px; box-shadow: var(--ombre);
}
.jour-agenda.auj { border-left: 3px solid var(--marine); }
.jour-tete { display: flex; align-items: baseline; gap: 9px; margin-bottom: 8px; }
.jour-tete b { font-size: 14.5px; }
.jour-tete span { font-size: 12px; color: var(--tres-doux); }
.evt {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 0; border-top: 1px solid var(--trait);
}
.evt:first-of-type { border-top: 0; }
.evt-type {
  flex: none; min-width: 96px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: 4px 8px; border-radius: 6px; text-align: center;
}
/* Le passé se lit, l'avenir s'attend : deux gris, pas deux couleurs vives. */
.evt-passe .evt-type { background: var(--vert-pale); color: var(--vert); }
.evt-avenir .evt-type { background: var(--ambre-pale); color: var(--ambre-encre); }
.evt.en-retard .evt-type { background: var(--rouge-pale); color: var(--rouge); }
.evt-qui { min-width: 0; }
.evt-qui b { font-size: 14px; }
.evt-qui span { display: block; font-size: 12.5px; color: var(--doux); }
.evt .gestes { margin-left: auto; display: flex; gap: 6px; flex: none;
               flex-wrap: wrap; justify-content: flex-end; }

/* Les deux cas courants de « Décaler » (étape 57). Plus discrets que les trois
   gestes : ce sont des raccourcis, pas des intentions de plus. Ils portent une
   date COMPLÈTE — l'amorce est prête à envoyer, et c'est le commercial qui
   appuie. */
.geste-vite { font-size: 11px; padding: 3px 8px; border-radius: 999px;
              border: 1px solid var(--trait); background: var(--fond);
              color: var(--doux); }
.geste-vite:hover { border-color: var(--marine); color: var(--marine); }

/* Un écran qui n'a pas pu se charger (étape 58) — il DIT, et il donne un
   bouton. Ambre et non rouge : ce n'est pas une faute, c'est une attente qui
   n'a pas abouti, et on ne dramatise pas devant une salle. */
.indisponible { display: flex; flex-direction: column; align-items: flex-start;
                gap: 8px; padding: 16px 18px; border-radius: var(--rayon);
                background: var(--ambre-pale); border: 1px solid var(--trait);
                border-left: 3px solid var(--ambre); }
.indisponible b { color: var(--ambre-encre); font-size: 14px; }
.indisponible span { color: var(--doux); font-size: 13px; }
/* 296 §2 — la session expirée : en surimpression, jamais dans la grille de
   la coque (un enfant de plus y prendrait la cellule du rail). */
.session-expiree { position: fixed; top: 16px; left: 50%;
                   transform: translateX(-50%); z-index: 1000;
                   width: min(420px, calc(100vw - 32px));
                   box-shadow: 0 8px 24px rgba(0, 0, 0, .15);
                   background: var(--ambre-pale); }

/* ── Le calendrier (étape 52) ────────────────────────────────────────
   Sept colonnes, toujours. Pas de grille horaire : nos événements n'ont pas
   d'heure, et une trame de 8 h à 19 h serait vide à 95 %. La charte reste la
   nôtre — on s'inspire de la DISPOSITION d'Outlook, pas de ses couleurs. */
.cal { background: var(--surface); border: 1px solid var(--trait);
       border-radius: var(--rayon); overflow: hidden; box-shadow: var(--ombre); }
.cal-entete, .cal-corps { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-entete {
  background: var(--fond); border-bottom: 1px solid var(--trait);
}
.cal-entete span {
  padding: 8px 10px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--doux);
}
.cal-case {
  border-right: 1px solid var(--trait); border-bottom: 1px solid var(--trait);
  padding: 7px 7px 9px; min-width: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.cal-case:nth-child(7n) { border-right: 0; }
.cal-semaine .cal-corps .cal-case { min-height: 220px; }
.cal-mois .cal-corps .cal-case { min-height: 96px; }
.cal-num { font-size: 12.5px; font-weight: 700; color: var(--doux); }
/* Le jour courant se voit sans crier : une pastille sur le numéro. */
.cal-case.auj { background: var(--marine-pale); }
.cal-case.auj .cal-num {
  background: var(--marine); color: #fff;
  width: 21px; height: 21px; border-radius: 50%;
  display: grid; place-items: center; font-size: 11.5px;
}
/* Hors du mois : estompé, jamais absent — une case vide reste une information. */
.cal-case.hors { background: var(--fond); }
.cal-case.hors .cal-num { color: var(--tres-doux); opacity: .65; }

.chip {
  display: block; width: 100%; text-align: left;
  border: 0; border-left: 3px solid var(--marine-clair);
  border-radius: 5px; padding: 4px 6px;
  background: var(--marine-pale); color: var(--encre);
  min-width: 0; overflow: hidden;
}
/* Étape 177 : un créneau Outlook se lit, il ne se clique pas. Filet en
   pointillé, fond blanc : on voit d'un coup d'œil ce qui vient d'Outlook. */
.chip-outlook { border-left-style: dashed; background: #fff; cursor: default; }
.evt-outlook { border-left-style: dashed; }
.chip:hover { filter: brightness(.96); }
.chip-type {
  display: block; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--marine-clair);
}
.chip-compte {
  display: block; font-size: 11.5px; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ── Les quatre états, le code de Laurent (étape 56) ─────────────────
   « Il faudrait différencier les actions réalisées de celles qui sont à
   réaliser. » Sur sa capture, sept événements se ressemblaient tous alors que
   ceux du 17 étaient faits et deux du 18 en retard.

   réalisée = vert · à réaliser = orange · en retard = rouge · annulée = gris.

   ⚠️ **La couleur ne porte jamais l'information seule.** Un daltonien deutan ne
   distingue pas notre vert de notre rouge ; chaque pastille porte donc un MOT —
   « fait », « à faire », « en retard » — et c'est lui qui informe. La couleur
   accélère la lecture, elle ne la remplace pas. */
.chip-passe { background: var(--vert-pale); border-left-color: var(--vert); }
.chip-passe .chip-type { color: var(--vert); }
.chip-avenir { background: var(--ambre-pale); border-left-color: var(--ambre-vif); }
.chip-avenir .chip-type { color: var(--ambre-encre); }
.chip.en-retard { background: var(--rouge-pale); border-left-color: var(--rouge); }
.chip.en-retard .chip-type { color: var(--rouge); }
/* Gris : prévu pour les annulées. ⚠️ L'agenda ne les montre pas (règle de
   l'étape 36 : `statut = 'annulee'` sort de toutes les listes par
   construction), donc cet état ne s'affiche aujourd'hui nulle part. Il est
   défini pour que le jour où on décide de les montrer, la couleur soit déjà
   la bonne — pas pour faire joli. */
.chip-annulee { background: var(--fond); border-left-color: var(--tres-doux); }
.chip-annulee .chip-type { color: var(--doux); }
.chip-annulee .chip-compte { text-decoration: line-through; }

/* L'état, en toutes lettres, à côté de la couleur. */
.chip-etat {
  display: block; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; opacity: .85;
}
.cal-plus { font-size: 11px; font-weight: 600; color: var(--marine-clair); }

/* Sur bureau, la liste par journée s'efface : le calendrier la remplace. */
.agenda-liste { display: none; }

/* L'écran vide est le cas PRINCIPAL, pas le cas limite : huit personnes sur
   neuf n'auront rien le 31. Il est centré, respirant, et il renvoie ailleurs. */
.agenda-vide {
  background: var(--surface);
  border: 1px dashed var(--trait); border-radius: var(--rayon);
  padding: 40px 28px; text-align: center;
}
.agenda-vide .grand {
  font-size: 15px; color: var(--encre); max-width: 46ch;
  margin: 0 auto 10px; line-height: 1.6;
}
.agenda-vide p { font-size: 13.5px; color: var(--doux); }
.lien-inline {
  border: 0; background: none; padding: 0;
  color: var(--marine-clair); font-weight: 600; text-decoration: underline;
}

.titre-section { display: flex; align-items: baseline; gap: 12px; margin-bottom: 13px; flex-wrap: wrap; }
.titre-section h2 { font-size: 16px; font-weight: 700; }
.titre-section span { font-size: 12.5px; color: var(--doux); }

.grille { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }

/* ⛔ `display: flex` sur `.vignette` l'emporte sur `[hidden]` : sans
   cette ligne, le filtre marquerait les cartes et n'en cacherait
   AUCUNE. C'est le piège de `.tr-repliee` (étape 226 §2), au même
   endroit — et un banc qui lit `c.hidden` en JavaScript ne peut pas le
   voir : il faut mesurer ce qui est RENDU. */
.grille .vignette[hidden] { display: none; }

.vignette {
  background: var(--surface);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: 15px; box-shadow: var(--ombre);
  display: flex; flex-direction: column; min-height: 172px;
  text-align: left; color: inherit;
  transition: transform .12s, box-shadow .12s;
}
.vignette:hover { transform: translateY(-2px); box-shadow: var(--ombre-forte); }
.vignette .haut { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 4px; }
/* ⚠️ Le nom et le badge ont une MARGE. Collés, ça donnait
   « Banque Transatlantiqueprospect » sur chaque ligne. */
.vignette h3 { font-size: 14.5px; font-weight: 700; line-height: 1.3; flex: 1; }
.badge {
  flex: none;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: 3px 7px; border-radius: 5px;
}
.badge.prospect { background: var(--marine-pale); color: var(--marine-clair); }
.badge.client { background: var(--vert-pale); color: var(--vert); }
/* ⛔ **SUSPECT — étape 145.** 448 comptes sur 527 portaient l'étiquette
   « prospect » sans avoir jamais été touchés. Le gris DIT ce qu'ils sont : un
   nom dans un fichier, pas un échec. ⚠️ Il ne crie pas — ce n'est ni une
   alerte ni un reproche, c'est un état de départ. */
.badge.suspect { background: var(--trait); color: var(--doux); }  /* audit 149 : --fond valait la couleur de la page, donc rien */
.secteur {
  font-size: 12.5px; color: var(--doux); margin-bottom: 12px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.contact { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--trait); }
.contact .nom { font-size: 13.5px; font-weight: 600; }
.contact .fonction { font-size: 12px; color: var(--doux); margin-bottom: 7px; }
.coord { display: flex; flex-direction: column; gap: 3px; align-items: flex-start; }
.coord a {
  font-size: 12.5px; color: var(--marine-clair); text-decoration: none;
  overflow-wrap: anywhere;
}
.coord a:hover { text-decoration: underline; }
.autres { font-size: 11.5px; color: var(--tres-doux); margin-top: 9px; }

/* L'état « aucun interlocuteur » : 18 comptes sur 21. Il est soigné parce que
   c'est l'état le plus fréquent, pas malgré ça. */
.sans-personne { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--trait); }
.sans-personne p { font-size: 12.5px; color: var(--doux); margin-bottom: 9px; }
.bt-ajout {
  width: 100%;
  background: var(--ambre-pale); color: var(--ambre-encre);
  border: 1px solid var(--ambre-trait); border-radius: 9px;
  padding: 8px; font-weight: 600; font-size: 12.5px;
}
.bt-ajout:hover { background: #FBE6D4; }

/* ⛔ 270 §9 : « en voir 40 de plus » était un `.lien` — gris clair, petit,
   aligné à droite, en fin d'une liste de quarante cartes. Personne ne le
   trouvait. Il a maintenant l'air de ce qu'il est : un bouton. */
.bt-voir-plus {
  background: var(--marine-pale); color: var(--marine);
  border: 1px solid var(--trait); border-radius: 9px;
  padding: 10px 16px; font-weight: 600; font-size: 13.5px;
}
.bt-voir-plus:hover { background: #E3EAF6; }

/* Un raccourci de frappe, pas une commande : il pré-remplit le champ. */
.demander {
  background: var(--marine-pale); color: var(--marine);
  border: 0; border-radius: 8px;
  padding: 6px 11px; font-size: 12.5px; font-weight: 600;
  align-self: flex-start;
}
.demander:hover { background: #DCE5F8; }
/* Dans une fiche, ces amorces suivent une liste : il leur faut de l'air. */
.bloc > .demander, .interlocuteur .demander { margin-top: 12px; }
.interlocuteur .demander { margin-top: 8px; }
.bloc > .bt-ajout { margin-top: 12px; max-width: 260px; }

/* ── Fiche compte et réglages ──────────────────────────────────── */

.voile {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 40px 16px; overflow-y: auto;
}
.voile-fond { position: fixed; inset: 0; background: rgb(13 37 52 / .42); }
.fiche {
  position: relative;
  background: var(--surface); border-radius: 18px;
  max-width: 820px; width: 100%;
  box-shadow: 0 24px 60px rgb(13 37 52 / .28);
  overflow: hidden;
}
.fiche.etroite { max-width: 460px; }
.fiche-tete {
  padding: 20px 24px 16px; border-bottom: 1px solid var(--trait);
  display: flex; align-items: flex-start; gap: 14px;
}
.fiche-tete h2 { font-size: 20px; font-weight: 700; line-height: 1.25; }
.fiche-tete .sous { font-size: 13px; color: var(--doux); margin-top: 3px; }
/* ⛔ 296 §6 — une seule croix de fenêtre : ronde, la même que les tiroirs
   de la direction (l'aide et les réglages avaient une croix nue). */
.fermer {
  margin-left: auto; border: 0; flex: none;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--fond); display: grid; place-items: center;
  font-size: 18px; line-height: 1; color: var(--doux); padding: 0;
}
.fermer:hover { color: var(--encre); background: var(--trait); }
.fiche-corps { max-height: min(64dvh, 620px); overflow-y: auto; }

.bloc { padding: 18px 24px; border-bottom: 1px solid var(--trait); }
.bloc:last-child { border-bottom: 0; }
.bloc h3 {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--marine); font-weight: 700; margin-bottom: 12px;
}
.bloc .explication { font-size: 12.5px; color: var(--doux); margin-bottom: 10px; }

.ligne-info {
  display: grid; grid-template-columns: 190px 1fr;
  gap: 6px 16px; font-size: 14px; margin: 0;
}
.ligne-info dt { color: var(--doux); }
.ligne-info dd { overflow-wrap: anywhere; }
.ligne-info dd.vide { color: var(--tres-doux); }

.interlocuteur {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 11px; border: 1px solid var(--trait); border-radius: 11px;
  margin-bottom: 8px;
}
.interlocuteur:last-child { margin-bottom: 0; }
.interlocuteur.absent { border-style: dashed; }
/* ⛔ 270 §8 : la carte entière est cliquable — il faut donc qu'elle le
   MONTRE, à la souris comme au clavier. Un élément qui réagit sans le dire
   est un élément que personne n'essaie. */
.interlocuteur[role="button"] { cursor: pointer; }
.interlocuteur[role="button"]:hover { border-color: var(--marine); }
.interlocuteur[role="button"]:focus-visible {
  outline: 2px solid var(--marine); outline-offset: 2px;
}
.interlocuteur .gestes {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px;
}
.init {
  width: 36px; height: 36px; flex: none;
  border-radius: 50%; background: var(--marine-pale); color: var(--marine);
  display: grid; place-items: center; font-weight: 700; font-size: 13px;
}
.interlocuteur.absent .init { background: var(--ambre-pale); color: var(--ambre-encre); }
.interlocuteur .identite { font-weight: 600; }
.interlocuteur .role { font-size: 12.5px; color: var(--doux); }
.interlocuteur .coord { flex-direction: row; flex-wrap: wrap; gap: 4px 14px; margin-top: 5px; }
.interlocuteur .manque { font-size: 12.5px; color: var(--ambre-encre); }

.echange { display: flex; gap: 11px; padding: 7px 0; font-size: 13.5px; }
.echange .quand { color: var(--doux); flex: none; font-variant-numeric: tabular-nums; }
.echange .quoi { min-width: 0; }
/* ⛔ Étape 263 §8 (E8) — un échange confidentiel se voit. Il marque
   l'EXISTENCE, jamais le contenu : c'est la garantie de l'étape 108. */
.echange-cadenas {
  flex: none;
  font-size: 0.82rem;
  color: var(--ambre-encre);
  background: var(--ambre-pale);
  border: 1px solid var(--ambre-trait);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
}
.echange.annulee { color: var(--tres-doux); }
.echange.annulee .quoi { text-decoration: line-through; }
/* ⛔ Étape 260 §2 : un échange corrigé est BARRÉ, jamais retiré. La ligne
   suivante porte la correction, décalée, pour qu'on voie d'un coup d'œil
   laquelle remplace laquelle. */
.echange.corrigee { color: var(--tres-doux); }
.echange.corrigee .quoi { text-decoration: line-through; }
.echange.correction { padding-top: 0; }
.echange.correction .quand { color: var(--tres-doux); }
.echange.correction .quoi { color: var(--doux); font-style: italic; }

.notes-libres {
  font-size: 13px; color: var(--doux); white-space: pre-wrap;
  background: var(--fond); border-radius: 10px; padding: 10px 12px;
}

.fiche-pied {
  padding: 14px 24px calc(14px + env(safe-area-inset-bottom));
  background: var(--fond);
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--trait);
}
.fiche-pied .note { font-size: 12.5px; color: var(--doux); margin-right: auto; }

#choix-voix {
  width: 100%;
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 10px; padding: 9px 11px;
}

.vide { color: var(--tres-doux); font-size: 13.5px; }

/* ── Direction ─────────────────────────────────────────────────── */
/* Sobre, sans rouge, sans classement. Ce tableau sera lu par quelqu'un qui
   décide de la carrière des gens : les chiffres suffisent. */

/* ⛔ 296 §5 — la direction et le support étaient collés au menu et au bord
   droit : la même marge que les autres écrans. */
.direction { padding: 0 20px 32px; max-width: 1400px; margin: 0 auto; }
.periode {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 11px 20px;
  background: var(--surface); border-bottom: 1px solid var(--trait);
  font-size: 14px;
}
.periode select {
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 8px; padding: 5px 8px; font-size: 14px;
}
.direction-corps { padding: 18px 20px; display: flex; flex-direction: column; gap: 18px; }
.direction-corps section {
  background: var(--surface); border: 1px solid var(--trait);
  border-radius: var(--rayon); padding: 16px 18px; box-shadow: var(--ombre);
}

.chiffres { display: flex; flex-wrap: wrap; gap: 10px; }
.chiffre {
  flex: 1 1 140px;
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 10px; padding: 11px 13px;
}
.chiffre .valeur { font-size: 25px; font-weight: 700; line-height: 1.15; }
.chiffre .quoi { font-size: 12px; color: var(--doux); margin-top: 2px; }
.chiffre .detail { font-size: 12px; color: var(--doux); margin-top: 5px; }
/* ⛔ La tuile qui annonce une réussite au lieu d'un zéro (étape 183 §2).
   Le vert dit que ce n'est pas un compteur cassé ; la phrase dit quoi. */
.chiffre.reussite { background: var(--vert-pale); border-color: var(--vert); }
.chiffre .reussite-phrase {
  font-size: 14px; font-weight: 600; line-height: 1.3; color: var(--vert);
}
.barre-part { height: 5px; border-radius: 3px; background: var(--trait); margin-top: 8px; }
.barre-part i { display: block; height: 100%; border-radius: 3px; background: var(--marine-clair); }

.tableau { width: 100%; border-collapse: collapse; font-size: 14px; }
.tableau th, .tableau td { padding: 8px 6px; text-align: right; }
.tableau th:first-child, .tableau td:first-child { text-align: left; white-space: nowrap; }
.tableau thead th {
  font-size: 11px; font-weight: 650; text-transform: uppercase; letter-spacing: .03em;
  color: var(--doux); border-bottom: 1px solid var(--trait);
}
.tableau tbody tr { border-bottom: 1px solid var(--trait); }
.tableau tbody tr:last-child { border-bottom: 0; }
.tableau td { font-variant-numeric: tabular-nums; }
.tableau .zero { color: var(--tres-doux); }
.tableau .phare { font-weight: 650; border-left: 2px solid var(--trait); padding-left: 10px; }
.tableau thead .phare { color: var(--encre); }
.tableau-cadre { overflow-x: auto; }
/* ⛔ Les lignes repliées (étape 226 §2) — une CLASSE et pas `[hidden]` :
   sous 640 px les lignes passent en `display: block`, et `display` l'emporte
   sur l'attribut. La ligne resterait visible et le pli ne replierait rien. */
.tr-repliee { display: none !important; }
.tr-plus td { text-align: left; padding-top: 10px; }

/* ══════════════════════════════════════════════════════════════════════
   ⛔ À 420 px, UNE LIGNE DEVIENT UNE CARTE (étape 226 §2).

   *Un débordement horizontal n'est jamais acceptable. Un tableau qui ne
   tient pas cesse d'être un tableau.* L'écran du président mesurait
   7 233 px de large à 420 px — c'est l'écran de quelqu'un qui le regardera
   sur son téléphone.

   Le nom devient le titre de la carte ; ses chiffres se rangent dessous, les
   uns sous les autres, chacun précédé du libellé de sa colonne — posé par
   `etiqueterTableaux()` dans `data-col`, jamais écrit à la main.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  /* L'en-tête sort de l'écran sans sortir du document : un lecteur d'écran
     lit encore la structure du tableau. */
  .tableau thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .tableau, .tableau tbody, .tableau tr, .tableau td { display: block; width: auto; }
  .tableau tbody tr {
    border: 1px solid var(--trait); border-radius: 10px;
    background: var(--surface); padding: 10px 12px; margin-bottom: 10px;
  }
  .tableau tbody tr:last-child { border-bottom: 1px solid var(--trait); }
  .tableau tbody td {
    display: flex; justify-content: space-between; gap: 14px;
    text-align: right; padding: 3px 0; border: 0;
  }
  .tableau tbody td::before {
    content: attr(data-col);
    color: var(--doux); text-align: left; font-size: 12px;
    text-transform: uppercase; letter-spacing: .03em;
    flex: 0 0 auto; max-width: 55%;
  }
  /* ⛔ Le nom est le TITRE de la carte : pas de libellé, pas de `nowrap` —
     c'est lui qui poussait la ligne au-delà de l'écran. */
  .tableau tbody td:first-child {
    display: block; text-align: left; white-space: normal;
    font-weight: 650; font-size: 15px;
    padding-bottom: 7px; margin-bottom: 5px;
    border-bottom: 1px solid var(--trait);
  }
  .tableau tbody td:first-child::before { content: none; }
  .tableau .phare { border-left: 0; padding-left: 0; }
  .tableau tbody tr.tr-plus { border: 0; background: none; padding: 0; }
  .tableau tbody tr.tr-plus td { display: block; text-align: left; }
  /* Le cadre ne défile plus : il n'y a plus rien qui dépasse. */
  .tableau-cadre { overflow-x: visible; }
}

.legende { font-size: 12px; color: var(--doux); line-height: 1.55; }
.univers { margin-top: 12px; }
.repartition { list-style: none; display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.repartition li { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.univers-nom { flex: 0 0 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.univers-barre {
  flex: 1; height: 7px; border-radius: 4px; background: var(--trait); position: relative;
}
.univers-barre::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: var(--part);
  border-radius: 4px; background: var(--marine-clair);
}
.univers-n { flex: none; font-variant-numeric: tabular-nums; color: var(--doux); }

.silence {
  margin: 0; padding: 26px 18px; text-align: center;
  color: var(--doux); font-size: 14px; line-height: 1.65;
}

/* ⛔ **CE QUI ATTEND, SOUS LA BARRE — 273 §3.** Elle dit pourquoi le message
   ne part pas tout de suite, et qu'il n'est pas perdu. ⚠️ Discrète : c'est un
   état passager, pas une alerte — mais elle occupe sa place, sinon la barre
   sauterait d'une ligne à chaque tour. */
.file-attente {
  margin: 0; padding: 4px 16px 8px;
  color: var(--doux); font-size: 13px; line-height: 1.45;
}
/* ⚠️ La flèche d'envoi pendant un tour : elle reste cliquable — on met en
   file — mais elle DIT qu'elle attend. */
.envoi.attend { opacity: 0.55; }

/* Étape 221 §7 : une société cessée au registre, dite sur sa fiche. Le texte
   est en ambre sombre (5,3:1), le filet en ambre vif : jamais de texte dessus. */
.avertissement {
  margin: 0 0 12px; padding: 10px 12px; border-left: 3px solid var(--ambre-vif);
  background: var(--ambre-pale); color: var(--ambre); font-size: 14px;
  line-height: 1.5;
}

/* Étape 221 §11 : les absences du compte rendu, nommées en bas. */
.absences { margin: 0; padding-left: 20px; line-height: 1.6; font-size: 14px; }

/* ── Téléphone ─────────────────────────────────────────────────── */
/* Laurent l'ouvre sur son téléphone. Le rail devient un tiroir, les vignettes
   passent sur une colonne, la barre de saisie reste sous le pouce. */

@media (max-width: 1250px) { .grille { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 950px)  { .grille { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 950px)  { .campagne .cartes { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 720px) {
  .app { grid-template-columns: 1fr; }

  .rail {
    position: fixed; inset: 0 auto 0 0; z-index: 60;
    width: min(84vw, var(--rail-largeur));
    transform: translateX(-102%);
    transition: transform .18s ease-out;
  }
  /* ⛔ 296 §5 — l'ombre ne vit qu'avec le rail OUVERT : posée sur le rail
     fermé, son flou débordait du bord et laissait une bande bleutée sur la
     gauche de tous les écrans. */
  .rail.ouvert { transform: none; box-shadow: 0 0 40px rgb(0 38 135 / .35); }
  .fermer-rail { display: block; }
  .voile-rail {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: rgb(13 37 52 / .42);
  }

  .burger { display: grid; place-items: center; }
  /* ⛔ **LA BARRE D'ONGLETS DÉFILE, ET LE TEXTE NE SE COUPE PLUS** —
     étape 264 §6 (T2). Mesuré à 390 px avec une vraie session : « Mes
     comptes » et « Mon agenda » faisaient **70 px de haut contre 36** pour
     « Déconnexion », c'est-à-dire deux lignes chacun.

     ⚠️ **`nowrap` seul ferait déborder la page** — les quatre onglets d'un
     commercial dépassent 390 px une fois dépliés. Et surtout : **un compte
     qui cumule en porte SIX** (Jarvis, Mes comptes, Mon agenda, Direction,
     Support, Déconnexion) — c'est le cas de Christelle depuis l'étape 264
     §3. *Le défilement de cette barre n'est donc pas un confort, c'est la
     seule forme qui tienne quand le nombre d'onglets change.*

     ⚠️ Le défilement est CONFINÉ à la barre : `overflow-x` ici n'élargit pas
     la page, et le contrôle vérifie les deux. C'est déjà la forme de
     `.subtabs` dans la V2. */
  /* ⛔ 296 §5 — LA BARRE PASSE À LA LIGNE. Le défilement de l'étape 264
     tenait la page, mais il cachait la fin sans le dire : à 390 px on lisait
     « Jarvis / Tous les comptes / Mon agenda / Resso », Missions et Support
     étaient invisibles, et sur Missions aucun onglet ne paraissait actif.
     Deux lignes montrent tout, l'actif compris, sans rien élargir. */
  .onglets { padding: 0 8px; flex-wrap: wrap; column-gap: 2px; row-gap: 0; }
  .onglet { padding: 11px 9px 9px; font-size: 14px; white-space: nowrap; flex: none; }
  #bouton-deconnexion { margin-left: auto; }

  .grille { grid-template-columns: 1fr; }
  .campagne .cartes { grid-template-columns: 1fr; }
  /* ⚠️ Sept colonnes sur 390 px ne sont pas un calendrier. Sur téléphone, le
     calendrier s'efface et la LISTE par journée revient — avec ses trois
     gestes explicites, qui ne tiennent pas dans une case de grille. Même
     règle que les vignettes, et même raison. */
  .cal { display: none; }
  .agenda-liste { display: block; }
  /* Téléphone : les gestes passent sous l'événement plutôt que de le
     comprimer, et le pilote de période reste sur une ligne. */
  .agenda-tete { flex-direction: column; gap: 10px; }
  .agenda-pilote { width: 100%; justify-content: space-between; }
  .evt { flex-wrap: wrap; }
  .evt .gestes { margin-left: 0; width: 100%; padding-left: 108px; }
  .agenda-vide { padding: 32px 18px; }
  .vignette { min-height: 0; }
  .comptes { padding: 16px 14px 32px; }
  .fil { padding: 18px 14px 4px; }
  /* 296 §7 — le gabarit des cartes vaut aussi sur téléphone : toutes. */
  .bulle { max-width: 92%; }
  :root { --carte-max: 92%; }
  .saisie-zone { padding: 10px 12px calc(12px + env(safe-area-inset-bottom)); }
  /* ⛔ 296 §5 — LE CHAMP PREND TOUTE LA LARGEUR, les boutons passent
     dessous. À 390 px il restait 78 px de texte entre six boutons : quatre
     mots par ligne, la première rognée, et la zone couvrait la moitié de la
     conversation. Seul le champ change de ligne : la barre ne porte toujours
     que ses commandes (règle de l'étape 198). */
  .saisie { flex-wrap: wrap; align-items: center; }
  #champ { order: -1; flex: 1 0 100%; max-height: 22dvh; padding: 8px 6px; }
  .saisie .envoi { margin-left: auto; }
  .aide { display: none; }
  /* ⛔ 296 §5 — UN DOIGT FAIT 44 px. « Faire avancer », « Son suivi », les
     flèches de l'agenda et « Fait · Décaler · Annuler » étaient sous 30. */
  .lien-discret, .action .gestes button, .evt .gestes button,
  .agenda-pilote button { min-height: 44px; min-width: 44px; }
  .lien-discret { display: inline-flex; align-items: center; padding: 0 10px; }

  .action { flex-wrap: wrap; }
  .action .gestes { margin-left: 57px; }

  .voile { padding: 0; align-items: stretch; }
  .fiche, .fiche.etroite { max-width: none; border-radius: 0; min-height: 100dvh; }
  .fiche-corps { max-height: none; }
  .ligne-info { grid-template-columns: 1fr; gap: 1px 0; }
  .ligne-info dt { font-size: 12.5px; margin-top: 8px; }
  .fiche-pied .note { flex: 1 0 100%; margin-bottom: 4px; }

  .direction-corps { padding: 14px; }
  .direction { padding: 0 14px 32px; }
  .periode { padding: 10px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  /* ⛔ 304 bis §2.5 — moins d'animations : un indicateur FIXE, jamais un
     anneau figé à moitié dessiné (on croirait l'écran planté). Un disque
     plein, et des blocs gris unis. */
  .attente-anneau { border-color: var(--marine); background: var(--marine-pale); }
  button.roue::after { border-right-color: currentColor; opacity: .55; }
  .squelette-bloc { background: var(--trait); }
}

/* ── Les quatre onglets de l'écran de direction (étape 106) ─────────
   Dictés par Ludovic le 31 août. Ils vivent DANS la vue direction : ce ne
   sont pas les onglets du produit, ce sont les vues d'un même écran. */
.onglets-direction {
  display: flex; flex-wrap: wrap; gap: 4px;
  border-bottom: 1px solid var(--trait); margin: 12px 0 16px;
}
.onglet-dir {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 8px 14px; font: inherit; color: var(--texte-doux);
  cursor: pointer; border-radius: 6px 6px 0 0;
}
.onglet-dir:hover { background: var(--fond-doux); color: var(--texte); }
.onglet-dir.actif {
  color: var(--bleu); border-bottom-color: var(--bleu); font-weight: 600;
}
.comptes-direction { margin-top: 10px; }
/* La ligne du commercial sélectionné, dans un classement où il figure. */
.tableau tr.en-avant { background: var(--fond-doux); font-weight: 600; }

/* ── La jauge de complétude et les chiffres cliquables (étape 107) ──
   ⛔ Aucun jugement de valeur : une barre, une cible, et ce qui manque. Le
   classement est l'écran de Ludovic, pas celui du commercial. */
.jauge { margin: 10px 0 16px; }
.jauge-tete { display: flex; justify-content: space-between; align-items: baseline; }
.jauge-titre { color: var(--texte-doux); font-size: 0.92rem; }
.jauge-valeur { font-size: 1.35rem; color: var(--bleu); }
.jauge-piste {
  position: relative; height: 10px; margin: 6px 0 6px;
  background: var(--fond-doux); border-radius: 5px; overflow: visible;
}
.jauge-barre {
  height: 100%; border-radius: 5px; background: var(--bleu);
  transition: width .4s ease;
}
.jauge-barre.atteinte { background: #1B7F4F; }
.jauge-repere {
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--texte-doux); opacity: .55;
}
.jauge-pied { color: var(--texte-doux); font-size: 0.88rem; margin: 2px 0 0; }

/* Un chiffre qu'on peut ouvrir se voit qu'on peut l'ouvrir. */
.stat.ouvrable { cursor: pointer; border-radius: 8px; }
.stat.ouvrable:hover, .stat.ouvrable:focus-visible { background: var(--fond-doux); }
.detail-chiffre {
  margin: 8px 0 16px; padding: 12px 14px;
  border: 1px solid var(--trait); border-radius: 10px;
}
.liste-detail { margin: 6px 0 0; padding-left: 18px; line-height: 1.7; }
.fermer-detail {
  background: none; border: none; font-size: 1.1rem; cursor: pointer;
  color: var(--texte-doux); padding: 2px 8px;
}
.icone-bt.plus svg { width: 22px; height: 22px; }

/* Le rappel « relie ta boîte » — une fois par jour, discret, avec sa sortie.
   ⚠️ Ce n'est PAS une bulle de Jarvis : il ne l'a pas dit, c'est le produit
   qui le rappelle. La forme le dit — pas d'avatar, un filet, un bouton. */
.bandeau-liaison {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 11px 14px;
  background: var(--bleu-tres-pale, #eef1f8);
  border-left: 3px solid var(--bleu, #002687);
  border-radius: 9px; font-size: 14px; color: var(--doux, #4a5878);
}
.bandeau-liaison .bt { flex: none; }
@media (max-width: 640px) { .bandeau-liaison { align-items: flex-start; } }

/* ⛔ **LA CARTE DE SIGNATURE — étape 248 §1.**

   ⚠️ Elle ressemble au bandeau de liaison (même famille : une proposition
   faite à l'accueil), mais elle porte un APERÇU, donc elle est en colonne et
   elle a plus d'air. *Deux allures identiques pour deux gestes différents
   feraient cliquer de travers.* */
.carte-signature {
  display: flex; flex-direction: column; gap: 10px;
  margin: 10px 0 4px; padding: 13px 16px;
  background: var(--bleu-tres-pale, #eef1f8);
  border-left: 3px solid var(--bleu, #002687);
  border-radius: 9px; font-size: 14px; color: var(--doux, #4a5878);
}
.carte-signature-titre { margin: 0; font-weight: 600; color: var(--encre, #16213e); }
.carte-signature-gestes { display: flex; gap: 8px; flex-wrap: wrap; }
.carte-signature .bt { flex: none; }

/* ⛔ L'aperçu montre la signature TELLE QU'ELLE PARTIRA — fond blanc, comme
   un corps de mail, et le logo À SA PLACE. */
.signature-apercu-carte {
  background: #fff; border: 1px solid var(--trait, #d8dee9);
  border-radius: 7px; padding: 12px 14px;
}
.signature-apercu-carte .signature-logo {
  display: block; max-width: 220px; max-height: 90px; margin-bottom: 8px;
}
.signature-apercu-carte .signature-apercu-texte {
  margin: 0; white-space: pre-wrap; font-family: inherit; font-size: 13px;
  color: var(--encre, #16213e);
}
.signature-logo-choix {
  display: flex; align-items: center; gap: 8px; font-size: 13px;
}
@media (max-width: 640px) {
  .signature-apercu-carte .signature-logo { max-width: 100%; }
}

/* ⛔ **Le refus d'un dépôt a la même forme que le rappel de liaison, et c'est
   voulu** (étape 154) : ce sont deux moments du même geste — « ta boîte n'est
   pas reliée ». Deux allures différentes feraient croire à deux problèmes.
   Le cas RÉUSSI, lui, se distingue : il ne demande rien, il informe — d'où le
   filet vert et l'absence de bouton. */
.bandeau-depot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 11px 14px;
  background: var(--bleu-tres-pale, #eef1f8);
  border-left: 3px solid var(--ambre, #A85513);
  border-radius: 9px; font-size: 14px; color: var(--doux, #4a5878);
}
.bandeau-depot .bt { flex: none; }
.bandeau-depot.depose { border-left-color: var(--vert, #256B54); }
@media (max-width: 640px) { .bandeau-depot { align-items: flex-start; } }

/* ⛔ **LE REFUS, TEL QUE LE CODE L'A ÉCRIT** (étape 200 §2). Même forme que
   l'aperçu et le bandeau de dépôt : un filet ambre, un fond plat, aucun des
   arrondis des bulles — *ce n'est pas Jarvis qui parle, c'est le produit qui
   dit ce qu'il ne peut pas faire.*
   ⚠️ Les couleurs sont celles de la charte, avec leur repli : le contrôle des
   variables fantômes (étape 157) refuse un `var()` qui n'existe pas. */
.carte-refus {
  /* ⛔ 296 §7 — le gabarit des cartes : un refus est une INFORMATION
     (filet marine), pas une question à confirmer (ambre). */
  margin: 0 0 14px; padding: 13px 16px;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--marine);
  border-radius: 12px; font-size: 14px;
  max-width: var(--carte-max);
}
.carte-refus-titre {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--marine); margin-bottom: 6px;
}
.carte-refus-texte { color: var(--encre, #16213e); line-height: 1.45; }
/* 291 §3 — la suite d'un refus : des gestes qui pré-remplissent. */
.carte-refus-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.carte-refus-actions button { white-space: normal; text-align: left; }

/* ⛔ **CE QUE JARVIS DIT UNE FOIS** — étape 208 §2. Même forme que le refus,
   filet BLEU et non ambre : ce n'est pas un refus, c'est une information qui
   protège. ⚠️ Les couleurs portent leur repli — le contrôle des variables
   fantômes (étape 157) refuse un `var()` qui n'existe pas. */
.carte-annonce {
  /* 296 §7 — le même gabarit que le refus : une information. */
  margin: 0 0 14px; padding: 13px 16px;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--marine);
  border-radius: 12px; font-size: 14px;
  max-width: var(--carte-max);
}
.carte-annonce-titre {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--marine); margin-bottom: 6px;
}
.carte-annonce-texte { color: var(--encre, #16213e); line-height: 1.45; }

/* ⛔ 282 §4 — le bélier : un profil par ligne, sa raison, sa disponibilité. */
.belier-profil {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--trait);
  overflow-wrap: anywhere;
}
.belier-raison { color: var(--encre, #16213e); line-height: 1.4; }
.belier-dispo { color: var(--texte-doux); font-size: 12.5px; }
.belier-mail { margin-top: 4px; }
/* 283 §3 — une ligne par compte, un bouton qui pré-remplit la note. */
.techno-ligne + .techno-ligne { margin-top: 10px; }
.techno-noter { margin-top: 4px; }
/* ⛔ 282 §5 — la source d'un numéro, sous les coordonnées. */
.source-coordonnees { color: var(--texte-doux); font-size: 12.5px; }
/* 291 §2 — le grand compte partagé par zone. */
.suivi-par { color: var(--texte-doux); font-size: 12.5px; margin-top: 2px; }
.zones-compte { display: grid; gap: 4px; }
.zone-ligne { overflow-wrap: anywhere; }

/* Les pièces jointes en attente — AU-DESSUS de la barre, jamais dans le fil.
   ⚠️ Ce ne sont pas des messages : les mettre dans la conversation laisserait
   croire qu'elles ont déjà été envoyées. */
/* ⛔ Au-DESSUS de la barre depuis l'étape 198, plus dedans : la largeur de
   `#champ` ne dépend plus de ce qu'on dépose. `max-width` et `margin` la
   calent sur `.saisie`, sinon la ligne des pièces flotterait à gauche
   pendant que la barre reste centrée. */
.pieces {
  display: flex; flex-wrap: wrap; gap: 8px;
  max-width: 760px; margin: 0 auto;
  padding: 0 10px 8px;
}
.pieces:empty { padding: 0; margin: 0 auto; }
.piece {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--bleu-tres-pale, #eef1f8); border: 1px solid var(--trait, #dfe4ef);
  border-radius: 8px; padding: 5px 8px 5px 10px; font-size: 13px;
  color: var(--encre, #12203f); max-width: 100%;
}
.piece-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
             max-width: 220px; }
.piece-poids { color: var(--doux, #4a5878); font-size: 12px; }
.piece-retirer { border: 0; background: transparent; font-size: 16px; line-height: 1;
                 color: var(--doux, #4a5878); padding: 0 2px; }
.piece-retirer:hover { color: var(--ambre-encre, #A85513); }
.piece-attente { opacity: .6; }
.pieces-envoyees { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px;
                   justify-content: flex-end; }
.pieces-envoyees .piece { font-size: 12px; padding: 3px 8px; }
/* La cible du glisser-déposer : visible, sobre, et sur toute la conversation.
   Un rectangle qui n'apparaît qu'au survol du champ se rate une fois sur deux. */
.depot-ouvert { outline: 2px dashed var(--bleu, #002687); outline-offset: -6px; }
.micro-bt { border: 0; background: transparent; font-size: 22px; line-height: 1;
            color: var(--doux, #4a5878); padding: 0 6px; }
.micro-bt:hover { color: var(--bleu, #002687); }

/* ⚠️ **Un corps de mail garde ses paragraphes** (étape 129). Sans cette
   règle, un `<dd>` replie tous les sauts de ligne : le mail proposé
   s'affichait d'un seul tenant, et le commercial validait un pavé alors que
   ce qui partait chez Microsoft, lui, avait bien ses paragraphes.
   ⛔ C'est du RENDU, jamais de la donnée : la chaîne déposée est identique. */
.apercu dd.texte-long {
  white-space: pre-wrap;
  line-height: 1.5;
}

/* ── « Activer la voix » (étape 135) ──────────────────────────────
   Discret : c'est une information, pas une alarme. Mais cliquable, et assez
   contrasté pour se lire — un indicateur qu'on ne voit pas ne vaut pas mieux
   que le silence qu'il explique. */
.voix-a-armer {
  display: flex; align-items: center; gap: 6px;
  margin: 6px auto 0; padding: 5px 12px;
  border: 1px solid var(--bordure); border-radius: 999px;
  background: var(--fond-doux); color: var(--texte-doux);
  font: inherit; font-size: 13px; cursor: pointer;
}
.voix-a-armer:hover { background: #fff; color: var(--bleu); }
.voix-a-armer svg { width: 15px; height: 15px; flex: 0 0 auto; }

/* La jauge de l'essai de micro (étape 156). ⚠️ Elle doit BOUGER : c'est tout
   son intérêt — sans elle, on ne saurait jamais si un vide est un silence ou
   une panne. */
.barre-micro {
  height: 14px; background: var(--bleu-tres-pale, #eef1f8);
  border-radius: 7px; overflow: hidden; margin: 8px 0 6px;
}
.barre-micro > div {
  height: 100%; width: 0; background: var(--bleu, #002687);
  transition: width .06s linear;
}
.barre-micro.muet > div { background: var(--ambre, #A85513); }

/* ⛔ La liste des mails — construite par le code, jamais par la prose du
   modèle (étape 157). Même famille visuelle que la carte d'aperçu : ce qui
   vient des données a sa forme, ce que Jarvis en dit a la sienne. */
.mails {
  margin: 0 0 14px;
  padding: 13px 16px;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--marine);
  border-radius: 12px;
  background: var(--surface);
  max-width: var(--carte-max);          /* le gabarit des cartes (296 §7) */
}
.mails-titre { font-weight: 700; margin-bottom: .5rem; color: var(--marine); }
/* ⛔ 296 §7 — une ligne à UN seul élément (un document, une ligne d'import)
   tombait dans la première colonne de la grille, étroite : presque un mot
   par ligne. Elle prend toute la largeur. */
.mails-ligne:has(> :only-child),
.mails-ligne.document-ligne { grid-template-columns: 1fr; }
.mails-ligne {
  display: grid;
  grid-template-columns: minmax(6rem, 11rem) 6.5rem 1fr;
  gap: .5rem;
  padding: .22rem 0;
  border-top: 1px solid var(--trait);
  align-items: baseline;
}
.mails-qui { font-weight: 600; overflow-wrap: anywhere; }
.mails-quand { color: var(--doux); font-variant-numeric: tabular-nums; }
.mails-objet { overflow-wrap: anywhere; }
.mails-vide { color: var(--doux); padding: .3rem 0; }
/* ⛔ Étape 270 §4 — le compte et son périmètre, au-dessus de la liste. Il
   n'est pas discret : c'est la phrase qui dit si le compte est complet. */
.mails-compte {
  margin: -.2rem 0 .5rem;
  padding: .35rem .6rem;
  background: var(--bleu-tres-pale);
  border-radius: var(--rayon);
  font-size: .92em;
}
.mails-note { margin-top: .45rem; font-size: .85em; color: var(--doux); }

/* ══ ⛔ 277 §3 — LE TABLEAU DES PAIRES BM/COMPTE/JOUR ══════════════════════
   ⛔ La PHRASE vient de la base et elle est en tête : c'est elle qui porte le
   total et la raison du silence, et c'est elle qu'on lit d'abord. Le tableau
   réutilise `.tableau`, donc le marquage par colonne de la 226 §2 le prend
   en charge sous 640 px — aucun débordement horizontal à fabriquer. */
.paires-phrase {
  margin: .2rem 0 .6rem;
  padding: .45rem .6rem;
  border-left: 3px solid var(--ambre, #A85513);
  background: var(--bleu-tres-pale);
  border-radius: var(--rayon);
}
.paires-sans { margin-top: .7rem; }
.paires-rdv .tableau { margin: 0; }

@media (max-width: 640px) {
  /* Sur téléphone, trois colonnes ne tiennent pas : on empile, et l'objet
     garde toute la largeur — c'est lui qu'on lit. */
  .mails-ligne { grid-template-columns: 1fr; gap: .1rem; }
  .mails-quand { font-size: .85em; }
}

/* Les documents d'un compte (étape 158) — ils existaient, personne ne les
   voyait. ⚠️ Variables prises dans la charte : `tests_conventions` refuse
   depuis l'étape 157 toute variable employée sans être définie. */
.document {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .15rem .6rem;
  padding: .35rem 0;
  border-top: 1px solid var(--trait);
  align-items: baseline;
}
.document-nom {
  justify-self: start;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--bleu);
  text-decoration: underline;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.document-nom[disabled] { color: var(--doux); text-decoration: none; cursor: default; }
.document-detail { color: var(--doux); font-size: .88em; grid-column: 1 / -1; }
.document-perdu { color: #A85513; font-size: .88em; grid-column: 1 / -1; }
.document-ligne .document-nom { font-weight: 600; }
/* La phrase qui dit ce qu'on peut faire d'un fichier déposé. */
.piece-astuce {
  width: 100%;
  margin-top: .35rem;
  color: var(--doux);
  font-size: .88em;
  line-height: 1.35;
}

/* Les tickets (étape 159) — côté commercial, puis côté support. */
.ticket, .ticket-support {
  padding: .5rem .65rem;
  margin: .35rem 0;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--doux);
  border-radius: 8px;
  background: var(--surface);
}
.ticket.traite, .ticket-support.traite { border-left-color: #1E7A46; }
.ticket.nouveau, .ticket-support.nouveau { border-left-color: var(--bleu); }
.ticket-etat, .ticket-quand { color: var(--doux); font-size: .85em; }
.ticket-etat { font-weight: 600; margin-right: .4rem; }
.ticket-texte { display: block; margin: .15rem 0; overflow-wrap: anywhere; }
.ticket-reponse {
  margin-top: .3rem;
  padding: .35rem .5rem;
  background: var(--fond);
  border-radius: 6px;
}
.ticket-tete { font-weight: 600; margin-bottom: .2rem; }
.ticket-contexte {
  margin-top: .3rem;
  color: var(--doux);
  font-size: .84em;
  overflow-wrap: anywhere;
}
.ticket-echange {
  margin-top: .35rem;
  padding: .35rem .5rem;
  background: var(--fond);
  border-radius: 6px;
  font-size: .85em;
  white-space: pre-wrap;
  max-height: 9rem;
  overflow: auto;
}
.ticket-actions { display: flex; gap: .4rem; margin-top: .45rem; }
.ticket-actions input { flex: 1; min-width: 0; }

/* La mention unique des capacités (étape 159) — en tête du fil, une fois. */
.mention-capacites {
  position: relative;
  margin: 0 0 .8rem;
  padding: .6rem 2rem .6rem .75rem;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--bleu);
  border-radius: 8px;
  background: var(--surface);
  line-height: 1.4;
}
.mention-capacites .piece-retirer { position: absolute; top: .2rem; right: .35rem; }

/* ══════════════════════════════════════════════════════════════════════
   LES DEMANDES DE LA DIRECTION — étape 160
   ══════════════════════════════════════════════════════════════════════

   ⛔ **LA CARTE NE DOIT RESSEMBLER À AUCUNE BULLE DE JARVIS.** C'est la règle
   du brief tenue par le style : *le message s'affiche comme venant de son
   auteur, jamais comme une initiative de Jarvis.* D'où un filet ambre à
   gauche — la couleur des repères, jamais celle du dialogue —, un fond plat,
   et aucun des arrondis asymétriques des bulles.

   ⚠️ L'ambre qui porte du texte est `--ambre-encre` (5,28:1), jamais
   `--ambre-vif` (3,00:1) : ce dernier est réservé aux filets, qui ne portent
   aucune lettre (étape 37). */
.demandes-recues { display: flex; flex-direction: column; gap: .5rem; }
.demandes-recues:not(:empty) { padding: .75rem 1rem 0; }

.demande {
  border-left: 3px solid var(--ambre-vif);
  background: var(--fond-doux);
  border-radius: 0 var(--rayon) var(--rayon) 0;
  padding: .6rem .85rem;
}
.demande.neuve { background: var(--ambre-pale); }

.demande-tete {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
  margin-bottom: .3rem;
}
.demande-de { font-weight: 600; color: var(--ambre-encre); }
.demande-quand { font-size: .8rem; color: var(--texte-doux); }
.demande-neuve {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ambre-encre); border: 1px solid var(--ambre-trait);
  border-radius: 999px; padding: 0 .4rem;
}
.demande-vues { font-size: .8rem; color: var(--texte-doux); }

/* ⛔ `pre-wrap` : le texte est rendu tel qu'il a été tapé, retours à la ligne
   compris. Le reformater serait déjà le réécrire. */
.demande-texte { white-space: pre-wrap; line-height: 1.45; }

.demande-actions { display: flex; gap: .75rem; margin-top: .45rem; }
/* 297 §4 — les propositions de candidats : trois gestes qui passent à la
   ligne à 390 px, la raison d'un écart sur une ligne, et la pastille « en
   attente » en minuscules (l'emphase est en gras, jamais en capitales). */
.proposition-candidat .demande-actions,
.proposition-suggestion .demande-actions { flex-wrap: wrap; }
.proposition-candidat .demande-neuve { text-transform: none; letter-spacing: 0; }
.proposition-raison { display: flex; gap: .5rem; width: 100%; }
.proposition-raison-champ {
  flex: 1; min-width: 0; font: inherit; padding: .3rem .5rem;
  border: 1px solid var(--trait); border-radius: 6px;
}
.proposition-retour { border-left-color: var(--marine); }
.proposition-suggestion { border-left-color: var(--marine); }
.proposition-suggestion .demande-de,
.proposition-retour .demande-de { color: var(--marine); }

.demande-reponse {
  margin-top: .5rem; padding-left: .6rem;
  border-left: 2px solid var(--trait);
  display: flex; flex-direction: column;
}
.demande-reponse-titre {
  font-size: .78rem; font-weight: 600; color: var(--texte-doux);
}
.demande-reponse-texte { white-space: pre-wrap; }

.demande-repondre {
  margin-top: .55rem; display: flex; flex-direction: column; gap: .4rem;
}
.demande-repondre textarea {
  width: 100%; font: inherit; padding: .45rem .6rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte); resize: vertical;
}

/* ⛔ **L'écran de support porte DEUX sections distinctes**, et elles doivent
   se voir comme telles : le titre des micros a été lu comme celui des
   tickets tant qu'ils se touchaient. */
.bloc-support { display: block; margin-bottom: 1.5rem; }
.bloc-support + .bloc-support {
  border-top: 1px solid var(--bordure); padding-top: 1.25rem;
}

/* ── Côté direction ──────────────────────────────────────────────── */
.bloc-demandes {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: 1rem; margin-bottom: 1rem;
}
/* ⛔ 289 §1 — le champ « Ce qui ne va pas » tenait à côté de son étiquette,
   étroit, sur la capture 11 du guide des TA. L'étiquette au-dessus, le champ
   sur toute la largeur. */
.etiquette { display: block; margin-top: .5rem; }
#ticket-texte {
  display: block; width: 100%; min-height: 5em; font: inherit;
  padding: .5rem .65rem; margin-top: .3rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: var(--fond); color: var(--texte); resize: vertical;
}
.bloc-demandes textarea {
  width: 100%; font: inherit; padding: .5rem .65rem; margin-top: .5rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: var(--fond); color: var(--texte); resize: vertical;
}
.demande-barre {
  display: flex; align-items: center; gap: .5rem; margin-top: .5rem;
  flex-wrap: wrap;
}
.demande-posee {
  border-left: 3px solid var(--trait); padding: .5rem .75rem;
  margin-top: .6rem; background: var(--fond-doux);
  border-radius: 0 var(--rayon) var(--rayon) 0;
}
/* ⛔ Retirée, jamais effacée : elle reste lisible chez son auteur, en retrait. */
.demande-posee.retiree { opacity: .6; }

/* Étape 178 : un chiffre qui porte sa réserve, dépliable d'un clic. */
details.reserve { margin: .35rem 0; }
details.reserve > summary { cursor: pointer; font-weight: 600; }
details.reserve-alerte > summary { color: var(--rouge); }
details.reserve .reserve-texte { margin: .3rem 0 .2rem 1.1rem; font-size: .92em; }

/* ══ Le chiffre qui s'ouvre — étape 211 §3 ══════════════════════════════ */
/* ⛔ Une cellule ouvrable se VOIT : sans marque, personne ne clique. Et seules
   celles que `detail_direction` sait ouvrir la portent — un curseur qui invite
   à cliquer sur ce qui ne s'ouvre pas est un bouton qui ment. */
.tableau td.ouvrable {
  cursor: pointer;
  text-decoration: underline dotted var(--bleu, #002687);
  text-underline-offset: 3px;
}
.tableau td.ouvrable:hover,
.tableau td.ouvrable:focus-visible {
  background: var(--bleu-tres-pale, #eef1f8);
  outline: none;
}
/* ⛔ **LES TROIS BOUTONS DE CIVILITÉ — étape 256 §2.** ⛔ Aucun n'est coché
   d'avance, et le style ne doit en avantager aucun : deux boutons identiques,
   côte à côte, et « Je ne sais pas » en lien discret — un choix à part
   entière, jamais un bouton qu'on pousse. */
.civilite-choix { display: flex; gap: 8px; align-items: center;
                  flex-wrap: wrap; }
.civilite-bouton {
  border: 1px solid var(--bleu);
  background: var(--surface);
  color: var(--bleu);
  border-radius: var(--rayon);
  padding: 5px 12px;
  font: inherit;
  cursor: pointer;
}
.civilite-bouton:hover, .civilite-bouton:focus-visible {
  background: var(--bleu-tres-pale);
  outline: none;
}
.civilite-bouton[disabled] { opacity: 0.45; cursor: default; }
/* ⛔ 297 §6.10 — une carte figée grisait AUSSI le bouton choisi : « Madame »
   devenait aussi pâle que les deux autres, et on ne voyait plus ce qui avait
   été choisi. Le choix reste plein ; seuls les autres pâlissent. */
.civilite-bouton.choisi[disabled] { opacity: 1; }
/* ⛔ **LE BOUTON CHOISI PASSE EN BLEU NORGAY — étape 270 §2.** Un clic
   SÉLECTIONNE, il n'envoie rien : sans cette marque, on ne saurait pas ce
   qu'on a choisi, et le seul retour serait le message parti tout seul — très
   exactement le défaut du 25/09 au matin.
   ⚠️ Le contraste est celui du bouton principal, déjà mesuré (étape 37) :
   blanc sur #002687. */
.civilite-bouton.choisi {
  background: var(--bleu);
  color: #FFFFFF;
  font-weight: 600;
}
.civilite-bouton.choisi:hover, .civilite-bouton.choisi:focus-visible {
  background: var(--bleu);
}
.civilite-posee { color: var(--vert); font-weight: 600; }
/* ⛔ Étape 263 §6 — la même question, DANS la carte d'aperçu. Le style
   du bouton est celui de l'écran des civilités : deux allures pour un
   même geste se liraient comme deux gestes. */
.civilite-demande {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 10px;
}

/* ⛔ **L'APERÇU GROUPÉ — 273 §1.** Une ligne par personne, et on doit voir
   d'un coup d'oeil COMBIEN il y en a : c'est le nombre que le bouton annonce,
   et celui qui sera écrit.
   ⚠️ Chaque ligne est un bloc séparé par un filet, jamais par un espace seul :
   à cinq lignes sur 390 px, un espace ne sépare plus rien et deux personnes se
   lisent comme une. */
.groupe-phrase { font-weight: 600; margin: 0 0 10px; }
.groupe-lignes { display: flex; flex-direction: column; gap: 0; }
.groupe-ligne {
  border-top: 1px solid var(--ambre-trait);
  padding: 10px 0 12px;
}
.groupe-ligne:first-child { border-top: none; padding-top: 0; }
.groupe-tete { display: flex; flex-wrap: wrap; gap: 4px 10px;
               align-items: baseline; }
.groupe-nom { font-weight: 600; }
.groupe-suite { color: var(--texte-doux); font-size: 13px; }
/* ⛔ « Retirer » est un LIEN, pas un bouton : il n'écrit rien et il ne
   confirme rien — il repropose. Lui donner l'allure d'un bouton d'action le
   ferait lire comme une suppression. */
.groupe-retirer { margin-top: 8px; font-size: 13px; }

/* ⛔ 290 §5 — la liste des recherches Kaspr du tiroir : une carte par
   recherche, qui se replie sans jamais déborder à 390 px. */
.kf { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.kf select { max-width: 100%; font: inherit; font-size: 13px;
             padding: 4px 6px; border: 1px solid var(--trait);
             border-radius: 8px; background: var(--surface); }
.kr-n { color: var(--texte-doux); font-size: 13px; margin: 0 0 6px; }
.kr { border-top: 1px solid var(--trait); padding: 8px 2px; }
.kr-h { display: flex; flex-wrap: wrap; gap: 2px 10px; align-items: baseline; }
.kr-d { color: var(--texte-doux); font-size: 12px; }
.kr-p { font-weight: 600; }
.kr-e { color: var(--texte-doux); font-size: 13px; }
.kr-v { display: flex; flex-wrap: wrap; gap: 2px 14px; font-size: 12px;
        margin-top: 3px; overflow-wrap: anywhere; }
.kr-s { color: var(--texte-doux); font-size: 12px; margin-top: 3px; }
.kr-fiche { margin: 4px 0 10px; }

/* ⛔ 290 §3 — les profils LinkedIn trouvés : une ligne par profil, le lien
   sous le nom, le bouton à droite (dessous, sous 640 px). */
.profil-ligne {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 12px; align-items: center;
  border-top: 1px solid var(--trait); padding: 8px 0;
}
.profil-tete { display: flex; flex-wrap: wrap; gap: 2px 10px; }
.profil-nom { font-weight: 600; }
.profil-suite { color: var(--texte-doux); font-size: 13px; }
.profil-lien { grid-column: 1; font-size: 12px; overflow-wrap: anywhere; }
.profil-choisir { grid-column: 2; grid-row: 1 / 3; }
@media (max-width: 640px) {
  .profil-ligne { grid-template-columns: 1fr; }
  .profil-choisir { grid-column: 1; grid-row: auto; justify-self: start; }
}

/* ⛔ 290 — LA CARTE KASPR : la fiche et Kaspr CÔTE À CÔTE, une case par
   champ. Sur bureau, quatre colonnes alignées ; sous 640 px, la case et le
   nom sur une ligne, les deux valeurs dessous, l'une sous l'autre : un
   « côte à côte » de 390 px qui déborde n'en est pas un (étape 226 §2). */
.kaspr-source { color: var(--texte-doux); font-size: 13px; margin: -4px 0 8px; }
.kaspr-titre { font-weight: 600; margin: 10px 0 4px; }
.kaspr-lignes { display: flex; flex-direction: column; }
.kaspr-ligne {
  display: grid;
  /* Des largeurs FIXES pour le nom et l'état : chaque ligne a sa grille, et
     des colonnes « auto » ne s'alignaient pas d'une ligne à l'autre. */
  grid-template-columns: 22px 9.5em minmax(0, 1fr) minmax(0, 1fr) 5.5em;
  gap: 4px 10px; align-items: baseline;
  border-top: 1px solid var(--ambre-trait); padding: 7px 0;
  cursor: pointer;
}
.kaspr-ligne:first-child { border-top: none; }
.kaspr-nom { font-weight: 600; }
.kaspr-avant { color: var(--texte-doux); overflow-wrap: anywhere; }
.kaspr-apres { overflow-wrap: anywhere; }
.kaspr-etat { color: var(--texte-doux); font-size: 12px; white-space: nowrap; }
.kaspr-different .kaspr-etat { color: var(--ambre-encre); }
.kaspr-identique { opacity: .7; cursor: default; }
.kaspr-regle { color: var(--texte-doux); font-size: 13px; margin-top: 8px; }
@media (max-width: 640px) {
  .kaspr-ligne { grid-template-columns: 22px 1fr auto; }
  .kaspr-avant, .kaspr-apres { grid-column: 2 / 4; }
  .kaspr-etat { grid-row: 1; grid-column: 3; }
}

/* ⛔ **« À ZÉRO CETTE SEMAINE » — étape 256 §1.** *Zéro n'est pas une place.*
   La ligne se VOIT, sinon les noms qui la suivent se lisent comme la suite
   du classement. Elle n'est pas un titre de section : c'est une frontière
   dans un tableau, et elle en garde la largeur. */
.tableau tr.separateur td {
  background: var(--fond-doux);
  font-size: 0.86rem;
  font-variant: small-caps;
  letter-spacing: 0.04em;
  color: var(--texte-doux);
  padding-top: 10px;
  padding-bottom: 6px;
  border-top: 2px solid var(--trait);
}

/* ⛔ **LA BARRE DE SEMAINE DES TROIS CURSEURS — étape 251, famille 2.**
   Elle porte les deux flèches et la semaine regardée. Sur téléphone elle
   passe en colonne : trois éléments sur une rangée de 390 px déborderaient,
   et *un débordement horizontal n'est jamais acceptable* (étape 226). */
.barre-semaine {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}
.semaine-dite { font-weight: 600; }
/* ⛔ Une flèche désactivée le DIT : sans marque, on clique et rien ne se
   passe — et on croit l'écran cassé. */
.barre-semaine .lien[disabled] {
  opacity: 0.45;
  cursor: default;
  text-decoration: none;
}
@media (max-width: 640px) {
  .barre-semaine { flex-direction: column; align-items: flex-start; }
}

.direction-detail {
  margin-top: 14px;
  padding: 12px 14px;
  border-left: 3px solid var(--bleu, #002687);
  background: var(--bleu-tres-pale, #eef1f8);
  border-radius: 6px;
}
.detail-entete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.detail-entete h3 { margin: 0; font-size: 1rem; }
/* ⚠️ « Jamais mesuré » ne se lit pas comme le reste : un zéro qui ne dit pas
   s'il est mesuré ou manquant est un mensonge poli. */
.legende.jamais-mesure {
  color: #A85513;
  font-weight: 600;
}

/* ── Les dormants (étape 222 §7) ────────────────────────────────────────────
   ⛔ Ce bloc MONTRE, il ne propose rien : il n'a donc ni la couleur ni le
   relief de la campagne, qui, elle, invite à agir. Un fond neutre, un filet
   ambre pour le distinguer de la liste, et rien qui crie. */
/* Les échanges de comptes (étape 261). ⛔ Filet ambre et fond plat, comme
   les demandes de direction : la forme dit que ce n'est pas Jarvis qui
   parle — aucun des arrondis d'une bulle. */
.echanges { display: flex; flex-direction: column; gap: .5rem;
            margin: 0 0 1rem; }
/* ⛔ **ELLE S'APPELAIT `.echange`, ET UNE AUTRE RÈGLE DU MÊME NOM LUI
   POSAIT `display: flex` EN RANGÉE** (l. 1121, les échanges d'une fiche
   compte, qui n'ont rien à voir). Les cinq blocs de la carte se mettaient
   donc côte à côte et s'écrasaient : 63 px de haut, cinq blocs entre y=103
   et y=111 — c'est « la ligne minuscule » du relevé M3 (étape 264 §6).
   *Deux notions sous un même mot se confondent tôt ou tard* (étape 83). */
.demande-compte { border-left: 3px solid var(--ambre);
                  background: var(--fond-doux); padding: .6rem .8rem; }
.echange-tete { display: flex; gap: .6rem; align-items: baseline;
                flex-wrap: wrap; }
.echange-de { font-weight: 600; }
.echange-quand { color: var(--tres-doux); font-size: .85em; }
.echange-quoi { margin-top: .2rem; }
.echange-suit { color: var(--doux); font-size: .9em; margin-top: .15rem; }
.echange-motif { margin-top: .4rem; display: flex; flex-direction: column;
                 gap: .1rem; }
.echange-motif-titre { color: var(--tres-doux); font-size: .8em;
                       text-transform: uppercase; letter-spacing: .04em; }
.echange-motif-texte { font-style: italic; }
.echange-actions { display: flex; gap: .8rem; margin-top: .5rem;
                   flex-wrap: wrap; }
.echange-reponse { font-weight: 600; }
.besoins-reperes summary { cursor: pointer; font-weight: 600; }
.besoin-repere { margin-top: .6rem; padding-top: .5rem;
                 border-top: 1px solid var(--trait); }
.echange-attente { color: var(--doux); font-size: .9em; padding: .2rem .8rem; }
.echange-attente-ligne { margin: .15rem 0; }
.vignette-bas { margin-top: .5rem; }

.dormants {
  margin: 0 0 18px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--ambre-vif);
  border-radius: var(--rayon);
}
.dormants-titre {
  margin: 0 0 4px;
  font-size: 15px;
  color: var(--encre);
}
.dormants-phrase {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--doux);
}
.dormants-liste { display: flex; flex-direction: column; gap: 8px; }
.dormant {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 8px 10px;
  background: var(--fond);
  border-radius: 10px;
  font-size: 13px;
}
.dormant-qui { font-weight: 600; color: var(--encre); }
.dormant-ou { color: var(--marine-clair); }
.dormant-fonction, .dormant-activite { color: var(--tres-doux); font-size: 12px; }
/* ⛔ Une société cessée est MARQUÉE, jamais tue — et jamais présentée comme
   une occasion : elle est en fin de liste, et elle le dit. */
.dormant-cesse { background: var(--rouge-pale); }
.dormant-cessee { color: var(--rouge); font-size: 12px; font-weight: 600; }
.dormant-muet { color: var(--tres-doux); font-size: 12px; font-style: italic; }

/* ── Les domaines à décider (étape 224 §8) ────────────────────────────
   Même forme que les dormants : c'est le même genre de bloc — il MONTRE ce
   qui attend une décision humaine, il ne réclame pas. Deux formes qui se
   ressemblent pour deux choses qui se ressemblent. */
.domaines {
  margin: 0 0 18px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--ambre-vif);
  border-radius: var(--rayon);
}
.domaines-titre { margin: 0 0 4px; font-size: 15px; color: var(--encre); }
.domaines-phrase {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--doux);
}
.domaines-liste { display: flex; flex-direction: column; gap: 8px; }
.domaine {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 8px 10px;
  background: var(--fond);
  border-radius: 10px;
  font-size: 13px;
}
.domaine-nom { font-weight: 600; color: var(--encre); }
.domaine-volume { color: var(--marine-clair); }
/* ⛔ Une adresse personnelle est MARQUÉE, jamais cachée — et rangée après le
   reste plutôt que retirée : taire l'existence est un mensonge (étape 108). */
.domaine-perso { opacity: 0.72; }
.domaine-muet { color: var(--tres-doux); font-size: 12px; font-style: italic; }
.domaine-gestes { display: flex; gap: 6px; margin-left: auto; }

/* ══ LE FILTRE DES VIGNETTES (étape 227 §4) ═══════════════════════════
   ⛔ Mesuré : 63 % des vignettes sont ex æquo en tête de leur liste, donc
   rangées par ordre alphabétique, et sept commerciaux sur onze doivent
   défiler plus de la moitié de leur liste pour retrouver le compte qu'ils
   viennent de travailler. Le tri ne bouge pas — c'est leur ordre de travail —
   mais chercher devient un geste. */
.filtre-zone { margin: 0 0 12px; }

.filtre-champ {
  width: 100%;
  max-width: 420px;
  padding: 9px 12px;
  font: inherit;
  color: var(--encre);
  background: var(--surface);
  border: 1px solid var(--trait);
  border-radius: 10px;
}

.filtre-champ:focus {
  outline: 2px solid var(--marine-clair);
  outline-offset: 1px;
  border-color: var(--marine-clair);
}

#filtre-comptes-note { margin: 6px 0 0; }

/* ⛔ L'ALARME DES TICKETS (étape 236 §1) — elle passe DEVANT tout l'écran
   de support, parce qu'un utilisateur qui cesse de signaler ne revient pas.
   ⚠️ Les jetons employés sont ceux de la charte (contrastes mesurés à
   l'étape 37) : aucune couleur neuve, aucune variable fantôme. */
.alarme-tickets {
  background: var(--ambre-pale);
  border-left: 4px solid var(--ambre-vif);
  border-radius: 6px;
  padding: 0.9rem 1.1rem;
}
.alarme-tickets h2 { color: var(--ambre-encre); margin: 0 0 0.6rem; }
.alarme-ligne {
  color: var(--ambre-encre);
  font-weight: 600;
  padding: 0.15rem 0;
}

/* ══════════════════════════════════════════════════════════════════════
   DEUX CLASSES QUI N'EXISTAIENT PAS — étape 242 §2.5
   ══════════════════════════════════════════════════════════════════════

   ⛔ `.bouton` et `.sr-only` étaient employées dans le HTML et n'avaient
   AUCUNE règle. Conséquences, sur l'écran du président et lui seul :
   le bouton « Envoyer » de sa demande avait l'aspect brut du navigateur,
   seul de tout le produit ; et « Votre demande », écrit pour être lu par
   un lecteur d'écran, s'affichait en clair.

   ⚠️ C'est la famille des variables fantômes de l'étape 157, pour les
   CLASSES cette fois : aucune erreur, aucune console, la règle est
   simplement absente. Seize classes sur deux cent quatre-vingt-une sont
   dans ce cas ; ces deux-là sont celles qui se voient. Le contrôle, avec
   sa morsure, vient cette semaine. */
.bouton {
  border: 1px solid var(--bleu);
  border-radius: 8px;
  background: var(--bleu);
  color: #fff;
  font-weight: 600;
  font-size: 14px;
  padding: 9px 16px;
}
.bouton:hover { filter: brightness(1.12); }
.bouton:disabled, .bouton[aria-disabled="true"] { opacity: 0.55; }

/* ⛔ **UN SECOND BOUTON, PARCE QU'UNE LISTE DE DOUZE N'EST PAS UNE ACTION**
   (étape 275 §1.3). Douze boutons pleins l'un sous l'autre se lisent comme
   douze alarmes ; ici ce sont douze choix, dont on n'en fera qu'un à la fois.
   Le bleu reste pour ce qui conclut. */
.bouton-secondaire {
  border: 1px solid var(--bordure);
  border-radius: 8px;
  background: var(--surface);
  color: var(--bleu);
  font-weight: 600;
  font-size: 14px;
  padding: 7px 13px;
}
.bouton-secondaire:hover { background: var(--marine-pale); }
.bouton-secondaire:disabled { opacity: 0.55; }

/* ── Les accès, dans le support (étape 275 §1.3) ─────────────────── */
.acces-liste { list-style: none; margin: .5rem 0 0; padding: 0; }
.acces-liste > li {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .55rem 0; border-top: 1px solid var(--bordure);
}
.acces-qui { flex: 1 1 14rem; min-width: 0; }
.acces-erreur { color: var(--rouge); margin: .35rem 0 0; flex-basis: 100%; }
/* ── La fiche candidat : la marge et les expériences (275 §3) ───── */
/* ⛔ **LA MARGE SE VOIT, ET ELLE N'EST PAS COLORIÉE** : aucun seuil n'a été
   donné, et un chiffre colorié par un seuil inventé est un jugement. */
.fiche-marge {
  display: flex; align-items: baseline; gap: .6rem; margin-top: .65rem;
  padding: .5rem .7rem; border-left: 3px solid var(--trait);
  background: var(--fond-doux); border-radius: 0 var(--rayon) var(--rayon) 0;
}
.fiche-marge-titre { font-weight: 600; }
.fiche-marge-valeur { font-size: 15px; }

/* ⛔ **UNE LIGNE PAR POSTE** : un résumé se lit, une expérience se compare. */
.fiche-exp {
  padding: .55rem 0; border-top: 1px solid var(--bordure);
}
.fiche-exp:first-of-type { border-top: 0; }
.fiche-exp-tete {
  display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap;
}
.fiche-exp-poste { font-weight: 600; }
.fiche-exp-societe { color: var(--texte-doux); }
.fiche-exp-bas { font-size: 13px; color: var(--texte-doux); }

/* ⛔ « Afficher 40 de plus » et ce qui reste (275 §3). */
.vivier-reste {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  margin-top: 1rem; padding-top: .75rem;
  border-top: 1px solid var(--bordure);
}

/* ⛔ Un compte de test se voit dans la liste (0210), et il se DIT. */
.acces-test {
  font-size: 12px; font-weight: 600; color: var(--ambre-encre);
  background: var(--ambre-pale); border: 1px solid var(--ambre-trait);
  border-radius: 999px; padding: .1rem .5rem;
}

/* ⛔ **LE LIEN NE S'AFFICHE QU'UNE FOIS, DONC IL SE VOIT.** Un secret qu'on
   ne peut pas relire doit être impossible à manquer dans l'écran. */
.acces-lien {
  flex-basis: 100%;
  border: 1px solid var(--ambre-trait);
  border-left: 3px solid var(--ambre-vif);
  border-radius: 0 var(--rayon) var(--rayon) 0;
  background: var(--ambre-pale);
  padding: .75rem .9rem; margin-top: .5rem;
}
.acces-lien-titre { font-weight: 600; margin: 0 0 .5rem; }
/* ⚠️ Chasse fixe et sélection entière : un lien se copie, il ne se relit
   pas à l'œil — et une lettre perdue en le recopiant à la main ne se voit
   qu'au moment où la personne clique. */
.acces-lien-champ {
  width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; padding: .45rem .6rem; margin-bottom: .5rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: var(--surface); color: var(--texte);
}
.acces-lien-note {
  margin: .5rem 0 0; font-size: 13px; color: var(--ambre-encre);
}

/* ⛔ Lu par un lecteur d'écran, jamais par l'œil. La forme est celle qui
   survit aux navigateurs : un rectangle d'un pixel, découpé, hors flux —
   `display: none` retirerait l'élément de l'arbre d'accessibilité, donc
   le rendrait muet pour ceux à qui il est destiné. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ══ LE BANDEAU DU PARTAGE — étape 249 §1 ═══════════════════════════════
   ⛔ **D'UNE AUTRE COULEUR QUE TOUT LE RESTE.** Le produit est bleu ; le
   Jarvis de quelqu'un d'autre est ambre. *On ne doit jamais se tromper de
   Jarvis en écrivant* — et une pastille discrète ne suffit pas, on écrit en
   regardant son clavier.
   ⚠️ `--ambre-encre` sur `--ambre-pale` : 6,0:1, mesuré (étape 37). L'ambre
   vif ne porte jamais de texte. */
.bandeau-partage {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem;
  padding: .55rem 1rem;
  background: var(--ambre-pale);
  color: var(--ambre-encre);
  border-bottom: 3px solid var(--ambre-vif);
  font-size: .92rem;
}
.bandeau-partage .partage-note { flex: 1 1 18rem; }
.bandeau-partage button { color: var(--ambre-encre); font-weight: 600; }

/* ⛔ 268 §5.1 — les gestes de partage d'une fiche. Aucun n'écrit : ils
   pré-remplissent la phrase du geste et basculent sur le chat. */
.partage-compte { margin-bottom: .75rem; }
.gestes-partage {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: .4rem;
  font-size: .9rem;
}

/* ⛔ 268 §5.3 — qui a noté cet échange. Discret : c'est un repère, pas le
   sujet de la ligne. */
.echange-auteur {
  margin-left: .5rem;
  color: var(--texte-doux);
  font-size: .82rem;
  white-space: nowrap;
}

/* ⛔ Et la trace est portée par TOUTE la page, pas par le seul bandeau : un
   bandeau se fait oublier dès qu'on défile. */
body.en-partage .app { box-shadow: inset 0 0 0 3px var(--ambre-vif); }

.partage-ligne { margin: .35rem 0; }
.partage-ligne button { margin-left: .5rem; }


/* ── ⛔ LES DEUX CARTES DE L'AGENDA (étape 262 §2) ─────────────────────
   Le même filet ambre que les demandes de direction : elles ne sont PAS des
   bulles, parce que ce n'est pas Jarvis qui parle — c'est une question posée
   par l'écran sur ce que l'agenda montre. */
.cartes-agenda {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  margin: 0 0 1rem;
}
.cartes-agenda[hidden] { display: none; }
.carte-agenda {
  border-left: 3px solid var(--ambre);
  background: var(--fond-doux);
  padding: .6rem .8rem;
}
.carte-agenda-titre { font-weight: 600; }
.carte-agenda-quoi { color: var(--doux); font-size: .9em; margin-top: .2rem; }
.carte-agenda-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .5rem;
}
.carte-agenda-liste {
  margin: .35rem 0 0 1.1rem;
  padding: 0;
  font-size: .9em;
  overflow-wrap: anywhere;
}
.carte-agenda-reste {
  margin-top: .35rem;
  font-size: .8em;
  color: var(--tres-doux);
}

/* ══ ÉCRAN DE DIRECTION V2 — étape 263 §4 ══
   ⛔ Porté depuis `maquettes/maquette-direction-v2.html` par
   `scripts/brancher_direction_v2_css_263.py` — jamais retapé.
   ⛔ TOUT est préfixé `.dir2` : la maquette emploie des noms
   génériques (`.row`, `.panel`, `.btn`, `table`) qui existent
   déjà ailleurs. *Une feuille qui déborde de son écran est un
   défaut qu'on ne voit que chez quelqu'un d'autre.* ══ */
/* ⛔ 296 §6 — UNE SEULE CHARTE. La direction portait la sienne : un autre
   bleu, un autre orange, un autre vert, d'autres arrondis et d'autres
   ombres, d'où la moitié des écarts relevés d'un écran à l'autre. Elle
   garde ses NOMS de variables (toute sa feuille les lit), mais leurs
   VALEURS viennent de `:root`, et nulle part ailleurs. */
.dir2 {
  color-scheme: light;
  --navy: var(--marine);
  --navy-2: var(--marine-clair);
  --navy-soft: var(--marine-pale);
  --navy-line: var(--marine-trait);
  --ink: var(--encre);
  --ink-2: var(--encre);
  --muted: var(--doux);
  --line: var(--trait);
  --bg: var(--fond);
  --card: var(--surface);
  --orange: var(--ambre);
  --orange-soft: var(--ambre-pale);
  --green: var(--vert);
  --green-soft: var(--vert-pale);
  --grey-soft: var(--fond);
  --amber: var(--ambre-encre);
  --amber-soft: var(--ambre-pale);
  --radius: var(--rayon);
  --shadow: var(--ombre);
  --sans: inherit;
  font-family: inherit;
  font-size: 14px; line-height: 1.45; color: var(--ink);
}
.dir2 .av { width:34px;height:34px;border-radius:50%;display:grid;place-items:center;font-weight:700;font-size:12px;flex:none;background:var(--navy-soft);color:var(--navy) }
.dir2 .side .av { background:var(--ambre-vif);color:#fff }
.dir2 .top { padding:18px 0 10px;display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end;justify-content:space-between }
.dir2 .top h1 { margin:0;font-size:24px;letter-spacing:-.02em }
.dir2 .top .sub { color:var(--muted);font-size:13px;margin-top:2px }
.dir2 .ctrl { display:flex;gap:10px;align-items:center;flex-wrap:wrap }
.dir2 select { font:inherit;border:1px solid var(--line);background:var(--surface);border-radius:11px;padding:8px 12px;color:var(--ink) }
.dir2 .btn { border:0;background:var(--navy);color:#fff;border-radius:11px;padding:9px 14px;font-weight:600;display:inline-flex;gap:8px;align-items:center }
.dir2 .btn.ghost { background:var(--surface);color:var(--navy);border:1px solid var(--line) }
.dir2 .absent { display:flex;gap:10px;align-items:flex-start;background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--orange);border-radius:12px;padding:10px 14px;font-size:13px;color:var(--ink-2) }
.dir2 .absent b { color:var(--ink) }
.dir2 .subtabs { display:flex;gap:4px;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:4px;margin-top:14px;overflow-x:auto }
.dir2 .subtabs button { border:0;background:none;padding:9px 14px;border-radius:10px;color:var(--ink-2);font-weight:600;white-space:nowrap }
.dir2 .subtabs button.on { background:var(--navy);color:#fff }
.dir2 .tab { display:none }
.dir2 .tab.on { display:block }
.dir2 section.bloc { margin-top:24px }
.dir2 .h2 { display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:0 0 12px }
.dir2 .h2 h2 { margin:0;font-size:17px;letter-spacing:-.01em }
.dir2 .h2 span { color:var(--muted);font-size:12.5px }
.dir2 .kpis { display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px }
.dir2 .kpi { background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px 16px 14px;text-align:left;position:relative;transition:transform .12s,box-shadow .12s,border-color .12s;display:flex;flex-direction:column }
.dir2 .kpi:hover { transform:translateY(-2px);border-color:var(--navy-line);box-shadow:0 10px 28px rgba(11,42,132,.10) }
.dir2 .kpi .q { font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;padding-right:22px }
.dir2 .kpi .v { font-size:32px;font-weight:800;letter-spacing:-.03em;line-height:1.1;margin-top:6px;font-variant-numeric:tabular-nums }
.dir2 .kpi .v small { font-size:15px;font-weight:600;color:var(--muted);letter-spacing:0 }
.dir2 .kpi .l { color:var(--ink-2);font-weight:600;margin-top:2px }
/* ⛔ 296 §8 — l'évolution sous le chiffre, en mots : la couleur ne fait que
   souligner ce que la phrase dit déjà. */
.dir2 .kpi .evo { display:block;font-size:12.5px;font-weight:600;margin-top:4px;color:var(--muted) }
.dir2 .kpi .evo.monte { color:var(--green) }
.dir2 .kpi .evo.baisse { color:var(--orange) }
.dir2 .kpi.hero .evo, .dir2 .kpi.hero .evo.monte, .dir2 .kpi.hero .evo.baisse { color:rgba(255,255,255,.88) }
.dir2 .kpi.etat-monte { border-left:4px solid var(--green) }
.dir2 .kpi.etat-baisse { border-left:4px solid var(--orange) }
.dir2 .kpi.etat-stable { border-left:4px solid var(--line) }
/* ⛔ 296 §8 — l'en-tête et les cartes sur le même bord : le corps de
   l'écran de direction ne rajoute plus 20 px de retrait à gauche et à
   droite. Et le bandeau d'alerte garde la même hauteur d'un onglet à
   l'autre, quel que soit son texte. */
.dir2 #direction-corps { padding-left:0;padding-right:0 }
.dir2 .absent { min-height:3.6em;box-sizing:border-box;align-items:center }
.dir2 details.mains summary { cursor:pointer }
.dir2 details.mains[open] div { padding:2px 0 0 14px;color:var(--ink-2) }
.dir2 .atteint { display:inline-block;margin-top:3px;font-size:11.5px;font-weight:700;color:var(--green) }
/* Six vignettes : trois et trois, jamais cinq et une orpheline. */
@media (min-width: 900px) { .dir2 .kpis.six { grid-template-columns:repeat(3,1fr) } }
.dir2 .kpi .s { color:var(--muted);font-size:12.5px;margin-top:6px }
.dir2 .kpi .go { position:absolute;top:14px;right:14px;color:var(--rail-titre);font-size:16px }
.dir2 .kpi.hero { background:var(--navy);color:#fff;border-color:var(--navy) }
.dir2 .kpi.hero .q, .dir2 .kpi.hero .l, .dir2 .kpi.hero .s { color:rgba(255,255,255,.82) }
.dir2 .kpi.hero .v small { color:rgba(255,255,255,.7) }
.dir2 .kpi.hero .go { color:rgba(255,255,255,.6) }
.dir2 .split { display:flex;gap:6px;flex-wrap:wrap;margin-top:8px }
.dir2 .split span { font-size:11.5px;font-weight:600;border-radius:999px;padding:2px 8px;background:var(--grey-soft);color:var(--ink-2) }
.dir2 .kpi.hero .split span { background:rgba(255,255,255,.14);color:#fff }
.dir2 .delta { display:inline-block;font-size:11.5px;font-weight:700;border-radius:6px;padding:1px 6px;margin-left:6px;vertical-align:middle;letter-spacing:0 }
.dir2 .delta.up { background:var(--green-soft);color:var(--green) }
.dir2 .delta.down { background:var(--orange-soft);color:var(--orange) }
.dir2 .delta.eq { background:var(--grey-soft);color:var(--muted) }
.dir2 .kpi.hero .delta { background:rgba(255,255,255,.16);color:#fff }
.dir2 .bar { height:8px;background:var(--grey-soft);border-radius:8px;margin-top:10px;overflow:hidden;display:flex }
.dir2 .bar i { display:block;height:100% }
.dir2 .panel { background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px }
.dir2 .panel h3 { margin:0 0 8px;font-size:15px }
.dir2 .sig { display:grid;grid-template-columns:10px 1fr auto;gap:12px;align-items:center;width:100%;border:0;background:none;text-align:left;padding:10px 8px;border-radius:10px }
.dir2 .sig:hover { background:var(--navy-soft) }
.dir2 .sig .pt { width:10px;height:10px;border-radius:50% }
.dir2 .sig .a { font-weight:600 }
.dir2 .sig .b { font-size:12.5px;color:var(--muted) }
.dir2 .sig .c { color:var(--navy);font-weight:600;font-size:12.5px;white-space:nowrap }
.dir2 .boards { display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:12px }
.dir2 .board { background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px;display:flex;flex-direction:column }
.dir2 .board h3 { margin:0;font-size:15px }
.dir2 .board .bs { color:var(--muted);font-size:12.5px;margin:3px 0 10px }
.dir2 .seg { display:inline-flex;background:var(--bg);border:1px solid var(--line);border-radius:10px;padding:3px;margin-bottom:8px;align-self:flex-start }
.dir2 .seg button { border:0;background:none;padding:5px 10px;border-radius:7px;color:var(--ink-2);font-weight:600;font-size:12.5px }
.dir2 .seg button.on { background:var(--surface);color:var(--navy);box-shadow:0 1px 2px rgba(15,23,42,.08) }
.dir2 .rk { display:grid;grid-template-columns:24px 1fr auto;gap:10px;align-items:center;width:100%;border:0;background:none;padding:8px 6px;border-radius:10px;text-align:left }
.dir2 .rk:hover { background:var(--navy-soft) }
.dir2 .rk .n { color:var(--muted);font-weight:700;font-size:12.5px;font-variant-numeric:tabular-nums }
.dir2 .rk .val { font-weight:700;text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap }
.dir2 .rk .x { font-size:12px;color:var(--muted) }
.dir2 .grp { width:100%;border:0;background:var(--bg);border-radius:10px;padding:9px 10px;margin-top:6px;text-align:left;font-size:13px;color:var(--ink-2) }
.dir2 .grp b { color:var(--ink) }
.dir2 .grp.off { background:var(--grey-soft);color:var(--muted) }
.dir2 .vide { background:var(--navy-soft);color:var(--navy);border-radius:12px;padding:12px;font-size:13px;margin-bottom:8px }
.dir2 .team { display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:12px }
.dir2 .pc { background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:14px;text-align:left;transition:transform .12s,border-color .12s }
.dir2 .pc:hover { transform:translateY(-2px);border-color:var(--navy-line) }
.dir2 .pc .hd { display:flex;gap:10px;align-items:center }
.dir2 .pc .nm { font-weight:700 }
.dir2 .pc .rl { font-size:12px;color:var(--muted) }
.dir2 .tag { display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:600;border-radius:999px;padding:3px 8px }
.dir2 .tag.ok { background:var(--green-soft);color:var(--green) }
.dir2 .tag.no { background:var(--grey-soft);color:var(--muted) }
.dir2 .tag.never { background:var(--orange-soft);color:var(--orange) }
.dir2 .mini { display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-top:12px }
.dir2 .mini div { background:var(--bg);border-radius:10px;padding:8px 4px;text-align:center }
.dir2 .mini b { display:block;font-size:17px;font-variant-numeric:tabular-nums }
.dir2 .mini span { font-size:10.5px;color:var(--muted);line-height:1.25;display:block }
.dir2 .pc .ft { margin-top:10px;font-size:12px;color:var(--muted);display:flex;justify-content:space-between;gap:8px }
.dir2 .pc.off { opacity:.8 }
.dir2 .two { display:grid;grid-template-columns:1.1fr 1fr;gap:12px }
.dir2 .hb { display:grid;grid-template-columns:150px 1fr 40px;gap:10px;align-items:center;padding:6px;border-radius:8px;width:100%;border:0;background:none;text-align:left }
.dir2 .hb:hover { background:var(--navy-soft) }
.dir2 .hb .t { height:8px;background:var(--grey-soft);border-radius:8px;overflow:hidden }
.dir2 .hb .t i { display:block;height:100%;background:var(--navy-2);border-radius:8px }
.dir2 .hb b { text-align:right;font-variant-numeric:tabular-nums }
.dir2 .leg { display:flex;flex-wrap:wrap;gap:12px;margin-top:10px;font-size:12.5px;color:var(--ink-2) }
.dir2 .leg i { display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:6px;vertical-align:-1px }
.dir2 .note { font-size:12.5px;color:var(--muted);margin-top:10px }
.dir2 .tw { overflow-x:auto }
.dir2 table { border-collapse:collapse;width:100%;font-size:13.5px }
.dir2 th, .dir2 td { text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:top }
.dir2 th { font-size:12px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em }
.dir2 tr:last-child td { border-bottom:0 }
.dir2 .veil { position:fixed;inset:0;background:rgba(15,23,42,.32);opacity:0;pointer-events:none;transition:opacity .2s;z-index:20 }
.dir2 .veil.on { opacity:1;pointer-events:auto }
.dir2 .drawer { position:fixed;top:0;right:0;height:100vh;width:min(600px,100vw);background:var(--surface);z-index:21;transform:translateX(100%);transition:transform .25s ease;display:flex;flex-direction:column;visibility:hidden }
.dir2 .drawer.on { transform:none;visibility:visible;box-shadow:-20px 0 40px rgba(15,23,42,.14) }
.dir2 .dh { padding:18px 20px 12px;border-bottom:1px solid var(--line);position:relative }
.dir2 .crumb { font-size:12px;color:var(--muted);display:flex;gap:6px;flex-wrap:wrap;min-height:16px;padding-right:40px }
.dir2 .crumb button { border:0;background:none;color:var(--navy);padding:0;font-weight:600 }
.dir2 .dh h3 { margin:6px 0 2px;font-size:20px;padding-right:40px }
.dir2 .dh .ds { color:var(--muted);font-size:12.5px }
.dir2 .def { margin-top:8px;font-size:12.5px;color:var(--ink-2);background:var(--bg);border-radius:10px;padding:8px 10px;min-height:6.2em;box-sizing:border-box }
.dir2 .def p { margin:0 }
.dir2 .def p + p { margin-top:4px }
.dir2 .def b { color:var(--navy) }
.dir2 .close { position:absolute;top:14px;right:14px;border:0;background:var(--bg);width:34px;height:34px;border-radius:50%;font-size:18px;color:var(--ink-2) }
.dir2 .chips { display:flex;gap:6px;flex-wrap:nowrap;overflow-x:auto;margin-top:10px;scrollbar-width:thin }
.dir2 .chips .chip { flex:none }
.dir2 .chip { border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:4px 10px;font-size:12.5px;color:var(--ink-2);font-weight:600 }
.dir2 .chip.on { background:var(--navy);border-color:var(--navy);color:#fff }
.dir2 .chip .k { font-weight:700;margin-left:4px;opacity:.75 }
.dir2 .db { overflow:auto;padding:8px 12px 24px;flex:1 }
.dir2 .row { display:grid;grid-template-columns:36px 1fr auto;gap:10px;align-items:center;width:100%;border:0;background:none;text-align:left;padding:10px 8px;border-radius:12px;border-bottom:1px solid var(--fond) }
.dir2 button.row:hover { background:var(--navy-soft) }
.dir2 .row .a { font-weight:600 }
.dir2 .row .b { font-size:12.5px;color:var(--muted) }
.dir2 .row .c { font-size:12.5px;color:var(--muted);text-align:right;white-space:nowrap }
.dir2 .pill { display:inline-block;font-size:11px;font-weight:600;border-radius:999px;padding:2px 8px;background:var(--grey-soft);color:var(--ink-2);margin-top:3px }
.dir2 .pill.o { background:var(--orange-soft);color:var(--orange) }
.dir2 .pill.g { background:var(--green-soft);color:var(--green) }
.dir2 .tabs { display:flex;gap:4px;margin-top:12px;border-bottom:1px solid var(--line);overflow-x:auto }
.dir2 .tabs button { border:0;background:none;padding:8px 10px;color:var(--muted);font-weight:600;border-bottom:2px solid transparent;white-space:nowrap }
.dir2 .tabs button.on { color:var(--navy);border-color:var(--navy) }
.dir2 .ps { display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:12px 8px }
.dir2 .ps div { background:var(--bg);border-radius:12px;padding:10px 4px;text-align:center }
.dir2 .ps b { display:block;font-size:20px;font-variant-numeric:tabular-nums }
.dir2 .ps span { font-size:11px;color:var(--muted) }
.dir2 .days { display:flex;gap:8px;margin:14px 8px }
.dir2 .days div { flex:1;text-align:center;border-radius:10px;padding:10px 0;font-weight:700;font-size:12.5px }
.dir2 .days .y { background:var(--green-soft);color:var(--green) }
.dir2 .days .n { background:var(--grey-soft);color:var(--muted) }
.dir2 .info { margin:10px 8px 0;font-size:12.5px;border-radius:10px;padding:9px 11px;background:var(--navy-soft);color:var(--navy) }
.dir2 .info.warn { background:var(--orange-soft);color:var(--orange) }
.dir2 .info.grey { background:var(--grey-soft);color:var(--ink-2) }
.dir2 .modal { position:fixed;inset:0;display:none;place-items:center;z-index:30;background:rgba(15,23,42,.35);padding:16px }
.dir2 .modal.on { display:grid }
.dir2 .mbox { background:var(--surface);border-radius:18px;padding:22px;width:min(520px,100%) }
.dir2 .mbox h3 { margin:0 0 4px }
.dir2 .mbox p { margin:0 0 12px;color:var(--muted);font-size:13px }
.dir2 textarea { width:100%;min-height:110px;border:1px solid var(--line);border-radius:12px;padding:12px;font:inherit;resize:vertical }
.dir2 .mact { display:flex;justify-content:space-between;align-items:center;margin-top:12px;gap:10px;flex-wrap:wrap }
.dir2 .toast { position:fixed;left:50%;bottom:24px;transform:translateX(-50%);background:var(--ink);color:#fff;border-radius:10px;padding:10px 14px;font-size:13px;z-index:40 }
@media (max-width:900px) {
  .dir2 .two { grid-template-columns:1fr }
  .dir2 .hb { grid-template-columns:120px 1fr 36px }
  .dir2 .kpis { grid-template-columns:repeat(auto-fit,minmax(150px,1fr)) }
}

/* ══ ⛔ L'IMPRESSION DE L'ÉCRAN DE DIRECTION — étape 264 §2 ═════════
   Le bouton « Exporter la semaine (PDF) » passe par l'impression du
   navigateur, qui sait enregistrer en PDF. Cette feuille masque le châssis
   — rail, onglets, saisie, tiroir — et garde le contenu.
   ⚠️ Elle ne s'applique QUE sous `body.impression` : sans cette classe, une
   impression ordinaire de l'écran de chat resterait ce qu'elle est. */
@media print {
  body.impression #rail, body.impression .onglets,
  body.impression .saisie, body.impression #dir-veil,
  body.impression #dir-drawer, body.impression #subtabs-direction,
  body.impression .ctrl, body.impression #vue-chat,
  body.impression #vue-comptes, body.impression #vue-agenda,
  body.impression #vue-support, body.impression #vue-hebdo,
  body.impression .bloc-demandes { display: none !important; }
  body.impression { background: #fff; }
  body.impression .app { display: block; }
  /* ⛔ **LE PDF ÉTAIT TRONQUÉ À LA PREMIÈRE PAGE** — mesuré le 23/09
     (`preuves_pdf_semaine_265.py`) : une seule page, **61 % du texte**, et
     il s'arrêtait juste avant « Ce qui mérite ton attention ». Ludovic
     aurait envoyé un rapport amputé en le croyant complet — *une légende
     qui ne décrit pas ce qu'elle affiche*, sur le document qui sort de
     l'entreprise.

     ⚠️ **LA CAUSE N'EST PAS L'IMPRESSION, C'EST L'ASCENSEUR.**
     `#vue-direction` est un `overflow: auto` de 848 px pour 1128 px de
     contenu, dans `#principal` et `.app` bornés à la hauteur de la
     fenêtre : le navigateur ne met en page que ce qu'il peut voir.
     `display: block` sur `.app` ne suffisait pas — il ne retire ni le
     débordement caché, ni la hauteur. */
  /* ⚠️ `.principal` est une CLASSE, pas un id : mon diagnostic imprimait
     « id ou className » et j'ai écrit `#principal` au premier jet — un
     sélecteur qui ne désigne rien ne corrige rien, et en silence. */
  body.impression .app,
  body.impression .principal,
  body.impression #vue-direction {
    overflow: visible !important;
    height: auto !important;
    max-height: none !important;
  }
  /* ⛔ Ni ombre ni fond coloré : ils mangent l'encre et ne disent rien. */
  body.impression .dir2 .kpi, body.impression .dir2 .panel,
  body.impression .dir2 .board {
    box-shadow: none; break-inside: avoid; page-break-inside: avoid;
  }
  body.impression .dir2 .kpi.hero { background: #fff; color: var(--ink);
    border: 2px solid var(--navy); }
  body.impression .dir2 .kpi.hero .q, body.impression .dir2 .kpi.hero .l,
  body.impression .dir2 .kpi.hero .s { color: var(--ink-2); }
  /* ⛔ **RIEN N'EST REPLIÉ SUR UNE PAGE IMPRIMÉE** — ceinture du JS, qui
     rouvre déjà les plis : si l'un lui échappait, la feuille le rattrape. */
  body.impression .tr-repliee { display: table-row !important; }
  body.impression details > * { display: revert !important; }
}

/* ⛔ L'ÉTAT D'UN TICKET S'ÉCRIT — étape 264 §6 (S2). Il était signalé par
   un trait de 4 px sur le bord gauche : une couleur de bordure ne se lit ni
   de loin, ni en noir et blanc, ni par quelqu'un qui distingue mal le vert
   du bleu. La bordure RESTE — elle range la liste d'un coup d'œil — mais
   elle ne porte plus l'information à elle seule. */
.etat-ticket {
  display: inline-block; font-size: 11.5px; font-weight: 700;
  border-radius: 999px; padding: 2px 9px; margin-right: 8px;
  letter-spacing: .02em; text-transform: uppercase;
}
.etat-ticket.nouveau { background: #FDE7E4; color: #A8341F; }
.etat-ticket.vu { background: #FFF3D6; color: #8A5B00; }
.etat-ticket.traite { background: #E3F4E9; color: #1E7A46; }
/* ⚠️ L'âge est une ATTENTE en cours, pas une date : il se lit à droite du
   nom, en gris, et il disparaît dès qu'on a répondu. */
.age-ticket {
  margin-left: 8px; font-size: 12px; font-weight: 600; color: #A8341F;
}
.ticket-support.traite .age-ticket { display: none; }

/* ══ RESSOURCES ET MISSIONS — 265 §2.4 et §2.5 ══════════════════════════════
   ⚠️ **Rien de neuf dans la palette.** Tout vient des variables posées en
   tête : l'audit 149 a trouvé sept variables employées sans exister, en
   trente-deux endroits, et sans valeur de repli — donc peintes en
   transparent, sans une erreur de console. On ne redessine pas, on assemble.
   ⛔ Et une carte du vivier est un `<button>` : elle s'atteint au clavier
   comme une vignette de compte, sans qu'on ait à y penser. */

.vivier-barre {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 14px;
}
.vivier-barre input[type="search"] {
  flex: 1 1 260px; min-width: 0;
  padding: 9px 12px; font-size: 13.5px;
  border: 1px solid var(--trait); border-radius: 10px;
  background: var(--surface); color: var(--encre);
}
.vivier-barre input[type="search"]:focus { border-color: var(--marine-clair); }
.vivier-barre select {
  padding: 9px 10px; font-size: 13px;
  border: 1px solid var(--trait); border-radius: 10px;
  background: var(--surface); color: var(--encre);
}
.vivier-compte { font-size: 12.5px; color: var(--doux); margin-left: auto; }
/* ⛔ 298 §5 — les chiffres de tête du vivier et des missions. */
.vivier-tete-chiffres { font-size: 13px; color: var(--texte); margin: 4px 0 10px; }
/* ⛔ 289 §4.1 — les quatre filtres de plus, repliés. */
.vivier-plus { margin: -6px 0 14px; }
.vivier-plus > summary {
  cursor: pointer; font-size: 13px; color: var(--marine-clair);
  padding: 4px 0; margin-bottom: 8px;
}
.filtre-etiquette {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 13px; color: var(--doux);
}
.vivier-barre input[type="date"] {
  padding: 8px 10px; font-size: 13px; font: inherit;
  border: 1px solid var(--trait); border-radius: 10px;
  background: var(--surface); color: var(--encre); max-width: 100%;
}
.vivier-note {
  font-size: 12.5px; color: var(--doux); line-height: 1.5;
  margin: 0 0 14px;
}

/* Les trois sous-onglets des missions. ⚠️ L'état actif ne tient PAS qu'à la
   couleur : le fond change ET le trait du dessous — une différence de teinte
   seule ne se voit pas de tout le monde. */
.sous-onglet {
  padding: 7px 13px; font-size: 13px; font-weight: 600;
  border: 1px solid var(--trait); border-radius: 9px;
  background: var(--surface); color: var(--doux);
}
.sous-onglet:hover { border-color: var(--rail-doux); }
.sous-onglet.actif {
  background: var(--marine-pale); color: var(--marine);
  border-color: var(--marine-clair);
}

/* ⚠️ `auto-fill` et non `auto-fit` : à une seule carte, `auto-fit` l'étire sur
   toute la largeur de l'écran, et une fiche de personne large de 1400 px se
   lit mal. */
.vivier-liste {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.vivier-carte, .mission-carte {
  background: var(--surface);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: 14px; box-shadow: var(--ombre);
  display: flex; flex-direction: column; gap: 6px;
  text-align: left; color: inherit;
}
.vivier-carte { transition: transform .12s, box-shadow .12s; }
.vivier-carte:hover { transform: translateY(-2px); box-shadow: var(--ombre-forte); }
/* Une carte de besoin porte ses candidats : elle n'est pas contrainte à la
   largeur d'une carte de personne. */
.mission-carte { grid-column: 1 / -1; }
/* La phrase qui dit qu'une liste est coupée tient toute la ligne : logée dans
   une cellule, elle passerait pour une carte vide. */
.vivier-liste > .vivier-note { grid-column: 1 / -1; margin: 0; }
/* ⛔ 302 §4 bis — dans la grille des vignettes de Missions, les sections
   d'en-tête tiennent toute la ligne, et une section VIDE ne prend aucune
   case : sinon la première vignette serait décalée d'un trou. */
.vivier-liste > section { grid-column: 1 / -1; }
.vivier-liste > section:empty { display: none; }
#mission-detail .mission-carte { box-shadow: none; }
/* ⛔ 302 bis — le titre est dans l'en-tête du tiroir : la carte ne le répète
   pas, elle garde sa pastille d'état. */
#mission-detail .mission-carte > .vivier-tete .vivier-nom { visibility: hidden; }
/* Le tiroir, ouvert sous sa vignette, tient toute la ligne de la grille. */
.vivier-liste > #mission-detail { grid-column: 1 / -1; margin: 0; }
/* ⛔ 302 §4 bis — la barre de Missions : la recherche, puis les filtres qui
   existaient, alignés à droite, comme dans Ressources. */
.missions-portees { display: flex; align-items: center; gap: 8px;
                    flex-wrap: wrap; margin-left: auto; }
/* Les quatre vignettes chiffrées : un chiffre, un mot, un clic qui filtre.
   L'état actif ne tient pas qu'à la couleur : le trait et le fond changent. */
.missions-chiffres {
  display: grid; gap: 12px; margin-bottom: 16px;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.vignette-chiffre {
  background: var(--surface); border: 1px solid var(--trait);
  border-radius: var(--rayon); box-shadow: var(--ombre);
  padding: 12px 14px; text-align: left; color: inherit;
  display: flex; flex-direction: column; gap: 2px;
}
.vignette-chiffre:hover { box-shadow: var(--ombre-forte); }
.vignette-chiffre.actif { border-color: var(--marine-clair);
                          background: var(--marine-pale); }
.vignette-chiffre-n { font-size: 22px; font-weight: 700; color: var(--marine); }
.vignette-chiffre-libelle { font-size: 12.5px; color: var(--doux); }
.missions-demandes, .missions-collaborateurs { margin-bottom: 18px; }
.missions-demandes > h3, .missions-titre > h3, .missions-collaborateurs > h3 {
  font-size: 14px; font-weight: 700; margin: 0 0 10px;
}
/* Le statut d'une demande, en MOTS, dans une pastille : la couleur n'y
   porte jamais l'information seule. */
.demande-pastilles { display: inline-flex; gap: 4px; flex-wrap: wrap;
                     justify-content: flex-end; flex: none; }
.demande-statut {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
  padding: 3px 7px; border-radius: 5px;
  background: var(--trait); color: var(--doux);
}
.demande-statut.statut-nouvelle { background: var(--marine-pale); color: var(--marine); }
.demande-statut.statut-rattache { background: var(--ambre-pale); color: var(--ambre-encre); }
/* ⛔ 302 bis §1.7 — au-delà de trois jours sans candidat. */
.demande-statut.statut-sans-candidat { background: var(--ambre-pale); color: var(--ambre-encre); }
/* ⛔ 302 bis §1.6 — l'explication est celle de la section, pas de la carte. */
.cartes-en-retrait .tete-repere { display: none; }
/* ⛔ 302 bis §1.3 — les annulées et perdues, repliées. */
.missions-fermees { margin-top: .75rem; }
/* ⛔ 305 §2.8 : les remplacements à trouver, un groupe à part. */
.missions-sous-titre { margin: 1rem 0 .4rem; font-size: 14px; font-weight: 600; }
.missions-fermees > summary { cursor: pointer; color: var(--texte-doux, inherit); }
/* ⛔ 302 bis §1.11 — un critère par ligne, chacun avec son libellé. */
.mission-criteres { display: flex; flex-wrap: wrap; gap: .25rem .9rem; }
.demande-statut.statut-presentee { background: var(--marine-pale); color: var(--marine-clair); }
.demande-statut.statut-gagnee { background: var(--vert-pale); color: var(--vert); }
.demande-statut.statut-perdue { background: var(--rouge-pale); color: var(--rouge); }
.demande-statut.statut-suspendue { background: var(--trait); color: var(--encre); }
.demande-statut.statut-recurrente { background: var(--surface);
                                    border: 1px solid var(--trait); }
.demande-candidats { display: flex; flex-wrap: wrap; gap: 4px; }
.demande-candidat {
  font-size: 11.5px; padding: 2px 8px; border-radius: 999px;
  background: var(--marine-pale); color: var(--marine-clair);
}
.demande-suite { font-size: 12.5px; color: var(--encre); font-weight: 600; }
.client-collaborateurs { margin: 0 0 0 16px; padding: 0; font-size: 12.5px;
                         color: var(--doux); line-height: 1.5; }
/* ⛔ 302 §4 bis (c) — une carte en attente tient sur DEUX lignes : ce
   qu'elle propose, puis ses boutons groupés à gauche et « depuis le … ».
   Le détail (techno, ville) reste dans la carte, masqué ici. */
.cartes-en-retrait .compacte {
  display: flex; flex-wrap: wrap; align-items: center;
  column-gap: .75rem; row-gap: .2rem;
  padding-top: 8px; padding-bottom: 8px; margin-bottom: 8px;
}
.cartes-en-retrait .compacte > * { margin-top: 0; }
.cartes-en-retrait .compacte > :first-child { flex-basis: 100%; }
.cartes-en-retrait .compacte .fiche-detail:not(.montree-sans-reponse) {
  display: none;
}
.cartes-en-retrait .compacte .demande-actions {
  justify-content: flex-start; flex-wrap: wrap; margin: 0;
}
.cartes-en-retrait .compacte .demande-actions > * {
  flex: 0 0 auto; width: auto;
}
.cartes-en-retrait .montree-sans-reponse { font-size: 12px;
                                           color: var(--tres-doux); }
@media (max-width: 640px) {
  .missions-chiffres { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .missions-portees { margin-left: 0; }
}
.missions-en-cours h3, .cartes-en-retrait > h3 {
  font-size: 14px; font-weight: 700; margin: 0 0 6px;
}
.cartes-en-retrait-pli > summary, .cartes-en-retrait-replie > summary {
  cursor: pointer; font-size: 14px; font-weight: 700; padding: 2px 0 6px;
}
.missions-en-cours-pli > summary {
  cursor: pointer; font-size: 13px; color: var(--marine-clair);
  padding: 2px 0 6px;
}
.missions-en-cours-liste { font-size: 13px; margin: 0 0 0 18px; }

/* Le nom et l'étiquette ont une MARGE : collés, ça donnait
   « Banque Transatlantiqueprospect » sur chaque ligne (étape 37). */
.vivier-tete {
  display: flex; align-items: flex-start; gap: 8px; justify-content: space-between;
}
.vivier-nom { font-size: 14.5px; font-weight: 700; line-height: 1.3; }
.vivier-statut {
  flex: none;
  /* ⛔ 302 bis — « Freelance », jamais « FREELANCE ». */
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .05em; padding: 3px 7px; border-radius: 5px;
  background: var(--marine-pale); color: var(--marine-clair);
}
.vivier-fonction { font-size: 12.5px; color: var(--doux); }
.vivier-bas {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  font-size: 12px; color: var(--tres-doux);
}
.vivier-comp { color: var(--doux); }
/* ⛔ 304 §4 — indisponible, placé : marqués, jamais cachés. */
.vivier-marque {
  font-weight: 600; color: var(--texte);
  padding: 0 7px; border-radius: 999px; background: var(--marine-pale);
}

.vivier-puces { display: flex; flex-wrap: wrap; gap: 6px; }
.puce {
  font-size: 12px; padding: 3px 9px; border-radius: 999px;
  background: var(--marine-pale); color: var(--marine-clair);
}
/* ⚠️ « À valider » ne se dit pas qu'en couleur : le titre au survol le dit en
   toutes lettres, et l'ambre est déjà réservé à ce qui appelle un geste. */
.puce.a-valider {
  background: var(--ambre-pale); color: var(--ambre-encre);
  border: 1px dashed var(--ambre-trait);
}

/* L'état d'un besoin. ⚠️ Chaque état garde son MOT : la couleur ne porte
   jamais l'information seule. */
.mission-etat {
  flex: none;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: 3px 7px; border-radius: 5px;
  background: var(--trait); color: var(--doux);
}
/* ⛔ 296 §6 — « ouvert » n'est pas un retard : l'orange est réservé à ce
   qui alerte. */
.mission-etat.etat-ouvert { background: var(--marine-pale); color: var(--marine); }
/* Les statuts du vivier ne sont plus tous du même bleu. */
.vivier-statut.statut-salarie { background: var(--marine-pale); color: var(--marine); }
.vivier-statut.statut-freelance,
.vivier-statut.statut-freelance_norgay { background: var(--vert-pale); color: var(--vert); }
.vivier-statut.statut-candidat { background: var(--trait); color: var(--encre); }
.mission-etat.etat-gagne { background: var(--vert-pale); color: var(--vert); }
.mission-etat.etat-perdu { background: var(--rouge-pale); color: var(--rouge); }
/* ⛔ Ce qui est SUIVI PAR QUELQU'UN D'AUTRE se voit d'un coup d'œil : sans
   ça, on clique avant de lire, et le refus arrive après le geste. */
.mission-autre { color: var(--ambre-encre); font-weight: 600; }

.mission-candidats, .mission-proches {
  margin-top: 6px; padding-top: 10px; border-top: 1px solid var(--trait);
}
.mission-candidats h4, .mission-proches h4 {
  font-size: 12.5px; font-weight: 700; color: var(--doux);
  text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px;
}

/* La fiche s'ouvre EN PLACE, au-dessus de la liste — jamais dans le panneau
   latéral, qui est celui de la fiche compte (étape 226). */
.detail-en-place {
  margin-bottom: 16px; padding: 14px 16px;
  border-left: 3px solid var(--marine);
  background: var(--marine-pale); border-radius: 6px;
}
.detail-en-place .bloc { padding: 12px 0; }
.detail-en-place .bloc:last-child { border-bottom: 0; }
.detail-en-place .detail-entete h3 { display: flex; align-items: center; gap: 8px; }

@media (max-width: 640px) {
  /* Une colonne, et le compte passe à la ligne plutôt que de pousser le
     sélecteur hors de l'écran. */
  .vivier-liste { grid-template-columns: 1fr; }
  .vivier-compte { margin-left: 0; }
  .detail-en-place { padding: 12px; }
}

/* ⛔ 268 §4 — « Tous les comptes ». La barre des sous-onglets réutilise
   `.sous-onglets` des missions : deux styles pour une même notion
   divergeraient au premier changement. Il ne reste ici que ce qui est
   propre à cet écran. */
.comptes-tous { margin-top: .5rem; }
.comptes-tous .vivier-barre { margin-bottom: .75rem; }
.comptes-tous .filtre-champ { flex: 1 1 14rem; }
/* ⚠️ Un `select` posé à côté d'un champ de recherche doit lui ressembler :
   sans cette ligne il prend la hauteur par défaut du navigateur et la barre
   se décale d'un pixel ou deux — visible, et pour rien. */
.comptes-tous select.filtre-champ { flex: 0 0 auto; min-width: 12rem; }


/* ⛔ **271 §4 — L'APERÇU DE LA SIGNATURE, RENDU.** Il montre ce que le
   destinataire verra : le logo, le tableau, les couleurs. Le cadre dit que
   c'est un aperçu et pas la page ; sans lui, une signature à fond blanc se
   confondrait avec les réglages autour. */
.apercu-mail {
  border: 1px solid var(--trait);
  border-radius: 6px;
  padding: .75rem 1rem;
  background: #fff;
  margin: 0;
  overflow-x: auto;
  font-size: .92rem;
}
pre.apercu-mail { white-space: pre-wrap; font-family: inherit; }
/* ⚠️ Le bloc du mail et la signature se touchent : on pose la ligne vide
   qu'un vrai brouillon porte, plutôt que de la laisser au hasard du HTML. */
#signature-apercu-riche > pre.apercu-mail {
  border: 0; padding: 0; margin: 0 0 .75rem 0;
}
/* ⛔ Une signature reprise d'Outlook porte ses propres largeurs : on BORNE
   l'image, sinon un logo de 900 px déforme le panneau des réglages. */
.signature-rendue img { max-width: 220px; height: auto; }
.signature-rendue table { border-collapse: collapse; }

/* 278 2 — LE SUIVI SUR LA FICHE, ET LES CHAMPS DU BESOIN.
   Un passage SAUTE porte un filet ambre : il est MARQUE, jamais cache — une
   etape sautee qu on tait se lit comme une etape franchie. */
.fiche-suivi { margin: 4px 0 10px 14px; border-left: 2px solid var(--trait);
               padding-left: 10px; }
.suivi-passage { color: var(--doux); font-size: .86em; line-height: 1.55; }
.suivi-saute { color: var(--ambre-encre); font-weight: 600; }
.mission-contrainte { color: var(--ambre-encre); font-weight: 600; }
.mission-budget { margin: 6px 0 0; color: var(--doux); font-size: .88em;
                  border-left: 3px solid var(--ambre); padding-left: 9px; }
/* ⛔ 280 §3 — la provenance d'un besoin saisi par une TA. */
.mission-mention { margin: 6px 0 0; color: var(--doux); font-size: .86em;
                   font-style: italic; }
/* `.lien-discret` vit dans le jeu de pièces (296 §6) ; ici, seulement l'air
   entre deux gestes d'une ligne de candidat. */
.lien-discret { margin-left: 8px; cursor: pointer; }

/* ⛔ 285 §1 — LA MAQUETTE V3, le sous-onglet « Indicateurs ». Les règles de
   maquettes/maquette-direction-v3.html (lignes 192 à 242), préfixées par
   `.dir2` comme celles de la V2 : elles ne repeignent que cet écran. */
.dir2 .subtabs button .new { display:inline-block;margin-left:6px;font-size:10.5px;font-weight:700;border-radius:999px;padding:1px 6px;background:var(--orange-soft);color:var(--orange);vertical-align:1px }
.dir2 .subtabs button.on .new { background:rgba(255,255,255,.2);color:#fff }
.dir2 .grp-h { display:flex;align-items:center;gap:12px;margin:22px 0 10px;font-size:12px;font-weight:700;color:var(--navy);text-transform:uppercase;letter-spacing:.06em }
.dir2 .grp-h::after { content:"";flex:1;height:1px;background:var(--navy-line) }
.dir2 .grp-h span { font-weight:500;text-transform:none;letter-spacing:0;color:var(--muted);font-size:12.5px }
.dir2 .kpi .qq { display:inline-block;font-size:11px;font-weight:600;border-radius:999px;padding:2px 8px;background:var(--grey-soft);color:var(--ink-2);align-self:flex-start;margin-top:8px }
.dir2 .rec { width:100% }
.dir2 .rec td { vertical-align:middle }
.dir2 .rec .vol { text-align:right;white-space:nowrap }
.dir2 .rec .lnk { border:0;background:none;padding:4px 8px;border-radius:8px;font-weight:800;font-size:17px;font-variant-numeric:tabular-nums;color:var(--ink) }
.dir2 .rec .lnk:hover { background:var(--navy-soft);color:var(--navy) }
.dir2 .rec .dd { font-size:12.5px;color:var(--muted) }
.dir2 .badge { display:inline-block;min-width:38px;text-align:center;font-size:12px;font-weight:700;border-radius:7px;padding:3px 7px;background:var(--navy-soft);color:var(--navy) }
.dir2 .badge.b3 { background:var(--amber-soft);color:var(--amber) }
.dir2 .badge.b4 { background:var(--grey-soft);color:var(--ink-2) }
.dir2 .badge.b5 { background:var(--green-soft);color:var(--green) }
.dir2 .badge.bx { background:var(--orange-soft);color:var(--orange) }
.dir2 .mx { font-size:13.5px }
.dir2 .mx th, .dir2 .mx td { text-align:right;white-space:nowrap;padding:7px 5px }
.dir2 .mx th:first-child, .dir2 .mx td:first-child { text-align:left }
.dir2 .mx tbody td, .dir2 .mx tfoot td { vertical-align:middle }
.dir2 .mx thead th { text-transform:none;letter-spacing:0;font-size:11.5px;line-height:1.25;white-space:normal;vertical-align:bottom;min-width:64px;max-width:96px }
.dir2 .mx thead tr.gh th { text-align:center;text-transform:uppercase;letter-spacing:.06em;font-size:11px;color:var(--navy);border-bottom:2px solid var(--navy-line);padding-bottom:6px }
.dir2 .mx thead tr.gh th.gv { border-bottom:0 }
.dir2 .mx .sep { border-left:1px solid var(--line) }
.dir2 .mx .cell { border:0;background:none;font-weight:700;font-variant-numeric:tabular-nums;padding:4px 7px;border-radius:8px;font-size:14px;min-width:34px }
.dir2 .mx .cell:hover { background:var(--navy-soft);color:var(--navy) }
.dir2 .mx .cell.z { color:var(--rail-titre);font-weight:600 }
.dir2 .mx .abs { color:var(--rail-titre) }
.dir2 .mx .nm { border:0;background:none;padding:0;font-weight:600;text-align:left;white-space:nowrap }
.dir2 .mx .nm:hover { color:var(--navy);text-decoration:underline }
.dir2 .mx tfoot td { border-top:2px solid var(--line);border-bottom:0;font-weight:800 }
.dir2 .mx tbody tr:hover td { background:var(--fond) }
.dir2 .lire { margin:12px 8px 0;font-size:12.5px;border-radius:10px;padding:9px 11px;background:var(--grey-soft);color:var(--ink-2) }
.dir2 .lire b { color:var(--ink) }
.dir2 .gbox { margin:12px 8px 6px;border:1px solid var(--line);border-radius:14px;padding:12px 12px 8px }
.dir2 .gbox h4 { margin:0 0 2px;font-size:14px }
.dir2 .gbox .gs { font-size:12px;color:var(--muted) }
.dir2 .vues { display:inline-flex;flex-wrap:wrap;gap:2px;background:var(--bg);border:1px solid var(--line);border-radius:10px;padding:3px;margin:10px 0 6px }
.dir2 .vues button { border:0;background:none;padding:6px 11px;border-radius:7px;color:var(--ink-2);font-weight:600;font-size:12.5px }
.dir2 .vues button.on { background:var(--surface);color:var(--navy);box-shadow:0 1px 2px rgba(15,23,42,.1) }
.dir2 .graph svg { display:block;width:100%;height:auto }
.dir2 .lg { display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 2px }
.dir2 .lg button { border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:4px 10px;font-size:12px;font-weight:600;display:inline-flex;gap:6px;align-items:center;color:var(--ink-2) }
.dir2 .lg button.off { opacity:.42 }
.dir2 .lg i { width:10px;height:10px;border-radius:50%;display:inline-block;flex:none }
.dir2 .lg b { font-variant-numeric:tabular-nums;color:var(--ink) }
.dir2 .lg .tt i { border-radius:3px }
/* ⛔ 296 §8 — une courbe vide se dit en une phrase ; sur un téléphone on ne
   survole rien, les valeurs du Total s'écrivent sous le graphique. */
.dir2 .graphe-vide { margin:10px 0 4px;padding:14px 16px;border:1px dashed var(--line);border-radius:12px;background:var(--surface);color:var(--ink-2);font-size:13px;line-height:1.5 }
.dir2 .valeurs-tel { display:none;font-size:12px;color:var(--ink-2);line-height:1.6;margin:6px 0 2px;font-variant-numeric:tabular-nums }
@media (max-width: 720px) {
  .dir2 .valeurs-tel { display:block }
  .dir2 .hors-tel { display:none }
}
.dir2 .sh { margin:16px 8px 4px;font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.05em }
.dir2 .more { display:block;width:calc(100% - 16px);margin:10px 8px 0;border:1px dashed var(--navy-line);background:var(--surface);border-radius:10px;padding:9px 12px;color:var(--navy);font-weight:600;text-align:left }
.dir2 .more:hover { background:var(--navy-soft) }

/* ⛔ 292 §2 — les contacts retrouvés par leur nom, sous le champ de recherche. */
.contacts-trouves { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 14px; }
.contact-trouve { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; text-align: left; padding: 8px 12px; border: 1px solid var(--trait); border-radius: 8px; background: var(--surface); cursor: pointer; font: inherit; color: var(--encre); }
.contact-trouve:hover, .contact-trouve:focus-visible { border-color: var(--marine-clair); }
.contact-trouve .qui { font-weight: 600; }
.contact-trouve .detail { color: var(--doux); font-size: 13px; overflow-wrap: anywhere; }
.grp.hors { color: var(--doux); }

/* ⛔ 296 §9 — dans les réglages, chaque bouton sur sa ligne : deux boutons
   côte à côte se lisent comme un choix, et ils n'en sont pas un. */
#reglages .bloc p > .bt { display: block; margin: 0 0 8px; }
#reglages .bloc p > .bt:last-child { margin-bottom: 0; }

/* ⛔ 296 §9 — les actions d'un candidat : de vrais boutons, petits, groupés
   à droite de sa ligne. */
.bt.petit { padding: 5px 11px; font-size: 13px; }
.mission-candidats .document { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
/* ⛔ 303 §1.5 — les gestes du tiroir, groupés à GAUCHE, sous la ligne. */
.mission-actions { flex-basis: 100%; display: flex; gap: 6px; flex-wrap: wrap; }

/* ⛔ 296 §9 — le support : un résumé en tête, une phrase par ligne avec sa
   pastille, le technique derrière « Voir le détail », un retour par ligne. */
.point-etat { width: 10px; height: 10px; border-radius: 50%; flex: none; margin-top: .45em; background: var(--doux); }
.point-etat.vert { background: #1E7A46; }
.point-etat.orange { background: #C06A12; }
.point-etat.rouge { background: #A31621; }
.support-resume { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 22px; }
.resume-ligne { display: flex; gap: 10px; align-items: flex-start; text-align: left; width: 100%; padding: 10px 14px; border: 1px solid var(--trait); border-radius: 10px; background: var(--surface); color: var(--encre); font: inherit; cursor: pointer; }
.resume-ligne:hover { border-color: var(--marine-clair); }
.resume-ligne[data-couleur="rouge"] { border-left: 4px solid #A31621; }
.resume-ligne[data-couleur="orange"] { border-left: 4px solid #C06A12; }
.ligne-support { display: flex; gap: 10px; align-items: flex-start; padding: 9px 0; border-bottom: 1px solid var(--trait); }
.ligne-support-corps { flex: 1; min-width: 0; line-height: 1.5; overflow-wrap: anywhere; }
.voir-detail { margin-top: 4px; }
.voir-detail summary { cursor: pointer; color: var(--marine); font-size: 13px; font-weight: 600; }
.voir-detail-texte { margin-top: 4px; padding: 6px 8px; background: var(--fond); border-radius: 6px; font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; color: var(--doux); }
details.ticket-support > summary { cursor: pointer; list-style: none; display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
details.ticket-support > summary::-webkit-details-marker { display: none; }
details.ticket-support > summary::before { content: '▸'; color: var(--doux); }
details.ticket-support[open] > summary::before { content: '▾'; }
.ticket-apercu { flex-basis: 100%; font-weight: 400; color: var(--doux); }
details.ticket-support[open] .ticket-apercu { display: none; }

/* ⛔ 296 §9 — sur la fiche et les vignettes, un téléphone et un mail se lisent
   dans la police de l'application. La chasse fixe reste là où elle sert :
   dans l'aperçu d'une écriture, où « un seul F » doit se voir (étape 32). */
#panneau .mono, #vue-comptes .mono { font-family: inherit; font-size: inherit; letter-spacing: normal; font-variant-numeric: tabular-nums; }
.a-completer { margin: 6px 0 0; color: var(--doux); font-size: 13.5px; }
.echange.en-retard .quoi, .echange.en-retard .quand { color: #A31621; font-weight: 600; }

/* ⛔ 296 §9 — l'agenda : la période entre les flèches ; UN seul état vide
   (la grille vide EST l'état, la phrase tient sur une ligne dessous) ; un
   bandeau avec son bouton quand la boîte n'est pas reliée ; les retards
   repliés en vue Mois. */
.fleches .agenda-periode { margin: 0 8px; font-weight: 650; white-space: nowrap; color: var(--encre); }
#agenda-corps .agenda-vide { padding: 10px 2px; border: 0; background: none; text-align: left; }
#agenda-corps .agenda-vide .grand { font-size: 14px; margin: 0; }
#agenda-corps .agenda-vide p { display: inline; margin: 0 6px 0 0; }
.agenda-relier { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 10px 0; padding: 10px 14px; border: 1px solid var(--trait); border-left: 4px solid var(--ambre-vif); border-radius: 10px; background: var(--surface); }
.agenda-relier span { flex: 1 1 260px; }
.pli-retards > summary { cursor: pointer; font-weight: 650; padding: 4px 0; }
@media (max-width: 720px) { #agenda-corps .agenda-vide { padding: 10px 2px; } .fleches .agenda-periode { margin: 0 4px; font-size: 13px; } }

/* ⛔ 299 §3 — le reste de la tête du fil, replié en une ligne. */
.tete-repli > summary { cursor: pointer; }
.cartes-en-retrait h3 { font-size: 14px; margin: 6px 0; }

/* ⛔ 299 §4 — mes chiffres de la semaine. */
.mes-chiffres { margin: 0 0 12px; border: 1px solid var(--trait, #dde3ea); border-radius: 10px; padding: 8px 12px; background: #fff; }
.mes-chiffres > summary { cursor: pointer; font-weight: 600; }
.mes-chiffres-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin: 8px 0; }
.mes-chiffres-vignette { text-align: left; border: 1px solid var(--trait, #dde3ea); border-radius: 8px; padding: 8px; background: #fff; cursor: pointer; }
.mes-chiffres-vignette b { display: block; font-size: 20px; }
.mes-chiffres-vignette span { display: block; font-size: 12.5px; color: var(--doux); }
.mes-chiffres-courbe svg { max-width: 100%; height: auto; }

/* 300 §3 : le compte rendu d une reunion, compose par le code. */
.compte-rendu-reunion h4 { margin: 0 0 8px; }
/* ⛔ 299 §6 — la page du point : six rubriques, une liste chacune. */
.point-client h4 { margin: 0 0 8px; }
.point-client h5 { margin: 12px 0 4px; font-size: 0.95em; }
.point-client ul { margin: 0; padding-left: 18px; }
.point-client li { margin: 2px 0; overflow-wrap: anywhere; }
.compte-rendu-texte p { margin: 2px 0; overflow-wrap: anywhere; }
.compte-rendu-texte .cr-item { padding-left: 12px; }
.compte-rendu-texte .cr-vide { height: 6px; }

/* 299 §8 : la carte du vendredi. */
.carte-vendredi .vendredi-titre { margin: 10px 0 4px; font-size: 14px; }
.carte-vendredi ul { margin: 0; }

/* ⛔ 302 bis — « 1 candidat », pas « 1 CANDIDAT PROPOSÉ ». */
.mission-candidats > h4 { text-transform: none; letter-spacing: 0; }
/* ⛔ 302 bis — le titre de la liste porte « Tout voir ». */
.missions-titre { display: flex; align-items: center; gap: 12px;
                  flex-wrap: wrap; }
.missions-titre > h3 { margin: 0; }
.missions-collaborateurs > .bt { margin-top: 10px; }
/* ⛔ 302 bis — au doigt, un bouton fait 44 px de haut. */
@media (max-width: 640px) {
  #vue-missions button:not(.vignette-chiffre):not(.mission-vignette) {
    min-height: 44px;
  }
}

/* ⛔ 303 §1.4 — à 390, l'en-tête de la fiche ne coupe rien : le titre prend
   toute la ligne, « Retour à la demande » et « Fermer » passent dessous. */
.detail-entete { flex-wrap: wrap; }
@media (max-width: 640px) {
  .detail-entete > h3 { flex-basis: 100%; }
}

/* ⛔ 304 §7 et §8 (0319) — « Où en sont mes candidats », les relances de la
   semaine, et la fiche « sans CV ». Rien de neuf dans la charte : les
   couleurs des demandes reçues (filet ambre), et le marine pâle du statut. */
.mes-candidats { padding: .75rem 1rem 0; max-width: var(--carte-max); }
.mes-candidats h3 { margin: 0 0 .25rem; font-size: 15px; color: var(--marine); }
.pli-candidats { margin: .35rem 0; }
.pli-candidats summary { cursor: pointer; font-weight: 600; color: var(--encre); }
.liste-candidats { list-style: none; margin: .35rem 0; padding: 0; }
.liste-candidats li { padding: .2rem 0; overflow-wrap: anywhere; }
.liste-candidats .lien { font-weight: 600; }
.liste-candidats .bt { margin-left: .5rem; }
.relances { display: flex; flex-direction: column; gap: .5rem; padding: .75rem 1rem 0; }
.carte-relance {
  border-left: 3px solid var(--ambre-vif);
  background: var(--ambre-pale);
  border-radius: 0 var(--rayon) var(--rayon) 0;
  padding: .6rem .85rem;
  max-width: var(--carte-max);
}
.carte-relance .carte-titre { margin: 0; font-weight: 600; color: var(--ambre-encre); }
.sans-cv {
  flex: none; font-size: 12px; font-weight: 600;
  padding: 3px 7px; border-radius: 5px;
  background: var(--ambre-pale); color: var(--ambre-encre);
}
/* ── ⛔ 304 bis §3 — la frise des fins de mission ──────────────────────
   Quatre couleurs, celles de la charte : le rouge et le vert portent du
   texte, l'ambre vif et le marine clair ne sont que des barres. */
.frise { margin-top: 24px; background: var(--surface); border-radius: var(--rayon);
         box-shadow: var(--ombre); padding: 16px 18px; }
.frise-entete { display: flex; flex-wrap: wrap; align-items: center;
                justify-content: space-between; gap: 8px; }
.frise-entete h3 { margin: 0; font-size: 1.05rem; color: var(--encre); }
.frise-legende { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 10px 0 4px;
                 font-size: .85rem; color: var(--doux); }
.frise-pastille::before { content: ""; display: inline-block; width: 12px; height: 8px;
                          border-radius: 4px; margin-right: 6px; vertical-align: middle;
                          background: var(--frise-couleur, var(--trait)); }
.frise-lignes { list-style: none; margin: 8px 0 0; padding: 0; }
.frise-ligne { padding: 10px 0; border-top: 1px solid var(--trait); }
.frise-ligne:first-child { border-top: 0; }
.frise-rouge {
  --frise-couleur: var(--rouge);
}
.frise-orange {
  --frise-couleur: var(--ambre-vif);
}
.frise-vert {
  --frise-couleur: var(--vert);
}
.frise-bleu {
  --frise-couleur: var(--marine-clair);
}
/* ⛔ 306 §2 : la maquette (Frise.dc.html) : deux colonnes, le collaborateur
   et son client à gauche, la barre à droite sur un axe d'Aujourd'hui aux
   mois à venir ; une phrase de tête, une note de bas. */
.frise-resume { margin: 4px 0 0; color: var(--doux); font-size: .9rem; }
.frise-carre { display: inline-block; width: 14px; height: 9px; border-radius: 3px;
               margin-right: 6px; vertical-align: middle; background: var(--frise-couleur); }
.frise-pastille::before { content: none; }
.frise-bleu .frise-carre, .frise-bleu .frise-barre {
  background: repeating-linear-gradient(45deg, var(--marine-clair) 0 4px,
                                        var(--surface) 4px 7px);
}
.frise-defile { overflow-x: auto; }
.frise-grille { min-width: 560px; }
.frise-axe { display: grid; grid-template-columns: 220px 1fr; gap: 12px;
             font-size: .78rem; color: var(--doux); padding: 6px 0 4px;
             border-bottom: 1px solid var(--trait); }
.frise-axe-mois { position: relative; height: 1.2em; }
.frise-repere { position: absolute; top: 0; white-space: nowrap; transform: translateX(-2px); }
.frise-aujourdhui { color: var(--encre); font-weight: 600; }
.frise-ligne { display: grid; grid-template-columns: 220px 1fr; gap: 12px;
               align-items: center; }
.frise-tete-ligne { display: flex; flex-direction: column; min-width: 0; }
.frise-qui { font-weight: 600; text-align: left; }
.frise-client { color: var(--doux); font-size: .85rem; overflow-wrap: anywhere; }
.frise-piste { position: relative; height: 26px; border-radius: 5px; background:
               repeating-linear-gradient(90deg, transparent 0 calc(100% / 6 - 1px),
                                         var(--trait) calc(100% / 6 - 1px) calc(100% / 6)); }
.frise-barre { height: 100%; border-radius: 5px; background: var(--frise-couleur); }
.frise-dit { position: absolute; top: 0; height: 100%; display: flex; align-items: center;
             gap: 6px; font-size: .85rem; white-space: nowrap; }
.frise-dit-dans { left: 8px; color: var(--surface); }
.frise-dit-apres { left: calc(var(--part) + 8px); }
.frise-bleu .frise-dit-dans { color: var(--encre); }
.frise-dit-dans .frise-phrase { background: rgba(0, 0, 0, .18); border-radius: 4px; padding: 0 6px; }
.frise-bleu .frise-dit-dans .frise-phrase { background: var(--surface); }
.frise-rouge .frise-dit-apres .frise-phrase { color: var(--rouge); font-weight: 600; }
.frise-vert .frise-dit-apres .frise-phrase { color: var(--vert); }
.frise-au-dela, .frise-non-fiable-mot { color: var(--doux); font-size: .8rem; }
.frise-non-fiable-mot { border: 1px solid var(--trait); border-radius: 999px; padding: 0 8px;
                        background: var(--surface); }
.frise-note { margin: 10px 0 0; font-size: .8rem; color: var(--doux); }
@media (max-width: 640px) {
  .frise { padding: 12px; }
  .frise-axe, .frise-ligne { grid-template-columns: 140px 1fr; }
}

/* ── ⛔ 304 bis §3 bis — la carte de France des missions ───────────────
   Une forme par calque : la demande est un carré, le collaborateur un rond,
   le candidat un losange, le compte un anneau. Pâle : la ville du client,
   à confirmer. */
.missions-carte { margin-top: 12px; }
.carte-reglages { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px;
                  margin-bottom: 10px; }
/* ⛔ 306 §2 : la maquette (Carte.dc.html) : un bandeau de réglages, la
   carte à gauche, la ville choisie à droite, une bulle par ville en
   camembert, ce qui manque dans un encadré ambre sous la carte. */
.carte-reglages { background: var(--surface); border: 1px solid var(--trait);
                  border-radius: var(--rayon); padding: 10px 14px;
                  justify-content: space-between; }
.carte-calques { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.carte-reglage-mot { font-size: .82rem; color: var(--doux); margin-right: 2px; }
.carte-couleur-bloc { display: flex; align-items: center; gap: 8px; }
.carte-calque { min-height: 40px; padding: 0 14px; border-radius: 999px; font: inherit;
                font-size: .9rem; cursor: pointer; display: inline-flex;
                align-items: center; gap: 8px; border: 1px solid var(--trait);
                background: var(--surface); color: var(--encre); }
.carte-calque i { width: 16px; height: 16px; border-radius: 4px;
                  border: 1px solid var(--trait); background: var(--surface); }
.carte-calque[aria-pressed="true"] { border-color: var(--marine); background: var(--marine-pale);
                                     color: var(--marine); }
.carte-calque[aria-pressed="true"] i { background: var(--marine); border-color: var(--marine); }
.carte-calque-n { font-weight: 600; }
.carte-deux { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
.carte-colonne-carte { flex: 3 1 520px; min-width: 0; }
.carte-ville { flex: 2 1 320px; min-width: 0; background: var(--surface);
               border: 1px solid var(--trait); border-radius: var(--rayon); padding: 16px 18px; }
.carte-ville-tete { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.carte-ville-tete h3 { margin: 0; font-size: 1.15rem; }
.carte-ville-bloc { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.carte-ville-bloc-titre { font-weight: 600; font-size: .9rem; }
.carte-ville-ligne { display: flex; align-items: center; gap: 10px; min-height: 44px;
                     padding: 6px 10px; border: 1px solid var(--trait); border-radius: 10px;
                     background: var(--surface); color: var(--encre); font: inherit;
                     text-align: left; cursor: pointer; }
.carte-ville-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.carte-ville-titre { font-size: .9rem; font-weight: 500; }
.carte-ville-bulle { display: flex; align-items: center; justify-content: center;
                     border-radius: 999px; box-shadow: 0 1px 3px rgb(15 23 42 / .3); }
.carte-ville-bulle.choisie { box-shadow: 0 0 0 3px var(--surface), 0 0 0 6px var(--encre); }
.carte-ville-centre { background: var(--surface); border-radius: 999px; display: flex;
                      align-items: center; justify-content: center; font-weight: 700;
                      font-size: .8rem; color: var(--encre);
                      width: calc(100% - 14px); height: calc(100% - 14px); }
.carte-ville-nom { display: block; margin-top: 2px; font-size: .75rem; font-weight: 600;
                   color: var(--encre); background: rgb(255 255 255 / .85);
                   border-radius: 6px; padding: 0 4px; white-space: nowrap;
                   text-align: center; transform: translateX(-25%); }
.carte-manque-bloc { margin-top: 12px; background: var(--ambre-pale); color: var(--ambre-encre);
                     border-radius: 12px; padding: 10px 14px; font-size: .85rem; }
.carte-manque-bloc .carte-manque { color: inherit; margin: 4px 0; }
.carte-france { height: 560px; border-radius: var(--rayon); box-shadow: var(--ombre);
                background: var(--fond); z-index: 0; }
.carte-bulle {
  --carte-c: var(--marine);
  display: flex; align-items: center; justify-content: center;
  color: var(--surface); font-weight: 700; font-size: .8rem;
  background: var(--carte-c); border: 2px solid var(--surface);
  box-shadow: 0 1px 4px rgb(0 0 0 / .3); box-sizing: border-box;
}
.carte-collaborateurs { border-radius: 50%; }
.carte-demandes { border-radius: 4px; }
.carte-candidats { border-radius: 4px; transform: rotate(45deg); }
.carte-candidats > span { transform: rotate(-45deg); }
.carte-comptes { border-radius: 50%; background: var(--surface); color: var(--carte-c);
                 border: 4px solid var(--carte-c); }
.carte-bulle.pale { opacity: .45; border-style: dashed; }
.carte-forme { display: inline-block; width: 14px; height: 14px; margin-right: 6px;
               vertical-align: middle; }
.carte-teinte { display: inline-block; width: 12px; height: 12px; border-radius: 3px;
                margin-right: 6px; vertical-align: middle; }
.carte-legende, .carte-manque { list-style: none; padding: 0; margin: 10px 0 0;
                                font-size: .85rem; color: var(--doux); }
.carte-legende { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.carte-manque li { margin-top: 4px; }
.carte-ville-liste { list-style: none; padding: 0; margin: 8px 0 0; }
.carte-ville-liste li { padding: 4px 0; border-top: 1px solid var(--trait); }
.carte-ville-dit { color: var(--doux); font-size: .85rem; }
@media (max-width: 640px) {
  .carte-france { height: 420px; }
}

/* ⛔ 306 §3 : L'ÉCRAN DU CV (maquette du 10 octobre). Deux colonnes, le CV
   à gauche tel que Jarvis l'a lu, ce qui manque à droite. Le vert dit « lu
   par Jarvis », l'ambre dit « pas pu lire » : jamais la couleur seule, la
   légende est écrite au-dessus du CV. Aucune couleur neuve : la charte. */
.ecran-cv { padding: 16px; }
.cv-ecran {
  position: relative; width: 100%; max-width: 1360px;
  background: var(--surface); border-radius: 18px;
  box-shadow: 0 24px 60px rgb(13 37 52 / .28); overflow: hidden;
}
.cv-tete {
  padding: 16px 22px; border-bottom: 1px solid var(--trait);
  display: flex; align-items: flex-start; gap: 14px;
}
.cv-tete h2 { font-size: 20px; font-weight: 700; }
.cv-tete .sous { font-size: 13px; color: var(--doux); margin-top: 3px; }
.cv-deux { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.cv-gauche { border-right: 1px solid var(--trait); background: var(--fond); padding: 14px 18px; }
.cv-gauche > summary { display: none; }
.cv-outils { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; color: var(--doux); }
.cv-fichier { font-weight: 600; color: var(--encre); overflow-wrap: anywhere; }
.cv-zoom { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.cv-petit {
  border: 1px solid var(--marine-trait); background: var(--surface); color: var(--encre);
  border-radius: 8px; padding: 4px 10px; font: inherit; font-size: 13px;
}
.cv-legende { font-size: 12px; color: var(--doux); margin: 10px 0; line-height: 1.6; }
.cv-pastille { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -2px; }
.cv-pastille.lu { background: var(--vert-pale); outline: 1px solid var(--vert); }
.cv-pastille.non-lu { background: var(--ambre-pale); outline: 1px solid var(--ambre-encre); margin-left: 10px; }
.cv-page {
  background: var(--surface); border: 1px solid var(--trait); border-radius: 10px;
  padding: 26px 28px; max-height: 72dvh; overflow: auto; color: var(--encre);
  font-size: 13px; line-height: 1.55;
}
.cv-page p { margin: 0 0 2px; padding: 1px 4px; border-radius: 4px; overflow-wrap: anywhere; }
.cv-page p.cv-vide { height: 8px; }
.cv-page p.cv-section { font-weight: 700; margin-top: 10px; color: var(--marine); }
.cv-page p.cv-ligne-lu { background: var(--vert-pale); }
.cv-page p.cv-ligne-non-lu { background: var(--ambre-pale); color: var(--ambre-encre); }
.cv-page p.cv-focus { outline: 2px solid var(--vert); outline-offset: 1px; }
.cv-page p.cv-ligne-non-lu.cv-focus { outline-color: var(--ambre-encre); }
.cv-scanne { color: var(--ambre-encre); background: var(--ambre-pale); padding: 10px; border-radius: 8px; }
.cv-droite { padding: 16px 22px; max-height: 84dvh; overflow-y: auto; }
.cv-qui-nom { font-size: 18px; font-weight: 700; }
.cv-jauge { height: 8px; border-radius: 4px; background: var(--marine-pale); margin: 10px 0 6px; overflow: hidden; }
.cv-jauge > span { display: block; height: 100%; background: var(--marine); width: 0; }
.cv-resume { font-size: 13px; color: var(--doux); }
.cv-resume strong { color: var(--encre); }
.cv-bloc { border-top: 1px solid var(--trait); padding: 14px 0; }
.cv-bloc h3 { font-size: 16px; font-weight: 700; }
.cv-bloc .sous { font-size: 13px; color: var(--doux); margin: 2px 0 8px; }
.cv-question { margin: 12px 0; }
.cv-question-titre { font-weight: 600; font-size: 14px; display: flex; gap: 8px; align-items: baseline; }
.cv-num {
  flex: none; width: 22px; height: 22px; border-radius: 50%; display: inline-grid;
  place-items: center; font-size: 12px; background: var(--marine-pale); color: var(--marine);
}
.cv-question.repondue .cv-num { background: var(--vert); color: #fff; }
.cv-aide { font-size: 12px; color: var(--doux); margin: 2px 0 6px 30px; }
.cv-choix { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 0 30px; }
.cv-choix button {
  border: 1px solid var(--marine-trait); background: var(--surface); color: var(--encre);
  border-radius: 999px; padding: 5px 12px; font: inherit; font-size: 13px;
}
.cv-choix button[aria-pressed="true"] { background: var(--marine); border-color: var(--marine); color: #fff; }
.cv-montants { display: flex; flex-wrap: wrap; gap: 10px; margin: 8px 0 0 30px; font-size: 13px; }
.cv-montants label { display: flex; align-items: center; gap: 6px; }
.cv-montants input, .cv-edition input, .cv-question input[type="number"], .cv-propose textarea {
  border: 1px solid var(--marine-trait); border-radius: 8px; padding: 6px 8px; font: inherit; font-size: 13px;
  min-width: 0;
}
.cv-montants input { width: 90px; }
.cv-alerte { margin: 8px 0 0 30px; font-size: 13px; color: var(--ambre-encre); background: var(--ambre-pale); padding: 8px 10px; border-radius: 8px; }
.cv-propose-raison { font-size: 13px; color: var(--doux); margin: 4px 0; }
.cv-propose textarea { width: 100%; margin-top: 6px; }
.cv-lu-liste { list-style: none; }
.cv-lu-ligne {
  display: flex; align-items: flex-start; gap: 8px; border: 1px solid var(--trait);
  border-radius: 10px; padding: 8px 10px; margin: 6px 0; background: var(--surface);
}
.cv-lu-ligne[aria-pressed="true"] { background: var(--marine-pale); border-color: var(--marine); }
.cv-lu-voir { flex: 1; min-width: 0; text-align: left; border: 0; background: none; font: inherit; color: inherit; padding: 0; }
.cv-lu-libelle { display: block; font-size: 12px; color: var(--doux); }
.cv-lu-valeur { display: block; font-size: 14px; overflow-wrap: anywhere; }
.cv-crayon { flex: none; border: 1px solid var(--trait); background: var(--surface); border-radius: 8px; padding: 2px 8px; font: inherit; }
.cv-edition { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.cv-edition input { flex: 1 1 140px; }
.cv-doublon { margin: 12px 0; padding: 12px; border-radius: 10px; background: var(--ambre-pale); color: var(--ambre-encre); font-size: 14px; }
.cv-doublon .cv-choix { margin-left: 0; }
.cv-resultat { margin: 12px 0; padding: 12px; border-radius: 10px; background: var(--vert-pale); color: var(--vert); font-size: 14px; }
.cv-resultat.souci { background: var(--ambre-pale); color: var(--ambre-encre); }
.cv-pied { border-top: 1px solid var(--trait); padding-top: 12px; display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.cv-pied .note { flex-basis: 100%; font-size: 12px; color: var(--doux); }
.vignette-cv { margin-left: 6px; }
@media (max-width: 860px) {
  .ecran-cv { padding: 0; }
  .cv-ecran { border-radius: 0; min-height: 100dvh; }
  .cv-deux { grid-template-columns: minmax(0, 1fr); }
  .cv-gauche { border-right: 0; border-bottom: 1px solid var(--trait); }
  .cv-gauche > summary { display: list-item; font-weight: 600; margin-bottom: 8px; }
  .cv-page { max-height: 46dvh; padding: 16px; }
  .cv-droite { max-height: none; }
  .cv-choix, .cv-montants, .cv-alerte, .cv-aide { margin-left: 0; }
}
/* ⛔ 306 §4 : le CV Norgay d'une mission, selon la maquette « Valide ».
   Trois missions en boutons (le choisi s'encadre de marine), ce qui est mis
   en avant en liste numérotée, puis les deux documents. */
.cv-missions { display: flex; flex-direction: column; gap: .5rem; margin-top: .6rem; }
.cv-mission { display: flex; flex-direction: column; align-items: flex-start;
  gap: .15rem; min-height: 44px; padding: .55rem .9rem; text-align: left;
  border: 1px solid var(--trait); border-radius: 12px; background: var(--surface);
  color: var(--encre); font: inherit; cursor: pointer; }
.cv-mission[aria-pressed="true"] { border: 2px solid var(--marine); background: var(--marine-pale); }
.cv-mission-titre { font-weight: 600; }
.cv-mission-raison { font-size: .85rem; color: var(--doux); }
.cv-orientation { margin-top: .8rem; padding: .7rem .9rem; border-radius: 12px; background: var(--fond); }
.cv-en-avant { margin: .4rem 0 .4rem 1.2rem; padding: 0; }
.cv-fait { margin-top: .8rem; }
.cv-norgay-docs { display: flex; flex-direction: column; gap: .3rem; margin: .4rem 0; }

/* ⛔ 307 §1 : l'ORIGINAL, en images de pages. Les marques sont posées en
   pourcentages de la page, depuis la position des mots : elles suivent le
   zoom sans calcul. `multiply` laisse lire le texte sous la couleur. */
.cv-onglets { display: flex; gap: 6px; margin: 4px 0 10px; }
.cv-onglets button[aria-selected="true"] { background: var(--marine); border-color: var(--marine); color: #fff; }
.cv-original { max-height: 72dvh; overflow: auto; background: var(--marine-pale); border-radius: 10px; padding: 12px; }
.cv-feuilles { margin: 0 auto; }
.cv-feuille { position: relative; margin: 0 auto 12px; background: var(--surface); box-shadow: var(--ombre); }
.cv-feuille img { display: block; width: 100%; height: auto; }
.cv-marque { position: absolute; border-radius: 2px; mix-blend-mode: multiply; pointer-events: none; }
.cv-marque.lu { background: var(--vert-pale); outline: 1px solid var(--vert); }
.cv-marque.non-lu { background: var(--ambre-pale); outline: 1px solid var(--ambre-encre); }
.cv-marque.cv-focus { outline: 3px solid var(--vert); }
.cv-marque.non-lu.cv-focus { outline-color: var(--ambre-encre); }
.cv-coord { list-style: none; margin: 8px 0 0; font-size: 13px; }
.cv-coord li { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; padding: 4px 0; overflow-wrap: anywhere; }
.cv-coord .cv-avant { text-decoration: line-through; }
@media (max-width: 860px) {
  .cv-original { max-height: 46dvh; padding: 8px; }
}

/* ── ⛔ 309 §2 (0350) : les dates de fin des missions ──────────────── */
.dates-ecran { max-width: 880px; }
.dates-hors {
  margin: 14px 24px 0; padding: 10px 12px; border-radius: 10px;
  background: var(--ambre-pale); color: var(--ambre-encre); font-size: 13px;
}
.dates-lignes { list-style: none; margin: 0; padding: 4px 24px 8px; }
.date-ligne {
  display: grid; grid-template-columns: minmax(150px, 1.1fr) 2fr auto;
  gap: 10px 16px; align-items: center;
  padding: 14px 0; border-bottom: 1px solid var(--trait);
}
.date-ligne:last-child { border-bottom: 0; }
.date-qui { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.date-nom { overflow-wrap: anywhere; }
.date-client { font-size: 13px; color: var(--doux); overflow-wrap: anywhere; }
.date-note { font-size: 12px; color: var(--ambre-encre); }
.date-champs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.date-champ { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.date-etiquette { font-size: 12px; color: var(--doux); }
.date-champ input {
  width: 100%; min-width: 0; padding: 8px 10px; border-radius: 10px;
  border: 1px solid var(--trait); background: var(--surface);
  color: var(--encre); font: inherit; font-size: 14px;
}
.date-boutons { display: flex; flex-wrap: wrap; gap: 6px; }
.date-boutons .bt.actif {
  background: var(--marine); color: #FFFFFF; border-color: var(--marine);
}
.date-refus {
  grid-column: 1 / -1; font-size: 13px; color: var(--rouge);
}
.date-refus.date-fait-dit { color: var(--vert); }
.date-ligne.date-faite { opacity: .72; }
.dates-resultat {
  margin: 0 24px 14px; padding: 10px 12px; border-radius: 10px;
  background: var(--vert-pale); color: var(--vert); font-size: 14px;
}
.dates-resultat.erreur { background: var(--rouge-pale); color: var(--rouge); }
.dates-pied {
  padding: 14px 24px 18px; border-top: 1px solid var(--trait);
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
}
.dates-pied .note { font-size: 12.5px; color: var(--doux); flex: 1 1 260px; }
@media (max-width: 640px) {
  .dates-lignes { padding: 4px 16px 8px; }
  .date-ligne { grid-template-columns: 1fr; }
  .date-champs { grid-template-columns: 1fr; }
  .dates-hors, .dates-resultat { margin-left: 16px; margin-right: 16px; }
  .dates-pied { padding: 12px 16px 16px; }
}
