/* Atelier — feuille de style unique.
 *
 * Transposition de la maquette Claude Design (Aujourdhui-Clair / -Bandes /
 * -Mobile). Ce n'est pas une inspiration : les valeurs — palette, échelle,
 * espacements — viennent de là. Ce qui s'en écarte est commenté sur place.
 *
 * Écrite à la main, sans outil de construction : du CSS avec des variables se
 * relit dans deux ans sans réinstaller Node.
 *
 * Quatre règles tenues partout :
 *
 * 1. **Mobile d'abord.** Les styles de base sont ceux du téléphone ; les écrans
 *    larges ajoutent, ils ne corrigent pas.
 * 2. **Aucun style en ligne.** La politique de contenu ne porte pas
 *    `'unsafe-inline'`, donc un attribut `style=` serait ignoré. Seule exception :
 *    le bloc de géométrie du jour, autorisé par un nonce, qui ne contient que des
 *    positions.
 * 3. **La couleur de formateur est la seule variable de la palette.** Six valeurs,
 *    celles du champ Notion, qui doivent s'accorder à l'agenda Apple.
 * 4. **Les deux thèmes comptent autant.** Le clair est celui que Chris verra le
 *    matin.
 *
 * Les couleurs sont en `oklch()`, comme la maquette les définit : les convertir en
 * hexadécimal écraserait le rendu sur les écrans à large gamut.
 */

/* --- Jetons : thème clair ----------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Fonds et encres. Le fond n'est pas blanc mais très légèrement chaud (teinte
   * 85) : c'est ce qui distingue la maquette d'un tableur. */
  --fond:          oklch(0.958 0.009 85);
  --surface:       oklch(1 0 0);
  --surface-creuse: oklch(0.982 0.006 85);
  --encre:         oklch(0.235 0.015 265);
  --encre-forte:   oklch(0.300 0.015 265);
  --encre-douce:   oklch(0.400 0.018 265);
  --encre-tenue:   oklch(0.500 0.018 265);
  --encre-pale:    oklch(0.740 0.012 85);
  --trait:         oklch(0.905 0.010 85);
  --trait-fort:    oklch(0.855 0.010 85);
  --creux:         oklch(0.895 0.008 85);

  /* Le filet qui sépare une ZONE d'une autre — sous le bandeau, sous la bande. La
   * maquette lui donne sa propre valeur, entre `--trait` et `--trait-fort` : un
   * séparateur de zone aussi fort qu'une bordure de carte attire l'œil sur une
   * ligne qui ne dit rien. */
  --trait-moyen:   oklch(0.875 0.008 85);

  /* Le titre de section (« La journée », « À faire »). Volontairement plus retenu
   * que le texte courant : ces titres se lisent une fois, en balayage. Sur
   * `--encre-forte`, ils rivalisaient avec le contenu en thème sombre. */
  --titre:         oklch(0.330 0.018 265);

  /* Les creux entre deux cours, en deux crans de retrait. Ils font partie de la
   * lecture — c'est là que Chris déjeune ou traverse la ville — mais ils ne doivent
   * jamais rivaliser avec un cours. « Fin de journée » est le plus effacé des deux :
   * il ne porte aucune information, il ferme la liste. */
  --creux-texte:     oklch(0.560 0.018 265);
  --creux-texte-fin: oklch(0.640 0.014 85);

  /* Le fond de la bande, derrière les blocs. Distinct du fond de carte : la bande
   * est un CREUX dans la page, les cartes en ressortent. */
  --bande-fond:    oklch(0.895 0.008 85);

  /* Action neutre pleine largeur (« Marquer fait »). L'accent est réservé à ce qui
   * décide de l'argent — confirmer une séance la rend facturable. Cinq boutons
   * couleur terre cuite sur un écran, et l'accent ne veut plus rien dire. */
  --bouton-fond:   oklch(0.905 0.010 85);
  --bouton-encre:  oklch(0.265 0.015 265);

  /* Accent unique : la terre cuite de la maquette. Elle ne sert qu'au retard, à
   * l'action et au trait de la barre — jamais à décorer. */
  --accent:        oklch(0.545 0.165 48);
  --accent-texte:  oklch(0.520 0.160 48);
  --accent-trait:  oklch(0.560 0.170 48);
  --accent-clair:  oklch(0.995 0.006 85);

  /* Le refus. Distinct de l'accent, qui dit « à traiter » : un refus n'est pas une
   * tâche à venir, c'est un geste qui n'a pas eu lieu. La teinte 25 est celle du rouge
   * de formateur, pour ne pas introduire une septième couleur dans la palette. */
  --refus-fond:  oklch(0.960 0.035 25);
  --refus-trait: oklch(0.560 0.150 25);
  --refus-encre: oklch(0.400 0.130 25);

  /* Couleurs de formateur, dans la discipline de la maquette : clarté ~0.58,
   * chroma ~0.12, six teintes réparties. Les noms sont ceux du champ Notion —
   * c'est lui la source, parce que c'est l'agenda Apple que Chris reconnaît. */
  --f-bleu:    oklch(0.580 0.110 250);
  --f-vert:    oklch(0.580 0.110 160);
  --f-orange:  oklch(0.660 0.130 68);
  --f-violet:  oklch(0.545 0.130 300);
  --f-rouge:   oklch(0.560 0.150 25);
  --f-jaune:   oklch(0.700 0.120 95);
  --f-neutre:  oklch(0.755 0.010 85);
  /* Fond d'étiquette : la même teinte, lavée. Calculée à la main plutôt qu'en
   * `color-mix`, pour rester lisible et prévisible sur les deux thèmes. */
  --f-bleu-pale:   oklch(0.935 0.030 250);
  --f-vert-pale:   oklch(0.935 0.030 160);
  --f-orange-pale: oklch(0.945 0.042 78);
  --f-violet-pale: oklch(0.945 0.030 300);
  --f-rouge-pale:  oklch(0.940 0.035 25);
  --f-jaune-pale:  oklch(0.950 0.040 95);
  --f-neutre-pale: oklch(0.935 0.008 85);
  --f-bleu-texte:   oklch(0.430 0.100 250);
  --f-vert-texte:   oklch(0.415 0.090 160);
  --f-orange-texte: oklch(0.435 0.090 62);
  --f-violet-texte: oklch(0.420 0.100 300);
  --f-rouge-texte:  oklch(0.440 0.120 25);
  --f-jaune-texte:  oklch(0.450 0.090 90);
  --f-neutre-texte: oklch(0.340 0.015 265);

  /* Échelle typographique. Les bornes viennent de la maquette : le grand titre y
   * va de 42 à 84 px. `clamp` plutôt que des paliers — aucun saut de mise en page
   * à un seuil arbitraire. */
  --t-micro:  10px;
  --t-mini:   11px;
  --t-petit:  12px;
  --t-texte:  13px;
  --t-base:   15px;
  --t-medium: clamp(16px, 1.8vw, 20px);
  --t-titre:  clamp(19px, 2.1vw, 24px);
  --t-heure:  clamp(24px, 2.8vw, 32px);
  --t-compte: clamp(26px, 3vw, 36px);
  --t-retard: clamp(30px, 3.4vw, 44px);
  --t-date:   clamp(42px, 8vw, 84px);

  /* Espacements. La maquette respire par des multiples de 2 px et des `clamp`
   * entre téléphone et écran large. */
  --e1: 2px;
  --e2: 6px;
  --e3: 10px;
  --e4: 14px;
  --e5: 20px;
  --e6: clamp(15px, 1.9vw, 22px);
  --e7: clamp(20px, 3.2vw, 44px);
  --e8: clamp(26px, 3.2vw, 44px);

  --colonne: 1480px;
  /* Hauteur TOTALE de la bande, chevauchements compris. « À peine plus que le texte de
   * l'heure » : 10 px d'étiquette, deux pixels de part et d'autre. Elle faisait de 44 à
   * 68 px par piste — une frise de lecture rapide ne demande pas cette place, et le
   * détail est dans la liste juste en dessous. */
  --bande-h: 22px;
  /* Hauteur d'une demi-heure dans la grille du planning. Un seul jeton pour la
   * grille ET le rail horaire : deux valeurs recopiées se désaligneraient au premier
   * ajustement, et un cours apparaîtrait alors une demi-heure à côté. */
  /* FLUIDE, et deux fois plus compacte encore qu'au premier essai — donc quatre fois
   * moins que la maquette, qui pose 30 px par demi-heure sur une grille de 1 600 px. À
   * cette largeur un cours de trois heures fait une bande horizontale ; à 820 px, la
   * largeur minimale de la grille, les mêmes 180 px de haut sur 130 de large font un
   * pavé vertical et la journée ne tient plus dans l'écran.
   *
   * Le plancher est à 7 px et non à la moitié exacte de 10 : à 5 px, une heure pleine
   * fait 10 px et l'étiquette du rail — 10 px de haut — se superpose à la suivante. La
   * règle d'heures doit rester lisible, sinon les blocs tombent sur des graduations
   * qu'on ne peut plus lire. */
  --demi-h: clamp(7px, 0.95vw, 15px);

  /* Planning : quatre fonds que le reste de l'interface n'a pas.
   * `--grille-fond` est un CREUX plus marqué que `--surface-creuse` : la grille est
   * une surface où l'on pose, pas une carte. `--surface-jour` relève la colonne
   * d'aujourd'hui, `--fond-creux` met le week-end en retrait, `--surface-choisie`
   * marque la séance sélectionnée. */
  /* Pilotage : les gris de COMPARAISON. Ils ne disent rien d'autre que « ceci sert de
   * référence » — le vide d'une jauge, l'an dernier, ce qui n'est pas de la marge.
   * Distincts de `--trait` : un trait sépare, une comparaison se mesure, et leur donner
   * la même valeur ferait lire une bordure là où il y a une quantité. */
  --jauge-vide:        oklch(0.890 0.008 85);
  --comparaison:       oklch(0.855 0.010 85);
  --comparaison-forte: oklch(0.700 0.025 265);
  /* La teinte du CA, en version ternie : l'engagé n'est pas du réalisé. Même teinte
   * pour dire « même sujet », clarté baissée pour dire « pas encore acquis ». */
  --f-bleu-terne:      oklch(0.780 0.075 195);

  --grille-fond:     oklch(0.940 0.008 85);
  --surface-jour:    oklch(0.995 0.008 82);
  --fond-creux:      oklch(0.935 0.007 85);
  --surface-choisie: oklch(0.965 0.012 82);
}

/* --- Jetons : thème sombre ---------------------------------------------- */
/* Redéfinis, jamais ajoutés : une couleur qui n'existerait que sous cette requête
 * disparaîtrait en thème clair. */

