/* ---------------------------------------------------------------- boutons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: 44px;
  padding: 0 var(--s4);
  background: var(--acier-haut);
  color: var(--craie);
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  font: inherit;
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: 0.02em;
  cursor: pointer;
  /* un bouton reste un bouton quand c'est un lien : ni souligne, ni bleu. */
  text-decoration: none;
}

a.btn { color: var(--craie); }
a.btn--ghost { color: var(--craie-douce); }

.btn--p {
  background: var(--p25);
  border-color: var(--p25);
  color: var(--craie);
}

.btn--ghost {
  background: none;
  border-color: var(--filet);
  color: var(--craie-douce);
}

.btn--danger { color: var(--p25-txt); border-color: var(--p25); background: none; }
.btn--full   { width: 100%; }
.btn--sm     { min-height: 32px; padding: 0 var(--s3); font-size: var(--t-13); }

.btn:disabled { opacity: 0.4; cursor: not-allowed; }

.btns { display: flex; gap: var(--s2); flex-wrap: wrap; }

/* --------------------------------------------------------------- formulaire */

.fld { display: block; margin-bottom: var(--s3); }
.fld > .lab { display: block; margin-bottom: var(--s1); }

.fld input,
.fld select,
.fld textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--s2) var(--s3);
  background: var(--acier-haut);
  color: var(--craie);
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  font: inherit;
  font-variant-numeric: tabular-nums;
}

.fld textarea { min-height: 72px; resize: vertical; }

.fld__err {
  display: block;
  margin-top: var(--s1);
  font-size: var(--t-13);
  color: var(--p25-txt);
}

.fld--err input { border-color: var(--p25); }

.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }

/* Charge et repetitions cote a cote sur un telephone : le champ de saisie ne
   recoit que 63 px, or « 292,5 » en demande 84 (mesure a 390 px). Les fleches
   ne peuvent pas maigrir : 48 px est deja proche du plancher tactile de 44 px.
   On empile donc les deux compteurs, comme le fait deja le mode focus, plutot
   que de rogner le seul chiffre qu'on lit au milieu d'une serie. */
@media (max-width: 440px) {
  .pied .grid2 { grid-template-columns: minmax(0, 1fr); }
}

/* Stepper : les fleches avancent par increment reellement disponible sur le
   materiel (cran de pile, paire d'halteres), jamais par 1 kg arbitraire. */
.stepper {
  display: grid;
  /* minmax(0, 1fr) : la largeur intrinseque d'un input (env. 300 px) elargirait
     sinon le stepper bien au-dela de sa colonne. */
  grid-template-columns: 48px minmax(0, 1fr) 48px;
  align-items: stretch;
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  overflow: hidden;
  background: var(--acier-haut);
}

.stepper button {
  background: none;
  border: 0;
  color: var(--craie);
  font-size: var(--t-24);
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.stepper button:first-child { border-right: 1px solid var(--filet); }
.stepper button:last-child  { border-left: 1px solid var(--filet); }

.stepper input {
  width: 100%;
  min-width: 0;
  min-height: 52px;
  border: 0;
  border-radius: 0;
  text-align: center;
  font-size: var(--t-24);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: none;
  color: var(--craie);
  font-family: inherit;
}

.stepper__u {
  display: block;
  text-align: center;
  font-size: var(--t-11);
  color: var(--craie-douce);
}

/* Controle segmente */
.seg {
  display: inline-flex;
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  overflow: hidden;
}
.seg button {
  min-height: 36px;
  padding: 0 var(--s3);
  background: none;
  border: 0;
  border-right: 1px solid var(--filet);
  color: var(--craie-douce);
  font: inherit;
  font-size: var(--t-13);
  font-weight: 600;
  cursor: pointer;
}
.seg button:last-child { border-right: 0; }
.seg button[aria-pressed="true"] { background: var(--acier-haut); color: var(--craie); }

/* ---------------------------------------------------------- jetons, pastilles */

/* Le groupe musculaire est code par un filet de couleur, pas par du texte
   colore : le texte reste en --craie, donc le contraste reste conforme. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: 3px var(--s2) 3px var(--s2);
  border: 1px solid var(--filet);
  border-left-width: 3px;
  border-radius: var(--r-1);
  font-size: var(--t-11);
  font-weight: 600;
  font-stretch: 108%;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--craie);
  white-space: nowrap;
}
.chip--jambes { border-left-color: var(--p25); }
.chip--dos    { border-left-color: var(--p20); }
.chip--pecs   { border-left-color: var(--p15); }
.chip--epaule { border-left-color: var(--p10); }
.chip--bras   { border-left-color: var(--craie-douce); }
.chip--tri    { border-left-color: var(--filet-fort); }

.tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: var(--r-1);
  font-size: var(--t-11);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.tag--pr      { background: var(--p25); color: var(--craie); }
.tag--partiel { border: 1px solid var(--p15); color: var(--p15-txt); }
.tag--warm    { border: 1px solid var(--filet-fort); color: var(--craie-douce); }
.tag--todo    { background: var(--p15); color: var(--fonte); }
.tag--ok      { border: 1px solid var(--p10); color: var(--p10-txt); }

/* ------------------------------------------------------- feuille de series */

.ex {
  border: 1px solid var(--filet);
  border-radius: var(--r-2);
  background: var(--acier);
  margin-bottom: var(--s4);
  /* clip et non hidden : hidden ferait de la carte un conteneur de defilement,
     l'en-tete collant se caleraient alors a 49 px du haut de la carte et
     masquerait la premiere serie. */
  overflow: clip;
}

.ex__head {
  position: sticky;
  top: 49px;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--s3);
  background: var(--acier-haut);
  border-bottom: 1px solid var(--filet);
}

