/* ==========================================================================
   Officia — fondations et composants (D-014)
   Couleurs du drapeau du Niger : vert = l'action, orange = le repère,
   blanc et gris = le châssis. Aucune bibliothèque, aucune police téléchargée.
   ========================================================================== */

:root {
  /* Vert — action */
  --vert: #0B7A2B;
  --vert-fonce: #085C20;
  --vert-clair: #E7F5EA;
  --vert-bord: #B8E0C1;
  /* Les paliers des heures de pointe (D-212, P8), du plus clair au plus franc. */
  --palier-1: #D6EEDC;
  --palier-2: #A9DBB5;
  --palier-3: #6CBF82;
  --palier-4: #2F9A4E;

  /* Orange — repère et avertissement */
  --orange: #E05206;
  --orange-fonce: #B33F04;
  --orange-clair: #FEF0E6;
  --orange-bord: #F8C9A8;

  /* Gris — le châssis */
  --g900: #14181D;
  --g700: #384250;
  --g500: #667085;
  --g400: #98A2B3;
  --g300: #D0D5DD;
  --g200: #E4E7EC;
  --g100: #F2F4F7;
  --g50: #F8FAFC;
  --blanc: #FFFFFF;
  /* Le papier et l'encre de l'aperçu d'une étiquette (D-182) : blanc et noir
     quels que soient les gris de la feuille — c'est ce qui s'imprime. */
  --encre: #000000;

  /* Erreur et information */
  --rouge: #B42318;
  --rouge-clair: #FEF3F2;
  --rouge-bord: #FDA29B;
  --bleu: #175CD3;
  --bleu-clair: #EFF8FF;
  --bleu-bord: #B2DDFF;

  /* Tailles de texte — dix crans (D-157). Le téléphone en redéfinit quatre. */
  --t-capitale: 11px;
  --t-aide: 12px;
  --t-secondaire: 13px;
  --t-courant: 14px;
  --t-corps: 15px;
  --t-titre: 16px;
  --t-ecran: 20px;
  --t-montant: 22px;
  --t-chiffre: 28px;
  --t-du: 42px;

  /* Espacements — échelle de base 4 px */
  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e5: 20px;
  --e6: 24px;
  --e8: 32px;

  /* Formes et mesures */
  --r-ctrl: 4px;
  --r-carte: 6px;
  /* Une pastille (étiquette, raccourci, puce) : ses bouts sont des demi-cercles. */
  --r-pilule: 999px;
  /* Une marque de graphique : barre, case, pastille de légende (D-212). */
  --r-marque: 2px;
  --h-ctrl: 44px;
  /* Une suggestion tient sur deux lignes : la désignation d'un médicament ne
     se tronque pas, sans quoi douze paracétamols se ressemblent tous. */
  --h-suggestion: 52px;
  --h-barre-app: 48px;
  --h-entete: 68px;
  --l-menu: 248px;
  --h-onglets: 68px;

  --police: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--police);
  font-size: var(--t-corps);
  line-height: 1.5;
  color: var(--g700);
  background: var(--g50);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--vert); }
a:hover { color: var(--vert-fonce); }

/* Focus toujours visible, jamais supprimé (D-015). */
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--vert);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(11, 122, 43, 0.16);
}

/* Lien d'évitement, visible seulement au clavier. */
.saut-contenu {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: var(--e3) var(--e4);
  background: var(--blanc);
  border: 1px solid var(--vert);
  border-radius: var(--r-ctrl);
  font-weight: 600;
}
.saut-contenu:focus { left: var(--e3); top: var(--e3); }

/* ==========================================================================
   Coque : barre d'application, menu latéral, zone d'écran
   ========================================================================== */

.coque { display: flex; flex-direction: column; min-height: 100%; }

.barre-app {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  height: var(--h-barre-app);
  flex-shrink: 0;
  padding: 0 var(--e4);
  background: var(--blanc);
  border-bottom: 1px solid var(--g300);
}
.marque { display: flex; align-items: center; gap: 10px; min-width: 0; }
.marque-nom {
  font-size: var(--t-titre);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--g900);
}
.filet-vertical { width: 1px; height: 20px; background: var(--g200); flex-shrink: 0; }
.barre-app-officine {
  font-size: var(--t-secondaire);
  color: var(--g500);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.barre-app-session { display: flex; align-items: center; gap: var(--e3); flex-shrink: 0; }
.barre-app-session .etiquette { font-size: var(--t-secondaire); color: var(--g500); }
.barre-app-session .nom { font-size: var(--t-secondaire); font-weight: 600; color: var(--g900); }

.cadre { display: flex; flex-grow: 1; min-height: 0; }

.menu-lateral {
  display: flex;
  flex-direction: column;
  gap: var(--e1);
  width: var(--l-menu);
  flex-shrink: 0;
  padding: var(--e4) 10px;
  background: var(--blanc);
  border-right: 1px solid var(--g300);
  overflow-y: auto;
}

/* Le filet qui sépare le travail quotidien des domaines repliés. */
.menu-filet { height: 1px; background: var(--g200); margin: var(--e2) 10px; }

/* --- La section repliable ---
   `details` est natif : le repli fonctionne sans une ligne de script, et c'est
   le serveur qui ouvre celle contenant l'écran courant (D-080, D-055). */
.menu-section > summary.menu-titre {
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--h-ctrl);
  padding: 0 10px 0 13px;
  border-radius: var(--r-ctrl);
  font-size: var(--t-secondaire);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--g500);
  cursor: pointer;
  /* Le marqueur du navigateur cède la place à notre chevron. */
  list-style: none;
}
.menu-section > summary.menu-titre::-webkit-details-marker { display: none; }
.menu-section > summary.menu-titre:hover { background: var(--g50); color: var(--g900); }
.menu-section[open] > summary.menu-titre { color: var(--g900); }

.menu-chevron { margin-left: auto; stroke: var(--g400); transition: transform 120ms ease; }
.menu-section[open] > summary .menu-chevron { transform: rotate(180deg); }
/* Le mouvement est un agrément : il cesse quand le poste demande le calme. */
@media (prefers-reduced-motion: reduce) {
  .menu-chevron { transition: none; }
}

.menu-entrees { display: flex; flex-direction: column; gap: 1px; padding-bottom: var(--e1); }
.menu-directes { padding-bottom: 0; }

/* --- L'entrée --- */
.menu-entree {
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--h-ctrl);
  padding: 0 10px;
  border-left: 3px solid transparent;
  border-radius: var(--r-ctrl);
  font-size: var(--t-courant);
  color: var(--g700);
  text-decoration: none;
}
/* L'icône ne porte jamais le sens toute seule : elle accompagne le mot (D-015). */
.menu-entree svg { stroke: var(--g500); flex-shrink: 0; }
.menu-entree:hover { background: var(--g50); color: var(--g900); }
.menu-entree:hover svg { stroke: var(--g700); }
.menu-entree.actif {
  background: var(--g100);
  border-left-color: var(--orange);
  font-weight: 600;
  color: var(--g900);
}
.menu-entree.actif svg { stroke: var(--orange); }
/* Le titre d'une section fermée porte la somme de ses entrées ; ouverte,
   elle la perd et chaque entrée montre la sienne — par la feuille seule
   (D-211, P16 et P19). Le serveur ouvre la section de l'écran courant. */
.menu-section > summary .menu-reste { margin-left: auto; }
summary .menu-reste + .menu-chevron { margin-left: 0; }
.menu-section[open] > summary .menu-reste,
.groupe-liste[open] > summary .menu-reste { display: none; }
.ligne-repli .menu-reste { margin-left: auto; margin-right: var(--e3); }
/* Le nombre qu'une entrée porte, en permanence (D-195) : ce qui reste à faire
   sur son écran. Poussé au bout de la ligne, en chiffres alignés. */
.menu-reste {
  margin-left: auto;
  min-width: 22px;
  padding: 0 7px;
  border-radius: var(--r-pilule);
  background: var(--orange);
  color: var(--blanc);
  font-size: var(--t-aide);
  font-weight: 600;
  line-height: 20px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- Le compte, dans la barre d'application (D-080) --- */
.separateur-point { color: var(--g300); font-size: var(--t-secondaire); }
.lien-compte { font-size: var(--t-secondaire); color: var(--vert); text-decoration: none; }
.lien-compte:hover { color: var(--vert-fonce); text-decoration: underline; }
.lien-compte.actif { font-weight: 600; text-decoration: underline; }

.zone { display: flex; flex-direction: column; flex-grow: 1; min-width: 0; }

.entete-ecran {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e6);
  min-height: var(--h-entete);
  flex-shrink: 0;
  padding: var(--e3) var(--e6);
  background: var(--blanc);
  border-bottom: 1px solid var(--g300);
}
.entete-texte { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.fil-ariane {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--t-aide);
  color: var(--g500);
}
.fil-ariane .courant { color: var(--g700); }
.fil-ariane svg { stroke: var(--g400); }
.titre-ecran {
  margin: 0;
  font-size: var(--t-ecran);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--g900);
}
.actions-ecran { display: flex; gap: 10px; flex-shrink: 0; }

.corps { flex-grow: 1; padding: var(--e5) var(--e6); }
.corps-etroit { max-width: 1100px; }

/* ==========================================================================
   Composants
   ========================================================================== */

.carte {
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
  padding: var(--e5);
}

.section-titre {
  padding-bottom: var(--e2);
  margin-bottom: var(--e4);
  border-bottom: 1px solid var(--g200);
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--g500);
}

.grille-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e8);
}
.grille-2-serree {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--e4);
}
.colonne { display: flex; flex-direction: column; gap: var(--e6); }
.bloc-champs { display: flex; flex-direction: column; gap: var(--e4); }
/* Des champs côte à côte, le bouton aligné sur leur pied : il n'a pas besoin
   d'un libellé vide au-dessus de lui pour tomber au bon endroit. */
.rangee-champs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--e3); }
.rangee-champs > .champ { flex: 1 1 240px; }
.rangee-champs > .champ-large { flex: 3 1 320px; }
.rangee-champs > .champ-date { flex: 0 1 172px; }
.rangee-champs > .champ-copies { flex: 0 0 96px; }
/* Un champ qui s'allonge vers le bas — la liste des patients dans le flux
   d'un volet du comptoir (D-243) : le bouton à côté reste à la hauteur du
   champ au lieu de suivre le pied de la liste (D-244, Q1). */
.rangee-champs.rangee-champs-haut { align-items: flex-start; }
/* Des champs en grille, autant de colonnes que la largeur en tient. */
.grille-champs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--e4);
  align-items: start;
}
.grille-champs > .champ-large { grid-column: span 2; }
/* Les actes d'un formulaire en grille prennent les deux dernières colonnes,
   au pied des champs (26 px : la hauteur d'un libellé). */
.grille-champs > .rangee-actes { grid-column: -3 / -1; align-self: start; padding-top: 26px; }
/* Deux formulaires dans un même volet, séparés d'un filet. */
.volet-filet { margin-top: var(--e4); padding-top: var(--e4); border-top: 1px solid var(--g200); }
/* L'acte et son contraire sur une rangée : le premier à gauche, l'autre au bout. */
.rangee-actes { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--e3); }

/* Champs */
.champ { display: flex; flex-direction: column; }
.champ[hidden] { display: none; }
/* Le secours sans script (D-055) : le script le masque quand il équipe
   l'écran, et la classe d'un bouton (`display: inline-flex`) ne le fait pas
   reparaître (D-179, P10 ; D-244, Q1). */
[data-sans-script][hidden] { display: none; }
.champ label {
  margin-bottom: var(--e1);
  font-size: var(--t-secondaire);
  font-weight: 600;
  color: var(--g700);
}
.obligatoire { color: var(--rouge); }
.champ input[type="text"],
.champ input[type="password"],
.champ input[type="email"],
.champ input[type="date"],
.champ select,
.champ textarea {
  height: var(--h-ctrl);
  padding: 0 var(--e3);
  font-family: inherit;
  font-size: var(--t-corps);
  color: var(--g900);
  background: var(--blanc);
  border: 1px solid var(--g400);
  border-radius: var(--r-ctrl);
  width: 100%;
}
.champ textarea {
  height: auto;
  min-height: 88px;
  padding: 10px var(--e3);
  line-height: 1.5;
  resize: vertical;
}
.champ input:hover, .champ select:hover, .champ textarea:hover { border-color: var(--g500); }
.champ input[disabled] {
  color: var(--g500);
  background: var(--g100);
  border-color: var(--g200);
}
.champ.en-erreur input, .champ.en-erreur select, .champ.en-erreur textarea { border-color: var(--rouge); }

/* Le sélecteur de date (D-145). Un champ date natif, à la même hauteur et au
   même bord que le champ texte ; le calendrier reste celui du navigateur, en
   clair, avec le vert pour accent. L'icône est dessinée ici, au trait du jeu
   du menu (grille de 24, 1,7 px, extrémités rondes), pour que les six écrans
   qui saisissent une date l'aient sans toucher à leur gabarit. */
.champ input[type="date"] {
  position: relative;
  color-scheme: light;
  accent-color: var(--vert);
}
/* Là où le navigateur expose son déclencheur, il s'étale, invisible, sous
   notre icône : un clic sur l'icône ouvre le calendrier. Ailleurs (Firefox),
   le navigateur garde son propre bouton et on ne dessine rien par-dessus. */
@supports selector(::-webkit-calendar-picker-indicator) {
  .champ input[type="date"] {
    padding-right: 40px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='5' width='17' height='15.5' rx='2'/%3E%3Cpath d='M3.5 10h17'/%3E%3Cpath d='M8 3v4'/%3E%3Cpath d='M16 3v4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 20px 20px;
  }
  .champ input[type="date"]::-webkit-calendar-picker-indicator {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: var(--h-ctrl);
    margin: 0;
    opacity: 0;
    cursor: pointer;
  }
  .champ input[type="date"][disabled] {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2398A2B3' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.5' y='5' width='17' height='15.5' rx='2'/%3E%3Cpath d='M3.5 10h17'/%3E%3Cpath d='M8 3v4'/%3E%3Cpath d='M16 3v4'/%3E%3C/svg%3E");
  }
}
.aide { margin-top: 5px; font-size: var(--t-aide); color: var(--g500); }
.tableau td .aide { margin: 2px 0 0; }
/* Le message d'un état (une certification en échec) garde une largeur de
   lecture : sans elle, la colonne s'élargit et la date d'à côté passe à la ligne. */
.tableau td.cellule-etat .aide { max-width: 320px; }
/* Les totaux que la DGI a rendus au POST (D-189) : une note sous le résultat,
   verte quand tout concorde, orange quand un montant diffère — une trace pour
   le responsable, jamais un état de la pièce. */
.tableau td .trace-totaux { margin-top: 4px; padding: 1px 6px; border-left: 3px solid var(--vert);
                            background: var(--vert-clair); color: var(--vert-fonce); }
.tableau td .trace-totaux.ecart { border-left-color: var(--orange); background: var(--orange-clair);
                                  color: var(--orange-fonce); }
.fait .aide,
.historique-tete .aide,
.carte-pile > .aide,
.situation-actes > .aide { margin: 0; }
.message-erreur { margin-top: 5px; font-size: var(--t-aide); font-weight: 600; color: var(--rouge); }

/* Boutons */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--h-ctrl);
  padding: 0 var(--e4);
  font-family: inherit;
  font-size: var(--t-courant);
  font-weight: 600;
  border-radius: var(--r-ctrl);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
.bouton-principal {
  color: var(--blanc);
  background: var(--vert);
  border: 1px solid var(--vert);
  padding: 0 18px;
}
.bouton-principal:hover { background: var(--vert-fonce); border-color: var(--vert-fonce); color: var(--blanc); }
.bouton-secondaire {
  color: var(--g700);
  background: var(--blanc);
  border: 1px solid var(--g300);
}
.bouton-secondaire:hover { background: var(--g50); color: var(--g900); }
.bouton-danger { color: var(--rouge); background: var(--blanc); border: 1px solid var(--rouge-bord); }
.bouton-danger:hover { color: var(--rouge); background: var(--rouge-clair); border-color: var(--rouge); }
.bouton-petit { height: 32px; padding: 0 var(--e3); font-size: var(--t-secondaire); }
.bouton[disabled] {
  color: var(--g400);
  background: var(--g100);
  border-color: var(--g200);
  cursor: default;
}

/* Alertes */
.alertes { display: flex; flex-direction: column; gap: 10px; margin-bottom: var(--e4); }
.alerte {
  padding: 11px var(--e4);
  font-size: var(--t-courant);
  color: var(--g900);
  border-radius: var(--r-ctrl);
  border: 1px solid;
}
.alerte-success { background: var(--vert-clair); border-color: var(--vert-bord); border-left: 3px solid var(--vert); }
.alerte-error { background: var(--rouge-clair); border-color: var(--rouge-bord); border-left: 3px solid var(--rouge); }
.alerte-warning { background: var(--orange-clair); border-color: var(--orange-bord); border-left: 3px solid var(--orange); }
.alerte-info { background: var(--bleu-clair); border-color: var(--bleu-bord); border-left: 3px solid var(--bleu); }

.note-bas {
  margin: var(--e3) 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--g200);
  font-size: var(--t-aide);
  color: var(--g500);
}

/* Formulaire à une seule colonne (utilisateur, rôle, mot de passe) */
.formulaire-etroit { max-width: 560px; }

