/* ═══════════════════════════════════════════════════════════════════════════
   LISA Lab — le suivi des dossiers d'essai : tableau de bord et fiche

   Une feuille par écran, comme css/courriels.css et css/chatVisio.css. Celle-ci
   couvre les deux faces d'un même objet — la liste des dossiers et la fiche
   qu'on ouvre depuis elle — parce que la frise d'avancement paraît dans les
   deux et qu'un second fichier la ferait diverger d'elle-même.

   main.css n'est pas touché : il porte des caractères abîmés qu'on conserve
   octet pour octet, et son empreinte SHA-256 est figée par
   scripts/verif-ergonomie-fiche.js. Tout ce qui suit s'ajoute par-dessus.

   Aucune ressource extérieure : ni police, ni image, ni adresse. Les teintes
   reprennent les variables de la maison déclarées dans :root (main.css), à
   l'exception des deux déclarées ici et justifiées sur place.

   Et AUCUNE valeur de couleur écrite ici n'est inventée : chacune paraît déjà
   telle quelle dans main.css ou finitions.css. Aucun dégradé n'y est défini du
   tout — les bandeaux emploient les trois degrés de finitions.css, ils ne les
   recopient pas. C'est la règle que scripts/verif-frise-dossiers.js fait
   respecter, pour qu'une quatrième convention de bandeau, ressemblante mais
   jamais coïncidente, ne puisse pas réapparaître.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* L'encre des pastilles franchies de la frise. Le turquoise de la maison
     (--color-primary) ne tient pas 3:1 sur blanc quand il ne sert qu'à
     remplir un disque de 10 px ; celle-ci est sa version assombrie, déjà
     employée par --color-primary-h, désignée et non recopiée pour qu'une
     montée de palette l'emmène avec elle. */
  --frise-franchi: var(--color-primary-h);

  /* Le filet qui relie deux jalons non franchis. Plus clair que
     --color-border, qui est une bordure de cadre : un filet de liaison posé
     à la même valeur se lit comme le bord d'une cellule. La valeur n'est pas
     dosée ici — c'est celle que finitions.css donne déjà à ses filets de
     séparation (hr, .separateur, les sous-titres de section). */
  --frise-attente: #cfd9e4;
}

/* ── Le texte que seule une synthèse vocale lit ───────────────────────────────
   La frise dit son avancement en teinte ET en mots. Aucun écran de la maison
   ne portait encore cette classe ; elle reprend le nom employé par le portail
   client (public/portail/portail.css) pour que le même besoin garde le même
   nom des deux côtés. */
