/* ==========================================================================
   CAPMEDIA CLIENT HUB · hub.css
   Le système de design de l'espace client et du cockpit d'équipe.

   Direction : calme, premium, lisible. Une hiérarchie typographique forte,
   de l'air, des couleurs qui ne parlent que pour signaler, des mouvements
   discrets. L'identité Capmedia reste (le bleu, Inter), le reste emprunte
   à la grammaire d'Apple : fonds blanc et gris doux en alternance, rayons
   généreux sur ce qui flotte, pilules sur ce qui se presse.

   Trois états de thème : clair (défaut), automatique, forcé. Chaque
   couleur existe d'abord sur :root, puis est redéfinie pour le sombre.
   Jamais l'inverse.
   ========================================================================== */

:root {
  /* --- Fonds ---------------------------------------------------------- */
  --fond:        #FFFFFF;
  --fond-2:      #F5F5F7;
  --fond-3:      #ECECEF;
  --fond-eleve:  #FFFFFF;
  --voile-page:  rgba(0, 0, 0, 0.36);
  --voile-modale: rgba(0, 0, 0, 0.22);

  /* --- Encre ---------------------------------------------------------- */
  --encre:       #1D1D1F;
  --encre-2:     #6E6E73;
  --encre-3:     #86868B;
  --encre-4:     #B8B8BD;
  --sur-accent:  #FFFFFF;

  /* --- Traits --------------------------------------------------------- */
  --trait:       rgba(0, 0, 0, 0.08);
  --trait-fort:  rgba(0, 0, 0, 0.14);
  --survol:      rgba(0, 0, 0, 0.045);
  --pression:    rgba(0, 0, 0, 0.08);

  /* --- Accent et sémantique ------------------------------------------ */
  --accent:        #0075DE;
  --accent-survol: #0062BA;
  /* Le bleu des icônes de la barre latérale : celui du système, pas celui
     de l'accent, pour que la barre reste calme quand l'accent bouge. */
  --bleu-systeme:  #007AFF;
  --accent-voile:  #E8F2FD;
  --anneau:        rgba(0, 117, 222, 0.28);

  --ok:            #16763F;
  --ok-voile:      #E6F6EC;
  --attention:     #8A5200;
  --attention-voile: #FFF4DE;
  --alerte:        #B3261E;
  --alerte-voile:  #FDECEA;
  --violet:        #6E56CF;
  --violet-voile:  #EFEBFD;
  --gris-voile:    #F0F0F3;

  /* --- Ombres : réservées à ce qui flotte ----------------------------- */
  --ombre-carte:  0 1px 2px rgba(0, 0, 0, 0.03), 0 6px 20px rgba(0, 0, 0, 0.05);
  --ombre-levee:  0 2px 6px rgba(0, 0, 0, 0.05), 0 14px 36px rgba(0, 0, 0, 0.10);
  --ombre-modale: 0 8px 24px rgba(0, 0, 0, 0.10), 0 28px 80px rgba(0, 0, 0, 0.22);

  /* --- Rayons --------------------------------------------------------- */
  --r-carte:  18px;
  --r-champ:  12px;
  --r-petit:  8px;
  --r-pilule: 980px;

  /* --- Typographie ---------------------------------------------------- */
  --police: Inter, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  --police-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --t-display: 700 clamp(32px, 4vw, 44px) / 1.08 var(--police);
  --t-titre-1: 700 clamp(26px, 3vw, 32px) / 1.15 var(--police);
  --t-titre-2: 600 22px / 1.25 var(--police);
  --t-titre-3: 600 17px / 1.35 var(--police);
  --t-corps:   400 15px / 1.55 var(--police);
  --t-corps-fort: 500 15px / 1.55 var(--police);
  --t-petit:   400 13.5px / 1.5 var(--police);
  --t-micro:   500 12px / 1.4 var(--police);
  --t-chiffre: 700 34px / 1 var(--police);

  --ls-serre: -0.02em;
  --ls-titre: -0.015em;
  --ls-large: 0.06em;

  /* --- Espace --------------------------------------------------------- */
  --e-1: 4px;  --e-2: 8px;  --e-3: 12px; --e-4: 16px; --e-5: 24px;
  --e-6: 32px; --e-7: 48px; --e-8: 64px; --e-9: 96px;

  /* --- Gabarit -------------------------------------------------------- */
  --lat: 264px;
  --haut: 60px;
  --contenu-max: 1120px;
  --marge-page: 40px;

  /* --- Mouvement ------------------------------------------------------ */
  --vite: 140ms cubic-bezier(0.2, 0, 0, 1);
  --doux: 240ms cubic-bezier(0.2, 0, 0, 1);

  color-scheme: light;
}

/* Sombre automatique, tant que rien n'est forcé. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fond:        #161617;
    --fond-2:      #1F1F21;
    --fond-3:      #2A2A2D;
    --fond-eleve:  #1F1F21;
    --voile-page:  rgba(0, 0, 0, 0.6);
    --voile-modale: rgba(0, 0, 0, 0.44);
    --encre:       #F5F5F7;
    --encre-2:     #A1A1A6;
    --encre-3:     #86868B;
    --encre-4:     #5C5C61;
    --trait:       rgba(255, 255, 255, 0.10);
    --trait-fort:  rgba(255, 255, 255, 0.18);
    --survol:      rgba(255, 255, 255, 0.06);
    --pression:    rgba(255, 255, 255, 0.10);
    --accent:        #2E8FF0;
    --accent-survol: #58A6F5;
    --bleu-systeme:  #0A84FF;
    --accent-voile:  #16304A;
    --anneau:        rgba(46, 143, 240, 0.4);
    --ok:            #3FC46A;
    --ok-voile:      #163825;
    --attention:     #F2B33D;
    --attention-voile: #3E2E10;
    --alerte:        #F26B5E;
    --alerte-voile:  #4A1F1B;
    --violet:        #A08CFF;
    --violet-voile:  #2A2447;
    --gris-voile:    #2A2A2D;
    --ombre-carte:  0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.35);
    --ombre-levee:  0 2px 6px rgba(0, 0, 0, 0.35), 0 14px 36px rgba(0, 0, 0, 0.5);
    --ombre-modale: 0 8px 24px rgba(0, 0, 0, 0.5), 0 28px 80px rgba(0, 0, 0, 0.7);
    color-scheme: dark;
  }
}

/* Sombre forcé par le sélecteur. */
:root[data-theme="dark"] {
  --fond:        #161617;
  --fond-2:      #1F1F21;
  --fond-3:      #2A2A2D;
  --fond-eleve:  #1F1F21;
  --voile-page:  rgba(0, 0, 0, 0.6);
  --voile-modale: rgba(0, 0, 0, 0.44);
  --encre:       #F5F5F7;
  --encre-2:     #A1A1A6;
  --encre-3:     #86868B;
  --encre-4:     #5C5C61;
  --trait:       rgba(255, 255, 255, 0.10);
  --trait-fort:  rgba(255, 255, 255, 0.18);
  --survol:      rgba(255, 255, 255, 0.06);
  --pression:    rgba(255, 255, 255, 0.10);
  --accent:        #2E8FF0;
  --accent-survol: #58A6F5;
  --bleu-systeme:  #0A84FF;
  --accent-voile:  #16304A;
  --anneau:        rgba(46, 143, 240, 0.4);
  --ok:            #3FC46A;
  --ok-voile:      #163825;
  --attention:     #F2B33D;
  --attention-voile: #3E2E10;
  --alerte:        #F26B5E;
  --alerte-voile:  #4A1F1B;
  --violet:        #A08CFF;
  --violet-voile:  #2A2447;
  --gris-voile:    #2A2A2D;
  --ombre-carte:  0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.35);
  --ombre-levee:  0 2px 6px rgba(0, 0, 0, 0.35), 0 14px 36px rgba(0, 0, 0, 0.5);
  --ombre-modale: 0 8px 24px rgba(0, 0, 0, 0.5), 0 28px 80px rgba(0, 0, 0, 0.7);
  color-scheme: dark;
}

/* ==========================================================================
   1. Base
   ========================================================================== */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--fond);
  color: var(--encre);
  font: var(--t-corps);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  min-height: 100dvh;
}

h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
input, select, textarea { font: inherit; color: inherit; }
/* L'anneau suit la forme de ce qui a le focus : une pilule reste une
   pilule. Forcer un rayon ici changeait la forme du bouton au clavier. */
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fond), 0 0 0 4px var(--accent);
}
::selection { background: var(--accent-voile); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.masque { display: none !important; }
.tronque { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb { font-variant-numeric: tabular-nums; }

/* Un élément marqué caché l'est, quelle que soit la classe qui le dessine :
   sans cette règle, un `display` posé par une classe l'emporte sur
   l'attribut et le bloc reste à l'écran. */
[hidden] { display: none !important; }

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

/* ==========================================================================
   2. Typographie
   ========================================================================== */

.t-display  { font: var(--t-display); letter-spacing: var(--ls-serre); }
.t-titre-1  { font: var(--t-titre-1); letter-spacing: var(--ls-titre); }
.t-titre-2  { font: var(--t-titre-2); letter-spacing: var(--ls-titre); }
.t-titre-3  { font: var(--t-titre-3); }
.t-corps    { font: var(--t-corps); }
.t-petit    { font: var(--t-petit); }
.t-micro    { font: var(--t-micro); }
.t-mono     { font-family: var(--police-mono); font-size: 0.92em; }
.t-2        { color: var(--encre-2); }
.t-3        { color: var(--encre-3); }
.t-fort     { font-weight: 600; }
.t-centre   { text-align: center; }
.t-droite   { text-align: right; }

/* Le surtitre en petites capitales : il annonce, il ne crie pas. */
.surtitre {
  font: var(--t-micro);
  font-weight: 600;
  letter-spacing: var(--ls-large);
  text-transform: uppercase;
  color: var(--encre-3);
}

/* Le texte courant long, où l'on lit vraiment. */
.prose { max-width: 66ch; }
.prose p + p { margin-top: var(--e-3); }
.prose strong { font-weight: 600; color: var(--encre); }

/* ==========================================================================
   3. La coquille : barre latérale, barre haute, page
   ========================================================================== */

.coq {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}

/* --- La barre latérale --------------------------------------------------- */
.lat {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(var(--lat), 86vw);
  z-index: 60;
  display: flex;
  flex-direction: column;
  background: var(--fond);
  border-right: 1px solid var(--trait);
  transform: translateX(-100%);
  transition: transform var(--doux);
  /* La barre elle-même ne défile jamais : la marque reste en haut, le
     compte reste en bas, et seule la navigation glisse entre les deux. */
  overflow: hidden;
}
.lat.ouverte { transform: none; box-shadow: var(--ombre-modale); }
.voile-lat {
  position: fixed; inset: 0; z-index: 55;
  background: var(--voile-page);
  opacity: 0; pointer-events: none;
  transition: opacity var(--doux);
}
.voile-lat.visible { opacity: 1; pointer-events: auto; }

.lat-tete {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--haut); padding: 0 var(--e-4) 0 var(--e-5);
  flex: none;
}
.lat-marque {
  display: flex; align-items: center; gap: 10px;
  min-width: 0;
  font-weight: 600; font-size: 15px; letter-spacing: -0.01em;
  color: var(--encre); text-decoration: none;
}
.lat-marque:hover { text-decoration: none; }
.lat-marque img { width: 24px; height: 24px; border-radius: 7px; }
.lat-marque .service {
  font: var(--t-micro); font-weight: 600; letter-spacing: 0.04em;
  padding: 2px 8px; border-radius: var(--r-pilule);
  background: var(--accent-voile); color: var(--accent);
  text-transform: uppercase;
}

/* Le bouton qui plie la barre latérale, à sa place : en haut à gauche. */
.btn-plier {
  width: 34px; height: 34px; border-radius: 9px; flex: none;
  display: none; place-items: center; color: var(--encre-2);
  transition: background var(--vite), color var(--vite);
}
.btn-plier svg { width: 18px; height: 18px; }
.btn-plier:hover { background: var(--survol); color: var(--encre); }

.lat-corps {
  flex: 1 1 auto; min-height: 0;
  padding: var(--e-2) var(--e-4) var(--e-5);
  display: flex; flex-direction: column; gap: var(--e-5);
  /* Le seul bloc qui défile, et sans barre visible : une barre de
     défilement prend de la largeur et tronquait les compteurs à droite. */
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.lat-corps::-webkit-scrollbar { width: 0; height: 0; }

.lat-groupe { display: flex; flex-direction: column; gap: 2px; }
.lat-titre {
  font: var(--t-micro); font-weight: 600; letter-spacing: var(--ls-large); text-transform: uppercase;
  color: var(--encre-3); padding: var(--e-2) var(--e-3) var(--e-2);
}
.lat-lien {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  color: var(--encre-2);
  font: var(--t-corps-fort);
  font-size: 14px;
  text-decoration: none;
  transition: background var(--vite), color var(--vite);
  width: 100%;
  text-align: left;
}
.lat-lien svg { width: 18px; height: 18px; flex: none; color: var(--bleu-systeme); }
/* Un écusson de projet tient la place d'une icône, au même gabarit. */
.lat-lien .avatar-projet { flex: none; width: 18px; height: 18px; border-radius: 5px; font-size: 8px; }
.lat-lien.actif .avatar-projet { box-shadow: 0 0 0 1px var(--trait-fort); }
.lat-lien:hover { background: var(--survol); color: var(--encre); text-decoration: none; }
.lat-lien.actif { background: var(--fond-3); color: var(--encre); box-shadow: none; }
.lat-lien .comptes { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; flex: none; padding-left: 6px; }
.lat-lien .compte {
  font: var(--t-micro); font-variant-numeric: tabular-nums;
  color: var(--encre-3);
}
.lat-lien.actif .compte { color: var(--encre-2); }
.lat-lien .compte.vif {
  background: var(--alerte); color: #fff;
  box-shadow: 0 0 0 3px var(--alerte-voile);
  min-width: 18px; height: 18px; padding: 0 6px;
  border-radius: var(--r-pilule);
  display: inline-grid; place-items: center;
  font-weight: 600;
}
.lat-sous { padding-left: 28px; }
.lat-sous .lat-lien { padding-block: 6px; font-weight: 400; }

/* Les sections du projet ouvert. Un filet vertical les rattache à leur
   projet : sans lui, elles flotteraient au même rang que les pages qui
   traversent tous les projets, et c'est justement la confusion à éviter. */
.lat-sous-lien {
  margin-left: 12px;
  padding-block: 5px;
  font-weight: 400;
  color: var(--encre-3);
  border-left: 1.5px solid var(--trait);
  border-radius: 0 10px 10px 0;
  animation: sous-lien-entre var(--vite) both;
}
.lat-sous-lien svg { width: 16px; height: 16px; color: var(--bleu-systeme); }
.lat-sous-lien:hover { border-left-color: var(--encre-4); }
.lat-sous-lien.actif { border-left-color: var(--bleu-systeme); box-shadow: none; background: var(--fond-3); }
.lat-sous-lien.actif svg { opacity: 1; }
@keyframes sous-lien-entre { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .lat-sous-lien { animation: none; } }

.lat-pied {
  flex: none;
  padding: var(--e-4);
  border-top: 1px solid var(--trait);
  background: var(--fond);
}
.lat-compte {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 12px; width: 100%; text-align: left;
  transition: background var(--vite);
}
.lat-compte:hover { background: var(--survol); }
.lat-compte .nom { font: var(--t-corps-fort); font-size: 14px; }
.lat-compte .role { font: var(--t-micro); color: var(--encre-3); }

/* --- La barre haute ------------------------------------------------------ */
.haut {
  position: sticky; top: 0; z-index: 40;
  height: var(--haut);
  display: flex; align-items: center; gap: var(--e-3);
  padding: 0 var(--e-4);
  background: color-mix(in srgb, var(--fond) 84%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--vite);
}
.haut.decollee { border-bottom-color: var(--trait); }
.ariane {
  display: flex; flex-direction: row; align-items: center; gap: 6px;
  min-width: 0; flex: 1 1 auto;
  font: var(--t-petit); color: var(--encre-3); white-space: nowrap; overflow: hidden;
}
.ariane > * { flex: none; }
.ariane a { color: var(--encre-2); text-decoration: none; }
.ariane a:hover { color: var(--encre); }
.ariane .courant { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--encre); font-weight: 600; }
.ariane .sep { color: var(--encre-4); display: inline-flex; }
.ariane .sep svg { width: 14px; height: 14px; }
.haut .fin { margin-left: auto; display: flex; align-items: center; gap: var(--e-2); }

.btn-icone {
  width: 36px; height: 36px; border-radius: 10px;
  display: inline-grid; place-items: center;
  color: var(--encre-2);
  transition: background var(--vite), color var(--vite);
  position: relative;
}
.btn-icone svg { width: 20px; height: 20px; }
.btn-icone:hover { background: var(--survol); color: var(--encre); }
.btn-icone .point {
  position: absolute; top: 7px; right: 7px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--alerte); box-shadow: 0 0 0 2px var(--fond);
}
.btn-recherche {
  display: none; align-items: center; gap: 8px;
  height: 36px; padding: 0 12px 0 10px;
  border-radius: 10px; border: 1px solid var(--trait);
  background: var(--fond-2); color: var(--encre-3);
  font: var(--t-petit);
  transition: border-color var(--vite), background var(--vite);
}
.btn-recherche:hover { border-color: var(--trait-fort); color: var(--encre-2); }
.btn-recherche kbd {
  font: var(--t-micro); font-family: var(--police);
  padding: 1px 6px; border-radius: 6px;
  background: var(--fond); border: 1px solid var(--trait);
  color: var(--encre-3); margin-left: 4px;
}
.btn-recherche svg { width: 16px; height: 16px; }

