/* =============================================================================
   auGramme — habillage de l'application.
   =============================================================================
   Le design system (design-system.css) fournit les tokens et les composants
   ag-*. Ce fichier ne redéfinit AUCUN token : il habille les classes que le
   JavaScript de l'application pose déjà, en les branchant sur ces tokens.

   Règle de travail de cette refonte : les NOMS DE CLASSES sont le contrat entre
   le JS, les bancs d'essai et le style. On les conserve tous, on change ce
   qu'ils donnent à voir. Aucune logique n'a bougé.

   Trois règles de la charte qui expliquent la plupart des choix ci-dessous :
     * le corail est DÉCORATIF — il ne porte jamais de texte blanc. Le corail
       porteur de texte est --corail-ink (clair) ;
     * tous les chiffres sont en tabular-nums, sans exception : un poids qui
       monte ne doit pas faire gigoter la ligne ;
     * cibles tactiles à 48 px, 56 px dès que le geste se fait avec des gants.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   Trois tokens d'application, et trois seulement.

   La couche sémantique du design system ne fournit pas d'équivalent lisible du
   prune EN TANT QUE TEXTE une fois le thème sombre actif : --prune y devient
   #7C3A6A, soit 2,16:1 sur --surface. Ces trois variables basculent, elles ;
   les ratios sont vérifiés dans les deux thèmes, sur le fond le plus
   défavorable des trois (--ground, --surface, --surface-2).

   Le design system lui-même n'est pas modifié : design-system.css reste la
   copie exacte de design/. -------------------------------------------------- */
:root {
  /* Plancher de 15 px dans l'app (charte : « lecture à ~60 cm sur tablette »).
     Le design system sert aussi la vitrine, où --fs-caption vaut 13 px ; ici
     le plancher l'emporte. L'eyebrow reste à 12 px : capitales espacées, c'est
     une étiquette, et les maquettes d'app le composent ainsi. */
  --fs-caption: 15px;
  --lh-caption: 1.45;

  --text-prune: var(--prune);                   /* 9.31:1 au pire (sur --surface-2) */
  --text-on-prune-soft: var(--on-prune-muted);  /* 5.17:1 sur --prune */
  --border-prune: var(--prune);                 /* 9.31:1 — bien au-delà du seuil non-texte */
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
  --text-prune: #B97EA9;          /* 4.78:1 au pire (sur --surface-2 sombre) */
  --text-on-prune-soft: #DFC3D7;  /* 4.84:1 sur le prune sombre */
  --border-prune: #A5508E;        /* 3.35:1 — seuil non-texte (WCAG 1.4.11) */
} }
:root[data-theme="dark"] {
  --text-prune: #B97EA9;
  --text-on-prune-soft: #DFC3D7;
  --border-prune: #A5508E;
}

/* =============================================================================
   1. Coquille
   ============================================================================= */
/* L'attribut hidden cache, toujours. Le JS s'en sert partout (bouton « Terminé »
   avant la fin de la pesée, saisie manuelle balance branchée, zone de capture du
   bol…) ; sans !important, n'importe quel `display` d'une classe l'emporterait
   sur la règle du navigateur — c'est arrivé pendant cette refonte. */
[hidden] { display: none !important; }

body {
  background: var(--bg-app); color: var(--text-body);
  /* Charte : TOUS les chiffres en chasse fixe, sans exception. Posé ici
     une fois, plutôt que répété classe par classe — un poids qui monte ne
     doit jamais faire gigoter la ligne, où qu'il s'affiche. */
  font-variant-numeric: tabular-nums;
}

/* En-tête global : la marque composée en type, comme le veut la charte tant
   qu'aucun logo n'est retenu. Le G capitale est en corail-ink. */
.entete {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) var(--pad-screen);
  background: var(--bg-card);
  border-bottom: var(--stroke-hairline) solid var(--border-hairline);
}
body:has(.ecran.connexion) .entete { display: none; }
.marque { font: var(--fw-semibold) 22px/1 var(--serif); letter-spacing: var(--ls-serif); color: var(--ink); }
.marque-au { color: var(--ink); }
.marque-gramme { display: inline-block; }
.marque-gramme::first-letter { color: var(--corail-ink); }

.app { padding: var(--sp-5) var(--pad-screen) var(--sp-8); }

/* Arrivée d'écran : court, vers le haut, sans rebond — la charte interdit le
   ressort. Assez pour dire « ceci vient de changer », pas assez pour attendre. */
.ecran > * { animation: ag-entree var(--dur-2) var(--ease-out) both; }
@keyframes ag-entree { from { opacity: 0; transform: translateY(6px); } }
.ecran { max-width: var(--maxw-content); margin: 0 auto; }
.ecran-centre { display: grid; place-items: center; min-height: 60vh; text-align: center; gap: var(--gap-stack); }
.parcours { display: grid; gap: var(--gap-grid); }

/* Glyphes de la charte dessinés en SVG (js/icones.js) : ils prennent la taille
   du texte qui les entoure et sa couleur, comme le caractère qu'ils remplacent. */
.icone { display: block; width: 1em; height: 1em; flex: none; }
/* Dans une phrase d'alerte, l'icône s'aligne sur la ligne de texte. */
.message .icone { display: inline-block; vertical-align: -0.15em; margin-right: .4em; }