.ex__name {
  font-size: var(--t-18);
  font-weight: 700;
  font-stretch: 112%;
  letter-spacing: 0.01em;
}

.ex__target {
  font-size: var(--t-11);
  color: var(--craie-douce);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Le numero de serie est conserve parce que l'ordre des series EST une
   information. Aucune numerotation decorative ailleurs dans l'app. */
.set {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--filet);
}
.set:last-child { border-bottom: 0; }

.set__n {
  font-size: var(--t-13);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--craie-douce);
  text-align: right;
}

.set__load {
  font-size: var(--t-18);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.set__meta {
  font-size: var(--t-11);
  color: var(--craie-douce);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.set__mark {
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-1);
  color: var(--craie-douce);
  font-size: var(--t-13);
}

/* Le crayon d'une serie deja enregistree : cible de 44 px, mais discret. Il ne
   doit pas se confondre avec la pastille de validation .set__mark, qui dit un
   etat et ne se clique pas. */
.set__edit {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--r-1);
  color: var(--craie-douce);
  font-size: var(--t-15);
  cursor: pointer;
}
.set__edit:hover { border-color: var(--filet-fort); color: var(--craie); }

.set--done { background: color-mix(in srgb, var(--p20) 10%, transparent); }
.set--done .set__mark { background: var(--p20); border-color: var(--p20); color: var(--craie); }

.set--pr { box-shadow: inset 3px 0 0 var(--p25); }

.set--now {
  background: var(--acier-haut);
  box-shadow: inset 3px 0 0 var(--p15);
}

.set--ghost { opacity: 0.55; }

/* ------------------------------------- signature : colonne de charge a goupille */

/* Reprend la pile de la machine : un cran par increment disponible, la
   goupille pleine a la charge de travail, une goupille fantome au record
   precedent, et la zone parcourue depuis la premiere seance teintee.
   C'est l'element par lequel l'app se reconnait. */
.pile {
  display: grid;
  grid-template-columns: 44px 34px 1fr;
  align-items: end;
  gap: var(--s3);
}

.pile__col {
  display: flex;
  flex-direction: column-reverse;
  gap: 2px;
}

.cran {
  height: var(--pile-cran);
  border: 1px solid var(--filet);
  border-radius: 1px;
  background: var(--fonte);
}

.cran--done  { background: var(--filet); }            /* parcouru */
.cran--pin   { background: var(--p25); border-color: var(--p25); }   /* goupille */
.cran--ghost { border: 1px dashed var(--p15); background: none; }    /* record precedent */

.pile__axis {
  display: flex;
  flex-direction: column-reverse;
  gap: 2px;
  text-align: right;
}

.pile__t {
  height: var(--pile-cran);
  line-height: var(--pile-cran);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--craie-douce);
}
.pile__t--hi { color: var(--craie); font-weight: 700; }

.pile__leg { display: grid; gap: var(--s2); }
.pile__leg div { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-11); }
.pile__key { width: 14px; height: 10px; border: 1px solid var(--filet); }
.pile__key--pin   { background: var(--p25); border-color: var(--p25); }
.pile__key--ghost { border: 1px dashed var(--p15); }
.pile__key--done  { background: var(--filet); }

/* ------------------------------------------------------------- courbe SVG */

.chart { width: 100%; height: auto; display: block; }
.chart .axis   { stroke: var(--filet); stroke-width: 1; }
.chart .line   { fill: none; stroke: var(--p20-txt); stroke-width: 2; }
.chart .area   { fill: color-mix(in srgb, var(--p20) 14%, transparent); }
.chart .dot    { fill: var(--p20-txt); }
.chart .dot--pr{ fill: var(--p25); }
.chart .glab   { font-size: 9px; fill: var(--craie-douce); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------- grille de donnees */

/* `.tbl` est le conteneur qui defile, pas le tableau : un tableau large doit
   pouvoir glisser horizontalement sans emporter la page avec lui. */
.tbl, .tbl-wrap { overflow-x: auto; border: 1px solid var(--filet); border-radius: var(--r-2); }

.tbl table, table.tbl-wrap, .tbl-wrap table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-13);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tbl th {
  position: sticky;
  top: 0;
  background: var(--acier-haut);
  text-align: left;
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--filet-fort);
  font-size: var(--t-11);
  font-weight: 700;
  font-stretch: 110%;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--craie-douce);
}

