/* ==========================================================================
   Economat - feuille de style unique
   --------------------------------------------------------------------------
   Direction artistique : calme, aere, beaucoup de blanc.
   Un seul accent (vert profond), aucune ombre portee, aucun degrade,
   aucune bordure verticale dans les tableaux, casse de phrase partout.
   Deux graisses seulement : 400 et 500.

   Toutes les couleurs sont declarees en variables sur :root.
   Aucune couleur n'est ecrite en dur ailleurs dans ce fichier.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Variables
   -------------------------------------------------------------------------- */

:root {
  /* Les controles natifs (liste deroulante, calendrier, selecteur de couleur,
     ascenseurs) suivent le theme du systeme. Sans cette ligne, un champ de date
     reste blanc sur fond sombre et devient illisible. */
  color-scheme: light dark;

  /* surfaces et filets */
  --fond: #FAFAF9;
  --carte: #FFFFFF;
  --bord: #E7E5E4;
  --bord-fort: #D6D3D1;

  /* texte */
  --texte: #1C1917;
  --texte-doux: #78716C;
  --texte-faible: #A8A29E;

  /* accent unique */
  --accent: #15803D;
  --accent-fond: #F0FDF4;
  --accent-texte: #FFFFFF;

  /* etats */
  --danger: #B91C1C;
  --danger-fond: #FEF2F2;
  --alerte: #C2410C;
  --alerte-fond: #FFF7ED;
  --attention: #A16207;
  --attention-fond: #FEFCE8;

  /* surfaces derivees */
  --barre: #F5F5F4;          /* fond de la barre laterale */
  --survol: #F5F5F4;         /* survol de ligne et de lien */
  --anneau: rgba(21, 128, 61, 0.24);  /* unique ombre autorisee : le focus */
  --voile: rgba(28, 25, 23, 0.28);    /* fond du menu ouvert sur mobile */

  /* typographie */
  --police: system-ui, "Segoe UI Variable Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* geometrie */
  --rayon-carte: 10px;
  --rayon-controle: 8px;
  --largeur-barre: 232px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --fond: #151312;
    --carte: #1C1917;
    --bord: #2E2A28;
    --bord-fort: #44403C;

    --texte: #F5F5F4;
    --texte-doux: #A8A29E;
    --texte-faible: #78716C;

    --accent: #4ADE80;
    --accent-fond: #14261A;
    --accent-texte: #0B1F12;

    --danger: #F87171;
    --danger-fond: #2A1616;
    --alerte: #FB923C;
    --alerte-fond: #2A1A10;
    --attention: #FACC15;
    --attention-fond: #26200D;

    --barre: #1A1716;
    --survol: #232020;
    --anneau: rgba(74, 222, 128, 0.26);
    --voile: rgba(0, 0, 0, 0.55);
  }
}

/* --------------------------------------------------------------------------
   2. Reinitialisation minimale
   -------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--police);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-weight: 500; margin: 0; }
h1 { font-size: 20px; }
h2 { font-size: 16px; }
h3 { font-size: 15px; }

p { margin: 0 0 12px; }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

img { max-width: 100%; height: auto; }

hr {
  border: 0;
  border-top: 1px solid var(--bord);
  margin: 24px 0;
}

:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--anneau);
  border-radius: var(--rayon-controle);
}

/* --------------------------------------------------------------------------
   3. Mise en page
   -------------------------------------------------------------------------- */

.appli {
  display: grid;
  grid-template-columns: var(--largeur-barre) 1fr;
  min-height: 100vh;
}

.contenu {
  padding: 24px 32px 64px;
  max-width: 1280px;
  width: 100%;
  /* Une case de grille refuse par defaut de devenir plus etroite que son
     contenu. Sous 900 px les tableaux recoivent min-width: 560px pour rester
     lisibles ; sans cette ligne, cette largeur remonte jusqu'ici et c'est la
     PAGE ENTIERE qui glisse sous le doigt, en-tete et menu compris, au lieu
     du seul tableau dans son cadre. */
  min-width: 0;
}

/* En-tete de page : titre a gauche, boutons d'action a droite */
.entete-page {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

.entete-page h1 { font-size: 20px; font-weight: 500; }

.entete-page .sous-titre {
  display: block;
  font-size: 13px;
  font-weight: 400;
  color: var(--texte-doux);
  margin-top: 2px;
}

.entete-page .actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Grille de cartes ou de statistiques */
.grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.grille-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

/* Espacement standard entre deux blocs */
.bloc { margin-bottom: 24px; }

/* --------------------------------------------------------------------------
   4. Barre laterale
   -------------------------------------------------------------------------- */

.barre-laterale {
  background: var(--barre);
  border-right: 1px solid var(--bord);
  padding: 14px 12px 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.marque {
  display: block;
  padding: 0 12px 16px;
  color: var(--texte);
  font-size: 15px;
  font-weight: 500;
}
.marque:hover { text-decoration: none; }

/* Le logo de l'application, au-dessus du nom de l'etablissement.

   Le fichier livre est RECADRE sur son dessin : le PNG d'origine portait 24 %
   de vide transparent en haut et 27 % en bas, soit plus de la moitie de sa
   hauteur. Aucune regle CSS n'aurait explique cet ecart - il fallait le retirer
   du fichier, pas le compenser ici. La source non recadree reste a la racine
   du dossier, sous logo-klenea.png.

   width/height sont dans le HTML : sans eux, la place du logo n'est reservee
   qu'une fois l'image chargee, et tout le menu sursaute au chargement. */
.marque-logo {
  display: block;
  width: 100%;
  max-width: 132px;
  height: auto;
  margin-bottom: 10px;
}

.marque-nom { display: block; }

/* En mode sombre, le vert du logo (fonce, fait pour du papier blanc) tombe
   presque dans le noir du fond. On l'eclaircit pour l'amener au vert que
   l'application utilise deja la nuit - le fichier reste le meme, seule sa
   restitution change. */
@media (prefers-color-scheme: dark) {
  .marque-logo { filter: brightness(1.8); }
}

.marque .marque-lieu {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--texte-faible);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav-lien {
  display: flex;
  align-items: center;
  gap: 10px;
  /* 36 px, et non 40 : la barre porte dix-huit entrees et cinq intertitres.
     A 40 px elle depassait l'ecran, et « Déconnexion » demandait un
     defilement. La cible reste largement assez grande au doigt. */
  min-height: 36px;
  padding: 6px 12px;
  border-radius: var(--rayon-controle);
  color: var(--texte);
  font-size: 15px;
  font-weight: 400;
}
.nav-lien:hover { background: var(--survol); text-decoration: none; }

.nav-lien.actif {
  background: var(--accent-fond);
  color: var(--accent);
  font-weight: 500;
}

.nav-lien svg { flex: 0 0 auto; }

/* Les espacements de cette barre ont ete resserres pour loger le logo sans
   faire apparaitre une barre de defilement dans le menu : sur un ecran de
   929 px de haut, la barre etait remplie au pixel pres. */
/* Les intertitres de la barre laterale. Ils sont serres a dessein : depuis
   qu'il y en a cinq - Prevoir, Acheter, Servir, Suivre, Referentiel - chaque
   pixel gagne ici evite d'avoir a defiler pour atteindre Deconnexion. */
.nav-groupe {
  margin: 10px 0 2px;
  padding: 0 12px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--texte-faible);
}
/* Le premier ne pousse pas : le lien au-dessus a deja son propre espace. */
.nav-groupe:first-of-type { margin-top: 6px; }

.nav-bas { margin-top: auto; padding-top: 12px; }

/* Bouton hamburger : masque sur grand ecran */
.bouton-menu { display: none; }
.voile-menu { display: none; }

/* --------------------------------------------------------------------------
   5. Cartes et statistiques
   -------------------------------------------------------------------------- */

.carte {
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  padding: 16px 20px;
}

.carte + .carte { margin-top: 16px; }

.carte-titre {
  font-size: 13px;
  font-weight: 500;
  color: var(--texte-doux);
  margin-bottom: 12px;
}

.carte-lien { display: block; color: inherit; }
.carte-lien:hover { border-color: var(--bord-fort); text-decoration: none; }

/* Grand chiffre du tableau de bord */
.stat {
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  padding: 16px 20px;
  display: block;
  color: inherit;
}
.stat:hover { text-decoration: none; }
a.stat:hover { border-color: var(--bord-fort); }

.stat-valeur {
  display: block;
  font-size: 28px;
  font-weight: 500;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.stat-libelle {
  display: block;
  font-size: 13px;
  font-weight: 400;
  color: var(--texte-doux);
  margin-top: 4px;
}

.stat-detail {
  display: block;
  font-size: 12px;
  color: var(--texte-faible);
  margin-top: 4px;
}

.stat-accent  .stat-valeur { color: var(--accent); }
.stat-danger  .stat-valeur { color: var(--danger); }
.stat-alerte  .stat-valeur { color: var(--alerte); }

/* --------------------------------------------------------------------------
   6. Tableaux
   Aucune bordure verticale. Filets horizontaux uniquement.
   -------------------------------------------------------------------------- */

.table-defilante {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Un conteneur qui defile horizontalement devient, selon la specification, un
   conteneur de defilement sur les DEUX axes : "overflow-x: auto" force
   "overflow-y" a passer de "visible" a "auto". L'en-tete collant s'accrochait
   donc a ce conteneur au lieu de suivre la fenetre ; comme le conteneur fait
   exactement la hauteur du tableau, il n'avait jamais de quoi coller et
   l'effet etait nul sur tous les ecrans.

   Sur grand ecran on retire donc le conteneur, et thead se cale enfin sur le
   haut de la fenetre. Les trois tableaux les plus larges en sont exclus : eux
   debordent reellement et ont besoin de leur ascenseur horizontal. La regle
   est ecrite en :not(:has(...)) pour que, sur un navigateur qui ignorerait
   :has(), le selecteur soit invalide et le comportement actuel conserve :
   l'echec se fait du cote sur. */
@media (min-width: 901px) {
  .table-defilante:not(:has(.tableau-prix)):not(:has(.cmd-tableau)):not(:has(.tableau-lignes)) {
    overflow: visible;
  }
}

.tableau {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}

.tableau th,
.tableau td {
  text-align: left;
  padding: 12px 12px;
  border: 0;
  border-bottom: 1px solid var(--bord);
  vertical-align: middle;
}

.tableau th:first-child,
.tableau td:first-child { padding-left: 0; }

.tableau th:last-child,
.tableau td:last-child { padding-right: 0; }

.tableau thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  /* fond identique a la carte qui contient le tableau : visuellement neutre,
     mais opaque pour que les lignes ne transparaissent pas au defilement */
  background: var(--carte);
  font-size: 12px;
  font-weight: 500;
  color: var(--texte-doux);
  border-bottom: 1px solid var(--bord-fort);
  white-space: nowrap;
}

.tableau thead th a { color: inherit; }

.tableau tbody tr:hover { background: var(--survol); }

.tableau tbody tr:last-child td { border-bottom: 0; }

.tableau tfoot td {
  font-weight: 500;
  border-top: 1px solid var(--bord-fort);
  border-bottom: 0;
}

/* Nombres : toujours a droite, chasse fixe */
.num,
.tableau th.num,
.tableau td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Colonne d'actions : discrete, revelee au survol sur grand ecran */
.actions-ligne {
  text-align: right;
  white-space: nowrap;
}

.actions-ligne a,
.actions-ligne button {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  font-size: 13px;
  color: var(--texte-doux);
  background: none;
  border: 0;
  padding: 4px 8px;
  cursor: pointer;
  font-family: inherit;
}
.actions-ligne a:hover { color: var(--accent); }
.actions-ligne button:hover { color: var(--danger); }

@media (hover: hover) and (min-width: 901px) {
  .actions-ligne { opacity: 0; transition: opacity 0.12s ease-out; }
  tr:hover .actions-ligne,
  .actions-ligne:focus-within { opacity: 1; }
}

/* Doigt plutot que souris : toutes les cibles passent a 40px.
   L'econome est souvent en cuisine, sur une tablette, les mains prises. */
@media (pointer: coarse) {
  .actions-ligne a,
  .actions-ligne button,
  .bouton-discret,
  .tableau .sortie-note { min-height: 40px; }
}

/* Ligne de sous-total ou de regroupement */
.ligne-groupe td {
  font-size: 12px;
  font-weight: 500;
  color: var(--texte-doux);
  background: var(--fond);
}

/* --------------------------------------------------------------------------
   7. Pastilles, badges, etats
   -------------------------------------------------------------------------- */

/* Pastille ronde de 6px : prend la couleur du texte courant */
.pastille {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  vertical-align: 0.12em;
  margin-right: 6px;
  flex: 0 0 auto;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--bord);
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 400;
  color: var(--texte-doux);
  white-space: nowrap;
  /* Un badge porte souvent une quantite : "385 paquets en stock". */
  font-variant-numeric: tabular-nums;
}

.badge-accent    { color: var(--accent);    border-color: var(--accent); }
.badge-danger    { color: var(--danger);    border-color: var(--danger); }
.badge-alerte    { color: var(--alerte);    border-color: var(--alerte); }
.badge-attention { color: var(--attention); border-color: var(--attention); }

/* Etats DLC : ils colorent le TEXTE et la pastille, jamais la ligne entiere */
.dlc-perime { color: var(--danger); }
.dlc-urgent { color: var(--alerte); }
.dlc-proche { color: var(--attention); }
.dlc-ok     { color: var(--texte); }

/* --------------------------------------------------------------------------
   8. Boutons
   Un seul bouton plein par ecran : .bouton-primaire.
   -------------------------------------------------------------------------- */

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 16px;
  border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-controle);
  background: var(--carte);
  color: var(--texte);
  font-family: inherit;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.3;
  cursor: pointer;
  white-space: nowrap;
  text-decoration: none;
}
.bouton:hover { background: var(--survol); text-decoration: none; }
.bouton:disabled,
.bouton[aria-disabled="true"] { color: var(--texte-faible); cursor: default; }

