/* ---------- les deux thèmes ----------
   Toute la couleur de l'application tient dans ce bloc et dans son jumeau juste
   en dessous. Une règle qui écrit une couleur en dur est une règle qui ne saura
   pas changer de thème : il n'y en a pas une seule.

   Trois choses valent d'être sues avant d'y toucher.

   1. Les couleurs d'état sont données AUSSI en composantes (--x-rgb), pour qu'une
      règle puisse en tirer un lavis à l'opacité qu'elle veut :
      rgba(var(--retard-rgb),.16). Sans ça il faudrait un jeton par opacité.

   2. Deux jetons se ressemblent et ne font pas le même travail.
        --hair  est le REFLET du haut d'une surface, « inset 0 1px 0 ». Il imite
                une lumière qui tombe d'en haut : blanc sur du sombre, blanc aussi
                sur du clair, où il ne se voit presque pas.
        --trait est un vrai FILET entre deux choses. Lui s'inverse : clair sur du
                sombre, sombre sur du clair.
      Les confondre pose une barre brune au-dessus de chaque carte en crème.

   3. Les ombres portées ne s'inversent pas, elles s'allègent. Elles sont donc
      nommées une par une et non calculées : l'opacité fait partie du thème. */
:root{
  --bg:#0D0C0B; --page:#141210; --surface:#1B1815; --surface-2:#211D19; --surface-3:#2C2621;
  --dock:rgba(38,33,27,.82);
  --hair:rgba(255,255,255,.13);
  --trait:rgba(255,255,255,.13);
  --lift-rgb:255,255,255;
  --ombre-rgb:0,0,0;
  --voile-fond:rgba(6,5,4,.66);
  --txt:#F6F2EB; --txt-2:#A99F92; --txt-3:#8A8074;
  --accent:#E8A33D; --accent-rgb:232,163,61; --accent-soft:rgba(232,163,61,.15);
  --accent-ink:#231803;
  --accent-txt:#F7D9A6;
  --fait:#4FC08A; --fait-rgb:79,192,138; --fait-soft:rgba(79,192,138,.14);
  --fait-ink:#08301F; --fait-txt:#9BDCBE;
  --retard:#F2626B; --retard-rgb:242,98,107; --retard-soft:rgba(242,98,107,.14);
  --retard-ink:#2a0a0d; --retard-txt:#F7A9AF;
  --o-dock:0 10px 34px -8px rgba(0,0,0,.85);
  --o-feuille:0 -20px 50px -12px rgba(0,0,0,.85);
  --o-av:0 2px 8px -2px rgba(0,0,0,.6);
  --r-out:26px; --r-md:21px; --r-in:18px; --r-tile:15px;
  --ease:cubic-bezier(.16,1,.3,1);
  --sys:-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,system-ui,sans-serif;
  --haut:env(safe-area-inset-top,0px);
  --bas:env(safe-area-inset-bottom,0px);
  /* LA HAUTEUR DU DOCK, NOMMÉE UNE FOIS. Une barre d'action se pose juste
     au-dessus de lui, et elle a besoin de savoir où il commence. Recopier le
     calcul à chaque endroit qui en a besoin, c'est se condamner à ce qu'un des
     endroits ne suive pas le jour où le dock change de hauteur, et à ce que la
     barre d'action passe dessous sans que personne ne s'en aperçoive avant un
     téléphone. 6 + 44 + 8, plus la zone sûre du bas. */
  --dock-h:calc(var(--bas) + 58px);
  color-scheme:dark;
}

/* ---------- crème ----------
   Le même fournil, vu de jour : la farine, le papier, la mie. L'ambre ne bouge
   pas d'un ton, c'est la marque. Ce qui change de NATURE et pas seulement de
   valeur : une carte n'est plus plus CLAIRE que la page, elle est plus BLANCHE ;
   le vert et le rouge s'assombrissent, parce qu'ils doivent maintenant se lire
   sur du clair ; le voile qui relevait une surface devient une ombre ; les ombres
   portées perdent les trois quarts de leur force.
   Rien d'autre n'est touché : ni une taille, ni un rayon, ni un geste. */
:root[data-theme="creme"]{
  --bg:#E9DFCC; --page:#F6F0E3; --surface:#FFFDF7; --surface-2:#F1E9D9; --surface-3:#E6DBC5;
  --dock:rgba(255,253,247,.86);
  --hair:rgba(255,255,255,.8);
  --trait:rgba(58,42,20,.14);
  --lift-rgb:58,42,20;
  --ombre-rgb:74,56,30;
  --voile-fond:rgba(46,34,16,.4);
  --txt:#241C12; --txt-2:#6B5D49; --txt-3:#74664F;
  --accent:#E8A33D; --accent-rgb:232,163,61; --accent-soft:rgba(232,163,61,.26);
  --accent-ink:#231803;
  --accent-txt:#8A5A0B;
  --fait:#2F9E6B; --fait-rgb:47,158,107; --fait-soft:rgba(47,158,107,.15);
  --fait-ink:#FFFFFF; --fait-txt:#1B7A4F;
  --retard:#D0343F; --retard-rgb:208,52,63; --retard-soft:rgba(208,52,63,.13);
  --retard-ink:#FFF4F3; --retard-txt:#B02A35;
  --o-dock:0 8px 26px -10px rgba(74,56,30,.28);
  --o-feuille:0 -16px 44px -16px rgba(74,56,30,.24);
  --o-av:0 2px 8px -3px rgba(74,56,30,.24);
  color-scheme:light;
}

/* ---------- le socle ---------- */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;background:var(--bg)}
body{
  font-family:var(--sys);
  color:var(--txt);
  font-size:16px;
  line-height:1.4;
  -webkit-font-smoothing:antialiased;
  overscroll-behavior-y:none;
}
#app{min-height:100dvh;background:var(--page)}

/* ---------- la coquille ---------- */
#app{display:flex;flex-direction:column;min-height:100dvh}
.ecran{flex:1;padding:0 16px 96px;overflow-y:auto;-webkit-overflow-scrolling:touch}