/* --- La page ------------------------------------------------------------- */
.page {
  width: 100%;
  max-width: var(--contenu-max);
  margin-inline: auto;
  padding: var(--e-5) var(--e-4) var(--e-9);
  min-width: 0;
}
.page-tete {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--e-5); flex-wrap: wrap;
  margin-bottom: var(--e-6);
}
.page-tete h1 { font: var(--t-titre-1); letter-spacing: var(--ls-titre); margin-top: var(--e-1); }
.page-tete .chapo { font: var(--t-corps); color: var(--encre-2); margin-top: var(--e-2); max-width: 60ch; }
.page-tete .actions { display: flex; gap: var(--e-2); flex-wrap: wrap; align-items: center; }

/* L'en-tête d'un projet : le titre à gauche, les actions toujours à droite,
   quelle que soit la hauteur de la colonne de gauche. */
.page-tete--projet { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
@media (max-width: 720px) {
  .page-tete--projet { grid-template-columns: minmax(0, 1fr); }
  .page-tete--projet > .actions { justify-content: flex-start; }
}
.page-tete--projet > .actions { justify-content: flex-end; }
.tete-suivi { margin-top: var(--e-2); row-gap: var(--e-2); }
/* L'écusson et le titre ne se séparent jamais : la ligne de suivi peut
   tenir sur trois lignes sans faire descendre le nom du projet sous son
   logo, ce qui décrochait les actions du haut de la page. */
.page-tete--projet > .rang { flex-wrap: nowrap; }

/* Les plateformes du projet, en cartes : une tuile colorée, l'état de la
   brique, et le geste qui mène à l'application publiée. */
.cartes-plateformes {
  display: grid; gap: var(--e-2);
  margin: calc(var(--e-5) * -1) 0 var(--e-5);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.carte-plateforme {
  display: grid; grid-template-columns: 36px minmax(0, 1fr) 16px;
  align-items: center; gap: var(--e-3);
  padding: 10px 12px;
  border: 1px solid var(--trait); border-radius: var(--r-champ);
  background: var(--fond);
  color: inherit; text-decoration: none;
  transition: border-color var(--vite), transform var(--vite), box-shadow var(--vite), background var(--vite);
}
.carte-plateforme:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: currentColor;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.07);
}
.carte-plateforme-tuile {
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center; flex: none;
  transition: transform var(--doux);
}
.carte-plateforme-tuile svg { width: 18px; height: 18px; }
.carte-plateforme:hover .carte-plateforme-tuile { transform: scale(1.06) rotate(-2deg); }
.carte-plateforme-corps { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.carte-plateforme-nom { font: var(--t-corps-fort); font-size: 14px; color: var(--encre); }
.carte-plateforme-etat {
  font: var(--t-micro); color: var(--encre-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.carte-plateforme-fleche {
  display: grid; place-items: center; color: var(--encre-3);
  opacity: 0; transform: translateX(-4px);
  transition: opacity var(--vite), transform var(--vite);
}
.carte-plateforme-fleche svg { width: 15px; height: 15px; }
.carte-plateforme:hover .carte-plateforme-fleche { opacity: 1; transform: none; }
.carte-plateforme:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--anneau); }

.carte-plateforme--bleu   { color: var(--accent); }
.carte-plateforme--vert   { color: var(--ok); }
.carte-plateforme--ambre  { color: var(--attention); }
.carte-plateforme--rouge  { color: var(--alerte); }
.carte-plateforme--violet { color: var(--violet); }
.carte-plateforme--gris   { color: var(--encre-2); }
.carte-plateforme--bleu   .carte-plateforme-tuile { background: var(--accent-voile); }
.carte-plateforme--vert   .carte-plateforme-tuile { background: var(--ok-voile); }
.carte-plateforme--ambre  .carte-plateforme-tuile { background: var(--attention-voile); }
.carte-plateforme--rouge  .carte-plateforme-tuile { background: var(--alerte-voile); }
.carte-plateforme--violet .carte-plateforme-tuile { background: var(--violet-voile); }
.carte-plateforme--gris   .carte-plateforme-tuile { background: var(--gris-voile); }

.section { margin-top: var(--e-7); }
.section:first-child { margin-top: 0; }
.section-tete {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--e-4); margin-bottom: var(--e-4);
}
.section-tete h2 { font: var(--t-titre-2); letter-spacing: var(--ls-titre); }
.section-tete h3 { font: var(--t-titre-3); }
.section-tete .lien { font: var(--t-petit); font-weight: 500; white-space: nowrap; }

@media (min-width: 1024px) {
  .coq { grid-template-columns: var(--lat) minmax(0, 1fr); }
  .lat { inset: auto; position: sticky; top: 0; height: 100vh; height: 100dvh; transform: none; box-shadow: none; }
  .voile-lat { display: none; }
  .btn-menu { display: none; }
  .btn-recherche { display: inline-flex; }
  .page { padding: var(--e-6) var(--marge-page) var(--e-9); }
  .haut { padding: 0 var(--marge-page); }
  .btn-plier { display: inline-grid; }
  /* Le pliage : la colonne de la barre fond jusqu'à zéro et la barre glisse
     vers la gauche en s'effaçant. Ses blocs gardent leur largeur pendant le
     mouvement, sinon la navigation se tasserait au lieu de se retirer. */
  .coq { transition: grid-template-columns var(--doux); }
  .lat { width: auto; overflow-x: hidden; transition: transform var(--doux), opacity var(--doux); }
  .lat-tete, .lat-corps, .lat-pied { min-width: calc(var(--lat) - 1px); }
  .coq.pliee { grid-template-columns: 0 minmax(0, 1fr); }
  .coq.pliee .lat { transform: translateX(-24px); opacity: 0; pointer-events: none; }
  .coq.pliee .btn-deplier { display: inline-grid; }
}
.btn-deplier { display: none; }

/* ==========================================================================
   4. Boutons
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; padding: 0 16px;
  border-radius: var(--r-pilule);
  font: var(--t-corps-fort); font-size: 14px;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background var(--vite), color var(--vite), border-color var(--vite), transform var(--vite), box-shadow var(--vite);
  text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn svg { width: 16px; height: 16px; }

.btn-principal { background: var(--accent); color: var(--sur-accent); }
.btn-principal:hover { background: var(--accent-survol); }
.btn-secondaire { background: var(--fond); color: var(--encre); border-color: var(--trait-fort); }
.btn-secondaire:hover { background: var(--fond-2); }
.btn-doux { background: var(--fond-2); color: var(--encre); }
.btn-doux:hover { background: var(--fond-3); }
.btn-fantome { color: var(--encre-2); }
.btn-fantome:hover { background: var(--survol); color: var(--encre); }
.btn-danger { background: var(--alerte-voile); color: var(--alerte); }
.btn-danger:hover { background: var(--alerte); color: #fff; }
.btn-ok { background: var(--ok); color: #fff; }
.btn-ok:hover { filter: brightness(0.92); }
.btn-petit { height: 30px; padding: 0 12px; font-size: 13px; }
.btn-grand { height: 44px; padding: 0 22px; font-size: 15px; }
.btn-bloc { width: 100%; }
.btn-charge { position: relative; color: transparent !important; pointer-events: none; }
.btn-charge::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  color: var(--sur-accent);
  animation: tourne 0.8s linear infinite;
}
.btn-secondaire.btn-charge::after, .btn-fantome.btn-charge::after, .btn-doux.btn-charge::after { color: var(--encre-2); }
@keyframes tourne { to { transform: rotate(360deg); } }

/* ==================================================================
   5. Pastilles, puces, badges, avatars, progression
   ================================================================== */

.pastille {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px; padding: 0 10px;
  border-radius: var(--r-pilule);
  font: var(--t-micro); font-weight: 600;
  background: var(--gris-voile); color: var(--encre-2);
  white-space: nowrap;
}
.pastille i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pastille--bleu   { background: var(--accent-voile); color: var(--accent); }
.pastille--vert   { background: var(--ok-voile); color: var(--ok); }
.pastille--ambre  { background: var(--attention-voile); color: var(--attention); }
.pastille--rouge  { background: var(--alerte-voile); color: var(--alerte); }
.pastille--violet { background: var(--violet-voile); color: var(--violet); }
.pastille--gris   { background: var(--gris-voile); color: var(--encre-2); }
.pastille--plein  { background: var(--encre); color: var(--fond); }

.puce { display: inline-flex; align-items: center; gap: 6px; font: var(--t-petit); font-weight: 500; color: var(--encre-2); }
.puce i { width: 8px; height: 8px; border-radius: 50%; background: var(--encre-4); flex: none; }
.puce svg { width: 14px; height: 14px; flex: none; }
.puce--rouge i { background: var(--alerte); } .puce--rouge { color: var(--alerte); }
.puce--ambre i { background: var(--attention); } .puce--ambre { color: var(--attention); }
.puce--vert i { background: var(--ok); }
.puce--bleu i { background: var(--accent); }
.puce--violet i { background: var(--violet); }

