/* ------------------------------------------------------------------
   Couche applicative : reprend la maquette et l'adapte à une vraie
   application (fenêtre redimensionnable, champs de saisie réels, liens).
   Chargée APRÈS crm.css, elle ne modifie pas la maquette d'origine.
   ------------------------------------------------------------------ */

/* Largeur fluide : la maquette était figée à 1600 px, puis plancher à
   1100. Le plancher tombe — voir la section RESPONSIVE en fin de fichier. */
/* ------------------------------------------------------------------
   Un seul modèle de mise en page : la page défile, comme n'importe quel
   site. Il y en avait deux, séparés par un seuil de 900 px de hauteur.

   Le CRM était bâti comme une application à hauteur figée — la fenêtre ne
   défile pas, chaque panneau défile pour son compte — et on rendait la
   main au navigateur seulement sur les écrans courts. Ce seuil coupait le
   parc en deux : le MacBook Air d'un côté, l'écran du Mac mini de l'autre,
   avec deux comportements à maintenir et un seul des deux réellement
   éprouvé au quotidien.

   **Le mode à hauteur figée ne pouvait pas défiler jusqu'en bas**, et pas
   par accident : une rangée en « flex:1 » est taillée à la hauteur de la
   fenêtre, ses colonnes s'étirent d'autant, et les cartes débordent par
   dessus. `.wrap` n'offrait alors que le dépassement, pas la vraie hauteur
   du contenu. Mesuré le 10/08/2026 sur la fiche VOLLEY BALL PAYS VIENNOIS
   en 1329 px de haut : contenu réel 1515 px, rangée forcée à 1100, donc
   170 px de défilement offerts là où il en fallait 415. Le bas de la fiche
   était inatteignable, et aucune correction de la compression ne pouvait
   rendre les 245 px manquants.

   Les plafonds posés à la main sur certaines cartes (« max-height » dans
   les gabarits) restent respectés : ce sont des choix, pas des accidents.
   ------------------------------------------------------------------ */
body{width:auto;min-width:var(--page-mini);min-height:100vh;height:auto;
  overflow-y:auto}
/* La barre latérale et l'en-tête restent sous les yeux pendant qu'on
   descend : sans « align-self », la barre s'étirerait sur toute la hauteur
   de la page, qui peut faire plusieurs milliers de pixels. */
.side{position:sticky;top:0;height:100vh;align-self:flex-start}
.top{position:sticky;top:0;z-index:20}
.main{min-height:100vh}
.wrap{overflow:visible}
/* `.scroll` s'arrête au contenu, elle ne s'étire plus.

   `crm.css` lui donne « flex:1 », ce qui avait un sens tant que la page était
   à hauteur figée : la zone remplissait la fenêtre et défilait pour son
   compte. Depuis que la page défile elle-même (10/08/2026), ce « flex:1 » la
   fait grandir jusqu'au bas de l'écran même quand elle est presque vide —
   mesuré sur la fiche d'une facture : 400 px de blanc entre les gestes et le
   bloc de règlement, sur les 55 écrans qui emploient cette classe.

   Elle garde son défilement interne pour les rares blocs qui se plafonnent
   eux-mêmes (« .scroll.cap »), et rend la hauteur au flux partout ailleurs. */
.scroll{flex:0 0 auto;overflow-y:auto}
/* Dans un formulaire, les cartes se suivent : elles ne doivent pas se comprimer
   les unes sur les autres quand le contenu dépasse la hauteur de la fenêtre. */
.scroll>.card{flex:0 0 auto}

/* Rien ne se comprime : sans cette règle, les enfants de `.wrap` — qui est
   un conteneur flex en colonne — se rétrécissent au lieu de pousser la page
   vers le bas. Mesuré sur un MacBook Air avant qu'elle existe : le pilotage
   financier tombait à une bande défilante de 24 px, la fiche client à 0. */
.wrap>*,.wrap .card,.wrap .row,.wrap .col,.wrap .cols,
.wrap .colL,.wrap .colR{flex-shrink:0}

