/* L'atelier : ecran de tri et de classement. Il est fait pour etre parcouru
   au clavier, pas a la souris, parce qu'une session de reperage produit
   trente fiches et que les ranger une par une a la souris ne se fait pas. */

:root {
  /* Les FONDS sont chauds, l'ENCRE reste neutre. Une encre chaude vire au
     sepia des qu'il y en a beaucoup, alors qu'un fond chaud ne fait que
     poser le papier sous le texte. Toute la famille tient sur une seule
     teinte, celle de la bande de titre du tiroir, et la sarcelle de l'accent
     lui repond en complementaire : elle ressort sans qu'on l'augmente. */
  --papier: #F4F4F1;
  /* Le QUATRIEME neutre, et le plus clair : trois pour cent de gris chaud.
     Il ne sert qu'a une chose, enfermer un paquet de lignes sur une surface
     blanche. Les trois autres sont trop lourds pour cela : le papier fait
     quatre pour cent, la surface secondaire huit, et a ce poids la boite pese
     plus que les noms qu'elle contient. */
  --enclos: #F7F7F4;
  --surface: #FFFFFF;
  --surface-2: #EDEDE9;
  --encre: #1B1B19;
  --encre-2: #45443F;
  /* Le gris de second plan portait 4,1 de contraste sur le papier et 3,9 sur le
     gris des cases : sous le seuil de 4,5 que demande un texte courant, et
     c'est le plus employé des trois encres -- toutes les mentions, tous les
     comptes, toutes les précisions. Assombri juste ce qu'il faut pour passer
     partout, il reste le même gris chaud, au second plan. */
  --encre-3: #6B6963;
  --filet: #DCDBD7;
  /* Un seul filet fin pour toute l'application : les sections du tiroir en
     avaient un a elles, d'une valeur voisine mais pas egale, et deux gris a
     un point d'ecart ne se distinguent pas, ils se salissent. */
  --filet-doux: #E8E8E6;
  --accent: #14535E;
  /* L'accent doux ne dit plus qu'UNE chose : ce qui est selectionne. Il
     habillait aussi les etapes, les etiquettes de type et la barre
     d'actions ; a force d'etre partout il ne designait plus rien. */
  --accent-doux: #DCE8E9;
  --accent-encre: #0C3941;
  /* Les rayures d'une hachure. Elles doivent se lire comme une TEXTURE, pas
     comme un code-barres : a pleine force, la part hachuree criait plus fort
     que la part pleine juste a cote, et la rampe se lisait donc le plus fort
     la ou elle est le moins sure. La rayure s'adoucit, le sens ne bouge pas. */
  --accent-hachure: #91ADB0;
  --attente-hachure: #C8B58E;
  /* Trois couleurs SEMANTIQUES, et chacune sa gamme complete. Il en existait
     une seconde, non declaree, ecrite en hsl() au fil des blocs d'alerte :
     vingt-quatre rouges a cinq degres de teinte du rouge officiel, douze
     ambres, et trois restes froids de la palette d'avant. Deux rouges qui se
     ressemblent presque font plus de mal qu'un seul : l'oeil cherche la
     difference et n'en trouve pas.
     Quatre tons par couleur, et le role de chacun : le fond le plus clair,
     un fond soutenu, le filet, l'encre foncee qui se pose dessus. */
  --ok: #2F7A4F;   --ok-fond: #E9F1EB; --ok-encre: #22593A;
  --attente: #8F6410; --attente-fond: #F7F0DF; --attente-fond-2: #F2E7CD;
  --attente-filet: #E0CDA0; --attente-encre: #6A4A0C;
  --refus: #9E3B39;   --refus-fond: #F7EDEC; --refus-fond-2: #F2E0DE;
  --refus-filet: #E4C3C1; --refus-encre: #6E2422;
  /* L'or des etoiles et de la photo de couverture. Ce n'est pas une couleur
     semantique de plus : c'est la meme marque, celle qu'on pose sur ce qu'on
     a soi-meme distingue. Elle etait ecrite quatre fois, a deux valeurs. */
  /* L'or de la transformation. Il ne servait qu'à écrire, à 2,1 de contraste :
     illisible pour qui a la vue basse, et à peine plus pour les autres sur un
     écran de chantier en plein jour. Deux tons désormais : celui-ci pour les
     traits et les marques, qui demandent 3, et l'encre ci-dessous pour les
     mots, qui en demandent 4,5. */
  --distingue: #AA7F1E;
  --distingue-encre: #876518;
  /* La BANDE de titre d'une section ouverte. Un gris a peine chaud, une
     marche si faible qu'on la ressent avant de la remarquer.
     Elle habillait d'abord tout le corps de la section. C'etait juste tant
     qu'une seule section etait ouverte, et faux des qu'il y en avait
     plusieurs : onze corps teintes ne font plus onze sections, ils font un
     seul aplat, et la distinction disparait au moment ou l'on en aurait le
     plus besoin. On distingue donc les sections par leur TETE, jamais par
     leur corps : le corps reste blanc, quel que soit le nombre de sections
     ouvertes, et chaque chapitre garde une tete reperable. */
  --section-ouverte: #F6F6F4;
  /* Le survol passe SOUS le curseur : sinon la souris efface, en passant,
     l'endroit ou le clavier se trouve. */
  --survol: #FBFBFA;
  /* QUATRE rayons pour toute l'application, et rien d'autre. Il y en avait
     quinze, de deux a vingt pixels, poses au jugement du moment : deux
     boutons voisins ne s'arrondissaient pas pareil, et l'oeil le sentait
     sans pouvoir le nommer. La regle est celle du role, pas de la taille :
     petit pour ce qui se clique, moyen pour ce qui contient, grand pour ce
     qui se pose par-dessus, rond pour les gelules. */
  --rayon-petit: 6px;
  --rayon: 10px;
  --rayon-grand: 16px;
  --rond: 999px;
  /* Le rail etait cale a 232 pixels, largeur d'un menu. Il porte pourtant des
     intitules entiers et des montants a six chiffres cote a cote : sous cette
     largeur, « Articles selectionnes » passe a la ligne, les jauges se
     raccourcissent, et l'air qu'on met entre les lignes ne compense jamais
     celui qui manque en travers. */
  --rail: 300px;
  /* Teinte du projet ouvert. L'atmosphere la remplace sur le corps ;
     sans atmosphere, c'est celle de la zone des projets. */
  --h-projet: 206;
  /* Teinte d'un groupe d'objets. Posee sur la pastille elle-meme, une par
     groupe : elle ne veut rien dire de plus que « pas le meme groupe ». */
  --h-groupe: 206;
  /* Teinte d'un vehicule. Elle suit le camion d'un bout a l'autre du montage :
     deux traits de la meme couleur seraient deux fois le meme camion. */
  --h-moyen: 196;
  /* Teinte d'un paquet dans une case : celle du vehicule ou celle du groupe
     selon la facon dont on a demande a lire le tableau. Elle ne fait que
     reprendre l'une des deux, jamais en inventer une troisieme. */
  --h-paquet: 206;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--papier); color: var(--encre);
  font: 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  display: grid; grid-template-columns: var(--rail) minmax(0, 1fr); height: 100vh; overflow: hidden;
}
h1, h2, h3 { margin: 0; font-weight: 600; }
button { font: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--rayon-petit); }

/* ------------------------------------------------------------ rail */
.rail { background: var(--surface); border-right: 1px solid var(--filet); display: flex; flex-direction: column; overflow: hidden; }
.rail .titre { padding: 18px 20px 14px; }
.rail .haut-rail { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
/* Le nom en romain. Une seule note de caractere, sur le seul mot qui ne
   change jamais : c'est ce qui distingue un outil d'un gabarit. ui-serif rend
   New York sur les Mac, le romain systeme, et Georgia partout ailleurs. */
.rail .titre h1 {
  font-family: ui-serif, Georgia, "Iowan Old Style", "Palatino Linotype", serif;
  font-size: 21px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.1;
}
.rail .titre p { margin: 3px 0 0; font-size: 11px; color: var(--encre-3); }

.rail nav { flex: 1; overflow-y: auto; padding: 8px 0 14px; }
.rail a {
  display: flex; align-items: center; gap: 8px; padding: 5px 14px;
  color: var(--encre-2); text-decoration: none; cursor: pointer; border-left: 2px solid transparent;
}
.rail a .nb { margin-left: auto; white-space: nowrap; }
.rail .ajouter { padding: 2px 11px; }
.rail .ajouter button { background: none; border: 0; color: var(--encre-3); cursor: pointer; padding: 3px 0; font-size: 12px; }
/* Ce qui attend en boite se lit sous elle, pas dans le budget : c'est une
   pre-selection, pas une depense. */
.rail .ajouter.en-attente {
  padding: 0 14px 6px 14px; margin-top: -3px;
  font-size: 11px; color: var(--encre-3); font-variant-numeric: tabular-nums;
}

/* Le camaieu d'un projet se voit dans le rail avant meme de le choisir.
   Chaque teinte est posee par attribut, comme les blocs de pilotage plus
   bas : une variable CSS remplie depuis le JS ne se verifierait pas. */
.pastille-camaieu { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--encre-3); }
.pastille-camaieu[data-camaieu="sarcelle"]   { background: hsl(190 58% 40%); }
.pastille-camaieu[data-camaieu="ardoise"]    { background: hsl(235 58% 40%); }
.pastille-camaieu[data-camaieu="myrtille"]   { background: hsl(280 58% 40%); }
.pastille-camaieu[data-camaieu="prune"]      { background: hsl(325 58% 40%); }
.pastille-camaieu[data-camaieu="terracotta"] { background: hsl(10 58% 40%); }
.pastille-camaieu[data-camaieu="ocre"]       { background: hsl(55 58% 40%); }
.pastille-camaieu[data-camaieu="sauge"]      { background: hsl(100 58% 40%); }
.pastille-camaieu[data-camaieu="celadon"]    { background: hsl(145 58% 40%); }
.rail a.archive { opacity: .62; font-style: italic; }

/* L'encart respire au meme rythme que le rail. Il etait cale sur onze pixels
   et demi et trois pixels d'interligne : lisible pour trois lignes, illisible
   pour quatorze, ou les chiffres se collent et l'oeil ne sait plus quel
   montant appartient a quel intitule. */
/* La partie financiere se distingue par son FOND, pas par une borne. La
   borner la coupait en plein milieu d'une ligne, ce qui cache des chiffres et
   se voit. Un fond distinct dit « ici on ne navigue plus, on lit des
   montants », et il le dit sans rien couper.
   La teinte est celle du papier de l'application, pas une couleur de plus :
   elle suit donc le camaieu du projet comme le reste, et reste assez pale
   pour laisser l'ambre, le rouge et le vert dire ce qu'ils disent. */
.enveloppe-budget {
  background: var(--papier);
  border-top: 1px solid var(--filet);
  padding: 16px 20px 18px; font-size: 12.5px;
  /* Aucune borne : sur un ecran normal l'encart tient tout entier. Mais le
     rail cache ce qui deborde de lui, si bien que sur une fenetre courte
     l'encart etait rogne par le bas SANS barre de defilement : des chiffres
     disparaissaient et rien ne le disait. Il defile donc quand, et seulement
     quand, il ne tient pas. min-height a zero, sans quoi une boite flex
     refuse de descendre sous la hauteur de son contenu et deborde quand meme. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.enveloppe-budget .ligne {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  margin-bottom: 7px; line-height: 1.45; color: var(--encre-3);
  font-size: 12.5px;
}
/* L'intitule est une legende, le montant est le contenu : deux tailles, et la
   ligne tient sur une seule. Les mettre a la meme taille faisait passer
   « Articles selectionnes » et « Budget restant sans rendu » a la ligne, et un
   intitule sur deux lignes avec son montant cale sur la premiere se lit mal. */
.enveloppe-budget .ligne > span { min-width: 0; }
.enveloppe-budget .ligne b {
  color: var(--encre); font-variant-numeric: tabular-nums; font-weight: 600;
  font-size: 13px; white-space: nowrap;
}
.enveloppe-budget .jauge { height: 4px; background: var(--filet-doux); border-radius: var(--rayon-petit); overflow: hidden; margin: 9px 0 3px; }
.enveloppe-budget .jauge i { display: block; height: 100%; background: var(--ok); }
.enveloppe-budget .jauge.vigilance i { background: var(--attente); }
.enveloppe-budget .jauge.depassement i { background: var(--refus); }
.enveloppe-budget input {
  width: 100%; margin-top: 6px; padding: 3px 6px; font: inherit; font-size: 11.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}

/* ---------------------------------------------------------- espace */
.espace-travail { display: flex; flex-direction: column; overflow: hidden; }

.barre {
  display: flex; align-items: center; gap: 9px; padding: 10px 16px;
  background: var(--surface); border-bottom: 1px solid var(--filet-doux); flex: 0 0 auto;
}
.barre h2 { font-size: 14px; white-space: nowrap; }
.barre .compte { font-size: 11.5px; color: var(--encre-3); }
.barre .pousse { margin-left: auto; }
.barre input[type="search"] {
  width: 210px; padding: 5px 10px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.barre input[type="search"]:focus { outline: none; border-color: var(--encre-3); }
/* Une piste grise, une pastille blanche : le choix courant se leve, il ne
   s'allume pas. La sarcelle pleine faisait de trois vues d'un meme ecran une
   decision aussi forte que « Ranger ». */
.bascule { display: flex; border: 0; border-radius: var(--rayon-petit); background: var(--surface-2); padding: 2px; gap: 2px; }
/* display:flex l'emporte sur la regle [hidden] du navigateur, a specificite
   egale. Meme piege que pour le tiroir : il faut le dire explicitement. */
.bascule[hidden] { display: none; }
.bascule button {
  background: transparent; border: 0; padding: 4px 11px; cursor: pointer;
  color: var(--encre-2); font-size: 12px; border-radius: var(--rayon-petit);
}
.bascule button.actif {
  background: var(--surface); color: var(--encre); font-weight: 500;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .07);
}

/* barre d'action, visible seulement en selection */
/* La barre teintee en sarcelle, avec quinze boutons sarcelle dedans, criait
   plus fort que la liste qu'elle sert. Elle devient un bandeau neutre ou un
   seul bouton porte la couleur : celui qui fait le geste. */
/* Vise le DIV, pas la classe seule. « actions » nomme deux choses dans cette
   application : cette barre-ci, qui n'existe qu'en selection, et la derniere
   cellule des tableaux, celle qui porte le geste de la ligne. La regle
   « .actions { display: none } » les atteignait toutes les deux : dans « Ce
   qui bloque », la colonne des actions faisait zero pixel de large et AUCUN
   bouton n'etait visible, sur l'ecran dont tout le principe est « une file,
   une action par ligne ». Rien ne plantait, la cellule etait bien la, elle
   ne s'affichait simplement jamais. */
div.actions {
  display: none; align-items: center; gap: 8px; padding: 10px 16px;
  background: var(--section-ouverte); border-bottom: 1px solid var(--filet-doux); flex: 0 0 auto;
  /* Autant de boutons que de gestes possibles sur une selection : sans quoi
     rejeter deselectionner, sortait de l'ecran sans recours, aucun moyen d'y
     revenir. Elle passe donc a la ligne plutot que de deborder en silence. */
  flex-wrap: wrap; row-gap: 6px;
}
div.actions.visible { display: flex; }
.actions .nb { flex: 0 0 auto; }
.actions .nb { font-weight: 600; color: var(--encre); }
.actions select, .actions input {
  padding: 5px 8px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.actions button {
  padding: 5px 11px; border-radius: var(--rayon-petit); cursor: pointer;
  border: 1px solid var(--accent); background: var(--accent); color: #fff; font-size: 12.5px; font-weight: 600;
}
.actions button.doux {
  background: var(--surface); border-color: var(--filet); color: var(--encre-2); font-weight: 400;
}
.actions button.doux:hover { border-color: var(--encre-3); color: var(--encre); }
.actions .separateur { width: 1px; height: 18px; background: var(--filet); margin: 0 3px; }
.actions button.danger {
  background: var(--surface); border-color: var(--filet); color: var(--refus); font-weight: 400;
}
.actions button.danger:hover { border-color: var(--refus); }

/* Le centre est BLANC. Il etait pose sur le papier gris, ce qui donnait a
   onze lignes une seule masse uniforme : un back-office, pas une liste de
   travail. Le blanc rend chaque filet lisible et laisse au gris pale le soin
   de dire ou l'on se trouve. */
.contenu { flex: 1; overflow-y: auto; padding: 0 0 60px; background: var(--surface); }

/* ----------------------------------------------------- vue tableau */
table.fiches { width: 100%; border-collapse: collapse; }
table.fiches thead th {
  position: sticky; top: 0; background: var(--surface); z-index: 1;
  text-align: left; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 500; padding: 12px 12px; border-bottom: 1px solid var(--filet-doux);
}
table.fiches td { padding: 11px 12px; border-bottom: 1px solid var(--filet-doux); vertical-align: middle; }

/* Trois poids, pas onze colonnes egales. Ce qui se compare d'un coup d'oeil
   (le produit, le total, l'etat) tient l'encre ; ce qui sert a trier passe
   au gris ; ce qui ne se lit qu'en cas de doute s'efface presque. La fiche
   laterale dit deja tout : le tableau n'a pas a le raconter deux fois. */
/* La designation est le coeur de la ligne : c'est elle qui prend le mou.
   Sans largeur declaree, la mise en page automatique la serrait a deux cent
   quatre-vingts pixels pendant que trois cents restaient vides a droite, et
   chaque nom de produit passait sur deux lignes. */
/* La colonne du nom garde une largeur LISIBLE, même quand le tableau défile.
   Écrite en pourcentage, elle valait trente-quatre pour cent de la fenêtre :
   dans cinq cents pixels, quatre-vingt-seize, et « Suspension Hozuki M,
   naturel, Ø50cm » tombait sur douze lignes tandis que la colonne « Marque »,
   large de deux mots, gardait la sienne. Le tableau défile déjà de côté ;
   c'est donc une largeur de texte qu'il faut, pas une part de fenêtre. */
table.fiches th.designation, table.fiches td.designation { width: 34%; min-width: 230px; }
/* Et les colonnes courtes rendent le mou qu'elles prenaient : « Salon » ne
   demande pas trois cents pixels, et c'est la designation qui les voulait. */
table.fiches th.rangement, table.fiches td.rangement { width: 130px; }
table.fiches th.marque, table.fiches td.marque { width: 130px; }
table.fiches th.nature, table.fiches td.nature { width: 88px; }
table.fiches td.marque, table.fiches td.nature { font-size: 12.5px; color: var(--encre-2); }
table.fiches td.nature, table.fiches td.rangement, table.fiches td.veille,
table.fiches th.nature, table.fiches th.rangement, table.fiches th.veille { color: var(--encre-3); }
table.fiches td.nature, table.fiches td.rangement { font-size: 12px; }
table.fiches tr { cursor: pointer; }
/* L'en-tete est collant : sans cette marge, scrollIntoView amene la ligne
   juste dessous et l'en-tete la recouvre. */
table.fiches tbody tr { scroll-margin-top: 36px; }
.carte { scroll-margin-top: 14px; }
/* Plus aucun contour. Une ligne porte deux etats a la fois : le CURSEUR, qui
   suit le clavier, et la SELECTION, sur laquelle les actions vont tomber. Un
   seul gris pale ne peut pas dire les deux, alors la selection se dit par sa
   case cochee et le curseur par le fond. */
table.fiches tr:hover td { background: var(--survol); }
table.fiches tr.selectionne td, table.fiches tr.curseur td { background: var(--section-ouverte); }
table.fiches tr.selectionne td.designation { font-weight: 600; }

/* La case ne se montre qu'au survol, ou une fois cochee : onze cases vides
   en permanence font une colonne de bruit pour un geste occasionnel. */
td.cocher, th.cocher { width: 34px; padding-left: 16px; padding-right: 0; }
td.cocher input {
  width: 15px; height: 15px; margin: 0; cursor: pointer; display: block;
  accent-color: var(--accent); opacity: 0; transition: opacity .12s;
}
table.fiches tr:hover td.cocher input, td.cocher input:checked,
td.cocher input:focus-visible { opacity: 1; }
/* Sans survol, rien ne la revelerait jamais. */
@media (hover: none) { td.cocher input { opacity: 1; } }

td.vignette { width: 60px; padding: 7px 12px 7px 0; }
td.vignette img {
  width: 44px; height: 44px; object-fit: contain; display: block;
  background: var(--papier); border: 0; border-radius: var(--rayon);
}
td.designation { font-weight: 500; }
td.designation small { display: block; font-weight: 400; color: var(--encre-3); font-size: 11.5px; }
/* Les colonnes de chiffres s'alignent a droite, en-tete compris, sinon
   l'oeil ne peut pas comparer une colonne de prix. */
/* La regle d'en-tete ci-dessus est plus specifique, il faut donc la viser
   au meme niveau, sinon les titres restent a gauche des chiffres. */
table.fiches td.nombre, table.fiches thead th.nombre {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
td.nombre b { font-weight: 600; }
/* Le total pese, parce que c'est lui qui tombe dans le projet. La marge est
   une consequence : elle se lit quand on la cherche. */
table.fiches td.nombre { font-size: 12.5px; color: var(--encre-2); }
table.fiches td.nombre b { color: var(--encre); }
table.fiches td.marge, table.fiches th.marge { color: var(--encre-3); font-size: 12px; }

/* ---------------------------------------------------- vue planche */
.planche { display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; padding: 16px; }
.carte { background: var(--surface); border: 1px solid var(--filet-doux); border-radius: var(--rayon); overflow: hidden; cursor: pointer; }
.carte.selectionne { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.carte.curseur { box-shadow: 0 0 0 2px var(--accent); }
.carte .image { aspect-ratio: 1; background: var(--papier); display: flex; align-items: center; justify-content: center; }
.carte .image img { max-width: 100%; max-height: 100%; object-fit: contain; }
.carte .infos { padding: 7px 9px 9px; }
.carte .infos .nom { font-size: 12px; font-weight: 500; line-height: 1.3; margin-bottom: 3px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.carte .infos .bas { display: flex; align-items: baseline; gap: 6px; font-size: 11px; color: var(--encre-3); }
.carte .infos .bas .marque { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.carte .infos .bas b { flex: 0 0 auto; color: var(--encre); font-variant-numeric: tabular-nums; font-weight: 600; }

/* Aucun filet de couleur sur le flanc d'un bloc, nulle part.
   Il disait toujours ce que le fond, le mot ou la capsule disaient deja : une
   marque de plus pour une seule information. Et le motif se repetait dans
   huit endroits sans rapport entre eux, ce qui lui otait le peu de sens qu'il
   avait. L'etat se lit dans le mot et dans la capsule ; la couleur, quand
   elle sert, tient le fond ou l'encre du bloc entier. */

/* La garde de l'attribut hidden, pour toute la feuille.
   « display: grid » pose sur une classe l'emporte sur l'attribut hidden : le
   script croit avoir cache l'element, il reste a l'ecran. Le depot avait des
   gardes classe par classe, ce qui protege la classe gardee et laisse toutes
   les autres decouvertes ; le bloc des jours d'un composant s'affichait encore
   parce que sa classe posait un display et n'avait pas la sienne. */
[hidden] { display: none !important; }

/* --------------------------------------------------------- pastilles */
.pastille {
  display: inline-block;
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600;
  padding: 3px 7px; border-radius: var(--rayon-petit); white-space: nowrap; background: var(--surface-2); color: var(--encre-3);
}
.pastille.ok { background: var(--ok-fond); color: var(--ok); }
.pastille.attente { background: var(--attente-fond); color: var(--attente); }
.pastille.refus { background: var(--refus-fond); color: var(--refus); }
.pastille.accent { background: var(--accent-doux); color: var(--accent-encre); }

.vide { padding: 60px 20px; text-align: center; color: var(--encre-3); }
.vide h3 { font-size: 14px; color: var(--encre-2); margin-bottom: 5px; }
.vide p { margin: 0 auto; max-width: 42ch; font-size: 12.5px; }

/* ---------------------------------------------------------- tiroir */
.tiroir {
  /* L'en-tete de tableau est collant avec un z-index : sans celui-ci, les
     titres de colonnes passent devant le tiroir. */
  z-index: 30;
  position: fixed; top: 0; right: 0; bottom: 0; width: 430px; background: var(--surface);
  border-left: 1px solid var(--filet); box-shadow: -10px 0 34px rgba(0,0,0,.12);
  display: flex; flex-direction: column; transform: translateX(100%); transition: transform .16s ease-out;
}
.tiroir.ouvert { transform: translateX(0); }
/* display:flex sur .tiroir l'emporte sur la regle [hidden] du navigateur,
   qui a la meme specificite. Sans cette ligne, l'attribut hidden ne masque
   rien et le tiroir ferme reste dans la page. */
.tiroir[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .tiroir { transition: none; } }
.tiroir header { padding: 11px 14px; background: var(--accent); color: #fff; display: flex; align-items: center; gap: 9px; }
.tiroir header .titre { font-size: 13px; font-weight: 600; }
.tiroir header button { margin-left: auto; background: none; border: 0; color: #fff; font-size: 19px; cursor: pointer; opacity: .82; }
/* Aucun rembourrage EN HAUT du defilement : un titre colle se fixe au bord
   du cadre de defilement, donc sous ce rembourrage, et il laissait quatorze
   pixels par lesquels le contenu remontait au-dessus de son propre titre.
   L'air du haut est porte par le premier enfant. */
.tiroir .corps { flex: 1; overflow-y: auto; padding: 0 14px 14px; }
.tiroir .corps > :first-child { margin-top: 14px; }
.tiroir .galerie { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; margin-bottom: 10px; }
.tiroir .galerie img { width: 100%; aspect-ratio: 1; object-fit: contain; background: var(--papier); border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); }
/* Le meme champ, la meme forme, quel que soit l'endroit ou il s'affiche.
   La mise en page d'un « bloc » n'existait que dans le tiroir : le meme
   gabarit reutilise dans un dialogue rendait le libelle et le champ sur une
   seule ligne, avec la zone de texte posee par-dessus son propre intitule.
   La boite de reception, qui est le dernier filet avant qu'une casse ne se
   reclame plus, s'affichait ainsi. */
.tiroir .bloc, .comparaison .bloc { margin-bottom: 10px; }
/* Casse normale, ici comme ailleurs. « DÉSIGNATION » et « RÉFÉRENCE » en
   capitales espacees, ce sont des accents qui flottent au-dessus du mot et un
   usage qui n'est pas le notre. Un libelle de champ se lit comme il s'ecrit. */
.tiroir .bloc > label, .comparaison .bloc > label {
  display: block; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 500; margin-bottom: 4px;
}
.tiroir input, .tiroir select, .tiroir textarea,
.comparaison .bloc input, .comparaison .bloc select, .comparaison .bloc textarea {
  width: 100%; padding: 5px 8px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface); color: var(--encre);
}
.tiroir .duo, .comparaison .duo { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tiroir table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.tiroir table td { padding: 3px 5px; border-bottom: 1px solid var(--filet-doux); }
.tiroir table td:first-child { color: var(--encre-3); width: 44%; }
/* Le pied : le lien vers la source a gauche, l'action a droite. Les deux
   boutons se partageaient la largeur a parts egales et portaient tous deux le
   contour de l'accent : rien ne disait lequel des deux acheve le travail. Un
   seul est plein, et c'est celui qui enregistre. */
.tiroir footer {
  padding: 12px 16px; background: var(--surface); border-top: 1px solid var(--filet-doux);
  display: flex; align-items: center; gap: 12px;
}
.tiroir footer button {
  padding: 8px 16px; border-radius: var(--rayon); cursor: pointer; font: inherit; font-size: 13px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff; font-weight: 600;
}
.tiroir footer button.doux {
  margin-right: auto; padding: 6px 0; border: 0; background: none;
  color: var(--encre-2); font-weight: 400;
  display: inline-flex; align-items: center; gap: 8px;
}
.tiroir footer button.doux svg {
  width: 15px; height: 15px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}
.tiroir footer button.doux:hover { color: var(--accent); }
.tiroir footer button.doux:hover span { text-decoration: underline; }

/* ------------------------------------------------------------ aide */
.aide {
  position: fixed; left: calc(var(--rail) + 16px); right: 16px; bottom: 12px;
  display: flex; gap: 12px; font-size: 11px; color: var(--encre-3);
  background: var(--surface); border: 1px solid var(--filet-doux);
  padding: 6px 12px; border-radius: var(--rayon);
}
/* Des touches en relief font une documentation clavier ; on veut un outil.
   Un gris a peine pose, la touche un peu plus foncee que son intitule. */
.aide kbd {
  font: inherit; font-size: 10.5px; background: var(--surface-2); border: 0;
  border-radius: var(--rayon-petit); padding: 1px 5px; color: var(--encre-2);
}

/* ------------------------------------------------------------- veille */

button.veille {
  padding: 5px 11px; border-radius: var(--rayon-petit); cursor: pointer;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2); font-size: 12.5px;
  /* Un intitule coupe en deux lignes fait grandir toute la barre et se lit
     moins bien qu'un intitule qui passe a la ligne SUIVANTE, entier. La
     barre sait deja envelopper ses elements. */
  white-space: nowrap;
}
button.veille:hover { border-color: var(--encre-3); color: var(--encre); }
button.veille:disabled { opacity: .5; cursor: default; }

.progression {
  display: flex; align-items: center; gap: 11px; padding: 7px 16px;
  background: var(--attente-fond); border-bottom: 1px solid var(--filet);
  font-size: 12px; color: var(--attente); flex: 0 0 auto;
}
.progression[hidden] { display: none; }
.progression .jauge { flex: 1; height: 4px; background: rgba(143,100,16,.2); border-radius: var(--rayon-petit); overflow: hidden; }
.progression .jauge i { display: block; height: 100%; background: var(--attente); transition: width .3s; }
.progression button {
  border: 1px solid var(--attente); background: transparent; color: var(--attente);
  border-radius: var(--rayon-petit); padding: 2px 9px; cursor: pointer; font-size: 12px;
}

/* Variation relevee par la veille, lisible sans ouvrir la fiche. */
.variation { font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 600; }
.variation.hausse { color: var(--refus); }
.variation.baisse { color: var(--ok); }
td.designation small .veille-note { color: var(--attente); }

/* --------------------------------------------------- densites de planche */

.planche.dense { grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 9px; }
.planche.moyenne { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); }
.planche.grande { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.planche.grande .carte .infos { padding: 10px 12px 12px; }
.planche.grande .carte .infos .nom { font-size: 14px; -webkit-line-clamp: 3; }
.planche.grande .carte .infos .bas { font-size: 12.5px; margin-top: 4px; }
.planche.dense .carte .infos { padding: 5px 7px 7px; }
.planche.dense .carte .infos .nom { font-size: 11px; -webkit-line-clamp: 2; }
.planche.dense .carte .infos .bas { font-size: 10px; }

/* Loupe au survol d'une vignette : on voit qu'on peut agrandir. */
.carte .image, td.vignette img { position: relative; }
.carte .image::after, td.vignette::after {
  content: "⤢"; position: absolute; right: 4px; bottom: 4px;
  background: rgba(22,24,27,.62); color: #fff; font-size: 10px;
  width: 16px; height: 16px; border-radius: var(--rayon-petit); display: none;
  align-items: center; justify-content: center;
}
td.vignette { position: relative; }
.carte:hover .image::after, table.fiches tr:hover td.vignette::after { display: flex; }

/* ------------------------------------------------------- glisser-deposer */

tr.enleve, .carte.enleve { opacity: .4; }

/* ----------------------------------------------------------- filtres */

.filtres {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 9px 16px;
  background: var(--surface); border-bottom: 1px solid var(--filet-doux); flex: 0 0 auto;
}
.filtres[hidden] { display: none; }
.filtres .groupe-filtre { display: flex; align-items: center; gap: 5px; margin-right: 12px; }
.filtres .groupe-filtre > span {
  font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 600;
}
.filtres button {
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2);
  border-radius: var(--rond); padding: 3px 11px; font-size: 11.5px; cursor: pointer;
}
.filtres button:hover { border-color: var(--encre-3); color: var(--encre); }
.filtres button.actif { background: var(--encre); border-color: var(--encre); color: var(--surface); }

/* ------------------------------------------------------------ etapes */

/* Six teintes pour neuf etapes ne se classaient pas : le vert servait deux
   fois, l'ambre une, et personne ne pouvait dire laquelle venait apres
   laquelle. Quatre couleurs, quatre significations, et l'ordre se lit :
   gris ce qui attend, sarcelle ce qui est parti, vert ce qui est acquis,
   rouge ce qui est revenu. */
.etape { display: inline-block; font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  font-weight: 600; padding: 3px 7px; border-radius: var(--rayon-petit); white-space: nowrap;
  background: var(--surface-2); color: var(--encre-2); }
.etape.a-commander { background: var(--surface-2); color: var(--encre-2); }
.etape.commande, .etape.livre, .etape.construit { background: var(--accent-doux); color: var(--accent-encre); }
.etape.valide, .etape.receptionne { background: var(--ok-fond); color: var(--ok); }
.etape.retourne { background: var(--refus-fond); color: var(--refus); }

/* --------------------------------------------------------- barre d'aide */

.aide { flex-wrap: wrap; align-items: center; row-gap: 3px; }
.aide .astuce { margin-left: auto; }
.aide button {
  display: inline-flex; align-items: center; gap: 4px; background: none; border: 0;
  color: var(--encre-3); font-size: 11px; cursor: pointer; padding: 2px 4px; border-radius: var(--rayon-petit);
}
.aide button:hover { background: var(--surface-2); color: var(--accent); }
.aide .astuce { color: var(--encre-3); border-left: 1px solid var(--filet); padding-left: 12px; }

/* ------------------------------------------------------- visionneuse */

.visionneuse {
  position: fixed; inset: 0; z-index: 40; background: rgba(16,18,20,.94);
  display: flex; flex-direction: column;
}
.visionneuse[hidden] { display: none; }
.visionneuse .scene { flex: 1; display: flex; align-items: center; justify-content: center; padding: 26px; min-height: 0; }
.visionneuse .scene img { max-width: 100%; max-height: 100%; object-fit: contain; background: #fff; border-radius: var(--rayon-petit); }
.visionneuse .nav {
  background: rgba(255,255,255,.1); border: 0; color: #fff; font-size: 30px; line-height: 1;
  width: 46px; height: 76px; cursor: pointer; border-radius: var(--rayon-petit); flex: 0 0 auto;
}
.visionneuse .nav:hover { background: rgba(255,255,255,.2); }
.visionneuse .pellicule {
  display: flex; gap: 7px; padding: 0 26px 14px; overflow-x: auto; justify-content: center; flex: 0 0 auto;
}
.visionneuse .pellicule img {
  width: 62px; height: 62px; object-fit: contain; background: #fff;
  border: 2px solid transparent; border-radius: var(--rayon-petit); cursor: pointer; opacity: .55;
}
.visionneuse .pellicule img.actif { border-color: var(--accent); opacity: 1; }
.visionneuse .pellicule img.couverture { border-color: var(--distingue); opacity: 1; }
/* La rangee ne debordait pas : elle POUSSAIT « Fermer » hors de l'ecran, sur
   un telephone, et la visionneuse ne se refermait plus qu'au clavier, qui
   n'existe pas la. Elle passe donc a la ligne, et « Fermer » vient en tete
   des actions sur un ecran etroit. */
.visionneuse .commandes {
  display: flex; align-items: center; gap: 10px; padding: 12px 22px; flex-wrap: wrap;
  background: rgba(0,0,0,.35); color: #E9ECEC; font-size: 12.5px; flex: 0 0 auto;
}
.visionneuse .commandes span { margin-right: auto; }
.visionneuse .commandes button {
  padding: 6px 13px; border-radius: var(--rayon-petit); cursor: pointer; font-weight: 600; font-size: 12.5px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
}
.visionneuse .commandes button.doux { background: transparent; border-color: rgba(255,255,255,.34); color: #fff; }

/* Ou une reference a deja servi. Question posee des qu'on la retrouve. */
.usages { font-size: 11.5px; color: var(--encre-3); }
.etiquettes {
  display: flex; flex-wrap: wrap; gap: 5px; align-items: baseline; margin-top: 3px;
}
.etiquettes .tag {
  font-size: 10.5px; background: var(--surface-2); color: var(--encre-2);
  border-radius: var(--rayon-petit); padding: 1px 7px;
}
/* Ce qui nomme : du texte, separe par des points milieu. */
.etiquettes .mots { font-size: 11.5px; color: var(--encre-3); }
.etiquettes .mots b { font-weight: 500; color: var(--encre-2); }
/* Ce qui a ete repere pendant qu'on regardait ailleurs. L'etiquette passe en
   tete des autres et s'efface des qu'on quitte la vue : elle ne dit pas ce
   qu'est l'article, elle dit qu'il vient d'arriver. */
.etiquettes .tag.nouveau {
  background: var(--accent); color: #fff; font-weight: 600; letter-spacing: .01em;
}
.choix-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.choix-tags button {
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2);
  border-radius: var(--rayon); padding: 2px 9px; font-size: 11.5px; cursor: pointer;
}
.choix-tags button.actif { background: var(--encre); border-color: var(--encre); color: var(--surface); }

/* ------------------------------------------------ prix, notes, courbe */

.filtres input.prix-filtre {
  width: 68px; padding: 2px 7px; font: inherit; font-size: 11.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon); background: var(--papier);
}

/* Notes personnelles : elles servent a se laisser un avis a soi-meme,
   des mois plus tard, pas a produire une moyenne pour le client. */
.notes { display: grid; gap: 5px; }
.notes .critere { display: grid; grid-template-columns: 92px 1fr; align-items: center; gap: 8px; }
.notes .critere > span { font-size: 11.5px; color: var(--encre-3); }
.etoiles { display: flex; gap: 1px; }
.etoiles button {
  background: none; border: 0; cursor: pointer; padding: 0 1px;
  font-size: 15px; line-height: 1; color: var(--filet);
}
.etoiles button.pleine { color: var(--distingue); }
.etoiles button:hover { color: var(--distingue); }
.note-liste { color: var(--distingue-encre); font-size: 11px; letter-spacing: -1px; white-space: nowrap; }

.courbe { background: var(--papier); border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); padding: 8px; }
.courbe svg { display: block; width: 100%; height: 74px; }
.courbe .legende { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--encre-3); margin-top: 4px; }

.mots-suggeres { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.mots-suggeres button {
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2);
  border-radius: var(--rayon); padding: 1px 8px; font-size: 11px; cursor: pointer;
}
.mots-suggeres button:hover { border-style: solid; border-color: var(--accent); color: var(--accent); }

/* ------------------------------------------------------------- marge */

.resume-marge {
  margin-top: 7px; font-size: 12px; color: var(--encre-2);
  background: var(--papier); border-radius: var(--rayon-petit); padding: 6px 9px;
}
.resume-marge b { font-variant-numeric: tabular-nums; }

.enveloppe-budget input + input { margin-top: 4px; }

/* --------------------------------------------------- port et retour */

label.case { display: flex; align-items: center; gap: 7px; font-size: 12.5px; cursor: pointer; }
label.case input { width: auto; }
label.sous-champ { display: block; }
label.sous-champ > span {
  display: block; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); margin-bottom: 2px;
}
/* Un sous-objet du tiroir se distingue par son FOND, jamais par un cadre : un
   cadre pose dans une section qui en a deja fait deux contours emboites pour
   dire une seule chose. Meme traitement pour tous, un fond et un rayon. */
.encart-fournisseur {
  margin-top: 10px; border: 0; border-radius: var(--rayon);
  padding: 11px 12px; background: var(--papier);
}
.encart-fournisseur .titre {
  font-size: 11px; font-weight: 600; color: var(--encre-2); margin-bottom: 7px;
}
.note-fournisseur { font-size: 10.5px; color: var(--encre-3); margin-top: 6px; }
.resume-port {
  margin-top: 8px; font-size: 12px; color: var(--encre-2);
  background: var(--papier); border-radius: var(--rayon-petit); padding: 6px 9px;
}
.resume-port b { font-variant-numeric: tabular-nums; }
.enveloppe-budget .franco {
  margin-top: 6px; font-size: 11px; color: var(--attente);
  border-top: 1px solid var(--filet-doux); padding-top: 5px;
}

/* ------------------------------------------------------------ remises */

.tag.remise { background: var(--ok-fond); color: var(--ok); font-weight: 600; }
.resume-remise {
  margin-top: 7px; font-size: 12px; color: var(--encre-2);
  background: var(--papier); border-radius: var(--rayon-petit); padding: 6px 9px;
}
.resume-remise b { font-variant-numeric: tabular-nums; }
label.sous-champ[hidden] { display: none; }

/* ------------------------------------------------------- alternatives */

.option {
  display: inline-block;
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600;
  background: var(--surface-2); color: var(--encre-2);
  border-radius: var(--rayon-petit); padding: 3px 7px; white-space: nowrap;
}
.option.retenue { background: var(--ok-fond); color: var(--ok); }
.poste-nom { font-size: 11.5px; color: var(--encre-3); margin-top: 2px; }
.enveloppe-budget .arbitrage {
  margin: -1px 0 8px; font-size: 11.5px; line-height: 1.45; color: var(--accent-encre);
}

/* ------------------------------------------------- budget par piece */

/* Une ligne de pièce se lit en deux temps : le nom et le montant côte à côte,
   puis la jauge sous eux, sur toute la largeur. La jauge vivait à gauche, dans
   la même colonne que le nom : sa longueur suivait donc celle du montant, et
   une pièce à 1 028,80 € avait une barre plus courte qu'une pièce à 0 €. Deux
   barres qui ne partagent pas la même échelle ne se comparent pas, ce qui est
   pourtant tout ce qu'on leur demande.
   Une quatrième colonne pour l'épingle, qui n'est là que sur le projet de
   repérage : sans elle, le montant sauterait de colonne d'une pièce à l'autre. */
.rail a.espace {
  display: grid;
  grid-template-columns: 13px minmax(0, 1fr) auto auto;
  align-items: center;
  column-gap: 9px;
  row-gap: 6px;
}
.rail a.espace .jauge-espace { grid-column: 2 / -1; }
.rail .rang { color: var(--encre-3); font-size: 10px; text-align: right; }
.rail .nom-espace { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jauge-espace { display: block; height: 4px; background: rgba(0, 0, 0, .11); border-radius: var(--rayon-petit); overflow: hidden; }
.jauge-espace i { display: block; height: 100%; background: var(--ok); }
.jauge-espace.vigilance i { background: var(--attente); }
.jauge-espace.depassement i { background: var(--refus); }
.rail a.actif .jauge-espace { background: rgba(0, 0, 0, .13); }

.bandeau-espace {
  display: flex; align-items: flex-end; gap: 18px; padding: 9px 16px;
  background: var(--surface); border-bottom: 1px solid var(--filet); flex: 0 0 auto;
  position: relative;
}
.bandeau-espace[hidden] { display: none; }
.bandeau-espace input { width: 140px; }
.bandeau-espace .chiffres { display: flex; gap: 18px; font-size: 12px; color: var(--encre-3); padding-bottom: 3px; }
.bandeau-espace .chiffres b { color: var(--encre); font-variant-numeric: tabular-nums; margin-left: 4px; }
.bandeau-espace .chiffres .vigilance b { color: var(--attente); }
.bandeau-espace .chiffres .depassement b { color: var(--refus); }
.bandeau-espace .chiffres .discret { color: var(--encre-3); font-style: italic; }
.jauge-large {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--filet-doux);
}
.jauge-large i { display: block; height: 100%; background: var(--ok); }
.jauge-large.vigilance i { background: var(--attente); }
.jauge-large.depassement i { background: var(--refus); }

.enveloppe-budget .ventilation {
  margin-top: 6px; font-size: 11px; color: var(--encre-3);
  border-top: 1px solid var(--filet-doux); padding-top: 5px;
}
.enveloppe-budget .ventilation.trop { color: var(--refus); }

/* ------------------------------------------------------------ pilotage */

.pilotage { padding: 18px 20px 40px; max-width: 940px; }
.pilotage section { margin-bottom: 22px; }
.pilotage h3 {
  font-size: 12.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 600; margin-bottom: 9px;
}
.pilotage .rien { font-size: 12.5px; color: var(--encre-3); margin: 0; }
.pilotage .deux-colonnes { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }

.cartes { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-bottom: 24px; }
.carte-chiffre {
  background: var(--surface); border: 1px solid var(--filet-doux);
  border-radius: var(--rayon); padding: 14px 16px;
}
.carte-chiffre span {
  display: block; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 600; margin-bottom: 5px;
}
.carte-chiffre b { display: block; font-size: 21px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.carte-chiffre b.vert { color: var(--ok); }
.carte-chiffre b.rouge { color: var(--refus); }
.carte-chiffre em { display: block; font-style: normal; font-size: 11px; color: var(--encre-3); margin-top: 3px; }

ul.alertes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
/* Le filet de couleur sur le flanc disait ce que le fond, le mot ou la
   capsule disaient deja : une marque de plus pour une seule information,
   et le motif se repetait dans sept endroits sans rapport entre eux. */
ul.alertes li {
  background: var(--surface); border-radius: var(--rayon-petit);
  padding: 7px 12px; font-size: 12.5px; color: var(--encre-2);
}
ul.alertes li[data-aller] { cursor: pointer; }
ul.alertes li[data-aller]:hover { background: var(--surface-2); }
ul.alertes li.refus { color: var(--refus); }
ul.alertes li.refus { color: var(--refus); }

table.repartition { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.repartition tr[data-aller] { cursor: pointer; }
table.repartition tr[data-aller]:hover td { background: var(--surface); }
table.repartition td { padding: 5px 8px; vertical-align: middle; }
table.repartition td.nom { width: 150px; color: var(--encre-2); }
table.repartition td.jauge { position: relative; }
/* Les colonnes de chiffres s'alignent a droite, en-tete compris, sinon
   l'oeil ne peut pas comparer une colonne au-dessus de son titre. */
table.repartition td.nombre, table.repartition th.nombre { width: 96px; text-align: right; }
table.repartition td.nombre { font-variant-numeric: tabular-nums; }
table.repartition td.nombre.discret, table.repartition th.nombre.discret { color: var(--encre-3); width: 110px; }
.barre-h { display: block; position: relative; height: 9px; background: var(--surface-2); border-radius: var(--rayon-petit); }
.barre-h i { display: block; height: 100%; background: var(--accent); border-radius: var(--rayon-petit) 0 0 var(--rayon-petit); }
.barre-h.vigilance i { background: var(--attente); }
.barre-h.depassement i { background: var(--refus); }
.repere { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--encre); opacity: .55; }
.legende-repere { font-size: 11px; color: var(--encre-3); margin: 6px 0 0; }

/* ---------------------------------------------------------- messages */

.messages { position: fixed; left: 50%; bottom: 54px; transform: translateX(-50%); z-index: 45; }
/* L'avis se pose AU-DESSUS de la bande de sélection, pas dessus. Un avis qui
   dit « 2 articles marqués » en couvrant « Mettre dans un véhicule » cache
   précisément le geste qu'il annonce. La hauteur de la bande est mesurée par
   le script : sur un écran étroit ses boutons passent à la ligne. */
body:has(.bande-selection:not([hidden])) .messages {
  bottom: calc(78px + var(--haut-bande, 46px));
}
.message {
  display: flex; align-items: center; gap: 12px;
  background: var(--encre); color: #F1F2F3; font-size: 12.5px;
  padding: 9px 15px; border-radius: var(--rayon-petit); box-shadow: 0 8px 26px rgba(0,0,0,.28);
}
.message button {
  background: none; border: 1px solid rgba(255,255,255,.34); color: #fff;
  border-radius: var(--rayon-petit); padding: 2px 9px; font-size: 12px; cursor: pointer;
}
.message button:hover { border-color: #fff; }
button.veille[hidden]{display:none}

/* -------------------------------------------- validite d'un code promo */

.tag.remise.bientot { background: var(--attente-fond); color: var(--attente); }
.tag.remise.expire {
  background: var(--surface-2); color: var(--encre-3); text-decoration: line-through;
}
.resume-remise .validite { display: block; margin-top: 3px; font-size: 11.5px; color: var(--encre-3); }
.resume-remise .validite.bientot { color: var(--attente); font-weight: 600; }
.resume-remise .validite.expire { color: var(--refus); font-weight: 600; }
.mots-suggeres button.expire { opacity: .5; text-decoration: line-through; }
.mots-suggeres button.bientot { border-color: var(--attente); color: var(--attente); }
.tiroir input[type="date"] {
  width: 100%; padding: 5px 8px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface); color: var(--encre);
}

/* ---------------------------------------------------------- HT et TTC */

.resume-taxe {
  margin-top: 7px; font-size: 12px; color: var(--encre-2);
  background: var(--papier); border-radius: var(--rayon-petit); padding: 6px 9px;
}
.resume-taxe b { font-variant-numeric: tabular-nums; }
.resume-taxe .detail { display: block; font-size: 11px; color: var(--encre-3); margin-top: 2px; }
.enveloppe-budget .ligne.mode b { font-size: 11px; letter-spacing: .06em; color: var(--accent-encre); }
#mode-taxe button { min-width: 38px; font-weight: 600; }

/* ------------------------------------------------------------- kanban */

.kanban {
  display: flex; gap: 12px; padding: 14px 16px 20px;
  align-items: flex-start; overflow-x: auto; height: 100%;
}
/* Une colonne teintee et arrondie qui contient des cartes bordees et
   arrondies : deux fonds, deux rayons et un cadre pour dire une pile. La
   colonne se delimite par son titre et par la gouttiere ; les cartes gardent
   leur fond, qui suffit a les detacher. Le cadre transparent reste : il
   reserve la place du filet de survol et evite le saut de mise en page. */
.kanban .colonne {
  flex: 0 0 218px; display: flex; flex-direction: column; max-height: 100%;
  border: 1px solid transparent; border-radius: var(--rayon);
}
.kanban .colonne.survol { border-color: var(--accent); }
.kanban .colonne > header {
  display: flex; align-items: center; gap: 7px; padding: 9px 11px 7px; flex: 0 0 auto;
}
/* capitalize mettait une majuscule a CHAQUE mot : « A Valider », « A
   Commander ». En francais seule la premiere en prend une, et le JS la pose
   deja. */
.kanban .colonne > header .titre {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--encre-2);
}
.pastille-etape {
  width: 7px; height: 7px; border-radius: 50%; background: var(--encre-3); flex: 0 0 auto;
}
/* Les memes quatre couleurs que les capsules du tableau : gris ce qui
   attend, sarcelle ce qui est parti, vert ce qui est acquis, rouge ce qui
   est revenu. Deux endroits qui disent la meme chose doivent la dire de la
   meme facon, sinon le kanban et le tableau se contredisent. */
.pastille-etape.a-commander { background: var(--encre-3); }
.pastille-etape.commande, .pastille-etape.livre, .pastille-etape.construit { background: var(--accent); }
.pastille-etape.valide, .pastille-etape.receptionne { background: var(--ok); }
.pastille-etape.retourne { background: var(--refus); }
/* Le compteur devient le meme nombre que dans le rail : une capsule blanche
   pour porter un chiffre a deux caracteres, c'etait une forme de plus. */
.kanban .colonne > header .nb {
  font-size: 12px; color: var(--encre-3); font-variant-numeric: tabular-nums;
}
.kanban .colonne > header .somme {
  margin-left: auto; font-size: 12px; color: var(--encre-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.kanban .pile {
  display: flex; flex-direction: column; gap: 7px;
  padding: 0 8px 10px; overflow-y: auto; min-height: 60px;
}
.kanban .colonne-vide {
  margin: 0; padding: 14px 4px; font-size: 11.5px; color: var(--encre-3); text-align: center;
}

.fiche-kanban {
  background: var(--surface); border: 1px solid var(--filet-doux); border-radius: var(--rayon);
  overflow: hidden; cursor: grab; display: flex; flex-direction: column;
}
.fiche-kanban:active { cursor: grabbing; }
.fiche-kanban.selectionne { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.fiche-kanban.enleve { opacity: .4; }
.fiche-kanban img, .fiche-kanban .sans-image {
  width: 100%; height: 96px; object-fit: contain; background: var(--papier); display: block;
}
.fiche-kanban .corps { padding: 7px 9px 9px; }
.fiche-kanban .nom {
  font-size: 12px; font-weight: 500; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.fiche-kanban .bas {
  display: flex; align-items: baseline; gap: 6px; margin-top: 4px; font-size: 11px; color: var(--encre-3);
}
.fiche-kanban .bas span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fiche-kanban .bas b { flex: 0 0 auto; color: var(--encre); font-variant-numeric: tabular-nums; }
.fiche-kanban .lieu { margin-top: 3px; font-size: 10.5px; color: var(--encre-3); }

/* ------------------------------------------------------ retour espere */

.tag.a-rendre { background: var(--attente-fond); color: var(--attente); font-weight: 600; }
.tag.a-rendre.bientot { background: var(--refus-fond); color: var(--refus); }
.tag.a-rendre.expire { background: var(--refus); color: #fff; }
.tag.rendu { background: var(--ok-fond); color: var(--ok); font-weight: 600; }
.resume-retour {
  margin-top: 7px; font-size: 12px; color: var(--encre-2);
  background: var(--papier); border-radius: var(--rayon-petit); padding: 6px 9px;
}
.resume-retour .validite { display: block; margin-top: 3px; font-size: 11.5px; color: var(--encre-3); }
.resume-retour .validite.bientot, .resume-retour .validite.expire { color: var(--refus); font-weight: 600; }
.carte-chiffre b.orange { color: var(--attente); }

/* ------------------------------------------- glisser-deposer du kanban */

.fiche-kanban { touch-action: none; user-select: none; }
/* Le glissement natif d'une image prime sur les evenements de pointeur et
   annule le notre : on le desactive sur tout le contenu de la carte. */
.fiche-kanban img, .fiche-kanban * { -webkit-user-drag: none; user-drag: none; }
body.glisse-en-cours { cursor: grabbing; }
body.glisse-en-cours * { cursor: grabbing !important; }

/* La fiche que l'on tient : elle suit le pointeur, legerement inclinee et
   soulevee, pour qu'on la distingue de celles qui restent en place. */
.fiche-kanban.fantome {
  position: fixed; z-index: 60; pointer-events: none; margin: 0;
  box-shadow: 0 12px 30px rgba(0,0,0,.26);
  transform: rotate(-1.5deg) scale(1.02);
  opacity: .96; border-color: var(--accent);
}
.fiche-kanban.fantome[data-lot]::after {
  content: attr(data-lot);
  position: absolute; top: -9px; right: -9px;
  background: var(--accent); color: #fff; font-size: 10.5px; font-weight: 600;
  border-radius: var(--rayon); padding: 2px 8px; box-shadow: 0 2px 6px rgba(0,0,0,.25);
}

/* La place laissee par la fiche en cours de deplacement. */
.fiche-kanban.en-cours { opacity: .3; }

/* Le trait qui montre ou la fiche va atterrir. */
.marqueur-depot {
  height: 3px; border-radius: var(--rayon-petit); background: var(--accent);
  margin: 1px 0; flex: 0 0 auto;
  /* Le halo etait en accent-doux, tres proche du papier : sans le fond de
     colonne derriere lui, il ne se detachait plus. Du blanc le decoupe. */
  box-shadow: 0 0 0 3px var(--surface);
}

/* Un filet d'accent suffit a dire ou la fiche va tomber : le fond teinte
   ramenait ici la couleur qu'on venait de retirer, et une colonne survolee ne
   doit pas changer de nature, seulement se designer. */
.kanban .colonne.survol .pile { min-height: 90px; }

/* -------------------------------------------------- dimensions et poids */

.mesures { font-size: 10.5px; color: var(--encre-3); margin-top: 2px; font-variant-numeric: tabular-nums; }
.fiche-kanban .mesures { margin-top: 3px; }
.mesures-detail { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--encre); }

/* --------------------------------------------------- adresse permanente */

.rail .titre { position: relative; }

/* ------------------------------------------------- simulation de budget */

.simulation {
  background: var(--surface); border: 1px solid var(--filet-doux);
  border-radius: var(--rayon); padding: 15px 17px; margin-bottom: 24px;
}

.simulation .verdict { margin-bottom: 15px; }
.simulation .verdict b { display: block; font-size: 17px; letter-spacing: -0.015em; margin-bottom: 3px; }
.simulation.tenu .verdict b { color: var(--ok); }
.simulation.suspendu .verdict b { color: var(--attente); }
.simulation.depasse .verdict b { color: var(--refus); }
.simulation .verdict span { font-size: 12.5px; color: var(--encre-2); max-width: 74ch; display: block; }

.fourchette { margin-bottom: 15px; }
/* Trois zones sur une seule barre : ce qui est SUR, ce que le client
   tranchera, et ce qu'on espere recuperer. Les deux dernieres etaient
   hachurees dans deux gris a deux pour cent l'un de l'autre, sur un fond du
   meme gris : on ne voyait qu'une barre sarcelle suivie de rien, et la
   fourchette du budget ne se lisait plus du tout.
   La hachure garde son sens, « pas encore acquis », mais elle se fait avec
   la couleur qui porte deja ce sens ailleurs : la sarcelle pour ce qui est
   engage, l'ambre pour ce qui attend un retour. */
.rampe {
  position: relative; display: flex; height: 18px; border-radius: var(--rayon-petit);
  background: var(--surface-2); overflow: visible;
}
.rampe .part { display: block; height: 100%; }
.rampe .part:first-child { border-radius: var(--rayon-petit) 0 0 var(--rayon-petit); }
.rampe .part.ferme { background: var(--accent); }
.rampe .part.arbitrage { background: repeating-linear-gradient(115deg,
  var(--accent-hachure) 0 5px, var(--accent-doux) 5px 10px); }
.rampe .part.incertain { background: repeating-linear-gradient(115deg,
  var(--attente-hachure) 0 5px, var(--attente-fond) 5px 10px);
  border-radius: 0 var(--rayon-petit) var(--rayon-petit) 0; }
.trait-enveloppe {
  position: absolute; top: -5px; bottom: -5px; width: 2px; background: var(--encre);
}
.trait-enveloppe::after {
  content: ''; position: absolute; top: -3px; left: -3px;
  border: 4px solid transparent; border-top-color: var(--encre);
}
.bornes {
  display: flex; justify-content: space-between; margin-top: 9px;
  font-size: 12px; color: var(--encre-3);
}
.bornes b { color: var(--encre); font-variant-numeric: tabular-nums; margin-left: 4px; }
.bornes .cible { font-weight: 600; color: var(--encre-2); }

table.repartition td.commentaire { color: var(--encre-3); font-size: 11.5px; padding-left: 14px; }
table.repartition td.commentaire.bientot, table.repartition td.commentaire.expire { color: var(--refus); }
table.decompte tr.total td { border-top: 1px solid var(--filet); font-weight: 600; padding-top: 8px; }
table.decompte tr.total td.commentaire { font-weight: 400; }

.detail-retours { margin-top: 12px; }
.detail-retours summary {
  cursor: pointer; font-size: 12px; color: var(--accent); padding: 4px 0;
}

/* ------------------------------------------- ajustement du prix client */

td.modifiable { cursor: text; }
td.modifiable:hover { box-shadow: inset 0 0 0 1px var(--filet); border-radius: var(--rayon-petit); }
input.prix-sur-place {
  width: 100%; padding: 2px 5px; font: inherit; font-size: 13px; text-align: right;
  border: 1px solid var(--accent); border-radius: var(--rayon-petit); background: var(--surface);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- rentabilite */

.rentabilite {
  background: var(--surface); border: 1px solid var(--filet-doux);
  border-radius: var(--rayon); padding: 15px 17px; margin-bottom: 24px;
}
.decompte tr.resultat td { font-size: 14px; }
.rentabilite.positif .decompte tr.resultat td.nombre { color: var(--ok); }
.rentabilite.negatif .decompte tr.resultat td.nombre { color: var(--refus); }

.saisie-rentabilite {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px; margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--filet-doux);
}
.saisie-rentabilite input {
  width: 100%; padding: 5px 8px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}

.honoraires { margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--filet-doux); }
.entete-honoraires {
  display: flex; align-items: center; gap: 12px;
  font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 600; margin-bottom: 7px;
}
.entete-honoraires button {
  background: none; border: 0; color: var(--accent); cursor: pointer;
  font-size: 11.5px; text-transform: none; letter-spacing: 0; font-weight: 400;
}
.honoraires input, .honoraires select {
  width: 100%; padding: 4px 7px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.honoraires input.h-montant { text-align: right; font-variant-numeric: tabular-nums; }
.honoraires .h-retirer {
  background: none; border: 0; color: var(--encre-3); cursor: pointer; font-size: 13px; padding: 0 4px;
}
.honoraires .h-retirer:hover { color: var(--refus); }
#vue-kanban[hidden]{display:none}
table.fiches img, .carte img { -webkit-user-drag: none; user-drag: none; }

.resume-marge .detail-taux {
  display: block; margin-top: 3px; font-size: 11.5px; color: var(--encre-3);
}

/* ------------------------------------------- retours comptes ou deduits */

/* L'hypothese en vigueur ne se marque plus par un triangle sur l'une de deux
   lignes jumelles : elle se dit en toutes lettres sous le montant qu'elle
   explique, et l'autre hypothese a son propre bloc. */
#mode-retours button { font-size: 11px; }
/* Un montant qui ne compte pas dans l'enveloppe ne se barre pas : un trait
   ne dit pas POURQUOI, et la question se pose a chaque fois. Il passe en
   gris et porte son motif en toutes lettres, dessous. */
td.nombre.hors-enveloppe { color: var(--encre-3); }
td.nombre .pourquoi {
  display: block; font-size: 10px; line-height: 1.2; color: var(--encre-3);
  font-variant-numeric: normal; margin-top: 1px;
}

/* ---------------------------------------------- sections du tiroir */

/* L'en-tete de fiche : ce qu'on veut savoir en ouvrant, sans defiler. */
.tiroir .entete-fiche {
  flex: 0 0 auto; padding: 10px 14px 10px; background: var(--surface);
  border-bottom: 1px solid var(--filet);
}
.tiroir .entete-fiche:empty { display: none; }
.entete-fiche .ligne-1 { display: flex; gap: 11px; align-items: flex-start; }
.entete-fiche .vignette {
  flex: 0 0 52px; width: 52px; height: 52px; object-fit: contain;
  background: var(--papier); border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); cursor: zoom-in;
}
.entete-fiche .vignette.vide { display: flex; }
.entete-fiche .identite { flex: 1; min-width: 0; }
.entete-fiche .designation {
  font-size: 14px; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.entete-fiche .marque { font-size: 12px; color: var(--encre-3); margin-top: 2px; }
.entete-fiche .chiffres {
  display: flex; flex-wrap: wrap; gap: 3px 14px; margin-top: 7px;
  font-size: 12px; color: var(--encre-3);
}
.entete-fiche .chiffres b { color: var(--encre); font-variant-numeric: tabular-nums; margin-left: 4px; }
.entete-fiche .chiffres .ok b { color: var(--ok); }
.entete-fiche .situation {
  display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; align-items: center;
}

/* Les sections : un titre qui resume, un contenu qui se replie. */
/* Un filet extremement fin, beaucoup d'air dans la section ouverte, et des
   sections fermees compactes. Une section fermee n'est qu'un titre : lui
   donner l'air d'une section ouverte fait onze lignes qui flottent, et l'on
   ne voit plus la liste. Ouverte, au contraire, elle a besoin de place.
   Le filet reste a un pixel, qui est le minimum, mais perd du contraste :
   c'est la couleur qui fait la finesse quand l'epaisseur ne le peut plus. */
.tiroir details.section {
  border-top: 1px solid var(--filet-doux);
  margin: 0 -14px; padding: 0 14px;
}

/* Rien au-dessus de la tete : un rembourrage ici glissait une bande blanche
   entre le chapitre du dessus et la tete du suivant, et l'on voyait deux
   separations la ou il n'y en a qu'une. L'air d'avant appartient au chapitre
   qui finit, jamais a celui qui commence : la section ouverte le donne par le
   bas de son contenu, la fermee par la hauteur de sa propre ligne. */
.tiroir details.section:first-of-type { border-top: 0; }
/* Le titre d'une section OUVERTE reste sous les yeux pendant qu'on la
   parcourt : dans un tiroir de onze chapitres dont un seul est long, on
   perdait le fil de celui qu'on lisait. Il se colle en haut du defilement,
   sur son propre fond pour que le contenu passe dessous sans se melanger.
   Ferme, il ne colle pas : il n'y a rien a suivre. */
/* Une seule hauteur pour les onze tetes, ouvertes comme fermees : c'est la
   teinte, et elle seule, qui dit laquelle est ouverte. Une tete plus haute
   ferait une deuxieme marque pour la meme chose, et le pas de la liste se
   deplacerait a chaque ouverture. */
.tiroir details.section > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  min-height: 64px; box-sizing: border-box; padding: 8px 0; user-select: none;
}
/* Le fond du titre colle deborde d'un pixel vers le haut : sans cela, une
   ligne de contenu affleure entre le bord du cadre et le titre au moment ou
   elle passe dessous. */
/* La tete d'une section ouverte est une bande : elle reste sous les yeux
   pendant qu'on parcourt le chapitre, puisqu'elle est deja collante, et c'est
   elle seule qui porte l'etat ouvert. Une tete fermee reste blanche. */
.tiroir details.section[open] > summary {
  position: sticky; top: 0; z-index: 3;
  background: var(--section-ouverte); margin: -1px -14px 0; padding: 8px 14px;
}
.tiroir details.section > summary::-webkit-details-marker { display: none; }
/* Les sections sont numerotees. Onze sections, c'est trop pour se reperer au
   titre seul, et la couleur qu'elles portaient avant ne disait pas non plus
   ou l'on se trouve. Un numero le dit : « le prix, c'est 06 », et il dit en
   plus combien il en reste.
   Il est CALCULE par un compteur CSS, jamais ecrit dans le gabarit : un
   numero saisi a la main derive des qu'une section apparait, disparait ou
   change de place, et personne ne s'en apercoit. */
#corps-tiroir { counter-reset: section-tiroir; }
.tiroir details.section { counter-increment: section-tiroir; }
.tiroir details.section > summary .nom {
  display: flex; align-items: center; gap: 11px;
  font-size: 15px; font-weight: 600; letter-spacing: 0;
  color: var(--encre); flex: 0 0 auto;
}
.tiroir details.section > summary .nom::before {
  content: counter(section-tiroir, decimal-leading-zero);
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--papier); color: var(--encre-3);
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.tiroir details.section.vide > summary .nom::before { opacity: .5; }
.tiroir details.section > summary .resume {
  flex: 1; min-width: 0; font-size: 12.5px; color: var(--encre-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tiroir details.section[open] > summary .resume { display: none; }
.tiroir details.section > summary .chevron {
  margin-left: auto; width: 7px; height: 7px; flex: 0 0 auto;
  /* Le chevron reste : sur un repli il dit « ceci s'ouvre », ce qu'une liste
     ne dit pas d'elle-meme. Il perd sa couleur, qui n'apprenait rien. */
  border-right: 1.5px solid var(--encre-3); border-bottom: 1.5px solid var(--encre-3);
  opacity: .7;
  transform: rotate(-45deg); transition: transform .15s; align-self: center;
}
.tiroir details.section[open] > summary .chevron { transform: rotate(45deg); }
.tiroir details.section > summary:hover .chevron { opacity: 1; }
/* Plus d'air entre la fin d'un chapitre et la tete du suivant : c'est ce qui
   remplace le fond continu pour dire ou l'un s'arrete. */
.tiroir details.section > .contenu { padding: 18px 0 40px; }
.tiroir details.section.vide > summary { opacity: .55; cursor: default; }
.tiroir details.section.vide > summary .chevron { visibility: hidden; }
.tiroir details.section .bloc:last-child { margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) { .tiroir details.section > summary .chevron { transition: none; } }

/* --------------------------------------- en-tete de fiche, suite */

.entete-fiche .designation.vide { color: var(--encre-3); font-weight: 400; font-style: italic; }
.entete-fiche .chiffres .fois { color: var(--encre-3); }
.entete-fiche .chiffres b.vert { color: var(--ok); }
.entete-fiche .chiffres b.rouge { color: var(--refus); }
.entete-fiche .situation { gap: 6px; font-size: 12px; color: var(--encre-2); margin-top: 0; }
.entete-fiche .situation .ou { color: var(--encre-3); }
.entete-fiche .alerte-fiche {
  margin-top: 7px; font-size: 11.5px; font-weight: 600;
  padding: 4px 9px; border-radius: var(--rayon-petit); display: block;
}
.entete-fiche .alerte-fiche[hidden] { display: none; }
.entete-fiche .alerte-fiche.attente { background: var(--attente-fond); color: var(--attente); }
.entete-fiche .alerte-fiche.refus { background: var(--refus-fond); color: var(--refus); }

/* La barre accent disparait : l'en-tete de fiche la remplace. */
.tiroir > header {
  background: var(--surface); color: var(--encre); padding: 9px 14px 0;
  border-bottom: 0;
}
.tiroir > header .titre { font-size: 11.5px; color: var(--encre-3); }
.tiroir > header button { color: var(--encre-3); font-size: 21px; }
.tiroir > header button:hover { color: var(--encre); }
.tiroir .entete-fiche { padding-top: 8px; }

/* ----------------------------------------- sous-replis et details */

/* Le sous-repli etait une carte dans une carte : un troisieme fond, un cadre
   et un rayon, poses a l'interieur d'une section qui en avait deja. Un filet
   au-dessus et de l'air suffisent a dire « ceci est en dessous ». */
.tiroir details.sous-section {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--filet-doux);
}
.tiroir details.sous-section > summary {
  list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 8px;
  padding: 0 0 2px; user-select: none;
}
.tiroir details.sous-section > summary::-webkit-details-marker { display: none; }
.tiroir details.sous-section > summary .nom {
  font-size: 11.5px; font-weight: 500; color: var(--encre-2); flex: 0 0 auto;
}
.tiroir details.sous-section > summary .resume {
  flex: 1; min-width: 0; font-size: 11.5px; color: var(--encre-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tiroir details.sous-section[open] > summary .resume { display: none; }
.tiroir details.sous-section > summary .chevron {
  margin-left: auto; width: 6px; height: 6px; flex: 0 0 auto; align-self: center;
  border-right: 1.5px solid var(--encre-3); border-bottom: 1.5px solid var(--encre-3);
  transform: rotate(-45deg); transition: transform .15s;
}
.tiroir details.sous-section[open] > summary .chevron { transform: rotate(45deg); }
.tiroir details.sous-section > .contenu { padding: 6px 0 0; }

/* L'identite du produit : la couverture a gauche, les champs a droite. */
.identite-produit {
  display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 16px;
  align-items: start; margin-bottom: 14px;
}
.identite-produit .couverture {
  margin: 0; cursor: zoom-in; aspect-ratio: 1; border-radius: var(--rayon); overflow: hidden;
  background: var(--papier); position: relative;
}
/* Les fleches se voient toujours, en retrait. Une commande qui n'apparait
   qu'au survol n'existe pas pour qui ne survole pas, et sur un ecran tactile
   elle n'existe pas du tout. */
.identite-produit .couverture .fleche {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(255, 255, 255, .82); color: var(--encre);
  font-size: 15px; line-height: 1; padding: 0 0 2px;
  display: flex; align-items: center; justify-content: center;
  opacity: .72; transition: opacity .12s ease;
}
.identite-produit .couverture:hover .fleche { opacity: 1; }
.identite-produit .couverture .fleche:hover { background: #fff; }
.identite-produit .couverture .fleche.avant { left: 5px; }
.identite-produit .couverture .fleche.apres { right: 5px; }
.identite-produit .couverture .compte-photos {
  position: absolute; right: 6px; bottom: 6px;
  background: rgba(255, 255, 255, .82); color: var(--encre-2);
  font-size: 10.5px; font-variant-numeric: tabular-nums;
  padding: 1px 6px; border-radius: var(--rond);
}
.identite-produit .couverture img { width: 100%; height: 100%; object-fit: cover; display: block; }
.identite-produit .visuel-produit { display: flex; flex-direction: column; gap: 6px; }
/* Trois vignettes fines sous la couverture, dans la largeur de la colonne.
   Une rangee pleine largeur coutait cent dix pixels de hauteur ; celle-ci en
   coute trente. */
/* Quatre colonnes pour quatre vignettes : la bande montre la couverture ET
   les trois suivantes, puisqu'elle sert d'index et non de complement. */
.bande-photos { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; }
.bande-photos figure { margin: 0; position: relative; cursor: zoom-in; }
.bande-photos figure img {
  width: 100%; aspect-ratio: 1; object-fit: cover; display: block;
  border-radius: var(--rayon-petit); background: var(--papier);
}
.bande-photos figure.surplus img { filter: brightness(.5); }
/* La vignette de la photo montree : un filet d'accent, pas un fond, pour
   qu'on voie encore la photo qu'elle designe. */
/* La vignette de la photo montree. Un contour EXTERIEUR : un inset sur une
   image la recouvre au lieu de l'entourer, et se perd sur une photo sombre. */
.bande-photos figure.active img { outline: 2px solid var(--accent); outline-offset: 1px; }
.bande-photos figure figcaption {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 11px; font-weight: 600; pointer-events: none;
}
.identite-produit .champs-identite { display: flex; flex-direction: column; gap: 10px; }
.identite-produit .champs-identite .bloc { margin-bottom: 0; }
@media (max-width: 520px) {
  .identite-produit { grid-template-columns: 1fr; }
  .identite-produit .visuel-produit { max-width: 160px; }
}

/* Galerie : une seule rangee, le reste derriere un « +N ». */
.tiroir .galerie figure { margin: 0; position: relative; cursor: zoom-in; }
.tiroir .galerie figure img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: contain;
  background: var(--papier); border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); display: block;
}
.tiroir .galerie figure.surplus img { filter: brightness(.55); }
.tiroir .galerie figure figcaption {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 14px; font-weight: 600; pointer-events: none;
}

/* Mentions discretes sous un champ : ce qui est devine, ce que disait le site. */
/* Une precision se lit en gris, partout ou elle s'ecrit. Reservee au tiroir,
   elle tombait en encre pleine dans les dialogues, ou elle pesait alors
   autant que la question posee. */
.tiroir .devine, .comparaison .devine { font-size: 11px; color: var(--encre-3); margin-top: 3px; }
.tiroir .capture { font-size: 11px; color: var(--encre-3); margin-top: 10px; }
.tiroir .notes { grid-template-columns: 1fr 1fr; display: grid; gap: 4px 14px; }
.tiroir .notes .critere { grid-template-columns: 74px 1fr; }

/* ------------------------------------- les sections du tiroir */
/*
   Elles portaient neuf teintes : un fond plein sur la barre de titre, un
   filet de couleur de 3 px a gauche du bloc, une pastille ronde devant le
   nom, et l'encre du titre. Exactement le systeme que le rail vient
   d'abandonner, et pour la meme raison : neuf couleurs qui decorent, aucune
   qui dit.
   La promesse « on reconnait une section a sa couleur » ne tenait d'ailleurs
   pas. Le tiroir declare ONZE sections et neuf teintes seulement ; trois
   d'entre elles retombaient sur le gris, et une teinte declaree ne
   correspondait a aucune section. Pire, le chevron etait dessine avec
   --teinte-encre sans valeur de repli : sur ces trois sections la variable
   n'existait nulle part, la declaration devenait invalide, et le chevron ne
   se dessinait tout simplement pas. Trois sections sur onze n'avaient aucun
   indicateur de pli.
   Un seul fond, des filets fins, de l'air : la meme regle que partout.
*/
.tiroir details.sous-section > .contenu > .duo .bloc input,
.tiroir details.sous-section > .contenu > .duo .bloc select { background: var(--surface); }

/* L'encart fournisseur se distingue de la section qui l'accueille. */
.tiroir .encart-fournisseur { background: var(--papier); }

/* Ordre des photos : les commandes se grisent aux extremites. */
.visionneuse .commandes button:disabled { opacity: .35; cursor: default; }
.visionneuse .commandes button:disabled:hover { filter: none; }
.visionneuse .commandes button[hidden] { display: none; }
.visionneuse .pellicule img.actif::after { content: ''; }

/* ------------------------------------------- zones de la colonne gauche */
/*
   Le rail, refondu.
   ------------------
   Il portait cinq blocs de couleur, chacun avec son filet a gauche, et
   l'atmosphere du projet les faisait glisser ensemble. Cinq fonds, cinq
   filets, des cadres, des pastilles : autant de systemes de decoration
   empiles pour dire une chose simple, une liste. Une barre laterale n'a pas
   besoin de cela. Elle a besoin d'UN fond, d'espace entre les groupes, et
   d'une seule couleur, celle de la ligne ou l'on se trouve.

   Ce qu'on perd : le fond colore par section. Ce qu'on garde : le camaieu du
   projet, qui vit maintenant la ou l'on regarde pour savoir ou l'on est,
   c'est-a-dire sur la ligne selectionnee. La couleur dit alors quelque chose
   au lieu d'habiller.
*/
/* Le filet respire des deux cotes. Il avait vingt et un pixels apres lui et
   trois avant : la derniere ligne d'un groupe se retrouvait collee au trait
   qui la separe du suivant, et le trait paraissait lui appartenir. */
.rail .groupe-rail { padding: 21px 0 18px; margin: 0 20px; border-top: 1px solid var(--filet-doux); }
.rail .groupe-rail:first-child { border-top: 0; padding-top: 4px; }
.rail .groupe-rail:last-child { padding-bottom: 8px; }
/* Les lignes s'alignent sur le filet du groupe, et leur propre marge
   interieure ecarte le texte du bord. Le fond d'une ligne selectionnee part
   donc du filet, et le texte respire en dedans. */

/* Le titre de groupe et son geste. Le « + » se tient au bout de la ligne, et
   ne s'allume qu'en approchant : present pour qui le cherche, muet le reste
   du temps. Il vivait au fond de la liste des projets, ou le pli le cachait. */
.rail .titre-groupe {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 11px 9px;
  /* Casse normale, pas de capitale espacee. La capitale suivie d'un fort
     interlettrage est un usage anglo-saxon : en francais les accents y
     flottent au-dessus du mot et la lecture se disloque. Finder ecrit
     « Favoris » et « Emplacements », pas « FAVORIS ».
     Le titre se voit par l'encre et par l'air, pas par la taille : le
     grossir jusqu'a peser autant qu'une ligne lui ferait concurrence, alors
     qu'il doit seulement annoncer. Il passe donc a l'encre du texte courant,
     avec six pixels d'air de plus au-dessus. */
  font-size: 12px; font-weight: 600; letter-spacing: 0;
  color: var(--encre-2);
}
.rail .geste-groupe {
  background: none; border: 0; padding: 0 2px; cursor: pointer; line-height: 1;
  font-size: 15px; color: var(--encre-3); opacity: .45;
  transition: opacity .12s ease, color .12s ease;
}
.rail .groupe-rail:hover .geste-groupe { opacity: 1; }
.rail .geste-groupe:hover, .rail .geste-groupe:focus-visible { color: var(--accent); opacity: 1; }

/* Une ligne du rail : une pastille arrondie qui se remplit quand on y est.
   Ni filet a gauche, ni cadre, ni chevron. Le chevron au bout de chaque ligne
   est un usage de liste tactile : sur une colonne qu'on parcourt a la souris,
   il ajoute douze fleches qui ne disent rien qu'on ne sache deja. */
/* Ni icone ni chevron. Chaque libelle est un mot distinct : une icone a cote
   de « Pilotage » n'ajoute pas d'information, elle ajoute une forme et une
   couleur. Un chevron au bout de chaque ligne dit « ceci mene quelque part »,
   ce qu'une barre laterale dit deja par nature. Restent les mots, l'espace, et
   les chiffres : c'est ce qu'on vient lire. */
.rail a {
  gap: 10px; padding: 7px 11px; margin: 0; border-radius: var(--rayon);
  border-left: 0; font-size: 13.5px; color: var(--encre-2);
}
.rail a .quoi { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail a:hover { background: var(--filet-doux); }
/* La ligne ou l'on se trouve se marque par un fond neutre, pas par une
   couleur. Une barre laterale dont la selection est coloree depense sa seule
   couleur sur ce qu'on sait deja, et n'en a plus pour ce qui reclame un
   geste : ici le rouge ne sert qu'a ce qui est en retard. */
.rail a.actif { background: var(--surface-2); color: var(--encre); font-weight: 600; }
.rail a.actif .nb { color: var(--encre-2); }
.rail a.survol { background: var(--accent); color: #fff; }
.rail a.survol .nb { color: #fff; opacity: 1; }

/* Le compte se lit en chiffres tabulaires : deux nombres l'un sous l'autre
   doivent s'aligner sur leurs unites, sinon la colonne se lit de travers. */
.rail a .nb { font-size: 12px; color: var(--encre-3); font-variant-numeric: tabular-nums; }
.rail a .nb.presse {
  background: var(--refus); color: #fff; border-radius: var(--rayon-grand); padding: 1px 6px; font-weight: 600;
}

.rail .lien-discret { display: block; margin: 3px 11px 2px; }

/* La liste des projets se replie sur celui qu'on regarde, et se rouvre au
   survol en decalant ce qui suit. Deux volets, un de chaque cote de la ligne
   en cours : les autres projets se deplient AUTOUR d'elle et non a sa place,
   si bien que la ligne qu'on regarde ne s'echappe pas de sous le curseur.
   Le survol d'un enfant vaut survol du parent : la liste ouverte se garde
   elle-meme ouverte tant qu'on est dessus.
   Le pli s'anime par grid-template-rows, seule facon de passer de rien a une
   hauteur inconnue d'avance : une hauteur maximale devinee saccade des que la
   liste est plus courte qu'elle. */
.rail .volet-projets {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .22s cubic-bezier(.4, 0, .2, 1);
}
.rail .volet-projets > div { overflow: hidden; min-height: 0; }
.rail .pile-projets:hover > .volet-projets,
.rail .pile-projets:focus-within > .volet-projets,
/* Pendant un glisser le survol ne s'applique plus : c'est le JS qui pose
   cette classe, sinon on ne pourrait jamais deposer sur un autre projet. */
.rail .pile-projets.deplie > .volet-projets { grid-template-rows: 1fr; }
@media (prefers-reduced-motion: reduce) {
  .rail .volet-projets { transition: none; }
}
.rail nav { padding: 10px 0 14px; }

/* ------------------------------------------------ coloris et tailles */

.choix-variante { display: flex; flex-wrap: wrap; gap: 5px; }
.choix-variante button {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2);
  border-radius: var(--rayon-grand); padding: 3px 10px 3px 4px; font-size: 11.5px; cursor: pointer;
}
.choix-variante button:not(:has(.pastille-coloris)) { padding-left: 10px; }
/* Les boutons de coloris tiraient leur couleur de la teinte de section, qui
   n'existe plus. Ils prennent l'accent : un bouton retenu est une decision,
   c'est exactement ce que l'accent sert a dire. */
.choix-variante button:hover { border-color: var(--accent); color: var(--accent-encre); }
/* La valeur retenue porte une coche : la couleur seule se perd sur une
   pastille de coloris deja coloree, et ne dit rien a qui la distingue mal. */
.choix-variante button.actif {
  border-color: var(--accent); background: var(--accent-doux);
  color: var(--accent-encre); font-weight: 600;
}
.choix-variante button.actif::after {
  content: '✓'; font-size: 11px; line-height: 1; margin-left: 1px;
}
.pastille-coloris {
  width: 17px; height: 17px; border-radius: 50%; flex: 0 0 auto;
  background-size: cover; background-position: center;
  border: 1px solid rgba(0, 0, 0, .16);
}
.choix-variante button.actif .pastille-coloris { border-color: var(--accent-encre); }

/* Une commande sans effet vaut mieux absente que grisee et muette. */
.bascule button[hidden] { display: none; }
.barre input[type="search"]:disabled { background: var(--surface-2); color: var(--encre-3); cursor: not-allowed; }

/* --------------------------------------------- reglages sur le pilotage */

.reglages-projet {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px;
}
.reglages-projet input, .reglages-projet textarea {
  width: 100%; padding: 6px 9px; font: inherit; font-size: 13px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
  font-variant-numeric: tabular-nums;
}
.reglages-projet textarea { resize: vertical; }
/* Le projet se choisit avant la piece : les deux tiennent sur la meme
   ligne, la piece suivant le projet retenu. */
.ou-ajout + .ou-ajout { margin-left: 4px; }
.reglages-projet .pleine-largeur { grid-column: 1 / -1; }

/* Le choix du camaieu : une rangee de galets, la couleur porte le sens. */
.camaieux { display: flex; flex-wrap: wrap; gap: 8px; }
.camaieux .swatch {
  display: flex; align-items: center; gap: 6px; padding: 5px 10px 5px 6px;
  border: 1px solid var(--filet); border-radius: var(--rond); background: var(--surface);
  font: inherit; font-size: 12px; color: var(--encre-2); cursor: pointer;
}
.camaieux .swatch:hover { border-color: var(--encre-3); }
.camaieux .swatch.actif { border-color: var(--encre); color: var(--encre); font-weight: 600; background: var(--surface-2); }
.camaieux .swatch .pastille { width: 14px; height: 14px; border-radius: 50%; background: var(--encre-3); flex: 0 0 auto; }
.camaieux .swatch.neutre .pastille { background: var(--surface); border: 1px solid var(--encre-3); }
.camaieux .swatch[data-camaieu="sarcelle"] .pastille   { background: hsl(190 58% 40%); }
.camaieux .swatch[data-camaieu="ardoise"] .pastille    { background: hsl(235 58% 40%); }
.camaieux .swatch[data-camaieu="myrtille"] .pastille   { background: hsl(280 58% 40%); }
.camaieux .swatch[data-camaieu="prune"] .pastille      { background: hsl(325 58% 40%); }
.camaieux .swatch[data-camaieu="terracotta"] .pastille { background: hsl(10 58% 40%); }
.camaieux .swatch[data-camaieu="ocre"] .pastille       { background: hsl(55 58% 40%); }
.camaieux .swatch[data-camaieu="sauge"] .pastille      { background: hsl(100 58% 40%); }
.camaieux .swatch[data-camaieu="celadon"] .pastille    { background: hsl(145 58% 40%); }
.archive-projet { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--filet-doux); display: flex; align-items: center; gap: 10px; }
.archive-projet button {
  padding: 5px 11px; border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
  cursor: pointer; font: inherit; font-size: 12.5px;
}
.archive-projet button:hover { border-color: var(--refus); color: var(--refus); }
.archive-projet .devine { font-size: 11.5px; color: var(--encre-3); }
table.repartition td.budget-piece { width: 132px; color: var(--encre-3); text-align: right; }
table.repartition td.budget-piece input {
  width: 74px; margin-left: 5px; padding: 2px 6px; font: inherit; font-size: 12.5px;
  text-align: right; border: 1px solid transparent; border-radius: var(--rayon-petit);
  background: transparent; color: var(--encre); font-variant-numeric: tabular-nums;
}
table.repartition td.budget-piece input:hover { border-color: var(--filet); background: var(--surface); }
table.repartition td.budget-piece input:focus { border-color: var(--accent); background: var(--surface); outline: none; }
table.repartition td.budget-piece input::placeholder { color: var(--encre-3); font-style: italic; }

.enveloppe-budget .vers-reglages {
  margin-top: 8px; font-size: 11px; color: var(--encre-3);
  border-top: 1px solid var(--filet-doux); padding-top: 6px;
}
.enveloppe-budget .vers-reglages button {
  background: none; border: 0; color: var(--accent); cursor: pointer; padding: 0; font-size: 11px;
  text-decoration: underline;
}

/* ------------------------------------------ repartition du projet */

/* La barre dit COMMENT le budget se divise entre les pieces, pas laquelle
   est laquelle. Elle donnait pourtant une teinte par piece, calculee sur le
   rang : onze couleurs pour onze pieces, c'est-a-dire aucune information,
   et les dernieres montaient si haut en clarte que leur libelle blanc
   tombait a 1,4 pour 1 de contraste, illisible.
   Une seule couleur, des segments separes par un filet de papier : la
   proportion se lit a la largeur, la piece a son nom, la limite au blanc
   entre deux. Et le blanc sur la sarcelle passe a neuf pour un. */
.repartition-projet {
  display: flex; gap: 2px; width: 100%; height: 20px;
  border-radius: var(--rayon-petit); overflow: hidden;
  background: var(--surface-2); margin-left: 18px; flex: 1 1 260px; min-width: 180px;
}
.repartition-projet .part {
  position: relative; display: flex; align-items: center; justify-content: center;
  min-width: 8px; cursor: pointer; overflow: hidden; background: var(--accent);
  border: 0; padding: 0; font: inherit;
  /* Le segment se mesure lui-meme : c'est la seule facon de savoir si le nom
     d'une piece y tient. Coupe en plein mot, « Entrée » devenait « Entré » puis
     « Ent », ce qui ne se lit pas et fait croire a un defaut d'affichage.
     En dessous, le nom se lit dans l'infobulle, qui le porte deja. */
  container-type: inline-size;
}
@container (max-width: 62px) { .repartition-projet .part em { display: none; } }
.repartition-projet .part:hover { filter: brightness(1.25); }
.repartition-projet .part:focus-visible { outline: 2px solid var(--encre); outline-offset: -2px; }
.repartition-projet .part.boite {
  background: repeating-linear-gradient(115deg, var(--filet), var(--filet) 4px, var(--surface-2) 4px, var(--surface-2) 8px);
  cursor: default;
}
.repartition-projet .part em {
  font-style: normal; font-size: 10px; color: #fff; white-space: nowrap;
  padding: 0 6px;
}
.repartition-projet .part.boite em { color: var(--encre-3); }
.repartition-projet .part[style*="width:0"] em,
.repartition-projet .part em { pointer-events: none; }

/* ------------------------------------------- blocs du pilotage */
/*
   Ils rejouaient exactement l'empilement retire du rail et du tiroir : un
   cadre, un filet de couleur de 3 px a gauche, un bandeau de titre colore
   avec sa pastille, et onze teintes posees par attribut. Onze couleurs pour
   onze blocs, c'est une couleur par bloc, donc aucune information.
   Un filet et de l'air, comme partout. Le triplet de repli reste declare :
   « .mots-client blockquote » s'y accroche encore, et il retombe alors sur le
   gris, ce qui est le comportement voulu.
*/
.bloc-pilotage {
  --teinte: var(--surface-2); --teinte-filet: var(--filet); --teinte-encre: var(--encre-2);
  padding: 26px 0 22px; border-top: 1px solid var(--filet-doux);
}
.pilotage .bloc-pilotage:first-of-type,
.direction .bloc-pilotage:first-of-type { border-top: 0; padding-top: 0; }

.bloc-pilotage > header {
  display: flex; align-items: baseline; gap: 10px; padding: 0 0 14px;
}
.bloc-pilotage > header .nom {
  display: flex; align-items: center;
  font-size: 14px; font-weight: 600; letter-spacing: 0; color: var(--encre);
}
.bloc-pilotage > header .sous-titre { font-size: 12px; color: var(--encre-3); }
.bloc-pilotage > .contenu { padding: 0; }

/* Troisieme niveau : les sous-titres a l'interieur d'un bloc. */
/* Troisieme niveau : casse normale, comme les deux au-dessus. */
.pilotage h4 {
  font-size: 12px; letter-spacing: 0;
  color: var(--encre-2); font-weight: 600; margin: 0 0 9px;
}
.pilotage .deux-colonnes > div + div { }
.pilotage .deux-colonnes h4 { margin-top: 0; }
.pilotage .bloc-pilotage .deux-colonnes { margin-top: 18px; }

/* Les deux encarts perdent leur cadre : le bloc le porte deja. */
.simulation, .rentabilite { background: none; border: 0; padding: 0; margin: 0; }
.simulation .verdict b { font-size: 18px; }
.pilotage section { margin-bottom: 0; }

/* ------------------------------------------- reprendre un prix releve */

.releve-a-reprendre {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px; padding: 8px 10px; border-radius: var(--rayon-petit);
  font-size: 12px; line-height: 1.4;
  background: var(--attente-fond); color: var(--attente);
}
.releve-a-reprendre.baisse { background: var(--ok-fond); color: var(--ok); }
.releve-a-reprendre b { font-variant-numeric: tabular-nums; }
.releve-a-reprendre > div { flex: 1 1 200px; min-width: 0; }
.releve-a-reprendre button {
  flex: 0 0 auto; padding: 4px 11px; font: inherit; font-size: 12px; font-weight: 600;
  border-radius: var(--rayon-petit); cursor: pointer; border: 1px solid currentColor;
  background: var(--surface); color: inherit;
}
.releve-a-reprendre button:hover { background: currentColor; }
.releve-a-reprendre button:hover { color: var(--surface); }
td.nombre .variation .fleche { opacity: .5; font-weight: 400; margin: 0 1px; }

/* L'unite se lit dans le libellé : un chiffre sans devise ne dit rien. */
.tiroir .bloc > label em.unite, .comparaison .bloc > label em.unite {
  font-style: normal; font-weight: 400; color: var(--encre-3); margin-left: 4px;
}

/* La reprise d'un prix releve dit ce qu'elle va changer avant de le changer. */
.releve-a-reprendre .consequence {
  font-size: 12.5px; line-height: 1.45; color: var(--encre-2); margin: 6px 0 8px;
}
.releve-a-reprendre .deux-boutons { display: flex; flex-wrap: wrap; gap: 6px; }
.releve-a-reprendre .deux-boutons button { flex: 1 1 auto; }
.releve-a-reprendre .deux-boutons button.principal {
  background: var(--accent); color: #fff; border-color: var(--accent);
}

/* ---- barre de filtres repliee -------------------------------------------
   Alignee a plat, elle grossit avec la bibliotheque jusqu'a couvrir l'ecran.
   Repliee en menus, elle garde la meme hauteur a dix fiches comme a mille. */
#filtres { display: block; }
#filtres[hidden] { display: none; }
.menus-filtres { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

.menu-filtre { position: relative; }
.menu-filtre > summary {
  display: flex; align-items: center; gap: 6px; cursor: pointer; list-style: none;
  padding: 4px 9px; border: 1px solid var(--filet); border-radius: var(--rond);
  background: var(--papier); font-size: 12px; white-space: nowrap; user-select: none;
}
.menu-filtre > summary::-webkit-details-marker { display: none; }
.menu-filtre > summary:hover { border-color: var(--encre-3); }
.menu-filtre[data-choisi] > summary { border-color: var(--encre); background: var(--surface-2); }
.menu-filtre > summary .nom { color: var(--encre-2); }
.menu-filtre[data-choisi] > summary .nom { color: var(--encre-3); }
.menu-filtre > summary b { font-weight: 600; color: var(--encre); }
.menu-filtre > summary .compte {
  font-size: 10.5px; color: var(--encre-3); background: var(--surface-2);
  border-radius: var(--rond); padding: 0 5px; line-height: 15px;
}
.menu-filtre > summary .chevron {
  width: 0; height: 0; margin-left: 1px;
  border: 3.5px solid transparent; border-top-color: var(--encre-3); transform: translateY(2px);
}
.menu-filtre[open] > summary .chevron { transform: translateY(-2px) rotate(180deg); }

.menu-filtre > .liste {
  position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; min-width: 210px;
  max-height: 320px; overflow-y: auto; padding: 5px;
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--rayon);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .13); display: flex; flex-direction: column; gap: 1px;
}
.menu-filtre > .liste button {
  display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  padding: 5px 7px; border: 0; border-radius: var(--rayon-petit); background: none;
  font-size: 12.5px; color: var(--encre); cursor: pointer;
}
.menu-filtre > .liste button:hover { background: var(--surface-2); }
.menu-filtre > .liste button.actif { background: var(--surface-2); font-weight: 600; }
.menu-filtre > .liste button .valeur { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-filtre > .liste button em { font-style: normal; font-size: 11px; color: var(--encre-3); }
.menu-filtre > .liste button.effacer {
  color: var(--encre-2); border-bottom: 1px solid var(--filet); border-radius: 0;
  margin-bottom: 3px; padding-bottom: 6px;
}
.menu-filtre .chercher-option {
  margin-bottom: 4px; padding: 5px 7px; font-size: 12px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--papier);
}
.menu-filtre .liste.bornes { gap: 7px; padding: 9px; }
.menu-filtre .liste.bornes label {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--encre-2);
}
.menu-filtre .liste.bornes input { width: 84px; padding: 4px 6px; border: 1px solid var(--filet); border-radius: var(--rayon-petit); }

/* Seuls les filtres actifs restent a plat : ils sont peu nombreux. */
.filtres-actifs { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.chip-actif {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: var(--rond); cursor: pointer; font-size: 11.5px;
  background: var(--encre); color: var(--surface); border: 1px solid var(--encre);
}
.chip-actif b { font-weight: 600; }
.chip-actif.tout { background: none; color: var(--encre-2); border-color: var(--filet); }

/* Un contact se lit d'un coup d'oeil et se joint d'un clic. */
.carte-contact {
  margin-top: 8px; padding: 8px 10px; border-radius: var(--rayon);
  background: var(--papier); border: 1px solid var(--filet);
  font-size: 12.5px; line-height: 1.6;
}
.carte-contact a { color: var(--encre); }

/* Une perte non declaree n'est pas la meme chose qu'une perte assumee. */
.repartition.pertes .raison { color: var(--encre-3); font-size: 11.5px; }
.repartition.pertes tr.subie .raison { color: var(--refus); }
.repartition.pertes .rouge { color: var(--refus); }

/* Ce qu'une commande totalise, la ou on decide de la passer. */
.resume-commande {
  margin-top: 9px; padding: 8px 10px; border-radius: var(--rayon);
  background: var(--surface); border: 1px solid var(--filet);
  font-size: 12.5px; line-height: 1.55; color: var(--encre-2);
}
.resume-commande b { color: var(--encre); }
.resume-commande .atteint { color: var(--ok); }
.resume-commande .frais-change { color: var(--refus); }

.repartition.commandes .raison { color: var(--encre-3); font-size: 11.5px; margin-top: 1px; }

/* Ce qu'une vente a perte coute a l'agence, dit en euros. */
.montant-perte {
  padding: 7px 9px; border-radius: var(--rayon-petit); font-size: 12.5px; line-height: 1.4;
  background: var(--papier); border: 1px solid var(--filet); color: var(--refus);
}
.montant-perte .rien { color: var(--encre-3); }
.repartition.pertes .unitaire { display: block; color: var(--encre-3); }

/* ---- la vue des commandes ------------------------------------------------
   Une commande se lit comme un bon : son entete, son etat, son contenu. */
.vue-commandes { padding: 14px 16px 40px; display: flex; flex-direction: column; gap: 12px; }
.entete-commandes {
  display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
}

/* Le filet de couleur sur le flanc disait exactement ce que dit la capsule
   posee trois centimetres plus loin : « pas encore passee », « commandee ».
   Deux marques pour un etat, c'est une de trop, et c'est celle qui teinte
   toute la carte qui part. */
/* Une commande etait une carte contenant quatre bandes de fonds differents
   empilees : l'etat en gris, l'autorisation en gris, le dossier en blanc,
   les lignes en blanc. Quatre fonds pour un seul objet, et l'oeil ne savait
   plus ou commencait la commande suivante. C'est une SECTION : un titre, un
   filet, et de l'air. */
.carte-commande {
  border-top: 1px solid var(--filet-doux); padding: 4px 0 18px;
}
.carte-commande > header {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 16px 0 10px;
}
.carte-commande h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--encre); }
.carte-commande .sous { font-size: 11.5px; color: var(--encre-3); margin-top: 2px; }
.carte-commande .chiffres { text-align: right; white-space: nowrap; }
.carte-commande .chiffres b { display: block; font-size: 15px; font-variant-numeric: tabular-nums; }
.carte-commande .chiffres span { font-size: 11.5px; color: var(--encre-3); }

/* La ligne d'etat est une rangee d'outils, pas un bandeau : c'est le fond
   gris qui en faisait un objet de plus a l'interieur de la commande. */
.etat-commande {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; row-gap: 8px;
  padding: 0 0 12px; font-size: 12px; color: var(--encre-2);
}
.etat-commande .plafond { color: var(--encre-3); }
.etat-commande .plafond input { width: 66px; text-align: right; }
/* « Dossier de commande » suit les autres gestes dans la rangee : pousse a
   droite, il se retrouvait seul sur une deuxieme ligne des que la rangee
   etait pleine, comme s'il n'appartenait a rien. */
.etat-commande .vers-dossier { color: var(--encre-2); }
.etat-commande label { display: flex; align-items: center; gap: 5px; }
.etat-commande input[type="date"] {
  padding: 3px 6px; border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
  font-size: 12px; color: var(--encre);
}
.lien-discret {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--encre-3); font-size: 12px; text-decoration: underline;
}
.change-commande {
  padding: 7px 13px; font-size: 12.5px; color: var(--encre-2); border-top: 1px solid var(--filet);
}

.lignes-commande { width: 100%; border-collapse: collapse; }
.lignes-commande tr { cursor: pointer; border-top: 1px solid var(--filet); }
.lignes-commande tr:hover { background: var(--papier); }
.lignes-commande td { padding: 7px 10px; font-size: 12.5px; vertical-align: middle; }
.lignes-commande td.vignette { width: 44px; padding-left: 13px; }
.lignes-commande img {
  width: 34px; height: 34px; object-fit: cover; border-radius: var(--rayon-petit);
  background: var(--surface-2); -webkit-user-drag: none;
}
.lignes-commande td.nombre { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* UN SEUL bouton principal dans toute l'application, et il porte l'accent.
   L'encre pleine servait ici, la sarcelle ailleurs : deux couleurs pour le
   meme role, et plus personne ne savait laquelle etait « le geste ». L'encre
   pleine ne reste que sur ce qui est ALLUME, un filtre par exemple, ou l'on
   ne clique pas pour agir mais pour eteindre. */
/* Une commande a passer et une commande passee ne se lisent pas pareil. */
.groupe-commandes { display: flex; flex-direction: column; gap: 10px; }
.groupe-commandes + .groupe-commandes { margin-top: 18px; }
.groupe-commandes > h2 {
  display: flex; align-items: baseline; gap: 8px; margin: 0;
  font-size: 12.5px; font-weight: 600; letter-spacing: 0;
  color: var(--encre-2);
}
.groupe-commandes > h2 .nb {
  font-size: 10.5px; letter-spacing: 0; color: var(--encre-3);
  background: var(--surface-2); border-radius: var(--rond); padding: 1px 6px;
}
.groupe-commandes > h2 .somme {
  margin-left: auto; letter-spacing: 0; text-transform: none;
  font-variant-numeric: tabular-nums; color: var(--encre);
}
.groupe-commandes > .rien { margin: -4px 0 2px; font-size: 12px; }

.bouton-passer {
  padding: 5px 13px; border-radius: var(--rond); cursor: pointer; font-size: 12px; font-weight: 600;
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
}
.bouton-passer[disabled] { opacity: .45; cursor: default; }
.etat-commande .devine { font-size: 11.5px; color: var(--encre-3); }

/* La facture et le mail de confirmation sont les preuves de la commande. */
/* Les preuves d'une commande ne servent qu'apres son passage : quatre champs
   vides sous chaque commande a passer prenaient plus de place que la
   commande. Elles se replient, et s'ouvrent d'elles-memes des qu'il y a
   quelque chose dedans. */
.preuves > summary {
  list-style: none; cursor: pointer; font-size: 12px; color: var(--encre-2);
  padding: 6px 0; user-select: none;
}
.preuves > summary::-webkit-details-marker { display: none; }
.preuves > summary::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 9px;
  border-right: 1.5px solid var(--encre-3); border-bottom: 1.5px solid var(--encre-3);
  transform: rotate(-45deg) translateY(-2px); transition: transform .15s;
}
.preuves[open] > summary::before { transform: rotate(45deg) translateY(-2px); }
.preuves > summary .rien { color: var(--encre-3); }
.preuves[open] {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px 16px; padding-bottom: 10px;
}
.preuves[open] > summary { grid-column: 1 / -1; }
@media (prefers-reduced-motion: reduce) { .preuves > summary::before { transition: none; } }
.preuves .bloc { display: flex; flex-direction: column; gap: 4px; }
.preuves label {
  font-size: 11.5px; letter-spacing: 0; color: var(--encre-3);
}
.preuves input[type="url"], .preuves input[type="text"] {
  padding: 5px 7px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--papier); font-size: 12px; color: var(--encre); min-width: 0;
}
.preuves input[type="file"] { font-size: 11.5px; color: var(--encre-2); }
.fichier-joint { display: flex; align-items: center; gap: 7px; font-size: 12px; flex-wrap: wrap; }
.fichier-joint > span { color: var(--encre-3); font-size: 11px; }
.lien-fichier {
  background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
  color: var(--encre); font-size: 12px; text-decoration: underline;
}
.lien-sortie { font-size: 11.5px; color: var(--encre-2); }
.ecart-facture { font-size: 11.5px; line-height: 1.35; }
.ecart-facture.plus { color: var(--refus); }
.ecart-facture.moins { color: var(--ok); }

.deja-commande {
  margin-top: 6px; padding: 7px 9px; border-radius: var(--rayon-petit); font-size: 12px; line-height: 1.45;
  background: var(--papier); border: 1px solid var(--filet); color: var(--encre-2);
}

/* Un mot-cle pose est une etiquette : on le voit, et on le retire d'un clic. */
.etiquettes { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; }
.etiquettes:empty { display: none; }
.etiquette {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 5px 3px 9px; border-radius: var(--rond); font-size: 11.5px;
  background: var(--surface-2); border: 1px solid var(--filet); color: var(--encre);
}
.etiquette .retirer {
  background: none; border: 0; padding: 0 2px; cursor: pointer;
  color: var(--encre-3); font-size: 13px; line-height: 1;
}
.etiquette .retirer:hover { color: var(--refus); }
#mots-suggeres:empty { display: none; }

/* Completer une liste livree est un geste courant, pas une exception. */
.choix-tags .ajout-tag { color: var(--encre-3); }

/* Le prix relevé se reprend d'un clic, depuis la ligne. */
button.variation {
  background: none; border: 1px solid transparent; border-radius: var(--rond);
  padding: 2px 7px; cursor: pointer; font: inherit; white-space: nowrap;
}
button.variation:hover { border-color: currentColor; }

/* Ce qu'un article vaut comme proposition : proposé, retenu, écarté. */
.bilan-propositions {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px;
}
.bilan-propositions .chiffre {
  flex: 1 1 62px; padding: 8px 9px; border-radius: var(--rayon);
  background: var(--papier); border: 0; text-align: center;
}
.bilan-propositions .chiffre b {
  display: block; font-size: 17px; font-variant-numeric: tabular-nums; color: var(--encre);
}
.bilan-propositions .chiffre span { font-size: 10.5px; color: var(--encre-3); }
.bilan-propositions .chiffre.vert b { color: var(--ok); }
.bilan-propositions .chiffre.rouge b { color: var(--refus); }
.bilan-propositions .chiffre.taux { background: var(--surface-2); }

.usages .usage {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 5px 7px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12.5px;
}
.usages .usage:hover { background: var(--papier); }

/* Une référence arrêtée et un achat d'occasion se voient dans la liste. */
.tag.arrete { background: var(--attente-fond); border-color: var(--attente-filet); color: var(--attente-encre); }

/* L'acceptation se lit en comptes, le pourcentage n'est qu'un repère. */
td.acceptation b { font-variant-numeric: tabular-nums; font-weight: 600; }
td.acceptation b .sur { color: var(--encre-3); font-weight: 400; margin: 0 1px; }
td.acceptation small { display: block; font-size: 10.5px; color: var(--encre-3); }
td.acceptation.vide { color: var(--encre-3); font-size: 11.5px; font-weight: 400; }

.taux-discret { font-size: 12px; color: var(--encre-2); margin-bottom: 6px; }
.taux-discret b { color: var(--encre); }

th.triable { cursor: pointer; user-select: none; }
th.triable:hover { color: var(--encre); }
th.triable::after { content: ' ⇅'; opacity: .35; font-size: 10px; }
th.triable.trie.desc::after { content: ' ↓'; opacity: 1; }
th.triable.trie.asc::after { content: ' ↑'; opacity: 1; }

.bouton-racheter {
  width: 100%; padding: 7px 11px; border-radius: var(--rayon); cursor: pointer; font-size: 12.5px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre-2);
}
.bouton-racheter:hover { border-color: var(--encre-3); background: var(--surface-2); }

.tag.rendu.partiel { background: var(--attente-fond); border-color: var(--attente-filet); color: var(--attente-encre); }

/* Louer ce qu'on a acheté : le loyer et la durée remplacent le coefficient. */
.resume-loyer {
  margin-top: 6px; padding: 7px 9px; border-radius: var(--rayon-petit); font-size: 12.5px; line-height: 1.5;
  background: var(--papier); border: 1px solid var(--filet); color: var(--encre-2);
}
.resume-loyer b { color: var(--encre); }
#bloc-loyer[hidden], #bloc-coefficient[hidden] { display: none !important; }

.tri-commandes { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--encre-2); }
.tri-commandes select {
  padding: 3px 6px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: 12px; color: var(--encre);
}

/* Les commandes en kanban : trois états, la date suit le déplacement. */
.bascules-commandes { display: inline-flex; gap: 2px; background: var(--surface-2); border-radius: var(--rond); padding: 2px; }
.bascules-commandes button {
  border: 0; background: none; padding: 3px 11px; border-radius: var(--rond);
  font-size: 12px; color: var(--encre-2); cursor: pointer;
}
.bascules-commandes button.actif { background: var(--surface); color: var(--encre); font-weight: 600; }
.kanban-commandes .colonne { min-width: 250px; }
.carte-cmd { cursor: grab; }
.carte-commande.surlignee { box-shadow: 0 0 0 2px var(--encre); }

/* Les états de commande sont déjà écrits comme il faut : « En attente », pas
   « En Attente ». */
.kanban-commandes .colonne header .titre { text-transform: none; }


/* Une date butoir se lit à sa couleur : dépassée, proche, ou tranquille. */
.etat-commande .butoir { display: flex; align-items: center; gap: 5px; }
.dit-butoir { font-size: 11.5px; }
.dit-butoir.expire, .butoir.expire { color: var(--refus); font-weight: 600; }
.dit-butoir.bientot, .butoir.bientot { color: var(--attente); font-weight: 600; }
.butoir.expire input, .butoir.bientot input { border-color: currentColor; }
.carte-commande[data-etat="a-passer"] .dit-butoir.expire { color: var(--refus); }
/* Ces pastilles portent leur propre fond : la couleur du texte doit gagner
   contre les regles de rail, plus specifiques, sinon on lit du sombre sur du
   sombre. */
/* La pastille de ce qui presse : un fond rose pale et l'encre rouge, pas un
   pave sature. Elle doit se remarquer dans une colonne calme, ce qui demande
   beaucoup moins de couleur qu'on ne croit. */
.rail a .nb.presse, .rail a.actif .nb.presse {
  background: color-mix(in srgb, var(--refus) 14%, transparent);
  color: var(--refus); padding: 1px 8px; border-radius: var(--rond); font-weight: 600;
}
.rail a.survol .nb.presse { background: rgba(255, 255, 255, .22); color: #fff; }

/* L'empilement des prix : catalogue, promotion, code, avoir, prix payé. */
.cascade-prix {
  margin: 10px 0; border: 0; border-radius: var(--rayon);
  background: var(--papier); font-size: 12.5px; overflow: hidden;
}
.cascade-prix > div {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 5px 10px; color: var(--encre-2);
}
.cascade-prix > div + div { border-top: 1px solid var(--filet); }
.cascade-prix b { font-variant-numeric: tabular-nums; color: var(--encre); }
.cascade-prix .gain b { color: var(--ok); }
.cascade-prix .total { background: var(--surface-2); font-weight: 600; }
.cascade-prix .total span, .cascade-prix .total b { color: var(--encre); }
.cascade-prix .dit { display: block; color: var(--encre-3); font-size: 11.5px; line-height: 1.4; }

.second-avantage { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--filet); }
.titre-avantage { font-size: 12.5px; font-weight: 600; color: var(--encre); }


/* Une référence que la marque ne fait plus se lit en retrait, tant qu'elle
   peut encore être commandée. Une ligne déjà commandée reste normale. */
table.fiches tr.arretee td { opacity: .52; }
table.fiches tr.arretee:hover td, table.fiches tr.arretee.selectionne td,
table.fiches tr.arretee.curseur td { opacity: .82; }
table.fiches tr.arretee .tag.arrete { opacity: 1; }
.case-filtre { margin-top: 7px; font-size: 12px; color: var(--encre-2); }

/* ---- indisponibilités, promotions, alertes de champ ---------------------
   Ce bloc avait disparu du fichier : les ruptures ne se voyaient plus, et le
   bandeau de promotion n'avait plus de cadre. */

/* Une taille en rupture reste affichée, la rupture étant souvent passagère,
   mais elle doit se voir du premier coup d'oeil : en couleur, pas en gris. */
.choix-variante button { position: relative; }
.choix-variante button.indisponible {
  background: var(--refus-fond); border-color: var(--refus-filet); color: var(--refus);
}
.choix-variante button.indisponible > span { text-decoration: line-through; }
.choix-variante button.indisponible .pastille-coloris { opacity: .55; }
.choix-variante button.indisponible.actif {
  background: var(--refus-fond-2); border-color: var(--refus); color: var(--refus-encre);
  font-weight: 600; box-shadow: inset 0 0 0 1px var(--refus);
}
/* Une valeur courte barree devient illisible : « L » se lit « Ł ». La couleur
   suffit a dire l'indisponibilite, le cadre rouge dit le reste. */
.choix-variante button.indisponible > span { text-decoration: none; }

/* Marquer une indisponibilite se demande en toutes lettres. */
.signaler-rupture { margin: 8px 0 2px; }
.signaler-rupture label {
  display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 12px; color: var(--encre-2);
}
.signaler-rupture select {
  padding: 4px 8px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: 12px; color: var(--encre);
}

/* La mention de rupture était une note grise sous les étiquettes, illisible. */
/* Signaler une rupture et la liste de ce qui manque sont un seul sujet :
   un seul cadre, une seule couleur, une seule respiration. */
/* Un bloc gris arrondi POSE DANS une section qui a deja sa tete et son air :
   une carte dans une carte. Un filet et de l'air suffisent, comme partout.
   Le fond ne revient que lorsqu'il y a vraiment une rupture a signaler,
   c'est-a-dire quand il dit quelque chose. */
.bloc-indispo {
  margin: 18px 0 4px; border: 0; border-top: 1px solid var(--filet-doux);
  border-radius: 0; background: none; overflow: hidden;
}
.bloc-indispo.avec-ruptures {
  border-top: 0; border-radius: var(--rayon); background: var(--refus-fond);
}
.bloc-indispo .signaler-rupture { margin: 0; padding: 14px 0 4px; }
.bloc-indispo.avec-ruptures .signaler-rupture { padding: 11px 13px; }
.bloc-indispo.avec-ruptures .signaler-rupture { background: var(--refus-fond); }
.recap-rupture {
  padding: 11px 13px; background: var(--refus-fond); border-top: 1px solid var(--refus-filet);
}
.recap-rupture .titre-rupture {
  font-size: 12.5px; font-weight: 600; color: var(--refus-encre); margin-bottom: 7px;
}
.recap-rupture .valeurs-rupture { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 7px; }
.recap-rupture .valeurs-rupture span {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 4px 3px 11px; border-radius: var(--rond); font-size: 12px; font-weight: 600;
  background: var(--refus-fond-2); color: var(--refus-encre);
}
.recap-rupture .valeurs-rupture em {
  font-style: normal; font-weight: 400; font-size: 11px; color: var(--refus-encre);
}
.recap-rupture .valeurs-rupture button {
  padding: 2px 9px; border-radius: var(--rond); cursor: pointer; font-size: 11px; font-weight: 500;
  background: var(--surface); border: 1px solid var(--refus-filet); color: var(--refus-encre);
}
.recap-rupture .valeurs-rupture button:hover { background: var(--refus-fond); border-color: var(--refus); }
.recap-rupture p { margin: 0 0 9px; font-size: 12px; line-height: 1.45; color: var(--refus-encre); }
.recap-rupture .bloc label { color: var(--refus-encre); }

/* Un prix en promotion se lit avec le prix d'avant et la date de fin. */
.promo-relevee {
  background: var(--attente-fond); border: 1px solid var(--attente-filet);
  border-radius: var(--rayon); padding: 8px 10px; margin: 8px 0; font-size: 12.5px; line-height: 1.5;
}
.promo-relevee s { color: var(--encre-3); }
.promo-relevee .jusqua { color: var(--encre-2); margin-top: 2px; }

.alerte-champ { font-size: 11.5px; line-height: 1.4; color: var(--refus); margin-top: 4px; }

/* Une valeur disponible ailleurs mais pas dans le choix courant : ce n'est
   pas une rupture, ce n'est pas rien non plus. */
.choix-variante button.partiel {
  color: var(--attente-encre); border-color: var(--attente-filet); background: var(--attente-fond);
}

/* Signaler une rupture demande la combinaison, pas seulement une valeur. */
.signaler-rupture { margin: 10px 0 2px; }
.signaler-rupture .titre-signaler {
  font-size: 12px; font-weight: 600; color: var(--encre-2); margin-bottom: 5px;
}
.lignes-signaler { display: flex; flex-wrap: wrap; gap: 7px; align-items: flex-end; }
.lignes-signaler label { flex: 1 1 92px; min-width: 0; }
.lignes-signaler select { width: 100%; }
.lignes-signaler button { flex: 0 0 auto; }
.lignes-signaler label {
  display: flex; flex-direction: column; gap: 3px;
  font-size: 11.5px; letter-spacing: 0; color: var(--encre-3);
}
.lignes-signaler select {
  padding: 4px 8px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--papier); font-size: 12px; color: var(--encre); text-transform: none; letter-spacing: 0;
}
.lignes-signaler button {
  padding: 5px 12px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12px;
  background: var(--surface-2); border: 1px solid var(--filet); color: var(--encre);
}
.lignes-signaler button:hover { border-color: var(--encre-3); }

#recherche[hidden], .aide[hidden] { display: none !important; }


/* « + Ajouter » et « − Supprimer » COMMANDENT, ils ne representent pas une
   valeur. Ils portaient pourtant la meme gelule que « Laiton brosse » et
   « Noir mat », a un pointille pres : la forme disait « je suis un coloris »
   sur ce qui n'en est pas un. Ce sont des mots, poses apres les valeurs.
   « − Supprimer » ouvre un mode, comme « + Ajouter » ouvre une saisie : on
   clique ensuite ce qu'on enleve, autant de fois qu'on veut. */
/* Vises tous deux DANS .choix-variante : la regle « .choix-variante button »
   l'emporte sinon en specificite, et « − Supprimer » gardait sa gelule
   pendant que « + Ajouter » devenait un mot. Deux commandes voisines qui ne
   se ressemblent plus est pire que deux commandes deguisees. */
.choix-variante .ajout-tag, .choix-variante .retrait-tag, .retrait-tag {
  border: 0; background: none; padding: 3px 2px; margin-left: 6px;
  font: inherit; font-size: 11.5px; color: var(--encre-3); cursor: pointer;
}
.choix-variante .ajout-tag:hover, .choix-variante .retrait-tag:hover,
.retrait-tag:hover { color: var(--encre); text-decoration: underline; }
.choix-variante .retrait-tag:hover, .retrait-tag:hover { color: var(--refus); }
.choix-variante .retrait-tag.actif, .retrait-tag.actif {
  color: var(--refus); font-weight: 600; text-decoration: underline;
}
.mode-retrait [data-valeur], .mode-retrait [data-tag] { cursor: crosshair; }
.mode-retrait [data-valeur]:hover, .mode-retrait [data-tag]:hover {
  border-color: var(--refus); background: var(--refus-fond); color: var(--refus);
  text-decoration: line-through;
}
.mode-retrait .ajout-tag { opacity: .45; pointer-events: none; }

/* Ce qui a ete constate a la reception, sur la fiche de l'article. Une
   ligne, pas une carte : elle se lit dans le fil de la section. */
.constat-reception {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--filet-doux);
  font-size: 12.5px; color: var(--encre-2);
}
.constat-reception .quoi-constat { flex: 1 1 220px; min-width: 0; }
.constat-reception .quoi-constat b { color: var(--encre); }
.constat-reception .avec-reserve { display: block; color: var(--attente); margin-top: 2px; }
.constat-reception .rien { color: var(--encre-3); }
.constat-reception button {
  flex: 0 0 auto; padding: 5px 11px; border-radius: var(--rayon-petit); cursor: pointer;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-2); font-size: 12px;
}
.constat-reception button:hover { border-color: var(--encre-3); color: var(--encre); }

/* Combien de chaque : trois blancs en M, deux noirs en L. */
.ventilation { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--filet); }
.titre-ventilation { font-size: 12px; font-weight: 600; color: var(--encre-2); margin-bottom: 6px; }
.lignes-ventilation { display: flex; flex-direction: column; gap: 5px; }
.ligne-ventilation {
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px;
  padding: 4px 6px; border-radius: var(--rayon); background: var(--papier); border: 1px solid transparent;
}
.ligne-ventilation.en-rupture { background: var(--refus-fond); border-color: var(--refus-filet); }
.ligne-ventilation .quoi { flex: 1; font-weight: 600; color: var(--encre); }
.ligne-ventilation.en-rupture .quoi { color: var(--refus-encre); }

/* Les pastilles composent le panier : le bouton nomme ce qu'il ajoute. */
.ajout-panier { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 10px 0 2px; }
.ajout-panier button {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 9px 16px 9px 12px; border-radius: var(--rayon); cursor: pointer; font-size: 13px;
  background: var(--accent); border: 1px solid var(--accent); color: #fff;
}
.ajout-panier button:hover { filter: brightness(1.12); }
.ajout-panier button .signe {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; font-size: 15px; line-height: 1;
  background: rgba(255, 255, 255, .18);
}
.ajout-panier button b { font-weight: 700; }
.ajout-panier button.en-rupture { background: var(--refus); border-color: var(--refus); }
.ajout-panier .avertissement { font-size: 11.5px; color: var(--refus); }
.ligne-ventilation .qte-ventilation {
  width: 58px; padding: 3px 7px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: 12px; text-align: right;
}
.ligne-ventilation .retirer-ventilation {
  background: none; border: 0; padding: 2px 4px; cursor: pointer;
  color: var(--encre-3); font-size: 11.5px; text-decoration: underline;
}
.ligne-ventilation .retirer-ventilation:hover { color: var(--refus); }
.ligne-ventilation .avertissement { font-size: 11px; color: var(--refus); }
.pied-ventilation {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 7px;
}
.pied-ventilation button {
  padding: 4px 10px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre-2);
}
.pied-ventilation button:hover { border-color: var(--encre-3); color: var(--encre); }
.total-ventilation { font-size: 12.5px; font-weight: 600; color: var(--encre); }

/* Créer un critère : les choix du site ne couvrent pas tout. */
.creer-critere { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: 10px 0 2px; }
/* Le pointille etait un ornement : il ne disait rien qu'un bouton ordinaire
   ne dise. Il ne reste dans l'application que la ou il signifie « une place
   vide qu'on peut remplir », sur une vignette absente. */
.creer-critere button {
  padding: 5px 12px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre-2);
}
.creer-critere button:hover { border-color: var(--encre-3); color: var(--encre); }
.creer-critere .devine { flex: 1 1 200px; }

/* ---- rapprocher une facture --------------------------------------------- */
.rapprochement { padding: 16px 18px 40px; display: flex; flex-direction: column; gap: 12px; }
.rapprochement h2 { margin: 0; font-size: 16px; font-weight: 600; color: var(--encre); }
.rapprochement .retour {
  align-self: flex-start; background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--encre-2); font-size: 12.5px;
}
.rapprochement .retour:hover { color: var(--encre); }
.rapprochement textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--filet); border-radius: var(--rayon);
  background: var(--surface); font-size: 12.5px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  line-height: 1.5; resize: vertical; box-sizing: border-box;
}
.actions-rappro { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.actions-rappro button {
  padding: 6px 13px; border-radius: var(--rayon); cursor: pointer; font-size: 12.5px;
  background: var(--papier); border: 1px solid var(--filet); color: var(--encre);
}
.actions-rappro button:hover { border-color: var(--encre-3); }
.actions-rappro button.principal { background: var(--accent); border-color: var(--accent); color: #fff; }
.actions-rappro .devine { flex: 1 1 220px; }
/* Rapprocher une facture est un geste d'entretien, pas le geste du jour :
   il partageait l'accent avec « Passer la commande », qui est LE geste de
   cet ecran. Deux boutons pleins pour deux gestes d'importance differente
   ne disaient plus lequel comptait. */
.bouton-facture {
  padding: 5px 12px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12.5px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre-2);
}

.bilan-facture {
  display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 10px 12px;
  border: 1px solid var(--filet); border-radius: var(--rayon); background: var(--papier);
  font-size: 12.5px; color: var(--encre-2);
}
.bilan-facture b { color: var(--encre); }

.table-rappro { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.table-rappro th {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--filet);
  font-size: 11.5px; letter-spacing: 0; color: var(--encre-3);
}
.table-rappro th.nombre, .table-rappro td.nombre { text-align: right; font-variant-numeric: tabular-nums; }
.table-rappro td { padding: 7px 8px; border-bottom: 1px solid var(--filet); vertical-align: top; }
.table-rappro tr.incertain td { background: var(--attente-fond); }
.table-rappro .sous { font-size: 11px; color: var(--encre-3); margin-top: 2px; }
.table-rappro select {
  width: 100%; padding: 4px 7px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: 12px; color: var(--encre);
}

/* Un critère ajouté à la main dit s'il entre dans les combinaisons. */
/* Le badge etait un bouton dans un <label> : le navigateur y renvoyait le
   clic, qui basculait donc deux fois et semblait ne rien faire. */
.entete-critere { display: flex; align-items: center; gap: 7px; }
.entete-critere label { margin: 0; }


/* Les mots proposés se retirent du vocabulaire comme les autres listes. */
#mots-suggeres.mode-retrait [data-mot] {
  cursor: crosshair; border-color: var(--refus); color: var(--refus);
}
#mots-suggeres.mode-retrait [data-mot]:hover { background: var(--refus-fond); text-decoration: line-through; }
#mots-suggeres .retrait-tag { padding: 2px 9px; font-size: 11px; }

/* Une quantité qui n'est que la somme d'une sélection se lit, ne se saisit pas. */
#t-quantite[readonly] {
  background: var(--papier); color: var(--encre-2); cursor: default;
}

/* Une ligne de sélection dit aussi où elle va : le même article peut partir
   dans deux pièces. */
.ligne-ventilation .ou-ventilation {
  padding: 3px 7px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); font-size: 12px; color: var(--encre-2); max-width: 150px;
}
.ajout-panier .ou-ajout {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--encre-3);
}
.ajout-panier .ou-ajout select {
  padding: 5px 8px; border: 1px solid var(--filet); border-radius: var(--rayon);
  background: var(--surface); font-size: 12.5px; color: var(--encre);
}

/* Un critère qui vient d'être créé se signale, sinon on ne le voit pas
   arriver au bas de la liste. */
.bloc.vient-d-arriver {
  animation: arrivee 1.6s ease-out;
  border-radius: var(--rayon);
}
@keyframes arrivee {
  0%   { background: var(--accent-doux); box-shadow: 0 0 0 6px var(--accent-doux); }
  70%  { background: var(--accent-doux); box-shadow: 0 0 0 6px var(--accent-doux); }
  100% { background: transparent; box-shadow: 0 0 0 6px transparent; }
}

/* Declarer un manque, c'est constater, pas detruire : le bouton porte la
   couleur dans son encre, pas dans son fond. Un rectangle rouge plein tirait
   l'oeil de toute la fiche vers un geste qu'on fait une fois sur vingt. */
.lignes-signaler button {
  background: var(--surface); border-color: var(--filet); color: var(--refus); font-weight: 500;
}
.lignes-signaler button:hover { border-color: var(--refus); filter: none; }

/* ---- mettre de côté ------------------------------------------------------
   Un article mis de côté reste dans le projet, garde son prix, et ne compte
   plus : il faut le voir d'un coup d'oeil sans le perdre. */
/* Le bouton passe en fin de ligne et ne parait qu'au survol : repete onze
   fois en tete de tableau, il faisait une colonne de bruit pour un geste
   rare. Il reste visible tant que la ligne est mise de cote, parce que la
   c'est un etat, plus une action. */
td.mise-de-cote, th.mise-de-cote { width: 34px; padding-left: 0; padding-right: 14px; text-align: right; }
td.mise-de-cote button {
  width: 22px; height: 22px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-3);
  font-size: 12px; line-height: 1; opacity: 0; transition: opacity .12s;
}
table.fiches tr:hover td.mise-de-cote button, table.fiches tr.ecartee td.mise-de-cote button,
td.mise-de-cote button:focus-visible { opacity: 1; }
@media (hover: none) { td.mise-de-cote button { opacity: 1; } }
td.mise-de-cote button:hover { border-color: var(--refus); color: var(--refus); }
/* Mis de cote n'est pas une erreur : c'est un choix. Il s'efface, il ne
   s'alarme pas. Un fond rouge sur toute la ligne criait au probleme. */
table.fiches tr.ecartee td { color: var(--encre-3); }
table.fiches tr.ecartee td:not(.mise-de-cote):not(.vignette) { text-decoration: line-through; }
table.fiches tr.ecartee td.mise-de-cote button {
  border-color: var(--filet); color: var(--encre-2); background: var(--surface);
}
table.fiches tr.ecartee-en-partie td.mise-de-cote::after {
  content: ''; display: block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--refus); margin: 3px auto 0;
}

.ligne-ventilation.ecartee { background: var(--refus-fond); }
.ligne-ventilation.ecartee .quoi { color: var(--refus); text-decoration: line-through; }
.ecarter-ventilation {
  width: 22px; height: 22px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-3); font-size: 12px;
}
.ecarter-ventilation:hover, .ecarter-ventilation.actif { border-color: var(--refus); color: var(--refus); }
.total-ventilation .mis-de-cote { color: var(--refus); font-weight: 400; }
/* Une pastille rouge veut dire « agis maintenant ». Ce qu'on a mis de cote
   n'est pas une urgence, c'est une economie : trois pastilles rouges de suite
   dans la meme colonne, et plus aucune ne se voit. Elle redevient un nombre. */
.rail a .nb.economie { color: var(--ok); font-variant-numeric: tabular-nums; }
/* Un compte qui cache du neuf passe a l'encre pleine, comme une boite aux
   lettres. C'est le seul endroit du rail ou un chiffre se fait remarquer sans
   etre une urgence : il appelle un regard, pas un geste. */
.rail a .nb.neuf { color: var(--encre); font-weight: 600; }
/* Un budget de piece depasse : le montant est negatif, il le dit. */
.rail a .nb.depasse { color: var(--refus); font-weight: 600; }
.rail a.actif .nb.depasse { color: var(--refus); }
.rail a.actif .nb.neuf { color: var(--encre); }

.vue-mis-de-cote { padding: 16px 18px 40px; display: flex; flex-direction: column; gap: 14px; }
.bilan-economie {
  padding: 12px 14px; border-radius: var(--rayon);
  background: var(--refus-fond); border: 1px solid var(--refus-filet);
}
.bilan-economie > div:first-child { font-size: 14px; color: var(--refus-encre); }
.bilan-economie b { font-size: 17px; }
.bilan-economie .rien { margin: 6px 0 0; font-size: 12.5px; line-height: 1.5; }

.table-mis-de-cote { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.table-mis-de-cote th {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--filet);
  font-size: 11.5px; letter-spacing: 0; color: var(--encre-3);
}
.table-mis-de-cote th.nombre, .table-mis-de-cote td.nombre {
  text-align: right; font-variant-numeric: tabular-nums; color: var(--refus); font-weight: 600;
}
.table-mis-de-cote td { padding: 9px 8px; border-bottom: 1px solid var(--filet); vertical-align: middle; }
.table-mis-de-cote td.vignette { width: 46px; }
.table-mis-de-cote img { width: 38px; height: 38px; object-fit: cover; border-radius: var(--rayon-petit); background: var(--surface-2); }
.table-mis-de-cote b { cursor: pointer; }
.table-mis-de-cote b:hover { text-decoration: underline; }
.table-mis-de-cote .sous { font-size: 11px; color: var(--encre-3); margin-top: 2px; }
.table-mis-de-cote td.actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.table-mis-de-cote td.actions button {
  padding: 4px 10px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 11.5px;
  background: var(--surface); border: 1px solid var(--filet); color: var(--encre);
}
.table-mis-de-cote td.actions button:hover { border-color: var(--encre-3); }

/* Un critère peut dépendre d'un autre : bleu impose le logo bleu. */
/* Le critere se lit sur UNE ligne : son nom a gauche, ses valeurs a droite.
   Le nom au-dessus coutait une ligne par critere, et sur une fiche a trois
   criteres cela faisait trois lignes de titre pour trois lignes de valeurs.
   Les commandes secondaires, lier et retirer, ne s'allument qu'en approchant :
   elles servent une fois par fiche, pas a chaque regard. */
.tiroir .bloc:has(> .choix-variante) {
  display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 4px 14px;
  align-items: start;
}
.tiroir .bloc:has(> .choix-variante) > .entete-critere { grid-column: 1; padding-top: 5px; }
.tiroir .bloc:has(> .choix-variante) > .choix-variante { grid-column: 2; }
.tiroir .bloc:has(> .choix-variante) > .devine,
.tiroir .bloc:has(> .choix-variante) > .lignes-signaler { grid-column: 2; }
.entete-critere {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  flex-direction: column; gap: 2px;
}
.entete-critere .lien-critere, .entete-critere .retirer-critere {
  opacity: 0; transition: opacity .12s ease;
}
.tiroir .bloc:hover .entete-critere .lien-critere,
.tiroir .bloc:hover .entete-critere .retirer-critere,
.entete-critere .lien-critere:focus-within, .entete-critere .retirer-critere:focus-visible { opacity: 1; }
/* Le repli tactile que la feuille applique partout ailleurs manquait ici :
   sans survol, « Retirer ce critère » et « Lier à un autre critère » étaient
   dans le DOM, câblés, et invisibles pour toujours sur une tablette. */
@media (hover: none) {
  .entete-critere .lien-critere, .entete-critere .retirer-critere { opacity: 1; }
}
.lien-critere {
  display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 0;
  font-size: 11px; letter-spacing: 0; text-transform: none; color: var(--encre-3);
}
.lien-critere .dit-lien { color: var(--accent-encre); }
.lien-critere .ouvrir-lien {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--encre-3); font-size: 11px; text-decoration: underline;
}
.lien-critere .ouvrir-lien:hover { color: var(--encre); }
.choix-lien { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.choix-lien[hidden] { display: none !important; }

/* Un emplacement vide ne doit pas dessiner une barre : « hidden » perd
   contre « display: flex ». */
.attache-critere[hidden] { display: none !important; }
.lien-critere select {
  padding: 1px 5px; border: 1px solid var(--filet); border-radius: var(--rond);
  background: var(--papier); font-size: 10.5px; color: var(--encre-2); text-transform: none;
}
.attache-critere {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 7px; padding: 8px 10px; border-radius: var(--rayon);
  background: var(--accent-doux); border: 1px solid var(--accent);
}
.attache-critere .quoi { font-size: 12px; color: var(--accent-encre); }
.attache-critere.invite {
  background: var(--section-ouverte); border-color: var(--filet-doux); border-style: solid;
}
.attache-critere.invite .quoi { color: var(--encre-2); }
.attache-critere .devine { flex: 1 1 100%; margin: 0; color: var(--accent-encre); opacity: .8; }
.choix-attache { display: flex; flex-wrap: wrap; gap: 4px; }
.choix-attache button {
  padding: 2px 9px; border-radius: var(--rond); cursor: pointer; font-size: 11.5px;
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre-3);
}
.choix-attache button.actif {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
/* Une valeur liee a d'autres se reconnait sans avoir a la selectionner. */
.choix-variante button.liee {
  border-color: var(--accent); color: var(--accent-encre);
  box-shadow: inset 2px 0 0 var(--accent);
}
.choix-variante button.liee.actif { box-shadow: inset 2px 0 0 var(--accent), inset 0 0 0 1px var(--accent); }

/* Une valeur qui n'existe pas avec ce qui est choisi : grisee, pas cachee.
   On voit qu'elle existe, et l'infobulle dit pourquoi elle est ecartee. */
.choix-variante button.hors-lien {
  opacity: .38; cursor: not-allowed; pointer-events: none;
  background: var(--papier); border-color: var(--filet-doux); color: var(--encre-3);
  box-shadow: none;
}
.choix-variante .tag-modifiable:has(button.hors-lien) { opacity: 1; }

/* Le lien pose se replie en une phrase, « changer » le rouvre. */
.attache-critere.pose {
  background: var(--papier); border-color: var(--filet); border-style: solid;
  padding: 6px 10px;
}
.attache-critere.pose .quoi { color: var(--encre-2); font-size: 11.5px; }
.attache-critere.pose .lien-discret { margin-left: auto; }

.ligne-ventilation.vient-d-arriver { animation: arrivee 1.4s ease-out; }

/* On met de côté une unité à la fois. */
.mise-de-cote-ligne { display: inline-flex; align-items: center; gap: 5px; }
.compte-ecarte { font-size: 11px; color: var(--refus); white-space: nowrap; }
.remettre-ventilation {
  width: 22px; height: 22px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--refus); background: var(--surface); color: var(--refus); font-size: 12px;
}
.ecarter-ventilation[disabled] { opacity: .35; cursor: default; }
.ligne-ventilation.ecartee-en-partie { background: var(--refus-fond); }
.ligne-ventilation.ecartee-en-partie .quoi { color: var(--refus); }

.table-mis-de-cote tr[data-fiche] { cursor: pointer; }
.table-mis-de-cote tr[data-fiche]:hover { background: var(--papier); }

/* Mettre à jour depuis le site : on montre les écarts, on choisit. */
.relire-fiche { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.relire-fiche button {
  padding: 6px 13px; border-radius: var(--rayon); cursor: pointer; font-size: 12.5px;
  background: var(--papier); border: 1px solid var(--filet); color: var(--encre);
}
.relire-fiche button:hover:not([disabled]) { border-color: var(--encre-3); }
.relire-fiche button[disabled] { opacity: .6; cursor: default; }
.relire-fiche .devine { flex: 1 1 180px; }

.comparaison {
  position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .38); padding: 24px;
}
.comparaison .dedans {
  background: var(--surface); border-radius: var(--rayon-grand); padding: 20px 22px;
  max-width: 720px; width: 100%; max-height: 82vh; overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
}
.comparaison h2 { margin: 0 0 4px; font-size: 16px; font-weight: 600; color: var(--encre); }
.comparaison .rien { margin: 0 0 12px; font-size: 12.5px; line-height: 1.5; }
.comparaison table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.comparaison th {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--filet);
  font-size: 11.5px; letter-spacing: 0; color: var(--encre-3);
}
.comparaison td { padding: 7px 8px; border-bottom: 1px solid var(--filet-doux); }
.comparaison td.avant { color: var(--encre-3); }
.comparaison td.apres { color: var(--accent-encre); font-weight: 600; }
/* « .actions » est aussi le nom de la barre de selection, tout en haut de
   cette feuille, qui porte un fond gris et un filet de bas. Elle fuyait donc
   dans TOUS les dialogues : leur rangee de boutons s'affichait sur une bande
   grise barree d'un trait, y compris dans la boite de reception. On rend ici
   ce que la barre pose, sans quoi deux objets sans rapport se partagent une
   apparence. */
.comparaison .actions {
  display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px;
  background: none; border-bottom: 0; padding: 0; flex-wrap: wrap;
}
.comparaison .actions button {
  padding: 7px 14px; border-radius: var(--rayon); cursor: pointer; font-size: 12.5px;
  background: var(--papier); border: 1px solid var(--filet); color: var(--encre);
}
.comparaison .actions button.principal { background: var(--accent); border-color: var(--accent); color: #fff; }

/* L'ordre des valeurs se change en glissant une pastille. */
.choix-variante button[data-valeur] { touch-action: none; }
.choix-variante button.en-deplacement { opacity: .3; }
.fantome-valeur {
  position: fixed; z-index: 70; pointer-events: none;
  box-shadow: 0 8px 20px rgba(0, 0, 0, .24); transform: rotate(-2deg);
}

/* Ce qui est saisi se voit partout, mais n'est pas encore acquis. */
#etat-brouillon {
  font-size: 11.5px; color: var(--attente); font-weight: 600;
  margin-right: auto; padding-left: 2px;
}
#etat-brouillon[hidden] { display: none !important; }

/* Remplacer un article : on choisit dans la bibliothèque ou on en capture un. */
.remplacement .dedans { max-width: 780px; }
.filtres-remplacement {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 12px;
}
.filtres-remplacement input[type="search"] {
  flex: 1 1 220px; padding: 6px 10px; border: 1px solid var(--filet); border-radius: var(--rayon);
  background: var(--papier); font-size: 12.5px;
}
.remplacement td.vignette { width: 46px; }
.remplacement img { width: 38px; height: 38px; object-fit: cover; border-radius: var(--rayon-petit); background: var(--surface-2); }
.remplacement .sous { font-size: 11px; color: var(--encre-3); }
.remplacement .sous.gagne { color: var(--ok); font-weight: 600; }
.remplacement .sous.coute { color: var(--refus); font-weight: 600; }
.remplacement td.nombre { text-align: right; font-variant-numeric: tabular-nums; }
.remplacement tbody button {
  padding: 4px 11px; border-radius: var(--rayon-petit); cursor: pointer; font-size: 12px;
  background: var(--accent); border: 1px solid var(--accent); color: #fff;
}

.avert-remplace {
  margin-bottom: 10px; padding: 8px 11px; border-radius: var(--rayon); font-size: 12.5px; line-height: 1.45;
  background: var(--refus-fond); border: 1px solid var(--refus-filet); color: var(--refus-encre);
}
.avert-remplace.doux {
  background: var(--accent-doux); border-color: var(--accent); color: var(--accent-encre);
}

/* Retirer un critere entier, et pas seulement ses valeurs : le geste porte
   sur le critere, il tient donc dans son en-tete, discret jusqu'au survol. */
.entete-critere { align-items: center; }
.entete-critere .retirer-critere {
  margin-left: auto; padding: 2px 8px; border-radius: var(--rond);
  border: 1px solid var(--filet); background: transparent;
  color: var(--encre-3); font: inherit; font-size: 11px; cursor: pointer;
  opacity: 0; transition: opacity .12s, color .12s, border-color .12s;
}
.bloc:hover .entete-critere .retirer-critere,
.entete-critere .retirer-critere:focus-visible { opacity: 1; }
.entete-critere .retirer-critere:hover { color: var(--refus); border-color: var(--refus); }

/* La devise du site tient sur une demi-largeur : elle n'a pas besoin de plus. */
.bloc.etroit { max-width: 260px; }

/* ---------------------------------------------------- reponse du client
   On ne change jamais l'etat d'un projet sur un code colle sans montrer,
   ligne par ligne, ce qui va bouger. */
.comparaison.reponse-client .dedans { max-width: 760px; }
.reponse-client textarea#rep-code {
  width: 100%; min-height: 78px; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px;
  border: 1px solid var(--filet); border-radius: var(--rayon); padding: 9px 11px;
  background: var(--papier); color: var(--encre-2); word-break: break-all;
}
.reponse-client textarea#rep-code:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
.reponse-client .avert-lecture {
  margin: 12px 0 0; padding: 9px 12px; border-radius: var(--rayon);
  background: var(--attente-fond); color: var(--attente); font-size: 12.5px;
}
.reponse-client .compte-reponse { display: flex; gap: 7px; flex-wrap: wrap; margin: 14px 0 8px; }
.reponse-client .compte-reponse span {
  border-radius: var(--rond); padding: 3px 11px; font-size: 12px; font-weight: 600;
}
.reponse-client .compte-reponse .ok { background: var(--ok-fond); color: var(--ok); }
.reponse-client .compte-reponse .attente { background: var(--attente-fond); color: var(--attente); }
.reponse-client .compte-reponse .refus { background: var(--refus-fond); color: var(--refus); }
.reponse-client .compte-reponse .quand { background: var(--filet-doux); color: var(--encre-3); }
.reponse-client .mot-client-general {
  background: var(--accent-doux); color: var(--accent-encre); border-radius: var(--rayon);
  padding: 10px 13px; margin-bottom: 12px; font-size: 13px;
}
.reponse-client table.apercu-reponse { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.reponse-client table.apercu-reponse th {
  text-align: left; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 600; padding: 5px 8px; border-bottom: 1px solid var(--filet);
}
.reponse-client table.apercu-reponse td {
  padding: 7px 8px; border-bottom: 1px solid var(--filet-doux); vertical-align: top;
}
.reponse-client table.apercu-reponse em.mot-client {
  display: block; color: var(--encre-3); font-size: 11.5px; margin-top: 2px;
}
.reponse-client .pastille.ok { background: var(--ok-fond); color: var(--ok); }
.reponse-client .pastille.attente { background: var(--attente-fond); color: var(--attente); }
.reponse-client .pastille.refus { background: var(--refus-fond); color: var(--refus); }

/* Le mot du client vaut autant que sa decision : c'est lui qui dit pourquoi,
   et c'est ce qu'on relit six mois plus tard. Il se lit dans la fiche, la
   ou l'on decide de la suite. */
.retour-client {
  border: 1px solid var(--filet-doux);
  border-radius: var(--rayon); padding: 10px 12px; margin-bottom: 12px; background: var(--papier);
}
.retour-client .entete-retour { display: flex; align-items: center; gap: 8px; }
.retour-client .entete-retour em { font-style: normal; color: var(--encre-3); font-size: 11.5px; }
.retour-client blockquote {
  margin: 8px 0 0; font-size: 13px; color: var(--encre-2); line-height: 1.5;
}
.retour-client blockquote::before { content: '« '; color: var(--encre-3); }
.retour-client blockquote::after { content: ' »'; color: var(--encre-3); }

/* ------------------------------------------------------- ce qui bloque
   Une file, une action par ligne, du plus coûteux au moins urgent. Rien de
   décoratif : cet écran s'ouvre le matin et doit se vider dans la journée. */
.vue-bloque { padding: 16px 20px 40px; }
.vue-bloque > table.table-bloque { background: var(--surface); }
.vue-bloque .date-cle {
  display: grid; grid-template-columns: minmax(0, 1fr) 200px; gap: 16px;
  background: var(--surface); border: 1px solid var(--filet);
  border-radius: var(--rayon); padding: 14px 16px; margin-bottom: 16px;
}
.vue-bloque .duo-date { display: grid; grid-template-columns: minmax(0, 1fr) 170px; gap: 8px; }
.vue-bloque > p.rien { margin: 0 0 16px; }

table.table-bloque { width: 100%; border-collapse: collapse; }
table.table-bloque th {
  text-align: left; font-size: 11.5px; letter-spacing: 0;
  color: var(--encre-3); font-weight: 500; padding: 12px 12px;
  border-bottom: 1px solid var(--filet-doux); position: sticky; top: 0; background: var(--surface);
}
table.table-bloque td { padding: 11px 12px; border-bottom: 1px solid var(--filet-doux); vertical-align: middle; }
/* Vingt-huit lignes sur fond rose ne disent plus « en retard » : elles
   disent « cet ecran est rose ». Le retard se lit la ou il se mesure, dans
   la colonne des dates, et dans le mot rouge qui nomme le blocage. Le fond
   reste blanc, comme partout ailleurs. */
table.table-bloque tr:hover td { background: var(--survol); }
table.table-bloque tr.en-retard td.quand .sous { color: var(--refus); font-weight: 500; }
table.table-bloque td.vignette { width: 58px; padding-right: 0; }
table.table-bloque td.vignette img {
  width: 44px; height: 44px; object-fit: cover; border-radius: var(--rayon); display: block;
}
table.table-bloque .sous { color: var(--encre-3); font-size: 11.5px; margin-top: 2px; }
table.table-bloque td.quand { white-space: nowrap; font-variant-numeric: tabular-nums; }
table.table-bloque td.actions { text-align: right; white-space: nowrap; }
table.table-bloque .pastille.urgent { background: var(--refus-fond); color: var(--refus); }
table.table-bloque .pastille.attente { background: var(--attente-fond); color: var(--attente); }
table.table-bloque .pastille.doux { background: var(--surface-2); color: var(--encre-3); }

.comparaison.reception-article .dedans { max-width: 560px; }

/* ------------------------------------------------------ premier ecran
   Un atelier neuf ne montre pas une erreur mais un point de depart : ce que
   l'outil fait, les trois gestes pour commencer, et de quoi le voir plein
   avant d'y mettre son travail. */
.vide.bienvenue { max-width: 620px; margin: 0 auto; padding: 56px 24px; text-align: left; }
/* Le nom se dit comme en haut du rail : au romain, sur le seul mot qui ne
   change jamais. Des capitales espacees en faisaient une marque de plus. */
.vide.bienvenue .marque-bienvenue {
  font-family: ui-serif, Georgia, "Iowan Old Style", "Palatino Linotype", serif;
  font-size: 19px; font-weight: 500; letter-spacing: -0.01em;
  color: var(--encre); margin-bottom: 14px;
}
.vide.bienvenue h3 { font-size: 24px; line-height: 1.2; margin: 0 0 10px; font-weight: 600; }
.vide.bienvenue > p { color: var(--encre-2); margin: 0 0 26px; max-width: 52ch; }

ol.etapes-depart { list-style: none; counter-reset: pas; margin: 0 0 26px; padding: 0; }
ol.etapes-depart li {
  counter-increment: pas; position: relative; padding: 0 0 18px 40px;
  border-left: 1px solid var(--filet); margin-left: 13px;
}
ol.etapes-depart li:last-child { border-left-color: transparent; padding-bottom: 0; }
ol.etapes-depart li::before {
  content: counter(pas); position: absolute; left: -13px; top: -2px;
  width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
}
ol.etapes-depart li b { display: block; font-size: 14px; }
ol.etapes-depart li span { display: block; color: var(--encre-3); font-size: 12.5px; margin-top: 2px; }
ol.etapes-depart li button {
  margin-top: 8px; background: var(--accent); color: #fff; border: 1px solid var(--accent);
  border-radius: var(--rayon); padding: 7px 14px; font-weight: 600; cursor: pointer;
}
ol.etapes-depart li button:hover { background: var(--accent-encre); }

.vide.bienvenue .essai {
  border-top: 1px solid var(--filet-doux); padding-top: 18px;
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
}
.vide.bienvenue .essai button {
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--rayon);
  padding: 7px 14px; font-weight: 600; cursor: pointer; color: var(--encre);
}
.vide.bienvenue .essai button:hover { border-color: var(--accent); color: var(--accent); }
.vide.bienvenue .essai span { color: var(--encre-3); font-size: 12.5px; flex: 1 1 260px; }

/* --------------------------------------------------------- volets d'outils
   Trois réglages d'affichage et deux actions rares occupaient la barre en
   permanence. Ils tiennent sous un bouton : la barre ne montre plus que ce
   qu'on utilise à chaque instant. */
.menu-outil { position: relative; }
.menu-outil > button[aria-expanded="true"] { background: var(--surface-2); color: var(--encre); border-color: var(--filet); }
.menu-outil .volet {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--rayon);
  box-shadow: 0 10px 30px rgba(22,24,27,.14); padding: 10px;
  /* Un bloc absolu se retrecit a la largeur de son parent, ici un bouton :
     le contenu debordait de la boite. « max-content » l'affranchit. */
  width: max-content; min-width: 268px; max-width: 380px;
}
.menu-outil .volet[hidden] { display: none !important; }
.volet-liste { min-width: 210px; padding: 6px; }
.volet-liste button {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 8px 10px; border-radius: var(--rayon-petit); cursor: pointer; font: inherit; color: var(--encre);
}
.volet-liste button:hover { background: var(--filet-doux); }
.volet-liste button[disabled] { opacity: .5; cursor: default; }

/* ------------------------------------------------------------- identite
   La marque tient dans trois traits : un nuancier qu'on déplie. Elle vit
   dans l'atelier, jamais sur ce que le client reçoit. */
.rail .titre h1 { display: flex; align-items: center; gap: 8px; }
.rail .titre h1 .marque { width: 17px; height: 17px; fill: var(--accent); flex: 0 0 auto; }
.outils-rail { display: flex; gap: 7px; align-items: center; flex: 0 0 auto; }

/* Sauvegarder et partager sont des gestes rares : ils gardent leur place a
   portee de main, sans prendre la largeur d'un mot. Le titre et l'aria-label
   disent ce que le dessin ne dit pas. */
.outils-rail .outil-icone {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: none; border: 1px solid var(--filet); border-radius: 50%;
  color: var(--encre-3); cursor: pointer;
}
.outils-rail .outil-icone:hover { border-color: var(--accent); color: var(--accent); }
.outils-rail .outil-icone:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.outils-rail .outil-icone svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}

.comparaison.identite-agence .dedans { max-width: 560px; }
.identite-agence .duo-couleur { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 8px; }
.identite-agence input[type="color"] {
  width: 44px; height: 34px; padding: 2px; border: 1px solid var(--filet);
  border-radius: var(--rayon-petit); background: var(--surface); cursor: pointer;
}
.apercu-identite { margin: 16px 0 4px; }
.faux-doc {
  /* La couleur vient du choix en cours, posee sur l'element ; la valeur de
     secours evite un apercu sans couleur avant le premier reglage. */
  --accent-agence: var(--accent);
  border: 1px solid var(--filet); border-radius: var(--rayon); padding: 18px 20px;
  background: var(--surface);
}
.faux-sur-titre {
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--accent-agence); font-weight: 700;
}
.faux-titre { font-size: 19px; font-weight: 600; margin: 7px 0 13px; }
.faux-boutons { display: flex; gap: 7px; }
.faux-bouton {
  border-radius: var(--rayon); padding: 6px 13px; font-size: 12.5px; font-weight: 600;
  background: var(--accent-agence); color: #fff;
}
.faux-bouton.fantome {
  background: transparent; color: var(--encre-2); border: 1px solid var(--filet);
}
.faux-pied {
  margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--filet-doux);
  color: var(--encre-3); font-size: 11.5px;
}

/* ------------------------------------------------- contrôle avant envoi
   Une remarque n'est utile que si elle mène à la ligne fautive : chaque
   nom est un bouton qui ouvre la fiche. */
.comparaison.controle .dedans { max-width: 720px; }
.famille-controle { margin-top: 18px; }
.famille-controle h3 {
  font-size: 12px; letter-spacing: 0;
  color: var(--encre-2); font-weight: 600; margin: 0 0 9px;
}
.remarque {
  border: 1px solid var(--filet-doux);
  border-radius: var(--rayon); padding: 11px 13px; margin-bottom: 8px; background: var(--surface);
}
.tete-remarque { display: flex; align-items: center; gap: 9px; margin-bottom: 4px; }
.tete-remarque b { font-size: 13.5px; }
.remarque .pastille.doux { background: var(--filet-doux); color: var(--encre-3); }
.remarque p.quoi { margin: 0; color: var(--encre-2); font-size: 12.5px; }
.remarque p.conseil { margin: 3px 0 0; color: var(--encre-3); font-size: 12.5px; }
.lignes-remarque { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 9px; align-items: center; }
.lignes-remarque button {
  background: var(--papier); border: 1px solid var(--filet); border-radius: var(--rond);
  padding: 3px 11px; font-size: 12px; cursor: pointer; color: var(--encre-2); font: inherit;
  font-size: 12px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lignes-remarque button:hover { border-color: var(--accent); color: var(--accent); }
.controle p.tout-bon {
  background: var(--ok-fond); color: var(--ok); border-radius: var(--rayon);
  padding: 13px 15px; margin: 4px 0 0; font-weight: 500;
}

/* Ce qu'un fournisseur annonce et ce qu'il fait sont deux choses : la mesure
   se lit à côté de l'étape, là où l'on décide de commander. */
.bloc.delai-constate { background: var(--papier); border-radius: var(--rayon); padding: 10px 12px; }
.bloc.delai-constate .mesure { font-size: 12.5px; color: var(--encre-2); }
.bloc.delai-constate .mesure + .mesure { margin-top: 3px; }

/* Le rangement dit déjà si la fiche est classée : la pastille n'apparaît que
   lorsqu'elle ajoute quelque chose, rejetée ou incomplète. */
td.rangement { white-space: nowrap; }
td.rangement .pastille { margin-left: 6px; }
td.rangement .en-boite { color: var(--encre-3); }

/* Le transport : ce qui remplit un camion et ce qui demande deux personnes.
   Les totaux disent toujours sur combien d'articles ils portent. */
/* Les chiffres du transport vivent DANS un bloc : ils n'ont pas besoin du
   cadre que la carte-chiffre porte quand elle est posee seule sur le papier. */
.chiffres-transport { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 14px; }
.chiffres-transport .carte-chiffre { background: none; border: 0; padding: 0; }
table.repartition.transport td.nombre { font-variant-numeric: tabular-nums; }

/* Annuler un passage de commande et supprimer la commande n'ont pas le même
   poids : le premier se cherche et se lit, le second reste discret et rouge. */
.carte-commande button.bouton-rouvrir {
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--rayon);
  padding: 5px 12px; font: inherit; font-size: 12px; font-weight: 600;
  color: var(--encre); cursor: pointer;
}
.carte-commande button.bouton-rouvrir:hover { border-color: var(--accent); color: var(--accent); }
.lien-discret.danger:hover { color: var(--refus); }

/* Les liens du tiroir suivent la palette : le bleu et le violet du
   navigateur n'appartiennent à aucune des deux. */
#corps-tiroir a { color: var(--accent); text-decoration-color: var(--filet); text-underline-offset: 2px; }
#corps-tiroir a:hover { text-decoration-color: currentColor; }
#corps-tiroir a:visited { color: var(--accent); }
.bloc a.lien-notice { font-weight: 600; }

/* Rien à enregistrer : le bouton le montre au lieu d'attendre un clic pour
   ne rien faire. Le pied dit lequel des deux cas on est. */
.tiroir footer button[disabled] {
  background: var(--filet-doux); border-color: var(--filet-doux);
  color: var(--encre-3); cursor: default; font-weight: 500;
}
.tiroir footer button[disabled]:hover { background: var(--filet-doux); }
#etat-brouillon {
  align-self: center; font-size: 11.5px; color: var(--attente); white-space: nowrap;
}
#etat-brouillon[hidden] { display: none !important; }

/* -------------------------------------------------------------- direction
   Tous les projets ensemble, avenir, en cours et passe : le tableau de bord
   qui sert a juger une annee, pas un projet. */
.pilotage.direction .barre-direction {
  display: flex; align-items: center; gap: 14px; margin-bottom: 18px; flex-wrap: wrap;
}
.filtre-annee { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--encre-2); }
.filtre-annee select {
  padding: 5px 9px; border-radius: var(--rayon-petit); border: 1px solid var(--filet);
  background: var(--surface); color: var(--encre); font: inherit; font-size: 12.5px;
}

table.repartition tr[data-aller-annee], table.repartition tr[data-aller-projet] { cursor: pointer; }
table.repartition tr[data-aller-annee]:hover td, table.repartition tr[data-aller-projet]:hover td {
  background: var(--surface);
}
table.repartition tr[data-aller-annee].actif td { background: var(--accent-doux); }
table.repartition tr[data-aller-annee].actif td:first-child { font-weight: 600; color: var(--accent-encre); }
table.table-projets-direction td.nom { width: auto; color: var(--encre); font-weight: 500; }

.cartes-statut { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
/* Des cartes blanches a cadre posees dans un bloc blanc : on ne voyait que la
   superposition des deux contours. Le fond suffit a dire ce qui est
   selectionne, comme dans le rail, et il laisse la couleur a ce qui presse. */
.carte-statut {
  text-align: left; background: none; border: 0; border-radius: var(--rayon);
  padding: 10px 12px; cursor: pointer; font: inherit; color: var(--encre); display: block;
}
.carte-statut:hover { background: var(--surface-2); }
.carte-statut.actif { background: var(--surface-2); }
.carte-statut.actif b { font-weight: 700; }
.carte-statut[disabled] { cursor: default; opacity: .55; }
.carte-statut[disabled]:hover { background: none; }
.carte-statut .pastille { display: inline-block; margin-bottom: 8px; }
.carte-statut b { display: block; font-size: 22px; font-variant-numeric: tabular-nums; }
.carte-statut .mot { font-size: 12px; color: var(--encre-3); }
.carte-statut em { display: block; font-style: normal; font-size: 11.5px; color: var(--encre-3); margin-top: 4px; }

/* --------------------------------------------------- declinaisons depliees
   Un t-shirt jaune et un t-shirt vert restent une seule fiche : les deplier
   permet d'agir sur l'un sans toucher l'autre, sans quitter le tableau. */
.deplier-ventilation {
  border: 0; background: transparent; color: var(--encre-3); cursor: pointer;
  font-size: 13px; padding: 2px 6px 2px 2px; margin-left: -4px; vertical-align: middle;
  border-radius: var(--rayon-petit); transition: transform .12s ease-out, background .12s ease-out;
}
.deplier-ventilation:hover { background: var(--filet-doux); }
.deplier-ventilation.ouvert { transform: rotate(90deg); }
.deplier-ventilation:hover { color: var(--accent); background: var(--accent-doux); }

tr.sous-ligne { background: var(--papier); }
tr.sous-ligne:hover { background: var(--filet-doux); }
tr.sous-ligne.selectionne { background: var(--accent-doux); }
tr.sous-ligne td { padding: 4px 8px; border-bottom: 1px solid var(--filet-doux); font-size: 12px; }
tr.sous-ligne td.sous-check { text-align: center; }
tr.sous-ligne td.sous-designation { padding-left: 22px; color: var(--encre-2); }
tr.sous-ligne .quoi { font-weight: 500; }
tr.sous-ligne .ou { color: var(--encre-3); margin-left: 8px; }
tr.sous-ligne .avertissement { color: var(--refus); margin-left: 8px; }
tr.sous-ligne .qte-sous-ligne {
  width: 48px; padding: 2px 5px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  font: inherit; font-size: 12px; text-align: right; font-variant-numeric: tabular-nums;
}
/* Le chiffre d'une déclinaison tombe dans la colonne Qté, sous celui de sa
   fiche. C'est un CHAMP : son cadre d'un pixel et ses cinq pixels de marge
   intérieure poussaient le chiffre à gauche de la colonne, et une colonne de
   nombres ne se lit qu'alignée. On retire donc à la cellule exactement ce que
   le champ ajoute : 12 px de marge comme les autres cellules, moins les 6 px
   que le champ met entre son bord et son texte. */
tr.sous-ligne td.nombre { padding-right: calc(12px - 6px); }
/* Les flèches d'un champ nombre apparaissent au survol dans Chrome, mangent la
   largeur du texte et décalent le chiffre : la colonne bougerait au passage de
   la souris. */
tr.sous-ligne .qte-sous-ligne::-webkit-inner-spin-button,
tr.sous-ligne .qte-sous-ligne::-webkit-outer-spin-button {
  appearance: none; margin: 0;
}

/* La barre des declinaisons cochees se distingue de la barre des fiches
   cochees : deux selections independantes, deux teintes. */
.actions.declinaisons { background: var(--attente-fond-2); }
.actions.declinaisons .nb { color: var(--attente-encre); }

/* ------------------------------------------------ boite de composition
   D'ou vient chaque partie d'une nouvelle configuration : une colonne par
   source, une ligne par critere. Peut compter plus de sources qu'un
   comparatif classique ne prevoit de place : elle s'elargit et défile. */
.comparaison.composition .dedans { max-width: 920px; }
table.table-composition { display: block; overflow-x: auto; white-space: nowrap; }
table.table-composition th, table.table-composition td { text-align: center; padding: 7px 12px; }
table.table-composition thead th:first-child, table.table-composition tbody th {
  text-align: left; white-space: normal; max-width: 160px;
  position: sticky; left: 0; background: var(--surface);
}
table.table-composition tbody th { font-weight: 500; color: var(--encre-2); }
table.table-composition input[type="radio"] { cursor: pointer; }

/* ------------------------------------------------- dossier de commande */
.comparaison.dossier-commande .dedans { max-width: 640px; }
.dossier-commande textarea {
  width: 100%; min-height: 320px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; line-height: 1.5; border: 1px solid var(--filet); border-radius: var(--rayon);
  padding: 10px 12px; background: var(--papier); color: var(--encre-2); resize: vertical;
}

/* ------------------------------------------------------ alternatives
   Un choix ouvert est la seule chose qui empeche le budget d'etre un
   chiffre : l'ecran montre les propositions cote a cote, avec ce qu'elles
   coutent et ce qu'elles rapportent, pour qu'on tranche en comparant plutot
   qu'en se souvenant.

   Une question etait une CARTE contenant trois panneaux separes par des
   gouttieres d'un pixel, avec une bande de pied pour deux liens : une carte
   dans une carte, quatre fonds pour un seul objet. Une question est une
   SECTION, comme les chapitres du tiroir : un titre, un filet, de l'air, et
   des colonnes que le blanc separe. */
.vue-alternatives { padding: 4px 18px 40px; }
/* Le bilan et le geste qui fonde l'ecran tiennent sur la meme ligne : poser
   une question n'est pas un reglage range en fin de page, c'est ce pour quoi
   on vient ici. */
/* Le geste principal de l'ecran, dans la barre, contre le titre. C'est deja
   la place du « + » du rail, contre « Projets » et contre « Pièces et lieux ».
   Pose dans le contenu, il flottait au milieu d'une ligne de prose, puis
   tombait seul sous elle sans appartenir a rien. */
/* Il prend l'habit des autres boutons de la barre, dont il ne se distingue que
   par sa place : contre le titre, avant l'espace, parce qu'il agit sur ce que
   l'ecran montre et non sur l'atelier entier. */
.geste-vue { margin-left: 4px; }
.geste-vue[hidden] { display: none !important; }
.vide .poser-question { margin: 4px 0 14px; }
/* Dans un ecran vide, ce bouton est le seul geste possible : il prend donc
   l'accent, qui dans cette maison ne designe qu'une chose, le geste
   principal. Ailleurs il cotoie « + une proposition » et reste discret. */
.poser-question.seul-geste {
  background: var(--accent); border-color: var(--accent); color: #fff; padding: 9px 18px;
  font-size: 13px;
}
.poser-question.seul-geste:hover { background: var(--accent-encre); border-color: var(--accent-encre); color: #fff; }
/* Un constat n'est pas un objet : c'est une phrase. */
.bilan-alternatives {
  margin: 14px 0 4px; font-size: 13px; color: var(--encre-2);
}
.bilan-alternatives b { font-variant-numeric: tabular-nums; color: var(--encre); }
.bilan-alternatives .rien { color: var(--encre-3); }

.carte-arbitrage {
  border-top: 1px solid var(--filet-doux); padding: 22px 0 26px;
}
.carte-arbitrage > header {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; flex-wrap: wrap; margin-bottom: 16px;
}
.carte-arbitrage .quoi-question { flex: 1 1 260px; min-width: 0; }
.carte-arbitrage h3 { font-size: 15px; }
.carte-arbitrage .sous { font-size: 12px; color: var(--encre-3); margin-top: 2px; }
.carte-arbitrage .chiffres b { font-size: 15px; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Les gestes rares de la question : ils vivent avec elle et ne s'allument
   qu'au survol. Une bande de pied pour deux liens faisait un etage de plus
   sous chaque question. */
/* Ce qui construit la question reste visible ; ce qui la defait attend qu'on
   s'approche. Tout mettre au survol avait rendu « + une proposition »
   introuvable, alors qu'aucun autre chemin ne mene a ce geste. */
.gestes-question { display: flex; gap: 14px; flex: 0 0 auto; align-items: baseline; }
.gestes-question button {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--encre-3);
  opacity: 0; transition: opacity .12s;
}
.gestes-question button.toujours { opacity: 1; color: var(--encre-2); }
.carte-arbitrage:hover .gestes-question button,
.gestes-question button:focus-visible { opacity: 1; }
@media (hover: none) { .gestes-question button { opacity: 1; } }
.gestes-question button:hover { color: var(--encre); text-decoration: underline; }
.gestes-question button.danger:hover { color: var(--refus); }

/* Les propositions sont separees par du BLANC, pas par un filet d'un pixel
   pose sur un fond gris. */
/* Une proposition est un OBJET, pas une bande : elle garde une largeur de
   lecture. Etirees a 1fr, deux propositions prenaient neuf cents pixels
   chacune, avec deux vignettes perdues dans le vide et un bouton large
   comme un ecran. Elles s'alignent a gauche et se serrent quand il y en a
   cinq, comme des cartes sur une table. */
.carte-arbitrage .branches {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 320px));
  gap: 30px; justify-content: start;
}
.carte-arbitrage .branche { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.tete-branche { display: flex; align-items: center; gap: 8px; }
.tete-branche .lettre {
  width: 20px; height: 20px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 11px; font-weight: 600;
  background: var(--surface-2); color: var(--encre-2);
}
/* La proposition retenue se marque a sa lettre et a son mot, pas a un fond
   vert sur toute la colonne : on compare deux propositions, et teinter l'une
   des deux fausse la comparaison avant qu'elle ait lieu. */
.branche.choisie .tete-branche .lettre { background: var(--ok); color: var(--surface); }
.tete-branche .nom { font-weight: 600; font-size: 13px; min-width: 0; }
.montant-branche { font-size: 15px; font-variant-numeric: tabular-nums; }
.montant-branche em { font-size: 11.5px; color: var(--encre-3); font-style: normal; margin-left: 8px; }

/* Une proposition d'amenagement se juge sur l'image avant le titre : elle
   occupe donc la place, et le nom passe dessous. Les tuiles s'ajustent a la
   largeur de la colonne, une proposition pouvant en porter une ou six. */
.carte-arbitrage ul.engage {
  margin: 0; padding: 0; list-style: none;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 9px;
}
.carte-arbitrage ul.engage li {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 11.5px; color: var(--encre-2); min-width: 0;
}
.carte-arbitrage ul.engage li .quoi {
  cursor: pointer; line-height: 1.3; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.carte-arbitrage ul.engage li .quoi:hover { color: var(--accent); }
.pied-engage { display: flex; align-items: center; gap: 4px; margin-top: auto; }
.carte-arbitrage ul.engage li.rien {
  grid-column: 1 / -1; color: var(--encre-3); font-style: italic;
}
.qte-engagee {
  width: 42px; padding: 1px 5px; font: inherit; font-size: 11.5px; text-align: right;
  border: 1px solid transparent; border-radius: var(--rayon-petit); background: transparent;
  color: var(--encre-2); font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
.qte-engagee:hover { border-color: var(--filet); background: var(--surface); }
.qte-engagee:focus { border-color: var(--accent); background: var(--surface); outline: none; }
.qte-engagee::placeholder { color: var(--encre-3); font-style: italic; }
.retirer-engagement {
  border: 0; background: none; color: var(--encre-3); cursor: pointer; padding: 0 2px;
  font-size: 12px; flex: 0 0 auto; opacity: 0;
}
.carte-arbitrage ul.engage li:hover .retirer-engagement { opacity: 1; }
.retirer-engagement:hover { color: var(--refus); }

.carte-arbitrage h3[contenteditable]:hover, .tete-branche .nom[contenteditable]:hover {
  background: var(--papier); border-radius: var(--rayon-petit); outline: 1px solid var(--filet);
}
.carte-arbitrage h3[contenteditable]:focus, .tete-branche .nom[contenteditable]:focus {
  background: var(--surface); outline: 2px solid var(--accent); border-radius: var(--rayon-petit);
}

/* Trancher est LE geste de cet ecran, mais il y en a un par proposition :
   aucun n'est « le » principal, ils sont le meme geste applique a des objets
   differents. Ils restent donc calmes, et c'est l'etat retenu qui parle. */
.choisir-branche {
  margin-top: auto; padding: 7px 10px; font: inherit; font-size: 12.5px; cursor: pointer;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); color: var(--encre-2);
}
.choisir-branche:hover { border-color: var(--ok); color: var(--ok); }
.dit-choisie {
  margin-top: auto; font-size: 12.5px; font-weight: 600; color: var(--ok);
  border: 1px solid var(--ok-fond); border-radius: var(--rayon-petit); background: var(--ok-fond);
  padding: 7px 10px; text-align: center; cursor: pointer; font-family: inherit;
}
.dit-choisie:hover { border-color: var(--ok); }

/* Les gestes de la proposition, sur une ligne, en mots. Deux cadres pleine
   largeur empiles sous chaque colonne faisaient six rectangles pour une
   question a trois propositions. */
.gestes-branche { display: flex; gap: 14px; align-items: baseline; }
.gestes-branche button {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 11.5px; color: var(--encre-3); text-align: left;
}
.gestes-branche button:hover { color: var(--encre); text-decoration: underline; }
.gestes-branche .retirer-branche { margin-left: auto; opacity: 0; }
.branche:hover .gestes-branche .retirer-branche,
.gestes-branche .retirer-branche:focus-visible { opacity: 1; }
.gestes-branche .retirer-branche:hover { color: var(--refus); }
@media (hover: none) { .gestes-branche .retirer-branche { opacity: 1; } }

/* ------------------------------------------------------- sauvegarde
   Une reprise efface tout : elle se lit avant de se lancer, d'ou un
   tableau avant-apres plutot qu'une simple confirmation. */
.comparaison.sauvegarde .dedans { max-width: 620px; }
.comparaison.sauvegarde table.repartition { margin-top: 10px; }
.comparaison.sauvegarde td.nombre.rouge { color: var(--refus); font-weight: 600; }
.comparaison.sauvegarde #sauv-reprise:not(:empty) {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--filet);
}
label.bouton-fichier {
  padding: 6px 12px; border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  background: var(--surface); cursor: pointer; font-size: 12.5px; color: var(--encre-2);
}
label.bouton-fichier:hover { border-color: var(--accent); color: var(--accent); }

/* Ce que le client a dit : sa phrase pese plus que nos chiffres, elle se
   lit donc telle quelle, pas resumee en une pastille. */

.mots-client blockquote { margin: 0 0 10px; padding: 0 0 0 12px; border-left: 2px solid var(--filet); }
.mots-client blockquote:last-child { margin-bottom: 0; }
.mots-client p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--encre); }
.mots-client cite { display: block; margin-top: 3px; font-style: normal; font-size: 11px; color: var(--encre-3); }

/* L'epingle de destination : discrete jusqu'au survol, franche une fois
   posee. C'est un geste de tous les jours, il se fait la ou on lit. */
.rail a .epingle {
  border: 0; background: none; cursor: pointer; line-height: 1;
  font-size: 12px; color: var(--encre-3); opacity: 0; flex: 0 0 auto;
  /* La cible faisait 18 par 12 pixels : on vise a cote une fois sur trois.
     L'etoile garde sa taille, sa zone de clic passe a 24 sans deranger la
     ligne, grace a la marge negative qui rend l'espace pris. */
  padding: 6px; margin: -6px -3px; display: inline-flex;
  align-items: center; justify-content: center;
}
.rail a:hover .epingle, .rail a .epingle:focus-visible { opacity: 1; }
.rail a .epingle.posee { opacity: 1; color: var(--attente); }
.rail a .epingle:hover { color: var(--attente); }

/* ---------------------------------------------------- ecrans etroits
   Servi depuis un hebergement, l'atelier s'ouvre aussi sur un telephone,
   sur le chantier, la ou l'on receptionne et ou l'on note les reserves.
   Un rail de 232 px y prenait les deux tiers de l'ecran. */
#basculer-rail {
  display: none; border: 0; background: none; cursor: pointer;
  font-size: 18px; line-height: 1; padding: 2px 8px 2px 0; color: var(--encre-2);
}
@media (max-width: 760px) {
  body { grid-template-columns: minmax(0, 1fr); }
  #basculer-rail { display: block; }
  .rail {
    position: fixed; inset: 0 auto 0 0; width: min(86vw, var(--rail)); z-index: 41;
    transform: translateX(-101%); transition: transform .18s ease;
    pointer-events: none;
  }
  body.rail-ouvert .rail {
    transform: none; pointer-events: auto;
    box-shadow: 0 0 24px rgba(0, 0, 0, .18);
  }
  /* Le voile etait une ombre portee de 100vmax. Une ombre ne recoit pas le
     doigt : toucher a cote du rail ne le fermait donc pas, et il fallait
     choisir une destination pour s'en sortir. Pire, l'ombre recouvrait le
     bouton ☰ qui l'avait ouvert. C'est maintenant un vrai element, sous le
     rail et au-dessus du reste, et il se ferme d'un doigt n'importe ou. */
  /* [hidden] perd contre display : on le dit explicitement, comme partout
     ailleurs dans cette feuille. Ici c'est l'inverse qu'on veut : le voile
     n'existe QUE sur ecran etroit, et l'attribut hidden le tient hors du
     large ou il n'a rien a faire. */
  #voile-rail {
    display: block; position: fixed; inset: 0; z-index: 40;
    background: rgba(0, 0, 0, .32);
    opacity: 0; pointer-events: none; transition: opacity .18s ease;
  }
  body.rail-ouvert #voile-rail { opacity: 1; pointer-events: auto; }
  /* Les barres d'outils s'empilent plutot que de deborder hors de l'ecran. */
  .barre { flex-wrap: wrap; row-gap: 6px; }
  .barre .recherche, .barre input[type="search"] { min-width: 0; flex: 1 1 120px; }
  /* Le tiroir faisait 430 px de large : sur un telephone de 375, il sortait
     de l'ecran par la droite et la fiche etait illisible. */
  .tiroir { width: min(100vw, 430px); }
  /* La barre d'aide liste des raccourcis CLAVIER. Sur un telephone il n'y a
     pas de clavier : elle ne servait a rien et mangeait quatre-vingt-dix
     pixels d'un ecran qui en a sept cents, en recouvrant la derniere ligne
     de la liste. On la retire plutot que de lui faire de la place. */
  .aide { display: none; }
  .contenu { padding-bottom: 24px; }
  /* Un tableau de quinze colonnes ne rentre pas : il defile dans sa propre
     zone plutot que de pousser toute la page de cote. Et il garde une largeur
     minimale : comprime a 375 px, la designation s'ecrasait sur huit lignes
     et chaque fiche prenait un ecran entier. */
  #contenu { overflow-x: auto; }
  table.fiches { min-width: 820px; }
  /* Les dialogues prennent l'ecran, avec une marge pour le pouce. */
  .comparaison .dedans { width: auto; max-width: none; margin: 12px; }
  /* « Fermer » d'abord : c'est le geste dont on a besoin quand on ne sait
     plus comment sortir, et il ne doit jamais dependre de la place restante. */
  .visionneuse .commandes { padding: 10px 12px; }
  /* La legende dit quelle photo on regarde : elle passe en tete, comme un
     titre, plutot que sous les boutons ou personne ne la cherche. */
  .visionneuse .commandes span { order: -1; flex: 1 1 100%; margin: 0; }
  .visionneuse .commandes button { min-height: 44px; }
  .visionneuse .nav { width: 40px; height: 60px; }
}

/* Une proposition d'amenagement se juge sur ce qu'on voit. Les vignettes
   restent petites : elles servent a reconnaitre, la fiche sert a regarder. */
.vignette-engagee { cursor: pointer; line-height: 0; display: block; }
.vignette-engagee img, .vignette-engagee .sans-photo {
  width: 100%; aspect-ratio: 1; max-height: 130px; object-fit: contain; display: block;
  background: var(--surface); border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit);
}
.vignette-engagee:hover img { border-color: var(--accent); }
.vignette-engagee .sans-photo {
  display: grid; place-items: center; border-style: dashed; border-color: var(--filet);
  color: var(--encre-3); font-size: 10px; font-style: italic;
}

/* L'enveloppe se lit en tete : sans elle, le budget restant tombe du ciel
   et personne ne peut refaire la soustraction. */
.enveloppe-budget .ligne.budget-enveloppe {
  border-bottom: 1px solid var(--filet-doux); padding-bottom: 16px; margin-bottom: 16px;
}
.enveloppe-budget .ligne.budget-enveloppe b { color: var(--encre); }

/* Ajouter un produit a une proposition : on choisit sur l'image, comme
   partout ailleurs dans les alternatives. */
/* Devenu un mot dans la rangee des gestes de la proposition : le cadre en
   pointille faisait un rectangle de plus sous chaque colonne. La regle reste
   pour les autres endroits qui l'appellent. */
.ajouter-produit {
  border: 1px solid var(--filet); background: var(--surface); border-radius: var(--rayon-petit);
  padding: 4px 10px; cursor: pointer; font: inherit; font-size: 11.5px; color: var(--encre-2);
}
.ajouter-produit:hover { border-color: var(--encre-3); color: var(--encre); }
.comparaison.choix-produit .dedans { max-width: 640px; }
.comparaison.choix-produit #cp-chercher {
  width: 100%; padding: 7px 10px; font: inherit; font-size: 13px; margin-bottom: 10px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.grille-produits {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px; max-height: 46vh; overflow-y: auto;
}
.produit-choisissable {
  display: flex; flex-direction: column; gap: 4px; text-align: left; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--rayon-petit); background: none; padding: 5px;
  font: inherit; font-size: 11.5px; color: var(--encre-2);
}
.produit-choisissable:hover { border-color: var(--accent); background: var(--papier); }
/* Choisie, la fiche prend l'encre pleine : dans cette maison, le plein dit
   « ceci est actif », et rien d'autre ne le dit en meme temps. */
.produit-choisissable[aria-pressed="true"] {
  border-color: var(--encre); background: var(--surface-2);
}
.produit-choisissable[aria-pressed="true"] .quoi { color: var(--encre); font-weight: 600; }
.nouvelle-question .dedans { max-width: 700px; }
.champ-question {
  display: block; font-size: 11.5px; color: var(--encre-3); margin: 14px 0 10px;
}
.champ-question input {
  display: block; width: 100%; margin-top: 4px; padding: 8px 10px;
  font: inherit; font-size: 14px; color: var(--encre);
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.champ-question input:focus-visible { border-color: var(--encre); outline: none; }
/* Le compte se lit a gauche, loin des boutons : c'est un etat, pas un geste. */
.compte-prises { margin-right: auto; font-size: 12px; color: var(--encre-3); align-self: center; }
.comparaison .actions button[disabled] { opacity: .45; cursor: not-allowed; }
.produit-choisissable .quoi {
  line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.produit-choisissable .prix { color: var(--encre-3); font-variant-numeric: tabular-nums; }

/* L'extra est choisi et range, mais hors enveloppe : il se lit a cote du
   budget sans s'y ajouter, d'ou une teinte propre. */
.enveloppe-budget .ligne.extras b { color: var(--attente); }

/* Choisir une piece, et rien d'autre : la question tient en un ecran, les
   pieces en gros boutons parce qu'on y va vite et qu'il y en a peu. */
.pieces-choisissables {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px;
}
.piece-choisissable {
  padding: 10px 16px; border: 1px solid var(--filet); border-radius: var(--rayon);
  background: var(--surface); font-size: 14px; cursor: pointer;
}
.piece-choisissable:hover, .piece-choisissable:focus-visible {
  border-color: var(--encre); background: var(--surface-2);
}
/* Ou dort la fiche : la piece, ou l'aveu qu'elle n'en a pas encore. */
.produit-choisissable .ou {
  display: block; font-size: 11px; color: var(--encre-3);
}
.produit-choisissable[data-sans-piece="oui"] .ou { color: var(--attente); }

/* Ce qu'on prend d'une fiche : une case par article retenu, sa quantite a
   cote, parce qu'une proposition peut n'en prendre qu'une partie. */
.articles-retenus { margin: 12px 0 4px; display: grid; gap: 6px; }
.articles-retenus .case {
  display: flex; align-items: center; gap: 8px; padding: 7px 9px;
  border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); background: var(--surface);
}
.articles-retenus .case > span:first-of-type { flex: 1; }
.articles-retenus .part-qte { width: 62px; }
.articles-retenus .sur { font-size: 11px; color: var(--encre-3); }
.articles-retenus .ou { font-size: 11px; color: var(--accent); }

/* Le sort des propositions écartées : trois sorties, chacune disant ce
   qu'elle fait au budget, parce que c'est la seule chose qui distingue. */
.sort-ecartees ul.ecartees {
  list-style: none; margin: 12px 0; padding: 0; display: grid; gap: 4px;
  max-height: 220px; overflow-y: auto;
}
.sort-ecartees .ecartees li {
  display: flex; gap: 10px; align-items: baseline; padding: 6px 9px;
  border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); background: var(--surface);
}
.sort-ecartees .ecartees .quoi { flex: 1; }
.sort-ecartees .ecartees .ou { font-size: 11px; color: var(--encre-3); }
.sort-ecartees .ecartees .prix { font-variant-numeric: tabular-nums; }
.sort-ecartees .sorties { display: grid; gap: 7px; margin-top: 4px; }
.sort-ecartees .sorties button {
  text-align: left; padding: 10px 13px; border: 1px solid var(--filet);
  border-radius: var(--rayon); background: var(--surface); font-size: 13px; cursor: pointer;
}
.sort-ecartees .sorties button:hover,
.sort-ecartees .sorties button:focus-visible {
  border-color: var(--encre); background: var(--surface-2);
}
.sort-ecartees .sorties em {
  display: block; font-style: normal; font-size: 11px; color: var(--encre-3); margin-top: 2px;
}

/* Une fiche sans article ne montre pas une quantité qu'elle n'a pas. */
.fiches td .a-choisir { color: var(--attente); font-size: 11px; }
.fiches th .unitaire { font-weight: 400; color: var(--encre-3); font-size: 10px; }

/* Voir le projet tel qu'il est composé, sans ce qui attend en boîte. */
#bandeau-espace .sans-boite {
  margin-left: auto; padding: 3px 10px; border: 1px solid var(--filet);
  border-radius: var(--rayon-grand); background: var(--surface); color: var(--encre-3);
  font-size: 11.5px; cursor: pointer;
}
#bandeau-espace .sans-boite:hover { border-color: var(--encre-3); color: var(--encre); }
#bandeau-espace .sans-boite.posee {
  background: var(--accent-doux); border-color: var(--accent); color: var(--accent-encre);
}

/* Une référence partie dans plusieurs pièces nomme la première et compte
   les autres, plutôt que de laisser croire qu'elle n'est nulle part. */
.fiches .rangement .et-ailleurs { color: var(--encre-3); font-size: 10px; }

/* Le taux réel se lit à côté de la marge, sans lui voler la vedette. */
.enveloppe-budget .ligne b .taux { font-style: normal; font-size: 11px; font-weight: 400; opacity: .85; }

/* Choisir ce qu'on retient d'une fiche, quand un geste de rangement l'exige.
   Même grammaire que le panneau de capture : des puces, une par valeur. */
.choix-article .critere { margin-top: 11px; }
.choix-article .critere strong { font-size: 12px; display: block; margin-bottom: 4px; }
.choix-article .valeurs { display: flex; flex-wrap: wrap; gap: 5px; }
.choix-article .puce-critere {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border: 1px solid var(--filet); border-radius: var(--rayon-grand);
  background: var(--surface); font-size: 12px; cursor: pointer;
}
.choix-article .puce-critere:hover { border-color: var(--encre-3); }
.choix-article .puce-critere.prise {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.choix-article .puce-critere.indispo { opacity: .55; text-decoration: line-through; }
.choix-article .quantite-article {
  display: flex; align-items: center; gap: 8px; margin-top: 14px; font-size: 12px;
}
.choix-article .quantite-article input { width: 78px; }
.choix-article .rien.manque { color: var(--refus); }

/* Réceptionner article par article : « trois blancs et deux noirs reçus en
   quatre » ne dit pas lesquels manquent. */
.recu-par-article { display: grid; gap: 5px; margin: 12px 0; }
.recu-par-article .ligne-recue {
  display: flex; align-items: center; gap: 9px; padding: 6px 9px;
  border: 1px solid var(--filet-doux); border-radius: var(--rayon-petit); background: var(--surface);
}
.recu-par-article .quoi { flex: 1; }
.recu-par-article .rec-part { width: 70px; }
.recu-par-article .sur { font-size: 11px; color: var(--encre-3); }

/* PRENDRE LES COTES QUI MANQUENT.
   Une tâche unique, faite une fois, mètre en main : une ligne par article,
   toujours les deux mêmes champs à la même place, pour qu'on descende la
   liste sans avoir à relire les intitulés. Le champ déjà renseigné reste
   visible mais éteint : on voit qu'il ne manque que l'autre, et l'on ne perd
   pas la colonne. */
.prise-de-cotes .a-mesurer {
  display: grid; gap: 6px; margin: 12px 0 0;
  max-height: 46vh; overflow-y: auto;
}
.prise-de-cotes .ligne-mesure {
  display: grid; grid-template-columns: minmax(0, 1fr) 148px 92px; gap: 9px;
  align-items: center;
}
.prise-de-cotes .quoi { min-width: 0; }
.prise-de-cotes .quoi .nom {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.prise-de-cotes .quoi .ou { font-size: 11px; color: var(--encre-3); }
.prise-de-cotes .ligne-mesure input:disabled {
  background: var(--surface-2); color: var(--encre-3);
}
/* Une saisie que le moteur n'a pas comprise n'est pas une saisie vide.
   Enregistrer sans le dire remplacerait par un blanc une cote qu'on croit
   avoir donnée, et le camion se recalculerait sur le reste sans un mot. */
.prise-de-cotes input.incompris { border-color: var(--refus); }
.prise-de-cotes .compte-mesures { margin: 12px 0 0; }

/* Une question que la réponse du client vient de trancher : c'est la
   conséquence la plus lourde de l'import, elle se lit avant d'appliquer. */
.comparaison.reponse-client .tranchee {
  margin-top: 10px; padding: 9px 11px; border-radius: var(--rayon-petit);
  background: var(--accent-doux); color: var(--accent-encre); font-size: 12.5px;
}

/* L'encart du budget se lit en trois temps : ce qui est engagé et ce qui
   reste, puis les autres hypothèses, puis ce que le projet rapporte. Un
   filet sépare, rien de plus : trois titres tiendraient plus de place que
   les chiffres. */
/* Chaque bloc repond a une question differente, et aucun ne la posait : on
   lisait quatre groupes separes par des filets, sans savoir ce qui les
   separe. Un nom fait ce qu'un fond de couleur ne peut pas faire, il DIT.
   Et il laisse la couleur a ce qu'elle sait dire ici : l'ambre pour ce qui
   est espere, le rouge pour ce qui manque, le vert pour ce qui est gagne. */
.enveloppe-budget .nom-bloc {
  font-size: 12px; font-weight: 600; letter-spacing: 0;
  color: var(--encre-2); margin-bottom: 9px; padding-inline: 11px;
}
/* Le texte de l'encart s'aligne sur celui du rail, et les filets comme les
   jauges gardent la largeur pleine. Meme rapport que plus haut : le trait
   court d'un bord a l'autre, le texte respire en dedans. Sans ce retrait, la
   colonne avait deux marges gauches, a onze pixels l'une de l'autre. */
.enveloppe-budget .ligne, .enveloppe-budget .arbitrage,
.enveloppe-budget .ventilation, .enveloppe-budget .franco { padding-inline: 11px; }
.enveloppe-budget .bloc-budget {
  border-top: 1px solid var(--filet-doux);
  margin-top: 20px;
  padding-top: 16px;
}

/* L'encart dit beaucoup, et tout n'interesse pas tout le monde tous les
   jours. Ce qu'on a choisi se lit d'un coup d'oeil ; le reste se deplie au
   survol, en decalant ce qui est au-dessus.
   Une hauteur maximale suffit ici, contrairement au pli des projets : ces
   lignes ont toutes la meme hauteur, connue et courte, et la marche que
   laisserait une valeur trop genereuse ne se voit pas. */
/* La classe est doublee a dessein : « .enveloppe-budget .repliable » pese
   moins que « .enveloppe-budget .ligne.budget-enveloppe », qui garde son
   rembourrage bas et son filet. Le repli perdait donc la bataille de
   specificite sur cette ligne precise, et laissait un vide a sa place. */
.enveloppe-budget .repliable.repliable {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  /* Les DEUX cotes, et les bordures avec. Ne rendre que la hauteur et les
     marges du haut laissait a chaque ligne repliee sa marge basse, son
     rembourrage bas et son filet : invisibles un a un, ils ouvraient un vide
     de plusieurs dizaines de pixels des qu'on repliait le milieu d'un bloc.
     On voyait alors deux lignes separees par du rien. */
  margin-block: 0;
  padding-block: 0;
  border-block-width: 0;
  transition: max-height .22s cubic-bezier(.4, 0, .2, 1), opacity .14s ease,
    margin .22s cubic-bezier(.4, 0, .2, 1), padding .22s cubic-bezier(.4, 0, .2, 1);
}
.enveloppe-budget:hover .ligne.repliable,
.enveloppe-budget:focus-within .ligne.repliable { max-height: 4.4rem; opacity: 1; margin-bottom: 7px; }
.enveloppe-budget:hover .ligne.budget-enveloppe.repliable,
.enveloppe-budget:focus-within .ligne.budget-enveloppe.repliable {
  padding-bottom: 16px; margin-bottom: 16px; border-bottom-width: 1px;
}
.enveloppe-budget:hover .jauge.repliable,
.enveloppe-budget:focus-within .jauge.repliable { max-height: 4px; opacity: 1; margin: 9px 0 3px; }
.enveloppe-budget:hover .arbitrage.repliable,
.enveloppe-budget:focus-within .arbitrage.repliable { max-height: 4rem; opacity: 1; }
.enveloppe-budget:hover .bloc-budget.repliable,
.enveloppe-budget:focus-within .bloc-budget.repliable {
  max-height: 18rem; opacity: 1; margin-top: 20px; padding-top: 16px; border-top-width: 1px;
}
@media (prefers-reduced-motion: reduce) {
  .enveloppe-budget .repliable { transition: none; }
}

/* Le choix des lignes de l'encart, dans les reglages. Deux colonnes : la
   liste compte quatorze lignes, et une seule colonne obligerait a faire
   defiler pour voir ce qu'on decoche. */
.titre-reglage {
  margin: 16px 0 6px; font-size: 12px; font-weight: 600; color: var(--encre-2);
}
.cases-budget {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1px 18px;
}
.cases-budget .case { font-size: 12.5px; }
.cases-budget input:disabled + span { color: var(--encre-3); }

/* Un bouton de reglage : il ouvre, il n'engage rien. */
.bouton-doux {
  background: var(--surface); border: 1px solid var(--filet); border-radius: var(--rayon-petit);
  color: var(--encre-2); cursor: pointer; padding: 5px 11px; font: inherit; font-size: 12.5px;
}
.bouton-doux:hover { border-color: var(--accent); color: var(--accent); }
.enveloppe-budget .ligne.total { margin-top: 2px; }

/* « Budget restant sans rendu » passe sur deux lignes dans un rail de 232 px.
   La coupure se fait alors où la phrase respire, pas où la place manque. */
.enveloppe-budget .ligne span { text-wrap: balance; }

/* ------------------------------------------------------ réservations
   Ce qu'on tient pendant des jours : le camion, la nacelle, le garde-meuble.
   Un planning plutôt qu'une liste, parce que le seul défaut qui coûte cher
   ici, deux réservations du même camion aux mêmes dates, ne se voit pas sur
   une liste où chaque ligne est juste. */
.vue-reservations { padding: 4px 18px 40px; }
.conflit-planning {
  margin: 10px 0 0; padding: 9px 12px; font-size: 12.5px; line-height: 1.45;
  background: var(--refus-fond); border-radius: var(--rayon-petit); color: var(--refus-encre);
}
.conflit-planning b { color: var(--refus); }

/* LE RENDEZ-VOUS, RAPPELÉ DANS LA CASE OÙ IL A LIEU.
   Un objectif qui ne se lit que dans la fiche ne sert à rien : c'est devant la
   case, le jour venu, qu'on veut savoir que douze choses doivent s'y trouver
   et que trois manquent. Il se pose donc en tête de la case, teinté de sa
   couleur, avant tout ce que la journée raconte. */
.rendez-vous {
  display: block; width: 100%; text-align: left; font: inherit; border: 0; cursor: pointer;
  margin: 0 0 8px; padding: 5px 8px 6px; border-radius: var(--rayon-petit);
  font-size: 11px; line-height: 1.45;
  background: hsl(var(--h-objectif, 0) 46% 95%);
  box-shadow: inset 0 0 0 1px hsl(var(--h-objectif, 0) 34% 82%);
  color: hsl(var(--h-objectif, 0) 44% 26%);
}
.rendez-vous b { display: block; font-size: 10px; letter-spacing: .07em;
  text-transform: uppercase; }
.rendez-vous .combien-rv { font-variant-numeric: tabular-nums; font-weight: 600; }
/* Ce qui manque se nomme, et se voit. « Il en manque trois » ne se corrige
   pas ; « le praticable et deux caisses ne sont pas là » se corrige. */
.rendez-vous .manque { display: block; margin-top: 2px; color: var(--refus-encre); }
/* Tenu, il se tait : la couleur suffit, et un tableau qui félicite à chaque
   case cesse d'être lu là où il alerte. */
.rendez-vous.tenu { box-shadow: inset 0 0 0 1px hsl(var(--h-objectif, 0) 30% 86%); }
/* Il s'ouvre : on le corrige ou on le supprime là où on le lit, plutôt qu'en
   remarquant tous ses objets dans le dessin. */
.rendez-vous:hover, .rendez-vous:focus-visible {
  box-shadow: inset 0 0 0 1.5px hsl(var(--h-objectif, 0) 40% 62%);
}

/* LA ROAD MAP RACONTÉE : la même donnée, lue dans le temps.
   Le tableau répond à « où est chaque chose » d'un coup d'œil. Il ne répond
   pas à « raconte-moi la journée de ce camion », ni à « qu'est-ce qui se passe
   à l'atelier du premier au dernier jour ». C'est une lecture : rien ne s'y
   écrit, et sa mise en page est celle d'un document, pas d'un tableau de
   bord. */
/* Quelle version est devant vous. En bas du menu, en petit : ce n'est pas une
   chose qu'on lit tous les jours, c'est une chose qu'on doit pouvoir trouver
   le jour où l'on décrit un défaut au téléphone. */
.version-outil {
  margin: 4px 8px 2px; font-size: 10.5px; color: var(--encre-3);
  border-top: 1px solid var(--filet-doux); padding-top: 6px;
}
/* Quand une version plus recente attend sur le disque. Le meme endroit, un peu
   plus lisible : ce n'est pas une alerte, c'est un numero qui a change. */
.version-en-retard { color: var(--encre-2); }

/* CE QUE LA ROUTE COÛTE, sous la tournée du véhicule. Trois chiffres et jamais
   un seul : les kilomètres, les litres, les euros. Un coût calculé sur la
   moitié des étapes trompe plus qu'il n'informe, et la couverture se dit juste
   en dessous plutôt que dans une infobulle que personne n'ouvre. */
.carburant-moyen {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--filet-doux);
}
.tete-carburant {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 13px;
}
.tete-carburant .rien { font-size: 11.5px; }
.cout-carburant { color: var(--encre); }
.carburant-moyen .rien { margin: 4px 0 0; }

/* ------------------------------------------------------- la road map
   ON LIT UNE PAGE, PAS UN TABLEAU DE BORD. Un titre, le sujet, et la suite
   des faits : rien d'autre ne doit attirer l'oeil. Les filets sont des
   cheveux, les seules couleurs disent quelque chose, et l'espace fait le
   travail que feraient ailleurs des cadres. */
.comparaison.road-map-racontee .dedans { max-width: 760px; padding: 24px 26px 18px; }
/* DEUX RANGS, ET TOUJOURS LES MEMES. L'identite d'abord -- le titre et ce que
   la page contient -- puis les commandes. Sur un seul rang, le retour à la
   ligne décidait tout seul, selon la longueur du nom du sujet : la page
   changeait de forme d'un choix à l'autre. */
.tete-rmr { display: grid; gap: 12px; justify-items: start; padding-bottom: 14px; }
.tete-rmr h2 { margin: 0; font-size: 19px; letter-spacing: -.01em; }
/* Le sujet EST le titre de la page : le mettre au meme niveau que le mot
   « Road map » ferait deux titres pour une seule page. */
.sous-rmr { margin: 2px 0 0; font-size: 12.5px; color: var(--encre-3); }
.qui-rmr { min-width: 0; }
/* Le choix et l'impression restent ensemble : separes par le retour a la
   ligne, « L'imprimer » se retrouvait seul sur une ligne a lui, sous le titre,
   ou il avait l'air d'etre le sujet de la page. */
.outils-rmr { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; max-width: 100%; }
/* Le nom d'un produit fait deux fois la longueur d'un nom de camion : sa liste
   a droit à plus de place, les deux autres n'en demandent pas. */
.large-rmr select { max-width: 320px; }
/* Le menu deroulant du systeme est un objet gris a bord dur, dessine par
   l'ordinateur et non par nous : dans une page qui n'a que du texte, il attire
   tout l'oeil. On lui rend une bordure fine, un chevron et une respiration. */
.choix-rmr { position: relative; display: inline-flex; max-width: 100%; }
.choix-rmr::after {
  content: ''; position: absolute; right: 13px; top: 50%; width: 6px; height: 6px;
  border-right: 1.5px solid var(--encre-3); border-bottom: 1.5px solid var(--encre-3);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
}
.tete-rmr select {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--filet); background: var(--surface);
  border-radius: var(--rayon-petit); padding: 7px 32px 7px 13px;
  font: inherit; font-size: 13px; color: var(--encre); cursor: pointer;
  max-width: 210px; text-overflow: ellipsis;
}
.tete-rmr select:hover { border-color: var(--encre-3); }
.tete-rmr select:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-doux);
}
/* Elle se remet a quelqu'un, mais ce n'est pas ce qu'on vient faire ici : le
   bouton se tient a cote du choix, sans le concurrencer. */
.feuille-rmr {
  border: 0; background: none; padding: 7px 2px; font: inherit; font-size: 12.5px;
  color: var(--encre-3); cursor: pointer;
}
.feuille-rmr:hover { color: var(--accent); }
@media (max-width: 620px) {
  .outils-rmr { width: 100%; }
  .tete-rmr select { max-width: 100%; width: 100%; }
  .choix-rmr { flex: 1 1 auto; }
}

.jours-rmr { display: grid; gap: 22px; }
.jour-rmr h4 {
  margin: 0 0 2px; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .09em; color: var(--encre-3);
}
.deja-la { margin: 0 0 2px; font-size: 11.5px; color: var(--encre-3); }
.pas-rmr { margin: 0; padding: 0; list-style: none; }
/* Trois colonnes fixes : l'heure, le lieu, ce qui se passe. Alignées, elles se
   lisent en diagonale ; libres, il faut relire chaque ligne en entier. Un
   filet d'un cheveu entre deux pas, et rien autour : c'est l'alignement qui
   tient la liste, pas des cadres. */
.pas-rmr li {
  display: grid; grid-template-columns: 46px 140px minmax(0, 1fr); gap: 0 16px;
  align-items: baseline; padding: 10px 0; border-top: 1px solid var(--filet-doux);
}
.pas-rmr.sans-lieu li { grid-template-columns: 46px minmax(0, 1fr); }
.pas-rmr .heure-rmr {
  font-variant-numeric: tabular-nums; color: var(--encre-3); font-size: 11.5px;
  text-align: right;
}
.pas-rmr .lieu-rmr { color: var(--encre-3); font-size: 12px; }
/* La chose d'abord, ce qui lui arrive ensuite et en second. Sur une seule
   ligne, on cherchait où finit le nom du produit et où commence son trajet. */
.pas-rmr .quoi-rmr { font-size: 13.5px; color: var(--encre); line-height: 1.35; }
.detail-rmr {
  display: block; margin-top: 2px; font-size: 11.5px; color: var(--encre-3);
  line-height: 1.45;
}
/* LA JOURNÉE D'UN CAMION : ce qu'on dépose, ce qu'on charge, puis ce qu'il
   porte en repartant. Les deux gestes d'abord, parce que ce sont eux qu'on
   fait ; le compte ensuite, parce que c'est lui qu'on vérifie. */
.geste-rmr { display: block; }
.geste-rmr b { font-weight: 600; }
.souci-rmr { margin: 6px 0 0; font-size: 11.5px; color: var(--refus); }
/* Ce qu'il peut porter, dit une fois en tête : le répéter à chaque arrêt
   ferait vingt fois le même chiffre pour une question qu'on se pose une. */
.cap-rmr { margin: 0 0 14px; }
/* Le rendez-vous n'est pas un pas de plus : c'est ce que la journée doit
   produire, et il se lit avant ce qui l'entoure. */
.pas-rmr li.rendez-vous {
  background: var(--enclos); border-radius: var(--rayon-petit);
  padding: 10px 12px; border-top: 0; margin: 2px 0;
}
.pas-rmr li.rendez-vous .quoi-rmr { font-weight: 600; }
.pas-rmr li.devient .detail-rmr { color: var(--distingue-encre); }
/* CE QUI EST IMPOSSIBLE SE LIT À SON INSTANT, entre le départ qu'il contredit
   et l'arrivée qui n'aura pas lieu. Lu à part, en haut de page, il faut
   retrouver de quoi il parle parmi quarante lignes. */
.pas-rmr li.souci .quoi-rmr, .pas-rmr li.souci .detail-rmr { color: var(--refus); }
.aller-rmr { font-size: 11.5px; white-space: nowrap; }
/* Les pastilles de groupe suivent le texte de la ligne : posées en bloc, elles
   pousseraient la phrase sur une ligne de plus pour deux mots. */
.grps-rm { display: inline; }
@media (max-width: 620px) {
  .pas-rmr li, .pas-rmr.sans-lieu li { grid-template-columns: 46px minmax(0, 1fr); }
  .pas-rmr .lieu-rmr { grid-column: 2; font-size: 11.5px; }
  .pas-rmr .quoi-rmr { grid-column: 2; }
}

/* LA NOTE D'UN PASSAGE, derrière le nom de l'objet.
   Elle vivait sur le mouvement et ne s'affichait que dans l'infobulle d'un
   motif : une note écrite sans motif n'existait nulle part à l'écran. Le signe
   se lit sans se crier, et il s'ouvre d'un clic. */
.note-passage {
  border: 0; background: none; padding: 0 2px; margin-left: 2px; cursor: pointer;
  font: inherit; font-size: 0; line-height: 0; vertical-align: baseline;
  color: var(--attente);
}
.note-passage::before {
  content: '✎'; font-size: 11px; line-height: 1;
}
/* Une cible de vingt-quatre pixels sous un signe de onze : sur un écran
   tactile, on vise le nom et l'on ouvre la note, ou l'inverse. */
.note-passage::after {
  content: ''; position: absolute; inset: -7px -6px;
}
.note-passage { position: relative; }
.note-passage:hover::before, .note-passage:focus-visible::before { color: var(--attente-encre); }

/* CE QUI CHANGE ICI : il quitte un groupe, il en rejoint un.
   L'assemblage se lit déjà dans la case, « 34 tasseaux → un praticable » :
   c'est un changement d'état, et on le montre. En rejoindre un ou en sortir en
   est un autre, aussi lourd de conséquences, et rien ne le disait. On lisait
   une couleur qui change d'une ligne à l'autre sans savoir ni quand ni
   pourquoi. La teinte est celle du groupe dont on parle, pas celle de l'objet :
   c'est le groupe qui est le sujet de la phrase. */
.change-groupe {
  display: inline-flex; align-items: baseline; gap: 4px;
  margin-left: 6px; font-size: 10px; font-weight: 600; line-height: 1.4;
  white-space: nowrap; vertical-align: baseline; color: var(--encre);
  /* L'OBJET PORTE UN RETRAIT NÉGATIF, la mention ne doit pas en hériter.
     La ligne d'un objet rentre sa première ligne de treize pixels pour que
     les suivantes s'alignent sous le nom. Ce retrait descendait jusque dans
     la pastille, dont le texte partait donc treize pixels à gauche de son
     fond : on lisait « S » en clair, dehors, puis « cène 1 » sur l'encre. */
  text-indent: 0;
}
/* LE SIGNE DEHORS, LE NOM DANS SA PASTILLE.
   Collé à l'ovale, le signe se lisait comme une lettre du nom : « −Scène 1 ».
   Il dit ce qui se passe, le nom dit de quoi on parle, et les deux ne se
   prononcent pas ensemble. */
/* NI L'UN NI L'AUTRE NE SE LAISSE ECRASER.
   Dans une colonne étroite, la pastille rétrécissait sous son texte et le
   « S » de « Scène » passait sous son bord : on lisait « cène 1 ». Le signe,
   lui, tombait à zéro de large et son glyphe débordait à côté. Les deux
   gardent donc leur taille, et la mention passe à la ligne plutôt que de se
   couper. */
.change-groupe .signe {
  flex: 0 0 auto; min-width: 7px; text-align: center;
  font-weight: 700; font-size: 12px;
}
/* SUR L'ENCRE, PAS SUR LA TEINTE DU GROUPE.
   La pastille reprenait la couleur du groupe, c'est-à-dire celle que l'objet
   porte déjà : les deux se confondaient, et la mention se lisait comme une
   partie de l'objet plutôt que comme ce qui lui arrive. Sur l'encre, elle se
   détache de tout ce qui l'entoure et reste lisible quelle que soit la teinte
   d'à côté. */
.change-groupe .quel-groupe {
  flex: 0 0 auto;
  padding: 0 6px 1px; border-radius: var(--rond);
  background: var(--encre); color: var(--papier);
  letter-spacing: .01em;
}

/* CE QUI PRESSE, DIT ICI PLUTÔT QUE DANS UNE INFOBULLE.
   Le rang portait « 1 ! » en rouge et l'écran ne disait rien de plus, dans
   une phrase de bilan en gris : on voyait qu'il fallait agir sans savoir ni
   sur quoi ni comment. Une ligne par moyen, son jour, et le geste au bout. */
.a-reserver-vite {
  margin: 10px 0 0; padding: 10px 12px; font-size: 12.5px; line-height: 1.45;
  background: var(--attente-fond); border-radius: var(--rayon-petit);
  color: var(--attente-encre);
}
.a-reserver-vite > b { color: var(--attente-encre); }
.a-reserver-vite ul { margin: 7px 0 0; padding: 0; list-style: none; display: grid; gap: 5px; }
.a-reserver-vite li {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
.a-reserver-vite .quoi { font-weight: 500; }
.a-reserver-vite .rien { color: inherit; opacity: 0.72; }
/* Le jour est passé : ce n'est plus une réservation à faire, c'est un trou
   dans le montage, et la couleur le dit avant la phrase. */
.a-reserver-vite li.depasse .quoi { color: var(--refus); }
.a-reserver-vite button {
  margin-left: auto; color: var(--attente-encre); text-decoration-color: currentColor;
}
.a-reserver-vite > .rien { margin: 8px 0 0; color: inherit; opacity: 0.72; }

/* La part du planning deja ecoulee. Le script la pose sur le conteneur ;
   la valeur par defaut evite qu'un calc() reste invalide et fasse disparaitre
   le trait sans un mot le jour ou le script ne la donne pas. */
.planning { margin: 16px 0 22px; --part-aujourdhui: 0; --colonne-nom: 180px; }
.planning .echelle { padding-left: var(--colonne-nom); }
.planning .graduations {
  position: relative; height: 16px; border-bottom: 1px solid var(--filet);
}
/* La graduation porte son nom : la feuille la designait par « span », ce qui
   est vrai tant qu'il n'y a qu'une sorte d'element dedans, et faux le jour ou
   l'on en ajoute une seconde. */
.planning .graduations .graduation {
  position: absolute; top: 0; transform: translateX(-50%);
  font-size: 10.5px; color: var(--encre-3); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Aux deux bords, la graduation se cale sur son trait au lieu de se centrer
   dessus : centree, la moitie du texte sortait du cadre et s'y coupait. */
.planning .graduations .graduation.au-bord-gauche { transform: none; }
.planning .graduations .graduation.au-bord-droit { transform: translateX(-100%); }
.planning .graduations em { font-style: normal; margin-left: 3px; color: var(--encre-3); opacity: .75; }
.planning .rangees { position: relative; }
/* On ne livre pas un dimanche. Sans ces bandes, « du vendredi au lundi »
   paraît durer deux jours de travail. */
/* Les bandes sont posees AVANT les rangees dans le flux, mais elles sont
   positionnees et les rangees ne l'etaient pas : elles se peignaient donc
   par-dessus les noms et les barres. C'est la rangee qui remonte, pas la
   bande qui descend, sinon le trait d'aujourd'hui passerait dessous. */
.planning .fins-de-semaine { position: absolute; inset: 0 0 17px var(--colonne-nom); pointer-events: none; }
.planning .fins-de-semaine i { position: absolute; top: 0; bottom: 0; background: var(--papier); }
/* Le trait d'aujourd'hui. Sans lui on lit des barres sans savoir laquelle a
   déjà commencé, ce qui est précisément la question qu'on se pose. */
.planning .trait-aujourdhui {
  position: absolute; top: 0; bottom: 0; width: 0; pointer-events: none;
  left: calc(var(--colonne-nom) + (100% - var(--colonne-nom)) * var(--part-aujourdhui));
  z-index: 2;
  border-left: 1px dashed var(--encre-3);
}
.rangee-planning {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: var(--colonne-nom) 1fr; align-items: center;
  gap: 0; min-height: 30px; border-bottom: 1px solid var(--filet-doux); cursor: pointer;
}
.rangee-planning:hover { background: var(--survol); }
/* LE PLANNING ET LE TABLEAU PARLENT DES MÊMES CHOSES.
   Une commande occupait une rangée en haut, ses articles des cases en bas, et
   rien ne disait que c'étaient les mêmes. La rangée s'allume quand ce qu'on a
   marqué dans le dessin vient d'elle : le même vert que la sélection, parce
   que c'est la même sélection. */
.rangee-planning.montree { background: var(--accent-doux); }
.rangee-planning.montree .nom-au-planning b { color: var(--accent-encre); }
.rangee-planning .nom-au-planning { padding: 4px 12px 4px 2px; min-width: 0; }
.rangee-planning .nom-au-planning b {
  display: block; font-size: 12.5px; font-weight: 600; color: var(--encre);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rangee-planning .nom-au-planning span { font-size: 11px; color: var(--encre-3); }
.rangee-planning .piste { position: relative; height: 22px; }
.rangee-planning .barre-planning {
  position: absolute; top: 2px; bottom: 2px; border-radius: var(--rayon-petit);
  display: flex; align-items: center; font-size: 10.5px; white-space: nowrap;
  background: var(--surface-2); border: 1px solid var(--filet); color: var(--encre-2);
}
.rangee-planning .barre-planning.libelle-dedans { padding: 0 7px; overflow: hidden; }
/* Une barre de trois jours sur un trimestre fait quelques pixels : sa periode
   s'ecrit a cote, sinon elle est coupee au troisieme caractere. */
.rangee-planning .barre-planning.libelle-apres > span,
.rangee-planning .barre-planning.libelle-avant > span {
  position: absolute; color: var(--encre-3); font-size: 10.5px;
}
.rangee-planning .barre-planning.libelle-apres > span { left: calc(100% + 7px); }
.rangee-planning .barre-planning.libelle-avant > span { right: calc(100% + 7px); }
.rangee-planning .barre-planning.etat-a-reserver {
  background: var(--attente-fond); border-color: var(--attente-filet); color: var(--attente-encre);
}
/* L'encre pleine ne dit qu'une chose dans cette maison : c'est en marche. */
.rangee-planning .barre-planning.etat-en-cours { background: var(--encre); border-color: var(--encre); color: #fff; }
.rangee-planning .barre-planning.etat-rendu {
  background: var(--ok-fond); border-color: var(--ok); color: var(--ok-encre);
}
.rangee-planning .barre-planning.etat-annule {
  background: none; border-style: dashed; color: var(--encre-3); text-decoration: line-through;
}
.rangee-planning.en-conflit .barre-planning { border-color: var(--refus); }
.rangee-planning.en-conflit .nom-au-planning b { color: var(--refus-encre); }

.cartes-moyens { display: grid; gap: 12px; }
.carte-moyen {
  border: 1px solid var(--filet); border-radius: var(--rayon); background: var(--surface);
  padding: 12px 14px;
}
.carte-moyen > header {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
}
.carte-moyen .quoi-moyen { flex: 1 1 240px; min-width: 0; }
.carte-moyen h3 { font-size: 14px; }
.carte-moyen .sous { font-size: 11.5px; color: var(--encre-3); margin-top: 2px; }
.carte-moyen .chiffres { display: flex; align-items: baseline; gap: 9px; }
.carte-moyen .chiffres b { font-size: 14px; font-variant-numeric: tabular-nums; }
.carte-moyen.etat-annule { opacity: .55; }
.note-moyen { margin-top: 9px; font-size: 12px; color: var(--encre-2); }

/* Le contrôle de chargement. Il ne dit jamais « tout rentre » : il montre ce
   que le taux de remplissage retire du volume géométrique, et le laisse
   visible derrière, sinon le chiffre utile passerait pour le volume du
   camion. */
.chargement { margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--filet-doux); }
.chargement .tete-chargement {
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  font-size: 11.5px; margin-bottom: 6px;
}
.chargement .ou-charge { color: var(--encre-2); font-weight: 600; }
.jauge-chargement {
  position: relative; height: 12px; border-radius: var(--rond);
  background: var(--surface-2); overflow: hidden;
}
.jauge-chargement .part-utile { position: absolute; inset: 0 auto 0 0; background: var(--filet-doux); }
.jauge-chargement .part-prise { position: absolute; inset: 0 auto 0 0; background: var(--encre); }
.jauge-chargement .part-prise.deborde { background: var(--refus); }
.chargement .verdict { margin-top: 7px; font-size: 12.5px; line-height: 1.5; color: var(--encre-2); }
.chargement .verdict b { color: var(--encre); font-variant-numeric: tabular-nums; }
.chargement .verdict.alerte { color: var(--refus-encre); }
.chargement .verdict.alerte b { color: var(--refus); }
.chargement .verdict [data-aller-fiche] { cursor: pointer; text-decoration: underline; }
.chargement .verdict [data-aller-fiche]:hover { color: var(--encre); }
.chargement .rien { font-size: 11.5px; margin-top: 5px; }
.chargement.sans-cotes .rien { margin: 0 0 6px; }

/* La fiche d'un moyen : deux colonnes de champs courts, parce qu'un bon de
   location tient sur un tiers de page. */
.fiche-moyen .dedans { max-width: 620px; }
.grille-champs { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.grille-champs.serree { grid-template-columns: repeat(3, 1fr); }
.grille-champs .champ-question { margin: 12px 0 0; }
.champ-question select {
  display: block; width: 100%; margin-top: 4px; padding: 8px 10px;
  font: inherit; font-size: 14px; color: var(--encre);
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.cotes-moyen { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--filet-doux); }
.cotes-moyen h4 { font-size: 12px; color: var(--encre-2); margin-bottom: 3px; }
.cotes-moyen h4 + .rien { font-size: 11.5px; }
.cotes-moyen > h4:not(:first-child) { margin-top: 16px; }
.pieces-embarquees { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 8px; }
.pieces-embarquees .case {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--encre-2);
}
/* La colonne des noms se resserre avant de disparaitre : sur un ecran
   moyen, un planning sans noms ne vaut plus rien, mais un nom sur 180 px ne
   laisse plus de place aux barres. */
@media (max-width: 1100px) { .planning { --colonne-nom: 128px; } }
@media (max-width: 720px) {
  .grille-champs, .grille-champs.serree { grid-template-columns: 1fr; }
  /* En dessous, le nom passe au-dessus de sa barre : c'est la seule
     disposition qui garde les deux lisibles. */
  .planning { --colonne-nom: 0px; }
  .rangee-planning { grid-template-columns: 1fr; padding-bottom: 3px; }
  .rangee-planning .nom-au-planning { padding: 4px 2px 0; }
  .rangee-planning .nom-au-planning b { display: inline; }
  .rangee-planning .nom-au-planning span::before { content: ' · '; }
}

/* Une commande ne s'affiche pas comme une réservation, parce qu'elle ne dit
   pas la même chose. Un camion, on le tient : la barre est ce qu'on possède.
   Une commande, on l'attend : la barre est un délai, et le seul jour qui
   compte est celui du bout. Dessinées pareil, on lirait « le canapé est là du
   3 au 24 » quand il n'arrive que le 24. */
.rangee-planning.genre-commande .barre-planning {
  background: none; border-style: dashed; color: var(--encre-3);
}
/* Le bout du trait est une DATE, et une date se marque ici d'un trait
   vertical : c'est deja ce que font le jour même et la date clé, juste
   au-dessus. Il portait un pavé arrondi de quatre pixels, vert quand la
   commande était reçue, ambre quand elle restait à passer. Une pastille de
   couleur au bout d'une ligne ne dit rien que la ligne à côté ne dise déjà en
   toutes lettres, et un même objet, une date, se dessinait de deux façons
   dans le même cadre. */
.rangee-planning.genre-commande .barre-planning::after {
  content: ''; position: absolute; right: -1px; top: -3px; bottom: -3px; width: 0;
  border-right: 1px solid var(--encre-2);
}

/* La date clé du chantier, en travers de tout : c'est elle qui décide si une
   commande arrive à temps et si le camion est réservé au bon jour. */
.planning { --part-cle: 0; }
.planning .trait-cle {
  position: absolute; top: 0; bottom: 0; width: 0; pointer-events: none; z-index: 2;
  left: calc(var(--colonne-nom) + (100% - var(--colonne-nom)) * var(--part-cle));
  border-left: 1px solid var(--distingue);
}
/* Le nom de la date cle se posait au-dessus du trait, c'est-a-dire dans la
   bande des graduations, et il passait par-dessus « 5 oct. ». Il descend sous
   les rangees, dans une bande qui n'appartient qu'a lui. */
.planning .rangees { padding-bottom: 17px; }
.planning .trait-cle span {
  position: absolute; bottom: 1px; left: 3px; white-space: nowrap;
  font-size: 10px; font-weight: 600; color: var(--distingue-encre);
}
.planning .trait-cle.a-gauche span { left: auto; right: 3px; }
@media (max-width: 720px) {
  .planning .trait-cle { left: calc(100% * var(--part-cle)); }
}
/* La legende se pose SOUS ce qu'elle explique.
   Elle portait une marge haute negative, posee du temps ou elle suivait les
   barres du planning et devait s'y coller. Reprise sous le dessin du flux, la
   meme marge la faisait remonter par-dessus la derniere rangee : le texte
   mordait le tableau, et l'on relisait deux phrases superposees. Une marge
   negative sert un seul voisin et trahit tous les autres. */
.legende-planning { margin: 10px 0 18px; max-width: 72ch; }
.planning + .legende-planning { margin-top: 4px; }

/* Ce que l'agence avance. Une agence qui gagne de l'argent sur le papier peut
   mourir de cet écart : elle a payé ses fournisseurs et le client n'a pas
   encore versé. Le chiffre se lit donc en pleine phrase, pas dans une case. */
.verdict-tresorerie {
  margin-top: 12px; font-size: 12.5px; line-height: 1.55; color: var(--encre-2);
}
.verdict-tresorerie b { color: var(--encre); font-variant-numeric: tabular-nums; }
.verdict-tresorerie.avance { color: var(--attente-encre); }
.verdict-tresorerie.avance b { color: var(--attente); }

/* ------------------------------------------------------ les collaborateurs
   Ouvrir un accès à quelqu'un, et le lui retirer. */
.collaborateurs { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--filet-doux); }
.collaborateurs .rien { margin: 4px 0 10px; max-width: 62ch; }
.collaborateurs tr.retire { opacity: .5; }
.collaborateurs tr.retire s { text-decoration-thickness: 1px; }
.collaborateurs td.actions { text-align: right; background: none; border-bottom: 0; padding: 7px 8px; }
.collaborateurs td.actions button {
  padding: 3px 9px; font-size: 11.5px; border: 1px solid var(--filet);
  border-radius: var(--rayon-petit); background: var(--surface); color: var(--encre-2); cursor: pointer;
}
.collaborateurs td.actions button:hover { border-color: var(--refus); color: var(--refus); }
.ouvrir-acces { margin-top: 14px; display: grid; gap: 10px; }
.ouvrir-acces .pieces-embarquees { margin-top: 5px; }
.ouvrir-acces > button { justify-self: start; }

/* La clé ne s'affiche qu'une fois. Elle prend donc toute la place qu'il faut
   pour qu'on la voie, et le texte à donner est déjà écrit : le donner en
   morceaux, c'est se faire redemander l'adresse une semaine plus tard alors
   que la clé, elle, ne se redonne pas. */
.cle-neuve {
  margin-top: 14px; padding: 12px 14px; border-radius: var(--rayon);
  background: var(--attente-fond); color: var(--attente-encre);
}
.cle-neuve b { display: block; margin-bottom: 4px; }
.cle-neuve .rien { color: var(--attente-encre); opacity: .85; margin: 0 0 8px; }
.cle-neuve textarea {
  width: 100%; font: inherit; font-size: 12px; line-height: 1.5;
  padding: 9px 10px; border: 1px solid var(--attente-filet); border-radius: var(--rayon-petit);
  background: var(--surface); color: var(--encre); resize: vertical;
}
.cle-neuve button { margin-top: 8px; }

/* ------------------------------------------------------------- le flux
   Où est chaque chose, jour par jour. Un dessin et non un tableau, parce que
   la question qu'on se pose devant n'est pas « combien » mais « où ». Les
   lieux sont les colonnes, les jours les lignes : on lit une colonne pour
   suivre un endroit dans le temps, une ligne pour voir une journée, et le
   trait qui traverse la ligne est la route du camion ce jour-là. */
.titre-flux { font-size: 13px; margin: 26px 0 10px; }
/* La grille des colonnes est posee par le script sur la carte, part par part :
   une colonne qui porte quelque chose vaut une part, une colonne vide moins
   que la moitie. La valeur par defaut evite qu'un grid-template-columns reste
   invalide et fasse s'effondrer toute la grille sans un mot le jour ou le
   script ne la donne pas. */
.carte-flux {
  --grille: 1fr 1fr 1fr;
  border: 1px solid var(--filet); border-radius: var(--rayon);
  background: var(--surface);
}
/* LA BANDE DES LIEUX SE FIGE DANS LA PAGE, PAS DANS LA CARTE.
   Elle defilait avec le tableau : passe le troisieme jour, on lisait des
   colonnes sans savoir laquelle est le depot et laquelle est le chantier.
   La difficulte est que la carte defile dans DEUX sens. Un element ne se fige
   que dans le cadre qui defile : pose dans une carte qui defile de gauche a
   droite, il se figeait dans cette carte, laquelle s'en allait vers le haut
   avec lui. Deux rails, donc : la bande se fige dans la page, les jours
   defilent sous elle, et le script recopie le defilement horizontal de l'un
   sur l'autre. */
.rail-entete {
  position: sticky; top: var(--haut-regrouper, 0px); z-index: 4;
  /* La bande figee porte le meme fond que l'en-tete : avec le blanc de la
     carte, le contenu passait au travers au moment ou elle se decolle, et
     l'on voyait deux textes l'un sur l'autre. */
  overflow-x: hidden; background: var(--enclos);
}
/* Une ombre plutot qu'un filet, et seulement quand la bande a quitte sa
   place : posee en permanence, elle dessinerait un trait de plus sur un
   tableau qui en a deja beaucoup. La classe se pose par le script, qui sait
   seul si la carte a commence a defiler. */
.rail-entete.detachee { box-shadow: 0 1px 0 var(--filet), 0 6px 10px -8px rgba(0, 0, 0, .22); }
.rail-jours { overflow-x: auto; }
/* UNE BANDE PAR SUITE DE JOURNÉES QUI MONTRENT LES MÊMES LIEUX.
   Les colonnes s'accumulent : passé le troisième jour, la moitié d'entre elles
   ne porte plus rien, et l'on lit le tableau de travers pour retrouver les deux
   qui comptent. Chaque bande a donc ses colonnes, sa largeur et son en-tête, et
   celle-ci se fige comme avant, jusqu'à ce que la bande suivante la remplace.
   Le coin arrondi appartient à la dernière : posé sur toutes, il dessinerait un
   trait de séparation en creux au milieu du tableau. */
.carte-flux > .bloc-flux:last-of-type .rail-jours {
  border-radius: 0 0 var(--rayon) var(--rayon);
}
/* Le filet dit qu'une bande commence, et l'en-tête qui suit ne se lit plus
   comme la suite de la journée précédente. */
.bloc-flux + .bloc-flux .rail-entete { border-top: 1px solid var(--filet); }
/* La largeur minimale de la carte se calcule sur SES colonnes : cent vingt
   pixels pour une colonne qui porte, cinquante-six pour une colonne vide, et
   la colonne des jours. Un nombre fixe convenait a trois lieux et etranglait
   huit colonnes dans la meme largeur. Les deux grilles la partagent, sans quoi
   elles ne tomberaient pas en face l'une de l'autre. */
/* ET LE RÉGLAGE « combien de lieux à la fois » élargit la carte d'autant.
   Le pourcentage se résout sur le cadre qui défile, dont la largeur est celle
   de la carte : elle ne dépend pas de son contenu, donc le calcul ne tourne
   pas en rond. Étalé de 2, la carte fait deux fois la largeur visible et l'on
   voit donc la moitié des colonnes. Sans réglage, --etale vaut 1 et rien ne
   change. Les 86 px de la colonne des jours se retirent des deux côtés :
   ils ne défilent pas, ils sont toujours là. */
.entete-flux, .jour-flux {
  display: grid; grid-template-columns: 86px minmax(0, 1fr);
  min-width: max(var(--mini, 620px), calc(86px + (100% - 86px) * var(--etale, 1)));
}
/* UNE EN-TÊTE DOIT SE LIRE COMME UNE EN-TÊTE.
   Sur fond blanc, avec les mêmes noms que partout, la bande des lieux se lisait
   comme une ligne de plus : figée en haut, elle se confondait avec ce qui
   défilait dessous, et reposée entre deux journées — chaque fois que les
   colonnes changent — on croyait lire une journée sans contenu. Un fond en
   retrait la sort du flux, et le filet du bas dit où le tableau recommence. */
.entete-flux { border-bottom: 1px solid var(--filet); background: var(--enclos); }
.entete-flux .coin-flux { border-right: 1px solid var(--filet-doux); }
.entete-flux > .lieu-flux { display: none; }
/* Les en-têtes de lieux partagent la grille des cellules : sans cela, une
   colonne de titres et une colonne de contenus finissent par se décaler d'un
   pixel à chaque niveau de zoom, et le dessin cesse de se lire. */
.entete-flux { grid-template-columns: 86px var(--grille); }
.entete-flux > .lieu-flux {
  display: block; padding: 8px 10px; font-size: 11.5px; font-weight: 600; color: var(--encre);
  border-left: 1px solid var(--filet-doux); letter-spacing: .01em;
}
/* CE QU'UNE FICHE SUIT SANS L'AVOIR DIT.
   L'éditeur ne montrait que les étapes propres à la fiche. Une fiche qui suit
   son groupe n'en a aucune : on construisait un parcours dans le dessin, on
   ouvrait la fiche, et « Son parcours » répondait « sans étape, elle va de son
   point de départ au chantier », c'est-à-dire le contraire de ce que le dessin
   venait de montrer.
   Ces lignes se lisent, elles ne s'éditent pas : les changer, c'est changer le
   groupe, et cela se fait sur le groupe. Le fond en retrait le dit sans qu'on
   ait à l'écrire. */
.parcours-suivi {
  margin-top: 8px; padding: 8px 10px 9px; border-radius: var(--rayon-petit);
  background: var(--enclos);
}
.parcours-suivi .quoi-suivi {
  display: block; margin-bottom: 6px;
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .14em;
  font-weight: 600; color: var(--encre-2);
}
.etape-suivie {
  display: flex; align-items: baseline; gap: 7px;
  font-size: 12px; color: var(--encre-2); padding: 2px 0;
}
.etape-suivie b { font-variant-numeric: tabular-nums; }
.etape-suivie .heure-suivie { color: var(--encre-3); font-variant-numeric: tabular-nums; }
.etape-suivie .ou-suivi { color: var(--encre); }
.parcours-suivi .devine { margin-top: 5px; }

/* UNE COLONNE SE PREND PAR SON EN-TETE.
   Le curseur le dit avant le geste : sans lui, personne ne devine qu'un titre
   de colonne se déplace. Le nom d'un lieu qu'on possède reste sélectionnable
   pour être renommé, d'où le « draggable=false » posé sur lui : un ancêtre
   qui se glisse empêche autrement de poser le curseur dans son texte. */
.entete-flux > .lieu-flux[data-colonne] { cursor: grab; }
.entete-flux > .lieu-flux.bouge { opacity: .4; }
/* Là où la colonne va se poser : un filet plein sur le bord qu'elle prendra.
   Un fond coloré aurait fait croire qu'on dépose DANS cette colonne, ce qui
   est l'autre geste du dessin. */
.entete-flux > .lieu-flux.recoit-colonne {
  box-shadow: inset 2px 0 0 var(--accent);
}

/* Le nom d'une colonne vide s'ecrit PLUS PETIT, et il s'ecrit en entier.
   Coupe a « N... », il ne nommait plus rien : trois colonnes anonymes au bord
   du tableau ressemblaient a un decor, et l'on ne savait plus ou l'on pouvait
   deposer. Il passe donc a la ligne autant qu'il le faut, y compris au milieu
   d'un mot, ce qui coute quelques pixels a UNE rangee d'en-tetes et rend leur
   nom a des colonnes dont c'est la seule chose qu'elles aient a dire. */
.entete-flux > .lieu-flux.colonne-maigre {
  padding: 8px 6px; font-size: 10.5px; line-height: 1.2;
  overflow-wrap: anywhere; color: var(--encre-3);
}
.jour-flux { border-bottom: 1px solid var(--filet-doux); }
.jour-flux:last-child { border-bottom: 0; }
/* LA COLONNE DES JOURS RESTE VISIBLE ELLE AUSSI.
   La bande des lieux se fige vers le haut ; sans son pendant vers la gauche,
   faire glisser la carte vers la droite laissait des cases sans jour, et l'on
   ne savait plus si l'on lisait le montage ou le demontage. Les deux se
   figent dans le meme cadre, chacune sur son axe. */
.jour-flux .etiquette-jour {
  padding: 10px; border-right: 1px solid var(--filet-doux); background: var(--papier);
  position: sticky; left: 0; z-index: 2;
}
.entete-flux .coin-flux { position: sticky; left: 0; z-index: 2; background: var(--surface); }
.jour-flux .etiquette-jour b { display: block; font-size: 12.5px; }
/* Le numéro du jour et son chevron se touchaient à quatre pixels : deux cibles
   de vingt-quatre se seraient recouvertes, et l'une des deux serait devenue
   inatteignable. */
.jour-flux .etiquette-jour b { display: flex; align-items: center; gap: 12px; }
.jour-flux .etiquette-jour span { font-size: 11px; color: var(--encre-3); }
/* La route se dessine dans une bande a elle, en haut des cellules : posee sur
   le filet de la rangee, elle s'y confondait et l'on ne voyait plus si le
   camion passait ce jour-la. Sa hauteur depend du nombre de trajets, puisque
   la route est un escalier : le script la calcule et la pose ici. */
.jour-flux .cellules {
  position: relative; display: grid; grid-template-columns: var(--grille);
  padding-top: 14px;
}
.jour-flux .cellule {
  padding: 9px 10px; border-left: 1px solid var(--filet-doux);
  font-size: 11.5px; min-height: 46px;
}
/* La bande des routes est un étage à part, pas le haut de la première case.
   Un filet la sépare des produits sur toute la largeur : sans lui, les marches
   flottaient au-dessus des articles et l'on cherchait à quoi elles se
   rattachaient. Elle ne doit pas élargir la rangée : elle traverse toute la
   grille, et un dessin plus large y pousserait les colonnes du jour au-delà de
   celles de l'en-tête, qui ne la contient pas. */
/* La bande des routes respire par le bas : ce qui monte et ce qui descend du
   dernier véhicule touchait le filet, et la première case du tableau
   paraissait appartenir à sa frise. */
.routes-du-jour {
  grid-column: 1 / -1; display: grid; gap: 0; min-width: 0;
  padding: 6px 0 20px; border-bottom: 1px solid var(--filet-doux);
}

/* LA JOURNÉE D'UN VÉHICULE, LUE DE GAUCHE À DROITE.
   Six dessins ont échoué avant celui-ci, et tous posaient la route sur l'axe
   des LIEUX : il fallait tracer pour comprendre. Une suite se lit de gauche à
   droite, c'est le seul ordre qu'on n'apprend pas. L'axe des lieux, que les
   colonnes disent déjà très bien, est donc abandonné ici : la journée devient
   une frise, l'heure, l'arrêt, ce qui monte et ce qui descend.
   Le trait qui relie les arrêts est épais et pastel : il porte les pastilles
   au lieu de traverser la page, et il se pose sous le texte plutôt que de
   passer devant. */
/* LE NOM DU VEHICULE EST UNE CLE, ET IL TOUCHE SA FRISE.
   Il flottait a gauche, a cinq pixels de sa propre frise et a quatre de la
   suivante : deux vehicules le meme jour donnaient « Camion B », sa frise,
   « Camion A », sa frise, avec des ecarts si voisins qu'on rattachait chaque
   nom a la mauvaise ligne. Un titre doit toucher ce qu'il nomme et respirer
   loin de ce qu'il ne nomme pas.
   La pastille de couleur en fait une cle de lecture : c'est elle qui relie le
   nom au trait qui suit, et c'est la meme que dans la legende sous le
   tableau. */
/* LE NOM SE POSE AU-DESSUS DU PREMIER ARRÊT, PAS DANS LE COIN.
   Collé au bord gauche, il tombait dans un angle pendant que la frise
   commençait à un sixième de la largeur : entre les deux, une bande vide que
   rien n'occupait, et le nom paraissait appartenir à la ligne du dessus
   plutôt qu'au trait qu'il annonce. Les arrêts se partagent la largeur en
   parts égales : le premier point est donc au milieu de la première part, et
   c'est là que la pastille du nom vient se placer, à l'aplomb du départ.
   Un rail à gauche serait plus simple, mais l'étiquette du jour est collée au
   bord et le recouvrirait dès qu'on fait défiler le tableau. */
/* LE NOM SE MET DEVANT LA ROUTE, comme le jour se met devant sa ligne.
   Posé au-dessus du premier arrêt, il désignait un point plutôt qu'un trajet,
   et deux véhicules le même jour donnaient deux titres flottants qu'il
   fallait rattacher au bon trait.
   Il se fige à gauche, juste après l'étiquette du jour : la bande des routes
   défile horizontalement avec le tableau, et sans cela le nom passait sous
   l'étiquette dès qu'on faisait défiler. */
.une-route {
  display: grid; grid-template-columns: minmax(0, 134px) minmax(0, 1fr);
  column-gap: 0; align-items: start;
}
.une-route .qui {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  position: sticky; left: 86px; z-index: 3; align-self: stretch;
  /* Le fond couvre toute la hauteur de sa ligne : sur la seule hauteur du
     texte, les noms de lieux défilaient en dessous de lui et se lisaient
     par-dessous. */
  /* LE NOM SE RANGE CONTRE SA ROUTE, PAS CONTRE LE BORD.
     Sa colonne fait 134 px pour que les frises de deux véhicules tombent en
     face l'une de l'autre : un nom court y laissait donc soixante-dix pixels de
     vide avant son premier arrêt, et « Camion A » flottait loin de la journée
     qu'il annonce. Le nom se cale à droite de sa colonne : la colonne garde sa
     largeur, les frises restent alignées, et le nom touche presque son point de
     départ. */
  background: var(--surface); padding: 18px 10px 0 16px; margin: 0;
  overflow: hidden; text-overflow: ellipsis;
  align-items: flex-start; justify-content: flex-end;
  font-size: 11px; font-weight: 600;
  color: hsl(var(--h-moyen, 0) 42% 34%);
}
/* La pastille se pose au milieu de la LIGNE du nom, pas en haut de la boîte :
   celle-ci est étirée sur toute la hauteur de la route pour porter le fond, et
   caler la pastille sur son bord haut la mettait au-dessus du mot. */
.une-route .qui::before {
  content: ''; flex: none; width: 7px; height: 7px; border-radius: 50%;
  margin-top: 4px;
  background: hsl(var(--h-moyen, 0) 46% 42%);
}
.une-route + .une-route { margin-top: 16px; }
.une-route .etapes {
  position: relative;
  display: flex; align-items: flex-start; margin: 0; list-style: none;
  /* Avec DEUX arrêts il n'y a pas d'arrêt du milieu pour tenir l'espace : les
     deux se tasseraient à gauche et le trait irait tout seul jusqu'au bord. */
  justify-content: space-between;
  /* DE L'AIR AUX DEUX BOUTS. Buté contre le filet de la carte, le dernier
     arrêt donnait l'impression d'une journée coupée en plein trajet ; collé au
     nom, le premier faisait corps avec lui. Les deux mesures vivent ici et le
     trait les relit : sans cela, changer l'une remettrait le moignon que le
     trait vient de perdre. */
  --air-frise: 12px;
  /* Plus d'air au bout qu'au depart : au depart, le nom du vehicule tient la
     place ; a l'arrivee, il n'y a que le filet de la carte, et le dernier
     arret s'y appuyait. Le nom du lieu deborde de sa pastille des deux cotes :
     la mesure doit donc porter la moitie de ce nom, pas seulement le rond. */
  --air-frise-fin: 72px;
  padding: 0 var(--air-frise-fin) 0 var(--air-frise);
}
/* UN SEUL TRAIT, POSÉ DERRIÈRE LES PASTILLES.
   Dessiné par morceaux d'une pastille à la précédente, il obligeait chaque
   halte à occuper la même largeur, et posait donc le premier point à une
   demi-tranche du bord : entre le nom du véhicule et son premier arrêt
   s'ouvrait une bande vide. Un trait unique laisse les deux bouts se caler sur
   les bords, et la route commence là où son nom finit. */
/* LE TRAIT PORTE LE NOM DU VÉHICULE, il ne commence pas loin de lui.
   Tiré du premier arrêt au dernier, il laissait entre le nom et sa première
   pastille un vide qui grandit avec la largeur du tableau : sur une journée à
   quatre arrêts, cent vingt pixels de rien. Le nom flottait alors au milieu
   d'une bande, attaché à rien.
   Le trait court donc sur toute la largeur de la journée : il commence là où
   le nom finit, et les pastilles se posent dessus, chacune au milieu de sa
   tranche. C'est la ligne du véhicule, pas seulement la corde tendue entre
   son premier et son dernier arrêt.
   Il s'arrête avant le bord : buté contre le filet de la carte, il donnait
   l'impression d'une journée coupée en plein trajet. */
.une-route .rail-frise {
  /* D'UN ARRÊT À L'AUTRE, ET DE NULLE PART AILLEURS.
     Le trait courait sur toute la largeur de la journée : il commençait donc
     avant le premier arrêt et finissait après le dernier, deux moignons qui
     racontaient une route avant le départ et après l'arrivée. La journée
     commence où le véhicule dort et finit où il se gare ; le trait va d'un
     point à l'autre, et 9 px sont le rayon de la pastille. */
  /* 9 px est le rayon de la pastille : le trait part de son centre. */
  position: absolute; z-index: 0; top: 24px;
  left: calc(var(--air-frise) + 9px); right: calc(var(--air-frise-fin) + 9px);
  height: 6px; border-radius: 999px;
  background: hsl(var(--h-moyen, 0) 56% 85%);
}
.une-route .halte-frise {
  flex: 1 1 0; min-width: 0; position: relative;
  display: grid; justify-items: center; gap: 3px; text-align: center;
}
/* LES DEUX BOUTS SE POSENT AUX BOUTS.
   Ils tenaient une demi-tranche et leur pastille se centrait dedans : le
   premier arrêt se retrouvait à un quart de la largeur du bord, et le trait
   devait courir dans le vide pour le rejoindre. Ils prennent maintenant la
   largeur de leur contenu, la pastille contre le bord, et leur nom s'aligne
   sur elle au lieu de se centrer : trois arrêts centrés, deux qui s'appuient.
   `of-type` et non `child` : le trait est le premier enfant de la liste. */
.une-route .halte-frise:first-of-type {
  flex: 0 1 auto; justify-items: start; text-align: left;
}
.une-route .halte-frise:last-of-type {
  flex: 0 1 auto; justify-items: end; text-align: right;
}
.une-route .halte-frise:first-of-type:last-of-type {
  flex: 0 1 auto; justify-items: start; text-align: left;
}
.une-route .heure {
  font-size: 10.5px; color: var(--encre-3); font-variant-numeric: tabular-nums;
}
.une-route .rond {
  position: relative; z-index: 1;
  width: 18px; height: 18px; border-radius: 50%;
  background: hsl(var(--h-moyen, 0) 56% 85%);
  /* L'anneau blanc masque le trait qui passe dessous : a trois pixels, le
     trait semblait coller au dernier point, ou il s'arrete. */
  box-shadow: 0 0 0 4px var(--surface);
}
/* Là où le véhicule dort, au matin et au soir : le ton soutenu marque les deux
   bouts de la journée, comme la maison d'un itinéraire. */
.une-route .halte-frise.base .rond { background: hsl(var(--h-moyen, 0) 44% 38%); }
.une-route .lieu-frise {
  font-size: 11.5px; color: var(--encre); font-weight: 600; line-height: 1.25;
  overflow-wrap: anywhere;
}
.une-route .bouge {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 3px 7px;
  font-size: 10.5px; font-variant-numeric: tabular-nums;
}
/* Ce qui MONTE dans le camion et ce qui en DESCEND : deux gestes opposés, deux
   couleurs de l'atelier, et la flèche dit lequel sans qu'on ait à le lire. */
.une-route .monte { color: var(--ok); font-weight: 600; }
.une-route .descend { color: var(--refus); font-weight: 600; }
/* CE QUI TRAVERSE L'ARRÊT SANS BOUGER.
   Ni rouge ni vert : rien ne s'est passé pour ces articles-là. La flèche dit
   « ça continue », et le gris dit que ce n'est pas un geste, c'est un état. */
.une-route .reste-bord { color: var(--encre-3); font-weight: 500; }
.une-route .volume { color: var(--encre-3); font-style: normal; }
}
.legende-moyens { margin-top: 8px; }
.un-moyen-legende {
  display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--encre-2);
}
.un-moyen-legende .trait-moyen {
  width: 22px; height: 0; border-top: 1px solid hsl(var(--h-moyen) 48% 40%);
  position: relative; flex: none;
}
.un-moyen-legende .trait-moyen::before, .un-moyen-legende .trait-moyen::after {
  content: ''; position: absolute; top: -2px; width: 5px; height: 5px; border-radius: 50%;
  background: hsl(var(--h-moyen) 48% 40%);
}
.un-moyen-legende .trait-moyen::before { left: -1px; }
.un-moyen-legende .trait-moyen::after { right: -1px; }
/* Une case dit trois choses, et il faut qu'elles se distinguent : ce qu'on
   dépose ici, ce qu'on y prend, ce qu'on y laisse. Écrites à la suite sans les
   nommer, les douze choses qui dorment là noyaient les deux qui bougent. */
/* Six pixels entre deux sections d'une case suffisaient tant qu'elles
   n'étaient que des listes. Depuis que les paquets sont des bulles, « on
   prend » venait se coller au bas de la dernière bulle de « on dépose » et
   se lisait comme son pied de page. Un titre de section a besoin de plus
   d'air au-dessus qu'entre ses propres lignes. */
.groupe-case + .groupe-case, .groupe-case + .reste-case { margin-top: 16px; }
/* « On dépose », « on prend », « sur place » : les trois verbes de la journée,
   et c'est par eux qu'on entre dans une case.
   Ils étaient plus petits, plus clairs et plus gris que la liste qu'ils
   annoncent : la liste gagnait donc toujours. L'encre pleine leur revient, et
   la chasse large les range du côté des rubriques du tableau plutôt que du
   côté des étiquettes de contenu, sans leur coûter ni corps ni graisse. */
.quoi-case {
  display: block; font-size: 9.5px; text-transform: uppercase; letter-spacing: .14em;
  color: var(--encre); margin-bottom: 1px; font-weight: 600;
}
/* L'interligne se resserre DANS l'article, l'air se met ENTRE les articles.
   C'est ce qui fait lire « un titre sur trois lignes » plutôt que « trois
   choses » : les lignes d'un même nom se tiennent, celles de deux noms se
   séparent. */
.jour-flux .mouvement { font-variant-numeric: tabular-nums; line-height: 1.24; }
/* Deux articles dans une colonne étroite tiennent chacun sur trois lignes, et
   l'on ne voit plus où l'un finit. L'espace seul ne suffit pas : c'est le
   retour à la ligne qui trompe. On ajoute donc un peu d'air ENTRE les articles
   et un alinéa négatif, si bien que la pastille et la quantité commencent
   l'article et que les lignes suivantes se rangent en retrait. */
/* La marge verticale est SYMETRIQUE, parce que cet element porte aussi le
   fond de la selection : une marge intérieure de huit pixels en haut et de
   rien en bas peignait un rectangle décalé au-dessus du texte, et le texte
   n'était plus centré dedans. L'air entre deux articles se fait donc par la
   marge, jamais par la marge intérieure. */
.jour-flux .groupe-case .mouvement {
  position: relative; padding: 3px 3px 3px 16px; margin: 0 -3px; text-indent: -13px;
}
/* Un filet AU MILIEU de l'air, pas collé au texte. L'espace seul dit
   « peut-être liés », le trait dit « celui-ci s'arrête ici », et il ne ment
   pas quand un article tient sur trois lignes. Posé en incrustation, il ne
   prend pas de place dans la boîte et ne décale donc rien. */
.jour-flux .groupe-case .mouvement + .mouvement { margin-top: 10px; }
.jour-flux .groupe-case .mouvement + .mouvement::before {
  content: ''; position: absolute; left: 0; right: 0; top: -5px;
  border-top: 1px solid var(--filet-doux);
}
.reste-case .present span { display: block; padding: 3px 3px 3px 16px; margin: 0 -3px; text-indent: -13px; }
.reste-case .present span + span { margin-top: 5px; }
/* LE GRAS EST AU VERBE, PAS AUX ARTICLES.
   Ce qu'on dépose s'écrivait en gras et ce qu'on prend en maigre : une case
   qui fait les deux devenait deux listes de poids différents, dont l'une
   criait sans raison. Ce qui distingue les deux, c'est le verbe qui les
   annonce, et c'est lui qui porte le gras. */
/* L'ENCRE PLEINE APPARTIENT AUX TITRES.
   Elle etait la couleur du texte courant, donc elle ne signalait rien et les
   deux titres passaient dessous. Ce qui distingue ce qu'on depose de ce qu'on
   prend, c'est le verbe qui les annonce, comme pour le gras. */
.groupe-case.depose .mouvement, .groupe-case.prend .mouvement { color: var(--encre-2); }
.groupe-case.prend .quoi-case, .groupe-case.depose .quoi-case { color: var(--encre); }
.groupe-case.devient .mouvement, .groupe-case.devient .quoi-case { color: var(--distingue-encre); }
/* CE QU'ON FABRIQUE ICI. La matière à gauche, l'ensemble à droite : c'est un
   objet comme les autres, on le prend et on l'emmène. Il descend sous la
   flèche plutôt que de s'aligner à côté, parce qu'une colonne fait rarement
   plus de cent trente pixels et que deux noms de meuble n'y tiennent pas de
   front. */
.groupe-case.devient .devenu { display: grid; gap: 2px; margin-bottom: 6px; }
.groupe-case.devient .devenu:last-child { margin-bottom: 0; }
.groupe-case.devient .matieres { font-size: 11px; color: var(--distingue-encre); }
/* Défaire la construction, là où elle se voit. Discrète comme la croix qui
   retire un lieu : elle ne paraît qu'au survol, et sa cible fait 24 px. */
.groupe-case.devient .defaire-devenu {
  position: relative; border: 0; background: none; padding: 0 2px; margin-left: 5px;
  cursor: pointer; color: var(--encre-3); font-size: 10px;
  opacity: 0; transition: opacity .12s;
}
.groupe-case.devient .devenu:hover .defaire-devenu,
.groupe-case.devient .defaire-devenu:focus-visible { opacity: 1; }
.groupe-case.devient .defaire-devenu:hover { color: var(--refus); }
.groupe-case.devient .defaire-devenu::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 24px; height: 24px; transform: translate(-50%, -50%);
}
@media (hover: none) { .groupe-case.devient .defaire-devenu { opacity: 1; } }
.groupe-case.devient .matieres .plus { padding: 0 4px; }
.groupe-case.devient .devenu-quoi { display: flex; align-items: baseline; gap: 5px; }
.groupe-case.devient .devenu-quoi > .objet-flux { flex: 1; min-width: 0; }
.groupe-case.devient .fleche { font-size: 11px; color: var(--distingue-encre); line-height: 1; }
.groupe-case.devient .ne-de-la { border-color: var(--distingue); }

/* Ce qui est sur place est du contexte, pas un geste : le compte suffit, le détail
   s'ouvre quand on le demande. */
/* Ce qui dépasse le plafond d'une case. Même dépliant que « sur place » :
   un seul geste à apprendre. */
.suite-case { margin-top: 8px; }
.suite-case > summary { list-style: none; }
.suite-case > summary::-webkit-details-marker { display: none; }
.suite-case > .mouvement:first-of-type { margin-top: 8px; }

.reste-case { margin-top: 7px; }
/* Le compte passe A LA LIGNE, jamais le verbe.
   Dans une colonne de quatre-vingts pixels, « sur place 41 › » ne tient pas
   sur une ligne : la boite coupait le verbe en « ON / LAISSE » et le titre
   devenait illisible. Le texte ne se brise plus, et c'est le compte qui
   descend d'une ligne quand la place manque. */
.suite-case summary, .reste-case summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 4px;
  flex-wrap: wrap; white-space: nowrap; line-height: 1.15;
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--encre-3);
}
/* « On laisse » est un verbe de la journée comme les deux autres, même s'il
   ouvre un repli : il en prend le gras, l'encre et la chasse. « + 3 autres »
   n'en est pas un, c'est un compte, et il reste en gris serré. */
.reste-case > summary {
  font-weight: 600; color: var(--encre); letter-spacing: .14em;
}
.reste-case > summary:hover { color: var(--accent-encre); }
.reste-case summary::-webkit-details-marker { display: none; }
.reste-case summary b {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; text-transform: none; letter-spacing: 0; color: var(--encre-2);
  font-variant-numeric: tabular-nums;
}
.suite-case summary:hover { color: var(--encre-2); }
.suite-case summary .chevron, .reste-case summary .chevron {
  width: 5px; height: 5px; border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(-45deg); margin-left: 1px; transition: transform .12s ease;
}
.suite-case[open] summary .chevron, .reste-case[open] summary .chevron { transform: rotate(45deg); }
.jour-flux .present {
  margin-top: 4px; display: grid; gap: 1px;
  color: var(--encre-3); font-size: 11px; line-height: 1.35;
}
.jour-flux .present span {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.anomalies-flux {
  margin-top: 12px; padding: 10px 13px; border-radius: var(--rayon-petit);
  background: var(--refus-fond); color: var(--refus-encre); font-size: 12.5px;
}
.anomalies-flux b { color: var(--refus); }
.anomalies-flux ul { margin: 6px 0 0; padding-left: 18px; line-height: 1.5; }

/* L'état du dessin se lit à côté de son titre, et se change là. Rangé dans un
   menu, ce réglage ne se trouve pas : c'est pourtant lui qui donne au dessin
   ses colonnes et ses lignes. */
.tete-flux { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 26px 0 10px; }
.tete-flux .titre-flux { margin: 0; }
.lieux-jours .dedans { max-width: 620px; }
.lieux-jours h4 { font-size: 12px; color: var(--encre-2); margin: 20px 0 3px; }
.ligne-lieu { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; margin-bottom: 7px; }
/* UNE JOURNÉE AU MILIEU. Le choix du jour et les deux verbes sur une ligne :
   c'est une phrase, « la journée J3, supprimer », et la couper en deux blocs
   ferait chercher le second. */
.bouger-jours {
  display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap; margin: 6px 0 4px;
}
.bouger-jours .champ-question { margin: 0; }
/* Ce qu'on perd se lit avant d'accepter : un trajet effacé, c'est un camion
   qui ne passe plus, et personne ne s'en aperçoit avant le chantier. */
.perdus-jour {
  margin: 6px 0 0; padding: 10px 12px 10px 26px; border-radius: var(--rayon-petit);
  background: var(--attente-fond); color: var(--attente-encre); font-size: 12.5px;
}
.perdus-jour li { margin: 2px 0; }

/* QUEL LIEU VOIR ENSUITE. Une liste, pas une grille : c'est un ordre, et un
   ordre se lit de haut en bas. Les deux flèches suffisent — on remonte celui
   qu'on veut voir, on ne compose pas un classement de douze lignes. */
.ordre-lieux { display: grid; gap: 2px; margin: 6px 0 4px; }
.ligne-ordre {
  display: flex; align-items: center; gap: 6px; padding: 5px 8px;
  background: var(--enclos); border-radius: var(--rayon-petit); font-size: 12.5px;
}
.ligne-ordre span { flex: 1; min-width: 0; }
.ligne-ordre button {
  border: 1px solid var(--filet); background: var(--surface); border-radius: var(--rayon-petit);
  width: 26px; height: 24px; font: inherit; color: var(--encre-2); cursor: pointer;
}
.ligne-ordre button:hover:not(:disabled) { border-color: var(--encre-3); color: var(--encre); }
.ligne-ordre button:disabled { opacity: .3; cursor: default; }
.ligne-lieu input {
  padding: 7px 9px; font: inherit; font-size: 12.5px;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.ligne-lieu button {
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
  color: var(--encre-3); cursor: pointer; padding: 0 10px;
}
.ligne-lieu button:hover:not(:disabled) { border-color: var(--refus); color: var(--refus); }
.ligne-lieu button:disabled { opacity: .35; cursor: not-allowed; }
#lj-ajouter { margin-top: 6px; }

/* Le parcours d'une chose : une liste d'étapes, pas un formulaire, parce que
   c'est ainsi qu'on la raconte. Déplacements et transformations se mêlent dans
   le même ordre, celui des jours : les séparer obligerait à lire deux fois
   pour reconstituer une seule histoire. */
.bloc.parcours { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--filet-doux); }
.parcours .depart-parcours { font-size: 12px; color: var(--encre-3); margin-bottom: 7px; }
.parcours .depart-parcours b { color: var(--encre-2); }
.etapes-parcours { display: grid; gap: 6px; }
/* Une étape : le jour, l'heure, la destination, combien, pourquoi. L'heure ne
   se saisissait que dans la feuille de route, un écran plus loin : on décrivait
   un parcours entier sans pouvoir dire à quelle heure il passe, alors que
   c'est là qu'on y pense. */
/* SEPT colonnes, pas cinq. La ligne en comptait cinq pour six éléments : le
   bouton qui retire l'étape passait à la ligne suivante, seul, et la chaîne
   paraissait cassée en deux à chaque maillon. */
.etape-parcours {
  display: grid; gap: 6px; align-items: center;
  grid-template-columns: 40px 56px auto minmax(0, 1fr) 52px minmax(0, auto) auto;
}
.etape-parcours[data-genre="devient"] {
  grid-template-columns: 40px auto minmax(0, 1fr) 52px auto;
}
/* « 08:30 » ne tient pas dans quarante-quatre pixels : le champ affichait
   « 08:3 » et l'on croyait avoir mal tapé. */
.etape-parcours .p-heure { padding-left: 4px; padding-right: 4px; }
.etape-parcours .p-jour { padding-left: 2px; padding-right: 2px; }
.etape-parcours .p-heure { text-align: center; font-variant-numeric: tabular-nums; }
.etape-parcours input, .etape-parcours select {
  padding: 6px 8px; font: inherit; font-size: 12.5px; min-width: 0;
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
.etape-parcours .p-jour, .etape-parcours .p-quantite {
  text-align: center; font-variant-numeric: tabular-nums;
}
.etape-parcours .fleche { font-size: 11.5px; color: var(--encre-3); white-space: nowrap; }
.etape-parcours[data-genre="devient"] .fleche { color: var(--distingue-encre); }
.etape-parcours .p-retirer {
  border: 0; background: none; color: var(--encre-3); cursor: pointer; padding: 4px 6px;
}
.etape-parcours .p-retirer:hover { color: var(--refus); }
.gestes-parcours { display: flex; gap: 14px; margin-top: 8px; }
/* On ajoute une étape LÀ OÙ ELLE VA, pas au bout de la liste. Le « + » se
   glisse entre deux maillons et ne paraît qu'au survol de la chaîne : une
   croix permanente entre chaque ligne ferait une colonne de croix. */
.etapes-parcours { position: relative; }
.p-inserer {
  display: block; width: 18px; height: 18px; padding: 0; margin: -2px 0 -2px auto;
  border: 1px dashed var(--filet); border-radius: 50%; background: var(--surface);
  color: var(--encre-3); font-size: 12px; line-height: 1; cursor: pointer;
  opacity: 0; transition: opacity .12s;
}
.etapes-parcours:hover .p-inserer, .p-inserer:focus-visible { opacity: 1; }
.p-inserer:hover { border-style: solid; border-color: var(--accent); color: var(--accent-encre); }
.gestes-parcours button {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 11.5px; color: var(--encre-3);
}
.gestes-parcours button:hover { color: var(--encre); text-decoration: underline; }

/* Ce que le camion porte ce jour-là, sous le jour qu'il décrit. Le dessin
   montrait la route sans dire si le chargement tenait dedans, et c'est
   pourtant pour ça qu'on réserve un camion plutôt qu'un autre. */
.jour-flux .charge-jour {
  display: block; margin-top: 4px; font-size: 10.5px; color: var(--encre-3);
  font-variant-numeric: tabular-nums; line-height: 1.4;
}
.jour-flux .charge-jour b { display: block; color: var(--refus); font-weight: 600; }
.jour-flux .charge-jour.deborde { color: var(--refus-encre); }

/* Ce qu'il reste à régler. Il passe AVANT le dessin : ce qui reste à faire se
   lit avant ce qui est déjà su. */
.a-regler { display: grid; gap: 10px; margin: 0 0 16px; }
.groupe-a-regler {
  padding: 10px 13px; border-radius: var(--rayon-petit); background: var(--surface-2);
  font-size: 12.5px;
}
.groupe-a-regler.presse { background: var(--attente-fond); color: var(--attente-encre); }
.groupe-a-regler > b { display: block; margin-bottom: 6px; }
.groupe-a-regler.presse > b { color: var(--attente); }
/* Une ligne par fiche, avec sa raison a elle : un titre de groupe resume, et
   un resume ment des que deux fiches ne manquent pas de la meme chose. */
.lignes-a-regler { display: grid; gap: 3px; }
.ligne-a-regler {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; cursor: pointer;
  padding: 2px 0;
}
.ligne-a-regler:hover .quoi { text-decoration: underline; }
.ligne-a-regler .quoi { color: inherit; }
.ligne-a-regler .pourquoi { font-size: 11.5px; opacity: .72; }
.ligne-a-regler.rien { cursor: default; font-style: italic; }
.tout-regle { margin: 0 0 16px; }

/* Prendre et déposer dans le dessin. Déplacer une chose d'une case à l'autre,
   c'est dire « elle va là, ce jour-là » : le geste direct dit ce qu'on venait
   écrire dans le tiroir, trois écrans plus loin. */
.objet-flux { cursor: grab; border-radius: 3px; padding: 0 3px; margin: 0 -3px; }
.objet-flux:hover { background: var(--surface-2); }
/* Marqué l'emporte sur en attente : c'est ce qu'on est en train de faire. */
.objet-flux.pris, .objet-flux.a-dire.pris, .objet-flux.a-preciser.pris {
  background: var(--accent-doux); color: var(--accent-encre);
}
/* Ce qu'il reste à régler se voit DANS le dessin, pas seulement au-dessus.
   La liste disait « 1 fiche dont personne n'a dit si elle va sur le chantier »
   et il fallait ensuite la retrouver à l'œil parmi vingt-cinq objets répartis
   sur cinq jours et six colonnes. Deux tons d'ambre : personne n'a rien dit,
   et il manque un détail. */
.objet-flux.a-dire { background: var(--attente-fond-2); color: var(--attente-encre); }
.objet-flux.a-preciser { background: var(--attente-fond); color: var(--attente-encre); }
.objet-flux.a-dire:hover, .objet-flux.a-preciser:hover { filter: brightness(0.97); }
/* CE QUE PERSONNE N'A ÉCRIT. Sans un mot, une chose est supposée partir au
   chantier le jour où l'on en a besoin : c'est un défaut utile, sans quoi des
   caisses dormiraient au dépôt sans que personne s'en aperçoive. Mais la case
   l'écrivait comme un trajet décidé, et sur une livraison que le fournisseur
   fait lui-même on lisait deux gestes que personne n'a demandés.
   Un mot, pas une couleur : l'ambre veut dire « il faut répondre », et ici il
   n'y a rien à répondre — le défaut est peut-être le bon. */
.dit-suppose {
  margin-left: 5px; font-size: 9.5px; font-style: normal; color: var(--encre-3);
  text-transform: uppercase; letter-spacing: .08em;
}
.temoin-a-dire {
  background: var(--attente-fond-2); color: var(--attente-encre);
  border-radius: 3px; padding: 0 4px;
}
/* Marqué, un membre de groupe prend la couleur de SON groupe. Le vert de la
   sélection dit « celui-là » ; il ne peut pas dire en même temps « et les
   trois qui partent avec lui », et l'on croit avoir marqué trop de choses.
   Le filet vertical essayé à sa place peignait une colonne de barres devant
   une liste faite pour qu'on y lise des noms : la couleur ne paraît donc
   qu'au marquage, quand elle répond à une question qu'on vient de poser. */
.objet-flux.dans-un-groupe.pris, .objet-flux.dans-un-groupe.a-dire.pris,
.objet-flux.dans-un-groupe.a-preciser.pris {
  background: hsl(var(--h-groupe) 46% 91%); color: hsl(var(--h-groupe) 44% 26%);
}
.objet-flux:active { cursor: grabbing; }
/* Pendant qu'on traîne, les cases se signalent : sans cela on ne sait pas où
   l'on a le droit de déposer, et l'on relâche dans le vide. */
.flux-en-cours .cellule[data-lieu] { outline: 1px dashed var(--filet); outline-offset: -2px; }
/* DEUX GESTES QUI SE RESSEMBLENT ET QUI NE FONT PAS LA MÊME CHOSE.
   Une bulle vit DANS une case : en traînant un objet, on survolait les deux à
   la fois, elles s'allumaient du même vert, et rien ne disait laquelle allait
   recevoir. L'une change le LIEU où la chose se trouve ce jour-là, l'autre
   change le véhicule qui l'emmène ou le groupe avec lequel elle voyage.
   La case garde l'accent de l'application, la bulle prend la teinte de ce
   qu'on rejoint, et chacune dit son geste en un mot. */
.cellule.survole { background: var(--accent-doux); outline: 1px solid var(--accent) !important; }
.cellule.survole::after, .paquet-case.recoit::after {
  content: attr(data-geste);
  position: absolute; z-index: 6; top: 3px; right: 3px;
  max-width: calc(100% - 8px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 1px 7px 2px; border-radius: var(--rond);
  font-size: 9.5px; font-weight: 600; letter-spacing: .03em;
  background: var(--accent); color: #FFF; pointer-events: none;
}
.paquet-case { position: relative; }
/* La bulle s'annonce dans SA couleur : c'est celle du groupe ou du véhicule
   qu'on rejoint, et c'est la réponse à « je le mets où ». */
.paquet-case.recoit {
  outline: 2px solid hsl(var(--h-paquet, 0) 45% 45%); outline-offset: -1px;
  background: hsl(var(--h-paquet, 0) 42% 92%);
}
/* Le mot de la bulle se pose EN BAS : en haut, il recouvrait le nom du groupe,
   c'est-à-dire ce qu'on vient justement de viser. */
.paquet-case.recoit::after {
  background: hsl(var(--h-paquet, 0) 45% 36%);
  top: auto; bottom: 3px;
}
/* Sans teinte, il n'y a pas de couleur à reprendre : « sans véhicule » et
   « hors groupe » ne rejoignent rien, ils retirent. */
.paquet-case.sans-teinte.recoit {
  outline-color: var(--encre-2); background: var(--surface-2);
}
.paquet-case.sans-teinte.recoit::after { background: var(--encre); }
/* Une case vide se pose en retrait, mais PLUS LEGEREMENT que ce qui est
   plein : au papier, elle pesait davantage que les boîtes de paquets qui,
   elles, contiennent quelque chose, et l'œil allait aux colonnes vides. Le
   vide ne se lit pas, il se contourne. */
.jour-flux .cellule.vide { background: var(--enclos); }
/* Une colonne vide DU HAUT EN BAS n'a meme pas ce retrait.
   Le gris dit « rien ici aujourd'hui » et se lit parce que ses voisines
   portent quelque chose ; empile sur toute la hauteur d'une colonne qui ne
   porte jamais rien, il devient un mur gris que l'oeil prend pour une
   separation. La colonne maigre se signale deja par sa largeur. */
.jour-flux .cellule.vide.colonne-maigre { background: none; }

/* Les ventres des véhicules, à part. Un camion n'est pas un lieu : c'est une
   chose qui roule entre les lieux. Mêlé aux colonnes du chantier il se lisait
   comme une adresse de plus, et la route semblait s'y arrêter. Les lieux à
   gauche dans l'ordre où l'on y va, les camions à droite après un filet plein.
   Ils portaient EN PLUS un fond en retrait, le plus fonce du tableau, alors
   qu'ils sont presque toujours vides : on ne garde a bord que les nuits ou
   l'on decharge le lendemain. Deux colonnes grises fermaient donc la carte a
   droite et tiraient l'oeil vers ce qui ne contient rien. Le filet plein et
   l'en-tete en gris suffisent a dire qu'on a quitte les lieux. */
.entete-flux > .lieu-flux.un-moyen { color: var(--encre-3); }
.entete-flux > .lieu-flux.debut-des-moyens,
.jour-flux .cellule.debut-des-moyens { border-left: 1px solid var(--filet); }

/* Le groupe : une seule marque, une pastille devant le nom. Elle ne dit rien
   de plus que « ces objets-là partent ensemble », et c'est tout ce qu'on
   veut lire d'un coup d'œil dans une case déjà pleine. Pas de bandeau, pas de
   cadre : une case qui s'entoure pour chaque groupe devient illisible dès le
   deuxième. */
.pastille-groupe {
  display: inline-block; width: 6px; height: 6px; border-radius: var(--rond);
  background: hsl(var(--h-groupe) 34% 48%); margin-right: 5px;
  vertical-align: baseline; flex: none;
}
/* Ce qui bouge sans qu'on ait dit dans quel véhicule. La question ne se pose
   qu'avec un choix, et rien ne la posait : l'écran laissait deux camions vides
   à côté d'objets qui bougeaient. */
.a-affecter {
  margin: 12px 0 0; padding: 10px 13px; border-radius: var(--rayon);
  background: var(--attente-fond); color: var(--attente-encre);
}
.a-affecter b { font-size: 12.5px; }
.a-affecter .rien { color: var(--attente-encre); opacity: 0.75; margin: 2px 0 0; }
.jours-a-affecter { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.un-jour-a-affecter {
  display: inline-flex; align-items: baseline; gap: 6px; cursor: pointer;
  border: 1px solid var(--attente-filet); background: var(--surface);
  border-radius: var(--rond); padding: 4px 12px; font: inherit; font-size: 12px;
  color: var(--attente-encre); font-variant-numeric: tabular-nums;
}
.un-jour-a-affecter:hover { border-color: var(--attente); }
/* Les arrêts déjà écrits, en tête du panneau : un onglet par arrêt, plus un
   pour en ajouter. Le formulaire est le même, seul son contenu change ; deux
   formulaires pour une même chose finissent toujours par diverger. */
/* Le jour et l'heure vont ensemble. Sur deux lignes, le formulaire faisait
   deux fois sa hauteur et l'on ne voyait plus que la moitié du raisonnement
   à la fois. */
/* Ce qui se passe ENTRE deux étapes. Deux étapes « J1 vers l'atelier » puis
   « J1 vers le chantier » ne disaient nulle part que la chose s'arrête à
   l'atelier entre les deux, ni qu'elle finit au chantier : on lisait deux
   endroits sans lien, et le chemin paraissait s'interrompre. */
.entre-etapes {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 11px; color: var(--encre-3); margin: 2px 0 6px 20px;
  padding-left: 10px; border-left: 1px solid var(--filet);
}
.entre-etapes.fin { color: var(--encre-2); border-left-color: var(--encre-3); }

.duo-jour-heure { display: flex; gap: 6px; }
.duo-jour-heure input:first-child { flex: 1 1 auto; min-width: 0; }
.duo-jour-heure input:last-child { flex: 0 0 68px; }

.un-jour-a-affecter .rien { font-size: 11px; margin: 0; }
.proposer-repartition {
  margin-top: 8px; border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--attente-encre); text-decoration: underline;
}
.proposer-repartition:hover { color: var(--encre); }

/* La répartition proposée : un jour, ses camions, ce que chacun emmène. Elle
   se lit avant de s'appliquer, donc elle se lit comme un document et non
   comme un formulaire. */
.jour-reparti { margin-top: 14px; }
.jour-reparti h4 { margin: 0 0 6px; font-size: 12.5px; }
.moyen-reparti { margin-bottom: 8px; }
.quoi-reparti { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; margin-bottom: 3px; }
.quoi-reparti b { font-size: 12px; }
.quoi-reparti .rien { margin: 0; font-size: 11px; }
.refuses-reparti {
  font-size: 11.5px; color: var(--refus-encre); background: var(--refus-fond);
  border-radius: var(--rayon-petit); padding: 7px 10px; margin-top: 6px;
}

/* Le titre d'un groupe marque tout le groupe, l'étiquette du jour marque tout
   le jour : sans cela, mettre au camion ce qui part du dépôt le J2 se fait
   objet par objet, ce qui est exactement ce qu'une sélection sert à éviter.
   Ils gardent l'allure d'un libellé, pas celle d'un bouton. */
/* Tout déplier, tout replier, pour la journée. Un mot aurait pris toute la
   largeur de l'étiquette du jour ; deux chevrons suffisent, et ils disent le
   sens. Chacun ne paraît que s'il a quelque chose à faire. */
/* Ils se tiennent à côté du numéro du jour, sur sa ligne : rangés sous la
   date, ils faisaient douze pixels sur dix en gris clair, à l'endroit où
   l'œil ne va pas. Ils étaient là, et personne ne les trouvait. */
.tete-jour { display: flex; align-items: center; gap: 4px; }
.plis-du-jour { display: inline-flex; gap: 2px; }
/* Le cadre etait de trop : dix-neuf pixels de bouton pour un chevron de sept,
   ca pesait plus que l'etiquette du jour elle-meme. La fleche seule suffit ;
   ce qui la rendait introuvable n'etait pas sa taille, c'etait sa place, sous
   la date. A cote du numero du jour, elle se trouve. */
.pli-jour {
  border: 0; background: none; cursor: pointer; padding: 3px;
  display: inline-flex; align-items: center; justify-content: center; line-height: 0;
}
.pli-jour .chevron {
  display: block; width: 5px; height: 5px;
  border-right: 1.5px solid var(--encre-3); border-bottom: 1.5px solid var(--encre-3);
}
.pli-jour .chevron.bas { transform: rotate(45deg) translateY(-1px); }
.pli-jour .chevron.haut { transform: rotate(-135deg) translateY(-1px); }
.pli-jour:hover .chevron { border-color: var(--encre); }

button.quoi-case, button.marquer-jour {
  border: 0; background: none; padding: 0; cursor: pointer; text-align: left;
  font-family: inherit;
}
/* `font: inherit` reprendrait la taille et la casse que .quoi-case vient de
   poser juste au-dessus : le libellé grossirait et perdrait ses capitales
   pour la seule raison qu'il est devenu cliquable. */
button.quoi-case {
  display: block; font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em;
  color: inherit;
}
/* Le titre du groupe et le nom du véhicule tiennent sur UNE ligne. Le chip
   tombait sous le titre et se lisait comme un second titre, si bien que deux
   colonnes voisines montraient la même information à deux endroits
   différents : ici sous « on dépose », là au bout de chaque article. */
.tete-case {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin-bottom: 1px;
}
button.marquer-jour { display: block; font-size: inherit; color: inherit; }
button.quoi-case:hover, button.marquer-jour:hover { text-decoration: underline; }

/* Comment lire une case. Une case de quinze articles se lit par paquets quand
   on cherche « qu'est-ce qui part dans le 20m3 » ; à plat, il faut la
   parcourir en entier à chaque question. */
/* LA FACON DE LIRE RESTE SOUS LA MAIN.
   Ces quatre boutons changent ce que chaque case du tableau montre, et l'on
   change d'avis en cours de lecture, pas avant de commencer : c'est en voyant
   la journée du camion qu'on veut la relire par groupe. Ils partaient pourtant
   vers le haut dès le troisième jour, et il fallait remonter tout le dessin
   pour les retrouver.
   Ils se figent donc, comme la bande des lieux, et AU-DESSUS d'elle : la bande
   se cale sous eux plutôt que de leur passer devant. La hauteur de cette barre
   est donc une valeur partagée, et non un nombre recopié dans deux règles qui
   finiraient par diverger. */
.carte-flux, .regrouper-flux { --haut-regrouper: 33px; }
.regrouper-flux {
  display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap;
  position: sticky; top: 0; z-index: 5;
  margin: 0; padding: 7px 12px 6px; min-height: var(--haut-regrouper);
  background: var(--surface);
  /* Elle est le haut de la carte : elle en porte l'arrondi, sinon son angle
     droit se pose sur le coin rond et le mange. */
  border-radius: var(--rayon) var(--rayon) 0 0;
}
.regrouper-flux .rien { margin: 0 6px 0 0; font-size: 11px; }
.un-regroupement {
  border: 1px solid transparent; background: none; border-radius: var(--rond);
  padding: 3px 10px; font: inherit; font-size: 11.5px; color: var(--encre-3); cursor: pointer;
}
.un-regroupement:hover { color: var(--encre); }
.un-regroupement.choisi {
  background: var(--surface-2); border-color: var(--filet); color: var(--encre);
}
/* Un paquet dans une case : son nom en tête, et l'air qui le sépare du
   suivant. Il n'a ni cadre ni fond, sinon la case devient un empilement de
   boîtes dans une colonne large de six centimètres. */
/* LES PAQUETS SE SEPARENT PAR LE FILET ET PAR L'ESPACE.
   Un petit titre gris et dix pixels d'écart ne séparaient rien : quinze
   articles se suivaient sous trois titres, et l'on ne voyait ni où finissait
   un camion ni où commençait le suivant. Un aplat teinté par paquet séparait,
   lui, mais il repeignait le tableau en bandes de couleur alors que ce
   tableau est fait pour qu'on y lise des noms d'objets.
   Un filet pleine largeur, de l'air, et le nom en petites capitales : c'est
   la même façon que le reste de l'atelier sépare ses sections. La couleur ne
   sert qu'à un point, devant le nom, du diamètre d'une pastille de groupe. */
/* Ce qui va ensemble est ENFERME ENSEMBLE.
   Un filet et de l'air séparaient bien, mais ne réunissaient pas : on lisait
   une liste coupée en tronçons, pas trois paquets. Un fond gris arrondi qui
   contient ses articles se lit d'un seul coup comme un objet, et deux paquets
   voisins n'ont plus besoin de trait entre eux pour se distinguer, ils sont
   simplement deux boîtes. Le gris est neutre : la couleur ne sert qu'au point
   qui nomme le paquet. */
.paquet-case {
  /* Le plus clair des quatre neutres. Sur une cellule blanche, trois pour cent
     de gris chaud suffisent à enfermer : au double, la boîte pesait plus que
     ce qu'elle contient, et une colonne de six boîtes devenait une colonne de
     blocs gris où les noms se lisaient en second. */
  background: var(--enclos); border-radius: var(--rayon); padding: 10px 10px 9px;
}
/* ET UNE TEINTE PAR BULLE, au même poids.
   Trois pour cent de gris deviennent trois pour cent de la couleur du
   véhicule ou du groupe : deux bulles voisines se distinguent alors sans
   qu'on ait besoin de lire leur titre, et la couleur est celle que porte déjà
   la route du camion en haut de la ligne et la pastille du groupe. À
   saturation pleine, cette même idée repeignait le tableau en bandes ; à ce
   poids-là, elle ne fait que teinter le papier. Ce qui n'a ni véhicule ni
   groupe reste au gris : c'est le reste, il n'a pas de couleur à lui. */
.paquet-case:not(.sans-teinte) {
  background: hsl(var(--h-paquet) 40% 96.2%);
}
.paquet-case + .paquet-case { margin-top: 8px; }
/* Dans une boîte grise, le survol d'un article se marque en clair : le gris
   de survol s'y confondrait avec le fond. */
.paquet-case .objet-flux:hover { background: var(--surface); }
/* Le nom du paquet, en tête de sa boîte. Les petites capitales espacées
   allongent « Construction 1 » au point de le couper en deux dans une colonne
   étroite : l'espacement se réduit, le nom tient. */
/* Le nom du paquet RESPIRE. Collé au bord de sa bulle et à la première
   ligne, il se lisait comme une ligne de plus au lieu d'annoncer ce qui
   suit : un intitulé a besoin d'air au-dessus et au-dessous pour être un
   intitulé. */
/* Le nom du paquet EST UN TITRE, il en a donc l'encre.
   En gris clair, il etait la ligne la plus pale d'une case ou il annonce
   pourtant tout ce qui suit : on lisait les articles, puis on remontait
   chercher a quel camion ils appartenaient. Il ne prend pas la chasse large
   du verbe, et il ne risque donc pas de se confondre avec lui : le verbe
   ouvre la case depuis sa marge, le nom ouvre la bulle depuis l'interieur du
   fond teinte. */
.nom-paquet {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 9.5px; margin-bottom: 9px;
  font-weight: 600; text-transform: uppercase; letter-spacing: .02em;
  color: var(--encre);
}
.paquet-case:not(.sans-teinte) .nom-paquet::before {
  content: ''; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%;
  background: hsl(var(--h-paquet) 48% 42%); transform: translateY(-1px);
}
/* On avait retiré ici la teinte des objets d'un paquet par groupe, au motif
   qu'elle redisait le point du titre. Elle ne le redisait pas : cette teinte
   ne se pose QUE sur ce qui est marqué, et c'est elle qui montre lesquels
   partent ensemble. La règle l'emportait sur celle du marquage, et cocher
   cinq objets dans la vue par groupe ne se voyait plus du tout. */

.legende-groupes { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 0; }
/* LA LÉGENDE TIENT TANT QUE LE TABLEAU EST LÀ.
   Posée sous le dessin, elle sortait de l'écran dès qu'on descendait dans les
   journées : on lisait alors des pastilles de couleur sans plus savoir quel
   groupe chacune nomme, c'est-à-dire une couleur sans sa légende. Celle des
   véhicules n'en a pas besoin, chaque frise portant déjà son nom. */
.legende-groupes:not(.legende-moyens) {
  position: sticky; bottom: 0; z-index: 3;
  /* Autant d'air au-dessus qu'au-dessous : à deux pixels en haut contre huit
     en bas, les pastilles se posaient sur le haut de la bande au lieu d'y
     flotter, et la bande paraissait mal réglée. */
  padding: 8px 0; background: var(--papier);
}
/* Deux barres collées au même bord se recouvrent. La légende tient le bas, la
   bande de sélection se pose au-dessus d'elle. */
.vue-reservations:has(.legende-groupes:not(.legende-moyens)) .bande-selection { bottom: 46px; }
/* LA PASTILLE SE POSE AU CENTRE OPTIQUE, PAS AU CENTRE GÉOMÉTRIQUE.
   Centrée sur la boîte de la ligne, elle tombe un pixel sous le milieu des
   minuscules, parce que la boîte compte la descente des lettres et que
   « Scène A1 » n'en a presque pas : la pastille paraissait basse, et le bouton
   décentré. Et les deux bords valent autant : un point de six pixels lit plus
   léger qu'un mot, il lui faut donc au moins l'espace que le mot réclame, pas
   deux pixels de moins. */
.un-groupe {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--filet); background: var(--surface); border-radius: var(--rond);
  padding: 4px 11px; font: inherit; font-size: 12px; color: var(--encre-2);
}
.un-groupe .pastille-groupe { transform: translateY(-1px); }
/* LA MÊME TEINTE QUE LA BULLE QUI RASSEMBLE SES OBJETS.
   La pastille disait la couleur du groupe, le fond disait blanc : la légende
   et la bulle qu'elle nomme ne se ressemblaient qu'à un point près, et il
   fallait comparer deux points de six pixels pour relier l'une à l'autre.
   Même teinte, même poids : trois pour cent de couleur, comme la bulle. */
.un-groupe { background: hsl(var(--h-groupe) 40% 96.2%); border-color: hsl(var(--h-groupe) 30% 88%); }
.un-groupe:hover { border-color: hsl(var(--h-groupe) 32% 72%); color: var(--encre); }
.un-groupe .rien { font-size: 11px; }

/* Ce qu'on a marqué, et ce qu'on peut en faire. La bande n'existe que s'il y a
   une sélection : un rang de boutons toujours là, gris et sans objet, apprend
   à ne plus le lire. */
/* Elle colle au bas de l'écran, sous le dessin. Posée au-dessus, elle
   apparaissait au premier clic et poussait tout le tableau vers le bas :
   l'objet visé n'était plus sous le curseur, et le second clic d'un
   double-clic tombait à côté. */
.bande-selection {
  display: flex; align-items: center; gap: 8px; margin: 10px 0 0;
  padding: 7px 12px; border-radius: var(--rayon); background: var(--accent-doux);
  color: var(--accent-encre);
  position: sticky; bottom: 10px; z-index: 3;
  box-shadow: 0 1px 8px rgba(27, 27, 25, 0.12);
}
/* Le tiroir est un panneau fixe de 430 px sur la droite : la bande, elle,
   court sur toute la largeur du contenu et passait donc DESSOUS. Ses derniers
   boutons devenaient inatteignables au moment precis ou l'on venait d'ouvrir
   une fiche depuis le dessin. Elle se retire de la largeur du panneau tant
   qu'il est ouvert. */
body:has(.tiroir.ouvert) .bande-selection { margin-right: 442px; }
/* Sur un ecran etroit le tiroir couvre presque tout : la bande n'a plus la
   place de se ranger a cote, elle se range au-dessus de lui. */
@media (max-width: 900px) {
  body:has(.tiroir.ouvert) .bande-selection { margin-right: 0; }
}
.bande-selection b { font-size: 12px; margin-right: auto; }
.bande-selection button {
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre);
  border-radius: var(--rond); padding: 4px 12px; font: inherit; font-size: 12px; cursor: pointer;
}
.bande-selection button.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.bande-selection button.veille { border-color: transparent; background: none; color: var(--accent-encre); }
.bande-selection button:hover { filter: brightness(0.96); }
/* Le seul verbe de la bande qui ôte. Sa couleur le dit avant qu'on le clique,
   et il se range à la fin, loin de ceux qu'on enchaîne. */
.bande-selection button.a-part { color: var(--refus); }
.bande-selection button.a-part:hover { border-color: var(--refus); }

/* Dans quel véhicule ? Sur la ligne de l'objet, là où la question se pose.
   Rangée ailleurs, elle ne se posait qu'au moment du glisser-déposer et plus
   jamais après. */
.par-quoi {
  border: 0; background: none; padding: 0 2px; font: inherit; font-size: 11px;
  color: var(--encre-3); cursor: pointer; border-bottom: 1px dotted var(--filet);
  /* Le nom d'un véhicule ne casse jamais la ligne de l'objet : il s'abrège.
     Écrit en entier dans une colonne étroite, il repoussait le nom de la chose
     hors de vue, et la question mangeait ce sur quoi elle portait. */
  white-space: nowrap; max-width: 11ch; overflow: hidden;
  text-overflow: ellipsis; vertical-align: bottom;
}
.par-quoi.a-dire {
  max-width: none; font-weight: 600; padding: 0 4px; border-bottom: 0;
  border-radius: var(--rond); background: var(--attente-fond-2);
}
.par-quoi:hover { color: var(--encre); border-bottom-color: var(--encre-3); }
/* La pastille du véhicule porte SA couleur, celle de son trait. On voyait deux
   traits de couleurs différentes en haut de la ligne et « 20m3 » en gris à
   côté des objets : rien ne reliait l'un à l'autre. */
.par-quoi[style*="--h-moyen"] {
  color: hsl(var(--h-moyen) 46% 34%); border-bottom-color: hsl(var(--h-moyen) 40% 70%);
}
.par-quoi[style*="--h-moyen"]:hover { border-bottom-color: hsl(var(--h-moyen) 48% 40%); }
.par-quoi.a-dire { color: var(--attente); border-bottom-color: var(--attente-filet); }

/* Le nombre EST le geste : on clique dessus pour n'en bouger qu'une partie.
   Il garde donc l'allure d'un nombre, avec juste ce qu'il faut pour se
   laisser trouver au survol. */
.combien-bouge {
  border: 0; background: none; padding: 0; font: inherit; color: inherit; cursor: pointer;
  font-variant-numeric: tabular-nums; border-bottom: 1px dotted var(--filet);
}
.combien-bouge:hover { border-bottom-color: var(--encre-3); background: var(--surface-2); }

.liste-membres { display: flex; flex-direction: column; gap: 2px; max-height: 190px; overflow-y: auto; }
.ligne-membre {
  display: flex; align-items: center; gap: 8px; padding: 4px 8px;
  border-radius: var(--rayon-petit); background: var(--surface-2); font-size: 12px;
}
.ligne-membre span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ligne-membre button {
  border: 0; background: none; cursor: pointer; color: var(--encre-3);
  font: inherit; padding: 0 4px; line-height: 1;
}
.ligne-membre button:hover { color: var(--encre); }
.liste-membres.dehors .ligne-membre { background: none; }

/* Ajouter un lieu, un jour, une date : au bout de ce qu'ils prolongent, et non
   dans un réglage qu'il faut aller chercher. */
.lieu-flux.ajout, .jour-flux.ajout-jour .etiquette-jour { padding: 6px 10px; }
.lieu-flux.ajout button, .jour-flux.ajout-jour button, .coin-flux .date-montage {
  border: 0; background: none; padding: 0; cursor: pointer; font: inherit;
  font-size: 11px; color: var(--encre-3);
}
.lieu-flux.ajout button:hover, .jour-flux.ajout-jour button:hover,
.coin-flux .date-montage:hover { color: var(--encre); text-decoration: underline; }
.coin-flux { display: flex; align-items: center; padding: 6px 10px; }
.jour-flux.ajout-jour { border-bottom: 0; }
.jour-flux.ajout-jour .etiquette-jour { background: none; }

/* Plusieurs véhicules le même jour : une ligne par véhicule, dans l'ordre où
   leurs chargements se lisent à gauche. Une seule route pour tout le jour
   était la réunion de leurs arrêts : elle montrait un camion passant par des
   endroits où il n'allait pas.
   La bande des routes est un étage à part, pas le haut de la première case, et
   un filet la sépare des produits sur toute la largeur : sans lui, elle
   flottait au-dessus des articles et l'on cherchait à quoi elle se rattachait.
   Sa hauteur ne se calcule plus : elle tient dans le flux du tableau, ce qui
   évite au passage la marge intérieure qu'un calcul invalide remettait à zéro
   sur les rangées sans route. */
.charges-du-jour { display: grid; gap: 2px; margin-top: 4px; }
.une-charge {
  font-size: 10px; color: var(--encre-3); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.une-charge b { font-variant-numeric: tabular-nums; color: var(--encre-2); }
.une-charge.deborde, .une-charge.deborde b { color: var(--refus); }
.choix-vehicule .dedans { max-width: 460px; }

/* Un lieu se renomme là où on le lit, et se retire au même endroit. Rangé dans
   un dialogue, on ne l'y cherche pas : on regarde la colonne mal nommée et on
   se demande où aller. */
.entete-flux > .lieu-flux.sien { display: flex; align-items: baseline; gap: 6px; }
.lieu-flux [contenteditable] { outline: none; border-radius: 3px; min-width: 3ch; }
.lieu-flux [contenteditable]:hover { background: var(--surface-2); }
.lieu-flux [contenteditable]:focus { background: var(--surface-2); box-shadow: 0 0 0 1px var(--filet); }
.lieu-flux .retirer-lieu {
  border: 0; background: none; padding: 0 2px; cursor: pointer; margin-left: auto;
  color: var(--encre-3); font-size: 11px; opacity: 0; transition: opacity .12s;
}
.lieu-flux.sien:hover .retirer-lieu, .lieu-flux .retirer-lieu:focus-visible { opacity: 1; }
.lieu-flux .retirer-lieu:hover:not(:disabled) { color: var(--refus); }
.lieu-flux .retirer-lieu:disabled { cursor: not-allowed; }
@media (hover: none) { .lieu-flux .retirer-lieu { opacity: 1; } }

/* CE QUI SE VISE AU DOIGT FAIT 24 PIXELS, MÊME QUAND ÇA N'EN MONTRE QUE DOUZE.
   Ces commandes sont dessinées petites à dessein : elles ne doivent pas peser
   dans une case déjà pleine. Mais l'écran logistique se consulte sur un
   chantier, au doigt, et une croix de douze pixels se rate une fois sur trois.
   La cible s'agrandit sans que l'encre ne bouge, et chacune de celles-ci a de
   l'air autour d'elle : rien ne se recouvre. */
.lieu-flux .retirer-lieu, .ouvrir-le-lieu, .pli-jour, button.marquer-jour { position: relative; }
.lieu-flux .retirer-lieu::after, .ouvrir-le-lieu::after,
.pli-jour::after, button.marquer-jour::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 24px; height: 24px; transform: translate(-50%, -50%);
}

/* Le trajet d'un véhicule. Le dessin d'ensemble répond à « où est chaque
   chose » ; celui-ci répond à « qu'est-ce que j'ai dans ce camion », qui est la
   question qu'on se pose le matin, la porte ouverte, avant de charger. */
.trajet-moyen { margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--filet-doux); }
.jour-trajet {
  display: grid; grid-template-columns: 130px 1fr; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--filet-doux);
}
.jour-trajet:last-child { border-bottom: 0; }
.jour-trajet .quand b { display: block; font-size: 12.5px; }
.jour-trajet .quand span { font-size: 11px; color: var(--encre-3); line-height: 1.35; }
.quoi-trajet { display: grid; gap: 7px; font-size: 11.5px; }
.quoi-trajet .mouvement em { font-style: normal; color: var(--encre-3); }
.trajet-vide { margin-top: 10px; }

/* La feuille de route : d'où il part, ses arrêts dans l'ordre des heures, où
   il passe la nuit. Les deux bouts de journée s'écrivent en retrait de la
   colonne des heures, parce qu'ils ne sont pas des arrêts. */
.bout-de-journee { font-size: 11px; color: var(--encre-3); }
.bout-de-journee b { color: var(--encre-2); font-weight: 600; }
.un-arret { display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 8px; align-items: start; }
.quoi-arret > b { display: block; font-size: 11.5px; margin-bottom: 3px; }
.quoi-arret .groupe-case + .groupe-case { margin-top: 4px; }
input.heure-arret, input.heure-arrivee {
  width: 46px; border: 0; border-bottom: 1px dotted var(--filet); background: none;
  font: inherit; font-size: 11px; color: var(--encre-2); padding: 0 0 1px;
  font-variant-numeric: tabular-nums; text-align: right;
}
input.heure-arret:focus, input.heure-arrivee:focus {
  outline: none; border-bottom-color: var(--accent);
}
input.conducteur-jour {
  width: 100%; border: 0; border-bottom: 1px dotted var(--filet); background: none;
  font: inherit; font-size: 11px; color: var(--encre-2); padding: 0 0 1px; margin-top: 2px;
}
input.conducteur-jour:focus { outline: none; border-bottom-color: var(--accent); }
select.nuit-jour {
  border: 0; background: none; font: inherit; font-size: 11px; color: var(--encre-2);
  padding: 0 2px; cursor: pointer; max-width: 100%;
}
/* L'heure d'un mouvement, dans le dessin d'ensemble. Elle ne s'affiche que si
   quelqu'un l'a donnée : une heure inventée se planifie comme une heure vraie. */
/* Pourquoi une chose s'arrête là. Une halte de transbordement se supprime si
   l'on trouve un camion direct ; une halte d'assemblage se planifie. Sans le
   motif, les deux se ressemblent trait pour trait. */
.motif-halte {
  font-size: 10px; color: var(--attente-encre); background: var(--attente-fond);
  border-radius: var(--rond); padding: 1px 6px; white-space: nowrap;
}
.heure-mouvement {
  font-size: 10px; color: var(--encre-3); margin-right: 4px;
  font-variant-numeric: tabular-nums;
}
/* Chaque anomalie ouvre sa fiche : la lire sans pouvoir y aller, c'est devoir
   la retrouver à la main dans vingt-cinq fiches, et l'on renonce. */
.anomalies-flux li { cursor: pointer; }
.anomalies-flux li:hover { text-decoration: underline; }
@media (max-width: 720px) { .jour-trajet { grid-template-columns: 1fr; gap: 4px; } }

/* ------------------------------------------------- ce qui se passe ici
   La porte du lieu. Elle ne parait qu'au survol de la case : une case de
   flux montre deja ce qui arrive, ce qui part et ce qui reste, et un bouton
   permanent de plus dans chacune des soixante cases du tableau ferait
   soixante boutons a ignorer. */
.jour-flux .cellule { position: relative; }
.ouvrir-le-lieu {
  position: absolute; top: 3px; right: 4px; z-index: 2;
  border: 0; background: var(--surface); color: var(--encre-3);
  border-radius: var(--rayon-petit); cursor: pointer;
  width: 18px; height: 18px; padding: 0; line-height: 1;
  font-size: 12px; opacity: 0; transition: opacity .12s;
}
.jour-flux .cellule:hover .ouvrir-le-lieu { opacity: 1; }
.ouvrir-le-lieu:hover { background: var(--accent-doux); color: var(--accent-encre); }
.ouvrir-le-lieu:focus-visible { opacity: 1; outline: 2px solid var(--accent); }

.comparaison.ce-qui-se-passe .dedans { max-width: 560px; }
.liste-membres.ici { max-height: 46vh; gap: 1px; }
/* DISSOUDRE ICI : une ligne par membre, et à droite ce qu'il devient. La liste
   peut compter vingt objets ; c'est elle qui défile, pas la boîte, sinon les
   deux boutons du bas sortent de l'écran au moment de valider. */
/* CE QU'IL DEVIENT, une fois qu'on a dit qu'il se sépare. La suite ne s'ouvre
   qu'après la réponse : posée d'emblée, elle faisait lire trois questions là
   où il n'y en a qu'une, et la première décide des deux autres. */
.apres-separation {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--filet-doux);
}
.apres-separation .champ-question { display: block; margin-bottom: 10px; }
.apres-separation .titre-suivent { margin: 12px 0 6px; }
.apres-separation .liste-membres { max-height: 34vh; }
.apres-separation .ligne-membre { cursor: pointer; padding: 6px 9px; }
.apres-separation .ligne-membre:hover { background: var(--accent-doux); }
.apres-separation .liste-membres + .rien { margin-top: 8px; }
.dissoudre-ici .reformer { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.dissoudre-ici .avec-bouton { display: flex; gap: 6px; margin-top: 4px; }
.dissoudre-ici .avec-bouton input { flex: 1; min-width: 0; margin-top: 0; }
.dissoudre-ici .liste-membres { max-height: 42vh; margin-top: 14px; }
.dissoudre-ici .ligne-membre { padding: 3px 4px 3px 9px; }
.dissoudre-ici .ligne-membre select {
  flex: 0 1 auto; max-width: 52%; margin: 0; padding: 4px 6px;
  font: inherit; font-size: 11.5px; color: var(--encre);
  border: 1px solid var(--filet); border-radius: var(--rayon-petit); background: var(--surface);
}
/* Toute la ligne est la cible : cocher une case de treize pixels a la souris
   est un geste de precision, et c'est le geste le plus repete de cet ecran. */
.ligne-membre.case-ici { cursor: pointer; padding: 7px 9px; gap: 10px; }
.ligne-membre.case-ici:hover { background: var(--accent-doux); }
.ligne-membre.case-ici:has(input:checked) {
  background: var(--accent-doux); box-shadow: inset 2px 0 0 var(--accent);
}
.ligne-membre.case-ici input { flex: 0 0 auto; accent-color: var(--accent); margin: 0; }
.quoi-ici { flex: 1; min-width: 0; }
.quoi-ici b { font-variant-numeric: tabular-nums; }
/* L'etat se dit sous le nom, en gris : « dans tel groupe, repart au dépôt ».
   Sur la meme ligne, il entrait en concurrence avec le nom de l'objet, qui
   est ce qu'on vient lire. */
.quoi-ici .rien { display: block; font-size: 11px; margin: 1px 0 0; }
/* Les verbes n'apparaissent qu'avec une selection : sans rien de coche, ils
   ne pourraient rien faire, et cinq boutons gris disent surtout qu'on n'a
   pas compris quoi faire. */
.verbes-ici {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--filet-doux);
}
.verbes-ici b { font-size: 12px; color: var(--encre-2); margin-right: 4px; }
.verbes-ici button {
  border: 1px solid var(--filet); background: var(--surface); color: var(--encre);
  border-radius: var(--rayon-petit); padding: 5px 10px; font: inherit; font-size: 12px;
  cursor: pointer;
}
.verbes-ici button:hover { border-color: var(--encre-3); }
.verbes-ici button.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.verbes-ici button.veille { color: var(--encre-3); }
/* Le seul verbe qui ôte. Il se lit en dernier, poussé au bout de la ligne, et
   sa couleur dit ce qu'il fait avant qu'on le clique. */
.verbes-ici button.a-part { margin-left: auto; color: var(--refus); }
.verbes-ici button.a-part:hover { border-color: var(--refus); }
.comparaison.petit-verbe .dedans { max-width: 420px; }

/* DEUX RÉPONSES CÔTE À CÔTE, chacune avec ce qu'elle fait. Empilées plutôt
   qu'alignées : la phrase qui explique tient sur trois lignes, et deux
   colonnes de trois lignes ne se comparent plus, elles se lisent en zigzag. */
.comparaison.deux-reponses .dedans { max-width: 460px; }
.comparaison.deux-reponses .pieces-choisissables { flex-direction: column; }
.comparaison.deux-reponses .piece-choisissable {
  width: 100%; text-align: left; padding: 12px 14px; font-weight: 500;
}
.comparaison.deux-reponses .piece-choisissable .rien {
  display: block; margin-top: 3px; font-weight: 400; font-size: 12.5px;
}
/* La précision d'une case à cocher se colle à elle, et se sépare de ce qui
   suit : sans cet air, les deux paragraphes se lisaient comme un seul. */
.comparaison.petit-verbe .case { margin: 10px 0 2px; }
.comparaison.petit-verbe .legende-repere { margin: 0 0 14px; }

/* ------------------------------------------------------ le chemin d'accès
   Un passage se décrit d'une ligne : sa sorte, son nom, ses cotes. Un
   formulaire par passage aurait fait quatre écrans pour ce qui tient en
   trois minutes de mètre ruban. */
.passages { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.un-passage {
  display: flex; flex-direction: column; gap: 6px; width: 100%;
  padding: 8px 10px; border-radius: var(--rayon-petit); background: var(--surface-2);
}
.quel-passage { display: flex; align-items: center; gap: 8px; }
.un-passage select { flex: 0 0 auto; max-width: 200px; }
.un-passage .nom-passage { flex: 1 1 auto; min-width: 0; }
/* Sans une seule cote, un passage ne vérifie rien : il ne doit pas ressembler
   à un contrôle déjà fait. */
.un-passage.sans-cote { background: var(--attente-fond); }
.cotes-passage { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.cote-passage { display: flex; align-items: center; gap: 4px; font-size: 11px; color: var(--encre-3); }
.cote-passage input { width: 54px; text-align: right; font-variant-numeric: tabular-nums; }
.cote-passage .unite { font-style: normal; color: var(--encre-3); }
.cotes-passage .rien { font-size: 11px; }
.retirer-passage {
  border: 0; background: none; cursor: pointer; color: var(--encre-3);
  font-size: 16px; line-height: 1; padding: 0 2px; flex: 0 0 auto;
}
.retirer-passage:hover { color: var(--refus); }

/* Un verdict se lit comme une phrase, jamais comme une capsule : les capsules
   de cet atelier sont en petites capitales, faites pour « REÇU », et une
   mesure entière y hurlait. */
.verdicts { display: flex; flex-direction: column; }
/* La raison se range SOUS le nom, jamais à l'autre bout de la ligne. Alignée
   à droite dans un écran large, elle flottait à neuf cents pixels de
   l'article dont elle parle, et l'œil ne les rapprochait plus. */
.un-verdict {
  display: block; padding: 5px 7px; border-radius: var(--rayon-petit);
  cursor: pointer; font-size: 12.5px;
}
.un-verdict:hover { background: var(--papier); }
.un-verdict .quoi { display: block; }
.un-verdict .pourquoi { display: block; font-size: 11.5px; color: var(--encre-3); }
.un-verdict.bloque .pourquoi { color: var(--refus); }
.un-verdict .pourquoi b { font-weight: 600; }

/* Une commande qui n'est pas passée mais dont des articles se disent déjà
   commandés. La contradiction se DIT : elle se lisait comme un statut, à la
   place de celui de la commande, et l'on ne savait plus laquelle croire. */
.se-contredit { font-size: 11.5px; color: var(--attente); }

/* ------------------------------------------------------- le plan de route
   Ce qu'on ignore se demande là où ça manque. Le temps de trajet entre deux
   lieux ne se devine pas : le calculer demanderait d'envoyer les adresses
   des chantiers à un service de cartographie, et l'inventer rendrait un
   horaire faux, qu'on suit jusqu'au premier retard. */
.trajets-inconnus {
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
  margin: 8px 0 4px; padding: 8px 10px; border-radius: var(--rayon-petit);
  background: var(--attente-fond);
}
.trajets-inconnus label { display: flex; align-items: center; gap: 5px; font-size: 11.5px; }
.trajets-inconnus input { width: 46px; text-align: right; font-variant-numeric: tabular-nums; }
.trajets-inconnus .unite { font-style: normal; color: var(--encre-3); font-size: 11px; }
.trajets-inconnus .rien { flex: 1 1 100%; font-size: 11px; }
/* Une obligation qu'on ne peut plus tenir se dit avec le retard EXACT :
   « ça ne passe pas » ne se corrige pas, « il manque vingt minutes » si. */
.heures-intenables {
  display: flex; flex-direction: column; gap: 2px; margin: 6px 0 4px;
  font-size: 11.5px; color: var(--refus);
}
.attente-arret { margin-left: 6px; font-size: 11px; }
/* Les deux heures d'un arrêt. Celle de l'arrivée est le rendez-vous, celle du
   départ est l'heure à laquelle on repart. Les deux bouts d'une même étape
   portaient le même champ, et les deux écrivaient la même valeur. Un arrêt
   qui ne fait qu'une des deux choses n'a qu'un champ, sans intitulé : la
   colonne dit déjà que c'est une heure. */
.heures-arret { display: flex; flex-direction: column; gap: 2px; }
.une-heure { display: block; }
.une-heure > span { display: none; }
.une-heure.nommee > span {
  display: block; font-size: 9px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--encre-3); text-align: right; line-height: 1.3;
}
.bout-de-journee .heure-depart {
  width: 56px; text-align: center; font-variant-numeric: tabular-nums;
}
.bout-de-journee .rien { margin-left: 8px; font-size: 11px; }

/* Le parcours, sorti du tiroir. C'est la même chaîne que dans la fiche, en
   plus large, et il porte plusieurs objets à la fois. */
/* Un titre de sous-section dans une boîte. La classe était posée depuis
   longtemps sans qu'aucune règle ne la suive : le titre s'affichait au style
   par défaut du navigateur, en gras et trop gros, au milieu d'une boîte qui
   ne parle qu'en 12,5 pixels. */
.comparaison .titre-sous-section {
  margin: 20px 0 4px; padding-top: 14px; border-top: 1px solid var(--filet-doux);
  font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .07em; color: var(--encre-3);
}

/* ---------------------------------------------- le groupe, sur une ligne
   Le tableau porte le nom du groupe UNE fois, sur la bulle qui entoure ses
   lignes ; la road map met ces mêmes lignes à plat, et chacune doit alors le
   dire elle-même. La pastille reprend la teinte de la bulle et de la légende :
   c'est le même groupe, et on le reconnaît avant d'avoir lu le mot. Un objet
   peut en porter deux, un sous-groupe et son parent : elles se rangent côte à
   côte plutôt que de s'empiler sous le nom. */
/* Les pastilles restent EN LIGNE, et non en boîtes côte à côte : dans une
   colonne étroite, une boîte trop longue prend toute la largeur et son nom se
   coupe au milieu d'un pavé de couleur. En ligne, le nom se coupe entre deux
   mots et la pastille se poursuit d'une ligne à l'autre, arrondie au début et
   à la fin comme une seule étiquette. */
.grp-rm {
  font-size: 9.5px; color: var(--encre-2); margin-left: 6px;
  background: var(--surface-2); border-radius: var(--rond); padding: 0 6px;
}
.nom-grp { white-space: nowrap; }
.grp-rm.teinte {
  background: hsl(var(--h-groupe) 40% 94%); color: hsl(var(--h-groupe) 40% 26%);
}

/* CE QUI COMPOSE UNE CONSTRUCTION. Des jetons, pas une liste : chacun mène à
   sa fiche, et l'on en compte quatre d'un coup d'œil là où quatre lignes
   demandent de les lire. */
.liste-composants { display: flex; flex-wrap: wrap; gap: 5px; margin: 2px 0 4px; }
.un-composant {
  border: 1px solid var(--filet); background: var(--surface); border-radius: var(--rond);
  padding: 3px 10px; font: inherit; font-size: 12px; color: var(--encre-2); cursor: pointer;
  text-align: left; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.un-composant:hover { border-color: var(--encre-3); color: var(--encre); }

/* LA MODALE DU GROUPE : son nom, sa route, qui la suit.
   Le titre EST le champ du nom : un intitulé suivi d'un champ contenant le
   même mot demandait de lire deux fois la même chose. */
.un-groupe-ouvert .dedans { max-width: 640px; }
.titre-modifiable {
  display: block; width: 100%; margin: 0 0 4px; padding: 0;
  border: 0; border-bottom: 1px solid transparent; background: none;
  font: inherit; font-size: 19px; font-weight: 600; color: var(--encre);
}
.titre-modifiable:hover { border-bottom-color: var(--filet); }
.titre-modifiable:focus { outline: none; border-bottom-color: var(--accent); }
/* Une étape par ligne : le quand, le où, et qui la fait. Elle se lit, elle ne
   s'édite pas : la route appartient aux objets, pas au groupe, et c'est le
   tableau qui l'écrit. Les colonnes fixes alignent les jours entre eux, et
   c'est cet alignement qui rend la route lisible d'un coup. */
.route-groupe {
  display: grid; gap: 5px; margin: 8px 0 6px; padding: 0; list-style: none;
}
.etape-groupe {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline; gap: 4px 12px; font-size: 12.5px;
}
.quand-groupe {
  color: var(--encre-3); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ou-groupe { color: var(--encre); }
/* Qui fait ce pas : muet quand c'est tout le monde, nominatif dès qu'une
   partie du groupe s'en écarte. Sans couleur d'alerte : partir séparément est
   le cas ordinaire d'un groupe, ce sont les noms qui le disent, et une teinte
   d'attente sur chaque ligne aurait crié sur une route normale. */
.equipe-groupe { color: var(--encre-3); font-size: 11.5px; text-align: right; }
@media (max-width: 560px) {
  .etape-groupe { grid-template-columns: auto minmax(0, 1fr); }
  .etape-groupe .equipe-groupe { grid-column: 1 / -1; text-align: left; }
}
/* TOUS LES RENDEZ-VOUS, ET QUI LES VISE. Un bloc par rendez-vous, séparé du
   suivant par un filet et non par un cadre : ce sont des sections d'une même
   liste, pas des objets posés côte à côte. */
.les-objectifs .dedans { max-width: 620px; }
.un-objectif { padding: 14px 0; border-top: 1px solid var(--filet-doux); }
.un-objectif:first-of-type { border-top: 0; }
.tete-objectif {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px;
}
.tete-objectif b { font-size: 13px; }
/* La teinte du rendez-vous, la même que dans le tableau et la légende : on le
   reconnaît avant d'avoir lu le lieu. */
.un-objectif .tete-objectif b::before {
  content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 7px; background: hsl(var(--h-groupe, 0) 45% 55%);
}
.tete-objectif .lien-discret { margin-left: auto; }
.tete-objectif .lien-discret + .lien-discret { margin-left: 0; }
.marques-obj { border-left: 2px solid var(--accent); padding-left: 10px; }

/* L'OBJECTIF : le lieu où les éléments doivent finir par se retrouver. Il ne
   décide rien du chemin, et le compte à côté dit où l'on en est. */
.objectif-rm {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 6px 0 2px; font-size: 12px;
}
.objectif-rm label { display: inline-flex; align-items: baseline; gap: 6px; }
.ligne-membre .grp-sortir {
  border: 0; background: none; color: var(--encre-3); cursor: pointer;
  font-size: 13px; padding: 2px 4px;
}
.ligne-membre .grp-sortir:hover { color: var(--refus); }
/* Une liste où l'on coche : la case et le nom font une seule cible. */
.liste-membres.cochable .ligne-membre { cursor: pointer; gap: 8px; }
.liste-membres.cochable input { flex: none; }
.actions-groupe { flex-wrap: wrap; }

/* ------------------------------------------- des éléments restés sans style
   Ces classes étaient posées seules sur leur élément, sans une règle dans la
   feuille : ces éléments s'affichaient donc au style par défaut du
   navigateur, au milieu d'écrans qui parlent en 12,5 pixels. Rien n'était
   cassé, c'était simplement laid, et aucun contrôle ne le disait. */

/* La zone où l'on dépose une facture. Un <label> sans règle est en ligne :
   la phrase « Déposez la facture ici » se lisait comme du texte courant, et
   rien ne montrait qu'on pouvait y jeter un fichier. */
.depot-pdf {
  display: block; padding: 18px 14px; margin-bottom: 10px; text-align: center;
  border: 1px dashed var(--filet); border-radius: var(--rayon); cursor: pointer;
  background: var(--surface-2);
}
.depot-pdf:hover { border-color: var(--accent); background: var(--accent-doux); }
.depot-pdf b { display: block; font-size: 13px; }
.depot-pdf span { display: block; font-size: 11.5px; color: var(--encre-3); margin-top: 2px; }

/* Qui achète quoi : une colonne de listes, chacune avec son en-tête. */
.qui-achete { display: flex; flex-direction: column; gap: 14px; }
.une-liste { display: flex; flex-direction: column; gap: 2px; }
.une-liste .rien { margin: 0; }
.tete-liste { display: flex; align-items: baseline; gap: 8px; }

/* Les lieux du projet, un par ligne. */
.liste-lieux { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }

/* Qui conduit, sous le numéro du jour. */
.qui-conduit { display: block; }

/* Lier une valeur de critère à celles d'un autre : un rang par parent. */
.rang-attache { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.nom-parent { font-size: 11px; color: var(--encre-3); flex: 0 0 auto; }

/* « Tout remettre au départ » n'est pas une façon de lire le tableau : il se
   pose à droite, loin des trois boutons qui changent le regroupement, pour
   qu'on ne le prenne pas pour l'un d'eux. */
/* PHOTO OU MOT. Une façon de lire la case, comme le regroupement à côté :
   elle se pose donc dans la même barre, et se distingue par sa forme de
   bascule plutôt que par une place à part. */
.voir-photos {
  margin-left: 14px; border: 1px solid var(--filet); background: var(--surface);
  border-radius: var(--rond); padding: 3px 11px; font: inherit; font-size: 11.5px;
  color: var(--encre-3); cursor: pointer;
}
.voir-photos:hover { color: var(--encre); }
.voir-photos[aria-pressed="true"] {
  background: var(--surface-2); border-color: var(--filet); color: var(--encre);
}
.regrouper-flux .tout-au-depart { margin-left: auto; }

/* LA PHOTO PLUTÔT QUE LE NOM.
   « Console cannage, chêne » et « Console cannage, noyer » se distinguent à la
   lecture, pas au coup d'œil, et une case de quinze lignes de texte se
   déchiffre au lieu de se voir. La vignette REMPLACE le mot, elle ne s'ajoute
   pas à lui : une colonne de quatre-vingts pixels ne tient pas les deux. Le
   nom reste dans le document, et l'infobulle le redit. */
.vignette-flux {
  position: relative; display: block; flex: none;
  width: 38px; height: 38px; border-radius: 6px; overflow: hidden;
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--filet-doux);
}
.vignette-flux img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Combien on en bouge, sur la vignette : le nombre est la seule chose du mot
   qu'une image ne peut pas dire. */
/* En HAUT à droite : le bas droit appartient à la coche « c'est reçu », et
   deux pastilles au même coin s'avalent l'une l'autre. */
.combien-vignette {
  position: absolute; right: 0; top: 0;
  min-width: 15px; padding: 0 3px; border-radius: 0 6px 0 6px;
  background: rgba(27, 27, 25, .72); color: #fff;
  font-size: 10px; font-weight: 600; line-height: 15px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.carte-flux.en-photos .mot-flux { display: none; }
/* Les vignettes se rangent en grille dans leur case ; les titres et les
   déplis gardent leur ligne entière. */
.carte-flux.en-photos .groupe-case,
.carte-flux.en-photos .paquet-case,
.carte-flux.en-photos .reste-case .present {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 5px;
}
.carte-flux.en-photos .tete-case,
.carte-flux.en-photos .nom-paquet,
.carte-flux.en-photos .quoi-livraison,
.carte-flux.en-photos .suite-case,
.carte-flux.en-photos .par-vehicule { flex: 0 0 100%; }
.carte-flux.en-photos .objet-flux {
  display: flex; padding: 0; margin: 0; border-radius: 6px;
  border-bottom: 0;
}
.carte-flux.en-photos .objet-flux:hover { background: none; }
.carte-flux.en-photos .objet-flux:hover .vignette-flux {
  box-shadow: inset 0 0 0 1px var(--encre-3);
}
/* Marqué, en attente, dans un groupe : ce que le fond disait sur du texte, un
   anneau le dit sur une image, qui n'a pas de fond à teinter. */
.carte-flux.en-photos .objet-flux.pris .vignette-flux {
  box-shadow: 0 0 0 2px var(--accent);
}
.carte-flux.en-photos .objet-flux.a-dire .vignette-flux,
.carte-flux.en-photos .objet-flux.a-preciser .vignette-flux {
  box-shadow: 0 0 0 2px var(--attente);
}
.carte-flux.en-photos .objet-flux.dans-un-groupe .vignette-flux {
  box-shadow: 0 0 0 2px hsl(var(--h-groupe) 40% 62%);
}
.carte-flux.en-photos .objet-flux.dans-un-groupe.pris .vignette-flux {
  box-shadow: 0 0 0 2px var(--accent);
}
/* Le véhicule reste dit : ce n'est pas le nom de l'objet, c'est la réponse à
   « dans lequel ». Il passe SOUS la vignette plutôt qu'à côté, sinon une tuile
   de trente-huit pixels traîne une étiquette de cent. */
.carte-flux.en-photos .objet-flux { flex-direction: column; align-items: flex-start; gap: 2px; }
.carte-flux.en-photos .par-quoi { max-width: 38px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 9.5px; padding: 0 3px; }
/* Dans la ligne des livraisons, la coche reste : elle n'est pas un mot, c'est
   un geste. Elle se pose AU COIN de la vignette, en surimpression, pour ne pas
   pousser la tuile suivante. */
.carte-flux.en-photos .present-depart .objet-flux { position: relative; }
.carte-flux.en-photos .present-depart .coche-recue {
  position: absolute; right: -7px; bottom: -7px; margin: 0; z-index: 2;
  grid-column: auto; grid-row: auto;
}
/* Posée sur une photo, elle a besoin de son propre fond : un anneau vide sur
   une image se perd dans ce qu'il y a derrière. */
.carte-flux.en-photos .present-depart .coche-recue::before {
  background: var(--surface); box-shadow: 0 0 0 1.5px var(--surface);
}
.carte-flux.en-photos .present-depart .coche-recue.recue::before {
  background: hsl(147 40% 93%);
}
/* Le retard se dit par un anneau : « En retard » écrit sous une tuile de
   trente-huit pixels prendrait trois lignes. L'infobulle porte la date. */
.carte-flux.en-photos .tag-retard { display: none; }
.carte-flux.en-photos .objet-flux:has(.tag-retard) .vignette-flux {
  box-shadow: 0 0 0 2px var(--refus);
}
/* Une image n'a pas de fond à teindre : ce que l'ambre disait sur du texte,
   l'anneau le dit sur la tuile, et le fond se retire. */
.carte-flux.en-photos .objet-flux.a-dire,
.carte-flux.en-photos .objet-flux.a-preciser,
.carte-flux.en-photos .objet-flux.pris { background: none; }


/* LIEU DE LIVRAISON : la ligne d'avant le montage. Ce n'est pas un jour, c'est l'état
   des lieux avant que rien ne bouge, et elle ne porte donc ni numéro ni date.
   Le dessin commençait au premier mouvement : on voyait des choses partir
   d'endroits qui n'existaient nulle part à l'écran. */
.jour-flux.au-depart { border-bottom: 1px solid var(--filet); }
.jour-flux.au-depart .etiquette-jour b { font-weight: 600; }
.groupe-case.present-depart .quoi-case { color: var(--encre-3); }
/* CE QU'ON ATTEND ENCORE, ET CE QUI EST DÉJÀ LÀ.
   La bulle mélangeait les deux : un lieu où dix articles se suivent ne dit
   rien tant qu'on ne sait pas lesquels sont arrivés, et c'est la seule
   question qu'on se pose devant elle. */
.quoi-livraison {
  display: flex; align-items: baseline; gap: 5px;
  margin: 9px 0 3px; font-size: 9.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .12em; color: var(--encre-3);
}
.quoi-livraison:first-of-type { margin-top: 2px; }
.quoi-livraison span { letter-spacing: 0; font-weight: 400; }
/* La ligne devient une grille : le nom d'abord, la coche au bout, et le retard
   DESSOUS plutôt que de disputer la largeur au nom. En rangée, une colonne
   étroite réduisait « Moquette aiguilletée » à trois lettres par ligne pour
   loger le tag à côté.
   La coche est à la FIN : posée devant, elle se lisait avant le nom, alors
   qu'on cherche l'article d'abord et qu'on le coche ensuite. */
/* La coche a SA colonne, large comme elle, et une vraie gouttière avant le
   nom : à un pixel près, l'anneau venait mordre la première lettre, et
   « Élévateur » se lisait « lévateur ». La cible déborde vers le haut et le
   bas, jamais sur les côtés. */
.present-depart .objet-flux {
  display: grid; grid-template-columns: 24px minmax(0, 1fr);
  column-gap: 16px; row-gap: 3px; align-items: start;
}
.quoi-recu { grid-column: 2; grid-row: 1; min-width: 0; overflow-wrap: anywhere; }
/* LA COCHE DIT UNE CHOSE ET UNE SEULE : C'EST ARRIVÉ.
   Un anneau vide tant qu'on attend, une pastille cochée une fois reçu.
   Vingt-deux pixels de cible pour dix pixels de dessin : on la touche du
   premier coup, elle ne pèse rien à l'œil. Elle se cale sur la PREMIÈRE ligne
   du nom, pas au milieu du bloc : centrée, elle tombait au milieu d'un nom de
   trois lignes, loin de ce qu'elle coche. */
.coche-recue {
  grid-column: 1; grid-row: 1; justify-self: start;
  position: relative; width: 24px; height: 24px; margin: -4px 0;
  border: 0; background: none; padding: 0; cursor: pointer;
}
/* Dix-huit pixels de rond, pas dix : le chevron débordait par le bas et la
   pastille se lisait comme une épingle de carte plutôt que comme une coche.
   À cette taille, la coche pèse ce que pèse le nom qu'elle accompagne, et sa
   cible fait vingt-quatre pixels : on la touche du premier coup. */
.coche-recue::before {
  content: ''; position: absolute; inset: 3px;
  border: 1.5px solid var(--filet); border-radius: 50%;
}
.coche-recue:hover::before { border-color: var(--encre-3); }
/* Reçu se dit en vert, mais au poids d'une bulle : une colonne de huit ronds
   pleins criait plus fort que les noms qu'elle accompagne. */
.coche-recue.recue::before { border-color: hsl(147 34% 76%); background: hsl(147 40% 93%); }
/* Le trait du chevron, dessiné plutôt qu'écrit : un caractère « ✓ » change de
   dessin d'une police à l'autre et se centre mal dans un rond de dix pixels. */
/* Le chevron tient DANS le rond, et son ENCRE se centre, pas sa boîte.
   Le trait n'occupe que le bord droit et le bord bas de sa boîte : une fois
   tournée de 45 degrés, la boîte est bien centrée mais l'encre tombe un pixel
   plus bas et un demi-pixel à gauche, et la coche paraît basse. Les deux
   décalages sont donc repris ici, mesurés sur le dessin, pas calculés sur la
   boîte. */
.coche-recue.recue::after {
  content: ''; position: absolute; left: 8.75px; top: 5.25px;
  width: 4.5px; height: 9px; border: solid var(--ok);
  border-width: 0 1.6px 1.6px 0; transform: rotate(45deg);
}
.coche-recue:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 50%; }
/* Reçu, l'article se range : il ne demande plus rien. */
.present-depart .objet-flux:has(.coche-recue.recue) .quoi-recu { color: var(--encre-2); }
/* EN RETARD : attendu, et le jour où on l'attendait est passé. Le mot est
   court et rouge parce qu'il appelle un coup de téléphone, pas une lecture. */
/* Le tag se range SOUS le nom, dans sa colonne : la gouttière de la coche lui
   sert de retrait, et il se lit comme une précision sur la ligne du dessus. */
.tag-retard {
  grid-column: 2; grid-row: 2; justify-self: start;
  font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  color: var(--refus); border: 1px solid currentColor; border-radius: var(--rond);
  padding: 0 5px; white-space: nowrap;
}
