/* Bobines — feuille de style unique */

:root {
  --fond: #eceff4;
  --carte: #ffffff;
  --texte: #1c2126;
  --gris: #6b7683;
  --bord: #dde2e8;
  --accent: #2563eb;
  --accent-doux: #eff4ff;
  --ok: #15803d;
  --alerte: #b45309;
  --danger: #b91c1c;
  --rayon: 8px;

  /* Ajoutés pour donner du relief : un accent plus soutenu pour le survol,
     une teinte de survol pour les lignes, et un anneau de focus visible. */
  --accent-fort: #1d4ed8;
  --survol: #eef3fb;
  --anneau: rgba(37, 99, 235, .38);
  --ok-doux: #ecfdf3;
  --alerte-doux: #fff7ed;
  --danger-doux: #fef2f2;

  /* Une chiffre se lit mieux en chasse fixe, et les colonnes s'alignent.
     C'est aussi la police d'un atelier plutôt que celle d'une brochure. */
  --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono",
          "Cascadia Mono", Menlo, Consolas, monospace;

  --ombre: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
  --ombre-levee: 0 4px 12px rgba(16, 24, 40, .08), 0 2px 4px rgba(16, 24, 40, .04);
}

/* Thème sombre, servi dans deux cas : le système le demande et l'utilisateur
   n'a pas dit le contraire, ou l'utilisateur l'a choisi explicitement.
   La liste est écrite deux fois plutôt qu'une : une variable CSS ne peut pas
   porter un bloc entier, et la duplication reste plus lisible qu'un montage
   d'héritages. Toute couleur ajoutée en clair doit l'être ici aussi. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="clair"]) {
    --fond: #0f1216;
    --carte: #1b1f25;
    --texte: #e6e9ed;
    --gris: #949ea9;
    --bord: #2c323a;
    --accent: #5b8dff;
    --accent-doux: #1e2635;
    --ok: #4ade80;
    --alerte: #fbbf24;
    --danger: #f87171;
    --ombre: 0 1px 2px rgba(0, 0, 0, .3);
    --ombre-levee: 0 4px 14px rgba(0, 0, 0, .38);
    --accent-fort: #7ba7ff;
    --survol: #232b37;
    --anneau: rgba(123, 167, 255, .45);
    --ok-doux: #12261b;
    --alerte-doux: #2a2113;
    --danger-doux: #2b1717;
  }
}

:root[data-theme="sombre"] {
  --fond: #0f1216;
  --carte: #1b1f25;
  --texte: #e6e9ed;
  --gris: #949ea9;
  --bord: #2c323a;
  --accent: #5b8dff;
  --accent-doux: #1e2635;
  --ok: #4ade80;
  --alerte: #fbbf24;
  --danger: #f87171;
  --ombre: 0 1px 2px rgba(0, 0, 0, .3);
  --ombre-levee: 0 4px 14px rgba(0, 0, 0, .38);
  --accent-fort: #7ba7ff;
  --survol: #232b37;
  --anneau: rgba(123, 167, 255, .45);
  --ok-doux: #12261b;
  --alerte-doux: #2a2113;
  --danger-doux: #2b1717;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--fond);
  color: var(--texte);
}

main { max-width: 1100px; margin: 0 auto; padding: 0 20px 60px; }

/* ---- En-tête --------------------------------------------------------
   Trois zones : l'identité, la navigation, les outils du compte. Elle est
   collante parce qu'un inventaire se parcourt en défilant longtemps : la
   recherche et les onglets doivent rester à portée sans remonter. */
.entete {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 20px;
  padding: 12px 20px;
  background: color-mix(in srgb, var(--fond) 88%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--bord);
}
/* Les navigateurs sans color-mix retombent sur un fond plein : mieux vaut
   perdre la transparence que voir le contenu défiler sous le texte. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .entete { background: var(--fond); }
}
.entete > * { min-width: 0; }

/* ---- Identité ---- */
.marque {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit; line-height: 1.1; flex: none;
}
.marque-logo { width: 40px; height: 40px; flex: none; }
.logo-flasque { fill: var(--accent-doux); stroke: var(--accent); stroke-width: 2.5; }
.logo-trou    { fill: var(--fond); }
.logo-noyau   { fill: none; stroke: var(--accent); stroke-width: 2.5; opacity: .55; }
.logo-axe     { fill: var(--accent); }
.marque:hover .logo-flasque { fill: var(--accent); }
.marque:hover .logo-trou    { fill: var(--carte); }

.marque-nom {
  display: block; font-size: 22px; font-weight: 700; letter-spacing: -0.025em;
}
.marque-nom::first-letter { color: var(--accent); }
.marque-domaine {
  display: block; font-size: 10.5px; color: var(--gris); letter-spacing: .04em;
}

/* ---- Onglets ---------------------------------------------------------
   L'onglet courant ne se distingue pas seulement par une teinte : il porte
   un fond plein et un trait sous le pied. Une nuance de bleu sur du gris
   se perd sur un écran d'atelier mal calibré, une barre non. */
.nav-principale { display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none; }
.nav-principale::-webkit-scrollbar { display: none; }

.nav-principale a {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px; border-radius: 7px;
  color: var(--gris); text-decoration: none; font-size: 14px; font-weight: 500;
  white-space: nowrap; transition: background .12s ease, color .12s ease;
}
.nav-principale svg { flex: none; opacity: .8; }
.nav-principale a:hover { background: var(--carte); color: var(--texte); }
.nav-principale a.actif {
  background: var(--accent-doux); color: var(--accent); font-weight: 650;
}
.nav-principale a.actif svg { opacity: 1; }
.nav-principale a.actif::after {
  content: ''; position: absolute; left: 13px; right: 13px; bottom: -13px;
  height: 2px; background: var(--accent); border-radius: 2px 2px 0 0;
}

/* ---- Recherche ---- */
.recherche { margin-bottom: 32px; }

.champ-recherche { display: flex; gap: 8px; }

.champ-recherche input {
  flex: 1; padding: 14px 16px; font-size: 17px;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
.champ-recherche input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-doux);
}

.champ-recherche button {
  padding: 0 18px; font-size: 14px; cursor: pointer;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  background: var(--carte); color: var(--texte);
}
.champ-recherche button:hover { border-color: var(--accent); color: var(--accent); }

.aide { font-size: 13px; color: var(--gris); margin: 10px 2px 0; }
.exemple {
  background: var(--carte); border: 1px solid var(--bord); color: var(--gris);
  border-radius: 20px; padding: 3px 10px; font-size: 12px; cursor: pointer;
  font-family: inherit;
}
.exemple:hover { border-color: var(--accent); color: var(--accent); }

