
:root{
  /* LA GOUTTIÈRE — le rembourrage horizontal du corps sous 640 px, et la SEULE source de cette
     valeur. Les blocs qui sortent volontairement du rembourrage (le cartouche et la feuille en
     plein écran) la compensent par une marge négative : ils écrivaient `-14px` en dur pour un
     rembourrage de 12, d'où 4 px de page en trop et un défilement latéral que DESIGN.md
     interdit. Deux règles qui disent la même chose divergent toujours ; celles-ci LISENT. */
  --gouttiere:12px;
  /* HAUTEUR DU BANDEAU « DÉMONSTRATION » — LA source de cette valeur : le bandeau la POSE et la
     barre du haut la LIT pour caler son ancrage collant. Deux nombres pour une même hauteur
     divergent (règle 9), et ici la divergence se voit tout de suite : la barre recouvre le
     bandeau ou laisse un trou. 0 en production, où le bandeau n'existe pas. */
  --demo-h:30px;
  /* COULEURS. Ces valeurs sont celles qui s'appliquent — plus aucune couche ne les corrige
     plus bas. Elles ont porté un indigo #4b45d1 jusqu'au 28.07, écrasé 578 lignes plus loin par
     un bloc « OVERRIDE ARDOISE » : le haut du fichier annonçait une couleur que l'application
     n'a jamais affichée, et c'est en la citant qu'une question a été posée à Rémy pour rien. */
  /* ── 01.08 (soir) — LA PALETTE CHANGE, ET AVEC ELLE LE MÉTIER DE LA COULEUR ────────────────
     Rémy a fourni la palette et tranché après réserves écrites : space-indigo #2d3047 · teal
     #087e8b · celadon #abd1b5 · mint-cream #edf4ed · rosewood #ba324f. L'ardoise #5C6E99, épinglée
     le 28.07, est REMPLACÉE — ce n'est pas une dérive, c'est une décision.
     LA RÈGLE QUI GOUVERNE MAINTENANT : **si c'est coloré, ça se clique**. Mesuré au navigateur sur
     l'accueil avant correctif : 58 éléments cliquables, UN SEUL portait la moindre chroma, et 11
     objets colorés étaient inertes. La couleur était exactement à l'envers — elle peignait les
     états, qu'on ne peut que lire, et désertait les commandes. Tenu par l'invariant K.
     QUATRE des cinq couleurs tombaient sur la légende métier (rosewood ↔ alarme Δteinte 11,5° ;
     mint-cream ↔ fond « garde tenue » ΔL* 0,49 — la MÊME couleur ; celadon ↔ fatigue calme
     ΔL* 3,4). On ne les fait donc pas COHABITER avec la légende, on la lui fait ABSORBER : le
     rosewood DEVIENT l'alarme, le mint-cream DEVIENT le fond acquis, le celadon DEVIENT la bande
     calme. Deux couleurs voisines qui ne servent pas au même endroit finissent toujours par se
     confondre ; une couleur qui EST le jeton ne le peut pas.
     Le teal brut ne sait pas ÉCRIRE : #087e8b mesure 4,32:1 sur la feuille, sous le plancher.
     D'où `--accent-ink` #006f7b (5,29:1 sur la feuille, 5,90 sur la surface) — la règle de l'aplat
     et de l'encre, appliquée à l'accent lui-même. */
  --accent:#87a0b2; --accent-2:#2f546a; --accent-ink:#43687e; --violet:#c0c1c4; --on-accent:#02111b;
  /* L'EXERGUE (01.08). La palette n'a laissé AUCUNE couleur libre pour la mise en exergue : ses
     cinq membres sont pris par la charpente, l'action et trois signaux métier. L'indigo fait donc
     double emploi — charpente ET filet d'exergue — et c'est assumé, pas subi : il n'apparaît en
     exergue que sur la feuille, où la charpente n'est jamais. Un seul exergue par écran. */
  --ex:#3f4045; --ex-ink:#58595e; --ex-pale:#e3ecf4;
  /* 29.07 — L'ENCRE POSÉE SUR UN APLAT TEINTÉ, POUR LE VERT ET LE ROUGE AUSSI.
     Ces deux tokens existaient dans `portail_med.html` DEPUIS LE 27.07 et n'ont jamais atteint
     la feuille partagée. Résultat : le portail était juste, la CONSOLE peignait `#fff` en dur —
     23 règles, dont 6 à 2,42:1 en thème sombre (logo, bascule de rôle, onglet actif). C'est la
     MÊME divergence qu'au 28.07, à six heures d'intervalle, et exactement ce que le déménagement
     du monde visuel devait empêcher. Tant que le portail garde sa copie des 292 règles, ça
     recommencera : la vraie correction est de lui faire CONSOMMER cette feuille.
     Valeurs reprises TELLES QUELLES du portail — surtout pas recalculées : deux définitions du
     même token divergent d'un demi-ton, puis d'une règle entière (règle 9).
     MESURÉ le 29.07, jamais supposé — sombre : accent 2,42 → 7,75 · vert 2,36 → 7,59 ·
     rouge 3,15 → 5,71. En clair les trois valent #ffffff : la substitution n'y change rien. */
  --on-green:#02111b; --on-red:#ffffff;
  /* 29.07 — LES ENCRES DES FRISES (Tournus). Trois familles de fond y cohabitaient sans qu'aucune
     n'ait d'encre à elle, et l'encre de l'ACCENT était posée sur les trois : en thème sombre elle
     bascule à #111118 et l'on obtenait du quasi-noir sur du bleu nuit — 13 mesures entre 1,81:1
     et 3,75:1. Chaque famille a désormais la sienne, mesurée :
       · `--on-frise`  encre des 13 teintes FIXES de la frise CDC (fonds sombres, identiques dans
                       les deux thèmes) : blanc, de 5,02:1 à 10,36:1 selon la teinte.
       · `--sur-pale`  encre des fonds PÂLES figés (#cfe9da « présent », #94a3b8 « Off ») :
                       14,61:1 et 7,33:1. Le blanc y donnait 1,29:1 — la pastille de légende
                       « présent / dispo » était illisible dans LES DEUX thèmes.
       · `--on-ink-soft` encre sur un aplat gris `--ink-soft` : 5,01:1 en clair, 6,93:1 en sombre
                       (le blanc y tombait à 2,71:1 — c'est la pastille « Vacances »).
     Ces trois-là ne portent pas de sens métier : ce sont des encres, et elles n'existent que
     pour être MESURÉES contre leur fond. */
  --on-frise:#ffffff; --sur-pale:#02111b; --on-ink-soft:#ffffff;
  /* `--ink-soft` valait #6d6f78 : 5,01:1 sur la surface blanche, mais seulement 4,36 à 4,48 sur
     les QUATRE aplats pâles de signal (rouge, bleu, vert, ambre) — sous le plancher, sur les
     libellés et les marginalia qui vivent précisément dans ces encarts. Assombri de quatre unités,
     calculé sur les six fonds où il se pose : le pire cas passe de 4,36 à 4,63. À l'œil, rien ne
     bouge ; c'est le but — une encre atténuée doit rester atténuée, et rester lisible. */
  /* ── LA FEUILLE PREND LE GRAIN DE L'ARDOISE (01.08) ────────────────────────────────────────
     `--bg` valait #F4F5F7, un gris quasi neutre. Le monde s'appelle « la feuille et son
     cartouche » : une feuille topographique n'est pas blanche, et deux blancs superposés ne font
     pas un champ, ils font un vide. Mesuré sur l'écran d'accueil de la console, la SEULE mesure
     qui décrivait vraiment le grief « ça manque d'atmosphère » : 0,08 % de la surface portait la
     moindre chroma, et l'accent de marque n'y peignait AUCUN pixel.
     La feuille reçoit donc la teinte de l'ardoise, très diluée. Ce n'est pas de la couleur, c'est
     de la MATIÈRE : à l'œil rien n'est « bleu », mais le blanc des blocs redevient du papier
     POSÉ sur quelque chose au lieu de se fondre dans le fond.
     Effet second, et il sert le premier grief : l'écart feuille→surface passe de ΔL* 3,49 à 4,50
     — le pas que le thème SOMBRE tenait déjà (4,05). Les deux thèmes séparent enfin leurs plans
     du même geste, au lieu que le clair soit le plus plat des deux.
     L'encre atténuée y est REMESURÉE, pas supposée : 4,74:1 (contre 4,87 sur l'ancien fond),
     au-dessus du plancher de 4,5. */
  /* ⚠ CE QUI PRÉCÈDE DÉCRIT LE GRAIN D'ARDOISE DU 01.08 (matin) : le principe TIENT, la teinte
     a changé le soir même. La feuille porte désormais la teinte de l'INDIGO de la charpente, même
     dilution — « un peu de saturation dans les gris » (Rémy). Chroma 4 à 7 en Lab, plus au milieu
     de l'échelle où l'œil la voit, moins aux extrêmes : rien ne paraît bleu, mais le blanc des
     blocs redevient du papier POSÉ sur quelque chose. Encre atténuée remesurée sur la nouvelle
     feuille : 4,73:1, au-dessus du plancher. */
  --ink:#02111b; --ink-soft:#5f6f7b; --line:#d7e1e8; --bg:#ecf3f9; --card:#ffffff; --silver:#8b98a1;
  /* LA LÉGENDE ABSORBE LA PALETTE (01.08 soir — voir la note de l'accent). Le rosewood EST
     l'alarme, le mint-cream EST le fond acquis. Mesuré, jamais supposé : blanc sur rosewood
     5,74:1 · blanc sur le vert 5,18:1 · encre acquise sur son fond 4,80:1. Le vert d'aplat a été
     assombri de L* 52 à 46 pour que `--on-green` (blanc) repasse le plancher : à L* 52 il
     mesurait 4,19:1. La vigilance est le seul signal que la palette ne fournit pas — elle ne
     bouge donc pas. */
  /* ══ LA LÉGENDE REPREND SES TROIS COULEURS NOMMÉES (02.08, signalé par Rémy) ═══════════════
     Le portage sur quatre couleurs avait fondu les signaux dans la palette : l'acquis en acier,
     l'alarme en vanille, la vigilance en gunmetal. Mesuré, tout tenait. À l'écran, c'était FAUX —
     et pour une raison qu'aucun contraste ne peut voir : **ce produit NOMME ses couleurs dans son
     propre texte**. Le sélecteur IOT propose « vert (supervise) · orange (autonome) · rouge (ACR
     seul) », les légendes disent « ● atteint · ● proche · ● loin », `fatigue.bande()` renvoie les
     chaînes "vert"/"orange"/"rouge", et l'inbox écrit « 2 membres en zone fatigue (dont 1 en
     rouge) ». Un niveau appelé ROUGE peint en olive fait mentir l'interface à chaque ligne.
     D'où la séparation, qui est la bonne et qu'on aurait dû garder : **les quatre couleurs
     gouvernent l'INTERFACE** (charpente, feuille, action, attention) ; **la LÉGENDE MÉTIER garde
     ses trois couleurs nommées**, désaturées pour vivre avec elles, mais reconnaissables comme
     leur nom. Elles ne peignent QUE des niveaux — jamais un fond de page, jamais un contrôle.
     RAMPE MONOTONE, dans les deux thèmes : le rouge est TOUJOURS le plus loin de la page
     (clair L* 52 → 45 → 38 ; sombre 66 → 70 → 74). Elles se lisent donc aussi en niveaux de gris.
     ⚠ LA LEÇON, pour la prochaine palette : avant de retirer une couleur, chercher si le PRODUIT
     l'écrit en toutes lettres. Une contrainte de vocabulaire ne se voit dans aucune mesure. */
  --green:#59875e; --green-bg:#e0efe1; --orange:#8c6224; --orange-bg:#fae8d5; --red:#993a3b; --red-bg:#ffe4e1;
  --blue-bg:#dfedf7;
  /* ── BANDES DE FATIGUE — UNE ÉCHELLE, DONC UNE RAMPE DE CLARTÉ (01.08) ────────────────────
     Une échelle séquentielle ne se code pas par la TEINTE seule. Les deux palettes qui ont
     existé ici étaient construites sur la teinte, et TOUTES DEUX étaient illisibles en gris —
     mesuré au navigateur, luminance sur 255 :
       · ce que la bande peignait vraiment (--green/--orange/--red) : 160,3 · 160,6 · 131,9
         → calme et vigilance séparés de **0,3 sur 255**. Le même gris, exactement.
       · la famille --fat-* déclarée ici (et jamais utilisée) : écarts de 0,5 et 0,6.
     Autrement dit la palette DOCUMENTÉE était aussi cassée que celle en service ; adopter l'une
     pour l'autre n'aurait rien réglé. Le défaut n'était pas le choix des jetons, c'était le
     principe de construction.
     RAMPE : L* CIE régulier, un cran de 12 entre bandes voisines — écarts en gris désormais de
     31 à 37. Le voyage de teinte vert→ambre→rouge est CONSERVÉ (il porte le sens appris) ; c'est
     la clarté qui fait le travail, donc la bande se lit aussi en niveaux de gris, en daltonisme,
     et sur un écran de nuit mal réglé.
     PRINCIPE, valable dans les deux thèmes : PLUS C'EST CHAUD, PLUS C'EST LOIN DE LA PAGE.
     En clair la page est blanche → le calme est le plus pâle, le risque le plus sombre.
     En sombre la page est noire → l'ordre s'inverse, et ce n'est pas une inversion mécanique :
     le calme est l'état le PLUS FRÉQUENT, il reste donc discret la nuit, et c'est l'alarme qui
     brille. Chroma modéré près du blanc (une teinte pâle très saturée vire au fluo).
     `--fat-extreme` EST RETIRÉ : `fatigue.bande()` ne renvoie que vert/orange/rouge — aucun
     chemin de code ne pouvait produire une quatrième bande. C'était une valeur morte, comme
     l'indigo que DESIGN.md signale déjà. */
  /* 01.08 (soir) — LE CELADON DEVIENT LA BANDE CALME. Il était à ΔL* 3,4 et 1,4° de teinte de
     l'ancienne : deux noms pour une couleur. La rampe est RECONSTRUITE autour de lui pour garder
     le pas de L* 12 : 80,5 · 68,4 · 56,5 (pas de 12,1 et 11,9). Teintes du voyage vert→ambre→rouge
     conservées. Encre #14151a : 10,87 · 7,56 · 5,12 sur les trois. */
  --fat-calme:#b2d5b4; --fat-vigil:#d6af81; --fat-risque:#dc8b86;
  /* Encre des trois aplats. Elle NE BASCULE PAS : les trois aplats sont clairs dans les deux
     thèmes, donc son fond ne bascule pas non plus (même raisonnement que `--sur-pale`).
     Mesurée sur les six aplats : 4,63 au pire, 11,95 au mieux. */
  --fat-ink:#02111b;
  /* FRISE DE ROTATION. L'alternance 4+4 était peinte en --accent (SMUR) contre --violet (bloc) :
     deux violets voisins, illisibles côte à côte sur 53 semaines — on ne VOYAIT pas l'alternance.
     Règle retenue : le SMUR est COLORÉ (il est chez nous), l'ailleurs est SOURD (bloc = ardoise,
     urgences = sarcelle). Le contraste chaud/froid fait apparaître les blocs de 4 semaines.
     ⚠ LE CONTRASTE CHAUD/FROID NE SUFFISAIT PAS (01.08). Ce commentaire affirmait que
     l'alternance 4+4 « se voyait » depuis qu'on opposait l'ardoise à la sarcelle. Mesuré :
     ΔL* 2,4 en clair et 2,9 en sombre — deux teintes différentes, une seule CLARTÉ. En niveaux
     de gris, sur un écran de nuit mal réglé ou pour un daltonien, la frise redevenait ce qu'elle
     était avant le correctif : une bande unie sur 53 semaines. C'est le même défaut que les
     bandes de fatigue et que les postes, sur une troisième famille — d'où l'invariant I, qui les
     BALAIE toutes au lieu d'attendre qu'on y pense. Clartés écartées à ΔL* 9,2, teintes gardées.
     Ces deux teintes ne portent jamais de texte (la légende est à côté du pavé, pas dedans) :
     aucune encre à réapparier. */
  /* ⚠ LE FOND NE DOIT PAS CRIER PLUS FORT QUE LE SUJET (01.08, après retour de Rémy : « la
     couleur n'est pas si facile à lire »). La frise répond à « QUI EST AU SMUR, QUAND ». Or « aux
     urgences » est l'état par DÉFAUT du CDC — le sous-titre le dit : « le reste du temps aux
     urgences » — et il occupait jusqu'à 95 % de la surface en sarcelle PLEINE, mesurée à
     saturation 0,47 contre 0,25 pour l'accent du SMUR. La condition la moins intéressante était
     la plus criante, et ce qu'on vient chercher se noyait dedans : un mur de couleur, pas une frise.
     L'intention était pourtant écrite dans `ROTC` depuis le début — « SMUR = COLORÉ (il est chez
     nous) · ailleurs = SOURD ». Écrite, jamais tenue. Les deux « ailleurs » deviennent donc de
     vrais fonds (saturation 0,21 et 0,16), et le SMUR reste le seul aplat vif — et l'EXTRÊME de la
     rampe de clarté, ce qui le fait lire comme figure. Teintes conservées (sarcelle / ardoise) :
     on baisse la CHROMA et on écarte la CLARTÉ, on ne change pas l'identité des états.
     Clartés L* : hors tournus 95,5 · urgences 84,0 · bloc 75,5 · SMUR 46,6 (écarts 28,9 · 8,4 · 11,5). */
  --rot-anesth:#bbbbbf; --rot-urgences:#658092;
  /* LES DEUX NEUTRES DE SÉRIE (29.07). `#9aa0ab` était répété 8 fois dans `console_app.js`,
     `#9a9a9a` 4 fois et `#c08a3c` 3 fois — trois littéraux pour deux rôles : « rien à signaler »
     et « à surveiller, mais sans alarme ». Les deux gris étaient à deux unités l'un de l'autre :
     ils fusionnent. VOLONTAIREMENT identiques dans les deux thèmes, comme la palette de frise :
     une série doit rester reconnaissable d'un thème à l'autre. Ce sont des APLATS — ils peignent
     des barres et des points ; leur ENCRE passe par `encreDe` (console_app.js). */
  /* ⚠ `--serie-neutre` BASCULE DÉSORMAIS (02.08). Le commentaire ci-dessus dit « volontairement
     identiques dans les deux thèmes » — c'était vrai tant qu'il ne peignait que des points et des
     barres de série sur fond clair. Depuis que la jauge « atteint » du tableau hélico le porte, il
     est un APLAT posé sur la carte : mesuré **2,63:1 sur le blanc**, sous le plancher de 3:1. Il
     suit donc son fond, comme les axes.
     ⚠ ET L'AMBRE AUSSI — j'avais écrit ici même « il reste figé : 3,03:1, au-dessus ». C'était
     mesuré contre le BLANC, pas contre la FEUILLE, où il tombe à 2,71:1. L'invariant N m'a pris
     en défaut sur la ligne que je venais d'écrire : mesurer contre le mauvais fond, c'est ne
     rien mesurer (règle 13). */
  --serie-neutre:#8b8b8f; --serie-ambre:#7e784f;
  --fat-hd:#e3ecf4; --fat-hd-ink:#02111b; --fat-cell-line:#dfe6ec;
  --hover:rgba(2,17,27,.05);  /* survol de ligne / cellule (teinté à l'encre, adapté par le dark) */
  /* ── COULEURS DE POSTE — LA TEINTE DIT QUEL POSTE, LA CLARTÉ DIT COMBIEN IL PÈSE (01.08) ───
     SSOT visuelle du calendrier, de la légende et des tags, sur la console ET sur le portail.

     ⚠ ELLES ÉTAIENT QUATRE FOIS LA MÊME COULEUR. Mesurés au navigateur, les écarts de clarté
     entre voisines : 0,7 · 0,9 · 1,6 en clair (L* 93,6 → 95,5) et 0,7 · 1,0 · 1,3 en sombre,
     soit une étendue de 1,4 SUR 255 en niveaux de gris. Le 0,3 sur 255 séparant --sh-h de
     --sh-n en sombre est EXACTEMENT le chiffre que DESIGN.md cite comme preuve du défaut des
     bandes de fatigue — corrigé le 01.08 au matin, quelques lignes plus haut, dans ce fichier.
     Conséquence à l'écran : le calendrier était teinté sans être lisible. Pour savoir quel poste
     on regardait il fallait lire la lettre (« J · », « N · », « H · ») ; la couleur ne portait
     rien. C'est la définition d'une couleur décorative, ce que ce système dit refuser.

     LA RAMPE. Les quatre postes gardent leur TEINTE — le pourpre de l'hélico est une convention
     du service, il ne bouge pas — et reçoivent une seconde dimension : la CLARTÉ, qui ordonne
     jour → soir → nuit → hélico. L'ordre n'est pas décoratif, c'est le poids réel d'une garde :
     le jour est l'ordinaire, la nuit pèse (+15 %, cf. heures_poste), l'hélico engage une
     compétence qu'aucun forçage ne contourne. Plus le poste engage, plus il s'écarte de la page.
     Pas de ΔL* 4,0 en clair — au-dessus du ΔL* 3,5 que le thème clair s'impose déjà entre deux
     plans de travail. Le chroma monte à mesure qu'on descend : un ton pâle simplement assombri
     vire au gris, et l'on aurait remplacé quatre blancs par quatre gris.
     Tenu par l'invariant I de check_charte.py, qui balaie TOUTES les familles de couleur — la
     règle du 01.08 n'avait été appliquée qu'à celle qui l'avait inspirée.

     ENCRES APPARIÉES : inchangées, sauf --sh-ht. Le pourpre #8e44ad tombait à 3,59:1 sur l'aplat
     hélico devenu plus dense ; assombri À TEINTE CONSTANTE (le geste déjà posé le 28.07 pour
     --red-ink / --green-ink / --orange-ink), il mesure 4,61:1 sur son aplat, 6,58:1 sur la
     feuille et 7,18:1 sur la surface. Mesuré, jamais supposé. */
  /* ══ L'HÉLICO GARDE SON POURPRE (02.08, demande de Rémy) ═══════════════════════════════════
     Le portage sur quatre couleurs avait fait des quatre postes une rampe d'une SEULE teinte, et
     le pourpre était tombé avec les autres. Il revient — mais **sans quitter son barreau** : la
     rampe de clarté reste la structure (jour 92 → soir 87,5 → nuit 82 → hélico 76 en clair ;
     20 → 24,5 → 29 → 33,5 en sombre), et le pourpre est posé À la clarté de l'hélico, pas à la
     place de la clarté. La teinte (h 316) est celle du pourpre historique du service ; c'est sa
     CLARTÉ qui dit le poids du poste, sa teinte qui dit lequel c'est.
     Mesuré : encre 5,07:1 sur son aplat en clair, 5,71:1 en sombre ; ΔL* avec la nuit 6,07 et
     4,45 — au-dessus du plancher de 3,5 que l'invariant I impose à toute la famille `--sh-*`. */
  /* ══ LE SOIR PREND L'HEURE DORÉE (02.08, demande de Rémy) ══════════════════════════════════
     Comme le pourpre de l'hélico, cet ambre est posé À la clarté du soir, pas à la place de la
     clarté : la rampe tient (jour 92,1 → soir 86,5 → nuit 82,1 → hélico 76 en clair ; 19,9 →
     25 → 29,1 → 33,4 en sombre, écarts de 4,1 à 5,5). Deux postes portent donc une teinte propre
     — le soir et l'hélico — et deux restent sur l'acier : la teinte identifie, la clarté pèse.
     ⚠ EFFET DE BORD MESURÉ, ET CORRIGÉ ICI : en thème sombre, l'aplat du soir (L* 25) tombait
     sur `--orange-bg` (L* 24,05), même teinte chaude — un fond de vigilance et une garde du soir
     peuvent cohabiter dans une même cellule de calendrier. Le lavis de vigilance est descendu à
     L* 20 (ΔL* 4,9), son encre y gagne d'ailleurs : 6,44:1 contre 5,66.
     Encres mesurées sur leur aplat : 5,50:1 en clair, 6,57:1 en sombre. */
  --sh-j:#deeaf3; --sh-jt:#395e74; --sh-s:#fdd1a3; --sh-st:#6c4c24; --sh-n:#b4d0e4; --sh-nt:#295269; --sh-h:#cdb2da; --sh-ht:#583769;   /* hélico = POURPRE (convention) */
  --bleu:#43687e;
  /* ENCRES DE SIGNAL (28.07). Le vert, le rouge et l'ambre sont définis comme des APLATS —
     ils sont justes en fond. Posés comme ENCRE sur la feuille claire, aucun n'atteint 4,5:1 :
     le rouge plafonnait à 4,09 et servait de texte 140 fois. Ces variantes assombries ne
     servent QU'AU TEXTE ; les aplats gardent leur valeur, donc le monde visuel ne bouge pas.
     C'est le symétrique de `encre-sur-*`, qui règle le cas inverse (encre claire sur aplat).
     Calculées, pas choisies : plancher 4,6:1 sur la feuille, la surface et l'aplat pâle du
     signal lui-même. En thème sombre elles valent le signal, qui y est déjà lisible. */
  --red-ink:#993a3b; --green-ink:#3d6e44; --orange-ink:#845b1d; --violet-ink:#43687e;   /* compat : l'ancien bleu marine de la console suit l'accent — devenu teal le 01.08 */
  /* ENCRES DES SIX AXES D'ÉQUITÉ (29.07). Elles vivaient dans une table JS (`EQFIFA_ENCRE`),
     dont le commentaire disait lui-même qu'elles étaient « calculées, plancher 4,6:1 sur la
     feuille et sur la surface blanche » — donc pour le thème CLAIR uniquement. Posées telles
     quelles sur la carte sombre, les six chiffres du diagnostic d'équité tombaient à 3,5:1.
     C'est l'angle mort déclaré de `check_charte` : une encre sur un fond calculé en JS.
     Ici, ce sont des JETONS : le thème les bascule, et il n'y a qu'un endroit où les lire.
     Les APLATS, eux, restent en JS et ne basculent pas — une série doit rester discernable
     d'elle-même d'un thème à l'autre. Seule l'encre suit son fond. */
  /* ── LES SIX AXES D'ÉQUITÉ ENTRENT DANS LA CHARTE (02.08, signalé par Rémy) ──────────────
     Ils vivaient dans une table JS (`EQFIFA`, console_app.js) : six teintes vives choisies
     hors palette, jamais mesurées entre elles, et invisibles pour l'invariant I — qui balaie
     les JETONS, pas les tables JS. Mesuré sur l'écran Équité après la refonte : six aplats
     saturés, dont CINQ hors palette. C'est l'angle mort que J avait été inventé pour couvrir,
     mais J ne lit que `ROTC` ; la seconde famille peinte en JS lui échappait.
     Ils deviennent donc des JETONS — l'invariant I les balaie par le préfixe `--eq-ax-`, et un
     septième axe ajouté demain entrera dans la famille tout seul. Teintes ancrées sur la
     palette (rosewood 16° · ambre 72° · celadon 148° · sarcelle 175° · teal 213° · indigo
     289°) et surtout ÉCARTÉES EN CLARTÉ : pas de L* 5,0 entre voisines, contre 0,4 à 2,1
     auparavant. La frise se lit désormais en niveaux de gris — ce que six teintes vives à
     clarté égale ne permettaient pas, malgré leur vivacité.
     ⚠ ILS BASCULENT — J'AVAIS ÉCRIT L'INVERSE ICI MÊME, ET C'ÉTAIT FAUX (02.08, signalé par
     Rémy : « je t'ai pointé les mauvaises couleurs sur fond sombre »). J'avais gelé les six aplats
     « pour qu'une série reste reconnaissable d'un thème à l'autre » — un principe hérité, et juste
     en soi. Mais une VALEUR UNIQUE ne peut pas tenir 3:1 contre un fond L* 100 ET contre un fond
     L* 13,4. Mesuré : en SOMBRE `--eq-ax-helico` tombait à **2,65:1** sur la carte (la barre
     disparaissait) ; en CLAIR `--eq-ax-jours` à **2,52:1** et le neutre de série à **2,63:1** —
     donc la jauge « atteint » que je venais de poser sur le tableau hélico était elle-même sous le
     plancher. Le défaut était dans les DEUX thèmes, pas seulement celui qu'on regardait.
     C'est EXACTEMENT l'erreur du rail teal, commise deux heures plus tôt dans la même session sur
     une autre famille : une encre — un aplat ici — se calcule contre SON fond.
     Ce qui porte l'identité d'une série, ce n'est pas la valeur : c'est la TEINTE et l'ORDRE de
     clarté. Les deux sont conservés (helico < feries < heures < nuits < we < jours) ; seule
     l'échelle se déplace — L* 38→58 en clair, 55→75 en sombre. Plancher 3:1 contre la carte ET
     contre la piste de la jauge (WCAG 1.4.11, élément non textuel), tenu par l'invariant N. */
  --eq-ax-helico:#88898c; --eq-ax-feries:#5f5b33; --eq-ax-heures:#26526b;
  --eq-ax-nuits:#4a697e; --eq-ax-we:#6b8291; --eq-ax-jours:#797346;
  --eq-ink-heures:#26526b; --eq-ink-nuits:#4a697e; --eq-ink-we:#576d7d;
  --eq-ink-feries:#5f5b33; --eq-ink-helico:#6a6a6e; --eq-ink-jours:#716c3f;
  /* sidebar — neutre profond, plat (plus de dégradé navy) */
  /* 28.07 — MÊME CORRECTIF QUE LE PORTAIL, ET VOILÀ POURQUOI IL A FALLU L'ÉCRIRE DEUX FOIS.
     `--side-ink-soft` valait #7d7f8a : mesuré 4,27:1 sur la charpente #1b1c21 et 3,62:1 sur la
     pastille de rôle — sous 4,5 dans les DEUX thèmes. « Déconnexion » et l'onglet de rôle inactif
     étaient illisibles. La charpente est sombre quel que soit le thème : son encre se calcule
     contre SON fond, pas contre le thème. #9a9ca6 → 6,30:1 et 5,24:1.
     ⚠ Ce bloc et celui de portail_med.html sont DEUX copies du même monde : corrigé le matin dans
     le portail, le défaut vivait encore ici l'après-midi, dans la console. C'est le doublon qu'on
     résorbe juste en dessous (CARTOUCHE_CSS, servi aux deux pages). */
  /* 01.08 (soir) — LA CHARPENTE PASSE AU SPACE-INDIGO. Elle s'ÉCLAIRCIT : L* 10,4 → 20,5. C'est
     la conséquence la plus visible du choix de palette, et elle a été signalée avant : le cartouche
     n'est plus un quasi-noir, c'est une ardoise profonde. L'ordre des plans tient toujours
     (charpente 20,5 < feuille 95,6 < surface 100), et la règle du cartouche ne bouge pas : ce noir
     bleu porte la charpente et rien d'autre. Encre 10,51:1, atténuée 6,00:1, rail teal 6,34:1 —
     mesurés contre SON fond, jamais contre le thème. */
  --side-1:#02111b; --side-2:#141f26; --side-3:#09161d; --side-line:#2d3b44; --side-ink:#ffffff; --side-ink-soft:#aaabae;
  /* formes */
  /* LES FORMES SE DURCISSENT (29.07, reset visuel). 8/6/4 → 4/3/2. Un angle très arrondi
     matelasse, et un outil de planification n'a rien à amortir : c'est la signature du tableau de
     bord SaaS que ce système dit refuser depuis le premier jour. Le durcissement se lit surtout
     là où la forme se RÉPÈTE — cellules de calendrier, pastilles, cartes de mesure. Seule la
     pastille d'état reste pleinement ronde : sa forme porte du sens (« la règle du niveau rond »). */
  --radius:4px; --radius-s:3px; --radius-xs:2px;
  /* L'ANNEAU DE FOCUS EST UN JETON (01.08). Il était écrit EN DUR huit fois — cinq ici, deux dans
     le portail, une dans console_app.js — toutes à l'ancienne ardoise rgba(92,110,153,.18). Un
     changement d'accent laissait donc huit anneaux sur l'ancienne couleur, et rien ne pouvait le
     signaler : ce n'est ni un `color:` ni un `background:`, aucun invariant ne le regardait.
     Il se DÉRIVE de l'accent, comme la lueur du cartouche. */
  /* L'ENCRE DE LA NAVIGATION (02.08). Depuis que la navigation sort du coloriage, elle a besoin
     d'une encre à elle : elle n'est ni l'encre du texte (elle doit rester en retrait de l'onglet
     courant) ni l'encre atténuée du thème — en sombre, celle-ci est un GRIS, et Rémy veut du
     BLANC : « en mode sombre cela doit être en blanc les écritures ». Un jeton, deux valeurs,
     mesurées contre le plan qui les porte. */
  --nav-ink:#c0c1c4;
  --anneau:0 0 0 3px rgba(135,160,178,.42);
  /* LE CONTOUR D'UN CONTRÔLE (01.08). « Seuls les cliquables sont colorés » ne se joue pas que
     dans l'encre : un bouton fantôme au filet neutre reste un rectangle inerte. Son contour prend
     donc l'accent, très dilué — assez pour dire « ceci se presse », pas assez pour crier. */
  --accent-bord:rgba(67,104,126,.34);
  --shadow:0 1px 2px rgba(2,17,27,.06);
  --shadow-s:0 1px 1px rgba(2,17,27,.05);
  /* LE VOILE (29.07). Le système déclarait ses ombres et pas ses VOILES : chaque écran modal en
     inventait un — rgba(15,23,42,.12), rgba(10,14,30,.55), rgba(10,10,20,.42) : trois bleus nuit
     différents, aucun dans la palette. C'est le trou qu'un faux positif du détecteur avait mis au
     jour (« hors palette » : la règle n'avait rien à quoi comparer). Comme une ombre, un voile se
     teinte à l'ENCRE, jamais à une couleur d'ambiance. Deux profondeurs : le voile léger d'un
     traitement en cours, le voile franc d'une boîte de dialogue. */
  --voile:rgba(2,17,27,.30); --voile-fort:rgba(2,17,27,.58);
  --font:'Archivo',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;
  /* RESET DU 29.07 — « la typographie devient éditoriale » (DESIGN.md). Le display passe de
     Fira Sans à NEWSREADER, une serif de presse : un planning est un document qu'on LIT, pas un
     tableau de bord qu'on surveille. Le contraste serif/monospace remplace le contraste bloc/fond
     qu'on vient de retirer des contrôles. Replis en serif système, jamais en sans. */
  --display:'Newsreader',Georgia,'Times New Roman',serif;
  /* LA CHASSE FIXE EST UN JETON (29.07). Elle était réécrite en toutes lettres 20 fois dans cette
     feuille et dans le portail — c'est-à-dire 20 endroits à corriger le jour où la pile de repli
     change, et 20 occasions de diverger (règle 9). Elle porte trois métiers : la légende, la
     marginalia, et depuis le reset les HORAIRES — `07:30→07:30` s'aligne d'une ligne à l'autre. */
  --mono:'Space Mono',ui-monospace,Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
body{font-family:var(--font);background:var(--bg);color:var(--ink);font-size:14px;line-height:1.55;
  font-weight:400;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;letter-spacing:-.05px;margin:0}
/* ⚠ UN CONTRÔLE N'HÉRITE PAS DE LA POLICE DU DOCUMENT (29.07, trouvé par la passe d'audit de la
   vue « Générer »). Le navigateur impose sa propre face aux `button`, `input`, `select` et
   `textarea` — sur macOS, Arial 13,33 px. Les classes qui pensaient à écrire `font-family:inherit`
   allaient bien (`.ui-btn`, `.btn`, `.seg button`) ; `button.go` — LA classe de bouton la plus
   employée de la console — ne le faisait pas. Tous ses boutons étaient donc composés en ARIAL,
   dans une application dont la charte déclare trois familles choisies. Le défaut ne se voyait pas
   parce qu'une grotesque ressemble à une autre en 12,75 px ; il s'est vu en le MESURANT.
   Corrigé à la racine plutôt que classe par classe : tout contrôle hérite, désormais et pour tout
   contrôle écrit demain. Les champs qui veulent la chasse fixe la redemandent plus bas. */
button,input,select,textarea{font-family:inherit}
h1,h2,h3,.display{font-family:var(--display);font-weight:600;letter-spacing:-.3px}
/* Un lien ne se teinte plus : il se SOULIGNE. C'est l'affordance la plus ancienne du web, et
   elle ne coûte pas une couleur. Le survol épaissit le filet et le passe à l'accent. */
a{color:var(--ink);text-decoration:none;box-shadow:inset 0 -1px 0 var(--silver)}
a:hover{box-shadow:inset 0 -2px 0 var(--accent)}
a.hb-link,a.sb-link,a.go,a.ui-btn,a.btn,a.porte,a.lg2-lien{box-shadow:none}
a.hb-link:hover,a.sb-link:hover,a.go:hover,a.ui-btn:hover,a.btn:hover,a.porte:hover{box-shadow:none}

/* ---------- layout coquille ---------- */
.shell{display:grid;grid-template-columns:248px 1fr;min-height:100vh}
.sb{background:var(--side-1);color:var(--side-ink);
  display:flex;flex-direction:column;position:sticky;top:0;height:100vh;border-right:1px solid var(--side-line)}
.sb-brand{display:flex;align-items:center;gap:11px;padding:18px 18px 16px}
/* LA MARQUE N'EST PLUS UN CARRÉ COLORÉ (29.07). Un carré arrondi teinté portant une initiale est
   le logotype par défaut de toutes les interfaces générées — et il posait, en prime, le plus gros
   aplat d'accent permanent de l'écran, présent sur CHAQUE page. Il devient une capitale gravée :
   la serif du display, un filet d'un pixel, un angle presque droit. L'écusson du service reste
   l'identité qui gouverne le DISCOURS ; il n'a jamais eu à colorer un carré de 32 px. */
.sb-logo{width:32px;height:32px;border-radius:var(--radius-xs);background:transparent;border:1px solid var(--side-line);
  display:grid;place-items:center;font-family:var(--display);font-weight:600;color:var(--cartouche-ink);font-size:15px;letter-spacing:0}
.sb-brand b{color:var(--cartouche-ink);font-size:15px;font-weight:600}
.sb-brand span{display:block;font-size:11px;color:var(--side-ink-soft)}
.sb-nav{padding:6px 10px;overflow:auto;flex:1}
.sb-grp{font-size:11px;text-transform:uppercase;letter-spacing:.7px;color:#647691;margin:15px 12px 4px;font-weight:700}
.sb-grp-d{display:block;font-size:11px;text-transform:none;letter-spacing:0;color:#9aa7bd;font-weight:500;margin-top:1px}
.sb-link{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:var(--radius);color:var(--cartouche-ink);
  text-decoration:none;font-size:13.5px;font-weight:500;cursor:pointer;margin:2px 0;transition:.15s;border:none;background:none;width:100%;text-align:left}
.sb-link svg{width:17px;height:17px;flex:none;opacity:.85}
.sb-link:hover{background:rgba(255,255,255,.06);color:var(--cartouche-ink)}
.sb-link.on{background:rgba(255,255,255,.11);color:var(--cartouche-ink);box-shadow:inset 2px 0 0 var(--accent)}
.sb-link .pillN{margin-left:auto;background:var(--red);color:var(--on-red);font-size:11px;font-weight:700;padding:1px 7px;border-radius:20px}
.sb-who{border-top:1px solid var(--side-line);padding:12px 16px;display:flex;align-items:center;gap:10px}
.sb-who .av{width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.08);display:grid;place-items:center;color:#e7e8ee;font-weight:600;font-size:13px}
.sb-who b{color:#e7eefb;font-size:13px;font-weight:600} .sb-who small{display:block;color:var(--side-ink-soft);font-size:11px}

.main{display:flex;flex-direction:column;min-width:0}
/* 0,82 d'opacité ne masquait pas assez : le contenu défilait DESSOUS et restait
   fantomatiquement lisible à travers la barre. `DESIGN.md` proscrit le verre dépoli
   DÉCORATIF ; ici il ne l'est pas, mais il doit faire son travail — 0,96 laisse la
   sensation de matière sans laisser passer le texte. */
.tb{position:sticky;top:0;z-index:5;background:rgba(255,255,255,.96);backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line);display:flex;align-items:center;gap:14px;padding:13px 26px}
.tb h1{font-size:26px;margin:0;font-weight:700;letter-spacing:-.02em}
.tb .sub{color:var(--ink-soft);font-size:11px;margin-top:1px}
.tb .spacer{flex:1}
/* LA LIGNE DE CARTOUCHE (01.08). L'en-tête de page empilait TROIS lignes — le titre, le
   sous-titre, puis « à jour 21:47 » sur une quatrième voix (11,5 px, sans-serif, sa propre
   couleur). Trois voix pour situer un écran, dans la bande la plus chère de l'application : elle
   se répète sur les 34 écrans, et le contenu commençait 208 px plus bas.
   Un cartouche de carte porte le titre ET sa date d'édition SUR LA MÊME LIGNE, séparés d'un
   filet. C'est ce que fait cette rangée : sous-titre · fraîcheur · marqueur, une seule voix
   (la meta monospace de `DESIGN.md`), un seul filet vertical entre deux mentions. 22 px repris
   sur chaque écran, et une graduation de moins à lire. */
.tb-meta{display:flex;align-items:center;flex-wrap:wrap;gap:0 10px;margin-top:3px;min-width:0}
.tb-meta>*{min-width:0}
/* Le sous-titre et son filet séparateur ont quitté cette rangée le 01.08 (couche de slogans) :
   leurs règles partent avec eux — une classe sans porteur est une ruine qu'on croit vivante. */
@media (max-width:620px){ .tb-meta{row-gap:2px} }
/* La fraîcheur parle désormais la MÊME langue que le sous-titre (meta monospace, 11 px, capitales,
   +0,04em) au lieu de sa quatrième voix à 11,5 px. Elle reste au plancher documenté, jamais en
   dessous. Le point garde sa transition : c'est lui qui pulse quand une donnée vient de changer. */
#tb_fresh{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:11px;
  letter-spacing:.04em;text-transform:uppercase;color:var(--ink-soft);transition:color .4s}
#tb_fresh_dot{width:7px;height:7px;border-radius:50%;background:var(--ink-soft);flex:none;
  display:inline-block;transition:background .4s,box-shadow .4s}
.content{padding:22px 26px 44px;max-width:1280px;width:100%}

/* ---------- sous-onglets (segmented) ----------
   UNE SEULE GRAMMAIRE D'ÉTAT, À TOUTES LES LARGEURS (29.07, reset visuel). L'actif se disait de
   DEUX façons selon la largeur : aplat d'ardoise sous 881 px, soulignement au-dessus. Deux
   grammaires pour un même état — et c'est la mauvaise qui s'affichait au téléphone, là où le
   portail est le plus utilisé. Désormais, partout et pour tous les sélecteurs : SOULIGNEMENT de
   2 px, encre pleine, graisse 600. Rien d'autre ne change entre l'état inactif et l'état actif,
   et c'est suffisant — c'est même la seule chose qui se lit du premier coup d'œil dans une rangée.
   La BOÎTE disparaît aussi : une rangée d'onglets n'a pas besoin d'être encadrée, un filet dessous
   suffit et il aligne les onglets sur le corps de la page. */
.seg{display:inline-flex;gap:2px;background:transparent;border:none;border-bottom:1px solid var(--line);border-radius:0;padding:0;flex-wrap:wrap;margin-bottom:16px}
/* ⚠ L'INVERSION DES ONGLETS DU 01.08 EST ANNULÉE (02.08) — voir la note de `.hb-link`.
   J'avais coloré l'onglet inactif « puisqu'il est cliquable ». Sur l'espace Planifier cela
   faisait HUIT sous-onglets teal d'affilée : un ruban de couleur en travers de la page, pour
   dire une chose que le filet de 2 px disait déjà. Retour à la grammaire du 29.07 : l'inactif
   en encre atténuée, le courant en encre pleine, soulignement de 2 px. */
.seg button{border:none;background:none;padding:9px 14px;border-radius:0;font-size:13px;font-weight:500;color:var(--nav-ink);cursor:pointer;font-family:inherit;transition:.12s}
.seg button:hover{color:var(--ink)}
.seg button.on{background:transparent;color:var(--ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--accent)}
.seg.sub{background:transparent;border:none;border-bottom:1px solid var(--line);border-radius:0;padding:0;gap:0}
.seg.sub button{background:none;border:none;font-size:13.5px;font-weight:500;padding:11px 0;border-radius:0;color:var(--nav-ink)}
.seg.sub button:hover{background:transparent;color:var(--ink)}
.seg.sub button.on{background:transparent;color:var(--ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--accent)}

/* ---------- boutons ---------- */
/* ── LA COULEUR CLASSE, ELLE NE SIGNALE PAS (02.08) ─────────────────────────────────────────
   Troisième et dernier recul sur « tous les cliquables sont colorés ». Sur la file « à traiter »
   du Hub, SIX boutons portaient l'accent — encre ET contour, donc la couleur posée deux fois
   par bouton, six fois de suite. Plus rien ne classait : la couleur éclairait tout au lieu de
   désigner. Et sur le quasi-noir du thème sombre, six contours cyan à L* 72 font le « poste de
   pilotage néon sur noir » que ce système nomme explicitement comme contre-référence.
   La charte le disait déjà, depuis le reset du 29.07 : **un seul bouton principal par écran**.
   Le fantôme redevient donc un fantôme — encre du texte, contour au filet — et l'accent reste
   au SEUL bouton principal, qui le porte trois fois (contour à l'encre d'action, filet de 2 px,
   graisse 600). Sur la capture de Rémy, l'œil va enfin à « Voir la fatigue », c'est-à-dire à la
   seule décision urgente — celle que sa ligne signale déjà par son fond.
   Les LIENS gardent l'accent : un lien dans une phrase n'a aucune autre affordance. */
.ui-btn{background:transparent;border:1px solid var(--line);border-radius:var(--radius);padding:6px 12px;font-size:12.75px;font-weight:500;cursor:pointer;color:var(--ink);
  display:inline-flex;align-items:center;gap:6px;line-height:1.35;letter-spacing:-.1px;transition:.12s;font-family:inherit}
.ui-btn:hover{background:var(--hover);border-color:var(--silver)}
/* L'ACTION PRINCIPALE EST UN TAMPON, PAS UNE PASTILLE (29.07, reset visuel). Plus d'aplat : elle
   se distingue par TROIS choses simultanées — un contour à l'ENCRE PLEINE (et non au filet), un
   soulignement interne de 2 px en ardoise, et la graisse à 600. Sur fond identique au fantôme,
   c'est la force du contour qui la désigne, et le filet d'accent qui dit « c'est celle-là ».
   Testé au gris : les trois signaux survivent, ce qu'un aplat coloré ne garantissait pas. */
/* ── LE CLIQUABLE SE DIT PAR UN BOUTON, PAS PAR UNE TYPOGRAPHIE (02.08, décision de Rémy) ───
   « Pas fan de cette typo en bleu comme ça… retire-la partout et fais des boutons de couleur
   si tu veux faire du cliquable. Reviens sur du simple, beau, épuré. »
   102 encres d'action sont redevenues l'encre du texte. Ce qui porte la couleur, désormais,
   c'est UN OBJET — l'action principale, en aplat plein — et non des mots teintés éparpillés.
   ⚠ CECI REVIENT SUR LE RESET DU 29.07 (« l'accent ne remplit plus, il souligne »), et c'est
   la même personne qui l'avait demandé puis l'annule, en connaissance de cause. Ce que le
   reset combattait n'était pas l'aplat en soi : c'étaient CINQ aplats simultanés à 375 px.
   La règle qui reste, et que l'invariant G tient désormais, est le vrai remède : **un seul
   contrôle par écran porte un aplat d'accent — l'action principale, et rien d'autre.**
   Encres mesurées sur l'aplat : 4,81:1 en clair (blanc sur #087e8b), 8,62:1 en sombre. */
.ui-btn.primary{background:var(--accent);color:var(--on-accent);border-color:transparent;font-weight:600;box-shadow:none}
.ui-btn.primary:hover{background:var(--accent-2);border-color:transparent;box-shadow:none}
.ui-btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.ui-btn.ghost:hover{background:var(--hover);border-color:var(--silver)}
.ui-btn.sm{padding:5px 11px;font-size:12.5px;border-radius:var(--radius)}
.ui-btn:disabled{opacity:.5;cursor:default;transform:none}
/* DESTRUCTIF (charte UX, principe B « sûr par défaut ») : le ROUGE est RÉSERVÉ à ce qui supprime ou
   remplace des données (Supprimer, De zéro). Il ne s'applique JAMAIS à une action courante — ni aux
   boutons « ↩ Annuler », qui sont des SÉCURITÉS (retour en arrière), pas des dangers. Modificateur
   unique, valable sur .ui-btn / .subtab / .go → un seul style destructif dans toute la console. */
.ui-btn.danger,.subtab.danger,.go.danger{color:var(--red-ink);border:1px solid var(--red);background:transparent}
.ui-btn.danger:hover,.subtab.danger:hover,.go.danger:hover{background:var(--red-bg);border-color:var(--red-ink)}

/* ---------- L'ÉTAPE D'UNE CHAÎNE (29.07) ----------
   Pour un écran qui déroule un PROCESSUS — « ① Désidérata », puis « ② Générer & publier ». Deux
   défauts se répondaient sur la vue « Générer » : l'étape ① vivait dans une carte encadrée quand
   l'étape ② n'était qu'une ligne nue, si bien que deux moments de MÊME rang ne se ressemblaient
   pas ; et la carte ajoutait un troisième contour sous deux rangs de navigation déjà encadrés.
   Ici : aucune boîte. Un numéro atténué, un titre en serif, un filet plein sur toute la largeur —
   le filet SÉPARE et le blanc GROUPE, ce qu'un cadre fait moins bien parce qu'il fait les deux à
   la fois. Plus d'espace au-dessus du titre qu'en dessous (34 / 12), comme partout.
   ⚠ Le numéro reste « ① » / « ② » et NON « 01 » / « 02 » : plusieurs messages de l'application
   renvoient à « ② Générer » en toutes lettres (toasts, infobulles). Renuméroter l'écran aurait
   cassé la référence sans que rien ne le signale. */
.etape{display:flex;align-items:baseline;gap:11px;flex-wrap:wrap;margin:34px 0 12px;padding-bottom:9px;
  border-bottom:1px solid var(--line)}
.etape:first-child{margin-top:4px}
.etape .n{font-size:15px;font-weight:400;color:var(--ink-soft);flex:none;line-height:1}
.etape h3{font-family:var(--display);font-size:19px;font-weight:600;letter-spacing:-.01em;margin:0;line-height:1.1}
.etape .sep{flex:1;min-width:8px}
/* Les actions posées sur la ligne d'étape se recentrent sur elle : alignées sur la LIGNE DE BASE
   du titre, un bouton paraît tomber. */
.etape .go,.etape .ui-btn,.etape .act-link,.etape a{align-self:center;margin-top:0;margin-bottom:0}
/* Le corps d'une étape s'aligne sur son titre, sans se refermer dans un cadre. */
.etape-bd{margin:0 0 6px}

/* ---------- LE DÉCLENCHEUR DISCRET (29.07, reset visuel) ----------
   Pour une action secondaire NOMMÉE qui doit rester trouvable sans peser : « Je ne peux plus → ».
   Le bouton fantôme ne convenait pas — sa boîte à filet, posée seule sous un titre, pèse autant
   qu'un bouton principal tout en étant illisible de nuit : encre atténuée sur filet atténué, les
   deux à faible contraste sur la surface. Mesuré sur le portail en thème sombre avant d'y toucher.
   Ici : pas de boîte du tout. L'encre PLEINE (donc le contraste du texte porteur, pas celui d'un
   libellé), un filet d'un pixel sous le texte seul, un chevron fin. Au survol le filet passe à
   l'ardoise et double d'épaisseur — le filet change, jamais la position ni la taille.
   Sa cible tactile passe par une zone de frappe, pas par la police (règle du doigt). */
.act-link{display:inline-flex;align-items:center;gap:7px;background:none;border:none;padding:2px 0;
  font-family:var(--font);font-size:13px;font-weight:600;color:var(--ink);letter-spacing:-.1px;
  line-height:1.6;cursor:pointer;position:relative;
  box-shadow:inset 0 -1px 0 var(--silver);transition:box-shadow .12s cubic-bezier(.22,1,.36,1),color .12s cubic-bezier(.22,1,.36,1)}
.act-link:hover{color:var(--ink);box-shadow:inset 0 -2px 0 var(--accent)}
.act-link:focus-visible{outline:none;box-shadow:inset 0 -2px 0 var(--accent),var(--anneau)}

/* ⚠ UN `role=button` DOIT SE VOIR QUAND ON L'ATTEINT (01.08). Les cartes de groupe et les cartes
   de radar d'Équité viennent de recevoir rôle, tabindex et clavier (`gesteClavier`) : sans anneau,
   on les atteint au clavier sans savoir où l'on est — un focus invisible n'est pas de la
   navigation, c'est de la devinette. Même anneau que les champs et les boutons, pour ne pas
   inventer une troisième signalétique de focus. `:focus-visible` : rien ne s'affiche à la souris.
   ⚠ `outline`, pas `box-shadow` : ces cartes portent DÉJÀ un `box-shadow` (le liseré du panneau),
   qu'une ombre de focus écraserait — et l'anneau doit survivre au mode contraste élevé, qui
   supprime les ombres mais garde les contours. */
[role="button"]:focus-visible{outline:2px solid var(--accent);outline-offset:2px;
  box-shadow:var(--anneau)}
.act-link .chev{width:14px;height:14px;flex:none;stroke-width:1.5;fill:none;stroke:currentColor}
/* La zone de frappe vaut pour TOUS les pointeurs : viser un filet d'un pixel à la souris n'est pas
   agréable non plus, et elle ne déforme rien puisqu'elle est invisible.
   ⚠ ELLE NE S'ÉTENDAIT QUE VERTICALEMENT (31.07). `left:0;right:0` lui donnait la largeur du
   texte : un déclencheur court restait une cible courte — « Voir → » mesuré à 42,4 × 44 px.
   La hauteur était traitée, la largeur pas : le même défaut, à la même date, que la règle
   tactile générale. Elle atteint désormais 44 px dans les DEUX sens, par l'idiome que le
   système emploie déjà pour `.frm-choix` — le glyphe garde sa taille, la cible grandit. */
.act-link::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:100%;min-width:44px;height:44px}