.barre{
  position:sticky;top:0;z-index:20;
  padding:calc(var(--haut) + 10px) 16px 10px;
  background:var(--page);
  border-bottom:1px solid var(--trait);
}
/* ---------- le sélecteur de jour ----------
   Trois gestes : la flèche gauche recule d'un jour, la flèche droite avance
   d'un jour, et le cadre du milieu ouvre le calendrier natif du téléphone.
   Ce cadre n'est pas un bouton : il enveloppe un vrai <input type="date">,
   rendu invisible (opacity, jamais display ni visibility, pour qu'il reste
   au clavier et au doigt) et posé en pleine grandeur par dessus la phrase en
   toutes lettres. Le natif est accessible et traduit, un calendrier maison
   ne l'aurait pas été à si peu de lignes. */
.rang-jour{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.jour-fleche{
  flex:none;min-height:44px;min-width:44px;
  display:flex;align-items:center;justify-content:center;
  background:var(--surface);border:none;border-radius:var(--r-tile);
  color:var(--txt-2);cursor:pointer;
  box-shadow:inset 0 1px 0 var(--hair);
  transition:transform .14s var(--ease);
}
.jour-fleche:active{transform:scale(.94)}
.jour-fleche .ico{width:17px;height:17px}

.barre .jour{
  position:relative;flex:1 1 150px;min-width:130px;min-height:44px;
  display:flex;align-items:center;justify-content:center;gap:6px;
  padding:0 10px;
  background:var(--surface);border-radius:var(--r-tile);
  box-shadow:inset 0 1px 0 var(--hair);
  cursor:pointer;
}
.barre .jour .jour-texte{color:var(--txt);font-size:13px;font-weight:700;letter-spacing:.02em;white-space:nowrap}
.barre .jour .ico{flex:none;width:14px;height:14px;color:var(--txt-3)}
/* :has() retrouve le focus posé sur le champ natif, invisible mais bien là,
   pour le montrer sur le cadre qui l'entoure : sans lui, personne au clavier
   ne verrait jamais où il se trouve. */
.barre .jour:has(.jour-natif:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.jour-natif{position:absolute;inset:0;width:100%;height:100%;opacity:0;border:none;margin:0;padding:0;cursor:pointer}

.jour-auj{
  flex:none;min-height:44px;padding:0 14px;
  background:var(--surface-2);border:none;border-radius:var(--r-tile);
  color:var(--txt-2);font:inherit;font-size:12px;font-weight:700;letter-spacing:.02em;
  cursor:pointer;
  transition:transform .14s var(--ease);
}
.jour-auj:active{transform:scale(.96)}

.barre .titre{font-size:26px;font-weight:700;letter-spacing:-.02em;margin-top:8px}

.qui-je-suis{
  display:flex;align-items:center;gap:8px;
  margin-top:10px;padding:8px 12px;min-height:44px;
  background:var(--surface);border:none;border-radius:var(--r-tile);
  box-shadow:inset 0 1px 0 var(--hair);
  color:var(--txt);font:inherit;font-size:14px;text-align:left;cursor:pointer;
  transition:transform .14s var(--ease);
}
.qui-je-suis:active{transform:scale(.98)}
.qui-je-suis .role{color:var(--txt-3);font-size:12px}
.qui-je-suis .nom{font-weight:600}
.qui-je-suis .ico{width:16px;height:16px;margin-left:auto;color:var(--txt-3)}

/* ---------- le dock ----------
   Pas de backdrop-filter. Un flou d'arrière-plan sur une barre fixe piège les
   éléments fixes qu'elle contient à sa propre taille : leçon de La Ferme, quatre
   heures perdues. Un fond opaque fait le même travail sans le piège. */
.dock{
  position:fixed;left:0;right:0;bottom:0;z-index:30;
  display:flex;justify-content:space-around;
  padding:6px 8px calc(var(--bas) + 8px);
  background:var(--surface);
  border-top:1px solid var(--trait);
  box-shadow:var(--o-dock);
}
.onglet{
  flex:1;min-height:44px;min-width:44px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  background:none;border:none;border-radius:var(--r-tile);
  color:var(--txt-3);font:inherit;cursor:pointer;
  transition:color .14s var(--ease),background .14s var(--ease);
}
.onglet .ico{width:22px;height:22px}
.onglet .libelle{font-size:11px;font-weight:600;letter-spacing:.01em}
.onglet.actif{color:var(--accent);background:var(--accent-soft)}

/* ---------- la feuille qui monte du bas ---------- */
.voile{position:fixed;inset:0;z-index:40;background:var(--voile-fond);border:none;padding:0}
.feuille{
  position:fixed;left:0;right:0;bottom:0;z-index:41;
  max-height:80dvh;overflow-y:auto;
  padding:10px 16px calc(var(--bas) + 20px);
  background:var(--surface);
  border-radius:var(--r-out) var(--r-out) 0 0;
  box-shadow:var(--o-feuille),inset 0 1px 0 var(--hair);
  animation:monte .3s var(--ease);
}
@keyframes monte{from{transform:translateY(100%)}to{transform:translateY(0)}}
.feuille .poignee{width:38px;height:4px;border-radius:2px;background:var(--trait);margin:0 auto 14px}
/* La mention qui dit que ce sélecteur est un outil de démonstration, pas un
   morceau de l'application finie. Elle doit se voir tout de suite, avant même
   la première identité de la liste, pas se fondre dans le reste. */
.feuille .mention-demo{
  margin:0 0 14px;padding:10px 12px;
  background:var(--accent-soft);border-radius:var(--r-in);
  color:var(--txt-2);font-size:13px;line-height:1.45;
}
.feuille .intertitre{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--txt-3);margin:14px 0 6px}
.choix{
  display:flex;align-items:center;gap:10px;width:100%;min-height:48px;
  padding:10px 12px;margin-bottom:4px;
  background:var(--surface-2);border:none;border-radius:var(--r-in);
  color:var(--txt);font:inherit;font-size:15px;text-align:left;cursor:pointer;
}
.choix.actif{background:var(--accent-soft);color:var(--accent-txt)}
.choix .ico{width:18px;height:18px;color:var(--txt-3)}

/* ---------- les boutons ---------- */
.bouton{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:48px;padding:0 20px;
  border:none;border-radius:var(--r-in);
  font:inherit;font-size:16px;font-weight:600;cursor:pointer;
  transition:transform .14s var(--ease),opacity .14s var(--ease);
}
.bouton:active{transform:scale(.97)}
.bouton[disabled]{opacity:.45;cursor:default;transform:none}
.bouton.fort{background:var(--accent);color:var(--accent-ink);box-shadow:var(--o-av)}
.bouton.doux{background:var(--surface-2);color:var(--txt);box-shadow:inset 0 1px 0 var(--hair)}
.bouton .ico{width:18px;height:18px}

/* ---------- les états ---------- */
.pastille{
  display:inline-flex;align-items:center;gap:5px;
  padding:3px 9px;border-radius:999px;
  font-size:11px;font-weight:700;letter-spacing:.02em;white-space:nowrap;
}
.pastille .ico{width:12px;height:12px}
.pastille.envoye{background:var(--fait-soft);color:var(--fait-txt)}
.pastille.en-cours{background:var(--accent-soft);color:var(--accent-txt)}
.pastille.pas-ouvert{background:var(--retard-soft);color:var(--retard-txt)}

/* ---------- l'état vide ---------- */
.vide{padding:48px 24px;text-align:center;color:var(--txt-3)}
.vide .ico{width:40px;height:40px;margin-bottom:12px;opacity:.5}
.vide .quoi{font-size:17px;font-weight:600;color:var(--txt-2);margin-bottom:6px}
.vide .pourquoi{font-size:14px;line-height:1.5;max-width:30ch;margin:0 auto}

/* ---------- la liste de saisie ---------- */
.etat-saisie{padding:14px 0 2px}

.filtre{
  position:sticky;top:0;z-index:10;
  display:flex;align-items:center;gap:8px;
  margin:10px 0;padding:0 12px;min-height:44px;
  background:var(--surface);border-radius:var(--r-in);
  box-shadow:inset 0 1px 0 var(--hair);
}
.filtre .ico{flex:none;width:17px;height:17px;color:var(--txt-3)}
.filtre input{
  flex:1;min-width:0;height:44px;
  background:none;border:none;outline:none;
  color:var(--txt);font:inherit;font-size:15px;
}

.liste-saisie{background:var(--surface);border-radius:var(--r-md);overflow:hidden}
.ligne-saisie{
  display:flex;align-items:center;gap:12px;
  min-height:52px;padding:6px 12px;
  border-bottom:1px solid var(--trait);
}
.ligne-saisie:last-child{border-bottom:none}
.ligne-saisie.cachee{display:none}
.ligne-saisie .nom{flex:1;min-width:0;font-size:14px;font-weight:600;letter-spacing:.01em}
.ligne-saisie .nombre{
  flex:none;width:72px;height:40px;
  background:var(--surface-2);
  border:1px solid var(--trait);border-radius:var(--r-tile);
  color:var(--txt);font:inherit;font-size:17px;font-weight:700;
  text-align:center;font-variant-numeric:tabular-nums;
}
.ligne-saisie .nombre:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.ligne-saisie .nombre[readonly]{background:transparent;border-color:transparent;color:var(--txt-2)}

/* Une ligne que la porte a refusé d'enregistrer. Elle ne doit surtout pas avoir
   l'air normale : le chiffre affiché n'est pas celui qui est rangé. */
.ligne-saisie.pas-enregistree{background:var(--retard-soft)}
.ligne-saisie.pas-enregistree .nombre{border-color:var(--retard);color:var(--retard-txt)}
.ligne-saisie.pas-enregistree .nom::after{
  content:" pas enregistré";
  color:var(--retard-txt);font-size:11px;font-weight:700;letter-spacing:.02em;
}

.pied{padding:20px 0 8px;text-align:center}
.pied .bouton{width:100%}
.pied .note{margin:10px 0 0;font-size:13px;line-height:1.45;color:var(--txt-3)}
/* Un envoi qui n'est pas passé. La note grise pâle ne suffirait pas : c'est
   justement le message que personne ne doit rater. */
.pied .note.echec{color:var(--retard-txt);font-weight:600}
/* Une note vide ne prend pas de place : le refus d'export n'a rien à dire tant
   qu'il n'y a rien à refuser, et une ligne blanche sous les boutons se
   remarquerait tous les jours pour un cas qui n'arrive presque jamais. */
.pied .note:empty{display:none}

/* LA PAIRE DE BOUTONS. Côte à côte quand la place le permet, l'un sous l'autre
   sur un téléphone : « Imprimer ou enregistrer en PDF » ne tient pas en demi
   largeur, et un libellé coupé au milieu vaut moins que deux lignes. */
.pied .paire{display:flex;gap:10px;flex-wrap:wrap}
.pied .paire .bouton{flex:1 1 210px;width:auto}

/* ---------- la vue consolidée ---------- */
.rang-etats{display:flex;gap:14px;overflow-x:auto;padding:14px 0 6px}
.etat-marche{flex:none;display:flex;flex-direction:column;align-items:flex-start;gap:5px}
.etat-marche .ou{font-size:12px;font-weight:600;color:var(--txt-2)}

.tableau-consolide{
  margin-top:8px;overflow-x:auto;
  background:var(--surface);border-radius:var(--r-md);
}
.tableau-consolide table{width:100%;border-collapse:collapse;font-size:13px}
.tableau-consolide th,.tableau-consolide td{
  padding:9px 10px;text-align:right;white-space:nowrap;
  border-bottom:1px solid var(--trait);
}
.tableau-consolide tbody tr:last-child td{border-bottom:none}
.tableau-consolide th{
  font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--txt-3);
}
/* La première colonne reste visible quand on défile de côté : sans ça, à la
   troisième colonne on ne sait plus de quel produit on parle. */