/* ---- Interprétation de la requête ---- */
.interpretation { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.jeton {
  display: inline-flex; align-items: baseline; gap: 6px;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: 20px; padding: 4px 12px; font-size: 13px;
}
.jeton .type {
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gris);
}
.jeton.t-marque   { border-color: #7c3aed; }
.jeton.t-gamme    { border-color: var(--accent); }
.jeton.t-materiau { border-color: #0891b2; }
.jeton.t-couleur  { border-color: #059669; }
.jeton.t-diametre,
.jeton.t-poids    { border-color: #a16207; }
.jeton.t-libre    { border-style: dashed; color: var(--gris); }

/* ---- Résultats ---- */
.bloc-resultat { margin-top: 22px; }
.bloc-resultat h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gris); margin: 0 0 8px; font-weight: 600;
}

.carte {
  display: flex; align-items: center; gap: 14px;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 12px 14px; margin-bottom: 6px;
  text-decoration: none; color: inherit;
}
.carte:hover { border-color: var(--accent); }
.carte .principal { flex: 1; min-width: 0; }
.carte .principal b { display: block; }
.carte .meta { font-size: 13px; color: var(--gris); }
.carte .action {
  font-size: 13px; color: var(--accent); white-space: nowrap;
}

.message {
  padding: 12px 14px; border-radius: var(--rayon); font-size: 14px;
  background: var(--accent-doux); color: var(--accent); margin-top: 14px;
}
.message.avertissement { background: #fff7ed; color: var(--alerte); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="clair"]) .message.avertissement { background: #2a2113; }
}
:root[data-theme="sombre"] .message.avertissement { background: #2a2113; }

/* ---- Pastille couleur & jauge ---- */
/* La pastille est le seul repère visuel d une ligne de stock : on la lit
   avant le nom de la couleur. A 13 px elle ne se distinguait pas d une
   puce de liste — a 19 px la teinte est reellement identifiable. */
.pastille {
  display: inline-block; width: 25px; height: 25px; border-radius: 50%;
  background: var(--c); border: 2px solid rgb(128 128 128 / 64%);
  vertical-align: -4px; margin-right: 8px;
}
.pastille.grande { width: 38px; height: 38px; vertical-align: -11px; }

.jauge {
  display: block; height: 4px; border-radius: 2px; margin-top: 4px;
  background: var(--bord); overflow: hidden;
}
.jauge i { display: block; height: 100%; background: var(--ok); }

/* ---- Statistiques ---- */
.stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 24px 0; }
.stat {
  flex: 1; min-width: 130px; background: var(--carte);
  border: 1px solid var(--bord); border-radius: var(--rayon); padding: 14px;
}
.stat b {
  display: block; font-size: 24px; letter-spacing: -0.02em;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.stat span { font-size: 12px; color: var(--gris); }

/* ---- Encarts, tableaux ---- */
.encart {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 14px 16px; margin-bottom: 24px;
}
.encart h2 { font-size: 14px; margin: 0 0 10px; }
.inconnus { list-style: none; margin: 0; padding: 0; }
.inconnus li { display: flex; gap: 12px; align-items: center; padding: 4px 0; font-size: 14px; }

h2 { font-size: 16px; margin: 28px 0 12px; }

.tableau {
  width: 100%; border-collapse: collapse; background: var(--carte);
  border: 1px solid var(--bord); border-radius: var(--rayon); overflow: hidden;
}
.tableau th {
  text-align: left; font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; color: var(--gris); font-weight: 600;
  padding: 10px 12px; border-bottom: 1px solid var(--bord);
}
.tableau td { padding: 10px 12px; border-bottom: 1px solid var(--bord); font-size: 14px; }
.tableau tr:last-child td { border-bottom: 0; }

.etat {
  font-size: 11px; padding: 2px 8px; border-radius: 20px;
  border: 1px solid var(--bord); color: var(--gris);
}
.etat-en_cours { border-color: var(--ok); color: var(--ok); }
.etat-vide, .etat-rebut { opacity: .55; }

code { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 13px; }
.gris { color: var(--gris); }
.vide { color: var(--gris); padding: 20px 0; }
a { color: var(--accent); }

/* ---- Formulaire ---- */
.formulaire { background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 20px; margin-top: 18px; }
.formulaire h2:first-child { margin-top: 0; }
.grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; }
.groupe { display: flex; flex-direction: column; gap: 5px; }
.groupe label { font-size: 12px; color: var(--gris); font-weight: 600; }
.groupe input, .groupe select, .groupe textarea {
  padding: 9px 11px; font-size: 14px; font-family: inherit;
  border: 1px solid var(--bord); border-radius: 6px;
  background: var(--fond); color: var(--texte);
}
.groupe input:focus, .groupe select:focus, .groupe textarea:focus {
  outline: none; border-color: var(--accent);
}
.groupe .indice { font-size: 11px; color: var(--gris); }
.actions { display: flex; gap: 10px; margin-top: 22px; align-items: center; }
/* ---- Boutons -------------------------------------------------------
   Trois niveaux, et surtout des ÉTATS. Un bouton sans survol ni focus ne
   se distingue pas d'une étiquette : on ne sait pas qu'on peut cliquer,
   et une fois cliqué on ne sait pas que ça a été pris.

   Le secondaire était transparent avec du texte gris — donc invisible sur
   une carte blanche, qui est justement l'endroit où on le pose. Il a
   maintenant une vraie surface et la couleur du texte courant : discret ne
   veut pas dire effacé. */
.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 11px 20px; font-size: 15px; font-weight: 500; font-family: inherit;
  line-height: 1.2; cursor: pointer; text-decoration: none; white-space: nowrap;
  background: var(--accent); color: #fff; border: 1px solid transparent;
  border-radius: 7px; box-shadow: var(--ombre);
  transition: background-color .13s ease, border-color .13s ease,
              box-shadow .13s ease, transform .06s ease;
}
.bouton:hover { background: var(--accent-fort); box-shadow: var(--ombre-levee); }
/* Un enfoncement d'un pixel : le seul retour tactile qu'un écran sache donner. */
.bouton:active { transform: translateY(1px); box-shadow: var(--ombre); }

.bouton.secondaire {
  background: var(--carte); color: var(--texte); border-color: var(--bord);
}
.bouton.secondaire:hover {
  background: var(--survol); border-color: var(--accent); color: var(--accent);
}

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

.bouton[disabled], .bouton[aria-disabled="true"] {
  opacity: .55; cursor: not-allowed; box-shadow: none;
}
.bouton[disabled]:hover { background: var(--accent); }

/* Un champ actif se signale par un anneau plutôt que par un liseré : le
   contour seul se confond avec la bordure au repos, l'anneau non. Les liens
   et boutons gardent le contour, défini plus bas. */
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--anneau);
  outline: none;
}

#cam { width: 100%; max-width: 420px; margin-top: 14px; border-radius: var(--rayon); }

/* ---- Couleur et sa provenance -------------------------------------
   L'anneau autour de la pastille dit à quel point la couleur est sûre :
   plein = mesurée ou publiée par le fabricant, tireté = approximative,
   hachuré = inconnue. On ne présente jamais une teinte devinée comme un fait. */

.pastille { position: relative; }

.pastille[data-src="mesuree"],
.pastille[data-src="fabricant"] { box-shadow: 0 0 0 1px rgba(0,0,0,.28); }

.pastille[data-src="image"],
.pastille[data-src="deduite"]   { border-style: dashed; opacity: .9; }

.pastille[data-src=""],
.pastille:not([data-src]) {
  background-image: repeating-linear-gradient(45deg,
    rgba(128,128,128,.30) 0 3px, transparent 3px 6px);
}

.provenance {
  display: inline-block; font-size: 10px; line-height: 1.6;
  padding: 0 6px; border-radius: 20px; vertical-align: 1px;
  border: 1px solid var(--bord); color: var(--gris); white-space: nowrap;
}
.provenance.mesuree   { border-color: var(--ok);     color: var(--ok); }
.provenance.fabricant { border-color: var(--accent); color: var(--accent); }
.provenance.image,
.provenance.deduite   { border-style: dashed; }

/* ---- Nuancier d'une gamme ---- */
.nuancier {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 10px; margin-top: 14px;
}
.teinte {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); overflow: hidden; text-decoration: none; color: inherit;
}
.teinte:hover { border-color: var(--accent); }
.teinte .aplat {
  height: 54px; background: var(--c, #ccc);
  border-bottom: 1px solid var(--bord);
}
.teinte .aplat.inconnue {
  background-image: repeating-linear-gradient(45deg,
    rgba(128,128,128,.28) 0 5px, transparent 5px 10px);
}
.teinte .legende { padding: 7px 9px; }
.teinte .legende b { display: block; font-size: 12.5px; line-height: 1.25; }
.teinte .legende span { font-size: 10.5px; color: var(--gris); }

/* ---- Fin d'en-tête : langue, thème, compte -------------------------- */
.entete-fin {
  margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none;
}
.choix-langue select {
  font: inherit; font-size: 12px; font-weight: 600; padding: 7px 6px;
  background: var(--carte); color: var(--gris);
  border: 1px solid var(--bord); border-radius: 7px; cursor: pointer;
}
.choix-langue select:hover { color: var(--texte); border-color: var(--accent); }

/* Bouton carré à icône : thème, déconnexion. Ils ont l'air de boutons parce
   qu'ils en sont — un lien nu ne se distingue pas du texte alentour. */
.bouton-icone {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none; padding: 0; cursor: pointer;
  background: var(--carte); color: var(--gris);
  border: 1px solid var(--bord); border-radius: 7px;
  text-decoration: none; transition: color .12s ease, border-color .12s ease;
}
.bouton-icone:hover { color: var(--accent); border-color: var(--accent); }

/* Le bouton de thème ne montre que l'icône de l'état courant. */
.theme-icone { display: none; line-height: 0; }
#bascule-theme[data-theme-courant="auto"]   .theme-auto,
#bascule-theme[data-theme-courant="clair"]  .theme-clair,
#bascule-theme[data-theme-courant="sombre"] .theme-sombre { display: inline-flex; }

/* Identité : une pastille d'initiales, reconnaissable du coin de l'oeil, et
   le nom qui s'efface quand la place manque. */
.identite {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 3px 10px 3px 3px; border-radius: 20px;
  background: var(--carte); border: 1px solid var(--bord);
  text-decoration: none; color: var(--texte); font-size: 13px; font-weight: 500;
}
.identite:hover { border-color: var(--accent); color: var(--accent); }
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 27px; height: 27px; flex: none; border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
}
.identite-nom { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.bouton.petit { padding: 8px 15px; font-size: 14px; }

/* ---- En-tête sur petit écran ---------------------------------------
   L'identité et les outils tiennent sur une ligne, les onglets passent
   dessous et défilent horizontalement. Rien n'est masqué derrière un menu :
   quatre onglets se parcourent plus vite qu'ils ne se déplient. */
@media (max-width: 860px) {
  .entete { flex-wrap: wrap; gap: 10px 14px; padding: 10px 14px; }
  .nav-principale { order: 3; width: 100%; padding-bottom: 2px; }
  .nav-principale a.actif::after { bottom: -3px; }
  .entete-fin { margin-left: auto; }
  .identite-nom, .marque-domaine { display: none; }
  .identite { padding: 3px; }
}
@media (max-width: 420px) {
  .marque-nom { font-size: 18px; }
  .marque-logo { width: 34px; height: 34px; }
}

/* ---- Écrans de connexion ---- */
.panneau-auth {
  max-width: 400px; margin: 40px auto;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 26px;
}
.panneau-auth h2 { margin: 0 0 18px; font-size: 19px; }
.panneau-auth .groupe { margin-bottom: 14px; }
.panneau-auth .bouton { width: 100%; }
.separateur {
  display: flex; align-items: center; gap: 12px;
  margin: 20px 0; color: var(--gris); font-size: 12px;
}
.separateur::before, .separateur::after {
  content: ''; flex: 1; height: 1px; background: var(--bord);
}
.bouton-fournisseur {
  display: block; width: 100%; text-align: center; text-decoration: none;
  padding: 11px; margin-bottom: 8px; font-size: 14px;
  border: 1px solid var(--bord); border-radius: 6px;
  color: var(--texte); background: var(--fond);
}
.bouton-fournisseur:hover { border-color: var(--accent); color: var(--accent); }
.bas-panneau { margin-top: 18px; font-size: 13px; color: var(--gris); text-align: center; }
.badge-perso {
  font-size: 10px; padding: 1px 7px; border-radius: 20px;
  border: 1px solid #7c3aed; color: #7c3aed; vertical-align: 1px;
}

/* ---- Identité du site ---- */

/* ---- Boutons de connexion externe ---- */
.bouton-fournisseur {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-weight: 500;
}
.bouton-fournisseur svg { width: 18px; height: 18px; flex: none; }

/* Non configuré : le bouton reste visible pour montrer l'option, mais son
   inertie doit se lire immédiatement — logo désaturé et bordure en pointillés. */
.bouton-fournisseur.inerte {
  opacity: .5; cursor: not-allowed; border-style: dashed;
  background: transparent;
}
.bouton-fournisseur.inerte svg { filter: grayscale(1); }
.bouton-fournisseur.inerte:hover { border-color: var(--bord); color: var(--texte); }

/* ---- Présentation (visiteurs non connectés) -----------------------
   Même vocabulaire visuel que l'application : cartes claires, bordures
   discrètes, un seul accent. Une page d'accueil qui ne ressemblerait pas
   à l'outil qu'elle vend promettrait autre chose que ce qu'on livre. */

.presentation { padding-top: 8px; }

/* Bandeau en deux colonnes : l'argumentaire à gauche, la connexion à droite.
   Se connecter est le geste le plus fréquent de cette page — il mérite d'être
   le plus court, pas un lien vers une page de plus. */
.hero {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(300px, .85fr);
  gap: 48px; align-items: center; padding: 40px 0 12px;
}
.hero-texte { min-width: 0; }
.hero h1 {
  font-size: 42px; line-height: 1.1; letter-spacing: -0.03em;
  margin: 18px 0 0; max-width: 13em;
}
.hero-chapo {
  font-size: 17px; color: var(--gris); line-height: 1.6;
  max-width: 34em; margin: 18px 0 0;
}
.hero-note { font-size: 13px; color: var(--gris); margin-top: 18px; }
.hero-scene { justify-content: flex-start; margin-bottom: 0; }

/* Panneau de connexion du bandeau : même vocabulaire que la page dédiée, mais
   posé sur la page d'accueil. */
.panneau-connexion {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: 14px; padding: 24px; box-shadow: var(--ombre-levee);
}
.panneau-connexion h2 { margin: 0 0 18px; font-size: 17px; }
.panneau-connexion .groupe { margin-bottom: 14px; }
.panneau-connexion .bouton { width: 100%; margin-top: 4px; }
.panneau-connexion .separateur { margin: 18px 0 14px; }
.case {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; color: var(--gris); margin-bottom: 4px; cursor: pointer;
}
.case input { width: auto; }

@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; gap: 30px; padding-top: 26px; }
  .hero h1 { font-size: 34px; max-width: none; }
  .hero-chapo { max-width: none; }
}

