

.cours-ouvrir form { display: grid; gap: var(--e5); }

.cours-champ { display: grid; gap: 0.25rem; }
.cours-champ > span { font-size: 0.8rem; color: var(--encre-tenue); font-weight: 600; }
.cours-champ input, .cours-champ textarea {
  font: inherit;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--trait-fort);
  border-radius: 0.4rem;
  background: var(--surface);
  color: var(--encre);
}
.cours-champ-large textarea { width: 100%; resize: vertical; }

.cours-liste { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.cours-liste li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--trait);
}
.cours-liste li:last-child { border-bottom: 0; }
.cours-meta { color: var(--encre-tenue); font-size: 0.85rem; }
.cours-rien { color: var(--encre-douce); }

/* Un tour en vol se voit dans la LISTE aussi : sinon Chris ouvre une session pour
   découvrir qu'elle travaille, et il aura rechargé pour rien. */
.cours-envol { color: var(--accent-texte); font-size: 0.85rem; font-weight: 600; }

.cours-demande {
  color: var(--encre-douce);
  font-style: italic;
  margin: -0.4rem 0 var(--e6);
}

.cours-erreur {
  border-left: 3px solid var(--refus-trait);
  background: var(--refus-fond);
  color: var(--refus-encre);
  padding: 0.7rem 0.9rem;
  border-radius: 0.5rem;
}

/* L'accusé de réception. Il est visible sans être une alerte : « je travaille » est
   une bonne nouvelle, pas un problème. */
.cours-envol-bloc {
  margin: var(--e6) 0;
  padding: 0.9rem 1rem;
  border: 1px dashed var(--trait-fort);
  border-radius: 0.6rem;
  background: var(--surface-creuse);
}

/* LE CAS D'ABORD : c'est lui qui donne sa forme au module. */
.cours-cas { border-left: 3px solid var(--accent-trait); }
.cours-contexte { color: var(--encre-douce); }
.cours-parties { display: grid; gap: 0.5rem; padding-left: 1.2rem; }
.cours-partie-titre { font-weight: 600; display: block; }
.cours-attendu { color: var(--encre-tenue); font-size: 0.9rem; }

/* Les objectifs sont une PHRASE dans la fiche de l'école — 88 et 117 caractères sur
   les deux fiches réelles. Le gras y était justifié ; sur le paragraphe de 1 500
   caractères que le premier plan a produit, il rendait le bloc illisible. Le contrôle
   dit la longueur, la mise en forme ne prétend plus qu'elle est courte. */
.cours-objectifs { color: var(--encre-douce); }

/* **Un pavé par séance, et il se REPLIE.** Quatre séances de trois à huit thèmes,
   chacune avec son déroulé minuté : la page fait plusieurs écrans et rien ne permettait
   d'en sauter une. Repliée, la séance garde de quoi décider si on l'ouvre — le sommaire
   du plan est le plan lui-même une fois replié.

   Ouvertes par défaut : ce qui est un geste, c'est le pli, pas le dépli. */
.cours-seance {
  margin-top: var(--e6);
  padding-top: var(--e5);
  border-top: 1px solid var(--trait);
}
.cours-seance:first-of-type { border-top: 0; padding-top: 0; }
.cours-seance-tete {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: baseline;
  cursor: pointer;
  margin-bottom: 0.4rem;
}
/* Le chevron du navigateur reste — c'est lui qui dit que le pavé s'ouvre, et le
   remplacer par un dessin à nous ferait perdre le clavier et le lecteur d'écran. */
.cours-seance-tete::-webkit-details-marker { color: var(--encre-tenue); }
.cours-seance-tete:hover .cours-titre-seance { color: var(--accent-texte); }
/* Le rang porte l'ADRESSE de la séance — c'est par lui que Chris la désigne, et il
   se calcule, donc il ne peut pas être faux. */
.cours-seance-rang {
  font-weight: 700;
  color: var(--accent-texte);
  white-space: nowrap;
}
/* **Trois rangs, trois tailles.** Retour de Jonas : le titre de la séance repliable
   est trop petit, et celui qui vient dessous ne se distingue pas de lui. Séance,
   notion et appui sont trois niveaux emboîtés ; quand leurs tailles se ressemblent,
   l'arborescence ne se voit plus — et c'est par elle que Chris se repère.

   La séance est le rang le plus haut de ces trois : c'est l'unité qu'il corrige et
   qu'il désigne. Le rang en dessous grandit aussi, mais reste SOUS elle — égaliser
   les deux aurait supprimé la hiérarchie au lieu de la rendre lisible. */
.cours-titre-seance { font-weight: 600; margin: 0; font-size: 1.15rem; }
/* Les thèmes d'une séance, en liste à PUCES. Le retrait était posé et la puce
   jamais : la feuille réinitialise `ul { list-style: none }` pour tout le projet, et
   une liste sans puce se lit comme un paragraphe coupé — on ne voit plus combien il y
   a de thèmes sans les compter. Demandé deux fois, et ce qui manquait tenait ici. */
.cours-themes { margin: 0; padding-left: 1.2rem; list-style: disc; }

/* La dernière ligne de chaque séance, comme sur les fiches réelles. Distinguée
   parce que c'est l'ossature : elle n'est pas un thème de plus. */
.cours-formative { color: var(--accent-texte); font-weight: 600; }

/* **L'édition à la main du plan.** Les champs vivent DANS le pavé de leur séance :
   un bloc d'édition séparé aurait obligé à faire l'aller-retour entre ce qu'on lit et
   ce qu'on corrige, sur un écran qui fait déjà cinq écrans et demi. */
/* Le formulaire enveloppe les pavés : il ne dispose rien lui-même, ce sont les pavés
   qui gardent leur mise en page. Sa règle existe pour le dire. */
.cours-edition { display: contents; }
/* **Le champ EST l'affichage.** Vu au rendu : les thèmes sortaient deux fois, en
   liste puis dans la zone de saisie juste dessous — sept écrans au lieu de cinq, et
   deux textes identiques dont un seul fait foi. */
.cours-champ-titre { margin-top: var(--e5); }
.cours-edition input[type="text"],
.cours-edition textarea { width: 100%; }
/* Un seul pied pour tout le plan : le geste est « je relis, je corrige deux endroits,
   j'enregistre », pas « j'enregistre quatre fois ». */
.cours-edition-pied {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e5);
  align-items: center;
  margin-top: var(--e5);
  padding-top: var(--e5);
  border-top: 1px solid var(--trait);
}

.cours-remarques { border-left: 3px solid var(--f-orange); }
/* **Les puces reviennent ici.** La charte pose `ul { list-style: none }` pour ses
   listes de mise en page ; sur les points d'une séance, ça donnait un pavé de phrases
   qu'on ne compte pas — et ce qu'on vient y faire est justement les compter. */
.cours-remarques ul {
  margin: 0;
  padding-left: 1.2rem;
  list-style: disc;
}
.cours-remarques li { margin-bottom: 0.25rem; }

/* **Une donnée qui manque, et le geste qui la rend.** Le liseré est celui du
   refus et non l'orange des remarques : une remarque porte sur ce qu'on peut
   améliorer, ceci porte sur du contenu EFFACÉ, qui part devant une classe si
   personne ne le voit. Le fond le distingue d'une proposition, qui, elle, propose
   un texte. */
.cours-reparation {
  border-left: 3px solid var(--refus-trait);
  background: var(--refus-fond);
  padding: var(--e5);
  margin-bottom: var(--e6);
  border-radius: 6px;
}
.cours-reparation ul { margin: 0 0 var(--e5); padding-left: 1.2rem; list-style: disc; }

/* **Une proposition de correction.** Le liseré est vert et non orange : ce pavé ne
   signale pas un problème, il en porte la réparation. Les deux se distinguent à
   l'oeil, sinon l'écran ressemble à une liste de reproches. */