.tableau-consolide .produit{
  position:sticky;left:0;z-index:1;
  text-align:left;font-weight:600;background:var(--surface);
}
.tableau-consolide thead .produit{z-index:2}
.tableau-consolide .nombre{font-variant-numeric:tabular-nums;font-weight:600}
.tableau-consolide .nombre.rien{color:var(--txt-3)}

.note{margin:14px 0 0;font-size:13px;line-height:1.5;color:var(--txt-3)}

/* ---------- la feuille de production, à l'écran ---------- */
.choix-famille{display:flex;gap:8px;overflow-x:auto;padding:14px 0 4px}
.onglet-famille{
  flex:none;min-height:38px;padding:0 14px;
  background:var(--surface-2);border:none;border-radius:var(--r-tile);
  color:var(--txt-2);font:inherit;font-size:12px;font-weight:700;letter-spacing:.05em;
  cursor:pointer;
}
.onglet-famille.actif{background:var(--accent-soft);color:var(--accent-txt)}
.onglet-famille.alerte{background:var(--retard-soft);color:var(--retard-txt)}
.onglet-famille .ico{width:13px;height:13px;margin-right:5px;vertical-align:-2px}
.avertissement{
  margin:0 0 14px;padding:10px 12px;
  background:var(--retard-soft);border-radius:var(--r-in);
  font-size:13px;line-height:1.45;color:var(--retard-txt);text-align:left;
}