@media (prefers-color-scheme: dark) {
  :root {
    --fond:           oklch(0.185 0.012 265);
    /* La carte est un cran PLUS CLAIRE et un peu plus bleue que le fond — c'est ce
     * décollement de 0,05 qui fait qu'un écran sombre n'est pas un écran noir. À
     * 0.225/265 les cartes se confondaient presque avec la page. */
    --surface:        oklch(0.235 0.014 268);
    --surface-creuse: oklch(0.205 0.012 265);
    --encre:          oklch(0.95 0.008 85);
    --encre-forte:    oklch(0.88 0.008 85);
    --encre-douce:    oklch(0.72 0.015 265);
    --encre-tenue:    oklch(0.62 0.020 265);
    --encre-pale:     oklch(0.55 0.015 265);
    --trait:          oklch(0.27 0.012 265);
    --trait-fort:     oklch(0.33 0.015 265);
    --trait-moyen:    oklch(0.27 0.012 265);
    --creux:          oklch(0.25 0.012 265);
    --titre:          oklch(0.74 0.020 265);
    --creux-texte:     oklch(0.52 0.015 265);
    --creux-texte-fin: oklch(0.44 0.015 265);
    --bande-fond:     oklch(0.225 0.012 265);
    --bouton-fond:    oklch(0.29 0.012 265);
    --bouton-encre:   oklch(0.90 0.015 265);
    --jauge-vide:        oklch(0.280 0.012 265);
    --comparaison:       oklch(0.320 0.015 265);
    --comparaison-forte: oklch(0.450 0.030 265);
    --f-bleu-terne:      oklch(0.420 0.070 195);
    --grille-fond:     oklch(0.205 0.012 265);
    --surface-jour:    oklch(0.215 0.013 266);
    --fond-creux:      oklch(0.198 0.012 265);
    --surface-choisie: oklch(0.280 0.014 268);

    /* L'accent s'éclaircit : la terre cuite sombre serait illisible sur fond
     * sombre, et c'est le seul endroit où la maquette change de valeur plutôt
     * que d'inverser. */
    --accent:         oklch(0.72 0.150 68);
    --accent-texte:   oklch(0.84 0.150 78);
    --accent-trait:   oklch(0.78 0.160 72);
    --accent-clair:   oklch(0.20 0.030 70);
    --refus-fond:  oklch(0.290 0.060 25);
    --refus-trait: oklch(0.620 0.150 25);
    --refus-encre: oklch(0.900 0.060 25);

    --f-bleu:    oklch(0.640 0.110 250);
    --f-vert:    oklch(0.640 0.110 160);
    --f-orange:  oklch(0.720 0.130 72);
    --f-violet:  oklch(0.600 0.120 300);
    --f-rouge:   oklch(0.620 0.150 25);
    --f-jaune:   oklch(0.760 0.120 95);
    --f-neutre:  oklch(0.380 0.012 265);
    --f-bleu-pale:   oklch(0.30 0.045 250);
    --f-vert-pale:   oklch(0.30 0.045 160);
    --f-orange-pale: oklch(0.33 0.060 72);
    --f-violet-pale: oklch(0.31 0.050 300);
    --f-rouge-pale:  oklch(0.31 0.055 25);
    --f-jaune-pale:  oklch(0.32 0.055 95);
    --f-neutre-pale: oklch(0.29 0.012 265);
    --f-bleu-texte:   oklch(0.82 0.090 250);
    --f-vert-texte:   oklch(0.82 0.090 160);
    --f-orange-texte: oklch(0.86 0.100 78);
    --f-violet-texte: oklch(0.82 0.090 300);
    --f-rouge-texte:  oklch(0.83 0.100 25);
    --f-jaune-texte:  oklch(0.87 0.090 95);
    --f-neutre-texte: oklch(0.80 0.010 85);
  }
}

/* --- Police ------------------------------------------------------------- */
/* Inter, variable, auto-hébergée. Voir src/interface/static/fonts/LISEZ-MOI.md.
 * `font-display: swap` et une pile de repli choisie : sans le fichier la page
 * reste juste, dans une humaniste système. Le repli par défaut d'un navigateur
 * est une serif — exactement ce que la direction visuelle écarte. */

@font-face {
  font-family: "Atelier Sans";
  src: url("/static/fonts/interface.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --- Remise à zéro ------------------------------------------------------ */

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

html {
  background: var(--fond);
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--fond);
  color: var(--encre);
  font-family: "Atelier Sans", "Segoe UI Variable Text", "Segoe UI",
               system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  font-size: var(--t-base);
  line-height: 1.5;
  /* Chiffres tabulaires partout : la colonne des créneaux et la règle d'heures
   * danseraient si un « 1 » était plus étroit. */
  font-feature-settings: "tnum" 1;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, ul, li, figure { margin: 0; padding: 0; }
ul { list-style: none; }
button, input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Ossature ----------------------------------------------------------- */

.contenu {
  width: 100%;
  max-width: var(--colonne);
  margin-inline: auto;
  padding: var(--e7) clamp(14px, 3.5vw, 48px) 96px;
  display: grid;
  gap: var(--e8);
  align-content: start;
}

.bandeau {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--fond);
  border-bottom: 1px solid var(--trait-moyen);
}

/* Le fond du bandeau va d'un bord à l'autre, son contenu s'aligne sur la colonne
 * de la page. Les deux largeurs viennent du même jeton : les recopier les ferait
 * diverger au premier ajustement. */
.bandeau-interieur {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e4);
  width: 100%;
  max-width: var(--colonne);
  margin-inline: auto;
  padding: 12px clamp(14px, 3.5vw, 48px);
}

/* La marque de la maquette : un trait vertical accent, puis le mot en capitales
 * espacées. Pas un logo — l'écran se nomme lui-même. */
.marque {
  display: flex;
  align-items: center;
  gap: var(--e3);
  min-width: 0;
}

.marque::before {
  content: "";
  width: 9px;
  height: 22px;
  background: var(--accent);
  flex: none;
}

.marque-texte {
  font-size: var(--t-petit);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 700;
  white-space: nowrap;
}

.bouton-discret {
  padding: 7px 11px;
  border: 0;
  background: none;
  color: var(--encre-tenue);
  font-size: var(--t-mini);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}

.bouton-discret:hover { color: var(--encre); }

/* --- En-tête : la date en très gros ------------------------------------ */

.tete {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--e5);
  flex-wrap: wrap;
}

.date {
  font-size: var(--t-date);
  line-height: 0.85;
  font-weight: 800;
  letter-spacing: -0.055em;
}

/* Le mois en pâle : la date se lit en deux temps, le jour d'abord. C'est ce qui
 * permet au titre d'être énorme sans crier. */
.date-mois {
  color: var(--encre-pale);
}

.date-contexte {
  font-size: var(--t-texte);
  color: var(--encre-tenue);
  margin-top: 12px;
}

/* --- Les trois compteurs ------------------------------------------------ */
/* Repères, pas boutons : ni fond, ni bordure, ni curseur de main sur écran large.
 * Sur mobile ils deviennent des ancres, parce que l'écran y fait quatre hauteurs
 * — mais ils gardent la même apparence. */

.compteurs {
  display: flex;
  gap: clamp(12px, 2vw, 26px);
  align-items: stretch;
}

.compteur {
  border-left: 2px solid var(--trait-fort);
  padding-left: 12px;
  cursor: default;
}

.compteur-alerte { border-left-color: var(--accent-trait); }

.compteur-nombre {
  display: block;
  font-size: var(--t-compte);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 1;
}

.compteur-libelle {
  display: block;
  font-size: var(--t-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  margin-top: 7px;
}

.compteur-alerte .compteur-nombre,
.compteur-alerte .compteur-libelle { color: var(--accent-texte); }

@media (max-width: 47.99rem) {
  /* Ancre de défilement : le seul changement est le curseur, pas l'apparence. */
  .compteur { cursor: pointer; }
}

/* --- La bande de temps ------------------------------------------------- */
/* Les positions viennent du bloc `<style>` généré (src/interface/bande.py) :
 * `left` et `width` en pourcentage de la fenêtre du jour, calculés à la minute.
 * Ici ne vit que ce qui ne dépend pas du jour. */

.bande-zone { display: grid; gap: 8px; }

/* Une surface, pas une grille. Elle en était une, et c'était un défaut de fond : les
 * blocs y étaient des items placés par `grid-row`, donc plusieurs blocs d'une même
 * piste tombaient dans des COLONNES implicites — dimensionnées sur leur contenu. Une
 * séance de quatre heures avait alors la largeur du texte « 08:30 », et la bande
 * suggérait une journée au lieu de la dire.
 *
 * Les bords tombent maintenant exactement sur leurs graduations : `left` et `width`
 * sont des pourcentages de la MÊME largeur que la règle d'heures — celle de la bande —,
 * donc un cours de 8 h 30 à 12 h 30 couvre un tiers d'une frise graduée de 8 à 20. */
.bande {
  position: relative;
  height: var(--bande-h);
  background: var(--bande-fond);
}

/* Chaque bloc est posé aux quatre coins : `left`/`width` pour l'heure, `top`/`height`
 * pour la piste. Les pistes se partagent la hauteur au lieu de l'additionner — la frise
 * garde donc la même épaisseur qu'il y ait un chevauchement ou trois. */
.bande-bloc {
  position: absolute;
  display: flex;
  align-items: center;
  padding: 0 5px;
  overflow: hidden;
  /* Un cours de quinze minutes fait 2 % de la bande, soit une dizaine de pixels : sans
   * plancher il deviendrait un trait qu'on ne verrait pas. */
  min-width: 4px;
}

.bande-heure {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.08em;
  white-space: nowrap;
  line-height: 1;
}

/* Deux pistes ou plus : chaque voie fait la moitié de 22 px, et une étiquette de 10 px
 * n'y tient pas. On la retire plutôt que de la tronquer au milieu d'un chiffre — une
 * heure coupée est pire qu'une heure absente, et la liste juste en dessous la porte.
 *
 * C'est le prix de la hauteur constante, et il est assumé : sur une journée sans
 * chevauchement, qui est le cas normal, les heures restent écrites. */
.bande-serree .bande-heure { display: none; }

.regle {
  position: relative;
  height: 1.2em;
  border-top: 1px solid var(--trait-moyen);
  padding-top: 7px;
}

.regle-h {
  position: absolute;
  top: 7px;
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  color: var(--encre-tenue);
  transform: translateX(-50%);
}

/* La première et la dernière étiquette ne débordent pas de la bande. */
.regle-h0 { transform: none; }

.legende {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.legende-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--t-petit);
  color: var(--encre-douce);
}

.legende-pastille { width: 14px; height: 8px; flex: none; }