.bouton.grand {
  display: inline-block; text-decoration: none;
  padding: 13px 26px; font-size: 15px; font-weight: 500;
}
a.bouton.grand { color: #fff; }
a.bouton.grand.secondaire { color: var(--texte); }

.section-titre {
  font-size: 22px; letter-spacing: -0.02em;
  margin: 56px 0 10px; text-align: center;
}
.section-chapo {
  font-size: 15px; color: var(--gris); line-height: 1.6;
  max-width: 46em; margin: 0 auto; text-align: center;
}

/* Matières : des étiquettes, pas des boutons — rien n'est cliquable ici. */
.puces {
  display: flex; flex-wrap: wrap; gap: 6px;
  justify-content: center; margin: 18px 0 0;
}
.puce {
  background: var(--carte); border: 1px solid var(--bord); color: var(--gris);
  border-radius: 20px; padding: 4px 12px; font-size: 12.5px;
}
.puce-suite { border-style: dashed; }

.forces {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px; margin-top: 22px;
}
.force {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 18px 20px;
}
.force h3 { font-size: 15px; margin: 0 0 8px; }
.force p { font-size: 14px; color: var(--gris); line-height: 1.6; margin: 0; }

/* Étapes numérotées : le compteur porte le numéro, pas le balisage. */
.etapes {
  list-style: none; counter-reset: etape;
  margin: 22px 0 0; padding: 0;
  display: grid; gap: 10px;
}
.etape {
  counter-increment: etape;
  display: grid; grid-template-columns: 34px 1fr; gap: 4px 14px;
  align-items: baseline;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 16px 18px;
}
.etape::before {
  content: counter(etape);
  grid-row: 1 / span 2;
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-doux); color: var(--accent);
  font-size: 14px; font-weight: 600;
}
.etape b { font-size: 15px; }
.etape span { font-size: 14px; color: var(--gris); line-height: 1.6; }

.faq { margin-top: 22px; }
.faq details {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 14px 18px; margin-bottom: 8px;
}
.faq summary {
  cursor: pointer; font-size: 15px; font-weight: 500;
  list-style-position: outside;
}
.faq summary::marker { color: var(--gris); }
.faq details[open] summary { margin-bottom: 8px; }
.faq p { font-size: 14px; color: var(--gris); line-height: 1.6; margin: 0; }

.appel {
  text-align: center; margin-top: 56px;
  background: var(--accent-doux); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 36px 24px;
}
.appel h2 { font-size: 22px; letter-spacing: -0.02em; margin: 0; }
.appel p {
  font-size: 15px; color: var(--gris); line-height: 1.6;
  max-width: 38em; margin: 12px auto 22px;
}

@media (max-width: 620px) {
  .hero { padding-top: 28px; }
  .hero h1 { font-size: 30px; }
  .hero-chapo { font-size: 16px; }
  .hero-actions .bouton.grand { flex: 1; text-align: center; }
  .section-titre { font-size: 20px; margin-top: 44px; }
}


/* ---- Abonnement ---------------------------------------------------
   Un lien déguisé en bouton doit se comporter comme un bouton : sans
   ces deux propriétés, le padding reste inline et le soulignement
   traverse le fond plein. */
a.bouton { display: inline-block; text-decoration: none; }

.offres { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 24px; }
.offre {
  flex: 1; min-width: 200px; background: var(--carte);
  border: 1px solid var(--bord); border-radius: var(--rayon); padding: 18px 20px;
}
.offre h3 { margin: 0; font-size: 14px; color: var(--gris); font-weight: 600; }
.offre-prix { margin: 8px 0 0; }
.offre-prix b { font-size: 28px; letter-spacing: -0.02em; }
.offre-prix span { font-size: 13px; color: var(--gris); margin-left: 4px; }
.offre .bouton { width: 100%; margin-top: 16px; }

/* La formule annuelle est mise en avant : c'est celle où la commission
   du prestataire pèse cinq fois moins, donc celle qui finance le site. */
.offre.reco { border-color: var(--accent); background: var(--accent-doux); }
.offre-argument {
  margin: 6px 0 0; font-size: 12px; font-weight: 600; color: var(--accent);
}

/* ====================================================================
   Identité d'atelier
   --------------------------------------------------------------------
   Le site s'adresse à des gens qui règlent des températures de buse au
   degré près. Les chiffres passent donc en chasse fixe et alignée : ils
   se comparent d'une ligne à l'autre, et l'outil ressemble à ce qu'il
   est. Le reste de la page garde la police du système.
   ==================================================================== */

code, .mono, .chiffre {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.chiffre { font-size: inherit; }

/* ---- Étiquette de section, façon commentaire de code ---------------
   Le « // » situe le ton sans rien enlever à la lisibilité : c'est un
   clin d'oeil, pas une décoration qui coûterait un mot au lecteur. */
.etiquette-section {
  display: block; text-align: center;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--gris);
  margin: 56px 0 6px;
}
.etiquette-section::before { content: '// '; opacity: .55; }
.etiquette-section + .section-titre { margin-top: 0; }

/* ---- La bobine du bandeau -----------------------------------------
   Dessinée en SVG plutôt qu'en image : elle suit le thème clair ou
   sombre, pèse trois lignes et reste nette à toutes les tailles.
   Le rotor tourne, le brin de filament se dévide. */

.hero-scene {
  display: flex; align-items: center; justify-content: center;
  gap: 22px; margin-bottom: 6px;
}
.bobine-svg { width: 148px; height: 148px; flex: none; overflow: visible; }

.bobine-rotor { transform-origin: 60px 60px; animation: bobine-tourne 9s linear infinite; }
@keyframes bobine-tourne { to { transform: rotate(360deg); } }

.bobine-flasque { fill: var(--carte); stroke: var(--bord); stroke-width: 2.5; }
.bobine-noyau   { fill: var(--accent-doux); stroke: var(--accent); stroke-width: 2; }
.bobine-spire   { fill: none; stroke: var(--accent); stroke-width: 2.4; opacity: .5; }
.bobine-spire:nth-of-type(even) { opacity: .8; }

/* Le brin qui sort de la bobine : un tireté qui défile donne le
   mouvement sans animer la géométrie du tracé. */
.bobine-brin {
  fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 9 7; animation: bobine-devide .8s linear infinite;
}
@keyframes bobine-devide { to { stroke-dashoffset: -16; } }

/* ---- Mosaïque des coloris réels ------------------------------------
   Ce ne sont pas des couleurs décoratives : elles sortent du catalogue.
   Annoncer 28 000 coloris et les montrer coûte le même espace, et la
   preuve vaut mieux que le chiffre seul. */
.mosaique {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
  gap: 3px; margin: 20px 0 4px;
  border-radius: var(--rayon); overflow: hidden;
}
.mosaique i {
  display: block; aspect-ratio: 1; background: var(--c);
  border-radius: 3px;
  animation: mosaique-apparait .5s both;
}
@keyframes mosaique-apparait { from { opacity: 0; transform: scale(.7); } }
.mosaique-legende {
  text-align: center; font-size: 12px; color: var(--gris);
  font-family: var(--mono);
}