/* Tableaux */
.tableau-cadre {
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
  /* Un tableau large défile dans son cadre, jamais la page (D-015). */
  overflow-x: auto;
}
.tableau { width: 100%; border-collapse: collapse; }
.tableau thead th {
  padding: 0 14px;
  height: 38px;
  text-align: left;
  white-space: nowrap;
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--g500);
  background: var(--g100);
  border-bottom: 1px solid var(--g300);
}
.tableau tbody td {
  padding: 10px 14px;
  font-size: var(--t-courant);
  color: var(--g900);
  border-bottom: 1px solid var(--g200);
  vertical-align: middle;
}
.tableau tbody tr:last-child td { border-bottom: 0; }
.tableau tbody tr:hover { background: var(--g50); }
.colonne-nombre { text-align: right; font-variant-numeric: tabular-nums; }
.colonne-actions { white-space: nowrap; }
.rangee-actions { display: flex; align-items: center; gap: 8px; }
/* Jamais de retour à la ligne dans une colonne Actions : si le tableau ne
   tient pas, il défile dans son cadre, la page jamais (D-208, P9). */
.colonne-actions .rangee-actions { flex-wrap: nowrap; }

/* Les gestes d'une colonne Actions (D-208, B) : l'icône seule, dans un carré
   de 32 px ; l'intitulé reste dans le bouton — c'est lui que lit un lecteur
   d'écran, et l'infobulle le reprend. Au téléphone, il reparaît (plus bas). */
.bouton-geste { width: 32px; padding: 0; flex-shrink: 0; }
.bouton-geste svg { stroke: currentColor; flex-shrink: 0; }
.geste-intitule {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
/* L'infobulle de l'application (B3) : immédiate, au survol et au focus du
   clavier, sous le bouton. Un seul élément, posé par officia.js hors des
   cadres de tableau, qui la couperaient. */
.infobulle {
  position: fixed;
  z-index: 60;
  padding: 5px 9px;
  font-size: var(--t-aide);
  font-weight: 400;
  line-height: 1.4;
  color: var(--blanc);
  background: var(--g900);
  border-radius: var(--r-ctrl);
  white-space: nowrap;
  pointer-events: none;
}
.infobulle[hidden] { display: none; }

/* Étiquettes d'état */
.etat {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--r-pilule);
  font-size: var(--t-aide);
  font-weight: 600;
  white-space: nowrap;
}
.etat-actif { color: var(--vert-fonce); background: var(--vert-clair); border: 1px solid var(--vert-bord); }
.etat-inactif { color: var(--g500); background: var(--g100); border: 1px solid var(--g300); }
.etat-attente { color: var(--orange-fonce); background: var(--orange-clair); border: 1px solid var(--orange-bord); }
.etat-systeme { color: var(--bleu); background: var(--bleu-clair); border: 1px solid var(--bleu-bord); }

.code-inline {
  font-family: Consolas, "Courier New", monospace;
  font-size: var(--t-aide);
  color: var(--g500);
}

/* Mot de passe provisoire, affiché une seule fois */
.bloc-secret {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 20px 0;
  padding: 16px;
  background: var(--g50);
  border: 1px solid var(--g300);
  border-radius: var(--r-ctrl);
}
.bloc-secret-etiquette {
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--g500);
}
.bloc-secret-valeur {
  font-family: Consolas, "Courier New", monospace;
  font-size: var(--t-montant);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--g900);
  user-select: all;
  word-break: break-all;
}

/* Matrice des droits */
.tableau-matrice .colonne-fonctionnalite { min-width: 280px; }
.tableau-matrice .colonne-role { text-align: center; width: 1%; white-space: nowrap; }
.tableau-matrice thead .colonne-role { text-align: center; }
.ligne-domaine th {
  padding: 8px 14px;
  text-align: left;
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--g500);
  background: var(--g50);
  border-top: 1px solid var(--g200);
  border-bottom: 1px solid var(--g200);
}
.case-droit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--h-ctrl);
  height: var(--h-ctrl);
  cursor: pointer;
}
.case-droit input { width: 20px; height: 20px; accent-color: var(--vert); cursor: pointer; }
.case-droit input[disabled] { cursor: default; }

/* Texte réservé aux lecteurs d'écran. */
.lecture-seule {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Recherche et pagination */
.barre-recherche {
  display: flex;
  align-items: flex-end;
  gap: var(--e3);
  margin-bottom: var(--e4);
}
.barre-recherche .champ { flex-grow: 1; max-width: 480px; }
.compte-resultats { margin: 0 0 var(--e3); font-size: var(--t-secondaire); color: var(--g500); }
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--e4);
  margin-top: var(--e4);
}
.pagination-position { font-size: var(--t-courant); color: var(--g500); }

.formulaire-large { max-width: 820px; }

/* Atelier de saisie : une liste qui s'allonge à gauche, le formulaire qui
   l'alimente à droite. Le formulaire suit le défilement — sans quoi il
   descend d'une ligne à chaque ajout et finit hors de l'écran. */
.atelier {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--e6);
  align-items: start;
}
.atelier-liste { grid-column: 1; grid-row: 1; min-width: 0; }
.atelier-saisie {
  grid-column: 2;
  grid-row: 1;
  position: sticky;
  top: var(--e4);
}

/* Deux passes côte à côte demandent dix colonnes. Mesuré à 1366×768 :
   887 px de tableau contre 689 px de colonne tant que le panneau reste à
   droite — la colonne « Écart » de la passe en cours sortait de l'écran
   pendant la saisie. Le tableau prend donc toute la largeur et le panneau
   passe au-dessus : c'est l'ordre que la même page prend déjà sous 900 px. */
.atelier-empile { display: block; }
.atelier-empile .atelier-saisie,
.atelier-empile .atelier-liste { position: static; }
.atelier-empile .atelier-saisie {
  max-width: 820px;
  margin-bottom: var(--e6);
}
.compte-lignes { font-weight: 400; color: var(--g500); }

/* Les faits fixes d'un document, en une bande plutôt qu'en colonne : ils ne
   changent pas pendant la saisie, ils n'ont pas à occuper la hauteur qui lui
   revient (D-057). */
.bande-faits {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e3) var(--e8);
  padding: var(--e3) var(--e5);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.fait { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fait-etiquette {
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--g500);
  white-space: nowrap;
}
.fait-valeur { font-size: var(--t-courant); font-weight: 600; color: var(--g900); }


/* ==========================================================================
   Listes historiques (D-063, D-064)
   Journal des mouvements aujourd'hui ; ventes et caisse demain. Rien ici
   n'est propre au stock.
   ========================================================================== */

.filtres-historique {
  margin-bottom: var(--e4);
  padding: var(--e4) var(--e5);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.filtres-corps { display: flex; flex-direction: column; gap: 14px; }

/* Le bouton « Filtres » n'a de sens que là où la barre se replie : au bureau
   elle tient sur une ligne et reste déployée (D-066). */
.filtres-bouton { display: none; }
.filtres-historique > summary::-webkit-details-marker { display: none; }
/* Une rangée souple : de trois à six champs y tiennent, quel que soit
   l'écran. La grille fixe à six colonnes était faite pour le stock. */
.grille-filtres { display: flex; flex-wrap: wrap; gap: var(--e3); align-items: flex-end; }
.grille-filtres .champ { flex: 1 1 150px; min-width: 0; max-width: 320px; }
.grille-filtres .champ-large { flex: 2 1 240px; max-width: 480px; }
.grille-filtres .champ-date { flex: 0 1 172px; }
.grille-filtres .champ-bouton { flex: 0 0 auto; }
.champ-bouton { justify-content: flex-end; }
/* « Effacer les filtres » à côté de Filtrer, dès qu'un filtre est posé (D-208). */
.grille-filtres .champ-bouton { flex-direction: row; align-items: center; gap: var(--e4); }
.filtres-effacer { white-space: nowrap; font-size: var(--t-secondaire); }

/* La période appliquée se voit : un filtre caché fait croire qu'on voit tout. */
.raccourcis-periode { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2); }
.raccourci {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--e3);
  border: 1px solid var(--g300);
  border-radius: var(--r-pilule);
  background: var(--blanc);
  color: var(--g500);
  font-size: var(--t-secondaire);
  font-weight: 600;
  text-decoration: none;
}
.raccourci:hover { border-color: var(--g400); color: var(--g700); }
.raccourci.actif {
  color: var(--vert-fonce);
  background: var(--vert-clair);
  border-color: var(--vert-bord);
}

/* L'article : son code cesse de faire passer la désignation à la ligne. */
.tableau.tableau-journal tbody td.cellule-titre {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
}
.article-code { font-family: Consolas, "Courier New", monospace; font-size: var(--t-capitale); color: var(--g500); }
.article-nom { font-size: var(--t-courant); color: var(--g900); }

/* La nature du mouvement se lit à la couleur : une entrée n'est pas une
   sortie. Le sens vient de l'écriture, jamais du libellé (D-064). */
.sens-entree { color: var(--vert-fonce); background: var(--vert-clair); border: 1px solid var(--vert-bord); }
.sens-sortie { color: var(--rouge); background: var(--rouge-clair); border: 1px solid var(--rouge-bord); }
.sens-transfert { color: var(--bleu); background: var(--bleu-clair); border: 1px solid var(--bleu-bord); }

.quantite { font-weight: 600; font-variant-numeric: tabular-nums; }
.quantite-entree { color: var(--vert-fonce); }
.quantite-sortie { color: var(--rouge); }
/* Un transfert ne fait rien entrer ni sortir de l'officine : pas de signe. */
.quantite-transfert { color: var(--g700); }

/* Le stock avant et après, pour les seuls emplacements qui ont bougé. */
.transitions { display: flex; flex-direction: column; gap: 2px; }
.transition {
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.transition-lieu { min-width: 52px; font-size: var(--t-capitale); color: var(--g500); }
.transition-avant { font-size: var(--t-secondaire); color: var(--g500); }
.transition-fleche { font-size: var(--t-capitale); color: var(--g400); }
.transition-apres { font-size: var(--t-secondaire); font-weight: 600; }
.transition-apres.en-baisse { color: var(--rouge); }
.transition-apres.en-hausse { color: var(--vert-fonce); }

.date-jour { display: block; font-size: var(--t-secondaire); color: var(--g700); white-space: nowrap; }
.date-heure { display: block; font-size: var(--t-aide); color: var(--g500); }

/* La suite : pagination au bureau, « Afficher plus » au mobile (D-065). Un
   seul bloc rendu ; le CSS décide lequel paraît. */
.suite-historique { margin-top: var(--e4); }

/* La tête d'un historique : ce qu'on regarde à gauche, la période à droite.
   Elle était recopiée dans huit écrans. */
.historique { display: flex; flex-direction: column; gap: var(--e3); }
.historique-tete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--e3) var(--e4);
}
.historique-tete .aide { flex: 1 1 420px; max-width: 72ch; }
.historique > .filtres-historique,
.historique > .compte-resultats,
.historique > .suite-historique,
.historique > .titre-secondaire,
.historique-tete > .titre-secondaire { margin: 0; }
.historique-tete > .section-titre { margin: 0; padding: 0; border: 0; }
.bouton-suite, .suite-compte { display: none; }
.suite-compte { margin: var(--e2) 0 0; text-align: center; font-size: var(--t-secondaire); color: var(--g500); }

/* Un parcours : où l'on en est, et ce qui reste (D-060). */
.fil-etapes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e2) var(--e5);
  margin: 0 0 var(--e4);
  padding: 0;
  list-style: none;
}
.etape { display: flex; align-items: center; gap: var(--e2); }
.etape-puce {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: var(--r-pilule);
  background: var(--g200);
  color: var(--g500);
  font-size: var(--t-aide);
  font-weight: 700;
}
.etape-titre { font-size: var(--t-courant); font-weight: 600; color: var(--g500); }
.etape-courante .etape-puce { background: var(--vert); color: var(--blanc); }
.etape-courante .etape-titre { color: var(--g900); }
.etape-franchie .etape-puce { background: var(--vert-clair); color: var(--vert-fonce); }
.etape-franchie .etape-titre { color: var(--g700); }

/* L'article retenu, et le moyen d'en changer. */
.bande-article {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  padding: var(--e3) var(--e4);
  background: var(--g50);
  border: 1px solid var(--g200);
  border-radius: var(--r-ctrl);
}
.bande-article a { flex-shrink: 0; font-size: var(--t-secondaire); font-weight: 600; }

/* Suggestions pendant la frappe : le panneau se pose PAR-DESSUS le contenu,
   il ne le pousse pas. Sans quoi vingt correspondances chassent les champs
   hors de l'écran (D-056). */
.champ-suggestion { position: relative; }
.panneau-suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin-top: var(--e1);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-ctrl);
  box-shadow: 0 12px 28px rgba(20, 24, 29, 0.18);
  overflow: hidden;
}
.suggestion-entete {
  padding: 6px var(--e3);
  background: var(--g100);
  border-bottom: 1px solid var(--g200);
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--g500);
}
/* Six rangées visibles, le reste au défilement : le panneau a une hauteur,
   la liste des résultats n'en a pas. */
.suggestion-corps { max-height: calc(var(--h-suggestion) * 6); overflow-y: auto; }
/* Le nom du produit n'est jamais coupé : il passe à la ligne (D-199) — sa
   fin porte le dosage et la boîte, ce qui distingue deux présentations. */
.suggestion {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-height: var(--h-suggestion);
  padding: 6px var(--e3);
  border-left: 3px solid transparent;
  cursor: pointer;
}
.suggestion + .suggestion { border-top: 1px solid var(--g200); }
.suggestion.active { background: var(--vert-clair); border-left-color: var(--vert); }
.suggestion-identite { display: flex; align-items: baseline; gap: var(--e2); min-width: 0; }
.suggestion-designation {
  min-width: 0;
  font-size: var(--t-courant);
  color: var(--g900);
  overflow-wrap: anywhere;
}
/* La dénomination commune, sous le nom commercial : c'est par elle qu'on
   propose un équivalent quand le produit demandé manque. En retrait et plus
   pâle que le nom — elle éclaire la ligne, elle ne la dispute pas. */
.suggestion-dci {
  min-width: 0;
  font-size: var(--t-aide);
  font-style: italic;
  color: var(--g500);
  overflow-wrap: anywhere;
}
.suggestion-stock { font-size: var(--t-aide); color: var(--g500); white-space: nowrap; }
/* Le stock d'un produit (D-200) : le vendable en gros, à droite du nom, dans
   la couleur de son état ; le détail rayon · magasin reste dessous. Le
   panneau est un conteneur : c'est SA largeur qui décide où va le chiffre. */
.panneau-suggestions { container: suggestions / inline-size; }
.suggestion.suggestion-produit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "identite vendable" "dci dci" "stock stock";
  column-gap: var(--e3);
  align-content: center;
}
.suggestion-produit > .suggestion-identite { grid-area: identite; }
.suggestion-produit > .suggestion-dci { grid-area: dci; }
.suggestion-produit > .suggestion-stock { grid-area: stock; }
.suggestion-vendable {
  grid-area: vendable;
  align-self: start;
  text-align: right;
  white-space: nowrap;
  font-size: var(--t-titre);
  font-weight: 700;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}
.suggestion-vendable small {
  margin-left: 4px;
  font-size: var(--t-capitale);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.suggestion-vendable.ok { color: var(--vert); }
.suggestion-vendable.magasin { color: var(--orange); }
.suggestion-vendable.rupture { color: var(--rouge); }
/* Un panneau étroit (la réception, le téléphone : P6-b) : le chiffre passe
   sur la ligne du détail, à droite. Sur la ligne du nom, il repoussait les
   noms sur trois lignes. Même chiffre, même couleur, même taille. */
@container suggestions (max-width: 399px) {
  .suggestion.suggestion-produit { grid-template-areas: "identite identite" "dci dci" "stock vendable"; }
  .suggestion-vendable { align-self: end; }
  .suggestion-produit > .suggestion-stock { white-space: normal; }
}
/* La recherche d'un tiers payeur ou d'un fournisseur (D-178) : le panneau
   des produits, une ligne de détail à la place de la DCI et du stock. */
.suggestion-detail { min-width: 0; font-size: var(--t-aide); color: var(--g500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Dans un volet du comptoir, dont le corps est lui-même posé par-dessus le
   panier, borné en hauteur et défile : le panneau y prend sa place et pousse
   ce qui suit, le volet défile — rien ne sort de son cadre (D-243, Q2, qui
   remplace le débordement de D-178). */
.volet-corps .panneau-suggestions { position: static; }
/* La fiche patient (D-179) : ce que le champ Patient a retrouvé, ou pas. */
.fiche-patient { font-size: var(--t-aide); color: var(--g700); }
.fiche-patient:empty { display: none; }
.fiche-patient .code-inline { color: var(--g700); }
.fiche-patient.nouvelle { color: var(--orange); }
/* Une valeur fixée à la création, montrée à la place d'un champ. */
.valeur-fixe { margin: 0; min-height: var(--h-ctrl); display: flex; align-items: center; font-size: var(--t-corps); color: var(--g900); }
.suggestion-inactif { margin-left: var(--e2); padding: 1px 6px; border-radius: var(--r-ctrl); font-size: var(--t-capitale); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--g500); background: var(--g100); border: 1px solid var(--g200); }
.suggestion-pied {
  padding: 7px var(--e3);
  background: var(--g50);
  border-top: 1px solid var(--g200);
  font-size: var(--t-aide);
  color: var(--g500);
}

/* Valeurs calculées, non saisies : encadré discret pour qu'on ne cherche pas
   à les modifier. */
.calcules {
  margin: 0;
  padding: var(--e3) var(--e4);
  background: var(--g50);
  border: 1px solid var(--g200);
  border-radius: var(--r-ctrl);
}

/* Plusieurs produits correspondent : on choisit sans quitter l'écran. */
.liste-candidats {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--g300);
  border-radius: var(--r-ctrl);
  overflow: hidden;
}
.candidat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  min-height: var(--h-ctrl);
  padding: 10px var(--e4);
  color: var(--g900);
  text-decoration: none;
}
.candidat + .candidat { border-top: 1px solid var(--g200); }
/* Un candidat qui renvoie un formulaire (le tiers au comptoir, le fournisseur
   d'une facture, D-178) est un bouton dessiné comme le lien. */
