/* Mise en page reprise de docs.teeptrak.com : barre haute, colonne de lecture
   étroite, cartes blanches à bordure fine, ombres quasi absentes. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--body-text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.65;
}

img,
svg {
  max-width: 100%;
  height: auto;
}

a {
  color: var(--brand);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

h1,
h2,
h3 {
  color: var(--ink);
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-4);
}

h1 {
  font-size: clamp(1.9rem, 1.4rem + 2vw, 2.6rem);
}

/* Le lien d'évitement doit rester atteignable au clavier sans être visible. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--surface);
  color: var(--ink);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  z-index: 100;
}

.skip-link:focus {
  left: var(--space-4);
  top: var(--space-4);
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--page) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-warm);
}

.site-header__inner {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-3) var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.brand:hover {
  text-decoration: none;
}

.brand__mark {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--brand);
  flex: none;
}

.site-header__spacer {
  flex: 1;
}

.lang-switch {
  display: flex;
  gap: var(--space-1);
  align-items: center;
}

.lang-switch a {
  color: var(--muted);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  /* Cible tactile confortable sur les tablettes d'atelier. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.lang-switch a[aria-current='true'] {
  color: var(--ink);
  background: var(--surface-subtle);
  font-weight: 600;
}

.theme-toggle {
  min-height: 44px;
  min-width: 44px;
  border: 1px solid var(--line-warm);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 0.95rem;
}

main {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-12) var(--space-4) var(--space-16);
}

.lede {
  max-width: var(--reading-width);
  font-size: 1.125rem;
  color: var(--body-text);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-8);
  padding: 0;
  list-style: none;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-6);
}

.card h2 {
  font-size: 1.05rem;
  margin-bottom: var(--space-2);
}

.card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
}

.badge {
  display: inline-block;
  background: var(--brand-soft);
  color: var(--brand-ink);
  border-radius: 999px;
  padding: 2px var(--space-3);
  font-size: 0.8rem;
  font-weight: 600;
}

/* Un sujet réussi, sur le catalogue : une coche verte en coin de vignette, en
   plus du mot sur la ligne d'informations — la couleur seule ne dit rien. */
.card--reussie .card__illustration {
  position: relative;
}

.card--reussie .card__illustration::after {
  content: "✓";
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  background: var(--ok);
  color: #fff;
  font-weight: 700;
}

.sujet-fin--reussi {
  border-color: var(--ok);
  background: var(--ok-soft);
}

/* Un outil qui couvre tous les points choisis, dans la matrice. */
.badge--plein {
  background: var(--ok-soft);
  color: var(--ok);
}

.site-footer {
  border-top: 1px solid var(--line-warm);
  color: var(--muted);
  font-size: 0.875rem;
}

.site-footer__inner {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

.error-page {
  max-width: var(--reading-width);
}

.error-page__status {
  font-family: var(--font-mono);
  color: var(--muted);
}

/* --- Authentification --------------------------------------------------- */

.auth {
  max-width: 26rem;
  margin: 0 auto;
}

.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: var(--space-6) 0;
}

.form label {
  color: var(--ink);
  font-weight: 600;
  font-size: 0.9rem;
  margin-top: var(--space-3);
}

.form input {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-3);
  min-height: 44px;
}

.form__hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
}

.button:hover {
  text-decoration: none;
  border-color: var(--n400);
}

.button--primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--sur-brand);
}

/* La marge haute ne vaut que pour le bouton d'envoi d'un formulaire, qui se
   détache des champs. Posée sur tous les boutons principaux, elle les faisait
   descendre d'un rem sous leur voisin dans chaque rangée de boutons — corrigé
   rangée par rangée, trois fois, avant d'être corrigé ici. */
.form > .button--primary,
.form > button.button--primary {
  margin-top: var(--space-4);
}

.button--provider {
  width: 100%;
  margin-bottom: var(--space-2);
}

.auth__providers {
  margin-top: var(--space-6);
}

/* Séparateur « ou » : un trait de part et d'autre du mot. */
.auth__separator {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--muted);
  font-size: 0.85rem;
  margin: var(--space-6) 0 0;
}

.auth__separator::before,
.auth__separator::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line-warm);
}

.auth__links {
  color: var(--muted);
  font-size: 0.9rem;
}

.alert {
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0 0;
}

.alert--error {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-ink);
}

/* --- Logo ---------------------------------------------------------------- */

/* Le mot-symbole est en currentColor : il suit --ink, donc devient blanc en
   mode nuit. La marque rouge, elle, ne change pas. */
.logo {
  height: 22px;
  width: auto;
  display: block;
  color: var(--ink);
}

.brand {
  gap: var(--space-3);
}

.brand__name {
  padding-left: var(--space-3);
  border-left: 1px solid var(--line-warm);
  color: var(--muted);
  font-weight: 500;
}

@media (max-width: 30rem) {
  /* Sur mobile, le logo suffit à situer le site. */
  .brand__name {
    display: none;
  }
}

/* --- Sélecteur de langue -------------------------------------------------- */

/* Bâti sur <details> : le menu s'ouvre et se ferme sans JavaScript, et reste
   accessible au clavier nativement. Le script ne fait qu'ajouter le confort
   (Échap, clic à l'extérieur). */
/* Le menu replié de téléphone : un bouton rond, entre la langue et le thème.
   À cinq entrées, la barre occupait une ligne entière au-dessus de chaque page
   — sur un écran de six pouces, c'est autant de contenu en moins. */
.menu-plie {
  display: none;
  position: relative;
}

.menu-plie > summary {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-warm);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.menu-plie > summary::-webkit-details-marker {
  display: none;
}

.menu-plie > summary::marker {
  content: "";
}

/* L'initiale du compte quand il y en a un : on sait d'un coup d'œil sur quel
   compte on est, ce qui compte sur un poste partagé. Sinon, trois traits. */
.menu-plie__burger {
  display: block;
  overflow: visible;
}

.menu-plie__barre {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.18s var(--ease), opacity 0.18s var(--ease);
}

/* Ouvert : les barres du haut et du bas se croisent, celle du milieu s'efface. */
.menu-plie[open] .menu-plie__barre--haut {
  transform: translateY(5px) rotate(45deg);
}

.menu-plie[open] .menu-plie__barre--milieu {
  opacity: 0;
}

.menu-plie[open] .menu-plie__barre--bas {
  transform: translateY(-5px) rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .menu-plie__barre {
    transition: none;
  }
}

.menu-plie__liste {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 30;
  display: flex;
  flex-direction: column;
  min-width: 13rem;
  padding: var(--space-2);
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgb(0 0 0 / 8%);
}

.menu-plie__liste a,
.menu-plie__liste button {
  display: block;
  width: 100%;
  padding: var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.menu-plie__liste a:hover,
.menu-plie__liste button:hover {
  background: var(--surface-subtle);
  text-decoration: none;
}

.menu-plie__liste a[aria-current="page"] {
  font-weight: 600;
}

/* L'adresse du compte, en tête des actions qui le concernent. */
.menu-plie__compte {
  margin: var(--space-2) var(--space-3) var(--space-1);
  padding-top: var(--space-2);
  border-top: 1px solid var(--line-warm);
  color: var(--muted);
  font-size: 0.82rem;
  overflow-wrap: anywhere;
}

.lang-menu {
  position: relative;
}

.lang-menu > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

/* Retire le triangle natif : on fournit notre propre chevron. */
.lang-menu > summary::-webkit-details-marker {
  display: none;
}

.lang-menu > summary::marker {
  content: '';
}

.lang-menu > summary:hover {
  border-color: var(--n400);
}

.lang-menu__chevron {
  color: var(--muted);
  transition: transform 0.15s ease;
}

.lang-menu[open] .lang-menu__chevron {
  transform: rotate(180deg);
}

.lang-menu__list {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 30;
  min-width: 12rem;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgb(0 0 0 / 8%);
}

.lang-menu__list a {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--body-text);
}

.lang-menu__list a:hover {
  background: var(--surface-subtle);
  text-decoration: none;
}

.lang-menu__list a[aria-current='true'] {
  color: var(--ink);
  font-weight: 600;
  background: var(--surface-subtle);
}

/* Le drapeau porte une bordure : sans elle, le blanc du drapeau français se
   confond avec le fond de la carte. */
.flag {
  display: block;
  width: 20px;
  height: 15px;
  flex: none;
  border-radius: 2px;
  border: 1px solid var(--line-warm);
  object-fit: cover;
}

.flag--text {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 15px;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted);
  background: var(--surface-subtle);
}

