/* ═══════════════════════════════════════════════════════════════════════════
   V1 — LE DESSIN DE LA MAQUETTE DU 31/08/2026
   `maquettes/unitools-structure.html`, quatrième passe.
   ───────────────────────────────────────────────────────────────────────────
   ⚠️ CETTE FEUILLE NE VIT PAS DANS `app/`, ET C'EST LA RAISON D'ÊTRE DU
   DOSSIER. `app/` est la source du MVP : tout ce qu'on y pose part dans le
   paquet du MVP au déploiement suivant. Le V1 se dépose donc PAR DESSUS une
   copie de l'application, jamais dedans. Le MVP ne peut pas changer par
   accident : il n'a aucun chemin vers ce fichier.

   ⚠️ ELLE EST ADDITIVE. Elle est chargée APRÈS `unitools.css` et ne fait que
   redéfinir. Aucune règle du MVP n'est supprimée : retirer cette feuille rend
   exactement le MVP, ce qui est la seule preuve qui compte.

   Ce qu'elle porte, dans l'ordre :
     1. les trois polices, servies par nous
     2. l'échelle typographique à six crans
     3. le relief des plaques
     4. la géométrie partagée
     5. la plaque : tuile d'icône colorée par nature, étiquette de nature
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* ── 1. LES TROIS POLICES ────────────────────────────────────────────────
     Archivo (titres), Public Sans (texte), JetBrains Mono (chiffres).
     Les fichiers sont dans `assets/polices/`, déclarés par `polices.css`.
     AUCUNE requête ne sort : la maquette les prenait chez Google, ce qui
     transmettrait l'adresse IP de chaque personne qui ouvre l'outil. C'est
     l'écart RGPD n°3, fermé le 31/07/2026 sur l'application de Franck en
     auto-hébergeant ses quatre bibliothèques. On ne le rouvre pas.

     --font et --mono sont redéfinis en ALIAS : ils sont cités des centaines
     de fois dans unitools.css, et cette feuille n'a pas à les connaître. */
  --titre:'Archivo','Helvetica Neue',Arial,sans-serif;
  --texte:'Public Sans','Helvetica Neue',Arial,sans-serif;
  --nombre:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --font:var(--texte);
  --mono:var(--nombre);

  /* ── 2. L'ÉCHELLE TYPOGRAPHIQUE, SIX CRANS ──────────────────────────────
     Elle était trop basse d'un cran partout : 13 de corps, 15 pour un titre
     de carte, 19 pour un titre d'écran. Un titre à 15 au-dessus d'un corps à
     13, ce n'est pas une hiérarchie, ce sont deux textes presque de la même
     taille dont l'un est gras. Six crans, chacun son emploi : on ne prend
     jamais une taille « entre deux ». */
  --t-h1:31px;      /* le titre de l'écran */
  --t-h2:19px;      /* le titre d'une plaque */
  --t-h3:15px;      /* un sous-titre dans une plaque */
  --t-corps:14.5px;
  --t-second:13px;  /* onglets, méta, légendes */
  --t-micro:11.5px; /* étiquettes en capitales, jamais du texte courant */

  /* ── 3. LE RELIEF ────────────────────────────────────────────────────────
     Une seule ombre plate donne un carton posé à plat. Le relief se fait à
     quatre couches plus une lumière : un cerne d'un pixel qui pose le bord,
     une ombre de contact très courte, une ombre moyenne qui décolle, une
     ombre longue et diffuse qui creuse la page, et une lumière intérieure sur
     l'arête haute — c'est elle qui fait la PLAQUE plutôt que le rectangle. */
  --relief:
    0 0 0 1px rgba(21,32,26,.045),
    0 1px 1.5px rgba(21,32,26,.05),
    0 4px 8px -3px rgba(21,32,26,.07),
    0 16px 32px -14px rgba(21,32,26,.16),
    inset 0 1px 0 rgba(255,255,255,.94);
  --relief-haut:
    0 0 0 1px rgba(21,32,26,.05),
    0 2px 3px rgba(21,32,26,.06),
    0 8px 16px -5px rgba(21,32,26,.09),
    0 28px 52px -20px rgba(21,32,26,.22),
    inset 0 1px 0 rgba(255,255,255,.96);

  /* ── 4. LA GÉOMÉTRIE, PARTAGÉE ──────────────────────────────────────────
     Trois hauteurs, et tout s'y tient : la tuile d'icône, le bouton et le
     champ ont la MÊME hauteur et le MÊME rayon, donc ils font une famille au
     lieu de trois. Un bouton de 36 à côté d'une tuile de 38 ne se voit pas de
     face ; il se voit dès qu'ils sont côte à côte, et personne ne sait dire
     pourquoi la ligne « bouge ». */
  --h-1:38px;   /* tuile d'icône, bouton, champ */
  --h-2:32px;   /* petit bouton, onglet */
  --h-3:24px;   /* pastille, étiquette de nature */
  --r-plaque:14px; --r-uni:10px; --r-ctrl:12px; --r-petit:9px;
  --g-plaque:16px;  /* la gouttière : tout ce qui vit dans une plaque commence dessus */

  /* ── LES FILETS NE SONT PLUS VERTS (Antonio, 01/09/2026) ─────────────────
     « sur les cartes il ne faut pas mettre des contours vertes ».
     Mesuré : ce ne sont pas des contours de carte — les cartes n'ont plus de
     bordure du tout depuis le relief. Ce sont les FILETS DU THÈME, `--line`
     (#DDEAE2) et `--line-2` (#C3D8CC), des gris biaisés vert, posés sur les
     pieds de carte, les séparateurs de liste et le tour des petits boutons.
     Sur un fond déjà vert pâle et à côté d'un rail vert, un filet vert de plus
     fait une teinte de trop.
     La maquette pose un filet NEUTRE. On reprend sa valeur. */
  --line:#E7ECE9;
  --line-2:#DBE2DD;
}

/* ══ LE CORPS ══════════════════════════════════════════════════════════════ */
body{font-size:var(--t-corps); line-height:1.6}

/* ══ LES TITRES ════════════════════════════════════════════════════════════
   Le titre d'écran passe de 19 à 31 px, le titre de plaque de 15 à 19, et
   les deux prennent Archivo. C'est le cran qui manquait partout. */
.page-title{font-family:var(--titre); font-size:var(--t-h1); font-weight:700;
  letter-spacing:-.03em; line-height:1.14}
.card-title{font-family:var(--titre); font-size:var(--t-h2); font-weight:600;
  letter-spacing:-.02em; line-height:1.25}

/* ══ LA PLAQUE ═════════════════════════════════════════════════════════════
   ⚠️ UNE PLAQUE EN RELIEF N'A PAS DE BORDURE : le cerne d'un pixel de la
   première couche EST son bord. Garder les deux donne un trait double, qui se
   voit surtout dans les angles. */