.tbl td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--filet);
  background: var(--acier);
}

.tbl .n, .tbl .num, .tbl-wrap .n, .tbl-wrap .num { text-align: right; }
.tbl tr[aria-selected="true"] td { background: color-mix(in srgb, var(--p20) 14%, transparent); }
.tbl .cell-edit { box-shadow: inset 0 0 0 2px var(--p15); background: var(--acier-haut); }
.tbl .ro { color: var(--craie-douce); }

.selbar {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  padding: var(--s3);
  background: var(--acier-haut);
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  margin-bottom: var(--s3);
}
.selbar__n { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------ bandeaux et vides */

.banner {
  display: flex;
  gap: var(--s3);
  padding: var(--s3);
  border: 1px solid var(--filet-fort);
  border-left-width: 3px;
  border-radius: var(--r-2);
  background: var(--acier);
  margin-bottom: var(--s4);
  font-size: var(--t-13);
}
.banner--warn { border-left-color: var(--p15); }
.banner--info { border-left-color: var(--p20); }
.banner--ok   { border-left-color: var(--p10); }
.banner--stop { border-left-color: var(--p25); }

/* Un ecran vide est une invitation a agir, pas un constat. */
.empty {
  text-align: center;
  padding: var(--s7) var(--s4);
  border: 1px dashed var(--filet-fort);
  border-radius: var(--r-2);
}
.empty p { color: var(--craie-douce); margin: var(--s2) 0 var(--s4); }

/* ----------------------------------------------------------- feuille basse */

.sheet {
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2) var(--r-2) 0 0;
  background: var(--acier);
  padding: var(--s4);
  box-shadow: 0 -12px 32px var(--ombre);
}
.sheet__grip {
  width: 40px; height: 4px; border-radius: 2px;
  background: var(--filet-fort);
  margin: 0 auto var(--s3);
}

/* Grille de la feuille « Plus » : deux colonnes des 320 px, pour que les dix
   ecrans tiennent sans defilement sur un telephone. Lignes pleine largeur
   plutot que vignettes : le libelle est l'information, l'icone la confirme. */
.menu {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s2);
}

.menu__e {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: 48px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--filet);
  border-radius: var(--r-1);
  background: var(--acier-haut);
  color: var(--craie);
  text-decoration: none;
  font-size: var(--t-13);
  font-weight: 600;
}

.menu__e svg { width: 18px; height: 18px; color: var(--craie-douce); flex: none; }

/* L'ecran courant reste indique dans la feuille : on l'ouvre souvent depuis
   l'ecran lui-meme, pour aller ailleurs. */
.menu__e[aria-current="page"] { border-color: var(--p25); }
.menu__e[aria-current="page"] svg { color: var(--p25); }

/* ------------------------------------------------------------- minuteur */

/* Animation 1 sur 3 : la colonne se vide de haut en bas, comme une pile
   qu'on decharge. Les dix dernieres secondes passent en --p15. */
.timer { display: grid; grid-template-columns: 1fr 56px; gap: var(--s4); align-items: center; }

.timer__v {
  font-size: var(--t-56);
  font-weight: 700;
  font-stretch: 112%;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.02em;
}

.timer__drain {
  position: relative;
  height: 132px;
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-1);
  background: var(--acier-haut);
  overflow: hidden;
}
.timer__drain span {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 0;
  background: var(--p20);
}
.timer--soon .timer__drain span { background: var(--p15); }

/* Animation 2 sur 3 : la serie validee s'inscrit avec un depassement
   descendant de 4 px sur 120 ms, une plaque qui se pose. */
@keyframes settle {
  0%   { transform: translateY(-6px); opacity: 0; }
  70%  { transform: translateY(4px);  opacity: 1; }
  100% { transform: translateY(0); }
}
.set--settle { animation: settle 120ms ease-out; }

/* Animation 3 sur 3 : le filet de la ligne s'allume puis s'eteint sur
   400 ms quand un record tombe. Pas de confettis. */
@keyframes prflash {
  0%, 100% { box-shadow: inset 3px 0 0 var(--p25); }
  50%      { box-shadow: inset 3px 0 0 var(--p25), 0 0 0 1px var(--p25); }
}
.set--prflash { animation: prflash 400ms ease-in-out; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition: none !important; }
}

/* -------------------------------------------------------------- 900 px + */

@media (min-width: 900px) {
  .main { padding-bottom: var(--s7); }
  .two {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s5);
    align-items: start;
  }
  .ex__head { top: 49px; }
}

/* ============================================================ complements */
/* Classes utilisees par les vues et absentes de la feuille d'origine. Meme
   grammaire visuelle : filets, crans, tabulaire, aucun aplat decoratif. */

/* --- messages transitoires (ui.js message()) ------------------------------ */

#messages {
  position: fixed;
  left: 50%;
  bottom: calc(60px + var(--s4));
  transform: translateX(-50%);
  z-index: 40;
  display: grid;
  gap: var(--s2);
  width: min(520px, calc(100vw - 2 * var(--s4)));
  pointer-events: none;
}

