/* Page de base : grille, en-tête, lien d'évitement, formulaires, messages. La taille du corps
   (font-size de html) vient de la densité, dans jetons.css. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100vh;
  display: grid; grid-template-rows: auto auto 1fr;
  font-family: var(--police-ui); font-size: var(--t-corps); line-height: var(--interligne);
  color: var(--encre); background: var(--fond);
}
h1, h2, h3, h4 { font-weight: var(--graisse-titre); }
a { color: var(--lien); text-underline-offset: .18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }
::placeholder { color: var(--encre-2); opacity: 1; }

/* `data-etat` force un état que le catalogue montre sans pointeur ni clavier : survol, focus. */
:focus-visible, [data-etat="focus"] { outline: 3px solid var(--focus); outline-offset: 2px; }
/* La cible d'un lien « Corriger » dans un formulaire : un halo autour du focus, cinq secondes
   (formulaire.js pose et retire la classe) ; sans animation, il paraît puis disparaît d'un coup. */
.cible-marquee { box-shadow: 0 0 0 6px var(--accent); animation: cible-marquee 5s linear forwards; }
@keyframes cible-marquee { from { box-shadow: 0 0 0 6px var(--accent); } to { box-shadow: 0 0 0 6px transparent; } }

.lien-evitement {
  position: absolute; left: var(--e3); top: -4rem; z-index: 200;
  padding: var(--e3) var(--e5); background: var(--encre); color: var(--fond);
  font-weight: 600;
}
.lien-evitement:focus { top: var(--e3); }

.visuellement-cache {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ==== Composant : primitives de mise en page ====
   La pile (colonne), la rangée (.en-ligne), la rangée alignée sur la ligne de base et la grappe (rangée qui
   passe à la ligne) ; --ecart règle l'écart. Une zone que les pages nomment par son rôle
   (barre, pied, actions) est une grappe : elle est dans la liste, et ne porte plus que son écart
   et ses marges. */
.pile, .en-ligne { display: flex; gap: var(--ecart, var(--e2)); }
.pile { flex-direction: column; }
.en-ligne { align-items: center; }
.grappe, .actions, .haut-pages, .haut-personne, .haut .personne, .numero-courant, .toolbar, .sections-outils,
.pied-formulaire, .ligne-ordre, .etats-traduction .actions-bas,
.article-actions, .tableau-barre, .traduction .groupe-tete, .traduction .tete-source {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--ecart, var(--e2));
}
/* Sur la ligne de base : un titre et sa précision, de corps différents, se lisent sur un même trait. */
.en-ligne--base, .dernier-travail, .article-barre, .carte-tete, .ligne-word-tete { align-items: baseline; }
.dernier-travail, .article-barre, .carte-tete, .ligne-word-tete { display: flex; flex-wrap: wrap; }

/* ==== Composant : barre du haut ====
   Deux rangées sous un filet d'encre : la marque, la barre de pages et le numéro ouvert ; puis, sur
   la surface, le thème, la densité et la zone de la personne. Elle colle en haut de la fenêtre. */
.haut {
  display: flex; flex-direction: column;
  background: var(--fond); border-bottom: 1px solid var(--encre);
  position: sticky; top: 0; z-index: 40; min-height: var(--hauteur-entete);
}
.haut-pages { gap: var(--e1) var(--e5); min-height: var(--hauteur-rangee-1); padding: 0 var(--e6); }
.haut-personne {
  gap: var(--e2) var(--e5); min-height: var(--hauteur-rangee-2); padding: var(--e1) var(--e6);
  background: var(--surface); border-top: 1px solid var(--filet); font-size: var(--t-libelle);
}
/* L'en-tête collant garde le focus visible (WCAG 2.4.11) : le défilement au focus et aux ancres
   s'arrête sous lui. Dans une fenêtre basse (zoom 200 %, petit écran) ou étroite, où il se
   replierait sur plusieurs lignes, il redevient statique et sa hauteur vaut 0. */
html { scroll-padding-top: var(--hauteur-entete); }
@media (max-height: 29.99rem), (max-width: 899.98px) {
  :root { --hauteur-entete: 0px; }
  .haut { position: static; }
  .haut-pages, .haut-personne { padding: var(--e2) var(--e4); }
}
.haut .marque {
  display: inline-flex; align-items: center; gap: var(--e2);
  min-height: calc(var(--hauteur-rangee-1) - var(--e2)); padding: 0 var(--e2);
  font-size: 1.25rem; font-weight: 500; letter-spacing: -.01em; color: var(--encre); text-decoration: none;
  border-bottom: var(--barre-onglet) solid transparent;
}
/* Le logo est le seul lien vers Pronthome : sur Pronthome il porte la marque de page courante des onglets. */
.haut .marque:is(:hover, :focus-visible) { background: var(--survol); }
.haut .marque[aria-current] { border-bottom-color: var(--onglet-trait); font-weight: 600; }
/* Prontissimo (surprises/logo.js) : le nom long est dans le lien, masqué tant que html[data-prontissimo] manque ;
   le lien se replie dans .haut-pages avec le reste, le nom long pousse donc la barre au lieu de la recouvrir. */
.haut .marque-long, html[data-prontissimo] .haut .marque-court { display: none; }
html[data-prontissimo] .haut .marque-long { display: inline; white-space: nowrap; }
/* Le logo : la tuile bleu nuit de l'ancien logo, un P blanc, trois barres. Ses couleurs sont fixes ; seul le
   contour suit le thème, pour que la tuile reste visible sur le fond sombre. */
.logo { width: 1.5rem; height: 1.5rem; flex: none; }
.logo-tuile { fill: var(--logo-tuile); stroke: var(--cadre); stroke-width: 2; }
.logo-p { fill: none; stroke: var(--logo-p); stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; }
.logo-b1 { fill: var(--logo-b1); }
.logo-b2 { fill: var(--logo-b2); }
.logo-b3 { fill: var(--logo-b3); }
.haut .personne { margin-left: auto; gap: var(--e1) var(--e4); color: var(--encre); }
.haut .personne > span:first-child { font-weight: 600; }
.haut .personne form { margin: 0; }
.lien-bouton {
  padding: var(--e1) var(--e2); border: 1px solid transparent; background: none;
  color: var(--lien); text-decoration: underline; text-underline-offset: .18em; cursor: pointer;
}
/* Le menu Administration de la zone de la personne : un bouton à flèche, qui ouvre le composant menu
   sous lui, aligné à droite pour que la liste reste dans la fenêtre. */
.menu--haut [role="menu"] { left: auto; right: 0; min-width: 12rem; margin-top: var(--e1); }
.menu--haut [role="menuitem"].attention { margin-left: 0; }
.menu-bouton {
  display: inline-flex; align-items: center; gap: var(--e2); padding: var(--e1) var(--e2);
  border: 1px solid transparent; background: none; color: var(--lien); font: inherit; cursor: pointer;
  text-decoration: underline; text-underline-offset: .18em;
}
.menu-bouton[aria-expanded="true"] { background: var(--surface-2); }
.menu-bouton[aria-expanded="true"] .maitre-fleche { transform: rotate(-135deg); }

#rail:empty { display: none; }

/* Le panneau d'un onglet (`.panneau`) n'est pas une boite : ses enfants se règlent comme ceux de main, et le collant reste dans main. */
.panneau { display: contents; }
main { padding: var(--e6) var(--e6) var(--e7); min-width: 0; }
/* La page se lit depuis la gauche, sous la marque, dans la gouttière de la grille ; un texte garde
   sa mesure (44 rem), une page large (tables, sections) va à 72 rem. */
main > :not(dialog), main > .panneau > :not(dialog) { max-width: 44rem; margin-left: auto; margin-right: auto; }
@media (max-width: 899.98px) { main { padding: var(--e5) var(--e4) var(--e7); } }
/* ==== Composant : modale ====
   Un `<dialog>` ouvert par showModal : une petite tâche ciblée qui ramène au contexte. Centrée par
   le margin: auto du navigateur, que les règles `main > *` ne doivent pas défaire ; largeur
   bornée, défilement dedans, fond par jeton, reste de la page inerte. Trois largeurs : courante,
   moyenne (--moyenne) et large (--large). Fermer (.modale-fermer) est toujours visible, seul geste de
   fermeture, au pied après le contenu de chaque modale. */
dialog:modal {
  margin: auto; max-width: calc(100vw - 2 * var(--e4)); max-height: calc(100vh - 2 * var(--e4));
  overflow-y: auto;
}
dialog::backdrop { background: var(--voile-modale); }
.modale {
  width: min(36rem, calc(100vw - 2 * var(--e4))); padding: var(--e5) var(--e6);
  border: 1px solid var(--encre); border-radius: var(--rayon); background: var(--fond); color: var(--encre);
  box-shadow: 0 18px 48px var(--ombre);
}
.modale--moyenne { width: min(46rem, calc(100vw - 2 * var(--e4))); }
.modale--large { width: min(60rem, calc(100vw - 2 * var(--e4))); }
.modale :is(h1, h2) { margin: 0 0 var(--e4); font-size: 1.3rem; letter-spacing: -.01em; }
/* Le titre en tête de la modale (posé dans la boite, son formulaire, après le jeton CSRF, ou le
   corps de la modale commune) : sous un filet. Il garde les marges de la boite, que son anneau de
   focus ne déborde pas. */
.modale > :is(h1, h2):first-child, .modale > :is(form, div):first-child > :is(h1, h2):first-child,
.modale > form:first-child > input[type="hidden"]:first-child + :is(h1, h2) {
  margin: 0 0 var(--e4); padding: 0 0 var(--e4); border-bottom: 1px solid var(--filet);
}
/* Fermer, au pied : sur la surface, sous un filet, collé au bas de la boite qui défile. */
.modale-fermer {
  margin: var(--e5) calc(-1 * var(--e6)) calc(-1 * var(--e5));
  padding: var(--e4) var(--e6); text-align: right; background: var(--surface); border-top: 1px solid var(--filet);
}
/* Ouverte, la modale défile dedans : Fermer reste au bas de sa boite. */
dialog:modal > .modale-fermer { position: sticky; bottom: calc(-1 * var(--e5)); }
/* L'exemple du catalogue : une modale ouverte sans showModal se lit dans le flux de la page. */
.modale--exemple { position: static; margin: 0; width: auto; max-width: 36rem; }
main h1 { margin: 0 auto var(--e5); font-size: var(--t-page); line-height: 1.15; letter-spacing: -.02em; }
/* ==== Composant : titre de page ====
   Le h1 posé seul en tête de main : grand, sur toute la largeur, sous lui un filet d'encre. */
main > h1:first-child:not(:has(+ .onglets)), main > .messages + h1:not(:has(+ .onglets)) {
  max-width: none; margin-bottom: var(--e6); padding: var(--e3) 0 var(--e5);
  border-bottom: 1px solid var(--encre); font-size: var(--t-titre-page); letter-spacing: -.025em;
}

