/* ============================================================================
   BOUGE — composants.css
   Les briques visibles de l'app. Un composant = un bloc, ses éléments en
   `__`, ses variantes en `--`. Aucune couleur, taille ni durée en dur.
   Le catalogue commenté est dans docs/DESIGN.md § 6.
   ============================================================================ */

/* ---------- 1. Bouton GO — le geste unique de l'app ---------- */

.bouton-go {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--espace-4);
  width: 100%;
  min-height: var(--hauteur-go);
  padding: var(--espace-16) var(--espace-24);
  border-radius: var(--rayon-go);
  background: var(--go);
  color: var(--sur-go);
  border: 2px solid var(--go-contour);
  box-shadow: var(--ombre-go);
  text-align: center;
}

.bouton-go__mot {
  font-size: var(--taille-1);
  font-weight: var(--graisse-1);
  line-height: var(--ligne-1);
  letter-spacing: var(--lettre-1);
  font-variation-settings: "opsz" var(--opsz-1);
}

.bouton-go__detail {
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
  color: var(--sur-go);
  opacity: 0.78;
}

.bouton-go:disabled {
  opacity: 0.5;
  box-shadow: none;
  cursor: default;
}

/* ---------- 2. Boutons courants ---------- */

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-8);
  min-height: var(--hauteur-bouton);
  padding: 0 var(--espace-24);
  border-radius: var(--rayon-m);
  font-size: var(--taille-4);
  font-weight: 600;
  border: 2px solid transparent;
}

.bouton--primaire {
  background: var(--accent);
  color: var(--sur-accent);
}

.bouton--secondaire {
  background: var(--surface);
  color: var(--texte);
  border-color: var(--bordure);
}

.bouton--fantome {
  background: transparent;
  color: var(--accent);
  padding: 0 var(--espace-12);
}

.bouton--danger {
  background: transparent;
  color: var(--alerte);
  border-color: var(--alerte);
}

.bouton--pleine-largeur {
  width: 100%;
}

/* Bouton rond des commandes de séance (pause, reprendre, suivant). */
.bouton-rond {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: var(--rayon-rond);
  background: var(--surface);
  color: var(--texte);
  border: 2px solid var(--bordure);
  box-shadow: var(--ombre-carte);
}

.bouton-rond--principal {
  width: 76px;
  height: 76px;
  background: var(--accent);
  color: var(--sur-accent);
  border-color: transparent;
}

.bouton-rond__libelle {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/* ---------- 3. Carte ---------- */

.carte {
  background: var(--surface);
  border: var(--bord-eleve);
  border-radius: var(--rayon-carte);
  box-shadow: var(--ombre-carte);
  padding: var(--espace-24);
}

.carte--haute {
  background: var(--surface-haute);
}

.carte__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-12);
  margin-bottom: var(--espace-12);
}

.carte__titre {
  font-size: var(--taille-3);
  font-weight: var(--graisse-3);
  line-height: var(--ligne-3);
  letter-spacing: var(--lettre-3);
}

.carte__meta {
  color: var(--texte-doux);
  font-size: var(--taille-5);
}

/* ---------- 4. Puce (durée, langue, spécialité) ---------- */

.puce {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-4);
  padding: var(--espace-4) var(--espace-12);
  border-radius: var(--rayon-rond);
  background: var(--pression);
  color: var(--texte);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

