/* Le thème est celui du DSFR, au choix de chacun — clair, sombre ou celui du système —
 * depuis « Paramètres d'affichage », en pied de page. Arbitré le 23 septembre 2026 : la
 * palette sombre d'origine est abandonnée, comme #160 l'annonçait. Nos variables ne portent
 * plus de couleur à elles : elles **désignent** les jetons du DSFR, qui changent avec le
 * thème. Seul le terminal reste noir, dans les deux thèmes. Notre ancienne palette laissait
 * les composants du DSFR en clair sur un fond sombre — barres de défilement blanches,
 * contrastes non mesurés. */
:root {
  --fond: var(--background-default-grey);
  --fond-carte: var(--background-alt-grey);
  --fond-creux: var(--background-contrast-grey);
  --bord: var(--border-default-grey);
  --texte: var(--text-default-grey);
  --attenue: var(--text-mention-grey);
  --accent: var(--text-action-high-blue-france);
  --vert: var(--text-default-success);
  --rouge: var(--text-default-error);
  --ambre: var(--text-default-warning);
  --rayon: 8px;
  --mono: ui-monospace, "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;
}
* { box-sizing: border-box; }
/* Ni fond, ni couleur, ni police : ceux du DSFR (Marianne), qui suivent le thème. */
body { margin: 0; }
/* L'en-tête et le pied de page sont ceux du DSFR (#160, vendor/dsfr/) depuis le
 * 22 septembre 2026 : leur mise en page vient de dsfr.min.css, pas d'ici. Les liens de
 * l'apprenant y sont entrés le 23 septembre (`.fr-header__tools-links`), ceux de l'interface
 * enseignante le 24 (`fr-nav` pour ses onglets). */
/* `.fr-header__logo` et `.fr-footer__brand` portent eux-mêmes `display:flex`, plus
 * spécifique que la règle implicite du navigateur pour `[hidden]` : sans ce `!important`,
 * le bloc-marque de l'État reste visible malgré l'attribut. Mesuré le 22 septembre 2026,
 * sur l'instance de développement, `identite_ministerielle` à faux. */
[data-identite-etat][hidden] { display: none !important; }
/* Les liens de l'en-tête selon la séance (index.html et admin.html, `etatEnTete` dans app.js
 * et admin.js). Par le CSS et non par `hidden` : la copie du tiroir mobile doit suivre, et le
 * JS ne la connaît pas. `!important` pour la même raison que la règle ci-dessus : le DSFR pose son propre `display`
 * sur les éléments de `.fr-btns-group`. */
html:not([data-seance="connectee"]) [data-si="connectee"],
html:not([data-seance="visiteur"]) [data-si="visiteur"] { display: none !important; }
/* Sur l'écran de connexion, aucun lien : le bouton Menu ouvrirait un tiroir vide. Par un
 * attribut à nous et non par `.fr-header__navbar` : notre CSS ne cible aucune classe du
 * DSFR (test_dsfr.py). */
html:not([data-seance="connectee"]):not([data-seance="visiteur"]) [data-si="avec-liens"] {
  display: none !important;
}
/* La largeur et les marges latérales sont celles de `fr-container`, posé sur <main> : le
 * contenu s'aligne sur le logo et la navigation de l'en-tête. Notre ancien gabarit, 1 400 px
 * et 1,25 rem de marge, le décalait de 80 px vers la gauche à 1 440 px de large (mesuré le
 * 24 septembre 2026). Reste à nous l'espace au-dessus et au-dessous. */
main { padding-block: 1.25rem; }

/* Le catalogue et les cartes de parcours sont passés au DSFR (fr-card, fr-grid-row) le
 * 22 septembre 2026 (#160, Lot 2). `.pastille`, qu'employaient encore l'atelier, le détail
 * d'un parcours, le profil et le backoffice, les a tous perdus pour `fr-badge` le
 * 23 septembre 2026 et a été retirée ; `.meta` reste, pour la ligne de l'étape d'un parcours. */
.dsfr-eteint { opacity: .62; }
.meta {
  display: flex; flex-wrap: wrap; gap: .35rem .5rem; align-items: center;
  font-size: .78rem; color: var(--attenue);
}
/* Un badge ou « 15 min » ne se coupent pas en deux : c'est la ligne qui passe à la
   suivante, pas le mot. */
.meta > * { white-space: nowrap; }
/* Le conteneur des filtres du catalogue garde une largeur maîtrisée ; leur contenu
 * (thèmes, difficultés, recherche, tri) est du DSFR depuis le 22 septembre 2026
 * (fr-tags-group, fr-search-bar, fr-select-group) et n'a plus besoin d'habillage ici. */