/* ==== Composant : vignette ====
   Un aperçu réduit (une image, la miniature d'un tableau) sur papier blanc dans les deux thèmes.
   Bouton, il s'agrandit au clic dans une modale (`.vignette-grande` y montre l'image) ; en
   `--vide`, c'est la place gardée, avec sa raison écrite. */
.vignette {
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto; box-sizing: border-box;
  width: 7rem; height: 5.5rem; padding: var(--e1); overflow: hidden; font: inherit;
  border: 1px solid var(--champ-bord); border-radius: var(--rayon-mini); background: var(--papier); color: var(--papier-encre);
}
button.vignette { cursor: zoom-in; }
button.vignette:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.vignette img { display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
.vignette--vide { border-style: dashed; font-size: var(--t-libelle); text-align: center; overflow-wrap: anywhere; }
.vignette-grille { display: grid; grid-template-columns: repeat(var(--colonnes, 1), minmax(0, 1fr)); width: 100%; font-size: 0.625rem; line-height: 1.3; text-align: left; }
.vignette-grille > span { min-height: 1.3em; padding: 0 2px; overflow: hidden; border: 1px solid var(--papier-filet); white-space: nowrap; text-overflow: ellipsis; }
.vignette-grille > .vignette-entete { background: var(--papier-entete); font-weight: 700; }
.vignette-grande { display: block; max-width: 100%; max-height: 70vh; margin: 0 auto; object-fit: contain; background: var(--papier); }

/* ==== Composant : bandeau ====
   Un message, un bandeau du bail, une liste d'erreurs, un constat, une confirmation : un trait de
   gauche et une teinte de gravité (--g-*, voir « Gravités » plus bas), un cadre fin pour ceux qui
   se tiennent seuls, rien pour ceux qui vivent dans une carte. Le libellé dit la gravité aussi. */
.bandeau, .messages li, .erreurs, .confirmation, .couverture .avis { border: 1px solid var(--cadre); }
.bandeau, .messages li, .erreurs, .confirmation, .couverture .avis, .constat, .manques, .qualite, .notes-doi {
  border-left: var(--barre-notif) var(--g-style) var(--g-trait); background: var(--g-fond);
}
.bandeau, .messages li, .erreurs, .confirmation, .couverture .avis, .constat, .manques { border-radius: var(--rayon-mini); }
.bandeau, .messages li, .erreurs, .couverture .avis, .constat, .manques, .qualite { padding: var(--e3) var(--e4); }
.bandeau, .messages li { overflow-wrap: anywhere; }

.messages { list-style: none; padding: 0; }
.messages li { margin-bottom: var(--e2); }

.erreurs { margin-bottom: var(--e4); color: var(--encre); }

/* ==== Composant : carte ====
   Une surface cernée d'un filet : la carte d'article, l'outil du Secrétariat, la fiche, la
   révision. Chaque nom ne garde que son remplissage et ses marges. */
.carte, .outil, .figure, .revision, .portrait-media, .feuille,
details.section, details.auteur {
  border: 1px solid var(--cadre); border-radius: var(--rayon); background: var(--surface);
}
/* La révision (Historique de l'article) : une carte sur le fond, son titre en tête sous un filet. */
.revisions { list-style: none; margin: 0; padding: 0; }
.revision { margin: 0 0 var(--e4); padding: var(--e3) var(--e4); background: var(--fond); }
.revision > h3 { margin: calc(-1 * var(--e3)) calc(-1 * var(--e4)) var(--e2); padding: var(--e3) var(--e4); border-bottom: 1px solid var(--filet); font-size: var(--t-corps); }
.revision-meta { margin: var(--e1) 0; color: var(--encre-2); font-size: var(--t-libelle); }
.revision-extrait { margin: 0 0 var(--e3); white-space: pre-wrap; overflow-wrap: anywhere; font-family: var(--police-mono); font-size: var(--t-libelle); }
.erreurs ul { margin: 0; padding-left: var(--e4); }

/* ==== Composant : champ et libellé ====
   Un libellé gras au-dessus du champ, l'aide et l'erreur dessous. Le même contour pour une saisie,
   une liste, un texte long et le champ d'une modale, et pour une saisie hors d'un .champ (grille des
   mots-clés, Traduire, états d'une traduction) ; l'erreur double le trait et s'écrit. */
.champ { display: flex; flex-direction: column; gap: var(--e1); margin-bottom: var(--e5); }
.champ label { font-weight: 600; }
.champ input, .champ select, .champ textarea, .modale input[type="text"], .modale input[type="search"],
.grille-mots-cles input, .traduction .cible :is(input, textarea), .traduction-mots input, .etats-traduction select {
  font: inherit; padding: var(--e2) var(--e3); width: 100%; min-height: var(--h-ctl);
  color: var(--encre); background: var(--champ-fond);
  border: 1px solid var(--champ-bord); border-radius: var(--rayon-mini);
}
/* Un nombre (année, numéro, volume) tient dans un champ court. */
.champ input[type="number"] { max-width: 16rem; }
.champ input[aria-invalid="true"] { border-color: var(--erreur-trait); border-width: 2px; }
.champ .erreur { color: var(--erreur-texte); font-size: var(--t-libelle); font-weight: 700; }

/* ==== Composant : bouton et petit bouton ====
   Le bouton principal (.bouton, violet), le bouton secondaire (.bouton-lien, au trait), le bouton de vue
   (.interrupteur, avec son état actif), le petit bouton (.petit-bouton) et le bouton d'icône
   (.chevron) ; .bouton--danger est la variante d'erreur. Boutons, liens en forme de bouton et
   boutons de vue : une hauteur, le texte centré dans la hauteur, les mêmes marges, quelle que
   soit la barre qui les aligne. */
.bouton, .bouton-lien, .interrupteur {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e1);
  min-height: var(--h-ctl); padding: var(--e1) var(--e5); line-height: 1.25; text-align: center;
  vertical-align: middle;
}
/* Le bouton plein est le bouton principal, un seul par écran : l'accent violet. */
.bouton {
  cursor: pointer; text-decoration: none;
  border: 1px solid transparent; border-radius: var(--rayon-mini);
  background: var(--primaire); color: var(--sur-primaire); font-weight: var(--graisse-bouton);
}
.bouton:is(:hover, :focus-visible, [data-etat="survol"]) { background: var(--primaire-survol); }
/* Le bouton secondaire, le bouton de vue, le petit bouton et le bouton d'icône : une recette. */
.bouton-lien, .interrupteur, .petit-bouton, .chevron, .haut nav.pages a.signaler {
  border: 1px solid var(--bouton-bord); border-radius: var(--rayon-mini); background: var(--bouton-fond);
}
.bouton-lien, .interrupteur, .petit-bouton, .chevron { color: var(--encre); }
.bouton-lien, .interrupteur { text-decoration: none; font: inherit; font-weight: var(--graisse-bouton); }
.petit-bouton { padding: 0 var(--e2); font-size: var(--t-libelle); }
a.petit-bouton:not([hidden]) { display: inline-flex; align-items: center; text-decoration: none; }
.petit-bouton--icone { display: inline-flex; align-items: center; gap: var(--e1); }
.petit-bouton .ico { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 2; }
.chevron { padding: 0; }
.bouton-lien:is(:hover, :focus-visible, [data-etat="survol"]), .interrupteur:is(:hover, :focus-visible, [data-etat="survol"]),
.petit-bouton:is(:hover, :focus-visible, [data-etat="survol"]), .chevron:is(:hover, :focus-visible, [data-etat="survol"]) { background: var(--survol-bouton); }
/* Actif : fond foncé et texte clair (inversés dans le thème sombre), en plus du gras. */
.interrupteur[aria-pressed="true"], .interrupteur[aria-current="true"], .petit-bouton[aria-pressed="true"] {
  background: var(--actif-fond); color: var(--actif-texte); border-color: var(--actif-fond); font-weight: 700;
}
/* Désactivé : texte gris, trait tireté, curseur d'interdiction. */
:is(.bouton, .bouton-lien, .interrupteur, .petit-bouton, .chevron):is(:disabled, [aria-disabled="true"]) {
  color: var(--encre-2); cursor: not-allowed; border-style: dashed;
}
.bouton:is(:disabled, [aria-disabled="true"]) { background: var(--bouton-fond); border-color: var(--bouton-bord); }

/* Barre de pages de l'Accueil, dans l'en-tête. */
.haut nav.pages ul { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--e1); margin: 0; padding: 0; list-style: none; }
.haut nav.pages a {
  display: inline-flex; align-items: center; min-height: calc(var(--hauteur-rangee-1) - var(--e2));
  padding: 0 var(--e4); color: var(--encre); text-decoration: none; font-weight: 500;
  border-bottom: var(--barre-onglet) solid transparent;
}
.haut nav.pages a:is(:hover, :focus-visible) { background: var(--survol); }
.haut nav.pages a[aria-current] { border-bottom-color: var(--onglet-trait); font-weight: 600; }
/* Signaler une erreur : un bouton de la barre, avec sa coccinelle ; le libellé suffit sans elle. */
.haut nav.pages a.signaler { min-height: var(--h-ctl); margin-left: var(--e3); gap: var(--e2); }
.haut nav.pages a.signaler:is(:hover, :focus-visible) { background: var(--survol-bouton); }
.coccinelle { width: 1.25em; height: 1.25em; flex: none; fill: var(--encre); }
.coccinelle-corps { fill: var(--coccinelle); stroke: var(--encre); stroke-width: 1; }
.coccinelle-pattes, .coccinelle-raie { fill: none; stroke: var(--encre); stroke-width: 1.5; stroke-linecap: round; }
.signaler:hover .coccinelle, .signaler:focus-visible .coccinelle { animation: coccinelle .6s ease-in-out 2; }
@keyframes coccinelle {
  25% { transform: rotate(-12deg); }
  75% { transform: rotate(12deg); }
}

/* Pages larges : tables et sections, sur toute la largeur utile. */
main.large > :not(dialog), main.large > .panneau > :not(dialog) { max-width: 72rem; }
#contenu > :not(dialog), #contenu > .panneau > :not(dialog) { margin-left: 0; }
main h2 { margin: var(--e5) auto var(--e3); font-size: var(--t-titre); }
/* Un outil de Secrétariat : une section de page (plus bas, avec Pronthome), sans boite. */
.outil { margin: 0; padding: var(--e6) 0; border: 0; border-bottom: 1px solid var(--filet); border-radius: 0; background: none; }
.outil > h2 { margin-top: 0; }
/* ==== Composant : rangée de filtres ====
   Des liens en onglets sur un filet : le choix de la revue du Secrétariat, les filtres de Problèmes
   et de Traductions. Le lien courant porte la barre d'accent ; son compte suit le libellé, petit,
   sans fond. */
