/* Front du POC retail.
   Tactile d'abord : toute cible cliquable fait au moins 48 px de haut, parce
   qu'on tape dessus avec un doigt, debout, parfois les mains occupees. */

:root {
  --fond: #fbfbfa;
  --carte: #fff;
  --trait: #d8d6d1;
  --texte: #1c1a17;
  --discret: #6b6660;
  --accent: #1f5f4f;
  --accent-clair: #e7f1ee;
  --alerte: #a8331f;
  --alerte-clair: #fbeae7;
  --ok: #1f5f4f;
  --rayon: 8px;
  --cible: 48px;
}
@media (prefers-color-scheme: dark) {
  :root {
    --fond: #171614; --carte: #201f1c; --trait: #3a3833; --texte: #ece9e3;
    --discret: #9b958c; --accent: #5fb89f; --accent-clair: #1d2e29;
    --alerte: #e98b76; --alerte-clair: #33201c;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--fond); color: var(--texte);
  -webkit-text-size-adjust: 100%;
}
h1 { font-size: 1.6rem; margin: 0 0 .25rem; }
h2 { font-size: 1.15rem; margin: 1.25rem 0 .5rem; }

/* ------------------------------------------------------------- connexion */
.plein {
  min-height: 100dvh; display: grid; place-items: center; padding: 1.5rem;
}
#form-connexion {
  width: 100%; max-width: 22rem; background: var(--carte);
  border: 1px solid var(--trait); border-radius: var(--rayon); padding: 1.5rem;
  display: grid; gap: .9rem;
}
.sous-titre { margin: 0 0 .5rem; color: var(--discret); }

/* ---------------------------------------------------------- page d'accueil
   Plus large que la carte de connexion (22 rem) parce qu'elle porte du texte a
   LIRE, pas des champs a remplir : une ligne de 22 rem casserait chaque phrase
   en quatre. Toutes les couleurs viennent des variables de theme, jamais d'une
   valeur litterale — un fond pose sans sa couleur de texte devient illisible en
   theme sombre. */
#accueil {
  width: 100%; max-width: 34rem; background: var(--carte); color: var(--texte);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: 1.75rem 1.5rem;
}
#accueil-editeur {
  margin: 0 0 .75rem; font-size: .8rem; font-weight: 600;
  letter-spacing: .28em; color: var(--accent);
}
/* Marqueur de pile d'essai : teinte d'alerte, fond ET couleur de texte poses
   ensemble (un fond sans sa couleur de texte devient illisible en theme sombre). */
.pile-essai {
  margin: .5rem 0 .75rem; padding: .5rem .7rem;
  background: var(--alerte-clair); color: var(--alerte);
  border: 1px solid var(--alerte); border-radius: var(--rayon);
  font-size: .85rem; font-weight: 600;
}
#accueil-baseline em { font-style: normal; font-weight: 600; }
#accueil-fonctions {
  margin: 1.25rem 0; padding: 0; list-style: none;
  display: grid; gap: .6rem;
}
#accueil-fonctions li {
  padding-left: .9rem; border-left: 3px solid var(--accent-clair);
}
#accueil-fonctions strong { color: var(--accent); }
/* Les deux gestes de l'accueil, cote a cote (#68, 2026-10-04) : empiles en
   pleine largeur sur telephone, en deux colonnes des qu'il y a la place. Une
   seule colonne quand le lien d'inscription est masque (`:has` absent = le
   bouton garde toute la largeur, comme avant). */
#accueil-actions { display: grid; gap: .6rem; }
@media (min-width: 30rem) {
  #accueil-actions:has(#lien-inscription:not([hidden])) { grid-template-columns: 1fr 1fr; }
}
#btn-accueil-connexion, #lien-inscription {
  width: 100%; min-height: var(--cible); font-size: 1.05rem; box-sizing: border-box;
}
#lien-inscription[hidden] { display: none; }
#accueil-redirection, #accueil-acces { margin: .75rem 0 0; font-size: .92rem; }
#accueil-pied {
  margin: 1.5rem 0 0; padding-top: .9rem; border-top: 1px solid var(--trait);
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-size: .8rem; color: var(--discret);
}

/* Ouvrir une caisse : le TEXTE explicatif reste en retrait, sous la liste. Le
   lien, lui, est remonte a cote du bouton de connexion (#68) : en retrait, un
   commercant sans compte ne le trouvait pas, telephone en main. */
#accueil-inscription {
  margin-top: 1.5rem; padding-top: 1.1rem;
  border-top: 1px solid var(--trait);
}
#accueil-inscription-titre { font-size: 1rem; margin: 0 0 .35rem; }
/* Un lien qui a la taille d'une cible tactile, sans la couleur d'un bouton
   primaire : c'est une action offerte, pas l'action attendue. */
.bouton-lien {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--cible); padding: 0 1.1rem;
  border: 1px solid var(--accent); border-radius: var(--rayon);
  background: var(--carte); color: var(--accent);
  text-decoration: none; font-weight: 600;
}
.bouton-lien:hover { background: var(--accent-clair); }

/* ---------------------------------------------------------------- entete */
#entete {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap;
  padding: 0 1rem; background: var(--carte); border-bottom: 1px solid var(--trait);
  position: sticky; top: 0; z-index: 5;
}
#entete nav { display: flex; gap: .25rem; }

/* Le menu est a l'EXTREME DROITE de l'en-tete, apres « Quitter » (#41). Un ecart
   franc et un trait les separent : sur tablette, un doigt qui vise ☰ ne doit pas
   tomber sur « Quitter » (et « Quitter » n'a pas de confirmation). */
.menu-zone {
  position: relative; display: flex; align-items: center;
  margin-left: 1.75rem; padding-left: 1.75rem;
  border-left: 1px solid var(--trait);
}

/* ---------------------------------------------------------------------------
 *  MENU DES ECRANS ADMINISTRATIFS
 *  Huit ecrans qu'on visite quelques fois par jour n'ont pas a occuper une ligne
 *  permanente au-dessus de l'ecran ou l'on passe la journee.
 * ------------------------------------------------------------------------ */