/* --- Ce que le système a appris de Chris ---------------------------------
 *
 * La revue proposait des règles depuis le lot 3, et le seul écran qui en parlait
 * annonçait un NOMBRE dans une base que Chris n'ouvre jamais. Une correction qui
 * devient une règle est du travail qui ne se refera plus : c'est le meilleur argument
 * du système, et il était invisible.
 *
 * **Les classes portent le préfixe de leur écran, et ce n'est pas une coquetterie.**
 * `.regle` existait déjà — c'est la règle graduée de la bande horaire d'Aujourd'hui,
 * `height: 1.2em` et des enfants en `position: absolute`. Mes blocs héritaient donc
 * d'une hauteur d'une ligne et débordaient par-dessus la carte suivante : le gabarit
 * était juste, la page illisible, et le crible des classes orphelines ne pouvait rien
 * y voir — la classe AVAIT une règle. C'est la deuxième fois que ce projet paie une
 * collision de nom entre deux écrans. */
/* **Le bandeau de l'aval : « tes corrections ne sont pas dans les documents ».**
 *
 * Un liseré d'alerte plutôt qu'un fond : il vit sur les trois écrans du module, et un
 * aplat coloré répété trois fois deviendrait le décor qu'on cesse de lire. Ce qu'il
 * dit est temporaire — il disparaît dès que le rendu est refait. */
.cours-aval {
  border-left: 3px solid var(--accent-trait);
  display: grid;
  gap: var(--e5, 0.6rem);
}
.cours-aval-dit { margin: 0; }

/* Ce que le module a coûté. Discret : c'est un repère, pas un verdict. */
/* Le choix de la forme d'une page. Détaché des champs qu'il commande par un peu
 * d'air : c'est une décision, pas un champ de plus. */
.notion-forme { margin-top: 0.6rem; }
/* Les champs d'une forme non choisie. C'est `hidden` qui les retire, par la feuille
 * PAR DÉFAUT du navigateur et non par celle-ci : le script pose l'attribut, et un
 * écran sans script les montre tous — même règle que les pavés repliés. Cette
 * règle-ci existe pour que le bloc respire quand il EST visible. */
/* **`:not([hidden])`, et ce n'est pas une précaution.** Une règle de CLASSE qui pose
 * `display` l'emporte sur `[hidden] { display: none }` de la feuille par défaut du
 * navigateur : le bloc restait visible alors que l'attribut était bien posé. Vu en
 * regardant la page, jamais par un test — le DOM disait « hidden », l'écran montrait
 * le champ. */
.notion-si-forme:not([hidden]) { display: grid; gap: var(--e5, 0.6rem); }


.cours-appris { margin: 1.2rem 0; }
.cours-regles-groupe { margin-top: var(--e6, 1rem); }
/* Le compte à côté du titre, discret : c'est un repère, pas un état. */
.cours-regles-compte {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--encre-pale);
}
.cours-regle {
  display: grid;
  gap: 0.35rem;
  padding: 0.7rem 0 0.9rem;
  border-top: 1px solid var(--trait);
}
.cours-regle-enonce { margin: 0; font-weight: 600; }
/* **La citation, mise en avant comme une citation.** Le contrôle de la revue prouve
 * qu'une règle vient d'un message de Chris, jamais qu'elle DISE ce que le message
 * disait — mesuré, deux règles sur cinq disent plus que leur citation. La phrase doit
 * donc se lire aussi bien que la règle, sinon on croit le modèle sur parole
 * exactement là où on sait qu'il élargit. */
.cours-regle-citation {
  margin: 0;
  padding: 0.35rem 0.8rem;
  border-left: 3px solid var(--accent-trait);
  color: var(--encre-tenue);
  font-style: italic;
}
.cours-regle-signe { margin: 0; font-size: 0.9rem; }
.cours-regle-ou { margin: 0; font-size: 0.78rem; color: var(--encre-pale); }
/* Les gestes d'une règle. EN COLONNE, contrairement à ceux d'une proposition : les
 * libellés portent une conséquence — « qu'elle agisse », « qu'elle ne revienne plus » —
 * et quatre phrases sur une ligne se lisent en diagonale. Ce qui décide ici est un état
 * durable, pas un texte de trois mots. */
.cours-regle-gestes {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0.2rem 0 0;
  padding: 0.4rem 0 0;
  border: 0;
  border-top: 1px solid var(--trait, #e3e0d8);
}
.cours-regle-gestes legend { padding: 0; font-size: 0.78rem; color: var(--encre-pale); }
.cours-regle-gestes label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.9rem;
}
/* Le geste qu'on ne défait pas : détaché des quatre autres et plus discret. Vu au
 * rendu — dans le même rythme et à une ligne du défaut, il se clique par accident. */
