/* Carnet d'atelier. Voir docs/DESIGN.md.
 *
 * Ecart assume par rapport a DESIGN sections 2 et 9, sur demande explicite:
 * le dispositif des barres de mesure est retire, parce qu'il ne se lisait pas,
 * et des degrades sobres sont admis. La teinte de branche vient toujours des
 * donnees, jamais du CSS.
 */

/* --- polices ------------------------------------------------------------- */

/* Auto-hebergees dans assets/fonts, sous licence OFL, donc redistribuables avec
 * le projet. L'application ne fait aucun appel reseau: les fichiers sont dans le
 * depot. Les piles de repli restent declarees, au cas ou un fichier manquerait. */

@font-face {
  font-family: 'Fraunces';
  src: url('assets/fonts/Fraunces-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Sans';
  src: url('assets/fonts/IBMPlexSans-Variable.woff2') format('woff2-variations');
  font-weight: 100 700;
  font-display: swap;
}

@font-face {
  font-family: 'IBM Plex Mono';
  src: url('assets/fonts/IBMPlexMono-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

/* --- jetons -------------------------------------------------------------- */

:root {
  --encre: #161b26;
  --encre-haute: #1e2532;
  --trait: #2c3444;
  --papier: #e8e4da;
  --papier-bas: #8a8e9a;
  --sceau: #c4634a;

  /* Remplacee par la couleur declaree dans la BRANCHE, jamais en dur. */
  --branche: #8a8e9a;

  /* Le tier est deja une information: la couleur la porte, elle ne la decore
   * pas. Cinq paliers, du plus courant au plus rare, sur le modele des tiers de
   * rarete d'Hypixel SkyBlock, mais desatures pour tenir sur fond d'encre. */
  --tier-1: #a8b0c0;
  --tier-2: #4cc38a;
  --tier-3: #5a9cff;
  --tier-4: #b06bff;
  --tier-5: #e0a94a;

  --display: 'Fraunces', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
  --texte: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --donnee: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --e1: 4px;
  --e2: 8px;
  --e3: 12px;
  --e4: 16px;
  --e5: 24px;
  --e6: 32px;
  --e7: 48px;
  --e8: 64px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--encre);
  background-image: linear-gradient(180deg, #1b2231 0%, var(--encre) 46%);
  background-attachment: fixed;
  color: var(--papier);
  font-family: var(--texte);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-weight: 600; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--branche); }

:focus-visible {
  outline: 2px solid var(--branche);
  outline-offset: 2px;
}

/* --- echelle typographique ---------------------------------------------- */

.display-xl {
  font-family: var(--display);
  font-size: 48px;
  line-height: 1;
  font-weight: 600;
  font-variation-settings: 'opsz' 144;
}

.display-l {
  font-family: var(--display);
  font-size: 32px;
  line-height: 1.1;
  font-weight: 600;
}

.titre { font-size: 20px; line-height: 1.3; font-weight: 600; }

.libelle {
  font-size: 13px;
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--papier-bas);
}

.donnee, code, pre, textarea.ticket {
  font-family: var(--donnee);
  font-size: 13px;
  line-height: 1.4;
  color: var(--papier-bas);
}

.micro {
  font-size: 11px;
  line-height: 1.3;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--papier-bas);
}

/* --- ossature ------------------------------------------------------------ */

.entete {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e3) var(--e5);
  align-items: center;
  justify-content: space-between;
  padding: var(--e2) var(--e5);
  border-bottom: 1px solid var(--trait);
  background-image: linear-gradient(180deg, #212939 0%, var(--encre-haute) 100%);
  position: sticky;
  top: 0;
  z-index: 10;
}

.entete-nav { display: flex; flex-wrap: wrap; gap: var(--e4); align-items: center; }

.onglet {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--papier-bas);
  padding: var(--e2) 0;
  border-bottom: 2px solid transparent;
  transition: color 120ms ease-out, border-color 120ms ease-out;
}
.onglet:hover { color: var(--papier); }
.onglet.actif { color: var(--papier); border-bottom-color: var(--branche); }

.entete-coin { display: flex; align-items: center; gap: var(--e3); }

.coin-profil {
  display: flex;
  align-items: center;
  gap: var(--e2);
  padding: var(--e1) var(--e2);
  border: 1px solid transparent;
  border-radius: 2px;
  transition: border-color 120ms ease-out, background-color 120ms ease-out;
}
.coin-profil:hover, .coin-profil.actif { border-color: var(--trait); background: var(--encre); color: inherit; }
.coin-niveau {
  font-family: var(--display);
  font-size: 24px;
  line-height: 1;
  font-weight: 600;
  color: var(--branche);
}
.coin-detail { display: grid; line-height: 1.25; }

.bouton-icone {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--trait);
  border-radius: 2px;
  color: var(--papier-bas);
  transition: color 120ms ease-out, border-color 120ms ease-out, transform 200ms ease-out;
}
.bouton-icone:hover { color: var(--papier); border-color: var(--branche); transform: rotate(35deg); }
.bouton-icone.actif { color: var(--papier); border-color: var(--branche); }

.corps { max-width: 72rem; margin: 0 auto; padding: var(--e5) var(--e5) var(--e8); }

.fiche > * + * { margin-top: var(--e5); }
.fil { color: var(--papier-bas); font-size: 13px; margin-bottom: var(--e3); }

.bloc {
  background: var(--encre-haute);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e4) var(--e4);
}

/* Les ecrans ou l'on lit et ou l'on regle: aide, administration, parametres.
   Ils sont plus denses que les ecrans de consultation, donc ils ont plus d'air,
   pas moins. La regle vivait a trois endroits identiques; elle vit ici. */
.fiche-dense .bloc { padding: var(--e5); }
.fiche-dense .bloc + .bloc { margin-top: var(--e4); }
.fiche-dense .bloc > h2 { margin: 0 0 var(--e3); }
.fiche-dense .aide { margin: 0 0 var(--e4); max-width: 72ch; }
.fiche-dense .liste { margin: 0; }
.fiche-dense .actions { margin-top: var(--e3); }
.bloc > * + * { margin-top: var(--e3); }
details.bloc summary { cursor: pointer; font-weight: 600; }

.aide, .description { color: var(--papier-bas); font-size: 13px; }
.compteur { color: var(--papier-bas); font-size: 13px; }
.vide { color: var(--papier-bas); font-style: italic; }
.ok { color: var(--papier); }
.attention { color: var(--sceau); }

.meta { display: flex; flex-wrap: wrap; gap: var(--e2); }

.etiquette {
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 2px var(--e2);
  border: 1px solid var(--trait);
  border-radius: 2px;
  color: var(--papier-bas);
}

.critere { font-size: 17px; line-height: 1.45; }

/* La traduction lisible de la consigne du correcteur, puis sa ligne brute. */
.auto-lisible { color: var(--papier-bas); font-size: 14px; margin-top: var(--e2); }
.auto { margin-top: var(--e2); }
.auto code { font-family: var(--donnee); font-size: 12px; color: var(--papier-bas); overflow-wrap: anywhere; }
.note {
  border-left: 2px solid var(--trait);
  padding-left: var(--e3);
  color: var(--papier-bas);
  font-size: 13px;
}

.actions { display: flex; flex-wrap: wrap; gap: var(--e2); }

.bouton {
  display: inline-block;
  background: transparent;
  color: var(--papier);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e2) var(--e3);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: color 120ms ease-out, border-color 120ms ease-out;
}
.bouton:hover { border-color: var(--branche); }
.bouton.principal { border-color: var(--branche); }
.bouton.danger:hover { border-color: var(--sceau); color: var(--sceau); }
.bouton[disabled] { opacity: 0.4; cursor: not-allowed; }
.bouton[disabled]:hover { border-color: var(--trait); }

.champ, textarea.ticket {
  width: 100%;
  background: var(--encre);
  color: var(--papier);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e2) var(--e3);
  font-family: var(--donnee);
  font-size: 13px;
}
textarea.ticket { resize: vertical; color: var(--papier); }
.zone-inerte { opacity: 0.45; }

.bloc-texte {
  background: var(--encre);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e3);
  font-family: var(--donnee);
  font-size: 12px;
  overflow-x: auto;
  white-space: pre-wrap;
  color: var(--papier-bas);
}