.revues, .filtres-liens { display: flex; flex-wrap: wrap; gap: var(--e1); list-style: none; margin: 0 auto var(--e4); padding: 0; border-bottom: 1px solid var(--cadre); }
.revues a, .filtres-liens a { display: inline-block; padding: var(--e2) var(--e4); color: var(--encre-2); text-decoration: none; border-bottom: var(--barre-onglet) solid transparent; }
.revues a[aria-current="page"], .filtres-liens a[aria-current="page"] { color: var(--encre); font-weight: 700; border-bottom-color: var(--onglet-trait); }
.filtres-liens .compte { min-width: 0; padding: 0; background: none; color: inherit; font-size: var(--t-mini); }
/* Secrétariat : la barre des exports (chaque bouton avec sa raison dessous) et la table des numéros. */
.barre-exports { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e3); margin: 0 0 var(--e3); }
.barre-exports .export { display: flex; flex-direction: column; align-items: flex-start; gap: var(--e1); }
.raison { display: block; font-size: var(--t-mini); color: var(--encre-2); font-weight: 400; white-space: normal; }
.defile-x { overflow-x: auto; }
.table--numeros th[scope="row"] { color: var(--encre); }
/* ==== Composant : tableau triable ====
   La variante du tableau de Problèmes, de Traductions et de Pronthome : en-têtes triables par
   liens, rangée d'article en tête, les gestes d'une ligne côte à côte ; à 700 px la ligne devient
   une carte (plus bas). Les largeurs de colonnes sont la mise en page de chaque vue. */
.table--tri th[scope="row"] { color: var(--encre); font-size: inherit; }
.table--tri .tri { color: inherit; font-weight: 700; text-decoration: none; }
.table--tri .tri:is(:hover, :focus-visible) { text-decoration: underline; }
.table--tri .gestes-point > * { margin-right: var(--e3); }
.table--tri .gestes-point :is(form.masquer, form.reafficher) { display: inline; margin-left: 0; }
.table--tri .pastille { white-space: normal; }
.table--problemes th:nth-child(1), .table--problemes td:nth-child(1) { width: 22%; }
.table--traductions th[scope="row"] { width: 20%; }
.table--traductions .col-case { width: 2.4rem; }
.table--traductions th.col-etat { width: 14%; }
.table--traductions th.col-qui, .table--traductions th.col-date { width: 12%; }
/* Pronthome : la colonne des gestes est assez large pour quatre boutons sur une ligne à 1280 px ;
   plus étroite, les boutons passent à la ligne entre eux (flex). */
.table--pronthome th:nth-child(1) { width: 17%; }
.table--pronthome th:last-child { width: 38%; }
.table--pronthome .gestes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); }
.table--pronthome .gestes form { display: inline; margin-left: 0; }
.table--pronthome .pastille { white-space: normal; }
/* Traductions : deux rangées de filtres sous leur nom, la barre d'actions de la sélection (plus
   bas), le formulaire « M'attribuer » d'une cellule, l'avertissement des relectures sautées et
   l'historique d'une traduction. */
.rang-filtres { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--e1) var(--e3); }
.rang-filtres .lib { min-width: 7rem; font-weight: 700; }
.rang-filtres .filtres-liens { margin: 0 0 var(--e2); }
/* Composant : la barre d'actions d'une sélection (static/base/selection.js). Un formulaire au-dessus
   d'un tableau dont les cases sont la sélection : le compte, une liste d'actions et le bouton qui les
   applique. Caché sans case cochée ; sans script, toujours visible. */
.barre-selection {
  display: flex; flex-wrap: wrap; align-items: end; gap: var(--e2) var(--e4); margin: var(--e3) 0; padding: var(--e3);
  border: 1px solid var(--encre); border-radius: var(--rayon); background: var(--sec-fond);
}
.barre-selection[hidden] { display: none; }
.barre-selection-compte { margin: 0; align-self: center; font-weight: 700; }
.barre-selection .champ { flex: 0 1 18rem; margin-bottom: 0; }
.attribuer { display: inline; margin-left: var(--e2); }
.avertissement-saut { padding: var(--e3); margin-bottom: var(--e3); }
.historique { list-style: none; margin: 0; padding: 0; }
.historique li { display: grid; grid-template-columns: 9.5rem minmax(0, 1fr); gap: var(--e1) var(--e3); padding: var(--e2) 0; border-bottom: 1px solid var(--filet); }
.historique .qui { font-weight: 700; }
@media (max-width: 700px) {
  .table--tri, .table--tri tbody, .table--tri tr, .table--tri th, .table--tri td { display: block; width: auto; }
  /* Les en-têtes se cachent par clip : ils restent lus par les lecteurs d'écran. */
  .table--tri thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* Problèmes : les en-têtes qui trient restent visibles en rangée, car ils se tabulent. */
  .table--problemes thead { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; }
  .table--problemes thead tr { display: flex; flex-wrap: wrap; gap: var(--e1) var(--e4); border: 0; margin-bottom: var(--e2); }
  .table--problemes thead th { padding: var(--e1) 0; border: 0; background: none; }
  .table--problemes thead th:not(:has(a)) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); padding: 0; }
  .table--tri tr { margin-bottom: var(--e3); border: 1px solid var(--filet); border-radius: var(--rayon-mini); }
  .table--problemes th:nth-child(1), .table--problemes td:nth-child(1), .table--traductions th[scope="row"], .table--pronthome th:nth-child(1) { width: auto; }
  .table--traductions td[data-lib]::before { content: attr(data-lib); display: inline-block; width: 7.5rem; font-weight: 700; color: var(--encre-2); }
  .table--traductions td:empty { display: none; }
  .historique li { grid-template-columns: minmax(0, 1fr); }
}
.vide { margin: 0 auto var(--e4); padding: var(--e3); border: 1px dashed var(--champ-bord); border-radius: var(--rayon); background: var(--surface); color: var(--encre-2); }
/* ==== Composant : tableau ====
   Une table de lecture à colonnes fixes, filet bas entre les lignes ; la grille de mots-clés et la
   table des traductions en reprennent la mise en page. */
.table, .grille-mots-cles, .traduction-mots { width: 100%; table-layout: fixed; border-collapse: collapse; }
/* Sur le fond de la page : la rangée d'en-tête en petit gris sous un filet d'encre, une ligne aérée
   par rangée sous un filet, la rangée survolée sur la surface. */
.table th, .table td { padding: var(--e4) var(--e3); text-align: left; vertical-align: top; overflow-wrap: anywhere; border-bottom: 1px solid var(--filet); }
.table thead th { padding-top: var(--e2); padding-bottom: var(--e3); font-size: var(--t-libelle); font-weight: 600; color: var(--encre-2); background: var(--tete-fond); border-bottom-color: var(--encre); }
.table tbody th { font-weight: 600; }
.table tbody tr:hover { background: var(--surface); }
.table .nombre { text-align: right; }
/* Dans une cellule, un bouton serre ses marges : les gestes d'une ligne tiennent côte à côte. */
.table :is(.bouton, .bouton-lien) { padding-inline: var(--e3); }
/* Un champ dans une cellule prend la largeur de sa colonne (table-layout: fixed), jamais plus. */
.table :is(input:not([type="checkbox"], [type="radio"]), select) { width: 100%; min-width: 0; }
.table .dossier { font-family: var(--police-mono); font-size: var(--t-libelle); }
.table tr.aujourdhui td { background: var(--choix-fond); }
.marque-discrete, .quand { color: var(--encre-2); font-size: var(--t-libelle); }
.dernier-travail { gap: var(--e1) var(--e2); }
.archives summary, .journal summary { cursor: pointer; padding: var(--e1) 0; }
.archives { margin: var(--e3) auto; }
.cadenas { display: inline-flex; align-items: center; gap: var(--e1); font-size: var(--t-libelle); color: var(--encre-2); }
.cadenas .ico { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 2; }

/* Gravités. Quatre gabarits de teinte, que les composants lisent par --g-* : une pastille, un
   message, un constat ou un bandeau prend sa gravité en entrant dans l'une des listes
   ci-dessous, jamais en nommant une couleur. Le trait porte la gravité en plus de la teinte :
   double (erreur), plein (avertissement), pointillé (succès), tireté (information). Un
   composant reste toujours accompagné de son libellé. La liste de chaque gravité vient après
   celle des gravités qu'elle peut surcharger : information, succès, avertissement, erreur. */
/* ==== Composant : pastille et compte ====
   La pastille dit un état, par sa teinte, son trait et son mot ; le compte est la pastille grise
   du rail. L'état de l'import (.etat-import) en est une aussi. */
.pastille, .compte, .etat-import { border-radius: var(--rayon-pastille); font-size: var(--t-libelle); font-weight: 700; }
.pastille {
  --g-trait: var(--encre-2); --g-texte: var(--encre-2); --g-fond: var(--surface);
  --g-style: solid; --g-epaisseur: 1px;
  display: inline-block; padding: 0 var(--e2); border: var(--g-epaisseur) var(--g-style) var(--g-trait);
  background: var(--g-fond); color: var(--g-texte); white-space: nowrap;
}
.messages li, .bandeau, .constat.constat--info, .pastille--info, .pastille--en-cours, .pastille--attente, .attention--info {
  --g-trait: var(--info-trait); --g-texte: var(--info-texte); --g-fond: var(--info-fond);
  --g-style: dashed; --g-epaisseur: 2px;
}
/* L'état d'un numéro gelé, sans gravité : verrouillé en trait double, archivé en tireté, à l'encre. */
.pastille--verrou, .pastille--archive { --g-trait: var(--encre); --g-texte: var(--encre); --g-fond: var(--fond); }
.pastille--verrou { --g-style: double; --g-epaisseur: 3px; }
/* La pastille d'état d'un article : sa forme, son mot et son compte sur une ligne (composants/_pastille_etat.html). */
.pastille--etat { display: inline-flex; align-items: center; gap: .25em; }
.pastille--etat .forme { flex: 0 0 auto; }
.pastille--archive { --g-style: dashed; --g-epaisseur: 2px; }
.bandeau--verrou { --g-trait: var(--encre); --g-texte: var(--encre); --g-fond: var(--surface); --g-style: double; --g-epaisseur: var(--barre-notif); }
.messages .success, .pastille--ok, .pastille--termine, .pastille--pdfua-ua, .etat-import--detecte, .traitement--termine {
  --g-trait: var(--succes-trait); --g-texte: var(--succes-texte); --g-fond: var(--succes-fond);
  --g-style: dotted; --g-epaisseur: 2px;
}
.messages .warning, .bandeau--bail, .bandeau--occupe, .constat, .confirmation, .qualite, .manques, .notes-doi,
.couverture .avis, .carte-import, .etat-import--a-completer, .pastille--avert, .marque-incomplet,
.attention--avertissement {
  --g-trait: var(--avertissement-trait); --g-texte: var(--avertissement-texte); --g-fond: var(--avertissement-fond);
  --g-style: solid; --g-epaisseur: 2px;
}
.messages .error, .erreurs, .bandeau--expire, .bandeau--echec, .constat--blocage, .manque, .carte--erreur,
.pastille--echec, .pastille--pdfua-non, .bouton--danger, .attention--erreur, .etat--bloque, .traitement--echec, .traitement--annule {
  --g-trait: var(--erreur-trait); --g-texte: var(--erreur-texte); --g-fond: var(--erreur-fond);
  --g-style: double; --g-epaisseur: 3px;
}