.filtres {
  display: flex; flex-wrap: wrap; gap: .75rem 1.25rem; align-items: center;
  margin: 0 0 .9rem;
}

/* Dire qu'on filtre, et non laisser croire que le catalogue a rétréci. */
.filtre-actif { margin: 0 0 .8rem; }

button {
  font: inherit; cursor: pointer; border-radius: 6px; padding: .45rem .9rem;
  border: 1px solid var(--bord); background: var(--fond-carte); color: var(--texte);
}
button:hover:not(:disabled) { border-color: var(--accent); }
button:disabled { opacity: .5; cursor: not-allowed; }
button.primaire {
  background: var(--background-action-high-blue-france); border-color: var(--accent);
  color: var(--text-inverted-blue-france); font-weight: 600;
}

/* L'atelier : énoncé à gauche, terminal à droite. Le terminal prend la place.

   Sur un écran large, l'atelier sort du gabarit de 1400 px que suit le reste du site : un
   catalogue de cartes n'a que faire de la largeur, un énoncé et un terminal côte à côte
   si. La colonne de l'énoncé suit la largeur — un tiers — sans descendre sous 26rem ni
   dépasser 48rem, où une ligne de texte cesse d'être lisible. Le plafond de 2400 px garde
   au terminal des lignes qu'on lit encore d'un regard sur un écran ultra-large. */
main:has(.atelier) { max-width: 2400px; }
.atelier {
  display: grid; gap: 1rem; align-items: start;
  grid-template-columns: minmax(20rem, clamp(26rem, 34%, 48rem)) minmax(0, 1fr);
}
/* `minmax(0, 1fr)` et non `1fr`, qui vaut `minmax(auto, 1fr)` : la colonne ne descendait pas
   sous la largeur du terminal, que xterm avait calculée plus large, et la page défilait de
   côté à 640 px comme à 320 (RGAA 10.4 et 10.11, mesuré le 24 septembre 2026 : une colonne
   de 645 px dans une grille de 596). Contrainte, la colonne rétrécit, et le terminal se
   réajuste à sa boîte. */
@media (max-width: 900px) { .atelier { grid-template-columns: minmax(0, 1fr); } }
.panneau { background: var(--fond-carte); border: 1px solid var(--bord); border-radius: var(--rayon); }
.panneau > .entete {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .7rem 1rem; border-bottom: 1px solid var(--bord);
}
.panneau > .corps { padding: 1rem; }
.enonce { max-height: 46vh; overflow: auto; }
.enonce h2 { font-size: 1.05rem; margin: 1.1rem 0 .4rem; }
/* Une commande qu'on ne voit pas en entier est une commande qu'on recopie fausse : les blocs
   passent à la ligne plutôt que de défiler sous une barre qu'on ne remarque pas. Le retour
   est visuel seulement — un copier-coller rend la ligne d'origine. */
.enonce pre {
  background: var(--fond-creux); border: 1px solid var(--bord); border-radius: 6px;
  padding: .7rem .85rem; overflow-x: auto; font: 13px/1.5 var(--mono);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.enonce code { font: 13px/1.4 var(--mono); background: var(--fond-creux); padding: .1rem .3rem; border-radius: 4px; }
.enonce blockquote { margin: .6rem 0; padding-left: .9rem; border-left: 3px solid var(--bord); color: var(--attenue); }

#terminal { height: 62vh; min-height: 320px; padding: .5rem; background: #000; border-radius: 0 0 var(--rayon) var(--rayon); }
.chrono { font: 600 1rem/1 var(--mono); }
.chrono.urgent { color: var(--rouge); }
.etat { font-size: .85rem; color: var(--attenue); }

.indices li { margin-bottom: .35rem; }
.vide { color: var(--attenue); padding: 2rem 0; text-align: center; }

/* ------------------------------------------------------------------ accueil */
.titre-section {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--attenue); font-weight: 600; margin: 1.75rem 0 .75rem;
}
.titre-section:first-child { margin-top: .25rem; }
.actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .6rem; }

form { display: flex; flex-direction: column; gap: .5rem; margin-top: .75rem; }
input {
  padding: .5rem .6rem; border-radius: 6px; border: 1px solid var(--bord);
  background: var(--fond-creux); color: var(--texte); font: inherit;
}
input:focus-visible, button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
#err { color: var(--rouge); min-height: 1.2em; }