@media (max-width: 30rem) {
  /* Le drapeau seul suffit quand la place manque. */
  .lang-menu__label {
    display: none;
  }
}

/* --- Administration ------------------------------------------------------- */

/* Fond distinct : on doit voir d'un coup d'œil qu'on est dans l'administration
   et non sur l'académie. */
.admin-body {
  background: var(--surface-subtle);
}

.admin-header {
  background: var(--surface);
}

.admin-nav {
  display: flex;
  gap: var(--space-1);
}

.admin-nav a {
  color: var(--muted);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-size: 0.9rem;
}

.admin-nav a:hover {
  background: var(--surface-subtle);
  color: var(--ink);
  text-decoration: none;
}

.inline-form {
  display: inline;
}

.button--small {
  min-height: 36px;
  padding: var(--space-1) var(--space-3);
  font-size: 0.85rem;
  font-weight: 500;
}

.button--danger {
  color: var(--brand-ink);
  border-color: var(--line-warm);
}

.button--danger:hover {
  border-color: var(--brand);
}

.button[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.button-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
  flex-wrap: wrap;
}


.stat-row {
  display: flex;
  gap: var(--space-4);
  list-style: none;
  padding: 0;
  margin: var(--space-6) 0;
  flex-wrap: wrap;
}

.stat {
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-6);
  min-width: 8rem;
}

.stat__value {
  display: block;
  font-size: 1.8rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.1;
}

.stat__label {
  color: var(--muted);
  font-size: 0.85rem;
}

/* Un tableau large doit défiler dans son propre cadre : la page, elle, ne
   défile jamais horizontalement. */
.table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  margin: var(--space-6) 0 var(--space-3);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.table th,
.table td {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line-warm);
  vertical-align: middle;
}

.table thead th {
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.table tbody tr:last-child th,
.table tbody tr:last-child td {
  border-bottom: none;
}

.table .actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.tag {
  display: inline-block;
  padding: 2px var(--space-2);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--n100);
  color: var(--n700);
}

.tag--published {
  background: #e7f5ec;
  color: #1b6b3a;
}

:root[data-theme='dark'] .tag--published {
  background: #14301f;
  color: #7ddba2;
}

.tag--archived {
  background: var(--n200);
  color: var(--n600);
}

.alert--ok {
  background: #e7f5ec;
  border-color: #b6dfc6;
  color: #14512c;
}

:root[data-theme='dark'] .alert--ok {
  background: #14301f;
  border-color: #1f6b3f;
  color: #9ee7ba;
}

.alert--warn {
  background: #fdf3e3;
  border-color: #efd9ae;
  color: #6b4a12;
}

:root[data-theme='dark'] .alert--warn {
  background: #33280f;
  border-color: #6b5620;
  color: #e8ce8d;
}

.alert ul {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-6);
}

.admin-body .card {
  margin-top: var(--space-8);
}

/* --- Éditeur de contenu --------------------------------------------------- */

.fieldset,
.block {
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin: var(--space-4) 0;
  background: var(--surface);
}

.fieldset legend,
.block legend {
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0 var(--space-2);
}

.block textarea {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-3);
  resize: vertical;
}

.checkbox {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: var(--space-2) 0;
  font-weight: 400;
  color: var(--body-text);
}

.checkbox input {
  min-height: auto;
  width: auto;
}

/* Traduction périmée : la couleur seule ne doit jamais porter l'information,
   le texte du badge dit toujours combien de blocs repartiront. */
.tag--stale {
  background: #fdf3e3;
  color: #6b4a12;
}

:root[data-theme='dark'] .tag--stale {
  background: #33280f;
  color: #e8ce8d;
}

.tag--draft {
  background: var(--n100);
  color: var(--n700);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Lecture ------------------------------------------------------------- */

.reading {
  max-width: var(--reading-width);
  /* Centrée. Calée à gauche dans un `main` de 1240 px, elle laissait la moitié
     d'un écran de bureau vide — le premier reproche fait à la lecture. */
  margin-inline: auto;
}

/* Sauf dans la grille d'une leçon, où c'est la paire qui est centrée. */
.lecon .reading {
  margin-inline: 0;
}

.breadcrumb {
  color: var(--muted);
  font-size: 0.9rem;
  margin-bottom: var(--space-6);
}

.prose p,
.prose ul,
.prose ol,
.prose blockquote {
  margin: 0 0 var(--space-4);
}

.prose h2 {
  margin-top: var(--space-8);
  font-size: 1.3rem;
}

.prose blockquote {
  border-left: 3px solid var(--line-warm);
  padding-left: var(--space-4);
  color: var(--muted);
  font-style: italic;
}

/* Ce qui mérite d'être retenu. Le fond coloré ne porte pas seul le sens : le
   texte se suffit à lui-même. */
.callout {
  background: var(--brand-soft);
  border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: var(--space-4);
  margin: var(--space-6) 0;
  color: var(--ink);
}

.prose figure {
  margin: var(--space-8) 0;
  text-align: center;
}

.prose figure svg {
  max-width: 100%;
  height: auto;
}

.prose figcaption {
  color: var(--muted);
  font-size: 0.9rem;
  margin-top: var(--space-3);
}

/* Mention de traduction automatique : question de crédibilité, on ne la cache
   pas et on ne la met pas non plus en avant. */
/* Les listes de l'introduction au Lean : sept gaspillages, six questions, cinq
 * pièges. Chaque entrée est une phrase entière, pas un mot — serrées comme des
 * puces ordinaires, elles se lisaient comme un paragraphe haché. */
.lean-liste {
  margin: var(--space-4) 0;
  padding-left: var(--space-6);
}

.lean-liste li {
  margin-bottom: var(--space-3);
  padding-left: var(--space-1);
}

.lean-liste li::marker {
  color: var(--brand);
  font-weight: 600;
}

.notice {
  background: var(--surface-subtle);
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  color: var(--muted);
  font-size: 0.9rem;
}

.progress {
  color: var(--muted);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: var(--space-2);
}

.steps {
  padding-left: var(--space-6);
}

.steps li {
  margin-bottom: var(--space-3);
}

.steps .form__hint {
  display: inline;
  margin-left: var(--space-2);
}

.pager {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  border-top: 1px solid var(--line-warm);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
}

.card__meta {
  margin-top: var(--space-3);
  color: var(--muted);
  font-size: 0.85rem;
}

.sources summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.9rem;
  padding: var(--space-2) 0;
}

/* --- Quiz et progression --------------------------------------------------- */

.question {
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-6);
  margin: var(--space-6) 0;
  background: var(--surface);
}

/* Le verdict est aussi écrit en toutes lettres : la couleur seule ne doit
   jamais porter l'information. */
.question--juste {
  border-left: 3px solid #1b6b3a;
}

.question--faux {
  border-left: 3px solid var(--brand);
}

.question__stem {
  color: var(--ink);
  font-weight: 600;
  margin-bottom: var(--space-4);
}

.question__verdict {
  margin-top: var(--space-4);
  font-weight: 600;
  color: var(--ink);
}

/* Les jauges sont des <progress> : la CSP n'autorise aucun style en ligne, donc
   pas de `style="width: 75%"`. La valeur vit dans l'attribut, le navigateur
   dessine ; on habille les deux moteurs de rendu. */
.progress-bar,
.jauge {
  display: block;
  width: 100%;
  appearance: none;
  border: 0;
  overflow: hidden;
  color: var(--brand);
}

.progress-bar {
  height: 6px;
  background: var(--n200);
  border-radius: 999px;
  margin: var(--space-3) 0;
}

.progress-bar::-webkit-progress-bar,
.jauge::-webkit-progress-bar {
  background: transparent;
}

.progress-bar::-webkit-progress-value,
.jauge::-webkit-progress-value {
  background: var(--brand);
  border-radius: inherit;
}

.progress-bar::-moz-progress-bar,
.jauge::-moz-progress-bar {
  background: var(--brand);
  border-radius: inherit;
}

.validate {
  border-top: 1px solid var(--line-warm);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
}

.attestation code {
  background: var(--code-bg);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
}

.header-link {
  color: var(--muted);
  font-size: 0.9rem;
  padding: var(--space-2) var(--space-3);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-sm);
}

.header-link[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
}

.header-link:hover {
  color: var(--ink);
  background: var(--surface-subtle);
  text-decoration: none;
}