.feuille-prod{
  margin-top:10px;padding:16px 12px;overflow-x:auto;
  background:var(--surface);border-radius:var(--r-md);
  box-shadow:inset 0 1px 0 var(--hair);
}
.feuille-prod .tete{text-align:center;margin-bottom:14px}
.feuille-prod .quand{font-size:13px;color:var(--txt-2)}
.feuille-prod .famille{font-size:20px;font-weight:700;letter-spacing:.06em;margin-top:2px}

.feuille-prod table{width:100%;border-collapse:collapse;font-size:13px}
.feuille-prod th,.feuille-prod td{
  padding:7px 8px;white-space:nowrap;
  border-bottom:1px solid var(--trait);
}
.feuille-prod th{
  font-size:10px;font-weight:700;letter-spacing:.06em;
  color:var(--txt-3);text-align:center;
}
.feuille-prod td.produit{text-align:right;font-weight:600}
.feuille-prod td.nombre{text-align:left;font-variant-numeric:tabular-nums}
.feuille-prod td.total{font-weight:700;color:var(--accent-txt)}
.feuille-prod tbody tr:last-child td{border-bottom:none}

.rien-a-produire{padding:24px 0;text-align:center;font-size:14px;color:var(--txt-3)}

/* Une colonne qui ne compte pas dans le total, et la raison de l'écart. */
.feuille-prod th.hors-total{color:var(--txt-3)}
.note-hors-total{margin:12px 0 0;font-size:12px;line-height:1.45;color:var(--txt-3);text-align:left}

/* CE QUI MANQUE, SANS FERMER LA SORTIE.
   Ambre et non rouge : ce n'est pas une feuille fausse, c'est une journée
   incomplète, et ça arrive tous les matins. Le bloc vit DANS la feuille, sous
   le tableau, parce qu'il part à l'imprimante avec elle. */
.avertissements{
  margin:14px 0 0;padding:12px 14px;
  background:var(--accent-soft);border-radius:var(--r-in);
  color:var(--accent-txt);text-align:left;
}
.avertissements .quoi{font-size:13px;font-weight:700;margin-bottom:7px}
.avertissements ul{margin:0;padding-left:20px;font-size:13px;line-height:1.55}
.avertissements li{margin-bottom:5px}
.avertissements li:last-child{margin-bottom:0}

/* D19 : les problèmes se voient, et ils ferment le bouton d'impression. */
.problemes{
  margin-top:14px;padding:14px;
  background:var(--retard-soft);border-radius:var(--r-md);
  color:var(--retard-txt);
}
.problemes .quoi{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:700;margin-bottom:10px}
.problemes .ico{width:18px;height:18px;flex:none}
.problemes ul{margin:0;padding-left:20px;font-size:13px;line-height:1.55}
.problemes li{margin-bottom:5px}
.problemes .pourquoi{margin:10px 0 0;font-size:13px;line-height:1.5}

/* =====================================================================
   LE VOCABULAIRE DE LA TRANCHE 2

   Les listes de commandes, la prise de commande au comptoir et les quatre
   sections de réglages sont écrites contre les classes qui suivent, et elles
   n'en inventent aucune. Le contrat est écrit noir sur blanc dans
   docs/etudes/2026-09-19-vocabulaire-des-ecrans.md.

   Aucune couleur en dur ici non plus : tout passe par les jetons des deux
   thèmes, donc tout change de thème sans qu'on y revienne.
   ===================================================================== */

/* ---------- le bandeau : ce qu'il faut savoir avant de lire l'écran ----------
   Trois tons, et ils ne veulent pas dire la même chose. `info` renseigne,
   `alerte` prévient d'un risque, `fait` confirme quelque chose qui vient
   d'arriver. Ils empruntent les mêmes trois couleurs que les pastilles d'état,
   pour qu'un ambre veuille dire partout la même chose dans l'application. */
.bandeau{
  display:flex;align-items:flex-start;gap:10px;
  margin:14px 0;padding:12px 14px;
  border-radius:var(--r-in);
  font-size:13px;line-height:1.5;text-align:left;
}
.bandeau .ico{flex:none;width:18px;height:18px;margin-top:1px}
.bandeau .quoi{font-weight:700;margin-bottom:3px}
.bandeau .pourquoi{opacity:.92}
/* Ce bandeau-là vit dans la coquille, entre la barre et l'écran, et non dans
   un écran : il doit donc poser lui-même ses marges de côté, que `.ecran`
   donne à tout ce qu'elle contient. */