.cours-regle-effacer {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px dashed var(--trait, #e3e0d8);
  color: var(--encre-pale);
}

.cours-propositions { border-left: 3px solid var(--f-vert, #2e7d5b); }
.proposition {
  display: grid;
  gap: 0.4rem;
  padding: 0.7rem 0 0.9rem;
  border-top: 1px solid var(--trait);
}
.proposition:first-of-type { border-top: 0; }
.proposition-dit { margin: 0; font-weight: 600; }

/* D'où vient la correction, DIT avant tout le reste. « Ce qui se calcule ne coûte pas
   d'appel » est une décision du projet ; elle vivait dans l'étiquette du champ texte,
   donc la grille — la seule correction mécanique des données réelles — la perdait. */
.proposition-origine {
  margin: 0;
  font-size: 0.8rem;
  color: var(--encre-pale);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* --- Ce que la proposition CHANGE ----------------------------------------
 *
 * L'écran montrait l'avant et l'après dans le même format, sur plusieurs lignes qui se
 * ressemblent : on validait sans voir ce qu'on validait. Le bloc montre la DIFFÉRENCE,
 * et il se distingue du champ qui l'applique par un fond en creux — l'un explique,
 * l'autre agit. */
.proposition-ecart {
  display: grid;
  gap: 0.35rem;
  padding: 0.5rem 0.7rem;
  border-radius: 5px;
  background: var(--surface-creuse);
  font-size: 0.9rem;
}
/* Ce que ça change, en une phrase : le surlignage montre OÙ, celle-ci dit QUOI. Elle
   distingue « une cellule réécrite » d'« une colonne retirée », deux gestes que le
   même marquage rend visuellement proches. */
.proposition-combien {
  font-size: 0.78rem;
  color: var(--encre-pale);
}
/* Les deux grilles, l'une sous l'autre. Côte à côte, chacune aurait moins de place que
   ses cellules n'en demandent — mesuré sur la grille réelle, quatre colonnes. */
.proposition-grille table {
  width: 100%;
  margin: 0.25rem 0 0.6rem;
  border-collapse: collapse;
}
.proposition-grille th, .proposition-grille td {
  border: 1px solid var(--trait);
  padding: 0.22rem 0.4rem;
  text-align: left;
  vertical-align: top;
}
.proposition-grille th { background: var(--surface); font-weight: 600; }
/* La cellule qui BOUGE, et les MÊMES couleurs que le diff d'un tour : rouge pâle pour
   ce qui disparaît, vert pâle pour ce qui arrive. Deux conventions de surlignage dans
   le même module se seraient contredites — un fond, jamais un barré, la ligne se lit
   encore d'un trait. */
.proposition-grille-avant .proposition-bouge {
  background: var(--refus-fond);
  color: var(--refus-encre);
}
.proposition-grille-apres .proposition-bouge { background: var(--f-vert-pale); }
.proposition-forme { display: grid; gap: var(--e5); justify-items: stretch; }
/* Les trois gestes d'une proposition. En ligne : c'est un choix unique, et trois
 * lignes empilées le feraient lire comme trois questions. */
.proposition-gestes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin: 0;
  padding: 0.4rem 0 0;
  border: 0;
}
.proposition-gestes legend {
  padding: 0;
  font-size: 0.78rem;
  color: var(--encre-pale);
}
.proposition-gestes label { display: flex; align-items: center; gap: 0.3rem; }
.proposition-forme > button { justify-self: start; }

/* **Les trois documents, et la relecture : ce qu'on VIENT chercher sur cet écran.**
   Ils étaient en boutons discrets, du même gris que « retirer la validation » — donc
   au même rang qu'un geste qu'on ne fait presque jamais. */
.cours-documents-liens {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: var(--e5);
}

/* **`justify-items: start` rétrécissait le label à son propre contenu**, et le
   `width: 100%` du textarea valait alors 100 % de ce rétrécissement : la zone où naît
   la règle faisait 180 px, et le texte s'y repliait tous les cinq mots. Le réglage
   existait pour empêcher le BOUTON de s'étirer — c'est donc au bouton de le porter. */
.cours-marge form { display: grid; gap: var(--e5); justify-items: stretch; }
.cours-marge form > button { justify-self: start; }

.cours-echanges {
  margin: var(--e6) 0;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--trait);
  border-radius: 0.5rem;
  background: var(--surface-creuse);
  font-size: 0.9rem;
}
.cours-echanges summary { cursor: pointer; font-weight: 600; }
.cours-echanges ol { display: grid; gap: 0.4rem; padding-left: 1.2rem; }
.cours-tour { display: grid; gap: 0.15rem; }
.cours-quand { color: var(--encre-tenue); font-size: 0.75rem; }
.cours-texte { display: block; }
/* Ce que Chris a dit se distingue de ce que l'agent a répondu : c'est le verbatim
   qui portera les règles, et on le relit pour ça. */
.cours-tour-chris .cours-texte { font-weight: 600; }
.cours-tour-agent .cours-texte { color: var(--encre-douce); }
.cours-tour-erreur .cours-texte { color: var(--refus-encre); }

.cours-jeter { margin-top: var(--e6); }

.cours-aide { color: var(--encre-tenue); font-size: 0.85rem; margin: -0.3rem 0 0; }

.cours-champ select { font: inherit; padding: 0.4rem 0.5rem;
  border: 1px solid var(--trait-fort); border-radius: 0.4rem;
  background: var(--surface); color: var(--encre); }

/* Le choix des compétences est le geste principal du formulaire : il prend la
   largeur, et les codes se lisent en tête de ligne — c'est le code qui partira dans
   la fiche, pas le libellé. */
.cours-competences { width: 100%; font-family: inherit; }

/* Les deux autres entrées du référentiel, repliées : elles ne servent que si le
   référentiel n'est pas déjà dans Notion. Au même rang que la liste, elles feraient
   hésiter à chaque fois sur celle qui fait avancer. */
.cours-referentiel {
  padding: 0.6rem 0.9rem;
  border: 1px dashed var(--trait);
  border-radius: 0.5rem;
  background: var(--surface-creuse);
}
.cours-referentiel summary { cursor: pointer; font-size: 0.9rem; }
.cours-referentiel .cours-champ { margin-top: 0.6rem; }

/* **LE DÉROULÉ, rendu.** Il était produit et invisible : l'écran ne montrait que les
   thèmes, et le plan se lisait comme une liste de notions — pas un exercice, pas une
   méthode d'animation, aucun travail de groupe. Ils y étaient tous.

   Il ne part pas dans la fiche. Il est ici parce que c'est ce qu'un formateur relit
   pour juger une séance. */
.cours-deroule {
  list-style: none;
  padding: 0;
  margin: 0.6rem 0 0;
  display: grid;
  gap: 0.2rem;
  font-size: 0.9rem;
}
.cours-deroule li {
  display: grid;
  grid-template-columns: 4.5rem 8rem 1fr;
  gap: 0.5rem;
  align-items: baseline;
}
.cours-minutes { color: var(--encre-tenue); text-align: right; }

/* L'ACTIVITÉ porte une couleur, et c'est ce que Chris cherche : la proportion de
   pratique se lit alors d'un coup d'œil, sans compter les minutes. */
.cours-activite {
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--encre-tenue);
}
.cours-a-évaluation { color: var(--f-orange); font-weight: 600; }
.cours-etape { min-width: 0; }

@media (max-width: 34rem) {
  /* Trois colonnes ne tiennent pas : l'étape passe sous ses deux marqueurs plutôt
     que de se couper mot par mot. */
  .cours-deroule li { grid-template-columns: 4.5rem 1fr; }
  .cours-etape { grid-column: 1 / -1; }
}

/* **CE QUI A CHANGÉ, et QUOI.** La version d'avant portait des pastilles nommant les
   champs touchés : ça dit l'endroit, donc il faut rouvrir la séance pour savoir si la
   correction est passée. Les phrases se lisent ici — c'est le seul bloc de l'écran
   qu'on lit AVANT le document, donc il précède l'étude de cas. */
.cours-changes { margin-bottom: var(--e6); }
.cours-diff {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}
.cours-diff li {
  display: grid;
  gap: 0.15rem;
  /* Un filet coloré par nature : on distingue un ajout d'une réécriture sans lire
     l'étiquette, et la couleur ne repeint pas le texte — c'est lui qu'on lit. */
  border-left: 3px solid var(--accent-trait);
  padding-left: 0.7rem;
}
.cours-diff-ou {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--encre-douce);
}
.cours-diff-reste {
  margin: 0.7rem 0 0;
  font-size: 0.85rem;
  color: var(--encre-douce);
}
.cours-diff-reste:empty { display: none; }
.cours-change {
  /* **Insécable.** « 7 notion(s) · 9 page(s) projetée(s) » se coupait après le
   * chiffre, laissant un « 7 » seul au bout du titre et le reste à la ligne
   * suivante : deux lignes pour une étiquette, et un nombre orphelin. */
  display: inline-block;
  white-space: nowrap;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--creux);
  color: var(--creux-texte);
  font-size: 0.75rem;
  font-weight: 600;
}
/* Un filet, pas un fond : la marque doit guider l'œil sans repeindre le document. */
.cours-a-change { border-left: 3px solid var(--accent-trait); padding-left: 0.8rem; }

/* La fiche de l'école, sur l'écran de session. Ce qui EMPÊCHE et ce qui MANQUE ne se
   lisent pas pareil : le premier est un refus, le second une liste de choses à faire. */
.cours-fiche { margin-top: 1rem; }
.cours-fiche-bloque {
  margin: 0; padding: .55rem .7rem; border-radius: 6px;
  background: var(--refus-fond); border-left: 3px solid var(--refus-trait);
  color: var(--refus-encre);
}
.cours-fiche-vide { margin: 0 0 .6rem; color: var(--encre-douce); }
.cours-fiche-vide b { color: var(--refus-encre); }
.cours-fiche-lacunes { margin: 0 0 .9rem; font-size: .92em; color: var(--encre-tenue); }
.cours-fiche-lacunes summary { cursor: pointer; }
.cours-fiche-lacunes ul { margin: .4rem 0 0; padding-left: 1.2rem; }
.cours-fiche-lacunes li { margin: .15rem 0; }

/* ── L'écran de cours : une grille, pas trois largeurs ─────────────────────
   Les champs vivaient en trois tailles sans que rien ne le justifie — ce ne sont pas
   trois natures de saisie. Douze colonnes, chaque champ déclare sa part. */
.cours-grille {
  display: grid; grid-template-columns: repeat(12, 1fr);
  gap: var(--e5); align-items: end; margin-bottom: .3rem;
}
.cours-grille > .c-3 { grid-column: span 3; }
.cours-grille > .c-4 { grid-column: span 4; }
.cours-grille > .c-5 { grid-column: span 5; }
.cours-grille .cours-champ input,
.cours-grille .cours-champ select { width: 100%; box-sizing: border-box; }

.ref-grille { display: grid; grid-template-columns: repeat(12, 1fr);
              gap: var(--e5); align-items: end; margin-bottom: .6rem; }
.ref-grille > .ref-c2 { grid-column: span 3; }
.ref-grille > .ref-c4 { grid-column: span 6; }
.ref-grille > .ref-c12 { grid-column: 1 / -1; }
.ref-grille .cours-champ input,
.ref-grille .cours-champ select { width: 100%; box-sizing: border-box; }

/* Choisir une compétence : le référentiel d'abord, la recherche ensuite. */
.cours-choix { display: grid; grid-template-columns: 2fr 1fr;
               gap: var(--e5); align-items: end; margin: .8rem 0 .5rem; }
.cours-choix .cours-champ select,
.cours-choix .cours-champ input { width: 100%; box-sizing: border-box; }

/* Le libellé ENTIER : c'est lui qui permet de choisir, un code seul ne dit rien. */
.cours-competences {
  border: 1px solid var(--trait); border-radius: 6px;
  padding: .5rem .7rem; max-height: 22rem; overflow-y: auto;
}
.cours-competences legend { font-size: .8rem; font-weight: 600;
                            color: var(--encre-tenue); padding: 0 .3rem; }