#btn-menu {
  min-height: var(--cible); min-width: var(--cible); border: 0;
  background: none; color: var(--texte); font-size: 1.35rem; cursor: pointer;
  line-height: 1;
}
#btn-menu:hover { background: var(--accent-clair); border-radius: var(--rayon); }
#menu-panneau {
  position: absolute; top: calc(100% + .2rem); right: 0; z-index: 30;
  max-width: calc(100vw - 1rem);
  display: flex; flex-direction: column; min-width: 14rem;
  /* Fond ET couleur de texte ensemble : la moitie d'une paire rend le panneau
     illisible des que le theme du systeme change. */
  background: var(--carte); color: var(--texte);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  padding: .3rem;
}
#menu-panneau .onglet {
  text-align: left; border-bottom: 0; border-radius: var(--rayon);
  padding: 0 .9rem;
}
#menu-panneau .onglet-groupe {
  min-height: var(--cible); padding: 0 .9rem; border: 0; background: none;
  color: var(--discret); font-size: 1rem; font-weight: 600; cursor: pointer;
  text-align: left; border-radius: var(--rayon);
}
#menu-panneau .onglet:hover,
#menu-panneau .onglet-groupe:hover { background: var(--accent-clair); color: var(--texte); }
#menu-panneau .onglet.actif,
#menu-panneau .onglet-groupe.actif { color: var(--texte); background: var(--accent-clair); }

/* Rangee d'onglets d'un groupe (#79, #78) : sous l'en-tete, au-dessus de l'ecran.
   Fond ET couleur de texte ensemble, pour le theme sombre. [hidden] doit gagner
   sur display:flex, sinon la rangee resterait affichee. */
.sous-nav {
  display: flex; gap: .25rem; flex-wrap: wrap;
  padding: 0 1rem; background: var(--carte); color: var(--texte);
  border-bottom: 1px solid var(--trait);
}
.sous-nav[hidden] { display: none; }
.reglage { margin: 1rem 0; }

.onglet {
  min-height: var(--cible); padding: 0 1.1rem; border: 0; background: none;
  color: var(--discret); font-size: 1rem; font-weight: 600; cursor: pointer;
  border-bottom: 3px solid transparent;
}
.onglet.actif { color: var(--texte); border-bottom-color: var(--accent); }
.entete-droite { display: flex; align-items: center; gap: .9rem; }
.pastille {
  display: inline-block; min-width: 1.4rem; padding: 0 .35rem;
  background: var(--alerte); color: #fff; border-radius: 999px;
  font-size: .78rem; text-align: center;
}

/* ----------------------------------------------------------------- vues */
main { padding: 1rem; max-width: 84rem; margin: 0 auto; }
.vue { display: none; }
.vue.active { display: block; }
.colonnes { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; align-items: start; }
@media (max-width: 860px) { .colonnes { grid-template-columns: 1fr; } }

.barre { display: flex; gap: .75rem; align-items: center; flex-wrap: wrap; margin-bottom: 1rem; }

/* --------------------------------------------------------- formulaires */
label { display: grid; gap: .35rem; font-weight: 600; font-size: .9rem; }
label.gros { font-size: 1rem; }
input[type=text], input[type=email], input[type=password] {
  min-height: var(--cible); padding: 0 .8rem; font-size: 1.05rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte); width: 100%;
}
label.gros input { font-size: 1.5rem; font-variant-numeric: tabular-nums; }

/* Champ article de la caisse (#41) : le geste principal de l'ecran. Pleine
   largeur de sa colonne, haut, gros caracteres. */
#scan {
  display: block; width: 100%; box-sizing: border-box;
  min-height: 4rem; padding: 0 1rem; font-size: 1.75rem;
  border: 2px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
#scan:focus-visible { border-color: var(--accent); }
.carte > label.gros[for="scan"] { font-size: 1.1rem; font-weight: 600; display: block; margin-bottom: .4rem; }
input:focus-visible, button:focus-visible {
  outline: 3px solid var(--accent); outline-offset: 1px;
}

button, .bouton-fichier {
  min-height: var(--cible); padding: 0 1.2rem; font-size: 1rem; font-weight: 600;
  border-radius: var(--rayon); border: 1px solid var(--trait); cursor: pointer;
  background: var(--carte); color: var(--texte);
  display: inline-flex; align-items: center; justify-content: center;
}
button.primaire, .bouton-fichier.primaire {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
button:disabled { opacity: .45; cursor: not-allowed; }
button.lien {
  border: 0; background: none; color: var(--discret); min-height: var(--cible);
  padding: 0; text-decoration: underline;
}
.actions { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: 1rem; }
.interrupteur { display: flex; flex-direction: row; align-items: center; gap: .5rem; font-weight: 500; }
.interrupteur input { width: 1.15rem; height: 1.15rem; }

/* -------------------------------------------------------------- tableaux */
table { width: 100%; border-collapse: collapse; background: var(--carte); }
th, td { text-align: left; padding: .6rem .7rem; border-bottom: 1px solid var(--trait); }
th { font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--discret); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tbody tr.cliquable { cursor: pointer; }
tbody tr.cliquable:hover { background: var(--accent-clair); }
tr.sous-objectif td { background: var(--alerte-clair); }

.total-bloc {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: .9rem .7rem; border-bottom: 2px solid var(--texte);
  font-size: 1.15rem;
}
.total-bloc strong { font-size: 1.7rem; font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- verdict */
.verdict { padding: .8rem 1rem; border-radius: var(--rayon); margin-bottom: 1rem; font-weight: 600; }
.verdict.ok { background: var(--accent-clair); color: var(--ok); }
.verdict.ecart { background: var(--alerte-clair); color: var(--alerte); }
.verdict ul { margin: .5rem 0 0; padding-left: 1.2rem; font-weight: 400; }

#relecture { margin-top: 1.5rem; border-top: 1px solid var(--trait); padding-top: 1rem; }
#relecture-photo {
  width: 100%; border: 1px solid var(--trait); border-radius: var(--rayon); background: var(--carte);
}
#camera { width: 100%; max-width: 22rem; border-radius: var(--rayon); margin-top: .75rem; }

#conseil {
  margin-top: 1.5rem; padding: 1rem 1.2rem; background: var(--carte);
  border: 1px solid var(--trait); border-left: 4px solid var(--accent);
  border-radius: var(--rayon);
}
#conseil-texte { font-size: 1.05rem; }