.annonce {
  border: 1px solid var(--trait);
  border-left-width: 3px;
  border-radius: 2px;
  padding: var(--e2) var(--e3);
  font-size: 13px;
}
.annonce-ok { border-left-color: var(--sceau); }
.annonce-erreur { border-left-color: var(--sceau); color: var(--papier); }
.annonce-attention { border-left-color: var(--branche); }
.annonce-neutre { border-left-color: var(--papier-bas); }

/* --- barre de niveau ----------------------------------------------------- */

.rail-bloc { display: grid; gap: var(--e2); }
.rail-tete { display: flex; align-items: baseline; gap: var(--e2); flex-wrap: wrap; }
.rail-niveau { color: var(--branche); line-height: 1; }
.rail-mot { margin-right: var(--e2); }
.rail-xp { margin-left: auto; }

.rail {
  position: relative;
  height: 10px;
  border: 1px solid var(--trait);
  border-radius: 2px;
  background: var(--encre);
  overflow: hidden;
}

.rail-plein {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--branche);
  transform-origin: left;
  animation: remplir-rail 480ms ease-out;
}
@keyframes remplir-rail {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

.rail-marche { color: var(--papier-bas); opacity: 0.8; }

/* --- arbre: les modules ------------------------------------------------- */

.onglets-branches {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e5);
  border-bottom: 1px solid var(--trait);
  padding-bottom: var(--e2);
}
.onglet-branche { display: flex; align-items: baseline; gap: var(--e2); color: var(--papier-bas); }
.onglet-branche:hover { color: var(--papier); }
.onglet-branche.actif { color: var(--papier); }
.retour-hub::before { content: '‹ '; }
.onglet-branche.actif .onglet-branche-niveau { color: var(--branche); }

/* L'en-tete d'une compétence: la description, puis le rail de niveau, l'un sous
   l'autre. Ce bloc a longtemps affiche les deux sur une meme ligne, la phrase
   collee a la medaille: `.branche-tete` etait declare deux fois dans ce fichier,
   ici en grille et plus bas en `flex` pour la carte du hub, et c'est le dernier
   qui gagnait, sur les deux ecrans. La carte du hub s'appelle `.carte-tete`
   maintenant: un nom, un endroit. */
.branche-tete { display: grid; gap: var(--e3); margin: var(--e5) 0; }

/* Les modules s'empilent, et chacun deroule ses quetes sur la largeur. */
.modules { display: grid; gap: var(--e4); }

.module {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--trait);
  border-left: 3px solid var(--trait);
  border-radius: 2px;
  padding: var(--e4);
  background: var(--encre-haute);
}
/* La teinte de branche, en lavis: c'est elle qui rechauffe le bloc. */
.module::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(150deg, var(--branche), transparent 60%);
  opacity: 0.08;
  pointer-events: none;
}
.module > * { position: relative; }

.module.en-cours { border-left-color: var(--branche); }
.module.en-cours::before { opacity: 0.16; }
.module.terminee { border-left-color: var(--sceau); }
.module.fermee { opacity: 0.66; }
.module.fermee::before { opacity: 0.03; }

.module-tete {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e2) var(--e3);
  margin-bottom: var(--e3);
}
.module-numero {
  font-family: var(--donnee);
  color: var(--papier-bas);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: 0 6px;
}
.module-nom { flex: 1 1 auto; }
.module-etat { color: var(--branche); }
.module.terminee .module-etat { color: var(--sceau); }
.module-verrou { flex-basis: 100%; color: var(--papier-bas); font-size: 12px; }

.cartes { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--e2); }


/* --- tete de fiche ------------------------------------------------------- */

/* Le tier tient une medaille a droite; le titre et la ligne de rarete a gauche.
   Le lavis reprend la couleur du tier, tres bas, pour que la page entiere soit
   teintee sans que rien perde son contraste. */
.fiche-tete {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--e4);
  padding: var(--e4) var(--e4) var(--e3);
  margin-bottom: var(--e4);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--tier, var(--branche));
  border-radius: 3px;
  background-image:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--tier, var(--branche)) 12%, transparent), transparent 62%),
    linear-gradient(180deg, #232b3a 0%, #1b2230 100%);
}
.fiche-tete-corps { min-width: 0; }
.fiche-tete h1 { margin: 0; }

/* La ligne de rarete, juste sous le titre, est declaree plus bas, en un seul
   endroit: voir « bandeau de tier ». */
.bandeau-xp { color: var(--papier-bas); margin-left: var(--e3); }
/* La classe est ecrite en entier, donc elle prend de la place. Elle se met en
   retrait pour ne pas concurrencer le tier, qui est l'information de tete. */
.bandeau-classe { text-transform: none; letter-spacing: 0; font-size: 11px; cursor: help; }

/* La medaille: un chiffre, sa xp, et la couleur du tier autour. */
.tier-medaille {
  position: relative;
  flex: 0 0 auto;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 2px;
  width: 5rem;
  height: 5rem;
  border: 2px solid var(--tier, var(--trait));
  border-radius: 6px;
  background: color-mix(in srgb, var(--tier, var(--branche)) 10%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--tier, var(--branche)) 7%, transparent);
}
.tier-medaille-chiffre {
  font-family: var(--display);
  font-size: 26px;
  line-height: 1;
  color: var(--tier, var(--papier));
}
.tier-medaille-xp { font-size: 10px; color: var(--papier-bas); }

/* Fermee, la medaille perd sa couleur: elle passe en gris, et le cadenas se
   pose dessus. La couleur revient le jour ou la quete s'ouvre. */
.tier-medaille.fermee {
  border-color: color-mix(in srgb, var(--tier, var(--trait)) 45%, var(--trait));
  background: rgba(255, 255, 255, 0.02);
  box-shadow: none;
}
.tier-medaille.fermee .tier-medaille-chiffre { opacity: 0.6; }
.tier-medaille.fermee .tier-medaille-xp { opacity: 0.5; }

/* Sur la medaille, les chaines restent discretes et le cadenas se range en
   pastille de coin: le chiffre du tier ne doit jamais devenir illisible. */
.tier-medaille .verrou-chaine { opacity: 0.3; }
.tier-medaille .verrou-jeton {
  top: auto;
  left: auto;
  right: -8px;
  bottom: -8px;
  transform: none;
  width: 1.6rem;
  height: 1.6rem;
  color: var(--papier);
}
.tier-medaille .verrou-jeton svg { width: 15px; height: 15px; }
.tier-medaille .verrou-plaque { overflow: visible; }

/* --- le verrou, dessine -------------------------------------------------- */

/* Deux chaines en croix, posees derriere le contenu. Elles passent sous le
   texte et jamais devant: un bloc verrouille se lit, il n'est pas barre. */
.verrou-plaque {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
.verrou-croix { position: absolute; inset: 0; }
/* La barre part du centre et fait la longueur de la diagonale: pivotee de
   l'angle de cette diagonale, elle relie exactement deux coins opposes. La
   valeur de repli sert tant que la mesure n'a pas eu lieu. */
.verrou-chaine {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--diagonale, 140%);
  height: 12px;
  transform-origin: 50% 50%;
  background-repeat: repeat-x;
  background-position: center;
  opacity: 0.22;
}

/* Le cadenas au point de croisement, sur sa plaque. */
.verrou-jeton {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 1px solid var(--trait);
  background: var(--encre-haute);
  color: var(--papier-bas);
}

/* Sur un bloc large, le cadenas se range a droite: le texte garde le centre. */
.bloc-verrou { position: relative; overflow: hidden; }
.bloc-verrou > .verrou-plaque .verrou-jeton {
  top: var(--e4);
  left: auto;
  right: var(--e4);
  transform: none;
}
.bloc-verrou-corps { position: relative; }

/* Le bloc du chemin: un itineraire, pas un mur. Liseré a la couleur de branche,
   celle du travail en cours, et aucun cadenas. Le verrou se dit sur la medaille;
   ici on dit par ou on passe. */
.bloc-chemin { border-left: 3px solid var(--branche); }
.bloc-chemin > .aide { margin-bottom: var(--e3); }

/* Une fiche verrouillee eteint ses couleurs de tier partout sauf sur les
   etapes, ou la couleur sert encore a jauger ce qui vient. */
.fiche-verrouillee .critere { color: var(--papier-bas); }

/* --- cartes de quete ----------------------------------------------------- */