/* Formulaires : aide, choix, boutons. */
.champ select[aria-invalid="true"] { border-color: var(--erreur-trait); border-width: 2px; }
.champ .aide { color: var(--encre-2); font-size: var(--t-libelle); }
.champ--case { flex-direction: row; flex-wrap: wrap; align-items: center; }
/* Une case ou un bouton radio garde sa taille propre : ni la hauteur ni la marge d'un champ de saisie. */
.champ--case input { width: auto; min-height: 0; padding: 0; accent-color: var(--accent-trait); }
.champ--case label { font-weight: 400; }
.champ--case .aide, .champ--case .erreur { flex-basis: 100%; }
.actions { gap: var(--e3); }
/* Le bouton destructif : texte et contour d'erreur, contour doublé, texte gras. */
.bouton--danger {
  background: var(--g-fond); color: var(--g-texte); border-color: var(--g-trait);
  box-shadow: inset 0 0 0 1px var(--g-trait); font-weight: 700;
}
.bouton--danger:is(:hover, :focus-visible, [data-etat="survol"]) { background: var(--surface-2); }
.erreurs a { color: inherit; }
form.filtre { display: flex; flex-wrap: wrap; align-items: end; gap: var(--e3); margin-bottom: var(--e4); }
form.filtre .champ { margin-bottom: 0; flex: 1 1 10rem; }
form.filtre .actions { margin: 0; }
.journal-texte { margin: var(--e2) 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font-family: var(--police-mono); font-size: var(--t-libelle); }
.resultats { padding-left: var(--e4); }
.resultats .extrait { margin: 0 0 var(--e3); color: var(--encre-2); overflow-wrap: anywhere; }
.etapes li { margin-bottom: var(--e2); }

/* ==== Composant : cadre d'un numéro ====
   Le numéro ouvert dans la barre du haut (étiquette et pastille d'état), le rail à gauche, la
   ligne d'état en pied, sur toute la largeur. */
.numero-courant { gap: var(--e3); margin-left: auto; }
.numero-courant .etiquette { font-weight: 600; overflow-wrap: anywhere; }
.pastilles { display: inline-flex; gap: var(--e1); }
body.avec-rail {
  grid-template-columns: var(--largeur-rail) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-template-areas: "haut haut" "rail contenu" "etat etat";
}
body.avec-rail > .haut { grid-area: haut; }
body.avec-rail > #rail { grid-area: rail; padding: var(--e5) 0; border-right: 1px solid var(--filet); background: var(--fond); }
body.avec-rail > main { grid-area: contenu; }
body.avec-rail > .etat { grid-area: etat; }

/* ==== Composant : ligne d'état ====
   L'état du travail, le compte des constats et, dans l'article, la position du curseur : une ligne
   sur la surface, sous un filet d'encre. */
.etat {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--e1) var(--e3);
  padding: var(--e2) var(--e6); border-top: 1px solid var(--encre); background: var(--surface);
  color: var(--encre-2); font-size: var(--t-libelle);
}
.etat-phrase { font-style: italic; }
/* Une compilation bloquée : fond, trait double d'erreur, pictogramme et texte gras ; le lien vers
   Problèmes garde la couleur du texte, souligné. */
.etat.etat--bloque { background: var(--g-fond); color: var(--g-texte); border-top: var(--g-epaisseur) var(--g-style) var(--g-trait); font-weight: 700; }
.etat--bloque a { color: inherit; text-decoration: underline; }
.etat-bloquee { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--e1) var(--e2); }
.etat-bloquee .forme { width: 1.3em; height: 1.3em; }

/* La ligne d'état reste en bas de la fenêtre, sur toute sa largeur ; le défilement au focus
   s'arrête au-dessus d'elle. Le voile qu'elle porte couvre la page depuis son empilement. */
body.avec-rail { --hauteur-etat: 2.5rem; }
html:has(> body.avec-rail) { scroll-padding-bottom: calc(var(--hauteur-etat, 2.5rem) + var(--e3)); }
body.avec-rail > .etat { position: sticky; bottom: 0; z-index: 30; min-height: var(--hauteur-etat); }

/* ==== Composant : rail ====
   Pronthome, Import, Numéro et ses articles, Traductions, Actualité et ses sous-entrées, puis
   « Replier la barre ». Une entrée porte une barre d'accent à gauche quand elle est courante. Le
   menu reste visible au défilement, la colonne gardant toute sa hauteur ; il marque la section
   qui passe sous les yeux. */
@media (min-width: 900.02px) {
  body.avec-rail > #rail > * {
    position: sticky; top: calc(var(--hauteur-entete) + var(--e3));
    max-height: calc(100vh - var(--hauteur-entete) - var(--hauteur-etat) - 2 * var(--e3)); overflow-y: auto;
  }
}
.rail ul { list-style: none; margin: 0; padding: 0; }
.rail li { overflow-wrap: anywhere; }
.rail li > a, .rail-retour {
  position: relative; display: flex; align-items: center; gap: var(--e3);
  min-height: 2.25rem; padding: var(--e1) var(--e5) var(--e1) calc(var(--e6) - var(--barre));
  border-left: var(--barre) solid transparent; color: var(--encre); text-decoration: none;
}
.rail-retour { margin-bottom: var(--e2); color: var(--encre-2); font-size: var(--t-libelle); }
.rail li > a:is(:hover, :focus-visible), .rail-retour:is(:hover, :focus-visible) { background: var(--surface); color: var(--encre); }
.rail a[aria-current="page"] { font-weight: 600; background: var(--courant-fond); color: var(--courant-texte); border-left-color: var(--courant-barre); }
#rail [data-section][aria-current="location"] > a,
#rail [data-section] [aria-current="location"] { font-weight: 700; border-left-color: var(--courant-barre); }
/* Les articles et les sous-entrées d'Actualité : en retrait, plus petits ; le rang en chasse fixe.
   Le numéro, le titre et le panneau d'attention posent sur la même ligne de base. */
.rail .rail-articles li > a { align-items: baseline; min-height: 2rem; padding: var(--e1) var(--e4) var(--e1) calc(var(--e6) + var(--e2) - var(--barre)); font-size: var(--t-libelle); }
.rail-rang { flex: none; font-family: var(--police-mono); color: var(--encre-2); }
.rail a[aria-current="page"] .rail-rang { color: var(--courant-texte); }
.rail .rail-articles .attention { margin-left: auto; }
.rail .compte { margin-left: auto; }
.compte { display: inline-block; min-width: 1.5em; padding: 0 var(--e1); background: var(--surface-2); color: var(--encre-2); text-align: center; }
.rail a[aria-current="page"] .compte { background: var(--fond); color: var(--encre); }
/* Une séparation visible entre les pages du numéro et Actualité. */
.rail li.rail-separation { margin: var(--e3) var(--e5); border-top: 1px solid var(--filet); }
/* Le panneau d'attention d'un article : octogone rouge ou triangle orange, la forme dit la gravité
   en plus de la teinte (voir « Gravités »). Son texte est dans le lien, lu ; l'infobulle le montre
   au survol et au focus, à droite du rail, par-dessus la page (position: fixed, placée par clavier.js, pour échapper au défilement du rail) ; Échap la ferme (clavier.js). */
.attention { display: inline-block; vertical-align: middle; margin-left: var(--e1); }
.forme { width: 1.1em; height: 1.1em; vertical-align: middle; }
.forme polygon, .forme circle { fill: var(--g-trait); stroke: var(--g-trait); stroke-width: 2; stroke-linejoin: round; }
.forme path { fill: none; stroke: var(--fond); stroke-width: 2.4; stroke-linecap: round; }
.infobulle {
  display: none; position: fixed; z-index: var(--z-infobulle); left: var(--largeur-rail); top: 0; width: max-content; max-width: 14rem;
  padding: var(--e2) var(--e3); background: var(--g-fond); color: var(--g-texte);
  border: var(--g-epaisseur) var(--g-style) var(--g-trait); border-radius: var(--rayon-mini);
  font-size: var(--t-libelle); font-weight: 700; white-space: normal;
}
.infobulle::after { content: attr(data-infobulle); }
.infobulle--entree { display: none; background: var(--encre); color: var(--fond); border: 1px solid var(--encre); font-weight: 500; }
/* L'exemple du catalogue : l'infobulle posée dans le flux, visible sans le rail. */
.infobulle--exemple { display: inline-block; position: static; }
.rail :is(a, button):hover .infobulle:not(.infobulle--entree),
.rail :is(a, button):focus .infobulle:not(.infobulle--entree) { display: block; }
#rail.infobulle-fermee .infobulle { display: none; }
/* Le menu collant du rail est un contexte d'empilement : l'infobulle y reste enfermée, sous l'en-tête,
   les barres et l'éditeur. Tant que le pointeur ou le focus est dans le rail, ce contexte prend la couche
   de l'infobulle ; il ne couvre rien d'autre, sa colonne est la sienne. */
body.avec-rail > #rail > *:is(:hover, :focus-within) { z-index: var(--z-infobulle); }