.bande-note {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

/* --- Couleurs de formateur -------------------------------------------- */
/* Un seul jeu de classes, utilisé par la bande (fond), les cartes (liseré) et les
 * étiquettes (fond lavé + texte). Six teintes, celles du champ Notion. */

.bande-bloc.f-bleu   { background: var(--f-bleu); }
.bande-bloc.f-vert   { background: var(--f-vert); }
.bande-bloc.f-orange { background: var(--f-orange); }
.bande-bloc.f-violet { background: var(--f-violet); }
.bande-bloc.f-rouge  { background: var(--f-rouge); }
.bande-bloc.f-jaune  { background: var(--f-jaune); }
.bande-bloc.f-neutre { background: var(--f-neutre); }

/* L'heure posée dans le bloc : encre sombre sur teinte claire, pour que le
 * contraste tienne sur les six couleurs et dans les deux thèmes. */
.bande-bloc .bande-heure { color: oklch(0.22 0.04 250); }

.legende-pastille.f-bleu   { background: var(--f-bleu); }
.legende-pastille.f-vert   { background: var(--f-vert); }
.legende-pastille.f-orange { background: var(--f-orange); }
.legende-pastille.f-violet { background: var(--f-violet); }
.legende-pastille.f-rouge  { background: var(--f-rouge); }
.legende-pastille.f-jaune  { background: var(--f-jaune); }
.legende-pastille.f-neutre { background: var(--f-neutre); }

.cours.f-bleu, .confirmer.f-bleu     { border-left-color: var(--f-bleu); }
.cours.f-vert, .confirmer.f-vert     { border-left-color: var(--f-vert); }
.cours.f-orange, .confirmer.f-orange { border-left-color: var(--f-orange); }
.cours.f-violet, .confirmer.f-violet { border-left-color: var(--f-violet); }
.cours.f-rouge, .confirmer.f-rouge   { border-left-color: var(--f-rouge); }
.cours.f-jaune, .confirmer.f-jaune   { border-left-color: var(--f-jaune); }
.cours.f-neutre, .confirmer.f-neutre { border-left-color: var(--f-neutre); }

.etiq-formateur.f-bleu   { background: var(--f-bleu-pale);   color: var(--f-bleu-texte); }
.etiq-formateur.f-vert   { background: var(--f-vert-pale);   color: var(--f-vert-texte); }
.etiq-formateur.f-orange { background: var(--f-orange-pale); color: var(--f-orange-texte); }
.etiq-formateur.f-violet { background: var(--f-violet-pale); color: var(--f-violet-texte); }
.etiq-formateur.f-rouge  { background: var(--f-rouge-pale);  color: var(--f-rouge-texte); }
.etiq-formateur.f-jaune  { background: var(--f-jaune-pale);  color: var(--f-jaune-texte); }
.etiq-formateur.f-neutre { background: var(--f-neutre-pale); color: var(--f-neutre-texte); }

.confirmer-quand.f-bleu   { color: var(--f-bleu-texte); }

/* --- En retard : le bloc qui doit sauter aux yeux --------------------- */

.retard {
  background: var(--surface);
  border-top: 3px solid var(--accent-trait);
  padding: clamp(16px, 2.2vw, 26px);
}

.retard-tete {
  display: flex;
  align-items: baseline;
  gap: var(--e4);
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.retard-titre {
  font-size: var(--t-mini);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--accent-texte);
}

.retard-detail {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.retard-liste {
  display: grid;
  gap: var(--e1);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.retard-carte {
  background: var(--surface-creuse);
  padding: 16px;
  display: grid;
  gap: var(--e2);
  align-content: start;
}

/* Le nombre de jours est le point d'entrée de l'œil : très gros, en accent, et
 * l'action juste dessous. C'est le parti pris du bloc. */
.retard-nombre {
  font-size: var(--t-retard);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.85;
  color: var(--accent-texte);
}

.retard-unite {
  font-size: 0.32em;
  font-weight: 600;
  letter-spacing: 0.1em;
  margin-left: 6px;
}

.retard-quoi {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.015em;
  margin-top: 8px;
}

.retard-contexte {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

/* --- Deux colonnes ---------------------------------------------------- */
/* `auto-fit` avec un minimum : la bascule se fait quand la place manque, pas à un
 * seuil de largeur d'écran deviné. Sur téléphone, une seule colonne. */

.deux-colonnes {
  display: grid;
  gap: clamp(26px, 3vw, 44px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  align-items: start;
}

.colonne {
  min-width: 0;
  display: grid;
  gap: 12px;
  align-content: start;
}

/* La colonne droite empile trois SECTIONS distinctes — à faire, à confirmer,
 * ailleurs — là où la gauche empile les cours d'une seule liste. Au même écart de
 * 12 px, les sections se lisaient comme une seule. */
.colonne-sections {
  gap: clamp(26px, 3vw, 38px);
}

.pave { display: grid; gap: var(--e4); }

/* « À faire » contient deux sous-groupes titrés (du jour, en retard) : il respire
 * plus qu'un pavé d'une seule liste, sinon les sous-titres collent à ce qui les
 * précède. */
.pave-groupes { gap: var(--e5); }

.section-tete {
  display: flex;
  align-items: baseline;
  gap: 12px;
}

.section-titre {
  font-size: var(--t-mini);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--titre);
}

.section-filet {
  height: 1px;
  flex: 1;
  background: var(--trait);
}

.section-compte {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
  white-space: nowrap;
}

/* --- Un cours --------------------------------------------------------- */

.cours {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(14px, 1.8vw, 22px);
  background: var(--surface);
  padding: var(--e6);
  border-left: 6px solid var(--f-neutre);
}

.cours-creneau {
  display: grid;
  align-content: start;
  gap: 3px;
}

.cours-debut {
  font-size: var(--t-heure);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 1;
}

.cours-fin {
  font-size: var(--t-medium);
  letter-spacing: -0.035em;
  color: var(--encre-tenue);
  line-height: 1.1;
}

/* Séance saisie sans heure : le job lui applique une heure par défaut pour la
 * poser dans l'agenda, l'écran ne la fait pas passer pour une heure voulue. */
.cours-sans-heure {
  color: var(--encre-tenue);
  font-weight: 400;
}

.cours-duree {
  font-size: var(--t-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  margin-top: 8px;
}

.cours-corps {
  min-width: 0;
  display: grid;
  gap: 9px;
  align-content: start;
}

.cours-titre {
  font-size: var(--t-titre);
  font-weight: 600;
  letter-spacing: -0.032em;
  line-height: 1.12;
  text-wrap: pretty;
}

.cours-ecole {
  font-size: var(--t-texte);
  color: var(--encre-douce);
}

.etiquettes {
  display: flex;
  gap: var(--e2);
  flex-wrap: wrap;
  margin-top: 2px;
}

.etiq {
  font-size: var(--t-mini);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 9px;
  background: var(--f-neutre-pale);
  color: var(--f-neutre-texte);
}

/* --- Les creux entre deux cours -------------------------------------- */
/* Ils font partie de la lecture : c'est là que Chris déjeune, prépare, ou
 * traverse la ville. Une liste qui les tairait donnerait une journée fausse. */

.creux {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0 4px 6px;
}

.creux-point {
  width: 6px;
  height: 6px;
  background: var(--f-neutre);
  flex: none;
}

.creux-libelle {
  font-size: var(--t-mini);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--creux-texte);
}

.creux-filet { flex: 1; height: 1px; background: var(--trait); }

.creux-fin .creux-point { background: var(--trait-fort); }
.creux-fin .creux-libelle { color: var(--creux-texte-fin); }

/* --- À faire ---------------------------------------------------------- */

.sous-titre-liste {
  font-size: var(--t-mini);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  margin-bottom: 9px;
}

.sous-titre-alerte { color: var(--accent-texte); }

.taches { display: grid; gap: var(--e1); }

.tache {
  background: var(--surface);
  padding: 14px 16px;
  display: flex;
  justify-content: space-between;
  gap: var(--e4);
  align-items: baseline;
  flex-wrap: wrap;
  border-left: 3px solid var(--f-neutre);
}

.tache-retard { border-left-color: var(--accent-trait); }

.tache-titre { font-size: var(--t-base); }

.tache-detail {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.tache-jours {
  font-size: var(--t-petit);
  font-weight: 600;
  color: var(--accent-texte);
}

.note-liste {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.enjeu {
  font-size: var(--t-petit);
  font-weight: 600;
  color: var(--accent-texte);
}

/* --- À confirmer ------------------------------------------------------ */

.confirmations { display: grid; gap: var(--e1); }

.confirmer {
  background: var(--surface);
  padding: clamp(15px, 1.9vw, 20px);
  display: grid;
  gap: var(--e3);
  border-left: 3px solid var(--f-neutre);
}

.confirmer-tete {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  align-items: baseline;
}

.confirmer-quand {
  font-size: var(--t-texte);
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--encre-forte);
}

.confirmer-meta {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.confirmer-titre {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.028em;
}

.confirmer-qui {
  font-size: var(--t-texte);
  color: var(--encre-douce);
}

/* --- Ailleurs -------------------------------------------------------- */
/* Compte + destination, rien d'autre. Bordure fine, pas de fond : ce ne sont pas
 * des cartes de travail mais des sorties. Chris ne traite rien depuis là. */

.ailleurs { display: grid; gap: var(--e1); }

.sortie {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 20px;
  border: 1px solid var(--trait-fort);
}

.sortie-nombre {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 1;
}

.sortie-quoi { flex: 1; min-width: 120px; font-size: var(--t-base); }

.sortie-ou {
  font-size: var(--t-mini);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  white-space: nowrap;
}

/* --- États vides ------------------------------------------------------ */
/* Chris en verra souvent : c'est le signe que le système fait son travail. Ils
 * informent au lieu de constater — « le prochain est lundi 10 août à 08:30 ». */

.vide {
  background: var(--surface-creuse);
  padding: clamp(26px, 4vw, 42px) clamp(18px, 3vw, 30px);
  display: grid;
  gap: var(--e4);
  align-content: center;
  justify-items: center;
  text-align: center;
  min-height: 220px;
}

.vide-titre {
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 600;
  letter-spacing: -0.032em;
}

.vide-texte {
  font-size: 14px;
  color: var(--encre-tenue);
  max-width: 32ch;
  line-height: 1.5;
}

.vide-marque-barre {
  width: min(100%, 220px);
  height: 8px;
  background: var(--trait);
}

.vide-marque-carre {
  width: 26px;
  height: 26px;
  border: 2px solid var(--trait-fort);
}

.vide-marque-pastilles { display: flex; gap: 3px; }

.vide-marque-pastilles span {
  width: 10px;
  height: 10px;
  opacity: 0.4;
}

.vide-marque-pastilles .f-bleu   { background: var(--f-bleu); }
.vide-marque-pastilles .f-orange { background: var(--f-orange); }
.vide-marque-pastilles .f-violet { background: var(--f-violet); }

/* --- Alerte et page de panne ----------------------------------------- */

.alerte {
  padding: 12px 14px;
  background: var(--surface);
  border-left: 3px solid var(--accent-trait);
  color: var(--accent-texte);
  font-size: var(--t-texte);
  font-weight: 600;
}

.repliable {
  cursor: pointer;
  color: var(--encre-douce);
  font-weight: 600;
  font-size: var(--t-texte);
}

.trace {
  margin-top: var(--e3);
  padding: var(--e4);
  background: var(--surface);
  border: 1px solid var(--trait);
  font-size: var(--t-petit);
  white-space: pre-wrap;
  overflow-x: auto;
}

/* --- Navigation entre écrans ------------------------------------------ */
/* L'emplacement des pastilles « Semaine / Année » de la maquette, qui ne se
 * transposent pas — un sélecteur de période sur un écran qui n'en a qu'une. La
 * maquette de Prospection, elle, n'a pas de bandeau du tout : aucune des deux ne
 * prévoit comment passer d'un écran à l'autre. */

.nav {
  display: flex;
  gap: 4px;
  align-items: center;
  flex: none;
  flex-wrap: wrap;
}

.nav-item {
  padding: 7px 11px;
  font-size: var(--t-mini);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  /* La cible tactile dépasse le texte : sur téléphone, deux pastilles côte à côte
   * se ratent une fois sur trois si elles font 24 px de haut. */
  min-height: 2.25rem;
  display: inline-flex;
  align-items: center;
}

.nav-item:hover { color: var(--encre); }

.nav-actif {
  background: var(--creux);
  color: var(--encre-forte);
}

/* --- Prospection : en-tête --------------------------------------------- */

/* « PIPELINE » au-dessus du titre. La maquette d'Aujourd'hui n'en a pas — la date
 * se suffit —, celle de Prospection en a besoin : « PROSPECTION » seul ne dit pas
 * de quoi on parle. */
.sur-titre {
  font-size: var(--t-mini);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  font-weight: 600;
  margin-bottom: 8px;
}

/* Un nom d'écran est plus long qu'une date : les bornes descendent d'un cran pour
 * que « PROSPECTION » ne se coupe pas sur un téléphone. */
.titre-ecran { font-size: clamp(34px, 7vw, 76px); }

/* --- Prospection : le bloc « à traiter » ------------------------------- */
/* La même forme que « En retard » sur Aujourd'hui, et c'est voulu : la même chose
 * — ce qui attend Chris — au même endroit, en accent, en tête d'écran. */

.retard-large { display: grid; gap: var(--e5); }

.deux-listes {
  display: grid;
  gap: var(--e5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}

/* Ligne de liste sans liseré de couleur : dans ce bloc, la couleur d'étape ne veut
 * rien dire — tout ce qui y figure est à traiter. */
.tache-plate { border-left-color: transparent; }

.lien-fil {
  font-size: var(--t-mini);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  white-space: nowrap;
  /* Le rembourrage fait la cible tactile : le texte « Fil ↗ » seul mesure 30 px de
   * large sur 14 de haut, ce qui se rate au pouce. */
  padding: 10px 0 10px 14px;
}

.lien-fil:hover { color: var(--encre); }

/* --- Prospection : le tableau ----------------------------------------- */
/* `auto-fit` avec un minimum de 250 px : cinq colonnes sur un écran large, une
 * seule sur un téléphone, et les paliers intermédiaires viennent tout seuls. Sur
 * téléphone les cinq étapes s'empilent dans l'ordre du trajet d'une affaire, ce
 * qui est la bonne lecture — pas un tableau à faire défiler de côté. */

.tableau {
  display: grid;
  gap: var(--e1);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  align-items: start;
}

.etape {
  background: var(--surface-creuse);
  padding: var(--e4);
  display: grid;
  gap: var(--e1);
  align-content: start;
  min-height: 200px;
}

.etape-tete { display: grid; gap: 3px; padding: 4px 4px 12px; }

.etape-titre-ligne {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e3);
}

.etape-titre {
  font-size: var(--t-texte);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.etape-nombre {
  font-size: var(--t-texte);
  font-weight: 700;
  color: var(--encre-tenue);
}

.etape-statuts {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

.etape-vide {
  padding: var(--e4) 4px;
  font-size: var(--t-petit);
  color: var(--encre-pale);
}

/* --- Prospection : une fiche ------------------------------------------ */

.fiche {
  background: var(--surface);
  padding: var(--e4);
  display: grid;
  gap: 9px;
  border-left: 3px solid var(--f-neutre);
}

.fiche.accent  { border-left-color: var(--accent-trait); }
.fiche.f-bleu   { border-left-color: var(--f-bleu); }
.fiche.f-violet { border-left-color: var(--f-violet); }
.fiche.f-orange { border-left-color: var(--f-orange); }

.fiche-tete {
  display: flex;
  justify-content: space-between;
  gap: var(--e3);
  align-items: baseline;
}

.fiche-ecole {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.fiche-statut {
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  white-space: nowrap;
}

.fiche-qui {
  font-size: var(--t-texte);
  color: var(--encre-douce);
}

.fiche-ligne {
  display: flex;
  justify-content: space-between;
  gap: var(--e3);
  align-items: baseline;
  flex-wrap: wrap;
}

.fiche-quoi {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.fiche-silence {
  font-size: var(--t-texte);
  font-weight: 600;
  color: var(--accent-texte);
}

.fiche-montant {
  font-size: var(--t-texte);
  font-weight: 600;
  white-space: nowrap;
}

/* Le montant inconnu se DIT. Un blanc à la place d'un montant se lit comme une
 * petite affaire, et c'est le sens d'erreur qui fait négliger un dossier. */
.fiche-note {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

.fiche-pied {
  display: flex;
  justify-content: space-between;
  gap: var(--e3);
  align-items: center;
  padding-top: 4px;
  border-top: 1px solid var(--trait);
}

.fiche-echange {
  font-size: var(--t-petit);
  color: var(--encre-douce);
}

/* Le sens du dernier échange, en une flèche. Entrant en couleur : c'est celui qui
 * demande une réponse, et c'est l'information que Chris cherche sur cet écran. */
.fleche { font-weight: 700; color: var(--encre-tenue); }
.fleche-entrant { color: var(--f-bleu); }

/* --- Prospection : les affaires classées ------------------------------ */
/* Repliées par issue. Treize cartes de plus feraient une colonne quatre fois plus
 * haute que les autres, pour des affaires sur lesquelles il n'y a plus rien à
 * faire — mais les cacher tout à fait ferait perdre le total gagné, qui est la
 * seule bonne nouvelle de l'écran. */

.issue { background: var(--surface); }

.issue-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e3);
  padding: var(--e4);
  cursor: pointer;
  list-style: none;
}

/* Le triangle par défaut de `summary` est retiré des deux côtés : WebKit a son
 * propre pseudo-élément, et n'en retirer qu'un donnerait deux marqueurs sur
 * Safari — donc sur le téléphone de Chris. */
.issue-tete::-webkit-details-marker { display: none; }
.issue-tete::marker { content: ""; }

.issue-quoi { display: grid; gap: 3px; }

.issue-titre {
  font-size: var(--t-base);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.issue-note {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

.issue-compte {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
}

.issue-lignes { padding: 0 var(--e4) 12px; display: grid; }

.issue-ligne {
  display: flex;
  justify-content: space-between;
  gap: var(--e3);
  align-items: baseline;
  padding: 9px 0;
  border-top: 1px solid var(--trait);
}

.issue-qui { display: grid; gap: 2px; min-width: 0; }

.issue-ecole { font-size: 14px; }

.issue-quand {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

.issue-montant {
  font-size: var(--t-texte);
  font-weight: 600;
  white-space: nowrap;
  color: var(--encre-douce);
}

/* --- Planning : barre d'outils ---------------------------------------- */

.outils {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--e4);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--trait);
  padding-bottom: 14px;
}

.periodes { display: flex; gap: var(--e1); flex-wrap: wrap; }

.periode {
  padding: 10px 18px;
  font-size: var(--t-petit);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-tenue);
  /* Cible tactile : quatre commandes côte à côte au pouce, dont deux chevrons de
   * dix pixels de large. Le rembourrage fait le bouton. */
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
}

.periode:hover { color: var(--encre); }

.periode-actif {
  background: var(--f-neutre-pale);
  color: var(--encre);
  font-weight: 600;
}

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

.repere {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-petit);
  color: var(--encre-douce);
}

.repere-filet {
  width: 1px;
  height: 14px;
  background: var(--trait-fort);
}

/* La coche des séances validées d'office. Discrète : elle dit que le système a
 * fait son travail, pas qu'il y a quelque chose à faire. */
.coche { color: var(--encre-tenue); }

/* --- Planning : la grille de la semaine ------------------------------- */
/* `overflow-x` sur un conteneur DÉDIÉ, jamais sur la page : une page qui défile de
 * côté sur téléphone rend le reste de l'écran inutilisable. La grille a une largeur
 * minimale et c'est elle qui défile. */

.defilant {
  overflow-x: auto;
  /* Le défilement horizontal doit rester atteignable au clavier. */
  scrollbar-gutter: stable;
}

.grille-zone {
  min-width: 820px;
  display: grid;
  gap: var(--e1);
}

.grille-entetes,
.grille-corps {
  display: grid;
  /* Rail horaire, cinq jours ouvrés, colonne de week-end. Les deux lignes partagent
   * la même définition : des colonnes qui divergeraient d'un pixel décaleraient les
   * en-têtes des créneaux, et un cours apparaîtrait le mauvais jour. */
  grid-template-columns: 52px repeat(5, minmax(0, 1fr)) 104px;
  column-gap: var(--e1);
}

/* Le corps est UNE seule grille : le rail des heures, les fonds de jour et les
 * créneaux y sont tous des items. Trois grilles distinctes aux gabarits recopiés ne
 * pouvaient s'aligner que par coïncidence — et à l'essai réel, les blocs ne tombaient
 * plus sur les graduations. Ici un créneau et son étiquette d'heure partagent le même
 * `grid-template-rows` : l'alignement est vrai par construction, pas par entretien.
 *
 * Les lignes viennent du bloc de géométrie, qui connaît la fenêtre du jour. */
.grille-corps { position: relative; }

.entete-jour {
  padding: 10px 12px;
  background: var(--surface-creuse);
  display: grid;
  gap: 3px;
}

.entete-nom {
  font-size: var(--t-mini);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-tenue);
}

.entete-numero {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.04em;
}

.entete-heures {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

/* Aujourd'hui : un liseré accent en haut et un fond légèrement relevé. C'est le
 * repère que Chris cherche en premier sur une grille de cinq jours. */
.entete-aujourdhui {
  background: var(--surface);
  border-top: 3px solid var(--accent);
}

.entete-aujourdhui .entete-nom {
  color: var(--accent-texte);
  font-weight: 600;
}

.entete-aujourdhui .entete-heures { color: var(--encre-douce); }

/* Le week-end est en retrait : deux jours presque toujours vides ne doivent pas peser
 * autant que les cinq autres. */
.entete-weekend { background: var(--fond-creux); }
.entete-weekend .entete-nom { color: var(--encre-pale); }
.entete-weekend .entete-numero { color: var(--encre-pale); }

/* L'étiquette d'heure, posée SUR sa graduation. Elle occupe deux lignes de
 * demi-heure — une heure pleine — et son décalage vertical la centre sur le trait. */
.rail-h {
  grid-column: 1;
  /* Un cran plus petit que le reste : à 7 px la demi-heure, une heure pleine fait 14 px
   * et une étiquette de 11 px toucherait la suivante. */
  font-size: var(--t-micro);
  color: var(--encre-pale);
  text-align: right;
  padding-right: 10px;
  transform: translateY(-0.5em);
  line-height: 1;
}

/* Le fond d'un jour, sur toute la hauteur, avec sa trame horaire. Un élément plutôt
 * qu'une bordure par ligne : cinq colonnes × dix heures feraient cinquante div qui ne
 * portent rien. */
.jour-fond {
  grid-row: 1 / -1;
  background-color: var(--grille-fond);
  background-image: repeating-linear-gradient(
    to bottom,
    var(--creux) 0 1px,
    transparent 1px calc(var(--demi-h) * 2));
}

.jour-aujourdhui { background-color: var(--surface-jour); }

.jour-libre {
  grid-row: 1 / -1;
  align-self: center;
  justify-self: center;
  font-size: var(--t-mini);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--encre-pale);
}

/* Un créneau. `left` et `width` viennent du bloc de géométrie et traitent le
 * chevauchement en pistes : deux cours à la même heure se posent côte à côte au lieu
 * de se recouvrir — sans ça, celui du dessous serait purement invisible.
 *
 * `min-width: 0` n'est pas décoratif. La taille minimale automatique d'un item de
 * grille est celle de son contenu MIN-CONTENT : un titre en un seul mot long
 * l'emportait sur `width: 50%`, et la carte débordait sur le jour voisin — c'est
 * exactement ce qu'on a vu à l'essai réel, et seulement quand deux formateurs
 * partagent un créneau, puisque c'est là que la largeur tombe à la moitié. Le mot se
 * coupe désormais plutôt que de pousser la colonne. */
.creneau {
  position: relative;
  z-index: 1;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  overflow-wrap: anywhere;
  background: var(--surface);
  border-left: 4px solid var(--f-neutre);
  padding: 4px 7px;
  margin: 0 2px;
  display: grid;
  gap: 1px;
  align-content: start;
}

.creneau.f-bleu   { border-left-color: var(--f-bleu); }
.creneau.f-vert   { border-left-color: var(--f-vert); }
.creneau.f-orange { border-left-color: var(--f-orange); }
.creneau.f-violet { border-left-color: var(--f-violet); }
.creneau.f-rouge  { border-left-color: var(--f-rouge); }
.creneau.f-jaune  { border-left-color: var(--f-jaune); }

/* La séance choisie, marquée par un contour et non par une couleur : la couleur est
 * déjà prise par le formateur, et lui en superposer une seconde rendrait les deux
 * illisibles. */
.creneau-choisi {
  outline: 2px solid var(--encre-douce);
  outline-offset: -2px;
  background: var(--surface-choisie);
  z-index: 2;
}

.creneau-heure {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--encre-douce);
  white-space: nowrap;
}

.creneau.f-bleu   .creneau-heure { color: var(--f-bleu-texte); }
.creneau.f-vert   .creneau-heure { color: var(--f-vert-texte); }
.creneau.f-orange .creneau-heure { color: var(--f-orange-texte); }
.creneau.f-violet .creneau-heure { color: var(--f-violet-texte); }
.creneau.f-rouge  .creneau-heure { color: var(--f-rouge-texte); }
.creneau.f-jaune  .creneau-heure { color: var(--f-jaune-texte); }

.creneau-titre {
  font-size: var(--t-mini);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.15;
}

.creneau-ou {
  font-size: var(--t-micro);
  color: var(--encre-tenue);
}

/* Sous une certaine largeur, la grille est compacte et un créneau ne peut plus porter
 * trois lignes sans les tronquer au milieu d'un mot. On garde l'heure et le titre, qui
 * suffisent à reconnaître le cours ; le reste est dans le panneau. */
@media (max-width: 63.99rem) {
  .creneau-ou { display: none; }
}

.weekend-zone {
  grid-column: 7;
  grid-row: 1 / -1;
  background: var(--fond-creux);
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--e3);
  padding: 16px 10px;
  text-align: center;
}

.weekend-marque {
  width: 8px;
  height: 8px;
  background: var(--trait-fort);
}

.weekend-texte {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
  line-height: 1.5;
}

/* Une séance le week-end est rare, donc elle se remarque — mais la taire serait le
 * contraire de ce qu'on veut : c'est la plus facile à oublier. */
.weekend-seance {
  width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  background: var(--surface);
  border-left: 4px solid var(--f-neutre);
  padding: 8px 10px;
  display: grid;
  gap: 3px;
  text-align: left;
}

.weekend-seance.f-bleu   { border-left-color: var(--f-bleu); }
.weekend-seance.f-vert   { border-left-color: var(--f-vert); }
.weekend-seance.f-orange { border-left-color: var(--f-orange); }
.weekend-seance.f-violet { border-left-color: var(--f-violet); }
.weekend-seance.f-rouge  { border-left-color: var(--f-rouge); }
.weekend-seance.f-jaune  { border-left-color: var(--f-jaune); }

/* --- Planning : la séance sélectionnée -------------------------------- */

.choisie {
  background: var(--surface);
  border-left: 6px solid var(--f-neutre);
  padding: clamp(16px, 2vw, 24px);
  display: grid;
  gap: 18px;
  /* Repère de défilement : l'ancre amène ici, et le panneau ne doit pas se coller
   * sous le bandeau collant. */
  scroll-margin-top: 5rem;
}

.choisie.f-bleu   { border-left-color: var(--f-bleu); }
.choisie.f-vert   { border-left-color: var(--f-vert); }
.choisie.f-orange { border-left-color: var(--f-orange); }
.choisie.f-violet { border-left-color: var(--f-violet); }
.choisie.f-rouge  { border-left-color: var(--f-rouge); }
.choisie.f-jaune  { border-left-color: var(--f-jaune); }

.choisie-quoi { display: grid; gap: var(--e2); }

.choisie-sur-titre {
  font-size: var(--t-mini);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--encre-tenue);
}

.choisie-titre {
  font-size: var(--t-titre);
  font-weight: 600;
  letter-spacing: -0.03em;
}

.choisie-meta {
  font-size: var(--t-texte);
  color: var(--encre-douce);
}

.choisie-etat {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

/* Dit AVANT le clic ce que `src/outils.py` refuserait après : proposer une action
 * qui sera refusée est pire que ne rien proposer. */
.choisie-verrou {
  font-size: var(--t-petit);
  font-weight: 600;
  color: var(--accent-texte);
}

.choisie-formes {
  display: flex;
  gap: var(--e4);
  flex-wrap: wrap;
  align-items: flex-end;
}

.forme-duree,
.forme-deplacer {
  display: flex;
  gap: var(--e1);
  align-items: flex-end;
  flex-wrap: wrap;
}

/* Assez large pour la date et l'heure natives du navigateur, qui portent leur propre
 * icône de calendrier. */
.champ-date { min-width: 9.5rem; }
.champ-heure { min-width: 6.5rem; }

.bouton-etroit { width: auto; }

/* --- Planning : le mois ---------------------------------------------- */

.mois-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e4);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--trait);
  padding-bottom: 14px;
}

.mois-quoi { display: flex; align-items: baseline; gap: var(--e4); flex-wrap: wrap; }

.mois-titre {
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 700;
  letter-spacing: -0.04em;
}

.mois-detail {
  font-size: var(--t-texte);
  color: var(--encre-tenue);
}

.mois-grille {
  min-width: 760px;
  display: grid;
  /* Sept jours plus une colonne de total. Le total est à droite, où l'œil finit sa
   * ligne — le mettre à gauche demanderait de le lire avant de savoir de quoi il est
   * le total. */
  grid-template-columns: repeat(7, minmax(0, 1fr)) 84px;
  gap: var(--e1);
}

.mois-jour {
  font-size: var(--t-mini);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-pale);
  padding: 0 0 6px 2px;
}

.mois-jour-weekend { color: var(--creux-texte-fin); }
.mois-jour-total { text-align: right; }

.case {
  background: var(--surface-creuse);
  padding: 9px;
  min-height: 92px;
  display: grid;
  gap: 7px;
  align-content: start;
}

/* Les jours des mois voisins restent PRÉSENTS, en retrait. Une grille qui
 * commencerait au 1er décalerait les colonnes, et « mardi » ne serait plus au-dessus
 * des mardis. */
.case-hors { background: var(--fond-creux); }
.case-hors .case-numero { color: var(--f-neutre); }
.case-weekend { background: var(--fond-creux); }

.case-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e2);
}