.cours-groupe + .cours-groupe { margin-top: .8rem; }
.cours-groupe-titre { margin: .2rem 0 .35rem; font-size: .82rem; font-weight: 600;
                      color: var(--encre-tenue); }
/* **`:not([hidden])`, et c'est le defaut que le filtre n'a jamais filtre.**
 *
 * `cours.js` posait bien `ligne.hidden = true` sur les competences hors filtre — le DOM
 * disait « cachee » et l'ecran les montrait toutes. Une regle de CLASSE qui pose
 * `display` l'emporte sur `[hidden] { display: none }` de la feuille par defaut du
 * navigateur : la specificite d'une classe bat celle d'un selecteur d'attribut de la
 * feuille de l'agent.
 *
 * Le projet avait DEJA paye ce defaut — voir `.notion-si-forme`, avec le meme
 * commentaire — et la correction n'avait ete portee qu'a un seul endroit. Motif n°3 :
 * on croit avoir corrige, et il reste une copie. Un crible l'interdit maintenant pour
 * la classe entiere.
 *
 * Sur 33 competences, c'est le moment ou le filtre devient necessaire. */
.cours-competence:not([hidden]) {
  display: grid; grid-template-columns: auto auto 1fr; gap: .5rem;
  align-items: baseline; padding: .3rem .2rem; border-radius: 4px;
}
.cours-competence:hover { background: var(--surface-creuse); }
.cours-competence input { margin: 0; }
.cours-code { font-variant-numeric: tabular-nums; font-weight: 600;
              color: var(--accent-texte); white-space: nowrap; }
.cours-libelle { color: var(--encre); line-height: 1.35; }

/* La liste des sessions : un bouton, et où en est chacune. */
.cours-ligne { display: flex; gap: var(--e5); align-items: center;
               justify-content: space-between; flex-wrap: wrap; }
.cours-ligne-quoi { display: grid; gap: .15rem; }
.cours-etat { font-size: .85rem; color: var(--encre-tenue); }

/* Le compte pendant le tour. Une roue tournerait aussi sur un travail mort. */
.cours-chrono:not([hidden]) { display: flex; align-items: center; gap: .7rem;
                margin: .5rem 0 0; font-size: .9rem; color: var(--encre-douce); }
.cours-chrono-barre { flex: 1 1 8rem; height: 4px; border-radius: 2px;
                      background: var(--trait); overflow: hidden; }
.cours-chrono-barre > span { display: block; height: 100%; width: 0;
                             background: var(--accent); transition: width 1s linear; }

/* L'import de référentiel. */
.ref-compte { display: flex; gap: 1.4rem; flex-wrap: wrap; margin: 0 0 .8rem; }
.ref-compte b { font-size: 1.15rem; color: var(--accent-texte); }
.ref-reprend { margin: .4rem 0 .8rem; padding: .5rem .7rem; border-radius: 6px;
               background: var(--surface-creuse); color: var(--encre-douce); }
.ref-bloque { margin: .4rem 0 .8rem; padding: .5rem .7rem .5rem 1.6rem;
              border-radius: 6px; background: var(--refus-fond);
              border-left: 3px solid var(--refus-trait); color: var(--refus-encre); }
.ref-bloque li { margin: .2rem 0; }
.ref-boutons { display: flex; gap: var(--e5); align-items: center; flex-wrap: wrap; }
/* **La phrase qui dit pourquoi la lecture gratuite n'a rien rendu.**

   Elle prend la place de tout ce qui s'affichait a cote d'elle — le compte, la liste,
   le formulaire. Le liseré est celui d'un CONSTAT et non d'un refus : le document n'a
   rien de fautif, c'est notre lecture gratuite qui s'arrete la, et le geste suivant est
   juste au-dessous. */
/* **La reprise d'un tour.** Un CONSTAT, pas un refus : le controle a mordu et un
   appel de plus a evite une notion hors bornes. Le liseré est donc celui d'une
   information — la rendre rouge apprendrait a la craindre alors qu'elle rassure. */
.cours-reprise { margin: .4rem 0 .8rem; padding: .5rem .7rem; border-radius: 6px;
                 background: var(--surface-creuse); color: var(--encre-douce);
                 border-left: 3px solid var(--trait); white-space: pre-line;
                 font-size: .92em; }
.ref-illisible { margin: .2rem 0 .9rem; padding: .6rem .8rem; border-radius: 6px;
                 background: var(--surface-creuse); color: var(--encre-douce);
                 border-left: 3px solid var(--trait); }
/* **La liste des compétences détectées.** Elle emprunte la forme des remarques :
   c'est le même geste — on relit avant de décider — et deux mises en page pour un
   même geste feraient hésiter sur ce qu'on regarde. */
.ref-competences, .ref-remarques, .ref-anomalies { margin-top: .9rem; font-size: .92em; }
.ref-competences summary { cursor: pointer; font-weight: 600; }

/* **Le pavé du découpage.** Il porte une dépense à décider, pas un défaut : le
   liseré est celui d'une proposition et non d'un refus — ce que le document a,
   on sait le lire, il reste à le payer. */
.ref-decoupage {
  border-left: 3px solid var(--f-orange);
  padding: var(--e5);
  margin: .9rem 0;
  border-radius: 6px;
}
.ref-decoupage p { margin-top: 0; }

/* **Le diff d'une reformulation, et ce que Chris avait précisé.** Même forme que
   le diff d'un tour : c'est le même geste — lire ce qui a bougé —, et deux mises
   en page pour une même lecture feraient hésiter sur ce qu'on regarde. */
.cours-regles-diff { margin-bottom: var(--e6); }
.cours-regle-precise { margin: .6rem 0 .2rem; font-style: italic; }
/* Le champ n'est pas caché sans JavaScript : un champ qu'un script seul fait
   apparaître est un champ qui n'existe pas quand le script ne tourne pas. */
/* **Le champ se rattache VISUELLEMENT au choix qui l'ouvre.**

   Il apparaissait entre deux options, au meme rang qu'elles : on le lisait comme une
   troisieme case a cocher. Le filet a gauche et le retrait le font descendre DE
   l'option du dessus — c'est la seule chose qui dise a quoi il repond.

   Et il etait hors charte : chasse fixe, deux lignes, un tiers de largeur, parce que
   rien ne le stylait et qu'un `textarea` nu prend les valeurs du navigateur. Il
   ressemble maintenant aux autres champs du projet, et il laisse la place d'ecrire une
   phrase. */
.cours-regle-champ { display: block; margin: .3rem 0 .6rem 1.6rem;
  padding-left: .8rem; border-left: 2px solid var(--trait); }
.cours-regle-champ > span { display: block; font-size: .82rem; font-weight: 600;
  color: var(--encre-douce); margin-bottom: .2rem; }
.cours-regle-champ textarea {
  font: inherit; width: 100%; box-sizing: border-box; min-height: 4.5rem;
  padding: .45rem .6rem; border: 1px solid var(--trait-fort); border-radius: .4rem;
  background: var(--surface); color: var(--encre); resize: vertical;
}

/* **Un champ qui s'ouvre seul.** L'affordance est la flèche du `<summary>`, sur le
   texte même qu'on va corriger — plus près du geste que ne l'était un « Modifier
   ces textes » sous le bloc, qui ouvrait dix champs pour une virgule. */
.champ-editable > summary {
  cursor: pointer;
  border-radius: 4px;
  padding: .1rem .2rem;
  margin: 0 -.2rem;
  /* **Pas de fleche.** Le texte est cliquable, et il porte deja son affordance : le
     survol le detache du fond. Une fleche par champ, sur une notion qui en porte une
     dizaine, fait dix chevrons alignes qui n'apprennent rien — l'oeil les compte au
     lieu de lire le texte. Les deux syntaxes : `list-style` pour les navigateurs
     recents, le pseudo-element pour WebKit. */
  list-style: none;
}
.champ-editable > summary::-webkit-details-marker { display: none; }
.champ-editable > summary::marker { content: ""; }
.champ-editable > summary:hover { background: var(--surface-creuse); }
.champ-editable[open] > summary { color: var(--encre-tenue); }
/* Un champ vide DIT ce qui manque : « — » seul ne distingue pas un développé
   absent d'un exemple absent, et un pli sans étiquette ne se distingue pas de
   celui d'à côté. */