.puce--accent {
  background: transparent;
  color: var(--accent);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

/* Lignes « Au programme » de l'accueil : les trois exercices annoncés ouvrent leur fiche.
   Une ligne entière, pas une pastille — une cible de 48 px se vise avec un pouce, une
   pastille de 26 px non. Le libellé « Voir la fiche » est écrit à droite : une ligne qui ne
   dit pas qu'elle s'appuie ne s'appuie jamais. */
.liste-exercices {
  margin-top: var(--espace-8);
  border-top: 1px solid var(--bordure);
}

.lien-exercice {
  display: flex;
  align-items: center;
  gap: var(--espace-12);
  width: 100%;
  min-height: var(--cible-tactile);
  padding: var(--espace-8) 0;
  border-bottom: 1px solid var(--bordure);
  color: var(--texte);
  text-align: left;
  font-size: var(--taille-4);
  font-weight: var(--graisse-4);
}

.lien-exercice__action {
  flex: none;
  color: var(--accent);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

.lien-exercice__chevron {
  flex: none;
  color: var(--accent);
}

/* « Tous les exercices » : la porte de la bibliothèque, sous les trois lignes du programme. */
.lien-exercice--tous {
  font-size: var(--taille-5);
}

/* Écran court (375 × 667 et moins) : le GO doit tenir au premier écran, au-dessus de la nav.
   La carte perd l'accroche du coach et les trois lignes du programme ; il lui reste la porte
   de la bibliothèque, où les sept fiches sont toutes (mesuré : GO à 585 px pour une nav à 607).
   « et 4 de plus » n'a plus de sens sans les lignes au-dessus : il s'efface (visibility garde la
   place qui pousse « Tous les exercices » à droite, et sort le texte de l'arbre d'accessibilité). */
@media (max-height: 740px) {
  .ecran--accueil .lien-exercice__reste {
    visibility: hidden;
  }
  .ecran--accueil .carte > .t4,
  .ecran--accueil .carte .section > .t5,
  .ecran--accueil .carte .liste-exercices {
    display: none;
  }
  .ecran--accueil .lien-exercice--tous {
    border-top: 1px solid var(--bordure);
  }
}

/* Bibliothèque (src/ui/ecrans/bibliotheque.js) : une ligne par exercice, sa pose clé à gauche. */
.bibliotheque {
  margin-top: 0;
}

.bibliotheque__ligne {
  gap: var(--espace-16);
  padding: var(--espace-12) 0;
}

.bibliotheque__vignette {
  position: relative;
  flex: none;
  width: var(--vignette-exercice);
  aspect-ratio: 400 / 380;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-m);
  background: var(--perso-scene);
  overflow: hidden;
}

.bibliotheque__texte {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
}

.bibliotheque__nom {
  font-size: var(--taille-4);
  font-weight: var(--graisse-5);
}

/* Réglages › Tes données : le lien vers la confidentialité, libellé sur son aide. */
.lien-reglage__texte {
  display: flex;
  flex-direction: column;
  gap: var(--espace-4);
}

/* Confidentialité (src/ui/ecrans/confidentialite.js) : une carte par question, le texte entier. */
.confidentialite__section > * + * {
  margin-top: var(--espace-8);
}

/* Progression › Dernières séances : la date à gauche, la durée et le coach alignés à droite. */
.historique__ligne {
  display: flex;
  align-items: baseline;
  gap: var(--espace-12);
  padding: var(--espace-8) 0;
  border-bottom: 1px solid var(--bordure);
}

.historique__ligne:last-child {
  border-bottom: 0;
}

/* ---------- 5. Navigation basse ---------- */

.nav {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--plan-nav);
  display: flex;
  justify-content: space-around;
  align-items: stretch;
  height: calc(var(--hauteur-nav) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--surface);
  border-top: 1px solid var(--bordure);
}

.nav__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: var(--cible-tactile);
  color: var(--texte-doux);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

/* L'onglet actif se lit par la couleur ET par la graisse : la couleur seule
   ne suffit jamais à porter une information. */
.nav__item[aria-current="page"] {
  color: var(--accent);
  font-weight: 700;
}

@media (min-width: 1024px) {
  .nav {
    inset: 0 auto 0 0;
    flex-direction: column;
    justify-content: flex-start;
    gap: var(--espace-8);
    width: 88px;
    height: 100dvh;
    padding: var(--espace-24) 0;
    border-top: 0;
    border-right: 1px solid var(--bordure);
  }

  .nav__item {
    flex: none;
    height: 64px;
  }
}

/* ---------- 6. Chronomètre circulaire ---------- */

.chrono {
  position: relative;
  width: var(--diametre-chrono);
  height: var(--diametre-chrono);
  margin: 0 auto;
}

.chrono__svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg); /* le zéro est en haut */
}

.chrono__piste {
  fill: none;
  stroke: var(--piste);
  stroke-width: var(--epaisseur-anneau);
}

.chrono__arc {
  fill: none;
  stroke: var(--accent);
  stroke-width: var(--epaisseur-anneau);
  stroke-linecap: round;
}

.chrono--repos .chrono__arc {
  stroke: var(--succes);
}

.chrono__centre {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--espace-4);
  text-align: center;
}

.chrono__valeur {
  font-size: var(--taille-chrono);
  font-weight: var(--graisse-1);
  line-height: 1;
  letter-spacing: var(--lettre-1);
  font-variation-settings: "opsz" var(--opsz-1);
}

.chrono__legende {
  color: var(--texte-doux);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

/* ---------- 7. Barre de progression de la séance ---------- */

.barre {
  height: 8px;
  border-radius: var(--rayon-rond);
  background: var(--piste);
  overflow: hidden;
}

.barre__remplissage {
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: var(--accent);
  transform-origin: left center;
}

/* ---------- 8. Compte à rebours 3-2-1 ---------- */
/* ⚠️ Cette surcouche couvre l'écran entier. Elle doit disparaître par
   `hidden` (ou être retirée du DOM), jamais par `opacity: 0` : une couche
   transparente laissée en place avale tous les taps et l'app paraît figée. */

.compte {
  position: fixed;
  inset: 0;
  z-index: var(--plan-compte);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--espace-16);
  background: var(--fond);
  text-align: center;
}