.visuellement-cache {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* =============================================================================
   1 bis. Rail de navigation — maquettes 3a à 7a
   =============================================================================
   216 px, fond de carte, filet à droite ; liens pleine hauteur de 52 px (cible
   tactile au-dessus des 48 px de la charte), lien actif en lavis prune. Le rail
   porte le logotype : l'en-tête global disparaît quand il est là. Sous 900 px
   (tablette tenue à la verticale), il devient une barre horizontale. */
body:has(.cadre-rail) .entete { display: none; }
body:has(.cadre-rail) .app { padding: 0; }
.cadre-rail { display: flex; min-height: 100vh; }
.rail {
  position: sticky; top: 0; height: 100vh; width: 216px; flex: none;
  display: flex; flex-direction: column; padding: var(--sp-5) var(--sp-4);
  background: var(--bg-card); border-right: var(--stroke-hairline) solid var(--border-hairline);
}
.rail-marque {
  padding: 0 var(--sp-4) 22px; color: var(--text-strong);
  font: var(--fw-semibold) 22px/1 var(--serif); letter-spacing: var(--ls-serif);
}
.rail-marque-g { color: var(--text-accent); }
.rail-liens { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.rail-lien {
  display: flex; align-items: center; min-height: 52px; padding: 0 var(--sp-4);
  border-radius: var(--r-pill); text-decoration: none;
  font: var(--fw-semibold) 17px/1.2 var(--sans); color: var(--text-muted);
  transition: background var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.rail-lien:hover { background: var(--bg-sunken); color: var(--text-strong); }
.rail-lien.actif { background: var(--wash-prune); color: var(--text-prune); }
.rail-pied {
  margin-top: auto; display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-3) 0; border-top: var(--stroke-hairline) solid var(--border-hairline);
}
.rail-avatar {
  width: 40px; height: 40px; flex: none; border-radius: var(--r-pill); display: grid; place-items: center;
  background: var(--prune); color: var(--on-prune); font: var(--fw-semibold) var(--fs-body-sm)/1 var(--sans);
}
.rail-qui { display: grid; min-width: 0; }
.rail-prenom { font: var(--fw-semibold) var(--fs-body-sm)/1.3 var(--sans); color: var(--text-strong); }
.rail-salon {
  font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rail-salon:empty { display: none; }
/* Le volet reprend exactement les marges de .app : la barre d'action collante
   compte dessus (marges négatives de --pad-screen). */
.volet { flex: 1; min-width: 0; padding: var(--sp-5) var(--pad-screen) var(--sp-8); }
@media (max-width: 900px) {
  .cadre-rail { flex-direction: column; }
  .rail {
    height: auto; width: auto; z-index: 10; flex-direction: row; align-items: center; gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4); overflow-x: auto;
    border-right: 0; border-bottom: var(--stroke-hairline) solid var(--border-hairline);
  }
  .rail-marque { padding: 0 var(--sp-3) 0 0; font-size: 20px; }
  .rail-liens { display: flex; gap: var(--sp-1); }
  .rail-lien { min-height: var(--touch-comfort); white-space: nowrap; }
  .rail-pied { display: none; }
}

/* =============================================================================
   1 ter. Réglages — Équipe · Salon · Mon compte
   ============================================================================= */
.reglages-corps { display: grid; gap: var(--gap-grid); }
/* Onglets : des liens (chaque onglet a son adresse), à la hauteur tactile. */
.onglets {
  display: flex; gap: var(--sp-1); flex-wrap: wrap; padding: var(--sp-1);
  background: var(--bg-sunken); border-radius: var(--r-pill); justify-self: start;
}
.onglet {
  display: inline-flex; align-items: center; min-height: var(--touch-comfort); padding: 0 var(--sp-5);
  border-radius: var(--r-pill); text-decoration: none;
  font: var(--fw-semibold) var(--fs-body)/1 var(--sans); color: var(--text-muted);
}
.onglet:hover { color: var(--text-strong); }
.onglet.actif { background: var(--bg-card); color: var(--text-strong); box-shadow: var(--shadow-1); }

/* Équipe : la liste à gauche, l'ajout à droite (maquette 9a). */
.equipe-grille { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--gap-grid); align-items: start; }
@media (max-width: 1000px) { .equipe-grille { grid-template-columns: 1fr; } }
.equipe-liste { display: grid; }
.ligne-equipe {
  display: grid; gap: var(--sp-3); padding: var(--sp-4) 0;
  border-top: var(--stroke-hairline) solid var(--border-hairline);
}
.ligne-equipe:first-child { border-top: 0; padding-top: 0; }
.ligne-equipe-haut { display: flex; align-items: center; gap: var(--sp-3); }
.avatar-equipe {
  width: 44px; height: 44px; flex: none; border-radius: var(--r-pill); display: grid; place-items: center;
  background: var(--prune); color: var(--on-prune); font: var(--fw-semibold) var(--fs-body)/1 var(--sans);
}
.ligne-equipe.inactive .avatar-equipe { background: var(--bg-sunken); color: var(--text-muted); }
.ligne-equipe-texte { display: grid; gap: var(--sp-1); min-width: 0; }
.ligne-equipe-nom { font: var(--fw-semibold) var(--fs-body-lg)/1.3 var(--sans); color: var(--text-strong); }
.ligne-equipe.inactive .ligne-equipe-nom { color: var(--text-muted); }
.ligne-equipe-soi { font-weight: var(--fw-regular); color: var(--text-muted); }
.ligne-equipe-badges { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.ligne-equipe-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.ligne-equipe-actions .bouton { flex: 1 1 180px; }
/* En-tête d'Équipe : le forfait et son occupation, puis la visibilité. */
.badges-equipe { display: flex; gap: var(--sp-2); flex-wrap: wrap; justify-content: flex-end; }
.badge-quota { font-weight: var(--fw-bold); }
/* Forfait complet : on dit pourquoi le bouton ne répond plus. */
.raison-quota { color: var(--text-accent); font-weight: var(--fw-semibold); }
.ligne-equipe-raison { margin: 0; font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }

.panneau-ajout { position: sticky; top: var(--sp-5); }
.choix-roles { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.choix-role {
  flex: 1 1 140px; min-height: var(--touch-glove); padding: 0 var(--sp-4); border-radius: var(--r-pill);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  font: var(--fw-semibold) var(--fs-body)/1 var(--sans); color: var(--text-muted); cursor: pointer;
}
.choix-role:hover { border-color: var(--border-accent); color: var(--text-strong); }
.choix-role.choisi { background: var(--prune); border-color: transparent; color: var(--on-prune); }

/* Le badge « fait » du design system écrit en --prune, qui ne bascule pas en
   thème sombre (#7C3A6A sur fond sombre : illisible). L'app le repasse sur
   --text-prune, audité dans les deux thèmes. design-system.css n'est pas touché. */
.ag-badge--done { color: var(--text-prune); }

/* Vide la plupart du temps : elle ne doit pas laisser de trou dans la grille. */
.zone-code:empty { display: none; }

/* Le code créé ou remplacé : en grand, une seule fois. */
.code-revele {
  display: grid; justify-items: center; gap: var(--sp-3); text-align: center;
  padding: var(--sp-6); border-radius: var(--r-card);
  background: var(--wash-prune); border: var(--stroke-strong) solid var(--border-prune);
}
.code-revele-chiffres {
  margin: 0; font: var(--fw-semibold) var(--fs-weigh)/var(--lh-num) var(--mono);
  letter-spacing: .12em; color: var(--text-prune);
}
.code-revele-consigne { margin: 0; max-width: 46ch; font: var(--fw-semibold) var(--fs-body)/1.45 var(--sans); color: var(--text-strong); }
.panneau-texte { margin: 0; font: var(--fw-regular) var(--fs-body)/1.5 var(--sans); color: var(--text-body); }

/* Salon : la tolérance, au demi-gramme. */
.reglage-salon { max-width: 640px; }
.tolerance-reglage { display: flex; align-items: center; gap: var(--sp-4); }
/* `.bouton.` devant : la règle .bouton vient plus bas dans la feuille et, à
   spécificité égale, écraserait la taille du signe. */
.bouton.tolerance-pas { width: var(--touch-glove); min-height: var(--touch-glove); padding: 0;
  font: var(--fw-semibold) var(--fs-title-3)/1 var(--sans); }
.tolerance-valeur {
  min-width: 5ch; text-align: center;
  font: var(--fw-semibold) var(--fs-num-xl)/1 var(--mono); color: var(--text-strong);
}

.tolerance-exemple { margin: 0; min-height: 1.45em; }

/* Mon compte : le profil, et le changement de code au pavé. */
.compte-grille { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--gap-grid); align-items: start; }
@media (max-width: 1000px) { .compte-grille { grid-template-columns: 1fr; } }
.changer-code { justify-items: start; }
.consigne-code { margin: 0; font: var(--fw-semibold) var(--fs-title-3)/1.2 var(--serif); letter-spacing: var(--ls-serif); color: var(--text-strong); }
.pave-code { display: grid; gap: var(--gap-stack); justify-items: start; }

/* =============================================================================
   1 quater. Colorations en cours
   ============================================================================= */
.liste-en-cours { display: grid; gap: var(--gap-stack); }
/* Sur l'accueil, le titre de la section respire comme ailleurs. */
.accueil .en-cours { display: grid; gap: var(--gap-stack); }
.lignes-en-cours { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.ligne-en-cours {
  display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-card-sm);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
}
/* Oubliée depuis plus de 12 h : un lavis, pas une alarme. */
.ligne-en-cours.a-regler { background: var(--wash-corail); border-color: var(--border-accent); }
.ligne-en-cours-texte { flex: 1 1 260px; min-width: 0; display: grid; gap: 2px; }
.ligne-en-cours-cliente { font: var(--fw-semibold) var(--fs-body-lg)/1.3 var(--sans); color: var(--text-strong); }
.ligne-en-cours-etape { font: var(--fw-semibold) var(--fs-body-sm)/1.3 var(--sans); color: var(--text-accent); }
.ligne-en-cours-detail { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.ligne-en-cours-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.ligne-en-cours-actions .bouton { min-height: var(--touch-glove); }
.en-cours-regler { display: grid; gap: var(--sp-2); }

/* =============================================================================
   2. Titres, textes, fil d'Ariane
   ============================================================================= */
.titre-ecran { font: var(--fw-semibold) var(--fs-title-2)/var(--lh-title-2) var(--serif);
  letter-spacing: var(--ls-serif); color: var(--text-strong); margin: 0; }
.titre-section { font: var(--fw-bold) var(--fs-heading)/var(--lh-heading) var(--sans);
  color: var(--text-strong); margin: 0; display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.sous-titre { font: var(--fw-regular) var(--fs-body-sm)/var(--lh-body-sm) var(--sans); color: var(--text-muted); margin: var(--sp-1) 0 0; }
.en-tete-ecran { display: grid; gap: var(--sp-1); }
/* Titre à gauche, commandes de l'écran à droite, sur la même ligne. */
.entete-avec-actions {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--gap-grid); flex-wrap: wrap;
}
.mention { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.note-champ { margin: 0; font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.note-large { font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); margin-bottom: var(--sp-4); }

.fil-retour {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--touch-min); padding: 0 var(--sp-3) 0 0;
  background: none; border: 0; cursor: pointer;
  font: var(--fw-semibold) var(--fs-body-sm)/1 var(--sans); color: var(--text-accent);
}
.fil-retour:hover { color: var(--text-prune); }

/* =============================================================================
   3. Boutons — repris de ag-btn, sous les noms que le JS pose déjà
   ============================================================================= */
.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--touch-comfort); padding: 0 22px;
  font: var(--fw-semibold) var(--fs-body)/1 var(--sans);
  border: var(--stroke-strong) solid transparent; border-radius: var(--r-pill);
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.bouton:active { transform: translateY(1px); }
.bouton-principal { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.bouton-principal:hover:not(:disabled) { background: var(--btn-primary-bg-hover); }
.bouton-principal:focus-visible { outline-color: var(--focus-ring-on-accent); }
.bouton-secondaire { background: var(--btn-secondary-bg); color: var(--btn-secondary-fg); }
.bouton-secondaire:hover:not(:disabled) { background: var(--btn-secondary-bg-hover); }
.bouton-discret { background: transparent; color: var(--btn-ghost-fg); border-color: var(--border-hairline); }
.bouton-discret:hover:not(:disabled) { background: var(--bg-sunken); border-color: var(--border-strong); }
.bouton-danger { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.bouton-danger:hover:not(:disabled) { background: var(--btn-primary-bg-hover); }
/* Le geste se fait avec des gants de coloration : 56 px. */
.bouton-large { min-height: var(--touch-glove); font-size: var(--fs-body-lg); padding: 0 32px; }
.bouton:disabled, .bouton[aria-disabled="true"] {
  background: var(--btn-disabled-bg); color: var(--btn-disabled-fg);
  border-color: transparent; cursor: not-allowed; transform: none;
}
/* Validation très éloignée de la cible : le bouton reste primaire (il l'est
   déjà) mais s'entoure d'un anneau corail et passe en gras — le libellé, lui,
   dit l'écart en toutes lettres. */
.bouton.a-confirmer {
  font-weight: var(--fw-bold);
  box-shadow: 0 0 0 var(--stroke-focus) var(--corail);
}
.bouton-abandon {
  background: none; border: 0; min-height: var(--touch-min); padding: 0 var(--sp-3);
  font: var(--fw-regular) var(--fs-body-sm)/1 var(--sans); color: var(--text-muted);
  text-decoration: underline; text-underline-offset: 4px; cursor: pointer;
}
.bouton-abandon:hover { color: var(--text-accent); }
.zone-abandon { display: flex; justify-content: center; margin-top: var(--sp-5); }
.lien-reessayer {
  background: none; border: 0; padding: 0 var(--sp-1); cursor: pointer;
  font: var(--fw-semibold) inherit var(--sans); color: var(--text-accent);
  text-decoration: underline; text-underline-offset: 3px;
}
.bouton-retirer {
  width: var(--touch-min); height: var(--touch-min); flex: none;
  border: 0; border-radius: var(--r-pill); background: var(--bg-sunken); color: var(--text-muted);
  font-size: var(--fs-heading); line-height: 1; cursor: pointer;
}
.bouton-retirer:hover { background: var(--wash-corail); color: var(--text-accent); }

/* Barre d'action collante : sur tablette, mains prises, le bouton principal
   reste sous le pouce sans faire défiler. Elle reste DANS le flux, donc le
   contenu ne peut pas passer dessous. */
.barre-action {
  position: sticky; bottom: 0; z-index: 5;
  margin: var(--sp-4) calc(-1 * var(--pad-screen)) calc(-1 * var(--sp-8));
  padding: var(--sp-3) var(--pad-screen) max(var(--sp-3), env(safe-area-inset-bottom));
  background: linear-gradient(180deg, transparent 0%, var(--bg-app) 38%, var(--bg-app) 100%);
  backdrop-filter: blur(10px);
}
.barre-action-contenu {
  display: flex; flex-wrap: wrap; gap: var(--gap-inline);
  max-width: var(--maxw-content); margin: 0 auto;
}
.barre-action .bouton { flex: 1 1 240px; min-height: var(--touch-glove); }

/* =============================================================================
   4. Cartes, messages, chargement
   ============================================================================= */
.carte-formule, .carte-graphique {
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card); padding: var(--pad-card);
  display: grid; gap: var(--gap-stack);
}
.message {
  border-radius: var(--r-field); padding: var(--sp-3) var(--sp-4); margin: 0;
  font: var(--fw-semibold) var(--fs-body-sm)/1.45 var(--sans);
}
/* Pas de rouge sémantique dans la charte : une alerte est un lavis corail. */
.message-erreur { background: var(--wash-corail); color: var(--text-accent);
  box-shadow: inset 0 0 0 1px var(--border-accent); }
.message-alerte { background: var(--wash-corail); color: var(--text-accent); }
.message-succes { background: var(--wash-prune); color: var(--text-prune); }
.zone-message:empty { display: none; }

.chargement { display: flex; align-items: center; gap: var(--sp-3); color: var(--text-muted);
  font: var(--fw-regular) var(--fs-body-sm)/1.4 var(--sans); }
.spinner {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  border: 2px solid var(--border-accent); border-top-color: transparent;
  animation: ag-spin 720ms linear infinite;
}
.spinner-petit { width: 16px; height: 16px; border-width: 2px; }
.spinner-recherche { position: absolute; right: var(--sp-4); top: 50%; margin-top: -11px; }

.etat-vide {
  display: grid; justify-items: center; gap: var(--sp-2); text-align: center;
  padding: var(--sp-10) var(--sp-6);
  border: var(--stroke-hairline) dashed var(--border-hairline); border-radius: var(--r-card);
  background: var(--bg-card);
}
.etat-vide-grand { padding: var(--sp-10) var(--sp-6); }
.ecran-provisoire { gap: var(--gap-stack); }
/* Une note dans un état vide reste une note : `.etat-vide p` la grossissait. */
.etat-vide .note-champ { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.etat-vide-icone { font-size: var(--fs-title-2); color: var(--text-muted); }
.etat-vide p { font: var(--fw-semibold) var(--fs-body-lg)/1.4 var(--sans); color: var(--text-strong); margin: 0; }
.etat-vide-detail { font: var(--fw-regular) var(--fs-body-sm)/var(--lh-body-sm) !important;
  color: var(--text-muted) !important; font-weight: var(--fw-regular) !important; max-width: 46ch; }

/* =============================================================================
   5. Connexion — choix de la coiffeuse, puis code personnel
   =============================================================================
   Deux panneaux, comme la maquette : la marque à gauche sur aplat prune, la
   saisie à droite. Le panneau de marque n'affiche aucune donnée — avant la
   connexion, on ne sait rien du salon. En dessous de 860 px il se replie en
   bandeau : sur une tablette tenue à la verticale, le pavé prime. */
.ecran.connexion {
  max-width: 1120px;
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: min(620px, 78vh);
  background: var(--bg-card); border-radius: var(--r-screen); overflow: hidden;
  box-shadow: var(--shadow-2);
}
.connexion-marque {
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-8);
  padding: var(--sp-12) var(--sp-10);
  background: radial-gradient(120% 140% at 0% 0%, var(--prune) 0%, var(--prune-deep) 100%);
  color: var(--text-on-prune);
}
.connexion-logotype { font: var(--fw-semibold) var(--fs-title-2)/1 var(--serif); letter-spacing: var(--ls-serif); }
.connexion-logotype-g { color: var(--corail); }
.connexion-phrase {
  margin: 0; font: var(--fw-semibold) var(--fs-title-1)/var(--lh-title-1) var(--serif);
  letter-spacing: var(--ls-serif); text-wrap: balance;
}
.connexion-phrase-detail {
  margin: var(--sp-4) 0 0; max-width: 38ch;
  font: var(--fw-regular) var(--fs-body-lg)/1.55 var(--sans); color: var(--text-on-prune-soft);
}
.connexion-forme {
  display: flex; flex-direction: column; justify-content: center; gap: var(--gap-stack);
  padding: var(--sp-10) var(--sp-10);
}
.titre-connexion {
  margin: var(--sp-2) 0 0; font: var(--fw-semibold) var(--fs-title-1)/var(--lh-title-1) var(--serif);
  letter-spacing: var(--ls-serif); color: var(--text-strong);
}
@media (max-width: 860px) {
  .ecran.connexion { grid-template-columns: 1fr; min-height: 0; }
  .connexion-marque { flex-direction: row; align-items: center; padding: var(--sp-5) var(--sp-6); gap: var(--sp-4); }
  .connexion-marque > div, .connexion-marque > span:last-child { display: none; }
  .connexion-forme { padding: var(--sp-6); }
  .titre-connexion { font-size: var(--fs-title-2); line-height: var(--lh-title-2); }
}

/* Les profils : une ligne pleine largeur chacun, lisible d'un coup d'œil. */
.grille-badges { display: grid; gap: var(--sp-3); }
.badge-coiffeuse {
  display: flex; align-items: center; gap: var(--sp-4); text-align: left;
  min-height: 72px; padding: var(--sp-3) var(--sp-5);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card-sm); cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.badge-coiffeuse:hover { border-color: var(--border-accent); }
.badge-coiffeuse:active { transform: translateY(1px); }
/* La responsable du salon se distingue par un fond, pas par une couleur de texte. */
.badge-coiffeuse.est-admin { background: var(--wash-prune); border-color: var(--text-prune); border-width: var(--stroke-strong); }
.badge-emoji {
  width: 48px; height: 48px; flex: none; border-radius: var(--r-pill); display: grid; place-items: center;
  background: var(--bg-sunken); color: var(--text-prune);
  font: var(--fw-semibold) var(--fs-body-lg)/1 var(--sans);
}
.badge-coiffeuse.est-admin .badge-emoji { background: var(--prune); color: var(--on-prune); }
.badge-prenom { font: var(--fw-semibold) var(--fs-body-lg)/1.3 var(--sans); color: var(--text-strong); }
.badge-role { font: var(--fw-regular) var(--fs-body-sm)/1.3 var(--sans); color: var(--text-muted); margin-left: auto; }

.saisie-pin { display: grid; gap: var(--gap-stack); justify-items: start; }
.saisie-pin-qui { display: flex; align-items: center; gap: var(--sp-4); }
.emoji {
  width: 48px; height: 48px; flex: none; border-radius: var(--r-pill); display: grid; place-items: center;
  background: var(--prune); color: var(--on-prune); font: var(--fw-semibold) var(--fs-body-lg)/1 var(--sans);
}
/* Quatre cases plutôt que quatre points : à bras tendu, on voit où on en est. */
.points-pin { display: flex; gap: var(--sp-3); }
.point-pin {
  width: 62px; height: 72px; border-radius: var(--r-field);
  background: var(--bg-sunken); display: grid; place-items: center;
  transition: background var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.point-pin.rempli { background: var(--bg-sunken); box-shadow: inset 0 0 0 2px var(--corail); }
.point-pin.rempli::after {
  content: "•"; font-family: var(--mono); font-size: 30px; font-weight: var(--fw-semibold); color: var(--ink);
}
.points-pin.secousse { animation: ag-secousse 420ms var(--ease-out); }
@keyframes ag-secousse { 25% { transform: translateX(-7px) } 75% { transform: translateX(7px) } }

/* Pavé « à quatre doigts » : des cibles franchement plus grandes que le
   plancher, parce qu'on le touche sans regarder. */
.pave { display: grid; grid-template-columns: repeat(3, 92px); gap: var(--gap-inline); }
.touche {
  min-height: 64px; border-radius: var(--r-field);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  color: var(--text-strong);
  font: var(--fw-semibold) 24px/1 var(--mono);
  cursor: pointer; transition: background var(--dur-2) var(--ease-out);
}
.touche:hover:not(:disabled) { background: var(--bg-sunken); }
.touche:active { transform: translateY(1px); }
.touche:disabled { opacity: .5; cursor: not-allowed; }
.touche-effacer, .touche-valider { font: var(--fw-semibold) var(--fs-body-sm)/1.2 var(--sans); }
.touche-effacer { color: var(--text-muted); }
.touche-valider { background: var(--btn-primary-bg); color: var(--btn-primary-fg); border-color: transparent; }
.touche-valider:hover:not(:disabled) { background: var(--btn-primary-bg-hover); }
/* Désactivé mais lisible (charte : 4,57:1) — pas d'opacité par-dessus. */
.touche-valider:disabled { background: var(--btn-disabled-bg); color: var(--btn-disabled-fg); opacity: 1; }

/* =============================================================================
   6. Accueil
   ============================================================================= */
.accueil { display: grid; gap: var(--gap-grid); }
.accueil-entete { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.accueil-salut { display: flex; align-items: center; gap: var(--sp-4); }
.medaillon {
  width: 56px; height: 56px; border-radius: var(--r-pill); display: grid; place-items: center; flex: none;
  background: var(--prune); color: var(--on-prune); font-size: var(--fs-title-3);
}
.medaillon-grand { width: 72px; height: 72px; font-size: var(--fs-title-2); }
.medaillon-initiales { font: var(--fw-semibold) var(--fs-heading)/1 var(--sans); }

.recherche { display: grid; gap: var(--sp-2); }
.recherche-boite { position: relative; }
.recherche-champ {
  width: 100%; min-height: var(--touch-glove); padding: var(--sp-3) var(--sp-5);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-pill); color: var(--text-strong);
  font: var(--fw-regular) var(--fs-body-lg)/1.4 var(--sans);
}
.recherche-champ::placeholder { color: var(--text-muted); }
.recherche-champ:hover { border-color: var(--border-strong); }
.recherche-champ-compacte { min-height: var(--touch-comfort); font-size: var(--fs-body); }
.recherche-etat { margin: 0; font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.recherche-etat-erreur { color: var(--text-accent); }

.resultats { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.carte-cliente {
  display: flex; align-items: center; gap: var(--sp-4); width: 100%;
  min-height: var(--touch-glove); padding: var(--sp-3) var(--sp-4);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card-sm); cursor: pointer; text-align: left;
  transition: border-color var(--dur-2) var(--ease-out);
}
.carte-cliente:hover { border-color: var(--border-accent); }
.avatar {
  width: 44px; height: 44px; flex: none; border-radius: var(--r-pill); display: grid; place-items: center;
  background: var(--wash-prune); color: var(--text-prune); font: var(--fw-semibold) var(--fs-body-sm)/1 var(--sans);
}
.avatar-creation { background: var(--wash-corail); color: var(--text-accent); }
.carte-cliente-texte { flex: 1; min-width: 0; display: grid; gap: 2px; }
.carte-cliente-nom { font: var(--fw-semibold) var(--fs-body)/1.3 var(--sans); color: var(--text-strong); }
.carte-cliente-tel { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.carte-creation { border-style: dashed; }
.carte-creation:hover { border-style: solid; border-color: var(--border-accent); }

/* En flex plutôt qu'en grille : la carte phare occupait toutes les colonnes,
   la grille ne se repliait plus et laissait une colonne vide à droite. */
.actions { display: flex; flex-wrap: wrap; gap: var(--gap-inline); }
.actions > .carte-action { flex: 1 1 240px; width: auto; }
/* Même spécificité que la règle au-dessus, et après elle : la carte phare
   garde sa ligne entière. */
.actions > .carte-action-principale { flex-basis: 100%; }
.carte-action {
  display: flex; align-items: center; gap: var(--sp-4); width: 100%;
  min-height: 92px; padding: var(--sp-4) var(--sp-5);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card); cursor: pointer; text-align: left;
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.carte-action:hover:not(:disabled) { border-color: var(--border-accent); }
.carte-action:disabled { opacity: .55; cursor: not-allowed; }
/* L'action du jour occupe la moitié de l'écran : aplat prune, titre en serif,
   appel à l'action en bas — c'est la première chose qu'on touche en arrivant. */
.carte-action-principale {
  flex-basis: 100%; min-height: 240px;
  flex-direction: column; align-items: flex-start; justify-content: flex-start;
  gap: var(--sp-3); padding: var(--sp-8) var(--sp-8) var(--sp-6);
  background: radial-gradient(120% 140% at 0% 0%, var(--prune) 0%, var(--prune-deep) 100%);
  border-color: transparent; color: var(--text-on-prune);
}
.carte-action-principale:hover { border-color: transparent; }
.carte-action-sur { color: var(--text-on-prune-soft); }
.carte-action-icone {
  width: 48px; height: 48px; flex: none; border-radius: var(--r-pill);
  display: grid; place-items: center; background: var(--wash-corail);
  font: var(--fw-semibold) var(--fs-heading)/1 var(--sans); color: var(--text-accent);
}
.carte-action-texte { display: grid; gap: 2px; min-width: 0; }
.carte-action-titre { font: var(--fw-semibold) var(--fs-heading)/1.25 var(--sans); }
.carte-action-principale .carte-action-titre {
  font: var(--fw-semibold) var(--fs-title-1)/var(--lh-title-1) var(--serif);
  letter-spacing: var(--ls-serif); text-wrap: balance;
}
.carte-action-detail { font: var(--fw-regular) var(--fs-body-sm)/1.45 var(--sans); color: var(--text-muted); }
.carte-action-principale .carte-action-detail {
  color: var(--text-on-prune-soft); font-size: var(--fs-body-lg); line-height: 1.5; max-width: 42ch;
}
/* Faux bouton : la carte entière est cliquable, ceci en donne le geste. */
.carte-action-appel {
  margin-top: auto; display: inline-flex; align-items: center;
  min-height: var(--touch-glove); padding: 0 28px; border-radius: var(--r-pill);
  background: var(--btn-primary-bg); color: var(--btn-primary-fg);
  font: var(--fw-semibold) var(--fs-body-lg)/1 var(--sans);
  transition: background var(--dur-2) var(--ease-out);
}
.carte-action-principale:hover .carte-action-appel { background: var(--btn-primary-bg-hover); }
.carte-action.en-cours { opacity: .7; }

.en-cours-section { display: grid; gap: var(--gap-stack); }
.pastille-historique, .pastille-bientot {
  display: inline-flex; align-items: center; gap: var(--sp-2); flex: none;
  padding: 6px var(--sp-3); border-radius: var(--r-pill);
  font: var(--fw-semibold) var(--fs-caption)/1 var(--sans);
  background: var(--wash-prune); color: var(--text-prune);
}

/* =============================================================================
   7. Fiche cliente, choix du mode
   ============================================================================= */
.fiche-entete { display: flex; align-items: center; gap: var(--sp-5); }
/* L'historique tient la colonne large : c'est lui qu'on vient lire. */
.fiche-grille > section { display: grid; gap: var(--gap-stack); align-content: start; }
.fiche-grille { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--gap-grid); align-items: start; }
@media (max-width: 900px) { .fiche-grille { grid-template-columns: 1fr; } }
.fiche-cote {
  display: grid; gap: var(--gap-stack);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card); padding: var(--pad-card);
}
.infos { display: grid; gap: var(--sp-3); }
.info { background: var(--bg-sunken); border-radius: var(--r-tile); padding: var(--sp-3) var(--sp-4); display: grid; gap: 2px; }
.info-libelle { font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.info-valeur { font: var(--fw-regular) var(--fs-body)/1.4 var(--sans); color: var(--text-strong); }
.info-vide { color: var(--text-muted); }

.liste-historique { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gap-inline); }
.carte-historique {
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card-sm); padding: var(--sp-4) var(--sp-5); display: grid; gap: var(--sp-3);
}
.carte-historique-tete { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.carte-historique-date { font: var(--fw-semibold) var(--fs-body)/1.3 var(--sans); color: var(--text-strong); }
.carte-historique-par { font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.carte-historique-composants { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.carte-historique-composants li {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3);
  font: var(--fw-regular) var(--fs-body-sm)/1.5 var(--sans); color: var(--text-muted);
}
.carte-historique-composants b { font-family: var(--mono);
  font-size: var(--fs-num-sm); color: var(--text-strong); }
.carte-historique-total { margin: 0; font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }

.choix-mode { display: grid; gap: var(--gap-inline); }
.carte-choix { min-height: 104px; }

/* =============================================================================
   8. Pesée — le cœur
   ============================================================================= */
.pesee-entete { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-5); flex-wrap: wrap; }
.barre-balance { display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap; }
.actions-balance { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* État de la balance : badge du design system. Le point respire en reconnexion. */
.etat-balance {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px var(--sp-3); border-radius: var(--r-pill);
  font: var(--fw-semibold) var(--fs-caption)/1 var(--sans);
  background: var(--bg-sunken); color: var(--text-muted);
}
.etat-balance::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.etat-balance.etat-connectee { background: var(--wash-prune); color: var(--text-prune); }
.etat-balance.etat-connexion, .etat-balance.etat-reconnexion, .etat-balance.etat-reveil {
  background: var(--wash-corail); color: var(--text-accent);
}
.etat-balance.etat-connexion::before, .etat-balance.etat-reconnexion::before, .etat-balance.etat-reveil::before {
  animation: ag-pulse 1.6s ease-in-out infinite;
}
.etat-balance.etat-reveil { font-weight: var(--fw-bold); }

/* Deux colonnes, comme la maquette : la jauge à gauche, la formule à droite. */
.pesee-grille { display: grid; grid-template-columns: 470px minmax(0, 1fr); gap: var(--gap-grid); align-items: start; }
@media (max-width: 1080px) { .pesee-grille { grid-template-columns: 1fr; } }

.pesee-zone, .pesee-composants {
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-screen-sm); padding: var(--sp-5) var(--sp-6);
  display: flex; flex-direction: column; gap: var(--gap-stack);
}
/* La carte de la balance est la plus dense de l'app : en paysage tablette, le
   statut et la barre de stabilité doivent tenir AU-DESSUS de la barre collante,
   sans défiler — on pèse les mains prises. */
.pesee-zone { gap: var(--sp-3); padding-block: var(--sp-4); }
.pesee-zone .zone-mesure { gap: var(--sp-2); }
.pesee-zone { align-items: center; text-align: center; }

/* Bandeau de carte : l'étiquette à gauche, le compteur à droite. */
.carte-tete { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-inline); width: 100%; }

.progression-pesee { font-family: var(--mono);
  font-size: var(--fs-num-sm); font-weight: var(--fw-semibold); color: var(--text-muted); }

/* La goutte reprend le rôle de l'arc de la maquette : même lecture, même
   corail décoratif, même transition LINÉAIRE — l'aiguille suit la balance,
   elle ne lisse pas, sinon on doute de la mesure. */
.goutte-cadre { position: relative; display: grid; place-items: center; width: 220px; max-width: 100%; }
.goutte { width: 100%; height: auto; display: block; }
.goutte-fond { fill: var(--gauge-track); }
.goutte-contour { fill: none; stroke: var(--border-hairline); stroke-width: 3; }
.goutte-liquide { fill: url(#goutte-degrade); transition: transform var(--dur-1) var(--ease-linear); }
.goutte-haut { stop-color: var(--corail); }
.goutte-bas { stop-color: var(--corail-ink); }
.goutte.zone-cible .goutte-contour { stroke: var(--border-prune); }
.goutte.zone-dessus .goutte-liquide { fill: var(--corail-ink); }
.goutte.validee .goutte-contour { stroke: var(--border-prune); stroke-width: 5; }
.goutte-valeurs { position: absolute; inset: 0; display: grid; place-items: center; }

/* La colonne de mesure : tout y est centré sous la goutte. */
.zone-mesure { display: grid; justify-items: center; gap: var(--gap-stack); width: 100%; }

/* Le poids, en mono, à bras tendu. */
/* Le poids ne repose JAMAIS directement sur le liquide : prune sur corail est
   à peine lisible en clair, et corail sur corail disparaît en sombre. Il a sa
   pastille, couleur de carte — le couple --gauge-number / --bg-card est audité
   (10,9:1 en clair, 6,1:1 en sombre). Une seule ligne : « 148,5 g » ne se coupe
   pas. */
.poids-geant {
  white-space: nowrap;
  padding: var(--sp-1) var(--sp-4); border-radius: var(--r-field);
  background: var(--bg-card); box-shadow: var(--shadow-1);
  font-family: var(--mono); font-weight: var(--fw-semibold);
  font-size: 64px; line-height: var(--lh-num); letter-spacing: var(--ls-num);
  color: var(--gauge-number);
}
.poids-unite { font-size: .4em; color: var(--text-muted); }
.poids-moyen {
  font-family: var(--mono); font-weight: var(--fw-semibold);
  font-size: var(--fs-num-xl); letter-spacing: var(--ls-num); color: var(--gauge-number);
}
.pesee-produit { font: var(--fw-semibold) var(--fs-heading)/1.3 var(--sans); color: var(--text-accent); margin: 0; }
.pesee-cible { margin: 0; font: var(--fw-regular) var(--fs-body-sm)/1.4 var(--sans); color: var(--text-muted); }
.pesee-cible b { color: var(--text-strong); font-family: var(--mono); }
.pesee-statut { margin: 0; font: var(--fw-semibold) var(--fs-body-lg)/1.4 var(--sans); color: var(--text-accent); min-height: 1.4em; }
.statut-vide { color: var(--text-muted); }
.statut-cible, .statut-fini { color: var(--text-prune); }
.statut-dessus { color: var(--text-accent); }

.stabilite { height: 6px; border-radius: var(--r-pill); background: var(--gauge-track); overflow: hidden; width: 100%; }
.stabilite-barre { display: block; height: 100%; border-radius: var(--r-pill); background: var(--corail);
  transform-origin: left; transform: scaleX(0); transition: transform var(--dur-1) var(--ease-linear); }

.ligne-tare { display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap; justify-content: center; }
.etat-tare { font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.tare-materielle { color: var(--text-prune); font-weight: var(--fw-semibold); }
.tare-logicielle { color: var(--text-accent); }

/* Total du bol : ce qui est dans le bol sur ce qui doit y être. */
.total-bol { display: grid; gap: var(--sp-2); }
.total-bol-ligne { display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-inline); }
.total-bol-libelle { font: var(--fw-semibold) var(--fs-body-sm)/1.3 var(--sans); color: var(--text-muted); }
.total-bol-chiffre { font-family: var(--mono);
  font-size: var(--fs-num-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.total-bol-piste { height: 10px; border-radius: var(--r-pill); background: var(--gauge-track); overflow: hidden; }
.total-bol-remplissage { display: block; height: 100%; border-radius: var(--r-pill); background: var(--corail);
  transform-origin: left; transform: scaleX(0); transition: transform var(--dur-2) var(--ease-out); }

/* Formule guidée, composant par composant — ag-ing du design system. */
.liste-pesee { list-style: none; margin: 0; padding: 0; display: grid; }
.ligne-pesee {
  display: flex; align-items: center; gap: var(--gap-inline); width: 100%;
  min-height: 64px; padding: var(--sp-3) 0;
  border: 0; border-top: var(--stroke-hairline) solid var(--border-hairline);
  background: none; cursor: pointer; text-align: left;
  font: var(--fw-regular) var(--fs-body)/1.3 var(--sans); color: var(--text-muted);
}
.ligne-pesee-etat {
  width: 22px; height: 22px; flex: none; border-radius: var(--r-pill);
  display: grid; place-items: center; font-size: 12px; line-height: 1;
  border: var(--stroke-strong) solid var(--border-hairline);
}
.ligne-pesee-texte { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ligne-pesee-nom { font-size: var(--fs-body-lg); }
.ligne-pesee-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.ligne-pesee.pesee-faite { color: var(--text-muted); }
.ligne-pesee.pesee-faite .ligne-pesee-etat { background: var(--wash-prune); color: var(--text-prune); border-color: transparent; }
.ligne-pesee.courante {
  min-height: 76px; padding-inline: var(--sp-4); border-top-color: transparent;
  background: var(--wash-corail); border-radius: var(--r-field);
  color: var(--text-strong); font-weight: var(--fw-semibold);
}
.ligne-pesee.courante .ligne-pesee-etat { background: var(--btn-primary-bg); color: var(--btn-primary-fg); border-color: transparent; }
.ligne-pesee.courante .ligne-pesee-detail { color: var(--text-accent); font-weight: var(--fw-semibold); }

/* Bols capturés */
.barre-bols { display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap; }
.bol-capture, .bol-absent {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 6px var(--sp-3); border-radius: var(--r-pill);
  font: var(--fw-semibold) var(--fs-caption)/1 var(--sans);
  background: var(--wash-prune); color: var(--text-prune);
}
.bol-absent { background: var(--bg-sunken); color: var(--text-muted); font-weight: var(--fw-regular); }
.zone-capture, .capture-bol { display: grid; gap: var(--gap-stack); justify-items: center; text-align: center; }
.capture-bol-consigne { margin: 0; font: var(--fw-regular) var(--fs-body-lg)/1.5 var(--sans); color: var(--text-strong); }
.capture-bol-titre { font: var(--fw-semibold) var(--fs-body)/1.3 var(--sans); color: var(--text-strong); margin: 0; }
.capture-bol-actions { display: flex; gap: var(--gap-inline); flex-wrap: wrap; justify-content: center; }

/* =============================================================================
   9. Formule : composants et doses
   ============================================================================= */
.liste-composants { list-style: none; margin: 0; padding: 0; display: grid; }
.ligne-composant {
  display: flex; align-items: center; gap: var(--gap-inline);
  min-height: var(--touch-comfort); padding: var(--sp-3) 0;
  border-top: var(--stroke-hairline) solid var(--border-hairline);
}
.ligne-composant:first-child { border-top: 0; }
.ligne-composant-texte { flex: 1; min-width: 0; display: grid; gap: 2px; }
.ligne-composant-nom { font: var(--fw-regular) var(--fs-body)/1.35 var(--sans); color: var(--text-strong); }
.ligne-composant-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.ligne-composant-dose { font-family: var(--mono);
  font-size: var(--fs-num-sm); font-weight: var(--fw-semibold); color: var(--text-strong); }
.total-formule {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-inline);
  padding-top: var(--sp-3); border-top: var(--stroke-accent) solid var(--border-accent);
}
.total-formule b { font-family: var(--mono);
  font-size: var(--fs-num); font-weight: var(--fw-semibold); color: var(--text-strong); }
.formule-vide { margin: 0; color: var(--text-muted); font: var(--fw-regular) var(--fs-body-sm)/1.5 var(--sans); }

.dose { display: flex; align-items: center; gap: var(--sp-2); background: var(--bg-sunken);
  border: var(--stroke-hairline) solid var(--border-hairline); border-radius: var(--r-field);
  padding: 0 var(--sp-4); }
.dose:focus-within { border-color: transparent; outline: var(--stroke-focus) solid var(--focus-ring); outline-offset: 1px; }
.dose-champ {
  flex: 1; min-width: 0; min-height: var(--touch-glove); border: 0; background: none;
  font-family: var(--mono); text-align: right;
  font-size: var(--fs-num-lg); font-weight: var(--fw-semibold); color: var(--text-strong);
}
.dose-champ:focus { outline: none; }
.dose-unite { font-family: var(--mono); font-size: var(--fs-body); color: var(--text-muted); flex: none; }
.dose-manuelle { width: 100%; }
.doses-rapides { display: flex; gap: var(--sp-2); flex-wrap: wrap; justify-content: center; }
.puce-dose {
  min-height: var(--touch-comfort); padding: 0 var(--sp-4); border-radius: var(--r-pill);
  background: var(--bg-sunken); border: var(--stroke-hairline) solid var(--border-hairline);
  font-family: var(--mono);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); color: var(--text-strong); cursor: pointer;
}
.puce-dose:hover { border-color: var(--border-accent); }
.puce-dose.choisie { background: var(--prune); border-color: transparent; color: var(--on-prune); }
.dose-produit { display: grid; gap: 2px; }
.dose-produit-nom { font: var(--fw-semibold) var(--fs-heading)/1.25 var(--sans); color: var(--text-strong); }
.dose-produit-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }

/* Catalogue produits, en panneau */
.catalogue { display: grid; gap: var(--gap-stack); max-height: 46vh; overflow: auto; }
.groupe-marque { display: grid; gap: var(--sp-1); }
.groupe-marque-titre { margin: 0; font: var(--fw-bold) var(--fs-caption)/1.3 var(--sans);
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase; color: var(--text-muted); }
.groupe-marque ul { list-style: none; margin: 0; padding: 0; display: grid; }
.ligne-produit {
  display: flex; align-items: center; gap: var(--gap-inline); width: 100%;
  min-height: var(--touch-glove); padding: var(--sp-3) 0;
  border: 0; border-top: var(--stroke-hairline) solid var(--border-hairline);
  background: none; cursor: pointer; text-align: left;
}
.ligne-produit:hover { background: var(--bg-sunken); }
.ligne-produit-nom { flex: 1; min-width: 0; font: var(--fw-regular) var(--fs-body)/1.35 var(--sans); color: var(--text-strong); }
.ligne-produit-stock { font-family: var(--mono);
  font-size: var(--fs-num-sm); color: var(--text-muted); }
.ligne-produit.stock-bas .ligne-produit-stock { color: var(--text-accent); font-weight: var(--fw-semibold); }

.pastille-type {
  padding: 3px var(--sp-2); border-radius: var(--r-pill); flex: none;
  font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans);
  background: var(--wash-prune); color: var(--text-prune);
}
.pastille-oxydant { background: var(--wash-corail); color: var(--text-accent); }

/* =============================================================================
   10. Application, pose, rajouts
   ============================================================================= */
.recap-bols, .rajouts-faits { display: flex; gap: var(--gap-inline); flex-wrap: wrap; }
.choix-temps { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
/* L'anneau se remplit à mesure que la pose avance : le JS pose --progression
   en degrés, le conic-gradient s'en charge. La minute écoulée ne « glisse »
   pas — comme la jauge de pesée, l'aiguille suit le temps réel. */
.minuteur { display: grid; justify-items: center; gap: var(--sp-4); }
.minuteur-anneau {
  --progression: 0deg;
  width: min(280px, 70vw); aspect-ratio: 1; border-radius: var(--r-pill);
  display: grid; place-items: center;
  background:
    radial-gradient(closest-side, var(--bg-card) 84%, transparent 85%),
    conic-gradient(var(--corail) var(--progression), var(--gauge-track) 0);
  box-shadow: var(--shadow-1);
  transition: background var(--dur-1) var(--ease-linear);
}
.minuteur-chiffres {
  font-family: var(--mono); font-weight: var(--fw-semibold);
  font-size: var(--fs-weigh); line-height: var(--lh-num); letter-spacing: var(--ls-num); color: var(--text-prune);
}
/* Pose finie : l'anneau est plein et respire. C'est un signal à distance,
   depuis l'autre bout du salon. */
.minuteur-anneau.termine {
  background:
    radial-gradient(closest-side, var(--bg-card) 84%, transparent 85%),
    conic-gradient(var(--corail-ink) 360deg, var(--corail-ink) 0);
  animation: ag-respiration 2s ease-in-out infinite;
}
@keyframes ag-respiration { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.03); } }
.minuteur-anneau.termine .minuteur-chiffres { color: var(--text-accent); }
.minuteur-etat { font: var(--fw-regular) var(--fs-body-sm)/1.4 var(--sans); color: var(--text-muted); margin: 0; }
.poids-rajout { font-family: var(--mono);
  font-size: var(--fs-num-lg); font-weight: var(--fw-semibold); color: var(--gauge-number); }
.pastille-manque {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 6px var(--sp-3); border-radius: var(--r-pill);
  background: var(--wash-corail); color: var(--text-accent);
  font: var(--fw-semibold) var(--fs-caption)/1 var(--sans);
  box-shadow: inset 0 0 0 1px var(--border-accent);
}
.pastille-large { padding: var(--sp-3) var(--sp-4); font-size: var(--fs-body-sm); }

/* =============================================================================
   11. Finalisation et bilan
   ============================================================================= */
.bols-reste { display: grid; gap: var(--gap-inline); }
.carte-bol {
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card-sm); padding: var(--sp-4) var(--sp-5); display: grid; gap: var(--sp-3);
}
.carte-bol.faite { background: var(--wash-prune); border-color: transparent; }
.carte-bol .bouton-discret { background: var(--bg-card); }
.carte-bol-titre { margin: 0; font: var(--fw-semibold) var(--fs-body)/1.35 var(--sans); color: var(--text-strong); }
.carte-bol-titre span { font-weight: var(--fw-regular); color: var(--text-muted); }
.calcul-reste {
  margin: 0; font-family: var(--mono);
  font-size: var(--fs-body-sm); color: var(--text-prune);
}
.calcul-reste.alerte { color: var(--text-accent); font-weight: var(--fw-semibold); }
.total-reste { gap: var(--sp-3); }
.bascule { border-style: dashed; }
.bascule.active { background: var(--wash-corail); color: var(--text-accent); border-style: solid; border-color: var(--border-accent); }

.bilan-entete { display: grid; justify-items: center; gap: var(--sp-2); text-align: center; }
.chiffres { display: grid; gap: var(--gap-inline); grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.chiffre { background: var(--bg-sunken); border-radius: var(--r-tile); padding: var(--sp-4) var(--sp-5); display: grid; gap: var(--sp-1); align-content: start; }
.chiffre-libelle { font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.chiffre-valeur { font: var(--fw-semibold) var(--fs-title-3)/1.05 var(--serif); letter-spacing: var(--ls-serif);
  color: var(--text-strong); }
.chiffre-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
/* Ce que le bol a coûté pour rien : c'est le chiffre qui fait changer un geste. */
.chiffre-phare { background: var(--wash-corail); }
.chiffre-phare .chiffre-valeur { color: var(--text-accent); }

/* =============================================================================
   12. Tableau de bord — rentabilité
   ============================================================================= */
.tableau-corps { display: grid; gap: var(--gap-grid); }
/* Le chiffre qui décide, sur aplat prune. */
.phare {
  position: relative; overflow: hidden; text-align: center;
  padding: var(--sp-10) var(--sp-6); border-radius: var(--r-screen);
  background: radial-gradient(120% 140% at 0% 0%, var(--prune) 0%, var(--prune-deep) 100%);
  color: var(--text-on-prune); box-shadow: var(--shadow-2);
}
.phare-libelle { margin: 0; font: var(--fw-semibold) var(--fs-body)/1.3 var(--sans); color: var(--text-on-prune-soft); }
.phare-montant {
  margin: var(--sp-2) 0 0; font: var(--fw-semibold) var(--fs-display)/var(--lh-display) var(--serif);
  letter-spacing: var(--ls-serif);
}
.phare-detail { margin: var(--sp-3) 0 0; font: var(--fw-regular) var(--fs-body-sm)/1.5 var(--sans); color: var(--text-on-prune-soft); }
.tendance {
  display: inline-flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; justify-content: center;
  margin: var(--sp-4) 0 0; padding: var(--sp-2) var(--sp-4); border-radius: var(--r-pill);
  background: rgba(255,255,255,.14); font: var(--fw-semibold) var(--fs-body-sm)/1.3 var(--sans);
}
.tendance-fleche { font-size: var(--fs-heading); }
.tendance-detail { font-weight: var(--fw-regular); font-size: var(--fs-caption); color: var(--text-on-prune-soft); }
.tendance-bonne { background: var(--wash-corail-strong); }
.tendance-mauvaise { background: rgba(255,255,255,.2); }
.tendance-neutre { background: rgba(255,255,255,.1); font-weight: var(--fw-regular); }

.cartes-kpi { display: grid; gap: var(--gap-inline); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.carte-kpi { background: var(--bg-sunken); border-radius: var(--r-tile); padding: var(--sp-4) var(--sp-5); min-width: 0; }
.carte-kpi-libelle { margin: 0; font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.carte-kpi-valeur {
  margin: var(--sp-2) 0 0; font: var(--fw-semibold) var(--fs-title-3)/1.05 var(--serif);
  letter-spacing: var(--ls-serif); color: var(--text-strong);
}
.carte-kpi-detail { margin: var(--sp-1) 0 0; font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.kpi-attention { background: var(--wash-corail); }
.kpi-attention .carte-kpi-valeur { color: var(--text-accent); }

/* Échelle uniforme (le viewBox fait 480 × 150) : plus d'étirement vertical,
   donc plus d'étiquettes déformées. Les tailles des étiquettes sont en unités
   du viewBox, calées sur la carte en paysage tablette (~1 030 px, soit × 2,15) :
   elles y rendent à ~15-16 px. */
.graphique { display: block; width: 100%; height: auto; margin-top: var(--sp-3); }
.graphique-base { stroke: var(--border-hairline); stroke-width: 1; }
.barre rect { fill: var(--wash-corail-strong); transition: fill var(--dur-2) var(--ease-out); }
.barre-courante rect { fill: var(--corail); }
.barre:hover rect { fill: var(--corail-ink); }
.barre-valeur { fill: var(--text-accent); font-size: 7.5px; font-weight: var(--fw-bold);
  font-family: var(--mono); }
.barre-mois { fill: var(--text-muted); font-size: 7px; font-family: var(--sans); }

.tableau-equipe { width: 100%; border-collapse: collapse; margin-top: var(--sp-3); }
.tableau-equipe th, .tableau-equipe td {
  padding: var(--sp-3) var(--sp-2); border-bottom: var(--stroke-hairline) solid var(--border-hairline);
  text-align: right;
  font: var(--fw-regular) var(--fs-body-sm)/1.4 var(--sans); color: var(--text-body);
}
.tableau-equipe thead th { font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); white-space: nowrap; }
.tableau-equipe th:first-child, .tableau-equipe td:first-child, .tableau-equipe tbody th {
  text-align: left; font-weight: var(--fw-semibold); color: var(--text-strong); }
.tableau-equipe tbody tr:last-child th, .tableau-equipe tbody tr:last-child td { border-bottom: 0; }
.ligne-attention td, .ligne-attention th { background: var(--wash-corail); }

.liste-alertes { list-style: none; margin: var(--sp-3) 0; padding: 0; display: grid; gap: var(--sp-2); }
.ligne-alerte {
  display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-field);
  background: var(--wash-corail); box-shadow: inset 0 0 0 1px var(--border-accent);
}
.ligne-alerte-texte { flex: 1 1 180px; min-width: 0; display: grid; gap: 2px; }
.ligne-alerte-nom { font: var(--fw-semibold) var(--fs-body-sm)/1.35 var(--sans); color: var(--text-strong); }
.ligne-alerte-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.ligne-alerte-stock { display: grid; justify-items: end; gap: 2px;
  font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
.ligne-alerte-stock b { font-family: var(--mono);
  font-size: var(--fs-num-sm); color: var(--text-accent); }

/* =============================================================================
   13. Stocks et produits
   ============================================================================= */
.stocks-filtres { display: grid; gap: var(--gap-inline); margin-bottom: var(--sp-4); }
.chips-categories { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--touch-min); padding: var(--sp-2) var(--sp-4);
  border: var(--stroke-hairline) solid var(--border-hairline); border-radius: var(--r-pill);
  background: var(--bg-card); color: var(--text-muted);
  font: var(--fw-semibold) var(--fs-body-sm)/1 var(--sans); cursor: pointer;
  transition: border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out),
              background var(--dur-2) var(--ease-out);
}
.chip:hover { border-color: var(--border-accent); color: var(--text-strong); }
.chip-active { background: var(--prune); border-color: transparent; color: var(--on-prune); }
.chip-compte { padding: 1px var(--sp-2); border-radius: var(--r-pill); background: var(--bg-sunken);
  color: var(--text-muted); font-family: var(--mono); font-size: var(--fs-caption); }
.chip-active .chip-compte { background: rgba(255,255,255,.18); color: var(--on-prune); }

.bascule-archives { display: flex; align-items: center; gap: var(--gap-inline);
  min-height: var(--touch-min); margin-bottom: var(--sp-4);
  font: var(--fw-regular) var(--fs-body-sm)/1.4 var(--sans); color: var(--text-muted); cursor: pointer; }
.bascule-archives input { width: 22px; height: 22px; accent-color: var(--corail-ink); }

.stocks-liste { display: grid; gap: var(--sp-8); }
.groupe-categorie { display: grid; gap: var(--sp-3); }
.groupe-categorie-titre {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-inline);
  margin: 0 0 var(--sp-3); font: var(--fw-semibold) var(--fs-title-3)/1.2 var(--serif);
  letter-spacing: var(--ls-serif); color: var(--text-strong);
}
.pastille-usage { padding: 3px var(--sp-3); border-radius: var(--r-pill);
  font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans); }
.usage-dosable { background: var(--wash-prune); color: var(--text-prune); }
.usage-stock { background: var(--wash-corail); color: var(--text-accent); }
.usage-inactive { background: var(--bg-sunken); color: var(--text-muted); }

.cartes-produits { display: grid; gap: var(--sp-2); }
.carte-produit {
  display: grid; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-card-sm);
  transition: border-color var(--dur-2) var(--ease-out);
}
.carte-produit:hover { border-color: var(--border-accent); }
.carte-produit-haut { display: flex; align-items: center; gap: var(--gap-inline); min-height: var(--touch-comfort); }
.carte-produit-texte { flex: 1; min-width: 0; display: grid; gap: 2px; }
.carte-produit-nom { font: var(--fw-semibold) var(--fs-body)/1.35 var(--sans); color: var(--text-strong); }
.carte-produit-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.carte-produit-stock { display: grid; justify-items: end; gap: 2px; white-space: nowrap; }
.carte-produit-stock b { font-family: var(--mono);
  font-size: var(--fs-num); font-weight: var(--fw-semibold); color: var(--text-strong); }
.carte-produit-seuil { font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); }
/* Alerte stock : lavis corail, pas un rouge d'erreur. */
.carte-produit.stock-bas { background: var(--wash-corail); border-color: var(--border-accent); }
.carte-produit.stock-bas .carte-produit-stock b { color: var(--text-accent); }
.carte-produit.archive { opacity: .6; }
.carte-produit-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2);
  padding-top: var(--sp-2); border-top: var(--stroke-hairline) solid var(--border-hairline); }