.bandeau.graine-perimee{margin:12px 16px 0}
.bandeau.info{background:var(--surface-2);color:var(--txt-2);box-shadow:inset 0 1px 0 var(--hair)}
.bandeau.info .quoi{color:var(--txt)}
.bandeau.alerte{background:var(--retard-soft);color:var(--retard-txt)}
.bandeau.fait{background:var(--fait-soft);color:var(--fait-txt)}

/* ---------- la barre d'outils : période, lieu, état ----------
   Un rang qui défile de côté plutôt qu'un rang qui se replie sur deux lignes :
   à six magasins et quatre périodes, un rang replié pousse la liste hors de
   l'écran et il faut défiler avant d'avoir rien vu. */
.rang-outils{
  display:flex;gap:8px;overflow-x:auto;
  padding:12px 0 4px;margin:0 -16px;padding-left:16px;padding-right:16px;
  scrollbar-width:none;
}
.rang-outils::-webkit-scrollbar{display:none}
.puce{
  flex:none;min-height:36px;padding:0 14px;
  background:var(--surface-2);border:none;border-radius:var(--r-tile);
  color:var(--txt-2);font:inherit;font-size:13px;font-weight:600;
  white-space:nowrap;cursor:pointer;
  transition:transform .14s var(--ease);
}
.puce:active{transform:scale(.96)}
.puce.actif{background:var(--accent-soft);color:var(--accent-txt)}

/* Ce qu'on regarde, en une ligne. Il ne décore pas : c'est lui qui dit quand
   un filtre cache quelque chose, et c'est la décision D19 qui l'exige. */
.resume{margin:10px 0 0;font-size:13px;line-height:1.45;color:var(--txt-3)}
.resume .cache{color:var(--accent-txt);font-weight:600}

/* Le jour d'un paquet de cartes, dès que la période en couvre plusieurs. */
.tete-groupe{
  position:sticky;top:0;z-index:5;
  margin:18px 0 8px;padding:6px 0;
  background:var(--page);
  font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--txt-3);
}

/* ---------- une commande, en carte ----------
   La carte plutôt que le tableau, parce qu'une commande n'a pas de colonnes :
   elle a un nom, un jour, un lieu, et entre une et quinze lignes. Un tableau
   l'aurait écrasée dans une largeur de téléphone. */
.liste-cartes{display:flex;flex-direction:column;gap:10px;margin-top:4px}
.carte-cmd{
  padding:13px 14px;
  background:var(--surface);border-radius:var(--r-md);
  box-shadow:inset 0 1px 0 var(--hair);
}
.carte-cmd .tete{display:flex;align-items:flex-start;gap:10px;justify-content:space-between}
.carte-cmd .qui{font-size:16px;font-weight:700;letter-spacing:-.01em}
.carte-cmd .quand{margin-top:2px;font-size:13px;color:var(--txt-2)}
.carte-cmd .lignes{list-style:none;margin:11px 0 0;padding:0}
.carte-cmd .lc{
  display:flex;align-items:baseline;gap:10px;
  padding:5px 0;border-bottom:1px solid var(--trait);
}
.carte-cmd .lc:last-child{border-bottom:none}
/* La quantité d'abord, et de largeur fixe : une vendeuse lit la colonne des
   nombres de haut en bas, elle ne lit pas des phrases. */
.carte-cmd .lc .q{
  flex:none;min-width:2.2em;
  font-size:15px;font-weight:700;font-variant-numeric:tabular-nums;
  color:var(--accent-txt);text-align:right;
}
.carte-cmd .lc .n{flex:1;min-width:0;font-size:14px;font-weight:600;letter-spacing:.01em}
/* Un produit que le catalogue ne connaît pas. Il ne disparaît pas, il se
   signale : c'est D19, et c'est le seul endroit de la carte qui doit accrocher
   l'oeil. */
.carte-cmd .lc .n.inconnu{color:var(--retard-txt);font-weight:700}
.carte-cmd .pied-carte{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;
  margin-top:11px;padding-top:10px;border-top:1px solid var(--trait);
}
.carte-cmd .meta{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--txt-3)}
.carte-cmd .meta .ico{width:13px;height:13px}
/* Une commande qui a bougé après coup. Elle se distingue du reste du pied,
   parce que c'est le seul renseignement qui puisse faire changer d'avis
   quelqu'un qui a déjà sorti sa feuille. */
.carte-cmd .meta.modifiee{color:var(--accent-txt);font-weight:600}
/* La commande qu'on vient d'enregistrer, le temps d'un dessin. Un liseré et
   rien d'autre : elle n'est pas différente des autres, elle est juste celle
   qu'on cherche des yeux à cette seconde. */
.carte-cmd.neuve{box-shadow:inset 0 0 0 2px var(--accent),inset 0 1px 0 var(--hair)}
.carte-cmd .actions{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}
.carte-cmd.note-cmd{margin-top:8px}
.carte-cmd .note-client{margin:9px 0 0;font-size:13px;line-height:1.45;color:var(--txt-2)}

/* D'où vient la commande. Deux mots, jamais une couleur seule : un badge qui
   ne se distinguerait que par sa teinte ne dirait rien à qui ne voit pas
   bien les couleurs. */
.badge{
  flex:none;padding:4px 10px;border-radius:var(--r-tile);
  font-size:11px;font-weight:700;letter-spacing:.02em;white-space:nowrap;
}
.badge.client{background:var(--surface-3);color:var(--txt-2)}
.badge.site{background:var(--accent-soft);color:var(--accent-txt)}