button.candidat { width: 100%; text-align: left; background: var(--blanc); border: 0; font: inherit; cursor: pointer; }
.candidat:hover { background: var(--g50); color: var(--g900); }
.candidat-identite { display: flex; align-items: center; gap: var(--e3); min-width: 0; }
.candidat-stock { flex-shrink: 0; font-size: var(--t-secondaire); color: var(--g500); }
/* La DCI accompagne le nom commercial dans la liste des candidats, comme dans
   le panneau de suggestions : les deux chemins montrent la même chose (D-055). */
.candidat-dci { font-size: var(--t-aide); font-style: italic; color: var(--g500); }
.titre-secondaire {
  margin: var(--e8) 0 var(--e3);
  font-size: var(--t-titre);
  font-weight: 600;
  color: var(--g900);
}
.etat-rupture { color: var(--rouge); background: var(--rouge-clair); border: 1px solid var(--rouge-bord); }

/* Familles et sous-familles : deux niveaux sur un même écran */
.liste-familles { display: flex; flex-direction: column; gap: var(--e3); }
.famille { padding: 0; }
.famille-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  flex-wrap: wrap;
  padding: var(--e4) var(--e5);
}
.famille-identite { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.famille-libelle { font-size: var(--t-titre); font-weight: 600; color: var(--g900); }
.famille-code { display: flex; align-items: center; gap: var(--e2); }
.liste-sous-familles {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--g200);
}
.sous-famille {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  padding: 10px var(--e5);
  border-bottom: 1px solid var(--g200);
}
.sous-famille:last-child { border-bottom: 0; }
.sous-famille-identite {
  display: flex;
  align-items: center;
  gap: var(--e3);
  flex-wrap: wrap;
  min-width: 0;
  font-size: var(--t-courant);
  color: var(--g900);
}
.famille-vide {
  margin: 0;
  padding: var(--e3) var(--e5) var(--e4);
  border-top: 1px solid var(--g200);
  font-size: var(--t-secondaire);
  color: var(--g500);
}

/* Liste description (accueil) */
.liste-infos { display: flex; flex-direction: column; gap: var(--e2); margin: 0; }
.ligne-info { display: flex; justify-content: space-between; align-items: baseline; gap: var(--e4); }
.ligne-info dt { margin: 0; font-size: var(--t-courant); color: var(--g700); }
.ligne-info dd {
  margin: 0;
  font-size: var(--t-courant);
  color: var(--g900);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ligne-info-total {
  margin-top: var(--e1);
  padding-top: var(--e3);
  border-top: 1px solid var(--g200);
}
.ligne-info-total dt { font-size: var(--t-titre); font-weight: 600; color: var(--g900); }
.ligne-info-total dd { font-size: var(--t-montant); font-weight: 600; }
/* La variante filetée : les faits d'une pièce, un par rangée. */
.liste-infos.filetee { gap: 0; }
.liste-infos.filetee .ligne-info { padding: var(--e1) 0; border-bottom: 1px solid var(--g200); }
.liste-infos.filetee .ligne-info:last-child { border-bottom: 0; }

/* P4 : les montants signés, trois classes. Le signe vient du filtre
   `francs` (moins typographique, espace insécable). */
.montant-negatif { color: var(--rouge); }
.montant-positif { color: var(--vert-fonce); }
.montant-nul { color: var(--g500); }

/* P5 : la carte de situation — des chiffres, puis l'acte. */
.carte-situation {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--e4) var(--e8);
  padding: var(--e5) var(--e6);
}
.faits { display: flex; align-items: center; flex-wrap: wrap; gap: var(--e4) 40px; margin: 0; }
.fait dt, .fait dd { margin: 0; }
.fait-nombre {
  font-size: var(--t-chiffre);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: var(--g900);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fait-nombre small { font-size: var(--t-courant); font-weight: 600; letter-spacing: 0; color: var(--g500); }
.fait-filet { width: 1px; height: 52px; background: var(--g200); }
.fait-large { flex: 1 1 320px; }
.fait-large .fait-valeur { white-space: normal; }
.situation-actes { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
/* D-176 : la série de l'année, une ligne sous les cases de la carte de
   situation (Certification, Journal électronique). */
.ligne-serie {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--e2) var(--e3);
  padding-top: var(--e4);
  border-top: 1px solid var(--g200);
}
.ligne-serie .aide { margin: 0; }

/* P6 : les valeurs à chasse fixe et la référence d'une pièce. */
.valeur-mono { font-family: Consolas, "Courier New", monospace; font-size: var(--t-secondaire); color: var(--g700); }
/* D-251 : les mots de la période d'un rapport (« du », « après »…), entre ses dates. */
.periode-mot { font-weight: 400; color: var(--g500); }
/* D-251 : la bande d'un rapport resserrée (32 → 24 px), pour qu'« après … jusqu'au … »
   tienne sur une rangée à 1366 px (D-015). Les autres bandes de faits ne bougent pas. */
.faits-rapport { column-gap: var(--e6); }
/* ... et en étroit, la période passe à la ligne dans sa case plutôt que de perdre une date. */
.faits-rapport .fait-valeur { white-space: normal; }
.code-inline.reference { font-weight: 600; color: var(--g900); }

/* P9 : la carte en colonne, à intervalle régulier. */
.carte-pile { display: flex; flex-direction: column; gap: var(--e3); }
.carte-pile > .section-titre { margin: 0; }

/* Les pages d'erreur (D-203) : le message, et de quoi repartir. Rien de plus
   — ni code technique, ni trace : elle reste au serveur. */
.carte-erreur { display: grid; gap: var(--e4); }
.carte-erreur .titre-erreur { margin: 0; font-size: var(--t-ecran); color: var(--g900); }
.carte-erreur .erreur-message { margin: 0; color: var(--g700); }
.carte-erreur p:last-child { margin: 0; }

/* ==========================================================================
   Écran de connexion (sans coque)
   ========================================================================== */

.page-connexion {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100%;
  padding: var(--e6);
  background: var(--g50);
}
.bloc-connexion { width: 100%; max-width: 380px; }
.marque-connexion {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--e3);
  margin-bottom: var(--e6);
}
.marque-connexion .nom {
  font-size: var(--t-chiffre);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--g900);
}
.marque-connexion .sous-titre { font-size: var(--t-courant); color: var(--g500); }
.pied-connexion {
  margin-top: var(--e5);
  text-align: center;
  font-size: var(--t-aide);
  color: var(--g500);
}

/* ==========================================================================
   Coque mobile : barre d'onglets et panneau de menu
   Masqués au-dessus de 900 px.
   ========================================================================== */

.barre-onglets,
.panneau-menu { display: none; }

@media (max-width: 899px) {
  :root {
    --h-ctrl: 52px;
    --h-suggestion: 60px;
    --r-ctrl: 8px;
    --r-carte: 12px;
    --t-corps: 16px;
    --t-titre: 17px;
    --t-ecran: 18px;
    --t-du: 36px;
  }

  body { font-size: var(--t-corps); }

  /* Le menu latéral cède la place à la barre d'onglets. */
  .menu-lateral { display: none; }

  .barre-app { padding: 0 var(--e3); }
  .barre-app-officine, .barre-app-session { display: none; }

  .entete-ecran {
    flex-direction: column;
    align-items: stretch;
    gap: var(--e2);
    padding: var(--e3) var(--e4);
  }
  .fil-ariane { display: none; }
  .titre-ecran { font-size: var(--t-ecran); }

  /* Dégagement sous le contenu : barre d'onglets + barre d'action fixe, plus
     une marge. Calculé, pour rester juste si ces hauteurs changent. */
  .corps { padding: var(--e4); padding-bottom: calc(var(--h-onglets) + 110px); }

  .carte { border-radius: var(--r-carte); border-color: var(--g200); }
  .grille-2, .grille-2-serree { grid-template-columns: minmax(0, 1fr); gap: var(--e4); }

  /* Une seule colonne : la saisie repasse au-dessus de la liste — l'ordre du
     document — pour rester sous le pouce sans faire défiler la facture. */
  .atelier { display: block; }
  .atelier-saisie, .atelier-liste { position: static; }

  /* Les faits passent sur deux colonnes : en bande, ils deviendraient une
     seule colonne interminable. */
  .bande-faits {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--e3) var(--e4);
    padding: 14px var(--e4);
  }
  .fait-valeur { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Cinq rangées : au-delà, le panneau couvre l'écran entier. */
  .suggestion-corps { max-height: calc(var(--h-suggestion) * 5); }
  .suggestion-designation { font-size: var(--t-corps); }
  .suggestion-dci { font-size: var(--t-secondaire); }
  .suggestion-stock { font-size: var(--t-secondaire); }
  .colonne { gap: var(--e5); }

  .champ input[type="text"],
  .champ input[type="password"],
  .champ input[type="email"],
  .champ input[type="date"],
  .champ select,
  .champ textarea {
    /* 16 px minimum : en dessous, les navigateurs mobiles zooment à la saisie. */
    font-size: var(--t-corps);
    padding: 0 14px;
  }
  .champ textarea { padding: 12px 14px; }
  /* L'icône du sélecteur de date garde sa place à droite (D-145). */
  @supports selector(::-webkit-calendar-picker-indicator) {
    .champ input[type="date"] { padding-right: 40px; background-position: right 14px center; }
  }
  .champ label { font-size: var(--t-courant); margin-bottom: 6px; }

  .bouton { font-size: var(--t-corps); }
  /* Le format compact du bureau n'existe pas sur mobile : 32 px est sous la
     cible tactile minimale. Tout bouton atteint la hauteur de contrôle. */
  .bouton-petit { height: var(--h-ctrl); font-size: var(--t-corps); }

  /* ------------------------------------------------------------------
     Listes historiques sur mobile (D-063, D-065).
     ------------------------------------------------------------------ */
  /* La barre se replie derrière un bouton : déployée, elle occupait la moitié
     de l'écran avant la première ligne (D-066). Le compte des filtres posés
     reste visible replié — sans quoi on croirait tout voir (D-063). */
  .filtres-historique { padding: 0; border-color: var(--g200); }
  .filtres-bouton {
    display: flex;
    align-items: center;
    gap: var(--e2);
    min-height: var(--h-ctrl);
    padding: 0 var(--e4);
    font-size: var(--t-corps);
    font-weight: 600;
    color: var(--g700);
    cursor: pointer;
    list-style: none;
  }
  .filtres-libelle::after {
    content: "▾";
    margin-left: var(--e2);
    font-size: var(--t-aide);
    color: var(--g500);
  }
  .filtres-historique[open] .filtres-libelle::after { content: "▴"; }
  .filtres-historique[open] .filtres-bouton { border-bottom: 1px solid var(--g200); }
  .filtres-compte {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: var(--r-pilule);
    background: var(--vert-clair);
    border: 1px solid var(--vert-bord);
    color: var(--vert-fonce);
    font-size: var(--t-aide);
    font-weight: 700;
  }
  .filtres-corps { padding: var(--e4); }
  .grille-filtres { flex-direction: column; align-items: stretch; gap: var(--e4); }
  .grille-filtres .champ, .grille-filtres .champ-date { flex: none; max-width: none; }
  .champ-bouton .bouton { width: 100%; }
  .grille-filtres .champ-bouton { flex-direction: column; align-items: stretch; gap: var(--e3); }
  .filtres-effacer { align-self: center; font-size: var(--t-corps); }
  .raccourci { height: var(--h-ctrl); padding: 0 var(--e4); border-radius: var(--r-pilule); font-size: var(--t-corps); }

  /* La pagination cède la place au déroulé continu : sur un pouce, « page
     suivante » est moins naturel qu'un bouton qui allonge la liste. */
  .pagination-bureau { display: none; }
  .bouton-suite { display: flex; width: 100%; }
  .suite-compte { display: block; }

  /* La quantité est ce qu'on cherche sur une carte : elle domine. */
  .tableau.tableau-journal tbody td .quantite { font-size: var(--t-ecran); }
  .transition-lieu { min-width: 0; font-size: var(--t-secondaire); }
  .transition-avant, .transition-apres { font-size: var(--t-corps); }
  .date-jour, .date-heure { display: inline; font-size: var(--t-corps); }

  /* La recherche passe en colonne : côte à côte, le champ devient trop étroit. */
  .barre-recherche { flex-direction: column; align-items: stretch; }
  .barre-recherche .champ { max-width: none; }
  .pagination { flex-direction: column; gap: var(--e2); }
  .pagination .bouton { width: 100%; }

  /* ------------------------------------------------------------------
     Un tableau devient une pile de cartes (D-039).
     Même balisage qu'au bureau : la table reste la structure, la CSS
     seule la réorganise. L'entête de colonne est restitué par
     data-libelle sur chaque cellule.
     ------------------------------------------------------------------ */
  .tableau-cadre {
    background: transparent;
    border: 0;
    border-radius: 0;
    overflow-x: visible;
  }
  .tableau, .tableau thead, .tableau tbody, .tableau tr, .tableau td {
    display: block;
  }
  .tableau thead { display: none; }

  .tableau tbody tr {
    display: flex;
    flex-direction: column;
    margin-bottom: var(--e3);
    padding: var(--e4);
    background: var(--blanc);
    border: 1px solid var(--g200);
    border-radius: var(--r-carte);
  }
  .tableau tbody tr:hover { background: var(--blanc); }
  .tableau tbody tr:last-child { margin-bottom: 0; }

  .tableau tbody td {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0 var(--e4);
    padding: 6px 0;
    border-bottom: 0;
    font-size: var(--t-corps);
    text-align: right;
  }
  .tableau tbody td > .aide { flex-basis: 100%; }
  /* L'entête de colonne, restitué à gauche de la valeur. */
  .tableau tbody td::before {
    content: attr(data-libelle);
    flex-shrink: 0;
    font-size: var(--t-secondaire);
    color: var(--g500);
    text-align: left;
  }

  /* Hiérarchie de la carte. L'ordre des colonnes du bureau est conservé
     dans le balisage ; seul l'affichage est réordonné. */
  .tableau tbody td.cellule-titre {
    order: -2;
    padding: 0;
    font-size: var(--t-titre);
    font-weight: 600;
    color: var(--g900);
    text-align: left;
  }
  .tableau tbody td.cellule-sous-titre {
    order: -1;
    padding: 0 0 10px;
    font-size: var(--t-courant);
    color: var(--g500);
    text-align: left;
  }
  .tableau tbody td.cellule-titre::before,
  .tableau tbody td.cellule-sous-titre::before,
  .tableau tbody td.cellule-actions::before,
  .tableau tbody td.colonne-actions::before { content: none; }

  .tableau tbody td.cellule-etat {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--e2);
    padding-bottom: 10px;
  }

  .tableau tbody td.cellule-actions,
  .tableau tbody td.colonne-actions {
    margin-top: 10px;
    padding: var(--e3) 0 0;
    border-top: 1px solid var(--g200);
  }
  .tableau tbody td.cellule-actions .rangee-actions,
  .tableau tbody td.colonne-actions .rangee-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: var(--e2);
  }
  .tableau tbody td.cellule-actions .bouton,
  .tableau tbody td.cellule-actions form,
  .tableau tbody td.colonne-actions .bouton,
  .tableau tbody td.colonne-actions form { width: 100%; }
  /* Au doigt, pas de survol : la carte garde l'icône ET l'intitulé (B4). */
  .bouton-geste { width: 100%; gap: var(--e2); padding: 0 var(--e3); }
  .bouton-geste .geste-intitule {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
  }

  /* ---- Matrice des droits : une carte par fonctionnalité ---- */
  .tableau-matrice .ligne-domaine {
    /* L'intitulé de domaine reste un titre de section, hors carte. */
    display: block;
    margin: var(--e5) 0 var(--e3);
    padding: 0;
    background: transparent;
    border: 0;
  }
  .tableau-matrice .ligne-domaine th {
    display: block;
    padding: 0;
    background: transparent;
    border: 0;
  }
  .tableau-matrice .colonne-fonctionnalite {
    order: -2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 0 0 var(--e3);
    margin-bottom: var(--e2);
    border-bottom: 1px solid var(--g200);
    font-size: var(--t-titre);
    font-weight: 600;
    color: var(--g900);
    text-align: left;
  }
  .tableau-matrice .colonne-fonctionnalite::before { content: none; }
  .tableau-matrice td.colonne-role {
    width: auto;
    padding: 0;
    text-align: right;
    white-space: normal;
  }
  /* La case garde sa cible tactile pleine (52 px sur mobile). */
  .tableau-matrice .case-droit { width: var(--h-ctrl); margin-right: -14px; }

  /* Les actions d'écran deviennent une barre fixe au-dessus des onglets —
     celles de l'entête seulement : posées dans le contenu, trois barres
     s'empilaient au même endroit et deux disparaissaient. */
  .entete-ecran > .actions-ecran {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--h-onglets);
    z-index: 20;
    flex-direction: row-reverse;
    gap: var(--e2);
    padding: var(--e3) var(--e4);
    background: var(--blanc);
    border-top: 1px solid var(--g200);
  }
  .entete-ecran > .actions-ecran .bouton { flex-grow: 1; }

  .barre-onglets {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    height: var(--h-onglets);
    background: var(--blanc);
    border-top: 1px solid var(--g200);
  }
  .onglet {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--e1);
    flex-grow: 1;
    font-size: var(--t-aide);
    color: var(--g500);
    text-decoration: none;
  }
  .onglet svg { stroke: var(--g500); }
  .onglet.actif { color: var(--vert); font-weight: 600; }
  .onglet.actif svg { stroke: var(--vert); }

  /* Panneau de menu : ouvert par l'ancre #menu, sans script ni route dédiée. */
  .panneau-menu {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: var(--g50);
    transform: translateY(100%);
    visibility: hidden;
  }
  .panneau-menu:target { transform: none; visibility: visible; }
  .panneau-menu-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e4);
    height: 56px;
    flex-shrink: 0;
    padding: 0 var(--e4);
    background: var(--blanc);
    border-bottom: 1px solid var(--g200);
  }
  .panneau-menu-entete h2 { margin: 0; font-size: var(--t-ecran); font-weight: 600; color: var(--g900); }
  .panneau-menu-corps {
    display: flex;
    flex-direction: column;
    gap: var(--e6);
    flex-grow: 1;
    padding: var(--e5) var(--e4);
    overflow-y: auto;
  }
  /* Un groupe à overflow: hidden peut rétrécir dans une colonne flex : sans
     cette règle, une section ouverte écrasait les autres au lieu de faire
     défiler le panneau. */
  .panneau-menu-corps > * { flex-shrink: 0; }
  /* La barre d'application masque le compte sous 900 px : le panneau le
     reprend, en haut, là où on le cherche (D-080). */
  .panneau-menu-compte {
    display: flex;
    align-items: center;
    gap: var(--e2);
    flex-shrink: 0;
    padding: var(--e3) var(--e4);
    background: var(--g100);
    border-bottom: 1px solid var(--g200);
  }
  .panneau-menu-compte .etiquette { font-size: var(--t-courant); color: var(--g500); }
  .panneau-menu-compte .nom { font-size: var(--t-courant); font-weight: 600; color: var(--g900); }

  .groupe-liste {
    display: flex;
    flex-direction: column;
    background: var(--blanc);
    border: 1px solid var(--g200);
    border-radius: var(--r-carte);
    overflow: hidden;
  }
  .ligne-liste {
    display: flex;
    align-items: center;
    gap: var(--e3);
    width: 100%;
    min-height: 56px;
    padding: 0 var(--e4);
    border: 0;
    border-left: 3px solid transparent;
    background: none;
    font-family: inherit;
    font-size: var(--t-corps);
    text-align: left;
    color: var(--g900);
    text-decoration: none;
  }
  .ligne-liste svg { stroke: var(--g500); flex-shrink: 0; }
  .ligne-liste + .ligne-liste { border-top: 1px solid var(--g200); }
  /* La déconnexion est un formulaire : le trait se pose sur lui. */
  .groupe-liste form { border-top: 1px solid var(--g200); }
  .groupe-liste form:first-child { border-top: 0; }
  .ligne-liste.actif { border-left-color: var(--orange); font-weight: 600; }
  .ligne-liste.actif svg { stroke: var(--orange); }
  .ligne-liste.deconnexion { color: var(--rouge); font-weight: 600; cursor: pointer; }
  .ligne-liste.deconnexion svg { stroke: var(--rouge); }

  /* Le repli mobile, même mécanique native que sur le bureau. */
  summary.ligne-repli {
    font-weight: 600;
    color: var(--g700);
    cursor: pointer;
    list-style: none;
  }
  summary.ligne-repli::-webkit-details-marker { display: none; }
  details.groupe-liste[open] > summary.ligne-repli {
    color: var(--g900);
    border-bottom: 1px solid var(--g200);
  }
  details.groupe-liste[open] > summary.ligne-repli + .ligne-liste { border-top: 0; }
  details.groupe-liste[open] > summary .menu-chevron { transform: rotate(180deg); }
}