/* Le texte lu occupe la ligne du sommaire ; la flèche du `<details>` reste à gauche. */
.champ-lu { color: inherit; }
.champ-vide { color: var(--encre-tenue); font-style: italic; }
/* **Le pli d'une grille ou d'un schéma porte le GESTE, pas la lecture** — un
   `<summary>` ne prend ni `<table>` ni `<ol>`, et leur bloc de lecture reste donc
   affiché au-dessus. Il se distingue d'un champ replié : ce n'est pas le texte qu'on
   lit, c'est ce qu'on va faire. */
.champ-geste { margin-top: .4rem; }
.champ-quoi { color: var(--encre-tenue); font-size: .9em; }
/* L'explication du projeté, sous ses boutons : elle se lit une fois, et ce qu'on vient
   chercher est le document. */
.projete-quoi { margin-top: .6rem; }
/* Le surtitre absent : annoncé ici, avant le rendu, pour ne pas se découvrir en salle. */
.projete-surtitre-absent { margin-top: .6rem; }
.ref-competences ul { margin: .4rem 0 0; padding-left: 1.2rem; }
.ref-competences li { margin-bottom: .3rem; }
.ref-remarques summary, .ref-anomalies summary { cursor: pointer; font-weight: 600; }
.ref-remarques ul, .ref-anomalies ul { margin: .4rem 0 0; padding-left: 1.2rem; }
.ref-remarques li, .ref-anomalies li { margin: .2rem 0; color: var(--encre-douce); }
.ref-anomalies li { color: var(--refus-encre); }

@media (max-width: 640px) {
  .cours-grille > .c-3, .cours-grille > .c-4, .cours-grille > .c-5,
  .ref-grille > .ref-c2, .ref-grille > .ref-c4 { grid-column: 1 / -1; }
  .cours-choix { grid-template-columns: 1fr; }
  .cours-competence { grid-template-columns: auto 1fr; }
  .cours-code { grid-column: 2; }
  .cours-libelle { grid-column: 2; }
}
/* L'aperçu est le cœur de l'écran : il porte les comptes, les champs et les remarques
   avant toute écriture. Un peu d'air autour, pour qu'il se distingue du dépôt. */
.ref-apercu { padding-bottom: .4rem; }

/* ── L'ÉCRAN de cours, et pourquoi ce n'est pas `.cours` ───────────────────
   `.cours` existait déjà : c'est la carte d'UN cours dans le planning, avec sa
   grille `auto 1fr` et son filet à gauche. Mes deux écrans reprenaient ce nom pour
   leur conteneur de page, et héritaient donc d'une grille à deux colonnes : les
   sections tombaient alternativement dans la colonne `auto`, qui se rétrécit à son
   contenu. D'où un formulaire tassé sur 350 px et la moitié gauche de l'écran vide.

   Le crible des classes orphelines ne pouvait pas le voir — la classe AVAIT une
   règle. C'est la moitié qu'il laisse au regard, et c'est la deuxième fois sur cet
   écran-là. */
.ecran-cours { display: grid; gap: var(--e6); align-content: start; }
/* Le bloc du refus : trois natures, trois traitements. Tout joint par des
   points-virgules faisait sept cents caractères où l'endroit à corriger se perdait. */
.cours-fiche-bloque ul { margin: .35rem 0 .5rem; padding-left: 1.2rem; }
.cours-fiche-bloque li { margin: .15rem 0; }
.cours-fiche-tete { margin: 0 0 .2rem; font-weight: 600; }
.cours-fiche-ou { margin: .5rem 0 0; padding-top: .45rem;
                  border-top: 1px solid var(--refus-trait); font-size: .95em; }

/* Le désaccord et ses deux gestes. Encadré : il porte une DÉCISION, pas un
 * avertissement de plus — et les deux gestes s'y lisent comme un couple, jamais comme
 * deux boutons voisins dont on choisirait le plus proche. */
.cours-desaccord {
  margin: 0.6rem 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--trait, #e3e0d8);
  border-left: 3px solid var(--f-rouge);
  background: var(--surface);
}
.cours-desaccord-dit { margin: 0 0 0.6rem; font-size: 0.92rem; }
.cours-desaccord-geste { margin: 0.4rem 0; }
.cours-desaccord-geste summary { cursor: pointer; font-size: 0.92rem; }

/* **Les notions développées.** C'est le contenu dont les deux supports descendront,
   et l'écran existe pour le juger sur le FOND — pas sur sa mise en page. Les deux
   formes d'un point sont donc montrées CÔTE À CÔTE : les séparer ferait croire que
   l'une descend de l'autre, alors qu'elles sont écrites dans le même appel. */
.cours-seance-notions { display: grid; gap: var(--e5); }
/* Le pavé d'une séance est un `<details>` : la grille porterait le `<summary>` comme
   une rangée de plus et casserait le pli. */
details.cours-seance-notions { display: block; }
details.cours-seance-notions > * + * { margin-top: var(--e5); }

/* L'étude de cas se replie : son contexte fait mille deux cents caractères et il est
   en tête. Le `<summary>` porte le titre, donc il ne doit pas doubler sa marge. */
.cours-cas-tete { cursor: pointer; }
.cours-cas-tete h2 { display: inline; }
.cours-seance-tete h2 { display: inline; margin: 0; font-size: 1.15rem; }

.notions-liste { display: grid; gap: var(--e6); }
/* **L'arborescence se lit dans les titres**, parce qu'elle ne se voit pas : séance,
   notion, appui sont trois niveaux emboîtés rendus par des tailles qui se ressemblent.
   Le rang est calculé depuis la position, jamais saisi. */
.notion-rang {
  font-weight: 700;
  color: var(--accent-texte);
  white-space: nowrap;
}
.notion-sur { font-size: 0.8rem; font-weight: 400; color: var(--encre-tenue); }
/* **Le repère de page.** Il dit quelle diapositive un bloc donne, et sous quelle
   forme — « page 12 · grille ». Discret : c'est une adresse, pas un état. */
.projete-repere {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--encre-tenue);
  border: 1px solid var(--trait);
  border-radius: 3px;
  padding: 0.05rem 0.35rem;
  white-space: nowrap;
}
/* Un geste qui coûte un appel prend la largeur de sa zone : un bouton de la taille de
   son texte, sous un champ pleine largeur, se lisait comme un lien secondaire. */
.cours-bouton-large { width: 100%; }
/* Écrit comme sur la carte projetée — 01 et non 1 — pour qu'une remarque de Chris
   désigne la même chose à l'écran et en salle. */
.notion-appui-rang {
  color: var(--accent-texte);
  font-variant-numeric: tabular-nums;
  margin-right: 0.35rem;
}

/* La formule projetée en tête, le développé en retrait dessous : c'est l'ordre dans
   lequel Chris les rencontrera en salle, et c'est ce qui rend l'écart lisible. */
.notion-points { margin: 0.2rem 0 0; display: grid; gap: 0.5rem; }
.notion-points dt { font-weight: 600; color: var(--encre-forte); }
.notion-points dd {
  margin: 0.1rem 0 0 0.9rem;
  color: var(--encre-douce);
  line-height: 1.5;
}

/* Repliée : sur sept notions, sept zones ouvertes feraient un mur de champs vides là
   où Chris en remplit une. */
.notion-corriger { margin-top: 0.4rem; font-size: 0.9rem; }
.notion-corriger summary { cursor: pointer; color: var(--accent-texte); }
.notion-corriger textarea { width: 100%; }

/* Les champs de la notion : le piège, son projeté, l'exemple. Ils étaient AFFICHÉS
   sous les appuis ; ils sont maintenant saisissables au même endroit, parce qu'un
   texte qu'on relit est un texte qu'on corrige. */
/* **Exactement UNE des deux versions est visible.** La lecture vit dans le
   `<summary>`, les champs dans le corps : ouvert, la lecture s'efface. Sans ça, le
   même texte serait à l'écran deux fois et rien ne dirait lequel fait foi — c'est ce
   que l'écran du plan avait appris. */