/* Le pictogramme d'une entrée du rail, du style de la maison de la marque. */
.rail-ico { width: 1.25em; height: 1.25em; flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.rail-libelle { vertical-align: middle; }
.rail-articles .rail-libelle, .rail-articles .attention { vertical-align: baseline; }
.rail-bascule {
  position: relative; display: flex; align-items: center; gap: var(--e3); width: 100%;
  margin-top: var(--e4); padding: var(--e2) var(--e5) var(--e2) var(--e6);
  border: 0; border-top: 1px solid var(--filet); background: transparent; text-align: left;
}
@media (max-width: 900px) { .rail-bascule { display: none; } }

/* Le tiroir du téléphone : sous 600 px, le menu du rail se ferme derrière son bouton (clavier.js) ;
   sans script, le bouton reste caché et le menu ouvert. */
.rail-tiroir { display: none; }
@media (max-width: 37.49em) {
  .rail-tiroir:not([hidden]) { display: flex; justify-content: flex-start; width: calc(100% - 2 * var(--e4)); margin: 0 var(--e4); }
  body.avec-rail[data-tiroir="ferme"] .rail > :not(.rail-tiroir) { display: none; }
  body.avec-rail[data-tiroir="ouvert"] .rail-tiroir { margin-bottom: var(--e3); }
}

/* Le rail replié : une colonne étroite de pictogrammes. Les libellés restent lus (masqués à l'œil),
   le rang de chaque article et son panneau d'attention restent visibles, l'infobulle dit l'entrée
   au survol et au focus. Sous 900 px le rail passe au-dessus du contenu et ne se replie pas. */
@media (min-width: 900.02px) {
  body.avec-rail[data-rail="replie"] { grid-template-columns: var(--largeur-rail-replie) minmax(0, 1fr); }
  body.avec-rail[data-rail="replie"] > #rail > * { overflow: visible; max-height: none; }
  [data-rail="replie"] .rail li > a, [data-rail="replie"] .rail-retour { padding: var(--e2) 0; justify-content: center; flex-wrap: wrap; gap: 0 var(--e1); }
  [data-rail="replie"] .rail .rail-libelle, [data-rail="replie"] .rail .compte {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  [data-rail="replie"] .rail .rail-articles li > a { padding: var(--e1) 0; font-size: var(--t-mini); }
  [data-rail="replie"] .rail .rail-articles .attention { margin-left: 0; }
  [data-rail="replie"] .rail .rail-sous, [data-rail="replie"] .rail li.rail-separation { display: none; }
  [data-rail="replie"] .rail-bascule { justify-content: center; padding: var(--e2) 0; }
  [data-rail="replie"] .rail-bascule .rail-ico { transform: rotate(180deg); }
  [data-rail="replie"] .rail :is(a, button):hover .infobulle--entree,
  [data-rail="replie"] .rail :is(a, button):focus .infobulle--entree { display: block; }
}
.liste-articles li { margin-bottom: var(--e1); }
@media (max-width: 900px) {
  body.avec-rail {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "haut" "rail" "contenu" "etat";
  }
  body.avec-rail > #rail { padding: var(--e3) 0; border-right: 0; border-bottom: 1px solid var(--filet); }
  .etat { padding: var(--e2) var(--e4); }
}

/* Prontogenda : une date importante est en gras avec un filet d'accent ; le texte « Important : » la dit aussi. */
.table tr.evenement--important td { font-weight: 700; }
.table tr.evenement--important td:first-child { border-left: var(--barre-notif) solid var(--encre); }

/* ==== Composant : section de page ====
   Les sections de Pronthome et les outils du Secrétariat (page sans rail) : une par rangée de la grille, sous un
   filet ; le titre à gauche (un quart), le contenu à droite. Une section de tâches de traduction garde
   toute la largeur, pour ses quatre boutons. Sous 900 px, le titre repasse au-dessus. */
@media (min-width: 900.02px) {
  :is(main.pronthome > section:not(:has(.table--pronthome)), body:not(.avec-rail) .outil) {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 3fr); column-gap: var(--e6);
    padding: var(--e6) 0; border-bottom: 1px solid var(--filet);
  }
  :is(main.pronthome > section:not(:has(.table--pronthome)), body:not(.avec-rail) .outil) > h2 { grid-column: 1; grid-row: 1; margin: 0; font-size: var(--t-titre); }
  :is(main.pronthome > section:not(:has(.table--pronthome)), body:not(.avec-rail) .outil) > :not(h2) { grid-column: 2; }
}
/* Pronthome : numéros et livres en deux colonnes, l'une sous l'autre à 700 px. */
.prontogenda th:first-child { width: 33%; }
.deux-colonnes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e5); align-items: start; }
.deux-colonnes > div > h3 { margin: 0 0 var(--e2); font-size: var(--t-corps); }
@media (max-width: 700px) { .deux-colonnes { grid-template-columns: minmax(0, 1fr); } }
/* Le livre en pointillé en fond des pages calmes (classe `fond-livre` sur le body : Pronthome, pages de
   produit, Aide, Journal). Même tracé que `.szh-book` du compilateur, en points de 4 px tous les 12 px,
   quelle que soit la taille. Pseudo-élément fixe, sans contenu, derrière tout : hors du document et de
   l'arbre d'accessibilité, sans événement, absent de l'impression. Le masque ne garde que le trait,
   l'encre du thème le teinte ; la densité n'y change rien (vh et px). Le test de contraste des pages
   calmes mesure le texte le plus pâle sur le point le plus sombre, à cette opacité. */
body.fond-livre::before {
  content: ""; position: fixed; z-index: -1; pointer-events: none;
  top: calc(var(--hauteur-entete) + 24px); right: 24px; width: 40vh; height: 40vh;
  background: var(--encre); opacity: var(--opacite-livre);
  -webkit-mask: url("livre-pointille.svg") center / 100% 100% no-repeat;
          mask: url("livre-pointille.svg") center / 100% 100% no-repeat;
}
@media print { body.fond-livre::before { display: none; } }

/* Bandeaux du bail, du verrou et de l'archive : information, avertissement (bail, occupé), erreur (expiré). */
.bandeau { margin: 0 0 var(--e4); }
/* Survol et focus clavier : un même état, une bordure de 2 px à l'encre en plus du fond que
   chaque composant change (--survol, --survol-bouton). L'état actif (aria-pressed, aria-current)
   garde son fond inversé ou son trait, le désactivé garde son curseur. Un texte en --lien (rail,
   lien-bouton) prend --surface-2 : sous --survol il tomberait sous 4,5:1. */
:is(.bouton, .bouton-lien, .interrupteur, .petit-bouton, .chevron, .lien-bouton, .menu-bouton, .bascule,
    .haut nav.pages a, nav.onglets a, .rail li > a, .rail-retour, .menu [role="menuitem"], .maitre-lien, .maitre-bouton, details > summary):not(:disabled, [aria-disabled="true"]) { cursor: pointer; }
:is(.bouton, .bouton-lien, .interrupteur, .petit-bouton, .chevron, .lien-bouton, .menu-bouton, .bascule,
    .haut nav.pages a, nav.onglets a, .rail li > a, .rail-retour, .menu [role="menuitem"], .maitre-lien, .maitre-bouton, details > summary):is(:hover, :focus-visible, [data-etat="survol"]):not(:disabled, [aria-disabled="true"], [aria-pressed="true"], [aria-current], .bouton--danger) {
  box-shadow: inset 0 0 0 2px var(--survol-bord);
}
.lien-bouton:is(:hover, :focus-visible), .menu-bouton:is(:hover, :focus-visible) { background: var(--surface-2); }
.bandeau .bouton-lien { margin-left: var(--e2); }
/* Les constats qu'aucune carte de la vue Articles ne montre : un cadre neutre, chaque point garde sa gravité. */
.hors-cartes { margin: 0 0 var(--e4); padding: var(--e2) var(--e3); border: 1px solid var(--cadre); border-radius: var(--rayon-mini); }
.hors-cartes h2 { margin: 0 0 var(--e2); font-size: var(--t-titre); }
.hors-cartes-groupe, .groupe-problemes { margin: var(--e3) 0 0; font-size: var(--t-corps); }
/* L'onglet Exports : une rangée par export, le bouton puis ce qu'il fait. */
/* Une rangée par export sous un filet : le bouton dans une colonne de largeur fixe, à pleine largeur, puis ce qu'il fait. */
.lignes-export { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--encre); }
.ligne-export { display: grid; grid-template-columns: minmax(0, 18rem) minmax(0, 1fr); align-items: center; gap: var(--e2) var(--e5); padding: var(--e4) 0; border-bottom: 1px solid var(--filet); }
.ligne-export > :first-child, .ligne-export > form > :is(.bouton, .bouton-lien) { width: 100%; justify-content: flex-start; }
.ligne-export form { margin: 0; }
@media (max-width: 36rem) { .ligne-export { grid-template-columns: minmax(0, 1fr); } }
.ligne-export p { margin: 0; flex: 1 1 16rem; color: var(--encre-2); }

/* Formulaires de la rédaction : pied, couverture. */
.pied-formulaire { gap: var(--e2) var(--e3); margin: var(--e4) 0; }
.pied-etat { color: var(--encre-2); }
.pied-erreurs { flex-basis: 100%; margin: 0; padding-left: var(--e4); color: var(--erreur-texte); font-weight: 700; }
.couverture { margin: var(--e5) 0; }

/* ==== Composant : zone de dépôt, fichier déjà là, traitement long ====
   Une seule zone pour tout fichier déposé (composants/_depot.html, depot.js) : le champ natif est
   masqué mais garde le focus, la zone-label le montre. Le fichier déjà là (.fichier) et le
   traitement (.traitement, travaux/_traitement.html) sont deux cartes de même famille. */
.zone-depot { margin: var(--e4) 0; }
.depot-champ { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.depot-zone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--e2);
  padding: var(--e5) var(--e4); text-align: center; cursor: pointer;
  background: var(--champ-fond); border: 2px dashed var(--champ-bord); border-radius: var(--rayon);
}
.depot-zone:hover { background: var(--sec-fond); }
.depot-zone.survol, .depot-champ:focus-visible + .depot-zone { border-style: solid; border-color: var(--focus); background: var(--accent-fond); }
.depot-champ:focus-visible + .depot-zone { outline: 2px solid var(--focus); outline-offset: 2px; }
.depot-zone svg.ico { width: 1.8em; height: 1.8em; fill: none; stroke: var(--encre-2); stroke-width: 1.6; }
.depot-bouton { display: inline-flex; align-items: center; min-height: var(--h-ctl); padding: .15em .8em; border: 1px solid var(--bouton-bord); border-radius: var(--rayon-mini); background: var(--bouton-fond); }
.depot-saisie > .aide { margin: var(--e2) 0 0; color: var(--encre-2); font-size: var(--t-libelle); }
.depot-saisie .garder { margin-top: var(--e2); }
.depot-erreur { margin: var(--e2) 0 0; }
.depot-erreur:empty { display: none; }
.fichier, .traitement {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--e1) var(--e3); align-items: center;
  margin: 0 0 var(--e3); padding: var(--e3); background: var(--surface); border-radius: var(--rayon-mini);
  border: var(--g-epaisseur, 1px) var(--g-style, solid) var(--g-trait, var(--cadre));
}
.fichier { grid-template-columns: auto minmax(0, 1fr) auto; }
.fichier .vignette { width: 4.2rem; height: 4.2rem; }
.fichier .vignette svg { width: 100%; height: 100%; fill: none; stroke: var(--encre-2); stroke-width: 1.4; }
.fichier p, .traitement p { margin: 0; }
.fichier .nom, .traitement .nom { font-weight: 700; overflow-wrap: anywhere; }
.fichier .detail, .traitement .detail { font-size: var(--t-libelle); color: var(--encre-2); }
.fichier .gestes { display: flex; flex-wrap: wrap; gap: var(--e2); justify-content: flex-end; }
.traitement .raison, .traitement .resultat { grid-column: 1 / -1; }
.traitement .raison { color: var(--g-texte); }
.traitement progress { grid-column: 1 / -1; width: 100%; height: .5rem; accent-color: var(--accent-trait); }
@media (max-width: 36rem) {
  .fichier { grid-template-columns: auto minmax(0, 1fr); }
  .fichier .gestes { grid-column: 1 / -1; justify-content: flex-start; }
}

/* ==== Composant : onglets ====
   Des liens sur un filet d'encre : ceux de l'article et ceux de la page Numéro ; l'onglet ouvert
   porte la barre d'accent dessous. */