.msg {
  pointer-events: auto;
  padding: var(--s3);
  border: 1px solid var(--filet-fort);
  border-left-width: 3px;
  border-radius: var(--r-2);
  background: var(--acier-haut);
  color: var(--craie);
  font-size: var(--t-13);
  box-shadow: 0 8px 24px var(--ombre);
  animation: msg-in 140ms ease-out;
}
.msg--info { border-left-color: var(--p20); }
.msg--ok   { border-left-color: var(--p10); }
.msg--warn { border-left-color: var(--p15); }
.msg--stop { border-left-color: var(--p25); }

/* La sortie est une transition, pas une disparition seche : 300 ms, la meme
   duree que le retrait du noeud dans ui.js. */
.msg--sort { opacity: 0; transform: translateY(6px); transition: opacity 300ms, transform 300ms; }

@keyframes msg-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* --- voile de la feuille modale ------------------------------------------ */

.voile {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: var(--voile);
  animation: voile-in 120ms ease-out;
}
.voile > .sheet {
  width: min(560px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  animation: sheet-in 160ms ease-out;
}
@keyframes voile-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheet-in { from { transform: translateY(16px); } to { transform: none; } }

/* --- bandeau de semaine (ecran Aujourd'hui) ------------------------------- */

.sem {
  display: block;
  text-align: center;
  padding: var(--s2) 0;
  border: 1px solid var(--filet);
  border-top-width: 3px;
  border-radius: var(--r-1);
  font-size: var(--t-11);
  letter-spacing: 0.04em;
  color: var(--craie-douce);
  text-decoration: none;
}
.sem b { display: block; font-size: var(--t-13); color: var(--craie); font-variant-numeric: tabular-nums; }
.sem--prevu { border-top-color: var(--p20); color: var(--craie); }
.sem--fait  { border-top-color: var(--p10); }
.sem--jour  { border-top-color: var(--p25); background: var(--acier-haut); color: var(--craie); }

/* --- liste du plan du jour ------------------------------------------------ */

.plan { display: grid; gap: 0; }
.plan__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s3);
  align-items: baseline;
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--filet);
}
.plan__row:last-child { border-bottom: 0; }
.plan__n { font-weight: 600; }
.plan__sub {
  font-size: var(--t-11);
  color: var(--craie-douce);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.plan__prop { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.plan__prop b { font-size: var(--t-18); }

/* --- champs cote a cote --------------------------------------------------- */

.fld-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
@media (max-width: 380px) { .fld-row { grid-template-columns: 1fr; } }

/* --- chiffre etiquete (stats3) -------------------------------------------- */

.stat__l {
  display: block;
  font-size: var(--t-11);
  font-weight: 600;
  font-stretch: 110%;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--craie-douce);
  margin-bottom: 2px;
}
.stat__v { display: block; }

/* --- etats de ligne et etiquettes ----------------------------------------- */

.tag--warn { border: 1px solid var(--p15); color: var(--p15-txt); }

/* Une ligne douteuse n'est pas rouge : elle porte un filet gauche, comme les
   bandeaux. Le rouge reste reserve a la destruction. */
.tbl .tr--warn td:first-child { box-shadow: inset 3px 0 0 var(--p15); }
.tbl .tr--off td { color: var(--craie-douce); }

/* ------------------------------------------------------------- utilitaires */
/* La politique de securite interdit l'attribut style : ces quelques classes
   remplacent les rares reglages d'espacement qui vivaient en ligne dans les
   vues. Elles restent volontairement peu nombreuses. */

.mt0 { margin: var(--s1) 0 0; }
.mt1 { margin-top: var(--s2); }
.mt2 { margin-top: var(--s3); }
.mt3 { margin-top: var(--s4); }
.mt4 { margin-top: var(--s5); }
.mb2 { margin-bottom: var(--s3); }
.mb3 { margin-bottom: var(--s4); }
.my2 { margin: var(--s3) 0; }
.my3 { margin: var(--s4) 0; }
.ml1 { margin-left: var(--s2); }
.m0  { margin: 0; }
.centre { text-align: center; }
.jc { justify-content: center; }
.craie { color: var(--craie); }

/* Un lien qui occupe toute la ligne d'une carte sans se signaler comme lien :
   la cible cliquable est la ligne, pas le mot souligne. */
.lien-plat { color: var(--craie); text-decoration: none; flex: 1; min-width: 0; }

/* Case a cocher et son libelle sur une meme ligne, cible de 44 px conservee. */
.coche { display: flex; gap: var(--s2); align-items: center; font-size: var(--t-13); }
.coche input { min-width: 22px; min-height: 22px; }

/* Bandeau de semaine : sept crans egaux. */
.semaine { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-bottom: var(--s4); }

/* Action principale d'un ecran : elle reste au-dessus de la barre de
   navigation pendant le defilement. Fond opaque, sinon la liste defile en
   transparence derriere le bouton et devient illisible. */
.go {
  position: sticky;
  bottom: 60px;
  padding: var(--s3) 0 var(--s2);
  background: var(--fonte);
  box-shadow: 0 -8px 16px -8px var(--ombre-forte);
  /* Au-dessus des en-tetes collants des cartes (.ex__head, z 10), sous la
     barre haute et la navigation (z 20) : sinon une carte recouvre le bouton. */
  z-index: 15;
}

.pied { padding: var(--s3); border-top: 1px solid var(--filet); }

/* Fin de seance : en bas de la liste, jamais collee au-dessus de la barre de
   navigation. Collee, elle etait touchee par erreur en visant la navigation ;
   la marge haute la separe du dernier exercice et du bouton d'ajout. */
.fin {
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid var(--filet);
}

/* Liste longue dans une feuille modale : elle defile dans la feuille, pas la
   page derriere. */
.defile { max-height: 46vh; overflow: auto; }

/* Ligne d'une liste de choix : un bouton qui ne se voit pas comme tel. */
.opt {
  width: 100%;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--filet);
  color: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 44px;
}
.opt:last-child { border-bottom: 0; }