/* ---- Cartes qui répondent au survol -------------------------------- */
.force, .etape, .stat { box-shadow: var(--ombre); }
.force { transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease; }
.force:hover {
  transform: translateY(-2px);
  box-shadow: var(--ombre-levee); border-color: var(--accent);
}

/* ---- Stock : lecture du restant ------------------------------------
   Trois seuils plutôt qu'une barre uniforme. Savoir qu'il reste 8 %
   n'a d'intérêt que si ça se voit sans lire le nombre. */
.jauge.basse i   { background: var(--alerte); }
.jauge.critique i { background: var(--danger); }
.restant-valeur { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.restant-pct { font-size: 11px; color: var(--gris); margin-left: 4px; }

tr.est-critique td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
tr.est-basse    td:first-child { box-shadow: inset 3px 0 0 var(--alerte); }

/* ---- Bandeau « à surveiller » --------------------------------------- */
.surveiller { display: grid; gap: 8px; margin-top: 6px; }
.surveiller a {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--rayon);
  background: var(--carte); border: 1px solid var(--bord);
  text-decoration: none; color: inherit;
}
.surveiller a:hover { border-color: var(--accent); }
.surveiller .titre { flex: 1; min-width: 0; font-size: 14px; }
.surveiller .titre span { color: var(--gris); }
.surveiller .reste {
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  color: var(--alerte); white-space: nowrap;
}
.surveiller .reste.critique { color: var(--danger); }

/* ---- Le tableau de stock devient une liste de cartes sur téléphone --
   Huit colonnes ne tiennent pas sur un écran d'atelier tenu d'une main.
   Chaque cellule porte son intitulé en data-libelle : la même table
   sert alors de tableau et de liste, sans balisage dupliqué. */
@media (max-width: 760px) {
  .tableau.stock, .tableau.stock tbody, .tableau.stock tr, .tableau.stock td {
    display: block; width: 100%;
  }
  .tableau.stock { border: 0; background: none; }
  .tableau.stock thead { display: none; }
  .tableau.stock tr {
    background: var(--carte); border: 1px solid var(--bord);
    border-radius: var(--rayon); margin-bottom: 8px; padding: 6px 2px;
  }
  .tableau.stock td {
    border: 0; display: flex; justify-content: space-between;
    align-items: baseline; gap: 14px; padding: 5px 12px;
  }
  .tableau.stock td::before {
    content: attr(data-libelle);
    font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
    color: var(--gris); flex: none;
  }
  .tableau.stock td:empty { display: none; }
  tr.est-critique td:first-child, tr.est-basse td:first-child { box-shadow: none; }
  tr.est-critique { border-left: 3px solid var(--danger); }
  tr.est-basse    { border-left: 3px solid var(--alerte); }
}

/* ---- Rien ne bouge pour qui a demandé que rien ne bouge ------------- */
@media (prefers-reduced-motion: reduce) {
  .bobine-rotor, .bobine-brin, .mosaique i { animation: none; }
  .force { transition: none; }
  .force:hover { transform: none; }
}

/* Les perçages du flasque : c'est par eux que la rotation se voit. Une
   couronne parfaitement lisse tournerait sans que l'oeil le remarque. */
.bobine-trou { fill: var(--fond); stroke: var(--bord); stroke-width: 1.5; }

/* Encart de démarrage : le premier écran d'un compte vide doit proposer une
   action, pas constater une absence. */
.encart .actions { margin-top: 14px; }
.encart.demarrage h2 { font-size: 16px; }

/* ---- En-tête de page ------------------------------------------------
   Chaque écran s'ouvrait sur un <h2> nu, sans dire ce qu'on y fait ni ce
   qu'on peut y faire. Un titre, une phrase d'intention et les actions du
   moment : c'est le minimum pour qu'une page se présente. */
.page-titre {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding: 26px 0 18px; margin-bottom: 6px;
  border-bottom: 1px solid var(--bord);
}
.page-titre h1 {
  margin: 0; font-size: 26px; letter-spacing: -0.025em; line-height: 1.2;
}
.page-chapo {
  margin: 7px 0 0; font-size: 14.5px; color: var(--gris);
  line-height: 1.55; max-width: 62ch;
}
.page-actions { display: flex; gap: 8px; flex-wrap: wrap; flex: none; }
.page-actions .bouton { padding: 9px 16px; font-size: 14px; }

@media (max-width: 620px) {
  .page-titre { padding: 18px 0 14px; }
  .page-titre h1 { font-size: 22px; }
}

/* ---- Liens ----------------------------------------------------------
   Par défaut un lien dans un tableau ou une liste héritait de la couleur
   d'accent sans soulignement, donc rien ne le distinguait d'un libellé
   coloré. On souligne au survol plutôt qu'en permanence : lisible dans un
   tableau dense, et sans ambiguïté sur ce qui est cliquable. */
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}
/* Ce qui est déjà visiblement cliquable ne se souligne pas en plus. */
.bouton:hover, .bouton-icone:hover, .carte:hover, .teinte:hover,
.marque:hover, .identite:hover, .nav-principale a:hover,
.surveiller a:hover, .bouton-fournisseur:hover, .exemple:hover {
  text-decoration: none;
}

/* ---- Code interne, en étiquette -------------------------------------
   Le code d'une bobine est ce qui figure sur l'autocollant collé sur le
   support : c'est une référence qu'on lit, qu'on compare et qu'on cherche
   des yeux dans une liste. Une étiquette la fait ressortir là où un lien
   souligné se noyait dans la colonne. */
.puce-code {
  display: inline-block; padding: 3px 9px; border-radius: 5px;
  background: var(--accent-doux); color: var(--accent);
  border: 1px solid transparent;
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  letter-spacing: .02em; white-space: nowrap;
  transition: border-color .12s ease, background .12s ease;
}
a:hover > .puce-code { border-color: var(--accent); }
a:has(> .puce-code):hover { text-decoration: none; }

/* La famille de couleur : on connaît la teinte de référence, pas la nuance
   exacte. Même traitement que les autres approximations — anneau tireté.
   Ne pas la confondre avec l'absence totale d'information, qui reste
   hachurée : dire « noir, à peu près » vaut mieux que « je ne sais pas ». */
.pastille[data-src="famille"] { border-style: dashed; opacity: .92; }
.provenance.famille { border-style: dashed; }

/* Encart « déjà en stock » : le même vocabulaire visuel que « À surveiller »,
   parce que c'est la même chose — une liste de bobines qu'on peut ouvrir. */
.deja-stock { border-color: var(--accent); background: var(--accent-doux); }
.deja-stock .surveiller a { background: var(--carte); }
.deja-stock h2 { color: var(--accent); }
.surveiller .titre .etat { margin-right: 4px; }

/* ---- Arbre des emplacements ----------------------------------------
   L'indentation dit la hiérarchie mieux qu'un pictogramme : on lit un
   plan de rangement comme on lit une table des matières. */