/* --- Illustrations de couverture ------------------------------------------
 *
 * Le catalogue est une grille de cartes : sans image, elles se ressemblent
 * toutes et l'œil n'accroche rien. L'illustration porte le repérage, le titre
 * porte l'information — d'où une image purement décorative, sortie de l'ordre
 * de tabulation et des lecteurs d'écran.
 */

.card--illustree {
  /* Le padding passe sur le contenu : l'illustration doit toucher les bords. */
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.card--illustree > :not(.card__illustration) {
  padding-inline: var(--space-6);
}

/* Le résumé d'un sujet vient du contenu, et sa longueur varie du simple au
 * quadruple : une carte faisait deux fois la hauteur de sa voisine, et la
 * grille devenait un escalier. Quatre lignes, coupées proprement.
 *
 * Certains résumés s'arrêtent déjà en plein mot — « acteurs s'approprient des
 * stan ». Les points de suspension ne réparent pas le texte, mais ils font
 * lire la coupe comme voulue plutôt que comme un bogue. Le reste est sur la
 * page du sujet, à un clic. */
.card--illustree > p:not(.card__meta) {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}

/* La ligne d'informations est repoussée en pied de carte : alignée d'une carte
 * à l'autre, elle se parcourt d'un coup d'œil au lieu de flotter à la hauteur
 * où le résumé s'est arrêté. */
.card--illustree .card__meta {
  margin-top: auto;
  padding-top: var(--space-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
}
/* Par l'élément, pas par la position : l'étoile des favoris, posée en
   absolu, s'ajoute aux enfants de la carte sans devoir déplacer les marges. */
.card--illustree > .card__illustration + * {
  padding-top: var(--space-5);
}
.card--illustree > :last-child:not(.favori),
.card--illustree > :nth-last-child(2):has(+ .favori) {
  padding-bottom: var(--space-6);
}

.card__illustration {
  display: block;
  /* `aspect-ratio` plutôt qu'une hauteur fixe : la carte suit la largeur de la
   * colonne, et rien ne saute quand l'image arrive. */
  aspect-ratio: 16 / 10;
  /* Le rose de marque, pas le gris chaud. Vingt panneaux gris empilés faisaient
   * une page grise ; c'était le premier reproche sur cette grille. Et c'est
   * bien ici que la teinte doit vivre, pas dans le SVG : le fichier est servi
   * en `<img>`, il ne peut pas suivre le thème, alors que ce jeton le fait. */
  background: var(--brand-soft);
  overflow: hidden;
}

.card__illustration img {
  width: 100%;
  height: 100%;
  /* `contain` et non `cover` : une vignette carrée dans un cadre plus large ne
   * doit pas être rognée sur ses bords, où se trouve souvent le sens. */
  object-fit: contain;
  padding: var(--space-4);
}

/* --- Page d'un sujet ------------------------------------------------------

   Reproche fondé : « vraiment très laide, avec des erreurs de mise en page sur
   portable ». C'était un mur de texte — trois titres, deux listes à puces — avec
   une vignette en `float: right` autour de laquelle le résumé s'enroulait, et
   qui sur téléphone prenait un tiers de l'écran avant le premier mot.
   Ce qui suit reprend la grammaire de fiche du site : un carré d'accent arrondi
   à gauche, un titre en gras, une note discrète en dessous. */

.sujet-tete {
  display: grid;
  gap: var(--space-6);
  align-items: start;
  margin-bottom: var(--space-10);
}

@media (min-width: 56rem) {
  .sujet-tete {
    /* Le texte porte la page ; la vignette l'accompagne, à taille fixe. */
    grid-template-columns: minmax(0, 1fr) 180px;
    gap: var(--space-10);
  }
}

.sujet-tete h1 {
  margin: 0 0 var(--space-3);
}

.sujet-tete .lede {
  margin-bottom: var(--space-5);
}

.sujet-tete__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin: 0 0 var(--space-4);
  color: var(--muted);
  font-size: 0.9rem;
}

/* Un point entre les éléments, posé par le CSS : dans le gabarit, il aurait
   fallu le rendre conditionnel à chaque fois. Il est accroché à ce qui
   **précède** : en `::before`, un repli de ligne le faisait commencer la
   suivante, et la ligne s'ouvrait sur un point orphelin. */
.sujet-tete__meta > span:not(:last-child)::after {
  content: "·";
  margin-left: var(--space-3);
  color: var(--line);
}

.sujet-tete__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: var(--space-6) 0 var(--space-2);
}

/* Ce qui ne sert qu'en l'absence de script — le bouton d'envoi de la matrice —
   disparaît dès que le script est là. La classe est posée par le script en
   tête de page, donc avant le premier rendu : plus de bouton qui apparaît puis
   s'efface. Sans script, la classe n'existe pas et le bouton reste, seul moyen
   d'envoyer le formulaire.

   Au niveau racine, et nulle part ailleurs : collée par erreur à l'intérieur
   de `.sujet-tete__vignette`, l'imbrication CSS en faisait
   `.sujet-tete__vignette :root.js [data-sans-js]`, qui ne cible rien — et le
   bouton « Voir les outils » de la matrice restait affiché, redondant. */
:root.js [data-sans-js] {
  display: none;
}

.sujet-tete__vignette {
  background: var(--surface-subtle);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  /* Sur téléphone, la vignette passe **avant** le texte, en petit : posée après
     les boutons, elle coupait l'en-tête de l'introduction au milieu. En tête,
     elle se lit comme l'emblème du sujet et ne repousse rien. */
  order: -1;
  max-width: 104px;
  padding: var(--space-3);
}

@media (min-width: 56rem) {
  .sujet-tete__vignette {
    order: 0;
    max-width: none;
  }
}

.sujet-tete__vignette img {
  display: block;
  width: 100%;
  height: auto;
}

/* La page d'un sujet : une colonne de 60rem, centrée. Le corps était borné à
   la mesure de lecture (68ch) et calé à gauche, l'en-tête étiré sur 1240 px
   avec la vignette au bord de l'écran : sur PC, la moitié droite restait vide.
   Sous 56rem, `main` est plus étroit que 60rem — le téléphone ne change pas. */
.sujet-tete,
.sujet-corps {
  max-width: var(--sujet-width);
  margin-inline: auto;
}

/* Le texte courant garde sa mesure de lecture dans la colonne : un paragraphe
   de 60rem se lit mal. Les fiches, elles, prennent toute la largeur. */
.sujet-corps .prose,
.sujet-corps .encart {
  max-width: var(--reading-width);
}

/* Le fil d'Ariane s'aligne sur la colonne, sinon il reste seul collé à gauche. */
.breadcrumb--sujet {
  max-width: var(--sujet-width);
  margin-inline: auto;
}

.sujet-bloc {
  margin-bottom: var(--space-10);
}

.sujet-bloc h2 {
  margin-bottom: var(--space-5);
}