.carte-produit-actions .bouton { flex: 1 1 auto; min-height: var(--touch-comfort); }
.pastille-alerte {
  padding: 3px var(--sp-3); border-radius: var(--r-pill); white-space: nowrap;
  background: var(--btn-primary-bg); color: var(--btn-primary-fg);
  font: var(--fw-semibold) var(--fs-caption)/1.3 var(--sans);
}

.liste-categories { display: grid; gap: var(--sp-2); }
.ligne-categorie {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-inline);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-card-sm);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
}
.ligne-categorie.inactive { opacity: .6; }
/* Monter / descendre : côte à côte, pas empilés. Empilées, les deux flèches
   tombaient à 30 px de haut — sous le plancher absolu de 44 px de la charte. */
.ligne-categorie-rang { display: flex; gap: var(--sp-1); }
.bouton-rang {
  width: var(--touch-min); height: var(--touch-min); border-radius: var(--r-field);
  border: var(--stroke-hairline) solid var(--border-hairline);
  background: var(--bg-sunken); color: var(--text-muted); line-height: 1; cursor: pointer;
}
.bouton-rang:hover:not(:disabled) { border-color: var(--border-accent); color: var(--text-accent); }
.bouton-rang:disabled { opacity: .35; cursor: default; }
.ligne-categorie-texte { flex: 1 1 200px; min-width: 0; display: grid; gap: 2px; }
.ligne-categorie-nom { font: var(--fw-semibold) var(--fs-body)/1.35 var(--sans); color: var(--text-strong); }
.ligne-categorie-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.ligne-categorie-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.liste-livraisons { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.ligne-livraison {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-inline);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-card-sm);
  background: var(--bg-card); border: var(--stroke-hairline) solid var(--border-hairline);
}
.ligne-livraison-texte { flex: 1 1 180px; min-width: 0; display: grid; gap: 2px; }
.ligne-livraison-nom { font: var(--fw-semibold) var(--fs-body-sm)/1.35 var(--sans); color: var(--text-strong); }
.ligne-livraison-detail { font: var(--fw-regular) var(--fs-caption)/1.4 var(--sans); color: var(--text-muted); }
.ligne-livraison-quantite { font-family: var(--mono);
  font-size: var(--fs-num-sm); color: var(--text-prune); white-space: nowrap; }