.arbre { display: grid; gap: 4px; margin-bottom: 10px; }
.noeud {
  margin-left: calc(var(--profondeur) * 26px);
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 10px 14px;
}
.noeud-ligne { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.noeud-nom { font-weight: 600; flex: 1; min-width: 8em; }
.noeud-places {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 13px; color: var(--gris); white-space: nowrap;
}
.noeud-places.complet { color: var(--danger); font-weight: 700; }
.noeud-ligne .jauge { width: 120px; margin: 0; flex: none; }
.noeud-actions { font-size: 13px; }

.noeud-reglage { margin-top: 6px; }
.noeud-reglage summary {
  cursor: pointer; font-size: 12px; color: var(--gris);
  list-style: none; display: inline-block;
}
.noeud-reglage summary::-webkit-details-marker { display: none; }
.noeud-reglage summary:hover { color: var(--accent); }
.ligne-reglage {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px;
}
.ligne-reglage input[type="text"] { flex: 1; min-width: 10em; }
.ligne-reglage input[type="number"] { width: 6.5em; }
.bouton.danger { color: var(--danger); border-color: var(--danger); }

/* Une racine se détache : c'est une pièce, pas une case. */
.noeud[style*="--profondeur:0"] { border-left: 3px solid var(--accent); }

/* ---- Rangement suggéré par teinte -----------------------------------
   Le but est de voir le dégradé, pas de lire un tableau : les pastilles
   se suivent, le reste est secondaire. */
.degrade { display: grid; gap: 4px; }
.degrade-item {
  display: flex; align-items: center; gap: 12px;
  padding: 6px 12px; border-radius: var(--rayon);
  background: var(--carte); border: 1px solid var(--bord);
  text-decoration: none; color: inherit; font-size: 14px;
}
.degrade-item:hover { border-color: var(--accent); text-decoration: none; }

@media (max-width: 620px) {
  .noeud { margin-left: calc(var(--profondeur) * 14px); }
  .noeud-ligne .jauge { width: 70px; }
}

/* Une capacité déduite des sous-emplacements se signale : le sigma dit que le
   chiffre est une somme, pas une saisie. Sans ça on chercherait où on l'a
   tapé. */
.noeud-places.calculee { color: var(--accent); }
.noeud-places.calculee.complet { color: var(--danger); }

/* Le schéma d'arborescence de la page vide : montrer la forme attendue vaut
   mieux que la décrire. */
.exemple-arbre {
  font-family: var(--mono); font-size: 13px; line-height: 1.7;
  color: var(--gris); margin: 12px 0 0; white-space: pre;
  overflow-x: auto;
}
.exemple-arbre b { color: var(--texte); font-weight: 600; }

/* ====================================================================
   Suivi : alertes, séchage, consommation
   ==================================================================== */

/* Pastille de comptage sur l'onglet Alertes. Elle n'apparait que s'il y a
   quelque chose a voir — un compteur a zero permanent finit par ne plus etre
   regarde, y compris le jour ou il compte. */
.pastille-nombre {
  min-width: 17px; height: 17px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--danger); color: #fff;
  border-radius: 9px; font-size: 11px; font-weight: 700;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.nav-principale a.actif .pastille-nombre { background: var(--danger); }

/* Rappel discret sur l'accueil : il renvoie vers la page des alertes plutot
   que d'en recopier le contenu. */
.message.rappel {
  display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center;
  background: var(--accent-doux); color: var(--texte);
}
.message.rappel a { font-weight: 600; }

/* ---- Séchage --------------------------------------------------------
   Une ligne = une bobine + le geste qui la resout. Le bouton est sur la
   ligne, pas au bout d'un detour : sinon le journal de sechage ne se
   remplit jamais. */
.alertes-sechage { display: grid; gap: 8px; margin-top: 6px; }
.ligne-sechage {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 14px; background: var(--carte);
  border: 1px solid var(--bord); border-radius: var(--rayon);
}
.ligne-sechage.urgente { border-color: var(--alerte); }
.sechage-bobine {
  display: flex; align-items: center; gap: 12px;
  flex: 1; min-width: 220px; text-decoration: none; color: inherit;
}
.sechage-bobine:hover { text-decoration: none; }
.sechage-bobine .titre { font-size: 14px; min-width: 0; }
.sechage-bobine .titre span { color: var(--gris); }
.sechage-etat { display: flex; flex-direction: column; font-size: 13px; }
.sechage-etat b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.ligne-sechage.urgente .sechage-etat b { color: var(--alerte); }
.sechage-recette {
  font-family: var(--mono); font-size: 12px; color: var(--gris);
  padding: 3px 9px; border: 1px solid var(--bord); border-radius: 20px;
}

/* ---- Histogramme des douze mois -------------------------------------
   Trois barres par mois, cote a cote : grammes imprimes, cout de ces
   grammes, achats du mois. Elles ne sont surtout pas empilees — ce sont
   trois grandeurs distinctes, dont deux en euros et une en grammes, et
   les empiler suggererait une somme qui n'existe pas. */
.histogramme {
  display: flex; align-items: flex-end; gap: 4px;
  height: 150px; margin-top: 6px; padding: 0 2px;
  overflow-x: auto;
}
.histogramme .colonne {
  flex: 1; min-width: 42px; height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 5px;
}
.histogramme .barres {
  flex: 1; display: flex; align-items: flex-end; gap: 2px;
  border-bottom: 1px solid var(--bord);
}
.histogramme .barres i {
  flex: 1; border-radius: 2px 2px 0 0; min-height: 0;
  transition: opacity .12s ease;
}
.histogramme .colonne:hover .barres i { opacity: .75; }
.histogramme .mois {
  font-size: 11px; color: var(--gris); text-align: center;
  text-transform: uppercase; letter-spacing: .04em;
}
.histogramme .valeur {
  font-family: var(--mono); font-size: 10px; color: var(--gris);
  text-align: center; font-variant-numeric: tabular-nums;
}

.b-conso { background: var(--accent); }
.b-cout  { background: var(--alerte); }
.b-achat { background: var(--gris); }

.legende-histo {
  display: flex; flex-wrap: wrap; gap: 16px;
  font-size: 12px; color: var(--gris); margin: 10px 2px 0;
}
.legende-histo span { display: inline-flex; align-items: center; gap: 6px; }
.legende-histo i { width: 10px; height: 10px; border-radius: 2px; }

/* ---- Calculateur de cout --------------------------------------------- */
.calculateur { max-width: 460px; }
.calcul-resultat {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--bord);
}
.calcul-resultat b {
  font-family: var(--mono); font-size: 22px; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.calcul-resultat p { margin: 0 0 6px; }

/* ---- Tableau de repartition ------------------------------------------
   Sans cadre ni en-tete : il vit dans un encart qui porte deja le titre,
   et les bordures d'un tableau complet le feraient paraitre plus lourd
   qu'il n'est. */
.tableau.nu { border: 0; background: none; }
.tableau.nu td { border-bottom: 1px solid var(--bord); padding: 8px 6px; font-size: 14px; }
.tableau.nu tr:last-child td { border-bottom: 0; }
.tableau.nu td:first-child { width: 100%; }
.tableau.nu .jauge { margin-top: 5px; }
td.chiffre {
  text-align: right; white-space: nowrap; color: var(--gris);
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 13px;
}

/* Le formulaire du geste quotidien se distingue de ceux qu'on ouvre une
   fois par mois. */
.formulaire.principale { border-color: var(--accent); }

@media (max-width: 620px) {
  .ligne-sechage { align-items: flex-start; }
  .sechage-recette { order: 3; }
  .histogramme .colonne { min-width: 34px; }
  .histogramme .valeur { display: none; }
}

/* ------------------------------------------------------------------ */
/* Slicer-Link : imprimantes, emplacements de filament, travaux        */
/* ------------------------------------------------------------------ */

.machine {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 16px 18px; margin-bottom: 14px;
}
.machine.inactive { opacity: .6; }
.machine-entete {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; flex-wrap: wrap;
}
.machine-entete h2 { margin: 0; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.machine-entete h2 .gris { font-weight: 400; font-size: 14px; }
.machine-entete .aide { margin: 4px 0 0; font-size: 13px; }
.machine-reglages summary { list-style: none; cursor: pointer; }
.machine-reglages summary::-webkit-details-marker { display: none; }
.machine-reglages[open] { flex-basis: 100%; }
.machine-reglages .formulaire { margin-top: 12px; }

/* Une grille plutôt qu'une liste : quatre emplacements d'AMS se regardent
   ensemble, comme on regarde la machine, et non les uns après les autres. */
.slots {
  display: grid; gap: 8px; margin-top: 14px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.slot {
  display: grid; gap: 6px 10px; align-items: center;
  grid-template-columns: auto 1fr;
  border: 1px solid var(--bord); border-radius: var(--rayon);
  padding: 10px 12px; background: var(--fond);
}
.slot.occupe { background: var(--carte); }
.slot-entete { display: flex; align-items: center; gap: 8px; }
.slot-numero {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
  background: var(--accent-doux); color: var(--accent);
  font: 600 12px/1 var(--mono);
}
.slot-bobine { display: grid; gap: 2px; font-size: 13px; min-width: 0; }
.slot-bobine b { font-size: 14px; }
.slot-bobine .gris { font-size: 12px; }
.slot-bobine a { text-decoration: none; color: inherit; }
.slot-bobine a:hover b { color: var(--accent); }
.slot select { grid-column: 1 / -1; font-size: 13px; }
/* Un emplacement vide se voit : pastille creuse, pas pastille grise. */
.pastille.vide-slot { background: transparent; border: 1px dashed var(--bord); }

/* --- La commande à coller ----------------------------------------- */
/* Elle doit se sélectionner d'un geste et ne jamais se couper au milieu :
   un retour à la ligne collé dans un champ de réglages casse la commande. */
.commande {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 12px 14px; margin-bottom: 10px;
}
.commande pre {
  flex: 1; margin: 0; overflow-x: auto;
  font: 13px/1.7 var(--mono); color: var(--texte);
  white-space: pre; -webkit-user-select: all; user-select: all;
}
.commande button { flex: none; }

.cle-neuve { border-color: var(--accent); }
.cle-secrete {
  margin: 0 0 8px; padding: 12px 14px;
  background: var(--accent-doux); border-radius: var(--rayon);
  overflow-x: auto;
}
.cle-secrete code {
  font: 15px/1.6 var(--mono); color: var(--accent);
  -webkit-user-select: all; user-select: all; white-space: nowrap;
}

/* --- Travaux d'impression à confirmer ------------------------------ */
.travail {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); padding: 14px 16px; margin-bottom: 10px;
}
.travail-entete {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 14px; flex-wrap: wrap; margin-bottom: 10px;
}
.travail-entete .gris { display: block; font-size: 12px; margin-top: 2px; }
.travail-total { font: 600 17px/1 var(--mono); }
.travail-ligne {
  display: grid; gap: 4px 10px; align-items: center;
  grid-template-columns: auto auto 1fr auto;
  padding: 8px 0; border-top: 1px solid var(--bord);
}
.travail-ligne.orpheline { opacity: .7; }
.travail-case { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.travail-bobine { display: grid; gap: 2px; font-size: 13px; min-width: 0; }
.travail-bobine a { text-decoration: none; color: inherit; }
.travail-bobine a:hover b { color: var(--accent); }
.travail-bobine .gris { font-size: 12px; }
.travail-grammes { display: flex; align-items: center; gap: 4px; font-size: 13px; }
.travail-grammes input { width: 5.5em; text-align: right; font-family: var(--mono); }
.travail-actions {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--bord);
}
.travail-actions .indice { margin: 0; }
/* L'écart signalé n'est pas une erreur bloquante : il se remarque sans crier. */
.avis {
  font-size: 12px; color: var(--alerte);
  display: inline-flex; align-items: center; gap: 4px;
}
.avis::before { content: "▲"; font-size: 9px; }

@media (max-width: 620px) {
  .travail-ligne { grid-template-columns: auto auto 1fr; }
  .travail-grammes { grid-column: 2 / -1; justify-content: flex-end; }
  .commande { flex-direction: column; }
  .commande button { align-self: flex-start; }
}

/* Brancher le trancheur : replié une fois la machine en service, déplié tant
   qu'elle n'a rien envoyé. C'est un réglage qu'on fait une fois, il n'a pas à
   occuper la place du geste quotidien. */
.branchement {
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--bord);
}
.branchement > summary {
  cursor: pointer; font-size: 14px; font-weight: 500;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  list-style-position: outside;
}
.branchement > summary::marker { color: var(--gris); }
.branchement[open] > summary { margin-bottom: 12px; }
.branchement .etapes { margin-top: 10px; }
.branchement .aide { font-size: 13px; }
.jeton.ok { border-color: var(--ok); color: var(--ok); font-size: 12px; padding: 2px 10px; }

/* Le procédé en quatre temps : icônes et flèches plutôt que trois paragraphes.
   Ce sont les FLÈCHES qui portent l'essentiel — « tout seul », « ça attend »,
   « un clic » —, parce que la question qu'on se pose devant cette page n'est
   pas « que fait le logiciel » mais « qu'est-ce que j'ai à faire, moi ». */
.flux {
  list-style: none; margin: 4px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 4px;
}
.flux-etape {
  flex: 1 1 130px; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  text-align: center; padding: 14px 10px;
  background: var(--fond); border: 1px solid var(--bord);
  border-radius: var(--rayon);
}
.flux-etape b { font-size: 13.5px; line-height: 1.35; }
.flux-icone {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--accent-doux); color: var(--accent);
}
/* La flèche ne compte pas comme une étape : elle ne prend que sa place. */
.flux-fleche {
  flex: 0 0 auto; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
  color: var(--gris); padding: 0 2px;
}
.flux-fleche span {
  font-size: 11px; letter-spacing: .02em; white-space: nowrap;
}