/* --------------------------------------------------------------- divers */
.erreur { color: var(--alerte); font-weight: 600; }
.ok { color: var(--ok); font-weight: 600; }
.aide, .discret { color: var(--discret); font-size: .875rem; }
.aide { max-width: 34rem; }
[hidden] { display: none !important; }

/* =====================================================================
   POS retail : grille de caisse, tuiles, pave numerique, dialogues.
   Ajoute a l'etape « vrai POS ». Tout reste tactile d'abord : aucune cible
   cliquable sous 48 px, et les tuiles montent a 96 px parce qu'on les touche
   vite et sans regarder.
   ===================================================================== */

.carte {
  background: var(--carte);
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  padding: 1rem;
}
.carte > h2:first-child { margin-top: 0; }

/* Trois zones : le ticket, la saisie, les tuiles. Le ticket reste a gauche
   parce que c'est ce que le client regarde. */
.caisse-grille {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1.1fr 0.85fr 1.15fr;
  align-items: start;
}
@media (max-width: 1240px) {
  .caisse-grille { grid-template-columns: 1fr 1fr; }
  .caisse-grille > .tuiles-zone { grid-column: 1 / -1; }
}
@media (max-width: 820px) {
  .caisse-grille { grid-template-columns: 1fr; }
}

.ticket-zone .total-bloc { margin-top: .5rem; }
button.gros { min-height: 60px; font-size: 1.1rem; flex: 1; }

/* Une quantite cliquable : c'est la correction la plus fréquente. */
td.modifiable {
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
td.modifiable:hover { background: var(--accent-clair); }

/* ------------------------------------------------------ pave numerique --- */
#pave { margin-top: 1rem; border-top: 1px solid var(--trait); padding-top: .9rem; }

/* ---------------------------------------------------------------------------
 *  MODES DU PAVE
 *  Le mode actif se voit, parce que taper 20 en croyant regler une quantite
 *  alors qu'on applique une remise est une erreur qu'aucun message ne rattrape
 *  apres l'encaissement.
 * ------------------------------------------------------------------------ */
.pave-modes { display: flex; gap: .3rem; margin-bottom: .6rem; }
.mode-pave {
  flex: 1; min-height: 2.4rem; cursor: pointer;
  background: var(--carte); color: var(--discret);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  font-size: 1rem; font-weight: 600;
}
.mode-pave.actif {
  background: var(--accent-clair); color: var(--texte);
  border-color: var(--accent);
}
#remise-motif-bloc { display: block; margin: .5rem 0 .2rem; }

/* La ligne sur laquelle agit le pave. Sans ce reperage, taper une quantite
   reviendrait a l'appliquer a une ligne devinee. */
tr.ligne-visee > td {
  background: var(--accent-clair); color: var(--texte);
}
tr.ligne-visee > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
/* Consigne client (#94) : sa propre ligne, sous l'article, hors prix et hors TVA. */
tr.ligne-consigne > td { font-size: 0.9em; color: var(--discret); }

/* Une remise s'ECRIT sur la ligne : un prix plus bas sans explication fait
   douter le client et ne se relit pas six mois plus tard. */
.etiquette-remise {
  display: inline-block; padding: 0 .35rem; border-radius: 999px;
  background: var(--alerte); color: #fff; font-size: .75rem; font-weight: 700;
}
.prix-barre { color: var(--discret); text-decoration: line-through; }
.pave-entete {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: .5rem; margin-bottom: .5rem; min-height: 1.5rem;
}
.pave-entete strong { font-size: 1.05rem; }
#pave-ecran {
  display: block; width: 100%;
  padding: .6rem .8rem; margin-bottom: .5rem;
  background: var(--fond); border: 1px solid var(--trait); border-radius: var(--rayon);
  font-size: 2rem; font-variant-numeric: tabular-nums; text-align: right;
  line-height: 1.2;
}
.pave-calcul {
  margin: 0 0 .6rem; padding: .5rem .7rem;
  background: var(--accent-clair); color: var(--accent);
  border-radius: var(--rayon); font-weight: 600;
  font-variant-numeric: tabular-nums;
}
/* Refus de touche : la MEME ligne que le calcul, en couleur d'alerte. Avaler une
   touche en silence a deja coute une pesee fausse (125 g lu 12 kg). */