/* ==========================================================================
   Aperçu d'un document (D-069)
   Ce qui est affiché est LE PDF, pas une approximation : le même part au
   téléchargement et à l'imprimante.
   ========================================================================== */
.champ-copies { width: 96px; flex-shrink: 0; }

/* Le cadre suit le format du papier, pas une fraction de la fenêtre : sans
   quoi un document d'une page laisse des centaines de pixels de vide. */
.cadre-document {
  display: flex;
  justify-content: center;
  padding: var(--e4);
  background: var(--g100);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.apercu-document {
  display: block;
  width: 100%;
  /* 860 plutôt que 794 : la visionneuse ajoute ses propres marges autour de
     la page, et on veut l'A4 à sa taille réelle à l'intérieur. */
  max-width: 860px;
  aspect-ratio: 794 / 1123;
  border: 0;
  background: var(--blanc);
}

/* La page d'une pièce (D-136) : une colonne de gestes, puis le papier. */
.piece { display: grid; grid-template-columns: 400px minmax(0, 1fr); gap: var(--e6); align-items: start; }
.piece-gestes { display: flex; flex-direction: column; gap: var(--e4); min-width: 0; }
/* Une cellule de texte long (un motif, un client) : une largeur de lecture. */
@media (min-width: 900px) {
  .tableau td.cellule-texte { max-width: 280px; }
}

@media (max-width: 899px) {
  .piece { grid-template-columns: minmax(0, 1fr); }
  /* Les faits passent l'un sous l'autre : le filet qui séparait les chiffres
     devient une ligne, au lieu d'un trait debout au milieu de la carte. */
  .fait-filet { flex-basis: 100%; width: auto; height: 1px; }
  /* Une ligne de retour tient en trois rangs : l'article ; son groupe, son
     prix et sa remise ; puis les quantités, la saisie au bout. En pile de
     libellés, elle mesurait 300 px par article. */
  .tableau-retour tbody tr { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: var(--e2) var(--e3); padding: var(--e3) var(--e4); }
  .tableau-retour tbody td { flex: 1 1 28%; flex-direction: column; align-items: flex-start; gap: 0; padding: 0; text-align: left; }
  .tableau-retour tbody td::before { font-size: var(--t-aide); }
  .tableau-retour tbody td.cellule-titre { flex: 1 0 100%; }
  .tableau-retour tbody td[data-libelle="Vendue"],
  .tableau-retour tbody td[data-libelle="Déjà reprise"],
  .tableau-retour tbody td[data-libelle="Restante"],
  .tableau-retour tbody td[data-libelle="À retourner"] { flex-basis: 18%; }
  .tableau-retour tbody td[data-libelle="À retourner"] { align-items: flex-end; }
  .champ-copies { max-width: none; width: auto; }

  /* Un A4 sur un téléphone se regarde, il ne se lit pas : le cadre garde le
     format, et le téléchargement reste le vrai chemin. */
  .cadre-document { padding: var(--e2); }
}


/* Le triangle des prix (D-072) : trois sommets, dont un calculé et figé. */
.grille-3-serree {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--e4);
}
/* Plus spécifique que `.champ input[type="text"]`, sans quoi le blanc l'emporte
   et le sommet calculé ne se distingue pas. */
.champ.sommet-calcule input[type="text"] { background: var(--g50); }
.etiquette-calcule {
  display: inline-block;
  margin-left: var(--e1);
  padding: 1px 6px;
  border-radius: var(--r-pilule);
  background: var(--g100);
  border: 1px solid var(--g200);
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--g500);
}

@media (max-width: 899px) {
  .grille-3-serree { grid-template-columns: minmax(0, 1fr); }
}


/* Saisie d'un comptage d'inventaire (D-078). Le champ vit DANS le tableau :
   on travaille plusieurs minutes sur une liste, on modifie des quantités sur
   place, on peut interrompre et reprendre — les comptages vivent en base, pas
   dans la page. */
.saisie-comptage,
.saisie-cellule {
  width: 84px;
  height: 34px;
  padding: 0 var(--e2);
  font-family: inherit;
  font-size: var(--t-courant);
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--g900);
  background: var(--blanc);
  border: 1px solid var(--g400);
  border-radius: var(--r-ctrl);
}
.saisie-comptage:hover, .saisie-cellule:hover { border-color: var(--g500); }
/* Une case refusée garde sa place, bordée de rouge ; son message vient sous
   la ligne, sur toute la largeur (D-243, Q1). */
.cellule-saisie.en-erreur .saisie-comptage { border-color: var(--rouge); }
.tableau tbody tr.ligne-erreur td { padding-top: 0; border-top: 0; }
.ligne-erreur .message-erreur { display: block; margin-top: 0; }
/* Une ligne qu'on ne peut plus reprendre : elle s'efface sans disparaître. */
.tableau tbody tr.ligne-epuisee td { color: var(--g500); }
/* Non comptée n'est pas comptée à zéro : elle se lit comme une absence. */
.non-comptee { font-size: var(--t-aide); font-style: italic; color: var(--g500); }

/* Une ligne qu'une passe antérieure a confirmée : rien à recompter, rien à
   lire dans les colonnes de la passe en cours (D-081). Elle s'efface sans
   disparaître — son écart, lui, reste lisible à gauche. */
.cellule-close {
  font-size: var(--t-aide);
  font-style: italic;
  color: var(--g500);
  text-align: center;
  background: var(--g50);
}

@media (max-width: 899px) {
  /* Sur un téléphone, le comptage se fait debout dans le rayon : le champ
     atteint la cible tactile et prend la largeur de sa cellule. */
  .saisie-comptage,
  .saisie-cellule { width: 100%; max-width: 140px; height: var(--h-ctrl); font-size: var(--t-corps); }
}

/* La préparation des commandes (D-180) : un seul formulaire, dont le premier
   bouton — « Enregistrer » — est celui qu'Entrée déclenche. Il existe pour le
   navigateur, pas pour l'œil : présent dans la page, hors de la vue. */
.envoi-par-defaut {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.proposer-quantites { margin-bottom: var(--e3); }
.enregistrer-quantites { margin-top: var(--e3); }

/* ==========================================================================
   Comptoir de vente — le poste de vente (D-097, D-102, D-106)
   ========================================================================== */

/* Un écran « plein cadre » tient dans la hauteur de la fenêtre et ne fait
   jamais défiler la page : c'est le panier qui défile dans son cadre. Mesuré
   avant/après à 1366×768, la cible matérielle de D-015 : l'écran faisait
   1 060 px pour 768 disponibles, et le bouton d'envoi tombait 251 px sous le
   pli — le vendeur défilait pour conclure, à chaque client.

   La règle ne vaut qu'au-dessus de 900 px. Sur un téléphone, les trois bandes
   se remettent à la file et la page redéfile normalement (D-032). */
@media (min-width: 900px) {
  .coque.plein-cadre { height: 100%; }
  .coque.plein-cadre .zone { min-height: 0; }
  .coque.plein-cadre .corps {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-top: var(--e4);
    padding-bottom: var(--e4);
  }
  .coque.plein-cadre .corps-etroit {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    min-height: 0;
  }
  /* Un bandeau se lit en entier ou ne sert à rien : c'est le panier qui cède
     la hauteur, jamais le message. */
  .coque.plein-cadre .alertes { flex-shrink: 0; }
  .comptoir { flex-grow: 1; min-height: 0; }
  .comptoir-panier { flex-grow: 1; min-height: 0; }
  .comptoir-lignes { flex-grow: 1; min-height: 0; overflow-y: auto; }
  /* L'entête de colonnes reste lisible pendant qu'on défile dans le panier. */
  .comptoir-lignes thead th { position: sticky; top: 0; z-index: 1; }
}

/* Trois bandes : la saisie en tête, le panier au milieu, l'envoi en pied.
   Rien ne bouge sous la main du vendeur — le champ produit ne descend pas à
   mesure que le panier s'allonge. */
.comptoir { display: flex; flex-direction: column; gap: var(--e4); }

/* --- Bande 1 : la saisie --- */
.comptoir-saisie { flex-shrink: 0; padding: var(--e3) var(--e4); }
.saisie-rangee {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 132px 188px;
  gap: var(--e3);
  align-items: end;
}
/* Le bouton s'aligne sur les champs, qui portent un libellé au-dessus. */
.saisie-rangee > .bouton { margin-bottom: 0; }
/* Un champ en erreur porte son message : la rangée cesse d'être alignée en
   pied, sinon le message pousserait le bouton hors de la ligne. */
.saisie-rangee.avec-erreur { align-items: start; }
.saisie-rangee.avec-erreur > .bouton { margin-top: 26px; }
.comptoir-saisie > .aide { margin-top: var(--e2); }
.comptoir-saisie > .liste-candidats { margin-top: var(--e3); }

/* --- Bande 2 : le panier --- */
.comptoir-panier {
  display: flex;
  flex-direction: column;
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.panier-entete {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  flex-shrink: 0;
  min-height: 44px;
  padding: var(--e1) var(--e4);
  border-bottom: 1px solid var(--g300);
}
/* Il ne passe pas à la ligne : avec l'ordonnance, cinq volets le serraient
   jusqu'à le couper en deux à 1366 px (D-195, lot 2). */
.panier-titre { font-size: var(--t-corps); font-weight: 600; color: var(--g900); white-space: nowrap; }
.panier-outils { display: flex; align-items: center; gap: var(--e2); }
/* Le panier ne coupe plus ce qui déborde : son volet doit pouvoir descendre
   sur le pied. C'est la zone des lignes qui garde les coins arrondis. */
.comptoir-lignes,
.encaissement-lignes { overflow-x: auto; border-radius: 0 0 var(--r-carte) var(--r-carte); }
.comptoir-vide { margin: var(--e4); }
/* La quantité d'une ligne se change sur place (D-231) : un champ court, à la
   hauteur du bouton « Retirer », pour que la ligne ne grandisse pas. Sur un
   téléphone, il garde la cible tactile de la saisie en tableau. */
@media (min-width: 900px) {
  .tableau-panier .quantite-ligne .saisie-cellule { width: 64px; height: 32px; }
}

/* La ligne du timbre : elle est sur la pièce, mais ce n'est pas un article.
   Le fond la distingue sans la cacher (D-086, D-091). */
.ligne-timbre td { background: var(--g50); color: var(--g700); }
.ligne-dci { font-size: var(--t-aide); font-style: italic; color: var(--g500); }
/* La classe réglementaire d'une ligne (D-195, lot 2), après son groupe de taxe. */
.ligne-tableau { margin-left: var(--e2); vertical-align: 1px; }

/* --- Les volets : ce qui ne se lit pas à chaque vente ---
   Le récapitulatif par groupe est une pièce fiscale (D-091), le bloc client
   sert une vente sur vingt (D-066). Ils sont à un clic, derrière un libellé
   en toutes lettres — jamais derrière une icône seule (D-015). */
.volet { position: static; }
.volet > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 var(--e3);
  border: 1px solid var(--g300);
  border-radius: var(--r-ctrl);
  background: var(--blanc);
  font-size: var(--t-secondaire);
  font-weight: 600;
  color: var(--g700);
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.volet > summary::-webkit-details-marker { display: none; }
.volet > summary:hover { background: var(--g50); color: var(--g900); }
.volet[open] > summary { background: var(--g100); color: var(--g900); }
.volet-marque { font-weight: 400; color: var(--g500); }
/* Le volet qui attend quelque chose se signale sans s'ouvrir (D-195, lot 2) :
   l'ordonnance d'une ligne réglementée, tant qu'un champ manque. */
.volet-requis > summary,
.volet-requis > summary:hover { border-color: var(--orange-bord); background: var(--orange-clair); }
.volet-requis .volet-marque { color: var(--orange-fonce); font-weight: 600; }
.ordonnance-motif { margin: 0; }
.volet-chevron { stroke: var(--g500); transition: transform 120ms ease; }
.volet[open] .volet-chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .volet-chevron { transition: none; } }
.volet-corps {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  /* Un volet ouvert recouvre le panier et, s'il le faut, le pied : c'est là
     que la main travaille à ce moment. Il s'arrête au bas de l'écran — à
     1366×768, 360 px sous un entête de panier posé à 408 px. La première
     valeur sert au navigateur qui ne connaît pas max(). */
  max-height: 360px;
  max-height: max(240px, calc(100vh - 408px));
  overflow-y: auto;
  padding: var(--e4);
  background: var(--blanc);
  border-bottom: 1px solid var(--g300);
  box-shadow: 0 8px 16px rgba(20, 24, 29, 0.10);
}

/* --- Bande 3 : le pied, ce que le client paie et l'acte qui clôt --- */
.comptoir-pied {
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--e6);
  flex-wrap: wrap;
  padding: var(--e3) var(--e4);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-top: 3px solid var(--vert);
  border-radius: var(--r-carte);
}
/* Le montant et son explication se rangent en colonne : côte à côte, la phrase
   poussait la rangée de signature sur un second rang, et le panier y perdait
   soixante-dix pixels. La caisse se lit sur le bouton : la colonne reprend la
   largeur de la phrase qui la nommait, et l'explication tient en deux lignes. */
.pied-total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 320px;
  min-width: 0;
  max-width: 480px;
}
.pied-montant-rangee { display: flex; align-items: baseline; gap: var(--e3); }
.pied-etiquette { font-size: var(--t-secondaire); font-weight: 600; color: var(--g700); white-space: nowrap; }
/* Le nombre qu'on dit au client à voix haute : il se lit d'un bout du
   comptoir à l'autre. */
.pied-montant {
  font-size: var(--t-chiffre);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--g900);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.pied-detail { font-size: var(--t-aide); color: var(--g500); }
.pied-envoi { display: flex; align-items: flex-end; gap: var(--e3); flex-shrink: 0; }
.pied-envoi .champ { width: 172px; }
/* Un mot de passe et un nom de caisse sont courts : ils ne prennent pas la
   largeur d'un nom de vendeur. */
.pied-envoi .champ-court { width: 148px; }
.pied-envoi .champ label { font-size: var(--t-aide); color: var(--g500); }
.pied-envoi .alerte { margin: 0; }
.entete-note { font-size: var(--t-aide); color: var(--g500); }