.bouton-primaire {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-texte);
  font-weight: 500;
}
.bouton-primaire:hover { background: var(--accent); opacity: 0.92; }

.bouton-danger {
  border-color: var(--bord-fort);
  color: var(--danger);
  background: var(--carte);
}
.bouton-danger:hover { background: var(--danger-fond); }

.bouton-discret {
  min-height: 36px;
  padding: 4px 8px;
  border: 0;
  background: none;
  color: var(--texte-doux);
  font-size: 13px;
}
.bouton-discret:hover { background: none; color: var(--accent); text-decoration: underline; }

.bouton-large { width: 100%; }

/* --------------------------------------------------------------------------
   9. Formulaires
   -------------------------------------------------------------------------- */

.ligne-formulaire { margin-bottom: 16px; }

.ligne-formulaire > label,
.libelle {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--texte-faible);
  margin-bottom: 4px;
}

.champ {
  display: block;
  width: 100%;
  min-height: 40px;
  padding: 8px 12px;
  border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-controle);
  background: var(--carte);
  color: var(--texte);
  font-family: inherit;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.4;
}
.champ:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--anneau);
}
.champ::placeholder { color: var(--texte-faible); }
.champ:disabled { color: var(--texte-doux); background: var(--fond); }

textarea.champ { min-height: 88px; resize: vertical; line-height: 1.55; }

/* La fleche de la liste deroulante est celle du systeme : aucune image, aucune
   couleur en dur, et elle suit le mode sombre grace a color-scheme. */
select.champ { padding-right: 8px; }

.champ-nombre {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.champ-court { max-width: 140px; }
.champ-moyen { max-width: 260px; }

/* Cases a cocher : cible tactile confortable */
.case {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  font-size: 15px;
  cursor: pointer;
}
.case input { width: 18px; height: 18px; accent-color: var(--accent); }

/* Les sept jours d'une tournee fournisseur. Ils tiennent sur une ligne au
   bureau et se replient sur telephone, sans jamais casser l'ordre de la
   semaine : c'est dans cet ordre qu'on les lit. */
.jours-tournee {
  display: flex;
  flex-wrap: wrap;
  gap: 0 18px;
  margin-top: 2px;
}
.jours-tournee .case { flex: 0 0 auto; }

.aide {
  display: block;
  font-size: 12px;
  color: var(--texte-faible);
  margin-top: 4px;
}

/* Deux ou trois champs cote a cote */
.champs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

.actions-formulaire {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--bord);
}

/* --------------------------------------------------------------------------
   10. L'equivalence
   La classe la plus utilisee du projet : le texte discret place sous un champ
   pour dire "2 colis = 400 paquets". Elle est le langage de la conversion.
   -------------------------------------------------------------------------- */

.equivalence {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
  min-height: 17px;   /* reserve la place : le champ ne saute pas a la frappe */
}

.equivalence:empty { min-height: 17px; }

/* Variante appliquee brievement quand la valeur vient de changer */
.equivalence-forte {
  color: var(--accent);
  animation: equivalence-apparait 0.9s ease-out;
}

@keyframes equivalence-apparait {
  from { background: var(--accent-fond); }
  to   { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .equivalence-forte { animation: none; }
}

/* Equivalence placee dans une cellule de tableau, alignee a droite */
.tableau .equivalence { text-align: right; }

/* --------------------------------------------------------------------------
   11. Alertes et encadres de synthese
   Les fonds teintes sont reserves a ces encadres, jamais aux lignes.
   -------------------------------------------------------------------------- */

.alerte {
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  padding: 12px 16px;
  font-size: 15px;
  margin-bottom: 16px;
  color: var(--texte);
}

.alerte-succes { background: var(--accent-fond);    border-color: var(--accent);    color: var(--accent); }
.alerte-erreur { background: var(--danger-fond);    border-color: var(--danger);    color: var(--danger); }
.alerte-info   { background: var(--fond);           border-color: var(--bord-fort); color: var(--texte-doux); }
.alerte-attention { background: var(--attention-fond); border-color: var(--attention); color: var(--attention); }

/* Encadre du verdict prix : le fournisseur le moins cher, la tendance */
.verdict {
  background: var(--accent-fond);
  border: 1px solid var(--accent);
  border-radius: var(--rayon-carte);
  padding: 16px 20px;
  margin-bottom: 24px;
}
.verdict .verdict-reponse {
  font-size: 20px;
  font-weight: 500;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.verdict .verdict-detail {
  font-size: 13px;
  color: var(--texte-doux);
  margin-top: 4px;
}

/* --------------------------------------------------------------------------
   12. Barre d'outils, recherche, pagination, etat vide
   -------------------------------------------------------------------------- */

.barre-outils {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.barre-outils .espaceur { flex: 1 1 auto; }

.recherche {
  position: relative;
  flex: 1 1 240px;
  max-width: 340px;
}

.recherche input {
  width: 100%;
  min-height: 40px;
  padding: 8px 12px 8px 36px;
  border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-controle);
  background: var(--carte);
  color: var(--texte);
  font-family: inherit;
  font-size: 15px;
}
.recherche input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--anneau);
}