/* Les fiches : le motif commun aux objectifs et aux étapes. */
.fiches {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 48rem) {
  .fiches--deux {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.fiche {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.fiche__icone {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 10px;
  background: var(--brand-soft);
  color: var(--brand);
  font-weight: 700;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
}

.fiche__corps {
  flex: 1;
  min-width: 0;
}

.fiche__titre {
  display: block;
  font-weight: 600;
  color: var(--ink);
}

.fiche__note {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
  color: var(--muted);
  font-size: 0.88rem;
}

/* Une étape franchie garde sa fiche, mais son rang devient une coche. */
.fiche--faite .fiche__icone--rang {
  background: var(--ok-soft, var(--brand-soft));
  color: var(--ok, var(--brand-ink));
}

.fiche__chevron {
  flex: none;
  align-self: center;
  color: var(--line);
  font-size: 1.5rem;
  line-height: 1;
}

/* Toute la fiche répond au survol quand elle mène quelque part : le lien est
   dans le titre, mais c'est la carte entière qu'on vise avec un doigt. */
.etapes-fiches .fiche:has(a) {
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.etapes-fiches .fiche:has(a):hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-lg);
}

.etapes-fiches .fiche:has(a):hover .fiche__chevron {
  color: var(--brand);
}

.fiche__titre a {
  color: inherit;
}

/* Toute la fiche d'étape est cliquable, pas seulement son titre : le lien est
   étiré sur la fiche par un pseudo-élément. Le balisage ne change pas — le
   lien reste le seul élément focusable, et la liste reste une liste. Sans
   compte, pas de lien : la fiche reste inerte. */
.etapes-fiches .fiche {
  position: relative;
}

.etapes-fiches .fiche__titre a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.etapes-fiches .fiche:has(a:focus-visible) {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

.etapes-fiches .fiche__titre a:focus-visible {
  outline: none;
}

.encart {
  background: var(--surface-subtle);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: 0;
}

/* La fin de page : le quiz et l'attestation, qui sont la promesse du sujet. */
.sujet-fin {
  background: var(--surface-subtle);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  margin-bottom: var(--space-10);
}

.sujet-fin h2 {
  margin-top: 0;
  margin-bottom: var(--space-3);
}

.sujet-fin p:last-child {
  margin-bottom: 0;
}

.cover-preview {
  margin: var(--space-5) 0;
  max-width: 160px;
}
.cover-preview img {
  width: 160px;
  height: 160px;
  border: 1px solid var(--line-warm);
  border-radius: var(--radius);
  background: var(--surface);
}

/* --- Une leçon : sommaire à gauche, texte à droite ------------------------ */

/* Le texte ne s'élargit pas — au-delà de 75 caractères, l'œil perd sa ligne, et
   c'est précisément ce qu'on demande à quelqu'un qui lit entre deux réunions.
   C'est la paire sommaire + texte qui occupe et centre la page. Avant, une
   colonne de 68ch calée à gauche laissait la moitié d'un écran de bureau vide. */
.lecon {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-8);
}

.lecon__texte {
  min-width: 0;
}

@media (min-width: 64rem) {
  .lecon {
    grid-template-columns: 17rem minmax(0, var(--reading-width));
    gap: var(--space-12);
    justify-content: center;
    align-items: start;
  }

  .lecon__cote {
    /* Collant : le fil reste sous les yeux pendant qu'on descend dans le texte.
       `top` dégage la hauteur de l'en-tête. */
    position: sticky;
    top: var(--space-8);
    max-height: calc(100vh - var(--space-16));
    overflow-y: auto;
  }
}

.sommaire {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: var(--surface);
}

.sommaire__sujet {
  display: block;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  margin-bottom: var(--space-3);
}

.sommaire__sujet:hover {
  text-decoration: underline;
}

.sommaire__etat {
  margin: 0 0 var(--space-2);
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.jauge {
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  margin-bottom: var(--space-5);
}

.sommaire__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}

.sommaire__item a {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr);
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius);
  color: var(--body-text);
  text-decoration: none;
  font-size: 0.92rem;
  line-height: 1.4;
}

.sommaire__item a:hover {
  background: var(--brand-soft);
}

/* La puce porte le numéro, ou une coche quand l'étape est validée. Elle ne
   porte pas seule l'information : l'état courant est aussi marqué par le poids
   du texte, pour qui ne distingue pas les couleurs. */
.sommaire__puce {
  display: inline-grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  font-size: 0.8rem;
  color: var(--muted);
}

.sommaire__item.est-faite .sommaire__puce {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand);
}

.sommaire__item.est-courante a {
  background: var(--brand-soft);
  font-weight: 600;
  color: var(--ink);
}

.sommaire__item.est-courante .sommaire__puce {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--sur-brand);
}

.sommaire__item--quiz {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}

/* --- Rythme du texte ----------------------------------------------------- */

.etape-rang {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
}

.etape-rang__numero {
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--brand);
  color: var(--sur-brand);
  font-weight: 600;
}

.etape-rang__total {
  font-size: 0.85rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Le paragraphe d'ouverture pose la situation : il se lit avant tout le reste. */
.prose__ouverture {
  font-size: 1.12rem;
  line-height: 1.7;
  color: var(--ink);
}

/* Un filet court plutôt qu'un trait pleine largeur : il marque la rupture sans
   couper la colonne en tranches. */
.prose h2::before {
  content: "";
  display: block;
  width: 2.5rem;
  height: 2px;
  background: var(--brand);
  margin-bottom: var(--space-3);
}

.prose ul {
  padding-left: 0;
  list-style: none;
}

.prose ul li {
  position: relative;
  padding-left: var(--space-6);
  margin-bottom: var(--space-2);
}

.prose ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brand);
}

/* Variante à marque : réservée au corps d'une leçon. Le `.callout` nu sert
   ailleurs (explications du quiz) et doit rester un simple bloc — lui appliquer
   la grille laisserait une colonne vide devant chaque explication. */
.callout--marque {
  display: grid;
  grid-template-columns: 1.8rem minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

.callout__marque {
  display: inline-grid;
  place-items: center;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 50%;
  background: var(--brand);
  color: var(--sur-brand);
  font-weight: 700;
}

.prose figure {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: var(--surface);
}

/* --- Fin d'étape --------------------------------------------------------- */

.suite-quiz {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
  margin: var(--space-8) 0;
  padding: var(--space-5);
  border: 1px solid var(--brand);
  border-radius: var(--radius);
  background: var(--brand-soft);
  color: var(--ink);
  text-decoration: none;
}

.suite-quiz:hover {
  background: var(--brand);
  color: var(--sur-brand);
}

.suite-quiz:hover .suite-quiz__oeil {
  background: #fff;
  color: var(--brand);
}

/* Petit et discret. À 2,5 rem il pesait autant que les deux lignes de texte
   réunies et tirait l'œil vers lui plutôt que vers ce qu'il annonce. */
.suite-quiz__oeil {
  display: inline-grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--brand);
  color: var(--sur-brand);
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1;
}

.suite-quiz small {
  display: block;
  color: inherit;
  opacity: 0.8;
}

.pager {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: 1px solid var(--line);
}