@media (max-width: 899px) {
  /* Au comptoir sur téléphone : les bandes se remettent à la file, la saisie
     passe en colonne, et le volet cesse de survoler le panier. */
  .saisie-rangee { grid-template-columns: minmax(0, 1fr); }
  .saisie-rangee.avec-erreur > .bouton { margin-top: 0; }
  .panier-entete { flex-wrap: wrap; }
  .volet-corps {
    position: static;
    max-height: none;
    padding: var(--e4) 0 0;
    border-bottom: 0;
    box-shadow: none;
  }
  .grille-champs > .champ-large,
  .grille-champs > .rangee-actes { grid-column: auto; padding-top: 0; }
  /* Le champ Patient prend la largeur du volet ; « Retrouver », le secours
     sans script, passe dessous (D-179, P14). */
  .grille-champs > .champ-large.champ-patient { grid-column: 1 / -1; }
  .rangee-champs > .champ-suggestion { flex-basis: 100%; }
  .comptoir-pied { align-items: stretch; }
  .pied-total { flex-wrap: wrap; }
  .pied-envoi { flex-direction: column; align-items: stretch; width: 100%; }
  .pied-envoi .champ { width: 100%; }
  .entete-note { display: none; }

  /* Une ligne de panier tient en deux rangs : l'article, puis la quantité,
     le prix, le montant et le retrait côte à côte. En pile de libellés, elle
     mesurait 280 px, et l'envoi tombait trois écrans plus bas (D-032). */
  .tableau-panier tbody tr {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--e2) var(--e3);
    padding: var(--e3) var(--e4);
  }
  .tableau-panier tbody td {
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 0;
    text-align: left;
  }
  .tableau-panier tbody td::before { font-size: var(--t-aide); }
  .tableau-panier tbody td.cellule-titre { flex: 1 0 100%; gap: 2px; }
  .tableau-panier tbody td.cellule-sous-titre { display: none; }
  .tableau-panier tbody td[data-libelle="Montant"] { align-items: flex-end; text-align: right; }
  .tableau-panier tbody td.colonne-actions {
    flex: 0 0 auto;
    align-self: center;
    margin: 0;
    padding: 0;
    border-top: 0;
  }
  .tableau-panier tbody td.colonne-actions form,
  .tableau-panier tbody td.colonne-actions .bouton { width: auto; }
  /* Le timbre se distingue par le fond de sa carte, pas de chaque cellule. */
  .tableau-panier tbody tr.ligne-timbre { background: var(--g50); }
  .tableau-panier tbody tr.ligne-timbre td { background: transparent; }
  /* Trois volets ne tiennent pas sur une ligne de 390 px : le troisième
     sortait de l'écran. Ils passent à la ligne. */
  .panier-outils { flex-wrap: wrap; }
}

/* ==========================================================================
   Encaissement — l'écran de caisse (D-116, D-117, D-118)
   ========================================================================== */

.encaissement { display: flex; flex-direction: column; gap: var(--e4); }
.champ-court { max-width: 200px; }
.groupe-taxe { font-size: var(--t-aide); color: var(--g500); }

@media (min-width: 900px) {
  .encaissement { flex-grow: 1; min-height: 0; }
  .encaissement-detail { flex-grow: 1; min-height: 0; }
  .encaissement-lignes { flex-grow: 1; min-height: 0; overflow-y: auto; }
  .encaissement-lignes thead th { position: sticky; top: 0; z-index: 1; }
}

/* --- Écran prise de caisse --- */
.encaissement-prise { max-width: 480px; margin: 0; align-self: flex-start; }
.prise-titre { font-size: var(--t-ecran); font-weight: 600; color: var(--g900); margin-bottom: var(--e2); }
.prise-sous-titre { font-size: var(--t-courant); color: var(--g500); margin: 0 0 var(--e5); }
.prise-form { display: flex; flex-direction: column; gap: var(--e4); }

/* --- Bandeau file d'attente --- */
.bandeau-file {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 56px;
  padding: var(--e2) var(--e4);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.bandeau-file-active {
  background: var(--orange-clair);
  border-color: var(--orange-bord);
}
.bandeau-file-gauche { display: flex; align-items: center; gap: 10px; }
.bandeau-file-caisse { font-size: var(--t-courant); font-weight: 600; color: var(--g900); }
.bandeau-file-sep { width: 1px; height: 16px; background: var(--g300); }
.bandeau-file-active .bandeau-file-sep { background: var(--orange-bord); }
.bandeau-file-compte { font-size: var(--t-secondaire); color: var(--g500); }
.bandeau-file-active .bandeau-file-compte { font-weight: 600; color: var(--orange-fonce); }
.bouton-appel-bandeau { height: 42px; padding: 0 26px; font-size: var(--t-corps); }

/* --- État vide (pas de vente en cours) --- */
.encaissement-vide {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
  text-align: center;
  padding: var(--e6);
}
.encaissement-vide-icone { color: var(--g300); margin-bottom: var(--e4); }
.encaissement-vide-titre { font-size: var(--t-titre); font-weight: 600; color: var(--g900); margin-bottom: var(--e1); }
.encaissement-vide-texte { font-size: var(--t-courant); color: var(--g500); max-width: 320px; }
.encaissement-vide-action { margin-top: var(--e5); }

/* --- Bande 2 : le détail de la vente --- */
.encaissement-detail {
  display: flex;
  flex-direction: column;
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.detail-entete {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  flex-shrink: 0;
  flex-wrap: wrap;
  min-height: 44px;
  padding: var(--e1) var(--e4);
  border-bottom: 1px solid var(--g300);
}
/* Le titre et l'information se suivent sur une ligne ; une information trop
   longue (celle d'un avoir) passe dessous, et les volets gardent leur rang. */
.detail-identite {
  display: flex;
  flex: 1 1 0;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px var(--e4);
  min-width: 0;
  padding: 6px 0;
}
.detail-titre { font-size: var(--t-corps); font-weight: 600; color: var(--g900); }
.detail-info { font-size: var(--t-aide); color: var(--g500); }

/* --- Bande 3 : le pied d'encaissement --- */
.encaissement-pied {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: var(--e3);
  padding: var(--e3) var(--e4);
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-top: 3px solid var(--vert);
  border-radius: var(--r-carte);
}

/* Bandeau du total */
.bandeau-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px var(--e4);
  background: var(--vert-clair);
  border: 1px solid var(--vert-bord);
  border-radius: var(--r-ctrl);
}
.bandeau-total-gauche { display: flex; align-items: baseline; gap: var(--e3); }
.bandeau-total-etiquette {
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--vert-fonce);
}
.bandeau-total-montant {
  font-size: var(--t-du);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--g900);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.bandeau-total-detail { font-size: var(--t-aide); color: var(--g500); text-align: right; line-height: 1.4; }

/* Contrôles : remise + séparateur + règlement */
.pied-controles {
  display: flex;
  align-items: flex-end;
  gap: var(--e3);
}
.pied-remise-groupe {
  display: flex;
  align-items: flex-end;
  gap: var(--e2);
  flex-shrink: 0;
}
.pied-remise-groupe .champ-court { max-width: 72px; }
.pied-remise-info { font-size: var(--t-secondaire); color: var(--g700); align-self: center; }
.pied-separateur { width: 1px; height: var(--h-ctrl); background: var(--g200); flex-shrink: 0; }
.pied-reglement-groupe {
  display: flex;
  align-items: flex-end;
  gap: var(--e2);
  flex: 1;
  min-width: 0;
}
.pied-reglement-groupe > .champ { flex: 1; min-width: 130px; max-width: 200px; }
.pied-reglement-groupe > .champ.champ-court { max-width: 120px; min-width: 100px; }
/* L'acte au bout de la rangée, quelle que soit la largeur des champs. */
.bouton-encaisser { height: 52px; margin-left: auto; padding: 0 var(--e6); font-size: var(--t-titre); flex-shrink: 0; }
/* La monnaie à rendre se lit à côté du reçu, à la hauteur des champs : sous
   lui, elle faisait remonter la rangée pendant la frappe. */
.monnaie-rendue {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  height: var(--h-ctrl);
  padding: 0 var(--e3);
  background: var(--vert-clair);
  border: 1px solid var(--vert-bord);
  border-radius: var(--r-ctrl);
  font-size: var(--t-courant);
  font-weight: 600;
  color: var(--vert-fonce);
  white-space: nowrap;
}
.monnaie-rendue[hidden] { display: none; }

/* Un avoir fait sortir l'argent du tiroir : le bandeau et le filet du pied
   passent à l'orange de l'identité, l'attention ; le bouton reste vert. */
.encaissement-pied.pied-avoir { border-top-color: var(--orange); }
.bandeau-total-avoir { background: var(--orange-clair); border-color: var(--orange-bord); }
.bandeau-total-avoir .bandeau-total-etiquette { color: var(--orange-fonce); }

/* Au téléphone, le total sous le pouce (comptoir et encaissement). */
.barre-total { display: none; }

/* --- Fermeture : le comptage du tiroir, sur deux colonnes (D-147, D-148) --- */
.fermeture { max-width: 800px; }
.billetage-colonnes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e8); align-items: start; }
/* Colonnes égales : au téléphone, les deux tables empilées alignent leurs champs. */
.billetage { width: 100%; border-collapse: collapse; table-layout: fixed; }
.billetage th {
  padding: 0 0 var(--e2);
  font-size: var(--t-capitale);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: left;
  color: var(--g500);
}
.billetage td { padding: 3px 0; }
.billetage .colonne-nombre { text-align: right; }
.billetage .champ { max-width: 96px; margin-left: auto; }
.billetage .champ input { height: 36px; }
.billetage-montant { color: var(--g700); white-space: nowrap; }

/* --- Numéraire : la caisse tenue, et le geste (2.11, D-146, D-148) --- */
.numeraire { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e6); align-items: start; max-width: 960px; }

@media (max-width: 899px) {
  .billetage-colonnes { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .billetage-colonnes > .billetage + .billetage thead { display: none; }
  .numeraire { grid-template-columns: minmax(0, 1fr); }
  .encaissement-prise { max-width: none; }
  .champ-court { max-width: none; }
  .detail-entete { flex-wrap: wrap; }
  .bandeau-file { height: auto; min-height: 48px; padding: var(--e2) var(--e4); flex-wrap: wrap; gap: var(--e2); }
  .bouton-appel-bandeau { width: 100%; height: var(--h-ctrl); font-size: var(--t-corps); }
  .bandeau-total { flex-direction: column; align-items: flex-start; gap: var(--e2); }
  .bandeau-total-montant { font-size: var(--t-du); }
  .bandeau-total-detail { text-align: left; }
  .pied-controles { flex-direction: column; align-items: stretch; }
  .pied-remise-groupe { flex-wrap: wrap; }
  .pied-separateur { width: auto; height: 1px; }
  .pied-reglement-groupe { flex-wrap: wrap; }
  .pied-reglement-groupe > .champ { max-width: none; min-width: 0; flex: auto; }
  .bouton-encaisser { width: 100%; }

  /* Les deux écrans plein cadre gardent leurs actes d'entête sous le titre ;
     la barre fixe porte le total et un lien vers l'envoi ou le règlement.
     Le pouce trouve l'acte qui conclut, plus celui qui détruit (D-032). */
  .coque.plein-cadre .actions-ecran { position: static; padding: 0; border: 0; background: transparent; }
  .coque.plein-cadre .actions-ecran .bouton { height: 40px; font-size: var(--t-secondaire); }
  .barre-total {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--h-onglets);
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e3);
    padding: var(--e3) var(--e4);
    background: var(--blanc);
    border-top: 1px solid var(--g200);
    text-decoration: none;
  }
  .barre-total-chiffre { display: flex; flex-direction: column; }
  .barre-total-etiquette { font-size: var(--t-aide); color: var(--g500); }
  .barre-total-montant { font-size: var(--t-montant); font-weight: 700; color: var(--g900); white-space: nowrap; }
}

/* ==========================================================================
   Contrôler la caisse (lot Design 4, D-160)
   ========================================================================== */

/* Un écran fait de cartes l'une sous l'autre, et des cartes côte à côte :
   autant de colonnes que la largeur en tient, une seule au téléphone. */
.pile-cartes { display: flex; flex-direction: column; gap: var(--e5); }
.grille-cartes { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--e5); }
.situation-actes > form { margin: 0; }
/* L'acte qui ne se défait pas, sa mise en garde dessous (le Z, D-138). */
.acte-annonce { display: flex; flex-direction: column; align-items: flex-end; gap: var(--e1); margin: 0; }
.acte-annonce > .aide { margin: 0; }

/* Une cellule courte ne passe pas à la ligne (« CAISSE 01 »). */
.tableau td.cellule-courte { white-space: nowrap; }
/* Un tableau serré : le récapitulatif d'un quart tient ses huit modes. */
.tableau-serre td, .tableau-serre th { padding-top: 6px; padding-bottom: 6px; }
/* Une ligne sans mouvement se lit comme une absence (D-157, piste D). */
.tableau tbody tr.ligne-vide td { color: var(--g500); }
/* La ligne de total d'un rapport et d'un récapitulatif de quart : filet
   double au-dessus, en gras (D-138). L'encaissement et les relevés gardent
   la leur. */
.tableau-rapport tr.ligne-total td,
.tableau-serre tr.ligne-total td { font-weight: 700; border-top: 2px solid var(--g400); }

/* L'écart d'un tiroir : juste, ou faux dans un sens comme dans l'autre. */
.ecart-juste, .ligne-info .ecart-juste { color: var(--vert-fonce); }
.ecart-faux, .ligne-info .ecart-faux { color: var(--rouge); }

/* La page d'un quart (D-147, D-148) : le quart et son récapitulatif à
   gauche, le rapprochement et le document à droite. Au téléphone, le
   rapprochement passe avant le récapitulatif : c'est lui qu'on vient faire. */
.quart {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "faits actes" "recap actes";
  gap: var(--e6);
  align-items: start;
  max-width: 1100px;
}
.quart-faits { grid-area: faits; }
.quart-actes { grid-area: actes; display: flex; flex-direction: column; gap: var(--e6); min-width: 0; }
.quart-recap { grid-area: recap; }
.justification-lue { margin: 0; font-size: var(--t-courant); font-weight: 600; color: var(--g900); }

/* La page d'un rapport (D-138) : quatre tuiles, puis ses rubriques. */
.tuiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--e4); }
.tuile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 18px;
  background: var(--blanc);
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
}
.tuile .aide { margin: 0; }
.tuile .aide.ok { color: var(--vert-fonce); }
.rubrique { display: flex; flex-direction: column; gap: var(--e3); }
.rubrique > .section-titre { margin: 0; padding: 0; border: 0; }
.rubrique > .aide { margin: 0; }
.tableau-rapport td.colonne-nombre, .tableau-rapport th.colonne-nombre { white-space: nowrap; }
.tableau-rapport tr.ligne-type td { font-weight: 600; background: var(--g50); }
.tableau-rapport tr.ligne-groupe td:first-child { padding-left: 34px; color: var(--g700); }
.tableau-rapport tr.ligne-famille td { background: var(--g50); font-weight: 700; letter-spacing: 0.02em; }
.tableau-rapport tr.ligne-sous-total td { color: var(--g500); font-weight: 600; }
/* Les zéros s'effacent en gris (D-138), au contraste des absences (D-157). */
.tableau-rapport td.zero, .tableau-rapport tr.ligne-zero td, .fait-nombre.zero { color: var(--g500); }

/* Un nombre de la carte de situation prend le sens d'un montant : rouge
   quand il signale un défaut, gris quand il est nul. */
.fait-nombre.montant-negatif { color: var(--rouge); }
.fait-nombre.montant-nul { color: var(--g500); }

@media (max-width: 899px) {
  /* Au téléphone, la ligne de total est une carte : un filet sur la carte,
     pas un sur chaque valeur. */
  .tableau-serre tbody tr.ligne-total { border-top: 2px solid var(--g400); }
  .tableau-serre tr.ligne-total td { border-top: 0; }
  /* Les rubriques d'un rapport restent des tables (D-039 amendé) : une pile
     de cartes sans libellés n'y dit plus rien. Le cadre défile. */
  .tableau-cadre.cadre-defile {
    overflow-x: auto;
    background: var(--blanc);
    border: 1px solid var(--g300);
    border-radius: var(--r-carte);
  }
  .tableau.tableau-rapport { display: table; min-width: 100%; }
  .tableau-rapport thead { display: table-header-group; }
  .tableau-rapport tbody { display: table-row-group; }
  .tableau-rapport tr,
  .tableau-rapport tbody tr { display: table-row; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; }
  .tableau-rapport th,
  .tableau-rapport tbody td {
    display: table-cell;
    padding: var(--e2) var(--e3);
    font-size: var(--t-courant);
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--g200);
  }
  .tableau-rapport tbody td.colonne-nombre,
  .tableau-rapport th.colonne-nombre { text-align: right; }
  .tableau-rapport tbody td::before { content: none; }
  .tableau-rapport tr.ligne-groupe td:first-child { padding-left: var(--e6); }
  .quart { grid-template-columns: minmax(0, 1fr); grid-template-areas: "faits" "actes" "recap"; }
  /* Au téléphone, un mode de paiement sans mouvement ne fait pas une carte :
     huit cartes dont quatre vides repoussaient le tiroir de 500 px. */
  .tableau-serre tbody tr.ligne-vide { display: none; }
  .tuiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .acte-annonce { align-items: stretch; }
}

/* ==========================================================================
   Stock et inventaire (lot Design 5, D-161)
   ========================================================================== */

/* L'article retenu d'un mouvement et son stock, dans le même encadré : la
   désignation, le lien pour en changer, puis rayon, magasin et total en
   faits (D-062). */
.bande-article { flex-wrap: wrap; }
.bande-article > .fait { flex: 1 1 0; }
.bande-article > .faits {
  flex-basis: 100%;
  gap: var(--e2) var(--e8);
  padding-top: var(--e3);
  border-top: 1px solid var(--g200);
}
.bande-article > .faits .fait-valeur { font-size: var(--t-titre); font-variant-numeric: tabular-nums; }

/* Une liste en sections : un titre et son compte, son aide, son tableau. */
.section-liste { display: flex; flex-direction: column; gap: var(--e3); }
.section-liste + .section-liste { margin-top: var(--e6); }
.section-liste > .titre-secondaire,
.section-liste > .aide { margin: 0; }

/* Le commentaire d'un mouvement se relit sous son motif, pas à côté : à
   côté, il élargissait la colonne et faisait passer le numéro et la
   désignation à la ligne (le journal réel : « Vente V-002837 »). */
.tableau-journal td[data-libelle="Motif"] > .aide { display: block; }