.recherche svg {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--texte-faible);
  pointer-events: none;
}

.compteur-resultats {
  font-size: 13px;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

.pagination {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 20px;
}

.pagination a,
.pagination span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 40px;
  padding: 0 10px;
  border-radius: var(--rayon-controle);
  font-size: 15px;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}
.pagination a:hover { background: var(--survol); color: var(--texte); text-decoration: none; }
.pagination .actif { background: var(--accent-fond); color: var(--accent); font-weight: 500; }
.pagination .inactif { color: var(--texte-faible); }

/* Etat vide : une phrase courte qui invite */
.vide {
  padding: 48px 24px;
  text-align: center;
  color: var(--texte-doux);
  font-size: 15px;
}
.vide p { margin-bottom: 16px; }

/* --------------------------------------------------------------------------
   13. Textes secondaires et divers
   -------------------------------------------------------------------------- */

.doux   { color: var(--texte-doux); font-size: 13px; }
.faible { color: var(--texte-faible); font-size: 12px; }
.accent { color: var(--accent); }
.rouge  { color: var(--danger); }

.mono { font-variant-numeric: tabular-nums; }

.nowrap { white-space: nowrap; }

.separateur {
  border-top: 1px solid var(--bord);
  margin: 24px 0;
}

/* Liste de definitions : fiche fournisseur, fiche produit */
.fiche {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px 24px;
  margin: 0;
}
.fiche dt {
  font-size: 12px;
  color: var(--texte-faible);
  margin-bottom: 2px;
}
/* Une fiche empile des quantites, des prix et des dates sur deux colonnes :
   la chasse fixe les aligne verticalement, comme dans un tableau. */
.fiche dd { margin: 0; font-size: 15px; font-variant-numeric: tabular-nums; }

/* Liste a puces sobre */
.liste {
  margin: 0;
  padding-left: 20px;
  color: var(--texte-doux);
  font-size: 13px;
}
.liste li { margin-bottom: 4px; }

/* Bloc de code ou de configuration a recopier */
.bloc-code {
  margin: 0;
  overflow-x: auto;
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 13px;
  line-height: 1.5;
  color: var(--texte-doux);
  white-space: pre;
}

/* Page autonome centree : installation, message isole */
.page-simple {
  max-width: 760px;
  margin: 0 auto;
  padding: 40px 24px 64px;
}
@media (max-width: 900px) {
  .page-simple { padding: 24px 16px 64px; }
}

/* Ecran de connexion */
.connexion {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.connexion-carte {
  width: 100%;
  max-width: 360px;
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  padding: 32px;
}
.connexion-carte h1 { margin-bottom: 4px; }
.connexion-carte .doux { margin-bottom: 24px; display: block; }

/* --------------------------------------------------------------------------
   14. Petit ecran : jusqu'a 380px de large
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .appli { grid-template-columns: 1fr; }

  .barre-laterale {
    position: fixed;
    inset: 0 auto 0 0;
    width: 260px;
    z-index: 40;
    transform: translateX(-100%);
    transition: transform 0.16s ease-out;
    border-right: 1px solid var(--bord-fort);
  }
  .barre-laterale.ouverte { transform: translateX(0); }

  .voile-menu {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--voile);
    z-index: 30;
  }
  .voile-menu.visible { display: block; }

  .bouton-menu {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 8px 12px;
    margin: 0 0 16px;
    border: 1px solid var(--bord-fort);
    border-radius: var(--rayon-controle);
    background: var(--carte);
    color: var(--texte);
    font-family: inherit;
    font-size: 15px;
    cursor: pointer;
  }

  .contenu { padding: 16px 16px 64px; }

  .grille,
  .grille-2,
  .champs,
  .fiche { grid-template-columns: 1fr; }

  .entete-page { align-items: flex-start; flex-direction: column; gap: 12px; }
  .entete-page .actions { width: 100%; }

  .recherche { max-width: none; flex-basis: 100%; }

  /* Les tableaux defilent horizontalement dans leur conteneur */
  .table-defilante { margin: 0 -16px; padding: 0 16px; }
  .tableau { min-width: 560px; }

  /* Sur tablette et telephone, les actions restent toujours visibles */
  .actions-ligne { opacity: 1; }
}

@media (max-width: 420px) {
  .carte { padding: 16px; }
  .connexion-carte { padding: 24px; }
  .stat-valeur { font-size: 24px; }
  .bouton { padding: 8px 12px; }
}

/* --------------------------------------------------------------------------
   15. Impression
   Les ecrans Tracabilite et Prix servent de justificatif : ils doivent
   s'imprimer proprement, en noir sur blanc, sans navigation.
   -------------------------------------------------------------------------- */

@media print {
  /* TOUTES les variables sont redefinies, y compris celles des etats.
     Sans cela, un poste regle en mode sombre imprimerait un rouge pale et un
     jaune vif sur du papier blanc : illisible. */
  :root {
    color-scheme: light;

    --fond: #FFFFFF;
    --carte: #FFFFFF;
    --bord: #CCCCCC;
    --bord-fort: #999999;
    --texte: #000000;
    --texte-doux: #333333;
    --texte-faible: #555555;

    --accent: #000000;
    --accent-fond: #FFFFFF;
    --accent-texte: #FFFFFF;

    --danger: #000000;
    --danger-fond: #FFFFFF;
    --alerte: #333333;
    --alerte-fond: #FFFFFF;
    --attention: #333333;
    --attention-fond: #FFFFFF;

    --survol: #FFFFFF;
    --barre: #FFFFFF;
    --anneau: transparent;
    --voile: transparent;
  }

  /* Rien de cliquable ne doit atteindre le papier : ni bouton, ni raccourci,
     ni depliant de saisie. Un bon imprime ne porte que de l'information. */
  .barre-laterale,
  .bouton-menu,
  .voile-menu,
  .barre-outils,
  .pagination,
  .actions-formulaire,
  .entete-page .actions,
  .bouton,
  .bouton-discret,
  .recherche,
  .sans-impression,
  .actions-ligne,
  .filtres-actions,
  .param-boutons,
  .sortie-raccourcis,
  .sortie-reprise,
  .recherche-ajout,
  .cmd-pied,
  .assistant,
  .tri-fleche { display: none !important; }

  .appli { display: block; }
  .contenu { padding: 0; max-width: none; }

  body { background: var(--fond); color: var(--texte); font-size: 11pt; }

  .carte,
  .stat,
  .alerte,
  .verdict {
    border: 1px solid var(--bord);
    background: var(--carte);
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .tableau { font-size: 10pt; }
  .tableau thead th { position: static; background: var(--carte); }
  .tableau tr {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .tableau thead { display: table-header-group; }

  a { color: var(--texte); text-decoration: none; }

  .table-defilante { overflow: visible; }
  .tableau { min-width: 0; }
}

/* --------------------------------------------------------------------------
   16. Module tableau de bord, paramètres et compte
   Ajouts de l'agent "tableau de bord". Aucune couleur en dur : uniquement
   les variables déclarées sur :root.
   -------------------------------------------------------------------------- */

/* En-tête d'un bloc : un titre à gauche, une précision ou une action à droite */
.bloc-entete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.bloc-entete h2 { font-size: 16px; font-weight: 500; }
.bloc-entete .doux { font-size: 13px; color: var(--texte-doux); }
.bloc-entete .bouton { align-self: center; }

/* Deux cartes qui se suivent gardent le rythme de 24px, sans s'additionner */
.carte.bloc + .carte.bloc { margin-top: 0; }
.grille > .carte + .carte { margin-top: 0; }

/* Seconde ligne discrète dans une cellule : numéro de bon, échéance, rappel.
   --texte-faible est réservé aux libellés et aux mentions ; ici on porte des
   chiffres que l'économe doit vraiment lire, parfois sur une tablette en
   cuisine. On prend donc --texte-doux, nettement plus contrasté. */
.tb-second {
  display: block;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}
.tableau .num .tb-second { text-align: right; }

/* Note posée sous un tableau */
.tb-note {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--texte-doux);
}

/* Réapprovisionnement : un groupe par fournisseur */
.tb-groupe {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--bord);
}
/* Le premier groupe suit directement l'en-tête du bloc : pas de filet inutile */
.bloc-entete + .tb-groupe { margin-top: 0; padding-top: 0; border-top: 0; }