.compte__chiffre {
  font-size: var(--taille-compte);
  font-weight: var(--graisse-1);
  line-height: 1;
  letter-spacing: var(--lettre-1);
  font-variation-settings: "opsz" var(--opsz-1);
  color: var(--accent);
}

.compte__exercice {
  font-size: var(--taille-3);
  font-weight: var(--graisse-3);
  color: var(--texte-doux);
}

/* ---------- 9. Exercice en cours ---------- */

.exercice {
  text-align: center;
}

.exercice__nom {
  font-size: var(--taille-2);
  font-weight: var(--graisse-2);
  line-height: var(--ligne-2);
  letter-spacing: var(--lettre-2);
  font-variation-settings: "opsz" var(--opsz-2);
}

.exercice__consigne {
  color: var(--texte-doux);
  font-size: var(--taille-4);
  margin-top: var(--espace-8);
}

.exercice__rang {
  color: var(--texte-doux);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

.commandes {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-24);
  margin-top: var(--espace-32);
}

/* ---------- 10. Portrait de coach ---------- */

.portrait {
  position: relative;
  width: var(--diametre-portrait);
  height: var(--diametre-portrait);
  flex: none;
  border-radius: var(--rayon-rond);
  overflow: hidden;
  background: var(--pression);
  display: flex;
  align-items: center;
  justify-content: center;
}

.portrait--grand {
  width: 96px;
  height: 96px;
}

.portrait__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Repli quand l'image du coach n'est pas là : son initiale, jamais un vide. */
.portrait__initiale {
  font-size: var(--taille-3);
  font-weight: 700;
  color: var(--texte-doux);
}

/* ---------- 11. Carte de coach ---------- */

.carte-coach {
  display: flex;
  align-items: center;
  gap: var(--espace-16);
  width: 100%;
  text-align: left;
  padding: var(--espace-16);
  border-radius: var(--rayon-carte);
  background: var(--surface);
  border: 2px solid transparent;
  box-shadow: var(--ombre-carte);
}

/* Le coach choisi porte une bordure ET une coche : deux indices, pas un. */
.carte-coach[aria-pressed="true"] {
  border-color: var(--accent);
}

.carte-coach__coche {
  color: var(--accent);
}

.carte-coach[aria-pressed="false"] .carte-coach__coche {
  visibility: hidden;
}

.carte-coach__nom {
  font-size: var(--taille-3);
  font-weight: var(--graisse-3);
}

.carte-coach__detail {
  color: var(--texte-doux);
  font-size: var(--taille-5);
}

/* ---------- 12. Série (jours consécutifs) ---------- */

.serie {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  color: var(--serie);
  font-weight: 700;
}

.serie__nombre {
  font-variant-numeric: var(--chiffres);
  font-size: var(--taille-3);
}

.serie__libelle {
  color: var(--texte-doux);
  font-weight: var(--graisse-5);
  font-size: var(--taille-5);
}

/* ---------- 13. Semaine en pastilles ---------- */

.pastilles {
  display: flex;
  justify-content: space-between;
  gap: var(--espace-8);
}

.pastille {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--espace-8);
  font-size: var(--taille-5);
  color: var(--texte-doux);
}

.pastille__disque {
  width: 32px;
  height: 32px;
  border-radius: var(--rayon-rond);
  background: var(--pastille-vide);
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
}

/* Jour fait : disque plein + coche. Un daltonien voit la coche. */
.pastille--faite .pastille__disque {
  background: var(--succes);
  color: var(--sur-succes);
}

.pastille--aujourdhui .pastille__disque {
  box-shadow: 0 0 0 2px var(--accent);
}

/* ---------- 14. Bilan de fin de séance ---------- */

.bilan {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--espace-12);
  text-align: center;
}

.bilan__valeur {
  font-size: var(--taille-2);
  font-weight: var(--graisse-2);
  font-variant-numeric: var(--chiffres);
  line-height: var(--ligne-2);
}

.bilan__libelle {
  color: var(--texte-doux);
  font-size: var(--taille-5);
}

/* ---------- 15. Lignes de réglage ---------- */

.ligne-reglage {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-16);
  width: 100%;
  min-height: 56px;
  padding: var(--espace-8) 0;
  border-top: 1px solid var(--bordure);
  text-align: left;
}

.ligne-reglage:first-of-type {
  border-top: 0;
}

.ligne-reglage__libelle {
  font-weight: 600;
}

.ligne-reglage__aide {
  color: var(--texte-doux);
  font-size: var(--taille-5);
}

/* Interrupteur : la position du curseur porte l'information, pas la couleur.
   La piste visible fait 52 x 32, mais la zone touchable fait 52 x --cible-tactile
   (48 aujourd'hui) — la piste est dessinée en `::before`, pas sur l'élément lui-même.
   Piste et curseur se CENTRENT par calcul sur le jeton : écrits en `top` fixe, ils
   étaient centrés à 44 et décalés de 2 px à 48, sans qu'aucun test ne le voie. */