/* La liste des refus d'une alerte (D-078). */
.alerte ul { margin: var(--e2) 0 0; padding-left: 18px; }

/* La campagne (seul l'atelier de l'inventaire : la facture fournisseur
   garde le sien, lot 7) : les faits, puis l'atelier ; à gauche la liste et son titre
   à la hauteur de la première carte, à droite les cartes l'une sous l'autre. */
.bande-faits + .atelier-inventaire { margin-top: var(--e5); }
/* Le geste qui accompagne un fait : réimprimer la fiche qui l'a figé. */
.fait-lien { font-size: var(--t-secondaire); font-weight: 600; }
.atelier-inventaire .atelier-liste > .titre-secondaire:first-child { margin-top: 0; }
.atelier-inventaire .atelier-saisie { display: flex; flex-direction: column; gap: var(--e4); }
/* Deux actes sur une rangée étroite passent à la ligne plutôt que de sortir
   de la carte (la fiche de comptage, au téléphone). */
.piece-gestes .rangee-actions { flex-wrap: wrap; }
/* Deux passes : le tableau prend la largeur (D-082), les cartes se rangent
   côte à côte au-dessus au lieu de s'empiler. */
.atelier-empile .atelier-saisie {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  align-items: start;
  max-width: none;
}
/* Ce qui demande attention le dit sous sa ligne, en orange. */
.atelier-controle .ligne-info { flex-wrap: wrap; }
.atelier-controle .ligne-info > dd.aide { flex-basis: 100%; margin: 0; text-align: left; white-space: normal; }
.ligne-info.a-surveiller dt,
.ligne-info.a-surveiller dd { color: var(--orange-fonce); }
.ligne-info.a-surveiller dt { font-weight: 600; }

@media (max-width: 899px) {
  /* La désignation passe à la ligne : coupée, deux dosages se confondent. */
  .bande-article { align-items: flex-start; }
  .bande-article .fait-valeur { overflow: visible; white-space: normal; }
  .bande-article > .faits { gap: var(--e2) var(--e6); }

  /* La campagne au téléphone : ce qu'on a compté, puis la liste à compter,
     puis les actes. Le magasinier vient compter. */
  .atelier-inventaire { display: flex; flex-direction: column; gap: var(--e4); }
  .atelier-inventaire .atelier-saisie { display: contents; }
  .atelier-inventaire .atelier-controle { order: 1; }
  .atelier-inventaire .atelier-liste { order: 2; }
  .atelier-inventaire .atelier-acte { order: 3; }

  /* Une carte en rangs (D-039) : le titre et sa référence, puis les valeurs
     côte à côte, libellé au-dessus. En pile de libellés, une rupture
     mesurait 380 px, une campagne 360. */
  .tableau-rangs tbody tr { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: var(--e3) var(--e4); }
  .tableau-rangs tbody td {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 2px;
    padding: 0;
    text-align: left;
  }
  .tableau-rangs tbody td::before { font-size: var(--t-aide); }
  .tableau-rangs tbody td.cellule-titre,
  .tableau-rangs tbody td.cellule-sous-titre,
  .tableau-rangs tbody td.cellule-large,
  .tableau-rangs tbody td.cellule-etat,
  .tableau-rangs tbody td.cellule-actions { flex: 1 0 100%; }
  .tableau-rangs tbody td.cellule-titre { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--e1) var(--e2); }
  .tableau-rangs tbody td.cellule-sous-titre { margin-top: calc(var(--e1) - var(--e3)); }
  .tableau-rangs tbody td.cellule-etat { flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--e2); }
  .tableau-rangs tbody td.cellule-large { flex-direction: row; align-items: baseline; gap: var(--e2); }
  .tableau-rangs tbody td.cellule-actions { margin-top: 0; }

  /* Une ligne de comptage tient en deux rangs : l'article, puis ses nombres
     et la saisie au bout (comme la ligne de retour d'un avoir, D-159). La
     passe précédente, s'il y en a une, fait un rang à elle, en gris. */
  .tableau-comptage tbody tr { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: var(--e2); padding: var(--e3) var(--e4); }
  .tableau-comptage tbody td {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: flex-start;
    justify-content: flex-end;
    gap: 2px;
    padding: 0;
    text-align: left;
  }
  .tableau-comptage tbody td::before { font-size: var(--t-aide); }
  .tableau-comptage tbody td.cellule-titre,
  .tableau-comptage tbody td.cellule-sous-titre { flex: 1 0 100%; padding: 0; }
  .tableau-comptage tbody td.cellule-sous-titre { margin-top: calc(2px - var(--e2)); }
  .tableau-comptage tbody td.cellule-precedente { flex: 1 1 30%; color: var(--g500); }
  /* « A bougé de » garde son libellé sur une ligne : la colonne du signal
     prend la place que les deux autres nombres n'emploient pas. */
  .tableau-comptage tbody td[data-libelle="A bougé de"] { flex-grow: 1.5; }
  .tableau-comptage tbody td.cellule-saisie { flex: 0 0 84px; align-items: stretch; }
  .tableau-comptage tbody td.cellule-ecart { flex: 0 0 52px; align-items: flex-end; text-align: right; }
  .tableau-comptage tbody td.cellule-close { flex: 1 0 100%; align-items: center; padding: var(--e2); }
  .tableau-comptage tbody td.cellule-close::before { content: none; }
  .tableau-comptage .saisie-comptage { max-width: none; }
  .tableau-comptage tbody tr.ligne-erreur td { flex: 1 0 100%; }
  .tableau-comptage tbody tr.ligne-erreur td::before { content: none; }

  /* Le journal : une carte en rangs, sans libellés — l'article ; le motif et
     la quantité ; le stock et le moment ; le numéro et l'auteur. En pile de
     libellés, un mouvement mesurait 300 px. */
  .tableau-journal tbody tr { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: var(--e2) var(--e3); }
  .tableau-journal tbody td { padding: 0; }
  .tableau-journal tbody td::before { content: none; }
  .tableau-journal tbody td.cellule-titre { flex: 1 0 100%; }
  .tableau-journal tbody td[data-libelle="Motif"] { order: 1; flex: 1 1 55%; justify-content: flex-start; gap: 0; text-align: left; }
  .tableau-journal tbody td[data-libelle="Quantité"] { order: 2; flex: 0 0 auto; }
  .tableau-journal tbody td[data-libelle="Stock"] { order: 3; flex: 1 1 50%; justify-content: flex-start; }
  .tableau-journal tbody td[data-libelle="Date"] { order: 4; flex: 0 0 auto; justify-content: flex-end; gap: 0 6px; }
  .tableau-journal tbody td.cellule-sous-titre { order: 5; flex: 1 1 40%; padding: 0; }
  .tableau-journal tbody td[data-libelle="Par"] { order: 6; flex: 0 0 auto; font-size: var(--t-secondaire); color: var(--g500); }
  .tableau-journal .date-jour, .tableau-journal .date-heure { font-size: var(--t-secondaire); }
}

/* ==========================================================================
   Tiers payeurs (lot Design 6, D-162)
   ========================================================================== */

/* Un montant signé prend sa couleur jusque dans une cellule de tableau et
   une ligne de faits : la couleur de la cellule l'emportait (D-157, P4). */
.tableau tbody td.montant-negatif, .ligne-info dd.montant-negatif { color: var(--rouge); }
.tableau tbody td.montant-positif, .ligne-info dd.montant-positif { color: var(--vert-fonce); }
.tableau tbody td.montant-nul, .ligne-info dd.montant-nul { color: var(--g500); }

/* Un fait dont la valeur est une phrase (à qui le relevé est adressé, un
   commentaire) se lit sous son libellé, alignée à gauche, au lieu
   d'élargir la carte. */
.ligne-info-texte { flex-direction: column; align-items: flex-start; gap: 2px; }
.ligne-info-texte dd { min-width: 0; white-space: normal; text-align: left; }

/* Des actes sur une carte étroite passent à la ligne plutôt que de sortir
   de la carte (remettre un relevé, au téléphone). */
.carte-pile > .rangee-actions { flex-wrap: wrap; }

/* Les lignes d'un relevé (D-152) : la société souscriptrice en bande, son
   sous-total sous un filet, le total sous un filet appuyé. L'assuré se lit
   en une phrase, à la taille d'une aide. */
.tableau-releve tr.ligne-groupe td {
  background: var(--g100);
  font-size: var(--t-aide);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--g700);
}
.tableau-releve tr.ligne-sous-total td { font-weight: 600; border-top: 1px solid var(--g400); }
.tableau-releve tr.ligne-total td { font-size: var(--t-corps); font-weight: 600; border-top: 2px solid var(--g900); }
.tableau-releve tr.ligne-avoir td { color: var(--g700); }
.tableau-releve td[data-libelle="Assuré"] { font-size: var(--t-secondaire); color: var(--g700); }
.tableau-releve td.colonne-nombre { white-space: nowrap; }
/* Au bureau, la facture, sa référence SECeF, la date et la police tiennent
   sur leur ligne : seul l'assuré passe à la ligne. */
@media (min-width: 900px) {
  .tableau-releve td.cellule-titre,
  .tableau-releve td.cellule-sous-titre,
  .tableau-releve td[data-libelle="Police"] { white-space: nowrap; }
}

/* Un relevé imputé ne se coupe pas à son tiret (« REL- / 000004 »). */
.tableau-reglements td.cellule-large a { white-space: nowrap; }

@media (max-width: 899px) {
  /* Une ligne de relevé en rangs (D-039, D-161) : la facture, sa date,
     l'assuré, puis police, taux et les trois montants côte à côte. En pile
     de libellés, elle mesurait 390 px. */
  .tableau-releve tbody td[data-libelle="Police"],
  .tableau-releve tbody td[data-libelle="Assuré"] { order: -1; }
  .tableau-releve tbody td[data-libelle="Police"] { flex: 1 0 100%; flex-direction: row; align-items: baseline; gap: var(--e2); }
  /* L'aide sous le titre d'une carte reste une aide : elle prenait le gras
     du titre (« émis le 03/09/2026 · Abdoulaye Djingo »). */
  .tableau-releve tbody td.cellule-titre .aide,
  .tableau-releves tbody td.cellule-titre .aide,
  .tableau-reglements tbody td.cellule-titre .aide,
  .tableau-situation-tiers tbody td.cellule-titre .aide { font-weight: 400; }
  .tableau-releve tbody tr.ligne-groupe { padding: var(--e2) var(--e4); background: var(--g100); border-color: var(--g200); }
  .tableau-releve tbody tr.ligne-groupe td { background: transparent; }
  .tableau-releve tbody tr.ligne-sous-total td,
  .tableau-releve tbody tr.ligne-total td { border-top: 0; }
  .tableau-releve tbody tr.ligne-total { border: 2px solid var(--g900); }

  /* Un règlement reçu : ce qu'il a soldé vient en dernier, avant « Voir ». */
  .tableau-reglements tbody td.cellule-large { order: 1; }
  .tableau-reglements tbody td.cellule-actions { order: 2; }
}

/* ==========================================================================
   Achats (lot Design 7, D-163)
   ========================================================================== */

/* La facture : les faits, puis l'atelier ou les cartes d'une facture entrée ;
   à gauche la liste et son titre à la hauteur de la première carte, à droite
   les cartes l'une sous l'autre (comme la campagne, D-161). */
.bande-faits + .atelier-achat,
.bande-faits + .facture-entree { margin-top: var(--e5); }
.atelier-achat .atelier-liste > .titre-secondaire:first-child { margin-top: 0; }
.atelier-achat .atelier-saisie { display: flex; flex-direction: column; gap: var(--e4); }
/* Le contrôle : trois faits au plus par ligne — les totaux HT, TVA, TTC,
   puis la facture et l'écart (D-224), le dernier un cran plus grand ;
   l'entrée en stock dessous, séparée par un filet. */
.faits-controle { flex-wrap: nowrap; justify-content: space-between; gap: var(--e2) var(--e4); }
.faits-controle .fait-valeur { white-space: nowrap; font-variant-numeric: tabular-nums; }
.faits-controle .fait-ecart .fait-valeur { font-size: var(--t-titre); }
.carte-controle > .acte-entree { padding-top: var(--e3); border-top: 1px solid var(--g200); }
/* Abandonner le brouillon (D-217) : sous l'entrée ; seul tant qu'il n'y a
   aucune ligne, il prend le filet de l'entrée. */
.carte-controle > .faits-controle + .acte-abandon { padding-top: var(--e3); border-top: 1px solid var(--g200); }
@media (min-width: 900px) {
  /* Sur une rangée, la mise en garde à gauche du bouton : la colonne de
     saisie tient dans l'écran. */
  .carte-controle > .acte-annonce { flex-direction: row-reverse; align-items: center; justify-content: space-between; gap: var(--e3); }
}

/* Une ligne de facture : le code au-dessus de la désignation, comme le
   journal ; la désignation ne se coupe plus en trois (« 000123 — /
   PARACETAMOL / 500MG CP B/20 »). À côté de la saisie, les cellules se
   resserrent : huit colonnes tiennent dans la colonne de la liste. Pleine
   largeur, une fois la facture entrée, le code précède la désignation. */
.tableau-lignes-achat td.colonne-nombre { white-space: nowrap; }
.tableau-lignes-achat .article-code { margin-right: var(--e2); }
/* « Montant », et dessous ce qu'il compte : le prix de la facture (D-224). */
.tableau-lignes-achat thead th .entete-precision { display: block; font-weight: 400; letter-spacing: 0; text-transform: none; }
/* Le lot sous la désignation (D-181), à sa ligne dans les deux dispositions ;
   l'aide des deux champs du lot se tient contre eux, comme celle d'un champ. */
.tableau-lignes-achat td.cellule-titre > .aide { display: block; }
.bloc-champs > .aide-lot { margin-top: -8px; }
/* Les lots en stock, sous le bloc Stock de la fiche produit (D-181). */
.tableau-lots { margin-top: var(--e3); }
.tableau-lots td .aide { display: block; }
/* L'échéance sous la date d'un lot (D-181, lot 2) : « dans 16 jours » ;
   passée, elle se lit en rouge — « depuis 14 jours ». */
.aide-echeance { display: block; }
.aide-echeance.echeance-passee { color: var(--rouge); font-weight: 600; }
/* Répartir les lots : le numéro et la date d'un lot trouvé se tapent dans le
   tableau, comme un comptage, mais à gauche et plus larges (D-181, lot 2). */
.saisie-cellule.saisie-lot { width: 150px; text-align: left; }
.bloc-repartir { margin-top: var(--e5); max-width: 640px; }
@media (min-width: 900px) {
  .atelier-achat .tableau-lignes-achat tbody td.cellule-titre { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; }
  .atelier-achat .tableau-lignes-achat .article-code { margin-right: 0; }
  .tableau-lignes-achat thead th,
  .tableau-lignes-achat tbody td { padding-left: var(--e2); padding-right: var(--e2); }
  .tableau-lignes-achat thead th:first-child,
  .tableau-lignes-achat tbody td:first-child { padding-left: 14px; }
  .tableau-lignes-achat thead th:last-child,
  .tableau-lignes-achat tbody td:last-child { padding-right: 14px; }
}
/* Une référence ne se coupe pas à son tiret (« FA- / 000041 »). */
.tableau-factures-achat .code-inline { white-space: nowrap; }

@media (max-width: 899px) {
  /* Le contrôle et la saisie, puis la liste (D-054). */
  .atelier-achat .atelier-liste { margin-top: var(--e6); }
  /* L'entrée et le commentaire prennent la largeur de la bande et passent à
     la ligne : coupés, ils ne disaient plus qui avait fait entrer. */
  .bande-faits > .fait-large,
  .bande-faits > [data-entree] { grid-column: 1 / -1; }
  .bande-faits > [data-entree] .fait-valeur { white-space: normal; }
  /* Le rang d'une ligne se lit à sa place dans la liste : seul sous la
     désignation, il faisait un rang à lui. */
  .tableau-lignes-achat tbody td.cellule-rang { display: none; }
  .tableau-lignes-achat tbody td.cellule-titre { flex-direction: column; align-items: flex-start; gap: 1px; }
  /* L'aide sous le titre d'une carte reste une aide (le numéro du
     fournisseur, le code). */
  .tableau-factures-achat tbody td.cellule-titre .aide,
  .tableau-fournisseurs tbody td.cellule-titre .aide { font-weight: 400; }
}

/* ==========================================================================
   Catalogue (lot Design 8, D-164)
   ========================================================================== */

/* La fiche d'un produit : le stock se lit comme le taux de marque, et le
   mouvement se saisit à côté, pour qui en a le droit (D-044, D-047). */
.stock-fiche { display: flex; flex-direction: column; align-items: flex-start; gap: var(--e2); }
.stock-fiche > .liste-infos { align-self: stretch; }
.stock-fiche > .aide { margin: 0; }
/* Un rayon négatif : un transfert qui reste à faire (D-105). */
.tableau tbody td.stock-a-transferer { color: var(--orange-fonce); font-weight: 600; }

@media (max-width: 899px) {
  /* Un produit en rangs, comme une rupture (D-161) ; ses deux gestes côte à
     côte plutôt que l'un sous l'autre. */
  .tableau-produits tbody td.cellule-actions .rangee-actions { flex-direction: row; }
  .tableau-produits tbody td.cellule-actions .bouton { flex: 1 1 0; width: auto; }
  /* L'aide sous le titre d'une carte reste une aide (le code). */
  .tableau-referentiel tbody td.cellule-titre .aide { font-weight: 400; }
}

/* ==========================================================================
   Administration et accès (lot Design 9, D-165)
   ========================================================================== */

/* Les derniers styles écrits dans le balisage — la marque de la connexion,
   l'accueil, le mot de passe provisoire, la société — rejoignent la feuille :
   plus aucun gabarit ne porte d'attribut style. */