.hors-ecran {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  border: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   1. LA LÉGENDE DU SUIVI, AU DEUXIÈME DEGRÉ
   ═══════════════════════════════════════════════════════════════════════════

   La maison compte trois degrés de bandeau, définis et commentés dans
   css/finitions.css : le premier pour le nom d'un écran ou d'une fiche
   (.modal-header), le deuxième pour l'affaire (.suivi-entete), le troisième
   pour les titres de bloc et de section. La ligne de légende du tableau de
   suivi est au deuxième.

   Elle emploie donc .suivi-entete, et rien n'est recopié ici de son dégradé ni
   de ses teintes : un habillage recopié cesse de suivre le jour où le degré
   est retouché, et la ressemblance survit à la parenté. Ce qui suit ne corrige
   que ce que l'usage du degré 2 HORS d'une carte bordée laisse de travers. */

/* Le modificateur ne nomme pas un contenu mais une SITUATION : un bandeau de
   degré 2 qui ne coiffe aucune carte. finitions.css le remonte d'un pixel sur
   trois côtés et n'arrondit que ses deux coins hauts, parce qu'il y vient
   épouser le bord d'une carte bordée. Posé seul, la remontée mord sur ce qui
   le précède, et deux coins carrés sur quatre se lisent comme un bandeau
   tronqué. Rien d'autre n'est corrigé : ni la teinte, ni le dégradé, ni le
   bâtonnet, ni l'encre — tout cela reste au degré.

   La classe est doublée dans le sélecteur pour passer devant « body
   .suivi-entete », que finitions.css pose en !important : à poids égal, c'est
   l'ordre de chargement qui trancherait, et l'ordre des feuilles n'est pas une
   chose sur laquelle s'appuyer. */
body .suivi-entete.suivi-entete--flottant {
  margin: 0 0 10px !important;
  border-radius: var(--radius-lg) !important;
}

/* La ligne garde la hauteur que finitions.css lui réserve — sans filtre, le
   tableau ne doit pas remonter d'une ligne à chaque frappe — mais perd la
   remontée négative qui la collait sous les filtres : dans un bandeau, elle la
   ferait chevaucher la bordure. */
.suivi-entete--flottant .resume-filtre { margin: 0; font-size: 13px; }

/* Le bouton « Tout afficher » que js/dashboard.js dépose dans la ligne est un
   bouton fantôme, dessiné pour le blanc. Sur l'ardoise du degré 2 il ne se
   verrait plus. Il reprend l'encre du bandeau par héritage plutôt que par une
   valeur écrite : aucune teinte n'est donc introduite, et celle du degré reste
   la seule source. */
.suivi-entete--flottant .btn {
  color: inherit;
  border-color: currentColor;
  background: transparent;
}
.suivi-entete--flottant .btn:hover { text-decoration: underline; }

/* ── Ce qui explique, en retrait ──────────────────────────────────────────────
   Un rappel de lecture expose une règle ; il ne dit rien de l'état du moment.
   Lui donner un degré le mettrait au rang d'un titre de section — et ce qui
   change vraiment cesserait de se détacher. Un retrait et un filet suffisent,
   aux teintes déjà déclarées par main.css.

   AUCUN ÉCRAN N'EN PORTE PLUS : le tableau de bord en avait deux sous sa ligne
   de légende, la fiche d'essai trois sous sa progression, et le propriétaire
   les a tous fait retirer après les avoir vus en situation. Les règles qu'ils
   énonçaient, elles, restent dites en commentaire là où elles s'appliquent.

   La règle reste écrite ici, et ce n'est pas un oubli : elle est la seule mise
   en page que la maison ait arrêtée pour un texte de ce genre, et la réécrire
   le jour où il en faudra un reviendrait à en inventer une seconde. */
.notes-suivi {
  margin: 0 0 14px;
  padding-left: 13px;
  border-left: 2px solid var(--color-border);
}
.notes-suivi p { margin: 0; font-size: 12px; line-height: 1.5; }
.notes-suivi p + p { margin-top: 5px; }
.notes-suivi strong { font-weight: 600; }

/* ═══════════════════════════════════════════════════════════════════════════
   2. LE TABLEAU DE BORD
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── La ligne de filtres ──────────────────────────────────────────────────────
   `.select` vaut 100 % de large dans main.css : la liste des statuts prenait
   donc toute la ligne et repoussait la corbeille sur la sienne. Elle reprend
   ici sa largeur propre, et la corbeille est poussée au bout par la marge
   automatique plutôt que par un espaceur vide — un espaceur se serait fait
   lire comme une cellule par une synthèse vocale. */
.filters-bar--dossiers { flex-wrap: nowrap; align-items: center; }
.filters-bar--dossiers .input-search { flex: 1 1 22rem; max-width: none; }
.filters-bar--dossiers .select { width: auto; min-width: 13rem; flex: 0 0 auto; }
/* Sur un seul rang, c'est la croissance de la recherche qui pousse la corbeille
   au bout : lui ajouter une marge automatique ferait tenir l'alignement par
   deux mécanismes à la fois, dont aucun ne pourrait plus être éprouvé seul. */
.filters-bar--dossiers #btn-corbeille-essais { flex: 0 0 auto; }

/* Sous 900 px la ligne s'enroule : trois commandes sur un rang y deviennent
   trois commandes illisibles. L'ordre d'enroulement garde la recherche en
   tête, qui est la commande la plus employée. */
@media (max-width: 900px) {
  .filters-bar--dossiers { flex-wrap: wrap; }
  .filters-bar--dossiers .input-search { flex: 1 1 100%; }
  .filters-bar--dossiers #btn-corbeille-essais { margin-left: auto; }
}

/* ── Les quatre panneaux d'état ───────────────────────────────────────────────
   Quatre cartes grises et muettes : on lisait le chiffre sans savoir s'il
   était bon. Chacune porte maintenant un filet de couleur sur sa tranche
   gauche — la même teinte que les pastilles de statut du tableau, de sorte que
   l'œil fasse le lien — et le chiffre est tabulaire pour que quatre nombres
   de largeurs différentes restent alignés d'un rafraîchissement à l'autre.

   Le filet est un REDOUBLEMENT du libellé, jamais son remplaçant : le libellé
   reste écrit en toutes lettres sous le chiffre. */
#tab-dashboard .stats-strip { gap: 14px; }

#tab-dashboard .stat-card {
  position: relative; overflow: hidden;
  padding-left: 22px;
  transition: border-color .15s ease, box-shadow .15s ease;
}