.pave-calcul.pave-alerte {
  background: var(--alerte-clair); color: var(--alerte);
}
.pave-touches {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem;
}
.touche {
  min-height: 58px; font-size: 1.35rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.touche:active { background: var(--accent-clair); }
.pave-actions { display: flex; gap: .5rem; margin-top: .5rem; }
.pave-actions button { flex: 1; }

/* -------------------------------------------------------------- tuiles --- */
.grille {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: .6rem;
}
.tuile {
  min-height: 96px; padding: .7rem;
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
  gap: .15rem; text-align: left;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  cursor: pointer; overflow: hidden;
}
.tuile-nom {
  font-weight: 600; font-size: 1rem; line-height: 1.25;
  /* Un libelle long ne doit pas deformer la grille. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.tuile-prix { font-size: 1.2rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.tuile-sous { font-size: .78rem; opacity: .75; }

/* Categorie : la couleur vient de la base, posee en JS apres validation du
   format #rrggbb. Le texte est blanc (avec une ombre) ou noir (sans), choisi
   par contraste cote serveur -- le JS pose alors color et text-shadow. Le blanc
   reste la valeur de repli d'un catalogue garde en cache. */
.tuile-categorie {
  color: #fff; border-color: transparent;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
}
.tuile-categorie .tuile-sous { opacity: .9; }

.tuile-article { background: var(--carte); color: var(--texte); }
.tuile-article:hover { border-color: var(--accent); }
/* Un article au poids se distingue d'un coup d'oeil : il ouvre le pave au lieu
   de tomber directement au ticket. */
.tuile-poids {
  border-left: 5px solid var(--accent);
  background: var(--accent-clair);
}

/* ------------------------------------------------ ranger les tuiles --- */
/* Mode « ranger » de la grille et fenetre du Catalogue (db/53, web/ordre-tuiles.js).
   Chaque surface pose son fond ET sa couleur de texte ensemble (theme sombre). */
.rangement-aide { margin: .25rem 0 .5rem; }
.tuile-rangement {
  display: flex; flex-direction: column; gap: .25rem; padding: .25rem;
  border: 2px dashed var(--accent); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
.tuile-rangement .tuile { width: 100%; }
/* Un article ne s'ajoute pas au ticket pendant le rangement : seule la poignee agit.
   Une categorie reste cliquable, pour descendre ranger son contenu. */
.tuile-rangement .tuile-article { pointer-events: none; }
.rangement-barre { display: flex; gap: .25rem; justify-content: space-between; }
.poignee-ordre, .ordre-moins, .ordre-plus {
  min-width: 44px; min-height: 44px; font-size: 1.25rem; line-height: 1;
  user-select: none; -webkit-user-select: none;
}
/* Sans cela, un doigt sur la poignee fait defiler la page au lieu de glisser la tuile. */
.poignee-ordre { touch-action: none; cursor: grab; }
.en-deplacement { opacity: .6; outline: 3px solid var(--accent); }
.liste-ordre {
  list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
  gap: .35rem; max-height: 55vh; overflow: auto;
}
.ligne-ordre {
  display: flex; align-items: center; gap: .5rem; padding: .3rem .5rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
.ligne-ordre-nom { flex: 1; }
.dlg-ordre-corps { padding: 1.25rem; display: grid; gap: .9rem; min-width: min(520px, 90vw); }

/* ----------------------------------------------------------- catalogue --- */
.puce {
  display: inline-block; width: 1.1rem; height: 1.1rem;
  border-radius: 4px; border: 1px solid var(--trait);
}
td.actions-cellule { white-space: nowrap; }
td.actions-cellule button { margin-right: .6rem; }
button.lien.danger { color: var(--alerte); }

/* ----------------------------------------------------------- dialogues --- */
dialog {
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
  padding: 0; max-width: 30rem; width: calc(100% - 2rem);
}
dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog form { padding: 1.25rem; display: grid; gap: .9rem; }
dialog h2 { margin: 0; font-size: 1.2rem; }
dialog fieldset {
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: .7rem .9rem; display: grid; gap: .5rem;
}
dialog legend { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--discret); }
dialog select, dialog input[type=number], dialog input[type=color] {
  min-height: var(--cible); padding: 0 .6rem; font-size: 1.05rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte); width: 100%;
}
dialog input[type=color] { padding: .2rem; cursor: pointer; }
dialog .actions { margin-top: .25rem; }
dialog .actions button { flex: 1; }

/* ------------------------------------------------- roles et enrichissement --- */

/* Le role en vigueur, toujours visible : en demonstration, on doit pouvoir dire
   d'un coup d'oeil sous quelle identite on est en train de cliquer. */
.badge {
  padding: .2rem .6rem; border-radius: 999px;
  font-size: .75rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; border: 1px solid var(--trait);
}
.badge-gerant { background: var(--accent); color: #fff; border-color: var(--accent); }
.badge-caissier { background: var(--accent-clair); color: var(--accent); }
/* Articles crees en caisse en attente du gerant : une alerte, donc la couleur
   de la pastille des factures, et un bouton qui mene a la file. */
.badge-alerte { background: var(--alerte); color: #fff; border-color: var(--alerte); cursor: pointer; }

/* Catalogue vu par un caissier : la colonne des categories est masquee, la
   liste des articles reprend toute la largeur au lieu d'une demi-colonne. */
.colonnes.une-seule { grid-template-columns: 1fr; }
/* File de validation : separee du reste du catalogue, comme une alerte. */
#file-a-valider { border-left: 4px solid var(--alerte); padding-left: .8rem; margin-bottom: 1.2rem; }
#art-historique { margin: .6rem 0; }
#art-historique table { font-size: .85rem; }

/* Code-barres inconnu : la proposition de creation. Bordure accentuee, parce que
   c'est une invitation a agir, pas un message d'erreur. */
#article-inconnu {
  margin-top: .9rem; padding: .9rem 1rem;
  background: var(--accent-clair);
  border: 1px solid var(--accent); border-left-width: 5px;
  border-radius: var(--rayon);
}
#article-inconnu strong { display: block; font-size: 1.05rem; margin-bottom: .3rem; }
#inconnu-champs {
  display: grid; grid-template-columns: auto 1fr; gap: .25rem .8rem;
  margin: .6rem 0;
}
#inconnu-champs dt { font-size: .8rem; color: var(--discret); }
#inconnu-champs dd { margin: 0; font-weight: 600; }
#inconnu-source { margin: .5rem 0 0; font-size: .8rem; }

/* Code releve a l'inventaire, ou d'un article inactif (#60). Meme invitation a
   agir que le code inconnu. Chaque ligne porte son propre fond ET sa couleur de
   texte : un fond pose seul devient illisible en theme sombre. */
#a-traiter-scan {
  margin-top: .9rem; padding: .9rem 1rem;
  background: var(--accent-clair); color: var(--texte);
  border: 1px solid var(--accent); border-left-width: 5px;
  border-radius: var(--rayon);
}
#a-traiter-scan > strong { display: block; font-size: 1.05rem; margin-bottom: .3rem; }
.at-ligne {
  background: var(--carte); color: var(--texte);
  border: 1px solid var(--trait); border-radius: var(--rayon);
  padding: .7rem .9rem; margin: .6rem 0;
}
.at-ligne > p { margin: 0 0 .3rem; }
.at-ligne .actions { margin-top: .5rem; }
.at-zone input[type="search"] { width: 100%; min-height: var(--cible); margin-top: .5rem; }
.at-form { display: grid; gap: .5rem; margin-top: .6rem; max-width: 30rem; }
.at-form label { display: grid; gap: .2rem; }
.at-form input, .at-form select { min-height: var(--cible); }

/* Un champ verrouille doit SE VOIR verrouille : l'EAN vient de la douchette, on
   ne veut pas laisser croire qu'il est modifiable. */
input[readonly] {
  background: var(--fond); color: var(--discret); cursor: not-allowed;
}

/* ------------------------------------------- paiement et cloture --- */

/* L'etape de paiement. Le total domine l'ecran : c'est le dernier moment ou le
   caissier et le client regardent le meme chiffre. */
.paiement { padding: 1.5rem; text-align: center; }
.paiement-libelle { margin: 0; color: var(--discret); text-transform: uppercase;
  font-size: .78rem; letter-spacing: .06em; }
#paiement-total {
  display: block; font-size: 3rem; font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums; margin: .25rem 0 1rem;
}
/* Le montant en especes, si l'arrondi le change : lisible d'un coup d'oeil, sans
   rivaliser avec le total (c'est une precision, pas un second total). */