/* ================================================= editeurs (chantier C) */

/* Texte reserve aux lecteurs d'ecran : libelle long d'une colonne abregee. */
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Donnees : grille et fiches (F13.1) ---------------------------------- */

/* La grille a besoin de largeur ; le conteneur de vue appartient au routeur,
   on l'elargit donc depuis son contenu, a partir de 900 px seulement. */
@media (min-width: 900px) {
  .main:has(> .donnees), .main:has(> .catalogue) { max-width: 1180px; }
}

.filtres { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s3); }
.filtres > .fld:nth-child(3) { grid-column: 1 / -1; }
@media (min-width: 900px) {
  .filtres { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .filtres > .fld:nth-child(3) { grid-column: auto; }
}
.filtres__coches { display: grid; gap: var(--s1); }
.filtres__coches .coche { min-height: 44px; }

.th-tri {
  background: none; border: 0; padding: 0; min-height: 32px;
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; cursor: pointer;
}
.th-tri:hover { color: var(--craie); }

/* Cellule editable : elle se reconnait au survol et au focus, pas par un
   ornement permanent qui chargerait 100 lignes de bruit. */
.grille td { height: 44px; }
.grille td.ed { cursor: text; }
.grille td.ed:hover { background: var(--acier-haut); }
.grille td.ed:focus-visible { outline: 2px solid var(--p20); outline-offset: -2px; }
.grille td.cell-edit { padding: 0 var(--s1); }
.grille td[aria-busy="true"] { color: var(--craie-douce); }
.grille td.cell--err { box-shadow: inset 0 0 0 2px var(--p25); }
.grille .cell-in {
  width: 100%; min-width: 72px; min-height: 36px; padding: 0 var(--s2);
  background: var(--acier-haut); color: var(--craie);
  border: 1px solid var(--filet-fort); border-radius: var(--r-1);
  font: inherit; font-variant-numeric: tabular-nums;
}
.grille td.num .cell-in { text-align: right; }
.grille select.cell-in { min-width: 140px; }
.grille td:first-child input,
.grille th:first-child input { min-width: 22px; min-height: 22px; }
/* Barre de lot du catalogue : libelle, groupe cible et bouton alignes sur leur base. */
.catalogue__lot { align-items: flex-end; }
.catalogue__lot .fld { margin-bottom: 0; min-width: 200px; }

.fiches { display: grid; gap: var(--s2); }
.fiche {
  background: var(--acier);
  border: 1px solid var(--filet);
  border-left-width: 3px;
  border-radius: var(--r-2);
  padding: var(--s3);
}
.fiche--sel  { border-left-color: var(--p20); background: color-mix(in srgb, var(--p20) 10%, transparent); }
.fiche--todo, .fiche--warn { border-left-color: var(--p15); }
.fiche__top { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.fiche__sel { display: flex; align-items: center; gap: var(--s2); min-height: 44px; min-width: 0; font-weight: 600; }
.fiche__sel input { min-width: 22px; min-height: 22px; flex: 0 0 auto; }
.fiche__ex { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fiche__id {
  display: block; margin-bottom: var(--s2);
  font-size: var(--t-11); color: var(--craie-douce); letter-spacing: 0.06em;
  text-transform: uppercase; font-variant-numeric: tabular-nums;
}
.fiche__g { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); margin-top: var(--s2); }
.fiche__f { min-width: 0; }
.fiche__f--l { grid-column: span 2; }
.fiche__f .lab { display: block; margin-bottom: 2px; }
.fiche__f input, .fiche__f select {
  width: 100%; min-height: 44px; padding: 0 var(--s2);
  background: var(--acier-haut); color: var(--craie);
  border: 1px solid var(--filet); border-radius: var(--r-1);
  font: inherit; font-size: var(--t-13); font-variant-numeric: tabular-nums;
}
.fiche__f input:focus-visible, .fiche__f select:focus-visible { border-color: var(--p20); }
.fiche__f--ro input { background: none; border-style: dashed; color: var(--craie-douce); }
.fiche__f--err input, .fiche__f--err select { border-color: var(--p25); }
.fiche__f[aria-busy="true"] input, .fiche__f[aria-busy="true"] select { color: var(--craie-douce); }

.pager { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s4); }
.pager .btn { min-height: 44px; }

/* --- Programme : entrees reordonnables (mockup 05) ------------------------ */

.ents { border: 1px solid var(--filet); border-radius: var(--r-2); overflow: hidden; margin-bottom: var(--s2); }
.ent {
  display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px 44px; gap: var(--s1);
  align-items: center;
  padding: 0 var(--s1);
  border-bottom: 1px solid var(--filet);
  background: var(--acier);
  position: relative;
}
.ent:last-child { border-bottom: 0; }
.ent--ss { box-shadow: inset 3px 0 0 var(--p20); }
.ent__grip, .ent__b {
  width: 44px; height: 44px;
  background: none; border: 0; border-radius: var(--r-1);
  color: var(--craie-douce); font: inherit; font-size: var(--t-18); line-height: 1;
  cursor: pointer;
}
/* Seule la poignee capte le geste : le reste de la liste defile au doigt. */
.ent__grip { cursor: grab; touch-action: none; }
.ent__grip:hover, .ent__b:hover:not(:disabled) { color: var(--craie); background: var(--acier-haut); }
.ent__b:disabled { opacity: 0.3; cursor: default; }
.ent__main {
  display: grid; gap: 2px; min-height: 56px; min-width: 0; padding: var(--s2);
  background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.ent__n { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ent__t { font-size: var(--t-11); color: var(--craie-douce); text-transform: uppercase; letter-spacing: 0.06em; font-variant-numeric: tabular-nums; }
.grp {
  padding: var(--s1) var(--s3);
  background: color-mix(in srgb, var(--p20) 12%, transparent);
  border-bottom: 1px solid var(--filet);
  font-size: var(--t-11); letter-spacing: 0.08em; text-transform: uppercase; color: var(--p20-txt);
}

/* Pendant le geste : l'element saisi flotte au-dessus, les autres glissent
   pour lui faire place. Le mouvement repond au doigt, il n'est pas decoratif. */
.glisse--actif { user-select: none; }
.glisse--leve {
  z-index: 2;
  background: var(--acier-haut);
  box-shadow: 0 0 0 1px var(--filet-fort), 0 8px 20px color-mix(in srgb, var(--fonte) 70%, transparent);
}
.glisse--leve .ent__grip { cursor: grabbing; color: var(--craie); }
.glisse--decale { transition: transform 150ms ease-out; }

.decharge__v { font-variant-numeric: tabular-nums; }
.decharge .btn { min-height: 44px; }

/* --- Modeles de programme ------------------------------------------------- */

.tpls { display: grid; gap: var(--s3); }
.tpl { border: 1px solid var(--filet); border-radius: var(--r-2); padding: var(--s3); background: var(--acier); }
.tpl__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.tpl__n { margin: 0; font-size: var(--t-15); font-weight: 700; }
.tpl__days { list-style: none; margin: var(--s2) 0; padding: 0; border-top: 1px solid var(--filet); }
.tpl__d {
  display: grid; grid-template-columns: 5.5em minmax(0, 1fr); gap: 0 var(--s2);
  padding: var(--s2) 0; border-bottom: 1px solid var(--filet); font-size: var(--t-13);
}
.tpl__j { font-size: var(--t-11); text-transform: uppercase; letter-spacing: 0.06em; color: var(--craie-douce); padding-top: 2px; }
.tpl__dn { display: block; font-weight: 600; }
.tpl__ex { display: block; color: var(--craie-douce); }
.tpl__go { width: 100%; min-height: 44px; }
.manquants { margin: var(--s2) 0; padding-left: var(--s4); }
.manquants li { padding: 2px 0; }

/* --- Statistiques : series dures par groupe ------------------------------- */

.vol { list-style: none; margin: var(--s3) 0 0; padding: 0; display: grid; gap: var(--s3); }
.vol__head { display: flex; align-items: center; gap: var(--s2); }
.vol__t { font-size: var(--t-13); font-weight: 600; flex: 1; min-width: 0; }
.vol__v { font-size: var(--t-15); font-weight: 700; }
.vol__bar {
  position: relative; height: 12px; margin-top: var(--s1);
  background: var(--acier-haut); border: 1px solid var(--filet); border-radius: 1px; overflow: hidden;
}
.vol__zone, .vol__prim, .vol__sec { position: absolute; top: 0; bottom: 0; left: 0; }
.vol__zone { border-left: 1px dashed var(--craie-douce); border-right: 1px dashed var(--craie-douce); background: color-mix(in srgb, var(--p10) 14%, transparent); }
.vol__prim { background: var(--p20); }
.vol__sec { background: color-mix(in srgb, var(--p20) 45%, transparent); }
.vol__row--sous .vol__prim, .vol__row--sur .vol__prim { background: var(--p15); }
.vol__row--sous .vol__sec, .vol__row--sur .vol__sec { background: color-mix(in srgb, var(--p15) 45%, transparent); }
.vol__d { display: block; margin-top: 2px; font-size: var(--t-11); color: var(--craie-douce); font-variant-numeric: tabular-nums; }
.vol__leg { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s2); font-size: var(--t-11); color: var(--craie-douce); }
.vol__leg span { display: inline-flex; align-items: center; gap: var(--s1); }
.vol__key { display: inline-block; width: 12px; height: 10px; border: 1px solid var(--filet); }
.vol__key--prim { background: var(--p20); }
.vol__key--sec { background: color-mix(in srgb, var(--p20) 45%, transparent); }
.vol__key--zone { background: color-mix(in srgb, var(--p10) 14%, transparent); border-style: dashed; border-color: var(--craie-douce); }

/* Valeur longue et insecable (chemin de fichier) dans une ligne cle/valeur. */
.kv__v--long { min-width: 0; white-space: normal; overflow-wrap: anywhere; text-align: right; }

/* Fiche exercice : visuel du geste. L'image garde ses proportions (400x300
   dans le catalogue) et ne mange pas l'ecran sur telephone. Fond blanc fixe,
   meme en theme sombre : les photos sont detourees sur blanc. */
.visuel { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s3); }
.visuel__img {
  display: block; width: 100%; max-width: 400px; height: auto; max-height: 240px;
  object-fit: contain; background: #fff; border-radius: var(--r-1);
}

/* Carte d'exercice : actions de l'en-tete (plein ecran, fiche) groupees a
   droite, sans jamais ecraser le nom. */
.ex__actions { display: flex; flex: none; gap: var(--s2); }

/* Plein ecran « exercice en cours ». Au-dessus de la barre haute et de la
   navigation (z 20), sous les messages (z 40) et les feuilles (z 50) : une
   correction de serie ou un message reste visible par-dessus. La page
   derriere ne defile pas ; la couche defile seule si l'ecran est court. */
html.focus-ouvert { overflow: hidden; }
.focus {
  position: fixed;
  inset: 0;
  z-index: 30;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--fonte);
  padding: max(var(--s3), env(safe-area-inset-top)) var(--s4) max(var(--s5), env(safe-area-inset-bottom));
}
.focus:focus { outline: none; }
.focus__in { max-width: 520px; margin: 0 auto; display: grid; gap: var(--s3); }
.focus__tete { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.focus__corps { display: grid; gap: var(--s3); }
.focus__nom {
  margin: var(--s1) 0;
  font-size: var(--t-34);
  font-weight: 700;
  font-stretch: 112%;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
/* Charge et repetitions l'une sous l'autre, en grand : lisibles a bras tendu,
   touchables avec des mains moites. */
.focus .grid2 { grid-template-columns: minmax(0, 1fr); }
.focus .stepper { grid-template-columns: 72px minmax(0, 1fr) 72px; }
.focus .stepper input { min-height: 72px; font-size: var(--t-34); }
.focus .stepper button { font-size: var(--t-34); }
.focus__nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2); }
/* Pendant le repos, le minuteur occupe le haut : on le compacte, et
   « Valider la serie » reste colle au bas de l'ecran pour ne jamais avoir a
   defiler. Fond opaque et ombre, comme .go, sinon le contenu passe a travers. */