.case-numero { font-size: var(--t-texte); font-weight: 600; }

.case-heures {
  font-size: var(--t-micro);
  color: var(--encre-pale);
}

.case-barres { display: grid; gap: 3px; }

/* Une barre par séance, largeur proportionnelle à la durée. C'est un lien : cliquer
 * une barre ouvre la séance, comme cliquer un créneau de la semaine. */
.barre {
  height: 5px;
  background: var(--f-neutre);
  /* Cible tactile élargie sans grossir la barre : cinq pixels de haut se ratent au
   * pouce, mais une barre épaisse ferait perdre la lecture de la durée. */
  box-sizing: content-box;
  padding: 4px 0;
  background-clip: content-box;
}

.barre.f-bleu   { background-color: var(--f-bleu); }
.barre.f-vert   { background-color: var(--f-vert); }
.barre.f-orange { background-color: var(--f-orange); }
.barre.f-violet { background-color: var(--f-violet); }
.barre.f-rouge  { background-color: var(--f-rouge); }
.barre.f-jaune  { background-color: var(--f-jaune); }

.case-total {
  padding: 9px 2px;
  text-align: right;
  font-size: var(--t-texte);
  font-weight: 600;
  color: var(--encre-douce);
}

/* Le titre de la séance, pour un lecteur d'écran : une barre sans texte est une
 * information perdue pour qui n'y voit pas. */
