/*
 * Charte de la Ferme des Condémines.
 *
 * Les teintes viennent du même nuancier que l'application Android (ui/theme/Color.kt).
 * Deux écarts assumés, hérités de ce fichier :
 *   — la charte n'a pas de rouge d'alerte, il a fallu en ajouter un fonctionnel ;
 *   — sauge, bronze et grège sont des couleurs d'aplat : en texte sur fond clair
 *     elles passent sous le seuil de lisibilité, d'où les variantes assombries.
 *
 * Les polices de la charte sont servies depuis assets/polices/, en woff2 avec un
 * repli woff. Les fichiers viennent du jeu web fourni avec la charte — celui qui
 * contient .woff2, .eot et .svg, formats qui n'existent que pour le web.
 */

/*
 * DEUX FORMATS, ET UN SEUL EST TÉLÉCHARGÉ.
 *
 * Le navigateur prend le premier qu'il sait lire : woff2 partout depuis 2016,
 * woff pour ce qui est plus ancien. Les .eot, .ttf et .svg du jeu d'origine ne
 * sont pas repris — le premier ne sert qu'à Internet Explorer, le deuxième pèse
 * le double sans rien apporter, le troisième n'est plus lu par personne.
 *
 * « font-display: swap » affiche tout de suite le texte dans la police de repli
 * et le rebascule à l'arrivée de la vraie. Sans lui, un titre reste INVISIBLE
 * jusqu'à ce que sa police soit téléchargée — trois secondes de page blanche sur
 * une liaison lente, pour un gain esthétique de trois secondes.
 */
/*
 * LA VARIANTE EST « CONDENSED », COMME SUR LE SITE PRINCIPAL.
 *
 * www.fermedescondemines.ch declare MotterCorpusStd-Condensed sous le nom
 * « motterCorpusStd » et l'applique a ses titres, a son menu et a ses boutons.
 * La Regular du meme jeu a un dessin proche mais une chasse nettement plus
 * large : passer d'un site a l'autre se serait vu, sans qu'on sache dire ce
 * qui avait change. Les trois sites portent donc la meme.
 */