/* « En détail » doit se voir comme un bouton, pas comme une note de bas de page.
   En gris clair sur le fond teinté du guide, il disparaissait : on ne clique pas
   sur ce qu on ne distingue pas du décor. */
.flux-detail { margin-top: 14px; }
.flux-detail > summary {
  cursor: pointer; font-size: 13.5px; font-weight: 500;
  color: var(--accent); list-style: none;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; border-radius: 20px;
  background: var(--carte); border: 1px solid var(--bord);
}
.flux-detail > summary::-webkit-details-marker { display: none; }
/* Un chevron dessiné en CSS : il pivote à l ouverture et dit donc l état,
   ce qu un libellé figé ne fait pas. */
.flux-detail > summary::after {
  content: ""; width: 7px; height: 7px;
  border-right: 1.8px solid currentColor; border-bottom: 1.8px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform .15s ease;
}
.flux-detail[open] > summary::after { transform: translateY(1px) rotate(-135deg); }
.flux-detail > summary:hover { border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .flux-detail > summary::after { transition: none; }
}
.flux-detail .etapes { margin-top: 10px; }

/* En colonne étroite, la flèche pivote : une flèche qui pointe à droite au-dessus
   d'un bloc empilé indiquerait la mauvaise direction. */
@media (max-width: 700px) {
  .flux { flex-direction: column; align-items: stretch; }
  .flux-fleche { flex-direction: row; gap: 8px; padding: 2px 0; }
  .flux-fleche svg { transform: rotate(90deg); width: 24px; }
  .flux-etape { flex-direction: row; text-align: left; gap: 12px; }
}

/* Un champ qu'on peut laisser vide se signale sur son étiquette, pas dans une
   phrase d'aide qu'on lit après avoir déjà hésité. */
.facultatif {
  font-size: 11px; font-weight: 400; color: var(--gris);
  text-transform: lowercase; letter-spacing: .02em;
}

/* ------------------------------------------------------------------ */
/* Bloc « marche à suivre »                                            */
/* ------------------------------------------------------------------ */
/* Un encart qui explique ne doit pas ressembler à un encart qui montre des
   données : sans distinction, on le saute au deuxième passage et on revient
   poser la question qu'il répondait. D'où un fond teinté, un liseré à gauche
   et une ampoule — trois signaux qui disent « ceci t'aide à faire ».

   Volontairement dans la famille de l'accent, pas dans celle de l'alerte :
   une marche à suivre n'est pas un avertissement, et le premier réflexe
   devant de l'ambre est de chercher ce qui ne va pas. */
.guide {
  background: var(--accent-doux);
  border: 1px solid var(--bord);
  border-left: 3px solid var(--accent);
  padding: 16px 18px;
}
.guide > h2 {
  display: flex; align-items: center; gap: 8px;
  color: var(--accent); font-size: 14px; margin: 0 0 12px;
}
.guide > h2 svg { flex: none; }
/* Les cases du schéma reprennent le fond des cartes : sur un encart déjà
   teinté, un fond gris les aurait fait disparaître. */
.guide .flux-etape { background: var(--carte); }
.guide .etape { background: var(--carte); }
.guide .exemple-arbre { background: var(--carte); }

/* Les grandes étapes de la page : elles doivent se repérer au défilement,
   sinon la numérotation ne sert à rien — on ne compte pas des titres qu'on ne
   distingue pas des sous-titres. */
.section-numerotee {
  margin-top: 34px; padding-top: 16px;
  border-top: 2px solid var(--bord);
  font-size: 18px;
}
.section-numerotee + .aide { margin-top: -4px; }
/* Titre de la grille des emplacements, dans la fiche d'une machine. */
.machine-titre {
  font-size: 13px; color: var(--gris); font-weight: 500;
  margin: 16px 0 0; text-transform: uppercase; letter-spacing: .04em;
}
/* Titre d'un formulaire subordonné à une section : présent, mais qui ne se
   fait pas passer pour une étape de plus. */
.formulaire-titre { font-size: 15px; margin: 0 0 14px; }
/* Régénérer la ligne : présent, mais discret. C'est un recours, pas un geste
   courant, et un bouton trop visible sous une commande invite à cliquer. */
.jeton-refaire {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 4px 0 10px;
}
.jeton-refaire .indice { margin: 0; }

/* Le chemin de clics : un fil d'Ariane qu'on suit du regard en comparant à
   l'écran. Sorti de la prose exprès — noyé dans un paragraphe, il fallait le
   relire trois fois pour retrouver où l'on en était. */
.chemin-reglage {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 2px 0 8px;
}
.chemin-reglage b {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: 5px; padding: 3px 9px;
  font: 500 12.5px/1.5 var(--mono); color: var(--texte);
  white-space: nowrap;
}
.chemin-reglage i { color: var(--gris); font-style: normal; font-size: 14px; }

/* Télécharger le script et dire où il a été rangé : deux gestes d'un même
   moment, donc une seule ligne. Le champ est large — c'est un chemin Windows
   complet, et le tronquer obligerait à faire défiler pour se relire. */
.script-emplacement {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 8px 0 4px;
}
.script-emplacement form { display: flex; align-items: center; gap: 8px; flex: 1 1 380px; }
.script-emplacement input[type="text"] {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--mono); font-size: 12.5px;
}
/* Étiquette réservée aux lecteurs d'écran : le champ est décrit par le texte
   qui le précède, mais un lecteur d'écran ne lit pas ce voisinage. */
.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ==================================================================== */
/*  Passe de relief                                                     */
/* ==================================================================== */
/* Le reproche était juste : tout était plat. Bordure grise sur fond blanc,
   partout, du conteneur décoratif au bouton d'action — donc rien ne se
   détachait et l'oeil n'avait aucun point d'accroche.

   Les ombres existaient en jetons mais ne servaient nulle part. Elles sont
   maintenant employées selon une règle simple, et une seule : ce qui est un
   OBJET manipulable est légèrement soulevé, ce qui est un fond ou une
   explication reste posé à plat. Si tout était soulevé, plus rien ne le
   serait. */

.carte, .stat, .machine, .travail, .slot.occupe, .tableau, .formulaire {
  box-shadow: var(--ombre);
}

/* Ce qu'on peut ouvrir, cliquer ou survoler le dit en se soulevant. */
.carte { transition: border-color .13s ease, box-shadow .13s ease, transform .06s ease; }
.carte:hover { box-shadow: var(--ombre-levee); }
.carte:active { transform: translateY(1px); }

/* Une ligne de tableau qu'on peut viser des yeux — et souvent cliquer —
   doit réagir : sans cela on perd la ligne en glissant vers la droite. */
.tableau tbody tr { transition: background-color .1s ease; }
.tableau tbody tr:hover { background: var(--survol); }

/* Un emplacement chargé est un objet ; un emplacement vide est un trou.
   Le premier se soulève, le second reste creux et pointillé. */
.slot { transition: border-color .13s ease, box-shadow .13s ease; }
.slot.occupe:hover { border-color: var(--accent); box-shadow: var(--ombre-levee); }
.slot:not(.occupe) { border-style: dashed; }

/* Les jauges : trois couleurs pour trois décisions différentes — continuer,
   penser à racheter, racheter maintenant. Elles gagnent du corps, parce
   qu'un filet de 4 px ne se voit pas en diagonale à travers une grille. */
.jauge { height: 6px; border-radius: 3px; }
.jauge i { transition: width .2s ease; }

/* Le chiffre d'une tuile est ce qu'on vient y chercher : il prend la couleur
   du texte plein, et son intitulé s'efface d'un cran. */
.stat b { font-weight: 600; }
.stat { transition: border-color .13s ease, box-shadow .13s ease; }
.stat:hover { box-shadow: var(--ombre-levee); }

/* Les blocs qui expliquent restent plats : c'est ce qui les distingue des
   blocs qui contiennent des données. */