#tab-dashboard .stat-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
  background: var(--color-border);
}

#tab-dashboard .stat-card:hover {
  border-color: var(--frise-attente);
  /* L'ombre des cartes de la maison, reprise telle quelle de finitions.css
     plutôt que dosée à nouveau : deux ombres voisines mais inégales se voient
     dès qu'elles se côtoient sur le même écran. */
  box-shadow: 0 1px 2px rgba(16, 32, 48, .06), 0 2px 8px rgba(16, 32, 48, .05);
}

#tab-dashboard .stat-value {
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  color: var(--color-text);
}

/* Le libellé passe au-dessus du chiffre : on lit d'abord ce qu'on compte,
   puis combien. L'inverse obligeait à redescendre des yeux pour savoir de
   quoi le nombre parlait. L'ordre du document ne bouge pas — c'est celui que
   lit une synthèse vocale, et le chiffre y reste premier, nommé par son
   libellé. */
#tab-dashboard .stat-card { flex-direction: column-reverse; justify-content: flex-end; }

#tab-dashboard .stat-label {
  text-transform: uppercase; letter-spacing: .04em;
  font-size: 11px; font-weight: 600; color: var(--color-text-2);
}

/* Les quatre tranches. « En cours » et « Rapports envoyés » reprennent les
   teintes des statuts correspondants du tableau ; « En attente lecture »
   celle de l'attente ; « Non conformes » celle du danger, déjà portée par
   .stat-card--danger sur le chiffre. */
#tab-dashboard .stat-card--en-cours::before        { background: var(--statut-odm); }
#tab-dashboard .stat-card--attente-lecture::before { background: var(--statut-lecture); }
#tab-dashboard .stat-card--danger::before          { background: var(--color-danger); }
#tab-dashboard .stat-card--rapports::before        { background: var(--statut-rapport); }