.carte {
  display: grid;
  grid-template-columns: 1.9rem 1fr auto;
  gap: var(--e2);
  align-items: center;
  background-image: linear-gradient(180deg, #232b3a 0%, #1b2230 100%);
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e2) var(--e3);
  min-height: 2.7rem;
  transition: border-color 120ms ease-out, color 120ms ease-out, transform 90ms ease-out;
}
/* La carte se tourne vers le curseur. Les deux angles sont poses en JavaScript,
   parce que le CSS ne connait pas la position du pointeur dans un element; tout
   le reste, y compris le retour a plat, est ici. */
.carte {
  transform: perspective(700px) rotateX(var(--incline-x, 0deg)) rotateY(var(--incline-y, 0deg));
  transform-style: preserve-3d;
  will-change: transform;
}
.carte:hover {
  border-color: var(--branche);
  transform: perspective(700px) rotateX(var(--incline-x, 0deg)) rotateY(var(--incline-y, 0deg))
    translateZ(6px);
}
.carte:hover .nom { color: var(--papier); }
.carte .tier {
  font-family: var(--donnee);
  font-size: 10px;
  color: var(--tier);
  border: 1px solid var(--tier);
  border-radius: 2px;
  padding: 1px 3px;
  text-align: center;
  opacity: 0.9;
}

/* La teinte du tier, posee sur la carte par le rendu. */
.tier-1 { --tier: var(--tier-1); }
.tier-2 { --tier: var(--tier-2); }
.tier-3 { --tier: var(--tier-3); }
.tier-4 { --tier: var(--tier-4); }
.tier-5 { --tier: var(--tier-5); }
.carte .nom { font-size: 14px; line-height: 1.3; }
.carte .marque { font-size: 11px; color: var(--papier-bas); font-family: var(--donnee); display: flex; align-items: center; }

.carte-verrouillee { background-image: none; background: var(--encre); color: var(--papier-bas); }
.carte-verrouillee .tier { opacity: 0.4; }
.carte-disponible { border-color: var(--tier, var(--branche)); }
.carte-disponible .nom { color: var(--tier, var(--papier)); font-weight: 500; }
.carte-disponible:hover { border-color: var(--tier, var(--branche)); }
.carte-validee,
.carte-a-rafraichir { position: relative; padding-left: calc(var(--e3) + 3px); }
.carte-validee .nom,
.carte-a-rafraichir .nom { color: var(--papier-bas); }
.carte-validee::before,
.carte-a-rafraichir::before {
  content: '';
  position: absolute;
  left: 0;
  top: -1px;
  bottom: -1px;
  width: 3px;
  background: var(--sceau);
}
.carte-a-rafraichir::before { background: none; border-left: 3px dashed var(--sceau); }
.carte-depreciee { opacity: 0.45; }

/* --- entretien ----------------------------------------------------------- */

.entretien { border-top: 1px solid var(--trait); padding-top: var(--e3); }
.entretien-tete { display: flex; align-items: baseline; gap: var(--e3); margin-bottom: var(--e2); }
.cartes-missions { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--e2); }
.carte-mission {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  align-items: start;
  padding: var(--e3);
}
.carte-mission .periode { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--papier-bas); }
.carte-mission .nom { font-size: 14px; line-height: 1.35; }
.carte-mission .transversale { color: var(--papier-bas); font-style: italic; font-size: 11px; }
.carte-mission .marque { font-size: 11px; }
.carte-mission.faite { opacity: 0.5; }


/* --- hub des competences ------------------------------------------------- */

/* Deuxieme dessin. Le premier empilait titre, description, rail et deux lignes
   de compte, tous de la meme taille: rien ne dominait, et une grille de
   rectangles gris ne donne envie d'ouvrir aucune carte.
 *
 * Celui-ci reprend ce qui marchait sur la fiche de quete: une medaille a
 * droite, le niveau dedans, a la couleur de la competence. Le niveau est ce
 * qu'on vient regarder; c'est donc lui qui accroche l'oeil. */

.hub-tete { padding: var(--e5) 0 var(--e6); }
.hub-tete h1 { margin: 0; }

.domaine { margin-bottom: var(--e6); }

/* L'en-tete d'un domaine: un filet a sa couleur, et le nom en grand. Pas de
   cadre: un domaine n'est pas une boite, c'est un intitule au-dessus de ses
   competences. */
.domaine-tete {
  display: flex;
  align-items: baseline;
  gap: var(--e3);
  padding-bottom: var(--e3);
  margin-bottom: var(--e4);
  border-bottom: 1px solid var(--trait);
}
.domaine-tete::before {
  content: '';
  width: 3px;
  align-self: stretch;
  border-radius: 2px;
  background: var(--branche);
}
.domaine-nom { margin: 0; font-size: 24px; }
.domaine-tete .donnee { color: var(--papier-bas); }
.domaine-tete .micro { margin-left: auto; color: var(--papier-bas); }
.domaine > .description { margin: calc(-1 * var(--e2)) 0 var(--e4); color: var(--papier-bas); max-width: 70ch; }

.branches { display: grid; grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: var(--e3); }

/* La carte. Une grille de deux colonnes: le corps, la medaille. La jauge et le
   pied traversent les deux. */
.branche-carte {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--e2) var(--e4);
  padding: var(--e4);
  border: 1px solid var(--trait);
  border-left: 3px solid color-mix(in srgb, var(--branche) 40%, var(--trait));
  border-radius: 4px;
  text-decoration: none;
  color: inherit;
  background-image:
    radial-gradient(120% 130% at 100% 0%, color-mix(in srgb, var(--branche) 9%, transparent), transparent 60%),
    linear-gradient(180deg, #232b3a 0%, #1b2230 100%);
  transform: perspective(900px) rotateX(var(--incline-x, 0deg)) rotateY(var(--incline-y, 0deg));
  transform-style: preserve-3d;
  transition: border-color 160ms ease, transform 110ms ease-out, box-shadow 160ms ease;
  will-change: transform;
}
.branche-carte.entamee { border-left-color: var(--branche); }
.branche-carte:hover {
  border-color: var(--branche);
  box-shadow: 0 6px 24px -12px color-mix(in srgb, var(--branche) 70%, transparent);
}
.branche-carte:focus-visible { outline: 2px solid var(--branche); outline-offset: 3px; }

.branche-corps { min-width: 0; }
.carte-tete { display: flex; align-items: baseline; gap: var(--e2); }
.branche-nom {
  font-family: var(--display);
  font-size: 19px;
  line-height: 1.2;
  color: var(--papier);
  transition: color 160ms ease;
}
.branche-carte:hover .branche-nom { color: var(--branche); }
.branche-code { color: var(--papier-bas); letter-spacing: 0.1em; }
.branche-description {
  margin: var(--e2) 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--papier-bas);
  max-width: 46ch;
}

/* La medaille de niveau: le meme objet que sur une fiche de quete, ce qui n'est
   pas un hasard. Un dispositif qui marche se reutilise plutot que de s'inventer
   un cousin. */
.branche-medaille {
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  display: grid;
  place-items: center;
  gap: 0;
  width: 4.2rem;
  height: 4.2rem;
  border: 2px solid color-mix(in srgb, var(--branche) 45%, var(--trait));
  border-radius: 6px;
  background: color-mix(in srgb, var(--branche) 8%, transparent);
  transition: border-color 160ms ease, background 160ms ease;
}
.branche-carte.entamee .branche-medaille {
  border-color: var(--branche);
  background: color-mix(in srgb, var(--branche) 16%, transparent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--branche) 7%, transparent);
}
.branche-niveau {
  font-family: var(--display);
  font-size: 30px;
  line-height: 1;
  color: var(--papier-bas);
  transition: color 160ms ease;
}
.branche-carte.entamee .branche-niveau { color: var(--branche); }
.branche-medaille .micro { font-size: 9px; color: var(--papier-bas); }

/* La jauge du palier, sur les deux colonnes: c'est la seule chose qui bouge
   d'une visite a l'autre, elle a droit a toute la largeur. */
.branche-jauge {
  grid-column: 1 / -1;
  height: 4px;
  margin-top: var(--e2);
  border-radius: 2px;
  background: var(--trait);
  overflow: hidden;
}
.branche-jauge-part {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--branche) 55%, transparent), var(--branche));
  transition: width 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.branche-pied {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--e1) var(--e3);
  margin: 0;
  font-size: 12px;
  color: var(--papier-bas);
}
.branche-pied .donnee { color: var(--papier); }
.branche-reste::before,
.branche-compte::before,
.branche-dispo::before { content: '· '; opacity: 0.5; }
.branche-dispo { color: var(--branche); }