.ligne-livraison-stock { font: var(--fw-regular) var(--fs-caption)/1.3 var(--sans); color: var(--text-muted); white-space: nowrap; }

/* =============================================================================
   14. Formulaires
   ============================================================================= */
.formulaire { display: grid; gap: var(--gap-stack); }
.champs-dosage { display: grid; gap: var(--gap-stack); }
.champ { display: grid; gap: 6px; }
.champ-libelle { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: baseline;
  font: var(--fw-semibold) var(--fs-body-sm)/1.3 var(--sans); color: var(--text-strong); }
.champ-aide { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--sans); color: var(--text-muted); }
.champ-boite {
  display: flex; align-items: center; gap: var(--sp-2); padding: 0 var(--sp-4);
  background: var(--bg-sunken); border: var(--stroke-hairline) solid var(--border-hairline);
  border-radius: var(--r-field);
  transition: border-color var(--dur-2) var(--ease-out);
}
.champ-boite:hover { border-color: var(--border-strong); }
.champ-boite:focus-within { border-color: transparent; outline: var(--stroke-focus) solid var(--focus-ring); outline-offset: 1px; }
.champ-saisie {
  flex: 1; min-width: 0; min-height: var(--touch-glove); border: 0; background: none;
  font: var(--fw-regular) var(--fs-body-lg)/1.4 var(--sans); color: var(--text-strong);
}
.champ-saisie:focus { outline: none; }
.champ-saisie::placeholder { color: var(--text-muted); }
.champ-unite { font-family: var(--mono);
  font-size: var(--fs-body-sm); color: var(--text-muted); flex: none; }