.tb-groupe-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.tb-groupe-entete h3 { font-size: 15px; font-weight: 500; }

/* Paramètres : aperçu du logo et boutons posés côte à côte */
.param-logo {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px;
  margin-bottom: 16px;
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  background: var(--fond);
}
.param-logo img { max-height: 96px; width: auto; }

.param-en-ligne { display: inline-flex; margin: 0; }

/* Nettoyage du vocabulaire des unites : le champ et son bouton cote a cote,
   et le rappel « meme unite que ... » sur l'ecriture minoritaire. */
.unite-corriger { gap: 8px; align-items: center; flex-wrap: wrap; }
.unite-corriger .champ { min-width: 0; }

/* Deux classes, et non une seule : .sous-ligne impose sa couleur grise plus
   bas dans cette feuille, et l'emporterait sur un selecteur simple. */
.sous-ligne.unite-doublon { color: var(--attention); }

/* Les fiches nommees sous une ecriture rare : des liens, mais discrets - ils
   sont un moyen d'aller voir, pas le sujet de la ligne. */
.unite-fiches a { color: var(--texte-doux); text-decoration: none; }
.unite-fiches a:hover { color: var(--accent); text-decoration: underline; }

/* Rangée de boutons sans séparateur : hors formulaire, pas de filet au-dessus */
.param-boutons {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
}

/* Case à cocher isolée, hors grille de champs */
.param-case { margin-bottom: 16px; }

/* --------------------------------------------------------------------------
   Module Sorties - ecrans sorties.php et sortie_edit.php
   --------------------------------------------------------------------------
   Rappel : sur ces ecrans, TOUTES les quantites sont en unite de suivi.
   L'unite d'achat n'apparait qu'en rappel gris sur le stock disponible.
   -------------------------------------------------------------------------- */

/* Filtre de periode, aligne sur la ligne de la barre d'outils */
.sortie-filtre {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
}
.sortie-filtre .ligne-formulaire { margin-bottom: 0; }

/* Raccourcis de periode : de simples liens, aucun bouton de plus */
.sortie-raccourcis {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin: -4px 0 16px;
  font-size: 13px;
}
.sortie-raccourcis a { color: var(--texte-doux); }
.sortie-raccourcis a:hover { color: var(--accent); }

/* Reprise d'une sortie precedente : un depliant sobre, sans onglet */
.sortie-reprise { padding: 0; }
.sortie-reprise > summary {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 10px 20px;
  list-style: none;
  cursor: pointer;
  font-size: 15px;
  color: var(--texte);
}
.sortie-reprise > summary::-webkit-details-marker { display: none; }
.sortie-reprise > summary::after {
  content: '+';
  margin-left: auto;
  padding-left: 16px;
  color: var(--texte-faible);
}
.sortie-reprise[open] > summary::after { content: '–'; }
.sortie-reprise[open] > summary { border-bottom: 1px solid var(--bord); }
.sortie-reprise-corps { padding: 12px 20px 16px; }


/* Tableau de saisie des lignes */
.sortie-nom { display: block; }

/* Rappel de ce que le point de service avait demande, quand la ligne ne le
   sert pas a elle seule. Il se lit sans se faire remarquer : c'est un repere
   de controle, pas une alerte - la sortie n'a rien d'anormal. */
.sous-ligne.sortie-demande { color: var(--texte-doux); }

.tableau .sortie-note {
  display: block;
  width: 100%;
  max-width: 220px;
  margin-top: 4px;
  min-height: 32px;
  padding: 4px 8px;
  border: 1px solid var(--bord);
  border-radius: var(--rayon-controle);
  background: var(--carte);
  color: var(--texte-doux);
  font-family: inherit;
  font-size: 13px;
}
.tableau .sortie-note:focus {
  outline: none;
  color: var(--texte);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--anneau);
}

.tableau .sortie-lot { min-width: 240px; }

/* Ligne A REGULARISER : la marchandise est la, son entree n'est pas saisie.
   Elle se distingue franchement d'une ligne ordinaire - un lot va naitre a
   l'enregistrement, ce n'est pas anodin - sans pour autant crier a l'erreur :
   c'est un geste normal, pas une faute. */
.tableau-lignes tr[data-regul] { background: var(--alerte-fond); }

.sortie-regul {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.sortie-regul .champ { min-height: 36px; font-size: 14px; }
.sortie-nlot { flex: 1 1 150px; min-width: 0; }
.sortie-dlc  { flex: 0 0 150px; }

/* Liste des sorties en attente de regularisation, sur le tableau de bord. */
.tb-regul { margin: 8px 0 0; padding-left: 20px; }
.tb-regul li { margin-bottom: 2px; }

/* Etat de la DLC : couleur de texte et pastille, jamais la ligne entiere */
.sortie-info {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

.sortie-dispo {
  color: var(--texte-doux);
  font-size: 13px;
}

.tableau .sortie-qte {
  display: inline-block;
  width: 100px;
}

.sortie-unite {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--texte-faible);
}

.sortie-alerte {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--danger);
  white-space: normal;
}

.sortie-champ-erreur { border-color: var(--danger); }
.sortie-champ-erreur:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-fond);
}

.sortie-actions {
  text-align: right;
  white-space: normal;
}
.sortie-actions button {
  display: block;
  margin-left: auto;
  text-align: right;
}

/* Le total est pousse a droite de la barre d'enregistrement */
.actions-formulaire .espaceur { flex: 1 1 auto; }

@media (max-width: 900px) {
  /* Le tableau de saisie porte un select et deux champs : il lui faut de la place */
  .tableau-lignes { min-width: 760px; }
}

/* --------------------------------------------------------------------------
   16. Module Stock, tracabilite et inventaire
   Ajout cible : rien de ce qui precede n'est modifie.
   Aucune couleur en dur, uniquement les variables declarees sur :root.
   -------------------------------------------------------------------------- */

/* Barre de filtres : des controles alignes par le bas, qui passent a la ligne */
.filtres {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 12px 16px;
  margin-bottom: 16px;
}

.filtres .filtre {
  display: flex;
  flex-direction: column;
  min-width: 150px;
}

.filtres .filtre .libelle { margin-bottom: 4px; }

.filtre-large { flex: 1 1 240px; }
.filtre-large .recherche { flex: none; max-width: none; width: 100%; }

.filtres .champ-filtre { min-width: 150px; }

.filtres .filtre-case { align-self: center; font-size: 13px; color: var(--texte-doux); }

/* Bascule entre deux vues : deux liens contigus, un seul en evidence */
.segments {
  display: inline-flex;
  border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-controle);
  overflow: hidden;
}

.segments a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 8px 16px;
  background: var(--carte);
  color: var(--texte-doux);
  font-size: 15px;
  font-weight: 400;
}
.segments a + a { border-left: 1px solid var(--bord); }
.segments a:hover { background: var(--survol); color: var(--texte); text-decoration: none; }
.segments a.actif { background: var(--accent-fond); color: var(--accent); font-weight: 500; }

/* En-tete de colonne triable */
.tri-lien { color: inherit; }
.tri-actif { color: var(--texte); font-weight: 500; }
.tri-lien:hover, .tri-actif:hover { text-decoration: underline; }

/* Colonne secondaire : presente, mais qui ne tire pas l'oeil */
.colonne-discrete { color: var(--texte-doux); font-size: 13px; }

/* Formulaire pose dans une cellule d'actions */
.actions-ligne .en-ligne { display: inline; }

/* Rappel de l'equivalent en unite d'achat, sous une valeur ou un champ.
   C'est le coeur du logiciel : "385 paquets (soit 1,9 colis)". Il se lit,
   il ne se devine pas. Donc --texte-doux, jamais --texte-faible. */
.equivalent-achat {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
  min-height: 17px;
}

/* Champ de comptage : compact et cale a droite dans sa colonne */
.champ-comptage { max-width: 130px; margin-left: auto; }

/* Ecarts d'inventaire : une couleur de texte, jamais une ligne coloree */
.ecart-plus  { color: var(--accent); }
.ecart-moins { color: var(--danger); }
.ecart-nul   { color: var(--texte-faible); }