.focus .timer__drain { height: 88px; }
.focus .pied > .btn--p {
  position: sticky;
  bottom: 0;
  box-shadow: 0 -8px 16px -4px var(--ombre-forte), 0 0 0 var(--s2) var(--fonte);
}

/* ------------------------------------------------------------ progression */

/* Bilan : trois comptes, l'etat porte par le filet de couleur au-dessus du
   chiffre et par le libelle, jamais par la couleur seule. */
.bilan { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.bilan__c { display: grid; gap: 2px; padding-top: var(--s2); border-top: 3px solid var(--filet-fort); min-width: 0; }
.bilan__c--up     { border-top-color: var(--p10); }
.bilan__c--stable { border-top-color: var(--p15); }
.bilan__c--down   { border-top-color: var(--p25); }
.bilan__v { font-size: clamp(var(--t-24), 8vw, var(--t-34)); font-weight: 700; font-stretch: 112%; line-height: 1; }
.bilan__c--up .bilan__v     { color: var(--p10-txt); }
.bilan__c--stable .bilan__v { color: var(--p15-txt); }
.bilan__c--down .bilan__v   { color: var(--p25-txt); }
.bilan__l { font-size: var(--t-13); color: var(--craie-douce); }
.bilan__note { margin: var(--s3) 0 0; }
.card__head .seg button { min-height: 36px; padding: 0 var(--s2); font-size: var(--t-13); }
.card__head:has(.seg) { flex-wrap: wrap; align-items: center; }
.card__head > .lab { flex-shrink: 0; }

/* Listes d'action : nom et valeur sur une ligne, detail dessous. */
.act { list-style: none; margin: 0; padding: 0; }
.act__l {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px var(--s3);
  align-items: baseline;
  padding: var(--s3) 0;
  border-top: 1px solid var(--filet);
}
.act__l:first-child { border-top: 0; padding-top: 0; }
.act__nom { font-weight: 600; color: var(--craie); text-decoration: none; min-width: 0; overflow-wrap: anywhere; }
.act__nom:hover { text-decoration: underline; }
.act__v { font-size: var(--t-18); font-weight: 700; white-space: nowrap; text-align: right; }
.act__v--s { font-size: var(--t-15); font-weight: 600; white-space: normal; }
.act__monte { color: var(--p10-txt); }
.act__d { grid-column: 1 / -1; font-size: var(--t-13); color: var(--craie-douce); }

.pastille {
  display: inline-block;
  padding: 2px 6px;
  border-radius: var(--r-1);
  font-size: var(--t-11);
  font-weight: 700;
  font-stretch: 108%;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--fonte);
  background: var(--craie-douce);
}
.pastille--up     { background: var(--p10-txt); }
.pastille--stable { background: var(--p15-txt); }
.pastille--down   { background: var(--p25-txt); }
.pastille--vide   { background: none; color: var(--craie-douce); border: 1px solid var(--filet-fort); }