.hors-ecran {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Pilotage : ossature ---------------------------------------------- */
/* Trois dispositions, toutes en `auto-fit` : deux cartes côte à côte, une pleine
 * largeur pour le graphe des douze mois, puis trois. Sur téléphone tout s'empile dans
 * l'ordre des six chiffres, qui est celui du raisonnement — combien j'ai vendu, à qui,
 * quand, ce qui vient, ce que ça rapporte, ce qui revient. */

.tete-pilotage { align-items: flex-end; }

.tete-note {
  font-size: var(--t-petit);
  color: var(--encre-pale);
  text-align: right;
  line-height: 1.6;
}

.paire,
.trio {
  display: grid;
  gap: var(--e1);
  align-items: start;
}

.paire { grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr)); }
.trio { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }

/* --- Pilotage : une carte de chiffre ---------------------------------- */

.chiffre {
  background: var(--surface);
  padding: clamp(18px, 2.2vw, 28px);
  display: grid;
  gap: var(--e5);
  align-content: start;
}

.chiffre-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e3);
  flex-wrap: wrap;
}

.chiffre-titre {
  font-size: var(--t-mini);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--titre);
}

/* Le repère — objectif, seuil, exercice comparé. Un indicateur qui montre un écart
 * sans dire à quoi laisse deviner sa propre règle. */
.chiffre-repere {
  font-size: var(--t-mini);
  color: var(--encre-pale);
}

.chiffre-valeur-ligne {
  display: flex;
  align-items: baseline;
  gap: var(--e4);
  flex-wrap: wrap;
}

.chiffre-valeur {
  font-size: clamp(38px, 4.6vw, 58px);
  font-weight: 800;
  letter-spacing: -0.055em;
  line-height: 0.9;
}

/* Les trois cartes du bas portent des chiffres plus courts et disposent de moins de
 * place : la même échelle les ferait passer à la ligne. */
.chiffre-valeur-moyen { font-size: clamp(34px, 4vw, 50px); }

/* L'accent ne dit qu'une chose ici : ce chiffre appelle une décision. Au-dessus du
 * seuil de dépendance, sur la marge la plus faible. Nulle part ailleurs. */
.chiffre-alerte { color: var(--accent-texte); }

.chiffre-precision {
  font-size: 14px;
  color: var(--encre-douce);
}

.chiffre-ecart {
  font-size: var(--t-base);
  font-weight: 600;
  color: var(--f-bleu-texte);
}

.ecart-bas { color: var(--accent-texte); }

/* La note de lecture, saisie par Chris. Le code n'en produit jamais : une phrase
 * engendrée qui aurait l'air d'une analyse serait crue. */
.chiffre-note {
  font-size: var(--t-texte);
  color: var(--encre-douce);
  line-height: 1.5;
  border-top: 1px solid var(--trait);
  padding-top: 14px;
}

.chiffre-note-large { max-width: 62ch; border-top: 0; padding-top: 0; }

/* --- Saisie de la note ---------------------------------------------------
 *
 * L'état précédent disait « elles se saisissent dans Notion, base Notes de pilotage,
 * clé ca ». C'était une fonction morte : Chris n'ouvre pas Notion pour une phrase, et
 * une clé technique n'a rien à faire sous un chiffre.
 *
 * `<details>` fait l'ouverture nativement — il n'y a pas une ligne de JavaScript dans
 * ce projet. Fermé, le pli n'occupe qu'une ligne : c'est la condition pour qu'un écran
 * de six chiffres ne se transforme pas en formulaire. */
.note-bloc { border-top: 1px solid var(--trait); padding-top: 14px; }
.note-bloc .chiffre-note { border-top: 0; padding-top: 0; }

.note-pli { margin-top: 6px; }

.note-ouvrir {
  display: inline-block;
  font-size: var(--t-micro);
  color: var(--encre-pale);
  cursor: pointer;
  /* La cible tactile fait la hauteur d'un doigt sans occuper la place d'un bouton :
   * l'action est secondaire, elle ne doit pas concurrencer le chiffre. */
  padding: 6px 0;
  list-style: none;
}

.note-ouvrir::-webkit-details-marker { display: none; }
.note-ouvrir::before { content: "";}
.note-pli[open] .note-ouvrir { color: var(--encre-douce); }

.note-forme { display: grid; gap: 8px; margin-top: 4px; }

.note-etiquette {
  font-size: var(--t-micro);
  color: var(--encre-pale);
}

.note-champ {
  width: 100%;
  padding: 10px;
  border: 1px solid var(--trait-moyen);
  background: var(--surface);
  color: var(--encre);
  font: inherit;
  font-size: var(--t-petit);
  line-height: 1.5;
  /* Verticalement seulement : `resize: both` laisse élargir le champ au-delà de la
   * carte, et la mise en page se casse sans qu'on comprenne d'où ça vient. */
  resize: vertical;
}

.note-pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* Le bouton neutre est pleine largeur ailleurs — c'est une action principale. Ici il
 * partage sa ligne avec l'explication, et pleine largeur la repousserait en dessous. */
.note-pied .bouton-neutre { width: auto; }

.note-aide { font-size: var(--t-micro); color: var(--encre-pale); }

/* La phrase DÉRIVÉE de la marge. Distincte de la note de Chris — un filet accent plutôt
 * qu'un filet neutre — parce qu'elle vient du calcul : la confondre avec une note
 * saisie brouillerait exactement la distinction que cet écran tient. */
.chiffre-derive {
  font-size: var(--t-texte);
  color: var(--encre);
  line-height: 1.5;
  border-top: 1px solid var(--trait);
  padding-top: 14px;
}

/* L'âge de la donnée. Ce qui remplace le « calculé à 06:00 » de la maquette : il n'y a
 * pas de traitement de nuit, les chiffres se calculent à la lecture. */
.chiffre-age {
  font-size: var(--t-mini);
  color: var(--encre-pale);
  line-height: 1.5;
}

.chiffre-pied {
  display: flex;
  justify-content: space-between;
  gap: var(--e4);
  flex-wrap: wrap;
  align-items: baseline;
}

.chiffre-vide { display: grid; gap: var(--e2); }

.chiffre-vide-titre {
  font-size: clamp(18px, 2vw, 22px);
  font-weight: 600;
  letter-spacing: -0.03em;
}

/* --- Pilotage : la jauge du chiffre d'affaires ------------------------ */

.jauge {
  display: flex;
  height: 34px;
  gap: var(--e1);
}

.jauge-part { display: block; }

/* Le reste prend la place libre : sans objectif il n'y a pas de reste, donc pas de
 * segment — et la jauge devient une répartition entre réalisé et engagé. */
.jauge-reste { flex: 1; background: var(--jauge-vide); }

.jauge-legende {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 12px;
}

.cle {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: var(--t-texte);
  color: var(--encre-tenue);
}

.cle strong { font-weight: 600; color: var(--encre); }

.pastille { width: 10px; height: 10px; flex: none; }
.pastille-reste { background: var(--jauge-vide); }
.pastille-avant { background: var(--comparaison); }