/* Champ de recherche suivi de son bouton */
.ligne-recherche {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.recherche-large { flex: 1 1 320px; max-width: 480px; }

/* Fiche d'un lot en tracabilite */
.fiche-lot-entete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.fiche-lot-entete .doux { display: block; margin-top: 2px; }
.fiche-lot-etat { display: flex; gap: 8px; flex-wrap: wrap; }

/* Frise verticale : d'ou il vient, ce qu'il en reste, ou il est parti */
.frise {
  list-style: none;
  margin: 0;
  padding: 0 0 0 24px;
  border-left: 1px solid var(--bord);
}

.frise-etape { position: relative; padding-bottom: 24px; }
.frise-etape:last-child { padding-bottom: 0; }

.frise-etape::before {
  content: "";
  position: absolute;
  left: -30px;
  top: 5px;
  width: 9px;
  height: 9px;
  border: 1px solid var(--bord-fort);
  border-radius: 50%;
  background: var(--carte);
}
.frise-etape.etape-accent::before { border-color: var(--accent); background: var(--accent); }

.frise-titre {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 400;
  color: var(--texte-faible);
}

.frise .fiche { margin-bottom: 8px; }
.frise .fiche > div { min-width: 0; }
.frise .fiche dd .faible { display: block; }

/* Tableau imbrique dans une frise : un peu plus serre */
.tableau-compact th,
.tableau-compact td { padding: 8px 12px; }

/* Libelle reserve aux lecteurs d'ecran */
.sr-libelle {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 900px) {
  .filtres .filtre { min-width: 0; flex: 1 1 160px; }
  .filtre-large { flex: 1 1 100%; }
  .segments { width: 100%; }
  .segments a { flex: 1 1 50%; justify-content: center; }
  .champ-comptage { max-width: none; }
  .frise { padding-left: 20px; }
  .frise-etape::before { left: -26px; }
}

@media print {
  .filtres,
  .segments,
  .compteur-resultats { display: none !important; }

  /* La feuille d'inventaire s'emporte en réserve : le champ de comptage
     devient une case vide qu'on remplit au crayon. */
  .champ-comptage {
    border: 1px solid var(--bord-fort);
    background: var(--carte);
    min-height: 28px;
    max-width: 90px;
  }

  .frise-etape { break-inside: avoid; page-break-inside: avoid; }
  .fiche-lot { break-inside: avoid; page-break-inside: avoid; }
}

/* --------------------------------------------------------------------------
   16. Module Prix
   Ecrans pages/prix.php et pages/prix_produit.php.
   Ajout en fin de feuille : rien de ce qui precede n'est redefini.
   Seules exceptions a la regle du mono-accent : les couleurs de courbe, une
   par fournisseur, sans lesquelles un graphique multi-series est illisible.
   Elles ne servent QUE dans le graphique de prix et sa legende.
   -------------------------------------------------------------------------- */

:root {
  --serie-1: #15803D;
  --serie-2: #1D4ED8;
  --serie-3: #B45309;
  --serie-4: #7E22CE;
  --serie-5: #0F766E;
  --serie-6: #BE123C;
}

@media (prefers-color-scheme: dark) {
  :root {
    --serie-1: #4ADE80;
    --serie-2: #60A5FA;
    --serie-3: #FBBF24;
    --serie-4: #C084FC;
    --serie-5: #2DD4BF;
    --serie-6: #FB7185;
  }
}

.serie-1 { color: var(--serie-1); }
.serie-2 { color: var(--serie-2); }
.serie-3 { color: var(--serie-3); }
.serie-4 { color: var(--serie-4); }
.serie-5 { color: var(--serie-5); }
.serie-6 { color: var(--serie-6); }

/* Barre d'outils : les listes deroulantes de filtre ne s'etirent pas */
.filtre-champ {
  width: auto;
  min-width: 168px;
  flex: 0 1 auto;
}

/* Titre de section a l'interieur d'une carte */
.bloc-titre {
  font-size: 16px;
  font-weight: 500;
  margin: 0 0 12px;
}

/* En-tete de carte : titre a gauche, selecteur a droite */
.carte-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.carte-entete h2 { font-size: 16px; font-weight: 500; }

/* Seconde ligne discrete dans une cellule de tableau : le prix par unite
   d'achat sous le prix par unite de suivi, le fournisseur sous le montant. */
/* Le prix par unite d'achat sous le prix par unite de suivi, le fournisseur
   sous le montant : c'est la reponse a la directrice. On la lit sans effort. */
.cellule-detail {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cellule-detail.accent { color: var(--accent); }
.cellule-detail.rouge  { color: var(--alerte); }

/* Variation d'un achat a l'autre : hausse en rouge, baisse en vert */
.variation-hausse { color: var(--danger); white-space: nowrap; }
.variation-baisse { color: var(--accent); white-space: nowrap; }
.variation-stable { color: var(--texte-faible); white-space: nowrap; }

/* Le prix actuel, en tres gros : la reponse a la question posee */
.prix-vedette { padding: 20px 24px; }

.prix-vedette-valeur {
  font-size: 36px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}

.prix-vedette-unite {
  font-size: 15px;
  font-weight: 400;
  color: var(--texte-doux);
  letter-spacing: 0;
  margin-left: 4px;
}

.prix-vedette-detail {
  margin-top: 8px;
  font-size: 15px;
  color: var(--texte-doux);
}

.prix-vedette-achat {
  margin-top: 2px;
  font-size: 13px;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}

.prix-vedette-fiche {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--bord);
  font-size: 12px;
  color: var(--texte-faible);
}

/* Selecteur de periode du graphique */
.periodes {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex-wrap: wrap;
}

.periodes .periode {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 14px;
  border-radius: var(--rayon-controle);
  color: var(--texte-doux);
  font-size: 15px;
}
.periodes .periode:hover { background: var(--survol); color: var(--texte); text-decoration: none; }
.periodes .periode.actif { background: var(--accent-fond); color: var(--accent); font-weight: 500; }

/* Graphique d'evolution : SVG genere par PHP, aucune bibliotheque */
.graphique {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: 12px;
}

.graphique-svg {
  display: block;
  width: 100%;
  min-width: 680px;
  height: auto;
}

.graphique-svg .grille-svg { stroke: var(--bord); stroke-width: 1; }
.graphique-svg .axe-ligne-svg { stroke: var(--bord-fort); stroke-width: 1; }

/* Graduations du graphique : ce sont des montants, pas de la decoration.
   L'ecran est montre a la directrice, il se lit a un metre. */
.graphique-svg .axe-svg {
  fill: var(--texte-doux);
  font-family: var(--police);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.graphique-svg .ligne-svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.graphique-svg .point-svg {
  fill: var(--carte);
  stroke: currentColor;
  stroke-width: 1.75;
}
.graphique-svg .point-svg:hover { fill: currentColor; }

/* Legende : une pastille coloree, un nom de fournisseur en texte normal */
.serie-legende {
  display: flex;
  align-items: center;
  gap: 8px 20px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.serie-item {
  display: inline-flex;
  align-items: center;
  font-size: 13px;
  color: var(--texte-doux);
}

/* Les tableaux de l'ecran Prix comptent jusqu'a onze colonnes, et certains
   rappels y sont longs ("achat par colis de 200 paquets"). On les laisse
   revenir a la ligne : moins de defilement horizontal a l'ecran, et surtout un
   tableau qui tient dans la feuille a l'impression, ou la largeur est imposee.
   Les nombres, eux, restent insecables : c'est .num qui les protege. */
.tableau-prix thead th { white-space: normal; }
.tableau-prix .cellule-detail { white-space: normal; }

/* Les tableaux de l'ecran Prix comptent beaucoup de colonnes */
@media (max-width: 900px) {
  .tableau-prix { min-width: 880px; }
  .filtre-champ { width: 100%; min-width: 0; flex: 1 1 100%; }
  .carte-entete { align-items: flex-start; }
  .prix-vedette-valeur { font-size: 28px; }
}

@media print {
  /* Les filtres ne s'impriment pas : la periode figure dans les titres. */
  .periodes,
  .filtre-champ { display: none !important; }

  .graphique { overflow: visible; }
  .graphique-svg { min-width: 0; }

  /* En noir et blanc, les courbes se distinguent par leur trace. */
  :root {
    --serie-1: #000000;
    --serie-2: #333333;
    --serie-3: #555555;
    --serie-4: #000000;
    --serie-5: #333333;
    --serie-6: #555555;
  }
  .graphique-svg .serie-2 .ligne-svg { stroke-dasharray: 6 3; }
  .graphique-svg .serie-3 .ligne-svg { stroke-dasharray: 2 3; }
  .graphique-svg .serie-4 .ligne-svg { stroke-dasharray: 8 3 2 3; }
  .graphique-svg .serie-5 .ligne-svg { stroke-dasharray: 4 2; }
  .graphique-svg .serie-6 .ligne-svg { stroke-dasharray: 1 3; }

  .variation-hausse,
  .variation-baisse,
  .variation-stable { color: var(--texte); }

  .prix-vedette-valeur { font-size: 24pt; }
}

/* --------------------------------------------------------------------------
   16. Module Referentiel
   Produits, fournisseurs, zones de stockage, categories.
   Ajoute par le module referentiel : ne rien reecrire au-dessus.
   -------------------------------------------------------------------------- */

/* L'attribut hidden l'emporte sur toute regle de disposition (grille, table). */
[hidden] { display: none !important; }

/* Bouton d'envoi implicite : invisible, mais premier de son formulaire, pour que
   la touche Entree enregistre au lieu de declencher une suppression de ligne. */
.submit-implicite {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Barre d'outils : les selecteurs gardent une largeur naturelle */
.barre-outils .champ { width: auto; min-width: 168px; }
.barre-outils .case { white-space: nowrap; }

/* Fleche de tri dans un en-tete de colonne cliquable */
.tri-fleche {
  font-size: 12px;
  color: var(--texte-doux);
  margin-left: 2px;
}

/* Deuxieme ligne discrete dans une cellule de tableau */
.sous-ligne {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--texte-faible);
}

/* Couleurs de texte pour un signalement d'etat, jamais une ligne entiere */
.txt-attention { color: var(--attention); }
.txt-alerte    { color: var(--alerte); }

/* Pastille prenant la couleur d'une categorie.
   La couleur arrive en variable inline : c'est une donnee, pas une decision
   de style, et elle est validee en PHP avant d'etre ecrite. */
.pastille-couleur { background: var(--pastille-couleur, var(--texte-faible)); }

/* Carte mise en avant : le bloc Unites de la fiche produit */
.carte-appuyee { border-color: var(--bord-fort); }

/* Bloc Unites : libelle a gauche, champ au milieu, precision a droite */
.unites-ligne {
  display: grid;
  grid-template-columns: minmax(180px, 24em) minmax(120px, 220px) 1fr;
  gap: 12px;
  align-items: center;
  margin-bottom: 12px;
}

.unites-ligne > label {
  margin: 0;
  font-size: 15px;
  font-weight: 400;
  color: var(--texte);
}

.unites-suffixe {
  font-size: 13px;
  color: var(--texte-doux);
}

/* Choix d'une unite : la liste deroulante, et dessous le champ libre qui ne
   s'ouvre qu'au choix de "Autre unite". Les deux partagent la meme colonne de
   la grille, la ligne ne s'elargit donc pas quand le champ libre apparait. */
.unite-choix {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.unite-choix .champ { width: 100%; min-width: 0; }

/* Variante d'attention de l'encadre de verdict : conversion incomplete */
.verdict-attention {
  background: var(--attention-fond);
  border-color: var(--attention);
}
.verdict-attention .verdict-reponse { color: var(--attention); }

/* Tableau de saisie en ligne : zones de stockage, categories */
.tableau-saisie td {
  padding-top: 8px;
  padding-bottom: 8px;
}
.tableau-saisie .champ { min-width: 0; }
.tableau-saisie .case { min-height: 40px; }

.champ-mini { max-width: 96px; }

.champ-couleur {
  width: 48px;
  min-width: 48px;
  padding: 2px;
  cursor: pointer;
}

/* Barre de titre d'une carte, avec un lien ou un rappel a droite */
.carte-barre {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.carte-barre .carte-titre { margin-bottom: 0; }

@media (max-width: 720px) {
  .unites-ligne {
    grid-template-columns: 1fr;
    gap: 4px;
    margin-bottom: 16px;
  }
  .unites-ligne > label {
    font-size: 12px;
    color: var(--texte-faible);
  }
  .barre-outils .champ { width: 100%; }
}

/* --------------------------------------------------------------------------
   Module Entrées - écrans entrees.php et entree_edit.php
   --------------------------------------------------------------------------
   Une réception se saisit en cartes, pas en tableau : l'économe est souvent
   debout devant la palette, sur une tablette, et chaque ligne porte huit
   informations (quantité, unité de saisie, prix, lot, DLC, origine, agrément,
   zone). Un tableau les rendrait illisibles.
   Rappel d'unités : la quantité saisie peut être en unité d'ACHAT ou en unité
   de SUIVI ; le stock enregistré est toujours en unité de suivi.
   -------------------------------------------------------------------------- */

/* Une carte = une ligne de bon = un lot */
.ligne-entree {
  background: var(--carte);
  border: 1px solid var(--bord);
  border-radius: var(--rayon-carte);
  padding: 16px 20px;
}
.ligne-entree + .ligne-entree { margin-top: 12px; }

/* Un bloc masqué le reste, même quand sa classe impose un display */
.ligne-entree [hidden] { display: none; }

.ligne-entree-tete {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 16px;
}
.ligne-entree-produit { flex: 1 1 auto; min-width: 0; }
.ligne-entree-tete .bouton-discret { margin-top: 20px; }

.ligne-entree-chiffres { align-items: start; }

/* Champ suivi de son unité : "2 [colis]" ou "60,00 [€ le colis]" */
.saisie-unite {
  display: flex;
  align-items: center;
  gap: 8px;
}
.saisie-unite .champ { flex: 1 1 auto; min-width: 0; }

.champ-unite {
  flex: 0 0 auto;
  width: auto;
  min-width: 104px;
}

.suffixe-unite {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--texte-doux);
  white-space: nowrap;
}

.total-ligne {
  display: block;
  min-height: 40px;
  padding-top: 8px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Repère de variation : la comparaison porte TOUJOURS sur le prix par unité
   de suivi, jamais sur le prix du colis. */
.repere-prix {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--texte-doux);
  font-variant-numeric: tabular-nums;
}
.repere-prix.hausse { color: var(--danger); }
.repere-prix.baisse { color: var(--accent); }

/* Conditionnement : visible seulement quand le produit a une unité d'achat */
.entree-conditionnement {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 16px;
}
.entree-conditionnement .case { margin-bottom: 2px; font-size: 13px; }
.entree-conditionnement.different .champ { border-color: var(--attention); }
.entree-conditionnement.different .libelle { color: var(--attention); }

/* Assistant de prix : replié par défaut, il ne gêne personne */
.assistant { margin-top: 12px; }
.assistant > summary {
  display: flex;
  align-items: center;
  min-height: 40px;
  font-size: 13px;
  color: var(--texte-doux);
  cursor: pointer;
}
.assistant > summary:hover { color: var(--accent); }
.assistant-corps {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  padding: 4px 0 8px;
}
.assistant-corps .champ-court { max-width: 120px; }
.assistant-corps .equivalence { flex: 1 1 200px; margin-top: 0; }

.entree-lot { margin-top: 16px; }

/* Pied du bon : ajout d'une ligne à gauche, total général à droite */
.entree-pied {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 16px;
}
.entree-total-general {
  font-size: 20px;
  font-weight: 500;
  color: var(--texte);
  font-variant-numeric: tabular-nums;
}

/* Le verrou d'une entrée déjà sortie en cuisine désactive les lignes d'un bloc */
.entree-fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.actions-formulaire .espaceur { flex: 1 1 auto; }

/* Liste des entrées : rappel discret sous la valeur principale d'une cellule */
.entree-sous-ligne {
  display: block;
  font-size: 12px;
  line-height: 1.4;
  color: var(--texte-faible);
}

/* Le formulaire de suppression tient dans la cellule d'actions */
.actions-ligne form { display: inline; }

/* Boutons et raccourcis sous les champs de filtre */
.filtres-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
}

@media (max-width: 900px) {
  .ligne-entree { padding: 16px; }
  .ligne-entree-tete { flex-wrap: wrap; }
  .total-ligne { min-height: 0; padding-top: 0; }
}

/* --------------------------------------------------------------------------
   16. Module commandes
   Liste des commandes et saisie d'une commande au telephone.
   Aucune couleur en dur : uniquement les variables declarees sur :root.
   -------------------------------------------------------------------------- */


/* Seconde ligne discrete d'une cellule ou d'une ligne de saisie :
   code produit, conditionnement, stock, provenance du prix */
.cmd-meta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--texte-faible);
}

/* Formulaire de suppression pose dans une colonne d'actions */
.cmd-form-inline { display: inline; }

/* --- Saisie d'une commande ----------------------------------------------- */

.cmd-nom {
  display: block;
  font-size: 15px;
  line-height: 1.4;
}


/* Un champ et son unite, cote a cote */
.cmd-saisie {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.cmd-unite {
  font-size: 12px;
  color: var(--texte-faible);
  white-space: nowrap;
}

/* Conditionnement : replie par defaut, deplie a la demande */
.cmd-cond { display: block; margin-top: 6px; }

.cmd-coef {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}
.cmd-coef[hidden] { display: none; }
.cmd-coef .libelle { margin: 0; }
.cmd-coef .champ { width: 84px; }

/* Colonnes du tableau de saisie */
.cmd-tableau .cmd-col-produit { width: 42%; }
.cmd-tableau .cmd-col-qte     { width: 168px; }
.cmd-tableau .cmd-col-prix    { width: 210px; }
.cmd-tableau .cmd-col-total   { width: 110px; }
.cmd-tableau .cmd-col-retirer { width: 80px; text-align: right; }

.cmd-tableau .cmd-col-qte .champ  { width: 88px; }
.cmd-tableau .cmd-col-prix .champ { width: 104px; }

.cmd-tableau td { vertical-align: top; padding-top: 14px; }

/* Etat vide du tableau de saisie */
.cmd-aucune {
  padding: 32px 0;
  text-align: center;
  color: var(--texte-doux);
}

/* Actions de bas de page : envoyer, supprimer */
.cmd-pied {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--bord);
}
.cmd-supprimer:hover { color: var(--danger); }

/* Une ligne de saisie de commande. L'en-tete du tableau est collant : sans
   cette marge, la ligne qu'on vient d'ajouter se glisse dessous au moment ou
   le script amene le curseur sur sa quantite. */
.cmd-ligne { scroll-margin-top: 56px; }

/* Le commentaire ferme le bloc : pas de marge en trop sous la carte. */
.cmd-commentaire { margin-bottom: 0; }

@media (max-width: 900px) {
  /* Le tableau de saisie defile horizontalement plutot que de se tasser */
  .cmd-tableau { min-width: 700px; }
}

/* Un en-tete de colonne ne se cache jamais : seules les actions des lignes
   apparaissent au survol. */
.tableau thead th.actions-ligne { opacity: 1; }

/* --------------------------------------------------------------------------
   Feuilles - le plan des menus sur quatre semaines
   --------------------------------------------------------------------------
   La grille se lit comme un calendrier : quatre lignes, sept colonnes. Chaque
   case est un lien qui remplit toute la cellule, pour qu'on n'ait pas a viser
   trois mots sur une tablette.
   -------------------------------------------------------------------------- */

/* Un produit que le stock couvre deja : il reste dans le tableau - c'est la
   preuve qu'il a ete regarde - mais il ne doit pas retenir l'oeil. */
.besoin-couvert td { opacity: 0.6; }

/* Les deux faces d'une journee : ce qui sort du stock, ce qu'on en fait.
   Deux onglets, et non deux entrees de menu : on ne quitte pas la journee. */
.onglets-jour {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--bord);
}