.pos { color: var(--p10-txt); }
.neg { color: var(--p25-txt); }
.nul { color: var(--craie-douce); }

/* Exercices cles */
.prog__aide { margin: 0 0 var(--s3); }
.puces { display: flex; flex-wrap: wrap; gap: var(--s2); }
.puces:not(:empty) { margin-bottom: var(--s2); }
.puce {
  min-height: 36px;
  padding: 0 var(--s3);
  background: none;
  border: 1px solid var(--filet-fort);
  border-radius: var(--r-2);
  color: var(--craie-douce);
  font: inherit;
  font-size: var(--t-13);
  cursor: pointer;
}
.puce[aria-pressed="true"] { border-color: var(--craie); color: var(--craie); }
.prog { list-style: none; margin: 0; padding: 0; }
.prog > li { border-top: 1px solid var(--filet); }
.prog > li:first-child { border-top: 0; }
.prog__ligne {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px auto;
  grid-template-areas: "nom spark e1" "meta spark var";
  gap: 2px var(--s3);
  align-items: center;
  padding: var(--s3) 0;
  min-height: 56px;
  background: none;
  border: 0;
  color: var(--craie);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.prog__nom { grid-area: nom; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prog__meta { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: var(--t-13); color: var(--craie-douce); min-width: 0; }
.prog__spark { grid-area: spark; display: block; }
.prog__e1 { grid-area: e1; font-size: var(--t-18); font-weight: 700; text-align: right; white-space: nowrap; }
.prog__var { grid-area: var; font-size: var(--t-13); text-align: right; white-space: nowrap; }
.prog__chevron { display: inline-block; margin-left: var(--s1); color: var(--craie-douce); transition: transform 150ms ease; }
.prog__ligne[aria-expanded="true"] .prog__chevron { transform: rotate(90deg); }
.prog__detail { display: grid; gap: var(--s3); padding: 0 0 var(--s4); }
.prog__detail > .btn { justify-self: start; }

.spark { display: block; width: 84px; height: 30px; }
.spark__line { fill: none; stroke: var(--craie-douce); stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.spark__area { fill: color-mix(in srgb, var(--craie-douce) 12%, transparent); stroke: none; }
.spark__dot  { fill: var(--craie-douce); }
.spark--up .spark__line     { stroke: var(--p10-txt); }
.spark--up .spark__area     { fill: color-mix(in srgb, var(--p10) 18%, transparent); }
.spark--up .spark__dot      { fill: var(--p10-txt); }
.spark--stable .spark__line { stroke: var(--p15-txt); }
.spark--stable .spark__area { fill: color-mix(in srgb, var(--p15) 14%, transparent); }
.spark--stable .spark__dot  { fill: var(--p15-txt); }
.spark--down .spark__line   { stroke: var(--p25-txt); }
.spark--down .spark__area   { fill: color-mix(in srgb, var(--p25) 16%, transparent); }
.spark--down .spark__dot    { fill: var(--p25-txt); }

/* Force relative */
.force { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.force__l { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); align-items: baseline; }
.force__nom { min-width: 0; overflow-wrap: anywhere; }
.force__v { white-space: nowrap; }
.force__barre { grid-column: 1 / -1; position: relative; height: 6px; background: var(--acier-haut); border-radius: var(--r-1); overflow: hidden; }
.force__rempli { position: absolute; top: 0; bottom: 0; left: 0; background: var(--p20); }
.force__avant { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--craie); }

/* Bloc replie */
.replie > summary { list-style: none; }
.replie > summary::-webkit-details-marker { display: none; }
.replie__tete { display: flex; align-items: center; justify-content: space-between; min-height: 36px; cursor: pointer; }
.replie__chevron { font-size: var(--t-18); color: var(--craie-douce); transition: transform 150ms ease; }
.replie[open] .replie__chevron { transform: rotate(90deg); }
.replie__sous { display: block; }

@media (prefers-reduced-motion: reduce) {
  .prog__chevron, .replie__chevron { transition: none; }
}