/* ----------------------------------------------------------------- parcours */
.jauge {
  height: 6px; border-radius: 999px; background: var(--fond-creux);
  border: 1px solid var(--bord); overflow: hidden; margin: .75rem 0 .4rem;
}
.jauge > div { height: 100%; background: var(--vert); transition: width .4s ease; }

.etapes { list-style: none; margin: 1rem 0 0; padding: 0; display: flex; flex-direction: column; gap: .6rem; }
.etape {
  display: flex; gap: .85rem; padding: .85rem 1rem;
  border: 1px solid var(--bord); border-radius: var(--rayon); background: var(--fond-creux);
}
.etape > div { flex: 1; }
.etape strong { display: block; }
.etape .meta { margin: .4rem 0 .55rem; }
.etape .marque {
  flex: 0 0 1.8rem; height: 1.8rem; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--bord); font: 600 .85rem/1 var(--mono); color: var(--attenue);
}
.etape.reussie { border-color: color-mix(in srgb, var(--vert) 45%, transparent); }
.etape.reussie .marque { color: var(--vert); border-color: var(--vert); }
.etape.verrouillee { opacity: .6; }
.verrou { margin: 0; font-style: italic; }

/* ------------------------------------------- tableaux et formulaires, partagés
   Ils servaient d'abord à l'administration ; le classement, la progression et le profil
   les emploient à l'identique. Les garder en double aurait fini par les faire diverger. */
table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th, td { text-align: left; padding: .45rem .6rem; border-bottom: 1px solid var(--bord); }
th { color: var(--attenue); font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; }
td.fin, th.fin { text-align: right; }
/* Le texte réservé aux lecteurs d'écran (`fr-sr-only`) est posé en absolu. Dans une cellule
 * sans position, il se place par rapport au premier ancêtre positionné — l'enveloppe du
 * tableau du DSFR, qui est **hors** du conteneur à défilement : il échappait donc au rognage
 * et élargissait la page entière. Mesuré le 24 septembre 2026 à 375 px de large, l'onglet
 * « Bacs » : une page de 1 209 px, par le seul « en vie » de la dernière colonne. Une cellule
 * positionnée le retient à l'intérieur du tableau, qui défile seul comme prévu. */
table td, table th { position: relative; }
/* Les cellules qui passent à la ligne plutôt que d'élargir le tableau. Le DSFR interdit le
 * retour à la ligne dans ses cellules (`white-space: nowrap`) : la liste des parcours, quatre
 * boutons par ligne, mesurait 1 619 px dans une page de 1 326 le 24 septembre 2026, et
 * « Remettre en brouillon » sortait du cadre. `table` en tête pour l'emporter sur la règle du
 * DSFR sans nommer sa classe (test_dsfr.py).
 *
 * Ce qui se coupe, c'est le texte nu et l'espace entre les pièces — jamais une pièce : un
 * bouton, un badge, une date. Les boutons, eux, passent à la ligne par `flex-wrap`, que
 * `white-space` ne gouverne pas. */
table :is(td, th).sur-lignes { white-space: normal; }
td.sur-lignes > * { white-space: nowrap; }
/* Un en-tête de colonne qui passe à la ligne descendrait sinon à la largeur de son plus
 * long mot. Neuf rem : quatre lignes au plus pour « Scénario La Jument : L'outil qui ne
 * trouve plus sa bibliothèque ». */
th.sur-lignes { min-width: 9rem; }
.actions-ligne { display: flex; flex-wrap: wrap; gap: .25rem .5rem; justify-content: flex-end; }
tbody tr:hover { background: var(--fond-creux); }
tr.absent td { color: var(--attenue); }
code { font: 12px/1.4 var(--mono); }

.formulaire { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: .75rem 1rem; }
.formulaire .large { grid-column: 1 / -1; }
select {
  padding: .45rem .5rem; border-radius: 6px; border: 1px solid var(--bord);
  background: var(--fond-creux); color: var(--texte); font: inherit;
}

/* --------------------------------------------------------------- communauté */
button.lien {
  background: none; border: none; padding: 0; color: var(--accent);
  font: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
button.lien:hover { color: var(--texte); }

textarea {
  padding: .5rem .6rem; border-radius: 6px; border: 1px solid var(--bord);
  background: var(--fond-creux); color: var(--texte); font: 13px/1.5 var(--mono);
  resize: vertical;
}
tr.moi td { background: color-mix(in srgb, var(--accent) 14%, transparent); font-weight: 600; }
tr.peu-sur td { color: var(--attenue); }