.onglet-jour {
  padding: 10px 18px;
  font-size: 15px;
  color: var(--texte-doux);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.onglet-jour:hover { color: var(--texte); }

.onglet-actif {
  color: var(--accent);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

/* La zone de saisie d'un menu : une ligne, un plat. Chasse fixe pour que les
   lignes s'alignent comme sur la fiche imprimee. */
.champ-menu {
  min-height: 150px;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.7;
  resize: vertical;
}

/* --------------------------------------------------------------------------
   La fiche de menu a placarder en cuisine
   --------------------------------------------------------------------------
   Reprend le modele que l'econome imprime deja : logo, « MENU DU JOUR », le
   numero de semaine en cartouche, le jour en bandeau, puis un bloc par service
   dont le nom se lit a la VERTICALE. Tout en capitales, gros, lisible a deux
   metres sur un mur de cuisine.
   -------------------------------------------------------------------------- */

.fiche-menu {
  max-width: 780px;
  margin: 0 auto;
  padding: 24px 16px 48px;
  color: #000;
}

.fiche-menu-outils {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-bottom: 20px;
}

.fiche-menu-tete {
  display: grid;
  grid-template-columns: 200px 1fr 110px;
  align-items: stretch;
  border: 2px solid #000;
}
.fiche-menu-tete > * {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 12px;
  min-height: 62px;
}
.fiche-menu-logo { border-right: 2px solid #000; }
.fiche-menu-logo img { max-height: 46px; max-width: 100%; object-fit: contain; }
.fiche-menu-etab { font-weight: 700; font-size: 15px; text-align: center; }

.fiche-menu-titre {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.fiche-menu-semaine {
  border-left: 2px solid #000;
  font-size: 30px;
  font-weight: 700;
}

.fiche-menu-jour {
  border: 2px solid #000;
  border-top: 0;
  padding: 10px;
  text-align: center;
  font-size: 26px;
  font-weight: 700;
  text-transform: uppercase;
}

.fiche-menu-service {
  display: grid;
  grid-template-columns: 92px 1fr;
  border: 2px solid #000;
  margin-top: 26px;
  min-height: 210px;
}

/* Le nom du service, ecrit de bas en haut le long du bloc. */
.fiche-menu-nom {
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 2px solid #000;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 34px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.fiche-menu-plats {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  gap: 12px;
  padding: 18px 16px;
}

.fiche-menu-plat {
  text-align: center;
  font-size: 17px;
  line-height: 1.35;
  text-transform: uppercase;
}
.fiche-menu-role { font-weight: 700; margin-right: 6px; }

.fiche-menu-rien { text-align: center; color: var(--texte-faible); margin-top: 32px; }

@media print {
  /* Seule la fiche s'imprime : ni boutons, ni barre laterale. */
  .fiche-menu-outils { display: none !important; }
  .fiche-menu { max-width: none; padding: 0; }
  .fiche-menu-service { break-inside: avoid; page-break-inside: avoid; }
}

@media (max-width: 640px) {
  .fiche-menu-tete { grid-template-columns: 120px 1fr 64px; }
  .fiche-menu-titre { font-size: 20px; }
  .fiche-menu-semaine { font-size: 20px; }
  .fiche-menu-jour { font-size: 19px; }
  .fiche-menu-service { grid-template-columns: 58px 1fr; min-height: 160px; }
  .fiche-menu-nom { font-size: 22px; }
  .fiche-menu-plat { font-size: 15px; }
}

/* Navigation d'une feuille a l'autre : la precedente, ou l'on est, la suivante.
   Le cycle boucle - apres S4 dimanche vient S1 lundi - et les deux cotes sont
   des cibles larges, pour se suivre au doigt sur une tablette. */
.feuille-nav {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}

.feuille-nav-cote {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 1 auto;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid var(--bord-fort);
  border-radius: var(--rayon-controle);
  background: var(--carte);
  color: var(--texte-doux);
  text-decoration: none;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.feuille-nav-cote:hover { color: var(--accent); border-color: var(--accent); }
.feuille-nav-apres { justify-content: flex-end; }

.feuille-nav-fleche { font-size: 18px; line-height: 1; }

.feuille-nav-ici {
  display: inline-flex;
  align-items: center;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--texte);
  white-space: nowrap;
}

@media (max-width: 560px) {
  /* Sur telephone, le rappel du milieu disparait : le titre de la page le dit
     deja, et les deux fleches ont besoin de toute la largeur. */
  .feuille-nav-ici { display: none; }
  .feuille-nav-cote { flex: 1 1 0; min-width: 0; }
}

.tbl-feuilles th { white-space: nowrap; }

.feuille-semaine {
  white-space: nowrap;
  font-weight: 600;
  color: var(--texte);
}

.feuille-case { padding: 0 !important; }

.feuille-case > a {
  display: block;
  padding: 10px 12px;
  min-height: 56px;
  text-decoration: none;
  color: var(--texte);
}
.feuille-case > a:hover { background: var(--fond); }

.feuille-nb {
  display: block;
  font-size: 14px;
  white-space: nowrap;
}

/* Le jour du cycle ou l'on se trouve : c'est celui qu'on vient chercher. */
.feuille-aujourdhui > a { box-shadow: inset 3px 0 0 var(--accent); }
.feuille-aujourdhui .feuille-nb { font-weight: 600; color: var(--accent); }

/* Ajout d'un produit : recherche, quantite, bouton. Sur telephone les trois
   s'empilent plutot que de se serrer. */
.feuille-ajout {
  display: grid;
  grid-template-columns: minmax(220px, 2fr) minmax(120px, 1fr) auto;
  gap: 16px;
  align-items: start;
  margin-bottom: 16px;
}
.feuille-ajout .ligne-formulaire { margin: 0; min-width: 0; }
.feuille-cherche { position: relative; }
.feuille-bouton { padding-top: 22px; }

/* Recopier et vider : deux gestes rares, ranges ensemble sous la liste du
   service, pour ne pas se confondre avec l ajout de produits. */
.feuille-outils {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

@media (max-width: 720px) {
  .feuille-ajout { grid-template-columns: 1fr; gap: 12px; }
  .feuille-bouton { padding-top: 0; }
}

/* --------------------------------------------------------------------------
   Formulaire public de demande
   --------------------------------------------------------------------------
   Ouvert sur des telephones d'equipe dont on ne sait rien : cibles larges,
   une ligne par produit, rien qui depende de JavaScript.
   -------------------------------------------------------------------------- */

/* En-tete : le logo de l'etablissement et son nom. La demandeuse doit voir du
   premier coup d'oeil a quelle maison elle s'adresse - le lien lui arrive par
   messagerie, souvent sans un mot d'explication. Le logo est borne en HAUTEUR
   et non en largeur : on ne sait pas s'il sera carre ou en bandeau. */
/* Logo a gauche, maison a droite, ecartes aux deux bords : la demandeuse voit
   d'un coup a qui elle s'adresse, comme sur un en-tete de courrier. Ils etaient
   colles l'un a l'autre, ce qui les faisait lire comme un seul bloc. */
.demande-entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 24px;
}

.demande-logo {
  flex: 0 0 auto;
  height: 52px;
  width: auto;
  max-width: 180px;
  object-fit: contain;
}

.demande-maison {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  min-width: 0;
}

.demande-etab {
  font-size: 17px;
  font-weight: 600;
  color: var(--texte);
  line-height: 1.3;
}

.demande-ville {
  font-size: 13px;
  color: var(--texte-faible);
}

@media (max-width: 480px) {
  .demande-entete { gap: 10px; margin-bottom: 18px; }
  .demande-logo { height: 40px; max-width: 130px; }
  .demande-etab { font-size: 15px; }
}

.demande-points {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

.demande-points .bouton { flex: 1 1 200px; justify-content: center; }

.demande-ligne {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.demande-ligne .champ { flex: 1 1 220px; min-height: 44px; }
.demande-ligne .champ-court { flex: 0 1 130px; }

/* --------------------------------------------------------------------------
   Le formulaire de demande sur un telephone
   --------------------------------------------------------------------------
   C'est l'ecran des equipes, et elles l'ouvrent sur leur telephone. En
   tableau, il faisait 560 px de large dans 341 disponibles : il fallait
   glisser lateralement pour atteindre la case quantite, et on ne voyait alors
   plus le nom du produit. Sur un bon de commande papier, le nom et la case
   sont cote a cote ; ici ils doivent l'etre aussi.

   Chaque produit devient donc une LIGNE : son nom a gauche, sa case a droite,
   l'unite entre les deux. Le tableau reste un tableau sur grand ecran.
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
  #tbl-demande,
  #tbl-demande tbody,
  #tbl-demande tr,
  #tbl-demande td {
    display: block;
    width: auto;
  }

  /* Sous 900 px, .tableau recoit min-width: 560px : les tableaux de gestion
     doivent defiler plutot que de se tasser. Celui-ci ne se tasse pas, il
     change de forme - il faut donc lever ce plancher, sans quoi la ligne
     garde 560 px de large et le nom du produit refuse de se replier. */
  #tbl-demande { min-width: 0; }

  /* Les intitules de colonnes n'ont plus de colonnes a coiffer. */
  #tbl-demande thead { display: none; }

  /* DEUX LIGNES par produit : son nom, puis sa quantite et son unite.
     Le nom dispose ainsi de toute la largeur - « BARQUETTE RONDE TYPE 250 -
     AVEC COUVERCLE » ne se replie plus dans une colonne de 190 px. */
  #tbl-demande tbody tr:not(.ligne-groupe) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid var(--bord);
  }

  /* Le nom occupe toute la premiere ligne et force le retour a la suivante. */
  #tbl-demande tbody tr:not(.ligne-groupe) > td:first-child {
    flex: 0 0 100%;
    padding: 0;
  }
  #tbl-demande tbody tr:not(.ligne-groupe) > td:first-child label {
    display: block;
    line-height: 1.35;
  }

  /* Seconde ligne : la case D'ABORD, l'unite ensuite. Dans le tableau elles
     sont dans l'autre sens ; « order » les echange a l'affichage, sans toucher
     au HTML - qui doit rester un vrai tableau pour les grands ecrans. */
  #tbl-demande tbody tr:not(.ligne-groupe) > td:last-child {
    order: 1;
    flex: 0 0 96px;
    padding: 0;
    text-align: left;
  }
  #tbl-demande tbody tr:not(.ligne-groupe) > td:nth-child(2) {
    order: 2;
    flex: 0 0 auto;
    padding: 0;
    font-size: 14px;
    white-space: nowrap;
  }

  /* 44 px : la cible tactile confortable. 16 px de texte : en dessous, Safari
     sur iPhone ZOOME la page des qu'on touche le champ, et la demandeuse se
     retrouve a devoir dezoomer entre chaque ligne. */
  #tbl-demande .champ-court {
    max-width: none;
    width: 100%;
    min-height: 44px;
    font-size: 16px;
    text-align: center;
  }

  /* La categorie devient un intertitre, pas une ligne de tableau. */
  #tbl-demande tr.ligne-groupe { display: block; }
  #tbl-demande tr.ligne-groupe td {
    padding: 14px 0 6px;
    border: 0;
    border-bottom: 1px solid var(--bord-fort);
    background: transparent;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }

  /* UNE LIGNE MASQUEE DOIT LE RESTER. Le filtre de recherche pose l'attribut
     hidden, dont le display:none par defaut est MOINS fort que les regles
     ci-dessus : sans ce rappel, taper dans la recherche ferait reapparaitre
     tout ce qu'elle vient d'ecarter. */
  #tbl-demande tr[hidden] { display: none !important; }

  /* Le bouton d'envoi, au pouce. */
  .bouton-large { min-height: 48px; font-size: 16px; }

  /* Le choix du service est le tout premier geste, et il se fait debout, un
     chariot dans l'autre main : 40 px etaient un peu justes. */
  .demande-points { gap: 8px; }
  .demande-points .bouton {
    flex: 1 1 100%;
    min-height: 48px;
    font-size: 16px;
  }
}