nav.onglets { margin: 0 0 var(--e4); border-bottom: 1px solid var(--encre); }
nav.onglets ul { display: flex; flex-wrap: wrap; gap: 0 var(--e5); margin: 0; padding: 0; list-style: none; }
nav.onglets a {
  display: inline-flex; align-items: center; gap: var(--e2); min-height: var(--h-ctl); padding: 0 var(--e1);
  margin-bottom: -1px; color: var(--encre-2); font-weight: 600; text-decoration: none;
  border-bottom: var(--barre-onglet) solid transparent;
}
nav.onglets a:is(:hover, :focus-visible) { background: var(--survol); color: var(--encre); }
nav.onglets a[aria-current="page"] { border-bottom-color: var(--onglet-trait); color: var(--encre); }
/* Le compte d'un onglet (Problèmes) : à l'encre, en négatif. */
nav.onglets .compte { background: var(--encre); color: var(--fond); }
/* La liste des articles : la barre d'actions collée en haut. */
.toolbar { position: sticky; top: var(--hauteur-entete); z-index: 10; gap: var(--e2) var(--e5); margin: 0 0 var(--e5); padding: var(--e3) 0; background: var(--fond); border-bottom: 1px solid var(--filet); }
.toolbar .modifie { margin-left: auto; color: var(--encre-2); font-size: var(--t-libelle); }
/* ==== Composant : menu ====
   Un `[role="menu"]` sous son bouton (le conteneur `.menu`), fait de colonnes (`.col`) de groupes
   nommés (`[role="group"]`, son nom en `p.groupe`) ; une entrée est un `[role="menuitem"]`, son
   raccourci en `.raccourci`. `menu--2` met deux colonnes côte à côte, séparées d'un filet ; sans
   lui, les colonnes se suivent. `.danger` (Supprimer) est en rouge d'erreur, séparé des autres ;
   une entrée `aria-disabled` est grisée. Le menu prend la largeur de son contenu, que la fenêtre
   borne (menu.js le décale pour qu'il y tienne) ; un libellé trop long passe à la ligne, le
   raccourci reste sur sa ligne, à droite. Gabarit : composants/_menu.html. */
.menu { position: relative; }
.menu [role="menu"] {
  position: absolute; left: 0; top: 100%; z-index: 20; min-width: 14rem;
  width: max-content; max-width: calc(100vw - 2 * var(--e4)); overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; padding: var(--e1) 0;
  border: 1px solid var(--encre); border-radius: var(--rayon); background: var(--fond); box-shadow: 0 10px 28px var(--ombre);
}
.menu [role="menu"][hidden], [role="menu"] [hidden] { display: none; }
/* L'exemple du catalogue : le menu ouvert, posé dans le flux de la page. */
.menu--exemple [role="menu"] { position: static; max-width: 36rem; }
/* Chaque colonne prend la largeur de ses entrées. */
[role="menu"].menu--2 { display: grid; grid-template-columns: repeat(2, auto); }
[role="menu"].menu--2 > .col + .col { border-left: 1px solid var(--filet); }
[role="menu"] p.groupe {
  margin: 0; padding: var(--e3) var(--e5) var(--e1); color: var(--encre-2);
  font-size: var(--t-mini); font-weight: 600; font-variant-caps: all-small-caps; letter-spacing: .04em;
}
[role="menu"] [role="group"] + [role="group"] { margin-top: var(--e1); border-top: 1px solid var(--filet); }
.menu [role="menuitem"], [role="menu"] [role="menuitem"] {
  display: flex; align-items: baseline; gap: var(--e4); width: 100%; min-height: 2rem;
  padding: var(--e1) var(--e5) var(--e1) calc(var(--e5) - var(--barre));
  border: 0; border-left: var(--barre) solid transparent; background: none;
  color: var(--encre); font: inherit; text-align: left; text-decoration: none; cursor: pointer;
}
[role="menu"] [role="menuitem"] > span:first-child { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
[role="menu"] [role="menuitem"] .raccourci { flex: none; margin-left: auto; color: var(--encre-2); font-family: var(--police-mono); font-size: var(--t-libelle); white-space: nowrap; }
/* ==== Composant : touche ====
   Une touche du clavier dessinée : chasse fixe, filet plus épais dessous. */
kbd {
  display: inline-block; padding: .1em .4em; line-height: 1.2; white-space: nowrap;
  border: 1px solid var(--filet); border-bottom-width: 2px; border-radius: var(--rayon-mini);
  background: var(--surface); color: var(--encre-2); font-size: var(--t-mini); font-weight: 500;
}
/* ==== Composant : liste de choix ====
   Une `listbox` d'options (Lier un appel, la palette) : l'option active porte la barre d'accent et
   le fond de choix, comme l'entrée d'un menu ; un type à gauche, le raccourci à droite. --retrait
   règle la marge de gauche et de droite des options. */
.liste-choix { list-style: none; margin: var(--e2) 0 0; padding: 0; max-height: 50vh; overflow-y: auto; }
.liste-choix [role="option"] {
  display: flex; align-items: baseline; gap: var(--e4);
  padding: var(--e2) var(--retrait, var(--e4)) var(--e2) calc(var(--retrait, var(--e4)) - var(--barre));
  border-left: var(--barre) solid transparent; cursor: pointer; overflow-wrap: anywhere;
}
.liste-choix [role="option"]:is(:hover, [aria-selected="true"]) { background: var(--choix-fond); color: var(--encre); border-left-color: var(--accent-trait); }
.liste-choix .palette-libelle { flex: 1 1 auto; min-width: 0; }
.liste-choix .raccourci { flex: none; margin-left: auto; }
.liste-choix [data-type]::before { content: attr(data-type) / ""; flex: none; width: 7rem; color: var(--encre-2); font-size: var(--t-libelle); overflow-wrap: anywhere; }
.liste-choix .palette-groupe {
  padding: var(--e3) var(--retrait, var(--e4)) var(--e1); color: var(--encre-2);
  font-size: var(--t-mini); font-weight: 600; font-variant-caps: all-small-caps; letter-spacing: .04em;
}
/* ==== Composant : palette ====
   Ctrl+K : le champ de recherche de la barre du haut qui l'ouvre (loupe, invite, touches), puis la
   boite, posée haut dans la fenêtre pour ne pas sauter quand la liste change de hauteur : la
   recherche sous un filet d'encre, la liste par groupes, l'aide des touches, Fermer. */
.palette-ouvrir {
  display: inline-flex; align-items: center; gap: var(--e3); min-height: 2rem; min-width: min(17rem, 100%);
  padding: 0 var(--e2) 0 var(--e3); border: 1px solid var(--champ-bord); border-radius: var(--rayon-mini);
  background: var(--champ-fond); color: var(--encre-2); text-align: left; cursor: pointer;
}
.palette-ouvrir:is(:hover, :focus-visible) { border-color: var(--encre); color: var(--encre); }
.palette-invite { flex: 1 1 auto; }
.palette-ouvrir .touches { display: inline-flex; gap: var(--e1); }
.palette-ouvrir .ico, .palette-recherche .ico { width: 1.15em; height: 1.15em; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
dialog.palette:modal { margin-top: 10vh; }
.palette { width: min(40rem, calc(100vw - 2 * var(--e4))); }
.palette-recherche {
  display: flex; align-items: center; gap: var(--e3);
  margin: calc(-1 * var(--e5)) calc(-1 * var(--e6)) 0; padding: var(--e2) var(--e6);
  border-bottom: 1px solid var(--encre); color: var(--encre-2);
}
.palette-recherche input[type="text"] { flex: 1 1 auto; min-width: 0; min-height: 3rem; border: 0; background: transparent; font-size: var(--t-titre); }
.palette-liste { --retrait: var(--e6); margin: 0 calc(-1 * var(--e6)); padding: var(--e1) 0; max-height: min(56vh, 30rem); }
.palette-rien { margin: 0; padding: var(--e4) 0; color: var(--encre-2); }
.palette-aide {
  display: flex; flex-wrap: wrap; gap: var(--e1) var(--e5); margin: 0 calc(-1 * var(--e6));
  padding: var(--e3) var(--e6) 0; border-top: 1px solid var(--filet); color: var(--encre-2); font-size: var(--t-libelle);
}
/* Un filet entre deux groupes d'entrées que le script compose. */
.menu .menu-filet { display: block; height: 1px; margin: var(--e1) 0; background: var(--filet); }
[role="menu"] [role="menuitem"]:is(:hover, :focus-visible, [data-etat="survol"]):not([aria-disabled="true"]) { background: var(--choix-fond); border-left-color: var(--accent-trait); }
[role="menu"] [role="menuitem"][aria-disabled="true"] { color: var(--encre-2); cursor: not-allowed; }
[role="menu"] [role="menuitem"].danger { margin-top: var(--e1); border-top: 1px solid var(--filet); color: var(--erreur-texte); font-weight: 600; }
.cartes { display: grid; gap: var(--e4); }
.carte { padding: var(--e3) var(--e4); overflow-wrap: anywhere; }
.carte-supprimer { position: absolute; top: var(--e2); right: var(--e2); z-index: 2; }
.carte--erreur { border: 2px var(--g-style) var(--g-trait); }
.carte-tete { gap: var(--e1) var(--e3); }
/* Le titre prend sa ligne : « type · langue » passe toujours dessous, même sous un titre court. */
.carte-tete > .carte-titre { flex-basis: 100%; }
.carte-titre { margin: 0; font-size: var(--t-titre); }
.carte-meta, .carte-import { margin: 0; color: var(--encre-2); font-size: var(--t-libelle); }
.carte-import { color: var(--g-texte); font-weight: 700; }
.carte-rien { margin: var(--e2) 0 0; color: var(--encre-2); }
/* ==== Composant : maître-détail ====
   Une liste fine à gauche (`.maitre-liste`, un lien par entrée : rang, titre tronqué, pastille d'état),
   la fiche de l'entrée choisie à droite (`.maitre-fiche`, une seule visible) ; les entrées sont des
   liens, `aria-current="true"` marque la choisie. Sous 42 rem de largeur du conteneur (et donc à
   200 % de zoom), la liste disparaît : `.maitre-barre` montre l'entrée courante dans un bouton qui
   ouvre le menu de toutes les entrées, avec Précédent et Suivant. Le conteneur `.maitre` porte la
   requête de conteneur, pas la fenêtre : la page garde son rail. Gabarits : numeros/articles.html,
   numeros/_maitre_ligne.html ; script : maitre.js. */
.maitre { container: maitre / inline-size; }
.maitre-grille { display: grid; grid-template-columns: minmax(15rem, 21rem) minmax(0, 1fr); gap: var(--e5); align-items: start; line-height: 1.3; }
.maitre-liste { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--encre); }
.maitre-lien { display: grid; grid-template-columns: 1.8rem minmax(0, 1fr) auto; align-items: center; gap: var(--e2); min-height: 1.9rem; padding: var(--e1) var(--e2) var(--e1) calc(var(--e2) - var(--barre)); border-bottom: 1px solid var(--filet); border-left: var(--barre) solid transparent; color: var(--encre); text-decoration: none; }
.maitre-lien:is(:hover, :focus-visible) { background: var(--sec-fond); }
.maitre-lien[aria-current="true"] { background: var(--choix-fond); border-left-color: var(--accent-trait); font-weight: 700; }
/* Une entrée en erreur garde sa barre rouge, choisie ou non : la gravité ne dépend pas de la sélection. */
.maitre-lien--erreur, .maitre-lien--erreur[aria-current="true"] { border-left-color: var(--erreur-trait); }
.maitre-rang { font-family: var(--police-mono); font-size: var(--t-libelle); color: var(--encre-2); }
.maitre-titre { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.maitre :is(.maitre-lien, .maitre-courant, .menu--large [role="menuitem"]) .pastille { font-size: var(--t-mini); line-height: 1.3; }
.maitre-barre { display: none; position: relative; flex-wrap: wrap; align-items: stretch; gap: var(--e2); margin: 0 0 var(--e3); }
.maitre-choix { flex: 1 1 100%; min-width: 0; }
.maitre-bouton { display: flex; align-items: center; gap: var(--e2); width: 100%; min-width: 0; min-height: var(--h-ctl); padding: var(--e1) var(--e3); border: 1px solid var(--encre); background: var(--fond); color: var(--encre); font: inherit; font-weight: 700; text-align: left; cursor: pointer; }
.maitre-courant { display: grid; grid-template-columns: 1.8rem minmax(0, 1fr) auto; align-items: center; gap: var(--e2); flex: 1 1 auto; min-width: 0; }
.maitre-fleche { flex: none; width: .5em; height: .5em; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg) translate(-15%, -15%); }
.maitre-bouton[aria-expanded="true"] .maitre-fleche { transform: rotate(-135deg); }
.maitre-pas { display: flex; flex: 1 1 100%; gap: var(--e2); }
.maitre-pas .bouton-lien { flex: 1 1 0; justify-content: center; white-space: nowrap; }
.menu--large[role="menu"] { left: 0; right: 0; width: auto; max-width: none; max-height: min(70vh, 32rem); padding: 0; margin-top: var(--e1); }
.menu--large [role="menuitem"] { display: grid; grid-template-columns: 1.8rem minmax(0, 1fr) auto; align-items: center; gap: var(--e2); padding: var(--e1) var(--e3) var(--e1) calc(var(--e3) - var(--barre)); min-height: 2.1rem; }
.menu--large [role="menuitem"][aria-current="true"] { background: var(--choix-fond); border-left-color: var(--accent-trait); font-weight: 700; }
.menu--large [role="menuitem"] > span:first-child { flex: none; }
.maitre-fiche { padding: var(--e3) var(--e4); }
.maitre-fiche .carte-tete { flex-wrap: nowrap; align-items: baseline; }
.maitre-fiche .carte-titre { flex: 1 1 auto; font-size: var(--t-titre); }
.maitre-fiche .carte-titre a { color: var(--encre); text-decoration: none; }
.maitre-fiche .carte-titre a:hover { text-decoration: underline; }
.maitre-fiche .carte-supprimer { position: static; }
.maitre-fiche :is(.carte-meta, .carte-pastilles, .carte-import) { margin: var(--e1) 0 0; }
.maitre-fiche h3 { margin: var(--e4) 0 var(--e1); padding-bottom: var(--e1); border-bottom: 1px solid var(--filet); font-size: var(--t-libelle); }
.fiche-paires { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); column-gap: var(--e6); margin: 0; }
.fiche-paire { display: grid; grid-template-columns: minmax(6rem, 9rem) minmax(0, 1fr); gap: var(--e3); padding: var(--e1) 0; }
.fiche-paire--large { grid-column: 1 / -1; }
.fiche-paire dt { color: var(--encre-2); font-size: var(--t-libelle); overflow-wrap: normal; hyphens: auto; }
.fiche-paire dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.fiche-valeur { display: block; }
.fiche-langue { display: inline-block; min-width: 2em; color: var(--encre-2); font-size: var(--t-mini); font-weight: 700; }
.maitre-fiche .constats { margin: 0; }
.maitre-fiche .carte-rien { margin: 0; }
.maitre-fiche .taches fieldset { display: flex; flex-wrap: wrap; column-gap: var(--e5); margin: 0 0 var(--e1); }
.maitre-fiche .tache { padding: 0; }
/* L'exemple étroit du catalogue : le menu ouvert, dans un conteneur sous 42 rem. */
.maitre--exemple { max-width: 26rem; }
@container maitre (max-width: 42rem) {
  .maitre-grille { grid-template-columns: minmax(0, 1fr); }
  .maitre-nav { display: none; }
  .maitre-barre { display: flex; }
  .maitre-fiche { padding: var(--e3); }
  .maitre-fiche .carte-tete { flex-wrap: wrap; }
}
.carte-actions { display: flex; flex-wrap: wrap; gap: var(--e2); margin: var(--e3) 0 0; }
.taches fieldset { margin: 0 0 var(--e2); padding: var(--e2) var(--e3); border: 1px solid var(--filet); border-radius: var(--rayon-mini); }
.taches legend { padding: 0 var(--e1); font-weight: 700; }
.resume-taches { color: var(--encre-2); font-weight: 400; }
.tache { display: flex; align-items: center; gap: var(--e2); padding: var(--e1) 0; }
.constats { list-style: none; margin: var(--e2) 0 0; padding: 0; }
/* Un constat se lit à son trait de gauche : plein (avertissement), double (blocage), tireté (info). */
.constat { margin-bottom: var(--e1); }
/* Traductions : le formulaire d'une ligne, un état par groupe, le commentaire, « Tout l'article ». */
.etats-traduction { display: grid; gap: var(--e3); margin: var(--e3) 0 0; }
.etats-traduction .remplissage { margin: 0; padding-left: var(--e4); color: var(--encre-2); font-size: var(--t-libelle); }
.etats-traduction select { width: auto; max-width: 100%; min-height: 1.7rem; padding: .1em .4em; }
.etats-traduction .champ { margin-bottom: 0; }
.etats-traduction .actions-bas { gap: var(--e3); }
/* Dépôt de Word et liste de Word en attente : la zone pointillée est le champ de fichiers lui-même,
   avec le fond et la marge de la zone de dépôt ; la liste est en rangées sous filets, comme les exports. */