.encart, .encart.guide { box-shadow: none; }

/* Le survol d'un onglet de navigation, qui n'en avait aucun. */
.nav-principale a { transition: color .12s ease, background-color .12s ease; }
.nav-principale a:hover:not(.actif) { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .bouton, .carte, .slot, .stat, .jauge i, .tableau tbody tr, .nav-principale a {
    transition: none;
  }
  .bouton:active, .carte:active { transform: none; }
}

/* L'en-tête d'un tableau doit se lire comme un en-tête, pas comme une
   première ligne pâle : une teinte de fond suffit à le détacher, et la
   colonne se suit ensuite toute seule. */
.tableau th { background: var(--fond); }

/* Les titres de section portaient le même poids que du texte courant. Un
   cran de plus, et le regard trouve où commencent les blocs. */
h2 { font-weight: 600; letter-spacing: -0.01em; }

/* L'intitulé d'une tuile de chiffre s'efface d'un cran sous le chiffre :
   c'est le chiffre qu'on vient chercher, l'intitulé ne fait que le nommer. */
.stat span { text-transform: uppercase; letter-spacing: .04em; font-size: 11px; }

/* ==================================================================== */
/*  Passe de structure : moins de cadres, plus de niveaux               */
/* ==================================================================== */
/* Le défaut à corriger : chaque section avait fini dans une carte, et la
   fiche d'une machine empilait quatre niveaux de rectangles bordés —
   machine, branchement, étape, commande — tous de la même valeur. Une boîte
   dans une boîte dans une boîte ne hiérarchise rien : elle fatigue.

   Règle tenue à partir d'ici : UN SEUL niveau de boîte visible à la fois.
   À l'intérieur d'une carte, on sépare par l'espacement, un filet, ou un
   fond en creux — jamais par une autre carte. */

/* --- Les étapes du branchement perdent leur cadre ------------------- */
/* Elles restent numérotées et espacées : c'est suffisant pour se suivre,
   et la carte de la machine redevient le seul cadre du bloc. */
.branchement .etapes { gap: 0; margin-top: 6px; }
.branchement .etape {
  background: none; border: 0; border-radius: 0;
  border-top: 1px solid var(--bord);
  padding: 16px 0;
}
.branchement .etape:first-child { border-top: 0; padding-top: 8px; }
.branchement .etape:last-child { padding-bottom: 8px; }

/* --- Les emplacements reposent dans un plateau en creux ------------- */
/* Des cartes blanches sur un fond creusé : le changement de niveau se lit
   d'un coup, là où carte-sur-carte donnait deux rectangles identiques. */