@media (min-width: 40rem) {
  .pager {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.pager__lien {
  display: block;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  text-decoration: none;
}

.pager__lien:hover {
  border-color: var(--brand);
  background: var(--brand-soft);
}

.pager__lien small {
  display: block;
  color: var(--muted);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 2px;
}

.pager__lien--apres {
  text-align: right;
}

/* La suite : le geste principal (valider et avancer), et dessous le geste
   discret (avancer sans valider). */
.pager__suite {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.pager__form {
  margin: 0;
}

.pager__lien--valider {
  width: 100%;
  font: inherit;
  cursor: pointer;
  background: var(--brand);
  border-color: var(--brand);
  color: var(--sur-brand);
}

.pager__lien--valider small {
  color: rgba(255, 255, 255, 0.85);
}

.pager__lien--valider:hover {
  background: var(--brand-ink);
  border-color: var(--brand-ink);
  color: var(--sur-brand);
}

.pager__passer,
.pager__note {
  margin: 0;
  text-align: right;
  font-size: 0.88rem;
  color: var(--muted);
}

/* --- Le quiz -------------------------------------------------------------- */

.resultat__ligne {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: 0 0 var(--space-3);
}

.resultat__score {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
}

/* Le seuil marqué sur la jauge : un score nu ne dit pas s'il manque un point ou
   la moitié. */
.jauge--score {
  position: relative;
}

.jauge--score .jauge {
  height: 8px;
  border-radius: 4px;
  margin-bottom: 0;
}

/* Le repère est un SVG étiré sur la largeur : sa position est un attribut `x`
   en centièmes, pas un `left` en ligne. */
.jauge__seuil {
  position: absolute;
  top: -3px;
  left: 0;
  width: 100%;
  height: 14px;
  fill: var(--ink);
  pointer-events: none;
}

.question {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: 0 0 var(--space-5);
}

.question--juste {
  border-color: var(--ok);
}

.question--faux {
  border-color: var(--brand);
}

.question__rang {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  font-size: 0.8rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.question__numero {
  display: inline-grid;
  place-items: center;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand);
  font-weight: 700;
  font-size: 0.9rem;
}

.question__stem {
  font-size: 1.05rem;
  line-height: 1.6;
  margin: var(--space-3) 0 var(--space-4);
}

.choix {
  display: grid;
  gap: var(--space-2);
}

/* Une ligne entière cliquable : sur une tablette d'atelier, viser un rond de
   16 px avec un gant ne marche pas. */
.choix__ligne {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  min-height: 44px;
}

.choix__ligne:hover {
  border-color: var(--brand);
  background: var(--brand-soft);
}

.choix__ligne input {
  margin: 0;
  align-self: center;
}

/* L'état ne tient pas qu'à la couleur : chaque ligne corrigée porte aussi un
   mot. Une bordure verte seule ne se lit ni en niveaux de gris, ni pour un
   daltonien. */
.choix__ligne.est-attendu {
  border-color: var(--ok);
  background: var(--ok-soft);
}

.choix__ligne.est-faux {
  border-color: var(--brand);
  background: var(--brand-soft);
}

.choix__marque {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ok);
  white-space: nowrap;
}

.choix__marque--faux {
  color: var(--brand);
}

.question__verdict {
  margin: var(--space-4) 0 0;
  font-weight: 600;
}

.tentatives {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-2);
}

.tentatives__ligne {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.tentatives__ligne time {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.85rem;
}

/* --- Confort tactile ------------------------------------------------------ */

/* Sous 64rem, le sommaire disparaît. Cinq titres d'étapes en tête de page
   repoussent le texte sous la ligne de flottaison, et l'on vient lire, pas
   naviguer. Ne reste qu'une barre et le rang — « où en suis-je » tient en une
   ligne. La liste complète reste à un clic, sur la fiche du sujet. */
.jauge--compacte {
  display: none;
}

@media (max-width: 63.99rem) {
  .lecon__cote {
    display: none;
  }

  .jauge--compacte {
    display: block;
    margin-bottom: var(--space-4);
  }
}

@media (max-width: 30rem) {
  .etape-rang__numero {
    width: 1.75rem;
    height: 1.75rem;
  }

  .choix__ligne {
    grid-template-columns: auto minmax(0, 1fr);
    padding: var(--space-3);
  }

  .choix__marque {
    grid-column: 2;
  }

  .pager__lien--apres {
    text-align: left;
  }

  .resultat__score {
    font-size: 1.6rem;
  }
}

/* --- Navigation principale ------------------------------------------------ */

/* Le catalogue et la matrice n'étaient atteignables que depuis la page
   d'accueil. Passé le premier clic, il fallait repasser par le logo — et rien
   ne disait que la matrice existait. */
.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.header-link--icone {
  display: inline-flex;
  align-items: center;
  padding-inline: var(--space-2);
}

.brand__name {
  white-space: nowrap;
}

.header-link--fort {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
}

/* Le seuil de repli était à 48rem quand la barre portait quatre entrées. À
   cinq — l'introduction au Lean s'est ajoutée — elle débordait entre 48 et
   64rem : la navigation passait sur deux lignes et le nom de la marque se
   coupait en deux, sur toutes les tablettes en portrait. Le seuil suit donc le
   contenu de la barre, et non l'inverse.

   Au-dessous, les entrées passent derrière le bouton rond : une ligne de barre
   en moins au-dessus de chaque page. */
@media (max-width: 64rem) {
  .site-header__inner {
    flex-wrap: wrap;
    row-gap: var(--space-2);
  }

  /* Les entrées passent derrière le bouton rond : une ligne de barre en moins
     au-dessus de chaque page. Le défilement latéral d'avant coupait
     « Connexion » au bord de l'écran, et le repli sur deux lignes mangeait la
     hauteur qu'on vient justement gagner. */
  .site-nav {
    display: none;
  }

  .menu-plie {
    display: block;
  }

  .brand__name {
    font-size: 0.95rem;
  }
}

/* Très petit écran : le nom de la marque s'efface, le logo suffit à identifier
   et à ramener à l'accueil. */
@media (max-width: 22rem) {
  .brand__name {
    display: none;
  }
}

/* --- Écran des travaux ---------------------------------------------------- */

.filtres {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.filtres label {
  display: grid;
  gap: 2px;
}

.filtres label span {
  font-size: 0.78rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.filtres select {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  min-height: 38px;
}

/* La place dans la file. Un rang qui saute d'un rafraîchissement à l'autre est
   normal : les travaux finissent et ceux qui suivent remontent. */
.rang {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

@media (max-width: 40rem) {
  .filtres {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .filtres button,
  .filtres a {
    grid-column: span 2;
  }
}

/* --- Matrice d'équivalence ------------------------------------------------ */

/* Une ligne : l'intitulé, la liste, le bouton. Avant, `.form` mettait le bouton
   sur toute la largeur — un bandeau rouge de 1200 px pour choisir dans une
   liste, qui pesait plus que la question posée. */
.matrice-choix {
  display: grid;
  gap: var(--space-2);
  max-width: 34rem;
  margin: var(--space-6) 0;
}

.matrice-choix__label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.matrice-select__boite {
  position: relative;
  display: block;
}

.matrice-select {
  width: 100%;
  padding: var(--space-3) var(--space-10) var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-size: 1rem;
  font-family: inherit;
  line-height: 1.4;
  min-height: 48px;
  /* L'apparence native varie d'un système à l'autre — flèche bleue sur macOS,
     bloc gris sur Windows. On la neutralise et on dessine la nôtre. */
  appearance: none;
  cursor: pointer;
}

.matrice-select:hover {
  border-color: var(--brand);
}

.matrice-select:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-color: var(--brand);
}

/* Un chevron en bordures plutôt qu'en image : il prend la couleur du texte,
   donc suit le mode nuit sans seconde version du fichier. */
.matrice-select__chevron {
  position: absolute;
  top: 50%;
  right: var(--space-4);
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  pointer-events: none;
}

.matrice-select:hover + .matrice-select__chevron {
  border-color: var(--brand);
}

/* Le bouton ne sert **qu'en l'absence de script** : dès que `matrice.js` prend
   la main, choisir dans la liste envoie le formulaire et le bouton se masque.
   Il reste dans le balisage parce qu'une page dont le script ne charge pas doit
   rester utilisable — sur une tablette d'atelier, ça arrive. */
.matrice-choix .button {
  justify-self: start;
  margin-top: var(--space-2);
}

.constats {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

.constat {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--brand);
  border-radius: 999px;
  background: var(--brand-soft);
  font-size: 0.9rem;
}

.constat a {
  display: inline-grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  color: var(--brand-ink);
  text-decoration: none;
  font-weight: 700;
  line-height: 1;
}

.constat a:hover {
  background: var(--brand);
  color: var(--sur-brand);
}

/* Colonne des cases à cocher : étroite, et la cible reste confortable au doigt. */
.col-case {
  width: 2.5rem;
  text-align: center;
}

.col-case input[type='checkbox'] {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

/* Les constats retenus. Sans titre, cette liste de phrases barrées d'une croix
   se prend pour un résultat plutôt que pour une sélection. */
.constats-bloc {
  margin: var(--space-6) 0;
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-subtle);
}

.constats__titre {
  margin: 0 0 var(--space-3);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.constats-bloc .form__hint {
  margin: var(--space-3) 0 0;
}

/* ==========================================================================
   Page d'accueil
   ==========================================================================

   Reproche fondé : « c'est un document, pas une page d'accueil ». Tout était
   blanc, séparé par des filets, rien n'accrochait. Ce qui suit pose des bandes
   colorées sur toute la largeur, des cartes qui se détachent, et une seule
   colonne de contenu bien proportionnée. Le vocabulaire — rayons, ombres,
   `march`, `rise` décalé de 90 ms — est celui de teeptrak.com et du site OPC UA,
   pour que l'académie soit visuellement sœur des autres sites TEEPTRAK. */

/* Une bande sur toute la largeur de la fenêtre, avec le contenu qui reste dans
   la colonne. Le fond est un pseudo-élément étiré jusqu'aux bords ; `main` ne
   change pas. `overflow-x: clip` sur `body` absorbe la largeur de la barre de
   défilement sans créer de conteneur de défilement — `hidden` casserait le
   sommaire collant des leçons. */
body {
  overflow-x: clip;
}

.bande {
  position: relative;
}

.bande::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  background: var(--bande-fond, transparent);
}

/* Le fond du héros : charbon, en léger dégradé — plus clair en haut à gauche,
   là où le titre se lit, plus profond en bas à droite — et une trame de points
   (`.hero::after`). L'uni était sans vie ; le dégradé est discret, et la trame
   est celle qui plaisait sur l'ancien héros rouge. Le charbon est celui de
   `--bande-sombre`, jeton hors thème (voir tokens.css). */
.hero.bande::before {
  /* Les deux bouts du dégradé sont dérivés du jeton : une autre marque change
     de surface sombre sans laisser ici un charbon TEEPTRAK. */
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--bande-sombre), #fff 7%) 0%,
    var(--bande-sombre) 55%,
    color-mix(in srgb, var(--bande-sombre), #000 35%) 100%
  );
}

/* La trame de points, en SVG dans le fond : un motif de 28 px, une seule forme,
   répété par le navigateur. Elle s'efface vers le bas, sur sa propre couche. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28'%3E%3Ccircle cx='2' cy='2' r='1.2' fill='%23ffffff' fill-opacity='0.13'/%3E%3C/svg%3E");
  mask-image: linear-gradient(180deg, #000 55%, rgba(0, 0, 0, 0.25));
}

/* Le halo de l'appel final vit dans le fond de la bande, pas dans un
   pseudo-élément positionné : celui-ci débordait sous la bande et laissait une
   tache rose sur la section suivante. */
.appel.bande::before {
  background:
    radial-gradient(closest-side at 12% 110%, color-mix(in srgb, var(--bande-rouge-encre) 55%, transparent), transparent 70%),
    var(--bande-sombre);
}

/* --- Héros ---------------------------------------------------------------- */

.hero {
  --bande-fond: var(--bande-sombre);
  color: #fff;
  position: relative;
  display: grid;
  gap: var(--space-8);
  /* Tout ce qui accroche — titre, phrase, boutons, chiffres — doit tenir sans
     défilement sur un portable de 768 px de haut, en-tête compris. */
  padding: clamp(2rem, 4vw, 3.5rem) 0 var(--space-12);
  margin-top: calc(-1 * var(--space-12));
}

/* Sur grand écran, le héros prend toute la hauteur restante : la page
   d'arrivée est lui seul, rien d'autre ne dépasse sous la ligne de flottaison.
   `svh` et non `vh` : sur une tablette, la barre du navigateur mange le bas de
   `100vh`. 4.25rem est la hauteur de l'en-tête collant. */
@media (min-width: 60rem) {
  .hero {
    min-height: calc(100svh - 4.25rem);
    align-content: center;
  }
}

/* Le fond du héros : une feuille de plan technique (voir le partial
   `fond-accueil.ejs`) — un grain, des graduations aux bords, des repères
   d'angle. Étirée jusqu'aux bords comme la bande, derrière le contenu, devant
   l'aplat charbon que `.bande::before` a peint. Rien n'y traverse le texte. */
.hero__fond {
  position: absolute;
  inset: 0 calc(50% - 50vw);
  width: 100vw;
  /* La règle globale des images borne `svg` à 100 % de son conteneur : la
     feuille s'arrêtait au bord de la colonne, graduations comprises. */
  max-width: none;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  color: #fff;
}

@media (min-width: 60rem) {
  .hero {
    /* Le texte un peu plus large que le dessin : c'est ce qui garantit deux
       lignes de titre en roumain, le plus long des quatre (50 caractères). */
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--space-8);
  }

  /* L'illustration prend toute sa colonne et déborde un peu vers la droite :
     elle a de la présence sans écraser le texte. */
  .hero__image {
    margin-right: -6%;
  }
}

/* Sur-titre et pastille « gratuit » sur une même ligne : deux lignes de moins
   dans un héros qui doit tenir à l'écran. */
.hero__entete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
}

.hero__sur-titre {
  margin: 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.78);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.hero__titre {
  margin: 0 0 var(--space-4);
  /* Borné en haut à 2.5rem : à 3.6rem le titre roumain prenait trois lignes et
     poussait les boutons sous la ligne de flottaison. 26ch, c'est deux lignes
     pour le plus long des quatre titres ; `balance` évite l'orphelin. */
  font-size: clamp(2rem, 2.8vw, 2.5rem);
  line-height: 1.06;
  letter-spacing: -0.025em;
  /* Explicite : la règle globale des titres pose l'encre, invisible sur le
     charbon. Une réécriture du bloc l'avait perdue — le titre disparaissait. */
  color: #fff;
  max-width: 26ch;
  text-wrap: balance;
}

.hero__chapeau {
  margin: 0 0 var(--space-6);
  font-size: 1.1rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.92);
  max-width: 44ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.button--grand {
  padding: var(--space-3) var(--space-6);
  font-size: 1.02rem;
  min-height: 50px;
  border-radius: 12px;
}

/* Sur fond sombre, le bouton secondaire est un contour clair. */
.button--clair {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, 0.55);
}

.button--clair:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #fff;
  color: #fff;
}