.badge {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--r-pilule);
  font: var(--t-micro); font-weight: 600; font-variant-numeric: tabular-nums;
  background: var(--fond-3); color: var(--encre-2);
}
.badge--vif { background: var(--alerte); color: #fff; }
.badge--accent { background: var(--accent); color: #fff; }

.etiquette {
  display: inline-flex; align-items: center;
  height: 22px; padding: 0 8px; border-radius: 6px;
  font: var(--t-micro); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  background: var(--fond-2); color: var(--encre-2);
}

.avatar {
  width: 32px; height: 32px; border-radius: 50%;
  display: inline-grid; place-items: center; flex: none;
  font: var(--t-micro); font-weight: 600;
  background: var(--fond-3); color: var(--encre-2);
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--equipe { background: var(--accent); color: #fff; }
.avatar--petit { width: 24px; height: 24px; font-size: 10px; }
.avatar--grand { width: 48px; height: 48px; font-size: 15px; }
.avatar--xl { width: 64px; height: 64px; font-size: 20px; border-radius: 18px; }
.avatar-projet {
  display: inline-grid; place-items: center; flex: none;
  border-radius: 12px; font-weight: 700; color: #fff;
  background: linear-gradient(140deg, var(--accent), var(--violet));
  width: 40px; height: 40px; font-size: 14px; letter-spacing: 0.02em;
}
.avatar-projet--grand { width: 64px; height: 64px; border-radius: 18px; font-size: 20px; }
.avatar-projet--petit { width: 28px; height: 28px; border-radius: 8px; font-size: 11px; }
/* Avec un logo, l'écusson devient un cadre neutre : le logo parle seul. */
.avatar-projet--logo { background: var(--fond-2); padding: 0; overflow: hidden; border: 1px solid var(--trait); }
.avatar-projet--logo img { width: 100%; height: 100%; object-fit: contain; }

.progression { height: 6px; border-radius: 3px; background: var(--fond-3); overflow: hidden; }
.progression > i { display: block; height: 100%; border-radius: 3px; background: var(--accent); transition: width var(--doux); }
.progression--vert > i { background: var(--ok); }
.progression--ambre > i { background: var(--attention); }
.progression--fine { height: 4px; }

.anneau {
  --v: 0; --taille: 56px; --epaisseur: 6px;
  width: var(--taille); height: var(--taille); border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--v) * 1%), var(--fond-3) 0);
  display: grid; place-items: center; position: relative; flex: none;
}
.anneau::before { content: ""; position: absolute; inset: var(--epaisseur); border-radius: 50%; background: var(--fond); }
.anneau > span { position: relative; font: var(--t-micro); font-weight: 700; font-variant-numeric: tabular-nums; }
.anneau--grand { --taille: 88px; --epaisseur: 8px; }
.anneau--grand > span { font-size: 17px; }

/* ==========================================================================
   6. Cartes, listes, lignes, métriques
   ========================================================================== */

.carte {
  background: var(--fond-eleve);
  border: 1px solid var(--trait);
  border-radius: var(--r-carte);
  padding: var(--e-5);
}
.carte--creuse { background: var(--fond-2); border-color: transparent; }
.carte--serree { padding: var(--e-4); }
.carte--cliquable { cursor: pointer; transition: transform var(--vite), box-shadow var(--vite), border-color var(--vite); display: block; color: inherit; text-decoration: none; }
.carte--cliquable:hover { transform: translateY(-2px); box-shadow: var(--ombre-carte); border-color: var(--trait-fort); text-decoration: none; }
.carte-tete { display: flex; align-items: center; justify-content: space-between; gap: var(--e-3); margin-bottom: var(--e-4); }
.carte-tete h3 { font: var(--t-titre-3); }

.grille { display: grid; gap: var(--e-4); }
.grille-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grille-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grille-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grille-auto { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.grille-tiers { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
@media (max-width: 900px) {
  .grille-3, .grille-4, .grille-tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .grille-2, .grille-3, .grille-4, .grille-tiers { grid-template-columns: minmax(0, 1fr); }
}

.rang { display: flex; align-items: center; gap: var(--e-3); flex-wrap: wrap; }
.rang-espace { display: flex; align-items: center; justify-content: space-between; gap: var(--e-4); flex-wrap: wrap; }
.pile { display: flex; flex-direction: column; gap: var(--e-3); }
.pousse { margin-left: auto; }

/* Une liste : des lignes séparées par des filets fins, sans boîte. */
.liste { display: flex; flex-direction: column; }
.ligne {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: var(--e-4);
  padding: var(--e-3) var(--e-3);
  margin-inline: calc(var(--e-3) * -1);
  border-radius: var(--r-champ);
  color: inherit; text-decoration: none;
  width: calc(100% + var(--e-3) * 2);
  text-align: left;
  transition: background var(--vite);
}
.ligne + .ligne { position: relative; }
.ligne + .ligne::before {
  content: ""; position: absolute; left: var(--e-3); right: var(--e-3); top: 0;
  border-top: 1px solid var(--trait);
}
.ligne:hover { background: var(--survol); text-decoration: none; }
.ligne:hover + .ligne::before, .ligne:hover::before { border-top-color: transparent; }
.ligne--sans-icone { grid-template-columns: minmax(0, 1fr) auto; }
.ligne-corps { min-width: 0; }
.ligne-titre { font: var(--t-corps-fort); overflow-wrap: anywhere; }
/* Le titre devient le bouton quand la ligne porte déjà un crayon : un
   <button> dans un <button> est invalide et le navigateur l'éjecte. Il
   garde l'apparence d'un titre, le clic en plus. */
.ligne-titre--bouton {
  display: block; width: 100%;
  background: none; border: 0; padding: 0; margin: 0;
  text-align: left; color: inherit; font: inherit;
  cursor: pointer;
}
.ligne-titre--bouton:hover { text-decoration: underline; text-underline-offset: 3px; }
.ligne--titre-agit { cursor: default; }
.ligne-sous { font: var(--t-petit); color: var(--encre-3); margin-top: 2px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.ligne-fin { display: flex; align-items: center; gap: var(--e-3); flex: none; }
.ligne-fin .boutons-edition { flex-wrap: nowrap; gap: 2px; }
.ligne--inerte { cursor: default; }
.ligne--inerte:hover { background: transparent; transform: none; }
.ligne-fin .chevron { width: 16px; height: 16px; color: var(--encre-4); }
.ligne.non-lu .ligne-titre::before {
  content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); margin-right: 8px; vertical-align: 2px;
}
.ligne-icone {
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center; flex: none;
  background: var(--fond-2); color: var(--encre-2);
}
.ligne-icone svg { width: 18px; height: 18px; }
.ligne-icone--bleu { background: var(--accent-voile); color: var(--accent); }
.ligne-icone--vert { background: var(--ok-voile); color: var(--ok); }
.ligne-icone--ambre { background: var(--attention-voile); color: var(--attention); }
.ligne-icone--rouge { background: var(--alerte-voile); color: var(--alerte); }
.ligne-icone--violet { background: var(--violet-voile); color: var(--violet); }

/* La métrique : un chiffre, un libellé, parfois une nuance. Pas une carte. */
.metriques {
  /* Assez étroit pour que sept chiffres tiennent sur une seule ligne : au
     delà, la grille se répartit d'elle-même en rangées égales. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: var(--e-4);
  padding: var(--e-5) 0;
  border-block: 1px solid var(--trait);
}
.metrique { min-width: 0; padding: 0 var(--e-4); border-left: 1px solid var(--trait); }
.metrique:first-child { border-left: 0; padding-left: 0; }
.metrique-valeur { font: var(--t-chiffre); letter-spacing: var(--ls-serre); font-variant-numeric: tabular-nums; }
.metrique-libelle { font: var(--t-petit); color: var(--encre-2); margin-top: 6px; }
.metrique-nuance { font: var(--t-micro); color: var(--encre-3); margin-top: 2px; }
.metrique--rouge .metrique-valeur { color: var(--alerte); }
.metrique--ambre .metrique-valeur { color: var(--attention); }
.metrique--vert .metrique-valeur { color: var(--ok); }
.metrique--accent .metrique-valeur { color: var(--accent); }
@media (max-width: 600px) {
  .metriques { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .metrique { border-left: 0; padding-left: 0; }
}

/* Les faits : libellé discret au-dessus, valeur en dessous. */
.faits { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--e-4) var(--e-5); }
.fait dt { font: var(--t-micro); color: var(--encre-3); text-transform: uppercase; letter-spacing: 0.05em; }
.fait dd { margin: 4px 0 0; font: var(--t-corps); overflow-wrap: anywhere; }

/* La chronologie : activité, historique, roadmap verticale. */
.chrono { position: relative; display: flex; flex-direction: column; gap: 0; }
.chrono-item { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: var(--e-3); padding-bottom: var(--e-4); position: relative; }
.chrono-item::before {
  content: ""; position: absolute; left: 13px; top: 28px; bottom: 0;
  border-left: 1px solid var(--trait);
}
.chrono-item:last-child::before { display: none; }
.chrono-point {
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--fond-2); color: var(--encre-2);
  border: 1px solid var(--trait);
}
.chrono-point svg { width: 14px; height: 14px; }
.chrono-point--vert { background: var(--ok-voile); color: var(--ok); border-color: transparent; }
.chrono-point--bleu { background: var(--accent-voile); color: var(--accent); border-color: transparent; }
.chrono-point--ambre { background: var(--attention-voile); color: var(--attention); border-color: transparent; }
.chrono-point--rouge { background: var(--alerte-voile); color: var(--alerte); border-color: transparent; }
.chrono-point--violet { background: var(--violet-voile); color: var(--violet); border-color: transparent; }
.chrono-texte { font: var(--t-corps); padding-top: 4px; overflow-wrap: anywhere; }
.chrono-texte strong { font-weight: 600; }
.chrono-date { font: var(--t-micro); color: var(--encre-3); margin-top: 2px; }
.chrono-jour { font: var(--t-micro); font-weight: 600; color: var(--encre-3); text-transform: uppercase; letter-spacing: 0.05em; padding: var(--e-3) 0 var(--e-3) 40px; }

/* La feuille de route : des phases en ligne, chacune avec son état. */
.route { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--e-3); }
.phase {
  padding: var(--e-4); border-radius: var(--r-champ);
  background: var(--fond-2); position: relative; min-width: 0;
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--vite), border-color var(--vite), transform var(--vite);
}
.phase:hover { background: var(--fond-3); border-color: var(--trait); transform: translateY(-1px); }
.phase:active { transform: none; }
.phase-etat { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.phase-etat i { width: 10px; height: 10px; border-radius: 50%; background: var(--encre-4); }
.phase--terminee .phase-etat i { background: var(--ok); }
.phase--en-cours .phase-etat i { background: var(--accent); box-shadow: 0 0 0 4px var(--accent-voile); }
.phase--bloquee .phase-etat i { background: var(--alerte); }
.phase-nom { font: var(--t-corps-fort); display: block; }
.phase-sous { font: var(--t-micro); color: var(--encre-3); margin-top: 4px; display: block; }
.phase .progression { margin-top: 10px; }

/* Le kanban : des colonnes qui défilent, jamais la page. */
.kanban { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(260px, 1fr); gap: var(--e-4); overflow-x: auto; padding-bottom: var(--e-3); -webkit-overflow-scrolling: touch; }
.kanban-col { background: var(--fond-2); border-radius: var(--r-carte); padding: var(--e-3); min-height: 200px; }
.kanban-tete { display: flex; align-items: center; gap: 8px; padding: 6px 8px 12px; font: var(--t-corps-fort); font-size: 14px; }
.kanban-tete .badge { margin-left: auto; }
.kanban-carte { background: var(--fond); border-radius: var(--r-champ); padding: 12px; box-shadow: 0 1px 2px rgba(0,0,0,0.05); margin-bottom: 8px; cursor: pointer; transition: transform var(--vite), box-shadow var(--vite); text-align: left; width: 100%; }
.kanban-carte:hover { transform: translateY(-1px); box-shadow: var(--ombre-carte); }
.kanban-carte .titre { font: var(--t-corps-fort); font-size: 14px; }
.kanban-carte .sous { display: flex; align-items: center; gap: 8px; margin-top: 8px; font: var(--t-micro); color: var(--encre-3); }

/* Les onglets : un trait sous l'actif, rien d'autre. */
/* La barre d'onglets défile sans ascenseur ; un dégradé au bord droit dit
   qu'il en reste, et s'efface quand on arrive au bout. */
.onglets-enveloppe { position: relative; margin-bottom: var(--e-5); }
.onglets-enveloppe::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 1px; width: 48px;
  pointer-events: none; opacity: 0; transition: opacity var(--doux);
  background: linear-gradient(to right, transparent, var(--fond) 80%);
}
.onglets-enveloppe.deborde::after { opacity: 1; }
.onglets-enveloppe .onglets { margin-bottom: 0; scroll-behavior: smooth; }
.onglets { display: flex; gap: var(--e-1); border-bottom: 1px solid var(--trait); overflow-x: auto; scrollbar-width: none; margin-bottom: var(--e-5); }
.onglets::-webkit-scrollbar { display: none; }
.onglet {
  padding: 10px 12px; margin-bottom: -1px;
  font: var(--t-corps-fort); font-size: 14px; color: var(--encre-2);
  border-bottom: 2px solid transparent; white-space: nowrap;
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px;
  transition: color var(--vite), border-color var(--vite);
}
.onglet:hover { color: var(--encre); text-decoration: none; }
.onglet.actif { color: var(--encre); border-bottom-color: var(--encre); }
.onglet .badge { min-width: 18px; height: 18px; }

/* Les filtres en pilules. */
.filtres { display: flex; gap: var(--e-2); flex-wrap: wrap; align-items: center; }
.filtre {
  height: 32px; padding: 0 12px; border-radius: var(--r-pilule);
  font: var(--t-petit); font-weight: 500; color: var(--encre-2);
  background: var(--fond-2); border: 1px solid transparent;
  display: inline-flex; align-items: center; gap: 6px;
  transition: background var(--vite), color var(--vite);
}
.filtre:hover { background: var(--fond-3); color: var(--encre); }
.filtre.actif { background: var(--encre); color: var(--fond); }
.filtre .compte { opacity: 0.65; font-variant-numeric: tabular-nums; }

/* Le tableau, uniquement quand des colonnes ont un sens. */
.cadre-defile { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tableau { width: 100%; border-collapse: collapse; font: var(--t-petit); }
.tableau th { text-align: left; font: var(--t-micro); text-transform: uppercase; letter-spacing: 0.05em; color: var(--encre-3); padding: 8px 12px; border-bottom: 1px solid var(--trait); white-space: nowrap; }
.tableau td { padding: 12px; border-bottom: 1px solid var(--trait); vertical-align: middle; }
.tableau tr:last-child td { border-bottom: 0; }
.tableau .droite { text-align: right; font-variant-numeric: tabular-nums; }
.tableau tbody tr:hover td { background: var(--survol); }

/* ==========================================================================
   7. Formulaires
   ========================================================================== */

.champ, .zone, .select {
  width: 100%;
  height: 40px; padding: 0 14px;
  border-radius: var(--r-champ);
  border: 1px solid var(--trait-fort);
  background: var(--fond);
  color: var(--encre);
  font: var(--t-corps); font-size: 14.5px;
  transition: border-color var(--vite), box-shadow var(--vite), background var(--vite);
  -webkit-appearance: none; appearance: none;
}
.zone { height: auto; min-height: 110px; padding: 10px 14px; resize: vertical; line-height: 1.5; }
.select {
  padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2386868B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
.champ::placeholder, .zone::placeholder { color: var(--encre-3); }
.champ:hover, .zone:hover, .select:hover { border-color: var(--encre-3); }
.champ:focus, .zone:focus, .select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--anneau); outline: none; }
.champ[aria-invalid="true"], .zone[aria-invalid="true"] { border-color: var(--alerte); }
.champ:disabled, .zone:disabled, .select:disabled { background: var(--fond-2); color: var(--encre-3); }

.groupe { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.etiquette-champ { font: var(--t-petit); font-weight: 600; color: var(--encre); }
.etiquette-champ .facultatif { font-weight: 400; color: var(--encre-3); }
.aide { font: var(--t-micro); font-weight: 400; color: var(--encre-3); }
.erreur-champ { font: var(--t-micro); font-weight: 500; color: var(--alerte); }
.forme { display: flex; flex-direction: column; gap: var(--e-4); }
.forme-rang { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--e-4); }
@media (max-width: 600px) { .forme-rang { grid-template-columns: minmax(0, 1fr); } }
.forme-pied { display: flex; justify-content: flex-end; gap: var(--e-2); padding-top: var(--e-2); }

.case { display: inline-flex; align-items: center; gap: 10px; font: var(--t-corps); cursor: pointer; }
.case input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; flex: none; }
/* Une icône posée dans une case n'avait pas de taille : le SVG prenait
   alors la sienne, et remplissait la moitié de la feuille. Toute icône
   d'un libellé se cale sur la hauteur du texte. */
.case svg { width: 18px; height: 18px; flex: none; }

.interrupteur { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font: var(--t-corps); }
.interrupteur input { position: absolute; opacity: 0; }
.interrupteur i { width: 40px; height: 24px; border-radius: 12px; background: var(--fond-3); position: relative; transition: background var(--vite); flex: none; }
.interrupteur i::after { content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.25); transition: transform var(--vite); }
.interrupteur input:checked + i { background: var(--ok); }
.interrupteur input:checked + i::after { transform: translateX(16px); }
.interrupteur input:focus-visible + i { box-shadow: 0 0 0 3px var(--anneau); }

/* Les choix segmentés : un seul actif, comme un sélecteur de thème. */
.segments { display: inline-flex; padding: 3px; border-radius: 10px; background: var(--fond-2); gap: 2px; }
.segments button, .segments a {
  height: 30px; padding: 0 12px; border-radius: 8px;
  font: var(--t-petit); font-weight: 500; color: var(--encre-2);
  transition: background var(--vite), color var(--vite);
  text-decoration: none; display: inline-flex; align-items: center;
}
.segments button:hover, .segments a:hover { color: var(--encre); }
.segments [aria-pressed="true"], .segments .actif { background: var(--fond); color: var(--encre); box-shadow: 0 1px 2px rgba(0,0,0,0.08); }

