/* Styles propres à un seul écran. Tout ce qui sert à deux écrans ou plus vit dans theme.css. */

/* --- Connexion : la planche à gauche, le guichet à droite ---------------

   La moitié gauche pose `granuscan/img/labo.jpg` sur toute sa hauteur. Le voile
   est un dégradé oblique, pas un aplat : il blanchit la photographie à gauche,
   là où passent le titre et le parcours, et la laisse intacte à droite. Un
   deuxième dégradé, vertical et léger, dégage le wordmark en haut.

   Le socle sombre du bas n'est pas un pied de page : c'est la troisième bande
   de la planche, et elle est posée hors de `.planche-corps` pour aller d'un
   bord à l'autre sans hériter de sa gouttière. */

.porte { min-height: 100vh; }
.porte-grille {
  display: grid;
  grid-template-columns: 1.54fr 1fr;
  min-height: 100vh;
}

.planche {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  background: var(--plate-bg);
  color: var(--on-plate);
}
.planche-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 64% center;
  z-index: -2;
}
.planche::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(
      96deg,
      var(--plate-veil-fort)  0%,
      var(--plate-veil-fort) 30%,
      var(--plate-veil-mi)   57%,
      var(--plate-veil-fin)  86%,
      transparent           100%
    ),
    linear-gradient(0deg, var(--plate-veil-mi) 0%, transparent 30%),
    linear-gradient(180deg, var(--plate-veil-haut) 0%, transparent 32%);
}

/* Le wordmark en haut, le titre au centre, le parcours en bas : la rangée
   souple du milieu tient l'écart quelle que soit la hauteur de fenêtre. */
.planche-corps {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: var(--s6);
  padding: var(--s6) var(--s7);
}
.planche-mot { display: flex; align-items: center; gap: var(--s3); align-self: start; }
.planche .wordmark { font-size: var(--fs-marque); color: var(--ink); }

.marque-icone { width: 40px; height: 40px; flex: none; }
.marque-icone .disque { fill: var(--accent); }
.marque-icone .lames {
  fill: none;
  stroke: var(--surface);
  stroke-width: 2.2;
  stroke-linecap: round;
}
.marque-icone .pupille { fill: var(--surface); }

.planche-dire { align-self: center; display: flex; flex-direction: column; gap: var(--s4); }
.planche h1 {
  font-family: var(--f-sans);
  font-weight: 600;
  font-size: var(--fs-porte);
  line-height: 1.06;
  letter-spacing: var(--tr-display);
  color: var(--on-plate);
  max-width: 31ch;
}
/* Le mot que la page mesure, mis à l'accent — un <em> parce que c'est bien une
   emphase, pas une couleur posée sur un <span> vide de sens. */
.planche h1 em { font-style: normal; color: var(--accent); }
.planche p { color: var(--on-plate-2); font-size: var(--fs-md); max-width: 48ch; }

/* --- Le parcours : quatre temps, trois flèches --- */