.depot { margin: 0 0 var(--e4); }
.depot input[type="file"] { width: 100%; padding: var(--e5) var(--e4); border: 2px dashed var(--champ-bord); border-radius: var(--rayon); background: var(--champ-fond); color: var(--encre); font: inherit; }
.lignes-word { list-style: none; margin: 0 0 var(--e4); padding: 0; border-top: 1px solid var(--encre); }
.ligne-word { padding: var(--e3) 0; border-bottom: 1px solid var(--filet); overflow-wrap: anywhere; }
.ligne-word-tete { gap: var(--e1) var(--e3); margin: 0; }
.ligne-word-nom { font-family: var(--police-mono); font-size: var(--t-libelle); }
.ligne-word-cible { color: var(--encre-2); font-size: var(--t-libelle); }
.ligne-word form { margin: var(--e2) 0 0; }
.question-word fieldset, .choix-numero { margin: 0 0 var(--e3); padding: var(--e2) var(--e3); border: 1px solid var(--filet); border-radius: var(--rayon-mini); }
.question-word legend, .choix-numero legend { padding: 0 var(--e1); font-weight: 700; }
/* ==== Composant : groupe de choix ====
   Un fieldset de cases ou de boutons radio (travaux/_choix.html, exports/_choix.html) : un choix
   par ligne, serrés sous la légende, comme dans les autres formulaires. */
:is(.choix-numero, fieldset.groupe, .question-word fieldset) > .champ--case { margin-bottom: 0; padding: var(--e1) 0; }
fieldset.groupe { margin: 0 0 var(--e4); padding: var(--e2) var(--e3); border: 1px solid var(--filet); border-radius: var(--rayon-mini); }
fieldset.groupe legend { padding: 0 var(--e1); font-weight: 700; }

/* Changer l'ordre. */
.liste-ordre { list-style: none; margin: 0 0 var(--e4); padding: 0; }
.ligne-ordre { gap: var(--e2) var(--e3); padding: var(--e2) var(--e3); border: 1px solid var(--filet); border-radius: var(--rayon-mini); background: var(--surface); margin-bottom: var(--e1); }
.ligne-rang { font-family: var(--police-mono); color: var(--encre-2); }
.ligne-titre { flex: 1 1 12rem; overflow-wrap: anywhere; }
/* Une ligne qui porte des champs (les éditeurs d'un livre) : ils se partagent la place du titre. */
.ligne-titre.en-ligne { flex-wrap: wrap; align-items: flex-start; }
.ligne-ordre .champ { flex: 1 1 9rem; min-width: 0; margin: 0; }

/* Contrôles : un point par constat, sa flèche, sa croix (Masquer). La croix est un petit bouton
   de la taille minimale d'une cible (24 px) ; sous le tableau, une ligne repliée liste les points
   masqués, chacun avec Réafficher. */
.constat .fleche, .constat a { margin-left: var(--e2); }
.constat :is(form.masquer, form.reafficher) { display: inline; margin-left: var(--e2); }
.croix { min-width: 1.5rem; min-height: 1.5rem; font-size: 1.1rem; line-height: 1; }
details.quittances { margin-top: var(--e3); }
details.quittances > summary { cursor: pointer; }
/* La modale des erreurs d'import, sur la page Import et dans le cadre d'un article. */
.erreurs-import h3 { margin: var(--e3) 0 0; font-size: var(--t-corps); overflow-wrap: anywhere; }
.erreurs-import-vider { margin: var(--e3) 0 0; }
.erreurs-import-vider summary { cursor: pointer; }
.erreurs-import .actions { margin: var(--e4) 0 0; }
.controles-section { margin: var(--e5) 0 0; }
.controles-section .carte { margin-bottom: var(--e3); }
.carte-controles .carte-tete form { margin: 0; }
.controles-nature, .controles-rien { margin: var(--e2) 0; color: var(--encre-2); font-size: var(--t-libelle); }
.controles-pdfua { padding-left: var(--e4); }
.controles-pdfua li { margin-bottom: var(--e1); overflow-wrap: anywhere; }
.carte-pastilles { margin: var(--e1) 0 0; }
.pastille--perime { --g-style: dashed; --g-texte: var(--encre-2); --g-trait: var(--encre-2); --g-fond: var(--surface); }
.dernier-export { margin: var(--e5) 0 0; overflow-wrap: anywhere; }
.constat--resultat { font-weight: 700; }
#menu-export form { display: contents; }
#menu-export button[role="menuitem"] { border: 0; background: none; text-align: left; font: inherit; color: var(--encre); cursor: pointer; }
#menu-export button[role="menuitem"]:hover, #menu-export button[role="menuitem"]:focus { background: var(--choix-fond); }

/* Le voile « Analyse en cours » de la ligne d'état : Contrôles le montre pendant tout travail,
   les pages d'export pendant un export ou Tout exporter (jamais pendant un contrôle PDF/UA, qui
   couvrirait leurs boutons), la vue Articles pendant Tout exporter seulement. */