.pastille.f-bleu       { background: var(--f-bleu); }
.pastille.f-vert       { background: var(--f-vert); }
.pastille.f-orange     { background: var(--f-orange); }
.pastille.f-violet     { background: var(--f-violet); }
.pastille.f-rouge      { background: var(--f-rouge); }
.pastille.f-jaune      { background: var(--f-jaune); }
.pastille.f-neutre     { background: var(--f-neutre); }
.pastille.f-bleu-pale  { background: var(--f-bleu-terne); }

.jauge-realise.f-bleu      { background: var(--f-bleu); }
.jauge-engage.f-bleu-pale  { background: var(--f-bleu-terne); }

/* --- Pilotage : les rangs de dépendance ------------------------------- */
/* Les barres sont en proportion de la PREMIÈRE, pas du total : la question posée est
 * « à quel point la première écrase les autres ». En proportion du total, une première
 * école à 38 % donnerait une barre courte et la comparaison se perdrait. */

.rangs { display: grid; gap: 9px; }

.rang {
  display: grid;
  grid-template-columns: minmax(80px, 120px) 1fr auto;
  gap: 12px;
  align-items: center;
}

.rang-nom {
  font-size: var(--t-texte);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rang-autres { color: var(--encre-tenue); }

.rang-piste {
  display: block;
  height: 12px;
  background: var(--jauge-vide);
}

.rang-barre { display: block; height: 12px; }
.rang-tete { background: var(--accent-trait); }
.rang-suite { background: var(--comparaison-forte); }
.rang-reste { background: var(--comparaison); }

.rang-part {
  font-size: var(--t-texte);
  font-weight: 600;
  width: 42px;
  text-align: right;
}

/* --- Pilotage : les douze mois --------------------------------------- */

.colonnes {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(3px, 0.6vw, 8px);
  align-items: end;
  height: 170px;
}

.colonne-mois {
  display: grid;
  gap: 8px;
  align-content: end;
  height: 100%;
}

.colonne-valeur {
  font-size: var(--t-mini);
  text-align: center;
  color: var(--encre-tenue);
}

/* Les deux composantes empilées. La hauteur de chacune vient du bloc de géométrie ;
 * le conteneur donne l'assise et la direction. */
.colonne-empilee {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
}

.colonne-part { display: block; }
.colonne-fait { background: var(--comparaison-forte); }

/* L'engagé, plus pâle. Les derniers mois d'une année scolaire sont presque entièrement
 * engagés : les confondre avec du réalisé ferait lire un chiffre d'affaires acquis. */
.colonne-prevu { background: var(--comparaison); }
.colonne-part.f-bleu { background: var(--f-bleu); }

.colonnes-etiquettes {
  height: auto;
  align-items: baseline;
  border-top: 1px solid var(--trait);
  padding-top: 10px;
}

.colonne-nom {
  font-size: var(--t-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  color: var(--encre-pale);
}

.colonne-nom-courant { color: var(--encre-douce); font-weight: 600; }

/* --- Pilotage : l'engagement comparé --------------------------------- */
/* Les deux années partagent la même échelle, sinon la comparaison ne veut rien dire —
 * c'est le défaut classique d'un graphe à deux axes. */

.paires { display: grid; gap: 12px; }

.paire-mois {
  display: grid;
  grid-template-columns: 46px 1fr;
  gap: 12px;
  align-items: center;
}

.paire-nom {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.paire-barres { display: grid; gap: 3px; }

.paire-barre { display: block; height: 13px; }
.paire-barre.f-bleu { background: var(--f-bleu); }
.paire-avant { background: var(--comparaison); }

/* --- Pilotage : la marge par formateur ------------------------------- */

.marges { display: grid; gap: 14px; }

.marge { display: grid; gap: var(--e2); }

.marge-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--e3);
}

.marge-nom {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}

.marge-taux {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.marge-piste { display: flex; height: 10px; gap: var(--e1); }
.marge-part { display: block; }
.marge-cout { background: var(--comparaison); }

.marge-part.f-bleu   { background: var(--f-bleu); }
.marge-part.f-vert   { background: var(--f-vert); }
.marge-part.f-orange { background: var(--f-orange); }
.marge-part.f-violet { background: var(--f-violet); }
.marge-part.f-rouge  { background: var(--f-rouge); }
.marge-part.f-jaune  { background: var(--f-jaune); }
.marge-part.f-neutre { background: var(--f-neutre); }

.marge-detail {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

/* --- Pilotage : la reconduction -------------------------------------- */
/* Un écusson par école de l'exercice précédent. Comptables d'un coup d'œil jusqu'à une
 * quinzaine, ce qui couvre l'activité de Chris ; au-delà le chiffre suffit et la
 * grille se resserre sans casser. */

.ecussons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18px, 1fr));
  gap: 3px;
  height: 42px;
}

.ecusson { display: block; }
.ecusson.f-bleu { background: var(--f-bleu); }
.ecusson-perdu { background: var(--comparaison); }

.perdues { display: grid; gap: var(--e1); }

.perdue {
  background: var(--surface-creuse);
  padding: 12px 14px;
  display: flex;
  justify-content: space-between;
  gap: var(--e3);
  align-items: baseline;
  flex-wrap: wrap;
}

.perdue-nom { font-size: 14px; }

.perdue-montant {
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

/* --- Connexion -------------------------------------------------------- */
/* La trame de créneaux n'apparaît que là : c'est la première chose que Chris voit,
 * et elle annonce le sujet — des créneaux, pas des tableaux. */

.page-connexion {
  display: grid;
  place-items: center;
  background-image:
    repeating-linear-gradient(to bottom, transparent 0, transparent 63px,
      var(--trait) 63px, var(--trait) 64px),
    repeating-linear-gradient(to right, transparent 0, transparent 119px,
      var(--trait) 119px, var(--trait) 120px);
  background-position: center;
}

.page-connexion .contenu {
  max-width: 26rem;
  padding: var(--e7);
}

.carte {
  background: var(--surface);
  border: 1px solid var(--trait);
  padding: var(--e7);
  display: grid;
  gap: var(--e4);
}

.titre-connexion {
  font-size: clamp(32px, 6vw, 44px);
  line-height: 0.9;
  font-weight: 800;
  letter-spacing: -0.05em;
}

.sous-titre { color: var(--encre-tenue); font-size: var(--t-texte); }

.formulaire { display: grid; gap: var(--e4); margin-top: var(--e3); }

.champ { display: grid; gap: var(--e2); }

.champ-libelle {
  font-size: var(--t-mini);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-tenue);
}

.champ-saisie {
  width: 100%;
  padding: 12px 14px;
  background: var(--fond);
  border: 1px solid var(--trait-fort);
  /* 16 px minimum : en dessous, iOS zoome sur le champ au premier appui et la
   * page se met à défiler latéralement. */
  font-size: max(16px, var(--t-base));
}

.champ-saisie:focus { border-color: var(--accent); background: var(--surface); }

.aide { font-size: var(--t-petit); color: var(--encre-tenue); }

.bouton-principal {
  min-height: 2.75rem;
  padding: 12px 16px;
  border: 0;
  background: var(--accent);
  color: var(--accent-clair);
  font-size: var(--t-texte);
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.titre-page {
  font-size: clamp(28px, 5vw, 44px);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
}

/* --- Actions ----------------------------------------------------------- */
/* Trois niveaux, et l'écart entre eux est la seule hiérarchie : l'action attendue
 * est pleine, l'alternative est grise, la sortie est un simple texte. Aucune
 * n'est décorée — ce sont des gestes, pas des ornements. */

.bouton-action {
  min-height: 2.75rem;
  padding: 12px 16px;
  border: 0;
  width: 100%;
  background: var(--accent);
  color: var(--accent-clair);
  font-size: var(--t-texte);
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
}

/* Pleine largeur comme `.bouton-action`, mais neutre. La maquette distingue les
 * deux, et la distinction porte du sens : l'accent va à ce qui rend une séance
 * facturable. Tout mettre en terre cuite rendait l'accent muet. */
.bouton-neutre {
  min-height: 2.75rem;
  padding: 12px 16px;
  border: 0;
  width: 100%;
  background: var(--bouton-fond);
  color: var(--bouton-encre);
  font-size: var(--t-petit);
  font-weight: 500;
  cursor: pointer;
}

.bouton-secondaire {
  min-height: 2.75rem;
  padding: 12px 16px;
  border: 0;
  background: var(--creux);
  color: var(--encre-douce);
  font-size: var(--t-texte);
  cursor: pointer;
}

.bouton-tertiaire {
  min-height: 2.5rem;
  padding: 8px 0;
  border: 0;
  background: none;
  color: var(--encre-tenue);
  font-size: var(--t-petit);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.bouton-tertiaire:hover { color: var(--accent-texte); }

/* Les deux actions d'un retard, côte à côte : « Marquer fait » prend la place,
 * « Demain » ce qu'il lui faut. C'est la répartition de la maquette. */
.retard-actions {
  display: flex;
  gap: var(--e1);
  margin-top: var(--e3);
}

.retard-actions form:first-child { flex: 1; }

/* Le formulaire de confirmation : le champ et le bouton sur une ligne. La saisie
 * est étroite — une durée fait trois caractères — et le bouton prend le reste. */
.confirmer-forme {
  display: flex;
  align-items: flex-end;
  gap: var(--e1);
  margin-top: var(--e2);
}

.confirmer-forme .bouton-action { flex: 1; }

.duree-champ {
  display: grid;
  gap: 4px;
  flex: none;
}

.duree-libelle {
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-tenue);
}

.duree-saisie {
  width: 5.5rem;
  padding: 12px 10px;
  background: var(--fond);
  border: 1px solid var(--trait-fort);
  /* 16 px minimum : en dessous, iOS zoome au premier appui. */
  font-size: max(16px, var(--t-base));
  font-weight: 600;
  text-align: center;
}

.duree-saisie:focus { border-color: var(--accent); background: var(--surface); }

/* --- Message d'après-action -------------------------------------------- */
/* Un filet accent et rien de plus : il informe, il n'alerte pas. Le distinguer de
 * `.alerte`, qui signale un écran incomplet, évite de crier pour un succès. */

.message {
  padding: 12px 14px;
  background: var(--surface);
  border-left: 3px solid var(--f-vert);
  font-size: var(--t-texte);
  scroll-margin-top: 5rem;
}

/* Un REFUS ne se lit pas comme une réussite. Le vert du message de succès faisait
 * passer « durée nulle refusée » pour une confirmation, et l'écran fait quatre hauteurs
 * : le bandeau restait hors du champ de vision pendant que Chris regardait son
 * formulaire.
 *
 * Trois choses, donc, et les trois comptent : le rouge, le poids, et le COLLANT. Il
 * suit le défilement juste sous le bandeau, donc il reste visible où que Chris se
 * trouve dans la page. L'action y ramène en plus par une ancre. */
.message-refus {
  position: sticky;
  top: 3.25rem;
  z-index: 4;
  background: var(--refus-fond);
  border-left: 4px solid var(--refus-trait);
  color: var(--refus-encre);
  font-weight: 600;
}

/* --- Revenir sur une validation d'office ------------------------------- */
/* Traitement délibérément discret : c'est le cas RARE. Le mode auto valide les
 * cours du jour à 19 h et Chris ne signale que l'exception — cette liste ne doit
 * pas donner l'impression qu'il y a quelque chose à faire. D'où le repli, l'absence
 * de fond, et un lien plutôt qu'un bouton. */

.revenir {
  margin-top: var(--e3);
  padding-top: var(--e3);
  border-top: 1px solid var(--trait);
}

.validees {
  display: grid;
  gap: var(--e1);
  margin-top: var(--e3);
}

.validee {
  display: flex;
  align-items: baseline;
  gap: var(--e3);
  flex-wrap: wrap;
  padding: var(--e2) 0;
  border-bottom: 1px solid var(--trait);
  font-size: var(--t-petit);
  color: var(--encre-tenue);
}

.validee-quand {
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--encre-douce);
  flex: none;
}