/* ---------- les champs d'un formulaire ---------- */
.champs{display:flex;flex-direction:column;gap:12px;margin-top:14px}
.champ{display:flex;flex-direction:column;gap:5px}
.champ .etiquette{font-size:12px;font-weight:700;letter-spacing:.02em;color:var(--txt-3)}
.champ input,.champ select,.champ textarea{
  width:100%;min-height:48px;padding:0 13px;
  background:var(--surface);
  border:1px solid var(--trait);border-radius:var(--r-in);
  color:var(--txt);font:inherit;font-size:16px;
}
.champ textarea{min-height:76px;padding:12px 13px;line-height:1.45;resize:vertical}
.champ select{appearance:none;cursor:pointer;padding-right:34px}
.champ input:focus,.champ select:focus,.champ textarea:focus{
  outline:2px solid var(--accent);outline-offset:1px;border-color:transparent;
}
.champ .aide{font-size:12px;line-height:1.4;color:var(--txt-3)}
/* Un champ que la porte a refusé. Le message de la porte va dans son aide :
   il est déjà écrit pour être lu par une vendeuse, on ne le traduit pas. */
.champ.faux input,.champ.faux select,.champ.faux textarea{border-color:var(--retard)}
.champ.faux .aide{color:var(--retard-txt);font-weight:600}
.champ input[readonly]{background:var(--surface-2);color:var(--txt-2)}
.paire-champs{display:flex;gap:10px;flex-wrap:wrap}
.paire-champs .champ{flex:1 1 150px;min-width:0}

/* Une liste de cases à cocher, dans les réglages. La case est native, donc
   elle est déjà au clavier et au lecteur d'écran sans une ligne de code, et
   toute la ligne est cliquable parce que c'est un <label> : au pouce, viser un
   carré de vingt points est un geste qu'on rate une fois sur trois. */
.cases{display:flex;flex-direction:column;gap:2px;margin-top:8px}
.case,.rang-etat{
  display:flex;align-items:center;gap:11px;min-height:48px;
  padding:6px 12px;margin-bottom:2px;border-radius:var(--r-in);
  background:var(--surface-2);cursor:pointer;
}
.case input,.rang-etat input{flex:none;width:20px;height:20px;accent-color:var(--accent);cursor:pointer}
.case>span,.rang-etat .nom{flex:1;min-width:0;font-size:14px;font-weight:600}
/* Le mot de la machine à côté du mot français. C'est LUI qui compte : le jour
   où l'interface du site dira « rejected » plutôt que « declined », c'est
   cette colonne qu'on relira pour s'en apercevoir. */
.rang-etat .meta{flex:none;font-size:12px;color:var(--txt-3)}

/* Une zone qui ne reçoit un bandeau qu'au moment où quelque chose est arrivé.
   Vide, elle ne doit rien occuper : une marge blanche sous les boutons se
   remarquerait tous les jours pour un cas qui n'arrive presque jamais. */
.message,.zone-message,.zone-refus{margin-top:12px}
.message:empty,.zone-message:empty,.zone-refus:empty{display:none;margin:0}

/* Masquer sans détruire. Filtrer une liste en enlevant des noeuds du document
   coûte une reconstruction à chaque frappe et fait perdre le curseur de celle
   qui tape. On cache, on ne retire pas. */
.cachee{display:none}

/* Le texte collé depuis le site : une chasse fixe, pour qu'on voie du premier
   coup d'oeil où la copie s'est arrêtée. */
.zone-collage{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px}
.champ input[type="file"]{padding:11px 12px;font-size:14px}

/* Les commandes qu'un import n'a pas écrites. JAMAIS tronquée, et jamais
   repliée : c'est la liste que personne ne doit pouvoir rater (D19). */
.refusees{margin:8px 0 0;padding:0;list-style:none}
.refusees li{padding:5px 0;border-top:1px solid var(--trait);font-size:13px;line-height:1.45}
.refusees li:first-child{border-top:none}

/* ---------- la grille de prise de commande ----------
   Des tuiles, comme sur une caisse de boulangerie. La disposition exacte de
   LEUR caisse n'a pas encore été vue (question Q1), et l'écran le dit lui-même
   en haut : ceci se rhabillera quand les photos arriveront. */
.tete-famille{
  margin:20px 0 8px;
  font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--txt-3);
}
.grille-caisse{display:grid;grid-template-columns:repeat(auto-fill,minmax(102px,1fr));gap:8px}
.tuile{
  position:relative;
  display:flex;align-items:center;justify-content:center;
  min-height:66px;padding:10px 8px;
  background:var(--surface);border:none;border-radius:var(--r-tile);
  box-shadow:inset 0 1px 0 var(--hair);
  color:var(--txt);font:inherit;text-align:center;cursor:pointer;
  transition:transform .12s var(--ease);
}
.tuile:active{transform:scale(.95)}
.tuile .nom{font-size:12px;font-weight:600;line-height:1.25;letter-spacing:.01em}
/* Une tuile déjà prise, et combien de fois. Le fond change ET un nombre
   apparaît : la couleur seule ne dirait pas la quantité. */
.tuile.prise{background:var(--accent-soft);box-shadow:inset 0 0 0 1px var(--accent)}
.tuile .q{
  position:absolute;top:5px;right:6px;
  min-width:22px;padding:1px 5px;border-radius:var(--r-tile);
  background:var(--accent);color:var(--accent-ink);
  font-size:12px;font-weight:700;font-variant-numeric:tabular-nums;
}
.tuile.cachee{display:none}

/* ---------- le panier ---------- */
.panier{margin-top:16px;background:var(--surface);border-radius:var(--r-md);overflow:hidden}
.panier .pl{
  display:flex;align-items:center;gap:10px;
  min-height:56px;padding:8px 12px;
  border-bottom:1px solid var(--trait);
}
.panier .pl:last-child{border-bottom:none}
.panier .pl .n{flex:1;min-width:0;font-size:14px;font-weight:600;letter-spacing:.01em}
.panier .pl .n.inconnu{color:var(--retard-txt)}
/* Le compteur porte un CHAMP au milieu, pas un nombre affiché : douze
   croissants se tapent, ils ne s'appuient pas douze fois. Il refuse ce qui
   n'est pas un chiffre, comme la liste de saisie, et pour la même raison. */