.slots {
  background: var(--fond); border-radius: var(--rayon);
  padding: 12px; margin-top: 8px;
  /* auto-fit et non auto-fill, et un minimum plus bas : quatre emplacements
     d'AMS doivent tenir sur UNE rangée. En 3 + 1, on ne lit plus la machine,
     on lit trois emplacements et un orphelin. */
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.slot { background: var(--carte); box-shadow: var(--ombre); }
.slot:not(.occupe) { background: transparent; box-shadow: none; }
.slot select { font-size: 12.5px; }

/* --- Le schéma se resserre ------------------------------------------ */
/* Icône et libellé côte à côte : empilés, chaque case réservait 90 px de
   hauteur pour trois mots, et le bloc devenait une bande vide sur un écran
   large. En ligne, il se lit comme une phrase — ce qu'il est. */
.flux-etape {
  flex-direction: row; align-items: center; text-align: left;
  gap: 10px; padding: 12px 14px; flex: 1 1 0; min-width: 150px;
}
.flux-icone { width: 36px; height: 36px; flex: none; }
.flux-etape b { font-size: 13px; line-height: 1.3; }

/* --- Le champ de chemin --------------------------------------------- */
/* Il occupait toute la largeur restante et son texte d'exemple, en gris
   pâle, le faisait passer pour un champ désactivé. */
.script-emplacement form { flex: 0 1 520px; }
.script-emplacement input[type="text"]::placeholder {
  color: var(--gris); opacity: .75;
}

/* --- Le bloc de commande reste encadré ------------------------------ */
/* C'est le seul sous-cadre qui se justifie : ce n'est pas une section, c'est
   un OBJET qu'on vient prendre. Il gagne un fond en creux pour se distinguer
   du blanc de la fiche. */
.commande { background: var(--fond); border-color: var(--bord); }

@media (max-width: 700px) {
  .flux-etape { padding: 10px 12px; }
  .slots { padding: 8px; }
}

/* Le nom d'une bobine tient sur une ligne, tronqué au besoin : dans un
   plateau de quatre emplacements, un nom qui passe à la ligne fait grandir
   sa case et casse l'alignement de la rangée — on ne lit plus une machine à
   quatre emplacements, on lit trois cases et une différente. Le nom complet
   reste dans l'infobulle et dans la liste déroulante juste en dessous. */
.slot-bobine b,
.slot-bobine .gris {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Les cases s'alignent par le haut et se remplissent : la jauge et le
   restant tombent alors à la même hauteur d'un emplacement à l'autre. */
.slot { align-content: start; }
.slot-bobine { align-self: start; }
/* Une case de grille refuse par défaut de descendre sous la largeur de son
   contenu : sans cela, le nom en « nowrap » élargissait la colonne au lieu
   d'être tronqué, et débordait de la carte avec sa jauge. */
.slot { min-width: 0; }
.slot > * { min-width: 0; }
/* Le nom vit dans un lien, et c'est le LIEN qui grandissait : le rognage
   posé sur le texte à l'intérieur n'opérait donc jamais. Chaque maillon de
   la chaîne doit accepter de rétrécir, sinon le dernier ne peut pas trancher. */
.slot-bobine > * { min-width: 0; }
.slot-bobine a {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- « Brancher X sur cette imprimante » ----------------------------- */
/* Replié par défaut, donc il faut qu'il se voie : une ligne de texte grise
   au milieu d'une carte ne se remarque pas, et le réglage ne se fait jamais.
   Traité comme un bouton d'accent, avec l'ampoule des blocs d'aide — le même
   signal que « Comment ça marche », pour la même raison. */
.branchement > summary {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 9px 16px; margin-top: 4px; border-radius: 20px;
  background: var(--accent-doux); color: var(--accent);
  border: 1px solid transparent;
  font-size: 14px; font-weight: 500; cursor: pointer; list-style: none;
  transition: border-color .13s ease, background-color .13s ease;
}
.branchement > summary::-webkit-details-marker { display: none; }
.branchement > summary::marker { content: ""; }
.branchement > summary:hover { border-color: var(--accent); }
.branchement-ampoule { display: inline-flex; line-height: 0; }
/* Un chevron qui pivote : le libellé dit ce que ça fait, le chevron dit l'état. */
.branchement > summary::after {
  content: ""; width: 7px; height: 7px; margin-left: 2px;
  border-right: 1.8px solid currentColor; border-bottom: 1.8px solid currentColor;
  transform: translateY(-2px) rotate(45deg); transition: transform .15s ease;
}
.branchement[open] > summary::after { transform: translateY(1px) rotate(-135deg); }

/* --- « Ajouter une imprimante » -------------------------------------- */
/* Repliée dès qu'une machine existe : c'est un geste qu'on fait une fois. */
.ajout-machine { margin-bottom: 24px; }
.ajout-machine > summary {
  display: inline-flex; align-items: center; gap: 7px;
  list-style: none; cursor: pointer; width: auto;
}
.ajout-machine > summary::-webkit-details-marker { display: none; }
.ajout-machine > summary::marker { content: ""; }
.ajout-machine > summary::before { content: "+"; font-size: 17px; line-height: 1; }
.ajout-machine[open] > summary { margin-bottom: 12px; }

/* --- Choix de bobine à la confirmation ------------------------------- */
.travail-choix { margin-top: 6px; font-size: 12.5px; max-width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .branchement > summary, .branchement > summary::after { transition: none; }
}
/* Le numéro d'étape reste en haut de sa colonne. Tenté « grid-row: 1 / -1 »
   pour le faire courir sur toute la hauteur : sans grid-template-rows, le -1
   désigne la fin de la grille EXPLICITE, c'est-à-dire la ligne 1 — la règle
   devenait absurde et écrasait la colonne de texte à un mot par ligne. */
.branchement .etape::before { align-self: start; }
/* Le bloc de commande vit désormais DANS une cellule de grille, et une cellule
   refuse par défaut de descendre sous la largeur de son contenu : le « pre »
   en chasse fixe, non coupable, écrasait tout le reste. C'est le même piège que
   sur les emplacements — chaque maillon doit accepter de rétrécir pour que le
   défilement horizontal se déclenche au bon endroit. */
/* Le numéro n'occupe la colonne de gauche que sur DEUX rangées — c'était
   suffisant tant qu'une étape tenait en un titre et un paragraphe. Depuis
   qu'une étape porte aussi le bloc de commande et le bouton de régénération,
   les enfants suivants retombaient dans la colonne de 34 px et s'y écrasaient.
   On force donc TOUT le contenu en colonne 2 ; le pseudo-élément du numéro
   n'est pas un enfant, il reste seul en colonne 1. */
.branchement .etape { grid-template-columns: 34px minmax(0, 1fr); }
.branchement .etape > * { grid-column: 2; min-width: 0; }
.branchement .etape .commande,
.branchement .etape .commande pre { min-width: 0; }

/* ==================================================================== */
/*  Page d'ajout unifiée                                                */
/* ==================================================================== */
/* Un bouton porte « display: inline-flex » depuis la passe sur les boutons,
   ce qui l'emportait sur l'attribut hidden : les commandes de la caméra
   (Arrêter, Lampe, Autre caméra) restaient visibles alors que la caméra
   était éteinte. Un attribut du HTML doit toujours gagner contre une classe. */
[hidden] { display: none !important; }

/* La vue caméra ne prend de la place qu'une fois allumée, et s'ouvre sous le
   champ plutôt qu'à côté : c'est le même geste qui se poursuit, pas un second
   outil posé à droite. */
.recherche .scene { max-width: 560px; margin: 14px 0; }
.recherche .commandes { margin-top: 10px; }

/* La saisie à la main est un recours, pas la porte d'entrée : elle se replie
   derrière un bouton discret tant qu'aucune référence n'est choisie. */
.saisie-main { margin-top: 20px; }
.saisie-main > summary {
  display: inline-flex; align-items: center; gap: 7px;
  list-style: none; cursor: pointer; width: auto;
}
.saisie-main > summary::-webkit-details-marker { display: none; }
.saisie-main > summary::marker { content: ""; }
.saisie-main[open] > summary { margin-bottom: 14px; }

.derniers-scans { margin-top: 18px; }
.derniers-scans .ligne.journal { margin-top: 8px; }

/* --- Vue caméra ------------------------------------------------------ */
/* Ces règles vivaient dans le <style> de l'ancienne page « Scanner ».
   Celle-ci n'étant plus qu'une redirection, elles rejoignent la feuille
   commune — sans quoi la vue restait ouverte et vide sur la page d'ajout. */
.scene {
  position: relative; background: #000; border-radius: var(--rayon);
  overflow: hidden; aspect-ratio: 4 / 3;
}
.scene video { width: 100%; height: 100%; object-fit: cover; display: block; }
.scene.inactive { display: none; }

/* Fenêtre de visée : on cadre le code, pas toute la bobine. */
.visee {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
}
.visee i {
  display: block; width: 78%; height: 30%;
  border: 2px solid rgba(255, 255, 255, .85); border-radius: 6px;
  box-shadow: 0 0 0 2000px rgba(0, 0, 0, .35);
}
/* Le cadre vire au vert à la lecture : le retour le plus rapide possible,
   avant même que le résultat n'arrive du serveur. */
.visee.touche i { border-color: #4ade80; }

.commandes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* --- État du poste ---------------------------------------------------- */
/* Trois conditions doivent être réunies pour scanner à la caméra ; autant
   dire laquelle manque plutôt que de laisser un bouton sans effet. */
.diagnostic { font-size: 13px; margin-top: 16px; color: var(--gris); }
.diagnostic ul { padding-left: 0; margin: 6px 0 0; }
.diagnostic li { margin: 3px 0; list-style: none; }
.diagnostic .ok { color: var(--ok); }
.diagnostic .ko { color: var(--alerte); }

/* --- Lignes de codes déjà lus ---------------------------------------- */
.journal .ligne {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px;
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); margin-bottom: 6px; font-size: 14px;
}
.journal .ligne code { font-size: 14px; }
.journal .ligne .verdict { margin-left: auto; font-size: 13px; }
.journal .ligne.trouve  { border-color: var(--ok); }
.journal .ligne.inconnu { border-color: var(--alerte); }

/* --- Stock : tri par colonne et filtre -------------------------------- */
/* Le tri se fait côté serveur : l'en-tête est donc un vrai lien, et doit se
   voir comme tel — sinon personne ne devine qu'on peut cliquer dessus. */
.stock-entete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.stock-entete h2 { margin-bottom: 0; }
.stock-filtre { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.stock-filtre input[type="search"] { min-width: 220px; }

.tableau.stock th { padding: 0; }
.tableau.stock th a {
  display: flex; align-items: center; gap: 5px;
  padding: 10px 12px; text-decoration: none; color: inherit;
  transition: color .12s ease, background-color .12s ease;
}
.tableau.stock th a:hover { color: var(--accent); background: var(--survol); }
.tableau.stock th i { font-style: normal; font-size: 11px; }
/* La colonne active porte la couleur d'accent : on sait sur quoi on est trié
   sans avoir à chercher la petite flèche. */
.tableau.stock th.trie a { color: var(--accent); }
.tableau.stock th.trie { box-shadow: inset 0 -2px 0 var(--accent); }

@media (max-width: 760px) {
  .stock-entete { flex-direction: column; align-items: stretch; }
  .stock-filtre input[type="search"] { flex: 1 1 auto; min-width: 0; }
}

/* ==================================================================== */
/*  Les trois voies d'ajout                                             */
/* ==================================================================== */
/* Elles étaient annoncées par un schéma, puis introuvables dans la page :
   on lisait « trois façons », on n'en voyait qu'une. Le schéma a disparu et
   les voies sont devenues la page. Elles doivent donc se compter du regard —
   d'où un numéro en pastille, un titre de même poids, et le mot « sinon »
   entre deux blocs pour dire que ce sont des recours successifs. */
.voie {
  background: var(--carte); border: 1px solid var(--bord);
  border-radius: var(--rayon); box-shadow: var(--ombre);
  padding: 18px 20px; margin-bottom: 0;
}
.voie-titre {
  display: flex; align-items: center; gap: 11px;
  margin: 0 0 6px; font-size: 17px;
}
.voie-numero {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; border-radius: 50%;
  background: var(--accent); color: #fff;
  font: 600 14px/1 var(--mono);
}
.voie .aide { margin: 0 0 14px; max-width: 70ch; }
.voie .commandes { margin-bottom: 0; }
.voie .scene { max-width: 560px; margin-top: 14px; }
.voie .champ-recherche { margin-top: 0; }
.voie .flux-detail { margin-top: 14px; }

/* « sinon » : le lien logique entre deux recours. Un simple espace laisserait
   croire à trois choses à faire, alors qu'il s'agit de trois à essayer. */
.voie-sinon {
  margin: 0; padding: 10px 0 10px 34px;
  color: var(--gris); font-size: 13px; font-style: italic;
  position: relative;
}
.voie-sinon::before {
  content: ""; position: absolute; left: 14px; top: 0; bottom: 0;
  border-left: 2px dashed var(--bord);
}

/* --- Lecture d'étiquette : OCR et couleur ---------------------------- */
/* C'est une voie d'ajout entière, plus un repli caché dans une autre : elle
   est visible en permanence, comme les trois autres. Seul le bouton « lire
   depuis la caméra » va et vient, avec le flux. */
.etiquette {
  margin-top: 14px; padding-top: 14px;
  border-top: 1px dashed var(--bord);
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.etiquette .indice { margin: 0; }

/* L'aperçu à gauche, ce qu'on en a tiré à droite : le même parti que la
   caméra et ses résultats — on voit du même coup d'œil l'image analysée et ce
   qu'elle a donné. En colonne étroite, l'aperçu repasse au-dessus. */
/* Flex et non grille : un élément masqué n'est pas un élément flex, donc la
   colonne d'aperçu ne laisse aucun vide ni aucun espacement tant qu'aucune
   image n'a été lue. Une grille aurait gardé sa gouttière. */
.etiquette-lecture {
  display: flex; flex-wrap: wrap; gap: 14px; width: 100%; align-items: flex-start;
}
.etiquette-resultat { flex: 1 1 240px; min-width: 0; }
.etiquette-apercu {
  margin: 0; flex: 0 0 160px; max-width: 160px;
  display: flex; flex-direction: column; gap: 5px;
}
.etiquette-apercu img {
  display: block; width: 100%; height: auto; border-radius: 8px;
  border: 1px solid var(--bord); background: var(--fond);
}
.etiquette-apercu figcaption {
  font-size: 11.5px; color: var(--gris); text-transform: uppercase;
  letter-spacing: .04em;
}
/* La caméra de la voie photo : la vue, puis son déclencheur juste dessous. On
   cadre et on appuie sans quitter des yeux ce qu'on photographie. */
#photo-scene { margin-top: 12px; }
.photo-prise { margin-top: 10px; }

/* Le champ fichier est masqué : son focus clavier doit donc s'afficher sur le
   label qui lui sert de bouton, sinon la tabulation traverse un bouton
   invisible. Et un label désactivé doit se voir désactivé — pendant une
   lecture, il ne répond plus. */
#photo-fichier:focus-visible + .bouton {
  outline: 2px solid var(--anneau); outline-offset: 2px;
}
#photo-fichier:disabled + .bouton { opacity: .55; cursor: default; }

/* La réserve — « une piste, pas une identification » — se lit avant les
   résultats, jamais après coup. */
.etiquette-reserve {
  display: flex; align-items: flex-start; gap: 7px;
  color: var(--gris); font-size: 12.5px;
}
.etiquette-reserve svg { flex: none; margin-top: 1px; opacity: .8; }

@media (max-width: 620px) {
  .etiquette-apercu { flex-basis: 100%; max-width: 220px; }
}
.etiquette-etat { margin: 0; font-size: 13px; color: var(--gris); min-height: 1em; }
.etiquette-etat q { color: var(--texte); font-family: var(--mono); font-size: 12.5px; }

.etiquette-teinte {
  display: flex; align-items: center; gap: 10px;
  margin: 10px 0 8px; font-size: 13px; color: var(--gris);
}
.etiquette-teinte code { font-size: 12.5px; }

.etiquette-couleurs { display: grid; gap: 6px; width: 100%; }
/* L'écart est la seule chose qui empêche de lire une ressemblance comme une
   identification : il ne se cache jamais, même sur petit écran. */
.etiquette-couleurs .carte .action {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  color: var(--gris); white-space: nowrap;
}