/* Demandes recues : une demande classee reste lisible, mais s'efface. */
.demande-classee { opacity: 0.72; }
.actions-formulaire .en-ligne { display: inline; }

/* Le QR du formulaire de demande : cadre blanc, taille d'impression utile. */
.qr-cadre {
  display: inline-block;
  padding: 8px;
  background: #FFFFFF;
  border: 1px solid var(--bord);
  border-radius: 8px;
  line-height: 0;
}

.qr-cadre svg { width: 220px; height: 220px; }

@media print {
  .qr-cadre { border: 0; }
  .qr-cadre svg { width: 300px; height: 300px; }
}

/* --------------------------------------------------------------------------
   Champ produit du formulaire de demande : on tape, la liste se reduit.
   --------------------------------------------------------------------------
   La liste deroulante d'origine reste dans le formulaire, hors de vue : c'est
   elle qui porte la valeur envoyee. On ne la met pas en display:none, un champ
   ainsi cache cesserait d'etre atteignable par certains lecteurs d'ecran.
   -------------------------------------------------------------------------- */

.combo { position: relative; flex: 1 1 220px; }
.combo .champ { width: 100%; }

.combo-source {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* .recherche-ajout : la carte « Ajouter un produit » d'Entrees, Sorties,
   Commandes et Dotation.
   Elle ne porte AUCUNE declaration ici, et c'est voulu : le champ doit prendre
   toute la largeur de sa carte, comme n'importe quel champ de l'application.
   Commandes portait un conteneur a max-width: 520px que les trois autres
   n'avaient pas - d'ou l'impression de passer d'une application a une autre.
   La classe ne sert donc qu'a deux choses : nommer le motif, et le faire
   disparaitre a l'impression (voir la liste display:none du @media print).
   Un champ de recherche vide n'a rien a faire sur un papier. */

/* La liste se pose SOUS le champ, dans le flux, et pousse ce qui suit.
   Elle etait en position absolue : elle se placait alors par rapport au
   premier ancetre positionne, et la ou il n'y en avait pas - la page de
   dotation - elle partait au pied de l'ecran ou dans le coin haut-gauche.
   Dans le flux, elle ne peut plus s'echapper, sur aucun ecran ni telephone. */
.combo-liste {
  margin-top: 4px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--carte);
  border: 1px solid var(--bord-fort);
  border-radius: 8px;
}