/* Une branche dont le domaine manque n'est pas cachee: elle est rangee a part. */
.domaine-orphelin .domaine-tete::before { background: var(--sceau); }
.domaine-orphelin .aide { margin-bottom: var(--e4); max-width: 72ch; }

@media (prefers-reduced-motion: reduce) {
  .branche-carte, .branche-carte:hover { transform: none; }
  .branche-jauge-part { transition: none; }
}

/* --- profil -------------------------------------------------------------- */

.chiffres { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--e3); }
.chiffre {
  border: 1px solid var(--trait);
  border-radius: 2px;
  padding: var(--e3);
  background-image: linear-gradient(180deg, #232b3a 0%, #1b2230 100%);
  transition: border-color 160ms ease-out;
}
.chiffre:hover { border-color: var(--branche); }
.chiffre-valeur { color: var(--papier); margin: 2px 0; }
.profil-domaine { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e2); }
.profil .liste > li { border-left: 3px solid var(--branche); padding-left: var(--e3); }

/* --- groupes du tableau de bord ------------------------------------------ */

.groupe-domaine { display: grid; gap: var(--e4); }
.groupe-tete {
  display: flex;
  align-items: baseline;
  gap: var(--e3);
  padding-bottom: var(--e1);
  border-bottom: 1px solid var(--trait);
}
.groupe-tete .micro { color: var(--branche); }

/* --- bandeau de tier ----------------------------------------------------- */

.bandeau-tier {
  display: flex;
  align-items: baseline;
  gap: var(--e2);
  font-family: var(--donnee);
  margin: var(--e3) 0 var(--e3);
  padding-top: var(--e2);
  border-top: 1px solid var(--trait);
  color: var(--tier, var(--papier-bas));
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.bandeau-tier .bandeau-xp { color: var(--papier-bas); letter-spacing: 0.02em; }

.etiquette-tier { color: var(--tier, var(--papier-bas)); border-color: var(--tier, var(--trait)); }

/* Un profil sans code est une porte ouverte, pas un detail de liste. */
.etiquette-alerte { color: var(--sceau); border-color: color-mix(in srgb, var(--sceau) 55%, var(--trait)); }

/* --- les deux modes d'une quete ------------------------------------------ */

/* Reviser et passer l'examen sont deux gestes differents, pas deux boutons dans
   une meme rangee. Chacun a son cadre, son explication et son etat. */
.modes { display: grid; gap: var(--e3); }
.mode {
  border: 1px solid var(--trait);
  border-left: 3px solid var(--trait);
  border-radius: 3px;
  padding: var(--e3);
}
.mode h3 { margin: 0 0 var(--e2); color: var(--papier); }
.mode .aide { margin: 0 0 var(--e3); }
.mode-revision { border-left-color: var(--papier-bas); }
.mode-examen.ouvert { border-left-color: var(--branche); }
.mode-examen.engage { border-left-color: var(--tier-5); }
.mode-examen.ferme { border-left-color: var(--sceau); }
.mode-examen.ferme .actions { opacity: 0.75; }

/* L'etat de la fenetre: une phrase, la meme que celle du bloc copie. */
.fenetre { margin: 0 0 var(--e2); font-size: 14px; }
.fenetre.ouverte { color: var(--tier-2); }
.fenetre.fermee { color: var(--sceau); }
/* Engage: le bloc est copie, le ticket n'est pas encore la. Ni le vert de ce
   qui est possible, ni le rouge de ce qui est refuse: la couleur d'un travail
   en cours. */
.fenetre.engagee { color: var(--tier-5); }
.fenetre .libelle { color: var(--papier-bas); }

/* --- succes: des disques ------------------------------------------------- */

/* Un succes est un vinyle. Pas une carte avec un dessin dessus: un disque, avec
   son etiquette, ses sillons et son nom imprime au centre. Il se retourne pour
   montrer sa face B, qui porte ce qu'il demande. */

.section-succes + .section-succes { margin-top: var(--e5); }
.grille-succes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: var(--e4);
  margin-top: var(--e3);
  justify-items: center;
}

.succes-disque {
  perspective: 1100px;
  width: 100%;
  max-width: 12rem;
  aspect-ratio: 1;
  cursor: pointer;
  border-radius: 50%;
}
.succes-disque:focus-visible { outline: 2px solid var(--branche); outline-offset: 4px; }

.disque-interieur {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 260ms cubic-bezier(0.2, 0.7, 0.2, 1);
  will-change: transform;
}
/* Le retournement prend son temps; l'inclinaison doit coller au curseur. La
   classe posee au clic rallonge la transition juste pour ce geste-la. */
.succes-disque.retourne .disque-interieur { transition-duration: 620ms; }
/* L'inclinaison et le retournement se composent dans la meme transformation:
   sans cela l'une ecraserait l'autre. Le survol incline, le clic retourne. */
.disque-interieur {
  transform: rotateX(var(--incline-x, 0deg)) rotateY(var(--incline-y, 0deg));
}
.succes-disque:focus-visible .disque-interieur,
.succes-disque.retourne .disque-interieur {
  transform: rotateX(var(--incline-x, 0deg)) rotateY(calc(var(--incline-y, 0deg) + 180deg));
}
.succes-disque:hover .disque-face { border-color: var(--branche); }