.paiement-especes { margin: -.5rem 0 1rem; font-size: 1.15rem; font-weight: 600;
  font-variant-numeric: tabular-nums; }
.paiement-choix {
  display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; margin-bottom: 1rem;
}
.moyen {
  min-height: 72px; font-size: 1.05rem; font-weight: 700;
  background: var(--accent); color: #fff; border-color: var(--accent);
}
.moyen:active { opacity: .85; }

/* Especes : ce que le client donne, ce qu'on lui rend (web/rendu-monnaie.js). Le RENDU est le
   chiffre a lire d'un coup d'oeil : gros, comme le total, avec sa couleur d'etat EN PLUS du
   texte (jamais la couleur seule). Boutons de montant hauts, pour un doigt sur ecran tactile. */
.especes-recu { text-align: center; }
/* Les regles `display:` ci-dessous et `.paiement-choix` l'emportent sur `hidden` : on le rend gagnant. */
.especes-recu[hidden], .paiement-choix[hidden], .rendu-banniere[hidden] { display: none; }
.recu-propositions {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; margin-bottom: 1rem;
}
.recu-propositions button { min-height: 64px; font-size: 1.1rem; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.recu-saisie { display: block; margin-bottom: .75rem; font-weight: 600; }
.recu-saisie input { display: block; width: 100%; margin-top: .25rem; font-size: 1.5rem;
  text-align: center; font-variant-numeric: tabular-nums; }
.recu-rendu { display: block; min-height: 3.2rem; margin: .5rem 0 1rem; font-size: 2rem;
  font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; }
.recu-rendu.recu-ok { color: var(--accent); }
.recu-rendu.recu-manque { color: var(--alerte); }
.recu-actions { display: grid; grid-template-columns: 1fr 2fr; gap: .6rem; }
.recu-actions button { min-height: 64px; font-size: 1.1rem; font-weight: 700; }

/* Le rendu apres l'encaissement : en grand, dans la vue caisse, jusqu'au ticket suivant. */
.rendu-banniere {
  display: block; margin: 0 0 1rem; padding: 1rem; text-align: center;
  background: var(--accent-clair); color: var(--texte);
  border: 2px solid var(--accent); border-radius: var(--rayon);
}
.rendu-banniere .rendu-titre { display: block; font-size: 2.6rem; font-weight: 800;
  line-height: 1.1; font-variant-numeric: tabular-nums; }
.rendu-banniere .rendu-detail { display: block; margin-top: .4rem; font-size: 1rem; }
.moyen[data-moyen="autre"] {
  background: var(--carte); color: var(--texte); border-color: var(--trait);
}

/* Le mode d'operation. Volontairement PLUS DISCRET que les moyens de paiement
   (pas de fond plein, hauteur moindre) : le geste principal de cet ecran reste
   l'encaissement, le mode n'est qu'un etat qu'on corrige a l'occasion. Mais il
   est toujours visible, parce qu'il est colle d'une vente a la suivante et
   qu'un oubli de bascule produit une ventilation de TVA fausse. */
.mode-operation { margin-bottom: .5rem; }
.mode {
  min-height: 52px; font-size: .95rem; font-weight: 600;
  background: var(--carte); color: var(--discret); border-color: var(--trait);
}
/* L'etat actif se lit sur aria-pressed, pas sur une classe : l'attribut porte
   deja l'information pour un lecteur d'ecran, une classe la dupliquerait. */
.mode[aria-pressed="true"] {
  background: var(--carte); color: var(--texte);
  border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent);
}
.mode:active { opacity: .85; }
/* Mode fixe du magasin (#74) : dit en toutes lettres a la place du choix. */
.mode-fixe {
  margin: 0 0 .5rem; padding: .6rem .8rem; font-weight: 600;
  background: var(--carte); color: var(--texte);
  border: 1px solid var(--accent); border-radius: var(--rayon);
}
.mode-taux {
  margin: 0 0 1rem; min-height: 1.2em;
  font-variant-numeric: tabular-nums; color: var(--discret);
}

/* Avertissement visible, pas dissimule en note de bas de page. */
.avertissement {
  max-width: none; padding: .8rem 1rem; border-radius: var(--rayon);
  background: var(--alerte-clair); border-left: 4px solid var(--alerte);
  color: var(--texte);
}
#z-empreinte { word-break: break-all; font-family: ui-monospace, monospace; font-size: .75rem; }
#detail-z { margin-top: 1.5rem; }
#table-clotures td:nth-child(6) { font-family: ui-monospace, monospace; font-size: .8rem; }

/* ------------------------------------- session de caisse et stock --- */

/* Bandeau de session : toujours visible pendant le service. Ce que la caissiere
   doit pouvoir lire sans reflechir, c'est ce qui devrait etre dans le tiroir. */