@media (max-width: 760px) {
  #tab-dashboard .stats-strip { grid-template-columns: repeat(2, 1fr); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   2 bis. UN DOSSIER, DEUX LIGNES
   ═══════════════════════════════════════════════════════════════════════════

   La frise tenait une colonne large de trente-quatre rem et n'en laissait pas
   assez à la référence du dossier ni au nom du client. Elle est descendue sur
   une seconde ligne, sous les colonnes de données, et la première est revenue à
   la hauteur ordinaire de la maison — les onze pixels de creux que main.css
   donne à toute cellule, qu'il n'y a donc plus lieu de redire ici.

   Tout ce qui suit sert une seule fin : que les DEUX lignes se lisent comme un
   dossier et non comme deux. */

/* Le filet de séparation est porté par la seconde ligne, qui ferme le dossier,
   et retiré de la première : main.css en pose un sous chaque cellule et
   finitions.css un au-dessus de chaque ligne qui suit une autre. Laissés tels
   quels, ils traçaient un trait ENTRE la ligne de données et sa frise, et les
   donnaient pour deux dossiers distincts. */
#table-essais tbody tr.ligne-donnees td { border-bottom: 0; }
#table-essais tbody tr.ligne-avancement { border-top: 0; }

/* ── Ce qu'on lit d'abord, et ce qui vient ensuite ───────────────────────────
   Les deux lignes se valaient : même corps, même encre, même fond. La frise,
   large et colorée, prenait donc l'œil avant la référence du dossier et le nom
   du client, qui sont pourtant ce qu'on cherche en arrivant.

   LE FONCÉ N'ÉTAIT PAS DISPONIBLE POUR CELA, et c'est le seul point sur lequel
   la demande n'a pas été suivie telle quelle. La maison ordonne ses bandeaux
   par l'OBSCURITÉ, et l'obscurité y désigne un TITRE : ardoise pleine pour le
   nom d'un écran ou d'une fiche, ardoise claire pour l'affaire (.suivi-entete),
   gris moyen pour les titres de bloc — les trois degrés de css/finitions.css.
   Dans ce tableau-ci, --color-bg est de surcroît déjà la teinte des cellules
   d'en-tête. Assombrir la ligne de DONNÉES l'aurait donc fait lire comme un
   en-tête de dossier, et aurait ouvert une quatrième convention qui ressemble
   aux trois autres sans coïncider avec aucune.

   La hiérarchie se fait donc par où la grammaire des teintes la laisse faire :
   le CORPS, le POIDS et l'ENCRE sur la première ligne, qui garde le blanc de la
   feuille ; et c'est la SECONDE qui recule, sur l'aplat pâle de la maison. Le
   fond qui démarque existe bien — il est seulement de l'autre côté du joint. */

/* Le blanc de la ligne d'infos est ÉCRIT, et non laissé à l'héritage de la
   table : c'est lui qui fait du fond de la frise un retrait, et un fond qu'on
   ne déclare pas est un fond qu'on ne peut pas mesurer. Les règles de survol
   ci-dessous passent devant sans qu'on ait à les toucher, leurs sélecteurs
   portant tous une classe de plus que celui-ci. */
#table-essais tbody tr.ligne-donnees > td {
  background: var(--color-surface);
  font-size: 14px;
}

/* Les lignes d'appoint — code client, ville, numéro de série — ne suivent pas
   la montée : elles redisent ce que la ligne porte déjà, et les faire grossir
   avec elle aurait remis à plat la hiérarchie interne de la ligne. */
#table-essais tbody tr.ligne-donnees > td .text-muted { font-size: 12px; }

/* La référence du dossier : la donnée qu'on cherche en premier, et qui était
   écrite en onze pixels gris — la plus petite et la plus pâle de toute la
   ligne. Elle prend l'encre pleine, le plus fort corps du tableau et le gras.
   Chiffres tabulaires : une référence est une suite de nombres qu'on compare
   d'une ligne à l'autre, et des chiffres de largeurs inégales la décalent. */
.ref-dossier {
  font-size: 15px; font-weight: 700; color: var(--color-text);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}

/* La cellule de la frise : collée à la ligne qu'elle prolonge, et décalée de la
   largeur d'une gouttière pour qu'elle se lise comme un retrait sous les
   données plutôt que comme une rangée de plus. */