/* L'EXPOSANT EST DU TEXTE D'INTERFACE (31.07). `sup` et `sub` prennent `font-size:smaller` du
   navigateur — mesuré à 10,4 px sur « 1er » dans les règles RH, donc sous le plancher, sans
   qu'aucune déclaration du projet ne le dise. C'est le pendant de l'invariant A étendu aux rem :
   une taille peut être fautive sans être écrite. On pose un plancher, la proportion est gardée
   partout où le parent est assez grand pour la permettre. */
sup,sub{font-size:max(11px,.75em)}

/* ---------- L'HORAIRE EST UNE MESURE (29.07) ----------
   `07:30→07:30` était composé dans la face du display, collé au libellé du poste dans le même
   bloc — donc lu comme la SUITE du titre, alors que c'est une grandeur. En chasse fixe il
   s'aligne d'une ligne à l'autre et la colonne des heures se lit verticalement, ce qu'aucune
   proportionnelle ne permet. C'est l'emploi légitime de la monospace : une donnée, pas un costume. */
.hor{font-family:var(--mono);font-size:13px;font-weight:400;letter-spacing:.02em;color:var(--ink-soft);
  font-variant-numeric:tabular-nums}

/* ---------- cartes ---------- */
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:none}
.panel-hd{padding:14px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px}
.panel-hd h3{margin:0;font-size:14.5px;font-weight:600}
.panel-hd .more{margin-left:auto;color:var(--ink);font-size:12.5px;font-weight:550;cursor:pointer;text-decoration:none}
.panel-bd{padding:16px 18px}
.row{display:grid;gap:16px}
/* UNE PISTE DE GRILLE NE RÉTRÉCIT PAS TOUTE SEULE. Par défaut un élément de grille porte
   `min-width:auto` : il refuse de passer sous la largeur de son contenu, et c'est la PISTE qui
   s'élargit — donc la page entière. Mesuré le 28.07 : dans « Réglages de génération », un
   calendrier poussait un `.panel` à 854 px dans une fenêtre de 760, et toute la console
   glissait latéralement. La rupture à 880 px fonctionnait pourtant : elle passait bien en une
   colonne, mais une colonne trop large. C'est `min-width:0` qui manquait, pas un point d'arrêt. */