@font-face {
  font-family: 'Motter Corpus';
  src: url('/assets/polices/MotterCorpusStd-Condensed.woff2') format('woff2'),
       url('/assets/polices/MotterCorpusStd-Condensed.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Daytona Condensed';
  src: url('/assets/polices/DaytonaW04-CondensedLight.woff2') format('woff2'),
       url('/assets/polices/DaytonaW04-CondensedLight.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

:root {
  --sapin:   #265656;
  --ardoise: #435760;
  --sauge:   #6CA490;
  --foret:   #29433A;
  --creme:   #FEF0C1;
  --miel:    #F4C86A;
  --bronze:  #B98C4C;
  --orange:  #E56D38;
  --rose:    #D3777F;
  --grege:   #807E76;

  /* Variantes assombries, pour le texte uniquement. */
  --sauge-texte:  #3F7A66;
  --bronze-texte: #8A6733;
  --grege-texte:  #5E5C55;

  /* Rouge fonctionnel : absent de la charte, nécessaire pour les alertes. */
  --alerte: #B3382C;

  --fond:        #F7F5EF;
  --fond-carte:  #FFFFFF;
  --bordure:     #E2DED2;
  --texte:       #23302F;
  --texte-doux:  var(--grege-texte);

  --titre: 'Motter Corpus', Georgia, 'Times New Roman', serif;
  --corps: 'Daytona Condensed', 'Segoe UI', system-ui, -apple-system, sans-serif;

  /*
   * LES CHIFFRES NE PRENNENT PAS LA POLICE DE LA CHARTE, et c'est une décision,
   * pas un oubli.
   *
   * Daytona Condensed n'existe qu'en Light : étroite ET maigre. Sur un titre,
   * c'est ce qui fait son caractère ; dans une colonne de montants à 14 pixels,
   * un 3 et un 8 se ressemblent, et cet écran-là sert à relire de la
   * comptabilité. Les montants, les quantités et les totaux gardent donc une
   * police système, avec des chiffres à chasse fixe pour que les colonnes
   * s'alignent.
   *
   * Pour revenir en arrière, il suffit de pointer cette variable sur --corps.
   */
  --chiffres: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', sans-serif;

  --rayon: 10px;
  --ombre: 0 1px 2px rgba(35, 48, 47, .06), 0 4px 12px rgba(35, 48, 47, .05);
}

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

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--corps);
  font-size: 16px;
  line-height: 1.5;
}

h1, h2, h3 { font-family: var(--titre); font-weight: 600; color: var(--foret); }
h1 { font-size: 1.7rem; margin: 0 0 1.25rem; }
h2 { font-size: 1.2rem; margin: 0 0 .75rem; }

a { color: var(--sapin); }
code { background: var(--creme); padding: .1em .35em; border-radius: 4px; font-size: .9em; }

/* Lien d'évitement : visible seulement au clavier, pour atteindre le contenu. */
.saut-contenu {
  position: absolute; left: -9999px;
  background: var(--sapin); color: #fff; padding: .6rem 1rem; z-index: 10;
}
.saut-contenu:focus { left: .5rem; top: .5rem; }

/* ---------------------------------------------------------- Structure */

.cadre { min-height: 100vh; display: flex; flex-direction: column; }

/*
 * ═══════════════════════════════════════════════════════════════════════════
 * LA BARRE VERTE PORTE TOUT : marque, menu, compte.
 * ═══════════════════════════════════════════════════════════════════════════
 *
 * Le menu a d'abord occupe une colonne de gauche, puis une bande sous l'en-tete.
 * Les deux gaspillaient une hauteur : la colonne poussait seize liens au-dessus
 * du contenu sur telephone, la bande ajoutait un second bandeau sous une barre
 * verte aux trois quarts vide.
 */
.entete {
  background: var(--sapin); color: var(--creme);
  padding: 0;
}
.entete-cadre {
  display: flex; align-items: center; gap: .4rem 1rem;
  min-height: 52px;
}

.marque { display: flex; flex-direction: column; line-height: 1.15;
  color: var(--creme); text-decoration: none; margin-right: .5rem; }
.marque-nom  { font-family: var(--titre); font-size: 1.05rem; white-space: nowrap; }
.marque-sous { font-size: .8rem; opacity: .75; letter-spacing: .08em; text-transform: uppercase; }
.marque-centree { align-items: center; margin-bottom: 1.5rem; color: var(--sapin); }

/* Le compte est pousse a droite : « auto » sur la marge gauche suffit. */
.compte { display: flex; align-items: center; gap: .75rem; font-size: .88rem;
  margin-left: auto; white-space: nowrap; }
.compte-nom { font-weight: 600; }
.compte .bouton-lien { color: var(--creme); }

/* --------------------------------------------------------------- Le menu */

.menu { display: flex; align-items: center; gap: .15rem; flex-wrap: wrap; }

/*
 * UNE SEULE APPARENCE POUR UN LIEN ET POUR UNE RUBRIQUE. Le <summary> d'un
 * deroulant et le <a> d'une entree unique portent la meme classe : rien dans la
 * barre ne doit laisser deviner lequel des deux ouvrira un panneau.
 */
.menu-lien {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .35rem .6rem; border-radius: var(--rayon);
  color: var(--creme); text-decoration: none; font-size: .95rem;
  white-space: nowrap; cursor: pointer; list-style: none;
}
.menu-lien::-webkit-details-marker { display: none; }
.menu-lien:hover { background: rgba(254, 240, 193, .14); }

/* La rubrique ou l'on se trouve : un fond clair, lisible sur le vert. */
.menu-lien--ici { background: var(--creme); color: var(--foret); font-weight: 600; }
.menu-lien--ici:hover { background: var(--creme); }

.rubrique { position: relative; }
.rubrique-fleche {
  width: 0; height: 0; border-left: 4px solid transparent;
  border-right: 4px solid transparent; border-top: 5px solid currentColor;
  opacity: .8;
}
.rubrique[open] > .menu-lien > .rubrique-fleche { transform: rotate(180deg); }

/*
 * LE PANNEAU FLOTTE AU-DESSUS DU CONTENU.
 *
 * « position: absolute » plutot qu'un deplacement du flux : sans lui, ouvrir une
 * rubrique pousserait toute la page vers le bas, et le clic suivant viserait
 * ce qui vient de bouger.
 */
.rubrique-panneau {
  position: absolute; top: calc(100% + .35rem); left: 0; z-index: 20;
  min-width: 12rem; margin: 0; padding: .35rem;
  list-style: none;
  background: var(--fond-carte); color: var(--texte);
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  box-shadow: var(--ombre);
}
.rubrique-panneau a {
  display: block; padding: .45rem .6rem; border-radius: var(--rayon);
  color: var(--texte); text-decoration: none; white-space: nowrap;
}
.rubrique-panneau a:hover { background: var(--creme); }
.rubrique-panneau a[aria-current="page"] { background: var(--sapin); color: var(--creme); }

/*
 * LE MEME DEROULANT, SUR FOND CLAIR.
 *
 * Le filtre du journal des sorties reprend la mecanique de la barre du haut —
 * <details>, panneau flottant, un seul ouvert a la fois — mais il vit sur la
 * page et non sur le vert. Seules les couleurs du bouton changent ; le panneau,
 * lui, etait deja clair.
 */
.filtres-menus { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.filtre-bouton {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .4rem .7rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: var(--fond-carte);
  color: var(--texte); cursor: pointer; list-style: none; font-size: .95rem;
}
.filtre-bouton::-webkit-details-marker { display: none; }
.filtre-bouton:hover { border-color: var(--texte-doux); }
.filtre-etiquette { font-size: .78rem; color: var(--texte-doux); }

/* Les fleches de mois : un pas en arriere, un pas en avant, sans ouvrir de menu. */
.filtre-fleche {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: var(--fond-carte);
  color: var(--texte); text-decoration: none;
}
.filtre-fleche:hover { border-color: var(--texte-doux); }

/* Douze mois en une colonne feraient un panneau plus haut que l'ecran. */
.panneau-mois { display: grid; grid-template-columns: repeat(2, 1fr); gap: .1rem; }
.panneau-annees {
  grid-column: 1 / -1; display: flex; gap: .2rem;
  margin-top: .3rem; padding-top: .35rem; border-top: 1px solid var(--bordure);
}
.panneau-annees a { flex: 1; text-align: center; font-family: var(--chiffres); }

/*
 * UNE BASCULE PLUTOT QU'UNE CASE A COCHER. Une case sans bouton ne fait rien,
 * et avec bouton demande deux gestes : le lien, lui, applique en un clic et
 * porte son etat dans son adresse — donc dans l'historique du navigateur.
 */
.filtre-bascule { text-decoration: none; }
.filtre-bascule--actif {
  background: var(--sapin); color: var(--creme); border-color: var(--sapin);
}
.filtre-bascule--actif:hover { border-color: var(--foret); }

/* Le compte d'une espece, sous son nom dans le menu. */
.rubrique-panneau .unite-ligne { display: block; font-size: .78rem; }

/*
 * L'EFFACEMENT EST REPLIE, ET SON BOUTON EST ROUGE.
 *
 * Poser une periode et en effacer une sont deux gestes voisins dans le meme
 * bloc : les mettre cote a cote, de meme taille et de meme couleur, ferait
 * cliquer l'un pour l'autre. Celui qui detruit se demande donc, et se confirme.
 */
.vider-periode { margin-top: 1rem; border-top: 1px solid var(--bordure); padding-top: .8rem; }
.vider-periode > summary {
  cursor: pointer; font-size: .88rem; color: var(--texte-doux);
  list-style: none; display: inline-block;
}
.vider-periode > summary::-webkit-details-marker { display: none; }
.vider-periode > summary::before { content: '▸ '; }
.vider-periode[open] > summary::before { content: '▾ '; }
.vider-periode > summary:hover { color: var(--alerte); }
.vider-periode[open] > summary { margin-bottom: .6rem; color: var(--alerte); }

/*
 * Une ligne de correspondance comptable : la source, le compte, le mot du
 * libelle, et le bouton.
 *
 * « .ligne-compta » A DISPARU AVEC LE FORMULAIRE EN LIGNE. Les quatre elements
 * etaient un flex dans une cellule « colspan=4 », sous trois en-tetes qui ne
 * les surmontaient donc pas — « Mot du libelle » ne tombait pas au-dessus du
 * champ du meme nom. Chacun a maintenant sa cellule, et c'est le tableau qui
 * aligne.
 *
 * Le champ du compte prend toute sa colonne : « 3300 Autres produits des
 * productions vegetales (sans detail) » fait soixante caracteres, et le
 * tronquer a l'ecran ferait douter de ce qui est range.
 */
/*
 * LA COLONNE DU COMPTE PREND TOUTE LA PLACE QUI RESTE. Sans cela, le tableau
 * partage sa largeur a parts a peu pres egales et le champ le plus long — celui
 * qui doit porter soixante caracteres — se retrouve aussi etroit que le mot du
 * libelle, qui en porte six.
 */
.tableau-compta th:nth-child(2), .tableau-compta td:nth-child(2) { width: 100%; }
.tableau-compta th:nth-child(1), .tableau-compta td:nth-child(1) { white-space: nowrap; }
.compta-source { font-weight: 600; }
.champ-compte {
  width: 100%; min-width: 12rem; font: inherit;
  padding: .35rem .55rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: #fff;
}

.bouton-danger { background: var(--alerte); }
.bouton-danger:hover { background: #8E2A21; }

/*
 * LE BOUTON N'EXISTE QUE SI LE SCRIPT TOURNE.
 *
 * Masque par defaut, revele par la classe « entete--js » que pose
 * assets/menu.js. Sans script, le menu reste entierement visible : degrade,
 * jamais inutilisable. L'inverse aurait cache la navigation derriere un bouton
 * mort.
 */
.menu-bouton { display: none; }
.menu-barres {
  display: inline-block; width: 1rem; height: 2px; background: currentColor;
  position: relative;
}
.menu-barres::before, .menu-barres::after {
  content: ''; position: absolute; left: 0; width: 1rem; height: 2px;
  background: currentColor;
}
.menu-barres::before { top: -5px; }
.menu-barres::after  { top: 5px; }

/*
 * LE MEME CADRE POUR LA BARRE ET LE CONTENU : meme boite, meme marge, donc
 * meme premiere colonne. Sans lui, la barre s'etale sur toute la largeur
 * pendant que le contenu s'arrete a 1100 px.
 */
.cadre-large { max-width: 1100px; margin: 0 auto; padding: 0 2rem; width: 100%; }

.contenu { flex: 1; padding: 1.75rem 2rem; max-width: 1100px; margin: 0 auto;
  width: 100%; min-width: 0; }

/* ---------------------------------------------------------- Chiffres */

.chiffres {
  display: grid; gap: 1rem; margin-bottom: 1.75rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.chiffre {
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: 1rem 1.15rem; box-shadow: var(--ombre);
}
.chiffre-accent { border-left: 4px solid var(--miel); }
.chiffre-etiquette {
  margin: 0 0 .3rem; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--texte-doux);
}
.chiffre-valeur {
  margin: 0; font-family: var(--titre); font-size: 1.9rem;
  line-height: 1.1; color: var(--foret);
}
/*
 * UN CHIFFRE QUI EST UN MOT SE PORTE PLUS PETIT. Un nom de client ou une date
 * a la taille d'un total — 1,9 rem — deborde la carte et crie plus fort que le
 * montant d'a cote. Ces trois cas l'ecrivaient en ligne, « style="font-size:
 * 1.2rem" », que la politique de securite bloque : ils s'affichaient donc en
 * grand. Une classe repetee trois fois etait de toute facon une classe qui
 * manquait.
 */
.chiffre-valeur--texte { font-size: 1.2rem; }
.chiffre-valeur span { font-size: .95rem; color: var(--texte-doux); }
.chiffre-detail { margin: .35rem 0 0; font-size: .88rem; color: var(--texte-doux); }

.bloc {
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: 1.25rem 1.4rem;
  box-shadow: var(--ombre); margin-bottom: 1.5rem;
}


/* ------------------------------------------------------- Bloc « Ce qui tourne »

   IL MESURE LE SILENCE, PAS LA BONNE SANTÉ. Le rapport quotidien a cessé de
   partir le 24 août 2026 et personne ne s'en est aperçu pendant vingt jours : un
   courriel qui n'arrive pas ne produit aucune erreur.

   D'où le parti pris visuel : AU REPOS, CE BLOC EST DISCRET. Un tableau de bord
   qui crie quand tout va bien devient un tableau de bord qu'on ne lit plus, et
   c'est exactement le résultat qu'on cherche à éviter. Il ne prend de la couleur
   que lorsqu'un voyant passe en alerte.
   -------------------------------------------------------------------------- */

.sante {
  background: var(--fond-carte);
  border: 1px solid var(--bordure);
  border-left: 3px solid var(--sauge);
  border-radius: var(--rayon);
  padding: 1rem 1.2rem;
  margin-bottom: 1.5rem;
}

/* Le filet de gauche vire au rouge dès qu'un seul point est en alerte : c'est ce
   qu'on voit du coin de l'œil sans avoir lu une ligne. */
.sante-inquiete { border-left-color: var(--alerte); }

.sante h2 {
  margin: 0 0 .7rem;
  font-size: 1rem;
}

.sante-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .45rem;
}

/*
 * Trois colonnes sur un écran large, empilées sur un téléphone.
 *
 * Le détail passe à la ligne et occupe toute la largeur : c'est la phrase qui
 * dit quoi faire, et elle ne doit pas se faire tronquer par une colonne étroite.
 */
.sante-point {
  display: grid;
  grid-template-columns: minmax(9rem, auto) auto 1fr;
  align-items: baseline;
  gap: .2rem .8rem;
  padding: .35rem 0 .35rem .9rem;
  border-left: 3px solid transparent;
  font-size: .9rem;
}

.sante-titre  { font-weight: 600; }
.sante-valeur { font-family: var(--chiffres); color: var(--texte-doux); white-space: nowrap; }
.sante-detail { color: var(--texte-doux); font-size: .85rem; }

/*
 * VERT DISCRET, ROUGE FRANC, GRIS POUR CE QU'ON NE SAIT PAS.
 *
 * L'état « inconnu » existe pour ne pas crier au loup sur une base qui vient
 * d'être mise en service : rien n'était enregistré avant le 13 septembre 2026, et
 * un écran qui s'alarme le jour de sa naissance apprend à être ignoré.
 */
.sante-ok      { border-left-color: var(--sauge); }
.sante-alerte  { border-left-color: var(--alerte); background: #FBEEEC; border-radius: 0 6px 6px 0; }
.sante-inconnu { border-left-color: var(--grege); }

.sante-alerte .sante-titre,
.sante-alerte .sante-valeur { color: var(--alerte); }
.sante-alerte .sante-detail { color: #8A2E24; }

/*
 * CE QUI VA BIEN : UN BOUTON VERT, SON NOM, RIEN D'AUTRE. Ils passent à la
 * ligne d'eux-mêmes sur un téléphone ; la phrase de chacun reste au survol.
 * Gris en pointillé pour ce qu'on ne sait pas encore — ni vert, ni rouge.
 */
.sante-calme {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin: 0; font-size: .85rem;
}
.sante-liste + .sante-calme { margin-top: .8rem; }
.sante-pastille {
  padding: .25rem .7rem; border-radius: 999px; border: 1px solid transparent;
  white-space: nowrap; cursor: default;
}
.sante-pastille.sante-ok { background: var(--sauge-texte); color: #FFFFFF; }
.sante-pastille.sante-inconnu { color: var(--texte-doux); border-color: var(--bordure); border-style: dashed; }

/*
 * LE SUIVI DES COMMANDES, sur l'accueil : du travail à faire, pas une alerte.
 * Des boutons cerclés de vert sapin plutôt que pleins — on les distingue des
 * voyants de santé, verts pleins, qui disent au contraire que rien n'est à faire.
 */
.suivi-commandes {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin: 0 0 1.2rem; font-size: .9rem;
}
.suivi-titre { font-weight: 600; margin-right: .3rem; }
.suivi-bouton {
  padding: .3rem .8rem; border: 1px solid var(--sapin); border-radius: 999px;
  color: var(--sapin); text-decoration: none; background: var(--fond-carte);
}
.suivi-bouton:hover { background: var(--sapin); color: var(--creme); }

@media (max-width: 720px) {
  .sante-point {
    grid-template-columns: 1fr auto;
  }
  /* Le détail sous les deux autres, sur toute la largeur. */
  .sante-detail { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------- Tableaux */

.tableau { width: 100%; border-collapse: collapse; font-size: .93rem; }
.tableau th {
  text-align: left; padding: .5rem .6rem; border-bottom: 2px solid var(--bordure);
  font-size: .78rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--texte-doux); font-weight: 600;
}
.tableau td { padding: .55rem .6rem; border-bottom: 1px solid var(--bordure); }
.tableau tr:last-child td { border-bottom: none; }

/* ---------------------------------------------------------- Messages */

.message {
  padding: .7rem 1rem; border-radius: var(--rayon);
  margin: 0 0 1.25rem; border-left: 4px solid;
}
.message-ok     { background: #EEF6F2; border-color: var(--sauge);  color: var(--foret); }
.message-alerte { background: var(--creme); border-color: var(--miel); color: var(--bronze-texte); }
.message-erreur { background: #FBEEEC; border-color: var(--alerte); color: var(--alerte); }

.etiquette {
  display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  background: var(--creme); color: var(--bronze-texte);
  font-size: .75rem; text-transform: uppercase; letter-spacing: .05em;
}
.etiquette-ok     { background: #EEF6F2; color: var(--sauge-texte); }
.etiquette-alerte { background: #FBEEEC; color: var(--alerte); }

/* ---------------------------------------------------------- Formulaires */

.formulaire { display: flex; flex-direction: column; gap: .3rem; }
.formulaire label { font-size: .88rem; color: var(--texte-doux); margin-top: .7rem; }
.formulaire input {
  font: inherit; padding: .6rem .7rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon);
  background: #fff; color: var(--texte);
}
.formulaire input:focus-visible,
.menu a:focus-visible,
.bouton:focus-visible,
.bouton-lien:focus-visible {
  outline: 2px solid var(--sapin); outline-offset: 2px;
}

.bouton {
  display: inline-block; font: inherit; cursor: pointer;
  padding: .6rem 1.1rem; border: none; border-radius: var(--rayon);
  background: var(--sapin); color: var(--creme); text-decoration: none;
}
.bouton:hover { background: var(--foret); }
.bouton-large { margin-top: 1.2rem; width: 100%; }

.bouton-lien {
  font: inherit; cursor: pointer; padding: 0; border: none;
  background: none; color: inherit; text-decoration: underline; opacity: .85;
}
.bouton-lien:hover { opacity: 1; }
.en-ligne { display: inline; }

/* ---------------------------------------------------------- Page seule */

.page-seule {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 1.5rem;
}
.carte-seule {
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); box-shadow: var(--ombre);
  padding: 2rem; width: 100%; max-width: 380px;
}
.titre-connexion { text-align: center; font-size: 1.35rem; }
.titre-erreur { font-family: var(--titre); font-size: 3rem; margin: 0; color: var(--bronze-texte); }
.sous-titre-erreur { margin: 0 0 1rem; font-size: 1.1rem; color: var(--foret); }

/* ---------------------------------------------------------- Petits écrans */

/*
 * LA MEME BORNE QUE menu.js — 720 px. Deux nombres pour une seule decision se
 * contredisent toujours un jour : changer celui-ci demande de changer l'autre.
 */
@media (max-width: 720px) {
  .cadre-large { padding: 0 1rem; }
  .entete-cadre { flex-wrap: wrap; padding-top: .5rem; padding-bottom: .5rem; }
  .marque-nom { font-size: .95rem; }

  /* Le bouton, des que le script a pose sa classe. Il pousse le compte a droite
     et le menu passe a la ligne dessous. */
  .entete--js .menu-bouton {
    display: inline-flex; align-items: center; gap: .55rem;
    font: inherit; font-size: .9rem;
    padding: .4rem .7rem; border: 1px solid rgba(254, 240, 193, .35);
    border-radius: var(--rayon); background: transparent; color: var(--creme);
    cursor: pointer; margin-left: auto;
  }
  .entete--js .compte { margin-left: .6rem; }
  .entete--js .menu { flex-basis: 100%; }

  /* Replie : le menu disparait, la page commence tout de suite. */
  .entete--replie .menu { display: none; }

  /*
   * EN COLONNE ET NON EN BARRE : seize liens qui passent a la ligne redeviennent
   * exactement le mur qu'on vient d'enlever. Et les panneaux reprennent leur
   * place dans le flux — un deroulant flottant au-dessus d'un menu deja
   * deroulant n'aide personne.
   */
  .menu { flex-direction: column; align-items: stretch; gap: 0;
    padding: .4rem 0 .6rem; }
  .menu-lien { justify-content: space-between; padding: .55rem .6rem; }
  .rubrique-panneau {
    position: static; min-width: 0; margin: .1rem 0 .3rem .6rem;
    box-shadow: none; background: rgba(254, 240, 193, .1);
    border-color: rgba(254, 240, 193, .25);
  }
  .rubrique-panneau a { color: var(--creme); }
  .rubrique-panneau a:hover { background: rgba(254, 240, 193, .15); }

  /*
   * LE COMPTE ENTRE DANS LE MENU.
   *
   * Sur 375 px, « Jordan Voirin · Se deconnecter » ne tenait pas a cote de la
   * marque et du bouton : il prenait une deuxieme rangee de barre verte, sur
   * toutes les pages. Il passe donc sous le menu, et disparait avec lui quand
   * il est replie.
   *
   * Se deconnecter devient un geste en deux touches au lieu d'une. C'est le bon
   * echange : on se deconnecte une fois par jour, on lit une page cent fois.
   */
  .compte { font-size: .85rem; gap: .5rem; flex-basis: 100%;
    margin-left: 0; padding: .2rem .6rem .1rem; }
  .compte .etiquette { display: none; }
  .entete--replie .compte { display: none; }

  /*
   * Sans « min-width: 0 », le contenu prend la largeur de ce qu'il contient :
   * un tableau un peu large deborde alors la page entiere, et
   * .tableau-defilant ne defile jamais — son cadre ayant grandi avec le tableau
   * au lieu de le contenir.
   */
  .contenu { padding: 1.25rem 1rem; min-width: 0; }
}

/* ---------------------------------------------------------- Catalogue */

.barre-actions {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.resume { margin: 0; color: var(--texte-doux); }
.discret { color: var(--texte-doux); }
/*
 * « .a-droite » DOIT BATTRE « .tableau th », ET NE LE FAISAIT PAS.
 *
 * « .tableau th » vaut (0,1,1) en specificite, « .a-droite » (0,1,0) : la
 * regle generale des en-tetes l'emportait. Consequence, jamais remarquee : dans
 * TOUS les tableaux du site, un en-tete de colonne de chiffres restait aligne a
 * gauche pendant que ses valeurs s'alignaient a droite. « Total » et « Prix
 * unitaire » ne tombaient au-dessus de rien.
 *
 * On monte donc « .a-droite » au meme niveau, sur les deux sortes de cellules,
 * plutot que d'ajouter un !important qui deplacerait le probleme.
 */
/* Ce qui suit un tableau et n'y colle pas : meme respiration qu'entre blocs. */
.apres-tableau { margin-top: 1.2rem; }

.a-droite,
.tableau th.a-droite,
.tableau td.a-droite { text-align: right; }

/*
 * CENTRE, POUR LES EN-TETES QUI COIFFENT UN GROUPE DE COLONNES.
 *
 * Meme piege de specificite que « .a-droite » ci-dessus, et meme parade. Un
 * « <th colspan=3> » cale a gauche se lit au-dessus de la PREMIERE colonne du
 * groupe, pas au-dessus du groupe : « Attente en jours » semblait titrer la
 * colonne « Lait » et laisser les deux autres sans nom. Centre, il coiffe ce
 * qu'il annonce — c'est aussi ce que fait le formulaire papier.
 */
.au-centre,
.tableau th.au-centre,
.tableau td.au-centre { text-align: center; }

.filtres {
  display: flex; align-items: flex-end; gap: .75rem; flex-wrap: wrap;
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: .9rem 1rem; margin-bottom: 1.25rem;
}
.filtres label {
  display: block; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texte-doux); margin-bottom: .2rem;
}
.filtres input, .filtres select {
  font: inherit; padding: .45rem .6rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: #fff;
}

/* Un tableau de 120 lignes deborde sur un petit ecran : il defile dans son
   propre cadre, jamais la page entiere. */
.tableau-defilant { overflow-x: auto; }

.ligne-retiree { opacity: .55; }
.ligne-retiree td:nth-child(2) { text-decoration: line-through; }

.cellule-icone { width: 40px; }
.vignette {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 6px; background: var(--creme);
  object-fit: contain;
}
.vignette-vide { font-size: .7rem; color: var(--texte-doux); }

/* ---------------------------------------------------------- Fiche produit */

.formulaire-fiche {
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); box-shadow: var(--ombre); padding: 1.4rem;
}
.grille-champs {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.champ { margin-bottom: 1rem; }
.champ label {
  display: block; font-size: .88rem; color: var(--texte-doux); margin-bottom: .25rem;
}
/* « date » est dans la liste depuis le journal des traitements. Il y manquait :
   un champ de date posé dans une .grille-champs sortait nu au milieu de champs
   encadrés, sur une largeur décidée par le navigateur. */
.champ input[type="text"], .champ input[type="number"],
.champ input[type="date"], .champ select {
  font: inherit; width: 100%; padding: .55rem .7rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: #fff;
}
.champ-case label { display: flex; align-items: center; gap: .5rem; font-size: 1rem; color: var(--texte); }
.champ-case input { width: auto; }
.aide { margin: .3rem 0 0; font-size: .82rem; color: var(--texte-doux); }
.erreur-champ { margin: .3rem 0 0; font-size: .85rem; color: var(--alerte); }

fieldset.champ { border: 1px solid var(--bordure); border-radius: var(--rayon); padding: 1rem; }
fieldset.champ legend { font-size: .88rem; color: var(--texte-doux); padding: 0 .4rem; }

/*
 * UN TRAITEMENT DONT UNE DENRÉE EST ENCORE SOUS DÉLAI D'ATTENTE.
 *
 * C'est le seul endroit de ce projet où une couleur porte autre chose qu'une
 * information de gestion : elle dit qu'il ne faut pas livrer. La ligne est donc
 * teintée, et suivie d'une bande qui l'écrit en toutes lettres — une date dans
 * une colonne se lit, elle ne se remarque pas.
 *
 * Le miel plutôt que le rouge : rien n'est cassé, rien n'est en faute. Une bête
 * sous délai d'attente est un traitement qui suit son cours normalement.
 */
/*
 * Les cases à cocher des bêtes d'un traitement.
 *
 * Une grille plutôt qu'une colonne : dix-huit bêtes en pile font défiler le
 * formulaire sur deux écrans, et on ne voit plus ce qu'on a coché.
 */
.grille-cases {
  display: grid; gap: .3rem .9rem;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  margin-bottom: .8rem;
}
.case-bete {
  display: flex; align-items: baseline; gap: .5rem;
  padding: .25rem .4rem; border-radius: var(--rayon);
}
.case-bete:hover { background: var(--creme); }
.case-bete input { width: auto; margin: 0; }
.etiquette-groupe {
  margin: .6rem 0 .2rem; font-size: .82rem; color: var(--texte-doux);
  text-transform: uppercase; letter-spacing: .04em;
}

/* Un lot, par opposition à une bête nommée. */
.etiquette {
  display: inline-block; padding: .05rem .4rem; border-radius: 999px;
  background: var(--bordure); color: var(--texte-doux); font-size: .74rem;
}

/* Une bête sortie du cheptel : présente pour l'histoire, plus pour le travail. */
.ligne-sortie > td { opacity: .55; }
.ligne-note > td { border-top: 0; padding-top: 0; font-size: .85rem; color: var(--bronze-texte); }
.champ-motif { font: inherit; padding: .3rem .5rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: #fff; }

/*
 * L'intertitre d'espèce dans le cheptel.
 *
 * La liste est triée par espèce de toute façon : le dire ici économise une
 * colonne répétée dix-huit fois et donne des repères pour parcourir la page.
 */
.ligne-groupe > th {
  background: var(--creme); text-align: left;
  font-size: .8rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--bronze-texte); padding-top: .5rem; padding-bottom: .5rem;
}

/*
 * Les actions d'une bête, repliées.
 *
 * Cette page se lit bien plus souvent qu'elle ne s'écrit : sortir une bête
 * arrive quelques fois par an, consulter la liste arrive à chaque traitement.
 * Vingt-quatre formulaires dépliés en faisaient un mur.
 *
 * <details> est du HTML natif — rien à charger, et surtout rien que la politique
 * de contenu du site puisse bloquer en silence, contrairement à un gestionnaire
 * écrit dans un attribut.
 */
.actions-bete > summary {
  cursor: pointer; list-style: none;
  font-size: .85rem; color: var(--texte-doux);
  padding: .1rem .45rem; border: 1px solid var(--bordure); border-radius: var(--rayon);
  display: inline-block;
}
.actions-bete > summary::-webkit-details-marker { display: none; }
.actions-bete > summary:hover { color: var(--texte); border-color: var(--texte-doux); }
.actions-bete[open] > summary { margin-bottom: .5rem; }
.actions-bete .ligne-formulaire { justify-content: flex-end; margin-bottom: .3rem; }
.actions-bete input[type="date"], .actions-bete .champ-motif {
  font: inherit; padding: .3rem .5rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: #fff;
}
/* Le champ de motif ne doit pas pousser la colonne : la liste reste maîtresse
   de sa largeur, le formulaire s'y plie. */
.actions-bete .champ-motif { flex: 0 1 11rem; min-width: 0; }

/* Sans la marque auriculaire, une ligne de cheptel tient en peu de place. */
.tableau-cheptel td { vertical-align: top; }

/*
 * La grille du journal des sorties : trente et une lignes, une par jour.
 *
 * Serrée volontairement. C'est un calendrier qu'on parcourt du regard pour
 * repérer les trous, pas un formulaire qu'on lit ligne à ligne — la même
 * fonction que la grille du papier, où un mois tient sur une colonne.
 */
.tableau-sorties td, .tableau-sorties th { padding-top: .25rem; padding-bottom: .25rem; }
/*
 * « .ligne-jour » A DISPARU AVEC LE FORMULAIRE EN LIGNE. La saisie du jour
 * etait un flex dans une cellule « colspan=4 », sous quatre en-tetes qui ne la
 * decrivaient donc pas. Chaque controle a maintenant sa cellule, et c'est le
 * tableau qui aligne — ces regles visent la colonne, plus le formulaire.
 */
.tableau-sorties .champ-case { font-size: .9rem; }
.tableau-sorties select.champ-motif { max-width: 16rem; width: 100%; }

/* P et S : les deux lettres du formulaire, reconnaissables d'un coup d'œil. */
.marque-sortie {
  display: inline-block; min-width: 1.1rem; text-align: center;
  font-family: var(--chiffres); font-weight: 600; color: var(--foret);
}

/* Les dimanches et jours fériés sont grisés sur le formulaire officiel. */
.jour-weekend > td { background: var(--creme); }

/*
 * PLUSIEURS CATEGORIES COTE A COTE. Un trait separe chaque categorie, le motif
 * se resserre, et la colonne du jour reste visible quand le tableau defile a
 * l'horizontale — sinon, a la quatrieme categorie, on coche sans savoir quel
 * jour.
 */
.tableau-sorties--plusieurs .entete-categorie { border-left: 2px solid var(--bordure); }
.tableau-sorties--plusieurs th.entete-categorie .aide { display: block; font-weight: normal; }
.tableau-sorties--plusieurs select.champ-motif { max-width: 9rem; }
/* thead : seulement la premiere ligne — dans la seconde, le premier en-tete
   est le « P » de la premiere categorie, « Jour » la couvrant deja. */
.tableau-sorties--plusieurs tbody td:first-child,
.tableau-sorties--plusieurs thead tr:first-child th:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--fond-carte);
}
.tableau-sorties--plusieurs .jour-weekend > td:first-child { background: var(--creme); }

/* Le menu des categories : une case pour combiner, le nom pour n'en voir qu'une. */
.panneau-categories ul { list-style: none; margin: 0; padding: 0; }
.panneau-categories li { display: flex; align-items: center; gap: .3rem; padding-left: .35rem; }
.panneau-categories li input { width: auto; }
.panneau-categories li a { flex: 1; }
.panneau-categories-actions {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin-top: .35rem; padding-top: .35rem; border-top: 1px solid var(--bordure);
}
.jour-aujourdhui > td { box-shadow: inset 2px 0 0 var(--sauge); }
/* Un jour à venir : la ligne existe pour pouvoir la préparer, mais rien n'y
   est encore reprochable. */
.jour-futur > td { opacity: .5; }

.ligne-retenue > td { background: var(--creme); }
.ligne-retenue-detail > td {
  background: var(--creme);
  color: var(--bronze-texte);
  border-top: 0;
  padding-top: 0;
  font-size: .88rem;
}

.grille-icones {
  display: grid; gap: .6rem;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
}
.choix-icone {
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  padding: .5rem; border: 1px solid var(--bordure); border-radius: var(--rayon);
  cursor: pointer; text-align: center;
}
.choix-icone:has(input:checked) { border-color: var(--sapin); background: var(--creme); }
.choix-icone .vignette { width: 40px; height: 40px; }
.nom-icone { font-size: .75rem; color: var(--texte-doux); }

/* ------------------------------------------------- Bibliothèque d'icônes */

.compte-icones { margin: 0 0 .85rem; }

/*
 * Une grille de dessins, pas de formulaires. Les tuiles sont petites : ce qu'on
 * vient chercher sur cette page, c'est reconnaître une image parmi trente.
 */
.bibliotheque {
  display: grid; gap: .7rem; margin-bottom: 1.75rem;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  align-items: start;
}

.tuile-icone > summary, .tuile-fixe {
  display: flex; flex-direction: column; align-items: center; gap: .45rem;
  margin: 0; padding: .8rem .55rem; text-align: center;
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon);
}
.tuile-icone > summary { cursor: pointer; }
/* Le triangle par défaut ne veut rien dire sur une vignette, et il décale le
   contenu. Les deux règles sont nécessaires : la seconde pour WebKit. */
.tuile-icone > summary { list-style: none; }
.tuile-icone > summary::-webkit-details-marker { display: none; }
.tuile-icone > summary:hover,
.tuile-icone > summary:focus-visible { border-color: var(--sapin); background: var(--creme); }

.vignette-tuile { width: 72px; height: 72px; flex: none; border-radius: 8px; }
.nom-tuile {
  font-size: .8rem; line-height: 1.3; color: var(--texte-doux);
  /* Deux lignes réservées : sans cela, « Miel » et « Pommes de terre de
     conservation » donnent des tuiles de hauteurs différentes et la rangée
     devient irrégulière. */
  min-height: 2.1rem;
  /* Un nom sans espace ne doit pas élargir la tuile et casser la grille. */
  overflow-wrap: anywhere;
}

/*
 * Ouverte, la tuile prend toute la largeur de la rangée et son encart se déplie
 * dessous. C'est ce qui évite de faire pousser une colonne toute seule, ce qui
 * décalerait toutes les tuiles voisines.
 */
.tuile-icone[open] { grid-column: 1 / -1; }
.tuile-icone[open] > summary {
  flex-direction: row; justify-content: flex-start; text-align: left; gap: .8rem;
  border-radius: var(--rayon) var(--rayon) 0 0; border-bottom: none;
  background: var(--creme);
}
.tuile-icone[open] > summary .nom-tuile {
  font-size: 1rem; color: var(--texte); font-weight: 600; min-height: 0;
}

.encart-icone {
  display: flex; flex-direction: column; gap: 1rem;
  padding: 1.1rem 1.2rem;
  background: var(--fond-carte);
  border: 1px solid var(--bordure); border-top: none;
  border-radius: 0 0 var(--rayon) var(--rayon);
}
.meta-icone { margin: 0; font-size: .8rem; }

.formulaire-icone { display: flex; flex-direction: column; gap: .9rem; }
.formulaire-icone .champ { margin-bottom: 0; }
.champs-icone { display: flex; gap: .8rem; align-items: flex-start; flex-wrap: wrap; }
.champ-extensible { flex: 1 1 14rem; min-width: 0; }
/* Le rang tient sa largeur ici, et non sur le champ : « .champ input » impose
   width 100 %, et une classe seule perdrait contre ce sélecteur plus précis. */
.champ-rang { flex: 0 0 5.5rem; }
.formulaire-icone input[type="file"] { max-width: 100%; font-size: .82rem; }
.formulaire-icone .bouton { align-self: flex-start; }

.retrait-icone { padding-top: .9rem; border-top: 1px solid var(--bordure); font-size: .88rem; }

/* Le champ d'envoi de la fiche produit, sous la grille de choix. */
.envoi-icone { margin: 1rem 0 0; }
.envoi-icone input[type="file"] { max-width: 100%; font-size: .82rem; }

.ligne-formulaire { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.ligne-formulaire input[type="text"] {
  font: inherit; padding: .4rem .6rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: #fff; flex: 1 1 12rem;
}
.ligne-formulaire input[type="number"] {
  font: inherit; padding: .4rem .6rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: #fff;
}
.petit-champ { width: 5rem; }

/*
 * Un champ suivi de son unité — « 30 % ».
 *
 * L'unité est du texte à côté du champ, et non un mot dans l'étiquette ou une
 * amorce grisée à l'intérieur : une amorce disparaît dès qu'on tape, et c'est
 * précisément au moment où l'on saisit un nombre qu'on veut savoir en quoi il
 * s'exprime.
 */
.avec-suffixe { display: flex; align-items: center; gap: .4rem; }
.avec-suffixe .suffixe { color: var(--grege-texte); }

/* ---------------------------------------------------------- Actions en lot */

.barre-lot {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  background: var(--fond-carte); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: .7rem 1rem; margin-bottom: .75rem;
}
.barre-lot select {
  font: inherit; padding: .4rem .6rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: #fff;
}
.etiquette-lot {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--texte-doux);
}
#compteur-selection { margin-right: auto; }

/* Un bouton desactive doit se voir desactive : sinon on clique sans effet et on
   croit le site en panne. */
.bouton:disabled { opacity: .45; cursor: not-allowed; }
.bouton:disabled:hover { background: var(--sapin); }

.cellule-case { width: 34px; }
.cellule-case input { width: 1.05rem; height: 1.05rem; cursor: pointer; }

/* ---------------------------------------------------- Statistiques */

/*
 * Le graphique est un SVG en ligne, pas une image : il hérite donc de cette
 * feuille de style, et la charte reste définie à un seul endroit. Le viewBox
 * fait le reste — le dessin s'étire à la largeur disponible sans qu'aucune
 * mesure ne soit refaite côté PHP.
 */
.cadre-graphique { overflow-x: auto; }
.graphique { display: block; width: 100%; height: 260px; }
.graphique .barre { fill: var(--sapin); }
.graphique .barre:hover { fill: var(--foret); }
/* Une tranche sans vente : un trait, pour qu'un creux se distingue d'un trou. */
.graphique .barre-vide { fill: var(--bordure); }
.graphique .axe { stroke: var(--bordure); stroke-width: 1; }
.graphique .etiquette-axe { fill: var(--texte-doux); font-size: 11px; font-family: var(--corps); }

.detail-chiffres { margin-top: 1rem; }
.detail-chiffres > summary { cursor: pointer; color: var(--texte-doux); font-size: .9rem; }

.classement { list-style: none; margin: 0; padding: 0; display: grid; gap: .9rem; }
.classement-tete { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.classement-nom { overflow-wrap: anywhere; }
.classement-valeur {
  font-family: var(--chiffres);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.classement-detail { margin: .25rem 0 0; font-size: .8rem; }

.jauge { height: 8px; border-radius: 999px; background: var(--bordure); overflow: hidden; }
.jauge-part { display: block; height: 100%; width: 0; background: var(--sauge); border-radius: 999px; }

/*
 * ═══════════════════════════════════════════════════════════════════════════
 * CENT UNE LARGEURS, PARCE QU'UN « style » EN LIGNE NE S'APPLIQUE PAS ICI
 * ═══════════════════════════════════════════════════════════════════════════
 *
 * Ces barres portaient leur largeur dans « style="width: 65%" ». La politique
 * de sécurité du site est « default-src 'self' » sans « style-src » : faute de
 * directive propre, « style-src-attr » retombe sur « default-src », et le
 * navigateur BLOQUE l'attribut. Vérifié en servant exactement cet en-tête —
 * « Applying inline style violates the following Content Security Policy
 * directive 'default-src 'self'' … The action has been blocked. »
 *
 * Rien ne le signalait à l'écran : les barres se dessinaient toutes de la même
 * largeur, ce qui ressemble à des données et n'en est pas. C'est la pire sorte
 * de panne — celle qui s'affiche.
 *
 * Une classe par pour cent entier lève l'interdit sans l'assouplir. Cent une
 * règles pèsent deux kilo-octets dans un fichier déjà mis en cache, et « .jauge
 * -part » garde « width: 0 » pour qu'une classe oubliée donne une barre vide
 * plutôt qu'une barre pleine : l'absence doit se voir comme une absence.
 */
.jauge-part--0 { width: 0%; }
.jauge-part--1 { width: 1%; }
.jauge-part--2 { width: 2%; }
.jauge-part--3 { width: 3%; }
.jauge-part--4 { width: 4%; }
.jauge-part--5 { width: 5%; }
.jauge-part--6 { width: 6%; }
.jauge-part--7 { width: 7%; }
.jauge-part--8 { width: 8%; }
.jauge-part--9 { width: 9%; }
.jauge-part--10 { width: 10%; }
.jauge-part--11 { width: 11%; }
.jauge-part--12 { width: 12%; }
.jauge-part--13 { width: 13%; }
.jauge-part--14 { width: 14%; }
.jauge-part--15 { width: 15%; }
.jauge-part--16 { width: 16%; }
.jauge-part--17 { width: 17%; }
.jauge-part--18 { width: 18%; }
.jauge-part--19 { width: 19%; }
.jauge-part--20 { width: 20%; }
.jauge-part--21 { width: 21%; }
.jauge-part--22 { width: 22%; }
.jauge-part--23 { width: 23%; }
.jauge-part--24 { width: 24%; }
.jauge-part--25 { width: 25%; }
.jauge-part--26 { width: 26%; }
.jauge-part--27 { width: 27%; }
.jauge-part--28 { width: 28%; }
.jauge-part--29 { width: 29%; }
.jauge-part--30 { width: 30%; }
.jauge-part--31 { width: 31%; }
.jauge-part--32 { width: 32%; }
.jauge-part--33 { width: 33%; }
.jauge-part--34 { width: 34%; }
.jauge-part--35 { width: 35%; }
.jauge-part--36 { width: 36%; }
.jauge-part--37 { width: 37%; }
.jauge-part--38 { width: 38%; }
.jauge-part--39 { width: 39%; }
.jauge-part--40 { width: 40%; }
.jauge-part--41 { width: 41%; }
.jauge-part--42 { width: 42%; }
.jauge-part--43 { width: 43%; }
.jauge-part--44 { width: 44%; }
.jauge-part--45 { width: 45%; }
.jauge-part--46 { width: 46%; }
.jauge-part--47 { width: 47%; }
.jauge-part--48 { width: 48%; }
.jauge-part--49 { width: 49%; }
.jauge-part--50 { width: 50%; }
.jauge-part--51 { width: 51%; }
.jauge-part--52 { width: 52%; }
.jauge-part--53 { width: 53%; }
.jauge-part--54 { width: 54%; }
.jauge-part--55 { width: 55%; }
.jauge-part--56 { width: 56%; }
.jauge-part--57 { width: 57%; }
.jauge-part--58 { width: 58%; }
.jauge-part--59 { width: 59%; }
.jauge-part--60 { width: 60%; }
.jauge-part--61 { width: 61%; }
.jauge-part--62 { width: 62%; }
.jauge-part--63 { width: 63%; }
.jauge-part--64 { width: 64%; }
.jauge-part--65 { width: 65%; }
.jauge-part--66 { width: 66%; }
.jauge-part--67 { width: 67%; }
.jauge-part--68 { width: 68%; }
.jauge-part--69 { width: 69%; }
.jauge-part--70 { width: 70%; }
.jauge-part--71 { width: 71%; }
.jauge-part--72 { width: 72%; }
.jauge-part--73 { width: 73%; }
.jauge-part--74 { width: 74%; }
.jauge-part--75 { width: 75%; }
.jauge-part--76 { width: 76%; }
.jauge-part--77 { width: 77%; }
.jauge-part--78 { width: 78%; }
.jauge-part--79 { width: 79%; }
.jauge-part--80 { width: 80%; }
.jauge-part--81 { width: 81%; }
.jauge-part--82 { width: 82%; }
.jauge-part--83 { width: 83%; }
.jauge-part--84 { width: 84%; }
.jauge-part--85 { width: 85%; }
.jauge-part--86 { width: 86%; }
.jauge-part--87 { width: 87%; }
.jauge-part--88 { width: 88%; }
.jauge-part--89 { width: 89%; }
.jauge-part--90 { width: 90%; }
.jauge-part--91 { width: 91%; }
.jauge-part--92 { width: 92%; }
.jauge-part--93 { width: 93%; }
.jauge-part--94 { width: 94%; }
.jauge-part--95 { width: 95%; }
.jauge-part--96 { width: 96%; }
.jauge-part--97 { width: 97%; }
.jauge-part--98 { width: 98%; }
.jauge-part--99 { width: 99%; }
.jauge-part--100 { width: 100%; }

/*
 * La quantité d'une ligne de commande, corrigeable sur place.
 *
 * SES RÈGLES SONT À ELLE, ET NE PASSENT PAS PAR « .ligne-formulaire ». Celui-ci
 * pose « flex: 1 1 12rem » sur ses champs texte, ce qui ferait déborder une
 * colonne de nombres — et « .petit-champ » ne le rattraperait pas, une base flex
 * l'emportant sur une largeur. Deux règles qui se battent dans une colonne
 * étroite, c'est le genre de chose qui se répare trois fois.
 *
 * Le champ garde l'alignement à droite et les chiffres tabulaires de la colonne :
 * elle doit rester lisible en diagonale même quand chaque ligne porte une boîte
 * de saisie. Pas de bouton ici : chaque champ vise « form-lignes » par son
 * attribut « form », et un seul bouton, sous le tableau, enregistre toutes les
 * lignes changées d'un coup — voir OrderController::editLignes.
 */
.cellule-quantite {
  display: flex; align-items: center; justify-content: flex-end; gap: .35rem;
}
.cellule-quantite input[type="text"] {
  font: inherit;
  font-family: var(--chiffres);
  font-variant-numeric: tabular-nums;
  width: 4.75rem;
  text-align: right;
  padding: .25rem .4rem;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  background: #fff;
}
.unite-ligne { color: var(--texte-doux); font-size: .85rem; }

/* La remarque d'une ligne, dans « .cellule-quantite » : le champ voisin de la
   quantité, mais pas un chiffre — « 8 poivrons » ne s'aligne pas à droite et
   ne tient pas dans une largeur pensée pour trois caractères. */
.cellule-quantite input.champ-remarque {
  font-family: inherit;
  font-variant-numeric: normal;
  width: 10rem;
  text-align: left;
  flex: 1 1 auto;
}

/* Le tableau de produits de la page « Nouvelle commande » : une quantité et
   une remarque par ligne du catalogue, cote a cote avec le prix — pas de
   « .champ » ni de « .ligne-formulaire » ici, la boîte de saisie ne l'hérite
   donc de nulle part ailleurs. */
.tableau-produits input[type="text"] {
  font: inherit; padding: .35rem .55rem; border: 1px solid var(--bordure);
  border-radius: var(--rayon); background: #fff;
}
.tableau-produits td:nth-child(4) input[type="text"] { width: 100%; }

/* Les montants s'alignent sur la virgule : des chiffres de largeurs inégales
   rendent une colonne de sommes pénible à parcourir. */
.chiffre-cellule {
  font-family: var(--chiffres);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ecart-manque   { color: var(--alerte); }
.ecart-excedent { color: var(--sauge-texte); }
.ecart-juste    { color: var(--texte-doux); }

.groupe-unite + .groupe-unite { margin-top: 1.5rem; }
.titre-unite {
  display: flex; justify-content: space-between; gap: 1rem; align-items: baseline;
  flex-wrap: wrap; font-size: 1rem; margin: 0 0 .7rem;
}
.titre-unite .discret { font-family: var(--corps); font-size: .85rem; font-weight: 400; }
/* Une teinte distincte des montants : une quantité n'est pas de l'argent, et
   deux jauges de la même couleur inviteraient à les comparer entre elles. */
.jauge-quantite { background: var(--miel); }

/* L'état et son bouton de bascule, sur une ligne de produit. */
.cellule-etat { white-space: nowrap; }
.cellule-etat .bouton-lien { margin-left: .5rem; font-size: .85rem; }

/* Une quantité n'est pas de l'argent : deux histogrammes de la même couleur
   inviteraient à comparer des kilos à des francs. */
.graphique .barre-quantite { fill: var(--bronze); }
.graphique .barre-quantite:hover { fill: var(--bronze-texte); }

/* ---------------------------------------------------------- Appareils */

/* Le jeton n'existe qu'une fois, sur une seule page. Le bloc est donc traité
   comme un avertissement plutôt que comme un résultat : bordure marquée, et
   le jeton assez gros pour être recopié sans se tromper de caractère. */
.bloc-jeton { border-color: var(--orange); border-width: 2px; }

.jeton-affiche {
  margin: 1rem 0;
  padding: .9rem 1rem;
  background: var(--creme);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon);
  overflow-x: auto;
}
.jeton-affiche code {
  font-family: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', Menlo, monospace;
  font-size: 1.05rem;
  /* Les groupes d'octets se recopient mieux espacés : un jeton se lit à la main
     au moins une fois, sur un écran de tablette, souvent mal éclairé. */
  letter-spacing: .06em;
  word-break: break-all;
  user-select: all;
}

/* Les actions d'une ligne, repliées : la liste reste lisible et un geste de plus
   sépare du bouton qui renouvelle un jeton. */
/* Le panneau vit dans une cellule de tableau : sans borne, le champ de nom
   s'étire (il est en flex: 1 1 12rem) et pousse les colonnes de droite sur deux
   lignes. On le borne plutôt que de retirer le panneau du tableau — la ligne et
   ses actions doivent rester au même endroit. */
.actions-ligne { margin-top: .4rem; max-width: 24rem; }
/* En grille plutôt qu'en ligne : dans un panneau étroit, une rangée qui se replie
   laisse l'étiquette « Canal » en fin de ligne et son menu à la ligne suivante,
   séparés de ce qu'ils nomment. Deux colonnes tiennent chaque étiquette contre
   son champ, quelle que soit la largeur. */
.actions-ligne .ligne-formulaire {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: .5rem .6rem; align-items: center;
}
.actions-ligne .ligne-formulaire input[type="text"] { flex: none; width: 100%; }
.actions-ligne .ligne-formulaire label { font-size: .85rem; color: var(--texte-doux); }
.actions-ligne .ligne-formulaire button { grid-column: 2; justify-self: start; }
.actions-ligne > summary {
  cursor: pointer; color: var(--texte-doux); font-size: .85rem;
}
.actions-ligne[open] > summary { margin-bottom: .6rem; }
.actions-ligne > * + * { margin-top: .6rem; }

.actions-secondaires {
  display: flex; gap: 1rem; flex-wrap: wrap; align-items: baseline;
  font-size: .85rem;
}
.actions-secondaires form { display: inline; }
.bouton-danger { color: var(--alerte); }

/*
 * Sur un vrai bouton, le rouge devient le FOND.
 *
 * « .bouton-danger » a été écrit pour des liens discrets — « retirer », « effacer »
 * — où seule la couleur du texte change. Posé sur un « .bouton », il écrivait du
 * rouge sur le vert sapin du bouton : un contraste d'à peine 2 pour 1, pour le
 * geste qu'on veut précisément le plus lisible.
 */
.bouton.bouton-danger { background: var(--alerte); border-color: var(--alerte); color: #fff; }
.bouton.bouton-danger:hover, .bouton.bouton-danger:focus { filter: brightness(.92); color: #fff; }

/* ---------------------------------------------------------- Rang des categories */

.cellule-rang { white-space: nowrap; }
.cellule-rang .rang { display: inline-block; min-width: 1.4rem; text-align: right; }

/* Les fleches remplacent la saisie d'un numero de rang. Assez grandes pour etre
   visees au doigt sur une tablette, discretes tant qu'on ne les survole pas. */
.bouton-fleche {
  font: inherit; line-height: 1; cursor: pointer;
  margin-left: .2rem; padding: .25rem .45rem;
  border: 1px solid var(--bordure); border-radius: 6px;
  background: var(--fond-carte); color: var(--texte);
}
.bouton-fleche:hover:not(:disabled) { background: var(--creme); border-color: var(--sapin); }
.bouton-fleche:focus-visible { outline: 2px solid var(--sapin); outline-offset: 2px; }

/* Premiere et derniere ligne : la fleche n'a nulle part ou aller. On la laisse en
   place plutot que de la retirer, pour que les colonnes ne dansent pas d'une
   ligne a l'autre. */
.bouton-fleche:disabled { opacity: .3; cursor: default; }

/* ---------------------------------------------------------- Plage personnalisee */

/* Les filtres alignent des blocs etiquette+champ ; la plage en groupe deux, pour
   que « Du » et « Au » restent cote a cote quand la barre se replie. */
/* Une liste de faits, sans puces : la fiche d'une vente dit d'où elle vient. */
.liste-simple { list-style: none; margin: 0; padding: 0; }
.liste-simple li + li { margin-top: .4rem; }

/* Un titre de formulaire, quand deux corrections se présentent côte à côte. */
.formulaire h3 { margin: 0; font-size: 1.05rem; }

.plage-perso { display: flex; align-items: flex-end; gap: .75rem; }
.plage-perso input[type="date"] {
  font: inherit; padding: .45rem .6rem;
  border: 1px solid var(--bordure); border-radius: var(--rayon); background: #fff;
}

/* ---------------------------------------------------------- Sous-catégories */

/* Le décalage dit la hiérarchie sans qu'on ait à l'écrire. Un filet plutôt qu'une
   simple marge : sur une liste longue, l'œil perd le niveau au bout de trois
   lignes, et le trait tient la colonne. */
.sous-categorie {
  padding-left: 1.6rem;
  border-left: 3px solid var(--bordure);
}

/*
 * LA SAISIE D'UNE RECOLTE, AU TELEPHONE. Les produits du moment en boutons
 * assez grands pour un doigt, la quantite en gros avec son unite a cote, et un
 * bouton pleine largeur : quelques secondes par recolte, gants compris.
 */
.saisie-recolte { max-width: 34rem; }
.recoltes-recents { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .9rem; }
.puce-produit {
  padding: .55rem .85rem; border: 1px solid var(--bordure); border-radius: 999px;
  background: var(--fond-carte); color: var(--texte); font: inherit; cursor: pointer;
}
.puce-produit:hover { border-color: var(--texte-doux); }
.puce-produit--active { background: var(--sapin); border-color: var(--sapin); color: var(--creme); }
.quantite-unite { display: flex; align-items: center; gap: .6rem; }
.quantite-unite input { max-width: 10rem; font-size: 1.3rem; }
.unite-recolte { font-size: 1.1rem; color: var(--texte-doux); }

/* Le journal sous la saisie : une ligne par recolte, le retrait a droite. */
.jour-recoltes { margin: 1rem 0 .3rem; font-size: 1rem; }
.liste-recoltes { list-style: none; margin: 0; padding: 0; }
.liste-recoltes li {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem;
  padding: .45rem 0; border-bottom: 1px solid var(--bordure);
}
.liste-recoltes .unite-ligne { display: block; }

/* La ligne du produit detaille, dans le tableau des statistiques. */
.ligne-choisie > td { background: var(--creme); }

/*
 * LE STATUT D'UNE COMMANDE (gestionFerme#14). La frise dit où elle en est sur
 * le chemin, la phrase dit l'état en clair, et les gestes viennent dessous,
 * séparés : l'étape suivante en bouton plein, les retours en lien discret.
 */
.frise {
  display: flex; flex-wrap: wrap; gap: .3rem; list-style: none;
  margin: 0 0 .9rem; padding: 0; counter-reset: etape;
}
.frise-etape {
  counter-increment: etape;
  padding: .3rem .8rem; border-radius: 999px; font-size: .85rem;
  border: 1px solid var(--bordure); color: var(--texte-doux); background: var(--fond-carte);
}
.frise-etape::before { content: counter(etape) '. '; }
.frise-faite { color: var(--sauge-texte); border-color: var(--sauge); }
.frise-faite::before { content: '✓ '; }
.frise-actuelle { background: var(--sapin); border-color: var(--sapin); color: var(--creme); font-weight: 600; }
.statut-actuel { margin: 0 0 1rem; }
.statut-titre-actions { margin: 1rem 0 .5rem; font-size: .95rem; }
.statut-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .8rem; }
.statut-annuler { margin-top: .8rem; }

/*
 * LE COURRIEL AU CLIENT, sur la fiche d'une commande ou d'une facture. Le
 * message en attente est encadré : il ne part qu'au clic, il ne doit pas se
 * confondre avec le reste de la page. Le texte garde sa police à chasse fixe :
 * le récapitulatif d'une commande est aligné en colonnes, comme il arrivera.
 */
.courriel-relire { margin-bottom: 1rem; }
.courriel-en-attente {
  border-left: 3px solid var(--bronze); padding: .6rem 0 .6rem 1rem;
  background: var(--creme); border-radius: 0 var(--rayon) var(--rayon) 0;
}
.courriel-titre { margin: 0 0 .6rem; }
.courriel-texte, .courriel-texte-envoye {
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .85rem; line-height: 1.35;
}
.courriel-texte { width: 100%; }
.courriel-texte-envoye {
  white-space: pre-wrap; margin: .4rem 0 0; padding: .6rem;
  background: var(--creme); border-radius: var(--rayon); max-height: 22rem; overflow: auto;
}
.courriel-ecrire { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0 0 1rem; }
.courriels-historique { list-style: none; margin: 0; padding: 0; font-size: .9rem; }
.courriels-historique li { padding: .45rem 0; border-bottom: 1px solid var(--bordure); }
.courriel-quand { font-family: var(--chiffres); color: var(--texte-doux); margin-right: .5rem; }
.courriel-echec { color: var(--alerte); }
.courriel-ignore { color: var(--texte-doux); }

/* Les messages types, en aperçu replié : on déplie, on lit, on retouche. */
.courriel-sous-titre { margin: 1.2rem 0 .3rem; font-size: 1rem; }
.courriel-modele { border: 1px solid var(--bordure); border-radius: var(--rayon); margin: .45rem 0; }
.courriel-modele > summary { padding: .55rem .8rem; cursor: pointer; }
.courriel-modele[open] > summary { border-bottom: 1px solid var(--bordure); background: var(--creme); }
.courriel-modele .courriel-formulaire { padding: .8rem; }
.courriel-en-attente .courriel-formulaire { margin-bottom: .4rem; }

/* La fiche d'une facture émise : envoi et suivi dans une seule section. */
.suivi-facture { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 .9rem; }
.courriel-integre { margin-top: 1.4rem; padding-top: 1rem; border-top: 1px solid var(--bordure); }
.courriel-integre > h3 { margin: 0 0 .4rem; font-size: 1.05rem; }
.annuler-facture { margin-top: 1.4rem; padding-top: .8rem; border-top: 1px solid var(--bordure); }
.annuler-facture > summary { cursor: pointer; color: var(--texte-doux); font-size: .9rem; }
.annuler-facture[open] > summary { margin-bottom: .6rem; color: var(--alerte); }

/* Une commande remise et pas encore encaissée : l'argent qu'on attend encore.
   Mise en évidence dans la liste, pour qu'elle se voie même sur « Toutes ». */
.ligne-a-encaisser > td { background: rgba(229, 109, 56, 0.12); }
.ligne-a-encaisser > td:first-child { box-shadow: inset 3px 0 0 #E56D38; }