.bascule {
  position: relative;
  flex: none;
  width: 52px;
  height: var(--cible-tactile);
  background: none;
  border: 0;
  border-radius: var(--rayon-rond);
}

.bascule::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: calc((var(--cible-tactile) - 32px) / 2);
  height: 32px;
  border-radius: var(--rayon-rond);
  background: var(--piste);
  border: 2px solid var(--bordure);
}

.bascule::after {
  content: "";
  position: absolute;
  top: calc((var(--cible-tactile) - 24px) / 2);
  left: 4px;
  width: 24px;
  height: 24px;
  border-radius: var(--rayon-rond);
  background: var(--surface-haute);
  box-shadow: var(--ombre-flottante);
}

.bascule[aria-checked="true"]::before {
  background: var(--succes);
  border-color: var(--succes);
}

.bascule[aria-checked="true"]::after {
  left: auto;
  right: 4px;
}

/* Choix segmenté — langue, récupération (Réglages), durée (Accueil) : des boutons `aria-pressed`,
   celui qui est actif est marqué. */
.choix-langue,
.choix {
  display: inline-flex;
  gap: var(--espace-4);
  padding: var(--espace-4);
  border-radius: var(--rayon-rond);
  background: var(--pression);
}

.choix-langue__option,
.choix__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cible-tactile);
  padding: 0 var(--espace-16);
  border-radius: var(--rayon-rond);
  font-weight: 600;
  color: var(--texte-doux);
}

.choix-langue__option[aria-pressed="true"],
.choix__option[aria-pressed="true"] {
  background: var(--surface-haute);
  color: var(--texte);
  box-shadow: var(--ombre-carte);
}

/* Pleine largeur : les options se partagent la ligne (la durée, juste sous le GO). */
.choix--large {
  display: flex;
}

.choix--large .choix__option {
  flex: 1;
}

/* ---------- 16. Voile et feuille ---------- */

.voile {
  position: fixed;
  inset: 0;
  z-index: var(--plan-voile);
  background: var(--voile);
}

.feuille {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--plan-feuille);
  max-height: 86dvh;
  overflow: auto;
  padding: var(--espace-24) var(--marge-ecran)
    calc(var(--espace-32) + env(safe-area-inset-bottom, 0px));
  border-radius: var(--rayon-carte) var(--rayon-carte) 0 0;
  background: var(--surface-haute);
  box-shadow: var(--ombre-flottante);
}

/* La feuille elle-même reçoit le focus en dernier recours : pas de contour pour ça, le voile
   dit déjà où l'on est. Les boutons qu'elle contient gardent le leur. */
.feuille:focus-visible {
  outline: none;
  box-shadow: var(--ombre-flottante);
}

.feuille__entete {
  margin-bottom: var(--espace-8);
}

/* Choix du coach depuis la fiche d'exercice : la même carte que l'onglet Coachs, dans une
   feuille. Deux listes de coachs qui ne se ressemblent pas seraient deux produits. */
.feuille-coach {
  max-width: var(--largeur-colonne);
  margin-inline: auto;
}

/* Questions courtes posées en feuille (quitter la séance, mise en garde avant la première) :
   la même colonne que leurs jumelles, et de l'air entre la question et les réponses. */
.feuille-question {
  max-width: var(--largeur-colonne);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: var(--espace-16);
}

/* ---------- 17. Mentions ---------- */

/* Mention obligatoire : les quatre coachs sont des personnages fictifs
   produits par intelligence artificielle. Elle apparaît sur l'écran Coachs
   et dans À propos ; elle n'est ni masquable ni réductible. */
.mention-ia {
  display: flex;
  gap: var(--espace-8);
  padding: var(--espace-12) var(--espace-16);
  border-radius: var(--rayon-m);
  background: var(--pression);
  color: var(--texte-doux);
  font-size: var(--taille-5);
  line-height: var(--ligne-5);
}

/* Le lien vers LICENCES-TIERS.txt (À propos) : un lien seul sur sa ligne, donc une vraie cible
   tactile, pas la hauteur d'une ligne de texte. */
.lien-licences {
  display: inline-flex;
  align-items: center;
  min-height: var(--cible-tactile);
}

.etat-vide {
  padding: var(--espace-32) var(--espace-16);
  text-align: center;
  color: var(--texte-doux);
}

/* ---------- 18. Fiche d'exercice ---------- */
/* Sur une fiche d'exercice, le MOUVEMENT est l'élément le plus fort de l'écran.
   En une colonne (téléphone), le bloc prend toute la largeur que la hauteur de
   l'écran autorise ; en deux colonnes (≥ 768 px), il prend sa taille réelle à
   gauche et les mots passent à droite. L'arbitrage de hauteur du téléphone
   (664 px) est écrit en tête de `src/ui/fiche.js` — il ne se déduit pas d'ici. */