.stock-actuel {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-inline);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-field); background: var(--bg-sunken);
}
.stock-actuel b { font-family: var(--mono); font-size: var(--fs-num); }

/* =============================================================================
   15. Panneaux
   ============================================================================= */
.panneau-fond {
  position: fixed; inset: 0; z-index: 20; display: grid; place-items: end center;
  background: rgba(20,6,14,.5); padding: var(--sp-4);
}
.panneau {
  width: min(640px, 100%); max-height: 88vh; overflow: auto;
  background: var(--bg-card); border-radius: var(--r-screen) var(--r-screen) 0 0;
  padding: var(--pad-card); box-shadow: var(--shadow-3);
  display: grid; gap: var(--gap-stack);
}
.panneau-tete { display: flex; align-items: center; justify-content: space-between; gap: var(--gap-inline); }
.panneau-actions { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin-top: var(--sp-4); }
.panneau-actions .bouton { flex: 1 1 180px; }

/* =============================================================================
   16. Accessibilité : mouvement réduit
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important; animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  /* Le spinner et le point de la balance restent des indicateurs : ralentis,
     pas arrêtés — sans eux, « reconnexion » et « connectée » se ressemblent. */
  .spinner { animation-duration: 1.6s !important; animation-iteration-count: infinite !important; }
  .etat-balance::before { animation-duration: 2.4s !important; animation-iteration-count: infinite !important; }
}