.parcours {
  display: flex;
  align-items: flex-start;
  gap: var(--s5);
  align-self: end;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* `.etape` désigne ici un pion du parcours de connexion, et dans le châssis une
   fiche du fil de progression : les deux sont cadrés, chacun sous son parent,
   pour qu'aucune des deux mises en forme ne déborde sur l'autre. */
.parcours .etape {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  width: 136px;
}
/* La flèche vit dans la gouttière, jamais dans la colonne : les quatre étapes
   gardent la même largeur, et la dernière n'en traîne pas une de trop. Elle est
   tracée en deux pseudo-éléments — la hampe et la pointe — parce que « → » tombe
   en tofu dans Instrument Sans, qui ne porte pas les flèches. */
.parcours .etape + .etape::before,
.parcours .etape + .etape::after {
  content: "";
  position: absolute;
  right: 100%;
}
.parcours .etape + .etape::before {
  top: 22px;
  width: var(--s5);
  height: 1px;
  background: var(--pion-fleche);
}
.parcours .etape + .etape::after {
  top: 19px;
  width: 6px;
  height: 6px;
  border-top: var(--hairline) solid var(--pion-fleche);
  border-right: var(--hairline) solid var(--pion-fleche);
  rotate: 45deg;
}
.etape-pion {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: var(--hairline) solid var(--pion-line);
  border-radius: var(--r3);
  background: var(--pion-bg);
  color: var(--accent);
}
.etape-pion svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.parcours .etape b { font-size: var(--fs-md); font-weight: 600; color: var(--on-plate); }
.etape-dit { font-size: var(--fs-sm); line-height: 1.45; color: var(--on-plate-2); }

/* --- Le socle : trois faits vérifiables, sur l'encre --- */

.socle {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5);
  margin: 0;
  padding: var(--s5) var(--s7);
  list-style: none;
  background: var(--socle-bg);
  color: var(--socle-ink);
}
.socle li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s1) var(--s3);
  align-items: center;
  padding-left: var(--s5);
  border-left: var(--hairline) solid var(--socle-rule);
}
.socle li:first-child { padding-left: 0; border-left: 0; }
.socle svg {
  grid-row: 1;
  width: 19px;
  height: 19px;
  fill: none;
  stroke: var(--socle-icone);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.socle b { grid-row: 1; font-size: var(--fs-h2); font-weight: 600; }
.socle span {
  grid-column: 1 / -1;
  font-size: var(--fs-tiny);
  line-height: 1.5;
  color: var(--socle-ink-2);
}

/* --- Le guichet --- */

.guichet {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s7) var(--s6);
  background: var(--surface);
}
/* Deux disques pâles débordant du bord droit : ils donnent un fond au guichet
   sans rien y écrire. Le z-index n'est pas décoratif — `::after` est le dernier
   enfant du guichet, et sans lui le disque du bas passerait par-dessus le
   formulaire dès que la fenêtre se resserre. */
.guichet::before,
.guichet::after {
  content: "";
  position: absolute;
  right: 0;
  z-index: 0;
  border-radius: var(--r3);
  background: var(--halo);
}
.guichet::before { width: 320px; height: 320px; top: 0; translate: 44% -46%; }
.guichet::after { width: 420px; height: 420px; bottom: 0; translate: 40% 50%; }

.acces { position: relative; z-index: 1; width: 100%; max-width: 440px; }
.acces h2 {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
}
.acces .intro { margin-bottom: var(--s2); }
.acces .errorlist { margin: 0; padding: 0; list-style: none; color: var(--warn-ink); font-size: var(--fs-sm); }
.acces .field .tiny.warn { color: var(--warn-ink); }
.acces .field ul { margin: 0; padding-left: var(--s4); }
.acces .field > label { font-weight: 600; color: var(--ink); }
/* Les formulaires de compte laissent Django rendre ses propres <input>. */
.acces .field input:not(.inp) {
  height: var(--ctrl-lg);
  padding: 0 var(--s3);
  border: var(--hairline) solid var(--line-2);
  border-radius: var(--r1);
  background: var(--surface);
  box-shadow: var(--inset);
  width: 100%;
}

/* --- Les champs de la connexion, marqués d'une icône --- */

.champ { position: relative; }
.champ .inp { height: var(--ctrl-lg); padding-left: var(--s7); }
.champ-icone {
  position: absolute;
  top: 50%;
  left: var(--s4);
  translate: 0 -50%;
  width: 17px;
  height: 17px;
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}
.champ-mdp .inp { padding-right: var(--s6); }
.voir {
  position: absolute;
  top: 50%;
  right: var(--s2);
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: var(--r1);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.voir svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.voir .oeil-barre { display: none; }
.voir[aria-pressed="true"] .oeil-ouvert { display: none; }
.voir[aria-pressed="true"] .oeil-barre { display: block; }
.voir:hover { color: var(--accent-ink); background: var(--surface-2); }
.voir:focus-visible { outline: none; box-shadow: var(--ring); }

.btn.grand { height: var(--ctrl-lg); font-size: var(--fs-md); }
.btn-icone {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.acces-pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2) var(--s4);
}
.garde {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--f-mono);
  font-size: var(--fs-tiny);
  color: var(--muted);
}
.garde .pastille {
  width: 7px;
  height: 7px;
  border-radius: var(--r3);
  background: var(--ok);
}
.garde .sep { color: var(--line-2); }