.compteur{flex:none;display:flex;align-items:center;gap:4px}
.compteur button{
  width:38px;height:38px;flex:none;
  display:flex;align-items:center;justify-content:center;
  background:var(--surface-2);border:none;border-radius:var(--r-tile);
  color:var(--txt);cursor:pointer;
  transition:transform .12s var(--ease);
}
.compteur button:active{transform:scale(.92)}
.compteur button .ico{width:16px;height:16px}
.compteur .v{
  width:52px;height:38px;flex:none;
  background:var(--surface-2);
  border:1px solid var(--trait);border-radius:var(--r-tile);
  color:var(--txt);font:inherit;font-size:16px;font-weight:700;
  text-align:center;font-variant-numeric:tabular-nums;
}
.compteur .v:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:transparent}
.panier .pl.pas-enregistree .v{border-color:var(--retard);color:var(--retard-txt)}

/* ---------- la barre d'action, juste au-dessus du dock ----------
   Fixe et non collante : `.ecran` défile pour son propre compte, une barre
   collée au bas de ce conteneur se retrouverait sous le dock. Elle se pose
   donc par rapport à la fenêtre, à la hauteur du dock, qui est un jeton. */
.barre-action{
  position:fixed;left:0;right:0;bottom:var(--dock-h);z-index:25;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:10px 16px;
  background:var(--page);
  border-top:1px solid var(--trait);
}
/* ELLE SE REPLIE, ET CE N'EST PAS UNE PRÉCAUTION EN L'AIR. Une commande qui
   vient d'être enregistrée en porte TROIS : imprimer le bon, en prendre une
   autre, revenir à la liste. Sur un téléphone de 375 points, trois boutons
   côte à côte poussent le dernier hors de l'écran, et le geste le plus
   naturel, revenir en arrière, devient impossible. Attrapé par le garde-fou
   de la prise de commande, qui a passé trente secondes à essayer de cliquer
   un bouton qu'il voyait et qui n'était pas là. */
/* Le compte cède la place au bouton, jamais l'inverse : « 0 ligne, 0 pièce »
   se lit sur deux lignes sans dommage, « Enregistrer la commande » coupé en
   deux fait un bouton deux fois trop haut au milieu de la barre. */
.barre-action .total{flex:1 1 90px;min-width:0;font-size:13px;line-height:1.3;color:var(--txt-2)}
.barre-action .bouton{flex:2 1 46%;min-height:46px;padding:0 14px;font-size:15px}
/* Ce qui manque encore pour pouvoir enregistrer passe AU-DESSUS des boutons,
   sur toute la largeur : c'est la phrase qui explique pourquoi le bouton est
   fermé, elle ne doit pas se retrouver serrée entre deux boutons. */
.barre-action .aide{flex:1 1 100%;order:-1;margin:0;font-size:12px;line-height:1.35;color:var(--accent-txt)}
.barre-action .aide:empty{display:none}
/* L'écran creuse sa propre place : sans ça, la barre d'action couvre la
   dernière carte de la liste, et personne ne peut plus l'atteindre. */
.ecran:has(.barre-action){padding-bottom:calc(var(--dock-h) + 160px)}

/* ---------- les réglages ---------- */
.sections{
  display:flex;gap:8px;overflow-x:auto;
  padding:14px 0 4px;margin:0 -16px;padding-left:16px;padding-right:16px;
  scrollbar-width:none;
}
.sections::-webkit-scrollbar{display:none}
.section-onglet{
  flex:none;min-height:38px;padding:0 15px;
  background:var(--surface-2);border:none;border-radius:var(--r-tile);
  color:var(--txt-2);font:inherit;font-size:13px;font-weight:700;letter-spacing:.02em;
  white-space:nowrap;cursor:pointer;
}
.section-onglet.actif{background:var(--accent-soft);color:var(--accent-txt)}

.bloc{
  margin-top:16px;padding:14px;
  background:var(--surface);border-radius:var(--r-md);
  box-shadow:inset 0 1px 0 var(--hair);
}
.bloc .tete-bloc{
  display:flex;align-items:center;gap:10px;justify-content:space-between;flex-wrap:wrap;
  font-size:16px;font-weight:700;letter-spacing:-.01em;
}
/* La phrase qui dit à quoi sert le bloc, et surtout ce qu'il ne fait PAS
   encore. Les heures limites se règlent et ne sont appliquées nulle part :
   un réglage qui ne règle rien et qui se tait est un mensonge. */
.bloc .aide{margin:7px 0 0;font-size:13px;line-height:1.5;color:var(--txt-3)}
.bloc .rangs{margin-top:12px}

.rang-reglage{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  min-height:56px;padding:9px 0;
  border-bottom:1px solid var(--trait);
}
.rang-reglage:last-child{border-bottom:none}
.rang-reglage .nom{flex:1 1 140px;min-width:0;font-size:15px;font-weight:600}
.rang-reglage .meta{flex:none;font-size:12px;color:var(--txt-3);font-variant-numeric:tabular-nums}
.rang-reglage .actions{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}
/* Éteint, jamais supprimé (D23) : le nom reste lisible, parce que des chiffres
   déjà saisis sont rangés dessous et qu'on doit encore pouvoir les nommer. */
.rang-reglage.eteint .nom{color:var(--txt-3);text-decoration:line-through}
.rang-reglage.eteint .meta{opacity:.6}

.zone-delicate{box-shadow:inset 0 0 0 1px var(--retard-soft)}
.zone-delicate .tete-bloc{color:var(--retard-txt)}

/* Une rangée de boutons au pied d'un bloc, ou au pied d'une feuille qui monte
   du bas. Elle se replie, parce que « Modifier, Monter, Descendre, Retirer »
   ne tient pas sur la largeur d'un téléphone et qu'un bouton poussé hors de
   l'écran est un bouton qui n'existe plus. */