.bandeau {
  display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
  padding: .7rem 1rem; margin-bottom: 1rem;
  background: var(--accent-clair); color: var(--texte);
  border: 1px solid var(--accent); border-left: 5px solid var(--accent);
  border-radius: var(--rayon);
  font-variant-numeric: tabular-nums;
}
.bandeau button { margin-left: auto; min-height: 44px; }
.bandeau strong { font-weight: 700; }

#session-fermee { max-width: 30rem; margin: 2rem auto; text-align: center; }
#session-fermee form { display: grid; gap: 1rem; margin-top: 1rem; }
#session-fermee .gros input { font-size: 2rem; text-align: center; }

#resultat-fermeture { max-width: 44rem; margin: 1.5rem auto; }
#table-rapprochement td:last-child { font-weight: 700; }

/* Une etiquette en ligne dans une barre d'outils, pour le champ de date. */
label.inline {
  display: flex; flex-direction: row; align-items: center; gap: .5rem;
  font-weight: 600; font-size: .9rem;
}
label.inline input {
  min-height: var(--cible); padding: 0 .6rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte); font-size: 1rem; width: auto;
}

#extrait { margin-top: 1.5rem; }
#table-extrait { font-variant-numeric: tabular-nums; }

/* =====================================================================
   IMPRESSION — ticket de caisse et rapport Z
   ===================================================================== */

/* A l'ecran, le bloc d'impression n'existe pas. */
#impression { display: none; }

/* Zone de remboursement : le champ de quantite doit rester petit dans un
   tableau, contrairement aux champs de formulaire en pleine largeur. */
#remb-lignes input {
  width: 6.5rem; min-height: 40px; padding: 0 .4rem;
  text-align: right; font-variant-numeric: tabular-nums;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
#remb-lignes { margin-bottom: .5rem; }
.interrupteur span { font-weight: 400; }
#msg-caisse button { margin-left: .75rem; }