.acces .banner { align-items: flex-start; }
.banner-icone {
  flex: none;
  margin-top: 1px;
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Sous 1180px la planche se resserre : le parcours prend presque toute sa
   largeur, et le voile oblique doit le suivre — sans quoi « Rapport » se lit sur
   les grains en pleine lumière. Les flèches tombent, la rangée pouvant passer à
   la ligne : une flèche en tête de seconde ligne ne relierait plus rien. */
@media (max-width: 1180px) {
  .porte-grille { grid-template-columns: 1.2fr 1fr; }
  .planche-corps { padding: var(--s5) var(--s6); }
  .planche::before {
    background:
      linear-gradient(
        96deg,
        var(--plate-veil-fort)  0%,
        var(--plate-veil-fort) 34%,
        var(--plate-veil-mi)   66%,
        var(--plate-veil-fin)  92%,
        transparent           100%
      ),
      linear-gradient(0deg, var(--plate-veil-mi) 0%, transparent 34%),
      linear-gradient(180deg, var(--plate-veil-haut) 0%, transparent 32%);
  }
  .parcours { flex-wrap: wrap; gap: var(--s4); }
  .parcours .etape { width: 120px; }
  .parcours .etape + .etape::before,
  .parcours .etape + .etape::after { content: none; }
  .socle { padding: var(--s4) var(--s6); gap: var(--s4); }
  .socle li { padding-left: var(--s4); }
  .socle b { font-size: var(--fs-md); }
}

@media (max-width: 900px) {
  .porte-grille { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; }
  .planche { min-height: 60vh; }
  .planche h1 { max-width: 24ch; }
  .guichet { padding: var(--s6) var(--s5); }
  .acces { max-width: 440px; }
}

@media (max-width: 640px) {
  .planche { min-height: 0; }
  .planche p, .parcours { display: none; }
  .socle { grid-template-columns: minmax(0, 1fr); gap: var(--s3); padding: var(--s4) var(--s5); }
  .socle li { padding-left: 0; border-left: 0; }
  .socle span { display: none; }
}

/* --- Tableau de bord ------------------------------------------------------
   L'écran s'ouvre sur la paillasse : une photographie de laboratoire posée en
   fond du bandeau de titre, éteinte en fondu vers la gauche et vers le bas.
   Elle dit ce que l'application mesure ; elle ne porte aucune donnée et
   reste donc `aria-hidden` par construction (pseudo-éléments). --- */
.bureau { position: relative; }
.bureau > * { position: relative; z-index: 1; }
.bureau::before,
.bureau::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
}
.bureau::before {
  top: calc(var(--marge-page) * -1);
  right: calc(var(--marge-page) * -1);
  left: 48%;
  height: 400px;
  background: url("../img/paillasse.jpg") center 74% / cover no-repeat;
  opacity: 0.82;
  /* Deux fondus croisés : la photographie s'éteint vers la gauche, où le titre
     se lit, et vers le bas, où commencent les chiffres. */
  -webkit-mask-image: linear-gradient(to right, transparent 4%, var(--masque-plein) 46%), linear-gradient(to bottom, var(--masque-plein) 58%, transparent 98%);
  mask-image: linear-gradient(to right, transparent 4%, var(--masque-plein) 46%), linear-gradient(to bottom, var(--masque-plein) 58%, transparent 98%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.bureau::after {
  right: calc(var(--marge-page) * -1);
  bottom: calc(var(--s7) * -1);
  width: 290px;
  height: 180px;
  background: url("../img/gravier.jpg") center bottom / cover no-repeat;
  mix-blend-mode: multiply;
  -webkit-mask-image: radial-gradient(80% 92% at 74% 94%, var(--masque-plein) 22%, transparent 70%);
  mask-image: radial-gradient(80% 92% at 74% 94%, var(--masque-plein) 22%, transparent 70%);
  opacity: 0.45;
}

/* Quatre cartes de comptage. Le filet du bas est l'état : accent tant qu'il y a
   de la matière, gris quand le compteur est à zéro, ambre quand il faut agir. */
.kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s4);
  margin-bottom: var(--s5);
}
.mesure {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s4) var(--s4) var(--s5);
  background: var(--surface);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r2);
  box-shadow: var(--e1);
}
.mesure::after {
  content: "";
  position: absolute;
  left: var(--s4);
  bottom: var(--s3);
  width: 30px;
  height: 3px;
  border-radius: var(--r3);
  background: var(--accent);
}
.mesure.calme::after { background: var(--line-2); }
.mesure.alerte::after { background: var(--warn); }
.mesure-pic {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r3);
  background: var(--accent-sft);
  color: var(--accent-ink);
}
.mesure-pic .ic { width: 22px; height: 22px; }
.mesure.alerte .mesure-pic { background: var(--warn-sft); color: var(--warn-ink); }
.mesure-dit { display: flex; flex-direction: column; gap: var(--s0); min-width: 0; }
/* Ce sont des dénombrements, pas des mesures : ils restent en linéale. La
   fonte à chasse fixe est réservée aux grandeurs mesurées. */