.voile { display: none; }
body.page-controles .voile,
body.page-export .voile:not([data-voile="analyse"]),
body.page-articles .voile[data-voile="numero"] {
  display: flex; position: fixed; inset: 0; z-index: 10; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--fond) 85%, transparent);
}
.voile p { margin: 0; padding: var(--e3) var(--e5); border: 1px solid var(--filet); border-radius: var(--rayon); background: var(--surface); color: var(--encre); font-size: var(--t-titre); font-weight: 700; }

/* ==== Composant : formulaire en sections ====
   Des sections repliables les unes sous les autres, chacune sous un filet d'encre : son résumé en
   tête (plus ou moins, titre, ce qu'elle contient) ; dedans, le libellé au-dessus du champ, les
   champs sur deux colonnes quand la largeur le permet. `.formulaire-sections--ligne` (la fiche d'un
   article, dans une colonne étroite) met le libellé et le champ sur une ligne, le libellé d'une
   largeur fixe (--lib), au-dessus du champ sous 22 rem. Les blocs de la page
   Rubriques de l'Actualité (`details.bloc`, `.bloc-corps`) sont les mêmes sections repliables. */
.formulaire-sections { --lib: 10rem; container: formulaire / inline-size; }
.sections-outils { gap: var(--e2) var(--e3); max-width: 56rem; margin: 0 0 var(--e3); }
.sections-outils [data-deplier] { margin-left: auto; }
.bascule { display: inline-flex; align-items: center; gap: var(--e2); min-height: var(--h-ctl); padding: var(--e1) var(--e3) var(--e1) var(--e2); border: 1px solid transparent; border-radius: var(--rayon-mini); background: transparent; color: var(--encre); font: inherit; font-weight: 600; cursor: pointer; }
.bascule:is(:hover, :focus-visible) { background: var(--survol); }
.bascule .piste { position: relative; flex: none; width: 2.1rem; height: 1.15rem; border: 2px solid var(--champ-bord); border-radius: var(--rayon-pastille); background: var(--surface); }
.bascule .piste::after { content: ""; position: absolute; top: 50%; left: 2px; width: .65rem; height: .65rem; margin-top: -.325rem; border-radius: 1px; background: var(--encre-2); transition: left .12s; }
.bascule[aria-checked="true"] .piste { border-color: var(--actif-fond); background: var(--actif-fond); }
.bascule[aria-checked="true"] .piste::after { left: calc(100% - .65rem - 2px); background: var(--actif-texte); }
.langue { display: inline-block; min-width: 1.9em; padding: 0 .2em; border: 1px solid var(--encre-2); border-radius: var(--rayon-mini); color: var(--encre-2); font-size: var(--t-mini); font-weight: 700; line-height: 1.4; letter-spacing: .05em; text-align: center; }
details:is(.section, .bloc) { max-width: 56rem; margin: 0; border: 0; border-top: 1px solid var(--encre); border-radius: 0; background: none; }
details:is(.section, .bloc):last-of-type { border-bottom: 1px solid var(--encre); }
/* Sur une page large (réglages des moissonneurs), les accordéons prennent la largeur de la carte au-dessus. */
.formulaire-sections--large { margin-top: var(--e3); }
.formulaire-sections--large > details.section { max-width: none; }
details:is(.section, .bloc) > summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--e1) var(--e4); min-height: 3rem; padding: var(--e4) var(--e2) var(--e4) 0; cursor: pointer; list-style: none; }
details:is(.section, .bloc) > summary:is(:hover, :focus-visible) { background: var(--surface); }
details:is(.section, .bloc) > summary::-webkit-details-marker { display: none; }
/* Le résumé d'un bloc d'Actualité est son titre, en texte nu : il en prend la graisse. */
details.bloc > summary { font-weight: var(--graisse-titre); }
/* Le signe d'une section : plus repliée, moins dépliée ; le titre et l'état disent le reste. */
:is(.formulaire-sections details, details.bloc) > summary::before { content: "+" / ""; flex: none; width: 1.2rem; font-family: var(--police-mono); font-weight: 700; }
:is(.formulaire-sections details, details.bloc)[open] > summary::before { content: "\2212" / ""; }
.section-titre { color: var(--encre); font-size: var(--t-titre); font-weight: var(--graisse-titre); }
.section-resume { flex: 1 1 12rem; min-width: 0; color: var(--encre-2); overflow-wrap: anywhere; }
.section-corps, .bloc-corps { padding: var(--e2) 0 var(--e5) calc(1.2rem + var(--e4)); }
/* Un accordéon dans le corps d'un autre (réglages avancés, sites) prend toute la largeur, sous un filet. */
.section-corps details.section { max-width: none; margin: var(--e3) 0 0; border-color: var(--filet); }
/* Libellé au-dessus du champ : un champ par rangée, deux colonnes dès 38 rem de large ; un texte long, un groupe, un bouton ou un accordéon prend la rangée. */
.formulaire-sections:not(.formulaire-sections--ligne) .champ { margin: 0 0 var(--e4); }
.formulaire-sections:not(.formulaire-sections--ligne) .champ .champ { margin: 0; }
.formulaire-sections:not(.formulaire-sections--ligne) :is(.section-corps, .section-corps > form) > :not(.champ), .formulaire-sections:not(.formulaire-sections--ligne) :is(.section-corps, .section-corps > form) > :is(fieldset, .champ:has(> textarea)) { grid-column: 1 / -1; }
@container formulaire (min-width: 38rem) {
  .formulaire-sections:not(.formulaire-sections--ligne) :is(.section-corps, .section-corps > form) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--e6); align-items: start; }
}
/* Libellé et champ sur une ligne (la fiche). */
.formulaire-sections--ligne .champ { display: grid; grid-template-columns: var(--lib) minmax(0, 1fr); gap: var(--e1) var(--e3); align-items: center; margin: 0; padding: .15rem 0; }
.formulaire-sections--ligne .champ > label { grid-column: 1; grid-row: 1; font-size: var(--t-libelle); }
.formulaire-sections--ligne .champ:not(.champ--case) > label::after { content: "\00a0:"; content: "\00a0:" / ""; font-weight: 400; }
.formulaire-sections--ligne .champ:has(> textarea) > label { align-self: start; padding-top: .45rem; }
.formulaire-sections--ligne .champ > :not(label) { grid-column: 2; min-width: 0; }
.formulaire-sections--ligne .champ > :not(label, input, select, textarea) { order: 1; }
.formulaire-sections--ligne .champ > .erreur { order: 2; }
/* La pastille « Modifié » d'un réglage de mise en page garde sa largeur, sous le champ. */
.formulaire-sections--ligne .champ > .pastille { justify-self: start; }
.formulaire-sections--ligne .champ input:not([type="checkbox"]), .formulaire-sections--ligne .champ select, .formulaire-sections--ligne .champ textarea { min-height: 2rem; padding: .3em .5em; }
.formulaire-sections--ligne .champ--case { display: flex; padding-left: calc(var(--lib) + var(--e3)); }
/* 22 rem : 352 px en densité Normal, 286 px en Condensé. */
@container formulaire (max-width: 22rem) {
  .formulaire-sections--ligne .champ { grid-template-columns: minmax(0, 1fr); }
  .formulaire-sections--ligne .champ > label { grid-row: auto; }
  .formulaire-sections--ligne .champ > :not(label) { grid-column: 1; }
  .formulaire-sections--ligne .champ:has(> textarea) > label { padding-top: 0; }
  .formulaire-sections--ligne .champ--case { padding-left: 0; }
}
/* Sans script, tout reste affiché : les outils n'ont rien à brancher. */
@media (scripting: none) { .sections-outils { display: none; } }
@media (scripting: enabled) { .formulaire-sections:not(.avec-autres) .autre { display: none; } }

/* IBM Plex Mono pour les chiffres et les identifiants : comptes, langues, rangs, heures. */
.compte, .langue, .fiche-langue, .ligne-rang, .rail-rang, .maitre-rang, .pastille-n, .quand, kbd { font-family: var(--police-mono); }
.pastille { letter-spacing: 0; font-weight: 600; }

/* Frise : une suite ordonnée (<ol>) dont chaque étape est franchie, courante, en partie franchie
   ou à venir. L'état se lit par la forme du repère et du trait (plein, double, demi, pointillé)
   et par un mot ; la couleur seule ne le porte pas. Sous 38rem de large, la suite passe à la verticale. */
.frise { container: frise / inline-size; margin: var(--e5) 0; padding: var(--e4); border: 1px solid var(--filet); background: var(--surface); }
.frise__tete { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--e2) var(--e4); margin: 0 0 var(--e2); }
.frise__tete h3 { margin: 0; font-size: var(--t-titre); }
.frise__resume { margin: 0 0 var(--e4); display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); }
.frise__liste { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
.frise__etape { position: relative; display: grid; align-content: start; justify-items: start; gap: var(--e1); padding-right: var(--e3); }
.frise__etape::after { content: ""; position: absolute; top: 1rem; left: 2.4rem; right: .4rem; height: 0; border-top: 3px solid var(--encre); }
.frise__etape:last-child::after { display: none; }
.frise__etape--courante::after, .frise__etape--a-venir::after { border-top: 3px dashed var(--cadre); }
.frise__marque { display: grid; place-items: center; width: 2rem; height: 2rem; border: 3px solid var(--encre); background: var(--fond); color: var(--fond); position: relative; z-index: 1; }
.frise__marque .ico { width: 1.2rem; height: 1.2rem; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: square; }
.frise__etape--franchie .frise__marque { background: var(--encre); }
.frise__etape--courante .frise__marque { border-color: var(--accent-trait); background: var(--accent-fond); box-shadow: 0 0 0 3px var(--fond), 0 0 0 5px var(--accent-trait); }
.frise__etape--courante .frise__marque::before { content: ""; width: .8rem; height: .8rem; background: var(--accent-trait); }
.frise__etape--a-venir .frise__marque { border-style: dashed; border-color: var(--cadre); background: var(--surface); }
.frise__nom { margin-top: var(--e2); font-weight: 700; }
.frise__etape--a-venir .frise__nom { color: var(--encre-2); }
.frise__mot { font-size: var(--t-libelle); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.frise__etape--courante .frise__mot { color: var(--accent-texte); }
.frise__date { font-size: var(--t-libelle); color: var(--encre-2); }
@container frise (max-width: 38rem) {
  .frise__liste { grid-template-columns: minmax(0, 1fr); gap: var(--e4); }
  .frise__etape { grid-template-columns: 2rem minmax(0, 1fr); column-gap: var(--e3); padding-right: 0; }
  .frise__marque { grid-row: 1 / span 4; }
  .frise__nom { margin-top: 0; }
  .frise__etape::after { top: 2.2rem; bottom: calc(-1 * var(--e4) - .2rem); left: calc(1rem - 1.5px); right: auto; height: auto; width: 0; border-top: 0; border-left: 3px solid var(--encre); }
  .frise__etape--courante::after, .frise__etape--a-venir::after { border-left: 3px dashed var(--cadre); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}