.marque-connexion-texte { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.bloc-connexion .bouton-principal { width: 100%; }
.carte-pile > .bloc-secret { margin: var(--e2) 0; }
.carte-societe { display: flex; flex-direction: column; gap: var(--e4); }
.carte-societe > .note-bas { margin: 0; }
.carte-societe .note-section { margin-top: var(--e3); }
.section-emcf > .aide { margin: 0 0 var(--e3); }
.saisie-jeton { font-family: Consolas, "Courier New", monospace; }
.test-emcf { display: flex; align-items: center; gap: var(--e3); flex-wrap: wrap; }
.test-emcf .resultat-ok { color: var(--vert-fonce); }
.test-emcf .resultat-ko { color: var(--rouge); }

/* La fiche d'un tiers payeur : la fiche à gauche, ses polices et les champs
   de sa prise en charge à droite. Une référence de police ne se coupe pas à
   son tiret ; dans la table des champs, les contrôles sont ceux d'une
   cellule, pas les contrôles natifs. */
.fiche-tiers { align-items: start; }
.tableau-polices .code-inline { white-space: nowrap; }
.ajout-police { padding-top: var(--e3); border-top: 1px solid var(--g200); }
.tableau-champs-pec .saisie-cellule { width: 56px; }
.tableau-champs-pec .saisie-cellule.saisie-choix,
.tableau-champs-pec .saisie-cellule.saisie-texte { width: 100%; min-width: 104px; text-align: left; }
@media (min-width: 900px) {
  /* Quatre colonnes dans la moitié de l'écran : les cellules se resserrent,
     comme les lignes d'une facture à côté de la saisie (D-163). */
  .tableau-champs-pec thead th,
  .tableau-champs-pec tbody td { padding-left: var(--e2); padding-right: var(--e2); }
  .tableau-champs-pec thead th:first-child,
  .tableau-champs-pec tbody td:first-child { padding-left: 14px; }
  .tableau-champs-pec thead th:last-child,
  .tableau-champs-pec tbody td:last-child { padding-right: 14px; }
}

@media (max-width: 899px) {
  /* L'aide sous le titre d'une carte reste une aide (le code). */
  .tableau-polices tbody td.cellule-titre .aide { font-weight: 400; }
}

/* ==========================================================================
   L'accueil (D-211) : ce qui reste à faire, selon les droits
   ========================================================================== */

/* Le salut sur une ligne (P8) ; l'heure de lecture est dans la tête de
   l'écran, à côté d'Actualiser (P9), et passe sous le salut au téléphone. */
.accueil-tete { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e4); flex-wrap: wrap; }
.accueil-salut-ligne { margin: 0; font-size: var(--t-titre); color: var(--g700); }
.accueil-salut-ligne strong { font-weight: 600; color: var(--g900); }
.accueil-salut-ligne .aide { margin-left: var(--e2); }
.accueil-lu { display: none; margin: 0; }
.accueil-lu-a { align-self: center; margin: 0 var(--e1) 0 0; }
/* Les actes en tête, en grands boutons avec l'icône du menu (P4) ; l'attente
   se dit sur « Encaisser » (P5). */
.accueil-actes { display: flex; gap: var(--e3); flex-wrap: wrap; }
.acte-accueil { height: 56px; gap: 10px; padding: 0 var(--e6); font-size: var(--t-titre); }
.acte-accueil svg { stroke: currentColor; }
/* L'attente se lit sur Encaisser, dans la pastille du menu (D-213 P5). */
.acte-accueil .acte-attente { margin-left: var(--e1); padding: 0 9px; border-radius: var(--r-pilule);
  background: var(--orange); color: var(--blanc); font-size: var(--t-secondaire); font-weight: 600;
  line-height: 22px; font-variant-numeric: tabular-nums; }
/* Deux colonnes (D-214 P1) : à gauche ce que vous suivez, à droite, sur
   340 px, l'officine en ce moment ; une seule quand la droite n'a rien. */
.accueil-colonnes { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--e5); align-items: start; }
.accueil-colonnes-seule { grid-template-columns: minmax(0, 1fr); }
.accueil-principal,
.accueil-cote { display: flex; flex-direction: column; gap: var(--e5); min-width: 0; }
/* Un bloc : son titre au-dessus de sa carte ou de ses tuiles (D-214 P8).
   Le rouge d'abord (D-213 P3). */
.accueil-etage { display: flex; flex-direction: column; gap: var(--e3); }
.accueil-etage-titre { margin: 0; font-size: var(--t-capitale); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--g500); }
.accueil-etage-rouge .accueil-etage-titre { color: var(--rouge); }
/* Une tuile par chose à faire, trois par rangée (D-214 P3) : le nombre ouvre
   la phrase, le domaine la ferme ; la tuile entière est le lien. */
.accueil-tuiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--e3); }
.accueil-tuile { display: flex; flex-direction: column; gap: 2px; min-height: 100px; box-sizing: border-box;
  padding: var(--e3) var(--e4); background: var(--blanc); border: 1px solid var(--g200);
  border-radius: var(--r-carte); color: var(--g700); text-decoration: none; }
.accueil-tuile:hover { border-color: var(--g400); }
.accueil-tuile:hover .accueil-tuile-phrase { color: var(--g900); text-decoration: underline; }
.accueil-tuile-nombre { font-size: var(--t-chiffre); font-weight: 600; line-height: 1.1; color: var(--g900);
  font-variant-numeric: tabular-nums; }
.accueil-tuile-phrase { margin-top: 2px; font-size: var(--t-courant); line-height: 1.3; color: var(--g700); }
.accueil-tuile-detail { margin-top: 2px; font-size: var(--t-aide); color: var(--g500); }
.accueil-tuile-domaine { margin-top: auto; padding-top: var(--e2); font-size: var(--t-aide); color: var(--g500); }
.accueil-tuile-rouge { background: var(--rouge-clair); border-color: var(--rouge-bord); }
.accueil-tuile-rouge .accueil-tuile-nombre { color: var(--rouge); }
.accueil-tuile-rouge .accueil-tuile-phrase { color: var(--g900); font-weight: 600; }
.accueil-tuile-rouge:hover { border-color: var(--rouge); }
/* L'icône du menu de l'écran où la tuile mène, en haut à droite, dans une
   pastille ronde ; elle accompagne la phrase, ne la remplace pas (D-214 P13). */
.accueil-tuile-tete { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--e2); }
.accueil-tuile-icone { display: inline-flex; flex: none; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--r-pilule); background: var(--g100); }
.accueil-tuile-icone svg { stroke: var(--g500); }
.accueil-tuile:hover .accueil-tuile-icone svg { stroke: var(--g700); }
.accueil-tuile-rouge .accueil-tuile-icone { background: var(--blanc); }
.accueil-tuile-rouge .accueil-tuile-icone svg,
.accueil-tuile-rouge:hover .accueil-tuile-icone svg { stroke: var(--rouge); }
/* Rien ne vous attend : la colonne répond, en grand (D-214 P10). */
.accueil-rien { display: flex; align-items: center; gap: var(--e4); margin: 0; padding: var(--e6);
  color: var(--g700); font-size: var(--t-corps); }
.accueil-rien p { display: flex; flex-direction: column; gap: 2px; margin: 0; }
.accueil-rien p strong { font-size: var(--t-titre); color: var(--g900); }
.accueil-rien p span { color: var(--g500); }
/* À jour : une liste de contrôle, par domaine, sur trois colonnes ; le
   compte en pastille verte (D-214 P4). */
.accueil-ajour { color: var(--g700); }
.accueil-ajour svg,
.accueil-rien svg { stroke: var(--vert); flex: none; }
.accueil-ajour-compte { margin-left: var(--e1); padding: 0 7px; border-radius: var(--r-pilule); background: var(--vert-clair);
  color: var(--vert-fonce); line-height: 18px; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.accueil-ajour-carte { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--e4) var(--e5);
  padding: var(--e4) var(--e5); }
.accueil-ajour-groupe h3 { margin: 0 0 var(--e1); font-size: var(--t-aide); font-weight: 600; color: var(--g500); }
.accueil-ajour-groupe ul { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.accueil-ajour-groupe a { display: flex; align-items: flex-start; gap: var(--e2); padding: 3px 0;
  font-size: var(--t-secondaire); line-height: 1.35; color: var(--g700); text-decoration: none; }
.accueil-ajour-groupe a svg { margin-top: 1px; }
.accueil-ajour-groupe a:hover span { color: var(--g900); text-decoration: underline; }
/* Aujourd'hui, en tête de la colonne de droite (D-214 P6) : le CA et son
   écart, la comparaison, puis ventes et panier côte à côte. */
.accueil-jour { display: flex; flex-direction: column; gap: var(--e1); padding: var(--e4) var(--e5); }
.accueil-jour-ca { display: flex; align-items: baseline; gap: var(--e3); margin: 0; font-size: var(--t-chiffre);
  font-weight: 600; color: var(--g900); font-variant-numeric: tabular-nums; }
.accueil-jour-ecart { font-size: var(--t-secondaire); }
.accueil-jour > .aide { margin: 0; }
.accueil-jour-faits { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e3);
  margin: var(--e2) 0 var(--e1); padding-top: var(--e3); border-top: 1px solid var(--g200); }
.accueil-jour-faits dt { font-size: var(--t-aide); color: var(--g500); }
.accueil-jour-faits dd { margin: 0; font-size: var(--t-titre); font-weight: 600; color: var(--g900);
  font-variant-numeric: tabular-nums; }
.accueil-jour > .fait-lien { align-self: flex-start; }
/* En ce moment, sous Aujourd'hui : une information par ligne, son icône à
   gauche, son titre au-dessus de ses valeurs (D-213 P4, D-214 P7, P13). */
.accueil-info { display: flex; flex-direction: column; align-items: stretch; gap: 0; padding: 0; }
.accueil-info-lien { display: grid; grid-template-columns: 18px minmax(0, 1fr); column-gap: var(--e3);
  padding: var(--e3) var(--e5); border-top: 1px solid var(--g200); color: var(--g700); text-decoration: none; }
.accueil-info-lien:first-child { border-top: 0; }
.accueil-info-lien:hover { background: var(--g50); }
.accueil-info-lien > svg { grid-row: span 2; margin-top: 2px; stroke: var(--g500); }
.accueil-info-titre { font-size: var(--t-aide); color: var(--g500); }
.accueil-info-valeur { font-size: var(--t-courant); }
.accueil-info-valeur > span { display: block; }
.accueil-info-lien:hover .accueil-info-valeur { color: var(--g900); text-decoration: underline; }
.accueil-vide { color: var(--g500); }

@media (max-width: 899px) {
  /* Au téléphone (P15) : les actes sur toute la largeur ;
     Actualiser descend dans la barre d'action, l'heure sous le salut. */
  .accueil-actes { flex-direction: column; }
  /* Une colonne : ce que vous suivez, puis Aujourd'hui et En ce moment
     (D-213 P12, D-214 P12) ; les tuiles par deux, la liste d'une traite. */
  .accueil-colonnes { grid-template-columns: minmax(0, 1fr); }
  .accueil-tuiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e2); }
  .accueil-tuile { min-height: 104px; padding: var(--e3); }
  .accueil-ajour-carte { grid-template-columns: minmax(0, 1fr); }
  .accueil-lu { display: inline; }
  .entete-ecran .accueil-lu-a { display: none; }
}

/* ==========================================================================
   Le jeton e-MCF (D-168)
   ========================================================================== */

/* Le jeton ne revient plus au navigateur : la page n'en montre que la fin,
   de quoi reconnaître celui qui est enregistré. */
.jeton-enregistre { margin: 0 0 var(--e1); font-size: var(--t-secondaire); color: var(--g700); }
.jeton-fin { font-family: Consolas, "Courier New", monospace; font-weight: 600; color: var(--g900); }

/* La boîte de dialogue de l'application (D-177) : une seule, dans la coque,
   ouverte par le script là où il confirmait ; le navigateur n'en montre plus.
   Une carte de 480 px au plus, l'ombre du panneau de suggestions, le voile en
   g900 à 45 % ; la question en titre, le reste en texte, la phrase de
   l'irréversible détachée en orange ; sous 900 px, les boutons s'empilent. */
.dialogue {
  width: min(480px, calc(100vw - 2 * var(--e4)));
  padding: 0;
  border: 1px solid var(--g300);
  border-radius: var(--r-carte);
  background: var(--blanc);
  color: var(--g700);
  box-shadow: 0 12px 28px rgba(20, 24, 29, 0.18);
}
.dialogue::backdrop { background: rgba(20, 24, 29, 0.45); }
.dialogue-corps { display: flex; flex-direction: column; gap: var(--e3); margin: 0; padding: var(--e5); }
.dialogue-titre { margin: 0; font-size: var(--t-titre); font-weight: 600; line-height: 1.35; color: var(--g900); }
.dialogue-texte { margin: 0; font-size: var(--t-courant); }
.dialogue-texte:empty { display: none; }
.dialogue-irreversible { margin: 0; font-size: var(--t-courant); font-weight: 600; color: var(--orange); }
.dialogue-irreversible[hidden] { display: none; }
.dialogue-actes { display: flex; justify-content: flex-end; gap: var(--e2); padding-top: var(--e2); }
.dialogue-actes .bouton {
  height: auto;
  min-height: var(--h-ctrl);
  padding-top: 10px;
  padding-bottom: 10px;
  white-space: normal;
  text-align: center;
}
@media (max-width: 899px) {
  .dialogue-actes { flex-direction: column-reverse; }
  .dialogue-actes .bouton { width: 100%; }
}

/* ── Les étiquettes de rayon (D-182) ─────────────────────────────────────
   L'aperçu : la case à l'échelle, ses éléments posés en pixels par le
   serveur (et déplacés par le script) — le même dessin que le PDF. */