.fiche__barre {
  min-height: var(--cible-tactile);
}

/* Pastille du coach, à droite de la barre du haut (apercu/gabarit.html:338). Elle montre QUI
   guide — portrait et nom — et dit ce qu'elle fait : « Changer ». Sans ce mot, une pastille
   ronde ressemble à une décoration. */
.chip-coach {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  min-height: var(--cible-tactile);
  padding: var(--espace-4) var(--espace-12) var(--espace-4) var(--espace-4);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-rond);
  background: var(--surface);
  color: var(--texte);
  max-width: 62%;
}

/* Le portrait est réduit dans la pastille : à son diamètre courant, la barre du haut passait de
   44 à 58 px de haut, et ces 14 px se prenaient directement sur le clip, plus bas. */
.chip-coach__portrait {
  display: flex;
  flex: none;
}

.chip-coach__portrait .portrait {
  width: 32px;
  height: 32px;
}

.chip-coach__nom {
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chip-coach__action {
  flex: none;
  color: var(--accent);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

.fiche__entete > * + * {
  margin-top: var(--espace-8);
}

.fiche__puces {
  gap: var(--espace-8);
}

.fiche__consigne {
  color: var(--texte-doux);
  font-size: var(--taille-4);
}

/* Emplacement vidéo 9:16. Le bloc prend TOUTE la largeur de sa colonne ; c'est un
   plafond de HAUTEUR qui le retient, jamais un plafond de largeur arbitraire.
   Ce plafond arrive par `--fiche-media-h`, posé par le JS (voir `fiche.js`) : la
   largeur maximale s'en déduit par le ratio, si bien que le 9:16 est TOUJOURS
   exact — un `max-height` posé directement écraserait la boîte hors ratio. */
/* Le cadre, puis le bouton qui descend aux consignes : cette gouttière de 12 px est comptée
   dans `RESERVE_SOUS_MEDIA` (src/ui/fiche.js). La changer ici sans la changer là-bas fait
   passer le bouton derrière la barre de navigation. */
.fiche__media {
  display: flex;
  flex-direction: column;
  gap: var(--espace-12);
}

/* « Voir comment faire » — le seul geste sous le clip, visible sans défiler. Le chevron
   pivote vers le bas : la page continue par là.
   La règle est portée par le BOUTON, qui a une icône et une seule (`src/ui/fiche.js`).
   Elle l'était par `.fiche__suite-fleche`, posée sur le chevron ; `.fiche__suite`, elle,
   n'avait aucune règle en face — une classe qui laisse croire à un style qui n'existe pas.
   Une classe, une règle, un endroit où régler ce bouton. */
.fiche__suite .icone {
  transform: rotate(90deg);
}

/* Cible du bouton : le titre ne colle pas au bord haut de la fenêtre après le défilement. */
.fiche__comment {
  scroll-margin-top: var(--espace-16);
}

.fiche__cadre {
  width: 100%;
  max-width: calc(var(--fiche-media-h, 560px) * 9 / 16);
  aspect-ratio: 9 / 16;
  margin-inline: auto;
  display: grid;
  place-items: center;
  padding: var(--espace-12);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-carte);
  background: var(--surface-haute);
  overflow: hidden;
}

/* État vide assumé : il dit ce qui manque et pourquoi la place est réservée.
   Ce n'est pas une zone cassée, c'est un emplacement qui attend son clip.
   Il occupe EXACTEMENT le gabarit du clip : le jour où la vidéo arrive, la mise
   en page ne bouge pas d'un pixel. */
.fiche__vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--espace-8);
  text-align: center;
  color: var(--texte-doux);
}

/* Le cadre 9:16 reste étroit sur un écran court (186 px sur un téléphone de
   664 px de haut) : un titre à la taille des cartes s'y couperait en trois lignes.
   TAILLE ET INTERLIGNE SEULEMENT — la couleur et la graisse s'HÉRITENT de
   `.fiche__vide` (2026-09-17). Elles étaient forcées ici à `--texte` et
   `--graisse-3` : dans l'élément que la charte désigne comme le plus fort de
   l'écran, le texte le plus appuyé devenait l'annonce que le contenu manque —
   18,50 de contraste pour « La vidéo arrive bientôt. » contre 6,77 pour la
   consigne du geste, qui est le vrai contenu. Un état vide se tait. */
.fiche__vide-titre {
  font-size: var(--taille-4);
  line-height: var(--ligne-3);
}

/* Le clip et ses commandes, DANS le cadre : la réserve de hauteur sous le clip ne change pas.
   Fonds pleins (`--surface-haute`, `--accent`) : ce n'est jamais l'image qui décide du contraste. */