.notion-editer > summary { cursor: pointer; list-style: none; }
.notion-editer > summary::-webkit-details-marker { display: none; }
.notion-editer[open] .notion-lecture { display: none; }
/* **« On ne sait pas qu'un texte est modifiable. »** C'était vrai : un libellé de
 * 0,85 rem, sans bordure, en pied de bloc, qui servait à la fois à ouvrir et à
 * fermer. Jonas a découvert la fonctionnalité principale du lot en cliquant au
 * hasard, et il savait ce qu'il cherchait.
 *
 * Il porte donc la forme d'un bouton — un cadre, un crayon, un curseur de main —
 * et il DIT dans quel sens il va. Ce n'est pas de l'ornement : un affordance
 * absente ne se rattrape pas par une explication ailleurs sur la page. */
.notion-editer-dit {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.5rem;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--trait-fort);
  border-radius: 4px;
  background: var(--surface);
  font-size: 0.85rem;
  color: var(--accent-texte);
  cursor: pointer;
}
.notion-editer > summary:hover .notion-editer-dit {
  border-color: var(--accent-trait);
  background: var(--accent-clair);
}
/* **Pas de glyphe, et pas de libellé posé par CSS.**
 *
 * Un crayon `¸E` rendait « Ɇ » dans la police de la page — vu au rendu, sur
 * les données réelles. Et l'astuce qui remplaçait le texte par un `::after`
 * quand le pavé s'ouvre ne se sélectionne pas, ne se traduit pas, et casse dès
 * que la police change. Le cadre suffit à dire qu'on peut cliquer ; l'état
 * ouvert se dit par la couleur, qui ne dépend d'aucun glyphe. */
.notion-editer[open] .notion-editer-dit {
  border-color: var(--accent-trait);
  background: var(--accent-clair);
}

/* **Ce qui part dans les DEUX documents.** Marqué là où on le corrige, pas au moment
   de valider : Chris doit savoir qu'il touche au fascicule quand il y touche. */
.projete-partage {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.35rem;
  border: 1px solid var(--trait-fort);
  border-radius: 3px;
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--encre-tenue);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* La légende du haut : même dessin, mais elle explique au lieu de marquer. */
.projete-legende { margin-left: 0; }

.notion-champs { display: grid; gap: 0.5rem; margin-top: 0.5rem; }
.notion-champs input[type="text"], .notion-champs textarea,
.notion-points input[type="text"], .notion-points textarea { width: 100%; }
.notion-points dd .cours-champ { margin-top: 0.3rem; }

/* Le piège et l'exemple, en LECTURE — ils vivent dans le `<summary>` de la notion,
   et leurs champs sont dans le corps du même pavé. */
.notion-piege, .notion-exemple, .notion-a-produire {
  margin: 0.3rem 0 0;
  font-size: 0.9rem;
}
/* Ce qui reste à Chris. Traité comme une tâche, pas comme un défaut : le support
   n'est pas cassé, il est incomplet et il le dit. */
.notion-a-produire { color: var(--accent-texte); font-weight: 600; }

/* Le pas suivant, depuis l'écran du plan. Une carte et non un lien dans un coin :
   c'est une ÉTAPE du travail, pas une option — et elle n'existe qu'une fois le plan
   produit, parce que les notions se découpent sur ses thèmes. */
.cours-suite { display: grid; gap: var(--e5); }

/* **DEUX LIGNES ENTIÈRES, un surlignage léger.** La version d'avant insérait les mots
   gagnés au milieu du texte barré : juste techniquement, illisible à l'usage — il
   fallait reconstituer deux phrases de tête pour les comparer. Chacune se lit
   maintenant d'un trait, et le fond dit où regarder. */
.cours-demande {
  margin: 0;
  padding: 0.5rem 0.8rem;
  border-left: 3px solid var(--accent-trait);
  background: var(--surface-creuse);
  font-style: italic;
}
.cours-diff-compte { margin: 0.4rem 0 0; font-size: 0.85rem; color: var(--encre-douce); }

/* L'avant en retrait et pâli, l'après en pleine encre : l'œil descend du passé au
   présent sans avoir besoin d'étiquette. */
.cours-diff-avant, .cours-diff-apres { display: block; line-height: 1.5; }
.cours-diff-avant { color: var(--encre-tenue); }
.cours-diff-avant mark {
  background: var(--refus-fond);
  color: var(--refus-encre);
  padding: 0 0.15rem;
  border-radius: 3px;
}
.cours-diff-apres mark {
  background: var(--f-vert-pale);
  color: var(--encre);
  padding: 0 0.15rem;
  border-radius: 3px;
}
.cours-diff-plus { margin-top: 0.6rem; font-size: 0.9rem; }
.cours-diff-plus summary { cursor: pointer; color: var(--encre-douce); }

/* Le bouton qui développe ce qui manque. Une ligne, pas une carte : c'est un geste,
   pas une section — et il disparaît quand il n'y a plus rien à développer. */
.cours-toutes {
  display: flex;
  gap: 0.8rem;
  align-items: baseline;
  flex-wrap: wrap;
  margin-bottom: var(--e5);
}

/* Une séance dont les notions datent d'un contrat plus ancien. Le filet d'accent et
   non celui de l'alerte : ce n'est pas un défaut du contenu, il lui manque un champ —
   et confondre les deux ferait chercher une erreur là où il n'y en a pas. */
.cours-perime {
  border-left-color: var(--accent-trait);
  padding: 0.5rem 0.8rem;
  background: var(--surface-creuse);
  font-size: 0.9rem;
}

/* ── Les quatre étapes d'un cours ──────────────────────────────────────────
 *
 * Une bande de progression, cliquable dans les deux sens. Elle ne dit pas que
 * l'ordre est obligatoire — revenir au plan depuis le projeté est un geste
 * normal —, elle dit où on en est.
 *
 * **Pas de couleur sémantique.** La charte n'a qu'un accent, et lui en ajouter
 * deux (un vert, un rouge) ferait trois codes de couleur pour trois états qui
 * se distinguent déjà par la forme : la puce est pleine, cerclée, ou vide.
 * Une couleur de plus se paie sur toutes les autres pages. */
.etapes {
  margin: 0 0 1.6rem;
}
.etapes ol {
  display: flex;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--trait);
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface);
}
.etape-etat {
  font-size: 0.78rem;
  color: var(--encre-tenue);
  /* L'état, lui, peut s'élider : « 3 séances sur 4 » perd sa fin sans perdre
   * son sens, et un écran étroit ne doit pas casser la bande. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.etape-puce {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2px solid var(--encre-pale);
  /* `flex: 0 0 auto` : sur un écran étroit, c'est l'état qui se coupe, jamais la puce —
   * une puce à moitié ronde ne dit plus rien de l'état de l'étape. */
  flex: 0 0 auto;
  align-self: center;
}
.etape-faite .etape-puce { background: var(--accent); border-color: var(--accent); }
.etape-en-cours .etape-puce { border-color: var(--accent); }
.etape-a-faire .etape-puce { background: transparent; }
/* L'étape COURANTE porte un filet, pas un aplat : un aplat la ferait lire
 * comme un bouton actif, alors qu'elle désigne la page qu'on regarde. */
.etape-ici { background: var(--surface-creuse); }
.etape-ici > a { color: var(--encre); }
.etape-ici > a { box-shadow: inset 0 -3px 0 var(--accent-trait); }

@media (max-width: 700px) {
  .etapes ol { flex-wrap: wrap; }
}

/* Une étape pas encore ouvrable : même place, même forme, pas de curseur de
 * lien. Le gris dit « plus tard », pas « désactivé par erreur ». */
/* Une étape pas encore ouvrable suit la MÊME géométrie que les autres : deux hauteurs
 * dans une bande de quatre feraient lire un décrochement là où il n'y a qu'un état. */
.etape-fermee {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.35rem 0.8rem;
  color: var(--encre-pale);
  cursor: default;
  min-width: 0;
}

/* L'avertissement de détachement, RÉPÉTÉ au pied, là où le bouton se trouve.
 * En tête d'un écran de six écrans de haut, il se lit après le geste — donc
 * jamais. Le liseré le distingue du bouton d'enregistrement ordinaire, qui est
 * juste à côté et ne demande aucune décision. */
.cours-detache-ici {
  flex-basis: 100%;
  margin-top: 0.8rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--trait-fort);
  border-left: 3px solid var(--accent-trait);
  border-radius: 5px;
  background: var(--surface-creuse);
}
.cours-detache-ici p { margin: 0 0 0.5rem; }
.cours-detache-ici ul { margin: 0 0 0.8rem; padding-left: 1.2rem; font-size: 0.9rem; }