.disque-face {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: grid;
  place-items: center;
  border: 1px solid var(--trait);
  background: radial-gradient(circle at 50% 50%, #20262f 0%, #12161d 72%, #0d1117 100%);
}
.disque-b { transform: rotateY(180deg); }

/* Les sillons: des anneaux concentriques, serres, a peine visibles. C'est ce
   qui separe un disque d'un simple rond. */
.disque-sillons {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: repeating-radial-gradient(
    circle at 50% 50%,
    rgba(255, 255, 255, 0.055) 0 1px,
    transparent 1px 4px
  );
}
/* Le reflet oblique d'une lampe sur le vinyle. */
.disque-reflet {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(118deg, transparent 38%, rgba(255, 255, 255, 0.07) 50%, transparent 62%);
}

/* L'etiquette: le nom du succes, le trou, la xp. Dans cet ordre, parce que
   c'est l'ordre d'un vrai disque. */
.disque-etiquette {
  position: relative;
  width: 58%;
  height: 58%;
  border-radius: 50%;
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  align-items: center;
  justify-items: center;
  gap: 2px;
  padding: 8%;
  text-align: center;
  background: #1b2230;
  border: 1px solid var(--trait);
  transition: background 240ms ease, border-color 240ms ease;
}
.disque-nom {
  align-self: end;
  font-family: var(--display);
  font-size: 13px;
  line-height: 1.15;
  color: var(--papier-bas);
  overflow-wrap: anywhere;
  transition: color 240ms ease;
}
.disque-trou {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--encre);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.disque-pied {
  align-self: start;
  font-family: var(--donnee);
  font-size: 10px;
  color: var(--papier-bas);
  opacity: 0.85;
}

/* La medaille.
 *
 * Deuxieme version. La premiere reprenait le fond du disque et posait un anneau
 * dessus: « fais un design pour le trophee, pas juste un disque comme pour les
 * musiques. » C'etait un vinyle deguise.
 *
 * Un disque est du plastique noir, plat, avec des sillons creuses. Une medaille
 * est du metal frappe: un bord cannele, un biseau qui accroche la lumiere, un
 * relief au centre. Ce sont deux matieres, et c'est la matiere qui doit les
 * separer, pas un detail ajoute. */
.disque-medaille {
  background:
    radial-gradient(circle at 38% 30%, rgba(255, 255, 255, 0.09) 0%, transparent 42%),
    radial-gradient(circle at 50% 55%, #3a4152 0%, #262d3a 52%, #171d27 100%);
  border-color: #454d5f;
}

/* Le bord cannele d'une piece frappee: des stries radiales, sur l'anneau
   exterieur seulement. C'est ce detail qui fait lire "metal". */
.medaille-cannelure {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: repeating-conic-gradient(
    from 0deg,
    rgba(255, 255, 255, 0.11) 0deg 1.1deg,
    rgba(0, 0, 0, 0.22) 1.1deg 2.6deg
  );
  -webkit-mask: radial-gradient(circle, transparent 0 84%, #000 84.5% 100%);
  mask: radial-gradient(circle, transparent 0 84%, #000 84.5% 100%);
  opacity: 0.7;
}

/* Le biseau: un creux et une arete, comme un coup de matrice. */
.disque-anneau {
  position: absolute;
  inset: 13%;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    inset 0 2px 5px rgba(0, 0, 0, 0.45),
    inset 0 -1px 0 rgba(255, 255, 255, 0.07),
    0 1px 0 rgba(255, 255, 255, 0.05);
}
.medaille-corps {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 3px;
  width: 68%;
  text-align: center;
}
/* L'objet est frappe dans le metal: une ombre portee vers le bas et une
   lumiere vers le haut lui donnent du relief. */
.medaille-objet {
  display: grid;
  place-items: center;
  color: #b9c1d1;
  opacity: 0.9;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55)) drop-shadow(0 -1px 0 rgba(255, 255, 255, 0.07));
  transition: color 240ms ease, opacity 240ms ease;
}
.medaille-objet svg { width: 40px; height: 40px; display: block; }
/* Le metal est plus clair que le vinyle: le texte doit remonter d'autant. */
.disque-medaille .disque-nom { align-self: auto; margin-top: 4px; color: #d5d9e3; }
.disque-medaille .disque-pied { align-self: auto; color: #9aa2b3; }
.succes-disque.obtenu .disque-medaille .disque-nom { color: var(--papier); }

/* Obtenue, la medaille se dore: le metal prend la teinte de la branche, la
   cannelure ressort, le relief s'affirme. */
.succes-disque.obtenu .disque-medaille {
  border-color: var(--branche);
  background:
    radial-gradient(circle at 38% 30%, rgba(255, 255, 255, 0.14) 0%, transparent 42%),
    radial-gradient(
      circle at 50% 55%,
      color-mix(in srgb, var(--branche) 34%, #3a4152) 0%,
      color-mix(in srgb, var(--branche) 20%, #262d3a) 52%,
      #171d27 100%
    );
}
.succes-disque.obtenu .medaille-cannelure { opacity: 1; }
.succes-disque.obtenu .disque-anneau { border-color: color-mix(in srgb, var(--branche) 60%, #ffffff); }
.succes-disque.obtenu .medaille-objet { color: var(--papier); opacity: 1; }

/* L'etat, sur le bord bas du disque, la ou une pochette porte sa mention. */
.disque-etat {
  position: absolute;
  bottom: 7%;
  color: var(--papier-bas);
  font-size: 9px;
}

/* Obtenu: l'etiquette prend la couleur de la branche, le disque s'allume. */
.succes-disque.obtenu .disque-a { border-color: color-mix(in srgb, var(--branche) 45%, var(--trait)); }
.succes-disque.obtenu .disque-etiquette {
  background: color-mix(in srgb, var(--branche) 20%, #1b2230);
  border-color: var(--branche);
}
.succes-disque.obtenu .disque-nom { color: var(--papier); }
.succes-disque.obtenu .disque-etat { color: var(--branche); }
.succes-disque.obtenu .disque-sillons { opacity: 1; }
.succes-disque:not(.obtenu) .disque-sillons { opacity: 0.5; }

/* La face B: le texte au centre, l'objet du domaine en filigrane derriere. */
.disque-dos {
  position: relative;
  width: 78%;
  max-height: 78%;
  overflow: auto;
  text-align: center;
  font-size: 12px;
}
.disque-dos .micro { margin: 0 0 var(--e2); }
.disque-dos .termes li { font-size: 12px; line-height: 1.3; }
.disque-filigrane {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--papier-bas);
  opacity: 0.12;
}
.disque-filigrane svg { width: 70%; height: 70%; }

/* Les silhouettes: l'engrenage et la disquette.
 *
 * « Un vrai design de succès pour les catégories différentes, pas juste un
 * cercle pour tout. » Ces deux-la ne sont pas des ronds. Leur contour est un SVG
 * rempli en `currentColor`: gris tant que le succes n'est pas obtenu, la couleur
 * de la branche une fois qu'il l'est. La face A ne porte donc ni fond ni bord --
 * la silhouette EST la forme --, et le nom se pose par-dessus, sur le moyeu de la
 * roue ou sur l'etiquette de papier de la disquette, comme le vinyle porte le
 * sien sur son etiquette. */
/* Ni disque ni medaille: on se detache du cercle sur les deux faces. La face A
   ne porte pas de fond (la silhouette EST la forme, les coins restent
   transparents); la face B est un panneau arrondi, pas un rond. Les enfants
   restent aplatis dans le plan de la face (overflow: hidden) pour que le
   retournement ne laisse jamais transparaitre la face du dessous. */
.forme-engrenage { border-radius: 12px; }
.forme-puce { border-radius: 8px; }
.forme-engrenage .disque-a,
.forme-puce .disque-a {
  background: none;
  border: none;
  overflow: hidden;
  color: #58627a;
  transition: color 240ms ease;
}
.forme-engrenage .disque-a { border-radius: 12px; }
.forme-puce .disque-a { border-radius: 8px; }
.forme-engrenage .disque-b,
.forme-puce .disque-b { border-radius: 12px; }
.succes-disque.obtenu.forme-engrenage .disque-a,
.succes-disque.obtenu.forme-puce .disque-a { color: var(--branche); }
.succes-disque:hover.forme-engrenage:not(.obtenu) .disque-a,
.succes-disque:hover.forme-puce:not(.obtenu) .disque-a {
  color: color-mix(in srgb, var(--branche) 45%, #58627a);
}

.silhouette {
  position: absolute;
  inset: 4%;
  width: 92%;
  height: 92%;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45));
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Le moyeu de la roue: un disque cerne, au centre des dents, ou s'imprime le
   nom. Il tourne avec la roue mais garde ses lettres droites. */
.forme-moyeu {
  position: relative;
  width: 48%;
  height: 48%;
  border-radius: 50%;
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  gap: 2px;
  padding: 5%;
  text-align: center;
  background: radial-gradient(circle at 42% 34%, #232b38 0%, #171d27 78%);
  border: 1px solid rgba(0, 0, 0, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.4);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.forme-moyeu .disque-nom { align-self: end; font-size: 12px; }

/* La disquette: le volet metallique en haut, l'etiquette de papier en bas. */
.puce-volet {
  position: absolute;
  top: 13%;
  left: 30%;
  width: 40%;
  height: 14%;
  background: linear-gradient(#2b3240, #1b2230);
  border: 1px solid rgba(0, 0, 0, 0.5);
  border-radius: 2px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.puce-label {
  position: absolute;
  left: 16%;
  right: 12%;
  top: 44%;
  bottom: 13%;
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  gap: 2px;
  padding: 5% 8%;
  text-align: center;
  background: #e9e4d6;
  border-radius: 2px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.22), 0 1px 2px rgba(0, 0, 0, 0.3);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.forme-puce .puce-label .disque-nom { align-self: end; font-size: 12px; color: #2a2f3a; }
.succes-disque.obtenu.forme-puce .puce-label .disque-nom { color: #1b2028; }
.forme-puce .puce-label .disque-pied { align-self: start; color: #5c5346; opacity: 0.9; }

/* L'etat se pose sur un fond charge (les dents, le corps de la disquette): une
   petite pastille sombre le detache pour qu'il reste lisible. */
.forme-engrenage .disque-etat,
.forme-puce .disque-etat {
  bottom: 3%;
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(13, 17, 23, 0.74);
}

/* Sans mouvement: pas de rotation. La face A se montre, la face B se pose
   dessous, en clair. Les silhouettes se rangent en simple panneau: un SVG
   positionne en absolu n'a pas de place dans une pile verticale. */
@media (prefers-reduced-motion: reduce) {
  .carte, .carte:hover { transform: none; }
  .trainee { display: none; }
  .succes-disque { aspect-ratio: auto; max-width: none; perspective: none; }
  .disque-interieur { transform: none !important; transform-style: flat; height: auto; }
  .disque-face {
    position: static;
    backface-visibility: visible;
    transform: none !important;
    border-radius: 3px;
    aspect-ratio: auto;
    padding: var(--e3);
  }
  .disque-b { margin-top: var(--e2); }
  .disque-etiquette { width: auto; height: auto; border-radius: 3px; }
  .silhouette, .puce-volet { display: none; }
  .forme-engrenage .disque-a,
  .forme-puce .disque-a {
    background: radial-gradient(circle at 50% 40%, #20262f, #12161d);
    border: 1px solid var(--trait);
    color: inherit;
  }
  .forme-moyeu, .puce-label {
    position: static;
    inset: auto;
    width: auto;
    height: auto;
    border-radius: 3px;
    background: none;
    box-shadow: none;
  }
  .forme-puce .puce-label .disque-nom,
  .forme-puce .puce-label .disque-pied { color: inherit; }
}

/* --- parametres ---------------------------------------------------------- */

.interrupteur { display: flex; align-items: center; gap: var(--e2); cursor: pointer; font-size: 14px; }
.interrupteur input { width: 16px; height: 16px; accent-color: var(--branche); }

/* Les profils. Un par ligne, celui qui est ouvert marque a gauche. */
/* Une ligne de profil porte un nom, des etiquettes, une date et des boutons.
   C'est dense: elle a besoin de hauteur, et d'un ecart entre son liseré et son
   texte.
 *
 * Le double `.liste.liste-profils` n'est pas une coquetterie. `.liste > li` pose
 * `padding: var(--e2) 0` plus bas dans ce fichier, a specificite egale (une
 * classe et un type des deux cotes), et l'ordre des lignes decidait donc du
 * gagnant. J'ai corrige ces marges deux fois sans les corriger: la regle etait
 * ecrite, elle etait ecrasee, et le calcul disait `8px 0px`.
 *
 * Deux classes contre une: la question ne se pose plus, quel que soit l'ordre.
 * Et le padding est ecrit en une seule declaration a quatre valeurs, parce
 * qu'un `padding-left` isole se fait toujours manger par un `padding` court. */
.liste.liste-profils > li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) var(--e2) var(--e3) var(--e4);
}
.profil-ligne { border-left: 2px solid transparent; }
.profil-ligne.actif { border-left-color: var(--branche); }
.profil-ligne .titre { font-weight: 500; margin-right: var(--e2); }
.profil-ligne .titre + .etiquette { margin-left: 0; }
.profil-ligne .libelle { margin: var(--e1) 0 0; }
.profil-ligne .actions { margin: 0; }

/* --- recette ------------------------------------------------------------- */

/* Ce que la chaine ouvre. En haut, encadre, parce que c'est le but. */
.bloc-cible {
  border: 1px solid var(--trait);
  border-left: 3px solid var(--tier, var(--branche));
  border-radius: 3px;
  padding: var(--e3);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent 60%);
}
.bloc-cible .titre { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--e2); margin: var(--e1) 0 var(--e3); }

/* Une jauge en crans: un cran par etape, remplis dans l'ordre. */
.jauge-chaine { display: flex; gap: 3px; }
.cran-chaine {
  flex: 1 1 0;
  height: 6px;
  border-radius: 3px;
  background: var(--trait);
  transition: background 200ms ease;
}
.cran-chaine.obtenu { background: var(--tier, var(--branche)); }

/* Les etapes, dans l'ordre, chacune nommee par la quete qui la produit. */
.etapes { list-style: none; margin: var(--e2) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--e2); }
.etape {
  display: grid;
  grid-template-columns: 2rem 1fr auto;
  align-items: center;
  gap: var(--e3);
  padding: var(--e3);
  border: 1px solid var(--trait);
  border-left: 3px solid transparent;
  border-radius: 3px;
  background-image: linear-gradient(180deg, #232b3a 0%, #1b2230 100%);
  transition: border-color 160ms ease, transform 160ms ease;
}
.etape.obtenue { border-left-color: var(--tier, var(--tier-2)); }
.etape:hover { border-color: var(--branche); transform: translateX(2px); }
.etape-numero {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 1px solid var(--trait);
  color: var(--papier-bas);
  font-family: var(--donnee);
}
/* Le numero prend la couleur du tier de sa quete: la rarete se lit de loin. */
.etape .etape-numero { border-color: var(--tier, var(--trait)); color: var(--tier, var(--papier-bas)); opacity: 0.7; }
.etape.obtenue .etape-numero, .etape.prochaine .etape-numero { opacity: 1; }
.etape.obtenue .etape-numero { background: color-mix(in srgb, var(--tier, var(--tier-2)) 14%, transparent); }
.etape.obtenue .etape-nom { color: var(--papier); }
.etape.manquante .etape-nom { color: var(--papier-bas); }

/* La prochaine etape utile: la seule qu'on ait besoin de trouver du regard. */
.etape.prochaine { border-color: var(--branche); border-left-color: var(--branche); }
.etape.prochaine .etape-marque { color: var(--branche); }

/* Une etape porte le tier de sa propre quete, jamais celui de la fiche autour:
   sans cette remise a zero, une etape sans tier empruntait la couleur du T5
   qu'elle sert a deverrouiller. */
.etapes > .etape { --tier: var(--papier-bas); }
.etapes > .etape.tier-1 { --tier: var(--tier-1); }
.etapes > .etape.tier-2 { --tier: var(--tier-2); }
.etapes > .etape.tier-3 { --tier: var(--tier-3); }
.etapes > .etape.tier-4 { --tier: var(--tier-4); }
.etapes > .etape.tier-5 { --tier: var(--tier-5); }

.etape-corps { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.etape-nom { font-weight: 500; font-size: 15px; overflow-wrap: anywhere; }
.etape-id { font-size: 11px; color: var(--papier-bas); }
.etape-marque { font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--papier-bas); white-space: nowrap; }
.etape.obtenue .etape-marque { color: var(--tier-2); }

/* Une chaine, dans le bloc de verrou: son nom, sa jauge, ses etapes. */
.groupe-chaine { margin-top: var(--e4); }
.groupe-chaine h3 { margin: 0 0 var(--e2); color: var(--papier); }
.groupe-chaine .jauge-chaine { margin: var(--e2) 0; }
.groupe-chaine .libelle { margin: 0; }

.debloque { border-top: 1px solid var(--trait); padding-top: var(--e3); display: flex; gap: var(--e3); align-items: baseline; }

/* --- listes -------------------------------------------------------------- */

.liste > li { padding: var(--e2) 0; border-bottom: 1px solid var(--trait); }
.liste > li:last-child { border-bottom: none; }

.historique li { padding: 2px 0; font-size: 13px; }
.historique .valide { color: var(--papier); }
.historique .refuse, .historique .annulee { color: var(--papier-bas); }
.historique .ticket { font-family: var(--donnee); font-size: 11px; color: var(--papier-bas); margin-left: var(--e2); }

.expiree { color: var(--sceau); }
.problemes li { color: var(--sceau); font-size: 13px; }

.termes li { font-size: 13px; color: var(--papier-bas); }
.terme.fait { color: var(--tier-2); }
.terme.fait::before { content: 'fait: '; opacity: 0.7; }
.terme.reste::before { content: 'reste: '; color: var(--papier-bas); }

.controles li { font-size: 13px; color: var(--papier-bas); padding: 2px 0; }
.controles li.verrou { color: var(--papier); }
.controles li.echoue { color: var(--sceau); border-left: 2px solid var(--sceau); padding-left: var(--e2); }

.rapport { width: 100%; border-collapse: collapse; font-size: 12px; }
.rapport th { text-align: left; color: var(--papier-bas); font-weight: 500; border-bottom: 1px solid var(--trait); padding: var(--e1) var(--e2); }
.rapport td { padding: var(--e1) var(--e2); border-bottom: 1px solid var(--trait); vertical-align: top; }
.rapport tr.erreur td:nth-child(3) { color: var(--sceau); }

.arborescence code { color: var(--papier-bas); }
.arborescence ul { padding-left: var(--e4); }

/* Le bouton de sortie: un mot, pas une icone. « Sortir » se lit sans legende,
   et un dessin de porte n'aurait pas ete plus clair. */
.bouton-sortie {
  background: transparent;
  border: 1px solid var(--trait);
  border-radius: 3px;
  color: var(--papier-bas);
  font-family: var(--texte);
  font-size: 12px;
  padding: 5px var(--e2);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 120ms ease, color 120ms ease;
}
.bouton-sortie:hover { border-color: var(--branche); color: var(--papier); }

/* --- la porte ------------------------------------------------------------ */

/* --- la console ---------------------------------------------------------- */

/* La console est dense: des formulaires, des listes et des boutons dans le meme
   bloc. Elle a besoin de plus d'air que les ecrans de lecture, pas de moins. */
.fiche-admin { max-width: 64rem; }
.fiche-admin .aide { max-width: 72ch; }

/* Un formulaire tient sur une ligne tant qu'il y a la place, et se replie
   proprement quand il n'y en a plus. Il est separe de la liste qu'il complete:
   ce sont deux gestes, lire et ajouter. */
.actions-formulaire {
  align-items: center;
  gap: var(--e2);
  margin-top: var(--e4);
  padding-top: var(--e4);
  border-top: 1px solid var(--trait);
}
.actions-formulaire .champ { flex: 1 1 10rem; min-width: 0; }
.champ-court { flex: 0 0 5rem !important; text-transform: uppercase; }
.champ-couleur { flex: 0 0 3rem !important; padding: 2px; height: 2.2rem; cursor: pointer; }

.liste-catalogue > li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e3);
  padding: var(--e3) 0;
}
.liste-catalogue .titre { font-weight: 500; }
.liste-catalogue .etiquette { margin-left: var(--e2); }

/* Une ligne de profil dans la console porte quatre boutons: elle a besoin de
   respirer, et de se replier sans se serrer quand la fenetre retrecit. */
.fiche-admin .liste.liste-profils > li { padding: var(--e4) var(--e2) var(--e4) var(--e4); }
.fiche-admin .profil-ligne .actions { flex-wrap: wrap; justify-content: flex-end; }
.fiche-admin .profil-ligne .libelle { margin: var(--e1) 0 0; }

/* Ce qu'un profil apprend: replie sous sa ligne, dans la console. Une liste
   plate de competences, sans les domaines: on attribue une competence a
   quelqu'un, pas une categorie. */
.competences-profil { flex-basis: 100%; margin-top: var(--e3); }
.competences-profil > summary { cursor: pointer; font-size: 13px; color: var(--papier-bas); }
.competences-profil > summary:hover { color: var(--papier); }
.cases { display: flex; flex-wrap: wrap; gap: var(--e2); margin-top: var(--e3); }
.case-branche {
  padding: var(--e2) var(--e3);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--branche);
  border-radius: 3px;
  transition: border-color 140ms ease;
}
.case-branche:hover { border-color: var(--branche); }

/* La connexion: un pseudo, un code, un bouton. Rien d'autre a l'ecran. */
.fiche-connexion { max-width: 24rem; margin: 0 auto; padding-top: var(--e8); }
.formulaire-connexion { display: grid; gap: var(--e2); margin-top: var(--e5); }
.formulaire-connexion .bouton { margin-top: var(--e3); text-align: center; }
.champ-libelle { font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--papier-bas); }
.champ-libelle + .champ { margin-bottom: var(--e2); }
.fiche-connexion .retour:empty { display: none; }
.fiche-connexion .retour { margin-top: var(--e4); }

/* Une note de mecanique: elle n'apparait qu'en mode developpeur, et elle se
   distingue de l'aide ordinaire pour qu'on ne la confonde pas avec une consigne. */
.note-technique { border-left: 2px solid var(--trait); padding-left: var(--e3); font-style: italic; }

/* La zone de depot: un rectangle en pointilles, qui dit ce qu'il attend. */
.zone-depot {
  display: grid;
  place-items: center;
  gap: var(--e1);
  padding: var(--e6) var(--e4);
  border: 2px dashed var(--trait);
  border-radius: 4px;
  cursor: pointer;
  text-align: center;
  transition: border-color 160ms ease, background 160ms ease;
}
.zone-depot:hover { border-color: var(--branche); }
.zone-depot.survolee {
  border-color: var(--branche);
  background: color-mix(in srgb, var(--branche) 10%, transparent);
}
.zone-depot .titre { margin: 0; }
.zone-depot .libelle { margin: 0; }

/* Le selecteur de fichier reste dans le document pour rester cliquable par la
   zone, mais il ne se montre pas: la zone est l'interface. */
.champ-fichier { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* Un refus montre les erreurs du parser en entier: c'est ce qu'on renvoie a
   celui qui a ecrit le fichier. */
.refus-depot { margin-top: var(--e3); }
.refus-depot .problemes { margin: var(--e2) 0 0; }

/* --- page d'aide --------------------------------------------------------- */

/* Cette page se lit, elle ne se consulte pas. Elle a donc une mesure, un
   rythme vertical large, et pas de cadre autour de chaque paragraphe: une
   succession de blocs encadres se lit comme un formulaire. */

.fiche-aide { max-width: 44rem; margin: 0 auto; }

/* L'ouverture: la phrase qui tient lieu de titre. C'est la seule chose qu'on
   est sur de lire, elle a droit a la taille d'un titre. */
.aide-ouverture { padding: var(--e6) 0 var(--e7); border-bottom: 1px solid var(--trait); }
.aide-ouverture .micro { color: var(--branche); margin: 0 0 var(--e4); }
.aide-phrase {
  font-family: var(--display);
  font-size: clamp(26px, 3.4vw, 38px);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: -0.01em;
  margin: 0 0 var(--e4);
  color: var(--papier);
}
.aide-ouverture .libelle { margin: 0; }

.aide-corps { display: grid; gap: var(--e8); padding: var(--e7) 0 var(--e8); }

.aide-chapitre h2 {
  font-family: var(--texte);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--papier-bas);
  margin: 0 0 var(--e4);
  padding-bottom: var(--e2);
  border-bottom: 1px solid var(--trait);
}
.aide-chapitre p { line-height: 1.65; margin: 0 0 var(--e3); font-size: 15px; }
.aide-chapitre p:last-child { margin-bottom: 0; }
.aide-chapitre strong { color: var(--papier); }

/* Une liste de prose: des puces discretes, du texte aere. */
.liste-aide { list-style: none; margin: 0 0 var(--e3); padding: 0; display: grid; gap: var(--e3); }
.liste-aide > li { position: relative; padding-left: var(--e4); line-height: 1.6; }
.liste-aide > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--branche);
}

/* Le lexique: le terme et son sens, sur deux colonnes tant qu'il y a la place. */
.lexique { display: grid; grid-template-columns: 9rem 1fr; gap: var(--e3) var(--e4); margin: 0; }
.lexique dt { font-weight: 600; color: var(--papier); }
.lexique dd { margin: 0; color: var(--papier-bas); line-height: 1.55; }

/* Ce que l'application ne fera jamais: chaque ligne barree d'une croix. */
.liste-jamais { list-style: none; margin: 0 0 var(--e4); padding: 0; display: grid; gap: var(--e3); }
.liste-jamais > li { display: flex; align-items: baseline; gap: var(--e3); line-height: 1.6; color: var(--papier-bas); }
.jamais-marque { position: relative; flex: 0 0 14px; height: 14px; align-self: center; }
.jamais-marque::before,
.jamais-marque::after {
  content: '';
  position: absolute;
  inset: 6px 0 auto;
  height: 1.5px;
  background: var(--sceau);
  border-radius: 1px;
}
.jamais-marque::before { transform: rotate(45deg); }
.jamais-marque::after { transform: rotate(-45deg); }

/* Le trajet, numerote. */
.etapes-aide { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--e4); }
.etape-aide { display: grid; grid-template-columns: 2rem 1fr; gap: var(--e4); align-items: start; }
.etape-aide .etape-corps { min-width: 0; }
.etape-aide .etape-numero {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 1px solid var(--branche);
  color: var(--branche);
  font-family: var(--donnee);
}
.etape-aide .etape-nom { font-weight: 600; font-size: 15px; color: var(--papier); }
.etape-aide .libelle { margin: var(--e1) 0 0; line-height: 1.6; }

/* --- les schemas --------------------------------------------------------- */

/* Un schema dit une chose que la phrase a cote ne dit pas. Il a donc de la
   place, et un fond qui le detache du texte sans l'encadrer comme un tableau. */
.schema-cadre {
  margin: 0 0 var(--e5);
  padding: var(--e5) var(--e4);
  border-radius: 6px;
  background:
    radial-gradient(120% 160% at 50% 0%, color-mix(in srgb, var(--branche) 8%, transparent), transparent 70%),
    linear-gradient(180deg, #212836 0%, #171d27 100%);
  border: 1px solid var(--trait);
  overflow-x: auto;
}
.aide-chapitre p + .schema-cadre,
.aide-chapitre ul + .schema-cadre { margin: var(--e4) 0 0; }

.schema { display: block; width: 100%; min-width: 34rem; height: auto; }

.schema-boite rect { fill: rgba(255, 255, 255, 0.03); stroke: var(--trait); stroke-width: 1; }
.schema-toi rect { fill: color-mix(in srgb, var(--branche) 16%, transparent); stroke: var(--branche); }
.schema-titre { fill: var(--papier); font-size: 14px; font-weight: 500; text-anchor: middle; }
.schema-sous { fill: var(--papier-bas); font-size: 11px; text-anchor: middle; }
.schema-legende { fill: var(--papier-bas); font-size: 11px; text-anchor: middle; }
.schema-faible { opacity: 0.65; }
.schema-note { fill: var(--papier-bas); font-size: 12px; font-style: italic; text-anchor: middle; }

.schema-trait { fill: none; stroke: var(--trait); stroke-width: 2; }
.schema-pointe { fill: var(--trait); }

/* Le courant qui parcourt une fleche: la seule animation de la page. Elle dit
   « ca circule » sans rien donner a suivre du regard. */
.schema-courant {
  fill: none;
  stroke: var(--branche);
  stroke-width: 2;
  stroke-dasharray: 6 10;
  animation: courant 1.6s linear infinite;
}
@keyframes courant {
  to { stroke-dashoffset: -16; }
}
.schema-morte .schema-courant { animation: none; stroke: var(--sceau); opacity: 0.4; }
.schema-morte .schema-trait { stroke-dasharray: 3 4; }

.schema-ticket rect { fill: rgba(255, 255, 255, 0.04); }
.schema-absent rect { stroke-dasharray: 4 4; opacity: 0.5; }
.schema-absent .schema-titre { opacity: 0.4; }

.schema-verdict circle { fill: none; stroke-width: 2; }
.schema-oui circle { stroke: var(--tier-2); fill: color-mix(in srgb, var(--tier-2) 14%, transparent); }
.schema-non circle { stroke: var(--sceau); fill: color-mix(in srgb, var(--sceau) 14%, transparent); }
.schema-coche { fill: none; stroke: var(--tier-2); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.schema-croix { fill: none; stroke: var(--sceau); stroke-width: 2.4; stroke-linecap: round; }

.schema-axe { fill: none; stroke: var(--trait); stroke-width: 2; }
.schema-minuit { fill: none; stroke: var(--trait); stroke-width: 1; stroke-dasharray: 3 4; }
.schema-jalon circle { stroke-width: 2; fill: var(--encre); }
.schema-jalon.schema-oui circle { stroke: var(--tier-2); fill: color-mix(in srgb, var(--tier-2) 22%, var(--encre)); }
.schema-jalon .schema-titre { font-size: 13px; }
.schema-cible circle { stroke: var(--tier-4); fill: color-mix(in srgb, var(--tier-4) 22%, var(--encre)); stroke-width: 2; }

.schema-accolade { fill: none; stroke: var(--trait); stroke-width: 1.5; }
.schema-etiquette { fill: var(--encre); stroke: var(--trait); stroke-width: 1; }

@media (prefers-reduced-motion: reduce) {
  .schema-courant { animation: none; }
}

@media (max-width: 720px) {
  .lexique { grid-template-columns: 1fr; gap: var(--e1) 0; }
  .lexique dd { margin-bottom: var(--e3); }
}

/* --- la banniere d'un succes obtenu -------------------------------------- */

/* En bas a droite, quelques secondes, puis elle s'en va. Elle ne demande rien:
   pas de bouton, rien a fermer. C'est un constat qui passe pendant qu'on
   travaille, pas une notification. */

.bannieres {
  position: fixed;
  right: var(--e4);
  bottom: var(--e4);
  z-index: 60;
  display: grid;
  gap: var(--e2);
  justify-items: end;
  /* La zone ne doit jamais intercepter un clic destine a la page dessous. */
  pointer-events: none;
}

.banniere {
  display: flex;
  align-items: center;
  gap: var(--e3);
  max-width: min(22rem, calc(100vw - 2 * var(--e4)));
  padding: var(--e3) var(--e4);
  border: 1px solid var(--trait);
  border-left: 3px solid var(--tier-5);
  border-radius: 4px;
  background-image:
    radial-gradient(120% 140% at 100% 0%, color-mix(in srgb, var(--tier-5) 12%, transparent), transparent 62%),
    linear-gradient(180deg, #232b3a 0%, #171d27 100%);
  box-shadow: 0 12px 32px -18px #000;

  /* L'entree et la sortie glissent depuis la droite. L'etat au repos est
     l'etat cache: la banniere est posee ainsi, puis la classe la fait entrer,
     ce qui donne au navigateur les deux images dont il a besoin. */
  opacity: 0;
  transform: translateX(1.5rem);
  transition: opacity 420ms ease, transform 420ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.banniere.entree { opacity: 1; transform: translateX(0); }
.banniere.sortie { opacity: 0; transform: translateX(1.5rem); }

.banniere-objet { display: grid; place-items: center; width: 2.2rem; color: var(--tier-5); }
.banniere-objet svg { width: 100%; height: auto; }
.banniere-corps { display: grid; gap: 2px; min-width: 0; }
.banniere-titre { color: var(--tier-5); }
.banniere-nom { font-family: var(--display); font-size: 16px; line-height: 1.2; color: var(--papier); }
.banniere-xp { font-size: 12px; color: var(--papier-bas); }

@media (prefers-reduced-motion: reduce) {
  /* Elle apparait et disparait, sans glisser. */
  .banniere { transition: opacity 200ms linear; transform: none; }
  .banniere.entree { transform: none; }
  .banniere.sortie { transform: none; }
}

/* --- la celebration d'une validation ------------------------------------- */

/* Les feux d'artifice se dessinent dans ce canvas, par-dessus tout, sans jamais
   intercepter un clic. Le module JavaScript le cree, l'anime et le retire; ici
   on ne fait que le placer et le rendre transparent aux gestes. */
.celebration {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 70;
  pointer-events: none;
}

/* Commencer n'est pas reussir. Le collage d'un exo merite un accuse de reception
   sobre, pas une fete: un fin balayage qui traverse le haut une fois, dans la
   couleur « en cours ». Il ne clignote pas, il ne monte pas: il passe. */
.celebration-balayage {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 70;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--tier-3), transparent);
  animation: balayage 1000ms cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes balayage {
  0% { transform: translateX(-100%); opacity: 0; }
  20% { opacity: 1; }
  80% { opacity: 1; }
  100% { transform: translateX(100%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .celebration-balayage { animation: balayage-sobre 800ms linear; transform: none; }
}
@keyframes balayage-sobre {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

/* Mouvement coupe: pas de particules. Un halo qui monte du bas, une fois. C'est
   la version sobre de la meme joie, et elle ne bouge presque pas. */
.celebration-halo {
  position: fixed;
  inset: auto 0 0 0;
  height: 40vh;
  z-index: 70;
  pointer-events: none;
  opacity: 0;
  animation: halo 900ms ease-out;
}
.celebration-halo.valide {
  background: radial-gradient(60% 100% at 50% 100%, color-mix(in srgb, var(--tier-5) 40%, transparent), transparent 70%);
}
.celebration-halo.commence {
  background: radial-gradient(60% 100% at 50% 100%, color-mix(in srgb, var(--tier-2) 32%, transparent), transparent 70%);
}
@keyframes halo {
  0% { opacity: 0; }
  40% { opacity: 1; }
  100% { opacity: 0; }
}

/* --- la trainee du curseur ----------------------------------------------- */

/* Une toile fixe, au-dessus de tout, sensible a rien. Elle ne capte aucun clic
   et ne participe a aucune mise en page. */
.trainee {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  z-index: 90;
}

/* La teinte suit l'ecran regarde: le JavaScript la relit a chaque trait. */
:root { --trainee-teinte: #6f7789; }

/* --- mouvement ----------------------------------------------------------- */

/* L'entree d'un ecran: une apparition breve, jamais un glissement. */
@keyframes paraitre {
  from { opacity: 0; }
  to { opacity: 1; }
}
.corps > * { animation: paraitre 160ms ease-out; }


/* Un seul moment orchestre: le sceau d'une validation se trace de haut en bas. */
@keyframes tracer-sceau {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}
.carte-validee.fraiche::before {
  transform-origin: top;
  animation: tracer-sceau 240ms ease-out;
}

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

/* --- mobile -------------------------------------------------------------- */

@media (max-width: 40rem) {
  body { font-size: 16px; }
  .corps { padding: var(--e4) var(--e3) var(--e7); }
  .entete { padding: var(--e3); }
  .display-xl { font-size: 40px; }
  .display-l { font-size: 26px; }
  .cartes-missions { grid-template-columns: 1fr; }
  .etape { grid-template-columns: 1.75rem 1fr; }
  .etape-marque { grid-column: 2; }
  .profil-ligne .actions { width: 100%; }
}