#table-essais tbody tr.ligne-avancement > td {
  padding-top: 0; padding-bottom: 13px; padding-left: 28px;
  /* L'aplat pâle de la maison : celui que main.css donne déjà à
     .badge-statut--demande, et sur lequel il a arbitré --color-text-3-aplat à
     4,86. Il est à 1,10:1 du blanc de la feuille, là où le plus clair des trois
     bouts du degré 2 en est à 5,01:1 — le retrait se voit sans jamais
     s'approcher de ce qui, dans la maison, signale un titre.

     Ce qu'il coûte, relevé et non supposé : le filet d'attente qui relie deux
     jalons (--frise-attente) descend de 1,43 à 1,30 sur ce fond. Il n'est pas
     redosé pour autant, parce que l'état d'un jalon ne tient pas à lui : il
     tient à la teinte du franchi, qui garde 5,82 sur cet aplat, et aux mots que
     la frise dit au lecteur d'écran. */
  background: #f1f5f9;
}

/* Le survol, et la prise de focus au clavier, prennent les DEUX lignes.
   Visées sur la CELLULE : main.css peint `.table tr:hover td`, et un fond posé
   sur la ligne resterait caché derrière celui des cellules. */
#table-essais tbody tr.ligne-donnees:hover > td,
#table-essais tbody tr.ligne-donnees:focus-within > td,
#table-essais tbody tr.ligne-donnees:hover + tr.ligne-avancement > td,
#table-essais tbody tr.ligne-donnees:focus-within + tr.ligne-avancement > td {
  background: var(--color-primary-fd);
}

/* Et dans l'autre sens, pour le pointeur posé sur la frise elle-même. Règle à
   part, et c'est délibéré : un navigateur qui ignorerait `:has()` rejette la
   TOTALITÉ de la règle où il paraît, et le mêler aux sélecteurs ci-dessus les
   emporterait avec lui — l'éclairage des deux lignes tomberait alors au lieu de
   se dégrader. Ici, au pire, le survol de la frise n'éclaire que la frise. */
#table-essais tbody tr.ligne-avancement:hover > td,
#table-essais tbody tr.ligne-donnees:has(+ tr.ligne-avancement:hover) > td {
  background: var(--color-primary-fd);
}

/* Les couples type de faisceau / énergie. Alignés à gauche : c'est une suite de
   codes qu'on lit, et non un nombre qu'on compare d'une ligne à l'autre. */
#table-essais .cellule-couples { white-space: normal; }
.couples-nc { color: var(--color-danger); font-weight: 700; }

/* ── La ligne s'ouvre ────────────────────────────────────────────────────────
   Le curseur est le seul signal que la souris reçoit : il n'y a plus de bouton
   « Voir » à viser. Posé sur les deux lignes du dossier, qui ouvrent toutes
   les deux.

   Rien ne touche à `user-select` : la sélection de texte dans une cellule
   reste celle du navigateur, et c'est le rendu qui écarte le clic-glisser. Une
   ligne rendue insélectionnable aurait réglé le même problème en supprimant la
   copie, qui est l'usage qu'on cherchait à préserver. */
#table-essais tbody tr.ligne-ouvrable { cursor: pointer; }

/* Le bouton d'ouverture : hors écran tant qu'il n'a pas le focus, à sa place
   dès qu'il l'a. Il remplace « Voir » dans l'ordre de tabulation sans occuper
   de place à l'œil, et c'est lui qui annonce la ligne comme ouvrable.

   Les mêmes déclarations que .hors-ecran ci-dessus, non mutualisées : la
   remise à l'état visible doit TOUT défaire, et une classe dont on ne connaît
   pas le contenu exact ne se défait pas à coup sûr. */