.mesure .v {
  font-size: var(--fs-metric);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: var(--tr-metric);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.mesure .k {
  font-size: var(--fs-caps);
  font-weight: 600;
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--muted);
}
.mesure-echo { color: var(--accent); opacity: 0.16; }
.mesure-echo .ic { width: 24px; height: 24px; }
.mesure.alerte .mesure-echo { color: var(--warn); }

.suite { display: inline-flex; align-items: center; gap: var(--s1); white-space: nowrap; }
.suite .ic { width: 15px; height: 15px; }

/* La vignette rappelle la planche : on reconnaît un échantillon à sa photo
   avant de lire sa référence. */
.cellule-ech { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
.vignette {
  width: var(--vignette-l);
  height: var(--vignette-h);
  flex: none;
  border-radius: var(--r1);
  border: var(--hairline) solid var(--line);
  background: var(--surface-2);
  overflow: hidden;
}
.vignette img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tb-ech td { padding-block: var(--s2); }

/* Rien à traiter n'est pas un vide à meubler : le dessin dit que la relecture
   est faite, la phrase dit ce qui reste. */
.rien {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  padding: var(--s5) var(--s3) var(--s4);
  text-align: center;
}
.rien-dessin { width: 152px; height: 116px; }
.rien-dessin .d-feuille,
.rien-dessin .d-trait,
.rien-dessin .d-loupe,
.rien-dessin .d-manche,
.rien-dessin .d-etoile {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.rien-dessin .d-feuille { fill: var(--accent-sft); stroke-opacity: 0.45; }
.rien-dessin .d-trait { stroke-opacity: 0.4; }
.rien-dessin .d-loupe { fill: var(--surface); fill-opacity: 0.88; stroke-opacity: 0.7; }
.rien-dessin .d-manche { stroke-width: 3.6; stroke-opacity: 0.7; }
.rien-dessin .d-etoile { stroke-opacity: 0.42; }

.reprise { display: grid; grid-template-columns: 128px minmax(0, 1fr) auto; gap: var(--s5); align-items: center; }
.reprise .thumb { width: 128px; height: 96px; }

/* Le tableau des échantillons porte cinq colonnes : plutôt que de le faire
   défiler sous un rail de 380 px, on rend la pleine largeur à la liste. */
@media (max-width: 1180px) {
  .bureau .cols.b { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1100px) {
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* La photographie de paillasse n'a plus la place de se déployer : elle sort
   plutôt que de se recadrer en timbre derrière les chiffres. */
@media (max-width: 900px) {
  .bureau::before, .bureau::after { display: none; }
}
@media (max-width: 560px) {
  .kpis { grid-template-columns: minmax(0, 1fr); }
}

/* --- Liste des projets : des lignes de registre --- */
.plist { display: flex; flex-direction: column; }
.prow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px 120px 150px 90px;
  gap: var(--s5);
  align-items: center;
  padding: var(--s4);
  border-bottom: var(--hairline) solid var(--line);
  transition: background-color var(--t-fast) var(--ease);
}
.plist .prow:first-child { border-top: var(--hairline) solid var(--line); }
.prow:hover { background: var(--surface-2); text-decoration: none; }
.prow .nm { font-size: var(--fs-body); font-weight: 500; color: var(--ink); }
.prow .rf { font-family: var(--f-mono); font-size: var(--fs-tiny); color: var(--muted); }
.prow.arch { opacity: 0.65; }

/* --- Fiche projet --- */
.tabs { display: flex; gap: var(--s5); border-bottom: var(--hairline) solid var(--line); margin-bottom: var(--s5); }
.tab {
  padding: 0 0 var(--s2);
  font-size: var(--fs-body);
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tab.on { color: var(--ink); border-color: var(--accent); font-weight: 500; }
.tab:hover { text-decoration: none; color: var(--ink); }

/* --- Nouveau projet --- */
.recap dt { color: var(--muted); }

/* --- Fiche échantillon --- */
.drop {
  border: var(--hairline) dashed var(--line-2);
  border-radius: var(--r2);
  padding: var(--s5);
  text-align: center;
  color: var(--muted);
  font-size: var(--fs-sm);
}
.echthumb { width: 96px; height: 96px; }

/* --- Calibration --- */
.pick { cursor: crosshair; }
.qc {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-bottom: var(--hairline) dashed var(--line);
  font-size: var(--fs-sm);
}
.qc:last-child { border-bottom: 0; }
.qc .st { font-family: var(--f-mono); font-size: var(--fs-sm); width: 14px; }
.qc .val { margin-left: auto; font-family: var(--f-mono); font-size: var(--fs-tiny); color: var(--muted); }
.ok { color: var(--ok-ink); }
.ko { color: var(--warn-ink); }

.calibwrap { position: relative; display: block; }
.calibwrap img { display: block; width: 100%; height: auto; }
.calibwrap svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.calibwrap.pick { cursor: crosshair; }

/* --- Descripteurs --- */
.cls4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4); }
.clsbox { padding-bottom: var(--s2); border-bottom: var(--hairline) solid var(--line); }
.clsbox .v {
  font-family: var(--f-mono);
  font-size: var(--fs-lg);
  letter-spacing: var(--tr-metric);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.clsbox .k {
  font-size: var(--fs-caps);
  font-weight: 600;
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--muted);
}
.seuils { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }

/* --- Figures et comparaison --- */
.figs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.radwrap { display: grid; grid-template-columns: minmax(0, 1fr) 150px; gap: var(--s4); }
.radlist { display: grid; gap: var(--s1); align-content: center; }
.radrow {
  display: flex;
  justify-content: space-between;
  gap: var(--s3);
  font-size: var(--fs-sm);
  border-bottom: var(--hairline) dashed var(--line);
  padding-bottom: var(--s1);
}
.radrow b { font-family: var(--f-mono); font-weight: 400; }
.sel { display: flex; flex-wrap: wrap; gap: var(--s2); }
.lgd { display: grid; gap: var(--s1); align-content: center; font-size: var(--fs-sm); }
.lgd .row { display: flex; align-items: center; gap: var(--s2); }
.lgd .sw { width: 12px; height: 3px; border-radius: var(--r3); }

/* --- Granulométrie --- */
.dtab { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s4); }
.dbox { padding-bottom: var(--s2); border-bottom: var(--hairline) solid var(--line); }
.dbox .v {
  font-family: var(--f-mono);
  font-size: var(--fs-h2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink);
}
.dbox .k {
  font-size: var(--fs-caps);
  font-weight: 600;
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  color: var(--muted);
}
.mfrow { display: grid; grid-template-columns: 1fr 1fr auto; gap: var(--s3); align-items: end; }

/* --- Essais mécaniques --- */
.saisie { display: grid; grid-template-columns: minmax(0, 1fr) 120px; gap: var(--s2) var(--s3); align-items: center; }
.saisie label { font-size: var(--fs-sm); color: var(--ink-2); }
.saisie .inp { height: var(--ctrl-sm); font-size: var(--fs-sm); text-align: right; }
.res { display: flex; align-items: baseline; gap: var(--s3); }
.res .v {
  font-family: var(--f-mono);
  font-size: var(--fs-metric);
  letter-spacing: var(--tr-metric);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.res .u { font-size: var(--fs-sm); color: var(--muted); }

/* --- Livrables -------------------------------------------------------------
   L'écran s'ouvre sur ce qu'il produit : une pile de feuillets, la tuile Word et
   la tuile Excel, dessinées et posées en tête à droite. Le dessin dit la sortie,
   il ne porte aucune donnée — d'où `aria-hidden` sur la figure entière. --- */
.livrables { position: relative; }
.livrables > * { position: relative; z-index: 1; }
.livrables-decor {
  position: absolute;
  z-index: 0;
  top: calc(var(--s5) * -1);
  right: calc(var(--marge-page) * -1);
  width: 400px;
  pointer-events: none;
}
.livrables-decor svg { display: block; width: 100%; height: auto; }
.livrables-decor .d-fond { fill: var(--accent-sft); opacity: 0.5; }
.livrables-decor .d-page { fill: var(--surface); stroke: var(--accent-sft); stroke-width: 2; }
.livrables-decor .d-ligne { fill: var(--accent-sft); }
.livrables-decor .d-barre { fill: var(--accent); opacity: 0.35; }
.livrables-decor .d-courbe { fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-linecap: round; opacity: 0.5; }
.livrables-decor .d-tuile.w { fill: var(--accent); }
.livrables-decor .d-tuile.x { fill: var(--ok); }
.livrables-decor .d-lettre {
  fill: var(--on-accent);
  font-family: var(--f-sans);
  font-size: var(--fs-lg);
  font-weight: 600;
}
.livrables-decor .d-feuillage { fill: var(--accent); opacity: 0.18; }

/* La colonne de gauche s'arrête avant le dessin : le titre ne passe jamais
   dessous, et le paragraphe garde sa longueur de lecture. */
.livrables .pagehead { max-width: 62ch; }
.livrables-blocage { margin-bottom: var(--s5); }

/* Le rang d'une section du rapport se lit comme un repère, pas comme une
   mesure : jeton rond, chiffre centré, largeur fixe pour que la colonne des
   titres parte au même endroit d'une ligne à l'autre. */
.tb-plan .rang {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: var(--r3);
  background: var(--accent-sft);
  color: var(--accent-ink);
  font-family: var(--f-mono);
  font-size: var(--fs-tiny);
}
.tb-plan td { vertical-align: middle; }

/* Une option cochée montre sa coche ; décochée, elle montre l'anneau vide qui
   dit qu'elle est cochable. La couleur ne porte jamais l'information seule. */
.opts { display: flex; flex-wrap: wrap; gap: var(--s2); }
.opts .btn { gap: var(--s2); }
.opts .coche {
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  flex: none;
  border: var(--hairline) solid var(--line-2);
  border-radius: var(--r3);
}
.opts .coche svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  visibility: hidden;
}
.opts .btn.on .coche { border-color: transparent; }
.opts .btn.on .coche svg { visibility: visible; }

/* Un livrable se reconnaît à sa tuile avant son nom : bleu pour le rapport
   Word, vert pour le classeur Excel, comme les deux applications qui l'ouvrent. */
.file {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) auto;
  gap: var(--s3);
  align-items: center;
  padding: var(--s3);
  border: var(--hairline) solid var(--line);
  border-radius: var(--r1);
  box-shadow: var(--e1);
  background: var(--surface);
}
.file .ext {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r1);
  background: var(--surface-2);
  color: var(--ink-2);
  font-weight: 600;
  font-size: var(--fs-md);
}
.file .ext.docx { background: var(--accent); color: var(--on-accent); }
.file .ext.xlsx { background: var(--ok); color: var(--on-accent); }
.file .strong { overflow-wrap: anywhere; }