.bloc>.actions,.feuille .corps .actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.feuille .corps .actions{margin-top:18px}
.feuille .corps .actions .bouton{flex:1 1 130px}

/* Le rang d'outils porte tantôt des puces de filtre, tantôt de vrais boutons
   (« Éteindre ces 249 produits »). Les puces défilent de côté, les boutons se
   replient : un libellé de bouton est long, et à six familles la dernière
   sortait de l'écran sans que rien ne le montre. */
.rang-outils:has(.bouton){flex-wrap:wrap;overflow:visible}

/* Un bandeau qui porte lui-même une porte de sortie, comme « Tout afficher »
   sous l'annonce de la troncature. */
.bandeau .bouton{margin-top:10px}

/* ---------- l'aperçu de la feuille, dans les réglages ----------
   Une section qui change les colonnes de la feuille sans montrer la feuille
   demande de lire quatre cases et d'imaginer le résultat. Le même tableau
   qu'à l'écran de production, en plus petit, dit la même chose sans effort. */
.apercu-feuille{
  margin-top:12px;overflow-x:auto;
  background:var(--surface-2);border-radius:var(--r-in);
}
.apercu-feuille table{width:100%;border-collapse:collapse;font-size:12px}
.apercu-feuille th,.apercu-feuille td{
  padding:6px 8px;white-space:nowrap;border-bottom:1px solid var(--trait);
}
.apercu-feuille th{font-size:10px;font-weight:700;letter-spacing:.05em;color:var(--txt-3);text-align:center}
.apercu-feuille th.hors-total{color:var(--accent-txt)}
.apercu-feuille td.produit{text-align:right;font-weight:600}
.apercu-feuille td.nombre{text-align:left;font-variant-numeric:tabular-nums}
.apercu-feuille td.total{font-weight:700;color:var(--accent-txt)}
.apercu-feuille tbody tr:last-child td{border-bottom:none}

/* ---------- les boutons, suite ---------- */
.bouton.petit{min-height:38px;padding:0 13px;font-size:13px}
.bouton.petit .ico{width:15px;height:15px}
/* MONTER ET DESCENDRE N'ONT PAS BESOIN DE MOTS.

   Écrits en toutes lettres, quatre actions (Modifier, Éteindre, Monter,
   Descendre) font 327 points de large : sur un téléphone de 375, « Descendre »
   passait à la ligne tout seul, chaque magasin occupait deux rangs, et la
   section des lieux devenait trois fois plus haute que nécessaire. Deux
   chevrons disent la même chose en 88 points. Le mot reste, dans aria-label,
   pour qui n'a que la voix. */
.bouton.ico-seule{width:38px;min-width:38px;padding:0}
.bouton.ico-seule .ico{width:17px;height:17px}
/* Le bouton dangereux ne ressemble à aucun autre, et il n'est jamais le bouton
   qui a le focus par défaut dans une confirmation. */
.bouton.danger{background:var(--retard);color:var(--retard-ink)}
.rang-boutons{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}

/* LE BON DE COMMANDE NE SE VOIT JAMAIS À L'ÉCRAN.

   Il est posé sur le corps de la page le temps d'une impression, et
   impression.css lui donne sa mise en page. Mais impression.css n'est chargée
   qu'au média « print » : sans cette ligne ici, le bon apparaîtrait à l'écran,
   sans mise en forme, par dessus l'application, pendant tout le temps que dure
   la fenêtre d'impression. */
.bon{display:none}

/* ---------- la relecture avant d'enregistrer une commande ----------
   Trois lignes, et elles sont dans l'ordre du risque. Le JOUR d'abord, en
   toutes lettres et en grand : c'est le seul champ qu'on oublie de changer,
   parce qu'il est déjà rempli. Le LIEU ensuite, marqué quand ce n'est pas
   celui où l'on se trouve. Le CLIENT enfin. */
.relecture{
  padding:14px;margin-top:4px;
  background:var(--surface-2);border-radius:var(--r-in);
}
.rel-quand{display:flex;flex-direction:column;gap:2px}
.rel-quand .grand{font-size:21px;font-weight:700;letter-spacing:-.02em;line-height:1.15}
.rel-quand .distance{font-size:13px;color:var(--txt-3)}
/* Aujourd'hui, ou un jour déjà passé : exactement ce qui reste à l'écran quand
   on a oublié de changer la date. On ne l'interdit pas, on le montre. */
.rel-quand.inhabituel .grand{color:var(--accent-txt)}
.rel-quand.inhabituel .distance{color:var(--accent-txt);font-weight:700}
.rel-ou{margin-top:10px;font-size:15px;font-weight:600}
.rel-ou.ailleurs{color:var(--accent-txt)}
.rel-qui{margin-top:4px;font-size:15px;color:var(--txt-2)}

/* Les lignes d'une commande se relisent dans une feuille comme sur une carte :
   même balisage, donc mêmes règles, plutôt qu'un second jeu qui dériverait. */
.feuille .corps .lignes{list-style:none;margin:12px 0 0;padding:0}
.feuille .corps .lc{
  display:flex;align-items:baseline;gap:10px;
  padding:6px 0;border-bottom:1px solid var(--trait);
}
.feuille .corps .lc:last-child{border-bottom:none}
.feuille .corps .lc .q{
  flex:none;min-width:2.2em;
  font-size:16px;font-weight:700;font-variant-numeric:tabular-nums;
  color:var(--accent-txt);text-align:right;
}
.feuille .corps .lc .n{flex:1;min-width:0;font-size:14px;font-weight:600;letter-spacing:.01em}
.feuille .corps .lc .n.inconnu{color:var(--retard-txt);font-weight:700}
.feuille .corps .resume{margin:10px 0 0}

/* ---------- la feuille qui monte du bas, pour un formulaire ---------- */
.feuille .titre-feuille{font-size:19px;font-weight:700;letter-spacing:-.01em;margin:0 0 4px}
.feuille .corps{padding-bottom:6px}
.feuille .corps .champs{margin-top:10px}