.card, .chaine, .rk{
  border:none;
  border-radius:var(--r-plaque);
  box-shadow:var(--relief);
  background:linear-gradient(180deg,#fff 0%,#FCFDFC 100%);
  transition:box-shadow .22s var(--nav-courbe), transform .22s var(--nav-courbe);
}
.card:hover, .chaine:hover, .rk:hover{box-shadow:var(--relief-haut); transform:translateY(-2px)}
/* ⚠️ Une plaque qui PORTE un champ ouvert ne bouge pas : un champ qui se
   déplace de deux pixels sous le curseur pendant la frappe est une gêne, pas
   une réponse. */
.card:focus-within, .chaine:focus-within, .rk:focus-within{
  transform:none; box-shadow:var(--relief)}

/* ⚠️ LE FILET SOUS L'EN-TÊTE EST PARTI. La maquette n'a plus un seul trait
   horizontal permanent dans la coquille ; ceux qui restent séparent deux
   natures (l'étiquette d'une colonne, la provenance d'un chiffre, la
   signature d'un compte rendu). Un filet sous chaque en-tête, sur les 495
   cartes de l'application, c'était le trait le plus répété de l'écran, et il
   ne séparait rien : le relief pose déjà le bord.

   ⚠️ L'ALIGNEMENT PASSE DE flex-start À center : avec une tuile de 38 px à
   côté d'un titre de 19, `flex-start` colle la tuile en haut et le titre
   flotte. C'est la même raison qui donne une hauteur partagée à la tuile, au
   bouton et au champ. */
.card-hd{padding:var(--g-plaque) var(--g-plaque) 14px; border-bottom:none;
  align-items:center; gap:14px}
.card-hd>div:first-child{min-width:0; flex:1}

/* La tuile : même hauteur et même rayon que le bouton et le champ. */
.tuile{width:var(--h-1); height:var(--h-1); border-radius:var(--r-ctrl); flex:none;
  display:grid; place-items:center}
.tuile svg{width:21px; height:21px; display:block}

/* ⚠️ LA COULEUR DIT LA NATURE DU BLOC, elle ne décore pas. On l'apprend une
   fois ; une teinte décorative se réapprend à chaque page.
   Le rail ne change pas : il reste vert, ses icônes restent blanches. */


/* ⚠️ TROIS NATURES QUE LA MAQUETTE N'AVAIT PAS EU À NOMMER, parce que ses
   plaques étaient des squelettes. Sur les vrais écrans, six sections ne
   tombaient dans aucune des six : un parcours en étapes, un graphe à barres,
   un bloc de couples clé-valeur. Les laisser sans tuile aurait fait croire que
   le décorateur les avait ratées ; leur coller « Liste » aurait été faux.
   Les teintes sont choisies distinctes des six premières — teal, ardoise,
   terre — pour qu'on continue d'apprendre la couleur une seule fois. */


/* ⚠️ DEUX NEUTRES, ET C'EST UNE RÈGLE, PAS UNE PANNE DE COULEURS.
   Une teinte dit une STRUCTURE DE DONNÉES : tableau, liste, formulaire,
   tuiles, carte, matrice, étapes, graphe, fiche. Le gris dit que ce n'en est
   pas une — de la prose qui explique, ou l'écran d'une autre application servi
   dans un cadre. Onze couleurs ne s'apprennent pas « une fois » ; neuf plus
   deux gris, si. */
/* « Sources » vient de la maquette elle-même : c'est la nature qu'elle donne au
   bloc « L'apprentissage en France », qui ne montre pas des données à nous mais
   ce que TROIS FLUX EXTÉRIEURS publient. Ce n'est ni une liste ni un texte :
   c'est de la lecture de dehors, et le pied du bloc nomme ce qu'on lit. */


/* ══ LA PALETTE DES NATURES ════════════════════════════════════════════════
   Antonio, 01/09/2026 : « plusieurs couleurs d'icônes, plus vivant, non IA ».

   ⚠️ CE QUI FAISAIT « MACHINE », MESURÉ : les douze teintes avaient toutes la
   MÊME CLARTÉ, autour de 94 %. Une rampe plate, régulière, sans accident —
   c'est exactement ce qu'une génération produit quand personne ne décide.
   Elles vont maintenant de 76 à 85 %, et chaque encre a sa profondeur propre.

   ⚠️ ET CHAQUE PAIRE EST MESURÉE. Une icône qui ne se lit pas sur sa tuile est
   pire qu'une absence d'icône : elle occupe la place sans rien dire. Contraste
   relevé pour les douze, le plus faible à 4,73 — au dessus du seuil de 4,5.
   L'ambre a été assombri exprès : à #A85F07 il tombait à 4,17.

   La couleur reste un CODE, pas une décoration : on l'apprend une fois, et
   c'est pour ça qu'elle n'est pas jolie au hasard mais distincte à dessein. */
.n-tableau{background:#DEE4FA}  .n-tableau svg{color:#2B3F9E}   /* indigo profond */
.n-liste{background:#D9F0E3}  .n-liste svg{color:#0F7343}   /* vert forêt */
.n-formulaire{background:#FCEBD2}  .n-formulaire svg{color:#8F4F04}   /* ambre brûlé */
.n-tuiles{background:#FBE0EA}  .n-tuiles svg{color:#AE2E68}   /* framboise */
.n-carte{background:#D6EDF8}  .n-carte svg{color:#12688F}   /* bleu ardoise */
.n-matrice{background:#EAE0FA}  .n-matrice svg{color:#5B36B5}   /* violet encre */
.n-etapes{background:#CFEDE7}  .n-etapes svg{color:#06655A}   /* sarcelle */
.n-graphe{background:#DFE5EC}  .n-graphe svg{color:#33475F}   /* bleu-gris */
.n-fiche{background:#F0E7D8}  .n-fiche svg{color:#6B5222}   /* terre */
.n-sources{background:#FBE3D9}  .n-sources svg{color:#B23F17}   /* terre cuite */
.n-texte{background:#E9ECE8}  .n-texte svg{color:#4A5249}   /* neutre */
.n-cadre{background:#DDE3DE}  .n-cadre svg{color:#28352E}   /* neutre profond */

.nature{font-family:var(--titre); font-size:10.5px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--text-3); background:var(--surface-3);
  height:var(--h-3); padding:0 11px; border-radius:999px; flex:none;
  display:inline-flex; align-items:center; white-space:nowrap}

/* ══ LE BANDEAU DU V1 ══════════════════════════════════════════════════════
   ⚠️ IL DIT OÙ L'ON EST, ET CE N'EST PAS DÉCORATIF. Le V1 partage la BASE et
   le COOKIE DE SESSION du MVP (.skhub.fr) : ce n'est pas un bac à sable, ce
   qu'on y écrit est écrit pour de bon. Ouvert dans un onglet voisin, rien ne
   distinguerait les deux — et une décision prise en croyant être sur un
   aperçu est une décision prise deux fois. */
body::before{
  /* Le texte par défaut, ou celui que `v1.js` pose quand `assets/version.json`
     dit quel paquet tourne (commit, date) : on ne compare plus des tailles de
     fichiers pour savoir ce qui est en ligne. */
  content:var(--v1-bandeau, "V1 · aperçu du nouveau dessin — même base et mêmes données que l'outil");
  position:fixed; inset:0 0 auto 0; z-index:9999;
  height:26px; display:grid; place-items:center;
  font-family:var(--titre); font-size:11px; font-weight:700; letter-spacing:.04em;
  color:#5C5600; background:var(--yellow);
  box-shadow:0 1px 0 rgba(21,32,26,.10);
}
body{padding-top:26px}
@media print{ body::before{display:none} body{padding-top:0} }

/* ═══════════════════════════════════════════════════════════════════════════
   LA COQUILLE DE LA MAQUETTE — écran par écran
   ═══════════════════════════════════════════════════════════════════════════ */

/* ══ LA GRILLE ═════════════════════════════════════════════════════════════
   La maquette pose ses plaques sur DEUX colonnes, `.large` prenant les deux.
   ⚠️ ELLE N'EST PAS APPLIQUÉE PARTOUT D'OFFICE. Beaucoup d'écrans de
   l'application ont une mise en page voulue — une colonne de lecture, un
   tableau pleine largeur, une carte et son panneau. Les mettre tous en deux
   colonnes d'un coup casserait ce qui marche, sans que personne sache
   pourquoi. `v1.js` porte une table écran par écran, et son défaut est
   « ne touche pas ». */
.v1-plaques{display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:20px; align-items:start}
.v1-plaques > .v1-large{grid-column:1 / -1}
@media (max-width:1100px){ .v1-plaques{grid-template-columns:1fr} }

/* ══ L'EN-TÊTE D'ÉCRAN ═════════════════════════════════════════════════════
   Le titre à gauche, la mesure à droite, sur la même ligne de base. */
.v1 .page-hd{display:flex; align-items:baseline; gap:16px; flex-wrap:wrap}
.v1 .page-hd .meta{margin-left:auto; font-family:var(--nombre);
  font-variant-numeric:tabular-nums; font-size:var(--t-second); color:var(--text-3)}

/* ══ LES ONGLETS DESCENDENT DANS LA PAGE ═══════════════════════════════════
   La maquette sépare deux choses que la barre du haut mélangeait : les
   APPLICATIONS (Projet digital, Chantiers, Services) restent en haut, et les
   ONGLETS DE L'ÉCRAN (Demandes reçues, Connexions…) descendent dans la page,
   en pilules sur fond creux.

   ⚠️ ON NE FABRIQUE PAS UNE SECONDE BARRE. Le balisage existe déjà dans chaque
   vue (`.tabx-bar`), il est seulement masqué depuis que le MVP a remonté les
   onglets en haut — et c'est LUI qui porte les gestionnaires de clic posés au
   chargement. On le montre, et on masque la copie du haut. Fabriquer une barre
   neuve aurait voulu dire recopier ces gestes, donc les tenir à jour deux fois.

   ⚠️ Et à treize entrées (le volet pédagogie), une rangée de traits devient une
   grille illisible : c'est pour cela que la maquette a choisi la pilule. */
.v1 .view.on > .tabx-bar{
  display:inline-flex !important; width:auto; max-width:100%;
  gap:3px; padding:4px; margin:0 0 24px;
  background:#E7EEE9; border:0; border-bottom:0; border-radius:var(--r-ctrl);
  overflow-x:auto; scrollbar-width:thin}
.v1 .view.on > .tabx-bar::after{display:none}   /* le trait qui glissait */
.v1 .view.on > .tabx-bar > .tabx{
  height:var(--h-2); padding:0 13px; border:0; border-radius:var(--r-petit);
  font-size:var(--t-second); color:var(--text-2); background:none;
  display:flex; align-items:center; white-space:nowrap; flex:none;
  transition:background .15s, color .15s}
.v1 .view.on > .tabx-bar > .tabx::after{display:none}
.v1 .view.on > .tabx-bar > .tabx:hover{color:var(--text)}
.v1 .view.on > .tabx-bar > .tabx.on{
  background:#fff; color:#1E6644; font-weight:600;
  box-shadow:0 0 0 1px rgba(21,32,26,.05), 0 1px 2px rgba(21,32,26,.07)}

/* La copie du haut disparaît : deux barres pour les mêmes onglets, c'est la
   certitude qu'un jour l'une sera cliquée pour l'autre. Les APPLICATIONS, elles,
   restent — ce ne sont pas les mêmes boutons. */
.v1 .modbar .ongrp, .v1 .modbar .ongfam, .v1 .modbar .ongx{display:none !important}
/* ⚠️ ET LE FILET QUI LES ANNONÇAIT (07/09/2026). `renderModules()` pose un
   séparateur avant la rangée d'onglets ; ceux-ci étant masqués, il restait en
   bout de ligne à séparer les applications de rien. Vu à l'écran sur les deux
   univers qui portent des applications. */
.v1 .modbar .sep{display:none !important}

/* ══ LES QUATRE RANGS DE BOUTON ════════════════════════════════════════════
   Un seul plein par zone. Le rouge ne remplit jamais : une action qui détruit
   ne se propose pas avec l'insistance d'un bouton plein. */
.v1 .btn{height:var(--h-1); padding:0 16px; border-radius:var(--r-ctrl);
  font-size:var(--t-second); font-weight:600; letter-spacing:-.005em;
  display:inline-flex; align-items:center; justify-content:center; gap:8px}
.v1 .btn-sm{height:var(--h-2); padding:0 12px; border-radius:var(--r-petit); font-size:12.5px}
.v1 .btn-p{background:#1E6644; color:#fff}
.v1 .btn-p:hover{background:#175136}

/* ══ LES BARRES TROP LONGUES SE RANGENT EN FAMILLES ═════════════════════════
   « Qualité et conformité » aligne DIX-NEUF onglets sur une seule rangée. À ce
   nombre, une rangée n'est plus une barre : c'est une liste qu'on parcourt en
   défilant, où « Planning » et « Calendriers » se ressemblent, où « Suivis
   individuels » voisine « Intégration en cours », et où l'on ne sait plus
   lequel appartient à quoi.

   La maquette les range en deux familles nommées, parce qu'elles ne se
   recouvrent pas : le volet pédagogique de Franck d'un côté, le dossier
   Qualiopi de l'autre. Ce ne sont pas les mêmes métiers ni les mêmes droits. */
.v1 .v1-groupes{display:flex; flex-wrap:wrap; gap:18px; align-items:flex-start; margin:0 0 24px}
.v1 .v1-groupe{display:flex; flex-direction:column; gap:6px; min-width:0; max-width:100%}
.v1 .v1-groupe-lbl{font-family:var(--titre); font-size:var(--t-micro); font-weight:700;
  letter-spacing:.09em; text-transform:uppercase; color:var(--text-3); padding-left:6px}
.v1 .v1-groupe-lbl .n{font-family:var(--nombre); font-weight:500; opacity:.75}
/* Chaque famille garde le fond creux et les pilules : c'est la même barre,
   coupée là où le sens change. */
.v1 .v1-groupe > .v1-ongs{display:inline-flex; flex-wrap:wrap; gap:3px; padding:4px;
  background:#E7EEE9; border-radius:var(--r-ctrl); max-width:100%}
.v1 .v1-groupe > .v1-ongs > .tabx{
  height:var(--h-2); padding:0 13px; border:0; border-radius:var(--r-petit);
  font-size:var(--t-second); color:var(--text-2); background:none;
  display:flex; align-items:center; white-space:nowrap; flex:none;
  transition:background .15s, color .15s}
.v1 .v1-groupe > .v1-ongs > .tabx::after{display:none}
.v1 .v1-groupe > .v1-ongs > .tabx:hover{color:var(--text)}
.v1 .v1-groupe > .v1-ongs > .tabx.on{background:#fff; color:#1E6644; font-weight:600;
  box-shadow:0 0 0 1px rgba(21,32,26,.05), 0 1px 2px rgba(21,32,26,.07)}
/* La barre d'origine s'efface une fois ses onglets rangés — mais elle RESTE
   dans le document : ce sont les mêmes boutons, déplacés, donc les gestes de
   clic posés au chargement les suivent. */
.v1 .view.on > .tabx-bar.v1-range{display:none !important}


/* ══ L'ACCUEIL ═════════════════════════════════════════════════════════════
   ⚠️ IL A DÉJÀ SES TUILES, ET C'EST POUR ÇA QU'ON NE LUI EN AJOUTE PAS.
   Mesuré : chaque carte du rail (`.rk`) porte un `.ict` de 32 px — la tuile de
   teinte posée le 26/08/2026 (règle 12, « les icônes passent à 20 px dans une
   tuile de teinte »). Le décorateur lui en a collé une SECONDE à côté, et
   l'écran s'est retrouvé avec deux pastilles pour un titre.

   Le premier essai a fait pire : la règle `.rk-hd > *:first-child{flex:1}`
   visait le conteneur du titre, mais le premier enfant est l'ICÔNE — elle est
   passée de 32 à 105 px de large, en pastille étirée. Vu à l'écran, invisible
   à la lecture.

   Donc : on ne décore pas `.rk`, on ALIGNE le `.ict` qui est déjà là sur la
   géométrie de la maquette. Un seul repère par titre.

   ⚠️ LA PROJECTION GARDE SON DESSIN. Elle reprend celui de la télévision du
   hall — grands chiffres, aplat jaune sur la mesure du mois — et une seule
   mesure ne peut pas avoir deux visages (règle 12). Relief, pas d'étiquette :
   « Tuiles » au-dessus de « WELCOME ON BOARD » ferait deux titres pour un
   bloc. */
.v1 #v-accueil .rk{border:none; box-shadow:var(--relief); border-radius:var(--r-plaque);
  background:linear-gradient(180deg,#fff 0%,#FCFDFC 100%)}
.v1 #v-accueil .rk > .rk-hd{border-bottom:none}
/* ⚠️ 15 px ICI, ET PAS LES 19 D'UN TITRE DE PLAQUE — écart assumé.
   La maquette pose H2 = 19 px, mais ses plaques d'accueil vivent sur une grille
   à deux colonnes, larges. Celles-ci vivent dans le rail de droite, ~330 px :
   à 19 px, « La publication du jour » passe sur trois lignes et le titre pèse
   plus que ce qu'il annonce. On garde le cran H3, qui est fait pour un
   sous-titre dans une plaque — c'est bien ce qu'est une carte de rail. */
.v1 #v-accueil .rk > .rk-hd h3{font-family:var(--titre); font-size:var(--t-h3);
  font-weight:600; letter-spacing:-.015em}

/* La tuile déjà posée prend la géométrie partagée : même rayon que le bouton
   et le champ. Sa taille ne bouge pas — 32 px est le cran de l'accueil, et il
   a été choisi (règle 12, « UNE échelle d'icônes, trois crans »). */
.v1 #v-accueil .rk > .rk-hd .ict{border-radius:var(--r-ctrl); flex:none}
.v1 #v-accueil .proj{border:none; box-shadow:var(--relief); border-radius:var(--r-plaque)}


/* ═══════════════════════════════════════════════════════════════════════════
   L'ACCUEIL — DÉCISIONS D'ANTONIO DU 01/09/2026
   « enlève ça [les trois pas] … on ne devrait pas répliquer la vue du TV, mais
   vraiment un résumé, les contrats du mois, ruptures sèches… et les listes des
   jeunes, il faut cliquer sur les indications pour voir les chiffres. »
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. LE BANDEAU DES TROIS PAS S'EN VA ────────────────────────────────────
   Il ouvrait l'écran que tout le monde ouvre sur une consigne, tous les jours,
   pour trois gestes qu'on ne fait qu'une fois. */
.v1 #v-accueil .prise{display:none}

/* ── 2. L'ACCUEIL NE RÉPLIQUE PLUS LA TÉLÉVISION ────────────────────────────
   ⚠️ CELA REVIENT SUR LA RÈGLE 12 DU 25/08/2026 (« la projection reprend le
   dessin de la télévision »), et c'est une décision, pas un oubli : l'accueil
   n'est pas un second écran de hall, c'est un résumé de travail. L'horloge et
   la date partent — elles ne servent qu'à un mur qu'on regarde de loin, et sur
   un poste elles redisent celles du système. Le bouton « Ouvrir l'écran »
   reste : c'est le lien VERS la télévision, pas sa copie.
   ⚠️ Le voyant de fraîcheur, lui, RESTE : il dit l'âge des chiffres (règle 18),
   et c'est la seule chose de ce bandeau qui parle des données. */
.v1 #v-accueil .proj .proj-h .heure,
.v1 #v-accueil .proj .proj-h .jour{display:none}
.v1 #v-accueil .proj .proj-h{align-self:center}

/* ── 3. LE RÉSUMÉ ───────────────────────────────────────────────────────────
   Les quatre mesures restent, et le jaune reste sur les contrats du mois : il
   ne veut plus dire « ce qui demande un geste » sur cet écran, il veut dire
   « la mesure du mois », et il n'y en a qu'une (règle 20, 27/08). */

/* ── 4. LES NOMS NE S'AFFICHENT QU'AU CLIC ──────────────────────────────────
   ⚠️ CE N'EST PAS QU'UNE QUESTION DE PLACE. L'accueil est ouvert par les neuf
   espaces, et il affichait « Camille Renard · BTS NDRC · Caen » à l'ouverture,
   sans que personne l'ait demandé. Un COMPTE n'est pas une donnée personnelle,
   un NOM si — c'est la même distinction que la carte des entreprises, où le
   nombre d'apprentis s'affiche et jamais leurs noms (règle 25).
   Le compte reste donc visible, la liste se demande. */
.v1 #v-accueil .tvl > h4{cursor:pointer; user-select:none;
  display:flex; align-items:center; gap:8px; width:100%;
  background:none; border:0; text-align:left; font:inherit; color:inherit;
  padding:0; border-radius:var(--r-petit)}
.v1 #v-accueil .tvl > h4::after{
  content:''; width:7px; height:7px; flex:none; margin-left:4px;
  border-right:1.6px solid currentColor; border-bottom:1.6px solid currentColor;
  transform:rotate(45deg) translate(-1px,-1px); opacity:.5;
  transition:transform .18s var(--nav-courbe)}
.v1 #v-accueil .tvl > h4[aria-expanded="true"]::after{
  transform:rotate(225deg) translate(-2px,-2px)}
.v1 #v-accueil .tvl > h4:hover::after{opacity:.9}
.v1 #v-accueil .tvl > h4:focus-visible{outline:2px solid var(--vif); outline-offset:3px}
.v1 #v-accueil .tvl > ul[hidden]{display:none}
/* Une invite discrète, pour que le pli ne passe pas pour une liste vide. */
.v1 #v-accueil .tvl > .v1-invite{font-size:var(--t-micro); color:var(--text-3);
  margin:6px 0 0; font-style:italic}


/* ══ LES BOUTONS N'ONT PAS DE BORDURE ══════════════════════════════════════
   Le petit bouton portait un trait de 1 px en `--line-2`, donc vert. La
   maquette ne borde aucun bouton : un aplat clair suffit à le poser, et la
   bordure ne revient qu'au FOCUS — où elle est alors le seul trait de l'écran,
   donc impossible à manquer.
   ⚠️ Le focus garde son cerne : le retirer rendrait l'écran inutilisable au
   clavier, et c'est exactement le genre de chose qu'on ne voit pas à la
   souris. */
.v1 .card .btn, .v1 .rk .btn, .v1 .card button.btn-sm, .v1 .rk button.btn-sm{
  border:0; background:#F1F6F3; color:#243128}
.v1 .card .btn:hover, .v1 .rk .btn:hover{background:#E6EFEA}
.v1 .card .btn:focus-visible, .v1 .rk .btn:focus-visible{
  outline:2px solid var(--vif); outline-offset:2px}
/* Le bouton plein garde sa couleur : un seul plein par zone (règle de la
   maquette), et c'est lui qui dit où est le geste principal. */
.v1 .card .btn-main, .v1 .rk .btn-main, .v1 .card .btn.btn-p, .v1 .rk .btn.btn-p{
  background:#1E6644; color:#fff}
.v1 .card .btn-main:hover, .v1 .rk .btn-main:hover{background:#175136}


/* ══ « NOUVELLE DEMANDE » ═══════════════════════════════════════════════════
   Le seul plein de la barre du haut : la maquette n'en pose qu'un par zone,
   et c'est lui qui dit où est le geste. */
.v1 .topbar .tb-right .v1-nouv{
  background:#1E6644; color:#fff; border:0;
  height:var(--h-2); padding:0 14px; border-radius:var(--r-petit);
  font-family:var(--titre); font-size:var(--t-second); font-weight:600;
  white-space:nowrap; flex:none; margin-right:4px}
.v1 .topbar .tb-right .v1-nouv:hover{background:#175136}
.v1 .topbar .tb-right .v1-nouv:focus-visible{outline:2px solid var(--vif); outline-offset:2px}
.v1 .topbar .tb-right .v1-nouv[hidden]{display:none}

/* ══ L'ACCUEIL S'ALLÈGE ET SE RANGE COMME LA MAQUETTE ══════════════════════
   Antonio, 01/09/2026 : « c'est bien de voir un accueil allégé et organisé
   comme la maquette ».

   ⚠️ MESURÉ AVANT DE TOUCHER. La colonne de gauche faisait 1364 × 144, celle
   de droite 400 × 1745 : une colonne large et presque vide à côté d'un rail
   douze fois plus haut qu'elle. Et ce n'est pas un artefact de l'aperçu — même
   avec ses neuf articles, la veille n'atteint pas 1745 px. La mise en page
   datait du 30/08, quand « Ce qui m'attend » occupait encore la gauche ; le
   bloc est parti, la colonne est restée.

   La maquette ne fait pas deux colonnes inégales : elle pose SIX PLAQUES sur
   une grille à deux colonnes. On reprend son organisation — la veille prend
   toute la largeur, et les quatre cartes du rail descendent en grille sous
   elle, deux par rangée. */
/* ⚠️ « L'APPRENTISSAGE EN FRANCE » VA À DROITE, comme la maquette.
   Relevé dans `unitools-structure.html`, plaque par plaque :
     1. Welcome on board          gauche
     2. L'apprentissage en France DROITE
     3. Ce qui arrive             gauche
     4. Nouveautés                DROITE
     5. La publication du jour    gauche
     6. Comptes rendus            pleine largeur
   Le premier essai avait mis la veille en pleine largeur au dessus du rail :
   c'était plus léger, mais ce n'était pas ce que la maquette dit. Elle pose
   deux colonnes ÉGALES, la veille dans celle de droite.
   ⚠️ `order` plutôt qu'un déplacement dans le DOM : `serveur.js` remplit
   `.colg` et `.cold` par leur classe, les intervertir casserait le
   remplissage. On change ce qu'on voit, pas ce que le code trouve. */
.v1 #v-accueil .duo.duo-acc{display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:22px; align-items:start}
.v1 #v-accueil .duo.duo-acc > .colg{order:2; width:auto; max-width:none; flex:none}
.v1 #v-accueil .duo.duo-acc > .cold{order:1; width:auto; max-width:none; flex:none}
@media (max-width:1100px){
  .v1 #v-accueil .duo.duo-acc{grid-template-columns:1fr}
  .v1 #v-accueil .duo.duo-acc > .colg{order:1}
  .v1 #v-accueil .duo.duo-acc > .cold{order:2}
}

/* Les quatre cartes du rail deviennent des plaques sur deux colonnes.
   ⚠️ `align-items:start` — sans lui, une carte de 800 px étirerait sa voisine
   de 180 px à la même hauteur, et on lirait deux blocs vides. */
/* Le rail occupe maintenant UNE colonne de la grille : ses cartes s'y empilent,
   comme « Ce qui arrive », « Nouveautés » et « La publication du jour » se
   suivent dans la colonne gauche de la maquette. */
.v1 #v-accueil .arail{display:flex; flex-direction:column; gap:20px}

/* ⚠️ « Comptes rendus » faisait 823 px de haut dans un rail de 400 : c'était
   la carte qui décidait de la hauteur de l'écran. Bornée, elle défile chez
   elle — c'est déjà la règle posée le 25/08 pour cette carte précise. */
.v1 #v-accueil .arail .rk-liste{max-height:340px; overflow-y:auto}


/* ══ « PARTAGER » DANS LE RAIL ═════════════════════════════════════════════
   Antonio, 01/09/2026 : « met la chaîne un peu plus grand, sans le fond
   blanc ». Mesuré : le bouton portait un voile blanc à 10 % et un liseré à
   22 %, et son icône faisait 14 px.

   ⚠️ ON NE LE RETIRE QUE DE « PARTAGER », PAS D'« INSTALLER ». Les deux
   partagent la classe `.rail-install`, mais ils ne demandent pas la même
   chose : installer l'application est une proposition, la partager est un
   geste d'appoint. Un seul des deux garde le voile — c'est la règle du plein
   unique par zone, et c'est ce qui rend « Installer » lisible comme le geste
   principal du bas du rail. */
/* ⚠️ LE SÉLECTEUR A ÉTÉ ÉCRIT SUR UN NOM TRONQUÉ. Ma mesure coupait les
   classes à 20 caractères et rendait « rail-install rail-pa » : j'ai pris le
   fragment pour le nom. La vraie classe est `rail-partage`, et la règle n'a
   simplement rien fait — sans erreur, sans rien pour le dire.
   Une mesure qui tronque ce qu'elle rapporte est une mesure qui ment. */
.v1 .rail .rail-partage{background:none; border-color:transparent}
.v1 .rail .rail-partage:hover{background:rgba(255,255,255,.10)}
.v1 .rail .rail-partage svg{width:17px; height:17px}

/* ══ L'ÉCHELLE DES ICÔNES, RANGÉE ET MONTÉE D'UN CRAN ══════════════════════
   Antonio, 01/09/2026 : « agrandis les icônes un peu plus ».

   ⚠️ MESURÉ AVANT : sept tailles vivaient à l'écran — 10, 13, 15, 16, 17, 19
   et 21 px. Sept, ce n'est plus une échelle, c'est une accumulation de
   décisions prises une par une. La maquette n'en veut que quatre, nommées.

   On les range ET on les monte, plutôt que d'agrandir les unes sans les
   autres — sinon la prochaine demande porterait sur celles qu'on a oubliées.

     dans une ligne de texte      13 → 14
     dans un contrôle             15,16,17 → 18
     pour annoncer une carte      19 → 22
     dans une tuile de nature     21 → 23
     le rail                      21 → 23

   ⚠️ 10 px NE MONTE PAS À 14 : ce sont les chevrons et les puces des menus,
   des signes de ponctuation plus que des icônes. Les grossir de 40 % ferait
   de la ponctuation un contenu. */
.v1 .tuile svg{width:23px; height:23px}
.v1 .rail svg{width:23px; height:23px}
.v1 .rail .rail-partage svg,
.v1 .rail .rail-install svg{width:19px; height:19px}
.v1 .card-hd .mi svg, .v1 .rk-hd .mi svg{width:22px; height:22px}
.v1 .btn svg{width:18px; height:18px}
.v1 .btn-sm svg{width:16px; height:16px}
.v1 .ict svg{width:22px; height:22px}


/* ══ LE LOGO, AVEC SES MARGES ══════════════════════════════════════════════
   Le fichier de remplacement porte 18 px de marge intégrée et un autre ratio
   (2,919 contre 3,360) : on fixe la HAUTEUR et on laisse la largeur suivre,
   sinon il serait étiré. Un peu plus haut que l'ancien, parce que ses marges
   font partie de l'image — à hauteur égale, le dessin paraîtrait plus petit. */
.v1 .tb-marque img{height:44px; width:auto; object-fit:contain}

/* ══ LE RAIL : L'UNIVERS OUVERT PASSE AU JAUNE ═════════════════════════════
   Antonio, 01/09/2026 : « les icônes du side navigation se mettent en jaune
   lorsqu'on les clique ».
   ⚠️ LE JAUNE EST DÉJÀ LA MARQUE DU « VOUS ÊTES ICI » DANS LE RAIL : le repère
   latéral de 3 px est jaune depuis toujours, précisément parce que le vert vif
   ne fait que 2,1:1 sur le vert foncé du rail et y serait illisible. L'icône
   rejoint donc le repère au lieu de rester dans un vert clair qui disait la
   même chose plus faiblement. Mesuré : #FFFE78 sur le fond du rail, 11,9:1. */
.v1 .rail .uni.on svg, .v1 .rail .rl.on svg{color:var(--yellow)}
.v1 .rail .uni.on, .v1 .rail .rl.on{color:var(--yellow)}

/* ══ LA CHAÎNE DE PARTAGE, EN BLANC FRANC ══════════════════════════════════
   Elle héritait du blanc voilé du rail (90 %). Sur un fond vert foncé, 10 %
   de moins se lit comme une icône éteinte. */
.v1 .rail .rail-partage svg{color:#fff; opacity:1}
.v1 .rail .rail-partage{color:#fff}

/* ══ LE TRAIT JAUNE DE GAUCHE S'EN VA ══════════════════════════════════════
   Antonio, 01/09/2026 : « sur la side navigation je ne veux pas de trait jaune
   à gauche ».

   ⚠️ IL DISAIT LA MÊME CHOSE QUE L'ICÔNE, MAINTENANT. Mesuré : un `::before`
   de 3 × 42 px en #FFFE78, collé au bord gauche. C'était le seul repère
   « vous êtes ici » du rail tant que l'icône restait verte — et il fallait un
   jaune, parce que le vert vif ne fait que 2,1:1 sur le vert foncé.
   Depuis que l'icône EST jaune (11,9:1), le trait est une seconde annonce du
   même fait. Deux marques pour un état, c'est la moitié de trop : on retire
   celle qui touche le bord.

   ⚠️ CE QUI RESTE, ET QUI N'EST PAS DÉCORATIF : le voile vert de la pastille
   active. Il donne à l'entrée ouverte une SURFACE, pas seulement une couleur —
   c'est ce qui la fait exister quand on parcourt le rail des yeux, et c'est
   aussi ce qui tient si quelqu'un ne distingue pas le jaune du blanc. */
.v1 .rail .uni.on::before, .v1 .rail .rl.on::before{display:none}

/* ══ LES BARRES DE PROGRESSION SE VOIENT ═══════════════════════════════════
   Antonio, 01/09/2026 : « sur la progression bar il faut que ça soit bien
   visible aussi ».

   ⚠️ CE N'ÉTAIT PAS QU'UNE QUESTION D'ÉPAISSEUR. Mesuré, contraste du
   remplissage SUR SA PISTE (le seuil d'un composant est 3:1, WCAG 1.4.11) :

     vert   #50CC89 (--brand-2, en service)   1,53  ⚠️
     jaune  #FFFE78 (--yellow, en service)    1,25  ⚠️
     rouge  #C00020 (écrit en dur)            4,85  ✓

   DEUX DES TROIS ÉTATS ÉTAIENT INVISIBLES. Une barre verte à 67 % et une barre
   jaune à 22 % se lisaient exactement comme une piste vide — c'est-à-dire que
   l'écran des objectifs annonçait « rien de fait » pour tout ce qui allait
   bien. Et la piste elle-même était à 1,13 du blanc de la carte.

   Quatre corrections, et chacune est mesurée :
     · hauteur 4 → 8 px, la valeur que `.prog` porte déjà dans cette feuille —
       une seule épaisseur de barre dans l'application, pas deux ;
     · piste #EBF3EE → #D8E2DB, pour qu'il y ait une barre même à 0 % ;
     · vert  → --ok  #1A7A52  (4,01) ;
     · jaune → --att #5C5600  (5,68) — c'est l'ENCRE du jaune, que la charte
       définit précisément parce que le jaune lui-même ne se lit pas ;
     · rouge → --alr #C22E13  (4,28), le corail de la marque, à la place d'un
       #C00020 écrit en dur qui est un reliquat des anciens outils.

   ⚠️ ON NE GARDE PAS LE JAUNE « PARCE QUE C'EST LA COULEUR DE LA MARQUE ». Le
   jaune de SKHUB est fait pour un APLAT qu'on lit en noir dessus, pas pour un
   trait de 8 px sur fond clair. La charte le dit déjà pour le texte ; une barre
   de progression obéit à la même physique. */
.v1 .gauge{height:8px; background:#D8E2DB; border-radius:99px}
.v1 .gauge i{border-radius:99px; background:#1A7A52}
.v1 .gauge.att i{background:#5C5600}
.v1 .gauge.alr i{background:#C22E13}
/* Une barre à 0 % reste une barre : sans largeur minimale, « 0 % » et « pas de
   mesure » se ressemblent. Le filet suffit à dire qu'il y a une jauge ici. */
.v1 .gauge i[style*="width:0"], .v1 .gauge i[style*="width: 0"]{min-width:3px; opacity:.55}

/* ⚠️ L'INDICATEUR QUI GLISSAIT SOUS LES ONGLETS S'EN VA. `.tabx-jauge` est un
   trait de 3 px en vert vif, posé PAR MESURE sous l'onglet ouvert — c'était le
   bon repère quand les onglets étaient une rangée de libellés soulignés.
   Depuis qu'ils sont des pilules sur fond creux, la pastille blanche dit déjà
   lequel est ouvert : le trait est une seconde annonce, et il flotte sous une
   pilule qui a son propre bord. Même raison que le trait jaune du rail. */
.v1 .view.on > .tabx-bar > .tabx-jauge,
.v1 .v1-groupe > .v1-ongs > .tabx-jauge{display:none}

/* ══ LES TRAITS HORIZONTAUX, SELON LA RÈGLE DE LA MAQUETTE ═════════════════
   Antonio, 01/09/2026 : « respecte les règles de la maquette ».

   Sa règle est explicite : « il ne reste AUCUN trait horizontal permanent dans
   la coquille ; ceux qui subsistent séparent deux natures, et il y en a
   trois — sous l'étiquette d'une colonne de tableau, au-dessus de la
   provenance d'un chiffre, au-dessus de la signature d'un compte rendu ».
   Et pour les tableaux : « un trait entre chaque ligne → espacement, et la
   ligne se révèle au survol ».

   ⚠️ RELEVÉ SUR SIX ÉCRANS : 92 traits, dont 68 sur des cellules de tableau et
   une trentaine sur des lignes de liste. On était très loin des trois.

   ⚠️ CE QUI RESTE, ET POURQUOI : le filet sous le `<th>`. Il sépare l'étiquette
   de la donnée, c'est-à-dire deux natures — c'est le premier des trois cas que
   la maquette conserve. Le retirer ferait flotter les en-têtes au-dessus des
   lignes. */
.v1 .card table td, .v1 .rk table td{border-bottom:none}
.v1 .card table th, .v1 .rk table th{border-bottom:1px solid var(--line)}
/* L'espacement remplace le trait : sans lui, les lignes se touchent. */
.v1 .card table td, .v1 .rk table td{padding-top:11px; padding-bottom:11px}
/* Et la ligne se révèle au survol — c'est elle qui rend la lecture d'un
   tableau long possible, mieux qu'un trait permanent. */
.v1 .card table tbody tr, .v1 .rk table tbody tr{transition:background .12s}
.v1 .card table tbody tr:hover, .v1 .rk table tbody tr:hover{background:#F3F7F4}

/* Les lignes de liste suivent la même règle que les lignes de tableau. */
.v1 .card .tri, .v1 .rk .tri,
.v1 .card .rki, .v1 .rk .rki, .v1 .card .rkj, .v1 .rk .rkj,
.v1 .card .row, .v1 .rk .row,
.v1 .card .todo-it, .v1 .card .obj, .v1 .card .srv{border-bottom:none}
.v1 .card .tri, .v1 .card .rki, .v1 .rk .rki, .v1 .card .row,
.v1 .card .todo-it, .v1 .card .obj, .v1 .card .srv{transition:background .12s}
.v1 .card .tri:hover, .v1 .card .rki:hover, .v1 .rk .rki:hover,
.v1 .card .todo-it:hover, .v1 .card .obj:hover, .v1 .card .srv:hover{background:#F3F7F4}

/* ══ LA BARRE DU HAUT : UNE OMBRE, PAS UN FILET ════════════════════════════
   Règle de la maquette, deuxième passe : « Barre du haut — un filet sous elle
   → une ombre, qui ne se voit que quand le contenu passe dessous ».
   ⚠️ Elle portait LES DEUX. L'ombre existait déjà ; le filet est resté. Un
   trait plus une ombre au même endroit, c'est deux fois la même séparation, et
   c'est le trait qui gagne à l'œil — donc la règle ne s'appliquait pas. */
.v1 .topbar{border-bottom:none}

/* ── Les lignes de liste du RAIL de l'accueil suivent la même règle ─────────
   `.todo-it` et `.rki-vide` vivent dans un `.rk`, pas dans un `.card` : la
   règle écrite plus haut les avait manqués. Trouvé en recomptant les traits
   après coup — 22 restants au lieu des trois que la maquette autorise. */
.v1 .rk .todo-it, .v1 .rk .rki-vide{border-bottom:none}
.v1 .rk .todo-it{transition:background .12s}
.v1 .rk .todo-it:hover{background:#F3F7F4}

/* ══ LES CHAMPS : UN APLAT, PAS UNE BORDURE ════════════════════════════════
   Règle de la maquette, deuxième passe : « Champs — un aplat sans bordure ; la
   bordure ne revient qu'au focus, et elle est alors le seul trait de l'écran ».
   Mesuré : le champ de recherche portait un liseré sur ses quatre côtés en
   permanence. L'aplat suffit à dire « on écrit ici » ; le liseré ne servait
   qu'à répéter la forme.
   ⚠️ ET LA BORDURE DE FOCUS RESTE, plus franche qu'avant. Sans elle, l'écran
   devient inutilisable au clavier — et c'est exactement ce qu'on ne voit pas
   en travaillant à la souris. */
.v1 .card .filtre, .v1 .rk .filtre, .v1 .card input[type=search],
.v1 .card .champ, .v1 .rk .champ{
  border:1px solid transparent; background:var(--surface-2)}
.v1 .card .filtre:focus-within, .v1 .rk .filtre:focus-within,
.v1 .card .champ:focus-within, .v1 .rk .champ:focus-within{
  background:#fff; border-color:transparent; box-shadow:0 0 0 2px var(--vif)}

/* ══ V1 · DIRECTION — LA DISPOSITION DES CONTENUS ══════════════════════════
   Antonio, 01/09/2026 : « mets toutes les dispositions des contenus d'abord ».
   Voir `v1-pilotage.js` pour la liste des plaques et leur source attendue. */

.v1 .v1p-avis{margin-bottom:20px}

/* Les tuiles d'une plaque de mesure. Elles portent le mot « en attente », pas
   un tiret : un tiret se lit comme un zéro dès qu'on le cite. */
.v1 .v1p-tuiles{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:14px}
.v1 .v1p-t{background:var(--surface-2); border-radius:var(--r-ctrl); padding:13px 15px}
.v1 .v1p-k{font-size:var(--t-micro); font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--text-3)}
.v1 .v1p-v{font-family:var(--titre); font-size:19px; font-weight:600;
  color:var(--text-3); margin:5px 0 2px; font-style:italic}
.v1 .v1p-n{font-size:var(--t-micro); color:var(--text-3); line-height:1.45}

.v1 .v1p-fiche .row{display:flex; gap:16px; padding:9px 0}
.v1 .v1p-fiche .k{flex:1; color:var(--text-2)}
.v1 .v1p-fiche .v{color:var(--text-3); font-style:italic}

.v1 .v1p-vide{padding:22px 4px; text-align:center; color:var(--text-3); font-style:italic}
.v1 .v1p-graphe{height:180px; display:grid; place-items:center;
  background:var(--surface-2); border-radius:var(--r-ctrl);
  color:var(--text-3); font-style:italic}

/* ⚠️ LA PROVENANCE ATTENDUE EST ÉCRITE, ET ELLE SE VOIT. C'est ce qui rend la
   plaque branchable : le jour où l'API arrive, on sait quel champ va où — et
   d'ici là, personne ne peut prendre cette plaque pour une mesure. */
.v1 .v1p-src{border-top:1px solid var(--line); padding-top:11px; margin-top:2px;
  font-size:var(--t-micro); color:var(--text-3)}
.v1 .v1p-src code{font-family:var(--nombre); font-size:11px;
  background:var(--surface-3); padding:2px 7px; border-radius:var(--r-petit)}

/* ── Les filtres repris de l'application de pilotage ───────────────────────
   Ils sont posés en TÊTE de l'écran, avant les plaques : un filtre qu'on
   découvre après avoir lu les chiffres, c'est un chiffre qu'on a lu pour le
   mauvais périmètre. */
.v1 .v1p-filtres{margin-bottom:22px}
.v1 .v1p-fs{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:16px}
.v1 .v1p-f{background:var(--surface-2); border-radius:var(--r-ctrl); padding:13px 15px}
.v1 .v1p-fv{font-family:var(--nombre); font-size:12px; color:var(--text-2); margin:6px 0 5px}
.v1 .v1p-fv code{background:var(--surface-3); padding:1px 6px; border-radius:5px}

/* L'intertitre des écrans sans onglets, qui reçoivent la disposition en bloc. */
.v1 .v1p-titre{font-family:var(--titre); font-size:var(--t-micro); font-weight:700;
  letter-spacing:.11em; text-transform:uppercase; color:var(--vif-ink);
  margin:30px 0 14px; padding-top:22px; border-top:1px solid var(--line)}

/* ── UN CADRE QUI N'A PAS RÉPONDU ──────────────────────────────────────────
   La page d'erreur brute du serveur (Times New Roman, « Error response ») au
   milieu de l'application se lit comme une panne de l'application. Elle est
   remplacée par une phrase qui dit ce qui manque et où — le cadre est masqué,
   pas supprimé : il reprend sa place dès qu'il répond. */
.v1 .v1-cadre-muet{background:var(--surface-2); border-radius:var(--r-plaque);
  padding:26px 24px; color:var(--text-2); font-size:var(--t-corps); line-height:1.6;
  box-shadow:var(--relief)}
.v1 .v1-cadre-muet b{color:var(--text)}
.v1 .v1-cadre-muet .ou{display:block; margin-top:9px; font-family:var(--nombre);
  font-size:12px; color:var(--text-3)}

/* ⚠️ `hidden` NE SUFFIT PAS SUR UN CADRE. Mesuré : un `<iframe hidden>` de
   l'application mesurait encore 1780 × 1400 et affichait sa page d'erreur en
   plein écran. L'attribut `hidden` n'est qu'un `display:none` posé par le
   navigateur, et la moindre règle CSS explicite le bat — l'application en pose
   une sur ses cadres.
   C'est la même famille que le `.tabx-bar` masqué : on croit avoir caché
   quelque chose, et on l'a seulement demandé. */
.v1 iframe[hidden]{display:none !important}

/* ⚠️ UN FILTRE EN ATTENTE SE VOIT, MAIS NE SE DÉSACTIVE PAS.
   Le désactiver le retirerait de la tabulation et le ferait disparaître pour
   qui lit à l'oreille : on saurait encore moins qu'il existe. Il reste donc
   atteignable, et c'est son APPARENCE qui dit qu'il n'a rien à offrir. */
.v1 select[data-v1-filtre="attente"]{
  color: var(--txt-3, #7c8a83);
  background-image: linear-gradient(0deg, var(--att-fond, #fdf6e3), var(--att-fond, #fdf6e3));
  border-style: dashed;
}

/* Le mot prend la place d'un grand chiffre : il se pose plus petit, sinon il
   déborde la tuile qu'il occupe. Ce n'est pas un chiffre, il n'en prend pas
   le poids. */
/* ⚠️ LA CLASSE EST RÉPÉTÉE, ET C'EST DÉLIBÉRÉ. Mesuré : le mot sortait à
   24 px dans deux tuiles et à 12,48 px dans deux autres, sur le même écran.
   La cause n'est pas la surcouche mais la SPÉCIFICITÉ : l'application pose
   `.stat .v.na` (0,3,0), qui bat `.v1 .v1-attente` (0,2,0) même en étant
   chargée avant. Répéter la classe porte la nôtre à 0,4,0 sans inventer un
   sélecteur qui décrirait le balisage de l'application, donc sans rien à
   recorriger le jour où il change. */
.v1 .v1-attente.v1-attente.v1-attente{
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--txt-3, #7c8a83);
  font-style: italic;
}

/* ═══ TROIS LECTURES PAR PLAQUE ══════════════════════════════════════════
   Antonio, 01/09/2026 : « met la disposition des textes éditables, du brut et
   des tableaux sur chaque page ». Une plaque porte donc trois corps — ce
   qu'elle montre, ce qui s'y saisit, la forme que le backend devra rendre —
   et un seul est visible à la fois. */
.v1 .v1p-vues{
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  /* Le contrôle vit SOUS le sous-titre, pas à droite : il commande le corps
     de la carte, il se lit donc juste avant lui. À droite, il entrerait en
     concurrence avec le badge de genre, qui dit autre chose. */
  margin: 12px 0 2px;
  background: var(--surface-2);
  border-radius: var(--r-ctrl);
  flex: none;
}
.v1 .v1p-lect{
  font: inherit;
  font-size: var(--t-micro);
  line-height: 1;
  padding: 6px 10px;
  border: 0;
  background: transparent;
  color: var(--text-3);
  border-radius: calc(var(--r-ctrl) - 2px);
  cursor: pointer;
  white-space: nowrap;
}
.v1 .v1p-lect:hover{ color: var(--text-2) }
.v1 .v1p-lect.on{
  background: var(--surface);
  color: var(--titre);
  box-shadow: var(--relief-haut);
}
.v1 .v1p-lect:focus-visible{ outline: 2px solid var(--accent, #43a074); outline-offset: 1px }

/* ⚠️ `hidden` NE SUFFIT PAS, POUR LA TROISIÈME FOIS AUJOURD'HUI. `.card-bd`
   porte un `display` explicite dans la feuille de l'application, et une règle
   explicite bat toujours l'attribut posé par le navigateur. Les trois corps
   s'afficheraient les uns sous les autres. */
.v1 .card-bd[data-vue][hidden]{ display: none !important }

/* Le brut : une esquisse, pas du JSON valide. Il défile chez lui — un
   squelette large ne doit pas faire glisser la page de côté. */
.v1 .v1p-brut{
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-micro);
  line-height: 1.65;
  color: var(--text-2);
  background: var(--surface-2);
  border-radius: var(--r-ctrl);
  padding: 14px 16px;
  overflow-x: auto;
  white-space: pre;
  tab-size: 2;
}

/* Ce qui se saisit : le nom du champ, et ce qu'il attend. */
.v1 .v1p-saisie{ display: grid; grid-template-columns: 1fr auto; gap: 0 16px }
.v1 .v1p-saisie .row{
  display: contents;
}
/* ⚠️ LE FOND DU `code` DE L'APPLICATION COUPAIT LA LIGNE EN DEUX : il ne
   couvrait que la colonne de gauche, et le type restait sur le blanc. Une
   ligne se lit d'un bloc, ou elle ne se lit pas. */
.v1 .v1p-saisie code{
  background: transparent;
  padding-left: 0;
  padding-right: 0;
  font-family: var(--mono);
  font-size: var(--t-micro);
  color: var(--titre);
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}
.v1 .v1p-saisie .t{
  font-size: var(--t-micro);
  color: var(--text-3);
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
  text-align: right;
  white-space: nowrap;
}
.v1 .v1p-saisie .row:last-child code,
.v1 .v1p-saisie .row:last-child .t{ border-bottom: 0 }

/* ═══ PASSE TYPOGRAPHIQUE (01/09/2026) ═══════════════════════════════════
   Antonio : « joue bien avec les couleurs et la taille des écritures, bien
   visible, gras et tout ».

   ⚠️ MESURÉ D'ABORD : le contraste n'était PAS le problème. Tout passait
   4,5 — titre de plaque 15,6, sous-titre 5,0, en-tête de tableau 5,2. Le
   problème était la TAILLE, et surtout l'inversion : le titre de section, qui
   nomme un pan entier de l'écran, était le plus petit texte de la page à
   11,5 px, sous les cellules du tableau qu'il coiffe.

   | élément              | avant       | après       |
   |----------------------|-------------|-------------|
   | titre de section     | 11,5 / 700  | 14 / 800    |
   | titre de plaque      | 19 / 600    | 20 / 700    |
   | sous-titre           | 12 / 400    | 13,5 / 400  |
   | en-tête de tableau   | 11 / 600    | 12,5 / 700  |
   | cellule              | 13 / 400    | 13,5 / 400  |
   | bouton de lecture    | 11,5 / 400  | 12,5 / 600  |
   | source attendue      | 11,5 / 400  | 12,5 / 400  |

   ⚠️ AUCUN LISERÉ VERTICAL, AUCUN CADRE DE PLUS. Le liseré à gauche d'un
   titre est l'un des marqueurs qui font lire « fabriqué par une IA », et
   Antonio l'a refusé deux fois sur le site. La hiérarchie se fait à la
   taille, à la graisse et à la couleur, pas au décor. */

.v1 .v1p-titre{
  font-size: 14px;
  font-weight: 800;
  letter-spacing: .09em;
  margin: 34px 0 16px;
}
.v1 .v1p-bloc .card-title{
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -.008em;
}
/* Le sous-titre est la PHRASE qu'on lit vraiment : elle porte la règle, le
   piège, ce qu'il ne faut pas confondre. Elle mérite d'être lisible. */
.v1 .v1p-bloc .card-sub{
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-2);
  max-width: 78ch;
}
.v1 .v1p-bloc th{
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-2);
}
.v1 .v1p-bloc td{ font-size: 13.5px }
.v1 .v1p-lect{ font-size: 12.5px; font-weight: 600 }
.v1 .v1p-lect.on{ font-weight: 700 }
.v1 .v1p-src{ font-size: 12.5px }
.v1 .v1p-src b{ color: var(--titre-c, #217a52); font-weight: 700 }
.v1 .v1p-n{ font-size: 12px; line-height: 1.5 }
.v1 .v1p-t .v1p-k{ font-size: 12px }
.v1 .v1p-vide{ font-size: 13.5px }

/* ═══ LE DOSSIER DU JEUNE ════════════════════════════════════════════════
   ⚠️ IL S'OUVRE AU MILIEU DEPUIS LE 07/09/2026, ET LA NOTE PRÉCÉDENTE DISAIT
   L'INVERSE. Elle expliquait « un tiroir, pas une page : on garde la liste
   derrière soi ». Antonio, deux fois : « le dossier candidat se met toujours à
   droite, pas au milieu » — la première fois le 04/09, à propos de la grille
   formation × mois (« une page flottante comme le dossier candidat, mais au
   milieu »), et de nouveau aujourd'hui, sur le dossier lui-même.
   La raison du tiroir ne tient pas ici : ce qu'on gardait « derrière soi »,
   c'est une liste dont on vient de choisir UNE ligne — on ne la compare plus,
   on lit un dossier de huit onglets. Collé au bord droit, il laissait
   1 160 pixels de vide à gauche et coupait ses tableaux à 760.
   Ce qui reste vrai : c'est un panneau, pas une page. Le retour coûte toujours
   un geste, l'adresse ne change pas.
   ⚠️ ET LES RÉSULTATS DE RECHERCHE RESTENT UN MENU DÉROULANT, À DROITE du
   champ (« mais les résultats dans le menu déroulant à droite »). Ils
   flottent au-dessus du dossier au lieu de le pousser vers le bas : sans cela,
   taper trois lettres faisait sauter tout le contenu de 210 pixels. */
.v1 .v1-dos{ position: fixed; inset: 0; z-index: 90; display: grid; place-items: center }
/* ⚠️ ET LE `hidden` DOIT ENCORE VOULOIR DIRE QUELQUE CHOSE (08/09/2026).
   C'est CETTE ligne qui a fait croire pendant deux jours que le bouton
   « Fermer » ne marchait pas. L'attribut `hidden` ne cache que par la feuille
   du NAVIGATEUR (`[hidden]{display:none}`) : n'importe quel `display` écrit
   par nous le bat, quelle que soit sa spécificité — une déclaration d'auteur
   passe toujours devant une déclaration du navigateur. En centrant la carte
   j'ai posé `display: grid` sans condition : `fermerLeDossier()` posait donc
   bien `tiroir.hidden = true`, et il ne se passait RIEN à l'écran. Mesuré :
   `hidden` vrai, `display` calculé « grid », hauteur 852 px.
   La preuve que c'est un oubli et non une intention est trois lignes plus
   bas : `.v1-dosq[hidden]` porte le garde-fou, la carte ne l'avait pas.
   ⚠️ Règle : dès qu'un élément qu'on cache par `hidden` reçoit un `display`
   dans notre feuille, il lui faut sa ligne `[hidden]{display:none}`. Sinon
   c'est le JavaScript qu'on ira débugger, et il n'y sera pour rien. */
.v1 .v1-dos[hidden]{ display: none }
.v1 .v1-dos-voile{
  position: absolute; inset: 0;
  background: rgba(12, 26, 19, .38);
  backdrop-filter: blur(2px);
}
.v1 .v1-dos-vol{
  position: relative;
  width: min(980px, 94vw); max-height: 90vh;
  background: var(--surface);
  border-radius: var(--r-plaque, 14px);
  box-shadow: 0 24px 64px rgba(12, 26, 19, .24);
  display: flex; flex-direction: column; overflow: hidden;
  animation: v1-dos-entre .22s cubic-bezier(.32,.72,0,1);
}
/* ⚠️ Une entrée en OPACITÉ avait été refusée sur la maquette (elle s'était
   figée à 7,6 %). Celle-ci ne joue que sur la position, et elle se coupe
   pour qui a demandé moins d'animation. */
@keyframes v1-dos-entre{ from{ transform: translateY(10px) } to{ transform: none } }
@media (prefers-reduced-motion: reduce){ .v1 .v1-dos-vol{ animation: none } }

.v1 .v1-dos-hd{
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px 18px;
  padding: 20px 24px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.v1 .v1-dos-q-zone{ grid-column: 1 / -1; position: relative }
.v1 .v1-dos-q{
  width: 100%;
  font: inherit; font-size: 14px;
  padding: 10px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-ctrl);
  background: var(--surface);
}
.v1 .v1-dos-q:focus-visible{ outline: 2px solid #43a074; outline-offset: 1px }
/* ═══ LA BULLE DE RECHERCHE (07/09/2026) ═════════════════════════════════
   Antonio : « la barre de recherche qui est du fond reste le lieu où on tape ;
   on tape le jeune dessus et la carte s'affiche au milieu SANS la barre de
   recherche ». Elle est donc sortie du panneau et vit ici, ancrée sous le
   bouton de la barre du haut.
   ⚠️ ET C'EST AUSSI LA RÉPARATION DU « ON NE PEUT PAS QUITTER » : dans le
   panneau, le menu des résultats se posait par-dessus les onglets ET le bouton
   « Fermer ». Le bouton répondait — mesuré — mais il était couvert. */
.v1 .v1-dosq{
  position: fixed; z-index: 96;
  width: min(460px, 92vw);
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--line-2); border-radius: var(--r-plaque, 14px);
  box-shadow: 0 18px 44px rgba(12, 26, 19, .22);
}
.v1 .v1-dosq[hidden]{ display: none }
.v1 .v1-dosq .v1p-n{ margin-top: 6px }
.v1 .v1-dos-res{ display: grid; gap: 2px; margin-top: 8px; max-height: 320px; overflow-y: auto }
.v1 .v1-dos-res:empty{ display: none }
.v1 .v1-dos-r{
  font: inherit; font-size: 13.5px; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--r-ctrl);
  background: var(--surface-2); color: var(--titre); cursor: pointer;
}
.v1 .v1-dos-r:hover{ background: #e3efe8 }
.v1 .v1-dos-nom{ font-family: var(--titre); font-size: 24px; font-weight: 700; letter-spacing: -.01em }
/* ═══ FERMER : UNE CIBLE QU'ON NE PEUT PAS RATER (08/09/2026) ══════════════
   Antonio, quatre fois : « la carte ne se ferme pas quand on appuie sur
   fermer », « Échap ferme, le voile ferme, mais pas le bouton ».
   Tout le reste a été éliminé par la mesure : la fonction marche, rien ne
   couvre le bouton, aucun `stopPropagation`, l'écoute est en capture sur le
   document. Ce qui restait tenait dans deux nombres, mesurés à l'écran :
   « Fermer » faisait **73 px** de large et vivait à **8 px** d'un bouton de
   **173 px** — « Exporter le dossier (PDF) ». Un clic dix pixels trop à gauche
   ne ferme pas : il lance un PDF, qui met plusieurs secondes et n'affiche rien.
   Vu de l'utilisateur, c'est exactement « le bouton ne fait rien », et il ne
   reste qu'à recharger.
   ⚠️ La cible passe donc à 40 px de haut et 104 px de large minimum, avec la
   croix devant le mot, et l'écart double. Ce n'est pas de la décoration : deux
   gestes voisins dont l'un est lent et muet, séparés de huit pixels, sont un
   piège — et c'est celui qui a coûté quatre allers-retours. */
.v1 .v1-dos-x{
  font: inherit; font-size: 13px; font-weight: 600;
  align-self: start; min-width: 104px; min-height: 40px; padding: 0 16px;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--titre); cursor: pointer;
}
.v1 .v1-dos-x::before{ content: '✕'; font-size: 14px; line-height: 1; opacity: .75 }
.v1 .v1-dos-x:hover{ background: #EEF4F0; border-color: #43a074 }
.v1 .v1-dos-x:focus-visible{ outline: 2px solid #43a074; outline-offset: 2px }
.v1 .v1-dos-corps{ padding: 8px 24px 32px; overflow-y: auto; flex: 1 }
.v1 .v1-dos-corps .v1-plaques{ grid-template-columns: 1fr }

/* L'appel depuis la barre du haut : sans lui, le dossier ne s'ouvrirait que
   depuis une liste, donc jamais quand on cherche quelqu'un. */
.v1 .v1-dos-appel{
  font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 8px 14px; margin-right: 10px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--surface); color: var(--text-2); cursor: pointer; white-space: nowrap;
}
.v1 .v1-dos-appel:hover{ color: var(--titre); border-color: #43a074 }

/* Un nom cliquable se voit : sinon personne ne sait qu'il ouvre quelque chose.
   C'est la leçon du bouton invisible, à l'envers. */
.v1 table tbody td.v1-nom{ cursor: pointer; text-decoration: underline;
  text-decoration-color: #bcd6c7; text-underline-offset: 3px }
.v1 table tbody td.v1-nom:hover{ text-decoration-color: #43a074; color: var(--titre) }
.v1.v1-dos-ouvert{ overflow: hidden }

/* La photo du jeune, ou ses initiales. Jamais un rond vide : il se lirait
   comme une image qui n'a pas chargé, donc comme une panne. */
.v1 .v1-dos-ident{ display: flex; gap: 14px; align-items: flex-start }
.v1 .v1-dos-photo{
  flex: none; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  background: #dcebe2; color: #1d6a48;
  font-family: var(--titre); font-size: 15px; font-weight: 700; letter-spacing: .02em;
  border: 1px solid #c4dccd;
}

/* Le compte des champs reconnus : c'est lui qui nomme le travail restant. */
.v1 .v1p-compte{ margin-left: 10px; font-size: 12px; color: #1d6a48; font-weight: 600 }
.v1 .v1p-compte.partiel{ color: #9a6b12 }
.v1 .v1p-compte.attente{ color: var(--text-3); font-weight: 500; font-style: italic }
/* ⚠️ « Je n'ai pas pu lire » se voit. Un écran muet peint comme un écran vide
   se lit « il n'y a rien », et c'est sur cette lecture qu'on décide. */
.v1 .v1p-muet{
  padding: 16px; border-radius: var(--r-ctrl);
  background: #fdecec; color: #8c2b2b; font-size: 13.5px; line-height: 1.5;
}

/* ── LES FILTRES DE DIRECTION SONT DE VRAIS SÉLECTEURS (01/09/2026, soir) ──
   Antonio, devant « perimetre · synthese | <région> » : « je veux des vrais
   données, pas des choses comme tels ». Les options viennent du serveur ;
   un sélecteur qui n'a pas été lu est grisé et le dit. */
.v1 .v1p-f{display:flex; flex-direction:column; gap:6px}
.v1 .v1p-sel{font:600 13.5px/1.3 var(--texte); color:var(--text-1,#15201A); background:#fff;
  border:1px solid var(--line); border-radius:var(--r-ctrl,10px); padding:8px 10px; width:100%}
.v1 .v1p-sel:disabled{color:var(--text-3); background:var(--surface-3,#EEF3EF); font-style:italic}
.v1 .v1p-sel:focus{outline:none; box-shadow:0 0 0 2px var(--vif,#3bae79)}
.v1 .v1p-periode{margin-top:14px; font-size:13.5px; color:var(--text-2)}
.v1 .v1p-refus{margin-top:6px; font-size:12.5px; color:#9a6b12}
.v1 .v1p-fetat{margin-top:8px}
.v1 .v1p-fetat.v1p-muet{margin-top:12px}
.v1 .v1p-periode-note, .v1 .v1p-portee{display:block; margin-top:6px; font-size:12px; color:var(--text-2)}
.v1 .v1p-portee{color:#9a6b12; font-style:italic}

/* La courbe des douze mois : deux barres par mois, le chiffre au-dessus. */
.v1 .v1p-courbe{width:100%; height:auto; display:block}
.v1 .v1p-courbe rect.c{fill:var(--vif,#3bae79)}
.v1 .v1p-courbe rect.r{fill:#c4553f}
.v1 .v1p-courbe text{font:600 11px var(--nombre); fill:var(--text-2)}
.v1 .v1p-courbe text.m{font-weight:500; fill:var(--text-3)}
.v1 .v1p-courbe text.r{fill:#c4553f}
.v1 .v1p-courbe .axe{stroke:var(--line); stroke-width:1}
.v1 .v1p-legende{display:flex; flex-wrap:wrap; gap:16px; align-items:center; margin-top:8px;
  font-size:12px; color:var(--text-2)}
.v1 .v1p-legende .c::before, .v1 .v1p-legende .r::before{content:''; display:inline-block;
  width:10px; height:10px; border-radius:2px; margin-right:6px; vertical-align:-1px; background:var(--vif,#3bae79)}
.v1 .v1p-legende .r::before{background:#c4553f}

/* ── LE RÉEL, PAS LA MAQUETTE (02/09/2026) ──────────────────────────────────
   Antonio : « je t'avais dit de respecter le backend, pas d'écrire Texte
   éditable, Brut ». Une carte : titre, contenu, un pied qui dit l'état, et les
   gestes. Rien qui ressemble à une spécification. */
.v1 .v1p-pied{border-top:1px solid var(--line); padding-top:10px; margin-top:2px;
  font-size:12.5px; color:var(--text-3)}
.v1 .v1p-actions{display:flex; flex-wrap:wrap; align-items:center; gap:10px 14px;
  border-top:1px solid var(--line); padding-top:10px}
.v1 .v1p-lien{font:600 12.5px/1 var(--texte); color:var(--vif-ink,#1d6a48); text-decoration:none;
  background:var(--surface-2); border-radius:var(--r-ctrl,10px); padding:8px 11px}
.v1 .v1p-lien:hover{background:var(--surface-3,#EEF3EF)}
.v1 .v1p-btn{font:600 12.5px/1 var(--texte); color:#fff; background:var(--vif,#3bae79); border:0;
  border-radius:var(--r-ctrl,10px); padding:7px 11px; cursor:pointer}
.v1 .v1p-btn.sec{color:var(--text-2); background:var(--surface-3,#EEF3EF)}
.v1 .v1p-btn:focus-visible{outline:none; box-shadow:0 0 0 2px var(--vif,#3bae79)}
.v1 td.v1p-geste{min-width:150px}
.v1 .v1p-mini{display:flex; flex-direction:column; gap:6px; margin-top:8px}
.v1 .v1p-mini textarea{font:13px/1.4 var(--texte); border:1px solid var(--line); border-radius:8px; padding:6px 8px; min-width:220px}
.v1 .v1p-mini input[type=date]{font:12.5px var(--texte); border:1px solid var(--line); border-radius:8px; padding:4px 6px; margin-left:6px}
.v1 .v1p-mini-b{display:flex; gap:8px}
.v1 .v1p-ok{color:#1d6a48; font-weight:600}
.v1 .v1p-ko{color:#8c2b2b; font-weight:600}
.v1 .v1p-fiche .v.lu{color:var(--text-1,#15201A); font-style:normal; font-weight:600}
/* ═══ LES CARTES DU DOSSIER SE REMPLISSENT, ELLES NE S'ALIGNENT PAS ════════
   Antonio, 08/09/2026 : « ajuste les cartes représentatives dans la carte
   dossier étudiant ».
   Mesuré à l'écran : dans une grille à deux colonnes, les cartes gardent bien
   leur hauteur propre (145, 335, 204, 166 px) — mais la LIGNE, elle, prend la
   hauteur de la plus grande. Sous une carte de 145 px voisine d'une carte de
   335, il restait 190 pixels de vide avant la ligne suivante. Sur un dossier
   fait de petites fiches de faits, ce sont des trous partout.
   Des COLONNES, pas une grille : chaque carte se pose sous la précédente dès
   qu'il y a la place, et il n'y a plus de ligne à égaliser. `break-inside`
   garde une carte d'un seul tenant ; une carte large (une carte, un tableau)
   traverse les deux colonnes comme elle traversait la grille. */
.v1 .v1-dos-corps .v1-plaques{display:block; columns:2; column-gap:20px}
.v1 .v1-dos-corps .v1-plaques > *{break-inside:avoid; margin:0 0 20px}
.v1 .v1-dos-corps .v1-plaques > .v1-large{column-span:all}
@media (max-width:820px){ .v1 .v1-dos-corps .v1-plaques{columns:1} }
/* ⚠️ ET L'INTERTITRE NE COLLE PLUS À LA CARTE DU DESSUS : il portait 4 px en
   haut, donc « Ses contrats » venait toucher la carte précédente — on lisait un
   titre comme s'il appartenait à ce qu'il suivait, pas à ce qu'il annonce. */
/* ⚠️ L'INTERTITRE SE DÉTACHE DE CE QUI PRÉCÈDE, QUELLE QUE SOIT SA CLASSE.
   Premier jet : la règle visait `.v1p-titre`. Vu à l'écran, « SES CONTRATS »
   touchait encore la carte du dessus — dans le dossier, l'intertitre est un
   `.sec` (petites capitales vertes), pas un `.v1p-titre`. On vise donc ce qui
   SUIT un bloc de cartes : un titre qui colle à ce qu'il termine se lit comme
   sa légende, pas comme l'annonce de ce qui vient. */
.v1 .v1-dos-corps .v1p-titre{margin-top:26px}
.v1 .v1-dos-corps .v1-plaques + *{margin-top:26px}
.v1 .v1-dos-corps .v1-dos-onglets + .v1p-titre{margin-top:4px}
/* La courbe, relue : une grille, des repères, des barres qui se lisent. */
.v1 .v1p-courbe .grille{stroke:var(--line); stroke-width:1; stroke-dasharray:2 4}
.v1 .v1p-courbe .tick{font:500 10.5px var(--nombre); fill:var(--text-3)}
.v1 .v1p-courbe rect.c{fill:var(--vif,#3bae79)}
.v1 .v1p-courbe rect.r{fill:#c4553f}
.v1 .v1p-courbe rect:hover{opacity:.85}

/* Les filtres d'une PLAQUE (piste d'audit, journées) : dans la carte, au-dessus
   de son contenu — un filtre qu'on découvre après avoir lu le tableau, c'est un
   tableau lu pour la mauvaise fenêtre. */
.v1 .v1p-fplaque{padding:0 0 14px; margin:0 0 14px; border-bottom:1px solid var(--line);
  grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:12px}
.v1 .v1p-fplaque .v1p-f{background:transparent; padding:0}
.v1 .v1p-fplaque .v1p-n{margin-top:2px}
.v1 .v1p-demande{margin-left:10px}
.v1 .v1p-demande:disabled{opacity:.6; cursor:progress}

/* L'écart entre deux sources d'une même mesure : discret quand elles
   concordent, ambré quand l'une décroche. */
.v1 .v1p-ecart{display:block; margin-top:6px; font-size:12px; color:var(--text-2)}
.v1 .v1p-ecart.alerte{color:#9a6b12; font-weight:600}

/* ══ V1 · LIRE UN TABLEAU DE BORD ══════════════════════════════════════════
   Antonio, 02/09/2026 : « les couleurs sur le tableau de bord… y a trop
   d'écriture mais difficile de lire le tableau, les titres sont les mêmes ».
   Trois causes, mesurées à l'écran, et trois corrections :

     1. UNE VALEUR LUE SE DESSINAIT COMME UNE ATTENTE. « en attente » et « 34 »
        partageaient la même règle : 19 px, italique, gris moyen. Le chiffre —
        la seule chose qu'on vient chercher — était le texte le plus discret de
        la tuile. Il passe en chasse fixe, à pleine encre, deux crans au dessus.
     2. TOUS LES TITRES AVAIENT LE MÊME POIDS. Titre de plaque, phrase
        d'explication, provenance : trois blocs de gris, sans hiérarchie. Le
        titre monte, l'explication descend, la provenance devient une note.
     3. LA COULEUR NE VOULAIT RIEN DIRE. Elle dit désormais une chose et une
        seule, celle de la règle 20 : le jaune est LA mesure du mois, il n'y en
        a qu'un ; le corail est ce qui sort du dispositif. Tout le reste est du
        papier. Deux aplats jaunes ne désigneraient plus rien. */

.v1 .v1p-v.v1p-lu{
  font-family:var(--nombre); font-size:30px; font-weight:600; font-style:normal;
  color:var(--text-1); letter-spacing:-.02em; font-variant-numeric:tabular-nums;
  line-height:1.1; margin:7px 0 3px}
.v1 .v1p-fiche .v.v1p-lu{font-style:normal; color:var(--text-1); font-weight:600}
.v1 .v1p-t .v1p-n{font-size:10.5px; color:var(--text-3); opacity:.92}

/* La mesure du mois, et elle seule. */
.v1 .v1p-t[data-ton="mesure"]{background:var(--t-jaune)}
.v1 .v1p-t[data-ton="mesure"] .v1p-k,
.v1 .v1p-t[data-ton="mesure"] .v1p-n{color:var(--t-jaune-i)}
.v1 .v1p-t[data-ton="mesure"] .v1p-v.v1p-lu{color:#2D2A00}
/* Ce qui sort du dispositif : le chiffre en corail, jamais un aplat — une
   rupture ne se lit pas sur un fond de couleur. */
.v1 .v1p-t[data-ton="sortie"] .v1p-v.v1p-lu{color:var(--alr)}

/* La hiérarchie des textes d'une plaque.
   ⚠️ MESURÉ AVANT D'ÉCRIRE : `unitools.css:904` pose le titre à 15 px / 620 et
   l'explication à 12 px / gris. Deux crans d'écart sur trois lignes qui se
   suivent, cela ne fait pas une hiérarchie — d'où « les titres sont les
   mêmes ». Le titre monte à 17 px, prend la police des titres et l'encre
   pleine ; l'explication passe en dessous et se borne à trois lignes ; la
   provenance devient une note.
   ⚠️ ET LE NOM DE LA CLASSE SE MESURE : le premier jet stylait `.v1p-sous`,
   qui n'existe nulle part. Le gabarit écrit `.card-sub`, celui de
   l'application, réutilisé exprès. */
.v1 .card > .card-hd .card-title{
  font-family:var(--titre); font-size:17px; font-weight:700;
  letter-spacing:-.02em; color:var(--text-1); line-height:1.25}
.v1 .card > .card-hd .card-sub{
  font-size:12px; color:var(--text-3); line-height:1.5; max-width:70ch; margin-top:5px;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden}
/* Elle se déplie au survol et au clavier : on borne la hauteur, on ne cache
   pas le texte. Une explication tronquée pour toujours, c'est une phrase
   qu'on a écrite pour personne. */
.v1 .card:hover > .card-hd .card-sub,
.v1 .card:focus-within > .card-hd .card-sub{-webkit-line-clamp:unset; overflow:visible}
.v1 .v1p-src{font-size:10.5px; opacity:.85}

/* ══ V1 · OUVRIR UN CHIFFRE ════════════════════════════════════════════════
   « Lorsqu'on clique sur contrat du mois… qu'on puisse avoir une carte pour
   voir la liste. Et qu'on puisse cliquer sur les jeunes pour voir sa fiche. »
   ⚠️ Ce qui s'ouvre doit ANNONCER qu'il s'ouvre : une tuile cliquable sans
   signe, personne ne clique dessus — c'est le bouton invisible de la règle 25,
   qui ne fait pas d'erreur et ne fait rien. */
.v1 .v1p-t-ouvre{
  display:block; width:100%; text-align:left; border:none; cursor:pointer;
  font:inherit; position:relative; padding-bottom:28px;
  transition:box-shadow .16s var(--nav-courbe), transform .16s var(--nav-courbe)}
.v1 .v1p-t-ouvre:hover{box-shadow:0 0 0 2px var(--vif-ring); transform:translateY(-1px)}
.v1 .v1p-t-ouvre:focus-visible{outline:2px solid var(--vif-ink); outline-offset:2px}
.v1 .v1p-t-ouv{
  position:absolute; left:15px; bottom:11px;
  font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--vif-ink); opacity:.75}
.v1 .v1p-t-ouv::after{content:' →'}
.v1 .v1p-t-ouvre:hover .v1p-t-ouv{opacity:1}
.v1 .v1p-t[data-ton="mesure"] .v1p-t-ouv{color:var(--t-jaune-i)}
.v1 tr.v1-lst-tr{cursor:pointer}
.v1 tr.v1-lst-tr:hover td{background:var(--vif-t)}
.v1 tr.v1-lst-tr:focus-visible{outline:2px solid var(--vif-ink); outline-offset:-2px}

.v1 .v1-lst-hd{padding:2px 0 12px; color:var(--text-2); font-size:var(--t-second)}
.v1 .v1-lst-coupe{color:var(--alr); font-weight:600}
.v1 .v1-lst{display:flex; flex-direction:column; gap:2px}
.v1 .v1-lst-r{
  display:grid; grid-template-columns:minmax(0,1fr) auto; gap:2px 14px;
  width:100%; text-align:left; border:none; background:none; cursor:pointer;
  font:inherit; padding:10px 12px; border-radius:var(--r-ctrl)}
.v1 .v1-lst-r:hover{background:var(--vif-t)}
.v1 .v1-lst-r:focus-visible{outline:2px solid var(--vif-ink); outline-offset:1px}
.v1 .v1-lst-n{font-weight:600; color:var(--text-1)}
.v1 .v1-lst-m{grid-column:1; font-size:11.5px; color:var(--text-3)}
.v1 .v1-lst-d{grid-column:2; grid-row:1/3; align-self:center; text-align:right;
  font-family:var(--nombre); font-size:11.5px; color:var(--text-3)}
.v1 .v1-lst-b{display:inline-block; margin-left:6px; padding:1px 7px; border-radius:999px;
  font-family:var(--texte); font-size:10.5px; font-weight:600;
  background:var(--surface-3); color:var(--text-2)}
.v1 .v1-lst-b-ok{background:var(--ok-bg); color:var(--ok)}
.v1 .v1-lst-b-ko{background:var(--alr-bg); color:var(--alr)}
.v1 .v1-lst-pied{padding-top:12px; border-top:1px solid var(--line); margin-top:10px}
.v1 .v1-lst-retour{
  display:inline-block; margin-bottom:14px; border:1px solid var(--line);
  background:#fff; border-radius:var(--r-ctrl); padding:7px 13px;
  font:inherit; font-size:var(--t-second); color:var(--text-2); cursor:pointer}
.v1 .v1-lst-retour:hover{border-color:var(--vif); color:var(--vif-ink)}
/* En mode liste, la pastille d'initiales n'a pas de sens : ce n'est pas
   quelqu'un. On la retire plutôt que d'afficher un rond vide. */
.v1 .v1-dos.v1-dos-l .v1-dos-photo{display:none}
.v1 .v1-dos.v1-dos-l .v1-dos-q-zone{display:none}

/* ══ V1 · DE VRAIS MENUS DÉROULANTS ════════════════════════════════════════
   Le `<select>` reste dans la page — invisible, non tabulable, piloté par le
   bouton — pour que `lireLesFiltres()` et les délégués `change` n'aient rien à
   savoir de cet habillage. */
.v1 .v1p-dd{position:relative}
.v1 .v1p-dd > select.v1p-sel{
  position:absolute; width:1px; height:1px; padding:0; margin:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; opacity:0;
  pointer-events:none}
.v1 .v1p-dd-b{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; text-align:left; font:inherit; font-size:var(--t-second);
  color:var(--text-1); background:#fff; cursor:pointer;
  border:1px solid var(--line); border-radius:var(--r-ctrl); padding:9px 12px}
.v1 .v1p-dd-b:hover{border-color:var(--vif)}
.v1 .v1p-dd-b:focus-visible{outline:none; border-color:var(--vif); box-shadow:0 0 0 2px var(--vif-ring)}
.v1 .v1p-dd-b[aria-expanded="true"]{border-color:var(--vif); box-shadow:0 0 0 2px var(--vif-ring)}
.v1 .v1p-dd-mort{background:var(--surface-2); color:var(--text-3); cursor:not-allowed}
.v1 .v1p-dd-v{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.v1 .v1p-dd-x{flex:none; width:9px; height:9px; border-right:1.6px solid currentColor;
  border-bottom:1.6px solid currentColor; transform:rotate(45deg) translate(-2px,-2px);
  opacity:.5; transition:transform .16s var(--nav-courbe)}
.v1 .v1p-dd-b[aria-expanded="true"] .v1p-dd-x{transform:rotate(225deg) translate(-3px,-3px); opacity:1}
.v1 .v1p-dd-l{
  position:absolute; z-index:60; left:0; right:0; top:calc(100% + 5px);
  max-height:280px; overflow:auto; background:#fff;
  border:1px solid var(--line); border-radius:var(--r-ctrl); box-shadow:var(--sh-2); padding:5px}
.v1 .v1p-dd-o{
  display:block; width:100%; text-align:left; font:inherit; font-size:var(--t-second);
  color:var(--text-1); background:none; border:none; cursor:pointer;
  padding:8px 11px; border-radius:var(--r-petit)}
.v1 .v1p-dd-o:hover{background:var(--vif-t)}
.v1 .v1p-dd-o:focus-visible{outline:none; background:var(--vif-t); box-shadow:inset 0 0 0 2px var(--vif-ring)}
.v1 .v1p-dd-sel{background:var(--vif-t); color:var(--vif-ink); font-weight:600}
.v1 .v1p-dd-sel::after{content:'✓'; float:right; opacity:.8}

/* ══ V1 · L'ÉCRAN D'ORIGINE, SERVI DANS LE V1 ══════════════════════════════
   « Tout devrait être fait sur le V1, pas ouvrir pilotage ou recrutement ou
   communication. » Le volet est plus large que celui d'un dossier : on y
   travaille, on n'y lit pas une fiche. */
.v1 .v1-dos.v1-dos-ecran .v1-dos-vol{width:min(1180px,97vw)}
.v1 .v1-ecr{flex:1; min-height:0; background:var(--surface-2); padding:0}
.v1 .v1-ecr-f{display:block; width:100%; height:100%; border:0; background:#fff}
.v1 .v1-ecr .v1-cadre-muet{margin:24px}
/* Le bouton qui l'ouvre : un bouton, pas un lien — il ne sort de nulle part. */
.v1 .v1p-lien{
  display:inline-block; font:inherit; font-size:var(--t-second); font-weight:600;
  color:var(--vif-ink); background:var(--vif-t); border:1px solid transparent;
  border-radius:var(--r-ctrl); padding:8px 14px; cursor:pointer}
.v1 .v1p-lien:hover{border-color:var(--vif)}
.v1 .v1p-lien:focus-visible{outline:2px solid var(--vif-ink); outline-offset:2px}

/* ══ V1 · LE CALENDRIER, AU DESSIN DU MVP ═════════════════════════════════
   Antonio, 03/09/2026 : « mieux vaut remettre le design du calendrier du MVP
   pour le V1 ». C'est la vue annuelle de `cfamc/pedagogie/calendriers.php`
   (`cfamc/assets/app.css`, « Calendriers pédagogie »), reprise valeur pour
   valeur sous le préfixe du V1 : les mois en cartes côte à côte, un événement
   = un bloc à liseré vert, le jour en indigo gras, « fait » en vert, incertain
   en pointillés sur fond paille. La grille de jours et l'agenda du 02/09 sont
   retirés avec leurs règles : deux calendriers pour une même mesure. */
.v1 .v1p-annee{display:grid; grid-template-columns:repeat(auto-fill,minmax(230px,1fr)); gap:16px}
.v1 .v1p-mois{border:1px solid #e5e7eb; border-radius:10px; overflow:hidden; background:#fff;
  display:flex; flex-direction:column; margin:0}
.v1 .v1p-mois.vide{opacity:.5; background:#fafafa}
.v1 .v1p-mois.charge{border-color:#c7d2fe; box-shadow:0 2px 10px rgba(40,130,90,.10)}
.v1 .v1p-mois-t{background:#f8f9ff; border-bottom:1px solid #e5e7eb; padding:10px 14px;
  font-weight:700; font-size:14px; display:flex; justify-content:space-between; align-items:baseline; gap:8px}
.v1 .v1p-mois-c{font-size:12px; font-weight:700; color:#fff; background:#28825A; border-radius:10px; padding:1px 8px}
.v1 .v1p-mois.vide .v1p-mois-t{background:#f5f5f5; color:#999}
.v1 .v1p-mois-corps{padding:8px; display:flex; flex-direction:column; gap:6px}
.v1 .v1p-mois-vide{padding:18px 14px; text-align:center; color:#bbb; font-size:12px}
.v1 .v1p-evt{border-left:4px solid #28825A; background:#f8f9ff; border-radius:6px; padding:7px 10px;
  font-size:12px; line-height:1.45}
.v1 .v1p-evt-j{font-weight:700; color:#4c51bf}
.v1 .v1p-evt-qui{font-weight:600}
.v1 .v1p-evt-ou{color:#666; font-size:11px}
.v1 .v1p-evt.incertain{border-left-style:dashed; background:#fffaf0}
.v1 .v1p-evt.realise{border-left-color:#16a34a; background:#f4fdf7}
.v1 .v1p-evt.realise .v1p-evt-j{color:#15803d}
.v1 .v1p-evt.realise .v1p-evt-qui s{text-decoration-color:#16a34a}
/* Ce que sa page ne montre pas parce que sa vue l'implique — le type — et le
   campus, en petites étiquettes ; ici tous les types sont dans la même carte. */
.v1 .v1p-evt-t{display:inline-block; margin-left:6px; font-size:10.5px; font-weight:700; letter-spacing:.03em;
  color:#4c51bf; background:#eef0ff; border-radius:6px; padding:1px 6px; vertical-align:1px}
.v1 .v1p-campus{display:inline-block; margin-left:6px; font-size:10.5px; font-weight:700;
  color:#1E6644; background:#DCF2E7; border-radius:6px; padding:1px 6px; vertical-align:1px}
/* Un nom ouvre son dossier, comme dans un tableau. */
.v1 .v1-nom-agd{cursor:pointer}
.v1 .v1-nom-agd:hover{text-decoration:underline}
.v1 .v1p-agd-pied{margin-top:16px; padding-top:12px; border-top:1px solid var(--line)}
@media print{ .v1 .v1p-annee{gap:8px} .v1 .v1p-mois{break-inside:avoid} }

/* ══ V1 · UNE PIÈCE DU DOSSIER, LUE DANS LE V1 ═════════════════════════════
   Le document n'est pas téléchargé ni ouvert dans un onglet : il se lit dans
   le volet, comme tout le reste depuis le 02/09. */
.v1 .v1-md-src{padding:10px 12px; background:var(--surface-2);
  border-radius:var(--r-ctrl); margin-bottom:18px; line-height:1.6}
.v1 .v1-md-src code{font-family:var(--nombre); font-size:10.5px}
.v1 .v1-md{max-width:74ch; line-height:1.65; color:var(--text-2)}
.v1 .v1-md h2{font-family:var(--titre); font-size:19px; font-weight:700;
  letter-spacing:-.02em; color:var(--text-1); margin:26px 0 10px}
.v1 .v1-md h3{font-family:var(--titre); font-size:15px; font-weight:700;
  color:var(--text-1); margin:22px 0 8px}
.v1 .v1-md h4, .v1 .v1-md h5{font-family:var(--titre); font-size:13px; font-weight:700;
  letter-spacing:.03em; text-transform:uppercase; color:var(--text-2); margin:18px 0 6px}
.v1 .v1-md p{margin:0 0 12px}
.v1 .v1-md .v1-md-l{margin:0 0 14px; padding-left:20px}
.v1 .v1-md .v1-md-l li{margin-bottom:5px}
.v1 .v1-md .v1-md-q{margin:0 0 14px; padding:10px 14px; border-left:3px solid var(--vif);
  background:var(--vif-t); border-radius:0 var(--r-petit) var(--r-petit) 0; color:var(--text-2)}
.v1 .v1-md .v1-md-pre{margin:0 0 14px; padding:12px 14px; overflow-x:auto;
  background:var(--surface-3); border-radius:var(--r-ctrl);
  font-family:var(--nombre); font-size:11.5px; line-height:1.55}
.v1 .v1-md code{font-family:var(--nombre); font-size:.92em;
  background:var(--surface-3); padding:1px 5px; border-radius:4px}
.v1 .v1-md hr{border:none; border-top:1px solid var(--line); margin:22px 0}
.v1 .v1-md .tbl{margin:0 0 16px; overflow-x:auto}
.v1 .v1-md table{width:100%; border-collapse:collapse; font-size:12px}
.v1 .v1-md th{text-align:left; font-size:10.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--text-3); padding:7px 10px;
  border-bottom:1px solid var(--line); white-space:nowrap}
.v1 .v1-md td{padding:7px 10px; border-bottom:1px solid var(--line); vertical-align:top}

/* ══ V1 · CHERCHER UN JEUNE DANS LES QUATRE SOURCES ════════════════════════
   « Il faut que l'outil soit capable d'avoir toutes les données qui existent
   des étudiants : pas seulement le CAFA — TCD, Edsquare, et notre
   hébergement. » Un résultat porte QUI le connaît : 3/4 n'est pas 4/4, et un
   jeune que seule une source connaît mérite qu'on s'en aperçoive. */
.v1 .v1-dos-r{display:grid; gap:2px; text-align:left; width:100%}
.v1 .v1-dos-rn{font-weight:600; color:var(--text-1)}
.v1 .v1-dos-ro{font-size:11.5px; color:var(--text-3)}
.v1 .v1-dos-rs{font-family:var(--nombre); font-size:10.5px; color:var(--vif-ink)}
.v1 .v1-dos-muettes{margin-top:12px; padding-top:10px; border-top:1px solid var(--line)}
.v1 .v1-dos-corps .card-hd .v1-lst-b{margin-left:auto}

/* ══ V1 · LES GESTES D'ÉCRAN ═══════════════════════════════════════════════
   « Je ne veux plus d'ouvrir dans pilotage, on le fait tout ici. » Tous les
   gestes ne portent pas sur une ligne : créer un campus, poser une variante,
   enregistrer les seuils. Ceux-là vivent dans le pied de la plaque. */
.v1 .v1p-gecran{display:flex; flex-wrap:wrap; gap:8px; align-items:flex-start}
.v1 .v1p-gecran > form{flex-basis:100%}
/* Une cellule « Geste » peut porter plusieurs boutons : ils se rangent, ils ne
   se serrent pas. */
.v1 td.v1p-geste{white-space:nowrap}
.v1 td.v1p-geste .v1p-btn + .v1p-btn{margin-left:6px}
.v1 .v1p-mini textarea{
  width:100%; min-height:74px; font:inherit; font-size:var(--t-second);
  border:1px solid var(--line); border-radius:var(--r-ctrl); padding:8px 10px;
  background:#fff; color:var(--text-1); resize:vertical}
.v1 .v1p-mini label{display:block; margin-bottom:8px}
.v1 .v1p-mini input{
  display:block; width:100%; margin-top:3px; font:inherit; font-size:var(--t-second);
  border:1px solid var(--line); border-radius:var(--r-ctrl); padding:7px 10px;
  background:#fff; color:var(--text-1)}
.v1 .v1p-mini input:focus, .v1 .v1p-mini textarea:focus,
.v1 .v1p-mini select:focus{
  outline:none; border-color:var(--vif); box-shadow:0 0 0 2px var(--vif-ring)}
/* ══ LES LISTES ET LES CASES DES ARBITRAGES (02/09/2026) ═══════════════════
   « Vu que Franck a mis des paramètres modifiables je veux des options
   pareilles. » Ses formulaires portent des listes et des cases : un champ de
   texte à la place demanderait de connaître par cœur la valeur qu'une fonction
   accepte. Même dessin que les champs de saisie, pour qu'un formulaire de geste
   reste un seul objet. */
.v1 .v1p-mini select{
  display:block; width:100%; margin-top:3px; font:inherit; font-size:var(--t-second);
  border:1px solid var(--line); border-radius:var(--r-ctrl); padding:7px 10px;
  background:#fff; color:var(--text-1)}
.v1 .v1p-mini select[multiple]{padding:4px; min-height:150px}
/* Une liste que le serveur n'a pas pu lire se voit : elle est grise, et elle le
   dit dans son unique option. */
.v1 .v1p-mini select:disabled{background:var(--surface-2); color:var(--text-2); cursor:not-allowed}
/* Une case n'est pas un champ : son intitulé est à côté d'elle, pas au dessus,
   et elle ne prend pas toute la largeur. */
.v1 .v1p-mini .v1p-case{display:flex; align-items:center; gap:8px; margin-bottom:8px}
.v1 .v1p-mini .v1p-case input{display:inline-block; width:auto; margin:0}

/* ══ V1 · LA BARRE DE SECTIONS ═════════════════════════════════════════════
   « Il faut organiser cela… onglet Organisation, Dossier apprentis. » Quatorze
   onglets de même taille, c'est zéro rangement : on les parcourt au lieu de les
   choisir. Quatre familles, et la barre est celle du V1 — celle du MVP est
   masquée, pas supprimée (app/vues/ est régénéré depuis sa maquette). */
.v1 .v1p-sec{display:flex; flex-wrap:wrap; gap:6px; margin:0 0 22px;
  padding-bottom:14px; border-bottom:1px solid var(--line)}
.v1 .v1p-sec-b{
  font:inherit; font-size:var(--t-second); font-weight:600; color:var(--text-2);
  background:var(--surface-2); border:1px solid transparent; cursor:pointer;
  border-radius:999px; padding:8px 16px; transition:background .15s var(--nav-courbe)}
.v1 .v1p-sec-b:hover{background:var(--vif-t); color:var(--vif-ink)}
.v1 .v1p-sec-b:focus-visible{outline:2px solid var(--vif-ink); outline-offset:2px}
.v1 .v1p-sec-b.on{background:var(--vif-ink); color:#fff}
/* Le titre de la section devient inutile au dessus de sa propre barre : la
   pastille active le dit déjà, et deux fois le même mot fait douter. */
.v1 .v1p-sec ~ .v1p-bloc .v1p-titre,
.v1 .v1p-sec + * .v1p-titre{border-top:none; padding-top:0; margin-top:0}
.v1 .v1p-sec-b{display:inline-flex; align-items:center; gap:8px}
.v1 .v1p-sec-b svg{width:17px; height:17px; flex:none; opacity:.85}
.v1 .v1p-sec-b.on svg{opacity:1}

/* ══ V1 · LES PETITES ICÔNES DES GESTES ════════════════════════════════════
   « Aussi les petites icônes supprimé, ajouté et les étapes à cocher. » Une
   rangée de boutons de même taille et de même couleur se lit mot par mot ;
   l'icône permet de trouver « Supprimer » sans lire.
   ⚠️ Deux couleurs, pas sept : le corail pour ce qui ENLÈVE, l'encre du bouton
   pour tout le reste. Un arc-en-ciel de boutons ne dit rien. */
.v1 .v1p-btn{display:inline-flex; align-items:center; gap:6px}
.v1 .v1p-btn svg{width:14px; height:14px; flex:none; opacity:.7}
.v1 .v1p-btn:hover svg{opacity:1}
/* ⚠️ LE BOUTON QUI ENLÈVE CHANGE DE FORME, PAS SEULEMENT D'ICÔNE. Vu à
   l'écran : `.v1p-btn` est une pastille VERTE PLEINE à texte blanc — une icône
   corail posée dessus est illisible, et « Supprimer » se dessinait exactement
   comme « Déplacer ». Huit lignes, huit suppressions à un clic, aucune
   distinction.
   ⚠️ Et il ne devient pas rouge PLEIN pour autant : huit pastilles rouges dans
   un tableau feraient crier l'écran, et l'on cesserait de les voir. Il passe en
   contour — fond clair, encre et bordure corail. Différent, et prudent. */
.v1 .v1p-btn-ko{background:#fff; color:var(--alr); box-shadow:inset 0 0 0 1px var(--alr)}
.v1 .v1p-btn-ko svg{color:var(--alr); opacity:.85}
.v1 .v1p-btn-ko:hover{background:var(--alr-bg); color:var(--alr)}
.v1 .v1p-btn-ko:hover svg{opacity:1}
.v1 .v1p-btn-ko:focus-visible{box-shadow:0 0 0 2px var(--alr)}
.v1 .v1p-sec-b svg{opacity:.85}
/* Ce qui reste à porter : une dette qu'on lit, pas une porte qu'on pousse. */
.v1 .v1p-reste{display:block; color:var(--text-3); font-style:italic}

/* ═══════════════════════════════════════════════════════════════════════════
   02/09/2026 AU SOIR — LISIBILITÉ, CARTES, EXPORTS, DOSSIER, ÉTAPES
   Antonio : « pour les indicateurs et les chiffres il faut que ça soit bien
   visible, plus facile à lire… le "?" toujours à droite, à l'extrémité, avec
   une animation qui grandit… ça se met en carte, pas en bandeau bleu ou
   rouge… sur les contrats du mois il faut que le chiffre du mois de l'année
   précédente s'affiche, et la rupture, comme Franck l'a mis ».
   Référence de dessin : les grands nombres des tableaux de bord relevés sur
   Mobbin (chiffre en très grand, l'écart en pastille colorée dessous, le
   libellé en capitales au-dessus). Rien d'autre ne bouge : ni la grille, ni
   la place des plaques.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 · LE CHIFFRE, EN GRAND. 30 px se lisait ; 38 px se lit de loin, et c'est
   la seule chose qu'on vient chercher sur une tuile. Le libellé reste en
   capitales fines au-dessus, la note en petit dessous : trois crans, pas
   trois textes de la même taille. */
.v1 .v1p-t{padding:16px 18px 14px}
.v1 .v1p-t .v1p-k{font-size:11px; letter-spacing:.1em}
.v1 .v1p-v.v1p-lu{font-size:38px; font-weight:700; letter-spacing:-.03em; line-height:1.05; margin:8px 0 4px}

/* L'écart avec la même période de l'an dernier, sous le chiffre — comme le
   tableau de bord de Franck (« +3 (+27 %) vs août 2025 »). Le vert dit
   « mieux », le corail « moins bien », et « mieux » dépend de la MESURE : une
   rupture de moins est un mieux (`compare.bon` dans ECRANS). Quand N-1 n'est
   pas mesuré, la pastille le dit en toutes lettres — jamais « 0 % ». */
.v1 .v1p-delta{display:inline-flex; align-items:center; gap:5px; margin:2px 0 8px;
  padding:3px 10px; border-radius:999px; font:600 12px/1.3 var(--texte);
  font-variant-numeric:tabular-nums; background:var(--surface-3,#EEF3EF); color:var(--text-2)}
.v1 .v1p-delta b{font-weight:800}
.v1 .v1p-delta.bon{background:var(--ok-bg,#E4F5EC); color:var(--ok,#1E6644)}
.v1 .v1p-delta.mauvais{background:var(--alr-bg,#FBE9E4); color:var(--alr,#B8432A)}
.v1 .v1p-delta.flat{background:var(--surface-3,#EEF3EF); color:var(--text-2)}
.v1 .v1p-delta.nm{background:transparent; color:var(--text-3); font-style:italic; padding-left:0}
.v1 .v1p-t[data-ton="mesure"] .v1p-delta.bon{background:rgba(255,255,255,.6); color:#1E6644}
.v1 .v1p-t[data-ton="mesure"] .v1p-delta.mauvais{background:rgba(255,255,255,.6); color:#B8432A}
.v1 .v1p-t[data-ton="mesure"] .v1p-delta.nm{color:var(--t-jaune-i)}

/* 2 · LE « ? » D'AIDE : à l'extrémité droite de la barre, et il respire. Il
   était collé au dernier onglet, à gauche : on ne le voyait pas. Il grandit
   doucement (un cycle de 2,6 s), s'arrête au survol et quand l'aide est
   ouverte — et ne bouge pas du tout pour qui a demandé moins de mouvement. */
.v1 .modbar .modx.aidx{margin-left:auto; order:99; width:30px; height:30px; font-size:16px;
  border:1px solid var(--vif,#3bae79); color:var(--vif-ink,#1E6644); background:#fff;
  box-shadow:0 0 0 0 rgba(59,174,121,.35); animation:v1-aide-grandit 2.6s ease-in-out infinite;
  transition:transform .2s}
.v1 .modbar .modx.aidx:hover{transform:scale(1.18); animation-play-state:paused; color:var(--vif-ink); border-color:var(--vif)}
.v1 .modbar .modx.aidx[aria-expanded="true"]{animation:none; background:var(--vif); color:#fff}
@keyframes v1-aide-grandit{
  0%,100%{transform:scale(1); box-shadow:0 0 0 0 rgba(59,174,121,.35)}
  50%{transform:scale(1.14); box-shadow:0 0 0 9px rgba(59,174,121,0)}}
@media (prefers-reduced-motion:reduce){
  .v1 .modbar .modx.aidx{animation:none}
  .v1 .modbar .modx.aidx:hover{transform:none}}

/* 3 · LES MESSAGES SONT DES CARTES, PLUS DES BANDEAUX. Un aplat bleu ou
   rouge sur toute la largeur crie ; une carte blanche avec une tuile d'icône
   colorée dit la même chose, et se range avec les autres plaques. La couleur
   ne quitte pas l'écran : elle tient dans la tuile, où elle dit le niveau. */
.v1 .msg, .v1 .ro-bar, .v1 .msg.inf.aide.on{background:#fff; border:1px solid var(--line);
  border-radius:var(--r-plaque,14px); box-shadow:var(--relief); padding:14px 16px 14px 14px;
  gap:12px; align-items:flex-start; color:var(--text-2)}
.v1 .msg .mi, .v1 .ro-bar .mi{width:32px; height:32px; border-radius:10px; display:grid;
  place-items:center; margin-top:0; flex:none; background:var(--surface-2); color:var(--text-3)}
.v1 .msg .mi svg, .v1 .ro-bar .mi svg{width:16px; height:16px}
.v1 .msg.inf .mi, .v1 .ro-bar .mi{background:var(--inf-bg); color:var(--inf)}
.v1 .msg.att .mi{background:var(--att-bg); color:var(--att)}
.v1 .msg.alr .mi{background:var(--alr-bg); color:var(--alr)}
.v1 .msg.ok .mi{background:var(--ok-bg); color:var(--ok)}
.v1 .msg b, .v1 .ro-bar b{color:var(--text-1)}

/* 4 · LES FILTRES, COMPACTS. Les explications sous chaque liste (ce que veut
   dire « exercice », d'où viennent les options) se replient derrière
   « Comprendre les filtres » : on les lit une fois, pas à chaque ouverture. */
/* ⚠️ `.v1 .card > .card-hd .card-sub` pèse 0,4,0 plus haut dans cette feuille :
   la règle qui replie doit peser autant, sinon elle perd sans un mot. Mesuré
   dans le navigateur avant d'écrire (la première version pesait 0,3,0 et le
   sous-titre restait affiché). */
.v1 .v1p-filtres .v1p-f .v1p-n, .v1 .v1p-filtres .v1p-fetat,
.v1 .card.v1p-filtres > .card-hd .card-sub{display:none}
.v1 .v1p-filtres.v1-aide-ouverte .v1p-f .v1p-n,
.v1 .v1p-filtres.v1-aide-ouverte .v1p-fetat{display:block}
.v1 .card.v1p-filtres.v1-aide-ouverte > .card-hd .card-sub{display:-webkit-box}
.v1 .v1p-filtres .v1p-f{padding:10px 13px}
.v1 .v1p-filtres .v1p-fs{gap:10px; grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.v1 .v1p-filtres .v1p-actions{margin-top:12px}

/* 5 · LE MENU D'EXPORT. Un bouton, quatre formats ; le menu se ferme au clic
   dehors. Les boutons « CSV » et « Excel » d'un tableau sont des mini-boutons
   dans son pied, à droite de la note d'âge. */
.v1 .v1p-export{position:relative; margin-left:auto}
.v1 .v1p-export-menu{position:absolute; right:0; top:calc(100% + 6px); z-index:30; min-width:320px;
  display:flex; flex-direction:column; background:#fff; border:1px solid var(--line);
  border-radius:12px; box-shadow:var(--relief); padding:6px}
.v1 .v1p-export-menu[hidden]{display:none}
.v1 .v1p-export-menu button{text-align:left; border:0; background:none; font:500 13px/1.35 var(--texte);
  color:var(--text-1); padding:9px 11px; border-radius:8px; cursor:pointer}
.v1 .v1p-export-menu button:hover, .v1 .v1p-export-menu button:focus-visible{background:var(--vif-t); outline:none}
.v1 .v1p-btn-mini{padding:5px 9px; font-size:11.5px}
.v1 .v1p-exp{display:inline-flex; gap:6px; margin-left:auto}
.v1 .v1p-pied:has(.v1p-exp){display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px}

/* 6 · L'ÉTAPE D'UN COURRIER : cinq pastilles, brouillon → à valider → signé
   → déposé → envoyé. Les faites en vert plein, l'étape en cours cerclée, le
   reste vide. Le mot reste à côté : les pastilles se lisent d'un coup d'œil,
   le mot se lit à voix haute. */
.v1 .v1p-etapes{display:inline-flex; align-items:center; gap:3px; white-space:nowrap}
.v1 .v1p-etapes i{display:inline-block; width:9px; height:9px; border-radius:50%;
  background:var(--surface-3,#EEF3EF); border:1px solid var(--line-2)}
.v1 .v1p-etapes i.fait{background:var(--vif); border-color:var(--vif)}
.v1 .v1p-etapes i.ici{background:#fff; border:2px solid var(--vif-ink,#1E6644); width:11px; height:11px}
.v1 .v1p-etapes span{margin-left:6px; font-size:12px; color:var(--text-2)}

/* 7 · LE TIROIR DU DOSSIER : « Exporter le dossier (PDF) » à côté de Fermer,
   et les quatre sources sous le dossier principal. */
/* ⚠️ 18 px, ET C'EST ICI QUE ÇA SE RÈGLE. Une première tentative avait posé le
   gap plus haut dans la feuille : cette règle-ci, plus bas, le reprenait à 8 px
   — mesuré après dépôt, l'écart n'avait pas bougé d'un pixel. Deux déclarations
   pour une même propriété, c'est la dernière qui gagne, et c'est celle qu'on
   n'avait pas vue. */
.v1 .v1-dos-btns{display:flex; gap:18px; align-self:start; align-items:center}
.v1 .v1-dos-export{flex:none}
.v1 .v1-dos-sources{margin-top:26px}
.v1 .v1-dos-sources .v1p-titre{margin-top:0; padding-top:0; border-top:0}

/* Les raccourcis Direction→Administration ont été retirés le 03/09 : plus
   de redirection (Antonio). Le paramétrage se règle dans Administration. */
.v1 .v1p-signal{flex-basis:100%; margin-top:8px}

/* 9 · « JE N'AI PAS PU LIRE » EST UNE CARTE, PAS UN BANDEAU ROUGE. Antonio,
   02/09 : « pas en mode bandeau bleu ou rouge, mais en carte ». L'aplat rose
   pleine largeur criait sur chaque plaque muette ; la carte blanche garde le
   corail dans une tuile et dans les mots en gras — on voit toujours que la
   source n'a pas répondu, sans que l'écran entier vire au rouge. */
.v1 .v1p-muet{position:relative; background:#fff; color:var(--text-2); border:1px solid var(--line);
  border-radius:var(--r-plaque,14px); box-shadow:var(--relief); padding:14px 16px 14px 58px; line-height:1.5}
.v1 .v1p-muet::before{content:'!'; position:absolute; left:14px; top:13px; width:32px; height:32px;
  border-radius:10px; background:var(--alr-bg,#FBE9E4); color:var(--alr,#B8432A);
  font:800 16px/32px var(--titre); text-align:center}
.v1 .v1p-muet b{color:var(--alr,#B8432A)}
.v1 .v1p-fetat.v1p-muet, .v1 .v1p-signal{font-size:13px}

/* ── 03/09/2026 — LA PHOTO DU JEUNE ET LE VOLET QUALIOPI DU DOSSIER ──────────
   La vraie photo (photo.php, derrière la session) se pose PAR-DESSUS les
   initiales. Un 404 les laisse : jamais un rond vide. */
.v1 .v1-dos-photo{position:relative; overflow:hidden}
.v1 .v1-dos-photo-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover}
.v1 .v1-dos-photo.a-photo{color:transparent}   /* la photo couvre : on tait les initiales */
.v1 .v1-dos-qualiopi{margin-top:22px}
.v1 .v1-dos-qualiopi .v1p-titre{margin-top:0; padding-top:0; border-top:0}
.v1 .v1-dos-photo-dep{margin-top:12px}
/* Le lien qui OUVRE un document (questionnaire sur l'hébergement, archive
   pCloud) : dessiné comme un lien, mais c'est un bouton — il ouvre un PDF dans
   un onglet, jamais une navigation de l'outil. */
.v1 .v1p-doc{border:0; background:none; padding:0; font:inherit; color:var(--vif-ink,#1E6644);
  font-weight:600; text-decoration:underline; text-underline-offset:2px; cursor:pointer}
.v1 .v1p-doc:hover{color:var(--vif,#3bae79)}
.v1 .v1p-doc:focus-visible{outline:2px solid var(--vif,#3bae79); outline-offset:2px; border-radius:3px}

/* ═══════════════════════════════════════════════════════════════════════════
   03/09/2026 — TOUTES LES BARRES DE NAVIGATION EN PILULES (sauf le rail)
   Antonio, devant la barre « Organisation · Dossier · Documentation · Piste
   d'audit · Création de document » : « je veux que tous les designs des barres
   de navigation (sauf side navigation) soient comme celle-là ». C'est le style
   `.v1p-sec-b` : pilule arrondie, l'active en encre verte pleine.
   Une seule famille de bouton de navigation, à trois étages (applications du
   haut, onglets d'écran, sections) : on ne les distingue plus par leur forme
   mais par leur place.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 · LA BARRE D'APPLICATIONS DU HAUT (`.modbar` / `.modx`). Le soulignement de
   l'actif laisse place à la pilule. ⚠️ SAUF le « ? » d'aide (`.aidx`), qui garde
   son rond — il n'est pas un onglet. */
.v1 .modbar{gap:8px; padding:12px 24px; border-top:0; align-items:center}
.v1 .modbar .fam{border-right:1px solid var(--line); color:var(--text-1)}
.v1 .modbar .modx:not(.aidx){
  min-height:0; padding:8px 16px; border-radius:999px; border:1px solid transparent;
  background:var(--surface-2); color:var(--text-2); font-size:var(--t-second); font-weight:600;
  transition:background .15s var(--nav-courbe), color .15s var(--nav-courbe)}
.v1 .modbar .modx:not(.aidx):hover{background:var(--vif-t); color:var(--vif-ink)}
.v1 .modbar .modx:not(.aidx).on,
.v1 .modbar .modx:not(.aidx).on:hover{background:var(--vif-ink); color:#fff; font-weight:600}
.v1 .modbar .modx:not(.aidx).on::after{display:none}   /* plus de trait sous l'actif */

/* 2 · LES ONGLETS D'ÉCRAN (`.tabx`). Ils quittaient le fond creux « segment »
   pour la MÊME pilule que les sections. Plus de double-fond, plus d'ombre :
   une pilule pleine dit l'actif, comme dans la barre de référence. */
.v1 .view.on > .tabx-bar,
.v1 .v1-groupe > .v1-ongs{
  background:none !important; padding:0; gap:6px; flex-wrap:wrap; overflow:visible;
  border-radius:0}
.v1 .view.on > .tabx-bar{margin:0 0 22px}
.v1 .view.on > .tabx-bar > .tabx,
.v1 .v1-groupe > .v1-ongs > .tabx{
  height:auto; padding:8px 16px; border-radius:999px; border:1px solid transparent;
  background:var(--surface-2); color:var(--text-2);
  font-size:var(--t-second); font-weight:600; box-shadow:none;
  transition:background .15s var(--nav-courbe), color .15s var(--nav-courbe)}
.v1 .view.on > .tabx-bar > .tabx:hover,
.v1 .v1-groupe > .v1-ongs > .tabx:hover{background:var(--vif-t); color:var(--vif-ink)}
.v1 .view.on > .tabx-bar > .tabx.on,
.v1 .v1-groupe > .v1-ongs > .tabx.on{
  background:var(--vif-ink); color:#fff; font-weight:600; box-shadow:none}

/* 3 · UN PEU D'ESPACE — LE RAIL ET LE HAUT DES PAGES (Antonio, 03/09) :
   « je veux un peu d'espace sur le side navigation et le début des mises en
   pages ». Le rail respire (plus de marge en tête, un cran entre les univers),
   et le contenu ne colle plus à la barre du haut. */
.v1 .rail{padding:18px 8px 12px}
.v1 #nav{gap:6px}
.v1 .content{padding-top:32px}


/* ═══════════════════════════════════════════════════════════════════════════
   03/09/2026 — LES ÉCRITURES NE SE CHEVAUCHENT PLUS, LES BOUTONS SONT CADRÉS,
   LA COULEUR DIT LE GESTE, LES ICÔNES SONT DES INDICATEURS
   Antonio : « évite les écritures qui se superposent… sur les px des boutons
   et des textes à l'intérieur il faut bien les cadrer, centrés et alignés…
   couleur des boutons : fais comme Edsquare, différentes couleurs, mais
   respecte la ligne graphique : ajouter vert, supprimer rouge, modifier bleu…
   sur les icônes, agrandis encore pour être de vrais indicateurs ».
   Tout est posé ICI, en fin de feuille, pour peser sur ce qui précède sans
   le réécrire : chaque règle plus haut reste lisible telle qu'elle a été
   décidée, celle-ci dit ce qui change et pourquoi.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 · LA TUILE NE SUPERPOSE PLUS RIEN. Vu à l'écran (Pilotage, tuile
   « Contrats ») : « Voir la liste » était posé en ABSOLU au bas de la tuile,
   et la pastille d'écart, pliée sur deux lignes, venait s'écrire dessus. Tout
   revient dans le flux : la tuile est une colonne, le lien en est le dernier
   élément et descend au bas de lui-même (`margin-top:auto`). Une pastille
   plus haute pousse le lien, elle ne le couvre plus. */
.v1 .v1p-t{display:flex; flex-direction:column; align-items:flex-start; min-width:0}
.v1 .v1p-t-ouvre{padding-bottom:14px}
.v1 .v1p-t-ouv{position:static; left:auto; bottom:auto; margin-top:auto; padding-top:10px; white-space:nowrap}
.v1 .v1p-t .v1p-k{white-space:normal; line-height:1.3}
.v1 .v1p-v.v1p-lu{margin:6px 0 6px}
.v1 .v1p-delta{display:inline-grid; grid-auto-flow:row; gap:1px; justify-items:start; text-align:left;
  line-height:1.25; padding:5px 11px; margin:0 0 6px; max-width:100%; box-sizing:border-box}
.v1 .v1p-delta b{white-space:nowrap; font-size:12.5px}
.v1 .v1p-delta small{font-size:11px; font-weight:600; opacity:.85; white-space:nowrap}
.v1 .v1p-delta.nm{display:inline-block}
.v1 .v1p-t .v1p-n{margin-top:2px}

/* 2 · LES BOUTONS ONT UNE HAUTEUR, ET LE TEXTE EST AU MILIEU. Mesuré dans le
   navigateur : 28 px de haut par la seule grâce du padding, un « CSV » monté à
   46 px parce que son conteneur l'étirait, « Exporter… » un cran plus haut que
   ses voisins. Chaque bouton mesure désormais 32 px (26 en mini), se centre
   lui-même dans sa rangée, et son texte est centré dedans, icône comprise. */
.v1 .v1p-btn{height:var(--h-ctrl); min-height:var(--h-ctrl); box-sizing:border-box; padding:0 13px;
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  font:600 12.5px/1 var(--texte); text-align:center; white-space:nowrap;
  vertical-align:middle; align-self:center; border-radius:10px}
.v1 .v1p-btn > span{display:inline-block; line-height:1}
/* ⚠️ LE RANG « MINI » A DISPARU LE 04/09/2026 : il valait 26 px et voisinait des
   boutons de 32 dans le même pied de carte (« CSV » et « Excel » au-dessus de
   « Créer un campus »). Il garde son coin plus doux, il n'a plus sa hauteur. */
.v1 .v1p-btn-mini{height:var(--h-ctrl); min-height:var(--h-ctrl); padding:0 10px; font-size:11.5px; border-radius:8px}
.v1 .v1p-lien{height:var(--h-ctrl); box-sizing:border-box; display:inline-flex; align-items:center; padding:0 12px}
.v1 .v1p-actions, .v1 .v1p-mini-b, .v1 .v1p-exp, .v1 .v1-dos-btns{align-items:center}
.v1 .v1p-export{display:inline-flex; align-items:center}
.v1 .v1p-pied:has(.v1p-exp){align-items:center}
.v1 td.v1p-geste{vertical-align:middle}
.v1 td.v1p-geste .v1p-btn + .v1p-btn{margin-left:8px}
.v1 .tabx, .v1 .v1p-sec-b{display:inline-flex; align-items:center; justify-content:center; line-height:1}

/* 3 · LA COULEUR DIT LE GESTE — QUATRE TONS (Antonio, 03/09/2026, « comme
   Edsquare »). Vert : ce qui AJOUTE ou valide. Bleu : ce qui MODIFIE. Rouge :
   ce qui ENLÈVE — en plein, comme le bouton « danger » d'Edsquare, parce que
   c'est le seul geste qu'on ne rattrape pas. Le reste (lire, ouvrir, déplacer,
   exporter) garde un fond clair et une encre sombre : la couleur n'est posée
   que là où elle veut dire quelque chose, sinon on ne la lit plus. Les teintes
   sont celles de la ligne SKHUB — le vert de la marque, le bleu d'information
   (`--inf`), le corail des alertes (`--alr`) — toutes lisibles en blanc dessus.
   ⚠️ La règle « deux couleurs, pas sept » posée le 02/09 est caduque : elle
   laissait « Ajouter » et « Déplacer » du même vert, et « Supprimer » en simple
   contour. */
/* ═══ LE QUATRIÈME TON : CE QUI SORT DE LA MAISON (04/09/2026) ═══════════
   Antonio : « sur le logo de SKHUB il y a une couleur violet, est-ce que tu
   pourrais utiliser des boutons en violet aussi, pas beaucoup, mais il faut
   qu'on hiérarchise les couleurs selon les boutons, les couleurs et les
   fonctions ».
   ⚠️ MESURÉ AVANT DE POSER : le logo N'A PAS de violet. Les trois fichiers du
   dépôt portent le jaune #FFFE78, le vert #3DB680, le noir #0B0B0B et le vert
   foncé #1D3B0B — et sur 1 156 images scannées, le violet n'apparaît que dans
   quatre fichiers, dont aucun logo (celui d'OPCO 2i, deux photos d'avatar,
   une photo de profil). Le violet posé ici est donc celui du SYSTÈME, pas
   celui de la marque : `#5B36B5`, déjà présent plus haut sous le nom de
   « violet encre » (nature `matrice`). ⚠️ Cette nature est utilisée ZÉRO fois
   sur les 74 plaques du V1 — la teinte était libre en pratique.
   ── CE QU'IL VEUT DIRE, ET POURQUOI IL FALLAIT LE DÉCIDER ────────────────
   La règle d'hier posait trois tons et refusait explicitement d'en poser un
   quatrième : « le reste (lire, ouvrir, déplacer, exporter) garde un fond
   clair — la couleur n'est posée que là où elle veut dire quelque chose,
   sinon on ne la lit plus ». Une couleur de plus n'est donc légitime que si
   elle nomme une FAMILLE de gestes, et il en restait une, la seule dont un
   clic de travers a des conséquences DEHORS, chez un jeune ou une
   entreprise : ce qui part. Envoyer, adresser, relancer, proposer, publier.
   Ce n'est ni un ajout, ni une modification, ni une suppression — et c'était
   habillé comme « lire ».
   ⚠️ « PAS BEAUCOUP » EST UNE MESURE, PAS UNE INTENTION : quatre boutons dans
   toute l'application (« Envoyer le placement », « Envoyer les 4 suivantes »,
   « Adresser la demande », « Relancer »). Les 72 libellés de gestes des
   plaques du V1 n'en portent AUCUN — c'est la règle n°3 en peinture : la
   machine prépare, elle n'envoie pas. */
.v1{--v1-vert:#2E9C68; --v1-vert-f:#247E53; --v1-bleu:#1A5497; --v1-bleu-f:#143F73;
  --v1-rouge:#C9341B; --v1-rouge-f:#A52A15;
  --v1-violet:#5B36B5; --v1-violet-f:#4A2B96}
.v1 .v1p-btn{background:#E6EEE9; color:#1B3327}
.v1 .v1p-btn:hover{background:#D9E5DE}
.v1 .v1p-btn.sec{background:#EEF3EF; color:var(--text-2)}
.v1 .v1p-btn.sec:hover{background:#E3EBE6}
.v1 .v1p-btn svg{opacity:.9; color:currentColor}
.v1 .v1p-btn-ajout, .v1 .v1p-btn-ok, .v1 .v1p-mini-b button[type=submit]{background:var(--v1-vert); color:#fff}
.v1 .v1p-btn-ajout:hover, .v1 .v1p-btn-ok:hover, .v1 .v1p-mini-b button[type=submit]:hover{background:var(--v1-vert-f)}
.v1 .v1p-btn-modif{background:var(--v1-bleu); color:#fff}
.v1 .v1p-btn-modif:hover{background:var(--v1-bleu-f)}
.v1 .v1p-btn-ko{background:var(--v1-rouge); color:#fff; box-shadow:none}
.v1 .v1p-btn-ko svg{color:#fff; opacity:.95}
.v1 .v1p-btn-ko:hover{background:var(--v1-rouge-f); color:#fff}
.v1 .v1p-btn-ko:hover svg{opacity:1}
.v1 .v1p-btn-ajout svg, .v1 .v1p-btn-ok svg, .v1 .v1p-btn-modif svg{opacity:.95}
.v1 .v1p-btn:focus-visible{box-shadow:0 0 0 2px #fff, 0 0 0 4px var(--vif-ink)}
.v1 .v1p-btn-ko:focus-visible{box-shadow:0 0 0 2px #fff, 0 0 0 4px var(--v1-rouge)}
.v1 .v1p-btn-modif:focus-visible{box-shadow:0 0 0 2px #fff, 0 0 0 4px var(--v1-bleu)}
/* Le ton « envoi », des deux côtés : sur une plaque du V1 (`v1p-btn-envoi`,
   posé par `boutonDeGeste()` dès qu'un geste s'appelle « Envoyer… ») et sur un
   bouton natif du MVP (`btn-envoi`, posé dans la maquette sur les quatre
   boutons qui partent vraiment). Un seul ton, deux balisages — sinon la même
   idée aurait deux violets. */
.v1 .v1p-btn-envoi, .v1 .btn.btn-envoi{background:var(--v1-violet); color:#fff; border-color:var(--v1-violet)}
.v1 .v1p-btn-envoi:hover, .v1 .btn.btn-envoi:hover{background:var(--v1-violet-f); border-color:var(--v1-violet-f); color:#fff}
.v1 .v1p-btn-envoi svg, .v1 .btn.btn-envoi svg{color:#fff; opacity:.95}
.v1 .v1p-btn-envoi:focus-visible, .v1 .btn.btn-envoi:focus-visible{box-shadow:0 0 0 2px #fff, 0 0 0 4px var(--v1-violet)}

/* ⚠️ LA BARRE D'ONGLETS DU MVP SE CACHE PAR LA VUE, PAS PAR LE NŒUD (05/09/2026).
   Vu à l'écran après le premier dépôt : les deux rangées côte à côte, la nôtre
   avec ses icônes et la sienne juste dessous, mêmes mots dans un autre ordre.
   Le `display:none` en ligne était pourtant posé — mais le MVP REMPLACE le
   nœud à la réécriture de l'écran, et notre style partait avec l'ancien. La
   marque est donc sur la VUE, qui ne se recrée pas, et la règle vaut pour
   toute barre qu'elle contiendra ensuite. `!important` parce que la feuille du
   MVP pose un `display` explicite sur `.tabx-bar`. */
.v1 .view[data-v1ongs] .tabx-bar{display:none !important}

/* 4 · LES ICÔNES SONT DES INDICATEURS. 14 px dans un bouton et 23 px dans une
   tuile se lisaient comme des points ; on passe à 18 px dans les boutons,
   20 px dans les pastilles de section, 26 px dans les tuiles de plaque et le
   rail. La tuile grandit avec (44 px) pour que le signe garde de l'air. */
.v1 .v1p-btn svg{width:18px; height:18px; margin-left:-2px}
.v1 .v1p-btn-mini svg{width:15px; height:15px}
.v1 .v1p-sec-b svg{width:20px; height:20px}
.v1 .tuile{width:44px; height:44px; display:grid; place-items:center}
.v1 .tuile svg{width:26px; height:26px}
.v1 .card-hd .mi, .v1 .rk-hd .mi{width:44px; height:44px; display:grid; place-items:center; flex:none}
.v1 .card-hd .mi svg, .v1 .rk-hd .mi svg{width:26px; height:26px}
.v1 .ict{width:36px; height:36px}
.v1 .ict svg{width:24px; height:24px}
.v1 .rail svg{width:26px; height:26px}
.v1 .rail .rail-install svg{width:21px; height:21px}
.v1 .msg .mi, .v1 .ro-bar .mi{width:38px; height:38px}
.v1 .msg .mi svg, .v1 .ro-bar .mi svg{width:20px; height:20px}

/* 5 · LE RAIL N'AMPUTE PLUS « ADMINISTRATION ». À 11 px le mot dépassait les
   76 px du rail et perdait son « n ». Un cran plus petit, et le mot a le droit
   de se couper proprement s'il ne tient toujours pas. */
.v1 .rail .uni .lbl{font-size:9.5px; letter-spacing:-.02em; line-height:1.2; white-space:normal;
  overflow-wrap:normal; max-width:100%}
/* Mesuré dans le navigateur : à 10 px, « Administration » faisait 68 px pour
   68 px de place, et se coupait « Administratio / n ». À 9,5 px et -.02em il
   fait 63 px : il tient, et « Comptes rendus » garde sa coupure au blanc. */

/* 6 · LA RANGÉE DES ACTIONS EST UNE RANGÉE. Mesuré : « Comprendre les
   filtres » portait `margin-top:24px` et ses voisins `margin-bottom:8px`,
   hérités d'un dessin plus haut — trois boutons à trois hauteurs. Dans une
   rangée d'actions, un bouton n'a pas de marge à lui : la rangée espace. */
.v1 .v1p-actions > .v1p-btn, .v1 .v1p-actions > .v1p-lien, .v1 .v1p-actions > .v1p-export{margin:0}
.v1 .v1p-actions > .v1p-export{margin-left:auto}
/* ⚠️ LA CAUSE : `.sec` est AUSSI une classe de l'application — le titre de
   section de l'accueil (`unitools.css` : `.sec{display:flex;
   align-items:baseline; margin:24px 0 8px}`). Un bouton `v1p-btn sec` en
   héritait : c'est lui qui montait de 24 px, et « CSV » qui s'étirait à 46 px.
   Le bouton secondaire redit donc tout ce que le titre de section lui prend. */
.v1 .v1p-btn.sec{display:inline-flex; align-items:center; justify-content:center; gap:7px; margin:0}


/* ═══ 03/09/2026 · LOT 1 — LA BARRE D'APPLICATION (cahier d'exécution § 3) ═══
   Sur une vue qui porte plusieurs applications du V1 (Qualité : « Qualité et
   conformité » et « Organisation pédagogique »), la barre du bas ne montre
   que les sections de l'application ouverte. Elle REMPLACE, à l'affichage,
   la barre d'onglets du MVP, ses rangées de familles et les barres de
   sections posées dans chaque panneau — tout cela continue d'exister et de
   porter l'état, on ne le dessine plus deux fois. */
.v1 .view.v1-appbar > .tabx-bar,
.v1 .view.v1-appbar > .v1-groupes,
.v1 .view.v1-appbar > .tabp .v1p-sec{display:none !important}
.v1 .v1p-appbar{display:flex; flex-wrap:wrap; gap:6px; margin:0 0 22px;
  position:sticky; top:0; z-index:3; padding:8px 0; background:var(--fond, #fff)}
.v1 .v1p-appbar .v1p-sec-b{display:inline-flex; align-items:center; gap:8px}

/* Lot 3 · la colonne de sélection du bloc à coller (CAFA).
   ⚠️ SCOPÉE AUX CELLULES (03/09/2026, vu en ligne) : `.v1p-sel` est AUSSI la
   classe des champs de filtre (`champDeFiltre()` : les dates et les listes de
   toutes les plaques). Écrite sur la classe seule, cette règle réduisait tous
   les filtres de plaque à 34 px — deux dates « Du / Au » réduites à leur icône
   sur Journées, Piste d'audit, Courrier. Même famille que `.sec` : une classe
   qui vit dans deux mondes. */
.v1 td.v1p-sel, .v1 th.v1p-sel{width:34px; text-align:center}
.v1 td.v1p-sel input, .v1 th.v1p-sel input{width:16px; height:16px; accent-color:#2E9C68; cursor:pointer}

/* ═══ 03/09/2026 · LES JOURNÉES DE COURS : LA FICHE SE SIGNE DANS LA LIGNE ═══
   L'univers Intervenants de Franck, porté 1 à 1. Son `journee.php` s'ouvre
   sous la ligne de la journée (une ligne dépliée, `tr.v1p-jour-tr`), avec ses
   six blocs ; sa `fiche.php` de même, en lecture. Les valeurs reprennent
   celles de son `app.css` (grille de vigilance, cartes-stat) sous `.v1`. */
.v1 tr.v1p-jour-tr > td{padding:0 !important; background:#F6FAF7; border-top:2px solid #CFE3D6}
.v1 .v1p-jour{padding:16px 18px 18px; display:flex; flex-direction:column; gap:12px}
.v1 .v1p-jour .v1p-titre{margin:6px 0 0}
.v1 .v1p-jour-hd{display:grid; grid-template-columns:repeat(auto-fit, minmax(170px, 1fr)); gap:10px}
.v1 .v1p-jour-hd > div{background:#fff; border:1px solid var(--line); border-radius:10px; padding:10px 12px}
.v1 .v1p-jour-hd .k{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.4px; color:#5B6B62}
.v1 .v1p-jour-hd .v{font-size:18px; font-weight:800; color:#12261B; margin-top:2px}
.v1 .v1p-vig{display:grid; grid-template-columns:repeat(auto-fit, minmax(260px, 1fr)); gap:12px}
.v1 .v1p-vig .pt{background:#fff; border:1px solid var(--line); border-radius:10px; padding:10px 12px}
.v1 .v1p-vig .pt-t{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.4px; color:#4B5B52; margin-bottom:6px}
.v1 .v1p-vig ul{margin:0; padding-left:18px; font-size:13px; line-height:1.55}
.v1 .v1p-vig .vide{font-size:13px; color:#8A958F; font-style:italic}
.v1 .v1p-jour-f{display:flex; flex-direction:column; gap:10px}
.v1 .v1p-jour textarea{width:100%; box-sizing:border-box; font:13px/1.45 var(--texte); border:1px solid var(--line); border-radius:8px; padding:8px 10px; background:#fff}
.v1 .v1p-jour table input[type=text]{width:100%; box-sizing:border-box; font:13px var(--texte); border:1px solid var(--line); border-radius:8px; padding:5px 8px; min-width:200px}
.v1 .v1p-jour th.c, .v1 .v1p-jour td.c{text-align:center; white-space:nowrap}
.v1 .v1p-jour input[type=radio]{width:16px; height:16px; accent-color:#2E9C68; cursor:pointer}
.v1 .v1p-jour input[type=file]{font:12.5px var(--texte); margin-left:6px}
.v1 .v1p-jour-b{display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-top:4px}
.v1 .v1p-jour-b input[name=confirmation]{font:13px var(--texte); border:1px solid var(--line); border-radius:8px; padding:5px 8px; width:80px; margin-left:6px; text-transform:uppercase}
.v1 .v1p-jour-p{font-size:14px; line-height:1.6; margin:0; white-space:normal}
/* Le corps d'un message tel qu'il est parti : il garde ses retours a la ligne
   (c'est un texte redige, pas une valeur) et defile s'il est long, sinon un
   message de deux pages pousserait la ligne suivante hors de l'ecran. */
.v1 .v1p-msg{font:14px/1.7 Georgia,'Times New Roman',serif; white-space:pre-wrap; word-break:break-word;
  margin:8px 0 0; padding:12px 14px; max-height:340px; overflow:auto;
  background:#fff; border:1px solid var(--line); border-radius:10px}
.v1 .v1p-jour-pieces{margin:4px 0 0; padding-left:18px; font-size:13px; line-height:1.8}
.v1 .v1p-avis{display:inline-block; padding:2px 9px; border-radius:999px; color:#fff; font-size:11px; font-weight:700; letter-spacing:.3px; white-space:nowrap}
/* Un bouton désarmé se voit : « Signer la fiche » reste gris tant que OUI n'est
   pas tapé, et un geste en cours d'envoi ne se reclique pas. */
.v1 .v1p-btn:disabled{opacity:.45; cursor:not-allowed}

/* ══ V1 · L'ÉTAT D'UN ÉVÉNEMENT DANS SON CALENDRIER (03/09/2026, cahier § 7) ═
   Chaque carte d'événement porte son état — à faire, confirmé, fait, fait
   sans justificatif, reporté, annulé — et, pour qui a le droit d'écrire, les
   gestes qui le changent. Le liseré dit l'état d'un coup d'œil (vert : fait,
   bleu : confirmé, ambre : reporté, gris rayé : annulé, corail : passé et pas
   marqué) ; la pastille l'écrit en toutes lettres. Les mêmes boutons que dans
   un tableau, aux mêmes tons, en plus petit : ils vivent dans une carte. */
.v1 .v1p-evt.confirme{border-left-color:#1A5497; background:#f3f7fd}
.v1 .v1p-evt.reporte{border-left-color:#b45309; background:#fffbeb}
.v1 .v1p-evt.annule{border-left-color:#9ca3af; background:#f9fafb; color:#6b7280}
.v1 .v1p-evt.annule .v1p-evt-qui{text-decoration:line-through; text-decoration-color:#9ca3af}
.v1 .v1p-evt.retard{border-left-color:#C9341B; background:#fff5f3}
.v1 .v1p-evt-etat{margin-top:5px; font-size:11px; line-height:1.4; display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 6px}
.v1 .v1p-evt-etat small{color:#666}
.v1 .v1p-evt-ns{color:#b45309}
.v1 .v1p-evt-b{display:inline-block; font-size:10.5px; font-weight:700; letter-spacing:.02em; border-radius:6px; padding:1px 7px;
  background:#e5e7eb; color:#374151}
.v1 .v1p-evt-b-confirme{background:#dbeafe; color:#1A5497}
.v1 .v1p-evt-b-fait{background:#DCF2E7; color:#1E6644}
.v1 .v1p-evt-b-fait_sans_justificatif{background:#fef3c7; color:#92400e}
.v1 .v1p-evt-b-reporte{background:#fef3c7; color:#92400e}
.v1 .v1p-evt-b-annule{background:#f3f4f6; color:#6b7280; text-decoration:line-through}
.v1 .v1p-evt-g{margin-top:6px; display:flex; flex-wrap:wrap; gap:4px}
.v1 .v1p-evt-g .v1p-btn{min-height:var(--h-ctrl); padding:0 8px; font-size:11px}
.v1 .v1p-evt-g .v1p-btn svg{width:14px; height:14px}
.v1 .v1p-evt-g small{color:#666; font-size:10.5px}
.v1 .v1p-evt .v1p-mini{margin-top:6px; display:flex; flex-direction:column; gap:6px}
.v1 .v1p-evt .v1p-mini input, .v1 .v1p-evt .v1p-mini select, .v1 .v1p-evt .v1p-mini textarea{width:100%; box-sizing:border-box; font-size:12px}
.v1 .v1p-evt .v1p-n{font-size:11px}
.v1 .v1p-agd-syn{margin:0 0 12px; padding:8px 12px; background:var(--surface-2); border-radius:var(--r-ctrl); font-size:12px; line-height:1.5}
.v1 .v1p-agd-syn.v1p-ko{background:#fff5f3; color:#9f2a12}
@media print{ .v1 .v1p-evt-g, .v1 .v1p-evt .v1p-mini{display:none} }

/* ═══ LES ONGLETS DU DOSSIER (03/09/2026) ═══════════════════════════════════
   Huit volets, tous dessinés ; l'onglet range, il ne charge pas. La pastille
   porte un COMPTE mesuré (contrats, absences, courriers…) et reste cachée tant
   qu'aucune source n'a répondu — un zéro qu'on n'a pas mesuré ne s'écrit pas. */
.v1 .v1-dos-onglets{display:flex; flex-wrap:wrap; gap:4px; position:sticky; top:0; z-index:2; padding:10px 0 12px; margin-bottom:6px;
  background:var(--surface); border-bottom:1px solid var(--line)}
.v1 .v1-dos-o{font:inherit; font-size:12.5px; font-weight:600; padding:7px 12px; border:1px solid var(--line-2); border-radius:999px;
  background:var(--surface); color:var(--text-2); cursor:pointer; display:inline-flex; align-items:center; gap:6px; white-space:nowrap}
.v1 .v1-dos-o:hover{color:var(--titre); border-color:#43a074}
.v1 .v1-dos-o.on{background:#1f5c3f; border-color:#1f5c3f; color:#fff}
.v1 .v1-dos-o:focus-visible{outline:2px solid #43a074; outline-offset:2px}
.v1 .v1-dos-ob{font-family:var(--nombre); font-size:10.5px; min-width:18px; height:18px; padding:0 5px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center;
  background:#e3efe8; color:#1f5c3f}
.v1 .v1-dos-o.on .v1-dos-ob{background:rgba(255,255,255,.22); color:#fff}
/* ⚠️ `display:inline-flex` battait l'attribut `hidden` : une pastille SANS compte (source muette) se voyait
   comme un point vide — vu en ligne le 03/09. Cachée, elle l'est vraiment. */
.v1 .v1-dos-ob[hidden]{display:none}
.v1 .v1-dos-p{padding-top:6px}
.v1 .v1-dos-p .v1p-titre{margin-top:18px}
.v1 .v1-dos-p .v1p-titre:first-child{margin-top:4px; padding-top:0; border-top:0}
.v1 .v1-dos-etatcivil, .v1 .v1-dos-absences, .v1 .v1-dos-journees, .v1 .v1-dos-courriers, .v1 .v1-dos-placements{margin-top:16px}
.v1 .v1-dos-p .tbl td small{display:block; color:var(--text-3); font-size:11px}
.v1 .v1-dos-p tr.v1p-evt.retard td{background:#fff4ef}

/* Les pavés de Courrier qui filtrent : celui qui est posé se voit. */
.v1 .v1p-t[data-filtre-cle].on{outline:2px solid #1f5c3f; outline-offset:-2px}
.v1 .v1p-cour-param{margin-left:6px}

/* La source d'une valeur retenue dans l'état civil : petite, à côté, jamais devinée. */
.v1 .v1-dos-src{display:inline-block; margin-left:8px; font-size:10.5px; color:var(--text-3); font-family:var(--nombre)}

/* ═══ 04/09/2026 · UNE SEULE HAUTEUR DE BOUTON, ET UNE BARRE QUI NE SE MARCHE
   PLUS DESSUS ═══════════════════════════════════════════════════════════════
   (Antonio : « prends en sorte de bien avoir une h:px de bouton aligné et
   pareil… état responsive de l'outil… l'alignement des rangs des boutons, pour
   ne pas avoir des décalages partout ».)

   MESURÉ EN LIGNE AVANT DE TOUCHER (unitoolsv1.skhub.fr, fenêtre 1080) : le
   MÊME bouton d'action existait en SIX hauteurs.
     .v1p-btn — plaques, lignes de tableau ........ 32 px  (97 sur Arbitrages)
     .btn / .btn-main — « Adresser la demande » ... 40 px, et 39 px ailleurs
     .v1-dos-appel — « Dossier d'un jeune » ....... 38 px
     .role-btn — « Administration » ............... 38 px
     .tb-btn — cloche, avatar ..................... 36 px
     .v1p-btn-mini — « CSV », « Excel » ........... 26 px

   ⚠️ LA CAUSE DES 40 px N'ÉTAIT PAS UN OUBLI, ET C'EST CE QUI LA RENDAIT
   INVISIBLE : le V1 pose bien `.v1 .btn{height:var(--h-1)}` — 38 px — mais
   `unitools.css` pose `min-height:40px` sur `.btn`, et un MINIMUM bat une
   hauteur. Le jeton du V1 annonçait donc 38 px sans qu'aucun bouton ne les
   fasse. On repose les deux (`height` ET `min-height`), sinon la règle du MVP
   revient par-dessous — c'est la même famille de piège que `.sec`, la classe
   qui vit dans deux mondes.

   ET ÇA SE VOYAIT DANS LA MÊME RANGÉE : la barre du haut alignait « Dossier
   d'un jeune » (38) contre « Nouvelle demande » (32), à côté d'une cloche de
   36 — trois hauteurs sur dix centimètres.

   UNE seule hauteur donc : 32 px. Pas un chiffre neuf — celui des 97 boutons
   de plaque, et celui que le 03/09 avait déjà tranché (« boutons 32 px
   centrés »). Il vit dans `--h-ctrl` pour qu'il n'y ait plus qu'UN endroit où
   le changer. Les minis (26 px) rejoignent le rang : « CSV » et « Excel »
   vivent dans le même pied de carte que « Créer un campus », et deux hauteurs
   à trois centimètres l'une de l'autre ne se justifiaient par rien.
   ⚠️ CE QUI N'EST PAS UN BOUTON GARDE SA MESURE, et c'est délibéré : les
   onglets d'écran (`.tabx`, 44), les pastilles de section (`.v1p-sec-b`, 38),
   la barre d'applications (`.modx`, 39) sont trois NIVEAUX de navigation — leur
   hauteur dit la hiérarchie. Chacun est déjà d'accord avec lui-même. Le « × »
   d'un volet (28) est une fermeture, pas une action, et ne voisine jamais un
   bouton.
   ⚠️ ET LES TROIS MESURES SERVENT, aucune n'est décorative : `min-height`
   contre le `min-height:40px` du MVP, `height` pour la mesure elle-même, et
   `max-height` contre un conteneur qui ÉTIRE — c'est ce qui avait monté
   « CSV » à 46 px le 03/09, et un `height` seul ne l'en empêche pas. */
.v1{--h-ctrl:32px}
.v1 .v1p-btn, .v1 .v1p-btn-mini, .v1 a.v1p-lien, .v1 .btn, .v1 .btn-sm, .v1 .btn-main,
.v1 .v1-nouv, .v1 .v1-dos-appel, .v1 .role-btn, .v1 .scope, .v1 .cmd-open,
.v1 .v1p-evt-g .v1p-btn, .v1 .v1p-mini-b button, .v1 .v1p-exp .v1p-btn{
  height:var(--h-ctrl); min-height:var(--h-ctrl); max-height:var(--h-ctrl);
  box-sizing:border-box; display:inline-flex; align-items:center; justify-content:center;
  padding-top:0; padding-bottom:0; line-height:1}
.v1 .topbar .tb-btn{width:var(--h-ctrl); height:var(--h-ctrl); min-height:var(--h-ctrl)}
.v1 .v1p-btn-mini, .v1 .v1p-exp .v1p-btn, .v1 .v1p-evt-g .v1p-btn{
  padding-left:11px; padding-right:11px; font-size:12px}
.v1 .v1p-evt-g .v1p-btn svg{width:16px; height:16px}
/* Un menu contextuel ne mélange pas non plus deux hauteurs de ligne : mesuré,
   « Basculer en brouillon » faisait 36 px au milieu de voisins à 38. */
.v1 .menu-ctx button{height:36px; min-height:36px; box-sizing:border-box;
  padding-top:0; padding-bottom:0; display:flex; align-items:center}
/* UN CHAMP QUI PARTAGE UNE RANGÉE AVEC UN BOUTON A SA HAUTEUR. Sinon la rangée
   de filtres flotte au-dessus de son bouton « Afficher », et le mini-formulaire
   d'un geste pose son « Confirmer » un cran plus bas que sa liste. */
.v1 .v1p-filtres input, .v1 .v1p-filtres select,
.v1 .v1p-actions input, .v1 .v1p-actions select,
.v1 .v1p-mini input:not([type=checkbox]):not([type=radio]):not([type=file]),
.v1 .v1p-mini select{
  height:var(--h-ctrl); min-height:var(--h-ctrl); box-sizing:border-box;
  padding-top:0; padding-bottom:0}

/* ── LA COLONNE « GESTE » EST UNE COLONNE ──────────────────────────────────
   La largeur de chaque rang est posée par `alignerLaColonneGeste()`
   (v1-pilotage.js) : elle se MESURE, elle ne s'écrit pas ici. Le CSS ne tient
   que l'espacement et la place vide qui bouche un trou du milieu. */
.v1 .v1p-vide{display:inline-block; height:var(--h-ctrl); vertical-align:middle}
.v1 td.v1p-geste > .v1p-btn, .v1 td.v1p-geste > .v1p-vide{margin-left:8px}
.v1 td.v1p-geste > .v1p-btn:first-child, .v1 td.v1p-geste > .v1p-vide:first-child{margin-left:0}
/* Le mini-formulaire d'un geste passe SOUS la rangée : la cellule est en
   `nowrap` pour tenir ses boutons sur une ligne, le formulaire ne l'est pas. */
.v1 td.v1p-geste .v1p-mini{white-space:normal; margin-top:8px}

/* ── LA BARRE DU HAUT SE CHEVAUCHAIT ENTRE 860 ET ~1120 px ─────────────────
   Mesuré à 1080 : « Dossier d'un jeune » écrit PAR-DESSUS « Rechercher… », et
   le mot UNITOOLS coupé. Ce n'est pas un manque de place, c'est une grille qui
   ne peut pas céder : `.tb-ligne` est un `1fr minmax(0,auto) 1fr` dont les
   items gardent `min-width:auto` — les deux colonnes latérales refusent de
   descendre sous leur contenu, la colonne du MILIEU encaisse tout (36 px
   mesurés pour la recherche) et son champ, qui porte `min-width:104px`,
   DÉBORDE sur ses voisins au lieu de rétrécir. Rien ne le disait : aucun
   ascenseur, aucune coupure — juste deux textes l'un sur l'autre.
   ⚠️ Le repli existait… mais seulement sous 860 px (`unitools.css`), c'est-à-dire
   jamais sur un portable. C'est la même leçon que `.tb-right` en août : un
   correctif qui ne vaut qu'en dessous d'une largeur qu'on n'utilise pas n'est
   pas un correctif. Mesuré après : 0 chevauchement de 880 à 1400 px.
   Ce qui cède, dans l'ordre, et pourquoi : le raccourci ⌘K (il est écrit dans
   la palette elle-même), puis le mot UNITOOLS (le logo dit déjà de qui est
   l'outil, et le rail dit où l'on est), jamais les commandes de droite —
   règle d'août : « c'est l'avatar qu'on perdait ». */
.v1 .tb-ligne > *{min-width:0}
.v1 .tb-ligne .tb-right{min-width:auto}
.v1 .cmd-open{min-width:0}
.v1 .tb-marque{min-width:0}
.v1 .tb-marque img{flex:none}
@media (max-width:1250px){ .v1 .cmd-open kbd{display:none} }
@media (max-width:1200px){ .v1 .tb-marque .t2{display:none} }

/* ── UNE PLAQUE NE SORT PLUS DE SA CARTE ───────────────────────────────────
   Sous 760 px, le contenu passait à travers le bord droit de la carte au lieu
   de défiler dedans : mesuré, 167 éléments hors cadre à 560 px et 314 à 390.
   La cause est la même qu'au-dessus, un cran plus bas : `.v1-plaques` est une
   grille, et un `1fr` a pour minimum le CONTENU de son item (`min-width:auto`).
   La carte refusait donc de rétrécir, le `.tbl` qui l'entoure n'atteignait
   jamais sa largeur de défilement, et son `overflow-x:auto` ne servait à rien.
   Mesuré après : 0 élément hors cadre à 760, 560 et 390 px — les tableaux
   défilent dans leur carte, ce qu'ils étaient censés faire depuis le début. */
.v1 .v1-plaques > *, .v1 .card, .v1 .card-bd, .v1 .rk{min-width:0}
.v1 .card-bd .tbl{overflow-x:auto; -webkit-overflow-scrolling:touch}

/* ── LES FILTRES D'EN-TÊTE (04/09/2026) ────────────────────────────────────
   Une rangée de plus sous les intitulés : un champ quand la colonne a cent
   valeurs, une liste quand elle en a six. Elle se lit comme une partie de
   l'en-tête, pas comme une première ligne de données — d'où le même fond que
   la tête et un filet dessous. La logique (quand poser une liste, quoi
   comparer) vit dans `poserLesFiltresDEntete()` : ici, rien que le dessin. */
.v1 .tbl > table > thead > tr.v1p-entete-f > td{
  padding:5px 8px 7px; background:var(--surface-2); border-bottom:1px solid var(--line);
  vertical-align:middle}
.v1 .v1p-filtre-c{
  width:100%; min-width:70px; max-width:220px; box-sizing:border-box;
  height:26px; min-height:26px; padding:0 7px;
  font:500 11.5px/1 var(--texte); color:var(--text);
  background:#fff; border:1px solid var(--line-2); border-radius:var(--r-petit, 8px)}
.v1 .v1p-filtre-c::placeholder{color:var(--text-3); font-weight:400}
.v1 .v1p-filtre-c:focus-visible{outline:2px solid var(--vif); outline-offset:1px; border-color:var(--vif)}
/* ⚠️ CE QUI EST CACHÉ SE COMPTE. Un tableau filtré qu'on prend pour un tableau
   vide, c'est nous qui aurions caché — la ligne le dit, et rend le tableau. */
.v1 .v1p-filtre-n{display:flex; align-items:center; gap:10px; padding:8px 2px 0;
  color:var(--text-2); font-size:12px}
.v1 .v1p-filtre-n[hidden]{display:none}

/* ═══ 04/09/2026 · LA GRILLE FORMATION × MOIS, ET LE PANNEAU DU MILIEU ══════
   (Antonio : « ce tableau n'est pas affiché dans V1 en version comme cela,
   selon filière et tout, et c'est en cliquant qu'on a une page flottante comme
   le dossier candidat, mais au milieu ».) */
.v1 table.v1p-grille{table-layout:auto; width:100%}
.v1 table.v1p-grille th.v1p-gr-form{
  text-align:left; vertical-align:top; min-width:180px; position:sticky; left:0; z-index:1;
  background:var(--surface)}
.v1 table.v1p-grille th.v1p-gr-form b{display:block; font-size:13px; color:var(--titre)}
.v1 table.v1p-grille th.v1p-gr-form .v1p-n{font-weight:400; margin-top:1px}
.v1 table.v1p-grille .v1p-gr-sr{color:var(--alr); font-weight:600}
.v1 table.v1p-grille th.v1p-gr-m{text-align:center; white-space:nowrap; font-size:11.5px}
.v1 table.v1p-grille td.v1p-gr-c{text-align:center; padding:4px 5px; vertical-align:middle}
/* ⚠️ UN MOIS SANS SÉANCE EST VIDE, PAS « 0 ». Un zéro se compte, et l'œil s'y
   arrête pour rien ; une case vide se saute. */
.v1 table.v1p-grille td.v1p-gr-vide{background:repeating-linear-gradient(135deg,
  transparent 0 6px, rgba(21,32,26,.035) 6px 7px)}
.v1 .v1p-gr-b{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
  width:100%; min-height:var(--h-ctrl); padding:5px 8px; border:0; cursor:pointer;
  background:#E6EEE9; color:#1B3327; border-radius:var(--r-petit, 9px); font:inherit}
.v1 .v1p-gr-b:hover{background:#D9E5DE}
.v1 .v1p-gr-b:focus-visible{outline:2px solid var(--vif); outline-offset:2px}
.v1 .v1p-gr-t{font-size:10px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--text-2)}
.v1 .v1p-gr-n{font-family:var(--nombre); font-size:12.5px; font-weight:700; white-space:nowrap}

/* ── Le panneau du MILIEU ───────────────────────────────────────────────────
   Le tiroir du dossier vient de la droite parce qu'on garde la liste derrière
   soi. Ici on ouvre une CASE d'une grille large : un tiroir de droite en
   couvrirait les colonnes voisines, c'est-à-dire ce qu'on compare. */
.v1 .v1-mil{position:fixed; inset:0; z-index:95; display:grid; place-items:center}
.v1 .v1-mil[hidden]{display:none}
.v1 .v1-mil-voile{position:absolute; inset:0; background:rgba(12,26,19,.38); backdrop-filter:blur(2px)}
.v1 .v1-mil-vol{
  position:relative; width:min(880px, 92vw); max-height:86vh;
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--surface); border-radius:var(--r-plaque, 14px);
  box-shadow:0 24px 64px rgba(12,26,19,.24);
  animation:v1-mil-entre .18s cubic-bezier(.32,.72,0,1)}
@keyframes v1-mil-entre{from{transform:translateY(10px)} to{transform:none}}
@media (prefers-reduced-motion:reduce){ .v1 .v1-mil-vol{animation:none} }
.v1 .v1-mil-hd{display:flex; align-items:center; justify-content:space-between; gap:18px;
  padding:16px 20px; border-bottom:1px solid var(--line); background:var(--surface-2)}
.v1 .v1-mil-t{font-family:var(--titre); font-size:15px; font-weight:700; color:var(--titre)}
.v1 .v1-mil-corps{padding:16px 20px 20px; overflow:auto}
.v1 .v1-mil-res{display:flex; flex-wrap:wrap; gap:6px; margin-bottom:12px}

/* ═══ 04/09/2026 · IMPRIMER UNE PLAQUE, ET UNE SEULE ═══════════════════════
   (Antonio : « travaille aussi sur les boutons imprimés et les boutons
   exportés ».)

   Le navigateur imprime la PAGE ; on veut une carte. `imprimerUneCarte()`
   marque le document et la carte le temps de l'impression ; ces règles ne
   valent QUE sous ce marquage — rien ne change tant qu'on n'imprime pas.

   ⚠️ CE QUI SORT DU PAPIER, ET CE QUI RESTE. Partent : le rail, la barre du
   haut, les onglets, les boutons, la rangée de filtres d'en-tête (un champ
   vide imprimé est une ligne grise qui n'apprend rien). Restent : le titre,
   le sous-titre, la LIGNE DE SOURCE et la barre de filtres — une liste de
   contrats imprimée sans sa période ni son campus est un tableau qu'on ne
   peut plus dater, et c'est le voyant de fraîcheur de la règle 18 sur papier.

   ⚠️ ET LES LIGNES MASQUÉES PAR UN FILTRE LE RESTENT : `[hidden]` tient à
   l'impression. On imprime ce qu'on voit, pas ce que la source contenait. */
@media print {
  body.v1-impression .rail,
  body.v1-impression .topbar,
  body.v1-impression .tabx-bar,
  body.v1-impression .v1-groupes,
  body.v1-impression .v1p-appbar,
  body.v1-impression .page-tete,
  body.v1-impression .crumb,
  body.v1-impression .toasts,
  body.v1-impression .v1-dos,
  body.v1-impression #v1-bandeau,
  body.v1-impression .v1-plaques > .card:not(.v1-imprime-ici),
  body.v1-impression .v1p-bloc > *:not(.v1-plaques),
  body.v1-impression .v1-mil-voile{ display:none !important }

  body.v1-impression .v1-imprime-ici .v1p-exp,
  body.v1-impression .v1-imprime-ici .v1p-actions,
  body.v1-impression .v1-imprime-ici .v1p-gecran,
  body.v1-impression .v1-imprime-ici td.v1p-geste,
  body.v1-impression .v1-imprime-ici th.v1p-th-geste,
  body.v1-impression .v1-imprime-ici .v1p-entete-f,
  body.v1-impression .v1-imprime-ici .v1p-filtre-n,
  body.v1-impression .v1-imprime-ici .v1-mil-btns{ display:none !important }

  body.v1-impression, body.v1-impression .main, body.v1-impression .content{
    display:block !important; padding:0 !important; margin:0 !important;
    background:#fff !important}
  body.v1-impression .v1-imprime-ici{
    box-shadow:none !important; border:0 !important; margin:0 !important;
    width:auto !important; max-width:none !important;
    position:static !important; max-height:none !important; overflow:visible !important}
  body.v1-impression .v1-imprime-ici .tbl{overflow:visible !important}
  /* Une ligne coupée en deux par un saut de page se relit deux fois. */
  body.v1-impression .v1-imprime-ici tr{break-inside:avoid}
  body.v1-impression .v1-imprime-ici thead{display:table-header-group}
  /* La grille est large : elle sort en paysage, sinon elle perd ses derniers mois. */
  body.v1-impression .v1-imprime-ici table.v1p-grille{font-size:9px}
}
@page{ margin:12mm }

/* Le panneau du milieu porte ses gestes en rangée. */
.v1 .v1-mil-btns{display:flex; align-items:center; gap:8px}

/* ── LES DIPLÔMÉS PAR TRIMESTRE : LA LISTE EST NOMINATIVE (04/09/2026) ──────
   L'écran ne montrait que les classes et leur compte. Chaque trimestre porte
   maintenant sa liste, et le questionnaire signé s'ouvre depuis la ligne. */
.v1 .v1-dip{margin:0 0 18px}
.v1 .v1-dip-hd{background:var(--surface-2); border-radius:var(--r-ctrl) var(--r-ctrl) 0 0; padding:9px 12px}
.v1 .v1-dip .tbl{border:1px solid var(--line); border-top:0; border-radius:0 0 var(--r-ctrl) var(--r-ctrl)}
.v1 .v1-dip td.v1-dip-g{white-space:nowrap}
.v1 .v1-dip td.v1-dip-g .v1p-n{display:inline; color:var(--text-3)}

/* Le panneau du milieu accueille un agenda : il lui faut la place d'un. */
.v1 .v1-mil-agenda{margin-top:4px}
.v1 .v1-mil-agenda .v1p-annee{gap:10px}
.v1 .v1-mil-agenda .v1p-mois{min-width:0}

/* ── LE JEUNE SUIVI DEPUIS LE CALENDRIER (04/09/2026) ───────────────────────
   ⚠️ LE JAUNE EST UN REPÈRE, PAS UN ÉTAT. Les cartes portent déjà des couleurs
   qui VEULENT dire quelque chose — vert : fait, bleu : confirmé, ambre :
   reporté, corail : passé non marqué (règle 32). Un aplat plein par-dessus les
   effacerait. Le repère est donc un fond TRANSLUCIDE et un liseré : l'état
   reste lisible dessous, et l'on voit quand même où sont ses cartes. */
.v1 .v1p-evt.v1p-evt-vise{
  background-image:linear-gradient(rgba(242,229,106,.55), rgba(242,229,106,.55));
  box-shadow:inset 0 0 0 2px rgba(191,164,20,.75); border-radius:8px}
.v1 .v1p-vise-bar{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:0 0 10px; padding:7px 11px; border-radius:var(--r-ctrl);
  background:rgba(242,229,106,.28); color:var(--titre)}
.v1 .v1p-vise-bar b{font-weight:700}
/* Le nom d'une carte d'agenda mène au Planning : il se comporte comme un lien. */
.v1 .v1-mil-agenda .v1-nom-agd{cursor:pointer; text-decoration:underline; text-decoration-style:dotted;
  text-underline-offset:2px}
.v1 .v1-mil-agenda .v1-nom-agd:hover{color:var(--titre)}

/* Deux bornes pour une colonne de dates : « à partir de » et « jusqu'au ». */
/* ⚠️ C'EST LE FILTRE QUI FAISAIT LA LARGEUR, PAS LA DONNÉE (05/09/2026).
   Antonio : « aussi les tableaux ». Mesuré sur le tableau des apprenants,
   colonne par colonne : la table fait 2 247 px dans une enveloppe de 956, et
   **cinq colonnes de date pèsent 233 px chacune** — 1 165 px, plus de la
   moitié. Une date affichée en fait 90 (« 03/09/2026 ») : les 233 venaient des
   DEUX champs `date` posés côte à côte dans la ligne de filtres.
   On les empile. La colonne retombe sur ce que la donnée demande, et l'on ne
   supprime aucune colonne — c'était l'autre solution, et elle coûtait de
   l'information pour un problème de mise en page. */
.v1 .v1p-filtre-p{display:flex; flex-direction:column; gap:2px; align-items:stretch}
.v1 .v1p-filtre-d{min-width:0; width:100%; flex:0 0 auto; padding:0 4px; font-size:10.5px}

/* ⚠️ ET ON NE PERD PLUS DE VUE QUI EST LA LIGNE. Un tableau qui défile de côté
   emmène le nom hors du champ : on lit « 03/09/2026 · CAEN · 1 » sans savoir de
   qui l'on parle. Les deux premières colonnes restent collées à gauche. Le fond
   est opaque, sinon le texte qui passe dessous se lit à travers. */
/* ⚠️ UNE SEULE COLONNE FIGÉE, ET C'EST DÉLIBÉRÉ. Figer aussi la deuxième
   demanderait de connaître la largeur de la première (`left: 114px` mesuré) —
   or elle dépend du contenu et de la fenêtre : le décalage serait juste sur mon
   écran et faux sur le sien, et un chevauchement d'une colonne sur l'autre est
   pire que la colonne qui défile. La première suffit à répondre à « de qui
   parle cette ligne ? ».
   Le fond est opaque : sans lui, le texte qui passe dessous se lit à travers. */
.v1 .tbl{position:relative}
.v1 .tbl table th:first-child, .v1 .tbl table td:first-child{
  position:sticky; left:0; background:#fff; z-index:2;
  box-shadow:1px 0 0 var(--line, #E7ECE9)}

/* ═══ UN ÉCART ENTRE SOURCES SE VOIT, SANS CRIER (04/09/2026) ═══════════════
   L'état civil retenu ne montre plus qu'une valeur par fait ; quand une autre
   source dit autre chose, la marque apparaît À CÔTÉ de la valeur retenue, pas
   à la place. Corail, comme tout ce qui appelle une vérification dans le V1 —
   jamais rouge plein, qui est la couleur de « supprimer ». */
.v1 .v1-dos-ecart{display:inline-block;margin-left:8px;padding:1px 7px;border-radius:999px;
  background:rgba(232,106,90,.12);color:#b4442f;font-size:11px;font-weight:600;white-space:nowrap}

/* ═══ CHERCHER DANS LES SOURCES, DEPUIS LE FORMULAIRE (04/09/2026) ══════════
   La barre tient toute la largeur du mini-formulaire : elle se lit AVANT les
   champs, parce qu'elle sert avant eux. Le compte rendu se replie dessous. */
.v1 .v1p-prop-b{flex:1 0 100%;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  margin:0 0 10px;padding:0 0 10px;border-bottom:1px solid rgba(16,24,32,.10)}
.v1 .v1p-prop-r{flex:1 0 100%;margin:0}
.v1 .v1p-prop-r > div{margin:3px 0}
/* Un champ rempli par une source le DIT : liseré vert à gauche, et le titre
   nomme la source. Jamais un aplat — on doit voir que la valeur est modifiable. */
.v1 form.v1p-mini [data-v1venu]{box-shadow:inset 3px 0 0 var(--v1-vert,#3bae79)}

/* ═══ CE QU'UNE SOURCE A COÛTÉ (05/09/2026) ════════════════════════════════
   Discret par défaut : un temps normal n'a pas à attirer l'œil. Corail au
   delà de 800 ms — le seuil où l'on SENT l'attente, pas un chiffre rond. */
.v1 .v1-src-ms{display:block;margin-top:2px;font-size:11px;opacity:.7}
.v1 .v1-src-ms.lent{color:#b4442f;opacity:1;font-weight:600}

/* ═══ 05/09/2026 · LA REPRISE EN LOT : ce qui est LU n'est pas ENREGISTRÉ ═══
   Les deux chiffres proposés par la lecture d'un relevé prennent la place des
   tirets dans la ligne, en italique : ils ne sont pas encore en base. L'origine
   dit si la lecture se recoupe avec les totaux imprimés — sinon, en corail, et
   elle ne partira pas dans le lot. */
.v1 .v1p-lot-lu{font-style:italic; color:#1A5497}
.v1 .v1p-lot-lu.v1p-lot-ko{color:#C9341B}
/* Le PDF d'un courrier signé, dans sa ligne. */
.v1 .v1p-pdf{margin-left:8px}

/* ═══ UNE FICHE DE CRÉATION SE LIT PAR GROUPES (05/09/2026) ════════════════
   Quatorze champs à plat, on ne sait plus où l'on en est. L'intertitre coupe
   la ligne du formulaire (`flex-basis:100%`) et porte sa raison en petit. */
.v1 form.v1p-mini .v1p-champ-groupe{flex:1 0 100%; margin:14px 0 2px;
  font-size:var(--t-second); font-weight:700; color:var(--text-1);
  border-top:1px solid var(--line); padding-top:12px}
.v1 form.v1p-mini .v1p-champ-groupe:first-child{border-top:0; margin-top:0; padding-top:0}
.v1 form.v1p-mini .v1p-champ-groupe small{display:block; font-weight:400;
  font-size:11px; color:var(--text-2); margin-top:2px}
/* La recherche SIRET vit SOUS son champ, jamais à côté : à côté, elle passe
   pour un second champ. */
.v1 .v1p-siret-go{margin-top:6px}
.v1 .v1p-siret-r{flex:1 0 100%; margin:4px 0 0}

/* ═══ LA CARTE DU DOSSIER D'UN JEUNE (05/09/2026) ═════════════════════════
   Antonio : « dans la carte de l'apprenti on devrait avoir où est son secteur,
   le centre et tout ». Elle vit dans l'onglet « Entreprise », AVANT les
   tableaux : « où » se lit d'un coup d'œil, « combien de kilomètres » se lit
   ensuite.
   ⚠️ La hauteur est POSÉE ici et non calculée : Leaflet mesure sa boîte à la
   création, et une boîte sans hauteur donne une carte d'un pixel — sans erreur,
   et sans que rien ne le dise. */
.v1 .v1p-carte-dossier{height:320px; margin:0 0 10px; border-radius:10px; overflow:hidden;
  border:1px solid var(--v1-vert, #2E9C68); box-shadow:0 0 0 3px rgba(46,156,104,.10);
  background:var(--fond-2, #f4f6f5); display:grid; place-items:center}
/* Une fois Leaflet dedans, on rend la boîte à la carte : `place-items` centrerait
   le plan au lieu de le laisser remplir. */
.v1 .v1p-carte-dossier .leaflet-container{width:100%; height:100%; display:block}
.v1 .v1p-carte-dossier:has(.leaflet-container){display:block}
.v1 .v1p-carte-dossier .leaflet-container{font:inherit}

/* ═══ VÉRIFIER, PUIS MODIFIER — DANS LA CARTE DU DOSSIER ═══════════════════
   Antonio, 08/09/2026 : « sur toutes les cartes dans le dossier candidat on
   peut le vérifier dessus et on peut le modifier à partir de cela ».
   Le formulaire est REPLIÉ par défaut (`<details>` natif) : le dossier reste
   un écran de lecture, et l'écriture est un geste qu'on demande. Ouvrir huit
   formulaires d'un coup, c'est huit champs modifiables devant quelqu'un qui
   venait vérifier une date.
   ⚠️ AUCUN NOM PARTAGÉ AVEC L'EN-TÊTE DE LA CARTE : `.v1-dos-btns` et
   `.v1-dos-ou` y sont déjà pris (les boutons Exporter/Fermer, la ligne
   « Trouvé par la recherche »), d'où `-fbtn` et `-fou`. Un nom partagé et deux
   intentions, c'est la faute du même jour un cran plus bas. */
.v1 .v1-dos-geste{ margin-top: 12px; border: 1px solid #dfe7e2; border-radius: 10px; background: #fbfdfc }
.v1 .v1-dos-geste > summary{
  cursor: pointer; padding: 9px 12px; font-size: 12.5px; font-weight: 600;
  color: var(--titre); list-style: none; display: flex; align-items: center; gap: 8px;
}
.v1 .v1-dos-geste > summary::before{ content: '✎'; opacity: .6; font-size: 12px }
.v1 .v1-dos-geste > summary::-webkit-details-marker{ display: none }
.v1 .v1-dos-geste[open] > summary{ border-bottom: 1px solid #e7eeea }
.v1 .v1-dos-geste > summary:hover{ background: #f2f7f4; border-radius: 10px 10px 0 0 }
.v1 .v1-dos-form{ padding: 12px }
.v1 .v1-dos-fou{ font-size: 11.5px; color: #6d7d75; margin-bottom: 10px }
.v1 .v1-dos-chs{ display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px }
.v1 .v1-dos-ch{ display: grid; gap: 3px }
.v1 .v1-dos-ch > span{ font-size: 11px; color: #6d7d75; text-transform: uppercase; letter-spacing: .03em }
.v1 .v1-dos-ch input, .v1 .v1-dos-ch select{
  font: inherit; font-size: 13px; padding: 7px 9px;
  border: 1px solid #d6e0da; border-radius: 8px; background: #fff; color: var(--titre); width: 100%;
}
.v1 .v1-dos-ch input:focus-visible, .v1 .v1-dos-ch select:focus-visible{ outline: 2px solid #43a074; outline-offset: 1px }
.v1 .v1-dos-fbtn{ margin-top: 12px; display: flex; gap: 10px; flex-wrap: wrap }
/* Ce que le serveur a répondu — jamais une couleur seule : le texte porte le
   sens, la couleur ne fait que le répéter. */
.v1 .v1-dos-dit{ margin-top: 10px; font-size: 12.5px; color: #6d7d75; min-height: 0 }
.v1 .v1-dos-dit:empty{ display: none }
.v1 .v1-dos-dit.ok{ color: #1d6b4a }
.v1 .v1-dos-dit.ko{ color: #b4462f }
/* La raison, à la place du bouton, sur ce qui ne s'écrit pas d'ici. */
.v1 .v1-dos-raison, .v1 .v1-dos-nogeste{ margin-top: 10px; font-size: 12px; line-height: 1.5 }
/* Le geste qui EFFACE se voit : la couleur dit le geste (règle du 03/09 —
   ajouter vert, supprimer rouge, modifier bleu). Il est aussi séparé du
   formulaire par un intertitre : le voisin du bouton « Enregistrer » se
   déclenche par erreur. */
.v1 .v1-dos-fsep{
  margin: 16px 0 8px; padding-top: 12px; border-top: 1px solid #e7eeea;
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #b4462f;
}
.v1 .v1-dos-efface{ background: #b4462f; border-color: #b4462f; color: #fff }
.v1 .v1-dos-efface:hover{ background: #9c3a25; border-color: #9c3a25 }

/* Ce qu'on peut faire sur une carte, quand aucun bouton ne le dit (08/09/2026).
   Discret : c'est une indication, pas un message d'erreur — et elle vit dans
   le pied, sous la source, là où la carte parle déjà d'elle-même. */
.v1 .v1p-faire{
  margin-top: 8px; font-size: 11.5px; line-height: 1.5; color: #6d7d75;
  padding-left: 16px; position: relative;
}
.v1 .v1p-faire::before{ content: '→'; position: absolute; left: 0; top: 0; opacity: .55 }