.ouvrir-dossier {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  border: 0; background: none; color: inherit;
  font: inherit; cursor: pointer;
}
.ouvrir-dossier:focus-visible {
  position: static; width: auto; height: auto;
  margin: 0 0 4px; padding: 3px 8px; overflow: visible;
  clip: auto; clip-path: none;
  display: block;
  border-radius: var(--radius);
  color: var(--color-primary);
  outline: 2px solid var(--color-primary); outline-offset: 1px;
  font-size: 11px; font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════════════
   3. LA FRISE D'AVANCEMENT
   ═══════════════════════════════════════════════════════════════════════════

   Le dessin du portail client, repris jalon pour jalon : une pastille par
   étape, reliée à la suivante, le libellé dessous, la date dessous encore.
   Les noms de classes sont préfixés « avancement- » et non « frise- » : main.css
   emploie déjà .frise, .frise-piste et .frise-libelle pour la frise du
   planning, qui est un diagramme de barres et n'a rien à voir. */

.avancement { display: flex; margin: 0; padding: 0; list-style: none; }

.avancement-jalon {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center;
  text-align: center; position: relative;
  padding: 0 2px;
}

/* Le filet de liaison. Posé sur le jalon et non entre deux jalons : un
   séparateur distinct se décalerait du disque dès que la hauteur de la ligne
   changerait. Le premier n'en porte pas — il n'y a rien avant lui. */
.avancement-jalon::before {
  content: ""; position: absolute; top: 5px; right: 50%; left: -50%;
  height: 2px; background: var(--frise-attente);
}
.avancement-jalon:first-child::before { display: none; }
.avancement-jalon--franchi::before { background: var(--frise-franchi); }

.avancement-point {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--color-surface);
  border: 2px solid var(--frise-attente);
  box-sizing: border-box; position: relative; z-index: 1;
}

.avancement-jalon--franchi .avancement-point {
  background: var(--frise-franchi); border-color: var(--frise-franchi);
}

/* L'étape en cours : un anneau, pour qu'elle se distingue des franchies
   autrement que par une nuance de la même teinte. Elle se dit aussi en
   mots — voir .hors-ecran dans le rendu — et son libellé passe en gras. */
.avancement-jalon--courant .avancement-point {
  background: var(--color-surface);
  border-color: var(--frise-franchi);
  box-shadow: 0 0 0 3px var(--color-primary-fd);
}

/* Les trois encres de la frise descendent d'un cran : c'est la seconde moitié
   du retrait, le fond n'en étant que la première. Seule l'étape du moment garde
   l'encre pleine — c'est la seule chose qu'on vient chercher dans une frise, et
   la seule qui ait à disputer le regard à la ligne du dessus.

   Elles sont RELEVÉES sur l'aplat #f1f5f9, pas sur le blanc : --color-text-3,
   qui tenait 4,88 sur blanc, n'y vaut plus que 4,46 et ne passe plus. D'où
   --color-text-3-aplat, que main.css a déclaré pour exactement ce cas et
   mesuré à 4,86 sur ce fond-là. */
.avancement-nom {
  margin-top: 5px; font-size: 10.5px; line-height: 1.25;
  color: var(--color-text-3-aplat); hyphens: auto;
}
/* L'étape du moment est AUSSI franchie : les deux règles la visent, à poids
   égal, et c'est la dernière écrite qui l'emporte. Le franchi passe donc
   devant — dans l'autre ordre, l'étape du moment prendrait l'encre en retrait
   des précédentes et la frise cesserait de dire où en est le dossier. */
.avancement-jalon--franchi .avancement-nom { color: var(--color-text-2); }
.avancement-jalon--courant .avancement-nom {
  font-weight: 700; color: var(--color-text);
}

.avancement-date {
  display: block; margin-top: 2px;
  font-size: 10px; color: var(--color-text-3-aplat);
  font-variant-numeric: tabular-nums;
}

/* Les trois étapes que le laboratoire n'horodate pas restent SANS date : pas de
   tiret, pas de « en attente ». La raison est écrite là où la décision se
   prend, dans friseAvancement (js/lignesEssais.js) ; elle a été portée un temps
   par une note sous le tableau, que le propriétaire a fait retirer de l'écran. */