.fiche__cadre {
  position: relative;
}

.fiche__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fiche__commandes {
  position: absolute;
  inset: var(--espace-8) var(--espace-8) auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-8);
}

.fiche__commandes--bas {
  inset: auto var(--espace-8) var(--espace-8);
}

.fiche__vues {
  display: flex;
  gap: var(--espace-4);
  margin-inline-start: auto;
}

.fiche__cmd,
.fiche__demo {
  background: var(--surface-haute);
  color: var(--texte);
}

.fiche__cmd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--cible-tactile);
  min-height: var(--cible-tactile);
  padding: 0 var(--espace-12);
  border-radius: var(--rayon-rond);
  font-weight: 600;
}

.fiche__cmd[aria-pressed="true"],
.fiche__lire {
  background: var(--accent);
  color: var(--sur-accent);
}

/* LE PERSONNAGE ANIMÉ, quand l'exercice n'a pas de clip (src/ui/personnage.js,
   docs/prototypes/personnages-phase2.md). CADRE B : aux proportions de la scène dessinée
   (400 × 380), pas au 9:16 d'un clip vertical — un personnage de profil dans un cadre de
   téléphone debout laisse deux tiers de vide au-dessus de sa tête. Le plafond de hauteur
   reste celui que pose `ajuster()` ; seul le ratio qui en tire la largeur change. */
.fiche__cadre--perso {
  max-width: calc(var(--fiche-media-h, 560px) * 400 / 380);
  aspect-ratio: 400 / 380;
  padding: 0;
  background: var(--perso-scene);
}

/* La tenue suit le coach choisi. Tahina par défaut : un coach inconnu retombe sur lui côté
   JS, et le CSS dit la même chose. */
.perso {
  --perso-t0: var(--perso-tahina-0);
  --perso-t1: var(--perso-tahina-1);
  --perso-t2: var(--perso-tahina-2);
  --perso-tl0: var(--perso-tahina-l0);
  --perso-tl1: var(--perso-tahina-l1);
  position: absolute;
  inset: 0;
}

.perso[data-coach="marc"] {
  --perso-t0: var(--perso-marc-0);
  --perso-t1: var(--perso-marc-1);
  --perso-t2: var(--perso-marc-2);
  --perso-tl0: var(--perso-marc-l0);
  --perso-tl1: var(--perso-marc-l1);
}

.perso[data-coach="aicha"] {
  --perso-t0: var(--perso-aicha-0);
  --perso-t1: var(--perso-aicha-1);
  --perso-t2: var(--perso-aicha-2);
  --perso-tl0: var(--perso-aicha-l0);
  --perso-tl1: var(--perso-aicha-l1);
}

.perso[data-coach="liam"] {
  --perso-t0: var(--perso-liam-0);
  --perso-t1: var(--perso-liam-1);
  --perso-t2: var(--perso-liam-2);
  --perso-tl0: var(--perso-liam-l0);
  --perso-tl1: var(--perso-liam-l1);
}

.perso__scene {
  display: block;
  width: 100%;
  height: 100%;
}

/* Le bandeau du haut : le souffle en pastille, la phase du geste à côté. Il double ce que
   la carte « Comment faire » dit déjà en toutes lettres : `aria-hidden` côté JS, et aucun
   clic à capter ici. Fonds pleins, annotés dans tokens.css (§ 3 bis). */
.perso__bandeau {
  position: absolute;
  inset: var(--espace-8) var(--espace-8) auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-8);
  pointer-events: none;
}

.perso__souffle {
  padding: var(--espace-4) var(--espace-12);
  border-radius: var(--rayon-rond);
  font-size: var(--taille-5);
  line-height: var(--ligne-5);
  font-weight: var(--graisse-3);
  background: var(--perso-respire-fond);
  color: var(--perso-respire-texte);
}

.perso__souffle[data-etat="inspire"] {
  background: var(--perso-inspire-fond);
  color: var(--perso-inspire-texte);
}

.perso__souffle[data-etat="expire"] {
  background: var(--perso-expire-fond);
  color: var(--perso-expire-texte);
}

.perso__souffle[data-etat="rythme"] {
  background: var(--perso-rythme-fond);
  color: var(--perso-rythme-texte);
}

.perso__phase {
  font-size: var(--taille-5);
  line-height: var(--ligne-5);
  font-weight: var(--graisse-3);
  color: var(--texte);
}

.fiche__titre {
  margin-bottom: var(--espace-12);
}

.fiche__aide {
  margin-top: var(--espace-12);
}

/* Étapes numérotées : le rang est un repère visuel, il est `aria-hidden` —
   une liste ordonnée se compte déjà toute seule pour un lecteur d'écran. */