/* La zone de dépôt de fichiers. */
.depot {
  display: block; border: 1.5px dashed var(--trait-fort); border-radius: var(--r-champ);
  padding: var(--e-5); text-align: center; color: var(--encre-2);
  font: var(--t-petit); cursor: pointer;
  transition: border-color var(--vite), background var(--vite);
  position: relative;
}
.depot:hover, .depot.survole { border-color: var(--accent); background: var(--accent-voile); }
.depot input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.depot strong { color: var(--accent); font-weight: 600; }
.pieces { display: flex; flex-wrap: wrap; gap: var(--e-2); margin-top: var(--e-3); }
.piece {
  display: inline-flex; align-items: center; gap: 8px;
  max-width: 100%; height: 32px; padding: 0 10px 0 8px;
  border-radius: 8px; background: var(--fond-2); color: var(--encre-2);
  font: var(--t-petit); text-decoration: none;
}
.piece svg { width: 14px; height: 14px; flex: none; }
.piece .nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; }
.piece:hover { background: var(--fond-3); color: var(--encre); text-decoration: none; }
.piece button { color: var(--encre-3); display: grid; }
.piece button:hover { color: var(--alerte); }
.piece--envoi { position: relative; overflow: hidden; }
.piece--envoi::after { content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: var(--p, 0%); background: var(--accent); transition: width var(--vite); }

/* ==========================================================================
   8. Surfaces flottantes : modale, feuille, menu, palette, toast
   ========================================================================== */

/* Le fond d'une fiche ouverte : assombri et flou. La page reste lisible
   derrière, mais plus lisible que la fiche : c'est elle qu'on lit. */
.voile {
  position: fixed; inset: 0; z-index: 100;
  background: var(--voile-modale);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
  backdrop-filter: saturate(140%) blur(16px);
  display: grid; place-items: center;
  padding: var(--e-4);
  animation: apparait var(--vite) both;
}
/* Sans le flou, le voile seul ne suffirait pas à détacher la fiche. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .voile { background: var(--voile-page); }
}
@keyframes apparait { from { opacity: 0; } to { opacity: 1; } }
@keyframes pose { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes monte { from { opacity: 0; transform: translateY(12px) scale(0.985); } to { opacity: 1; transform: none; } }
@keyframes glisse { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }

.modale {
  width: min(560px, 100%);
  max-height: min(90vh, 100%);
  background: var(--fond-eleve);
  border-radius: 22px;
  box-shadow: var(--ombre-modale);
  display: flex; flex-direction: column;
  animation: monte var(--doux) both;
  overflow: hidden;
}
.modale--large { width: min(760px, 100%); }
.modale-tete { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--e-4); padding: var(--e-5) var(--e-5) 0; }
.modale-tete h2 { font: var(--t-titre-2); letter-spacing: var(--ls-titre); }
.modale-tete p { font: var(--t-petit); color: var(--encre-2); margin-top: 4px; }
.modale-corps { padding: var(--e-5); overflow-y: auto; }
/* Le pied peut porter quatre gestes : annuler, renvoyer, retirer,
   supprimer. Sans retour à la ligne, le dernier sortait de la feuille et
   devenait inatteignable. Les boutons s'alignent à droite et passent à la
   ligne quand la largeur ne suffit plus. */
.modale-pied {
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center;
  gap: var(--e-2); padding: var(--e-4) var(--e-5) var(--e-5);
  border-top: 1px solid var(--trait);
}
/* Un bouton ne se laisse pas écraser sous son texte. */
.modale-pied .btn { flex: 0 1 auto; min-width: 0; }
/* « Pousse » sépare la gauche de la droite ; sur une ligne repliée, il ne
   doit pas créer un trou vertical. */
.modale-pied .pousse { flex: 1 1 auto; min-width: 0; }

/* La feuille : glisse depuis la droite sur grand écran, depuis le bas sur petit. */
.voile--feuille { place-items: stretch end; padding: 0; }
.feuille {
  width: min(520px, 100%); height: 100%;
  background: var(--fond-eleve);
  box-shadow: var(--ombre-modale);
  display: flex; flex-direction: column;
  animation: glisse var(--doux) both;
  margin-left: auto;
  /* Sans « overflow », un formulaire plus haut que l'écran pousse le pied
     hors de la fenêtre et le bouton d'enregistrement devient injoignable.
     La modale s'en protégeait déjà ; la feuille, non. */
  overflow: hidden;
}
/* « min-height: 0 » lève le plancher que le flex impose à ses enfants :
   sans lui le corps refuse de rétrécir, donc il ne défile jamais et c'est
   la feuille entière qui grandit. */
.feuille .modale-corps { flex: 1; min-height: 0; }
.feuille .modale-tete, .feuille .modale-pied { flex: 0 0 auto; }
@media (max-width: 700px) {
  .voile--feuille { place-items: end stretch; }
  .feuille { width: 100%; height: auto; max-height: 92vh; margin: auto 0 0; border-radius: 22px 22px 0 0; animation: monte var(--doux) both; }
}

.menu {
  position: fixed; z-index: 110;
  min-width: 200px; padding: 6px;
  background: var(--fond-eleve);
  border: 1px solid var(--trait);
  border-radius: 14px;
  box-shadow: var(--ombre-levee);
  animation: monte var(--vite) both;
}
.menu button, .menu a {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 9px 10px; border-radius: 9px;
  font: var(--t-petit); font-weight: 500; color: var(--encre);
  text-align: left; text-decoration: none;
}
.menu button:hover, .menu a:hover { background: var(--survol); text-decoration: none; }
.menu button svg, .menu a svg { width: 16px; height: 16px; color: var(--encre-2); }
.menu .danger { color: var(--alerte); }
.menu hr { border: 0; border-top: 1px solid var(--trait); margin: 6px 4px; }
.menu .titre { font: var(--t-micro); color: var(--encre-3); padding: 6px 10px 2px; text-transform: uppercase; letter-spacing: 0.05em; }

/* La palette de commande. */
.voile--palette { place-items: start center; padding-top: 12vh; }
.palette { width: min(620px, 100%); background: var(--fond-eleve); border-radius: 18px; box-shadow: var(--ombre-modale); overflow: hidden; animation: monte var(--vite) both; }
.palette-champ { display: flex; align-items: center; gap: 10px; padding: 0 var(--e-4); border-bottom: 1px solid var(--trait); }
.palette-champ svg { width: 18px; height: 18px; color: var(--encre-3); }
.palette-champ input { flex: 1; height: 54px; border: 0; background: none; font: var(--t-corps); font-size: 16px; outline: none; }
.palette-liste { max-height: 50vh; overflow-y: auto; padding: 8px; }
.palette-groupe { font: var(--t-micro); color: var(--encre-3); text-transform: uppercase; letter-spacing: 0.05em; padding: 10px 10px 4px; }
.palette-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border-radius: 10px; text-align: left; font: var(--t-petit); color: var(--encre); text-decoration: none; }
.palette-item svg { width: 16px; height: 16px; color: var(--encre-3); flex: none; }
.palette-item .sous { color: var(--encre-3); margin-left: auto; font: var(--t-micro); white-space: nowrap; }
.palette-item:hover, .palette-item.cible { background: var(--survol); text-decoration: none; }
.palette-vide { padding: var(--e-5); text-align: center; color: var(--encre-3); font: var(--t-petit); }

/* Le toast, en bas au centre. */
.toasts { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 120; display: flex; flex-direction: column; gap: 8px; pointer-events: none; width: min(480px, calc(100% - 32px)); }
.toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-radius: 14px;
  background: var(--encre); color: var(--fond);
  font: var(--t-petit); font-weight: 500;
  box-shadow: var(--ombre-levee);
  animation: monte var(--vite) both;
}
.toast svg { width: 16px; height: 16px; flex: none; }
.toast--ok svg { color: var(--ok); }
.toast--erreur svg { color: var(--alerte); }
.toast button { margin-left: auto; color: inherit; opacity: 0.7; font-weight: 600; }

/* L'info-bulle : un seul élément, posé sur le corps de la page et placé
   en coordonnées d'écran. Rien ne peut plus la tronquer, et elle ne
   compte dans la zone défilante d'aucun conteneur. */
.astuce {
  position: fixed; top: 0; left: -9999px; z-index: 200;
  max-width: min(260px, calc(100vw - 16px));
  padding: 6px 10px; border-radius: 8px;
  background: var(--encre); color: var(--fond);
  font: var(--t-micro); font-weight: 500; line-height: 1.35;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  opacity: 0; transform: translateY(3px);
  transition: opacity var(--vite), transform var(--vite);
}
.astuce.visible { opacity: 1; transform: none; }
.astuce--dessous { transform: translateY(-3px); }
.astuce--dessous.visible { transform: none; }

/* ==========================================================================
   9. États : squelette, vide, erreur, chargement
   ========================================================================== */