@media (max-width: 1200px) {
  .avancement-nom { font-size: 10px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   4. LA FICHE D'ESSAI — les sous-onglets
   ═══════════════════════════════════════════════════════════════════════════

   Même grammaire que la fiche client et l'administration : .sous-onglets /
   .sous-onglet, posés dans main.css. Seuls les écarts sont ici. */

.sous-onglets--essai {
  flex-wrap: wrap; gap: 2px;
  margin-bottom: 14px;
}

/* « Général » n'est pas une étape du circuit non plus : c'est la coiffe du
   dossier — qui, quoi, où en est-on —, ce qu'on lisait autrefois au-dessus de
   la barre et qui est devenu sa première rubrique.

   Elle prend l'ENCRE NEUTRE de la maison, celle dont main.css se sert déjà
   pour accentuer un onglet survolé sans l'affirmer, et le gris de page pour
   son fond actif. Pas de troisième teinte saturée : la barre en compte dix, et
   une couleur de plus aurait rendu moins lisible la seule distinction qui
   porte du sens — celle de « Pièces du dossier ». Rien n'est inventé ici,
   les deux valeurs sont des variables de la maison. */
.sous-onglet--general.actif {
  color: var(--color-text);
  border-bottom-color: var(--color-text);
  background: var(--color-bg);
}

/* « Pièces du dossier » n'est pas une étape du circuit : c'est le classeur du
   dossier, consultable à tout moment. Sa teinte le sépare des quatre onglets
   d'étape, qui sont, eux, les quatre étapes. */
.sous-onglet--pieces { color: var(--color-text-2); }
.sous-onglet--pieces::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -1px;
  height: 2px; background: var(--statut-valise); opacity: 0;
}
.sous-onglet--pieces { position: relative; }
.sous-onglet--pieces.actif {
  color: var(--statut-valise);
  border-bottom-color: var(--statut-valise);
}
.sous-onglet--pieces.actif::after { opacity: 1; }
/* L'aplat documenté de --statut-valise dans main.css : la teinte y a été
   arbitrée à 5,39:1 sur ce fond-là, et non sur un autre. */
.sous-onglet--pieces:hover { background: #f5f3ff; }

.volet-essai { display: block; }
.volet-essai.hidden { display: none; }

/* Le titre de section d'un volet. Les titres des neuf sections étaient écrits
   en style sur place, chacun répétant six déclarations.

   Ils portent maintenant .bloc-titre, c'est-à-dire le TROISIÈME degré de la
   maison, qui leur donne son ardoise claire, son bâtonnet turquoise, son encre
   et ses écarts. Rien n'en est redit ici : la seconde classe ne sert qu'à les
   désigner, et à poser le seul écart qui reste — un titre en tête de volet n'a
   rien au-dessus de lui dont il faille s'écarter. */
.volet-essai-titre:first-child { margin-top: 0 !important; }

/* ── À l'impression, le découpage ne retient rien ────────────────────────────
   La même règle que pour .volet-fiche et .volet-admin, posée dans index.html :
   un dossier imprimé doit sortir entier, onglets dépliés. */
@media print {
  .sous-onglets--essai { display: none; }
  .volet-essai, .volet-essai.hidden { display: block !important; }
  #table-essais tbody td { padding-top: 6px; padding-bottom: 6px; }

  /* Les deux lignes d'un dossier ne se séparent pas en bas de page. La coupure
     est refusée des deux côtés du joint : `break-after` sur la ligne de données
     ne suffit pas seul, les moteurs n'honorant pas tous la même moitié de la
     paire. Un dossier dont la frise serait passée à la page suivante serait lu
     comme une frise sans dossier et un dossier sans frise. */
  #table-essais tbody tr.ligne-donnees {
    break-after: avoid; page-break-after: avoid;
  }
  #table-essais tbody tr.ligne-avancement {
    break-before: avoid; page-break-before: avoid;
  }
}

/* ── Mouvement réduit ────────────────────────────────────────────────────────
   main.css coupe déjà tout mouvement par une règle générale ; celle-ci ne
   fait que nommer les pièces ajoutées ici, pour qu'un futur changement de la
   règle générale ne les laisse pas bouger en silence. */
@media (prefers-reduced-motion: reduce) {
  #tab-dashboard .stat-card { transition: none; }
}