.cadre-etiquette { padding: var(--e4); overflow: auto; }
.etiquette-apercu {
  position: relative;
  flex-shrink: 0;
  background: var(--blanc);
  border: 1px solid var(--g400);
  overflow: hidden;
  color: var(--encre);
  font-family: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
}
.etiquette-element {
  position: absolute;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  transform-origin: top left;
}
.etiquette-element.chasse-fixe { font-family: "IBM Plex Mono", Consolas, monospace; }
.etiquette-codebarres { box-sizing: border-box; }
.etiquette-codebarres svg { display: block; width: 100%; height: 100%; }
.etiquette-element.en-cours { outline: 2px dashed var(--vert); outline-offset: 2px; }
/* La planche à imprimer : les gestes à gauche, la liste à droite. */
.piece-etiquettes { grid-template-columns: 380px minmax(0, 1fr); }
.piece-planche { min-width: 0; }
.titre-planche { margin-top: var(--e5); }
.gestes-planche { align-items: center; margin-bottom: var(--e3); }
.gestes-planche .aide { flex: 1 1 260px; margin: 0; }
.compte-etiquettes { font-weight: 600; color: var(--g800); }
.saisie-lot { width: 100%; min-width: 190px; }
.case-option { display: flex; align-items: center; gap: var(--e2); font-size: var(--t-secondaire); cursor: pointer; }
.case-option input { width: 18px; height: 18px; accent-color: var(--vert); cursor: pointer; }
/* L'éditeur de modèles : les étapes à gauche, l'aperçu à droite, qui suit. */
.piece-editeur { grid-template-columns: minmax(0, 1fr) 420px; }
.piece-apercu-etiquette { position: sticky; top: var(--e4); }
.mesures-planche { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--e3); }
.mesures-planche input { width: 100%; }
.bandeau-edition { margin-top: var(--e5); }
.panneau-element { border: 1px solid var(--vert); margin-top: var(--e3); }
.tableau tbody tr.ligne-en-cours td { background: var(--vert-clair); }
.champ-suffixe { flex: 0 1 160px; }
.champ-alignement { flex: 0 1 160px; }
.champ-style { flex: 0 1 220px; }
.etiquette-champ { display: block; margin-bottom: var(--e1); font-size: var(--t-secondaire); font-weight: 600; color: var(--g700); }
.options-style { display: flex; gap: var(--e4); align-items: center; height: var(--h-ctrl); }
@media (max-width: 899px) {
  .piece-etiquettes, .piece-editeur { grid-template-columns: minmax(0, 1fr); }
  .piece-apercu-etiquette { position: static; }
  .mesures-planche { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   Les états (D-183, lot 1) : la liste, l'atelier « Un état », l'état ouvert
   ========================================================================== */

/* L'atelier et l'état ouvert prennent la largeur : l'aperçu a besoin de ses
   colonnes. */
.corps-atelier { max-width: none; }
.tableau-etats td.cellule-titre > .aide { display: block; }
/* L'atelier d'un état : les réglages à gauche, l'aperçu qui prend le reste. */
.atelier-etat { display: grid; grid-template-columns: 360px minmax(0, 1fr); gap: var(--e6); align-items: start; }
.apercu-colonne { display: flex; flex-direction: column; gap: var(--e4); min-width: 0; }
.sujets { display: flex; flex-direction: column; gap: 6px; }
.sujet { display: flex; gap: 10px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--g300); border-radius: var(--r-carte); background: var(--blanc); cursor: pointer; }
.sujet input { width: 18px; height: 18px; margin-top: 2px; accent-color: var(--vert); flex: none; }
.sujet.actif { border-color: var(--vert); background: var(--vert-clair); }
.sujet .sujet-nom { font-weight: 600; font-size: var(--t-courant); color: var(--g900); }
.sujet .aide { display: block; margin: 0; }
/* La période : les raccourcis sont des boutons radio au dessin des pilules,
   pour que « Voir » les relise sans script. */
label.raccourci { cursor: pointer; position: relative; }
.raccourci input[type="radio"] { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.raccourci:has(input:checked) { color: var(--vert-fonce); background: var(--vert-clair); border-color: var(--vert-bord); }
.raccourci:has(input:focus-visible) { outline: 2px solid var(--vert); outline-offset: 2px; }
.choix-forme { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.choix-forme.choix-forme-seule { grid-template-columns: minmax(0, 1fr); }
.choix-forme label { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border: 1px solid var(--g300); border-radius: var(--r-carte); background: var(--blanc); cursor: pointer; }
.choix-forme label.actif { border-color: var(--vert); box-shadow: 0 0 0 2px var(--vert-clair); }
.choix-forme .forme-nom { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: var(--t-courant); }
.choix-forme input { width: 18px; height: 18px; accent-color: var(--vert); }
.facette { margin-top: 8px; }
.facette-titre { font-size: var(--t-capitale); font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--g500); margin-bottom: 4px; }
.facette-titre.facette-titre-tete { margin-top: 12px; }
.rangee-champs.rangee-champs-tete { margin-top: 12px; }
.cases { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px 12px; }
/* Une condition : champ, opérateur, valeur, et son geste. */
.condition { display: grid; grid-template-columns: 1.3fr 1fr 1.2fr auto; gap: 8px; align-items: end; }
.condition .champ select, .condition .champ input { width: 100%; }
.condition > .message-erreur { grid-column: 1 / -1; margin-top: 0; }
.cases-condition { display: flex; flex-direction: column; gap: 2px; max-height: 132px; overflow-y: auto; padding: 4px 6px; border: 1px solid var(--g300); border-radius: var(--r-carte); background: var(--blanc); }
.cases-condition .case-option input { width: 16px; height: 16px; }
.valeurs-entre { display: flex; flex-direction: column; gap: 4px; }
.et-entre { display: flex; align-items: center; gap: 6px; font-size: var(--t-secondaire); color: var(--g500); }
.et-entre[hidden] { display: none; }
/* L'aperçu : le titre et son compte, puis la table. */
.apercu-tete { display: flex; flex-direction: column; gap: 2px; }
.apercu-tete .section-titre { margin: 0; }
/* Les lignes de l'aperçu, propres à sa table : les rapports ont les leurs. */
.tableau-etat tbody tr.ligne-groupe td { background: var(--g50); font-weight: 700; font-size: var(--t-capitale); letter-spacing: 0.07em; text-transform: uppercase; color: var(--g500); }
.tableau-etat tbody tr.ligne-sous-total td { font-weight: 600; border-top: 1px solid var(--g400); background: var(--g50); }
.tableau-etat tbody tr.ligne-total td { font-weight: 700; border-top: 2px solid var(--g400); }
.tableau-etat td.colonne-nombre, .tableau-etat th.colonne-nombre { text-align: right; font-variant-numeric: tabular-nums; }
.tableau-etat tbody tr.ligne-suite td { color: var(--g500); font-style: italic; }
.apercu-tete ~ .tableau-cadre td, .apercu-tete ~ .tableau-cadre th { white-space: nowrap; padding-left: 8px; padding-right: 8px; font-size: var(--t-secondaire); }
.etat-resume { margin: 0 0 var(--e4); }
.etat-periode { margin: 0 0 var(--e4); }
@media (max-width: 899px) {
  .atelier-etat { grid-template-columns: minmax(0, 1fr); }
  .condition { grid-template-columns: minmax(0, 1fr); }
  /* L'aperçu reste une table, qui défile dans son cadre (le téléphone n'est
     pas dessiné : piste BE) ; une pile de cartes sans libellés n'y dirait
     rien. */
  .apercu-tete ~ .tableau-cadre { overflow-x: auto; background: var(--blanc); border: 1px solid var(--g300); border-radius: var(--r-carte); }
  .tableau.tableau-etat { display: table; min-width: 100%; }
  .tableau-etat thead { display: table-header-group; }
  .tableau-etat tbody { display: table-row-group; }
  .tableau-etat tr, .tableau-etat tbody tr { display: table-row; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; }
  .tableau-etat th, .tableau-etat tbody td { display: table-cell; padding: var(--e2) var(--e3); text-align: left; border-bottom: 1px solid var(--g200); }
  .tableau-etat tbody td.colonne-nombre, .tableau-etat th.colonne-nombre { text-align: right; }
  .tableau-etat tbody td::before { content: none; }
}

/* === La qualification des produits (D-195, lot 1) === */
/* Les onglets des états, puis la phrase qui dit ce qu'on y trouve. */
.qualification-onglets { margin-bottom: var(--e2); }
.qualification-aide { margin: 0 0 var(--e4); max-width: 75ch; }
/* Forme, dosage, examinateur : sous le titre, sur leur ligne. */
.qualification-precisions { display: block; }
/* Les classes d'une ligne restent sur une ligne : si la table ne tient pas,
   elle défile dans son cadre (D-208, P9 — elles passaient à la ligne). */
.qualification-classes { margin: 0; }
/* Un champ qui se lit sur une fiche : le même libellé qu'un champ saisi. */
.libelle-lecture { margin-bottom: var(--e1); font-size: var(--t-secondaire); font-weight: 600; color: var(--g700); }
.champ .libelle-lecture + div { min-height: 24px; display: flex; align-items: center; }
/* Les lignes écartées du fichier d'une facture (D-232) : le même repli. */
.qualification-examens, .fichier-ecartees { margin-top: var(--e1); font-size: var(--t-aide); color: var(--g500); }
.qualification-examens summary, .fichier-ecartees summary { cursor: pointer; color: var(--vert); }
.qualification-examens ul, .fichier-ecartees ul { margin: var(--e1) 0 0; padding-left: var(--e4); }
@media (max-width: 899px) {
  .libelle-lecture { font-size: var(--t-courant); margin-bottom: 6px; }
}

/* === L'ordonnancier (D-195, lot 3) === */
/* Les classes, sous la tête de l'historique : l'idiome des onglets de la qualification. */
.ordonnancier-classes { margin-bottom: var(--e2); }


/* ==========================================================================
   La facture par fichier (D-196)
   ========================================================================== */
/* Le champ du fichier, à la hauteur des autres ; un bord en tirets dit qu'on
   y dépose quelque chose. */
.champ input[type="file"] {
  height: var(--h-ctrl);
  padding: 9px var(--e3);
  font: inherit;
  font-size: var(--t-courant);
  color: var(--g700);
  background: var(--blanc);
  border: 1px dashed var(--g400);
  border-radius: var(--r-ctrl);
  width: 100%;
}
.carte-import + .aide { margin: var(--e3) 0 0; }
.atelier-liste > .carte + .titre-secondaire { margin-top: var(--e5); }
.section-titre-seul { margin: 0; padding: 0; border: 0; }
/* Ce que le fichier dit, la ligne sous la désignation. */
.non-trouves .tableau td { vertical-align: top; }
.non-trouves .cellule-titre > span { display: block; }
/* « Compléter » ou « Modifier » : là où le lot se lit (P8). */
.lien-lot { margin-left: 6px; font-size: var(--t-secondaire); font-weight: 600; }
.aide-signal { color: var(--orange-fonce); }
/* La ligne qu'on complète se voit dans le tableau. */
.tableau tbody tr.ligne-choisie td { background: var(--vert-clair); }


/* ==========================================================================
   Les statistiques (D-212, redessinées par D-215) : la période en grand, le
   chiffre d'affaires et son évolution, cinq chiffres clés, deux colonnes
   comme l'accueil, les règles en bas
   ========================================================================== */
/* La tête (D-215 P1) : la période en grand à gauche, le choix à droite. */
.stats-entete { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--e4) var(--e6); flex-wrap: wrap; }
.stats-nom h2 { margin: 0; font-size: var(--t-chiffre); font-weight: 600; line-height: 1.15; color: var(--g900); }
.stats-nom h2 span { font-size: var(--t-titre); font-weight: 400; color: var(--g500); }
.stats-nom .aide { margin: 2px 0 0; }
.stats-periode { display: flex; flex-direction: column; align-items: flex-end; gap: var(--e2); }
/* Les dates : le champ date de l'application (D-145), libellé au-dessus,
   « Voir » à la hauteur des champs (D-215 P12). */
.stats-dates { display: flex; align-items: flex-end; gap: var(--e3); }
.stats-dates .champ-date { flex: 0 1 172px; }
.stats-dates .champ-date input[type="date"] { flex: none; width: 100%; height: var(--h-ctrl); }
.stats-dates .bouton { height: var(--h-ctrl); }
/* Un seul avis sans historique (D-215 P2). */
.stats-avis { display: flex; align-items: center; gap: var(--e2); margin: 0; padding: var(--e2) var(--e4);
  border-radius: var(--r-carte); background: var(--g100); font-size: var(--t-secondaire); color: var(--g700); }
.stats-avis svg { stroke: var(--g500); flex: none; }
/* Un bloc : son titre au-dessus de sa carte, la grammaire de l'accueil (P5). */
.stats-etage { display: flex; flex-direction: column; gap: var(--e3); min-width: 0; }
.stats-etage-titre { margin: 0; font-size: var(--t-capitale); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--g500); }
.stats-etage-titre span { margin-left: var(--e2); font-weight: 400; letter-spacing: 0; text-transform: none;
  font-size: var(--t-aide); color: var(--g400); }
/* Le chiffre d'affaires (P3) : le nombre et ses comparaisons à gauche, son
   évolution à droite, dans la même carte. */
.stats-hero { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--e6); padding: var(--e5); }
.stats-hero-chiffres { display: flex; flex-direction: column; gap: var(--e3); }
.stats-hero-nombre { font-size: var(--t-du); font-weight: 600; line-height: 1; color: var(--g900);
  font-variant-numeric: tabular-nums; }
.stats-hero-nombre span { margin-left: var(--e2); font-size: var(--t-titre); font-weight: 600; color: var(--g500); }
.stats-comparaisons { display: flex; flex-direction: column; gap: var(--e1); margin: 0; padding: 0; list-style: none;
  font-size: var(--t-secondaire); font-variant-numeric: tabular-nums; }
.stats-comparaisons li { display: flex; justify-content: space-between; gap: var(--e3); color: var(--g700); }
.stats-hero-faits { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e3); margin: var(--e1) 0 0;
  padding-top: var(--e3); border-top: 1px solid var(--g200); }
.stats-hero-faits dt { font-size: var(--t-aide); color: var(--g500); }
.stats-hero-faits dd { margin: 0; font-size: var(--t-titre); font-weight: 600; color: var(--g900); font-variant-numeric: tabular-nums; }
.stats-hero-dessin { display: flex; flex-direction: column; gap: var(--e2); min-width: 0; }
.stats-hero-legende { align-self: flex-end; }
/* Les cinq autres chiffres clés, en une rangée (P4). */
.stats-cles { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--e3); }
.stats-cle { display: flex; flex-direction: column; gap: 2px; padding: var(--e3) var(--e4); }
.stats-cle-etiquette { font-size: var(--t-aide); color: var(--g500); }
.stats-cle-nombre { font-size: var(--t-montant); font-weight: 600; color: var(--g900); font-variant-numeric: tabular-nums; }
.stats-cle-compare { display: flex; justify-content: space-between; gap: var(--e2); font-size: var(--t-aide); color: var(--g500); }
/* L'écart à la comparaison : ▲ vert, ▼ rouge (D-212 P5) — l'accueil le reprend. */
.ecart.hausse { color: var(--vert-fonce); }
.ecart.baisse { color: var(--rouge); }
.ecart.vide { color: var(--g400); font-weight: 400; }
/* Deux colonnes : l'analyse à gauche, les faits courts à droite, 340 px (P5). */
.stats-colonnes { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--e5); align-items: start; }
.stats-principal,
.stats-cote { display: flex; flex-direction: column; gap: var(--e5); min-width: 0; }
.stats-carte { padding: var(--e4) var(--e5); }
.stats-carte-tableau { padding: 0; }
.stats-carte-tableau .tableau { margin: 0; }
.stats-vide { margin: 0; padding: var(--e4) var(--e5); font-size: var(--t-secondaire); color: var(--g500); }
.stats-carte .stats-vide { padding: 0; }
.legende { display: flex; gap: var(--e4); font-size: var(--t-secondaire); font-weight: 400; color: var(--g500); text-transform: none; letter-spacing: 0; }
.legende i { display: inline-block; width: 12px; height: 12px; border-radius: var(--r-marque); margin-right: 6px; vertical-align: -1px; }
.legende .l-barre { background: var(--vert); }
.legende .l-ligne { height: 3px; width: 16px; background: var(--g400); vertical-align: 3px; border-radius: var(--r-marque); }
.stats-sous-total { display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--e2) var(--e4); font-size: var(--t-secondaire); color: var(--g500); margin-top: var(--e2); }
/* Un fait par ligne ; un zéro se dit en clair, en gris (P6). */
.stats-lignes { margin: 0; padding: 0; }
.stats-lignes.carte { padding: 0; }
.stats-ligne { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e3);
  padding: var(--e3) var(--e5); border-top: 1px solid var(--g200); }
.stats-ligne:first-child { border-top: 0; }
.stats-ligne dt { font-size: var(--t-secondaire); color: var(--g700); }
.stats-ligne dd { display: flex; flex-direction: column; align-items: flex-end; margin: 0; font-size: var(--t-corps);
  font-weight: 600; color: var(--g900); font-variant-numeric: tabular-nums; text-align: right; }
.stats-ligne dd .aide { font-weight: 400; }
.stats-ligne-zero dd { font-size: var(--t-secondaire); font-weight: 400; color: var(--g500); }
.stats-sous-titre { margin: var(--e3) 0 0; padding-top: var(--e3); border-top: 1px solid var(--g200);
  font-size: var(--t-aide); font-weight: 600; color: var(--g500); }
.stats-lignes-serrees .stats-ligne { padding: var(--e2) 0; }
/* Le stock : quatre faits côte à côte, les dormants dessous (D-212 P9). */
.stats-stock { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--e4); margin: 0; padding: var(--e4) var(--e5); }
.stats-stock dt { font-size: var(--t-aide); color: var(--g500); }
.stats-stock dd { margin: 0; font-size: var(--t-montant); font-weight: 600; color: var(--g900); font-variant-numeric: tabular-nums; }
.stats-stock dd.aide { font-size: var(--t-aide); font-weight: 400; color: var(--g500); }
.stats-stock .stats-zero dd:not(.aide) { font-size: var(--t-titre); font-weight: 400; color: var(--g500); }
.stats-stock-carte { padding: 0; }
.stats-dormants { border-top: 1px solid var(--g200); }
.stats-dormants .tableau { margin: 0; }
.stats-tva { display: inline; margin: 0; }
/* Comment on compte : les règles, rassemblées, en petit (P7). */
.stats-regles { padding: var(--e4) var(--e5); }
.stats-regles ul { display: flex; flex-direction: column; gap: var(--e1); margin: 0; padding-left: var(--e5);
  font-size: var(--t-aide); color: var(--g500); }
.tableau .colonne-rang { width: 28px; color: var(--g500); font-variant-numeric: tabular-nums; }
.taux-faible { color: var(--orange-fonce); font-weight: 600; }
/* Les dessins du serveur (P15) : les couleurs de la feuille, un <title> par
   marque. Un dessin par largeur : la feuille montre l'un ou l'autre. */
.graphique { display: block; overflow: visible; font-family: var(--police); }
.graphique .g-grille { stroke: var(--g200); stroke-width: 1; }
.graphique .g-base { stroke: var(--g300); stroke-width: 1; }
.graphique .g-axe { fill: var(--g500); font-size: var(--t-capitale); font-variant-numeric: tabular-nums; }
.graphique .g-libelle { fill: var(--g700); font-size: var(--t-secondaire); }
.graphique .g-valeur { fill: var(--g900); font-size: var(--t-secondaire); font-weight: 600; font-variant-numeric: tabular-nums; }
.graphique .g-part { fill: var(--g500); font-weight: 400; }
.graphique .g-barre { fill: var(--vert); }
.graphique .g-barre:hover { fill: var(--vert-fonce); }
.graphique .g-vide { fill: var(--g200); }
.graphique .g-fond { fill: var(--g100); }
.graphique .g-ligne { fill: none; stroke: var(--g400); stroke-width: 2; stroke-linejoin: round; }
.graphique .g-point { fill: var(--blanc); stroke: var(--g400); stroke-width: 1.6; }
/* Les six paliers des heures de pointe (P8), du gris au vert foncé. */
.g-palier-0 { fill: var(--g100); background: var(--g100); }
.g-palier-1 { fill: var(--palier-1); background: var(--palier-1); }
.g-palier-2 { fill: var(--palier-2); background: var(--palier-2); }
.g-palier-3 { fill: var(--palier-3); background: var(--palier-3); }
.g-palier-4 { fill: var(--palier-4); background: var(--palier-4); }
.g-palier-5 { fill: var(--vert-fonce); background: var(--vert-fonce); }
.palier { display: inline-block; width: 22px; height: 12px; border-radius: var(--r-marque); }
.paliers { display: flex; align-items: center; gap: 3px; font-size: var(--t-aide); color: var(--g500); }
.paliers span:first-child { margin-right: 6px; }
.paliers span.fin { margin-left: 6px; }
.dessin-telephone { display: none; }
@media (max-width: 899px) {
  /* Au téléphone (D-212 P16, D-215 P10) : une colonne, le chiffre
     d'affaires puis son graphique, les chiffres clés et le stock deux par
     deux, les graphiques redessinés à sa largeur, les tableaux en fiches. */
  /* Le choix de la période prend la largeur, sans la dépasser : ses dates
     ne poussent plus la page de côté ; « Voir » passe dessous, sur toute la
     largeur, comme dans la barre de filtres. */
  .stats-periode { flex: 1 1 100%; min-width: 0; align-items: stretch; }
  .stats-dates { flex-wrap: wrap; }
  .stats-dates .champ-date { flex: 1 1 0; min-width: 0; }
  .stats-dates .champ-bouton { flex: 1 1 100%; }
  .stats-hero { grid-template-columns: minmax(0, 1fr); }
  .stats-cles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats-colonnes { grid-template-columns: minmax(0, 1fr); }
  .stats-stock { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dessin-bureau { display: none; }
  .dessin-telephone { display: block; }
}