/* Seule exception : la recherche « changer » ouverte DANS une ligne d'entree.
   La pousser dans le flux ecarterait les champs de la ligne pendant la frappe.
   Son conteneur .combo est positionne, la superposition est donc sure. */
.combo .combo-liste {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  top: 100%;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
}

.combo-choix {
  display: block;
  width: 100%;
  padding: 10px 12px;
  min-height: 44px;
  border: 0;
  background: none;
  text-align: left;
  font-size: 15px;
  color: var(--texte);
  cursor: pointer;
}

.combo-choix:hover,
.combo-choix:focus { background: var(--accent-fond); }
.combo-vide { padding: 12px; color: var(--texte-doux); font-size: 14px; }

/* L'unite du produit retenu, a cote de la quantite. */
.demande-unite {
  align-self: center;
  min-width: 48px;
  font-size: 14px;
  color: var(--texte-doux);
}

/* Les raccourcis par categorie : des pastilles, pas un tableau. */
.dotation-categories {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

/* Une proposition de recherche : le nom, puis le detail en gris dessous.
   Sur une seule ligne, « ASSERT LEMON - 5L l · Produits d'entretien » se lit
   mal - l'unite colle au nom. */
.combo-choix .combo-nom    { display: block; }
.combo-choix .combo-detail { display: block; font-size: 13px; color: var(--texte-doux); }

/* Entrees : le produit d'une ligne, et de quoi en changer. */
.ligne-entree-nom { font-weight: 500; margin-right: 8px; }

/* Proposition sous le curseur des fleches : meme marque que le survol. */
.combo-choix.actif { background: var(--accent-fond); }

/* L'oeil des mots de passe --------------------------------------------------
   L'enveloppe et le bouton sont poses par le JavaScript, jamais ecrits dans
   les pages : sans JavaScript, rien de tout ceci n'existe et le champ reste
   un champ ordinaire. */

.champ-mdp { position: relative; }

/* La place du bouton, pour qu'un mot de passe long ne passe pas dessous. */
.champ-mdp > .champ { padding-right: 44px; }

.mdp-oeil {
  position: absolute;
  top: 1px;
  right: 1px;
  bottom: 1px;          /* dans la bordure du champ, jamais par-dessus */
  width: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--texte-faible);
  cursor: pointer;
  border-radius: 0 var(--rayon-controle) var(--rayon-controle) 0;
}

.mdp-oeil:hover { color: var(--texte); }

.mdp-oeil:focus-visible {
  outline: none;
  color: var(--texte);
  box-shadow: 0 0 0 3px var(--anneau);
}

.mdp-oeil svg { display: block; width: 18px; height: 18px; }