/* Le diff d'un tour, en tête d'écran. Un filet à gauche le distingue des cartes
 * de contenu qui suivent : ce n'est pas le document, c'est ce qui vient de lui
 * arriver. Il disparaît au tour suivant, donc il ne doit pas se confondre avec
 * ce qui reste. */
.cours-diff-tour {
  border-left: 3px solid var(--accent-trait);
}

/* L'aperçu du document produit. Une hauteur FIXE et généreuse : un PDF de
 * quarante-trois pages dans un cadre de 300 px ne se juge pas, et laisser
 * l'objet prendre toute la page ferait perdre le reste de l'écran. */
.projete-apercu .projete-pdf { border: 1px solid var(--trait);
  display: block;
  width: 100%;
  height: 70vh;
  min-height: 420px;
  border: 1px solid var(--trait);
  border-radius: 4px;
  background: var(--surface-creuse);
}

/* « Validé » dans la liste des cours. Un aplat d'accent : c'est le seul état de
 * cette liste qui vaille une couleur, parce que c'est le seul qui dise qu'on
 * n'a plus rien à y faire. */
.cours-valide {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-clair);
  font-size: 0.72rem;
  font-weight: 600;
  vertical-align: 0.1em;
}

/* Les deux gestes de la validation côte à côte : poser et retirer. Le retrait
 * est discret sans être caché — c'est ce qui rend la pose sans danger. */