.row>*,.cols>*,.grid-kpi>*{min-width:0}
/* Le conteneur à défilement des tableaux larges. Il existait dans le portail depuis le 27.07 et
   PAS dans la feuille partagée : la console n'en avait donc aucun, et sa table « Comptes & accès »
   (7 colonnes, 816 px) poussait la page. La charte : un tableau large défile dans SA boîte, le
   corps de la page jamais. */
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
.grid-kpi{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:15px 16px;box-shadow:none}
.kpi .lab{color:var(--ink-soft);font-size:12px;font-weight:550;display:flex;align-items:center;gap:7px}
.kpi .lab .dot{width:9px;height:9px;border-radius:50%}
.kpi .v{font-family:var(--display);font-size:28px;font-weight:600;margin-top:7px;letter-spacing:-.8px}
.kpi .t{font-size:11px;margin-top:3px;font-weight:550}
.up{color:var(--green-ink)} .down{color:var(--red-ink)} .flat{color:var(--ink-soft)}

/* ---------- aide / note ---------- */
.note{font-size:12.5px;color:var(--ink-soft);background:var(--bg);border:1px solid var(--line);border-radius:var(--radius);padding:9px 13px;margin-bottom:16px;line-height:1.5}
.hint{color:var(--ink-soft);font-size:13px;line-height:1.55;margin-bottom:14px;max-width:760px}

/* ---------- tables ---------- */
.ui-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px}
.ui-table th{text-align:left;font-size:11.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--ink-soft);font-weight:700;padding:10px 14px;border-bottom:1px solid var(--line)}
.ui-table td{padding:11px 14px;border-bottom:1px solid var(--line)}
.ui-table tr:last-child td{border-bottom:none}
/* ---------- LE COMPARATIF (29.07) : `.ui-table.compare` ----------
   Pour choisir ENTRE des options mesurées sur les mêmes critères. Les variantes du solveur étaient
   trois cartes côte à côte, chacune portant six mesures et quatre boutons : dix-huit chiffres et
   douze boutons pour une décision unique — « laquelle je publie ». Et comparer deux cartes oblige
   l'œil à sauter d'une colonne à l'autre en retenant le chiffre, ce qu'un tableau supprime : les
   valeurs d'un même critère s'alignent, et l'écart se VOIT au lieu de se calculer.
   Les nombres passent en chasse fixe et alignés à droite — c'est ce qui les rend comparables ;
   une proportionnelle décale les unités d'une ligne à l'autre. */
.ui-table.compare td.n,.ui-table.compare th.n{text-align:right;font-family:var(--mono);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.ui-table.compare th.n{font-family:var(--mono);font-size:11px;letter-spacing:.05em}
.ui-table.compare td.n{font-weight:700;font-size:13px}
.ui-table.compare .nom{font-family:var(--display);font-size:15.5px;font-weight:600;letter-spacing:-.01em}
/* La ligne recommandée se marque par un FILET en tête de ligne — pas par un fond teinté, qui
   colorerait toute la rangée et rendrait ses chiffres moins lisibles que ceux des autres. */
.ui-table.compare tr.reco td{background:var(--bg)}
.ui-table.compare tr.reco td:first-child{box-shadow:inset 3px 0 0 var(--accent)}
.ui-table.compare td.act{white-space:nowrap;text-align:right}
.ui-table.compare .sous{font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--ink-soft);
  margin-top:3px;display:block;font-weight:400}
/* La colonne des noms se faisait écraser par les colonnes de chiffres — le navigateur répartit la
   largeur au prorata du contenu, et six nombres courts pèsent plus qu'un nom long. « FEASIBLE ·
   optimum non prouvé » retombait alors sur trois lignes et faisait enfler toute la rangée. Elle
   garde un plancher ; les chiffres n'ont besoin que de leur chasse.
   ⚠ MESURÉ, PAS SUPPOSÉ : à 236 px de plancher et 14 px de gouttière, le tableau dépassait la
   colonne à 820 px de fenêtre et « Publier » — l'action principale — partait derrière le
   défilement horizontal. Un tableau peut défiler ; le geste qu'il commande, non. Plancher ramené
   à 200 px et gouttières resserrées : sept colonnes tiennent maintenant sous 820 px. */
.ui-table.compare td:first-child,.ui-table.compare th:first-child{min-width:200px}
.ui-table.compare th,.ui-table.compare td{padding-left:10px;padding-right:10px}
.ui-table.compare th:first-child,.ui-table.compare td:first-child{padding-left:14px}
.ui-table.compare td.act .go{padding:5px 11px;font-size:12.5px}
.ui-table tr:hover td{background:var(--hover)}