.squelette { display: flex; flex-direction: column; gap: 12px; }
.os { border-radius: 8px; background: linear-gradient(90deg, var(--fond-2) 25%, var(--fond-3) 37%, var(--fond-2) 63%); background-size: 400% 100%; animation: chatoie 1.4s ease infinite; }
@keyframes chatoie { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.os--titre { height: 22px; width: 40%; }
.os--texte { height: 14px; width: 80%; }
.os--court { height: 14px; width: 55%; }
.os--ligne { height: 56px; width: 100%; border-radius: 12px; }
.os--carte { height: 120px; width: 100%; border-radius: var(--r-carte); }
.os--rond { width: 40px; height: 40px; border-radius: 50%; }

.vide {
  text-align: center; padding: var(--e-7) var(--e-4);
  display: flex; flex-direction: column; align-items: center; gap: var(--e-2);
}
.vide-icone { width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; background: var(--fond-2); color: var(--encre-3); margin-bottom: var(--e-2); }
.vide-icone svg { width: 22px; height: 22px; }
.vide-titre { font: var(--t-titre-3); }
.vide-texte { font: var(--t-petit); color: var(--encre-2); max-width: 40ch; }
.vide .btn { margin-top: var(--e-3); }
.vide--compact { padding: var(--e-5) var(--e-3); }

.encart {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 16px; border-radius: var(--r-champ);
  background: var(--fond-2); font: var(--t-petit); color: var(--encre-2);
}
.encart svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.encart strong { color: var(--encre); font-weight: 600; }
.encart--info { background: var(--accent-voile); color: var(--encre); } .encart--info svg { color: var(--accent); }
.encart--ok { background: var(--ok-voile); color: var(--encre); } .encart--ok svg { color: var(--ok); }
.encart--attention { background: var(--attention-voile); color: var(--encre); } .encart--attention svg { color: var(--attention); }
.encart--alerte { background: var(--alerte-voile); color: var(--encre); } .encart--alerte svg { color: var(--alerte); }

/* ==========================================================================
   10. Blocs métier : pulse, en attente de vous, conversation, fichier
   ========================================================================== */

/* Le pouls du projet : quatre phrases, pas un tableau de bord. */
.pouls { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0; border-radius: var(--r-carte); background: var(--fond-2); overflow: hidden; }
.pouls > div { padding: var(--e-5); border-left: 1px solid var(--trait); }
.pouls > div:first-child { border-left: 0; }
.pouls .quoi { font: var(--t-micro); font-weight: 600; color: var(--encre-3); text-transform: uppercase; letter-spacing: 0.05em; display: flex; align-items: center; gap: 6px; }
.pouls .quoi svg { width: 14px; height: 14px; }
.pouls .texte { font: var(--t-corps-fort); margin-top: 8px; overflow-wrap: anywhere; }
.pouls .rien { color: var(--encre-3); font-weight: 400; }
@media (max-width: 700px) { .pouls > div { border-left: 0; border-top: 1px solid var(--trait); } .pouls > div:first-child { border-top: 0; } }

/* Ce qui attend le lecteur : une liste courte et nette. */
.attente { border-radius: var(--r-carte); background: var(--attention-voile); padding: var(--e-4) var(--e-5); }
.attente-tete { display: flex; align-items: center; gap: 10px; font: var(--t-titre-3); }
.attente-tete svg { width: 18px; height: 18px; color: var(--attention); }
.attente .ligne { margin-inline: 0; width: 100%; }
.attente .ligne:hover { background: rgba(255,255,255,0.35); }
:root[data-theme="dark"] .attente .ligne:hover { background: rgba(255,255,255,0.06); }

/* La conversation : deux voix. */
.fil { display: flex; flex-direction: column; gap: var(--e-4); }
/* Le fil ne charge que les derniers messages : le plus ancien se demande. */
.fil-plus-anciens { display: flex; justify-content: center; margin: 0; }
.message { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 10px; min-width: 0; max-width: 100%; }
.message > div { min-width: 0; }
.message-tete { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.message-auteur { font: var(--t-petit); font-weight: 600; }
.message-date { font: var(--t-micro); color: var(--encre-3); }
.message-corps {
  display: inline-block; max-width: 100%;
  padding: 10px 14px; border-radius: 16px 16px 16px 4px;
  background: var(--fond-2); font: var(--t-corps); overflow-wrap: anywhere;
}
.message-corps p + p { margin-top: 8px; }
.message--interne .message-corps { background: var(--attention-voile); }

/* Mes messages basculent à droite, avatar compris, et prennent la couleur
   d'accent ; ceux d'en face restent à gauche, sur le fond neutre. */
.message--moi { grid-template-columns: minmax(0, 1fr) 32px; }
.message--moi > .avatar { order: 2; }
/* La bulle de texte est en ligne : c'est l'alignement du bloc qui la pousse
   à droite, une marge automatique ne mordrait pas sur un inline-block. */
.message--moi > div { order: 1; min-width: 0; text-align: right; }
.message--moi .message-corps { text-align: left; }
.message--moi .message-tete { justify-content: flex-end; }
/* Mon propre nom n'apprend rien : la place et la couleur le disent déjà.
   Il ne reste que l'heure. */
.message--moi .message-auteur { display: none; }
.message--moi .message-corps {
  background: var(--accent-voile);
  border-radius: 16px 16px 4px 16px;
  margin-left: auto;
}
.message--moi .pieces { justify-content: flex-end; }
.message--moi .message-cote { text-align: right; }
.marque-interne { font: var(--t-micro); font-weight: 600; color: var(--attention); text-transform: uppercase; letter-spacing: 0.05em; }
.composer { display: flex; flex-direction: column; gap: 10px; padding-top: var(--e-4); border-top: 1px solid var(--trait); margin-top: var(--e-4); }
.composer .zone { min-height: 80px; }
.composer-pied { display: flex; align-items: center; gap: 8px; }

/* Une fiche de fichier. */
.fichier { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 12px; border-radius: var(--r-champ); border: 1px solid var(--trait); background: var(--fond); }
.fichier:hover { border-color: var(--trait-fort); }
.fichier-icone { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; background: var(--fond-2); color: var(--encre-2); font: var(--t-micro); font-weight: 700; text-transform: uppercase; }
.fichier-icone--image { background: var(--violet-voile); color: var(--violet); }
.fichier-icone--pdf { background: var(--alerte-voile); color: var(--alerte); }
.fichier-nom { font: var(--t-corps-fort); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fichier-sous { font: var(--t-micro); color: var(--encre-3); margin-top: 2px; }

/* Une ligne de lien vers un environnement. */
.lien-env { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 12px; border-radius: var(--r-champ); border: 1px solid var(--trait); color: inherit; text-decoration: none; transition: border-color var(--vite), background var(--vite); }
.lien-env:hover { border-color: var(--trait-fort); background: var(--survol); text-decoration: none; }
.lien-env .url { font: var(--t-micro); color: var(--encre-3); font-family: var(--police-mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* La checklist. */
.coche { display: flex; align-items: center; gap: 10px; padding: 6px 0; font: var(--t-petit); }
.coche input { width: 16px; height: 16px; accent-color: var(--ok); margin: 0; }
.coche.faite span { color: var(--encre-3); text-decoration: line-through; }

/* Le montant d'une pièce comptable. */
.prix { display: flex; align-items: baseline; gap: 6px; font-variant-numeric: tabular-nums; }
.prix .montant { font: 700 26px / 1 var(--police); letter-spacing: var(--ls-serre); }
.prix .unite { font: var(--t-micro); color: var(--encre-3); }

/* Le calendrier en grille mensuelle. */
.calendrier { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.calendrier .jour-nom { font: var(--t-micro); color: var(--encre-3); text-align: center; padding: 6px 0; text-transform: uppercase; letter-spacing: 0.05em; }
.calendrier .jour { min-height: 84px; padding: 6px; border-radius: 10px; background: var(--fond-2); font: var(--t-micro); color: var(--encre-3); display: flex; flex-direction: column; gap: 3px; }
.calendrier .jour.hors { opacity: 0.4; }
.calendrier .jour.aujourdhui { box-shadow: inset 0 0 0 2px var(--accent); }
.calendrier .jour .numero { font-weight: 600; color: var(--encre); }
.calendrier .evt { font: var(--t-micro); font-weight: 500; padding: 2px 6px; border-radius: 5px; background: var(--accent-voile); color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-decoration: none; cursor: pointer; text-align: left; }
.calendrier .evt--violet { background: var(--violet-voile); color: var(--violet); }
.calendrier .evt--vert { background: var(--ok-voile); color: var(--ok); }
.calendrier .evt--ambre { background: var(--attention-voile); color: var(--attention); }
.calendrier .evt--rouge { background: var(--alerte-voile); color: var(--alerte); }
@media (max-width: 700px) { .calendrier .jour { min-height: 56px; } .calendrier .evt { font-size: 10px; padding: 1px 4px; } }

/* Le tiroir des notifications. */
.notif { display: grid; grid-template-columns: 8px minmax(0, 1fr); gap: 12px; padding: 12px 8px; border-radius: 12px; text-decoration: none; color: inherit; transition: background var(--vite); align-items: start; }
.notif:hover { background: var(--survol); text-decoration: none; }
.notif i { width: 8px; height: 8px; border-radius: 50%; background: transparent; margin-top: 7px; }
.notif.non-lu i { background: var(--accent); }
.notif .titre { font: var(--t-petit); font-weight: 600; }
.notif .texte { font: var(--t-petit); color: var(--encre-2); margin-top: 2px; }
.notif .date { font: var(--t-micro); color: var(--encre-3); margin-top: 4px; }

/* ==========================================================================
   11. La porte d'entrée
   ========================================================================== */

.porte { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: var(--e-5); background: var(--fond-2); }
.porte-boite { width: min(440px, 100%); background: var(--fond); border-radius: 24px; padding: var(--e-7) var(--e-6); box-shadow: var(--ombre-carte); }
.porte-boite .marque { display: flex; align-items: center; gap: 10px; font-weight: 600; margin-bottom: var(--e-6); }
.porte-boite .marque img { width: 28px; height: 28px; border-radius: 8px; }
.porte-boite h1 { font: var(--t-titre-1); letter-spacing: var(--ls-titre); }
.porte-pied { display: flex; justify-content: space-between; align-items: center; margin-top: var(--e-6); padding-top: var(--e-4); border-top: 1px solid var(--trait); }
@media (max-width: 500px) { .porte-boite { padding: var(--e-6) var(--e-5); border-radius: 18px; } }

/* Le sélecteur de thème, version compacte. */
.selecteur-theme { display: inline-flex; padding: 3px; border-radius: 10px; background: var(--fond-2); gap: 2px; }
.selecteur-theme button { height: 28px; padding: 0 10px; border-radius: 7px; font: var(--t-micro); font-weight: 500; color: var(--encre-2); }
.selecteur-theme button[aria-pressed="true"] { background: var(--fond); color: var(--encre); box-shadow: 0 1px 2px rgba(0,0,0,0.08); }

/* Le lien d'évitement. */
.saut { position: absolute; left: -9999px; top: 8px; z-index: 200; padding: 8px 12px; background: var(--encre); color: var(--fond); border-radius: 8px; }
.saut:focus { left: 8px; }

/* Impression : la page seule. */
@media print {
  .lat, .haut, .toasts, .voile { display: none !important; }
  .coq { grid-template-columns: 1fr; }
  .page { max-width: none; padding: 0; }
}

/* --- Les plateformes : une icône, un libellé, une couleur ---------------- */
.plateforme {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 10px;
  border-radius: var(--r-pilule);
  font: var(--t-micro); font-weight: 600;
  background: var(--gris-voile); color: var(--encre-2);
  white-space: nowrap;
}
.plateforme svg { width: 14px; height: 14px; }
.plateforme--bleu   { background: var(--accent-voile); color: var(--accent); }
.plateforme--vert   { background: var(--ok-voile); color: var(--ok); }
.plateforme--ambre  { background: var(--attention-voile); color: var(--attention); }
.plateforme--rouge  { background: var(--alerte-voile); color: var(--alerte); }
.plateforme--violet { background: var(--violet-voile); color: var(--violet); }
.plateforme--gris   { background: var(--gris-voile); color: var(--encre-2); }

/* Le choix d'une plateforme dans un formulaire : des pastilles, pas un menu. */
.choix-plateformes { display: flex; flex-wrap: wrap; gap: 8px; }
.choix-plateformes label { cursor: pointer; }
.choix-plateformes input { position: absolute; opacity: 0; width: 0; height: 0; }
.choix-plateformes .plateforme {
  height: 36px; padding: 0 14px; font-size: 13px;
  border: 1.5px solid transparent;
  transition: border-color var(--vite), transform var(--vite);
}
.choix-plateformes input:checked + .plateforme { border-color: currentColor; }
.choix-plateformes input:focus-visible + .plateforme { box-shadow: 0 0 0 3px var(--anneau); }
.choix-plateformes label:hover .plateforme { transform: translateY(-1px); }

/* ==========================================================================
   19. Micro-animations
   Rien de spectaculaire : de courts mouvements qui expliquent ce qui vient
   de changer. Tout reste sous 240 ms et tout se tait si la personne a
   demandé moins de mouvement (voir la règle en tête de fichier).
   ========================================================================== */

/* Le corps d'un onglet se pose quand on change de section, et seulement
   alors : une donnée qui arrive en temps réel redessine la page sans que
   rien ne clignote. */
#onglet-corps.corps-anime { animation: pose 200ms cubic-bezier(0.2, 0, 0, 1) both; }

/* Les onglets : le trait glisse sous celui qu'on survole avant d'être actif. */
.onglet { position: relative; }
.onglet::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--encre); border-radius: 2px;
  transform: scaleX(0); transform-origin: center;
  transition: transform var(--vite);
}
.onglet:hover::after { transform: scaleX(0.6); }
.onglet.actif::after { transform: scaleX(1); }
.onglet.actif { border-bottom-color: transparent; }

/* Les boutons s'enfoncent légèrement sous le doigt. */
.btn:active:not(:disabled) { transform: translateY(1px) scale(0.985); }
.btn-icone:active:not(:disabled), .btn-plier:active, .btn-deplier:active { transform: scale(0.92); }
.btn-icone, .btn-deplier { transition: background var(--vite), color var(--vite), transform var(--vite); }

/* La navigation : l'icône avance d'un cheveu au survol. */
.lat-lien svg { transition: transform var(--vite), opacity var(--vite); }
.lat-lien:hover svg { transform: translateX(1px); opacity: 1; }
.lat-lien .compte { transition: background var(--vite), color var(--vite); }

/* Les lignes de liste répondent au survol sans bouger la mise en page. */
.ligne { transition: background var(--vite), transform var(--vite); }
.ligne:hover { transform: translateX(2px); }
.ligne .ligne-fin svg { transition: transform var(--vite); }
.ligne:hover .ligne-fin svg { transform: translateX(2px); }

/* Les métriques et les cartes d'accueil arrivent l'une après l'autre. */
.corps-anime .metriques > .metrique { animation: pose 240ms cubic-bezier(0.2, 0, 0, 1) both; }
.corps-anime .metriques > .metrique:nth-child(2) { animation-delay: 30ms; }
.corps-anime .metriques > .metrique:nth-child(3) { animation-delay: 60ms; }
.corps-anime .metriques > .metrique:nth-child(4) { animation-delay: 90ms; }

/* Le voile du tiroir et les pastilles de compte. */
.badge--vif { transition: transform var(--vite); }
.lat-lien:hover .badge--vif { transform: scale(1.06); }

/* --- Les projets d'un client, en logos ------------------------------------
   Posés en bout de ligne, juste avant le chevron : on voit d'un coup d'œil
   ce que le client suit, et de quelle nature est chaque application. */
.pile-projets { display: inline-flex; align-items: center; gap: 10px; margin-right: 4px; }
.pile-projet { position: relative; display: inline-grid; line-height: 0; transition: transform var(--vite); }
.pile-projet:hover { transform: translateY(-2px); }
.pile-projet .avatar-projet { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
.pile-badge {
  position: absolute; right: -4px; bottom: -4px;
  width: 16px; height: 16px; border-radius: 50%;
  display: grid; place-items: center;
  border: 2px solid var(--fond);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}
.pile-badge svg { width: 9px; height: 9px; }
.pile-badge--bleu   { background: var(--accent-voile); color: var(--accent); }
.pile-badge--violet { background: var(--violet-voile); color: var(--violet); }
.pile-badge--ambre  { background: var(--attention-voile); color: var(--attention); }
.pile-reste { font: var(--t-micro); font-weight: 600; color: var(--encre-3); }

/* ==========================================================================
   20. La bulle de discussion d'un projet
   Posée en bas à droite, elle ne recouvre jamais le contenu tant qu'elle
   est fermée, et se plie en plein écran sur un téléphone.
   ========================================================================== */

.bulle {
  position: fixed; right: var(--e-5); bottom: calc(var(--e-5) + env(safe-area-inset-bottom, 0px));
  z-index: 70; display: flex; flex-direction: column-reverse; align-items: flex-end; gap: var(--e-3);
  /* Le conteneur ne dessine rien : il ne doit pas capter le doigt à la
     place du contenu qui passe dessous. */
  pointer-events: none;
}
.bulle-pastille, .bulle-panneau { pointer-events: auto; }

.bulle-pastille {
  position: relative; width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: #fff; border: 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  transition: transform var(--doux), box-shadow var(--doux), background var(--vite);
}
.bulle-pastille svg { width: 22px; height: 22px; transition: transform var(--doux); }
.bulle-pastille:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.22); }
.bulle-pastille:active { transform: scale(0.94); }
.bulle--ouverte .bulle-pastille svg { transform: rotate(-8deg) scale(0.9); }
.bulle-compte {
  position: absolute; top: -2px; right: -2px; min-width: 20px; height: 20px;
  padding: 0 5px; border-radius: 10px;
  background: var(--alerte); color: #fff;
  font: var(--t-micro); font-weight: 700; line-height: 20px; text-align: center;
  border: 2px solid var(--fond);
  animation: pose var(--doux) both;
}
/* Tant qu'un message attend, la pastille respire, sans jamais s'agiter. */
.bulle--alerte .bulle-pastille { animation: respire 2.4s ease-in-out infinite; }
@keyframes respire {
  0%, 100% { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 0 0 0 var(--accent-voile); }
  50%      { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 0 0 10px transparent; }
}

.bulle-panneau {
  width: min(380px, calc(100vw - var(--e-5) * 2));
  height: min(560px, calc(100dvh - 140px));
  display: flex; flex-direction: column;
  background: var(--fond); border: 1px solid var(--trait);
  border-radius: 18px; overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.22);
  transform-origin: bottom right;
  animation: bulleEntre 220ms cubic-bezier(0.2, 0, 0, 1) both;
}
@keyframes bulleEntre { from { opacity: 0; transform: translateY(12px) scale(0.96); } to { opacity: 1; transform: none; } }
.bulle-panneau.survole { outline: 2px dashed var(--accent); outline-offset: -6px; }

.bulle-tete {
  display: flex; align-items: center; justify-content: space-between; gap: var(--e-2);
  padding: 12px 10px 12px 14px; border-bottom: 1px solid var(--trait);
  background: var(--fond-2); flex: none;
}
.bulle-tete-qui { display: flex; align-items: center; gap: 10px; min-width: 0; }
.bulle-tete-gestes { display: flex; align-items: center; gap: 2px; flex: none; }
.bulle-titre { font: var(--t-corps-fort); font-size: 14px; }
.bulle-sous { font: var(--t-micro); color: var(--encre-3); }
.bulle-point { width: 8px; height: 8px; border-radius: 50%; background: var(--trait-fort); flex: none; transition: background var(--vite); }
.bulle-point.vif { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-voile); }
#bulle-son.actif { color: var(--accent); }

.bulle-fil { flex: 1; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: var(--e-4); display: flex; flex-direction: column; gap: var(--e-4); }
.bulle-fil > * { min-width: 0; max-width: 100%; }
.bulle-message { min-width: 0; }
/* Le geste « en faire une demande » se pose à l'intérieur, jamais au-delà
   du bord : sinon le fil se met à défiler de côté. */
.bulle-message:has(.message--moi) .bulle-action { right: auto; left: 0; }
/* Pas d'animation d'entrée sur les messages : le fil se remplit parfois
   pendant que le panneau est replié, et une animation qui ne démarre pas
   laisserait le message invisible une fois le panneau rouvert. */
.bulle-accuse { align-self: flex-end; display: flex; align-items: center; gap: 4px; font: var(--t-micro); color: var(--encre-3); }
.bulle-accuse svg { width: 13px; height: 13px; color: var(--accent); }
.bulle-vide { margin: auto; text-align: center; color: var(--encre-3); display: grid; gap: 10px; justify-items: center; padding: var(--e-5); }
.bulle-vide svg { width: 28px; height: 28px; opacity: 0.5; }
.bulle-vide p { font: var(--t-petit); max-width: 28ch; }

/* Les trois points de la frappe : ils montent l'un après l'autre. */
.bulle-frappe { display: flex; align-items: center; gap: 4px; padding: 0 var(--e-4) 8px; font: var(--t-micro); color: var(--encre-3); }
.bulle-frappe i { width: 5px; height: 5px; border-radius: 50%; background: var(--encre-4); animation: saute 1.1s infinite; }
.bulle-frappe i:nth-child(2) { animation-delay: 0.15s; }
.bulle-frappe i:nth-child(3) { animation-delay: 0.3s; }
.bulle-frappe span { margin-left: 4px; }
@keyframes saute { 0%, 60%, 100% { transform: none; opacity: 0.45; } 30% { transform: translateY(-4px); opacity: 1; } }

.bulle-pied { border-top: 1px solid var(--trait); padding: 10px; flex: none; background: var(--fond); }
.bulle-saisie { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: end; gap: 6px; }
.bulle-saisie .zone {
  min-height: 40px; max-height: 132px; resize: none; padding: 10px 12px;
  border-radius: 14px; overflow-y: auto;
}
.bulle-envoyer { width: 40px; height: 40px; padding: 0; border-radius: 50%; background: var(--accent); color: #fff; flex: none; }
.bulle-envoyer svg { width: 17px; height: 17px; }
.bulle-joindre { width: 40px; height: 40px; flex: none; }
.depot--compact { display: none; }
#bulle-pieces .pieces:not(:empty) { margin-bottom: 8px; }
.fil { overflow-x: hidden; }
.fil > * { min-width: 0; max-width: 100%; }

@media (max-width: 640px) {
  .bulle { right: var(--e-4); bottom: var(--e-4); left: var(--e-4); align-items: flex-end; }
  .bulle-panneau { width: 100%; height: min(72dvh, 560px); }
}

/* L'en-tête de la bulle : le logo du projet, le nom du contact d'en face. */
.bulle-logo { flex: none; line-height: 0; }
.bulle-tete-texte { min-width: 0; }
.bulle-titre { display: flex; align-items: center; gap: 7px; }
.bulle-titre span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Un message porte un geste discret : en faire une demande, sur place. */
.bulle-message { position: relative; }
.bulle-action {
  position: absolute; top: 0; right: 0;
  width: 26px; height: 26px; border-radius: 8px;
  display: grid; place-items: center;
  border: 1px solid var(--trait); background: var(--fond); color: var(--encre-3);
  opacity: 0; transform: translateY(-2px); cursor: pointer;
  transition: opacity var(--vite), transform var(--vite), color var(--vite), border-color var(--vite);
}
.bulle-action svg { width: 13px; height: 13px; }
.bulle-message:hover .bulle-action, .bulle-action:focus-visible { opacity: 1; transform: none; }
.bulle-action:hover { color: var(--accent); border-color: var(--accent); }

/* Le compte posé contre un titre de section : un chiffre, pas une alerte. */
.compte-section {
  font: var(--t-petit); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--encre-3); background: var(--fond-2);
  padding: 1px 8px; border-radius: var(--r-pilule);
  vertical-align: middle; margin-left: 2px;
}
.compte-section--vif { background: var(--alerte-voile); color: var(--alerte); }

/* Les jetons de plateforme : l'icône seule, alignée avec les indicateurs
   de fin de ligne. Le libellé passe dans l'info-bulle. */
.jetons { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.jeton {
  width: 24px; height: 24px; border-radius: 7px;
  display: grid; place-items: center; flex: none;
  transition: transform var(--vite);
}
.jeton svg { width: 13px; height: 13px; }
.ligne:hover .jeton { transform: translateY(-1px); }
.jeton--bleu   { background: var(--accent-voile); color: var(--accent); }
.jeton--vert   { background: var(--ok-voile); color: var(--ok); }
.jeton--ambre  { background: var(--attention-voile); color: var(--attention); }
.jeton--rouge  { background: var(--alerte-voile); color: var(--alerte); }
.jeton--violet { background: var(--violet-voile); color: var(--violet); }
.jeton--gris   { background: var(--gris-voile); color: var(--encre-2); }
@media (max-width: 720px) { .jetons { display: none; } }

/* --- Les avatars de client, en couleur ------------------------------------
   Une teinte par nom, stable d'une liste à l'autre. Les fonds sont voilés
   pour que le texte reste lisible dans les deux thèmes. */
/* Fond plein et initiales blanches : ces teintes tiennent sur le fond
   clair comme sur le fond sombre, sans avoir à se dédoubler par thème. */
.avatar[class*="avatar--t-"] { color: #fff; }
.avatar--t-bleu     { background: #0075DE; }
.avatar--t-vert     { background: #1F9D55; }
.avatar--t-violet   { background: #6E56CF; }
.avatar--t-ambre    { background: #C77700; }
.avatar--t-rouge    { background: #D93025; }
.avatar--t-sarcelle { background: #0F7A72; }
.avatar--t-rose     { background: #B4326E; }
.avatar--t-indigo   { background: #3B47C4; }

/* L'avatar du client et le logo d'un de ses projets, en pile. */
.pile-avatar { position: relative; display: inline-grid; line-height: 0; flex: none; }
.pile-avatar-jeton { position: absolute; right: -5px; bottom: -5px; line-height: 0; }
.pile-avatar-jeton .avatar-projet {
  width: 18px; height: 18px; border-radius: 6px; font-size: 8px;
  border: 2px solid var(--fond);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.14);
}
.avatar-projet--mini { width: 18px; height: 18px; border-radius: 6px; font-size: 8px; }

/* --- La page d'une brique -------------------------------------------------
   L'icône de la plateforme en grand, et les notes de version en liste. */
.brique-icone {
  width: 64px; height: 64px; border-radius: 18px; flex: none;
  display: grid; place-items: center;
  background: var(--gris-voile); color: var(--encre-2);
}
.brique-icone svg { width: 28px; height: 28px; }
.brique-icone--bleu   { background: var(--accent-voile);    color: var(--accent); }
.brique-icone--vert   { background: var(--ok-voile);        color: var(--ok); }
.brique-icone--ambre  { background: var(--attention-voile); color: var(--attention); }
.brique-icone--rouge  { background: var(--alerte-voile);    color: var(--alerte); }
.brique-icone--violet { background: var(--violet-voile);    color: var(--violet); }
.brique-icone--gris   { background: var(--gris-voile);      color: var(--encre-2); }

.notes-version { list-style: none; margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.notes-version li { display: flex; align-items: flex-start; gap: 8px; font: var(--t-petit); color: var(--encre-2); }
.notes-version li .puce { flex: none; margin-top: 1px; }
.chrono-point--ok { background: var(--ok); }

/* Le dépliant d'une longue liste : ouvert, il ne pousse rien hors cadre. */
.depliant > summary {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  padding: 12px 0; list-style: none;
  border-bottom: 1px solid var(--trait);
}
.depliant > summary::-webkit-details-marker { display: none; }
.depliant > summary::after {
  content: ""; width: 8px; height: 8px; margin-left: auto;
  border-right: 2px solid var(--encre-3); border-bottom: 2px solid var(--encre-3);
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--vite);
}
.depliant[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.depliant > summary:hover { color: var(--encre); }
.depliant .tableau { display: block; max-height: 420px; overflow: auto; }

.etiquette--techno { text-transform: none; letter-spacing: 0; }
.etiquette--techno b { font-weight: 700; font-variant-numeric: tabular-nums; }

/* La lecture française d'une date, sous le champ natif du navigateur. */
.aide--date { color: var(--encre-2); font-weight: 500; }

/* ==========================================================================
   La tenue des délais, et la vie d'une demande
   ========================================================================== */

/* La carte des délais. Elle répond à la seule question pour laquelle un
   client décrochait son téléphone : est-ce qu'on tient la date. */
.delais { display: flex; flex-direction: column; gap: var(--e-5); }
.delais-tete {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--e-4); flex-wrap: wrap;
}
.delais-verdict { flex: none; }
.delais-risques, .delais-reports {
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
}
.delais-risques ul { list-style: none; margin: 0; padding: 0; }

/* L'anneau qui ne sait pas : un trait discontinu plutôt qu'un zéro. */
.anneau--vide { background: none; border: 2px dashed var(--trait); }
.anneau--vide span { color: var(--encre-3); }

/* La bande « où en est ma demande ». Elle vient avant tout le reste,
   parce que c'est la première chose que le client cherche. */
.suivi-demande {
  margin-top: var(--e-5);
  padding: var(--e-5);
  border-radius: var(--r-carte);
  border: 1px solid var(--trait);
  background: var(--fond);
}
.suivi-demande--info { background: var(--accent-voile); border-color: transparent; }
.suivi-demande--attention { background: var(--attention-voile); border-color: transparent; }
.suivi-demande--ok { background: var(--ok-voile); border-color: transparent; }
.suivi-demande-tete { display: flex; gap: var(--e-4); align-items: flex-start; }
.suivi-demande-pastille {
  flex: none; width: 34px; height: 34px; border-radius: 11px;
  display: grid; place-items: center;
  background: var(--fond); color: var(--encre-2);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}
.suivi-demande-pastille svg { width: 17px; height: 17px; }
.suivi-demande-faits {
  display: grid; gap: var(--e-4) var(--e-5);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin: var(--e-5) 0 0;
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
}
.suivi-demande-faits dt { font: var(--t-micro); color: var(--encre-3); }
.suivi-demande-faits dd { margin: 2px 0 0; font: var(--t-corps-fort); font-size: 13px; }
.suivi-demande-note { margin: var(--e-4) 0 0; font: var(--t-petit); color: var(--encre-2); }

/* Le bloc de report ne s'ouvre qu'à la vraie différence de date. */
.report-bloc {
  padding: var(--e-4);
  border-radius: var(--r-champ);
  background: var(--fond-2);
  border: 1px solid var(--trait);
}

/* Un mot qui alerte à l'intérieur d'une phrase. */
.t-alerte { color: var(--alerte); font-weight: 500; }

/* Le champ des six chiffres : grand, espacé, centré. On le lit à voix
   haute depuis son téléphone tout en le tapant, il doit être net. */
.champ-code {
  font: 600 28px / 1.2 var(--police);
  letter-spacing: 0.34em;
  text-align: center;
  text-indent: 0.34em;
  font-variant-numeric: tabular-nums;
  padding-block: 14px;
}
.champ-code::placeholder { color: var(--encre-4); letter-spacing: 0.34em; }

/* ==========================================================================
   Le rideau : un projet qui se prépare, avant d'être ouvert au client
   ========================================================================== */

.rideau {
  padding: var(--e-5);
  border-radius: var(--r-carte);
  background: var(--fond-2);
  border: 1px dashed var(--trait-fort);
}
.rideau-tete { display: flex; align-items: center; gap: var(--e-4); flex-wrap: wrap; }
.rideau-icone {
  flex: none; width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--fond); color: var(--encre-2);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}
.rideau-icone svg { width: 19px; height: 19px; }
.rideau-manque {
  display: flex; align-items: center; gap: 8px;
  margin: var(--e-4) 0 0;
  font: var(--t-petit); color: var(--attention);
}
.rideau-manque svg { width: 16px; height: 16px; flex: none; }
.rideau-etat {
  display: grid; gap: var(--e-4) var(--e-5);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin: var(--e-5) 0 0;
  padding-top: var(--e-4);
  border-top: 1px solid var(--trait);
}
.rideau-etat dt { font: var(--t-micro); color: var(--encre-3); }
.rideau-etat dd { margin: 2px 0 0; font: var(--t-corps-fort); font-size: 13px; }

/* ==========================================================================
   La plateforme de tests
   ========================================================================== */

/* Une ligne de scénario : la référence, le titre, le niveau de couverture.
   Le liseré à gauche marque les scénarios passés par deux testeurs : c'est
   ce qui coûte le double, et ça doit se voir en parcourant la liste. */
.bloc-scenarios { margin-top: 22px; }
.bloc-scenarios:first-of-type { margin-top: 14px; }

.bloc-tete {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; letter-spacing: .02em;
  color: var(--encre-3); text-transform: uppercase;
  margin: 0 0 8px;
}

.liste--serree { gap: 2px; }

.scenario {
  display: flex; align-items: center; gap: 4px;
  border-radius: 10px;
  transition: background-color .12s ease;
}
.scenario:hover { background: var(--fond-2); }

/* Un point discret devant la référence : il marque les scénarios passés
   par deux testeurs, donc payés deux fois. Un liseré vertical découpait la
   liste en tronçons et donnait l'impression d'un tableau cassé. */
.scenario-marque {
  flex: 0 0 auto; width: 6px; height: 6px; margin-right: 2px;
  border-radius: 50%; background: transparent;
}
.scenario--double .scenario-marque { background: var(--bleu-systeme); }

.scenario-corps {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 12px;
  padding: 9px 10px;
  background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}

.scenario-ref {
  flex: 0 0 auto; min-width: 58px;
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--encre-3);
}

.scenario-titre {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.scenario-fin {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 6px;
}

/* Les boutons de modification n'apparaissent qu'au survol : une liste de
   173 lignes avec deux icônes par ligne devient illisible. */
.scenario .boutons-edition { opacity: 0; transition: opacity .12s ease; padding-right: 6px; }
.scenario:hover .boutons-edition,
.scenario:focus-within .boutons-edition { opacity: 1; }
@media (hover: none) { .scenario .boutons-edition { opacity: 1; } }

.couverture { gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
.couverture .puce { gap: 6px; }

.puce--mini { font-size: 11px; padding: 1px 6px; }

/* La console de tests : la barre de filtres, et les chiffres du haut. */
.barre-tests { gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }

/* ---------------------------------------------------------------------
   La console de tests : trois étages, pas neuf sections plates.

   Un tableau de bord se balaie, il ne se lit pas. Ce qui donne un repère
   à l'œil, ce n'est pas un pictogramme dans une pastille, c'est la
   STRUCTURE : un surtitre d'étage, une phrase de résumé avec les chiffres
   en gras, puis les sections de l'étage en retrait. La couleur est
   réservée à ce qui porte une donnée (une jauge, une barre, une alerte),
   jamais à un titre.
   --------------------------------------------------------------------- */
/* ---------------------------------------------------------------------
   La frise d'un devis : les lignes du devis, dans l'ordre, à cocher.
   Une case pour l'équipe, une coche pour le client, la même frise pour
   les deux. La couleur ne va qu'à ce qui est fait.
   --------------------------------------------------------------------- */
.frise { border: 1px solid var(--trait); border-radius: var(--r-carte); padding: 18px 20px 8px; background: var(--fond-2); }
.frise + .frise { margin-top: 16px; }
.frise-tete { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.frise-titre { font: var(--t-corps-fort); color: var(--encre); }
.frise-sous { font: var(--t-petit); color: var(--encre-3); margin-top: 2px; }
.frise-sous b { font-weight: 650; color: var(--encre); font-variant-numeric: tabular-nums; }
.frise-pct { font: var(--t-titre-2); font-weight: 650; font-variant-numeric: tabular-nums; color: var(--encre); white-space: nowrap; }
.frise-jauge { height: 6px; border-radius: 999px; background: var(--fond-3); overflow: hidden; margin: 14px 0 6px; }
.frise-jauge i { display: block; height: 100%; background: var(--ok); border-radius: 999px; transition: width var(--vite); }
.frise-etapes { list-style: none; margin: 0; padding: 0; }
.frise-etape {
  display: grid; grid-template-columns: 28px 30px minmax(0, 1fr) auto;
  gap: 0 12px; align-items: center;
  padding: 12px 0; border-top: 1px solid var(--trait);
}
.frise-case { display: grid; place-items: center; cursor: pointer; }
.frise-case input { width: 18px; height: 18px; accent-color: var(--ok); margin: 0; cursor: pointer; }
.frise-coche { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--trait-fort); display: grid; place-items: center; color: #fff; }
.frise-coche svg { width: 12px; height: 12px; }
.est-faite .frise-coche { background: var(--ok); border-color: var(--ok); }
.frise-num { font-family: var(--police-mono); font-size: 12px; color: var(--encre-4); font-variant-numeric: tabular-nums; }
.frise-corps { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.frise-libelle { font: var(--t-corps-fort); color: var(--encre); overflow-wrap: anywhere; }
.est-faite .frise-libelle { color: var(--encre-2); }
.frise-detail { font: var(--t-petit); color: var(--encre-3); }
.frise-fin { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
/* La pastille de statut est un bouton pour l'équipe : même apparence,
   plus un chevron qui dit qu'elle s'ouvre. */
.frise-statut { display: inline-flex; align-items: center; gap: 2px; background: none; border: 0; padding: 0; cursor: pointer; border-radius: var(--r-pilule); }
.frise-statut svg { width: 14px; height: 14px; color: var(--encre-4); }
.frise-statut:hover svg, .frise-statut:focus-visible svg { color: var(--encre); }
.frise-statut:focus-visible { outline: 2px solid var(--anneau); outline-offset: 2px; }
.frise-fin .btn-icone { width: 28px; height: 28px; }
.frise-fin .btn-icone svg { width: 16px; height: 16px; }
.frise-montant { font: var(--t-petit); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--encre-2); }
.est-faite .frise-montant { color: var(--ok); }
@media (max-width: 640px) {
  .frise-etape { grid-template-columns: 28px minmax(0, 1fr); }
  .frise-num { display: none; }
  .frise-fin { grid-column: 2; justify-content: flex-start; }
}

.etage { margin-top: 56px; }

/* Le « i » d'un titre : discret au repos, il ne concurrence pas le
   titre. Il s'allume au survol, parce que c'est là qu'on le cherche. */
.btn-info {
  display: inline-grid; place-items: center; vertical-align: 2px;
  width: 20px; height: 20px; margin-left: 4px;
  border: 0; border-radius: 50%; background: none; padding: 0;
  color: var(--encre-4); cursor: pointer;
}
.btn-info svg { width: 16px; height: 16px; }
.btn-info:hover, .btn-info:focus-visible { color: var(--accent); background: var(--accent-voile); }

/* Le texte d'une explication : des paragraphes courts, une liste quand
   il y a des états à distinguer. */
.prose p { font: var(--t-corps); color: var(--encre-2); margin: 0 0 12px; max-width: 62ch; }
.prose p:last-child { margin-bottom: 0; }
.prose b { color: var(--encre); font-weight: 600; }
.prose ul { margin: 0 0 12px; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.prose li { font: var(--t-corps); color: var(--encre-2); }
.etage-tete {
  display: flex; flex-direction: column; gap: 6px;
  padding-bottom: 14px; margin-bottom: 4px;
  border-bottom: 1px solid var(--trait-fort);
}
.etage-sur {
  font: var(--t-micro); font-weight: 600; letter-spacing: var(--ls-large);
  text-transform: uppercase; color: var(--encre-3);
}
.etage-resume {
  font: var(--t-titre-3); font-weight: 450; color: var(--encre-2);
  max-width: 62ch; text-wrap: balance;
}
.etage-resume b { font-weight: 650; color: var(--encre); font-variant-numeric: tabular-nums; }
.etage .section { margin-top: 36px; }

/* Une référence de test est un code, pas un mot. La chasse fixe le dit
   d'elle-même, et donne aux sections machine une texture différente des
   sections humaines sans ajouter un seul pictogramme. */
.ref {
  font-family: var(--police-mono); font-size: 12.5px; font-weight: 500;
  color: var(--encre-2); background: var(--fond-2);
  border: 1px solid var(--trait); border-radius: 6px;
  padding: 1px 6px; vertical-align: 1px; white-space: nowrap;
}
.scenario-ref { font-family: var(--police-mono); font-weight: 500; }

/* La jauge : l'état des parcours en une seule forme. Quatre tuiles
   disaient la même chose en quatre fois plus de place, et sans montrer
   les proportions. */
.jauge {
  display: flex; gap: 2px; height: 10px;
  border-radius: 999px; overflow: hidden; background: var(--fond-3);
}
.jauge > i { display: block; height: 100%; min-width: 0; background: var(--encre-4); }
.jauge > i[data-ton="vert"]  { background: var(--ok); }
.jauge > i[data-ton="rouge"] { background: var(--alerte); }
.jauge > i[data-ton="ambre"] { background: var(--attention); }
.jauge > i[data-ton="bleu"]  { background: var(--accent); }
.jauge-legende { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 10px; }
.jauge-legende .puce b { font-weight: 650; font-variant-numeric: tabular-nums; color: var(--encre); }

/* Les barres : une famille par ligne, la longueur dit le nombre de cas.
   C'est le graphique le plus lisible qui existe, et il n'a besoin
   d'aucune bibliothèque. */
.barres {
  display: grid; grid-template-columns: minmax(120px, 190px) minmax(0, 1fr) 52px;
  gap: 9px 14px; align-items: center;
}
.barres-nom { font: var(--t-petit); color: var(--encre-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.barres-piste { height: 8px; border-radius: 999px; overflow: hidden; background: var(--fond-3); }
.barres-piste i { display: block; height: 100%; border-radius: 999px; background: var(--encre-4); }
.barres-piste i[data-ton="vert"]  { background: var(--ok); }
.barres-piste i[data-ton="rouge"] { background: var(--alerte); }
.barres-val { font: var(--t-petit); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; color: var(--encre); }

/* La doctrine, sous chaque jauge : le seul chiffre qui distingue une
   garde d'un fichier. Il est gros parce qu'il est le plus important, et
   il n'a pas de tuile parce qu'il n'est pas un compteur, c'est un aveu. */
.doctrine { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-top: 16px; font: var(--t-petit); color: var(--encre-3); }
.doctrine b { font: var(--t-titre-3); font-weight: 650; font-variant-numeric: tabular-nums; color: var(--encre); white-space: nowrap; }

/* Le seul endroit où la couleur est dépensée en surface : ce qui ne va
   pas. Quand il n'y a rien, le panneau disparaît et il reste une ligne :
   l'absence de couleur est l'information. */
.section--alerte { background: var(--alerte-voile); border-radius: var(--r-carte); padding: 18px 22px 20px; }
.section--alerte .section-tete h2 { color: var(--alerte); }
.section--alerte .ligne { background: transparent; }
.calme { display: flex; align-items: center; gap: 10px; font: var(--t-petit); color: var(--encre-3); margin-top: 6px; }
.calme svg { width: 16px; height: 16px; color: var(--ok); flex: none; }

/* L'index de page, collé à droite sur grand écran. Trois étages et huit
   sections, ça se saute, ça ne se fait pas défiler. */
.tests-corps { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 48px; align-items: start; }
.index-page { display: none; }
@media (min-width: 1360px) {
  .tests-corps--index { grid-template-columns: minmax(0, 1fr) 172px; }
  .index-page { display: block; position: sticky; top: 84px; padding-top: 60px; }
}
.index-page .etage-sur { display: block; margin-bottom: 8px; }
.index-page button {
  display: flex; justify-content: space-between; gap: 10px; width: 100%;
  background: none; border: 0; padding: 5px 0; cursor: pointer;
  font: var(--t-petit); color: var(--encre-3); text-align: left;
}
.index-page button:hover { color: var(--encre); }
.index-page button b { font-weight: 500; font-variant-numeric: tabular-nums; color: var(--encre-4); }
.index-page .index-etage { margin-top: 14px; }

.chiffres-tests { gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.chiffre {
  flex: 1 1 140px; min-width: 0;
  padding: 14px 16px;
  background: var(--fond-2);
  border: 1px solid var(--trait);
  border-radius: 14px;
  display: flex; flex-direction: column; gap: 2px;
}

.chiffre-valeur {
  font-size: 30px; font-weight: 650; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.chiffre-nom { font: var(--t-micro); font-weight: 400; color: var(--encre-3); }
/* Le seul chiffre qui change de couleur est celui qui demande une action :
   une anomalie ouverte. Colorer les quatre reviendrait à n'en colorer aucun. */
.chiffre--alerte .chiffre-valeur { color: var(--alerte); }

/* Le choix des blocs, dans la feuille d'une campagne. Deux colonnes : neuf
   blocs en une seule colonne poussent le bouton d'enregistrement trop bas. */
.cases-blocs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 6px 14px;
}
.cases-blocs .case { padding: 4px 0; }

/* ==========================================================================
   L'espace testeur
   ========================================================================== */

/* Une seule colonne, large sur téléphone : le testeur tient son appareil
   d'une main et coche de l'autre. Les trois boutons sont donc gros. */
.page--testeur { max-width: 760px; margin: 0 auto; padding: 22px 16px 80px; }

.testeur-tete { margin-bottom: 22px; }
.testeur-tete h1 { margin: 2px 0 0; }

.testeur-jauge {
  height: 8px; margin-top: 16px;
  background: var(--fond-2); border-radius: 99px; overflow: hidden;
}
.testeur-jauge-barre {
  height: 100%; background: var(--bleu-systeme);
  border-radius: 99px; transition: width .3s ease;
}

.testeur-filtres { gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }

.t-scenario {
  border: 1px solid var(--trait); border-radius: 14px;
  padding: 4px 4px 4px 0; margin-bottom: 8px;
  background: var(--fond-eleve);
}
/* Un coché se retire visuellement sans disparaître : le testeur doit
   pouvoir se corriger, et voir d'un coup d'œil ce qui reste. */
.t-scenario--ok { opacity: .6; }
.t-scenario--na { opacity: .6; }
.t-scenario--ko { border-color: var(--alerte); }

.t-scenario-corps {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 14px; background: none; border: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: left;
}
.t-scenario-ref {
  flex: 0 0 auto; min-width: 58px;
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--encre-3);
}
.t-scenario-titre { flex: 1; min-width: 0; }

.t-scenario-choix { display: flex; gap: 6px; padding: 0 10px 8px 72px; }
.t-choix {
  flex: 1; padding: 10px 8px;
  border: 1px solid var(--trait); border-radius: 10px;
  background: var(--fond); font: inherit; font-weight: 600; font-size: 14px;
  cursor: pointer; transition: background-color .12s ease, border-color .12s ease;
}
.t-choix:hover { background: var(--fond-2); }
.t-choix[aria-pressed="true"] { color: #fff; border-color: transparent; }
.t-choix--ok[aria-pressed="true"] { background: #1E8E3E; }
.t-choix--ko[aria-pressed="true"] { background: var(--alerte); }
.t-choix--na[aria-pressed="true"] { background: var(--encre-3); }

@media (max-width: 560px) {
  .t-scenario-choix { padding-left: 14px; }
  .t-choix { padding: 12px 8px; }
}

/* Le questionnaire d'appréciation */
.avis-famille { margin-bottom: 28px; }
.avis-famille:last-child { margin-bottom: 0; }

.avis-echelle { display: flex; gap: 6px; }
.avis-cran {
  flex: 1; padding: 12px 0;
  border: 1px solid var(--trait); border-radius: 10px;
  background: var(--fond); font: inherit; font-weight: 600;
  font-variant-numeric: tabular-nums; cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease;
}
.avis-cran:hover { background: var(--fond-2); }
.avis-cran[aria-pressed="true"] {
  background: var(--bleu-systeme); border-color: transparent; color: #fff;
}
/* De 0 à 10, les crans deviennent étroits : on les laisse plus petits
   plutôt que de les faire déborder. */
.avis-echelle--large .avis-cran { padding: 10px 0; font-size: 13px; }

.avis-bornes {
  justify-content: space-between; margin-top: 6px;
  font: var(--t-micro); font-weight: 400; color: var(--encre-3);
}

.avis-choix {
  padding: 9px 14px;
  border: 1px solid var(--trait); border-radius: 99px;
  background: var(--fond); font: inherit; font-size: 14px; cursor: pointer;
  transition: background-color .12s ease, border-color .12s ease;
}
.avis-choix:hover { background: var(--fond-2); }
.avis-choix[aria-pressed="true"] {
  background: var(--bleu-systeme); border-color: transparent; color: #fff;
}

.avis-appel { margin-bottom: 18px; }

.lien-sobre {
  background: none; border: 0; padding: 0;
  font: inherit; color: var(--bleu-systeme);
  text-decoration: underline; cursor: pointer;
}

/* La restitution des avis */
.avis-mesure { margin-bottom: 16px; }
.avis-verbatims { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }

/* Une réponse libre est rendue mot pour mot : c'est là qu'est la vraie
   information, et un résumé la tue. On la met donc en avant. */
.avis-verbatim {
  margin: 0; padding: 12px 14px;
  background: var(--fond-2); border-radius: 12px;
  border-left: 3px solid var(--bleu-systeme);
}
.avis-verbatim p { margin: 0; white-space: pre-wrap; }
.avis-verbatim cite {
  display: block; margin-top: 6px;
  font: var(--t-micro); font-weight: 500; font-style: normal;
  color: var(--encre-3);
}

/* Un testeur inscrit mais affecté à rien : une place payée pour rien. */
.puce--vide { color: var(--encre-3); }

/* --- Le questionnaire sur la page, et les résultats d'une campagne ------
   Une question sans réponse reste lisible : l'énoncé, puis ce qu'on
   attend comme réponse, en retrait. C'est ce que le client lit avant
   que la campagne commence. */
.avis-question { font: var(--t-corps); color: var(--encre); }
.avis-mesure--vide { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--trait); margin-bottom: 0; }
.avis-mesure--vide:last-child { border-bottom: 0; }
.avis-forme { font: var(--t-petit); color: var(--encre-3); }
.avis-famille .bloc-tete .etiquette { margin-left: 10px; vertical-align: middle; }
.jauge > i[data-ton="gris"]  { background: var(--encre-4); }
.puce--gris i { background: var(--encre-4); }

.resultat { margin-top: 14px; }
.resultat-tete { display: flex; align-items: baseline; gap: 8px; margin: 0 0 6px; font: var(--t-corps-fort); color: var(--encre); }
.resultat-tete span { font-weight: 500; color: var(--encre-2); }

/* --- La maintenance continue -------------------------------------------
   Le forfait est une carte, comme la frise d'un devis : même bord, même
   fond, mêmes chiffres en gras. Une séquence est une frise à son tour,
   avec sa jauge de jours. Rien de nouveau à apprendre pour l'œil. */
.forfait { border: 1px solid var(--trait); border-radius: var(--r-carte); padding: 18px 20px; background: var(--fond-2); }
.forfait-tete { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.forfait-titre { font: var(--t-titre-2); letter-spacing: var(--ls-titre); color: var(--encre); margin: 0; }
.forfait-sous { font: var(--t-petit); color: var(--encre-3); margin: 4px 0 0; }
.forfait-sous b { font-weight: 650; color: var(--encre); font-variant-numeric: tabular-nums; }
.forfait-actions { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.forfait-chiffres { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px 20px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--trait); }
.forfait-chiffre { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.forfait-chiffre b { font-size: 24px; font-weight: 650; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--encre); }
.forfait-chiffre span { font: var(--t-micro); color: var(--encre-3); }
.liste-points { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.liste-points li { font: var(--t-corps); color: var(--encre-2); }
.citation { border-left: 2px solid var(--trait-fort); padding: 6px 0 6px 16px; margin: 0; font: var(--t-corps); color: var(--encre-2); white-space: pre-line; overflow-wrap: anywhere; }
.citation cite { display: block; margin-top: 8px; font: var(--t-petit); font-style: normal; color: var(--encre-3); }
.sequence-journees { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--trait); }
.sequence-journees .ligne { padding-top: 8px; padding-bottom: 8px; }
.deux-colonnes { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px 32px; }

/* ==========================================================================
   LE TABLEAU DES TESTS
   Une carte par famille, une case par test. Le même dessin dans le cockpit,
   le hub et l'espace testeur. Les rayons sont plus généreux qu'ailleurs :
   c'est un écran qu'on regarde de loin, pas un formulaire.
   ========================================================================== */
:root {
  --case-ok: #1F9D55; --case-fragile: #E08A00; --case-casse: #D93A2F;
  --case-cours: var(--accent); --case-na: #A1A1A6; --case-vide: #E4E4E9;
  --case-trou: #ECECEF; --case-signe: #FFFFFF;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --case-ok: #3FC46A; --case-fragile: #F2B33D; --case-casse: #F26B5E;
    --case-na: #6E6E73; --case-vide: #2E2E32; --case-trou: #232326; --case-signe: #161617;
  }
}
:root[data-theme="dark"] {
  --case-ok: #3FC46A; --case-fragile: #F2B33D; --case-casse: #F26B5E;
  --case-na: #6E6E73; --case-vide: #2E2E32; --case-trou: #232326; --case-signe: #161617;
}

.tb { display: grid; gap: 14px; }
.tb-tete { background: var(--fond); border: 1px solid var(--trait); border-radius: 24px; padding: 20px 22px; display: grid; gap: 14px; }
.tb-tete-ligne { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.tb-tete-texte { min-width: 0; }
.tb-titre { font: var(--t-titre-2); letter-spacing: var(--ls-titre); margin: 2px 0 0; text-wrap: balance; }
.tb-meta { font: var(--t-petit); color: var(--encre-3); margin-top: 4px; }
.tb-pourcent { text-align: right; font-variant-numeric: tabular-nums; }
.tb-pourcent b { font: 700 44px/1 var(--police); letter-spacing: -0.03em; }
.tb-pourcent b small { font-size: 20px; color: var(--encre-3); font-weight: 600; }
.tb-pourcent span { display: block; color: var(--encre-3); font: var(--t-petit); margin-top: 4px; }
.tb-barre { height: 12px; border-radius: var(--r-pilule); background: var(--case-vide); display: flex; gap: 2px; overflow: hidden; }
.tb-barre i { display: block; height: 100%; transition: flex-basis var(--doux); }
.tb-legende { display: flex; flex-wrap: wrap; gap: 6px 18px; font: var(--t-petit); color: var(--encre-2); font-variant-numeric: tabular-nums; }
.tb-legende span { display: inline-flex; align-items: center; gap: 7px; }
.tb-legende b { color: var(--encre); font-weight: 600; }
.tb-puce { width: 12px; height: 12px; border-radius: 4px; display: inline-block; background: var(--case-vide); }
.tb-controles { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; }
.tb-controles .rang { gap: 10px; flex-wrap: wrap; }

.tb-familles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.tb-famille { background: var(--fond); border: 1px solid var(--trait); border-radius: 22px; padding: 16px 16px 18px; display: grid; gap: 10px; align-content: start; }
.tb-famille-tete { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.tb-famille-tete h3 { font: 600 15px/1.3 var(--police); margin: 0; }
.tb-compte { font: var(--t-micro); color: var(--encre-3); font-variant-numeric: tabular-nums; text-align: right; }
.tb-rouge { color: var(--case-casse); } .tb-orange { color: var(--case-fragile); } .tb-bleu { color: var(--case-cours); }
.tb-mini { height: 6px; border-radius: var(--r-pilule); background: var(--case-vide); display: flex; overflow: hidden; }
.tb-mini i { display: block; height: 100%; }
.tb-cases { display: grid; grid-template-columns: repeat(auto-fill, 20px); gap: 5px; }

.tb-case { width: 20px; height: 20px; border-radius: 6px; border: 0; padding: 0; cursor: pointer; display: grid; place-items: center;
  font: 700 11px/1 var(--police); color: var(--case-signe); background: var(--case-vide); transition: transform var(--vite); position: relative; }
.tb-case:hover { transform: scale(1.18); }
.tb-case:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tb-case[data-e="ok"], .tb-puce[data-e="ok"] { background: var(--case-ok); }
.tb-case[data-e="fragile"], .tb-puce[data-e="fragile"],
.tb-case[data-e="revoir"], .tb-puce[data-e="revoir"] { background: var(--case-fragile); }
.tb-case[data-e="casse"], .tb-puce[data-e="casse"],
.tb-case[data-e="ko"], .tb-puce[data-e="ko"] { background: var(--case-casse); }
.tb-case[data-e="cours"], .tb-puce[data-e="cours"],
.tb-case[data-e="tourne"], .tb-puce[data-e="tourne"] { background: var(--case-cours); }
.tb-case[data-e="na"], .tb-puce[data-e="na"],
.tb-case[data-e="suspendu"], .tb-puce[data-e="suspendu"] { background: var(--case-na); }
.tb-case[data-e="trou"], .tb-puce[data-e="trou"],
.tb-case[data-e="aecrire"], .tb-puce[data-e="aecrire"] { background: repeating-linear-gradient(45deg, var(--case-vide) 0 3px, var(--case-trou) 3px 6px); }
.tb-case[data-e="jamais"], .tb-puce[data-e="jamais"] { background: transparent; box-shadow: inset 0 0 0 1.5px var(--encre-4); }
/* Chez le testeur, une case à faire est un contour : elle attend sa main. */
.tb--testeur .tb-case[data-e="vide"] { background: transparent; box-shadow: inset 0 0 0 1.5px var(--encre-4); }
.tb-case[data-revoir]::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--case-signe); }
.tb-case--choisie { outline: 2px solid var(--encre); outline-offset: 2px; }
.tb-case--vivante::before { content: ""; position: absolute; inset: -3px; border-radius: 8px; border: 2px solid var(--case-cours); animation: tb-pouls 1.6s ease-out infinite; }
@keyframes tb-pouls { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(1.5); } }

/* Qui est là, en ce moment. L'équipe seule. */
.tb-direct { display: flex; flex-wrap: wrap; gap: 8px; }
.tb-direct:empty { display: none; }
.tb-present { display: inline-flex; align-items: center; gap: 8px; padding: 7px 12px 7px 10px; border-radius: var(--r-pilule); background: var(--fond-2); font: var(--t-petit); border: 0; color: var(--encre); cursor: pointer; }
.tb-present i { width: 8px; height: 8px; border-radius: 50%; background: var(--case-ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--case-ok) 25%, transparent); }
.tb-present span { color: var(--encre-3); }

.tb-gens { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.tb-personne { background: var(--fond); border: 1px solid var(--trait); border-radius: 20px; padding: 14px 16px; display: grid; gap: 8px; text-align: left; cursor: pointer; font: inherit; color: inherit; }
.tb-personne:hover { border-color: var(--trait-fort); }
.tb-personne-tete { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.tb-personne-tete b { font-weight: 600; }
.tb-etat { font: var(--t-micro); color: var(--encre-3); display: inline-flex; align-items: center; gap: 6px; }
.tb-etat--la { color: var(--case-ok); }
.tb-etat--la::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.tb-chiffres { display: flex; gap: 14px; font: var(--t-petit); color: var(--encre-2); font-variant-numeric: tabular-nums; flex-wrap: wrap; }
.tb-chiffres b { color: var(--encre); font-weight: 600; }
.tb-section-titre { font: 600 13px/1.4 var(--police); letter-spacing: var(--ls-large); text-transform: uppercase; color: var(--encre-3); margin: 10px 2px 0; }

.tb-passage { display: flex; justify-content: space-between; gap: 10px; padding: 10px 12px; border-radius: 12px; background: var(--fond-2); flex-wrap: wrap; align-items: center; }
.tb-passage p { margin: 0; }
.tb-pourquoi { font: var(--t-corps); }
.tb-sessions { display: grid; gap: 6px; }
.tb-session { display: flex; justify-content: space-between; gap: 10px; font: var(--t-petit); padding: 8px 12px; border-radius: 10px; background: var(--fond-2); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .tb-tete { padding: 16px; border-radius: 20px; }
  .tb-pourcent { text-align: left; }
  .tb-familles { grid-template-columns: 1fr; }
  .tb-cases { grid-template-columns: repeat(auto-fill, 28px); gap: 6px; }
  .tb-case { width: 28px; height: 28px; border-radius: 8px; font-size: 13px; }
}
@media (prefers-reduced-motion: reduce) {
  .tb-case, .tb-barre i { transition: none; }
  .tb-case--vivante::before { animation: none; }
}

/* La section du tableau, sous les quatre chiffres de Tests : l'avancement
   se lit replié, le tableau entier se déploie d'un geste. */
.tb-section { margin: var(--e-5) 0 var(--e-6); }
.tb-section:empty { display: none; }
.tb-resume { gap: 18px; }
.tb-ligne { display: grid; gap: 10px; }
.tb-ligne-tete { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; }
.tb-ligne-nom { display: block; font: 600 15px/1.3 var(--police); }
.tb-ligne-meta { display: block; font: var(--t-petit); color: var(--encre-3); margin-top: 2px; }
.tb-ligne-pc { font: 700 28px/1 var(--police); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tb-ligne-pc small { font-size: 15px; color: var(--encre-3); font-weight: 600; }
.tb-deplier { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; padding: 12px 16px; border: 1px solid var(--trait); border-radius: 14px;
  background: var(--fond-2); color: var(--encre); font: 500 14px/1.3 var(--police); cursor: pointer; transition: background var(--vite); }
.tb-deplier:hover { background: var(--fond-3); }
.tb-deplier:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tb-deplier svg { width: 16px; height: 16px; }
/* Le chevron pointe vers ce qui va s'ouvrir, et se retourne une fois ouvert. */
.tb-deplier svg { transition: transform var(--vite); }
.tb-deplier[aria-expanded="true"] svg { transform: rotate(180deg); }

/* ==========================================================================
   Les projets à faire : des cartes d'idées, et une note qui se lit
   ========================================================================== */

.etiquette--lien { gap: 4px; text-decoration: none; background: var(--accent-voile); color: var(--accent); }
.etiquette--lien:hover { text-decoration: none; background: var(--accent); color: var(--sur-accent); }
.etiquette--lien svg { width: 12px; height: 12px; }

.af-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: var(--e-4); }
.af-carte {
  display: flex; flex-direction: column; gap: 10px;
  padding: 20px; border-radius: 22px;
  background: var(--fond-eleve); border: 1px solid var(--trait);
  color: inherit; text-decoration: none;
  transition: transform var(--vite), box-shadow var(--vite), border-color var(--vite);
}
.af-carte:hover { transform: translateY(-2px); box-shadow: var(--ombre-carte); border-color: var(--trait-fort); text-decoration: none; }
.af-carte:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--anneau); }
.af-carte-tete { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 2px; }
.af-plateformes { display: flex; gap: 4px; }
.af-plateformes .plateforme { height: 24px; padding: 0 7px; }
.af-carte-nom { font: var(--t-titre-3); letter-spacing: var(--ls-titre); margin: 0; text-wrap: balance; }
.af-carte-phrase { font: var(--t-petit); color: var(--encre); margin: 0; }
.af-carte-extrait {
  font: var(--t-petit); color: var(--encre-2); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.af-carte-extrait--vide { color: var(--encre-3); font-style: italic; }
.af-carte-pied { font: var(--t-micro); color: var(--encre-3); margin: auto 0 0; padding-top: 12px; border-top: 1px solid var(--trait); font-variant-numeric: tabular-nums; }

.af-tete .chapo { max-width: 62ch; }
.af-tete-puces { gap: 8px; margin-top: var(--e-3); align-items: center; flex-wrap: wrap; }

.af-lecture { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: var(--e-7); align-items: start; }
.af-lecture--seule { grid-template-columns: minmax(0, 1fr); }
.af-sommaire {
  position: sticky; top: calc(var(--haut) + var(--e-5));
  max-height: calc(100vh - var(--haut) - var(--e-7)); overflow-y: auto;
  padding-right: 4px;
}
.af-sommaire-titre { font: var(--t-micro); font-weight: 600; letter-spacing: var(--ls-large); text-transform: uppercase; color: var(--encre-3); margin: 0 0 8px 10px; }
.af-sommaire ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.af-sommaire button {
  width: 100%; text-align: left; border: 0; background: none; cursor: pointer;
  font: var(--t-petit); color: var(--encre-2); padding: 5px 10px; border-radius: var(--r-petit);
}
.af-sommaire button:hover { background: var(--survol); color: var(--encre); }
.af-sommaire button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--anneau); }

.af-note { max-width: 68ch; font: 400 16px/1.7 var(--police); color: var(--encre); }
.af-note > :first-child { margin-top: 0; }
.af-note h2 { font: var(--t-titre-2); letter-spacing: var(--ls-titre); margin: var(--e-7) 0 var(--e-3); text-wrap: balance; scroll-margin-top: calc(var(--haut) + var(--e-4)); }
.af-note h3 { font: var(--t-titre-3); margin: var(--e-5) 0 var(--e-2); }
.af-note p, .af-note ul { margin: 0 0 14px; }
.af-note ul { padding-left: 22px; }
.af-note li { margin: 4px 0; }
.af-note li::marker { color: var(--encre-3); }
.af-note strong { font-weight: 600; }
.af-note blockquote { margin: var(--e-5) 0; padding: 18px 22px; border-radius: 18px; background: var(--fond-2); font-size: 18px; font-weight: 500; line-height: 1.5; }
.af-note blockquote p { margin: 0; }
.af-note hr { border: 0; height: 1px; background: var(--trait); margin: var(--e-6) 0; }
.af-note a { word-break: break-word; }

.af-zone { font: 400 13.5px/1.6 var(--police-mono); min-height: 360px; resize: vertical; }

@media (max-width: 900px) {
  .af-lecture { grid-template-columns: minmax(0, 1fr); gap: var(--e-5); }
  /* Sur un téléphone, le sommaire devient une rangée qui défile seule. */
  .af-sommaire { position: static; max-height: none; overflow: visible; padding: 0; }
  .af-sommaire-titre { margin-left: 0; }
  .af-sommaire ol { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; scrollbar-width: none; }
  .af-sommaire li { flex: none; }
  .af-sommaire button { white-space: nowrap; background: var(--fond-2); border-radius: var(--r-pilule); padding: 6px 12px; }
  .af-note { font-size: 15.5px; }
}