@media print {
  /*
     Tout dispraait sauf l'imprime. `body > *` cible les sections de premier
     niveau (entete, main, dialogues) : les masquer suffit, inutile de lutter
     avec chaque descendant.
  */
  body > * { display: none !important; }
  #impression { display: block !important; }

  /* Marges minimales : une imprimante thermique n'en a pas, et sur A4 une marge
     de 6 mm evite que le bord soit rogne. */
  @page { margin: 6mm; }

  html, body {
    background: #fff !important; color: #000 !important;
    margin: 0; padding: 0;
  }

  #impression {
    /* Monospace : c'est ce qui aligne les montants en colonne sur un ticket,
       comme le fait une imprimante de caisse. */
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    color: #000;
  }

  /* --- ticket de caisse : 72 mm, soit un rouleau 80 mm moins ses marges --- */
  #impression.imp-ticket { width: 72mm; font-size: 9pt; line-height: 1.35; }
  /* --- rapport Z : toute la largeur disponible --- */
  #impression.imp-z { width: 100%; font-size: 10pt; line-height: 1.5; }

  .imp-titre {
    text-align: center; font-weight: 700; font-size: 1.15em;
    text-transform: uppercase; letter-spacing: .05em;
  }
  .imp-centre { text-align: center; }
  .imp-section { font-weight: 700; margin-top: .3em; }

  /* Un filet de separation, dessine par une bordure plutot que par une rangee de
     tirets : le rendu est net quelle que soit la largeur du papier. */
  .imp-trait {
    border-top: 1px dashed #000;
    margin: 1.2mm 0; height: 0; overflow: hidden;
  }

  .imp-paire { display: flex; justify-content: space-between; gap: 2mm; }
  .imp-paire > span:last-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
  .imp-detail { font-size: .9em; }
  .imp-total { font-weight: 700; font-size: 1.25em; }

  .imp-empreinte { font-size: .7em; word-break: break-all; }

  /* --- inventaire (#67) : tableau pleine largeur, lignes jamais coupees --- */
  table.imp-inv { width: 100%; border-collapse: collapse; font-size: .9em; }
  table.imp-inv th, table.imp-inv td { padding: .6mm 1.5mm; border-bottom: 1px solid #999; text-align: left; }
  table.imp-inv th.num, table.imp-inv td.num { text-align: right; white-space: nowrap; }
  table.imp-inv tr { break-inside: avoid; }
  table.imp-inv thead { display: table-header-group; }
  table.imp-inv .imp-inv-categorie td { font-weight: 700; background: #eee; border-top: 1px solid #000; }
  table.imp-inv .imp-inv-total td { font-weight: 700; border-top: 1px solid #000; }
  table.imp-inv .imp-inv-general td { font-size: 1.1em; border-top: 2px solid #000; }

  /* --- etiquette de rayon (#45, #73) : Brother 62 mm, page fixee par etiquette-*.css ---
     Continu : 62 x 40 mm ; predecoupe : 62 x 29 mm. Le code-barres a une
     largeur FIXE en mm (pas en %) : c'est la taille du module qui decide si la
     douchette le lit. 113 modules (EAN-13 et ses marges) sur 34 mm = 0,30 mm,
     un peu plus de 90 % de la taille nominale ; en continu 37,3 mm = 100 %. */
  #impression.imp-etiquette {
    width: 62mm; padding: 1.5mm 2.5mm; box-sizing: border-box; overflow: hidden;
    font-family: system-ui, "Helvetica Neue", Arial, sans-serif; line-height: 1.15;
  }
  /* La taille de PAGE ne vit pas ici : elle vient de etiquette-continu.css ou
     etiquette-decoupe.css, accrochee le temps de l'impression (#73). Les pages
     nommees de la premiere version n'etaient pas honorees par la boite
     d'impression vers une vraie imprimante. Hauteur 0,5 mm SOUS celle de la
     page, et sans debord : un bloc exactement aussi haut que la page peut, par
     un arrondi sous-pixel, en ouvrir une seconde blanche (relecture de #73). */
  #impression.etq-continu { height: calc(40mm - .5mm); max-height: calc(40mm - .5mm); }
  #impression.etq-decoupe { height: calc(29mm - .5mm); max-height: calc(29mm - .5mm); }
  html:has(#etq-page), html:has(#etq-page) body { height: auto; overflow: hidden; }
  #impression.imp-etiquette #impression-contenu { height: 100%; }
  .etq {
    display: grid; height: 100%;
    grid-template-columns: 1fr auto; grid-template-rows: auto 1fr auto;
    column-gap: 2mm;
  }
  .etq-libelle {
    grid-column: 1 / 3; font-weight: 700; font-size: 9pt;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  }
  .etq-prix { align-self: center; font-size: 17pt; font-weight: 800; white-space: nowrap; }
  .etq-unite { font-size: 8pt; font-weight: 600; }
  .etq-code { align-self: end; text-align: center; }
  .etq-code svg { display: block; width: 34mm; height: 11mm; }
  .etq-continu .etq-code svg { width: 37.3mm; height: 18mm; }
  .etq-chiffres { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 7pt; letter-spacing: .4mm; }
  .etq-date { grid-column: 1 / 3; font-size: 6pt; }

  /* --- etiquette EN TRAVERS DU ROULEAU (#76), rouleau continu seulement ---
     Les carres gris vus par transparence sur l'etiquette sont le motif du support : ils
     courent le long du rouleau, "carre apres carre" (photo du 10/10, 18h49). Le texte
     doit COURIR EN TRAVERS de cette file, pas le long : les deux premiers essais (a plat,
     puis retourne de 180 degres) le laissaient parallele aux carres, des deux cotes.
     Le pilote met l'axe horizontal de la page le long du rouleau : le contenu est donc
     dessine en portrait (36,5 x 57 mm, soit le bloc moins ses marges : 62 - 2 x 2,5 et
     39,5 - 2 x 1,5) puis tourne autour de son centre pour remplir la page 62 x 40.
     La PAGE ne change pas (changer son orientation fait disparaitre le choix
     d'orientation de Chrome, voir etiquette-continu.css).
     --etq-angle donne le sens : -90deg ici ; 90deg donne le texte a l'envers (meme axe).
     Le decoupe (29 mm de haut) n'est PAS tourne : 26 mm utiles ne contiennent pas un
     code-barres de 34 mm. */
  #impression.etq-tourne #impression-contenu { position: relative; }
  #impression.etq-tourne .etq {
    --etq-angle: -90deg;
    position: absolute; left: 50%; top: 50%;
    width: var(--etq-largeur); height: 57mm;
    transform: translate(-50%, -50%) rotate(var(--etq-angle));
    grid-template-columns: 1fr; grid-template-rows: auto auto 1fr auto;
  }
  /* TAILLES DE L'ETIQUETTE TOURNEE (31/10/2026, apres l'essai d'Alain : « beaucoup de blanc »).
     LARGEUR DU BLOC : 33 mm, pas 36,5. Le long du rouleau l'imprimante ne peut pas imprimer
     les 3,03 premiers et derniers mm (media-bottom-margin de l'IPP) : la zone utile d'une
     etiquette de 40 mm est de 33,9 mm. A 36,5 mm le debut des lignes de texte tombait a
     37,5 mm sur 36,97 : rogne. Mesure sur l'apercu de Chromium a 300 dpi (le rendu du
     NAVIGATEUR, pas celui du pilote).
     Longueur du prix, chiffres les plus larges (8), mesuree sur l'apercu : 6 caracteres a 31 pt
     30,4 mm ; 7 a 26 pt 30,7 mm ; 8 a 23 pt 31,8 mm ; 9 a 20 pt 31,8 mm ; 10 a 17 pt 30,4 mm,
     pour un bloc de 33 mm. Le prix est en nowrap : un prix coupe vaudrait un prix
     faux, d'ou les classes etq-prix-l7 a etq-prix-l10 posees par imprimerEtiquette().
     Le libelle passe a 11 pt sur 3 lignes au plus. Le code gagne 2 mm de haut ; sa LONGUEUR est
     bornee par l'etiquette de 40 mm (un module de 5 points ferait 40,2 mm), pas sa hauteur.
     Hauteur du bloc (57 mm), ESTIMEE : 3 lignes de libelle 13,4 + prix 13,2 + code 22 + chiffres
     3,2 + date 2,5 = 54,3 mm ; « le kg » ajoute 3,2 mm. Verifie seulement sur l'apercu : avec un
     libelle de 3 lignes et « le kg », tout reste visible, la date comprise. */
  #impression.etq-tourne .etq-libelle { grid-column: 1; -webkit-line-clamp: 3; font-size: 11pt; }
  #impression.etq-tourne .etq-prix { align-self: start; font-size: 31pt; margin-top: 1mm; }
  #impression.etq-tourne .etq-prix.etq-prix-l7 { font-size: 26pt; }
  #impression.etq-tourne .etq-prix.etq-prix-l8 { font-size: 23pt; }
  #impression.etq-tourne .etq-prix.etq-prix-l9 { font-size: 20pt; }
  #impression.etq-tourne .etq-prix.etq-prix-l10 { font-size: 17pt; }
  #impression.etq-tourne .etq-chiffres { font-size: 8pt; }
  /* LE CODE-BARRES EN CONTINU : UN MODULE = 4 POINTS D'IMPRIMANTE, ENTIERS.
     Avant, le code tenait dans 34 mm pour 113 modules : 0,301 mm par module, soit 3,55
     points a 300 dpi. Un point ne se coupe pas : les barres sortaient a 3 ou 4 points
     (environ +/- 14 %), et la douchette ne lisait pas l'etiquette du POS alors qu'elle lisait
     celle de ql-print (essai d'Alain le 31/10/2026, photo des deux etiquettes). Cause
     SUPPOSEE, a confirmer par la douchette sur la prochaine impression.
     4 points = 25,4 mm x 4 / 300 = 0,3387 mm, soit 103 % de la taille nominale ; 3 points
     (0,254 mm) seraient sous la limite basse de la norme (80 % de la nominale, 0,264 mm).
     113 modules (11 de marge a gauche + 95 + 7 a droite) = 38,27 mm en EAN-13 ; 81 en EAN-8.
     Le SVG est plus large que le bloc de 33 mm : la marge negative le recentre, et les
     marges claires qui depassent sont du papier blanc de l'etiquette (40 mm), sans encre.
     La classe etq-ean13 ou etq-ean8 est posee par svgCodeBarres() (app.js). Le test de
     src/lib/etiquette.test.ts garde la valeur du module et le nombre de modules.
     Imprimer a 100 % : « Ajuster a la largeur de la page » change la taille du module. */
  #impression.etq-tourne { --etq-module: calc(25.4mm * 4 / 300); --etq-largeur: 33mm; }
  #impression.etq-tourne .etq-code svg { height: 22mm; }
  #impression.etq-tourne .etq-code svg.etq-ean13 {
    width: calc(113 * var(--etq-module));
    margin: 0 0 0 calc((var(--etq-largeur) - 113 * var(--etq-module)) / 2);
  }
  #impression.etq-tourne .etq-code svg.etq-ean8 {
    width: calc(81 * var(--etq-module));
    margin: 0 0 0 calc((var(--etq-largeur) - 81 * var(--etq-module)) / 2);
  }
  #impression.etq-tourne .etq-date { grid-column: 1; }

  /* --- etiquette de TEST (#76) : voir imprimerEtiquetteTest() dans app.js ---
     Le cadre est FIXE : il suit la PAGE que le navigateur imprime, pas le bloc de
     62 mm. C'est ce qui le rend utile : s'il deborde de la regle, la page est trop
     grande. #impression coupe tout ce qui depasse ses 62 mm (overflow hidden), le
     cadre fixe n'est pas coupe par lui. */
  .etq-test { position: relative; height: 100%; font-size: 7pt; line-height: 1.2; }
  .etq-test::before {
    content: ''; position: fixed; inset: 0; border: .4mm dashed #000; pointer-events: none;
  }
  .etq-test-titre { font-weight: 800; font-size: 9pt; }
  .etq-test-ligne { font-size: 7pt; }
  /* La regle est FIXE, comme le cadre : elle part du bord gauche de la PAGE, pas du
     bloc (qui a 2,5 mm de marge et couperait la graduation 60). */
  .etq-test-regle { position: fixed; left: 0; top: 13mm; width: 100vw; height: 8mm; border-top: .3mm solid #000; }
  .etq-test-trait { position: absolute; top: 0; border-left: .3mm solid #000; height: 1.5mm; font-size: 6pt; }
  .etq-test-long { height: 3mm; padding-left: .4mm; padding-top: 3mm; box-sizing: content-box; }
  .etq-test-pied { position: absolute; bottom: 0; font-size: 5pt; }
}

/* Reglage du format des etiquettes, dans la barre du catalogue. */
.etq-format-zone { display: inline-flex; align-items: center; gap: .4rem; }

/* Bandeau de reveil de la base : visible mais non bloquant. Il apparait en haut
   de la zone applicative pendant les ~15 s de sortie de veille du cluster. */
/* Magasin de formation (db/58) : bien visible, couleur d'alerte, sur tous les ecrans. */
.bandeau-formation {
  margin: 0 0 1rem; padding: .7rem 1rem; text-align: center;
  background: var(--alerte-clair); color: var(--texte); font-weight: 700; letter-spacing: .03em;
  border: 2px solid var(--alerte); border-left-width: 8px; border-radius: var(--rayon);
}
@media print { .bandeau-formation { display: none; } }

.bandeau-reveil {
  margin: 0 0 1rem; padding: .7rem 1rem;
  background: var(--alerte-clair); color: var(--texte);
  border: 1px solid var(--alerte); border-left: 5px solid var(--alerte);
  border-radius: var(--rayon); font-weight: 600;
}

/* Resultats de la recherche d'article par libelle. Une ligne = un article, son
   prix et un bouton d'action, assez large pour un doigt sur ecran tactile. */
.liste-resultats {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  max-height: 16rem;
  overflow-y: auto;
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  background: var(--carte);
  color: var(--texte);
}
.liste-resultats li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--trait);
}
.liste-resultats li:last-child { border-bottom: none; }
.liste-resultats li strong { flex: 0 1 auto; }
.liste-resultats li span { flex: 1 1 auto; }
.liste-resultats li button { flex: 0 0 auto; min-height: var(--cible); }