/* Sur téléphone, la gouttière du texte est de 16 px — la même distance au bord
   que les repères d'angle, qui touchaient le sur-titre. Ils s'effacent ; le
   grain et les graduations, aux bords, restent. */
@media (max-width: 59.99rem) {
  .fond__reperes {
    display: none;
  }
}

/* --- Les pertes, et l'outil qui y répond ------------------------------- */

/* Quatre pertes réelles lues dans la matrice, chacune avec l'outil de premier
   recours — le geste même de l'académie. Le bloc était dans le héros ; il y
   était de trop, et vit maintenant après le mode d'emploi, dont il illustre le
   premier temps. Sur fond de page : jetons de thème, pas ceux de la bande. */
.pertes-accueil {
  padding: var(--space-8) 0 var(--space-2);
}

.pertes-accueil__titre {
  margin: 0 0 var(--space-3);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.pertes-accueil__liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0 var(--space-6);
}

@media (min-width: 40rem) {
  .pertes-accueil__liste {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 60rem) {
  .pertes-accueil__liste {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* La perte au-dessus, « → outil » dessous : en quatre colonnes, un libellé de
   soixante caractères sur la même ligne que l'outil se pliait sur trois. */
.perte-outil {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-1) var(--space-2);
  padding: var(--space-4) 0;
  border-top: 2px solid var(--line-warm);
  color: var(--ink);
  font-size: 0.92rem;
  line-height: 1.3;
  text-decoration: none;
}

.perte-outil:hover,
.perte-outil:focus-visible {
  color: var(--brand-ink);
}

.perte-outil__perte {
  grid-column: 1 / -1;
  color: var(--muted);
}

.perte-outil__fleche {
  color: var(--brand);
  font-weight: 700;
}

.perte-outil__outil {
  font-weight: 600;
}

.pertes-accueil__tous {
  display: inline-block;
  margin-top: var(--space-3);
  font-size: 0.9rem;
}

/* Sur le charbon du héros, le bouton principal est le seul aplat rouge de la
   page : c'est ce qui le fait voir. `--bande-rouge`, pas `--brand` — la bande
   ne suit pas le thème, le bouton non plus. */
.button--marque {
  background: var(--bande-rouge);
  color: var(--sur-bande-rouge);
  border-color: var(--bande-rouge);
  font-weight: 600;
}

.button--marque:hover {
  background: var(--bande-rouge-encre);
  border-color: var(--bande-rouge-encre);
  color: var(--sur-bande-rouge);
}

/* Sur une bande sombre — l'appel de fin de page — le bouton principal
   s'inverse. Il reste blanc en mode nuit, la bande n'ayant pas changé, mais son
   libellé garde le rouge foncé de la marque : `var(--brand-ink)` vire au rose
   pâle la nuit, illisible sur blanc. */
.button--inverse {
  background: #fff;
  color: var(--bande-inverse-texte);
  border-color: #fff;
  font-weight: 600;
}

.button--inverse:hover {
  background: color-mix(in srgb, var(--bande-rouge), #fff 95%);
  color: var(--bande-inverse-texte);
}

/* La gratuité, dite sur le rouge : un cadre clair plutôt qu'un aplat, pour ne
   pas entrer en concurrence avec le bouton d'inscription juste en dessous. */
.hero__gratuit {
  display: inline-block;
  margin: 0;
  padding: var(--space-1) var(--space-3);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 999px;
  color: #fff;
  font-size: 0.82rem;
  font-weight: 600;
}

.hero__note {
  margin: var(--space-4) 0 0;
  color: rgba(255, 255, 255, 0.78);
  font-size: 0.92rem;
}

.hero__note a {
  color: #fff;
}

.hero__image {
  display: none;
  color: rgba(255, 255, 255, 0.9);
  /* Sur le charbon, l'accent reprend le rouge de la marque : c'est là, et sur
     le bouton d'inscription, qu'il vit désormais. `--bande-rouge` et non
     `--brand` : la bande ne suit pas le thème, l'accent non plus. (Sur l'ancien
     fond rouge, il passait en encre — un trait rouge sur rouge disparaissait.) */
  --illu-accent: var(--bande-rouge);
}

.illu__accent {
  stroke: var(--illu-accent, var(--brand));
}

@media (min-width: 60rem) {
  .hero__image {
    display: block;
  }
}

/* Sur téléphone, l'illustration passe sous le texte, en plus petit : le bouton
   d'inscription reste au-dessus de la ligne de flottaison. */
@media (max-width: 59.99rem) {
  .hero__image {
    display: block;
    max-width: 24rem;
    margin: 0 auto;
    opacity: 0.9;
  }
}

.illu {
  width: 100%;
  height: auto;
  display: block;
}

/* La scène isométrique : trait fin partout, faces translucides pour le volume,
   et quatre mouvements. Le convoyeur « marche » (idiome de teeptrak.com : les
   pièces avancent), les données remontent vers le tableau de bord (le même
   `march`, en sens inverse), la jauge et la tendance se tracent une fois
   (`pousse`), le tableau flotte. Le bras, la presse, le laser et la roue sont
   en SMIL dans le SVG lui-même. */
.illu__trame {
  stroke-width: 1;
  opacity: 0.14;
}

.illu__loin {
  stroke-width: 1.5;
  opacity: 0.35;
}

.illu__machine {
  stroke-width: 3;
}

.illu__bras {
  stroke-width: 7;
}

.illu__face {
  fill: currentColor;
  fill-opacity: 0.1;
}

.illu__face-haut {
  fill: currentColor;
  fill-opacity: 0.24;
}

.illu__joint {
  fill: var(--illu-accent, var(--brand));
  stroke-width: 3;
}

.illu__accent-fond {
  fill: var(--illu-accent, var(--brand));
  fill-opacity: 0.85;
}

.illu__piece {
  fill: var(--illu-accent, var(--brand));
  stroke: none;
}

/* « march » : des tirets qui courent le long du convoyeur. */
.illu__flux {
  stroke-width: 4;
  stroke-dasharray: 14 12;
  animation: march 1.6s linear infinite;
}

/* Les données remontent : mêmes tirets, sens inverse, trait plus fin. */
.illu__data {
  stroke-width: 2;
  stroke-dasharray: 6 8;
  opacity: 0.8;
  animation: march 2.4s linear infinite reverse;
}

.illu__capteur {
  fill: currentColor;
  fill-opacity: 0.25;
}

.illu__laser {
  stroke-width: 4;
  opacity: 0.9;
}

.illu__statut {
  animation: clignote 1.8s ease-in-out infinite;
}

.illu__halo {
  transform-origin: 0 0;
  animation: pulse 3.2s ease-in-out infinite;
}

.illu__carte {
  animation: float 6s ease-in-out infinite;
}

.illu__panneau {
  fill: currentColor;
  fill-opacity: 0.1;
  stroke-width: 2;
}

.illu__anneau-fond {
  stroke-width: 8;
  opacity: 0.25;
}

/* L'anneau de TRS se remplit à 78 % : circonférence 214, il en reste 47. */
.illu__jauge {
  stroke-width: 8;
  stroke-dasharray: 214;
  stroke-dashoffset: 214;
  animation: jauge 2.2s cubic-bezier(0.22, 0.61, 0.36, 1) 0.6s forwards;
}

.illu__trace {
  stroke-width: 3;
  stroke-dasharray: 280;
  stroke-dashoffset: 280;
  animation: pousse 2.6s cubic-bezier(0.22, 0.61, 0.36, 1) 1s forwards;
}

@keyframes jauge {
  to {
    stroke-dashoffset: 47;
  }
}

@keyframes clignote {
  0%,
  100% {
    fill-opacity: 0.25;
  }
  50% {
    fill-opacity: 1;
  }
}

@keyframes march {
  to {
    stroke-dashoffset: -76;
  }
}

@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.35;
  }
  50% {
    transform: scale(1.08);
    opacity: 0.15;
  }
}

@keyframes float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(22px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* --- Chiffres : une carte qui chevauche le bas du héros ------------------- */

/* Les chiffres : une ligne de faits sous les boutons. Ils étaient une carte
   blanche flottante, puis une plaque pleine largeur — deux façons d'occuper
   cent cinquante pixels qui manquaient au-dessus de la ligne de flottaison.
   Une ligne, des séparateurs, le nombre en rouge : ça se lit d'un coup d'œil. */
.chiffres-bande {
  margin: var(--space-6) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.hero__chiffres {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

.hero__chiffres li {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35em;
  white-space: nowrap;
}

/* Le séparateur ferme l'élément précédent plutôt que d'ouvrir le suivant :
   quand la ligne se plie — le roumain le fait à 1366 px — la seconde ligne
   commence par un chiffre, pas par un point. */
.hero__chiffres li:not(:last-child)::after {
  content: "·";
  margin-left: var(--space-3);
  color: rgba(255, 255, 255, 0.4);
}

.chiffre {
  display: inline;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
  /* Le rouge figé de la bande, pas `--brand` : la ligne ne bascule pas avec le
     thème, puisque la bande ne bascule pas. */
  color: var(--bande-rouge);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.chiffre__quoi {
  font-size: 0.88rem;
  color: rgba(255, 255, 255, 0.72);
}

/* --- Mode d'emploi : quatre cartes -------------------------------------- */

.mode-emploi {
  padding: var(--space-8) 0 var(--space-16);
  text-align: center;
}

.mode-emploi .lede {
  margin-inline: auto;
}

.etapes-emploi {
  list-style: none;
  margin: var(--space-10, 2.5rem) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  text-align: left;
  counter-reset: temps;
}

@media (min-width: 40rem) {
  .etapes-emploi {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 72rem) {
  .etapes-emploi {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-6);
  }
}

.etapes-emploi li {
  position: relative;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}

.etapes-emploi li:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

.etapes-emploi__rang {
  display: inline-grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: var(--brand);
  color: var(--sur-brand);
  font-weight: 700;
  margin-bottom: var(--space-4);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--brand) 35%, transparent);
}

.etapes-emploi h3 {
  margin: 0 0 var(--space-2);
  font-size: 1.1rem;
}

.etapes-emploi p {
  margin: 0 0 var(--space-3);
  color: var(--body-text);
  font-size: 0.97rem;
}

.etapes-emploi a {
  font-weight: 600;
}

/* --- Ruban : discret ------------------------------------------------------ */

/* Les vignettes des sujets restent en retrait : elles disent « il y a de la
   matière », elles ne rivalisent pas avec le titre. Petites, atténuées, sur la
   bande grise. */
.ruban {
  --bande-fond: var(--surface-subtle);
  overflow: hidden;
  padding: var(--space-6) 0;
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.ruban__piste {
  display: flex;
  gap: var(--space-5);
  width: max-content;
  animation: ruban-defile 60s linear infinite;
}

.ruban:hover .ruban__piste {
  animation-play-state: paused;
}

.ruban__vignette {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  opacity: 0.75;
  filter: saturate(0.85);
}

@keyframes ruban-defile {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* --- Aperçu : une liste sobre, pas une galerie ---------------------------- */

.apercu {
  padding: var(--space-12) 0;
}

.apercu__entete {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.apercu__entete h2 {
  margin: 0;
}

.apercu .card-grid {
  margin-top: 0;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-3);
}

/* La vignette devient une icône à gauche du titre : discrète, et la carte
   garde une hauteur constante quelle que soit l'illustration. */
.apercu .card--illustree {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.apercu .card--illustree:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow);
}

.apercu .card__illustration {
  margin: 0;
  width: 56px;
  height: 56px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface-subtle);
}

.apercu .card__illustration img {
  width: 100%;
  height: 100%;
  display: block;
}

.apercu .card h3 {
  margin: 0 0 var(--space-1);
  font-size: 1.02rem;
}

.apercu .card p {
  grid-column: 2;
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* L'adresse du compte et le bouton pour en sortir, sur une ligne. */
.compte-ligne {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-8);
  color: var(--muted);
  font-size: 0.92rem;
}

/* Un bouton qui doit se lire comme un lien de la barre : la déconnexion est un
   POST — donc un bouton — mais elle n'a pas à s'annoncer plus fort que
   « Mon parcours » juste à côté. */
.header-link--bouton {
  background: none;
  border: 0;
  font: inherit;
  cursor: pointer;
}

/* --- Atouts : bande grise, quatre colonnes ------------------------------- */

.atouts {
  --bande-fond: var(--surface-subtle);
  display: grid;
  gap: var(--space-6);
  padding: var(--space-12) 0;
}

@media (min-width: 48rem) {
  .atouts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-8);
  }
}

/* Quatre atouts depuis que la gratuité en est un : à trois colonnes, le
   quatrième se retrouvait seul sur sa ligne. */
@media (min-width: 72rem) {
  .atouts {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.atout__icone {
  display: inline-grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  color: var(--brand);
  margin-bottom: var(--space-4);
}

.atout__icone svg {
  width: 1.7rem;
  height: 1.7rem;
}

.atout h3 {
  margin: 0 0 var(--space-2);
  font-size: 1.1rem;
}

.atout p {
  margin: 0;
  color: var(--body-text);
}

/* --- Appel final : bande rouge ------------------------------------------- */

.appel {
  --bande-fond: var(--bande-sombre);
  color: #fff;
  padding: var(--space-16) 0;
  text-align: center;
}

.appel h2 {
  margin: 0 0 var(--space-3);
  color: #fff;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
}

.appel p {
  margin: 0 auto var(--space-6);
  max-width: 48ch;
  color: rgba(255, 255, 255, 0.88);
  font-size: 1.05rem;
}

/* Plus spécifique que `.appel p`, qui remettait la marge haute à zéro : la note
   collait au bouton. */
.appel p.appel__note {
  margin: var(--space-4) auto 0;
  font-size: 0.88rem;
  color: rgba(255, 255, 255, 0.72);
}

/* --- Questions fréquentes -------------------------------------------------- */

.faq {
  padding: var(--space-16) 0;
  max-width: var(--reading-width);
  margin-inline: auto;
}

.faq h2 {
  text-align: center;
  margin-bottom: var(--space-6);
}

.faq__item {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-3);
  background: var(--surface);
}

.faq__item[open] {
  box-shadow: var(--shadow);
}

.faq__item summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 1.02rem;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 32px;
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

.faq__item summary::after {
  content: "+";
  color: var(--brand);
  font-size: 1.5rem;
  line-height: 1;
  flex: none;
}

.faq__item[open] summary::after {
  content: "−";
}

.faq__item p {
  margin: var(--space-3) 0 0;
  color: var(--body-text);
}

/* --- Mouvement ------------------------------------------------------------ */

/* Rien n'est masqué tant que le script n'a pas posé `anime-actif` : sans lui,
   la page reste simplement visible. Le décalage de 90 ms entre cartes est
   l'idiome de teeptrak.com. */
.anime-actif [data-anime] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s cubic-bezier(0.22, 0.61, 0.36, 1), transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.anime-actif [data-anime].est-visible {
  opacity: 1;
  transform: none;
}

.anime-actif .etapes-emploi li {
  opacity: 0;
}

.anime-actif [data-anime].est-visible .etapes-emploi li {
  /* Courbe en dur, à dessein : ce contenu est masqué jusqu'à l'animation, et
     un `var()` absent invaliderait la déclaration entière — cartes invisibles
     pour toujours. Pas de dépendance à un jeton pour ce qui décide de la
     visibilité. */
  animation: rise 0.62s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

/* Le décalage par carte vient du rang, pas d'un `style="--i"` que la CSP
   refuse : quatre cartes, quatre délais. */
.anime-actif [data-anime].est-visible .etapes-emploi li:nth-child(2) {
  animation-delay: 90ms;
}

.anime-actif [data-anime].est-visible .etapes-emploi li:nth-child(3) {
  animation-delay: 180ms;
}

.anime-actif [data-anime].est-visible .etapes-emploi li:nth-child(4) {
  animation-delay: 270ms;
}

/* Le réglage système prime : une animation qui ne s'arrête pas donne la nausée
   à certaines personnes. */
@media (prefers-reduced-motion: reduce) {
  .anime-actif [data-anime],
  .anime-actif .etapes-emploi li,
  .anime-actif [data-anime].est-visible .etapes-emploi li {
    opacity: 1;
    transform: none;
    transition: none;
    animation: none;
  }

  .illu__flux,
  .illu__data,
  .illu__halo,
  .illu__carte,
  .illu__statut,
  .ruban__piste,
  .etapes-emploi li {
    animation: none !important;
    transition: none !important;
  }
}

/* La barre rouge de l'histogramme pousse : le gain, animé comme une mesure qui
   monte. */
.illu__gain {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: pousse 2.4s var(--ease) 0.6s forwards;
}

@keyframes pousse {
  to {
    stroke-dashoffset: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .illu__gain {
    animation: none;
    stroke-dashoffset: 0;
  }

  .illu__trace {
    animation: none;
    stroke-dashoffset: 0;
  }

  .illu__jauge {
    animation: none;
    stroke-dashoffset: 47;
  }

}

/* --- Suivi partageable ---------------------------------------------------- */

.partage {
  margin: var(--space-6) 0 var(--space-10);
  padding: var(--space-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-subtle);
}

.partage h1,
.partage h2 {
  margin-top: 0;
  font-size: 1.4rem;
}

/* Un champ en lecture seule et son bouton de copie. Le bouton est injecté par
 * `copier.js` : sans JavaScript, il n'existe pas et le champ reste sélectionnable
 * — c'est le mécanisme, la copie n'est qu'un confort.
 *
 * `flex-wrap` plutôt qu'une grille : sur un téléphone, le bouton passe sous le
 * champ au lieu de comprimer une adresse de quatre-vingts caractères. */
.champ-copie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.champ-copie label {
  flex: 0 0 100%;
  margin-bottom: var(--space-1);
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
}

.champ-copie input {
  /* Une hauteur de ligne pleine : les jetons portent des « _ », qu'une ligne
     serrée rognait — le jeton semblait contenir des espaces. */
  line-height: 1.6;
  flex: 1 1 16rem;
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.9rem;
}

.champ-copie__bouton {
  flex: 0 0 auto;
}

/* La confirmation de copie. Elle occupe sa place en permanence : apparaissant
 * d'un coup, elle décalait le bouton sous le doigt au moment du clic. */
.champ-copie__dit {
  flex: 0 0 100%;
  min-height: 1.2em;
  color: var(--ok);
  font-size: 0.82rem;
}

.partage__lien input {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.9rem;
}

.suivi__email {
  color: var(--ink);
  font-weight: 600;
}

.suivi__totaux {
  margin: var(--space-6) 0;
}

.suivi__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.suivi .progress-bar {
  min-width: 5rem;
}

/* Sur un téléphone, cinq colonnes ne tiennent pas : chaque sujet devient une
   fiche, avec son libellé devant chaque valeur (porté par data-libelle). */
@media (max-width: 640px) {
  .suivi .table,
  .suivi .table tbody,
  .suivi .table tr {
    display: block;
  }

  .suivi .table thead {
    display: none;
  }

  .suivi .table tr {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--line-warm);
  }

  .suivi .table tr:last-child {
    border-bottom: 0;
  }

  .suivi .table th,
  .suivi .table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-1) 0;
    border: 0;
  }

  .suivi .table th[scope="row"] {
    display: block;
    padding-bottom: var(--space-2);
    font-size: 1rem;
  }

  .suivi .table td::before {
    content: attr(data-libelle);
    flex: 0 0 auto;
    color: var(--muted);
    font-size: 0.8rem;
  }

  .suivi .table td > * {
    text-align: right;
  }

  .suivi .progress-bar {
    width: 6rem;
    min-width: 0;
    margin-left: auto;
  }
}

.aide pre {
  padding: var(--space-4);
  border-radius: var(--radius);
  background: var(--code-bg);
  overflow-x: auto;
  font-size: 0.88rem;
}

/* --- Mon parcours et la page publique de suivi ------------------------- */

.parcours-tete {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-4);
}