a{color:inherit;text-decoration:none}
button{font:inherit;border:none;background:none;cursor:pointer;color:inherit}
.nl,.btn,.fl,.tab{cursor:pointer}
.nl:hover{background:rgba(255,255,255,.05);color:#fff}
.nl.off{opacity:.42;cursor:default}
.nl.off:hover{background:none;color:#C3CDE6}
.btn:hover{filter:brightness(1.06)}
.fl:hover{border-color:#C6CFE4}
tbody tr.lgn:hover{background:#F8FAFD;cursor:pointer}

/* Champs de saisie réels */
.inp{width:100%;font-family:inherit;outline:none}
input.inp,select.inp,textarea.inp{display:block;height:33px;line-height:normal}
textarea.inp{height:auto;padding:9px 11px;line-height:1.5;resize:vertical}
select.inp{-webkit-appearance:none;appearance:none;cursor:pointer;
 background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M1 1l4 4 4-4' stroke='%23A6B0C9' stroke-width='1.6' fill='none' stroke-linecap='round'/></svg>");
 background-repeat:no-repeat;background-position:right 11px center;padding-right:28px}
.inp:focus{border-color:var(--cyan);background:#fff;box-shadow:0 0 0 3px rgba(41,166,201,.14)}
.inp::placeholder{color:#A6B0C9;font-weight:400}
.ck{width:16px;height:16px;accent-color:var(--orange);cursor:pointer;flex-shrink:0}

/* Grille de formulaire */
.frm{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}
.frm .full{grid-column:1 / -1}
.fld .hint{font-size:9.8px;color:var(--mut);margin-top:4px;display:block;line-height:1.4}
.fld .err{font-size:10.2px;color:var(--red);font-weight:700;margin-top:4px;display:block}
.fld.ko .inp{border-color:var(--red);background:#FEF6F6}
.chkline{display:flex;align-items:center;gap:9px;font-size:11.8px;color:#48557A;font-weight:600}
.frmact{display:flex;gap:10px;align-items:center;margin-top:16px;flex-shrink:0}
.btn.gh:hover{background:#F6F9FE}

/* Messages */
.msg{border-radius:10px;padding:9px 13px;font-size:11.8px;font-weight:600;flex-shrink:0}
.msg.ok{background:#E3F6EF;color:#117852;border:1px solid #BFE8D8}
.msg.ko{background:#FDE7E7;color:var(--red);border:1px solid #F5C9C9}

/* Bandeau d'alerte formulaire */
.alerte{background:#FDE7E7;border:1px solid #F5C9C9;color:#8C2020;border-radius:10px;
 padding:10px 13px;font-size:11.6px;line-height:1.5;margin-bottom:12px}
.alerte b{font-weight:800}

/* Vide */
.vide{padding:26px 10px;text-align:center;color:var(--mut);font-size:11.6px;line-height:1.6}
.vide b{display:block;color:var(--navy);font-size:12.6px;margin-bottom:5px}

/* Liste d'actions du tableau de bord */
.acti{display:flex;align-items:center;gap:11px;padding:9px 0;border-bottom:1px solid #F2F5FA}
.acti:last-child{border-bottom:none}
.acti .txt{flex:1;min-width:0}
.acti .a1{font-size:11.6px;font-weight:700;color:var(--navy)}
.acti .a2{font-size:10px;color:var(--mut);margin-top:2px;white-space:nowrap;
 overflow:hidden;text-overflow:ellipsis}
.acti form{flex-shrink:0}

/* Fil des notes sur la fiche */
.nt{border-left:2.6px solid var(--line);padding:2px 0 14px 14px;position:relative}
.nt:last-child{padding-bottom:2px}
.nt:before{content:"";position:absolute;left:-6px;top:4px;width:9px;height:9px;border-radius:50%;
 background:#fff;border:2.4px solid var(--cyan)}
.nt.r:before{border-color:var(--red)} .nt.s:before{border-color:#C6CFE4}
.nt .h{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.nt .d{font-size:11.4px;font-weight:800;color:var(--navy)}
.nt .cr{font-size:11.4px;color:#48557A;line-height:1.55;margin-top:5px;white-space:pre-wrap}
.nt .pa{margin-top:7px;background:#F6F9FE;border:1px solid #DCE5F5;border-radius:8px;
 padding:7px 10px;font-size:11.2px;color:var(--navy);display:flex;align-items:center;gap:8px}
.nt .pa b{font-weight:800}

/* Connexion */
body.login{display:flex;align-items:center;justify-content:center;min-width:0;background:var(--navy)}
.lgbox{background:#fff;border-radius:16px;padding:30px 32px;width:360px}
.lgbox .lg{text-align:center;margin-bottom:18px}
.lgbox .lg img{height:52px}
.lgbox h1{font-size:15px;font-weight:800;color:var(--navy);text-align:center;margin-bottom:18px}
.lgbox .fld{margin-bottom:12px}
.lgbox .btn{width:100%;justify-content:center;margin-top:6px}

/* Impression */
@media print{.side,.top,.frmact{display:none}body{height:auto;overflow:visible}}

/* Cases à cocher alignées sur une ligne : trois domaines d'activité se lisent
   mieux côte à côte qu'empilés en colonne. Django emboîte les choix dans un
   div intermédiaire — c'est lui qui doit porter la mise en ligne, pas le
   conteneur du gabarit. Repasse en colonne si la place manque. */
.ckl-ligne > div{display:flex;flex-wrap:wrap;gap:6px 22px;align-items:center}
.ckl-ligne > div > div{display:inline-flex;align-items:center}
.ckl-ligne label{display:inline-flex;align-items:center;gap:7px;font-size:12px;
  color:#48557A;font-weight:600;white-space:nowrap;cursor:pointer}
.ckl-ligne label input{margin:0 2px 0 0}

/* La modale — premier calque partagé du CRM.
   On lit l'écran par défaut, on agit dans une fenêtre qui s'ouvre : la fiche
   fournisseur n'a plus à porter en permanence un formulaire qu'on n'ouvre
   qu'occasionnellement. Voir static/js/modale.js pour le branchement. */
.mdl-fond{position:fixed;inset:0;z-index:100;background:rgba(34,49,92,.42);
  display:flex;align-items:center;justify-content:center;padding:24px}
.mdl-fond[hidden]{display:none}
.mdl{background:#fff;border-radius:12px;width:100%;max-width:560px;
  box-shadow:0 18px 48px rgba(34,49,92,.28);display:flex;flex-direction:column}
.mdl-tete{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:16px 18px 0}
.mdl-tete h2{font-size:12.5px;font-weight:800;color:var(--navy);
  text-transform:uppercase;letter-spacing:.7px}
.mdl-tete .lk{font-size:10.5px;color:var(--mut)}
.mdl-x{background:none;border:0;font-size:19px;line-height:1;color:var(--mut);
  cursor:pointer;padding:0 2px}
.mdl-x:hover{color:var(--navy)}
/* Volontairement sans overflow : le champ marque porte une liste de
   suggestions en position absolue, qu'un défilement rognerait. */
.mdl-corps{padding:14px 18px 0;overflow:visible}
.mdl-pied{display:flex;gap:10px;align-items:center;justify-content:flex-end;
  padding:16px 18px 18px}
/* Le lecteur de PDF, lui, occupe la place : on vient y feuilleter. */
.mdl.large{max-width:min(1100px,94vw);height:88vh}
.mdl.large .mdl-corps{flex:1;min-height:0;padding:12px 14px 14px;display:flex}
.mdl.large .mdl-corps object{flex:1;width:100%;border:0;border-radius:8px}

/* Une pièce jointe dans la boîte : l'œil et le nom font un seul bloc, pour
   qu'ils ne se séparent pas en fin de ligne. */
.bmpj-u{display:inline-flex;align-items:stretch;gap:3px}
.bmpj-oeil{padding-left:8px;padding-right:8px}

/* ------------------------------------------------------------------
   LA BARRE DES PAGES OUVERTES

   Elle vit dans le gabarit de base, en tête de la zone de contenu.
   Toutes les valeurs viennent de la charte : ce composant est né après
   elle, il n'a aucune raison d'écrire un pixel en dur.

   Sa hauteur est **réservée en permanence**, y compris sans onglet :
   le contenu ne doit jamais sauter verticalement quand la barre se
   remplit ou se vide.
   ------------------------------------------------------------------ */
.ong{
  height:var(--ong-hauteur); min-height:var(--ong-hauteur);
  flex-shrink:0;
  display:flex; align-items:center; gap:var(--e2);
  /* Jamais de retour à la ligne : la barre défile, le contenu ne
     descend pas. */
  overflow-x:auto; overflow-y:hidden; white-space:nowrap;
  /* Collante : elle reste sous les yeux quand la page défile. */
  position:sticky; top:0; z-index:15;
  background:var(--bg);
  /* Le fond de page dépasse du retrait de la zone de contenu, sinon on
     verrait les cartes glisser dessous par les côtés. */
  margin:calc(-1 * var(--e2)) calc(-1 * var(--e7)) 0;
  padding:0 var(--e7);
  scrollbar-width:thin;
}
.ong::-webkit-scrollbar{height:var(--e1)}
.ong::-webkit-scrollbar-thumb{background:var(--line); border-radius:var(--r1)}

.ong-i{
  display:inline-flex; align-items:center; gap:var(--e2);
  height:var(--ong-item-hauteur); padding:0 var(--e1) 0 var(--e4);
  border:1px solid var(--line); border-radius:var(--r2);
  background:var(--carte); color:var(--txt-3);
  font-size:var(--t3); font-weight:var(--gras-normal);
  flex-shrink:0; max-width:var(--ong-item-large);
}
.ong-i:hover{border-color:var(--orange); color:var(--navy)}

/* L'onglet regardé prend le bleu nuit de la barre latérale — la couleur
   du CRM, pas une de plus. */
.ong-i.on{background:var(--navy); border-color:var(--navy); color:#fff;
  font-weight:var(--gras-fort)}

.ong-n{overflow:hidden; text-overflow:ellipsis}

/* Cible cliquable confortable, discrète au repos : on ferme un onglet
   souvent, on ne doit pas le faire par accident. */
.ong-x{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--ong-croix); height:var(--ong-croix); flex-shrink:0;
  border-radius:var(--r1); font-size:var(--t1); line-height:1;
  color:inherit; opacity:.55;
}
.ong-x:hover{opacity:1; background:var(--etat-alerte-fond);
  color:var(--etat-alerte-texte)}
.ong-i.on .ong-x:hover{background:rgba(255,255,255,.22); color:#fff}

/* À l'impression, la barre n'a rien à dire. */
@media print{.ong{display:none}}

/* ------------------------------------------------------------------
   LE SUIVI MENSUEL — Achats · Ventes · Banque

   Trois tableaux s'y empilaient, chacun défilant dans son cadre de
   522 px, sur une page qui défilait elle-même. Deux défilements
   imbriqués, et cent quinze écritures bancaires dans une lucarne.

   Ici : un seul tableau à l'écran, choisi par onglet, qui prend toute
   sa hauteur. La page défile — un seul niveau.

   Toutes les valeurs viennent de la charte.
   ------------------------------------------------------------------ */

/* LA BANDE DE SYNTHÈSE — composant du CRM, pas du seul suivi mensuel.
   Là où des cartes de cent pixels se suivaient, les mêmes chiffres se lisent
   en ligne et rendent la hauteur au contenu qui compte. Elle s'adapte au
   nombre de mesures : quatre en comptabilité, cinq au pilotage. */
.bande{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  background:var(--carte);border:1px solid var(--line);
  border-radius:var(--r3);overflow:hidden;flex-shrink:0}
.bande > div{padding:var(--e4) var(--e6);border-left:1px solid var(--line)}
.bande > div:first-child{border-left:0}
.bande .kl{font-size:var(--t2);color:var(--mut);
  font-weight:var(--gras-fort);text-transform:uppercase;letter-spacing:.5px}
.bande .kv{font-size:var(--t7);color:var(--navy);
  font-weight:var(--gras-fort);margin-top:var(--e1)}
.bande .kv.rg{color:var(--red)}
/* Ces deux-là ne vivaient que sous `.pil-bande`, sans raison : une mesure
   à surveiller ou une mesure au vert se disent pareil partout. */
.bande .kv.or{color:var(--orange)}
.bande .kv.vt{color:var(--green)}
.bande .kd{font-size:var(--t2);color:var(--txt-3);margin-top:2px;
  line-height:1.4}

/* LA LIGNE D'ACTION — composant du CRM.
   Ce qu'il y a à faire sur cet écran, sur une ligne, en tête. Le liseré
   orange dit qu'il y a quelque chose à faire ; « calme » l'éteint quand
   il n'y a rien, sans que la ligne disparaisse ni que la page saute. */
.ligne-act{display:flex;align-items:center;gap:var(--e5);flex-shrink:0;
  background:var(--carte);border:1px solid var(--line);
  border-left:3px solid var(--orange);border-radius:var(--r3);
  padding:var(--e5) var(--e6);flex-wrap:wrap;
  /* En dessous, la phrase et les boutons passent l'un sous l'autre plutôt
     que de se serrer. Nommé ici : c'est un seuil propre à cette ligne, il
     n'a rien à faire dans la charte. */
  --seuil-repli:220px}
.ligne-act.calme{border-left-color:var(--line)}
.ligne-act .txt{flex:1;min-width:var(--seuil-repli)}
.ligne-act .t{font-size:var(--t5);font-weight:var(--gras-fort);color:var(--navy)}
.ligne-act .s{font-size:var(--t3);color:var(--txt-3);margin-top:2px;line-height:1.45}
.ligne-act form{margin:0}

/* Les trois dossiers, en onglets. */
.dos-bloc{overflow:visible}
.dos-ong{display:flex;align-items:center;gap:var(--e2);
  padding:var(--e4) var(--e6) 0;border-bottom:1px solid var(--line);
  flex-shrink:0}
.dos-o{display:inline-flex;align-items:baseline;gap:var(--e2);
  padding:var(--e3) var(--e5);font-family:inherit;font-size:var(--t4);
  font-weight:var(--gras-normal);color:var(--txt-3);cursor:pointer;
  border:0;border-bottom:2px solid transparent;margin-bottom:-1px;
  background:none;border-radius:var(--r2) var(--r2) 0 0}
.dos-o span{font-size:var(--t2);color:var(--mut)}
.dos-o:hover{color:var(--navy)}
.dos-o.on{color:var(--navy);font-weight:var(--gras-fort);
  border-bottom-color:var(--orange)}
.dos-o.on span{color:var(--orange)}
.dos-exp{margin-left:auto;font-size:var(--t2);color:var(--mut);
  padding-bottom:var(--e3)}
.dos-exp a{color:var(--cyan);font-weight:var(--gras-fort);
  margin-left:var(--e3)}

.dos-vue{display:none}
.dos-vue.on{display:block}

/* La légende des pastilles, sous le tableau qu'elle éclaire. */
.dos-leg{display:flex;gap:var(--e6);align-items:center;flex-wrap:wrap;
  padding:var(--e3) var(--e6);border-top:1px solid var(--line);
  font-size:var(--t2);color:var(--mut);background:#FCFDFF}
.dos-leg span{display:inline-flex;align-items:center;gap:var(--e2)}

/* L'avertissement TVA, descendu en note. */
.cpt-note{font-size:var(--t2);color:var(--mut);line-height:1.55;
  padding:0 var(--e2);flex-shrink:0}
.cpt-note b{color:var(--txt-2)}

/* ------------------------------------------------------------------
   LE TABLEAU QUI RESPIRE

   « aere » ne s'applique qu'ici. Les cellules avaient « padding: 0 6px »
   — aucun espace vertical, c'était le « trop serré ». Et le plafond de
   quinze lignes enfermait le tableau dans une lucarne : il tombe, la
   page défile à sa place.

   Les cinq autres écrans comptables gardent « cpt-tb » tel quel. Ce
   modificateur deviendra le défaut quand la charte passera sur eux.
   ------------------------------------------------------------------ */
.cpt-tb.aere{max-height:none;overflow:visible}
.cpt-tb.aere tbody td{height:auto;padding:var(--e2) var(--e5)}
.cpt-tb.aere thead th{padding:var(--e3) var(--e5)}
/* Un filet plutôt que des zébrures : à quinze lignes la zébrure aide,
   à cent quinze elle fatigue. */
.cpt-tb.aere tbody tr:nth-child(even) td{background:transparent}
.cpt-tb.aere tbody td{border-bottom:1px solid var(--line)}
.cpt-tb.aere tbody tr:last-child td{border-bottom:0}
.cpt-tb.aere tbody tr:hover td{background:#F8FAFD}
.cpt-tb.aere tbody tr:nth-child(even) td:first-child,
.cpt-tb.aere tbody tr:nth-child(odd) td:first-child{background:var(--carte)}
.cpt-tb.aere tbody tr:hover td:first-child{background:#F8FAFD}
.cpt-tb.aere tfoot td{background:var(--bg);color:var(--navy);
  font-weight:var(--gras-fort);font-size:var(--t3);
  padding:var(--e3) var(--e5);border-top:1px solid var(--line);
  position:sticky;bottom:0}
.cpt-tb.aere tfoot td.g{font-weight:var(--gras-normal);color:var(--txt-3)}
.cpt-tb.aere tfoot td.rg{color:var(--red)}

/* ------------------------------------------------------------------
   PILOTAGE FINANCIER — L'ACCUEIL

   L'écran tenait déjà en une page : sa longueur n'était pas le
   problème. Sa hiérarchie l'était. Cinq cartes de cent pixels
   occupaient le tiers supérieur pour cinq nombres, puis cinq blocs de
   tailles disparates — 444, 333, 274, 246, 246 px — se répartissaient
   sans qu'aucun ne se distingue.

   La bande rend cent cinquante pixels au contenu. Et les soixante-treize
   inscriptions de style qui vivaient dans le gabarit descendent ici :
   il n'en reste que huit, qui portent une **donnée** — une largeur, une
   hauteur, une teinte calculée depuis le nom d'un client — et jamais
   une couleur ni une taille choisies à la main.
   ------------------------------------------------------------------ */

/* La bande du pilotage porte cinq mesures, dont une avec sa jauge :
   un peu plus haute que celle de la comptabilité, qui n'en a que quatre. */
.pil-bande{flex-shrink:0}
.pil-bande .kd.rg{color:var(--red);font-weight:var(--gras-fort)}
.pil-bande .kd.vt{color:var(--green);font-weight:var(--gras-fort)}

/* La jauge d'atteinte. « --part » vient du serveur ; tout le reste est ici. */
.pil-jauge{height:5px;border-radius:var(--r1);background:#EAEEF7;
  margin-top:var(--e3);overflow:hidden}
.pil-jauge.haute{height:8px}
.pil-jauge span{display:block;height:100%;border-radius:var(--r1);
  background:linear-gradient(90deg,var(--cyan),var(--orange));
  width:var(--part,0%);max-width:100%}

/* Le sélecteur d'exercice, dans l'en-tête. */
.pil-exo{max-width:180px;height:29px;border-radius:var(--r4)}

/* Le graphique mois par mois : deux barres accolées par mois.

   **Un défaut qui précédait cette refonte, et qui la précédait de loin :
   les barres ne se voyaient pas.** Leur hauteur est un pourcentage, et un
   pourcentage se calcule sur un parent de hauteur connue. Le conteneur qui
   les portait n'en avait aucune — sa hauteur venait de son contenu, donc
   des barres elles-mêmes. Chacune valait zéro, quel que soit le chiffre.

   « flex:1 » lui donne la hauteur que la colonne lui laisse : une valeur
   définie, sur laquelle les pourcentages ont enfin un sens. */
.pil-paire{width:100%;flex:1;min-height:0;display:flex;gap:3px;
  align-items:flex-end;justify-content:center}
.pil-paire .bar{height:var(--h,0%);max-width:19px}
.pil-leg{margin-top:var(--e3)}
.leg i.p-navy{background:var(--navy)}
.leg i.p-or{background:var(--orange)}
.leg i.p-vt{background:var(--green)}
.leg i.p-rg{background:var(--red)}
.leg i.p-fut{background:#E5EAF4}
.sg i.p-vt{background:var(--green)}
.sg i.p-or{background:var(--orange)}
.sg i.p-rg{background:var(--red)}

/* La barre segmentée : « --f » est la part de chaque segment. */
.segbar span.s-vt{background:var(--green);flex:var(--f,0)}
.segbar span.s-or{background:var(--orange);flex:var(--f,0)}
.segbar span.s-rg{background:var(--red);flex:var(--f,0)}

/* L'en-tête d'une carte qui enveloppe un tableau : le retrait du bas
   revient au tableau lui-même. */
.ch-p0{padding:var(--e6) var(--e7) 0}

/* L'objectif de l'exercice, le seul chiffre de la page à cette taille :
   c'est la question que l'écran pose. */
.pil-gros{font-size:30px}
.kvl-1{margin-top:var(--e4)}
.kvl .v.or{color:var(--orange)}
.kvl .v.vt{color:var(--green)}
.pil-note{font-size:var(--t2);color:var(--mut);margin-top:var(--e4);
  line-height:1.5}
.pil-note b{color:var(--navy)}

/* L'avatar d'un client : sa teinte se calcule depuis son nom, elle vient
   donc du serveur comme une donnée. */
.av2{background:var(--teinte,var(--navy))}

/* ------------------------------------------------------------------
   TRÉSORERIE ET FACTURES & CRÉANCES

   Deux écrans de flux quotidien. Ils portaient à eux deux cent dix-sept
   inscriptions de style dans leurs gabarits — l'essentiel venant du
   bouton de retrait, répété sur chaque ligne du registre.

   Ils reprennent les trois composants du module : la bande de synthèse,
   la ligne d'action, le tableau qui respire.
   ------------------------------------------------------------------ */

/* Le corps d'une carte dont l'en-tête garde son retrait. */
.carte-corps{padding:0 var(--e6) var(--e6)}

/* Le formulaire posé dans une carte : mêmes retraits que le reste. */
.frm-carte{padding:var(--e6);gap:var(--e4)}

/* Un champ qui porte des suggestions doit ancrer leur boîte. */
.fld-sug{position:relative}

/* Un solde de compte, entre le chiffre de bande et le titre de page. */
.kv-moyen{font-size:var(--t7);margin:var(--e2) 0}

/* Le retrait d'une ligne : discret au repos, rouge sous le doigt. Il
   était écrit trois fois par ligne du registre, soit plus de cent
   inscriptions sur un écran qui en compte cinquante-deux. */
.en-ligne{display:inline}
.croix{padding:2px var(--e2);border-radius:var(--r1);color:var(--mut);
  font-size:var(--t3);line-height:1}
.croix:hover{background:var(--etat-alerte-fond);color:var(--etat-alerte-texte)}

/* La boîte de suggestions se cache par « hidden », pas par un style
   écrit depuis le JavaScript. */
.adr-sug[hidden]{display:none}

/* La phrase qui explique un dossier, sous ses onglets. Elle disait la même
   chose dans un en-tête de carte que les onglets rendent inutile. */
.dos-quoi{font-size:var(--t3);color:var(--txt-3);line-height:1.5;
  padding:var(--e4) var(--e6) 0;margin:0}

/* ------------------------------------------------------------------
   VAGUE 4 — analyse, objectifs, vues, registre, journal

   Les cinq derniers écrans du module. Ils ne portaient que trente-six
   inscriptions, mais toutes reprenaient des motifs déjà outillés par les
   vagues précédentes : le sélecteur d'exercice, le retrait d'une ligne,
   le corps d'une carte, le formulaire posé dedans.
   ------------------------------------------------------------------ */

.en-ligne-flex{display:inline-flex}
.frm-carte-haut{padding:var(--e6) var(--e6) 0;gap:var(--e4)}

/* Le bouton qui bascule un statut : c'est la pastille qu'on clique, pas
   un bouton qui contiendrait une pastille. */
.bascule-etat{padding:0;line-height:1}
.bascule-etat:hover .etat{filter:brightness(.94)}

/* Un bouton volontairement hors service : il dit pourquoi il ne sert pas
   au lieu de disparaître, et se voit qu'il ne servira pas. */
.btn.inerte{opacity:.55;cursor:not-allowed;margin-left:var(--e3)}
.btn.inerte:hover{filter:none}

/* Les graphiques des vues : la part vient du serveur, la forme est ici. */
.pil-col{height:var(--h,0%)}
.pil-bar{width:var(--part,0%)}

/* Le corps d'une carte, resserré quand ce qu'il porte est une phrase et
   non un tableau. */
.carte-corps.serre{padding-bottom:var(--e4)}
/* Une pile de cartes qui défile. */
.scroll.pile{display:flex;flex-direction:column;gap:var(--e5)}

/* ------------------------------------------------------------------
   LES PASTILLES D'ÉTAT — une seule vérité de couleur

   Le CRM en portait trois familles pour le même travail : « pill »,
   « tag » et « chip ». L'audit y a relevé **deux verts pour « signé »,
   trois gris pour « neutre », deux oranges de fond** — des écarts trop
   petits pour porter un sens, trop grands pour être un hasard. Puis
   j'en ai ajouté une quatrième, « etat », en refondant le pilotage :
   quatre familles valent moins que trois.

   Plutôt que de réécrire vingt gabarits — deux mille lignes touchées
   pour un changement de couleur —, les trois anciennes familles
   **empruntent les valeurs de la charte**. La cohérence est immédiate
   sur tous les écrans, et pas une ligne de gabarit ne bouge.

   La migration des noms suivra, écran par écran, quand la charte
   passera dessus. Ce bloc disparaîtra ce jour-là.

   Correspondances, du sens vers les anciens noms :
     neutre   nu · pa · soon · nu(chip)
     info     cy · nv · sp · ec
     succès   ok · done
     attente  wa · pr · today
     alerte   ko · no · late
     recette  te — les hachures restent, une fiche de test doit se voir
   ------------------------------------------------------------------ */

.pill.nu, .tag.pa, .chip.soon, .chip.nu{
  background:var(--etat-neutre-fond); color:var(--etat-neutre-texte)}

.pill.cy, .pill.nv, .tag.sp, .tag.ec{
  background:var(--etat-info-fond); color:var(--etat-info-texte)}

.pill.ok, .tag.ok, .chip.done{
  background:var(--etat-succes-fond); color:var(--etat-succes-texte)}

.pill.wa, .tag.pr, .chip.today{
  background:var(--etat-attente-fond); color:var(--etat-attente-texte)}

.pill.ko, .tag.no, .chip.late{
  background:var(--etat-alerte-fond); color:var(--etat-alerte-texte)}

/* Une seule taille, aussi : les trois familles allaient de 8,8 à 9,4 px
   et de 9 à 10 px de rayon, pour des objets qui se côtoient sur la même
   ligne d'un tableau. */
.pill, .tag, .chip{font-size:var(--t1); font-weight:var(--gras-fort);
  padding:3px var(--e3); border-radius:var(--r2); white-space:nowrap}

/* ==================================================================
   RESPONSIVE — le CRM descend jusqu'à la tablette

   Il était figé : 1 600 px dans la maquette, ramenés à un plancher de
   1 100 px par cette couche, et **pas une seule requête média en
   largeur** dans les deux fichiers. Sous ce plancher la page débordait,
   et il fallait défiler horizontalement en permanence. Ce n'était pas un
   défaut de finition : c'était une décision jamais prise.

   Elle l'est. **La cible est la tablette et le portable en fenêtre
   réduite, jusqu'à 768 px.** Le téléphone n'en fait pas partie —
   chiffrer un devis à vingt lignes ou rapprocher un relevé bancaire
   demande de la largeur, et prétendre le contraire ferait une promesse
   qu'aucun écran de 390 px ne tient.

   Trois paliers, chacun ne défaisant que ce qui vient de casser :

     · sous 1200 px — les grilles de cinq et six colonnes se replient ;
     · sous 1000 px — la barre latérale se réduit à ses icônes ;
     · sous  768 px — elle passe derrière un bouton, tout s'empile.

   **Au-dessus de 1200 px, pas une règle ne s'applique** : l'écran de
   travail habituel reste exactement celui qu'il était.
   ================================================================== */

/* ------------------------------------------------------------------
   UN TABLEAU VIDE NE RÉSERVE PLUS SA LARGEUR

   Trouvé en mesurant la fiche client, et **antérieur à tout ce qui
   suit** : sa colonne de droite débordait déjà de 162 px dans une
   fenêtre de 1 200 px, et `.wrap` coupait ce qui dépassait. Le module
   Factures était donc amputé de sa dernière colonne sur tout écran de
   moins de 1 360 px environ.

   La cause : `.cpt-tb table{min-width:720px}` — un plancher qui a du
   sens quand il y a des lignes à aligner — s'appliquait aussi au
   tableau **sans aucune ligne**. Et comme la variante « vide » n'a pas
   de cadre défilant (`overflow:visible`, voulu : pas de lucarne pour
   trois mots), ces 720 px remontaient jusqu'à la colonne et poussaient
   toute la fiche hors de l'écran.

   Un tableau sans ligne n'a rien à aligner. Son plancher tombe.
   ------------------------------------------------------------------ */
.cpt-tb.vide table{min-width:0}

/* La largeur maximale de la colonne étroite d'une fiche — celle qui
   porte l'identité, les contacts, le résumé. Elle vivait en clair dans
   cinq gabarits (`style="max-width:330px"`), donc hors d'atteinte de
   toute requête média : une déclaration en ligne ne se défait pas. Le
   nombre reste une donnée du gabarit, porté par la variable ; la règle
   qui l'applique vit ici, et peut donc se lever quand la place manque. */
.col-fixe{max-width:var(--col-fixe, 360px)}

/* Le bouton du tiroir n'existe qu'en dessous du seuil : au-dessus, le
   menu est là, un bouton pour l'ouvrir n'aurait pas de sens. */
.menu-bouton{display:none; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:var(--r2); color:var(--navy);
  border:1px solid var(--line); background:var(--carte); flex-shrink:0;
  cursor:pointer; padding:0}
.menu-bouton:hover{border-color:var(--orange); color:var(--orange)}

/* ---------- SOUS 1200 px : les grilles larges se replient ---------- */
@media (max-width: 1200px) {
  /* Cinq ou six colonnes ne tiennent plus ; trois restent lisibles. Les
     cartes gardent tout leur contenu, elles descendent d'un rang. */
  .kpis, .cats, .s5, .s6, .kan, .wk{grid-template-columns:repeat(3,1fr)}
  .s4, .g4, .phg{grid-template-columns:repeat(2,1fr)}

  /* La bande de chiffres passe du flux en colonnes à une vraie grille :
     ses séparateurs, jusqu'ici à gauche, deviennent des filets du haut
     pour tout ce qui n'est plus au premier rang. */
  .bande{grid-auto-flow:row; grid-template-columns:repeat(3,1fr)}
  .bande > div{border-left:0; border-top:1px solid var(--line)}
  .bande > div:nth-child(-n+3){border-top:0}

  /* Le pilotage tient sa colonne de droite à 1 pour 1,62 : sous
     1 200 px elle tombait à 250 px et son contenu se brisait. Elle
     passe dessous, à pleine largeur. */
  .cols{grid-template-columns:1fr}
}

/* ---------- SOUS 1000 px : la barre latérale perd ses mots ---------- */
@media (max-width: 1000px) {
  /* 238 px de menu sur 1 000, c'est un quart de l'écran pour de la
     navigation. Les libellés s'effacent, les icônes restent — et le
     libellé reparaît en infobulle, posée dans le gabarit. */
  .side{width:var(--rail)}
  .side .logo{margin:0 var(--e2) var(--e2); padding:var(--e2)}
  .side .logo img{height:26px}
  .side .sub{display:none}
  .nl span{display:none}
  .nl{justify-content:center; padding-left:0; padding-right:0}
  .sfoot{padding:var(--e3) var(--e2)}
  .sfoot .u > div:last-child{display:none}
  .sfoot .ua{margin:0 auto}

  .kpis, .cats, .s5, .s6, .kan, .wk, .agents, .g3{grid-template-columns:repeat(2,1fr)}
  .bande{grid-template-columns:repeat(2,1fr)}
  .bande > div:nth-child(3){border-top:1px solid var(--line)}

  /* L'en-tête cesse d'être une ligne intraitable : il a le droit de
     passer sur deux rangs, et la recherche prend le second pour elle. */
  .top{height:auto; min-height:60px; flex-wrap:wrap; padding-top:var(--e3);
       padding-bottom:var(--e3); row-gap:var(--e3)}
  .h1{white-space:normal}
  .srch{margin-left:0; max-width:none; order:3; flex-basis:100%}
  .sp{display:none}

  /* Le tableau comptable aéré avait rendu la main à la page : plus de
     lucarne, plus de défilement interne — c'est ce qui fait tenir son
     en-tête collé pendant qu'on descend. Mais ici la largeur manque, et
     `.wrap` coupe ce qui dépasse : mesuré à 768 px, la colonne
     Règlement était **hors d'atteinte**, pas seulement hors de vue.

     Sous le seuil, il redevient donc son propre cadre de défilement.
     **Ce qui se paie** : l'en-tête ne suit plus la descente, il reste en
     tête du tableau. Une colonne qu'on ne peut pas lire est pire qu'un
     en-tête qui ne suit pas. Au-dessus du seuil, rien ne change. */
  .cpt-tb.aere{overflow-x:auto}

  /* La barre de filtres tenait sur une seule ligne sans jamais se
     replier, et ses champs, qui font 100 % de leur place, se laissaient
     comprimer : « Tous les statuts » devenait « Tous les statut ». Elle
     passe sur plusieurs rangs, et chaque champ reprend sa largeur. */
  .tb{flex-wrap:wrap; row-gap:var(--e3)}
  .tb > .inp{width:auto; min-width:0}

  /* Les fiches — client, contact, devis, produit, affaire — posent une
     colonne étroite à gauche et le gros du contenu à droite. Le rapport
     de 1 à 2 ne veut plus rien dire quand le tout fait 900 px : la
     colonne de droite passe sous la gauche, chacune à pleine largeur,
     et le plafond de la colonne étroite se lève.

     `rep3` est écartée nommément : c'est la seule rangée qui sache déjà
     se replier toute seule — ses cartes ont un plancher de 270 px et la
     rangée les enroule. Lui imposer la colonne défairait un travail
     juste. Les documents PDF, qui emploient les mêmes noms, ne chargent
     pas ce fichier : ils ne sont pas concernés. */
  .row:not(.rep3){flex-direction:column}
  .row:not(.rep3) > .col{min-width:0}
  .col-fixe{max-width:none}

  /* ---- LES LISTES : elles défilent au lieu de s'écraser ----

     `table{width:100%}` n'est pas une largeur, c'est un plafond : quand
     la place manque, le navigateur ne fait pas déborder le tableau, il
     replie les cellules. Mesuré sur les 238 clients à 768 px, la
     colonne CA affichait « 258,76 € » sur **trois lignes** — le montant
     coupé entre ses milliers et son symbole. Rendre `overflow-x` au
     conteneur ne suffisait donc à rien : il n'y avait rien à faire
     défiler.

     C'est le repli qu'on interdit. Chaque cellule tient sur sa ligne,
     le tableau reprend sa largeur naturelle — 991 px pour cette liste —
     et le cadre le fait défiler.

     **Sauf la première colonne**, qui garde le droit de se replier : sur
     un tableau à huit colonnes elle porte le nom, et « Amicale des
     sapeurs-pompiers de la région de Beaurepaire » sur une seule ligne
     mangerait la moitié de l'écran.

     Et elle reste collée à gauche, comme le fait déjà le tableau
     comptable : sans elle, on défile vers la droite pour lire des
     chiffres sans plus savoir de qui ils sont. */
  .scroll > table th, .scroll > table td{white-space:nowrap}
  .scroll > table th:first-child,
  .scroll > table td:first-child{
    white-space:normal; max-width:230px;
    position:sticky; left:0; z-index:1; background:var(--carte)}
  .scroll > table thead th:first-child{z-index:3}
  .scroll > table tbody tr:hover td:first-child{background:#F8FAFD}
  /* Les bordures d'un tableau en `border-collapse` ne suivent pas une
     cellule collante : le filet de séparation est dessiné à part. */
  .scroll > table th:first-child::before,
  .scroll > table td:first-child::before{content:"";
    position:absolute; top:0; bottom:0; right:0; width:1px;
    background:var(--line)}
}

/* ---------- SOUS 768 px : le menu passe derrière un bouton ---------- */
@media (max-width: 768px) {
  /* Même réduit à ses icônes, le rail prend de la place qu'il n'y a
     plus. Il devient un tiroir : hors champ, il se pose par-dessus la
     page quand on l'appelle, et il retrouve alors ses libellés — on
     ne navigue pas à l'icône dans un menu qu'on vient d'ouvrir. */
  .side{position:fixed; top:0; left:0; bottom:0; z-index:60; width:238px;
        /* Sur un écran bas — un portable en paysage — le menu entier ne
           tient pas en hauteur : il défile pour son compte. */
        overflow-y:auto;
        transform:translateX(-100%); transition:transform .18s ease}
  .side.ouvert{transform:translateX(0)}
  .side .logo{margin:0 var(--e5) var(--e2); padding:11px 14px}
  .side .logo img{height:44px}
  .side .sub{display:block}
  .nl span{display:inline}
  .nl{justify-content:flex-start; padding-left:18px; padding-right:18px}
  .sfoot{padding:13px 18px}
  .sfoot .u > div:last-child{display:block}
  .sfoot .ua{margin:0}

  /* Le voile ferme le tiroir d'un clic n'importe où, et dit clairement
     que la page derrière n'est pas active. */
  .voile{position:fixed; inset:0; z-index:59; background:rgba(34,49,92,.42)}
  .voile[hidden]{display:none}
  .menu-bouton{display:inline-flex}

  /* Tout s'empile. Deux colonnes de 370 px, ce n'est déjà plus deux
     colonnes ; un formulaire à deux champs par rang non plus. */
  .kpis, .cats, .s5, .s6, .kan, .wk, .agents, .g3, .g2, .s4, .g4, .phg,
  .frm, .bande{grid-template-columns:1fr}
  .bande > div{border-top:1px solid var(--line)}
  .bande > div:first-child{border-top:0}

  /* La page se resserre, et la barre d'onglets suit son retrait —
     sinon son fond ne couvrirait plus les bords. */
  .wrap{padding:var(--e4) var(--e5)}
  .ong{margin-left:calc(-1 * var(--e5)); margin-right:calc(-1 * var(--e5));
       padding-left:var(--e5); padding-right:var(--e5)}
}

/* ---------- LES TABLEAUX, À TOUTES LES LARGEURS ----------
   Un tableau de huit colonnes ne se replie pas : il défile dans son
   cadre. C'est la seule réponse honnête — le transformer en fiches
   empilées demanderait de réécrire vingt-trois tableaux pour un usage
   qui n'est pas la cible, et ferait perdre la comparaison ligne à ligne
   qui est justement ce qu'on vient y chercher.

   Le conteneur `.scroll` — vingt-trois tableaux du CRM — défilait déjà
   verticalement ; il coupait horizontalement (`overflow:hidden` hérité
   de la maquette), ce qui rendait les dernières colonnes inatteignables
   au lieu de les faire défiler. `.cpt-tb` avait déjà son `overflow:auto`
   et n'est pas touché ; son variante aérée est traitée plus haut, sous
   le seuil de 1000 px. */
.scroll{overflow-x:auto}

/* ==================================================================
   LES GABARITS RENDENT LEURS VALEURS

   L'audit avait compté **573 attributs `style="…"` écrits en clair dans
   les gabarits**. Six d'entre eux en portaient 187 à eux seuls. Tant
   qu'une valeur vit là, elle est hors d'atteinte : changer un jeton de
   la charte ne l'atteint pas, et une requête média non plus — on vient
   d'en faire l'expérience avec cinq `max-width:330px` qui ont bloqué le
   responsive et qu'il a fallu sortir un par un.

   Ce qui suit n'invente presque rien. La plupart des styles se
   rabattent sur des classes **qui existaient déjà** — `td.r`, `.f1`,
   `.g`, `.en-ligne` — et n'avaient simplement pas été employées. Le
   reste devient un composant, quand le même motif revient dans deux
   gabarits ou plus.

   **Ce qui change à l'écran**, et c'est voulu : les valeurs se rangent
   sur les échelles de la charte. `10,5px` et `9,6px` deviennent 10 et
   9 ; `font-weight:700` devient la seule graisse d'emphase du CRM, 800.
   La charte le prescrit — « les décimales s'y rangent » — et c'est
   précisément ce chantier qui l'applique.

   Ce qui **reste** en clair dans un gabarit : ce qui porte une donnée
   et non une apparence. Une teinte calculée depuis le nom d'un client,
   une couleur qui dépend d'une marge, une largeur propre à une colonne
   qu'un seul écran possède.
   ================================================================== */

/* La ligne appuyée d'une liste clé-valeur : un filet la détache, et
   ses deux membres passent en emphase. Trois gabarits la dessinaient
   à la main, chacun à sa façon.

   À ne pas confondre avec `.kvl.tot`, qui existe déjà dans la maquette :
   celle-là est le **total d'un devis** — filet marine épais, valeur en
   orange et plus grande. Celle-ci ne fait qu'appuyer une ligne parmi
   d'autres. Deux intentions, deux noms. */
.kvl.fort{border-top:1px solid var(--line); margin-top:var(--e1);
  padding-top:var(--e3)}
.kvl.fort .k{font-weight:var(--gras-fort); color:var(--navy)}
.kvl.fort .v{font-weight:var(--gras-fort)}

/* La phrase qui explique, sous le contenu qu'elle éclaire. Plus petite,
   plus pâle, jamais en gras — si elle a besoin de gras, ce n'est pas
   une aide, c'est un message. */
.aide{font-size:var(--t2); color:var(--mut); margin-top:var(--e3);
  line-height:1.45}

/* Le titre d'un bloc à l'intérieur d'une carte — au-dessus d'un groupe
   de lignes, là où `.ch` serait trop lourd. */
.titre-b{font-weight:var(--gras-fort); color:var(--navy)}

/* La petite étiquette capitale, au-dessus d'une valeur. Elle existait
   déjà sous le nom `.fl2`, mais enfermée dans `.fld` : hors d'un champ
   de formulaire, chacun la réécrivait. */
.etq{font-size:var(--t1); color:var(--mut); text-transform:uppercase;
  letter-spacing:.7px; font-weight:var(--gras-normal)}

/* Le nombre qu'on met en avant sous son étiquette. */
.val-forte{font-size:var(--t5); font-weight:var(--gras-fort);
  color:var(--navy); margin-top:3px}

/* Les champs numériques d'un tableau de saisie. Leur largeur n'est pas
   une décoration : elle dit ce qu'on y écrit. Trois tailles suffisent
   aux six gabarits, là où on comptait onze largeurs différentes. */
.inp.nb{width:100px}                           /* une quantité */
.inp.eur{width:84px; text-align:right}         /* un montant */
/* Le champ qu'on veut voir en premier — le prix de vente, partout. Une
   seule règle : elle vaut quelle que soit la largeur du champ. */
.inp.fort{font-weight:var(--gras-fort)}
.inp.pt{width:74px; text-align:right}          /* un montant, colonne étroite */

/* La ligne de saisie qui attend une nouvelle entrée, en bas d'un
   tableau : elle se distingue des lignes déjà enregistrées. */
.tr-saisie{background:var(--fond-2)}

/* Un filet qui sépare deux groupes dans une même carte. */
.sep-h{border-top:1px solid var(--line); margin-top:var(--e1);
  padding-top:var(--e3)}

/* La mention discrète, dans une cellule ou au fil du texte. Nommée
   `txt-mini` et non `mini` : ce dernier est déjà, dans la maquette, un
   petit bouton — deux choses sans rapport. */
.txt-mini{font-size:var(--t2)}

/* ---- Géométrie des tableaux de saisie ----
   Un tableau a une forme, et cette forme lui appartient : elle se dit
   une fois, à son nom, plutôt qu'une fois par cellule dans le gabarit. */

/* Fiche produit — les paliers de prix. */
.tb-paliers th:first-child{width:26%}
.tb-paliers th:last-child{width:70px}

/* ---- L'EN-TÊTE D'UNE FICHE ----
   `.hero` existe dans la maquette, mais seulement pour ses trois
   premiers éléments. Ce qu'il contient — le bloc qui s'étire, et le
   chiffre calé à droite — était redessiné à la main dans chaque fiche. */
.hero > .info{flex:1; min-width:0}
.hero > .chiffre{text-align:right; flex-shrink:0}
.val-hero{font-size:var(--t8); font-weight:var(--gras-fort);
  color:var(--navy); margin-top:3px}
/* La mention qui suit une valeur, juste dessous. */
.sous-val{font-size:var(--t2); color:var(--mut); margin-top:2px}

/* ---- LE CORPS D'UNE CARTE SANS RETRAIT ----
   `.card.p0` retire le retrait pour qu'un tableau touche les bords ;
   tout ce qui n'est pas un tableau doit alors le remettre. Onze
   gabarits écrivaient `padding:0 14px 14px` en clair, et trois autres
   des variantes de deux pixels. */
.corps{padding:0 var(--e6) var(--e6)}
/* L'en-tête de la même carte, qui doit se caler sur ce corps. Deux
   besoins, deux classes : `tete` colle au contenu qui suit — un tableau
   qui commence juste dessous — tandis que `tete-aeree` garde son air en
   dessous, quand ce qui suit est une barre de recherche ou un bloc. */
.ch.tete{padding:var(--e6) var(--e6) 0}
.ch.tete-aeree{padding:var(--e5) var(--e6)}
/* Une suite de pastilles ou de petits boutons, qui va à la ligne. */
.corps.puces{display:flex; flex-wrap:wrap; gap:var(--e2)}
/* Un formulaire posé dans le corps d'une carte : ses champs se serrent,
   la carte porte déjà l'air autour. */
.frm.dans-carte{gap:var(--e4)}

/* ---- UTILITAIRES DE DISPOSITION ----
   Deux seulement, parce qu'ils reviennent partout et qu'aucun nom
   métier ne les décrirait mieux. */
.min0{min-width:0}          /* un enfant flex a le droit de rétrécir */
.min-h0{min-height:0}       /* … et de ne pas imposer sa hauteur */
.a-droite{text-align:right; flex-shrink:0}

/* Une zone défilante dont la hauteur est plafonnée. Le plafond est une
   donnée — chaque carte choisit le sien — et se pose dans le gabarit
   par la variable ; c'est la règle qui vit ici. */
.scroll.cap{max-height:var(--cap)}

/* La ligne qui annonce une section dans un tableau de lignes. */
.tr-section td{padding-top:var(--e5)}

/* ---- ESPACEMENT — deux classes, pas une famille de plus ----
   `détaché` dit qu'un bloc s'écarte de ce qui le précède, `espace`
   qu'il s'écarte de ce qui le suit. Les valeurs viennent de l'échelle.
   Trois nuances de six, huit et douze pixels traînaient dans les
   gabarits pour dire la même chose : elles se rangent sur dix. */
.detache{margin-top:var(--e4)}
.detache-court{margin-top:var(--e1)}
.espace{margin-bottom:var(--e4)}
/* Une phrase seule qui a besoin d'air autour d'elle. */
.creux{padding:var(--e2) 2px}

/* Une colonne étroite ne tient pas un titre et son explication côte à côte :
   « ÉMETTRE UN AVOIR » se coupait en deux lignes pour laisser la moitié de la
   place à sa phrase d'aide. Dans une colonne à largeur fixée, l'en-tête d'une
   carte s'empile. */
.col-fixe .ch{flex-direction:column; align-items:flex-start; gap:2px}

/* Devis et facture — le tableau des lignes.

   **Les colonnes de chiffres se collent à leur contenu.** Une largeur figée
   à 44 % sur la désignation laissait les cinq autres se partager le reste :
   quinze, 17,10 € et 256,50 € flottaient chacun au milieu d'une colonne
   large de deux cents pixels, et l'œil devait parcourir tout l'écran pour
   rapprocher une quantité de son montant. « width:1% » demande à chaque
   colonne la place de son contenu, ni plus ; la désignation absorbe le
   reste, ce qui est bien son rôle. */
.tb-lignes th:not(:first-child),
.tb-lignes td:not(:first-child){width:1%; white-space:nowrap}

/* Son pied, quand il en a un : le total sous ce qu'il additionne. Le devis
   n'en portait pas — ses totaux vivent dans une carte à part — mais la
   facture gagne à montrer la somme au bas de ses propres lignes.

   Le libellé s'aligne à droite, contre son montant : étalé depuis le bord
   gauche sur cinq colonnes, « Total HT de la commande » se lisait à une
   demi-largeur d'écran du chiffre qu'il annonce. */
.tb-lignes tfoot td{border-top:1px solid var(--line);color:var(--navy);
  font-weight:var(--gras-fort);padding-top:var(--e2)}
.tb-lignes tfoot td[colspan]{text-align:right; padding-right:var(--e4)}

/* Un formulaire qui occupe toute la hauteur de l'écran et empile ses
   cartes : trois gabarits d'import et de saisie le redéclaraient. */
.pile-plein{display:flex; flex-direction:column; gap:var(--e5);
  flex:1; min-height:0}

/* Deux bandeaux d'alerte de plus, à côté du rouge de `.alerte` : ce qui
   demande attention, et ce qui informe.

   **Les valeurs sont celles d'aujourd'hui, à l'identique.** Les ranger
   sur la palette d'états de la charte (`--etat-attente-*`,
   `--etat-info-*`) changerait leur teinte de façon visible — l'ambre
   passerait au brun-orangé, le bleu au turquoise. C'est une décision à
   prendre à l'écran, pas un effet de bord de ce chantier. */
.alerte.attention{background:#FFF7E8; border-color:#F3D89B; color:#8A5A00}
.alerte.info{background:#EEF6FF; border-color:#BBD6F5; color:#1D4ED8}

/* Un pourcentage : plus court qu'un montant. */
.inp.pct{width:64px; text-align:right}
/* Un champ posé dans une pastille — le palier de prix d'un import. */
.chip .inp{width:58px; text-align:right; height:22px}
.chip{white-space:nowrap}

/* Import de catalogue — la prévisualisation ligne à ligne. Les largeurs
   minimales disent ce que chaque colonne doit pouvoir montrer sans
   qu'on ait à l'élargir à la main. */
.tb-import th:first-child{width:34px}
.tb-import .inp{min-width:90px}
.tb-import td:nth-child(4) .inp{min-width:180px}   /* la désignation */
.tb-import td:nth-child(7) .inp{min-width:80px}    /* le coloris */

/* Une mention en rouge, au fil du texte. */
.rouge{color:var(--red)}

/* Boutique en ligne — le tableau des articles. Chaque colonne dit ce
   qu'elle doit pouvoir montrer. Les largeurs vivaient sur les champs,
   répétées **deux fois** : dans le gabarit pour les lignes déjà
   enregistrées, et dans le JavaScript pour celles qu'on ajoute. Elles
   pouvaient donc diverger — et elles ne le peuvent plus. */
.tb-boutique td:nth-child(1) .inp{width:80px}
.tb-boutique td:nth-child(2) .inp{width:100px}
.tb-boutique td:nth-child(3) .inp{width:160px}
.tb-boutique td:nth-child(4) .inp{width:110px}
.tb-boutique td:nth-child(5) .inp{width:220px}
.tb-boutique td:nth-child(6) .inp{width:150px}
.tb-boutique td:nth-child(8) .inp,
.tb-boutique td:nth-child(9) .inp{width:74px; text-align:right}

/* Le compositeur de pack, dans sa modale. */
.tb-pack td:nth-child(2){width:90px}
.tb-pack td:nth-child(2) .inp{width:70px; text-align:right}
.tb-pack td:nth-child(3){width:40px}

/* Le corps d'un formulaire de rapprochement, en retrait sous la ligne
   de commande qu'il concerne. */
.corps-retrait{padding:0 var(--e5) var(--e5) 26px}



/* Chiffrage d'un devis — le grand tableau de saisie. Onze colonnes, dont
   dix tenaient leur pourcentage en clair dans le gabarit. */
.tb-chiffrage th:nth-child(1){width:11%}   /* Référence  */
.tb-chiffrage th:nth-child(3){width:7%}    /* Qté        */
.tb-chiffrage th:nth-child(4){width:12%}   /* Palier     */
.tb-chiffrage th:nth-child(5){width:9%}    /* PHT        */
.tb-chiffrage th:nth-child(6){width:7%}    /* Remise %   */
.tb-chiffrage th:nth-child(7){width:7%}    /* TVA %      */
.tb-chiffrage th:nth-child(8){width:8%}    /* PA         */
.tb-chiffrage th:nth-child(9){width:10%}   /* Montant HT */
.tb-chiffrage th:nth-child(10){width:10%}  /* Marge      */
.tb-chiffrage th:last-child{width:4%}
/* La glose sous un intitulé de colonne : plus petite, et rendue au poids
   normal du texte — un `th` est gras, elle ne doit pas l'être. 400 n'est
   pas une valeur de la charte : c'est l'absence d'emphase. */
.tb-chiffrage th .g{font-weight:400; font-size:var(--t1)}

/* Le récapitulatif d'un pack, redessiné par le JavaScript à chaque
   changement. Ses largeurs vivaient dans des chaînes de caractères. */
.tb-compo td:nth-child(1){width:52px}
.tb-compo td:nth-child(3){width:76px}
.tb-compo td:nth-child(4){width:74px}
.tb-compo td:nth-child(5){width:86px}
.tb-compo td:nth-child(6){width:34px}

/* Le récapitulatif par groupe, sous le tableau de chiffrage. */
.recap-tt{font-weight:var(--gras-fort); color:var(--navy); font-size:var(--t2);
  text-transform:uppercase; letter-spacing:.6px; margin-bottom:var(--e2)}
.recap-l{display:flex; gap:var(--e5); justify-content:space-between;
  padding:var(--e1) 0; border-top:1px solid var(--line); font-size:var(--t3)}

/* Un champ ramené à la taille d'une pastille — la recherche posée dans
   une ligne de tableau, le nom d'une proposition. */
.inp.pastille{height:30px; border-radius:var(--r4)}
.inp.pastille.courte{height:26px; border-radius:13px; width:170px}

/* Une barre de recherche posée en tête d'un tableau, dans une carte
   sans retrait : son panneau de suggestions se cale sur elle. */
.barre-rech{padding:var(--e4) var(--e6);
  border-bottom:1px solid var(--line); position:relative}
.barre-rech .af-sug{left:var(--e6); right:var(--e6)}

/* Un corps de carte qui ne porte qu'une phrase, sous un tableau. */
.corps-bas{padding:0 var(--e6) var(--e5)}

/* Un champ borné en largeur dans une grille de formulaire — quantité,
   pourcentage. Trois bornes suffisent aux gabarits de saisie. */
.fld.etroit{max-width:110px}
.fld.moyen{max-width:130px}
.inp.borne{max-width:320px}

/* Une aide qui suit immédiatement le champ qu'elle commente. */
.lk.colle{margin-top:3px}
/* Une glose qui ne doit pas hériter de l'emphase de son voisin. */
.lk.normale{font-weight:400}

/* Une colonne d'éléments espacés du pas courant. */
.pile{display:flex; flex-direction:column; gap:var(--e5)}
/* Le repère d'un panneau de suggestions posé par-dessus. */
.pos-rel{position:relative}

/* ---- LA FICHE D'UN TIERS ----
   Le gabarit le plus chargé du CRM : quarante-cinq valeurs écrites en
   clair. Ce qui suit nomme celles qui reviennent. */

/* Le titre d'un groupe dans une liste d'éléments secondaires — « Reçus »,
   « Envoyés » au-dessus des mails d'une fiche. */
.a2.titre{font-weight:var(--gras-fort); color:var(--navy);
  margin:2px 0 var(--e1)}
.a2.titre.detache{margin-top:var(--e4)}

/* Une rangée d'éléments côte à côte, du pas le plus serré. */
.rang{display:flex; gap:var(--e2)}
/* Un élément centré dans la rangée qui le porte. */
.centre-v{align-self:center}

/* La ligne qui coiffe une liste clé-valeur, plutôt que de la clore. */
.kvl.tete{border-bottom:1px solid var(--line);
  padding-bottom:var(--e3); margin-bottom:var(--e1)}
.kvl.tete .v{font-weight:var(--gras-fort)}

/* Une zone défilante dont les puces de fil ne doivent pas toucher le
   bord — le fil des notes et ses pastilles débordantes. */
.scroll.gouttiere{padding-left:var(--e2)}

/* L'objet d'une note, en tête de son corps. */
.note-objet{font-size:var(--t3); font-weight:var(--gras-normal);
  color:var(--txt-2)}

/* Les deux variantes de la pièce jointe d'une note : ce qui est simplement
   là, et ce qui a été fait. */
.pa.neutre{background:var(--fond-2); border-color:var(--line); color:var(--mut)}
.pa.ok{background:var(--etat-succes-fond); border-color:#BFE8D8}

/* La croix qui retire une ligne, dans une liste. */
.btn.x{font-size:var(--t5); line-height:1}

/* ==================================================================
   LES QUATRE ÉCRANS JAMAIS REPRIS

   Boutique en ligne, Catalogues, Agenda et Tâches & relances n'avaient
   jamais été touchés depuis leur écriture. Deux d'entre eux portaient
   **cinquante-six lignes de CSS dans le gabarit lui-même**, et
   vingt-quatre couleurs écrites en dur — dont une famille de violets
   qui n'existe nulle part ailleurs dans le CRM.

   Ce n'était pas un chantier de sauvetage : ces écrans se lisent. Mais
   une feuille de style enfermée dans un gabarit ne se partage pas, ne
   se thème pas, et diverge au premier changement.
   ================================================================== */

/* ------------------------------------------------------------------
   TÂCHES & RELANCES — la file des demandes entrantes
   ------------------------------------------------------------------ */

/* La carte d'une demande. */
.ama{border:1px solid var(--line); border-radius:var(--r3);
  padding:var(--e5) var(--e6); margin-bottom:var(--e4); background:var(--carte)}
.ama-hd{display:flex; align-items:center; justify-content:space-between;
  margin-bottom:var(--e2)}

/* L'intention lue dans le mail — c'est un état, et le CRM n'en a qu'une
   palette. Les trois teintes inventées ici (#E7F0FF, #FFF0E6, #E9F7EF)
   disaient déjà information, attente et réussite : elles se rangent. */
.ama-int{font-size:var(--t3); font-weight:var(--gras-fort);
  padding:2px 9px; border-radius:20px; text-transform:uppercase;
  letter-spacing:.3px}
.ama-int.devis  {background:var(--etat-info-fond);   color:var(--etat-info-texte)}
.ama-int.relance{background:var(--etat-attente-fond);color:var(--etat-attente-texte)}
.ama-int.suivi  {background:var(--etat-succes-fond); color:var(--etat-succes-texte)}

.ama-dt{font-size:var(--t3); color:var(--mut)}
.ama-obj{display:flex; align-items:center; gap:var(--e2);
  font-weight:var(--gras-normal); color:var(--navy); margin-bottom:var(--e2)}
.ama-obj svg{width:15px; height:15px; flex:none; color:var(--mut)}
.ama-obj:hover span{text-decoration:underline}
.ama-meta{display:flex; flex-wrap:wrap; gap:var(--e1) 22px;
  font-size:var(--t4); margin-bottom:var(--e3)}
.ama-meta .mut, .ama .mut{color:var(--mut); font-weight:400}
.ama-fiche{background:var(--fond-2); border-radius:9px;
  padding:var(--e3) var(--e4); font-size:var(--t4)}
.ama-fiche.norel{display:flex; align-items:center;
  justify-content:space-between; gap:var(--e4)}
.ama-cli{display:inline-flex; align-items:center; gap:7px;
  font-weight:var(--gras-normal); color:var(--navy); margin-bottom:5px}
.ama-cli:hover{text-decoration:underline}
.av2.sm{width:22px; height:22px; font-size:var(--t2); border-radius:var(--e2);
  display:inline-flex; align-items:center; justify-content:center;
  color:#fff; font-weight:var(--gras-normal)}
.ama-note{line-height:1.35}
.ama-act{display:flex; flex-wrap:wrap; gap:var(--e3);
  margin-top:var(--e4); align-items:flex-start}
.ama-act details{flex:1; min-width:260px}
.ama-act summary{list-style:none; cursor:pointer; display:inline-flex; width:auto}
.ama-act summary::-webkit-details-marker{display:none}
.ama-form{margin-top:var(--e3); display:flex; flex-direction:column;
  gap:var(--e3); border:1px solid var(--line); border-radius:9px;
  padding:var(--e4); background:var(--fond-2)}
.ama-form label{display:flex; flex-direction:column; gap:3px;
  font-size:var(--t3); font-weight:var(--gras-normal); color:var(--txt-2)}
.ama-form-l{display:flex; gap:var(--e3)}
.ama-form-l label{flex:1}

/* Le titre d'une section entre deux cartes. */
.ama-sec{font-size:var(--t5); font-weight:var(--gras-fort);
  color:var(--navy); margin:16px 0 var(--e3)}
.ama-sec .mut{font-weight:400; color:var(--mut)}

/* ------------------------------------------------------------------
   AGENDA & RDV — la semaine

   Le calendrier n'est pas un tableau : c'est une grille de sept
   colonnes où chaque rendez-vous est posé au pourcentage, en haut et en
   hauteur, selon son heure. Cette géométrie-là reste dans le gabarit —
   elle est calculée, c'est une donnée. Tout le reste vient ici, et ses
   couleurs sont nommées dans la charte.
   ------------------------------------------------------------------ */
.cal{display:flex; flex-direction:column; flex:1; min-height:0}
.cal-nav{display:flex; align-items:center; gap:var(--e3);
  margin-bottom:var(--e3)}
.cal-nav .rg{font-weight:var(--gras-fort); color:var(--navy);
  margin-left:var(--e1)}

/* L'en-tête des jours et la bande « journée » partagent la même trame :
   une colonne d'heures étroite, puis sept jours à parts égales. */
.cal-head, .cal-allday{display:grid; grid-template-columns:54px repeat(7,1fr)}
.cal-head{border-bottom:1px solid var(--line)}
.cal-head > div{padding:var(--e2) var(--e1); text-align:center;
  font-size:var(--t3); font-weight:var(--gras-normal); color:var(--txt-2);
  border-left:1px solid var(--line)}
.cal-head > div:first-child{border-left:none}
.cal-head .on{background:var(--selection); color:var(--navy);
  border-radius:var(--r2) var(--r2) 0 0}
.cal-head .dn{font-size:var(--t1); text-transform:uppercase;
  letter-spacing:.4px; color:var(--mut)}

.cal-allday > div{min-height:22px; border-left:1px solid var(--line);
  padding:2px}
.cal-allday > div:first-child{border-left:none; font-size:var(--t1);
  color:var(--mut); text-transform:uppercase; letter-spacing:.4px;
  display:flex; align-items:center; justify-content:flex-end;
  padding-right:var(--e2)}
.cal-ad{display:block; background:var(--rdv-journee);
  color:var(--rdv-journee-t); border-radius:5px; font-size:var(--t2);
  padding:1px 5px; margin:1px 0; white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis}

.cal-scroll{overflow-y:auto; flex:1; border-top:1px solid var(--line)}
.cal-body{display:grid; grid-template-columns:54px repeat(7,1fr)}
.cal-hours .h{height:48px; font-size:var(--t2); color:var(--mut);
  text-align:right; padding-right:var(--e2); transform:translateY(-6px)}

/* Le filet horaire est peint, pas dessiné : une rayure d'un pixel tous
   les quarante-huit, ce qui évite quatorze bordures par colonne. */
.cal-day{position:relative; border-left:1px solid var(--line);
  background:repeating-linear-gradient(var(--carte) 0 47px,
                                       var(--grille-heure) 47px 48px)}
.cal-day.on{background:repeating-linear-gradient(var(--fond-actif) 0 47px,
                                                 var(--grille-actif) 47px 48px)}

.cal-ev{position:absolute; box-sizing:border-box;
  background:var(--rdv-fond); color:var(--rdv-texte);
  border-left:3px solid var(--rdv-bord); border-radius:5px;
  padding:2px 5px; font-size:var(--t2); line-height:1.15;
  overflow:hidden; min-height:16px}
.cal-ev b{font-weight:var(--gras-fort)}
.cal-ev .cl{display:block; font-size:var(--t1); color:var(--rdv-second)}
.cal-ev .lieu{display:flex; align-items:center; gap:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.cal-ev .lieu svg{width:9px; height:9px; flex:none}

/* ------------------------------------------------------------------
   LE CHAMP D'UNE BARRE DE FILTRES

   Douze gabarits portent une barre `.tb`, et vingt champs y répétaient
   la même paire — `height:29px; border-radius:15px` — soit quarante
   déclarations pour une seule intention : un champ de filtre est plus
   court qu'un champ de formulaire, et complètement arrondi.

   La largeur, elle, reste une donnée : chaque filtre sait ce qu'il doit
   pouvoir montrer, de « Toutes les marques » à une raison sociale
   entière. Elle se pose par la variable, comme un plafond de hauteur.
   ------------------------------------------------------------------ */
.tb .inp{height:29px; border-radius:var(--r4); max-width:var(--cap-l, none)}

/* Catalogue — le tableau des produits. */
.tb-catalogue th:nth-child(1){width:12%}
.tb-catalogue th:nth-child(2){width:26%}

/* Un montant qu'on veut voir en premier, dans une colonne de chiffres. */
.fort-navy{color:var(--navy)}

/* ------------------------------------------------------------------
   LA GRILLE DE VIGNETTES

   La charte l'annonçait au §5 : « le motif grille de cartes, prisonnier
   de son seul gabarit, devient un composant ». Il en existait **trois
   copies** — Catalogue, Administration, Analyse commerciale — qui
   avaient déjà divergé : 250 px de maille contre 240, 12 px de gouttière
   contre 10. Le jeton `--vignette-mini` attendait dans la charte depuis
   l'audit.

   Seule la grille du Catalogue passe ici : les deux autres vivent sur
   des écrans déjà repris, et les rebasculer changerait un travail validé
   pour deux pixels. C'est un geste à part.
   ------------------------------------------------------------------ */
.vignettes{display:grid; gap:var(--e5);
  grid-template-columns:repeat(auto-fill, minmax(var(--vignette-mini), 1fr))}
.vignettes > .vide{grid-column:1 / -1}

/* La vignette elle-même : une carte cliquable qui se soulève au survol.
   Sa bordure et son ombre étaient écrites en dur alors que la charte les
   nommait déjà — `--survol` et `--ombre-survol`, aux mêmes valeurs. */
.vig{display:block; border:1px solid var(--line); border-radius:var(--r3);
  padding:var(--e6); background:var(--carte);
  transition:border-color .12s, box-shadow .12s}
.vig:hover{border-color:var(--survol); box-shadow:var(--ombre-survol)}
.vig-tete{display:flex; align-items:center; gap:9px; margin-bottom:var(--e3)}
.vig-nom{font-weight:var(--gras-fort); color:var(--navy); line-height:1.2}
/* Le chiffre que la vignette porte, et son unité. */
.vig-nb{font-size:var(--t8); font-weight:var(--gras-fort); color:var(--navy)}
.vig-nb span{font-size:var(--t3); font-weight:var(--gras-normal);
  color:var(--mut); margin-left:var(--e1)}
/* La ligne de détail au pied de la vignette. */
.vig-detail{font-size:var(--t3); color:var(--mut); margin-top:var(--e2);
  line-height:1.5}

/* L'avatar carré d'une vignette — les initiales sur la teinte du nom.
   `.av2` existe déjà ; seule sa taille de vignette manquait. */
.av2.vig-av{width:30px; height:30px; border-radius:var(--r2);
  display:inline-flex; align-items:center; justify-content:center;
  color:#fff; font-weight:var(--gras-normal); font-size:var(--t3)}

/* ==================================================================
   LA BOÎTE MAIL

   Soixante-quatorze lignes de CSS vivaient dans `mail_boite.html` —
   le plus gros bloc enfermé du CRM, sur l'écran où l'on passe le plus
   de temps. Deux défauts s'y cachaient, que le déplacement met au jour :

   · **`var(--nv)` n'est déclarée nulle part.** Elle sert deux fois, et
     seul son repli — `#22315C`, c'est-à-dire `--navy` — sauvait la
     mise. Une variable fantôme avec la bonne valeur de secours ne se
     voit jamais, et casse le jour où quelqu'un retire le repli.

   · **L'arborescence des dossiers est déclarée « partagée avec
     `_arbre_outlook.html` »** par un commentaire, mais ses règles
     vivaient ici. Le fragment ne s'inclut aujourd'hui que depuis cette
     page, donc rien ne casse — mais l'employer ailleurs aurait donné un
     arbre sans style, et personne n'aurait su pourquoi.
   ================================================================== */

/* ---- L'ARBORESCENCE DES DOSSIERS OUTLOOK ----
   Partagée avec `_arbre_outlook.html`, qui s'inclut lui-même pour
   descendre dans les sous-dossiers. */
.dsl{display:flex; align-items:center; gap:7px;
  padding:var(--e1) var(--e2); border-radius:var(--e2);
  font-size:var(--t4); color:var(--txt); min-width:0}
.dsl.seul{margin-left:15px}
.dsl svg{width:14px; height:14px; color:var(--mut); flex:none}
.dsl span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.dsl b{margin-left:auto; font-size:var(--t2); color:var(--mut);
  font-weight:var(--gras-normal); padding-left:var(--e2)}
.dsl:hover{background:var(--selection)}
.dsl.on{background:var(--selection); color:var(--navy);
  font-weight:var(--gras-normal)}
.dsl.on svg, .dsl.on b{color:inherit}
.dsr > summary{list-style:none; cursor:pointer; display:flex; align-items:center}
.dsr > summary::-webkit-details-marker{display:none}
.dsr > summary::before{content:"\203A"; display:inline-block; width:15px;
  flex:none; text-align:center; color:var(--mut); transition:transform .12s}
.dsr[open] > summary::before{transform:rotate(90deg)}
.dsr > summary > .dsl{flex:1; min-width:0}
.dse{margin-left:15px; border-left:1px solid var(--line); padding-left:2px}

/* ---- LES TROIS VOLETS ----
   Les dossiers, la liste des messages, le message lu. */
.bml{display:flex; gap:var(--e4); align-items:stretch; flex:1; min-height:0}
.bmd{width:236px; flex:none; display:flex; flex-direction:column}
.bmc{width:340px; flex:none; display:flex; flex-direction:column; min-height:0}
.bmr{flex:1; min-width:0; display:flex; flex-direction:column}

/* Le volet des dossiers. */
.bms{overflow:auto; padding:var(--e3); flex:1}
.bmt{font-size:var(--t2); font-weight:var(--gras-normal); color:var(--mut);
  text-transform:uppercase; letter-spacing:.04em;
  padding:var(--e5) var(--e2) var(--e1);
  border-top:1px solid var(--line); margin-top:var(--e3)}

/* Le volet de la liste. */
.bmq{padding:var(--e3) var(--e3) var(--e2); border-bottom:1px solid var(--line)}
.bmq .inp{width:100%}
.bmp{padding:var(--e2) var(--e4); font-size:var(--t3)}
.bmi{overflow:auto; flex:1}
/* Le séparateur de jour, qui reste en tête pendant qu'on descend. */
.bmg{display:flex; align-items:center; gap:5px;
  padding:var(--e3) var(--e4) var(--e1); font-size:var(--t3);
  font-weight:var(--gras-normal); color:var(--mut);
  position:sticky; top:0; background:var(--carte); z-index:2}
.bmg svg{width:11px; height:11px}
/* Une entrée de la liste. */
.bme{display:flex; gap:9px; padding:9px var(--e4);
  border-bottom:1px solid var(--line); color:var(--txt);
  align-items:flex-start}
.bme:hover{background:var(--fond-2)}
.bme.on{background:var(--selection)}
.bme .av2{width:30px; height:30px; flex:none; font-size:var(--t3)}
.bmx{min-width:0; flex:1}
.bmn{display:flex; gap:var(--e2); font-size:var(--t4);
  font-weight:var(--gras-normal); align-items:baseline}
.bmn > span:first-child{overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap}
.bmh{margin-left:auto; font-size:var(--t2); font-weight:400;
  color:var(--mut); white-space:nowrap; display:inline-flex;
  align-items:center; gap:var(--e1)}
.bmh svg{width:11px; height:11px}
.bmo, .bma{display:block; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-size:var(--t4)}
.bmo{margin-top:1px}
.bma{color:var(--mut); font-size:var(--t3)}
/* Un message non lu : son objet s'appuie, son expéditeur passe en marine. */
.bme.nl .bmo{font-weight:var(--gras-normal)}
.bme.nl .bmn{color:var(--navy)}

/* Le volet de lecture. */
.bmv{display:flex; flex-direction:column; flex:1; min-height:0}
.bmw{padding:var(--e5) var(--e6) var(--e3); border-bottom:1px solid var(--line)}
.bmw h2{font-size:var(--t6); margin:0 0 var(--e3)}
.bmz{display:flex; gap:9px; align-items:center; font-size:var(--t4)}
.bmz .av2{width:32px; height:32px; flex:none; font-size:var(--t3)}
.bmk{display:flex; gap:var(--e2); flex-wrap:wrap; margin-top:var(--e3)}
/* Fiche, projet, devis puis le bouton : trois colonnes de même largeur et un
   bouton qui reste au bout, aligné sur le bas des menus. Le formulaire est
   le parent commun — un seul envoi pour les trois. */
.bmtr{display:flex; gap:var(--e4); align-items:center; margin-top:var(--e4)}
.bmtr label{display:flex; align-items:center; gap:var(--e1); margin:0}
.bmct{display:flex; align-items:center; gap:7px; margin-top:9px;
  font-size:var(--t4)}
.bmct svg{width:14px; height:14px; color:var(--mut)}
.bmb{display:flex; gap:var(--e2); flex-wrap:wrap; padding:var(--e3) var(--e6);
  border-bottom:1px solid var(--line)}
/* Les pièces jointes, sur la même ligne que les actions mais détachées : on
   les repère sans les confondre avec Répondre ou Transférer. */
.bmpj{display:flex; gap:var(--e2); flex-wrap:wrap;
  padding:var(--e3) var(--e6); background:var(--fond-2);
  border-bottom:1px solid var(--line)}
/* Le corps du message, dans son cadre isolé. */
.bmf{width:100%; flex:1; min-height:320px; border:0; background:var(--carte)}

/* Le champ de recherche du volet liste, plus court que celui d'un filtre. */
.inp.mini-rech{height:28px; border-radius:14px; font-size:var(--t4)}
/* Le choix d'un dossier de classement, dans le volet de lecture. */
.inp.mini-choix{height:27px; max-width:200px; font-size:var(--t3)}
/* Le mot du volet quand aucun message n'est ouvert. */
.vide.plein{padding:50px 20px}

/* Sous 1200 px, le volet de lecture passe sous les deux autres : à trois
   colonnes, il ne resterait rien pour lire. */
@media (max-width: 1200px){
  .bml{flex-wrap:wrap}
  .bmd{width:200px}
  .bmc{width:300px}
  .bmr{flex:1 1 100%; min-height:420px}
}

/* Une pastille qui ne porte pas d'état, juste une indication grise. */
.chip.mut{color:var(--mut)}

/* ------------------------------------------------------------------
   LE BOUTON DESTRUCTIF

   Le cinquième rôle que la charte décrivait sans le poser. Jusqu'ici,
   « Supprimer ce catalogue » et « Fiche du message » portaient le même
   bouton gris : rien ne distinguait un geste réversible d'un geste qui
   ne l'est pas.

   C'est le bouton fantôme, encre rouge. Quatre traitements ont été mis
   à l'écran côte à côte ; celui-ci a été retenu parce qu'il **se repère
   sans se rendre désirable**. Un aplat rouge plein attirait l'œil plus
   que le bouton primaire lui-même — sur la fiche boutique, « Supprimer
   la boutique » serait devenu l'objet le plus voyant de l'écran.

   **Où il se pose, et où il ne se pose pas.** Le rouge est réservé à ce
   qui ne se récupère pas. Mettre un mail à la corbeille d'Outlook,
   vider les brouillons, archiver un produit, détacher un contact —
   tout cela se rattrape, et reste gris. Un rouge qui sert à tout ne
   prévient plus de rien.
   ------------------------------------------------------------------ */
.btn.dg{background:var(--carte); color:var(--red);
  border:1px solid var(--line)}
.btn.dg:hover{background:var(--etat-alerte-fond); border-color:#F5C9C9;
  filter:none}

/* La croix qui retire une ligne d'un tableau est la forme en ligne du
   bouton destructif : trop de rouge au repos, sur cinquante lignes,
   ferait un mur qui ne prévient plus de rien. Sa forme suffit à dire ce
   qu'elle fait ; le rouge arrive au survol, au moment d'agir.

   `neutre` la rend à un geste qui ne détruit pas — modifier une ligne,
   par exemple, qui partage sa place et sa taille sans partager son sens. */
.croix.neutre:hover{background:var(--fond-2); color:var(--navy)}

/* ==================================================================
   LE VERROU D'INACTIVITÉ

   Trois pièces, et aucune n'invente de composant : le bandeau de
   pré-alerte emprunte `.msg`, l'écran de déverrouillage emprunte
   `.lgbox` — la boîte de la page de connexion —, et le calque reprend
   la teinte et le rang de `.mdl-fond`, le fond de modale du CRM.
   ================================================================== */

/* Le calque. **Opaque, pas atténué** : derrière un voile translucide, un
   nom de client se lit encore. Il monte au-dessus de tout, y compris du
   tiroir du menu (z-index 60) et des modales (100). */
.verrou-calque{position:fixed; inset:0; z-index:200;
  background:var(--navy);
  display:flex; align-items:center; justify-content:center}
.verrou-calque[hidden]{display:none}

/* La page derrière ne se lit ni ne se tabule : sans ce filtre, la touche
   Tab promènerait le curseur dans une fiche client sous le calque. */
body.verrouille > .side,
body.verrouille > .main{filter:blur(6px); pointer-events:none;
  user-select:none}

.verrou-mot{font-size:var(--t3); color:var(--mut); line-height:1.5;
  margin-bottom:var(--e5); text-align:center}

/* Le bandeau de pré-alerte : discret, en haut, au-dessus du contenu mais
   sous le calque. Il emprunte `.msg` — le composant de notification du
   CRM — et n'ajoute que sa position. */
.verrou-bandeau{position:fixed; top:var(--e5); left:50%;
  transform:translateX(-50%); z-index:150;
  display:flex; align-items:center; gap:var(--e4);
  box-shadow:var(--ombre-survol)}
.verrou-bandeau[hidden]{display:none}

/* Le mot qui dit qu'une action n'a pas été jouée. Même place, même
   composant : on ne rejoue jamais un enregistrement tout seul. */
.verrou-perdues{position:fixed; bottom:var(--e5); left:50%;
  transform:translateX(-50%); z-index:150;
  box-shadow:var(--ombre-survol)}
.verrou-perdues[hidden]{display:none}

/* La sortie de secours de la page de verrouillage servie par le serveur. */
.verrou-sortie{margin-top:var(--e5); text-align:center}
.verrou-sortie button{font-size:var(--t2); color:var(--mut)}
.verrou-sortie button:hover{text-decoration:underline}

/* --------------------------------------------- agenda : couleur par type
   La couleur d'un rendez-vous vient de son type, et **uniquement de jetons
   déjà déclarés dans la charte**. Aucune valeur n'est écrite ici : un
   type sans couleur garde le bleu d'origine, et l'agenda d'avant ne bouge
   pas tant qu'aucun type n'est créé.

   Les paires fond/encre sont celles de la charte, dont le contraste a déjà
   été mesuré au chantier des encres d'état. En inventer d'autres, c'était
   repasser sous le seuil sans que personne ne le voie. */
.cal-ev.rdv-neutre{background:var(--etat-neutre-fond);color:var(--etat-neutre-texte);
  border-left-color:var(--etat-neutre-texte)}
.cal-ev.rdv-info{background:var(--etat-info-fond);color:var(--etat-info-texte);
  border-left-color:var(--etat-info-texte)}
.cal-ev.rdv-succes{background:var(--etat-succes-fond);color:var(--etat-succes-texte);
  border-left-color:var(--etat-succes-texte)}
.cal-ev.rdv-attente{background:var(--etat-attente-fond);color:var(--etat-attente-texte);
  border-left-color:var(--etat-attente-texte)}
.cal-ev.rdv-alerte{background:var(--etat-alerte-fond);color:var(--etat-alerte-texte);
  border-left-color:var(--etat-alerte-texte)}
.cal-ev.rdv-neutre .cl,.cal-ev.rdv-info .cl,.cal-ev.rdv-succes .cl,
.cal-ev.rdv-attente .cl,.cal-ev.rdv-alerte .cl{color:inherit;opacity:.85}

/* La poignée de déplacement. Elle n'apparaît qu'au survol, et **jamais au
   tactile** : sous 768 px le glisser-déposer n'est pas proposé, l'heure se
   change par le formulaire. */
.cal-ev .cal-prise{position:absolute;top:0;right:0;width:var(--e6);height:var(--e6);
  cursor:grab;opacity:0;border-radius:var(--r1)}
.cal-ev:hover .cal-prise{opacity:.55}
.cal-ev .cal-prise:active{cursor:grabbing;opacity:1}
.cal-ev.deplace{opacity:.5}
/* Le créneau visé pendant le glissement : le même bleu de sélection que
   partout ailleurs dans le CRM. */
.cal-cible{background:var(--selection)}
@media (max-width:768px){.cal-ev .cal-prise{display:none}}
/* L'aperçu d'un type dans l'écran d'Administration : le même bloc que dans la
   grille, posé dans le flux du texte plutôt qu'en absolu. */
.apercu-type{position:static;display:inline-block;padding:1px var(--e3);
  border-radius:var(--r1);font-size:var(--t1)}

/* ------------------------------------------- la recherche avec suggestions
   Promue le 09/08/2026 depuis le `<style>` de `mail_detail.html`, où elle
   vivait enfermée : une feuille écrite dans un gabarit ne se partage pas et
   diverge au premier changement. Ce n'est pas un composant neuf — c'est
   celui-là, rendu disponible partout.

   Toutes les valeurs viennent des jetons, y compris l'ombre — `--ombre-survol`
   existait, je l'avais d'abord écrite en clair. Seule la hauteur maximale
   reste chiffrée : aucun jeton ne porte une hauteur de liste déroulante, et en
   inventer un pour un seul usage aurait été pire.

   **Dette laissée derrière** : `mail_detail.html` et `_classer_mail.html`
   emploient toujours `.af-sug` / `.af-item`, définis dans un `<style>` de
   gabarit. Ce sont les mêmes règles. Les faire pointer ici est un petit
   chantier à part, pas une reprise de celui-ci. */
.sug-liste{position:absolute; left:0; right:0; top:100%; z-index:30;
  background:var(--carte); border:1px solid var(--line);
  border-radius:var(--r2); box-shadow:var(--ombre-survol);
  margin-top:2px; max-height:240px; overflow:auto; display:none}
.sug-item{padding:var(--e2) var(--e4); font-size:var(--t4); cursor:pointer}
.sug-item:hover, .sug-item.on{background:var(--selection)}
.sug-item .n{font-size:var(--t2); color:var(--mut)}
/* Le champ qui porte une liste doit ancrer son positionnement absolu. */
.fld.sug-ancre{position:relative}