.validee-quoi { flex: 1; min-width: 140px; overflow-wrap: anywhere; }

.validee-duree { flex: none; font-weight: 600; color: var(--encre-douce); }

/* Un lien, pas un bouton : il n'a ni fond, ni bordure, ni hauteur de cible
 * tactile pleine. C'est voulu — un bouton appellerait le clic. */
.lien-discret {
  border: 0;
  background: none;
  padding: 0;
  color: var(--encre-tenue);
  font-size: var(--t-petit);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  flex: none;
}

.lien-discret:hover { color: var(--accent-texte); }

/* --- Actions compactes sur une ligne de rappel ------------------------- */
/* Sur les rappels du jour comme sur les retards : l'asymétrie se lirait comme un
 * défaut. En version texte plutôt qu'en boutons pleins — la ligne est dense, et deux
 * boutons y prendraient plus de place que le rappel lui-même. */

.tache { align-items: center; }

.tache-corps {
  flex: 1;
  min-width: 0;
  display: flex;
  justify-content: space-between;
  gap: var(--e4);
  align-items: baseline;
  flex-wrap: wrap;
}

.tache-actions {
  display: flex;
  gap: var(--e3);
  flex: none;
}

.lien-action {
  border: 0;
  background: none;
  padding: 6px 0;
  color: var(--encre-tenue);
  font-size: var(--t-mini);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.lien-action:hover { color: var(--accent-texte); }

/* ======================================================================
   ÉCRAN RÉGLAGES
   ======================================================================
   Ce que Chris change lui-même. Avant, chaque délai demandait un SSH et un
   redémarrage.

   Un formulaire par réglage, et aucun script : les interrupteurs sont des boutons
   d'envoi, les jours des cases à cocher, les choix des boutons radio. Tout ce qui
   ressemble ici à un composant est un élément de formulaire natif — c'est ce qui
   permet à cet écran d'exister dans un projet sans Node ni étape de construction. */

.bandeau-secondaire {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* Le lien est un `<a>`, le bouton de déconnexion un `<button>` : sans ça, le
 * soulignement du navigateur les désalignerait de deux pixels. */
.bandeau-secondaire a { text-decoration: none; display: inline-block; }

.reglages-tete { margin-top: var(--e4); }

/* L'origine des valeurs, dite et non supposée. Sans cette ligne, une panne de Notion
 * laisserait croire que l'écran montre la valeur effective alors qu'il montre la
 * dernière connue — le mensonge exact que cet écran doit éviter. */
.reglages-source {
  font-size: var(--t-micro);
  color: var(--encre-pale);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.reglages-panne {
  padding: 12px 14px;
  background: var(--refus-fond);
  border-left: 3px solid var(--refus-trait);
  color: var(--refus-encre);
  font-size: var(--t-petit);
  line-height: 1.5;
}

.reglages-groupe { margin-top: var(--e7); }

.reglages-groupe-tete {
  padding-bottom: var(--e3);
  border-bottom: 1px solid var(--trait-moyen);
}

.reglages-groupe-sous {
  margin-top: 6px;
  font-size: var(--t-petit);
  color: var(--encre-douce);
  line-height: 1.55;
  max-width: 68ch;
}

/* Une ligne par réglage. Empilé sur mobile, en deux colonnes au-delà : l'explication
 * à gauche, le geste à droite. Le geste ne passe jamais AVANT l'explication dans
 * l'ordre du document — un interrupteur qu'on atteint avant d'avoir lu ce qu'il
 * déclenche est un interrupteur qu'on actionne sans savoir. */
.reglage {
  display: grid;
  gap: var(--e3);
  padding: var(--e4) 0;
  border-bottom: 1px solid var(--trait);
}

.reglage-libelle {
  font-size: var(--t-texte);
  font-weight: 600;
  color: var(--encre);
}

.reglage-explication {
  margin-top: 4px;
  font-size: var(--t-petit);
  color: var(--encre-douce);
  line-height: 1.55;
  max-width: 62ch;
}

/* Ce que le réglage NE fait pas. En italique et non en alerte : c'est une précision,
 * pas un problème — mais elle doit se lire au moment de décider. */
.reglage-avertissement {
  margin-top: 6px;
  font-size: var(--t-micro);
  color: var(--encre-pale);
  font-style: italic;
  line-height: 1.5;
  max-width: 62ch;
}

.reglage-illisible {
  margin-top: 6px;
  padding: 8px 10px;
  background: var(--refus-fond);
  color: var(--refus-encre);
  font-size: var(--t-micro);
  line-height: 1.5;
}

.reglage-agir {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* « actif » / « éteint », écrit. Un interrupteur dont l'état ne se lit qu'à la
 * couleur du bouton se lit à l'envers une fois sur deux. */
.reglage-etat {
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-pale);
  padding: 4px 9px;
  background: var(--f-neutre-pale);
}

.reglage-etat-actif {
  background: var(--f-vert-pale);
  color: var(--f-vert-texte);
}

.reglage-forme {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.champ-reglage {
  padding: 9px 10px;
  border: 1px solid var(--trait-moyen);
  background: var(--surface);
  color: var(--encre);
  font: inherit;
  font-size: var(--t-petit);
  /* Assez large pour « 3,7,15 » sans occuper la ligne : un champ pleine largeur
   * repousserait le bouton en dessous et ferait croire à deux gestes. */
  width: 9ch;
}

.champ-nombre { width: 7ch; }

/* `input[type=time]` ignore la largeur en `ch` sur certains navigateurs et rend un
 * champ deux fois trop large. Fixé en `em`, où il se comporte. */
input[type="time"].champ-reglage { width: 8em; }

.reglage-unite {
  font-size: var(--t-micro);
  color: var(--encre-pale);
}

/* Les sept jours et les deux choix : des `fieldset` sans bordure. La bordure par
 * défaut du navigateur dessinerait un cadre que rien d'autre sur cet écran n'a. */
.jours, .choix {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  border: 0;
  padding: 0;
  margin: 0;
}

.choix { gap: 14px; }

/* La légende porte le nom du réglage pour les lecteurs d'écran : sept cases nommées
 * « lun » à « dim » ne disent pas de quoi elles règlent les jours. Masquée à l'œil,
 * qui a le libellé juste à gauche — et masquée sans `display:none`, qui la
 * retirerait aussi de l'arbre d'accessibilité. */
.jours-legende {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.jour-case, .choix-case {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* La cible tactile fait la hauteur d'un doigt : ces cases se cochent sur un
   * téléphone, entre deux cours. */
  min-height: 2.5rem;
  padding: 0 6px;
  font-size: var(--t-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--encre-douce);
  cursor: pointer;
}

.choix-case {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--t-petit);
}

.reglage-defaut {
  font-size: var(--t-micro);
  color: var(--encre-pale);
  line-height: 1.5;
}

.reglage-origine { font-style: italic; }

/* La confirmation d'un interrupteur qui écrit vers l'extérieur. En accent, dépliée
 * sur place : Chris doit lire ce qui partira et vers qui AVANT de le déclencher d'un
 * tap. Elle n'apparaît que dans le sens de l'allumage. */
.reglage-confirme {
  flex-basis: 100%;
  padding: 12px 14px;
  background: var(--surface-choisie);
  border-left: 3px solid var(--accent);
}

.reglage-confirme-texte {
  font-size: var(--t-petit);
  color: var(--encre);
  line-height: 1.55;
  max-width: 62ch;
}

.reglage-confirme-boutons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
}

.reglage-confirme-boutons .bouton-action { width: auto; }

.reglages-ailleurs {
  margin-top: var(--e7);
  padding-top: var(--e4);
  border-top: 1px solid var(--trait-moyen);
}

.reglages-ailleurs .reglages-groupe-sous { margin-top: var(--e3); }

/* Deux colonnes seulement quand il y a de la place. En dessous, l'explication et le
 * geste s'empilent — l'inverse serait un champ de 4 ch à côté d'un paragraphe. */
@media (min-width: 720px) {
  .reglage {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: var(--e5);
  }

  .reglage-agir { justify-content: flex-end; }
  .reglage-defaut { flex-basis: 100%; text-align: right; }
  .reglage-confirme-boutons { justify-content: flex-end; }
}

/* ── L'écran d'une proposition reçue (#13) ─────────────────────────────────
   Même grammaire que les quatre autres écrans : les jetons ci-dessus, aucune
   couleur en dur, aucune police de plus. Ce qui est propre à cet écran, c'est
   le TABLEAU — douze lignes qu'on corrige une à une —, et la hiérarchie entre
   ce qui bloque et ce qui se dit seulement.

   Aucun script : ce sont des `<form>`, des `<select>` et un `<details>`. */

.proposition-tete { margin: 1.5rem 0; }

.proposition-chiffres {
  display: flex; flex-wrap: wrap; gap: 2rem;
  padding: 1rem 1.25rem;
  background: var(--surface-creuse);
  border: 1px solid var(--trait);
  border-radius: 6px;
}
.proposition-chiffres dt {
  font-size: 0.8rem; color: var(--encre-tenue);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.proposition-chiffres dd {
  margin: 0.15rem 0 0; font-size: 1.35rem; color: var(--titre);
  font-variant-numeric: tabular-nums;
}

/* Les bloquants portent la couleur de refus, les signaux celle de l'accent.
   La distinction est dans la couleur ET dans le titre : « ce qui empêche de
   valider » contre « à regarder ». Une seule des deux ferait deviner. */
.proposition-bloquants, .proposition-signaux {
  margin: 1.25rem 0; padding: 0.9rem 1.1rem;
  border-radius: 6px; border-left: 3px solid;
}
.proposition-bloquants {
  background: var(--refus-fond); border-color: var(--refus-trait);
  color: var(--refus-encre);
}
.proposition-signaux {
  background: var(--accent-clair); border-color: var(--accent-trait);
  color: var(--encre-douce);
}
.proposition-bloquants h2, .proposition-signaux h2 {
  font-size: 0.9rem; margin: 0 0 0.4rem;
  text-transform: uppercase; letter-spacing: 0.04em;
}
.proposition-bloquants ul, .proposition-signaux ul {
  margin: 0; padding-left: 1.1rem;
}
.proposition-bloquants li, .proposition-signaux li { margin: 0.2rem 0; }

/* Une ligne = un formulaire. En grille souple plutôt qu'en `<table>` : sur un
   téléphone, un tableau de sept colonnes déborde ou devient illisible, et cet
   écran s'ouvre souvent depuis Telegram. */
.ligne-proposee {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem;
  padding: 0.85rem 1rem; margin-bottom: 0.6rem;
  background: var(--surface);
  border: 1px solid var(--trait); border-radius: 6px;
}
.ligne-signalee { border-left: 3px solid var(--accent-trait); }
.ligne-rang {
  flex: 0 0 100%; margin: 0 0 0.2rem;
  font-size: 0.8rem; color: var(--encre-tenue);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.ligne-faite {
  margin-left: 0.5rem; color: var(--accent-texte); text-transform: none;
  letter-spacing: 0;
}
.ligne-proposee label {
  display: flex; flex-direction: column; gap: 0.2rem;
  font-size: 0.8rem; color: var(--encre-tenue);
}
.ligne-proposee input, .ligne-proposee select {
  padding: 0.35rem 0.45rem; font-size: 0.95rem;
  color: var(--encre); background: var(--surface);
  border: 1px solid var(--trait-fort); border-radius: 4px;
}
.ligne-proposee input[type="text"] { min-width: 9rem; }
.ligne-anomalie {
  flex: 0 0 100%; margin: 0.3rem 0 0;
  font-size: 0.85rem; color: var(--encre-douce);
}
.ligne-anomalie-bloquante { color: var(--refus-encre); }

.proposition-fin { margin: 2rem 0 3rem; }
.proposition-fin .note-bouton {
  margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--encre-tenue);
}
.proposition-fin button[disabled] {
  opacity: 0.45; cursor: not-allowed;
}

/* Replié, et discret. C'est un geste destructeur : il doit être atteignable
   sans être voisin du bouton de validation. */
.proposition-jeter { margin-top: 2rem; }
.proposition-jeter summary {
  cursor: pointer; font-size: 0.9rem; color: var(--encre-tenue);
}
.proposition-jeter p {
  margin: 0.6rem 0; font-size: 0.9rem; color: var(--encre-douce);
  max-width: 46rem;
}

/* ── La page détaillée d'une opportunité ──────────────────────────────────
   Mêmes jetons que le reste, aucune couleur en dur. Ce qui est propre à cet
   écran, c'est la FRISE des échanges : une liste verticale, du plus récent au
   plus ancien, où le détail dicté est le texte qui compte. */

.opp-objet {
  margin: 0.3rem 0 0; color: var(--encre-douce); font-size: 1.05rem;
}

.opp-tete { margin: 1.5rem 0; }
.opp-chiffres {
  display: flex; flex-wrap: wrap; gap: 2rem;
  padding: 1rem 1.25rem;
  background: var(--surface-creuse);
  border: 1px solid var(--trait); border-radius: 6px;
}
.opp-chiffres dt {
  font-size: 0.8rem; color: var(--encre-tenue);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.opp-chiffres dd { margin: 0.15rem 0 0; color: var(--titre); font-size: 1.05rem; }

.opp-liens { display: flex; gap: 1rem; margin: 0.8rem 0 0; flex-wrap: wrap; }

.fiche-proposition {
  display: inline-block; margin-top: 0.5rem;
  font-size: 0.85rem; font-weight: 600;
  color: var(--accent-texte); text-decoration: none;
}
.fiche-proposition:hover { text-decoration: underline; }

/* Le lien sur le nom de l'école, dans la carte du tableau. Il ne doit pas se
   lire comme un lien : la carte reste une carte, et souligner le nom la
   ferait paraître cliquable partout. */
a.fiche-ecole { color: inherit; text-decoration: none; }
a.fiche-ecole:hover { text-decoration: underline; }

.opp-suite {
  margin: 1.25rem 0; padding: 0.9rem 1.1rem;
  background: var(--accent-clair); border-left: 3px solid var(--accent-trait);
  border-radius: 6px; color: var(--encre-douce);
}
.opp-suite h2 {
  font-size: 0.9rem; margin: 0 0 0.4rem;
  text-transform: uppercase; letter-spacing: 0.04em;
}
.opp-suite p { margin: 0.2rem 0; }

.opp-histoire { margin: 2rem 0 3rem; }
.echanges { list-style: none; margin: 0; padding: 0; }
.echange {
  padding: 0.8rem 0 0.8rem 1rem;
  border-left: 2px solid var(--trait-fort);
}
.echange + .echange { border-top: 1px solid var(--trait); }
.echange-tete {
  display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
  margin: 0;
}
.echange-date {
  color: var(--titre); font-variant-numeric: tabular-nums; font-weight: 600;
}
.echange-type { color: var(--encre-douce); font-size: 0.9rem; }
.echange-resultat {
  font-size: 0.8rem; color: var(--encre-tenue);
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--trait-fort); border-radius: 999px;
}
/* Le détail dicté. C'est le texte de Chris, et c'est lui qui rend une relance
   pertinente : il a la même taille que le corps, pas celle d'une annotation. */
.echange-detail {
  margin: 0.35rem 0 0; color: var(--encre); max-width: 46rem;
}

/* ── Écran Proposition : ajouts après le premier essai réel ──────────────── */

/* Le module sous le nom de l'école : c'est l'école qui identifie la
   proposition, le module qui distingue les affaires d'une même école. */
.prop-module {
  margin: 0.3rem 0 0; color: var(--encre-douce); font-size: 1.05rem;
}

/* Le vide entre le bandeau des volumes et le bloc suivant était trop grand :
   les deux se lisent ensemble — combien est annoncé, et ce qui cloche. */
.proposition-tete { margin: 1.25rem 0 0.75rem; }
.proposition-bloquants, .proposition-signaux { margin: 0.75rem 0; }

/* Les actions groupées. Visuellement en retrait des lignes : ce n'est pas un
   cours, c'est un outil pour les remplir. */
.prop-groupe {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem;
  margin: 0 0 1rem; padding: 0.85rem 1rem;
  background: var(--surface-creuse);
  border: 1px dashed var(--trait-fort); border-radius: 6px;
}
.prop-groupe legend {
  padding: 0 0.4rem; font-size: 0.8rem; color: var(--encre-tenue);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.prop-groupe label {
  display: flex; flex-direction: column; gap: 0.2rem;
  font-size: 0.8rem; color: var(--encre-tenue);
}
.prop-groupe input, .prop-groupe select {
  padding: 0.35rem 0.45rem; font-size: 0.95rem;
  color: var(--encre); background: var(--surface);
  border: 1px solid var(--trait-fort); border-radius: 4px;
}
.prop-groupe-note {
  flex: 0 0 100%; margin: 0.2rem 0 0;
  font-size: 0.8rem; color: var(--encre-tenue);
}

/* Une croix, pas « ENREGISTRER CE COURS » douze fois. Discrète mais atteignable
   au doigt : cet écran s'ouvre depuis Telegram, donc souvent sur téléphone. */
.ligne-retirer {
  margin-left: auto; padding: 0.35rem 0.55rem;
  font-size: 0.95rem; line-height: 1;
  color: var(--encre-tenue); background: transparent;
  border: 1px solid var(--trait-fort); border-radius: 4px; cursor: pointer;
}
.ligne-retirer:hover {
  color: var(--refus-encre); border-color: var(--refus-trait);
}

.proposition-fin { display: flex; flex-wrap: wrap; gap: 1rem;
                   align-items: center; }
.proposition-fin .note-bouton { flex: 0 0 100%; }

/* ── Noter un échange depuis la page d'une affaire ───────────────────────── */

/* Replié : l'écran sert d'abord à LIRE — c'est ce qu'on vient chercher avant de
   décrocher son téléphone. Un formulaire déployé en tête ferait de la saisie
   l'objet de la page. */
.opp-noter { margin: 1.5rem 0; }
.opp-noter summary {
  cursor: pointer; font-size: 0.9rem; font-weight: 600;
  color: var(--accent-texte);
}
.opp-noter form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem;
  margin-top: 0.8rem; padding: 0.9rem 1.1rem;
  background: var(--surface-creuse);
  border: 1px solid var(--trait); border-radius: 6px;
}
.opp-noter label {
  display: flex; flex-direction: column; gap: 0.2rem;
  font-size: 0.8rem; color: var(--encre-tenue);
}
.opp-noter select, .opp-noter textarea {
  padding: 0.35rem 0.45rem; font-size: 0.95rem;
  font-family: inherit;
  color: var(--encre); background: var(--surface);
  border: 1px solid var(--trait-fort); border-radius: 4px;
}
/* Le détail prend toute la largeur : c'est le champ qui compte, et c'est lui
   qu'on relira avant de rappeler. */
.opp-noter .opp-detail { flex: 0 0 100%; }
.opp-noter textarea { width: 100%; resize: vertical; }
.opp-noter-note {
  flex: 0 0 100%; margin: 0.2rem 0 0;
  font-size: 0.8rem; color: var(--encre-tenue);
}

/* Une affaire close : le refus est dit, et le chemin donné. */
.opp-close {
  margin: 1.5rem 0; padding: 0.9rem 1.1rem;
  background: var(--surface-creuse); border-left: 3px solid var(--trait-fort);
  border-radius: 6px; color: var(--encre-douce); max-width: 46rem;
}

/* ── L'âge des données, dans le bandeau ──────────────────────────────────
   Discret quand tout va bien : c'est une information, pas une alerte. Il ne
   devient voyant qu'au-delà du seuil, où il cesse d'informer pour avertir. */

.fraicheur {
  font-size: 0.8rem; color: var(--encre-tenue);
  white-space: nowrap; cursor: help;
}
.fraicheur-retard {
  color: var(--refus-encre); font-weight: 600;
  padding: 0.1rem 0.45rem;
  background: var(--refus-fond);
  border: 1px solid var(--refus-trait); border-radius: 999px;
}

/* ── Une proposition acceptée : l'écran change de nature ─────────────────
   Ce n'est plus un formulaire. Un bandeau plus voyant aurait traité le
   symptôme ; ce qui répond vraiment, c'est que l'écran dise ce qui existe
   maintenant et où le retrouver. */

.prop-faite {
  margin: 1.5rem 0; padding: 1.1rem 1.25rem;
  background: var(--accent-clair);
  border-left: 4px solid var(--accent-trait); border-radius: 6px;
  max-width: 46rem;
}
.prop-faite h2 {
  margin: 0 0 0.5rem; font-size: 1.15rem; color: var(--titre);
}
.prop-faite p { margin: 0.4rem 0; color: var(--encre); }
.prop-faite-liens { display: flex; gap: 1.5rem; margin-top: 0.8rem; flex-wrap: wrap; }
.prop-faite-liens a { color: var(--accent-texte); font-weight: 600; }

.prop-recap { list-style: none; margin: 0; padding: 0; }
.prop-recap li {
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  padding: 0.55rem 0; border-bottom: 1px solid var(--trait);
}
.prop-recap-quand {
  min-width: 11rem; color: var(--titre); font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.prop-recap-quoi { flex: 1 1 14rem; color: var(--encre); }
.prop-recap-duree { color: var(--encre-tenue); font-size: 0.9rem; }
/* Une ligne sans séance après validation : la création s'est arrêtée en chemin.
   Le dire sur la ligne plutôt que de laisser croire que tout est passé. */
.prop-recap-manque {
  flex: 0 0 100%; color: var(--refus-encre); font-size: 0.85rem;
}

/* Ce que l'extraction n'a pas pu faire. En tête et lisible : une proposition
   sans ligne s'affiche autrement vide, et un écran vide se lit comme une panne
   plutôt que comme « le mail ne donnait pas de dates ». */
.prop-extraction {
  margin: 1.25rem 0; padding: 0.9rem 1.1rem;
  background: var(--surface-creuse);
  border-left: 3px solid var(--trait-fort); border-radius: 6px;
  max-width: 46rem;
}
.prop-extraction h2 {
  font-size: 0.9rem; margin: 0 0 0.4rem; color: var(--encre-tenue);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.prop-extraction p { margin: 0.3rem 0; color: var(--encre); }

/* --- Pilotage : le détail complet par école ---------------------------
   Replié par défaut. Le bloc du haut répond à « à quel point la première écrase les
   autres » et doit rester court ; celui-ci répond à « où va le reste », et il contient
   les écoles que le premier ne peut pas montrer — celles dont le CA horaire est nul.

   Aucun script : `<details>` fait l'ouverture nativement, et l'état survit au
   rafraîchissement. */
.rangs-tout {
  margin-top: 0.9rem;
  border-top: 1px solid var(--trait);
  padding-top: 0.6rem;
}

.rangs-tout summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--encre-douce);
  list-style: none;
  padding: 0.15rem 0;
}

/* Le triangle par défaut est retiré des deux côtés : WebKit a le sien. */
.rangs-tout summary::-webkit-details-marker { display: none; }

.rangs-tout summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 0.4rem;
  transition: transform 0.12s ease;
}

.rangs-tout[open] summary::before { transform: rotate(90deg); }

.rangs-detail {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.5rem;
  font-size: 0.84rem;
}

.rangs-detail th {
  text-align: left;
  font-weight: 500;
  color: var(--encre-douce);
  padding: 0.25rem 0.4rem;
  border-bottom: 1px solid var(--trait);
}

.rangs-detail td {
  padding: 0.3rem 0.4rem;
  border-bottom: 1px solid var(--trait);
}

.rangs-detail th:not(:first-child),
.rangs-nombre { text-align: right; }

/* Une école sans montant valorisable reste LISIBLE, simplement en retrait : elle n'est
   pas une anomalie. Au forfait, elle est réglée ailleurs ; sans taux, elle attend une
   saisie. L'effacer serait reproduire le défaut qu'on corrige. */
.rang-muet td { color: var(--encre-douce); }

.rang-etat {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.35rem;
  border-radius: 0.6rem;
  background: var(--surface-creuse);
  font-size: 0.74rem;
  color: var(--encre-douce);
}