.etapes {
  display: flex;
  flex-direction: column;
  gap: var(--espace-12);
}

.etapes__item {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-12);
}

.etapes__rang {
  flex: none;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--rayon-rond);
  background: var(--pression);
  font-size: var(--taille-5);
  font-weight: 700;
}

/* Une icône, une phrase : erreur fréquente, respiration. */
.bloc-court {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-12);
}

.bloc-court__icone {
  color: var(--accent);
  margin-top: 3px;
}

/* Carte des muscles — le SVG est inliné, il hérite donc des variables du thème.
   Les rôles sont des classes posées sur les `<g>` de assets/muscles.svg. */
.fiche__dessin {
  padding: var(--espace-8) 0;
}

.muscles__corps {
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
}

.muscles__corps .silhouette {
  fill: var(--silhouette);
}

.muscles__corps .muscle {
  fill: var(--muscle-repos);
  stroke: var(--fond);
  stroke-width: 0.6;
}

.muscles__corps .muscle.primaire {
  fill: var(--accent);
}

.muscles__corps .muscle.secondaire {
  fill: var(--muscle-secondaire);
}

/* Un nom appuyé isole son muscle : les autres s'effacent, aucun ne disparaît. */
.muscles__corps.montre .muscle:not(.surligne) {
  opacity: 0.25;
}

.legende {
  display: flex;
  flex-direction: column;
  gap: var(--espace-12);
  margin-top: var(--espace-12);
}

.legende__rangee {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-8);
  margin-top: var(--espace-4);
}

/* Le rôle d'un muscle est ÉCRIT dans le titre de son groupe : la pastille
   colorée ne fait que rappeler ce que le texte a déjà dit. */
.legende__item {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-8);
  min-height: var(--cible-tactile);
  padding: 0 var(--espace-12);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-rond);
  background: var(--surface);
  font-size: var(--taille-5);
  font-weight: var(--graisse-5);
}

.legende__item[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 700;
}

.legende__pastille {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: var(--rayon-rond);
}

.legende__pastille--primaire {
  background: var(--accent);
}

.legende__pastille--secondaire {
  background: var(--muscle-secondaire);
}

.legende__tout {
  align-self: flex-start;
  min-height: var(--cible-tactile);
}

/* Accès à la fiche pendant le repos d'une séance. */
.seance__fiche {
  margin-top: var(--espace-12);
  min-height: var(--cible-tactile);
}

/* LE PERSONNAGE PENDANT LA SÉANCE (src/ui/ecrans/seance.js, phase 2b). L'écran devient une
   colonne à la hauteur de la fenêtre : le personnage prend ce qui reste entre la consigne et
   le chrono, plafonné, et les commandes ne passent jamais sous le bord. Pas d'`overflow` sur
   l'écran : il couperait l'ombre des boutons ronds. */
.ecran--seance {
  display: flex;
  flex-direction: column;
  height: calc(100dvh - env(safe-area-inset-top, 0px));
  padding-bottom: calc(var(--espace-16) + env(safe-area-inset-bottom, 0px));
}

.ecran--seance > * {
  flex: none;
}

.seance__perso {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  max-height: var(--perso-seance-max);
  margin-bottom: var(--espace-12); /* le chrono n'a pas de marge haute à lui */
  container-type: size;
}

/* La scène garde les proportions de son dessin (400 × 380), à la hauteur qu'on lui laisse. */
.seance__perso > .perso {
  position: relative;
  inset: auto;
  height: 100%;
  max-width: 100%;
  aspect-ratio: 400 / 380;
  margin-inline: auto;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-carte);
  background: var(--perso-scene);
  overflow: hidden;
}

/* À cette taille, la phase du geste écrite en toutes lettres touche la tête (mesuré à 213 px) :
   la séance ne garde que la pastille du souffle, la consigne est juste au-dessus. */
.seance__perso .perso__phase {
  display: none;
}

/* Trop court même pour la pastille : elle couvrirait le dessin. */
@container (max-height: 159px) {
  .seance__perso .perso__bandeau {
    display: none;
  }
}

/* Trop court pour qu'on reconnaisse le geste : rien plutôt qu'un timbre-poste. */
@container (max-height: 79px) {
  .seance__perso > .perso {
    display: none;
  }
}

/* Écran court (375 × 667 et moins) : le chrono rétrécit pour laisser voir le geste. */
@media (max-height: 740px) {
  .ecran--seance {
    --diametre-chrono: var(--diametre-chrono-court);
  }

  .ecran--seance > .commandes {
    margin-top: var(--espace-16);
  }
}

/* La fiche en feuille : barre et pied fixes, contenu qui défile entre les deux.
   Le bouton « Reprendre la séance » reste donc visible quoi qu'on lise. */