.cours-actions { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
.cours-actions form { margin: 0; }
/* Les trois documents, réunis sur le dernier écran du parcours. */
.cours-documents-liens { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
/* De quand date ce qu'on télécharge. À CÔTÉ du bouton et en petit : c'est un
 * repère, pas une information qu'on vient chercher. */
.cours-produit-le { font-size: 0.76rem; color: var(--encre-pale); }
/* **Le geste d'abord, sans vide au-dessus.** La rangée de boutons porte une marge
   haute pour se détacher de ce qui la précède — l'avancement du rendu, les pages
   refusées. Quand elle ouvre le pavé, cette marge s'ajoute au retrait de la carte :
   soixante et un pixels de blanc avant le seul bouton qu'on vient chercher. Mesuré
   en regardant la page, pas déduit du gabarit. */
.projete-apercu > .cours-documents-liens:first-child { margin-top: 0; }
/* Et le formulaire qui porte un de ces boutons perd sa marge basse : elle sert à
   détacher un bloc de gestes du texte qui suit, pas à écarter un bouton de son
   voisin dans une rangée. Elle ajoutait vingt pixels sous la rangée — invisibles
   dans le gabarit, puisque c'est le FORM qui les porte et non la rangée. */
.cours-documents-liens > form { margin-bottom: 0; }

/* Les remarques de la relecture. Chacune porte trois choses dans cet ordre :
 * où, quoi, pourquoi — et le pourquoi est en retrait parce que c'est ce qu'on
 * lit en second, une fois qu'on a décidé d'aller voir. */
.cours-relecture { list-style: none; margin: 0 0 0.8rem; padding: 0; display: grid;
  gap: 0.7rem; }
.cours-relecture li { display: grid; gap: 0.15rem; border-left: 2px solid var(--trait-fort);
  padding-left: 0.7rem; }
.cours-relecture-quoi { color: var(--encre); }

/* Le titre d'une séance en LECTURE, dans le `<summary>` de son pavé d'édition.
 * Il porte le poids d'un titre sans en être un : la hiérarchie de la page est
 * déjà prise par le `<h3>` du pavé replié. */
.cours-seance-titre {
  margin: 0 0 0.3rem;
  font-weight: 600;
  color: var(--encre-forte);
}
/* Le pavé d'édition d'une séance : pas de cadre à lui, il vit déjà dans la
 * carte de la séance. */
.cours-seance-editer { margin-top: 0.4rem; }

/* « Tu écris : la page ne se met plus à jour. » Deux états à la fois — une
 * saisie en cours et un tour qui tourne —, et Chris ne doit pas avoir à les
 * relier lui-même. Le fond marque que c'est une conséquence de son geste, pas
 * une panne. */
.cours-frappe-dit {
  margin-top: 0.6rem;
  padding: 0.5rem 0.7rem;
  border-left: 3px solid var(--accent-trait);
  background: var(--surface);
  font-size: 0.9rem;
}

/* La grille et le schéma d'une notion, en LECTURE. Ils n'apparaissaient nulle
 * part sur cet écran, et l'écran du projeté n'en montrait qu'un décompte —
 * conditionné par `utilisable`, donc éteint exactement quand il y a quelque
 * chose à voir. Chris relisait des cartes et la classe voyait un arbre dont il
 * n'avait jamais lu les branches. */
.notion-grille, .notion-schema {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
}
.notion-grille table {
  width: 100%;
  margin-top: 0.3rem;
  border-collapse: collapse;
}
.notion-grille th, .notion-grille td {
  border: 1px solid var(--trait);
  padding: 0.25rem 0.45rem;
  text-align: left;
  vertical-align: top;
}
.notion-grille th { background: var(--surface-creuse); font-weight: 600; }
/* La cellule ORPHELINE, marquée à sa place. « Nomme la colonne manquante »
 * n'était actionnable que dans sa formulation : rien ne disait laquelle, et
 * aucun écran ne la montrait. */
.notion-grille .grille-orpheline {
  background: var(--refus-fond);
  font-style: italic;
}
.notion-schema ol { margin: 0.2rem 0 0; padding-left: 1.4rem; }

/* Une grille large ne casse pas la page : elle défile dans son cadre. La règle du
 * projet vaut ici comme ailleurs — le corps de l'écran ne défile jamais
 * horizontalement, ce qui déborde défile dans sa propre boîte. */
.grille-cadre { overflow-x: auto; }

/* --- La grille en SAISIE : une matrice, pas trois champs texte -----------
 *
 * Elle se saisissait en « colonnes séparées par | » puis « lignes, cellules séparées
 * par | » : Chris devait compter les barres de chaque ligne et vérifier que le compte
 * égalait celui des colonnes. C'est l'opération que le défaut de production a ratée,
 * et celle que le système existe pour faire à sa place.
 *
 * Les cases sont des `input` SANS bordure propre : c'est la cellule qui porte le
 * trait. Deux traits emboîtés — celui du tableau et celui du champ — faisaient lire
 * une grille de boutons ; ici on lit un tableau, et on écrit dedans. */
.grille-saisie { margin: 0.6rem 0 0; }
.grille-matrice {
  width: 100%;
  margin-top: 0.3rem;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.grille-matrice th, .grille-matrice td {
  border: 1px solid var(--trait);
  padding: 0;
}
.grille-matrice input {
  width: 100%;
  min-width: 6.5rem;
  box-sizing: border-box;
  border: 0;
  border-radius: 0;
  padding: 0.3rem 0.45rem;
  font: inherit;
  color: inherit;
  background: transparent;
}
/* L'en-tête se lit comme un en-tête même en saisie : c'est ce qui rend les colonnes
 * visibles COMME colonnes, et une colonne sans nom se voit alors au premier coup
 * d'œil — c'est exactement le défaut qu'on vient corriger. */
.grille-matrice thead input { font-weight: 600; background: var(--surface-creuse); }
.grille-matrice input:focus {
  outline: 2px solid var(--accent-trait);
  outline-offset: -2px;
}
/* Le rang de la ligne. Il ne se saisit pas : il sert à parler d'une ligne — « la
 * ligne 3 » — quand un refus la nomme. */
.grille-rang {
  width: 1.7rem;
  padding: 0.3rem 0;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--encre-pale);
  background: var(--surface-creuse);
}

/* Les gestes d'une séance ou d'une notion, CÔTE À CÔTE et de même format. Ils
 * étaient l'un sous l'autre et de deux formes différentes — un bouton cadré et
 * un `<summary>` nu —, ce qui les faisait lire comme deux natures de choses
 * quand ce sont deux gestes du même rang. */
.cours-gestes { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: flex-start; }
.cours-gestes > .cours-geste { margin: 0; }
.cours-geste > summary { list-style: none; }
.cours-geste > summary::-webkit-details-marker { display: none; }
/* Ouverts, ils reprennent la largeur : un champ de saisie à moitié d'écran est un
 * champ dans lequel on n'écrit pas. */
.cours-gestes > .cours-geste[open] { flex-basis: 100%; }

/* La séparation entre ce qu'on peut FAIRE et ce qu'on LIT. Sans elle, les deux
 * boutons d'une séance et son déroulé se confondaient. */
.cours-sep {
  margin: 0.9rem 0 0.6rem;
  border: 0;
  border-top: 1px solid var(--trait);
}

/* Les trois gestes de l'écran, en bas et HORS pavé : « je corrige », « je fais
 * reprendre », « je passe à la suite ». Dispersés, on ne voyait pas qu'ils
 * forment une suite — et « reprendre » emporte les remarques écrites plus haut,
 * ce que sa place dans un pavé ne disait pas. */
.cours-barre-bas {
  display: flex;
  gap: 0.7rem;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 1.4rem;
  padding-top: 1rem;
  border-top: 2px solid var(--trait-fort);
}
.cours-barre-dit { margin-top: 0.4rem; }

/* **L'en-tete du COURS, sur les quatre ecrans.** Compacte : ce n'est pas ce qu'on
   vient faire, et un pave sur chaque ecran pousserait le travail sous la ligne de
   flottaison — ce que la refonte a justement corrige. Des valeurs separees, sans
   titres de colonnes : « BAC+3 » n'a pas besoin qu'on lui dise « Niveau ». */
.cours-entete-ligne { display: flex; flex-wrap: wrap; gap: .3rem .9rem;
  margin: .1rem 0 .9rem; font-size: .88rem; color: var(--encre-douce); }
/* **Un FILET, pas un caractere.** Un point median en `content` est un glyphe pose par
   la feuille de style : il depend d'une police que la machine n'a peut-etre pas, et le
   crible du projet le refuse — a raison, c'est ainsi qu'un « · » devient un carre vide
   sur l'ecran de quelqu'un d'autre. Une bordure ne depend d'aucune police. */
.cours-entete-ligne > span + span { border-left: 1px solid var(--trait);
  padding-left: .9rem; }
.cours-entete-cout b { color: var(--accent-texte); }

/* --- Les chiffres de l'etude de cas, sur l'ecran du plan -------------------
 *
 * Ils s'ecrivent une fois, dans le plan, et les quatre seances les citent. S'ils
 * n'apparaissaient que dans les documents produits, Chris ne pourrait ni les verifier
 * avant de payer les tours, ni savoir lequel corriger — motif n°11.
 *
 * En LECTURE : on les corrige par une phrase, avec le meme mecanisme que l'intitule
 * du cas. Une edition directe ferait un second chemin d'ecriture sur le plan.
 */
.cours-chiffres { list-style: none; margin: .9rem 0 0; padding: 0;
                  display: grid; gap: .35rem .9rem;
                  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }
.cours-chiffres li { font-size: .92rem; line-height: 1.45; }
.cours-precision { color: var(--encre-tenue); font-weight: normal; }
.cours-serie { margin-top: .7rem; font-size: .92rem; }
.cours-serie > summary { cursor: pointer; font-weight: 600; }
.cours-serie ul { list-style: none; margin: .4rem 0 0; padding: 0 0 0 1.1rem; }
/* Une serie se lit comme une colonne de valeurs : l'etiquette a gauche, le nombre a
 * droite, alignes. En ligne libre, l'oeil ne peut pas les comparer. */
.cours-serie li { display: flex; justify-content: space-between; gap: 1.2rem;
                  max-width: 34rem; padding: .15rem 0;
                  border-bottom: 1px solid var(--trait); }
/* La figure d'une notion, sur l'ecran du projete : meme forme que « a composer », parce
 * que les deux repondent a la meme question — qu'est-ce que cette page portera. */
.notion-figure { margin-top: .6rem; font-size: .92rem; color: var(--encre-douce); }

/* Le pave de correction sur l'ecran du projete. Il y arrive parce que c'est la que se
 * lisent les pages refusees au rendu : le diagnostic nomme la cellule et le nombre de
 * caracteres, et il n'avait aucun bouton. */
.projete-corrections { margin-top: 1.4rem; }

/* Le bouton d'extraction et son cout sur la MEME ligne : ce qu'on veut savoir avant de
 * cliquer tient en quelques mots, et le reste se lisait apres avoir deja decide. */
.ref-extraire { display: flex; align-items: baseline; gap: .9rem; flex-wrap: wrap; }

/* **Le titre du cours et son contexte sur la MEME ligne.** Les informations du module —
 * ecole, niveau, seances, volume, competences, cout — occupaient une ligne entiere sous
 * la timeline. Ce n'est pas du contenu, c'est du contexte : un contexte qui prend une
 * ligne pleine se lit comme une chose a faire.
 *
 * `align-items: baseline` et non `center` : le titre et les valeurs n'ont pas la meme
 * taille, et les centrer verticalement ferait flotter les petites au milieu du grand.
 * `flex-wrap` les renvoie sous le titre quand la place manque — jamais tronquees. */
.cours-titre-ligne { display: flex; align-items: baseline; flex-wrap: wrap;
                     gap: .3rem 1.1rem; }
.cours-titre-ligne > h1 { margin: 0; }
/* La ligne de valeurs ne pousse plus rien : elle prend la place qui reste a droite du
 * titre, et ses marges verticales disparaissent puisqu'elle partage sa ligne. */
.cours-titre-ligne > .cours-entete-ligne { margin: 0; flex: 1 1 auto; }

/* --- « Mes cours » : la liste, et elle doit tenir à cent lignes -------------------
 *
 * Ce qu'on vient y faire est retrouver un cours. Donc : une ligne compacte, des
 * filtres qui tiennent au-dessus sans faire descendre, et rien entre les lignes. Un
 * pavé d'explication entre deux cours se relit à chaque visite pour un geste qu'on
 * connaît déjà. */
.mescours-filtres {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem 1rem;
  align-items: flex-end;
  margin: 0 0 1rem;
}
.mescours-filtre { display: flex; flex-direction: column; gap: 0.2rem; }
.mescours-filtre > span { font-size: 0.78rem; color: var(--encre-pale); }
.mescours-filtre > span em { font-style: normal; }
.mescours-filtre-large select { min-width: 12rem; }
.mescours-coche { display: flex; align-items: center; gap: 0.35rem; font-size: 0.86rem; }
.mescours-tout { font-size: 0.82rem; align-self: center; }

.mescours-liste { list-style: none; margin: 0; padding: 0; }
/* Une ligne, pas une carte : cinquante cartes font cinquante encadrés, et on ne voit
 * plus la liste. Le filet suffit à séparer. */
.mescours-ligne {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--trait);
}
/* Ce qui demande du travail se voit sans se lire. */
.mescours-a-finir { border-left: 3px solid var(--accent); padding-left: 0.5rem; }
.mescours-entrer {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.8rem;
  text-decoration: none;
  color: inherit;
  min-width: 0;
}
.mescours-entrer:hover .mescours-titre { text-decoration: underline; }
.mescours-titre { font-weight: 600; }
.mescours-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.8rem;
  font-size: 0.8rem;
  color: var(--encre-pale);
}
.mescours-codes { font-variant-numeric: tabular-nums; }
.mescours-etat { color: var(--accent); }
/* Les documents sont REPLIÉS : on ne les cherche pas en parcourant la liste, on les
 * cherche sur un cours. Dépliés, ils feraient trois lignes de plus par cours. */
/* **Fermé, il tient au bout de la ligne ; OUVERT, il prend la largeur.**
 * Vu au rendu : coincé dans la colonne de droite, le pli déroulait ses trois documents
 * dans un tiers de la page, la moitié gauche vide et les phrases coupées. Un `[open]`
 * suffit — pas de JavaScript pour une mise en page. */
.mescours-documents { margin-left: auto; }
.mescours-documents[open] { flex-basis: 100%; margin-left: 0; }
.mescours-documents > summary {
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--encre-pale);
}
.mescours-documents ul { list-style: none; margin: 0.4rem 0 0.2rem; padding: 0; }
.mescours-documents li {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0.25rem 0;
}
.mescours-absent { font-size: 0.85rem; color: var(--encre-pale); }