/* ---------- chips / pills / badges ---------- */
.chip2{display:inline-flex;align-items:center;gap:6px;background:var(--bg);border:1px solid #e2e5f6;border-radius:20px;padding:3px 11px 3px 9px;font-size:12.5px;font-weight:550;margin:2px}
.pill{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;padding:3px 10px;border-radius:20px}
.pill.ok,.pill.prev,.pill.info{background:var(--bg);color:var(--ink-soft);border:1px solid var(--line)} .pill.todo{background:var(--red-bg);color:var(--red-ink)}
.badge2{display:inline-block;padding:5px 12px;border-radius:var(--radius);font-weight:600;font-size:13px}
.badge2.ok{background:var(--green-bg);color:var(--green-ink)} .badge2.ko{background:var(--red-bg);color:var(--red-ink)}
/* LA PASTILLE IOT — TROIS SILHOUETTES, PAS TROIS TEINTES (29.07). Mesuré : le rouge `#cf4046`
   (L 0,1737) et le vert `#1a874f` (L 0,1811) donnent **1,03:1 ENTRE EUX**. En niveaux de gris —
   le test que DESIGN.md prescrit lui-même — c'était rigoureusement le même point, sur le premier
   écran de la console. Un `title` n'y change rien : il n'est pas visible.
   Les trois restent RONDES (règle du niveau rond) et se distinguent par la FORME : disque plein ·
   anneau creux · disque cerclé. La couleur devient un renfort, plus le seul porteur.
   `outline` plutôt que `border` sur le rouge : il ne déplace rien dans la ligne. */
.dotmini{width:9px;height:9px;border-radius:50%;display:inline-block;box-sizing:border-box;flex:none}
.iot-v{background:var(--green)}
.iot-o{background:transparent;border:2.5px solid var(--orange)}
.iot-r{background:var(--red);outline:1.5px solid var(--red);outline-offset:1.5px}
.dotmini:not([class*="iot-"]){background:transparent;border:1.5px dashed var(--ink-soft)}

/* ---------- alertes ---------- */
.alert2{display:flex;gap:11px;align-items:flex-start;padding:11px 13px;border-radius:var(--radius-s);margin-bottom:9px;font-size:13px}
.alert2:last-child{margin-bottom:0}
.alert2 .ic{width:26px;height:26px;border-radius:var(--radius);display:grid;place-items:center;flex:none;font-size:13px;font-weight:700}
.alert2.red{background:var(--red-bg)} .alert2.red .ic{background:var(--red-bg);color:var(--red-ink)}
.alert2.org{background:var(--card);border:1px solid var(--line)} .alert2.org .ic{background:var(--bg);color:var(--ink-soft)}
.alert2.grn{background:var(--card);border:1px solid var(--line)} .alert2.grn .ic{background:var(--bg);color:var(--ink-soft)}
.alert2 .meta{color:var(--ink-soft);font-size:12px}
/* barre de progression (actions longues : génération…) */
.prog-wrap{padding:14px 2px}
.prog-track{height:10px;border-radius:var(--radius-s);background:var(--line);overflow:hidden}
.prog-fill{height:100%;border-radius:var(--radius-s);background:var(--accent);transition:width .35s ease;position:relative}
.prog-fill:not(.done)::after{content:"";position:absolute;inset:0;border-radius:var(--radius-s);background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);background-size:40% 100%;background-repeat:no-repeat;animation:progShine 1.1s linear infinite}
.prog-fill.done{background:var(--green)}
.prog-lbl{margin-top:8px;font-size:13px;color:var(--ink-soft);font-weight:600}
@keyframes progShine{0%{background-position:-40% 0}100%{background-position:140% 0}}
/* Survol : ni deplacement ni ombre teintee (charte) — le filet dit le survol. */
.alert2.act{transition:border-color .12s,background-color .12s;border:1px solid transparent}
.alert2.act:hover{border-color:var(--accent);background:var(--hover)}
.alert2.act.red:hover{border-color:#f0b4ae} .alert2.act.org:hover{border-color:#eccf95}
.alert2 .cta{font-size:11.5px;font-weight:700;opacity:.78;margin-top:2px}

/* ---------- inputs ---------- */
.ui-input,select.ui-input,input.ui-input{border:1px solid var(--line);border-radius:var(--radius);padding:7px 10px;font-size:13px;font-family:inherit;color:var(--ink);background:#fff}
.ui-input:focus{outline:none;border-color:var(--accent);box-shadow:var(--anneau)}
label.lab{font-size:12.5px;color:var(--ink-soft);font-weight:550}

/* ---------- barres de progression ---------- */
.bar{height:8px;border-radius:20px;background:#edeef8;overflow:hidden;display:inline-block;width:160px;vertical-align:middle}
.bar > i{display:block;height:100%;border-radius:20px;background:var(--accent)}

/* ---------- calendrier mensuel ---------- */
/* `1fr` VEUT DIRE `minmax(auto,1fr)`, et ce minimum `auto` est celui du CONTENU. Les pastilles
   de poste portent `white-space:nowrap` : un nom long élargissait donc la colonne, les sept
   colonnes faisaient 800 px, et toute la console glissait latéralement entre 620 et 880 px.
   `minmax(0,1fr)` autorise la piste à descendre sous son contenu — le nom s'abrège alors par
   les points de suspension déjà prévus sur `.shift`, au lieu de pousser la page. */
.calx{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:8px}
.calx .dow{font-size:11px;font-weight:400;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.1em;text-align:center;padding-bottom:2px}
.calx .cell{background:var(--card);border:1px solid var(--line);border-radius:var(--radius-s);min-height:104px;padding:7px 8px;display:flex;flex-direction:column;gap:4px;transition:.12s;content-visibility:auto;contain-intrinsic-size:auto 104px}
.calx .cell:hover{border-color:var(--accent)}
/* JOUR EN TENSION (prevision_tension) : un liseré ambre DISCRET. Pas d'aplat — la couleur de fond
   est déjà prise par le week-end, et deux aplats superposés ne se lisent plus. */
.calx .cell.tendu{border-color:var(--orange-ink);box-shadow:inset 0 0 0 1px var(--orange)}
.calx .cell.we{background:var(--bg)}
.calx .cell.out{background:transparent;border:none}
.calx .cell .d{font-size:11px;font-weight:600;color:var(--ink-soft)}
.calx .shift{font-size:11px;font-weight:550;border-radius:var(--radius-s);padding:2px 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.calx .s-j{background:var(--sh-j);color:var(--sh-jt)} .calx .s-n{background:var(--sh-n);color:var(--sh-nt)} .calx .s-h{background:var(--sh-h);color:var(--sh-ht)} .calx .s-s{background:var(--sh-s);color:var(--sh-st)}
.calx .force{background:var(--bg);color:var(--ink-soft);border:1px dashed var(--line)}
/* ══ « À CONFIRMER » — LA FORME DIT L'ÉTAT, LA COULEUR DIT LE POSTE (29.07) ════════════════════
   L'onglet Cadres peignait le nom validé en `--green-bg` : un aplat de STATUT, à 7×13 px, trois
   fois le rembourrage d'une pastille de garde. Une garde de cadre est une garde — elle prend donc
   la teinte de SON poste, comme C1, JC ou H. Ce qui reste à dire, c'est « pas encore confirmé par
   le cadre » : un contour TIRÉ, dans l'encre du poste (`currentColor`), donc sur la paire aplat/
   encre déjà mesurée — aucune couleur nouvelle, aucune paire nouvelle. Doublé par un « ? » dans le
   libellé : le test en niveaux de gris passe, la couleur ne porte jamais l'état seule.
   Le contour transparent sur la pastille de base garde les deux états EXACTEMENT à la même taille
   (`box-sizing:border-box` : le contour ne pousse rien). ══ */
.calx .shift{border:1px solid transparent}
.calx .shift.tbc{border-style:dashed;border-color:currentColor}
/* ══ FIGURE ET FOND, SANS DEGRADER LE FOND (29.07 — portail médecin) ═══════════════════════════
   « Mes gardes en évidence, celles des collègues en retrait » se faisait par `opacity:.62` sur la
   pastille du collègue. Mesuré après composition : 3,11 / 3,21 / 2,70 — tout sous le plancher de
   4,5, et sur un mois sans garde personnelle c'était TOUT l'écran. On ne construit pas une figure
   en abîmant le fond : le fond descend d'un cran de GRAISSE (550 → 450, il reste pleinement
   lisible), la figure monte d'un cran ET prend un liseré. La forme survit au gris. */
.calx .shift.collegue{font-weight:450}
.calx .shift.moi{font-weight:700;box-shadow:inset 0 0 0 1px currentColor;white-space:normal;line-height:1.3}
/* MA GARDE NE SE TRONQUE PAS. Mesuré : « Hélico 07:30→07:30 » demandait 119 px dans une cellule de
   107 (87 px utiles) et sortait en « Hélico 07:3… » — l'horaire, c'est-à-dire la seule chose que le
   médecin vient chercher, coupé. Les noms de collègues, eux, tenaient. Elle passe donc à la ligne
   plutôt qu'à l'ellipse : c'est l'élément prioritaire de la case, il peut coûter une ligne de haut.
   Les collègues gardent l'ellipse (15 sur 134 en usaient) — abréger un nom déjà secondaire est le
   bon compromis, tronquer l'horaire de sa propre garde ne l'est pas. */
/* Le champ de fichier cesse d'être un widget de formulaire brut : son bouton emprunte la grammaire
   du bouton fantôme (contour filet, fond transparent), le nom du fichier reste en encre atténuée. */
.ui-file{font-size:12.5px;color:var(--ink-soft);max-width:100%}
.ui-file::file-selector-button{font-family:inherit;font-size:12.5px;font-weight:600;color:var(--ink);
  background:transparent;border:1px solid var(--line);border-radius:var(--radius-s);padding:7px 13px;
  margin-right:11px;cursor:pointer;transition:.12s cubic-bezier(.22,1,.36,1)}
.ui-file::file-selector-button:hover{background:var(--hover);border-color:var(--ink-soft)}
/* L'ANCIENNE VALEUR d'une garde modifiée, sous sa pastille. Même traitement que dans la grille de
   semaine — chasse fixe, barrée — et au plancher de 11 px : c'est une information, pas une note. */
.calx .was{font-family:'Space Mono',ui-monospace,Menlo,monospace;font-size:11px;color:var(--ink-soft);text-decoration:line-through;margin:-3px 0 0 7px}

/* ---------- en-tête de carte : icône ---------- */
.panel-hd .hic{width:30px;height:30px;border-radius:var(--radius);background:var(--bg);color:var(--ink-soft);display:grid;place-items:center;flex:none}
.panel-hd .hic svg{width:17px;height:17px}
/* MOBILE : l'en-tête « Cadre & équipe du jour » ne tient pas sur une ligne (titre + hier/date) → on
   WRAPPE : le titre reste en haut, le bloc de navigation passe dessous, pleine largeur. Fini le titre tassé. */
@media(max-width:620px){
 .panel-hd{flex-wrap:wrap;gap:8px 10px}
 .panel-hd h3{flex:1 1 auto;min-width:0}
 .panel-hd > div[style*="margin-left:auto"]{margin-left:0 !important;width:100%;justify-content:space-between}
 #pjLabel,#eqjLabel{min-width:0 !important;flex:1 1 auto}
}

/* ---------- actions rapides ---------- */
.qa{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.qa a{display:flex;align-items:center;gap:11px;padding:12px;border:1px solid var(--line);border-radius:var(--radius);
  text-decoration:none;color:var(--ink);font-weight:550;font-size:13px;background:var(--card);transition:.15s;cursor:pointer}
.qa a:hover{border-color:var(--accent);background:var(--bg)}
.qa a .ic{width:32px;height:32px;border-radius:var(--radius);background:var(--bg);color:var(--ink);display:grid;place-items:center;flex:none}
.qa a .ic svg{width:17px;height:17px}

/* ---------- équipe du jour ---------- */
.team-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px dashed var(--line)}
.team-row:last-child{border:none}
.team-row .role{width:66px;font-size:11.5px;font-weight:700;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.4px;flex:none}
.tag{font-size:11px;font-weight:700;padding:2px 8px;border-radius:var(--radius-s);white-space:nowrap}
.tag.j{background:var(--sh-j);color:var(--sh-jt)} .tag.n{background:var(--sh-n);color:var(--sh-nt)} .tag.h{background:var(--sh-h);color:var(--sh-ht)} .tag.s{background:var(--sh-s);color:var(--sh-st)} .tag.x{background:var(--bg);color:var(--ink-soft)}

/* ---------- toast ---------- */
.toast{position:fixed;right:22px;bottom:22px;z-index:50;background:#1c2440;color:#fff;padding:12px 16px;border-radius:var(--radius);
  box-shadow:0 10px 30px rgba(9,10,22,.25);font-size:13.5px;font-weight:500;opacity:0;transform:translateY(10px);transition:.25s}
.toast.show{opacity:1;transform:translateY(0)}
.toast.ok{background:var(--green)} .toast.ko{background:var(--red)}

/* ===================================================================== */
/* PONT HÉRITAGE — re-style des anciennes classes des vues vers le thème  */
/* (chargé APRÈS l'ancien <style> de la console → ces règles l'emportent) */
main{background:transparent;margin:0;padding:0;border-radius:0;min-height:auto}
h2{font-family:var(--display);color:var(--ink);font-weight:600;letter-spacing:-.3px;margin:.1em 0 .55em;font-size:18px}
h3{font-family:var(--display);color:var(--ink);font-weight:600;margin:.6em 0 .35em;font-size:14.5px}
/* ⚠ `.aide` EST MORT (01.08). Il a existé sous TROIS destins simultanés, et aucun n'était celui
   qu'on croyait : `display:none` global (« HUB EPURE2 »), puis `.aide.clamp` — plus spécifique,
   donc gagnant — qui repliait à UNE ligne les blocs de plus de 160 signes SANS lien. Résultat
   mesuré au navigateur sur les 30 onglets : 24 préambules TRONQUÉS AU MILIEU D'UNE PHRASE
   (« …fatigue de l'équipe du jour,… »), 12 invisibles, et 3 invisibles ALORS QU'ILS PORTAIENT DES
   COMMANDES — le « Lien partagé (propriétaire) » de Tournus, champ et boutons compris, n'existait
   plus à l'écran. Le repli avait pourtant une exception écrite pour ça (« un bloc portant un
   lien/bouton ne se replie JAMAIS ») : elle marchait, et elle livrait le bloc au `display:none`
   posé un an plus tôt. DEUX DISPOSITIFS QUI S'ANNULENT, chacun juste pris seul.
   Et le repli à une ligne contredisait frontalement « la règle de la phrase entière » de
   `DESIGN.md` — c'est la charte elle-même qui interdit de couper un texte d'interface en son
   milieu. Ce qui le remplace est ci-dessous : LE MARQUEUR. */
label{font-weight:550;font-size:13px;color:var(--ink-soft);margin-right:8px}
/* ⚠ `input[type=text]` NE COUVRE PAS `<input>` SANS ATTRIBUT (29.07). Un `<input placeholder="…">`
   se comporte comme un champ texte, mais l'attribut `type` est ABSENT du balisage — donc aucun des
   sélecteurs d'attribut ci-dessous ne l'atteint, et le champ retombe sur le widget natif du
   navigateur : `border:2px inset`, rayon nul, Arial. Deux champs de la vue « Générer » vivaient
   ainsi depuis toujours au milieu d'une interface entièrement dessinée. Corrigé à la CLASSE,
   pas à l'occurrence : `input:not([type])` entre dans la liste, et tout champ écrit demain sans
   `type` sera juste par défaut.
   `background` passe de `#fff` en dur au jeton de surface, qui suit le thème. */
select,input:not([type]),input[type=date],input[type=text],input[type=number],input[type=time],input[type=month],input[type=email]{
  border:1px solid var(--line);border-radius:var(--radius-s);padding:7px 10px;font-size:13px;font-family:inherit;color:var(--ink);background:var(--card)}
/* CE QUI SE MESURE SE COMPOSE EN CHASSE FIXE (29.07). Une date, une heure, un nombre : la chasse
   fixe aligne les chiffres d'une ligne à l'autre et sépare la SAISIE D'UNE GRANDEUR de la saisie
   d'un mot. C'est la même règle que les horaires de garde ; ici elle s'applique au formulaire. */
input[type=date],input[type=time],input[type=month],input[type=number]{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.02em;font-variant-numeric:tabular-nums}
select:focus,input:focus{outline:none;border-color:var(--accent);box-shadow:var(--anneau)}
/* SYSTÈME DE BOUTONS UNIFIÉ — une seule famille, hiérarchie par le REMPLISSAGE (pas la couleur).
   .go = action principale (accent plein) · .vert = générer/confirmer · .gris/.ghost = secondaire (contour
   neutre) · .orange = prudence (teinte douce) · .rouge/.danger = destructif (teinte douce). */
/* Boutons AFFINÉS (fin/classe/UX) : compacts, police 500, coins nets 8px, secondaires aériens (filet).
   Un seul plein par vue = .primary/.vert (accent). .gris/.ghost/.orange = secondaire ; .rouge = destructif. */
button.go{background:transparent;color:var(--ink);border:1px solid var(--line);
  padding:6px 12px;border-radius:var(--radius);font-size:12.75px;font-weight:500;cursor:pointer;margin:5px 6px 0 0;
  display:inline-flex;align-items:center;gap:6px;vertical-align:middle;line-height:1.35;letter-spacing:-.1px;transition:.12s}
button.go:hover{background:var(--hover);border-color:var(--silver)}
/* Le tampon, pour l'autre famille de boutons — même grammaire que `.ui-btn.primary`, il n'y en a
   qu'une (29.07). `.vert` reste groupé avec `.primary` : c'est le MÊME rôle (l'action principale),
   sa nuance verte se pose ailleurs, quand l'action diffuse vraiment aux médecins. */
button.go.primary,button.go.vert{background:var(--accent);color:var(--on-accent);border-color:transparent;font-weight:600;box-shadow:none}
button.go.primary:hover,button.go.vert:hover{background:var(--accent-2);border-color:transparent;box-shadow:none}
button.go.gris,button.go.ghost,button.go.orange{background:transparent;color:var(--ink);border-color:var(--line)}
button.go.gris:hover,button.go.ghost:hover,button.go.orange:hover{background:var(--hover);border-color:var(--silver)}
button.go.rouge,button.go.danger,button.go.rouge2{background:transparent;color:var(--red-ink);border-color:var(--line)}
button.go.rouge:hover,button.go.danger:hover,button.go.rouge2:hover{background:var(--hover);border-color:var(--red-ink)}
button.go:disabled{background:transparent;color:var(--silver);cursor:default;transform:none;opacity:.65;border-color:var(--line)}
button.go.sm{padding:4px 10px;font-size:12px;border-radius:var(--radius-s)}
/* icônes de contenu (remplacent les emojis, injectées par iconify) */
.btnico{width:14px;height:14px;flex:none;stroke-width:1.5;opacity:.9}
h2 .btnico{width:19px;height:19px;vertical-align:-3px;margin-right:6px;display:inline-block}
h3 .btnico{width:16px;height:16px;vertical-align:-2px;margin-right:5px;display:inline-block}
.seg button .btnico{vertical-align:-2px;margin-right:4px;display:inline-block}
/* LE TROISIÈME NIVEAU SE DIT TROISIÈME (29.07). « Le planning / Cadres / Archives » vit SOUS les
   cinq espaces et sous les sept sous-onglets — mais il était dessiné à la main, en styles posés en
   ligne, avec la même graisse et le même aplat d'accent que le deuxième niveau : trois rangs de
   navigation qui se ressemblaient, donc trois rangs qu'on ne hiérarchisait pas.
   Il reprend le composant partagé `.seg` (fond feuille, actif en SURFACE) là où le deuxième niveau
   utilise `.seg.sub` (fond carte, actif en aplat d'accent). Un cran plus discret, et un seul
   auteur du composant. */
.seg.niv3{margin:2px 0 14px;border-radius:var(--radius);padding:2px}
.seg.niv3 button{font-size:12.5px;font-weight:600;padding:6px 13px}
/* L'ÉTIQUETTE EST UNE LÉGENDE, PAS UNE PHRASE (29.07). « MODE TEST → remy.midez@hug.ch » se
   composait dans la face du corps : elle avait l'aspect d'un fragment de texte posé dans une boîte,
   c'est-à-dire d'un widget par défaut. En chasse fixe et sur un rayon de 2 px, elle redevient ce
   qu'elle est — une mention technique, du même ordre que les légendes de colonne.
   ⚠ PAS de `text-transform:uppercase` ici, contrairement au pas d'étiquette de `DESIGN.md` : ces
   badges portent des ADRESSES e-mail. Crier une adresse la rend plus difficile à relire, et donne
   à croire à une casse qui n'est pas celle de la fiche. La chasse fixe suffit à la marquer. */
.badge{display:inline-block;padding:4px 9px;border-radius:var(--radius-xs);font-family:var(--mono);
  font-weight:400;letter-spacing:.03em;margin-top:12px;font-size:11.5px;background:var(--bg);
  color:var(--ink-soft);border:1px solid var(--line)}
/* NEUTRE + une seule ALERTE (rouge) : ok/warn/info = pastilles neutres (l'info est dans le texte) ;
   seul .ko/.bad porte du rouge. Fini le brun/navy/vert « sales » en dark. */
.badge.ok,.badge.warn,.badge.info,.badge.prev{background:var(--bg);color:var(--ink);border-color:var(--line)}
.badge.ko,.badge.bad{background:var(--red-bg);color:var(--red-ink);border-color:transparent}
.chips{margin:10px 0;display:flex;flex-wrap:wrap;gap:6px}
/* — RIEN QUI DÉBORDE : formulaires en lignes souples, champs/boutons contenus — */
.ligne{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin:8px 0}
.ligne > label{margin:0}
select,input[type=text],input[type=date],input[type=number],input[type=time],input[type=month],input[type=email]{max-width:100%}
.panneau{min-width:0}
.panneau table{max-width:100%}
/* frises / grands tableaux : conteneur qui scrolle horizontalement, jamais de débordement de page */
.frzwrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);padding:6px;background:var(--card);box-shadow:none;-webkit-overflow-scrolling:touch}
table.frz{border-collapse:separate;border-spacing:0}
table.frz th{color:var(--ink-soft);font-weight:600;background:var(--bg);border:1px solid var(--line);padding:5px 6px}
table.frz td{border:1px solid var(--line);padding:4px 6px}
table.frz td.nm,table.frz th.nm{background:var(--card);position:sticky;left:0;z-index:1}
table.frz th.nm{z-index:2}
table.frz td{height:24px;text-align:center}
/* ── FRISE DE ROTATION (onglet Rotation) — la colonne des noms colle, comme celle du Tournus ──
   La frise mesure 760 px au minimum : au téléphone on la fait glisser, et la colonne des noms
   partait avec elle — 53 bandes colorées sans savoir DE QUI. `table.frz td.nm` (juste au-dessus)
   règle déjà ce problème pour l'écran Tournus, qui montre le MÊME axe de 53 semaines. La frise ne
   le faisait pas : même geste, deux comportements, à un onglet de distance.
   ⚠ La frise est une GRILLE, pas un tableau — d'où une règle à elle et non un sélecteur partagé.
   La largeur vit dans un jeton pour que l'en-tête des mois et les lignes s'alignent forcément :
   deux `150px` écrits à la main auraient fini par diverger.
   ⚠⚠ ET ELLE S'ÉCRIT TOUJOURS `var(--frise-nom,150px)` DANS LE JS, JAMAIS `var(--frise-nom)` NU.
   Vu en direct, sur cet écran : tant que la feuille servie ne portait pas encore ce jeton (le
   serveur importe `ui_theme` AU DÉMARRAGE — une feuille modifiée après coup n'est pas servie), la
   déclaration entière `grid-template-columns:var(--frise-nom) repeat(53,1fr)` devenait INVALIDE.
   Pas « la première colonne fait 0 » : la propriété TOMBE, la grille repasse à une colonne, et les
   53 bandes s'empilent en pleine largeur. La frise disparaît, remplacée par un mur de lignes.
   Une variable manquante ne dégrade pas une grille, elle la SUPPRIME — et un cache de navigateur,
   un déploiement partiel ou un `▶ 3` qui pousse le JS avant la feuille suffisent à la faire
   manquer. La valeur de repli n'est pas une ceinture de sécurité décorative : c'est la seule
   chose qui garantit que l'écran reste un écran.
   ⚠ ELLE S'APPELLE `--frise-nom`, PAS `--rot-nom`. Écrite d'abord `--rot-nom`, elle a fait ROUGIR
   check_charte : l'invariant I balaie la famille « --rot- » en la supposant faite de COULEURS, et
   une largeur ne se résout pas en hexadécimal — il a refusé de conclure plutôt que de passer au
   vert. C'est exactement le comportement attendu (« un contrôle qui ne peut pas vérifier doit
   échouer »), et la leçon vaut d'être notée : un préfixe de jeton est un ESPACE DE NOMS, pas une
   décoration — s'y glisser change ce que les contrôles croient mesurer. */
.rotwrap{--frise-nom:150px}
.rotnom{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:8px;
  position:sticky;left:0;z-index:1;background:var(--card)}
@media (max-width:640px){ .rotwrap{--frise-nom:112px} .rotnom{font-size:12px} }

/* fiche médecin (RH) : champs regroupés en cartes titrées */
.rhgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:12px;margin-top:6px}
.rhcard{border:1px solid var(--line);border-radius:var(--radius);padding:12px 16px;background:var(--card);box-shadow:none}
.rhttl{font-weight:700;color:var(--ink);font-size:13px;margin-bottom:8px;border-bottom:1px solid var(--line);padding-bottom:5px}
.rhcard .ligne{margin:6px 0}
/* légende des frises / tournus : pastilles uniformes */
.frzleg{display:flex;gap:8px;flex-wrap:wrap;margin:4px 0 8px}
/* PAS de `color` ici : chaque pastille reçoit l'encre de SON fond (encreSur(), console_app.js).
   Un `color:#fff` global donnait 1,29:1 sur le vert pâle « présent / dispo » — illisible dans
   les DEUX thèmes. Une encre unique pour des fonds hétérogènes est toujours fausse quelque part. */
.frzleg span{font-size:11px;padding:2px 9px;border-radius:999px;line-height:1.5;white-space:nowrap;box-shadow:inset 0 0 0 1px rgba(9,10,22,.05)}
/* timeline (Gantt) des tournus — conservé pour compat */
.tl{display:grid;gap:2px;min-width:max-content;font-size:11px}
.tl-h{text-align:center;color:var(--ink-soft);font-size:11px;font-weight:600;line-height:1.25;padding:1px 0}
.tl-name{font-weight:600;color:var(--ink);padding:2px 8px;white-space:nowrap;display:flex;align-items:center;background:var(--card);position:sticky;left:0;z-index:1;font-size:11.5px}
.tl-cell{height:22px;border-radius:2px}
.tl-cell.empty{background:#f2f3fb}
table.hs{border-collapse:separate;border-spacing:0;font-size:13px;margin-top:6px;width:100%}
table.hs td{border-bottom:1px solid var(--line);padding:8px 14px 8px 0}
table.hs tr:last-child td{border-bottom:none}
.cards{display:flex;gap:12px;flex-wrap:wrap;margin:14px 0}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:13px 16px;min-width:150px;box-shadow:none}
.card .v{font-size:24px;font-weight:600;color:var(--ink);font-family:var(--display);letter-spacing:-.4px}
.card .l{font-size:12.5px;color:var(--ink-soft)}
table.grille{border-collapse:separate;border-spacing:0;font-size:11.5px;margin-top:14px;width:100%}
table.grille th{background:var(--bg);color:var(--ink);border:1px solid var(--line);font-weight:600}
table.grille td{border:1px solid var(--line)}
tr.we td{background:var(--bg)} tr.ferie td{background:var(--orange-bg)}
/* Le résumé d'un dépliant est un CONTRÔLE : 24 px au minimum à tous les pointeurs (2.5.8),
   44 px au doigt (voir la règle tactile). Il mesurait 19,4 px, et `<details>` est le motif
   d'explication que DESIGN.md recommande — il y en a partout. */
details{margin-top:12px} details>summary{color:var(--ink);font-weight:550;cursor:pointer;min-height:24px}
pre{background:#171a33;color:#d7d9f0;padding:14px;border-radius:var(--radius);font-size:12px;white-space:pre-wrap;max-height:48vh;overflow:auto;margin-top:8px}
.file button{background:var(--green);border:none;color:var(--on-green);padding:9px 16px;border-radius:var(--radius);font-weight:550;cursor:pointer}

/* ---------- fluidité : apparition douce du contenu ---------- */
@keyframes uiFade{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}
.panneau{animation:uiFade .16s ease both}
.panel,.kpi{animation:uiFade .18s ease both}
@media (prefers-reduced-motion: reduce){.panneau,.panel,.kpi{animation:none}}

/* ---------- responsive : sidebar = DRAWER coulissant (comme le portail médecin) ---------- */
.tb-burger{display:none;background:none;border:1px solid var(--line);color:var(--ink);font-size:20px;
  cursor:pointer;padding:4px 11px;border-radius:var(--radius);line-height:1}
.tb-burger:hover{background:var(--card)}
.sb-scrim{display:none;position:fixed;inset:0;background:rgba(10,12,22,.5);z-index:55}
@media(max-width:880px){
  .shell{grid-template-columns:1fr}
  .sb{position:fixed;left:0;top:0;height:100vh;width:270px;max-width:82vw;flex-direction:column;overflow:auto;
      transform:translateX(-100%);transition:transform .22s ease;z-index:60;box-shadow:0 0 44px rgba(9,10,22,.32)}
  .sb.open{transform:translateX(0)}
  .sb-nav{display:block} .sb-grp{display:block} .sb-who{display:flex}
  .sb-scrim.show{display:block}
  .tb-burger{display:inline-flex}
  .content{padding:16px}
  /* les mises en page 2 colonnes s'empilent (override des grid-template-columns inline) */
  .row,.cols{grid-template-columns:1fr !important}
  .tb{flex-wrap:wrap;gap:8px} .tb .spacer{flex-basis:100%;order:5}
  .qa{grid-template-columns:1fr}
  table.ui-table,table.hs{font-size:12px}
  .calx{gap:3px} .calx .cell{min-height:74px;padding:4px}
}

/* TÉLÉPHONE : un calendrier 7 colonnes ne tient JAMAIS sur un écran ~360-420px (il débordait à droite,
   colonnes rognées, noms coupés). On EMPILE en 1 colonne : chaque jour = une carte pleine largeur,
   alignée au bord de l'écran, nom complet lisible. Le n° de jour (.d) donne le contexte ; les cases
   vides de début/fin de mois (.out) et les entêtes Lun..Dim (.dow) disparaissent (inutiles empilés). */
@media(max-width:620px){
  .calx{grid-template-columns:1fr;gap:6px}
  .calx .dow{display:none}
  .calx .cell.out{display:none}
  .calx .cell{min-height:0;padding:8px 10px}
  .calx .shift{white-space:normal}
}

/* ========================================================================== */
/* MOBILE — COUCHE FINALE « toute la console au téléphone » (≤ 640 px).        */
/*                                                                            */
/* Le SOCLE existait déjà : la sidebar devient un tiroir (≤880), le calendrier */
/* s'empile (≤620), les matrices larges (rotation, fatigue) et les tables     */
/* gelées (Tournus) vivent dans des conteneurs `overflow-x:auto` — elles      */
/* DÉFILENT, il ne faut surtout pas les casser. Ce qui restait inconfortable, */
/* c'est le CONTENU des vues : des grilles 2-colonnes écrites en style INLINE  */
/* (donc invisibles pour `.row{…1fr}`), quelques tables nues, et la densité.   */
/*                                                                            */
/* RÈGLE DE SÉCURITÉ : tout est enfermé dans cette media-query → AUCUN effet   */
/* sur le desktop (le harnais rend en pleine largeur, rien ne bouge pour lui). */
/* On ne touche PAS aux grilles-matrices (`… repeat(…,1fr)`, `repeat(7,30px)`) */
/* : elles doivent défiler, pas s'empiler — les empiler détruirait la frise.   */
/* ========================================================================== */
@media(max-width:640px){
  /* — densité : on récupère chaque pixel de largeur —
     ⚠ `--gouttiere` EST la largeur de cette marge, et c'est la SEULE source (31.07). Les blocs
     qui sortent volontairement du rembourrage (`.cartouche`, `.feuille` — le « plein écran »
     du cartouche sous 620 px) la compensent par une marge négative. Ils écrivaient `-14px`
     quand ce rembourrage valait 12 : 2 px de trop de chaque côté, donc 4 px de page en trop —
     et « le champ ne défile jamais latéralement ». Deux règles disaient la même chose, elles
     ont divergé ; désormais elles LISENT la même valeur (règle 9, appliquée au CSS). */
  .content{padding:12px var(--gouttiere,12px) 40px}
  .panel-bd{padding:13px 13px}
  .panel-hd{padding:12px 13px}
  .tb{padding:11px 14px}
  .tb h1{font-size:17px}
  h2{font-size:16.5px} h3{font-size:14px}

  /* — grilles 2-colonnes de CONTENU écrites en INLINE → empilées.
       Ciblage par sous-chaîne du style inline : on ne prend QUE les formes de
       contenu (deux colonnes proportionnelles ou maître-détail), jamais les
       matrices `150px repeat(…)` / `130px repeat(…)` / `repeat(7,30px)` qui,
       elles, défilent dans leur conteneur. `.row/.cols` (≤880) et `.eq2col/
       .ficwrap` (≤860/900) sont déjà couverts ; on les répète ici par sûreté. */
  [style*="grid-template-columns:1fr 1fr"],
  [style*="grid-template-columns:1.5fr 1fr"],
  [style*="grid-template-columns:1.25fr 1fr"],
  [style*="grid-template-columns:minmax(0,300px)"],
  [style*="grid-template-columns:minmax(0,1.5fr)"],
  .eq2col,.ficwrap,.row,.cols{grid-template-columns:1fr !important}

  /* — une table NUE (sans conteneur défilant) élargissait la page entière ;
       on la rend défilante DANS son bloc. `.frz` est EXCLUE : elle a déjà son
       `.frzwrap` + colonne collante, et `display:block` casserait le sticky. */
  .content table:not(.frz){display:block;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}

  /* — un SVG/chart à largeur mini fixe ne doit jamais dépasser l'écran :
       s'il n'est pas déjà dans un conteneur défilant, il se borne. */
  .content svg{max-width:100%;height:auto}

  /* — sous-onglets : plutôt que de retomber sur 3 lignes, une bande qui défile
       horizontalement (le pouce balaie). `.seg` reste flex, on désactive le
       wrap et on autorise le débordement horizontal. */
  .seg,.seg.sub{display:flex;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;
    scrollbar-width:none}
  /* LA BARRE DE DÉFILEMENT SE CACHE (29.07). Sur la console à 375 px, la rangée d'onglets de la
     charpente affichait une glissière claire, épaisse, non stylée, juste sous les libellés — elle
     ressemblait à une jauge de progression et n'en était pas une. `.sb-nav` et `.seg.sub` du grand
     écran la masquaient déjà depuis longtemps ; la bande MOBILE, elle, ne l'avait jamais fait,
     c'est-à-dire précisément là où le pouce balaie et où la glissière est inutile. */
  .seg::-webkit-scrollbar,.seg.sub::-webkit-scrollbar{display:none}
  .seg button,.seg.sub button{flex:0 0 auto;padding:7px 12px;font-size:12.5px}

  /* — cibles tactiles un peu plus généreuses — */
  .ui-btn,button.go{padding:8px 13px}
  .sb-link{padding:11px 12px}          /* le menu du tiroir, plus facile au doigt */

  /* — KPI : deux par ligne (un empilement d'une colonne était interminable) — */
  .grid-kpi{grid-template-columns:1fr 1fr}
  .kpi{padding:13px 13px} .kpi .v{font-size:23px}

  /* — BANDE de KPI (écran « À traiter ») : UNE colonne. 27.07, constaté à 375 px.
       Elle était restée sur `minmax(150px,1fr)`, donc DEUX colonnes de ~180 px — trop
       étroites pour ses sous-titres, qui se coupaient EN PLEIN MILIEU D'UNE PHRASE :
       « médecins · 42 au / tournus », « septembre 2026 · 55 / manquants »,
       « 0 déclaration(s) / validée(s) ». C'est le défaut nommé en premier par Rémy.
       Ce n'est pas un réglage de densité : à pleine largeur, ces titres ne se coupent
       plus du tout. Et en pile, le séparateur doit passer à DROITE → EN BAS, sans quoi
       chaque tuile porte un trait vertical dans le vide.

     ⚠ `!important` OBLIGATOIRE ICI, et c'est un piège du fichier : `.kpi-strip` est déclarée
       PLUS BAS (≈ l.680) que cette couche mobile. À spécificité égale, la DERNIÈRE règle du
       fichier gagne — donc l'override mobile était écrasé et ne faisait RIEN, en silence.
       (`.grid-kpi` juste au-dessus fonctionne, elle, parce qu'elle est déclarée l.124, AVANT.)
       Toute future règle mobile visant une classe définie après ce bloc a le même besoin. */
  .kpi-strip{grid-template-columns:1fr !important}
  .kpi-strip .kpi{border-right:none !important;border-bottom:1px solid var(--line)}
  .kpi-strip .kpi:last-child{border-bottom:none}

  /* — actions rapides déjà en 1 colonne (≤880) ; on garde — */
  .qa{grid-template-columns:1fr}
}
/* très petits écrans : les KPI repassent en pile (2 colonnes deviennent illisibles). */
@media(max-width:400px){
  .grid-kpi{grid-template-columns:1fr}
}

/* ============ MODE SOMBRE (bouton 🌙, mémorisé) ============ */
[data-theme="dark"]{
  /* ══ LA CHARPENTE PASSE SOUS LE CHAMP (29.07) ═══════════════════════════════════════════════
     CE QUI ÉTAIT FAUX : `--side-1` restait figé à #1b1c21 dans les deux thèmes, au nom de « la
     charpente ne suit pas le thème ». Tenue au pied de la lettre, cette règle PRODUISAIT
     l'inversion : en sombre, la charpente (L* 10,4) devenait le plan le plus CLAIR de l'écran,
     au-dessus de la feuille (L* 4,0). « Champ clair pour le travail, cartouche sombre pour la
     charpente — jamais l'inverse » était donc violé par le token censé l'appliquer.
     L'INTENTION de la règle est que la charpente soit le plan qui ENFERME, donc le plus sombre —
     pas qu'elle soit un hexadécimal gelé. C'est l'intention qui est appliquée ici.

     ⚠ NE PAS MESURER DEUX PLANS SOMBRES AU RAPPORT DE CONTRASTE. Entre deux quasi-noirs il reste
     collé à 1 quel que soit l'écart réel (le +0,05 de la formule domine) : remonter la feuille de
     #0d0e11 à #1e2025 FAISAIT BAISSER le rapport de 1,13 à 1,04, alors que l'écart perçu
     augmentait. La bonne grandeur est l'écart de CLARTÉ CIELAB. Référence prise dans le thème
     clair lui-même : il sépare deux plans de ΔL* +3,5 (surface #fff sur feuille #F4F5F7).
     Ici : charpente → feuille ΔL* +4,2 · feuille → surface ΔL* +4,1. Même grammaire, en sombre.

     Bénéfice mesuré, et c'est ce qui a tranché entre les deux réparations possibles : enfoncer la
     charpente laisse les encres sur un fond PLUS SOMBRE, donc TOUTES gagnent — rouge 5,30 (contre
     4,55 si on avait remonté la feuille), encre de charpente 12,05, cartouche 19,68. Et la nuit
     reste la nuit : la feuille est à L* 7,2, pas 13,7. */
  /* 01.08 (soir) — versant nuit de la charpente space-indigo. Elle reste LE PLAN LE PLUS SOMBRE
     de l'écran, comme le veut la règle de l'ordre des plans : L* 5,9 < feuille 9,0 < surface 13,4.
     La teinte est celle du clair, la POSITION est celle qu'impose l'ordre — jamais un hexadécimal
     gelé, c'est en le gelant qu'on avait inversé l'ordre pendant des mois. */
  /* ⚠ CORRIGÉ DANS LA MÊME SESSION, SUR SIGNALEMENT DE RÉMY (« problème de couleur de fond »).
     La charpente était posée à L* 5,9 et la feuille à 9,0 : ΔL* 3,1, SOUS le plancher de 3,5 que
     ce système s'impose entre deux plans voisins. L'ORDRE était juste, le PAS ne l'était pas —
     et à l'écran le haut de la page faisait un aplat unique, barre du haut et sous-onglets
     confondus. Aucun contrôle ne pouvait le dire : la règle de l'ordre des plans était écrite
     dans DESIGN.md depuis le 29.07 et n'avait jamais eu de test. D'où l'invariant M.
     Nouveaux pas : charpente 4,3 → feuille 9,0 (ΔL* 4,7) → surface 13,4 (ΔL* 4,4). */
  --side-1:#000c17; --side-2:#09171f; --side-3:#00121a; --side-line:#273741;
  /* La feuille prend le même grain d'ardoise qu'en clair (voir :root) — la nuit aussi, le champ
     est une matière et non un vide. L'ordre des plans est conservé et légèrement raffermi :
     charpente 3,03 → feuille 7,82 → surface 11,92, soit ΔL* +4,79 et +4,10. */
  --ink:#dfe6ec; --ink-soft:#97a2aa; --line:#38393d; --bg:#161f25; --card:#1e282e; --silver:#828389;
  /* La légende absorbée, versant nuit : le celadon et le rosewood éclaircis pour leur fond noir.
     Mesurés sur la surface #212228 : acquis 6,90:1 · alarme 5,36:1. */
  /* ── LES FONDS DE SIGNAL, VERSANT NUIT — MESURÉS CONTRE LEUR CARTE (02.08) ────────────────
     Ils avaient été composés pour la feuille CLAIRE, où ils sont un souffle : chroma 4,4 à 8,5,
     à ΔL* −4,5/−6,9 régulier sous la carte. Reportés en sombre, ils portaient **chroma 15 à
     20,2** — deux à quatre fois plus — avec des écarts de clarté erratiques (+2,6 à +10,7).
     À l'écran : deux dalles olive dans la bande de mesures et une barre rouge en travers de la
     ligne urgente, qui pesaient plus que le bouton d'action censé la traiter.
     Un fond de signal n'est pas là pour être vu : il est là pour teinter. Il reprend donc en
     nuit la discrétion qu'il a le jour — ΔL* +5,0 régulier, chroma 8 — et la TEINTE fait seule
     le travail. Les encres remesurées dessus : 5,70 à 6,37:1 ; l'encre du texte, 11,5 au pire. */
  --green:#7fab83; --green-bg:#2f3c30; --orange:#d2a365; --orange-bg:#3c2e1d; --red:#ff9a95; --red-bg:#4b3331;
  --blue-bg:#2d3b44; --accent:#87a0b2; --accent-2:#aecade; --accent-ink:#8fafc6; --violet:#c0c1c4; --on-accent:#02111b;
  --ex:#afb0b6; --ex-ink:#c0c1c6; --ex-pale:#2f3b43;
  --on-green:#02111b; --on-red:#02111b;   /* 7,59:1 et 5,71:1 — cf. la note du thème clair */
  /* `--on-frise` et `--sur-pale` NE BASCULENT PAS : leurs fonds non plus. Les 13 teintes de la
     frise et les deux pâles sont figées dans les deux thèmes — une encre qui bascule sur un fond
     qui ne bascule pas, c'est exactement le bug qu'on répare ici. Seul `--on-ink-soft` suit le
     thème, parce que `--ink-soft` le suit. */
  --on-ink-soft:#02111b;
  --bleu:#8fafc6;
  /* ⚠ UNE ENCRE MESURÉE SUR UN PLAN, EMPLOYÉE SUR UN AUTRE (31.07).
     `--red-ink` reprenait `--red` (#e9686e), et c'était juste — SUR LA SURFACE (#1c1e23) : 5,30.
     Mais `.chip2` porte son propre fond en sombre (#2b2d34), plus clair, et le même rouge y tombe
     à **4,37**, sous le plancher. Mesuré au navigateur, en thème sombre, sur le mot « rouge » du
     niveau IOT — c'est-à-dire l'écran d'équipe lu de nuit, en garde.
     `--orange` et `--green` tiennent sur les DEUX plans (5,65 et 5,82) : eux ne bougent pas.
     Le rouge s'éclaircit juste assez : #ef7d82 → 6,29 sur la surface, 5,19 sur la puce.
     LA LEÇON : une encre n'est pas mesurée « en sombre », elle est mesurée SUR UN FOND. Quand un
     composant se donne son propre fond, il change la question. */
  --red-ink:#ffa59f; --green-ink:#8ab68d; --orange-ink:#dead6f; --violet-ink:#8fafc6;
  /* Sur la surface sombre, cinq des six couleurs VIVES d'axe font déjà de bonnes encres (4,87 à
     7,41:1) : on les reprend telles quelles, comme `--red-ink` reprend `--red`. Seule « nuits »
     tombait à 4,05 — elle est éclaircie jusqu'à 6,13. Mesuré sur #1c1e23, pas supposé. */
  /* Les six encres d'axe, versant nuit — mesurées sur la carte #212228 : 6,91 à 6,94:1.
     Et les six APLATS, qui basculent aussi depuis le 02.08 (voir la note du thème clair) :
     mêmes teintes, même ordre de clarté, échelle remontée pour tenir 3:1 sur le quasi-noir. */
  --eq-ax-helico:#cbccd0; --eq-ax-feries:#938d62; --eq-ax-heures:#57819b;
  --eq-ax-nuits:#809fb5; --eq-ax-we:#a7bfd0; --eq-ax-jours:#b3ac7d;
  --serie-neutre:#959699; --serie-ambre:#b3ac80;
  --eq-ink-heures:#7ca6c1; --eq-ink-nuits:#8fafc6; --eq-ink-we:#a7bfd0;
  --eq-ink-feries:#a8a276; --eq-ink-helico:#c0c1c4; --eq-ink-jours:#b9b282;
  /* Rampe de fatigue, versant nuit — voir la note complète du thème clair. L'ordre s'inverse
     (le calme est le plus sombre, le risque le plus clair) parce que la page a changé de côté :
     ce qui est chaud reste ce qui est LOIN de la page. Composée, pas inversée mécaniquement.
     L* 53,7 · 66,0 · 77,8 → écarts en gris de 30,8 et 31,0 (contre 0,3 avant).
     `--fat-ink` ne figure pas ici : elle est identique dans les deux thèmes, par construction. */
  --fat-calme:#638b67; --fat-vigil:#c19a69; --fat-risque:#ffaba6;
  /* Frise de rotation, en sombre — MÊME INVERSION QU'EN CLAIR (voir le commentaire du thème clair) :
     les deux « ailleurs » deviennent des fonds sourds, le SMUR reste le seul aplat vif et l'extrême
     de la rampe. Clartés L* : hors tournus 7,4 · urgences 26,9 · bloc 38,0 · SMUR 68,3
     (écarts 19,5 · 11,1 · 30,3 — très au-dessus du plancher de 3,5).
     ⚠ VACANCES (68,2) ET FORMATION (69,1) TOMBENT SUR SMUR (68,3) : ΔL* 0,09 et 0,81. C'est pour
     cela — et pour le clair, où Vacances (54,15) tombe sur Aux urgences (54,85) à ΔL* 0,70 — que
     ces deux ÉTATS D'ABSENCE sont désormais HACHURÉS et non teintés (voir `ROT_ABSENCE`,
     console_app.js). On ne les a PAS repeints : `--orange` et `--green` sont des jetons globaux,
     et une absence n'appartient pas à l'échelle des lieux de travail. C'est le CANAL qui change.
     ⚠⚠ ET `--rot-anesth` N'A PAS BOUGÉ — J'AI FAILLI LE REPEINDRE SUR UNE MESURE FAUSSE. J'avais
     calculé « anesthésie ↔ SMUR = ΔL* 2,9, sous le plancher » en comparant `--rot-anesth` SOMBRE
     au hexadécimal de `--accent` CLAIR (#5C6E99). Or le thème sombre redéfinit `--accent` en clair
     (L* 68,3) : l'écart réel est de 24,6, il n'y a jamais eu de collision. Mesurer un jeton d'un
     thème contre la valeur écrite d'un autre, c'est ne mesurer aucun des deux — règle 13, prise
     sur le fait. LIRE LA VALEUR RÉSOLUE PAR LE NAVIGATEUR, jamais la première déclaration trouvée
     dans le fichier (c'est déjà la leçon de l'indigo mort, PRODUCT.md). */
  --rot-anesth:#59595d; --rot-urgences:#2a4556;
  /* remontés avec la surface : ils la surplombent, ils ne doivent pas s'y noyer */
  --fat-hd:#2b363e; --fat-hd-ink:#d5dee5; --fat-cell-line:#313a41;
  --hover:rgba(255,255,255,.06);
  /* LA RAMPE DES POSTES, EN SOMBRE. Même principe qu'en clair et même ordre de poids
     (jour → soir → nuit → hélico), mais la page est noire : on s'en écarte en MONTANT.
     Pas de ΔL* 4,5. Les aplats restent tous sombres, donc les quatre encres claires gardent leur
     métier — mesurées sur leur nouvel aplat : 8,40 · 7,45 · 5,66 · 4,61:1.
     ⚠ On mesure ici en ΔL*, jamais en rapport de contraste : entre deux quasi-noirs le rapport
     WCAG reste collé à 1 et DÉCROÎT quand l'écart perçu grandit (DESIGN.md, « la règle de
     l'ordre des plans »). C'est en le mesurant à la mauvaise grandeur qu'on a pu croire ces
     quatre teintes distinctes pendant des mois. */
  --sh-j:#23323c; --sh-jt:#a3bfd3; --sh-s:#4d371f; --sh-st:#eabf92; --sh-n:#2a485a; --sh-nt:#b0d0e7; --sh-h:#5e4669; --sh-ht:#e5d0ef;   /* hélico = POURPRE (dark) */
  /* INVARIANT L (01.08) — aucun noir pur, pas même dans une ombre : elles se teintent au plan
     le plus sombre de la charpente (#090a16), pas à #000. */
  /* En sombre l'écriture de navigation est BLANCHE, pas grise : L* 78 contre L* 64 pour l'encre
     atténuée. 8,82:1 sur la surface ; l'onglet courant garde 13,31:1, son cran de graisse et son
     filet de 2 px — la hiérarchie tient sans que rien ne devienne gris. */
  --nav-ink:#c0c1c4;
  --anneau:0 0 0 3px rgba(135,160,178,.34);
  --accent-bord:rgba(135,160,178,.36);
  --shadow:0 1px 2px rgba(2,17,27,.55);
  --shadow-s:0 1px 1px rgba(2,17,27,.6);
  --voile:rgba(2,17,27,.52); --voile-fort:rgba(2,17,27,.76);
}
/* dark : neutraliser quelques surfaces (le reste suit désormais les tokens) */
/* Ces quatre surfaces se posent SUR la surface : elles suivent donc son relèvement, sinon elles
   s'y noient (le champ de saisie #1c1d22 valait exactement la nouvelle surface #1c1e23). */
[data-theme="dark"] .ui-input,[data-theme="dark"] input.ui-input,[data-theme="dark"] select.ui-input{background:#24262c;color:var(--ink);border-color:var(--line)}
[data-theme="dark"] .chip2{background:#2b2d34;border-color:var(--line);color:var(--ink)}
[data-theme="dark"] .prog-track,[data-theme="dark"] .bar{background:#2e3037}
[data-theme="dark"] input,[data-theme="dark"] select,[data-theme="dark"] textarea{background:#24262c;color:var(--ink);border-color:var(--line)}
[data-theme="dark"] .cmd-hints,[data-theme="dark"] details>div{color:var(--ink-soft)}
[data-theme="dark"] hr{border-color:var(--line)}
[data-theme="dark"] img{opacity:.92}
[data-theme="dark"] .tb{background:rgba(20,22,26,.96) !important}   /* la feuille, en translucide : suit --bg */
/* BANDEAUX D'INFO à fond clair codé « inline » : fond + texte + bordure traités ENSEMBLE pour garder
   un bon contraste en mode sombre (sinon fond clair éblouissant ou texte sombre devenu illisible). */
[data-theme="dark"] [style*="#eef3fb"]{background:#1b2540 !important;color:#cdd6ef !important;border-color:#33406a !important}
[data-theme="dark"] [style*="#fff3cd"]{background:#3a2f12 !important;color:#f0d68a !important;border-color:#6b551f !important}
[data-theme="dark"] [style*="#e3f2e8"]{background:#14301f !important;color:#9fe6bd !important;border-color:#2c6a45 !important}
[data-theme="dark"] [style*="background:#f7f9fc"]{background:#1c1d22 !important}
[data-theme="dark"] [style*="background:#f4f5fb"]{background:#1c1d22 !important}
[data-theme="dark"] [style*="color:#556"],[data-theme="dark"] [style*="color:#667"],[data-theme="dark"] [style*="color:#789"]{color:#aab4d0 !important}

/* ── INTERRUPTEUR CLAIR/SOMBRE — CURSEUR (Lot 1 refonte UX 09.07) : composant PARTAGÉ, repris du portail
   médecin (.themesw) pour un style d'interrupteur IDENTIQUE partout. Le knob glisse via [data-theme=dark],
   pas de JS d'icône. Variables adaptées à ui_theme (--line/--bg/--card). */
.themesw{position:relative;width:50px;height:26px;flex:0 0 auto;border:1px solid var(--line);background:var(--bg);border-radius:20px;cursor:pointer;padding:0;transition:border-color .15s,background .15s}
.themesw:hover{border-color:var(--ink-soft)}
.themesw svg{position:absolute;top:6px;width:13px;height:13px;stroke-width:2;pointer-events:none;fill:none;stroke:currentColor}
.themesw .ic-sun{left:6px;color:#c99a2e;opacity:.9}
.themesw .ic-moon{right:6px;color:var(--ink-soft);opacity:.5}
.themesw .knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:var(--card);box-shadow:0 1px 3px rgba(9,10,22,.22);transition:transform .2s cubic-bezier(.22,1,.36,1)}
[data-theme="dark"] .themesw{background:#20213a}
[data-theme="dark"] .themesw .knob{transform:translateX(24px)}
[data-theme="dark"] .themesw .ic-moon{opacity:.9;color:var(--ink)}
[data-theme="dark"] .themesw .ic-sun{opacity:.4;color:var(--ink-soft)}

/* ── ÉQUITÉ : 3 graphiques (grille de scouting · hexagones · courbe de dette) ─────────────── */
.eqgrp{margin:16px 0 6px}
.eqgt{font-weight:700;font-size:14px;margin-bottom:8px;color:var(--ink)}
.eq2col{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:860px){.eq2col{grid-template-columns:1fr}}
.card-eq{border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;background:var(--card);margin-bottom:12px}
.card-eq .eqh{font-size:13px;font-weight:700;margin-bottom:2px}
.card-eq .eqs{font-size:11.5px;color:var(--ink-soft);margin-bottom:8px;line-height:1.45}
.card-eq .eql{font-size:11px;color:var(--ink-soft);margin-top:6px}
.rgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:10px}
.rc{text-align:center;border:1px solid var(--line);border-radius:var(--radius);padding:6px 4px 4px}
.rc .rcn{font-size:12px;font-weight:700;margin-top:2px}
.rc .rcv{font-size:11px}
.eq-ok{color:var(--green-ink,#267948);font-weight:600}
/* ── FICHE MÉDECIN UNIQUE : maître-détail (liste figée à gauche, fiche à droite) ─────────────── */
.ficwrap{display:grid;grid-template-columns:250px 1fr;gap:14px;align-items:start}
@media(max-width:900px){.ficwrap{grid-template-columns:1fr}}
.ficlist{border:1px solid var(--line);border-radius:var(--radius);padding:8px;background:var(--card);
  max-height:560px;overflow:auto;position:sticky;top:70px}
.ficrow{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:var(--radius);cursor:pointer}
.ficrow:hover{background:var(--hover)}
.ficrow.on{background:var(--blue-bg);box-shadow:inset 2px 0 0 var(--accent)}
.ficdet{border:1px solid var(--line);border-radius:var(--radius);padding:16px 18px;background:var(--card);min-height:360px}
.ficsec{font-size:12px;font-weight:800;color:var(--ink);margin:16px 0 8px;padding-bottom:4px;border-bottom:1px solid var(--line)}
.ficsec:first-of-type{margin-top:4px}
.ficsec span{font-weight:400;color:var(--ink-soft)}
.ficgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px 14px}
.ficgrid select,.ficgrid input{width:100%}
/* tableau détaillé d'équité : lignes zébrées, en-tête collant, colonne écart en évidence */
.eqtab{border-collapse:collapse;margin-top:6px;width:100%;max-width:820px;font-size:12.5px}
.eqtab th{background:var(--bg);border-bottom:2px solid var(--line);padding:6px 8px;font-size:11px;
  font-weight:700;color:var(--ink-soft);text-align:center;white-space:nowrap}
.eqtab td{padding:6px 8px;border-bottom:1px solid var(--line)}
.eqtab td.c{text-align:center}
.eqtab td.mut{color:var(--ink-soft)}
.eqtab tr:hover td{background:var(--hover)}

/* ── PIED DE SIDEBAR (maquette) : bascule de rôle + fiche + clair/sombre ── */
.pip{display:inline-block;width:9px;height:9px;border-radius:50%;vertical-align:-1px;margin-right:5px;flex:none}
.sb-role{display:flex;gap:3px;margin:10px;padding:4px;background:rgba(255,255,255,.06);border-radius:var(--radius)}
.sb-role a,.sb-role span{flex:1;text-align:center;padding:8px 6px;border-radius:var(--radius);font-size:13px;font-weight:550;
  color:var(--side-ink-soft);text-decoration:none;cursor:pointer}
.sb-role .on{background:transparent;color:var(--cartouche-ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--accent)}
.sb-role a:hover:not(.on){background:rgba(255,255,255,.06);color:#fff}
.sb-who{position:relative}
.sb-sw{margin-left:auto;width:44px;height:24px;border-radius:var(--radius);border:0;background:rgba(255,255,255,.12);
  position:relative;cursor:pointer;flex:none;padding:0}
.sb-sw i{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:.18s;
  display:grid;place-items:center}
.sb-sw i svg{width:11px;height:11px;stroke:var(--side-1);fill:none;stroke-width:2}
[data-theme="dark"] .sb-sw i{left:23px}


/* ── Compteur de la sidebar (maquette : pastille rouge sur « À traiter ») ── */
.sb-link{ position:relative; }
.sb-cnt{ margin-left:auto; min-width:20px; height:20px; padding:0 6px; border-radius:var(--radius);
  background:var(--red); color:var(--on-red); font-size:11px; font-weight:600;
  display:inline-flex; align-items:center; justify-content:center; }


/* ============================================================================
   REFONTE UX — PASSE D'ÉPURE FINALE (override additif, purement visuel)
   ----------------------------------------------------------------------------
   À COLLER tel quel À LA FIN de THEME_CSS dans ui_theme.py (juste avant les
   triples guillemets fermants), APRÈS toutes les autres règles : la cascade
   fait gagner ce bloc sans qu'on modifie une seule classe HTML ni un endpoint.

   Ne touche NI aux données, NI au câblage /run, NI au JS : uniquement l'aspect.
   Réversible : supprime ce bloc pour revenir à l'état précédent.

   Ce que ça applique (état final validé de la console maquette) :
     · cartes/panneaux à PLAT (plus de barre d'accent à gauche, plus d'ombre)
     · surfaces neutres (fini les fonds teintés bleus des cartes/KPI)
     · sidebar plus calme (descriptions de groupe estompées)
     · tables et chips allégés
   ============================================================================ */

/* ---------- cartes & KPI : à plat, filet fin, aucune ombre ---------- */
.card{
     /* supprime la barre d'accent épaisse */
  
  background:var(--card);
}

/* ---------- surfaces neutres : plus de fonds bleutés « boîte » ---------- */
.card,.kpi,.panel{ background:var(--card); }
.note{  }              /* note : neutre au lieu du bleu */
.panel-hd .hic{  }     /* icône d'en-tête : neutre */
.qa a .ic{  }          /* action rapide : icône neutre */

/* ---------- sidebar : plus posée ---------- */
.sb-grp-d{ opacity:.72; }                    /* descriptions de groupe estompées */

/* ---------- tables : filets plus discrets, en-têtes calmes ---------- */

/* ---------- chips : neutres, sans fond bleu saturé ---------- */
.chip2{  border-color:var(--line); }
.chip{ background:var(--bg); color:var(--ink); }

/* ---------- segmented control : contour au lieu de plein ---------- */

/* ---------- retrait des ombres résiduelles sur petits éléments ---------- */
.card-eq{ box-shadow:none; }


/* ---------- onglet actif de la charpente : l'accent en aplat très dilué ----------
   Ce qui reste de l'ancien bloc « OVERRIDE ARDOISE ». Ses redéfinitions de tokens ont été
   remontées dans :root et dans le thème sombre — elles n'avaient rien à faire en fin de
   feuille. Ne subsiste ici que ce que le bloc AJOUTAIT vraiment. */
/* 29.07 — L'APLAT DILUÉ ÉTAIT ENCORE UN APLAT. Ces deux règles teintaient l'onglet courant de la
   charpente à 14 % et 16 % d'ardoise : dilué, donc discret, donc jamais discuté — et pourtant
   c'est le contrôle le plus présent de l'application, sur toutes les pages, dans les deux thèmes.
   Le voile redevient NEUTRE (il l'était déjà pour le survol, à 6 % et 11 %) ; c'est le
   soulignement qui désigne l'onglet, comme partout ailleurs depuis le reset. */
html:not([data-theme="dark"]) .sb-link.on{background:rgba(255,255,255,.11);}
[data-theme="dark"] .sb-link.on{background:rgba(255,255,255,.09);}


/* ==== HUB TOPBAR v2 (additif, desktop >=881px) : barre haute + nav integree, sans debordement. Mobile <=880 intact. Reversible. ==== */
@media(min-width:881px){
 .shell{display:block;min-height:100vh}
 .sb{flex-direction:row;align-items:center;height:56px;width:100%;position:sticky;top:0;z-index:40;border-right:none;border-bottom:1px solid var(--side-line);padding:0 12px;gap:2px;overflow:hidden}
 .sb-brand{order:0;flex:none;padding:0 10px 0 2px}
 .sb-brand span{display:none}
 .sb-nav{order:1;flex:0 0 auto !important;min-width:0;flex-direction:row;padding:0;margin:0;gap:2px;overflow-x:auto;scrollbar-width:none}
 .sb-nav::-webkit-scrollbar{display:none}
 .sb-link{width:auto;margin:0;padding:9px 13px;white-space:nowrap;border-radius:0;color:var(--side-ink)}
 .sb-link svg{opacity:.65}
 .sb-link:hover{background:rgba(255,255,255,.06);color:var(--cartouche-ink)}
 .sb-link.on{background:transparent;box-shadow:inset 0 -2px 0 var(--accent);color:#fff}
 .sb-link.on svg{opacity:1}
 .sb-cnt{margin-left:6px}
 .sb>button[onclick^='palOuvrir']{order:5;flex:none !important;width:168px !important;margin:0 2px 0 auto !important;padding:7px 10px !important;border-radius:var(--radius)}
 .sb-role{order:6;flex:none;margin:0 2px}
 .sb-role a,.sb-role span{padding:6px 10px}
 .sb-who{order:7;flex:none;border-top:none;padding:0 4px;margin:0;gap:6px !important}
 .sb-who b{font-size:12.5px} .sb-who small{display:none}
 .sb>div:last-child{order:8;flex:none;padding:0 6px !important}
 .tb{top:56px}
 .content{max-width:1560px;margin:0 auto}   /* corps CENTRE */
 /* CENTRAGE ALIGNE (tous onglets) : titre, sous-onglets, bandeaux et corps centres sur la MEME colonne 1560.
    Les barres restent pleine largeur (fond), mais leur CONTENU est repousse de l'inset de centrage + le padding habituel. */
 .tb{padding-left:calc(max(0px,(100% - 1560px)/2) + 26px);padding-right:calc(max(0px,(100% - 1560px)/2) + 26px)}
 #secbar .seg.sub{display:flex}
 #reassur{margin-left:calc(max(0px,(100% - 1560px)/2) + 18px);margin-right:calc(max(0px,(100% - 1560px)/2) + 18px)}
 #cmd_out{padding-left:calc(max(0px,(100% - 1560px)/2) + 18px);padding-right:calc(max(0px,(100% - 1560px)/2) + 18px)}
 /* sous-onglets = barre secondaire integree (souligne, defile, plus de pave blanc) */
 .seg.sub{background:transparent;border:none;border-bottom:1px solid var(--line);border-radius:0;padding:0;gap:0;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
 .seg.sub::-webkit-scrollbar{display:none}
 .seg.sub button{border-radius:0;padding:10px 15px;white-space:nowrap;color:var(--nav-ink)}
 .seg.sub button:hover{background:var(--hover);color:var(--ink)}
 .seg.sub button.on{background:transparent;color:var(--ink);box-shadow:inset 0 -2px 0 var(--accent)}
}
@media(min-width:881px) and (max-width:1199px){
 .sb-who>div{display:none}
 .sb>button[onclick^='palOuvrir']{width:150px}
 .sb>div:last-child a{font-size:0}
 .sb>div:last-child a::after{content:'AA';font-size:15px}
}


/* ==== TYPO (29.07) : Newsreader (titres) / Archivo (corps) / Space Mono (labels & meta).
   NEWSREADER remplace Fira Sans (reset du 29.07, DESIGN.md) : un planning est un document
   qu'on LIT. Fira Sans avait elle-meme remplace Space Grotesk le 28.07, sur maquette. Deux raisons,
   dont une qui se voit a l'oeil : le chiffre 1 de Space Grotesk n'a pas d'empattement de pied
   -- un simple baton vertical -- sur une application ou l'on lit des dates et des compteurs
   toute la journee ; et c'est l'une des faces les plus vues des interfaces generees, signalee
   comme telle par le detecteur. Fira Sans est humaniste, dessinee pour l'ecran. ==== */
.tb h1{font-family:var(--display);text-transform:uppercase;line-height:1.05}
.tb .sub{font-family:'Space Mono',ui-monospace,Menlo,Consolas,monospace;letter-spacing:.04em;text-transform:uppercase}
.kpi .v,.card .v{font-family:var(--display);letter-spacing:-.03em;font-weight:700}
/* LE BANDEAU DE KPI EST LE PREMIER ÉCRAN DE LA CONSOLE, et il était écrit en 10 px et 9,5 px —
   sous le pas d'étiquette documenté dans DESIGN.md (11 px / 600 / +0,06em / capitales). Sur une
   équipe à large tranche d'âge, c'est une obligation, pas un confort. Et les graisses étaient
   INVERSÉES : le détail (« 55 manquants ») portait 550 quand son titre (« DÉSIDÉRATA REÇUS »)
   portait 400 — la ligne accessoire criait plus fort que celle qu'elle accompagne. */
.kpi .lab,.kpi .l,.card .l{font-family:'Space Mono',ui-monospace,Menlo,Consolas,monospace;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft)}
.kpi .t{font-family:'Space Mono',ui-monospace,Menlo,Consolas,monospace;font-size:11px;font-weight:400;letter-spacing:.04em;text-transform:uppercase;line-height:1.45}


/* ==== HUB NAVFIX : les 5 espaces TOUJOURS visibles ; bloc droit compacte (nom masque, logout en icone) ==== */
@media(min-width:881px){
 .sb-nav{display:flex !important;overflow:visible !important}   /* display:flex OBLIGATOIRE : sans lui le <nav> reste bloc -> espaces empiles en colonne, un seul visible (bug 21.07) */
 .sb-who>div{display:none !important}
 .sb>div:last-child a{font-size:0}
 .sb>div:last-child a::after{content:'AA';font-size:16px}
}


/* ==== HUB CALX : calendriers harmonises (en-tetes mono, rayon aligne au reste) ==== */
.calx .dow{font-family:'Space Mono',ui-monospace,Menlo,Consolas,monospace;}
.calx .cell .d{font-family:'Space Mono',ui-monospace,Menlo,Consolas,monospace;letter-spacing:.02em}


/* ==== HUB EPURE : moins de texte inutile, KPI en bandeau joint, cartes a plat ==== */
.kpi-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));border:1px solid var(--line);border-radius:var(--r);overflow:hidden;margin-bottom:16px}
.kpi-strip .kpi{border:none;border-right:1px solid var(--line);border-radius:0;box-shadow:none;background:transparent}
.kpi-strip .kpi:last-child{border-right:none}
#reassur{display:none !important}   /* avertissement jugé inutile (arbitré 21.07) */
#reassur>span:first-child{display:none}


/* ==== HUB EPURE2 : sous-onglets soignes. (`.aide{display:none}` retire le 01.08 — voir la note
   « .aide EST MORT » plus haut : le texte ne se masque plus, il n'est plus ecrit.) ==== */
.seg.sub{margin:2px 0 20px}
.seg.sub button{margin-right:22px}


/* ==== HUB SECBAR : sous-onglets en barre secondaire collee sous la nav (Option C, 21.07). Reversible. ==== */
#secbar:empty{display:none}
#secbar{background:var(--bg);border-bottom:1px solid var(--line)}
#secbar .seg.sub{max-width:1560px;margin:0 auto;padding:0 26px;border-bottom:none;background:transparent}
#secbar .seg.sub button{padding:12px 0;margin-right:26px}
#secbar .seg.sub button.on{box-shadow:inset 0 -2px 0 var(--accent)}


/* Le cartouche du mois (`.cmois`) a vécu une journée (29.07) : il faisait une QUATRIÈME grammaire
   pour « situer un mois », alors que `.cartouche` — la feuille partagée, servie au portail par
   /theme_cartouche.css — portait déjà exactement ce rôle, avec son modificateur `.seul` pour le cas
   sans feuille en dessous. Le bloc du mois est donc un `.cartouche.seul` sur les DEUX surfaces, et
   ses commandes vivent sur sa rangée `.fl`. `.planbar`, `.pl-sorties` et `.cmois*` partent avec.
   La bande « à diffuser » (`.pubstrip`) reste : elle porte une case qui CHANGE ce que fait le
   bouton, ce n'est pas une commande de plus sur une rangée. */
.pubstrip{display:flex;align-items:center;gap:18px;flex-wrap:wrap;border:1px solid var(--line);
  border-radius:var(--radius);background:var(--card);padding:12px 16px;margin:0 0 24px}
.pubstrip .ps-h{font-size:11px;font-family:'Space Mono',ui-monospace,Menlo,monospace;text-transform:uppercase;
  letter-spacing:.06em;color:var(--ink-soft);width:100%;margin:0 0 2px}
#planmois .legend,#cadmois .legend{display:flex;flex-wrap:wrap;align-items:center;column-gap:18px;row-gap:6px;margin:0 0 8px}
.leg-indice{display:none}
@media (hover: hover){.leg-indice{display:inline;margin-left:auto;color:var(--ink-soft);padding-left:14px}}

/* Les interrupteurs de vue (Cadres, Modifs, À confirmer) : même contrôle sur la feuille et
   dans le cartouche, seules les encres suivent le support (cf. CARTOUCHE_CSS). */
.pl-toggles{display:inline-flex;align-items:center;gap:16px}
.pl-sw{display:inline-flex;align-items:center;gap:8px;cursor:pointer;font-size:12.5px;color:var(--ink);user-select:none}
/* LA CASE NE DISPARAÎT PAS, ELLE SE CACHE (29.07). `display:none` la retirait de l'ordre de
   tabulation ET de l'arbre d'accessibilité : « Cadres » et « Modifs », les deux seuls réglages de
   l'écran « Le planning », n'existaient que pour la souris — au clavier on ne pouvait pas les
   atteindre, et un lecteur d'écran ne les annonçait pas du tout. Masquage visuel classique : la
   case reste dans le flux, focalisable, et c'est le rail qui porte l'anneau de focus.
   ⚠ SÉLECTEUR QUALIFIÉ, ET C'EST NÉCESSAIRE : `input[type=checkbox]` impose 16×16 plus bas dans la
   feuille, à spécificité ÉGALE — un simple `.pl-sw input` perdait donc par l'ordre de source, et la
   case restait un carré de 16 px posé sur le rail. Mesuré, pas supposé. */
.pl-sw input[type=checkbox]{position:absolute;width:1px;height:1px;min-height:0;margin:0;padding:0;border:0;overflow:hidden;white-space:nowrap;clip-path:inset(50%)}
.pl-sw input:focus-visible + .pl-sw-t{outline:2px solid var(--accent);outline-offset:2px}
.pl-sw-t{width:34px;height:19px;border-radius:var(--radius);background:var(--line);position:relative;transition:.15s;flex:none}
/* ⚠⚠ LE BOUTON DE L'INTERRUPTEUR SUIVAIT SON RAIL (29.07). Il était peint `#fff` EN DUR pendant
   que le rail, lui, bascule entre deux tokens : `--line` éteint, `--ink` allumé. Un seul des deux
   états était donc lisible par thème — et c'était l'état OPPOSÉ d'un thème à l'autre. MESURÉ,
   bouton contre rail :
        clair  ALLUMÉ 17,40  ·  clair  ÉTEINT  1,24
        sombre ALLUMÉ  1,16  ·  sombre ÉTEINT 13,75
   En sombre, « allumé » était un bouton blanc sur un rail blanc : les deux interrupteurs de
   « Le planning » se lisaient comme deux pastilles vides, et on ne pouvait pas savoir si « Cadres »
   ou « Modifs » était actif. C'est la règle de `DESIGN.md` mot pour mot — « une couleur en dur, et
   le thème sombre ment » — et l'état ne tenait plus qu'à la POSITION du bouton.
   Le bouton bascule donc AVEC le rail : encre atténuée sur rail pâle, surface sur rail d'encre.
   Les quatre combinaisons passent 4:1 (seuil WCAG 1.4.11 pour un composant : 3:1).
   L'ombre portée du bouton part avec : elle compensait un bouton qu'on ne voyait pas, et un
   système plat ne pose pas d'ombre sur un objet de 15 px. */
.pl-sw-t::after{content:"";position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;background:var(--ink-soft);transition:.15s}
/* L'interrupteur allumé passe à l'ENCRE, pas à l'accent (29.07) : « allumé » est un état binaire,
   pas une désignation. L'ardoise est réservée à ce qui DÉSIGNE — l'onglet courant, l'action
   principale, le focus. Et l'encre pleine se distingue mieux du rail éteint que l'ardoise ne le
   faisait, dans les deux thèmes. */
.pl-sw input:checked + .pl-sw-t{background:var(--ink)}
.pl-sw input:checked + .pl-sw-t::after{left:17px;background:var(--card)}
.pl-sw-l{font-weight:500}
.grille-sem{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:0;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.grille-sem col.poste{width:120px}
.grille-sem th,.grille-sem td{border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
.grille-sem th:last-child,.grille-sem td:last-child{border-right:none}
.grille-sem tr:last-child td{border-bottom:none}
.grille-sem thead th{padding:10px 8px;text-align:center;vertical-align:middle;height:50px}
.grille-sem thead th .dw{font-family:var(--display);font-weight:700;font-size:13px;letter-spacing:-.01em}
/* PLANCHER À 11 PX DANS LA GRILLE DE SEMAINE (29.07). Ces trois-là n'étaient pas des marginalia :
   `.mo` est le MOIS de chaque colonne, `.h` sont les HEURES du poste (07–19, 19–07, 22–07), et
   `.was` est l'ANCIENNE VALEUR d'une garde modifiée — l'information la plus conséquente de la
   vue, écrite plus petit que tout le reste. `DESIGN.md` porte la règle depuis toujours ; elle
   était fausse au cœur de l'écran quotidien. La densité se rattrape par la casse et la chasse
   fixe de Space Mono, pas par la taille. */
.grille-sem thead th .mo{font-family:'Space Mono',ui-monospace,Menlo,monospace;font-size:11px;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.06em;margin-top:1px}
.grille-sem thead th.wknd .dw{color:var(--ink-soft)}
.grille-sem thead th.today{box-shadow:inset 0 -2px 0 var(--accent)}
.grille-sem thead th .crit{color:var(--red-ink);font-weight:700}
.grille-sem td.poste{padding:0 12px;vertical-align:middle;text-align:left;height:64px;background:var(--card)}
.grille-sem td.poste .p{font-family:var(--display);font-weight:700;font-size:12px;text-transform:uppercase}
.grille-sem td.poste .h{font-family:'Space Mono',ui-monospace,Menlo,monospace;font-size:11px;color:var(--ink-soft);margin-top:1px}
.grille-sem td.cell{height:64px;padding:6px;vertical-align:middle;text-align:center;position:relative}
.grille-sem td.cell.wknd{background:var(--hover)}
.grille-sem td.cell.out{background:var(--bg)}
.grille-sem tr.cadrerow td.cell{height:auto;padding:7px 6px;background:var(--bg)}
.grille-sem .cadretag{font-size:11px;line-height:1.3;color:var(--ink-soft)}
.grille-sem .pill{display:inline-flex;align-items:center;justify-content:center;font-size:12.5px;font-weight:500;color:var(--ink);background:var(--chip-bg);border:1px solid var(--line);border-radius:var(--radius-s);padding:5px 10px;line-height:1.2;max-width:100%}
.grille-sem .pill+.pill{margin-top:4px}
.grille-sem .pill .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grille-sem .pill.heli{background:var(--card);border-color:var(--accent);color:var(--ink);font-weight:600}
.grille-sem .pill.mod{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.grille-sem td.cell.mod{cursor:help}
.grille-sem td.cell.mod::after{content:"";position:absolute;top:5px;right:5px;width:0;height:0;border-top:9px solid var(--accent);border-left:9px solid transparent}
.grille-sem .was{display:block;font-family:'Space Mono',ui-monospace,Menlo,monospace;font-size:11px;color:var(--ink-soft);text-decoration:line-through;margin-top:2px}
.grille-sem .empty{color:var(--ink-soft);font-size:12px;font-family:'Space Mono',ui-monospace,Menlo,monospace}
.grille-sem .pill.piq{background:transparent;border-style:dashed;color:var(--ink-soft);font-weight:500}
.grille-sem tr.piqrow td.poste .p{color:var(--ink-soft)}
@media(max-width:880px){.grille-sem{font-size:11px}.grille-sem col.poste{width:76px}.grille-sem td.cell,.grille-sem td.poste{height:52px}}
/* sélecteur de mois (pilule + flèches) */
.mpick{display:inline-flex;align-items:center;gap:4px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:3px 5px;height:36px;vertical-align:middle}
.mpick .arrow{border:none;background:none;font-size:16px;line-height:1;color:var(--ink);width:28px;height:28px;border-radius:var(--radius-s);cursor:pointer;flex:none;display:inline-flex;align-items:center;justify-content:center;padding:0}
.mpick .arrow:hover{background:var(--hover);color:var(--ink)}
.mpick select{font-family:var(--display);font-weight:700;font-size:13px;color:var(--ink);text-align:center;min-width:116px;letter-spacing:-.01em}
/* Même pilule, sans `<select>` : la navigation par semaine de l'éditeur. Elle portait des boutons
   `.go.gris.sm` — une TROISIÈME grammaire pour « choisir une période » sur deux onglets voisins.
   ⚠ Ici les flèches sont TABULABLES, contrairement à celles du sélecteur de mois : là-bas elles
   doublent les touches fléchées natives du `<select>`, ici elles sont le seul moyen de bouger. */
.mpick .lbl{font-family:var(--display);font-weight:700;font-size:13px;color:var(--ink);text-align:center;min-width:148px;letter-spacing:-.01em;padding:0 4px}
/* ══ BARRE DE « Éditer le planning » (29.07) : UNE barre, deux moitiés qui répondent à deux
   questions. À GAUCHE « qu'est-ce que je regarde » (mois, semaine, construction à la main), à
   DROITE « qu'est-ce que je fais » (piquet, recharger, qui prévenir, état, Enregistrer).
   AVANT : deux rangées de contrôles empilées, sans principe de partage — le mois dans la première,
   la semaine dans la seconde —, et l'action DESTRUCTIVE (« Annuler la dernière publication »)
   posée en rouge au bout de la première, au-dessus de la grille, seule tache de couleur de l'écran
   et donc première chose que l'œil accrochait. Elle est descendue au pied, après la grille. ══ */
.edbar{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:6px 0 16px;padding-bottom:14px;border-bottom:1px solid var(--line)}
.edbar-l,.edbar-r{display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.edbar-r{margin-left:auto}
/* L'ÉTAT ET LE BOUTON SONT UN SEUL OBJET, jamais deux : « Aucune modification. » est la réponse à
   la question que pose Enregistrer. Séparés par le retour à la ligne, à 375 px, ils tombaient sur
   deux rangs différents et le bouton perdait sa légende. Ils passent à la ligne ENSEMBLE. */
.edbar .edsave{display:inline-flex;align-items:center;gap:10px;flex-wrap:nowrap;min-width:0}
.edbar .edstate{font-size:12px;color:var(--ink-soft);text-align:right}
.mpick select{-webkit-appearance:none!important;appearance:none!important;border:0!important;background:transparent!important;box-shadow:none!important;padding:0 4px!important;margin:0;cursor:pointer;text-align-last:center;height:28px;line-height:28px}
/* L'ANNEAU DE FOCUS VA SUR L'ENVELOPPE, PAS SUR LE `<select>` (29.07).
   CE QUI ÉTAIT FAUX : le `<select>` du sélecteur de mois était focalisable au clavier et
   STRICTEMENT INVISIBLE quand il l'était — mesuré par sonde comparative, repos et focus rendaient
   des styles IDENTIQUES. La règle générique `select:focus` pose bien bordure + anneau, mais la
   ligne au-dessus la désarme avec `box-shadow:none!important` (nécessaire : le select doit
   disparaître DANS la pilule). Au clavier, le curseur s'évanouissait donc sur le contrôle de
   navigation principal de Générer, Le planning et Éditer le planning. WCAG 2.4.7.
   ⚠ L'anneau ne peut PAS revenir sur le select — le `!important` le lui interdit — d'où
   `:focus-within` sur la pilule, qui est de toute façon la forme que l'œil voit.
   LES FLÈCHES GARDENT `tabindex="-1"`, et c'est DÉLIBÉRÉ : elles ne font que ce que les touches
   fléchées font déjà nativement sur un `<select>` focalisé. Les rendre tabulables ajouterait deux
   arrêts redondants par sélecteur, plusieurs fois par écran, sans rien rendre d'accessible qui ne
   le soit déjà. */
.mpick select:focus{outline:none}
.mpick:focus-within{border-color:var(--accent);box-shadow:var(--anneau)}

/* ===== BANDEAU DU HAUT PARTAGÉ (console + portail médecin) — voir barre_haut() ============
   Barre SOMBRE unique (fond --side-1) en clair ET sombre : logo, nav, recherche, interrupteur
   Gestionnaire⇄Médecin, thème, déconnexion, avatar. UN seul composant → switch invisible. */
.hb{position:sticky;top:0;z-index:45;display:flex;align-items:center;gap:6px;height:52px;padding:0 14px;
  background:var(--side-1);border-bottom:1px solid var(--side-line);color:var(--side-ink)}
/* LE BANDEAU « DÉMONSTRATION » (02.08). Posé au-dessus de la barre quand Reglages/DEMO.txt
   existe — donc JAMAIS en production, où le fichier n'est pas là. Il porte l'EXERGUE pâle
   (`--ex-pale` / `--ex-ink`), les deux seuls jetons de la palette qui ne peignent ni une
   commande ni un signal métier : la règle K dit que ce qui est coloré se clique, et un
   bandeau ne se clique pas. Il ne colle pas au défilement (la barre, elle, oui) : un rappel
   permanent qu'on ne peut plus lire cesse d'être lu — et c'est EXACTEMENT ce qui s'est passé
   au premier essai : posé en flux simple, il disparaissait dès la connexion, parce que l'écran
   d'accès fait une hauteur de fenêtre pleine et que les 30 px du bandeau la faisaient défiler
   d'autant. Sur LE seul écran que tout évaluateur traverse, le rappel ne tenait pas trois
   secondes. Il est donc COLLANT, et la barre du haut décale son propre ancrage de la même
   hauteur — lue, jamais recopiée. */
.hb-demo{position:sticky;top:0;z-index:60;display:flex;align-items:center;justify-content:center;
  gap:8px;min-height:var(--demo-h);padding:6px 14px;background:var(--ex-pale);color:var(--ex-ink);
  font-size:12px;font-weight:600;letter-spacing:.2px;text-align:center}
.hb-demo b{font-weight:700}
.hb-demo ~ .hb{top:var(--demo-h)}
.hb-brand{display:flex;align-items:center;gap:9px;padding-right:6px;flex:none}
.hb-logo{width:28px;height:28px;border-radius:var(--radius-xs);background:transparent;border:1px solid var(--side-line);display:grid;place-items:center;color:var(--cartouche-ink);font-family:var(--display);font-weight:600;font-size:14px}
.hb-brand b{color:var(--cartouche-ink);font-size:14px;font-weight:600;letter-spacing:-.2px;white-space:nowrap}
.hb-nav{display:flex;align-items:center;gap:2px;flex:1 1 auto;min-width:0;overflow-x:auto;scrollbar-width:none}
.hb-nav::-webkit-scrollbar{display:none}
/* ── LA NAVIGATION N'EST PAS UNE ACTION (02.08) ─────────────────────────────────────────────
   Signalé TROIS FOIS par Rémy, au même endroit : rails de la charpente, puis sous-onglets.
   J'avais appliqué « si c'est coloré, ça se clique » à la lettre — et une barre de navigation
   EST cliquable, donc je l'avais colorée. Compté à l'écran : **12 textes teal, dont 9 de
   navigation**. La carte était devenue la chose la plus bruyante de la page, et en thème
   sombre le cyan sur quasi-noir amplifie tout.
   Ce que la règle ne disait pas et qu'il faut écrire : une navigation répond à OÙ SUIS-JE,
   pas à QUE PUIS-JE FAIRE. Son état se dit déjà par le filet de 2 px — `DESIGN.md`, section
   Navigation, « UNE SEULE GRAMMAIRE, partout », posée au reset du 29.07 — et la demande de
   Rémy disait dans la même phrase « utilise les couleurs avec PARCIMONIE ». Colorer neuf
   repères de carte, c'était tenir la moitié du brief contre l'autre.
   L'accent reste donc à ce qui AGIT : boutons, liens, créneaux tapables, dans la feuille.
   Trois ou quatre par écran au lieu de douze. */
.hb-link{display:inline-flex;align-items:center;gap:7px;padding:7px 12px;border-radius:var(--radius);color:var(--side-ink);
  font-size:13.5px;font-weight:500;text-decoration:none;white-space:nowrap;cursor:pointer;border:none;background:none;font-family:inherit;transition:.12s}
.hb-link svg{width:16px;height:16px;opacity:.85;flex:none}
.hb-link:hover{background:rgba(255,255,255,.06);color:var(--cartouche-ink)}
.hb-link.on{background:rgba(255,255,255,.11);color:var(--cartouche-ink)}
.hb-right{display:flex;align-items:center;gap:8px;flex:none;margin-left:auto}
.hb-search{display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.06);border:1px solid var(--side-line);
  border-radius:var(--radius);color:var(--side-ink-soft);font-size:13px;padding:7px 11px;cursor:pointer;white-space:nowrap;font-family:inherit}
.hb-search svg{width:14px;height:14px}
/* `opacity:.7` écrasait une encre déjà calculée pour ce fond : le ⌘K tombait à 3,80:1 alors que
   `--side-ink-soft` vaut 6,30:1 sur la charpente. Une encre mesurée ne se re-voile pas. */
.hb-search kbd{font-size:11px;font-family:inherit}

/* TAILLE DE BASE DES CASES ET DES RADIOS (29.07). Elle n'existait QUE dans le bloc tactile ; sous
   pointeur fin chaque case retombait sur le défaut du navigateur (~13 px), et les endroits qui
   voulaient mieux le posaient EN LIGNE — un style en ligne qui battait ensuite la règle tactile,
   laissant la case à 16 px au doigt. La taille se déclare ici, la règle tactile la relève, et
   plus personne n'a besoin d'écrire un style en ligne. */
input[type=checkbox],input[type=radio]{width:16px;height:16px}
.hb-role{display:inline-flex;gap:3px;padding:3px;background:rgba(255,255,255,.06);border-radius:var(--radius);flex:none}
.hb-role a{display:inline-flex;align-items:center;gap:6px;padding:6px 11px;border-radius:var(--radius);font-size:13px;font-weight:550;
  color:var(--side-ink-soft);text-decoration:none;white-space:nowrap}
.hb-role a svg{width:14px;height:14px}
.hb-role a.on{background:transparent;color:var(--cartouche-ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--accent)}
.hb-role a:hover:not(.on){background:rgba(255,255,255,.07);color:var(--cartouche-ink)}
.hb-sw{width:44px;height:24px;border-radius:var(--radius);border:0;background:rgba(255,255,255,.12);position:relative;cursor:pointer;flex:none}
.hb-sw i{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:.18s;display:grid;place-items:center}
.hb-sw i svg{width:11px;height:11px;stroke:var(--side-1);fill:none;stroke-width:2}
[data-theme="dark"] .hb-sw i{left:23px}
/* 24 px MÊME SOUS POINTEUR FIN (WCAG 2.2 AA 2.5.8) — le plancher que ce projet s'applique déjà
   à `.dtag button` et `.dqp button`. La déconnexion mesurait 19,4 px de haut : c'est la SEULE
   sortie du portail au téléphone, et elle passait sous le minimum à tous les pointeurs. La
   taille tactile (44 px), elle, reste dans la requête du pointeur — c'est une autre question. */
.hb-logout{font-size:12.5px;color:var(--side-ink-soft);text-decoration:none;white-space:nowrap;
  display:inline-flex;align-items:center;min-height:24px}
.hb-logout:hover{color:var(--cartouche-ink)}
.hb-av{width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.10);display:grid;place-items:center;color:#e7e8ee;font-weight:600;font-size:12px;flex:none}
.hb-burger{display:none;background:none;border:1px solid var(--side-line);color:var(--side-ink);border-radius:var(--radius);font-size:18px;padding:2px 9px;cursor:pointer}
/* L'ÉTIQUETTE DU LIEN PRENAIT L'ENCRE DE LA PAGE (28.07). `.lbl` est stylé ailleurs par
   `.lbl,label{color:var(--ink-soft)}` — le jeton du CORPS du document. Or ce lien vit sur la
   charpente SOMBRE, qui ne suit pas le thème : en thème clair `--ink-soft` est un gris foncé, et
   les libellés de navigation tombaient à 3,4:1 sur du noir (2,45:1 sur l'onglet actif). Le
   libellé doit suivre la couleur de SON lien — il hérite, et suit donc l'état actif et le survol. */
.hb-link .lbl{color:inherit}
@media(max-width:900px){.hb-search,.hb-logout{display:none}}
/* SOUS 680 px, LA BARRE PASSE EN DEUX RANGS (29.07). Mesuré avant d'écrire : à 375 px la boîte
   `.hb-nav` faisait 130 px pour 208 px de liens — « Comprendre » et « Système » étaient COUPÉS,
   et `scrollbar-width:none` ne laissait aucun indice qu'il y avait une suite. Deux espaces sur
   cinq, dont l'équité qui justifie une décision d'échange, étaient inatteignables au téléphone.
   Élargir la barre ne suffisait pas : le rang porte aussi la marque, la bascule de rôle, le
   thème et l'avatar. On donne donc au champ de navigation UN RANG À LUI — 296 px utiles même à
   320 px, pour 188 px de liens : plus rien à faire défiler, donc plus rien à cacher.
   ⚠ `display:none` sur le libellé le retirait AUSSI de l'arbre d'accessibilité : les cinq
   boutons n'avaient plus aucun nom. Le libellé est désormais masqué VISUELLEMENT et reste LU. */
@media(max-width:680px){
  .hb{flex-wrap:wrap;height:auto;padding:0 12px 8px}
  .hb-brand,.hb-right{height:52px}
  .hb-nav{order:3;flex:1 0 100%;justify-content:space-between;gap:2px}
  .hb-link{padding:7px 10px}
  .hb-brand b{display:none}
  /* La déconnexion réapparaît : le rang 1 est libéré de la navigation, elle y tient. Elle était
     masquée dès 900 px et le portail n'avait alors PLUS AUCUNE sortie sur téléphone — l'avatar
     est un `div`, pas un lien. */
  .hb-logout{display:inline}
  .hb-role a span,.hb-link .lbl{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
}

/* ════════════════════════════════════════════════════════════════════════════════════════════
   LE DOIGT — adaptation à l'appareil de pointage, pas à la largeur d'écran (28.07).

   CE QUI ÉTAIT FAUX : ce projet n'avait AUCUN `pointer:coarse` ni `hover:none`, nulle part.
   Toutes les adaptations passaient par `max-width`. Or la largeur ne dit pas comment on touche :
   un portable tactile est large ET se manipule au doigt, et l'audit a mesuré des cibles à 14,
   16 et 19 px — sous le minimum WCAG 2.2 AA (24 px) et très loin des 34 px de la charte.

   LA RÈGLE RETENUE : la DENSITÉ reste pour la souris — c'est un choix assumé du produit, un
   planning est un champ de données — et la TAILLE grandit pour le doigt. Rien ne change donc
   sous un pointeur fin ; tout atteint 44 px sous un pointeur grossier.

   ⚠ On agrandit par le PADDING et par des zones de frappe invisibles, jamais par la police :
   grossir le texte reflowerait des tableaux entiers et casserait la mesure des colonnes. ════ */
@media (pointer: coarse){
  /* contrôles ordinaires : la hauteur passe le seuil sans que la maquette bouge.
     31.07 — quatre contrôles rejoignent la liste, tous mesurés en échec : la BASCULE DE RÔLE et
     la DÉCONNEXION (elles vivent sur la charpente, donc sur les 34 écrans), le RÉSUMÉ d'un
     dépliant (`<details>` est le motif d'explication recommandé par DESIGN.md, et son résumé
     mesurait 19,4 px), et le SÉLECTEUR DE VUE de la bourse (`.bviewbtn`, 35 px — sa règle vit
     dans une interpolation JS, l'angle mort documenté de check_charte). */
  .go,.ui-btn,.subtab,.seg button,.seg.sub button,.hb-link,.mpick .arrow,.bviewbtn,.hb-search,
  input:not([type=checkbox]):not([type=radio]),select,textarea{min-height:44px}

  /* ⚠⚠ UNE CIBLE EST UNE SURFACE, PAS UNE HAUTEUR (31.07).
     Cette règle existait depuis le 28.07 et n'a JAMAIS porté que `min-height`. Un contrôle de
     36 × 44 px n'est pas une cible de 44 px : WCAG 2.5.8 demande un carré, et un pouce ne vise
     pas une lame. Mesuré sur les 34 écrans de la console, à 375 px, pointeur grossier :
       · `.hb-link` ....... 36 × 44 — les SIX espaces, sur TOUS les écrans
       · `.hb-role a` ..... 36 × 26 — la bascule Gestionnaire ⇄ Médecin, idem
       · `.hb-logout` ..... 73 × 19,4 — la seule sortie au téléphone
       · `.mpick .arrow` .. 28 × 44 — mois précédent / suivant, 5 écrans
       · `.seg.sub button`  41 × 44 — les sous-onglets
       · `.ui-btn` (✓) .... 34,9 × 44 · `.go` (↻) 31,8 × 44
     La hauteur avait été traitée parce qu'elle se voit ; la largeur ne se voyait pas, et aucun
     contrôle ne pouvait la contredire. C'est la même leçon que les invariants A à D de
     check_charte, à une dimension près — d'où l'invariant H, écrit en même temps que ce
     correctif : il REFUSE désormais qu'une règle tactile ne porte qu'une seule dimension.
     MESURÉ AVANT D'ÉCRIRE, à 375 px : `.hb-nav` offre 351 px utiles pour six liens à 44 px
     (274 px avec les gouttières), et le rang 1 garde 65 px libres pour les 16 px que réclame
     la bascule de rôle. Rien ne déborde ; c'est vérifié plus bas, pas supposé. */
  .go,.ui-btn,.subtab,.seg button,.seg.sub button,.hb-link,.mpick .arrow,.bviewbtn,
  .hb-role a{min-width:44px}
  /* La bascule de rôle et la déconnexion sont des liens INLINE : `min-height` seul ne les touche
     pas (une boîte en ligne n'a pas de hauteur propre). Elles deviennent des boîtes. */
  .hb-role a{min-height:44px}
  .hb-logout{display:inline-flex;align-items:center;min-height:44px}
  /* Le résumé d'un dépliant garde sa PUCE — c'est elle qui dit qu'on peut l'ouvrir. On l'épaissit
     donc par le rembourrage, jamais en le passant en `flex` (ce qui retire le marqueur).
     ⚠ `details>summary` (0,0,2) BAT `summary` (0,0,1), et une requête média n'ajoute aucune
     spécificité : écrite seule, cette règle était annulée par le plancher de 24 px posé plus
     haut, et les résumés plafonnaient à 41,4 px. Mesuré, pas relu. Les deux sélecteurs sont
     donc nommés ensemble. */
  summary,details>summary{min-height:44px;box-sizing:border-box;padding-top:11px;padding-bottom:11px}
  /* ⚠ ET `min-height` NE PEUT RIEN SUR UNE BOÎTE EN LIGNE — troisième fois (01.08). C'était déjà
     la cause de `.hb-role a` (36×26) et de `.hb-logout` (73×19,4) le 31.07 ; c'est ici un
     `<summary style="display:inline">` (« légende des colonnes », onglet Équité), mesuré à 13 px
     au repos et à 35 px SOUS CETTE RÈGLE : le rembourrage gonfle la boîte peinte, il ne donne pas
     de hauteur à une ligne. La règle ci-dessus a donc l'air de s'appliquer, et un contrôle « à
     35 px » est plus trompeur qu'un contrôle à 13 : on le croit traité.
     Le résumé fautif est passé en `inline-block` à la source ; ce repli attrape les suivants.
     ⚠ `!important` est ICI une nécessité, pas une facilité : la déclaration visée est un style EN
     LIGNE, et une feuille ne bat un style en ligne d'aucune autre façon — sans lui, la règle
     serait écrite, lisible, et sans le moindre effet. Elle est bornée au pointeur grossier et à
     un `<summary>` qui se déclare en ligne : elle ne peut rien casser d'autre. */
  summary[style*="display:inline"]:not([style*="inline-block"]){display:inline-block !important}
  /* Contrôles nommés une seule fois dans leur écran, donc jamais entrés dans la liste ci-dessus :
     le segmenté des types d'absence, le déclencheur `.alink`, la puce-lien des archives et la
     pastille de filtre de la fiche 360. Mesurés à 26, 35, 28,6 et 27,4 px de haut. */
  #ab_typeseg button,.alink,a.chip,.chip2[onclick]{min-height:44px;min-width:44px}
  #ab_typeseg button,.alink{padding-top:10px;padding-bottom:10px}
  /* Les interrupteurs « Cadres » et « Modifs » de l'écran « Le planning » : la cible tactile est
     le LABEL entier (rail + mot), mesuré à 19 px. Le rail, lui, garde ses 34×19 — on grandit la
     surface de frappe, pas le dessin. */
  .pl-sw{min-height:44px}
  /* Le bouton du champ de fichier est un PSEUDO-ÉLÉMENT : donner 44 px au champ ne l'atteint pas.
     C'est pourtant lui qu'on vise au doigt — le champ, lui, n'est qu'une étiquette de nom. */
  .ui-file::file-selector-button{min-height:44px;padding:0 15px}
  /* `.act-link` porte déjà sa zone de frappe de 44 px à tous les pointeurs (voir sa définition) :
     lui imposer `min-height` ici décollerait son filet du texte, qui est précisément ce qui le
     rend lisible. On l'espace de ses voisins, on ne le grossit pas. */
  .act-link+.act-link{margin-left:14px}
  .go,.ui-btn,.subtab{padding-top:10px;padding-bottom:10px}
  /* les cases à cocher et les radios grossissent VRAIMENT : leur glyphe est la cible.
     22 → 24 px (31.07) : ce projet cite WCAG 2.5.8 comme son plancher ailleurs (« 24 px MÊME
     SOUS POINTEUR FIN », `.dtag button`, `.dqp button`), et 22 px passait dessous. Deux pixels
     qui ne se voient pas, mais une norme qu'on s'applique ou qu'on ne s'applique pas. */
  input[type=checkbox],input[type=radio]{width:24px;height:24px}
  /* espacer les actions voisines : deux cibles de 44 px collées se touchent quand même mal */
  .ligne .go+.go,.ui-btn+.ui-btn{margin-left:8px}
}

/* Zone de frappe invisible pour les glyphes trop petits pour être des cibles. Le signe garde sa
   taille — l'agrandir ferait une croix énorme au milieu d'un tableau — mais la surface tapable
   atteint 44 px. Vaut pour TOUS les pointeurs : viser un ✕ de 14 px à la souris n'est pas
   agréable non plus. */
.zone-frappe{position:relative}
.zone-frappe::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:44px;height:44px}

/* Le sélecteur de thème est une bascule de 44×24 : la grandir en hauteur la déformerait. On lui
   donne sa zone de frappe au lieu de sa taille. */
@media (pointer: coarse){
  .hb-sw{position:relative}
  .hb-sw::before{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:48px;height:44px}
}

/* CE QUI SE RÉVÈLE AU SURVOL DOIT EXISTER SANS SURVOL. Un doigt ne survole pas : une action
   cachée derrière `:hover` n'est pas discrète sur un téléphone, elle est INTROUVABLE. */
@media (hover: none){
  [data-survol-seul]{opacity:1 !important}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   REGISTRE DE FORMATION (onglet Formation, 30.07) — la grille marginale du reset du 29.07
   ------------------------------------------------------------------------------------------
   UN REGISTRE, PAS UN TABLEAU DE BORD. La question qu'on se pose en ouvrant cet écran est
   « qui arrive, et que doit-il encore faire ? » : la FILE mène, le registre suit, l'éditeur
   se convoque. Chaque ligne est une obligation datée — la date dans la MARGE en monospace,
   le nom en TITRE en serif. C'est la grammaire déjà retenue le 29.07 pour la carte de garde
   du portail, appliquée telle quelle : le contraste des GENRES tient la hiérarchie, aucun
   aplat n'est nécessaire.

   ⚠ CES RÈGLES VIVENT ICI, PAS DANS LE JS. L'ancien onglet composait son CSS dans des gabarits
   (`background:${TC[t]}`, `border:1px solid ${c}44`) : c'est l'angle mort DOCUMENTÉ de
   check_charte, donc du style non gardé — et `var(--accent)44` est du CSS INVALIDE, si bien que
   ces bordures ne s'affichaient pas du tout. Un seul auteur du monde visuel (invariant E).

   L'ACCENT NE PEINT RIEN ICI. Il souligne (`inset 0 -2px 0`) et il remplit la jauge — une
   quantité, pas un contrôle. Aucun `color:var(--ink)` : `--accent` est un APLAT, son encre
   posée est `--on-accent` (invariant B). Les états portent donc un MOT en plus de leur encre
   (règle du signal doublé), et le plancher de 11 px n'est franchi nulle part.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* ---------- l'échéance : un fait, en monospace, sur filet ---------- */
.frm-echeance{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 18px;
  font-family:var(--mono);font-size:12px;letter-spacing:.03em;color:var(--ink-soft);
  border:1px solid var(--line);border-radius:var(--radius);padding:11px 14px;margin-bottom:18px;
  background:var(--card)}
.frm-echeance b{color:var(--ink);font-weight:700}
.frm-echeance .frm-urgent{color:var(--red-ink);font-weight:700}

/* ---------- la file : une ligne = une obligation datée ---------- */
.frm-titre{font-family:var(--display);font-size:19px;font-weight:600;letter-spacing:-.01em;
  color:var(--ink);margin:26px 0 4px}
.frm-titre:first-child{margin-top:0}
.frm-sous{font-size:12px;color:var(--ink-soft);line-height:1.5;margin:0 0 12px;max-width:70ch}
.frm-file{border-top:1px solid var(--line)}
.frm-ligne{display:grid;grid-template-columns:minmax(0,124px) minmax(0,1fr);gap:0 18px;
  padding:13px 2px;border-bottom:1px solid var(--line);align-items:start}
.frm-ligne>*{min-width:0}
.frm-ligne:hover{background:var(--hover)}

/* la marge : la date et la fenêtre, en monospace — ce qui se MESURE */
.frm-marge{font-family:var(--mono);font-size:11px;line-height:1.45;letter-spacing:.03em;
  color:var(--ink-soft);padding-top:2px}
.frm-marge .frm-quand{display:block;color:var(--ink);font-weight:700}
.frm-marge .frm-bientot{color:var(--red-ink);font-weight:700}

/* le corps : le nom en serif, le rôle en accompagnement */
.frm-nom{font-family:var(--display);font-size:16px;font-weight:600;letter-spacing:-.01em;
  color:var(--ink);line-height:1.25;overflow-wrap:anywhere}
/* UN CRÉNEAU N'EST PAS UNE PERSONNE. Il n'a pas de nom parce qu'on ne lui en invente pas
   (« on ne devine jamais une identité ») : il se dit en italique et atténué, et le mot
   « créneau » l'accompagne toujours dans le balisage. */
.frm-nom.frm-creneau{font-style:italic;color:var(--ink-soft);font-weight:400}
.frm-role{font-size:12px;color:var(--ink-soft);line-height:1.45;margin-top:2px}
.frm-presume{font-family:var(--mono);font-size:11px;letter-spacing:.03em;color:var(--orange-ink)}

/* ---------- les phases : des jetons monospace, jamais des pastilles pleines ---------- */
.frm-phases{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px}
.frm-phase{display:inline-flex;align-items:baseline;gap:5px;font-family:var(--mono);font-size:11px;
  font-weight:600;letter-spacing:.03em;border:1px solid var(--line);border-radius:var(--radius-xs);
  padding:3px 8px;color:var(--ink-soft);background:transparent}
.frm-phase .frm-duree{font-weight:400;color:var(--ink-soft)}
/* À FAIRE : encre pleine, graisse, et le filet de 2 px — la grammaire d'état du 29.07. */
.frm-phase.frm-due{color:var(--ink);border-color:var(--ink-soft);
  box-shadow:inset 0 -2px 0 var(--accent)}
.frm-phase.frm-prevue{color:var(--ink)}
.frm-phase.frm-faite{color:var(--green-ink);border-color:var(--line)}
.frm-phase.frm-ouverte{border-style:dashed}
.frm-rien{font-family:var(--mono);font-size:11px;letter-spacing:.03em;color:var(--green-ink)}

/* ---------- LA FILE ET LE REGISTRE SONT DES LISTES ----------
   Elles étaient des `div` empilées : un lecteur d'écran recevait quatorze lignes en flux
   indifférencié, sans jamais savoir qu'une nouvelle entrée commençait, ni combien il y en avait. */
.frm-file{list-style:none;margin:0;padding:0}
.frm-item{display:block}

/* ---------- L'ÉDITEUR CONVOQUÉ ----------
   Il naît SOUS la ligne qui l'a appelé, décalé dans la colonne du corps pour se lire comme
   appartenant à cette ligne — pas comme un panneau flottant. Un filet, pas une carte : on
   n'empile pas une carte dans une carte (DESIGN.md). */
/* ⚠ Le filet de gauche marque la ligne qui a convoqué l'éditeur — il reste à 1 px : « Don't poser
   une barre latérale colorée de plus de 1 px sur un bloc, une ligne ou une alerte » (DESIGN.md).
   Il était à 2 px, et aucun garde-fou ne l'aurait dit : check_charte surveille l'accent employé
   en APLAT, pas son épaisseur en filet. C'est le décalage à l'œil qui l'a montré. */
.frm-editeur{border:1px solid var(--line);border-left:1px solid var(--accent);
  border-radius:var(--radius);background:var(--card);padding:12px 14px;margin:0 0 14px 142px}
@media (max-width:620px){.frm-editeur{margin-left:0}}
/* Le bouton qui a convoqué l'éditeur porte l'état actif : soulignement, jamais aplat. */
.frm-ouvrir[aria-expanded="true"]{box-shadow:inset 0 -2px 0 var(--accent);font-weight:600}
.frm-session-hd{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin-bottom:9px}
.frm-session-hd select{font-weight:600}

/* ---------- LE SÉLECTEUR DE NOMS ----------
   Il remplace un `datalist` branché sur un champ MULTI-VALEURS, où il ne pouvait pas fonctionner :
   le navigateur compare la valeur entière du champ, donc l'autocomplétion mourait après le
   premier nom. Replié par défaut — 63 options ouvertes seraient un mur. */
.frm-choisir{margin-top:6px}
.frm-choisir summary{cursor:pointer;font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink);padding:4px 0}
.frm-choisir summary:hover{color:var(--ink)}
/* Le choix du premier jour et le rappel de la durée tiennent sur une ligne. */
.frm-jours{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px}
.frm-jours input[type=date]{min-width:0}

/* FILTRER PLUTÔT QUE FAIRE DÉFILER : 63 noms ouverts d'un bloc sont un mur. */
.frm-filtre{display:flex;align-items:center;gap:8px;margin:6px 0}
.frm-filtre input{flex:1;min-width:0;max-width:280px}
.frm-reste{margin-top:6px}
.frm-reste summary{cursor:pointer;font-family:var(--mono);font-size:11px;letter-spacing:.03em;
  color:var(--ink);padding:3px 0}
.frm-reste summary:hover{color:var(--ink)}
/* Les soldés se rangent derrière un repli : la file ne garde que ce qui appelle une action. */
.frm-ajour{margin-top:8px}
.frm-ajour summary{cursor:pointer;font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink);padding:6px 0}
.frm-ajour summary:hover{color:var(--ink)}
/* UN ACQUIS N'EST PAS UNE SESSION TENUE. Même effet sur la dette, autre nature de preuve : il
   porte le mot « acquis » en plus de son ✓, et son encre reste celle du texte accompagnant. */
.frm-phase.frm-acquis{color:var(--green-ink);border-style:dashed;border-color:var(--line)}
/* Action secondaire posée dans une ligne de la file : elle ne doit peser ni plus que le nom
   qu'elle accompagne, ni moins qu'un bouton atteignable. */
.frm-mini{font-size:11px;padding:2px 8px;margin-left:6px}
.frm-choix-grp{display:flex;flex-wrap:wrap;gap:5px;margin:6px 0}
.frm-choix{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.03em;
  border:1px solid var(--line);border-radius:var(--radius-xs);padding:3px 8px;
  background:transparent;color:var(--ink);cursor:pointer}
.frm-choix:hover{background:var(--hover);color:var(--ink)}
/* CHOISI se dit par l'encre, la graisse et le filet de 2 px — plus le ✓ que pose le balisage
   (règle du signal doublé : en niveaux de gris, la coche reste). Jamais un aplat. */
.frm-choix.frm-choisi{color:var(--ink);border-color:var(--ink-soft);
  box-shadow:inset 0 -2px 0 var(--accent)}
/* ABSENT : l'encre d'alarme et le ✕ que pose le balisage. Pas d'aplat — et surtout pas la seule
   couleur : en niveaux de gris, c'est le ✕ contre le ✓ qui sépare les deux états. Le troisième
   état — PAS ENCORE TRANCHÉ — est l'absence des deux, et il ne se peint pas. */
.frm-choix.frm-absent{color:var(--red-ink);border-color:var(--red-ink)}
.frm-choix .frm-duree{margin-left:5px;font-weight:400}
.frm-champ{display:grid;grid-template-columns:minmax(0,124px) minmax(0,1fr);gap:6px 18px;
  align-items:center;margin:7px 0}
.frm-champ>*{min-width:0}
.frm-champ label{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-soft);margin:0}
.frm-champ input{width:100%}
.frm-vide{font-size:12.5px;color:var(--ink-soft);line-height:1.55;border:1px dashed var(--line);
  border-radius:var(--radius);padding:14px 16px;max-width:70ch}

/* ---------- F SMUR 3 : LA SESSION AGILE, ET PLUS DE JAUGE ----------
   La barre mesurait « inscrits / éligibles » : une promesse de 100 % posée sur une formation
   OBLIGATOIRE POUR PERSONNE, sur le seul écran dont l'objet est de distinguer ce qui est DÛ de ce
   qui est OUVERT. Elle fabriquait une dette qui n'existe pas. Rémy a tranché le 30.07 : il n'y a
   AUCUNE capacité fixée — donc aucun plafond à mesurer, donc pas de barre. Le compte écrit dit le
   même fait sans rien promettre.
   ⚠ Conséquence à connaître : il ne reste PLUS AUCUN aplat d'accent sur cet onglet. L'accent n'y
   souligne que l'état actif et l'action principale, ce qui est exactement le reset du 29.07. */
.frm-capacite{font-family:var(--mono);font-size:11px;letter-spacing:.03em;color:var(--ink-soft)}

/* ---------- CE QUI SE PASSE MAL SE DIT À CÔTÉ DE CE QUI L'A CAUSÉ ----------
   L'écran n'avait AUCUN message d'erreur : une date mal saisie ne produisait rien de visible.
   L'erreur vit donc sous son champ, elle nomme la valeur fautive, et elle ne peint pas un aplat —
   l'encre d'alarme et le mot suffisent (la couleur seule ne porte jamais un état). */
.frm-erreur{font-family:var(--mono);font-size:11px;line-height:1.45;letter-spacing:.03em;
  color:var(--red-ink);margin-top:4px;overflow-wrap:anywhere}
.frm-champ input[aria-invalid="true"]{border-color:var(--red-ink)}
/* LE FORMAT ATTENDU EST UNE AIDE PERMANENTE, PAS UN TEXTE INDICATIF. Dans un placeholder il
   disparaissait à la première frappe — et il y mesurait 3,28:1 en thème sombre, sous le plancher,
   faute de règle `::placeholder` (le gris par défaut du navigateur ne suit pas le thème). */
.frm-aide-champ{font-family:var(--mono);font-size:11px;line-height:1.45;letter-spacing:.03em;
  color:var(--ink-soft);margin-top:4px}
/* filet de sûreté : si un texte indicatif subsiste quelque part, il reste lisible dans les deux thèmes */
#frm_box input::placeholder{color:var(--ink-soft);opacity:1}
.frm-alerte{border:1px solid var(--red-ink);border-radius:var(--radius);padding:10px 13px;
  margin:12px 0;font-size:12.5px;line-height:1.55;color:var(--ink);background:transparent}
.frm-alerte b{color:var(--red-ink)}
.frm-sansdate{font-family:var(--mono);font-size:11px;letter-spacing:.03em;color:var(--orange-ink)}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   « DEPUIS MON PASSAGE » (onglet Accueil, 31.07) — l'écran où tout était tronqué
   ------------------------------------------------------------------------------------------
   Une ligne = un changement fait par quelqu'un d'autre. Sa DESCRIPTION portait
   `white-space:nowrap` + `text-overflow:ellipsis` : à 375 px, 185 px affichés pour 358 px de
   texte, sur les 120 lignes de l'écran. On ne lisait donc jamais CE QUI avait changé — la
   seule information que cet écran existe pour donner.
   La ligne reste une ligne sur grand écran ; sous 620 px elle devient une pile, et la phrase
   se lit en entier. « La règle de la phrase entière » (DESIGN.md) n'est pas une préférence :
   c'est la raison d'être de l'écran. */
.qn-item{display:flex;align-items:center;gap:10px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius);padding:9px 13px;margin-bottom:6px}
.qn-ic{font-size:15px;flex:none}
.qn-corps{flex:1;min-width:0}          /* la règle du minimum zéro */
.qn-qui{font-size:12.5px}
/* Le TYPE se dit par la casse et la chasse, pas par l'accent : `--accent` est un aplat, et
   « l'accent ne peint pas » depuis le reset du 29.07. */
.qn-type{font-family:var(--mono);font-size:11px;letter-spacing:.04em;color:var(--ink-soft)}
.qn-quoi{font-size:11.5px;color:var(--ink-soft);margin-top:1px;overflow-wrap:anywhere}
.qn-ts{font-family:var(--mono);font-size:11px;color:var(--ink-soft);white-space:nowrap;flex:none}
.qn-btn{padding:4px 10px;font-size:11.5px;margin:0;flex:none}
.qn-voir{flex:none}
@media(max-width:620px){
  /* La pile : l'horodatage et les actions passent sous le texte plutôt que de le comprimer. */
  .qn-item{flex-wrap:wrap;align-items:flex-start;gap:6px 10px}
  .qn-corps{flex:1 0 100%;order:1}
  .qn-ic{order:0}
  .qn-ts{order:2}
  .qn-btn,.qn-voir{order:3;margin-left:auto}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   GARDE MINIMALE HÉLICO — une ligne par médecin (onglet Hélico, 31.07)
   ------------------------------------------------------------------------------------------
   Six enfants de flex en `nowrap`, tous dimensionnés en dur (30 + 150 + jauge + 60 + deux
   pastilles) : 453 px de contenu pour 317 px de place à 375 px. Trente-cinq pastilles
   sortaient de l'écran par la droite et faisaient défiler la PAGE de 197 px — dont « treuil à
   faire », c'est-à-dire précisément l'information qu'on vient chercher ici.
   Sous 620 px la ligne devient une pile : identité, puis jauge pleine largeur, puis les
   pastilles. Rien n'est retiré — une carte ne rétrécit pas, elle choisit son rangement. */
.hli{display:flex;align-items:center;gap:12px;padding:9px 0;border-bottom:1px solid var(--line)}
.hli-ini{width:30px;height:30px;border-radius:50%;flex:none;background:var(--bg);
  border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:600;color:var(--ink-soft)}
.hli-qui{width:150px;flex:none;min-width:0}
.hli-nom{font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hli-team{font-size:11.5px;color:var(--ink-soft)}
.hli-jauge{flex:1;min-width:60px;height:8px;border-radius:var(--radius-s);background:var(--bg);overflow:hidden}
.hli-part{height:100%;border-radius:var(--radius-s)}
.hli-cpt{width:60px;text-align:right;font-family:var(--mono);font-size:12px;font-weight:600;flex:none}
/* Les quatre états portent une ENCRE, jamais un aplat — et le MOT est toujours là (règle du
   signal doublé) : « atteint », « reste 7 », « REGA à jour », « treuil à faire ». */
.chip2.hli-ok{color:var(--green-ink)}
.chip2.hli-att{color:var(--orange-ink)}
.chip2.hli-ko{color:var(--red-ink)}
.chip2.hli-nc{color:var(--ink-soft)}
@media(max-width:620px){
  .hli{flex-wrap:wrap;gap:8px 10px;padding:11px 0}
  .hli-qui{width:auto;flex:1 1 auto}
  .hli-nom{white-space:normal;overflow:visible}
  .hli-jauge{flex:1 0 100%;order:3}
  .hli-cpt{order:2;width:auto}
  .hli .chip2{order:4}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   CHECK ANNUEL REGA (onglet Hélico, 31.07) — le tableau qui écrivait son style dans le JS
   ------------------------------------------------------------------------------------------
   Ses règles vivaient dans `helicoCheckHTML()`, en styles posés ligne à ligne. Conséquences
   MESURÉES à 375 px, thème sombre, pointeur grossier : 560 px de large donc 197 px de
   défilement de la PAGE, deux boutons sans aucune classe (« Effacer », une action destructive,
   à 2,74:1 et sous la cible tactile), et le statut « à faire » peint avec l'APLAT `--red`.
   La leçon est celle du registre de formation, le 30.07 : ce qui n'est pas dans la feuille
   n'est ni thémé, ni agrandi au doigt, ni gardé. Le tableau défile dans SON conteneur
   (`.tscroll`), jamais la page ; les boutons sont des `.go` ; les statuts portent une encre. */
.regatab{border-collapse:collapse;min-width:100%}
.regatab th,.regatab td{border:1px solid var(--line);padding:6px 9px;font-size:12px;
  text-align:center;vertical-align:middle}
.regatab th{font-family:var(--mono);font-size:11px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink-soft);white-space:nowrap}
.regatab .rt-nom{text-align:left;font-weight:600;color:var(--ink);white-space:nowrap}
.regatab .rt-date{color:var(--ink-soft);font-family:var(--mono);white-space:nowrap}
/* LE SIGNAL EST DOUBLÉ : le mot dit l'état, l'encre l'appuie — jamais l'inverse (règle du
   signal doublé). Et c'est une ENCRE, pas un aplat : `--red` mesure 4,09:1 en `color:`. */
.regatab .rt-statut{font-weight:700;white-space:nowrap}
.regatab .rt-ok{color:var(--ink-soft)}
.regatab .rt-att{color:var(--orange-ink)}
.regatab .rt-ko{color:var(--red-ink)}
/* La colonne d'action garde ses trois contrôles sur une ligne : c'est le conteneur qui défile,
   pas la page. Au doigt ils grandissent tout seuls — ils sont enfin des `.go`. */
.regatab .rt-actions{white-space:nowrap}
.regatab .rt-actions>*+*{margin-left:6px}
.regatab .rt-actions .ui-input{font-size:12px;padding:4px 7px}
.regatab .rt-actions .go{font-size:12px;padding:4px 10px}

/* ---------- UNE LIGNE RANGÉE (« vu ») ----------
   Rangée n'est pas soldée : elle garde l'encre du texte courant et sa dette reste écrite en
   toutes lettres. Pas d'aplat, pas de barré — un barré dirait « réglé », et il ne l'est pas. */
.frm-rangee .frm-nom{color:var(--ink-soft)}

/* ---------- LE CALENDRIER ----------
   Une navigation, pas une pagination : deux flèches et le mois écrit en toutes lettres. */
.fcal-nav{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-bottom:4px}
.fcal-mois{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink)}
/* La seule famille que le service IMPOSE. L'accent souligne, il ne remplit pas. */
.frm-phase.fcal-impose{box-shadow:inset 0 -2px 0 var(--accent)}

/* espacements nommés — pour que le JS n'ait aucune raison d'écrire une marge en ligne */
.frm-actions{margin-top:9px}
.frm-sous.frm-serre{margin-top:8px;margin-bottom:0}
.frm-phases.frm-serre{margin-top:8px}

/* ---------- le journal : en ajout seul, replié ---------- */
.frm-journal{margin-top:22px}
.frm-journal summary{cursor:pointer;font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink);padding:6px 0}
.frm-journal summary:hover{color:var(--ink)}
.frm-entree{display:grid;grid-template-columns:minmax(0,124px) minmax(0,1fr);gap:0 18px;
  padding:8px 2px;border-bottom:1px solid var(--line);font-size:12px;align-items:baseline}
.frm-entree>*{min-width:0}
.frm-entree .frm-quand{font-family:var(--mono);font-size:11px;letter-spacing:.03em;
  color:var(--ink-soft)}
.frm-entree .frm-qui{font-weight:600;color:var(--ink)}
.frm-entree .frm-quoi{color:var(--ink-soft);line-height:1.5;overflow-wrap:anywhere}

/* ---------- LA MARGE PASSE AU-DESSUS quand la colonne se resserre ----------
   Aucune table, aucun `nowrap` : l'ancien suivi était un <table> en `white-space:nowrap`, donc
   un scroll horizontal garanti à 375 px. Ici tout s'empile et rien ne déborde. */
@media (max-width:620px){
  .frm-ligne,.frm-champ,.frm-entree{grid-template-columns:minmax(0,1fr);gap:3px 0}
  .frm-marge{padding-top:0}
  /* `.frm-pousse` faisait ici de « Retirer » un bouton PLEINE LARGEUR en tête de carte, au-dessus
     des champs qu'il vidait : la plus grosse cible de la carte était la destructive. Le bouton a
     quitté l'en-tête de l'éditeur ; la règle part avec lui. */
}

/* LA DENSITÉ APPARTIENT À LA SOURIS, LA TAILLE APPARTIENT AU DOIGT. On adapte au POINTEUR,
   pas à la largeur : un téléphone en paysage fait 800 px et garde son pouce. */
@media (pointer: coarse){
  .frm-session-hd select,.frm-champ input{min-height:44px}
  .frm-journal summary,.frm-choisir summary{min-height:44px;display:flex;align-items:center}
  /* Les jetons du sélecteur restent de la taille d'un jeton — c'est leur ZONE DE FRAPPE qui
     grandit, pas leur dessin (le glyphe garde sa taille, la cible devient atteignable). */
  .frm-choix{position:relative}
  .frm-choix::after{content:"";position:absolute;left:50%;top:50%;
    transform:translate(-50%,-50%);width:100%;min-width:44px;height:44px}
  .frm-choix-grp{gap:8px}
}

/* ══ LE MARQUEUR (01.08) ═══════════════════════════════════════════════════════════════════════
   UNE EXPLICATION N'EST PLUS UN PARAGRAPHE : C'EST UN REPÈRE POSÉ SUR LE TITRE DE CE QU'ELLE
   EXPLIQUE. Il remplace les 49 blocs `.aide` de la console et les 5 `.aidebox` du portail — voir
   la note « .aide EST MORT » en tête de cette feuille pour ce qu'ils étaient devenus.

   TROIS PROPRIÉTÉS, ET C'EST TOUT CE QU'IL PROMET :
   · il ne coûte RIEN à la surface de lecture — un glyphe de 15 px sur la ligne du titre, pas une
     rangée de prose au-dessus du contenu ;
   · le texte n'est JAMAIS tronqué (« la règle de la phrase entière »), parce qu'il n'est plus
     posé dans le flux : il n'a plus de largeur à voler à personne ;
   · il ne cache aucune COMMANDE. Une explication se replie ; un bouton, un champ, un lien, non.
     C'est la faute exacte qu'on vient de payer, et elle est désormais tenue par un invariant.

   ⚠ LA RÉVÉLATION EST EN CSS PUR, ET C'EST LE POINT. `:hover` seul aurait été un piège au doigt
   (le portail est une PWA de téléphone) et au clavier. `:focus-within` sur un vrai `<button>`
   donne les trois chemins d'un coup : survol à la souris, tabulation au clavier, appui au doigt.
   Le panneau reste dans l'arbre d'accessibilité (opacité 0, jamais `visibility:hidden` ni
   `display:none`) : un lecteur d'écran le lit, `aria-describedby` l'y rattache, et la recherche
   du navigateur le trouve. Un texte qu'on ne voit pas n'est pas un texte qui n'existe pas.
   Le JavaScript n'intervient QUE pour choisir le côté d'ouverture (`FRONT_JS`) : posée à gauche
   par défaut, la feuille de 460 px sortait de l'écran dès que le marqueur passait la moitié de la
   largeur — vu au navigateur sur l'en-tête de Tournus, 178 px hors champ. Un côté ne se devine
   pas à l'écriture, il se MESURE à l'ouverture. */
.mk{position:relative;display:inline-flex;vertical-align:baseline}
.mk-b{appearance:none;background:none;border:0;padding:0;margin:0;cursor:help;position:relative;color:var(--ink-soft);
  display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;
  border-radius:50%;transition:color .12s cubic-bezier(.22,1,.36,1)}
.mk-b svg{width:15px;height:15px;display:block}
.mk:hover .mk-b,.mk-b:focus-visible{color:var(--ink)}
.mk-b:focus-visible{outline:1px solid var(--accent);outline-offset:3px;
  box-shadow:var(--anneau)}
/* Le panneau : une FEUILLE posée, pas une bulle. Filet d'un pixel, angle de 4 px, et la seule
   ombre du système qui a le droit de porter — celle-ci flotte RÉELLEMENT au-dessus du flux. */
.mk-pop{position:absolute;top:calc(100% + 9px);left:-11px;z-index:60;
  width:max-content;max-width:min(460px,calc(100vw - 32px));
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 6px 18px rgba(25,26,29,.16);
  padding:13px 15px;text-align:left;text-transform:none;letter-spacing:0;
  font-family:var(--font);font-size:13px;font-weight:400;line-height:1.55;color:var(--ink-soft);
  opacity:0;pointer-events:none;transform:translateY(-3px);
  transition:opacity .12s cubic-bezier(.22,1,.36,1),transform .12s cubic-bezier(.22,1,.36,1)}
.mk-pop b,.mk-pop strong{color:var(--ink);font-weight:600}
.mk-pop p{margin:0}
.mk-pop p+p{margin-top:9px}
.mk:hover .mk-pop,.mk:focus-within .mk-pop{opacity:1;pointer-events:auto;transform:none}
/* Le filet de rattachement : 8 px de trait vertical entre le glyphe et sa feuille. C'est le même
   geste que partout ailleurs — on relie par un filet, pas par une flèche de bulle. */
.mk-pop::before{content:"";position:absolute;left:var(--mk-fil,14px);top:-9px;width:1px;height:9px;background:var(--line)}
[data-theme="dark"] .mk-pop{box-shadow:0 6px 20px rgba(9,10,22,.62)}
/* Repli sans JavaScript (le script de feuille n'a pas encore tourné) : contre le bord droit,
   la feuille s'aligne à droite. Dès que `FRONT_JS` mesure, il pose un `left` exact et retire
   cette classe — un décalage calculé bat toujours un choix binaire près d'un bord. */
.mk.fin .mk-pop{left:auto;right:-11px}
@media (prefers-reduced-motion: reduce){ .mk-pop{transition:none} }
/* UNE CIBLE EST UNE SURFACE, PAS UNE HAUTEUR (invariant H). Le glyphe garde ses 15 px ; c'est sa
   zone de frappe qui atteint 44 × 44, invisible, centrée — comme `.zone-frappe` ailleurs. */
@media (pointer: coarse){
  .mk-b::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:44px;height:44px}
}