.fiche-feuille {
  display: flex;
  flex-direction: column;
  gap: var(--espace-12);
  max-height: 88dvh;
  padding-top: var(--espace-12);
  overflow: hidden;
  /* Meme bride que `.feuille-coach` : sans elle, cette feuille etait la seule
     surface de l'app a depasser `--largeur-max` sur bureau (1216 px de bord a
     bord, contre 1120 pour l'ecran plein et 560 pour sa jumelle). Deux feuilles
     qui ne se ressemblent pas seraient deux produits (2026-09-17). */
  max-width: var(--largeur-colonne);
  margin-inline: auto;
}

.fiche-feuille__barre,
.fiche-feuille__pied {
  flex: none;
}

.fiche-feuille__corps {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* Deux colonnes dès 768 px : le geste à gauche, les mots à droite.
   En une seule colonne, un bloc 9:16 posé au milieu d'une bande de 1 120 px se lit
   comme une vignette perdue, pendant que « Comment faire » prend toute la largeur —
   la hiérarchie d'une fiche d'exercice est alors inversée.

   LA RÈGLE NE VISE QUE L'ÉCRAN PLEIN (`.ecran--exercice`), jamais la feuille du
   repos : celle-là n'a pas d'emplacement vidéo, deux colonnes y laisseraient une
   colonne vide de 380 px.

   CE QU'ON NE TROUVERA PAS ICI : la disparition du bouton « Voir comment faire ».
   Elle se décide dans `src/ui/fiche.js` (`ajuster()`), pas ici, et ce n'est pas un
   oubli. Le bouton ne doit tomber que là où la carte « Comment faire » se lit déjà
   en entier sans défiler — ce qui dépend de la HAUTEUR de la fenêtre et de la
   longueur du texte, deux choses qu'une media query ne connaît pas. Mesuré :
   à 768 × 600 les deux colonnes existent et la carte finit 89 px SOUS le pli (le
   bouton y reste), et le bas de cette carte va de 604 à 678 px selon l'exercice et
   la langue. Un `display: none` posé ici sur la seule largeur ouvrirait ce trou ;
   la garde e2e « MENSONGE » (tests/e2e/fiche.spec.mjs) échoue si on l'essaie. */
@media (min-width: 768px) {
  /* La colonne de lecture de 560 px ne peut pas porter deux colonnes : la fiche
     prend la largeur maximale du studio, comme les écrans larges au-delà de 1024. */
  .ecran--exercice {
    max-width: var(--largeur-max);
  }

  .ecran--exercice .fiche {
    display: grid;
    grid-template-columns: minmax(0, 380px) minmax(320px, 1fr);
    grid-auto-rows: min-content;
    column-gap: var(--espace-32);
    row-gap: 0;
    align-content: start;
  }

  .ecran--exercice .fiche > * {
    grid-column: 2;
  }

  /* Le bloc du geste TRAVERSE toutes les lignes de la colonne de droite.
     S'il n'occupait que la première, cette ligne prendrait sa hauteur (676 px) et
     « Comment faire » commencerait sous un trou de sable — le défaut d'origine, retourné.
     `span 30` couvre largement les six sections d'une fiche ; les lignes excédentaires
     sont vides, donc hautes de zéro, et `row-gap: 0` garantit qu'elles n'ajoutent rien
     (l'espacement entre sections reste celui de `.pile`). */
  .ecran--exercice .fiche__media {
    grid-column: 1;
    grid-row: 1 / span 30;
    align-self: start;
    margin-top: 0;
    /* La LARGEUR de toute la colonne du geste, clip et bouton ensemble : la plus petite
       de la colonne (380 px) et de ce que la hauteur de fenêtre autorise. Elle est posée
       ici, au-dessus des deux, pour que le bouton fasse exactement la largeur du clip —
       un bouton plus large que l'image qu'il commente est un bouton qui flotte.
       Mesuré avant d'écrire cette ligne : sans elle, le bouton finissait à 831,5 px sur
       une fenêtre de 800, tranché en deux par le bas de l'écran. */
    width: min(100%, calc(var(--fiche-media-h, 560px) * 9 / 16));
    /* Le clip accompagne la lecture des consignes au lieu de sortir par le haut. Il ne
       peut coller que parce qu'il tient dans la fenêtre (ligne du dessus) : sinon il
       collerait un bas de bloc invisible. */
    position: sticky;
    top: var(--espace-16);
  }

  /* La largeur est déjà tenue par la colonne ci-dessus ; le cadre la remplit, et la
     hauteur suit le ratio. */
  .ecran--exercice .fiche__cadre {
    max-width: none;
  }

  /* Le personnage : même colonne, ratio de sa scène (400 × 380) au lieu du 9:16. */
  .ecran--exercice .fiche__media--perso {
    width: min(100%, calc(var(--fiche-media-h, 560px) * 400 / 380));
  }
}