.parcours-tete h1 {
  margin: 0;
}

.carte-suivi {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.carte-suivi--valide {
  border-color: var(--ok);
}

.carte-suivi__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.carte-suivi__tete .tag {
  white-space: nowrap;
}

.carte-suivi__tete h2 {
  margin: 0;
  font-size: 1.1rem;
}

.carte-suivi__ligne {
  margin: 0;
}

.carte-suivi__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: auto 0 0;
  padding-top: var(--space-2);
}

/* --- Recherche et favoris du catalogue ---------------------------------- */

.recherche {
  display: flex;
  gap: var(--space-2);
  max-width: 32rem;
  margin: var(--space-6) 0 var(--space-2);
}

.recherche input[type="search"] {
  flex: 1;
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}

.recherche__compte {
  min-height: 1.4em;
  margin: 0 0 var(--space-4);
  color: var(--muted);
  font-size: 0.88rem;
}

/* Une carte masquée par le filtre : `hidden` suffit, sauf que `.card` pose
   un `display` qui l'emporte. */
.card[hidden] {
  display: none;
}

.card--illustree {
  position: relative;
}

/* L'étoile, en coin de vignette sur le catalogue, à côté du titre sur la fiche. */
.favori {
  margin: 0;
}

.card--illustree > .favori {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 1;
  padding: 0;
}

.favori__bouton {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}

.favori__bouton svg path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

.favori__bouton:hover {
  color: var(--brand);
  border-color: var(--brand);
}

.favori__bouton.est-actif {
  color: var(--brand);
  border-color: var(--brand);
}

.favori__bouton.est-actif svg path {
  fill: currentColor;
}

.sujet-tete__titre {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.sujet-tete__titre .favori {
  margin-top: var(--space-2);
}