/* Pile et version servies, dans l'en-tete. Discret par defaut, voyant quand le
   front et l'API ne sont pas a la meme version — ce cas-la doit se remarquer. */
.badge-pile {
  font-size: 0.8rem;
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--trait);
  border-radius: var(--rayon);
  color: var(--discret);
  cursor: help;
}
.badge-pile.desaccord {
  color: var(--alerte);
  border-color: var(--alerte);
}

/* Une ligne d'inventaire dont le compte ne tombe pas sur le stock theorique.
   Teintee, PAS rouge vif : un ecart est le resultat NORMAL d'un inventaire, pas
   une anomalie. Ce qui doit sauter aux yeux, c'est sa valeur en euros, et c'est
   le tri de la table qui s'en charge (les plus gros ecarts en premier). */
tr.ligne-ecart { background: var(--alerte-clair); }
tr.ligne-ecart td { font-weight: 500; }

/* Avertissement de securite des comptes (#58) : meme teinte que la pile
   d'essai, fond ET couleur de texte poses ensemble pour le theme sombre. */
.avertissement {
  padding: .5rem .7rem; max-width: 46rem;
  background: var(--alerte-clair); color: var(--alerte);
  border: 1px solid var(--alerte); border-radius: var(--rayon);
  font-weight: 600;
}
#securite-comptes .colonnes { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Consigne a poser : un groupe par format (web/consigne-groupes.js). */
.groupe-consigne { margin-top: 1rem; }
.groupe-consigne h3 { margin: 0 0 .4rem; }
.groupe-consigne ul { list-style: none; padding: 0; margin: .5rem 0 0; }
.groupe-consigne li { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; padding: .25rem 0; }