/* Trois colonnes de texte ne tiennent pas dans ce qui reste à gauche d'un rail
   de 380 px : la liste reprend la pleine largeur avant que le tableau ne se
   mette à défiler sous lui-même. */
@media (max-width: 1180px) { .livrables .cols.b { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 1240px) { .livrables-decor { width: 320px; } }
/* Sous ce palier, le dessin mordrait sur le titre : il sort plutôt que de se
   glisser derrière le texte. */
@media (max-width: 1080px) { .livrables-decor { display: none; } }

/* --- Assistance (M12) --- */
.assist { background: var(--surface-2); border-radius: var(--r2); padding: var(--s5); }
.off { opacity: 0.45; pointer-events: none; }
.prop {
  border: var(--hairline) solid var(--line-2);
  border-radius: var(--r1);
  padding: var(--s3);
  background: var(--surface);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}
.prop.texte { max-height: 210px; overflow: auto; }
.champs { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: var(--s2) var(--s3); align-items: center; font-size: var(--fs-sm); }
.champs .v { font-family: var(--f-mono); font-size: var(--fs-sm); }
.big { display: flex; align-items: center; gap: var(--s3); }
.big .t { font-size: var(--fs-body); font-weight: 500; color: var(--ink); }

/* Calibration : planche dominante et synthèse latérale, selon la référence. */
.main:has([data-ecran="calibration"]) { max-width: none; }
.main:has([data-ecran="calibration"]) .rail .etape { flex: 1 0 148px; min-height: 64px; }
.main:has([data-ecran="calibration"]) .rail .next-step { display: none; }
.main:has([data-ecran="calibration"]) h1 { font-size: var(--calib-titre); }
.main:has([data-ecran="calibration"]) .tete-pic { background: transparent; }
.main:has([data-ecran="calibration"]) .tete-pic .ic { width: 34px; height: 34px; }
.cols.b[data-ecran="calibration"] { grid-template-columns: minmax(0, 1.86fr) minmax(330px, 1fr); }
[data-ecran="calibration"] > .card > .toolbar { padding: var(--calib-outil-padding); gap: var(--s2); align-items: center; }
[data-ecran="calibration"] > .card > .toolbar .btn { min-height: 38px; height: auto; padding: var(--s2) var(--calib-outil-padding); font-size: var(--fs-sm); }
[data-ecran="calibration"] > .card > .toolbar > span { display: inline-flex; align-items: center; gap: var(--s2); padding: var(--s2); }
[data-ecran="calibration"] > .card > .bd { padding: var(--calib-image-padding-haut) var(--calib-marge) var(--s4); }
[data-ecran="calibration"] .frame { position: relative; background: var(--calib-image-fond); }
[data-ecran="calibration"] [data-defilement] { overflow: auto; max-height: 62vh; min-height: 370px; display: grid; align-items: center; }
[data-ecran="calibration"] .calibwrap { width: 100%; }
[data-ecran="calibration"] .frame > .toolbar { position: absolute; top: 14px; right: 14px; z-index: 2; }
[data-ecran="calibration"] .frame .btn { background: var(--calib-outil-fond); color: var(--calib-outil-encre); border: 0; width: 38px; height: 38px; padding: var(--s2); }
[data-ecran="calibration"] .frame .btn:disabled { opacity: .45; }
[data-ecran="calibration"] .frame:fullscreen { width: 100%; height: 100%; display: grid; align-items: center; }
[data-ecran="calibration"] .frame:fullscreen [data-defilement] { max-height: 100vh; }
[data-ecran="calibration"] #calibration-etat h2 { font-size: var(--calib-sous-titre); }
[data-ecran="calibration"] #calibration-etat .hd { align-items: center; }
[data-ecran="calibration"] #calibration-etat .kv { row-gap: var(--s3); }
[data-ecran="calibration"] #calibration-etat .kv dd { font-family: var(--f-sans); font-weight: 600; }
[data-ecran="calibration"] #calibration-etat .btn.wide { min-height: 42px; height: auto; white-space: normal; }
[data-ecran="calibration"] [data-qualite] { background: var(--accent-sft); }
[data-ecran="calibration"] summary { cursor: pointer; list-style: none; padding: var(--calib-marge) var(--calib-resume-padding); display: flex; gap: var(--calib-note-padding); align-items: center; }
[data-ecran="calibration"] summary::-webkit-details-marker { display: none; }
[data-ecran="calibration"] summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
[data-ecran="calibration"] [data-qualite] summary > span:last-child { font-size: var(--calib-chevron); }
[data-ecran="calibration"] [data-qualite][open] summary > span:last-child { transform: rotate(90deg); }
[data-ecran="calibration"] #calibration-etat > .card > .ft { margin: 0 var(--calib-marge) var(--calib-marge); border: 0; border-radius: var(--r1); padding: var(--calib-note-padding); background: var(--accent-sft); }
@media (max-width: 1150px) {
  .cols.b[data-ecran="calibration"] { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 600px) {
  [data-ecran="calibration"] [data-defilement] { min-height: 180px; }
  [data-ecran="calibration"] > .card > .toolbar { align-items: stretch; }
  [data-ecran="calibration"] > .card > .toolbar > form { width: 100%; }
  [data-ecran="calibration"] > .card > .toolbar .btn { width: 100%; }
  [data-ecran="calibration"] #calibration-etat .hd { flex-wrap: wrap; }
}

.main:has([data-ecran="calibration"]) .rail .etape { flex-basis: 164px; grid-template-columns: 24px minmax(0, 1fr); }
.main:has([data-ecran="calibration"]) .rail .jalon,
.main:has([data-ecran="calibration"]) .rail .etape-fleche { display: none; }
.main:has([data-ecran="calibration"]) .rail .t { white-space: normal; }
[data-ecran="calibration"] .fig { margin: 0; }
