/* =====================================================================
   Fondations et atomes. Aucune couleur littérale ici : tout passe par
   tokens.css, pour qu'une charte se change en éditant un seul fichier.
   ===================================================================== */
*,*::before,*::after{box-sizing:border-box}
/* `hidden` gagne TOUJOURS. La règle du navigateur (`display:none`) perd contre n'importe quel
   `display` posé par une classe — un bouton `.btn{display:inline-flex}` masqué par script
   restait visible, constaté sur le bouton « Filtrer » du journal. Le `!important` est ici le
   sens même de l'attribut : un élément caché n'a pas de forme à discuter. */
[hidden]{display:none !important}
body{margin:0;background:var(--bg);color:var(--texte);font:var(--fs-base)/1.55 var(--font);-webkit-text-size-adjust:100%}
h1,h2,h3,p,ul,ol,figure{margin:0}
ul{padding:0;list-style:none}
/* Graisse 600 et PAS de soulignement au repos ; souligné au survol. La base fournie fait
   ainsi, et c'est l'inverse de ce que faisait le socle. Le soulignement au survol n'est pas
   une décoration : il rend le lien identifiable pour qui ne distingue pas sa couleur, au
   moment où l'on s'apprête à cliquer. Dans un TEXTE COURANT, le soulignement au repos reste
   la bonne pratique — voir `.contenu p a` plus bas, qui le rétablit. */
a{color:var(--marque-encre);font-weight:var(--gras-etiquette);text-decoration:none}
a:hover{text-decoration:underline}
/* Dans un texte courant, le soulignement au repos : rien d'autre n'y distingue un lien pour
   qui ne perçoit pas sa couleur, alors qu'un lien de navigation est identifié par sa place. */
p a,li a,dd a,caption a{text-decoration:underline;font-weight:inherit}
img,svg{max-width:100%;height:auto}

/* Focus visible sur TOUT ce qui se focalise. Retirer cette règle rend la
   navigation au clavier aveugle sur l'ensemble du socle. */
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--radius-sm)}

/* Premier élément focalisable de la page : il n'apparaît qu'au clavier et
   permet de sauter la navigation, que l'on retraverse sinon à chaque écran. */
.evitement{position:absolute;left:-9999px;top:0;background:var(--surface);color:var(--texte-fort);padding:var(--e-3) var(--e-4);border-radius:0 0 var(--radius) 0;z-index:100;font-weight:600}
.evitement:focus{left:0}

/* ---- Titres ---- */
h1{font-size:var(--fs-xl);line-height:1.25;color:var(--texte-fort);font-weight:700}
h2{font-size:var(--fs-lg);line-height:1.3;color:var(--texte-fort);font-weight:600}
h3{font-size:var(--fs-md);line-height:1.35;color:var(--texte-fort);font-weight:600}

/* ---- Boutons ----
   .btn est le contour ; sa bordure emploie --bord et non --ligne, sans quoi
   la limite du composant serait sous le seuil de 3:1 du SC 1.4.11. */
/* La HAUTEUR vient d'un token, pas d'un rembourrage : `min-height` + `padding-block:0` +
   `inline-flex` est la forme qu'emploient les back-offices documentés (Carbon, Ant), parce
   qu'elle rend la cible prévisible quel que soit le libellé. Le rembourrage vertical, lui,
   dépendait de la taille du texte et donnait 44 px dans le socle contre 38 dans la base
   fournie. `--h-controle` vaut 44 sur les écrans publics et 38 sous `.coque`.

   SC 2.5.8 (AA) demande 24×24 : les deux passent largement. Le 44×44 souvent cité est le
   SC 2.5.5, niveau AAA, hors cible du cahier des charges. */
.btn,.btn-primaire{display:inline-flex;align-items:center;justify-content:center;gap:var(--e-2);min-height:var(--h-controle);padding:0 var(--e-4);font:var(--gras-etiquette) var(--fs-base)/1.2 var(--font);border-radius:var(--radius-sm);cursor:pointer;transition:background var(--duree),border-color var(--duree),color var(--duree)}
/* Taille dense, pour une cellule de tableau : la ligne suit la hauteur de son bouton. */
.btn.petit,.btn-primaire.petit{min-height:var(--h-controle-sm);padding:0 var(--e-3);font-size:var(--fs-sm)}
.btn{border:1px solid var(--bord);background:var(--surface);color:var(--texte-fort)}
/* `:not([disabled])` : sans lui, survoler un bouton désactivé le repeint aux couleurs
   de l'état actif et contredit le seul signal qui l'annonçait. */
.btn:hover:not([disabled]){border-color:var(--marque-encre);color:var(--marque-encre)}
/* Le bouton DISCRET : un geste répété sur chaque ligne d'une liste — « Gérer… » — ne dessine plus
   une colonne de cadres identiques. Filet clair et fond transparent au repos ; le survol reprend
   celui du bouton ordinaire. Le libellé l'identifie : le SC 1.4.11 n'exige pas de bordure d'un
   bouton qui porte un texte. Choisi avec la piste B de l'arbre, le 2026-09-15. */
.btn.btn-discret{border-color:var(--ligne);background:transparent}
/* Le bouton plein emploie --action et non --sur-marque : c'est le seul endroit où une
   couleur de marque sert de FOND, et un fond doit s'assombrir quand l'encre s'éclaircit.
   Il ne prend PAS toute la largeur par défaut : ce réglage-là appartenait aux écrans
   d'authentification, où le bouton est seul dans une carte étroite, et il transformait le
   moindre bouton de back-office en bandeau noir sur toute la page. Il vit désormais dans
   auth.css, avec les écrans qui le veulent. */
.btn-primaire{border:1px solid var(--action);background:var(--action);color:var(--sur-action)}
.btn-primaire:hover:not([disabled]){background:var(--action-survol);border-color:var(--action-survol)}
/* Bouton d'une action qui retire quelque chose. Il ne PRÉVIENT pas — l'écran l'a déjà dit et
   une confirmation le redemande — il signale, au moment du survol, qu'on n'est pas sur un
   bouton comme les autres. Au repos il reste un contour : un aplat rouge permanent dans une
   liste crie plus fort que la donnée. */
.btn.destructif{border-color:var(--err);color:var(--err)}
.btn.destructif:hover:not([disabled]){background:var(--err-bg);border-color:var(--err);color:var(--err)}

/* `opacity` sur un composant INACTIF : le SC 1.4.3 exclut nommément ce cas (« Incidental »),
   et le SC 1.4.11 exclut de même les composants inactifs. Un outil automatique le signalera
   quand même — c'est un faux positif normatif, ne pas le « corriger ». */
.btn[disabled],.btn-primaire[disabled]{opacity:.55;cursor:not-allowed}
/* Un LIEN habillé en bouton ne se souligne pas au survol : il a déjà l'aspect d'un bouton,
   et le soulignement le ferait ressembler à un lien qui aurait raté son habillage. */
a.btn,a.btn-primaire{text-decoration:none}
a.btn:hover,a.btn-primaire:hover{text-decoration:none}

/* Rembourrage vertical NON décoratif : sans lui la boîte fait 15,6 px de haut et ne tient le
   SC 2.5.8 que par son exception d'espacement — c'est-à-dire par la marge de son voisin. Une
   cible qui dépend de ce qui l'entoure cesse d'être conforme le jour où l'on resserre une
   grille, sans que rien ne le signale. 24 px de haut la rend conforme par elle-même. */
.btn-lien{background:none;border:none;padding:var(--e-1) 0;min-height:var(--e-6);display:inline-flex;align-items:center;color:var(--marque-encre);font:var(--gras-etiquette) var(--fs-sm)/1.2 var(--font);cursor:pointer;text-decoration:underline}
/* LE RETOUR vers l'onglet d'où l'on vient (`App\Http\Provenance`) — un bouton à la teinte de la
   marque, flèche en tête. Relevé par le user le 2026-09-28 : en `.btn-lien`, souligné dans une bande
   grise à part au-dessus du bandeau, il se voyait mal et paraissait posé là. Il vit dans le bandeau,
   devant le chemin (`.bandeau-fiche-provenance`) : d'où l'on vient à côté de ce qui dit où l'on est.
   Au survol, l'aplat de marque plein ; son encre (`--sur-marque-fort`) y tient le contraste. */
.btn-retour{display:inline-flex;align-items:center;gap:var(--e-2);min-height:var(--h-controle);padding:0 var(--e-4);
  border:1px solid var(--marque);border-radius:var(--radius-sm);background:var(--accent-bg);color:var(--accent);
  font:var(--gras-etiquette) var(--fs-sm)/1.2 var(--font);text-decoration:none;
  transition:background var(--duree),border-color var(--duree),color var(--duree)}
.btn-retour:hover{background:var(--marque);border-color:var(--marque);color:var(--sur-marque-fort)}
.btn-retour svg{flex:none}
/* Seul dans son paragraphe en tête de page — la forme de toutes les sous-pages —, le retour garde
   sa distance avec ce qui suit : sans elle, il touchait la carte de « Créer un rôle » (le user,
   2026-09-29). Une règle du composant, pas une marge par écran. */
p:has(>.btn-retour:only-child){margin:0 0 var(--e-4)}

/* ---- Champs ----
   Le libellé est un élément à part : c'est le gabarit qui pose `for`/`id`.
   La charte fournie générait des <label> frères sans liaison — 19 champs
   sans nom accessible, échec F68. Ne pas reproduire ce motif. */
.champ{display:block;margin-bottom:var(--e-4)}
/* Le bloc d'une saisie de quelques caractères. La largeur se règle sur le BLOC, jamais sur l'input. */
.champ.court{max-width:var(--l-champ-court)}
/* `.moyen` : un choix dans une liste de NOMS — un repreneur, un utilisateur. Pleine largeur, une liste
   de prénoms s'étirait sur toute la carte et l'œil cherchait la flèche à l'autre bout (suppression
   d'un compte, 2026-10-01). Une cellule de tableau, elle, borne déjà son champ, qui y perd sa marge. */
.champ.moyen{max-width:var(--l-donnee)}
td>.champ{margin-bottom:0}
.champ label{display:block;margin-bottom:var(--e-2);font-weight:var(--gras-etiquette);font-size:var(--fs-sm);color:var(--texte-fort)}
/* Fond légèrement teinté et rayon de la base fournie : un champ blanc bordé de gris froid a
   l'air d'un formulaire HTML brut posé sur la page. Le fond employé est `--bg`, celui de la
   page — la même surface, en creux, plutôt qu'une valeur de plus.

   Le bord reste `--bord` et non le filet clair de la base fournie : le SC 1.4.11 demande 3:1
   pour la limite visible d'un composant, et son #E8E5E0 vaut 1,26:1 sur blanc. C'est le seul
   endroit où l'on s'écarte d'elle sur la forme, et c'est une clause du § 2.8. */
/* Les cases et les boutons radio sont EXCLUS : ce sont des contrôles carrés dessinés par le
   système, pas des zones de saisie. Sans cette exclusion, la `min-height` de 38 px l'emportait
   sur leur `height` de 18 px — `min-height` gagne toujours contre `height` — et une case rendait
   18×38, un rectangle étiré. Le token `--h-case` cessait alors de décrire ce qu'on voit.
   Aucun test textuel ne pouvait l'attraper : c'est une géométrie calculée par le navigateur. */
.champ input:not([type=checkbox]):not([type=radio]),.champ select,.champ textarea{width:100%;min-height:var(--h-controle);padding:0 var(--e-3);border:1px solid var(--bord);border-radius:var(--radius);background:var(--bg);color:var(--texte-fort);font:var(--fs-base)/1.4 var(--font)}
.champ textarea{padding:var(--e-3);min-height:calc(var(--h-controle) * 2)}
/* L'outline est remplacé par un anneau VISIBLE, pas supprimé. */
/* Le champ passe au blanc au focus : le creux se remplit, on voit où l'on écrit. */
.champ input:not([type=checkbox]):not([type=radio]):focus,.champ select:focus,.champ textarea:focus{outline:none;background:var(--surface);border-color:var(--marque-encre);box-shadow:0 0 0 3px var(--halo)}
/* Une liste déroulante prend le dessin des champs, dans TOUS les navigateurs. Laissée native,
   Safari ignore sa hauteur et ses marges : relevé par le user le 2026-09-28 sur l'annuaire, des
   listes basses à côté d'un champ de 38 px, et les étiquettes décalées d'autant. Chrome honorait
   déjà la règle des champs — mesuré, 38 px —, si bien que le défaut ne se voyait pas partout.
   La flèche est DESSINÉE par deux dégradés, jamais par une image : ses couleurs suivent le thème
   (`--texte`), une image en `data:` les figerait. APRÈS la règle du focus, qui réécrit tout le fond
   (`background`) : placée avant, la flèche disparaissait dès qu'on ouvrait la liste. Une liste à
   choix multiples n'a pas de flèche. */
.champ select:not([multiple]){appearance:none;padding-right:var(--e-8);
  background-image:linear-gradient(45deg,transparent 50%,var(--texte) 50%),linear-gradient(135deg,var(--texte) 50%,transparent 50%);
  background-position:calc(100% - var(--e-4) - var(--e-1)) 50%,calc(100% - var(--e-4)) 50%;
  background-size:var(--e-1) var(--e-1),var(--e-1) var(--e-1);background-repeat:no-repeat}
.champ .aide{display:block;margin-top:var(--e-1);font-size:var(--fs-xs)}
/* Le placeholder n'est PAS un libellé de remplacement : il disparaît à la saisie. Il est ici
   assez contrasté pour être lu (6,58:1), et le libellé reste toujours présent au-dessus. */
.champ ::placeholder{color:var(--texte);opacity:1}
.champ.en-erreur input:not([type=checkbox]):not([type=radio]),.champ.en-erreur select{border-color:var(--err)}
.champ .erreur{display:block;margin-top:var(--e-1);color:var(--err);font-size:var(--fs-sm);font-weight:600}
/* La phrase qui explique l'astérisque des obligatoires, en tête du formulaire (RGAA 11.10). Détachée
   des champs d'un cran, le pas qui sépare deux lignes de champs : mesuré sur « Mon compte » le
   2026-09-15, sans elle 0 px la séparait de « Prénom * », et elle se lisait comme l'aide du prénom. */
.mention-obligatoire{margin:0 0 var(--e-4)}

/* Un `fieldset` porte par défaut un cadre gravé et une marge que rien d'autre n'a. Il sert
   ici à RATTACHER un groupe de cases à sa question — ce que `legend` fait pour un lecteur
   d'écran — et cette fonction n'a pas besoin d'être dessinée. `min-width:0` corrige un défaut
   ancien des navigateurs : sans lui, un fieldset refuse de rétrécir sous la largeur de son
   contenu et fait déborder la page. */
fieldset.champ{border:0;padding:0;margin:0 0 var(--e-4);min-width:0}
fieldset.champ legend{padding:0;margin-bottom:var(--e-1);font-weight:600;font-size:var(--fs-sm);color:var(--texte-fort)}

.case{display:flex;align-items:center;gap:var(--e-2);font-size:var(--fs-sm);padding:var(--e-1) 0}
/* Cochée, la case est ORANGE — l'accent de la base fournie, sur décision du client. Le glyphe
   de coche est dessiné par le navigateur (blanc sur l'orange, comme la maquette).

   Cette règle a été écrite TROIS fois, et l'histoire vaut d'être gardée : la première posait
   --marque-encre ; une seconde, dupliquée plus bas dans cette feuille, référençait
   `--orange-fort` — un jeton que RIEN ne définit. Une var() inconnue n'a pas de repli : la
   propriété tombe entière, et comme la copie venait après, la cascade la faisait gagner.
   Résultat : des cases BLEUES, au défaut du navigateur, pendant que deux règles croyaient
   chacune tenir la couleur. Trouvé par un balayage des jetons référencés-jamais-définis,
   déclenché par la capture d'écran d'un utilisateur. */
.case input{width:var(--h-case);height:var(--h-case);accent-color:var(--marque)}

/* ---- Interrupteur ----
   Celui de la base fournie est banni (docs/habillage.md §interrupteur : 1,46:1, aucun nom
   accessible, application au clic). CELUI-CI suit la recette que cette doctrine impose :
   - la piste allumée est --marque-encre (5,32:1), JAMAIS --marque (2,07:1) ;
   - éteinte, sa limite est un trait --texte : la forme se voit, pas seulement la teinte ;
   - le `<label>` enveloppe l'input ET un texte — le nom accessible vient de là ;
   - il ne soumet RIEN au clic : l'état part avec le bouton du formulaire (SC 3.2.2).
   `role="switch"` se pose sur l'input DANS LE GABARIT, pas ici : l'état reste porté par
   `checked`, donc par le navigateur, sans une ligne de script. */
.interrupteur{display:inline-flex;align-items:center;gap:var(--e-2);cursor:pointer}
.interrupteur input{appearance:none;margin:0;flex-shrink:0;cursor:pointer;position:relative;
  width:var(--l-interrupteur);height:var(--h-interrupteur);border-radius:var(--radius-gelule);
  background:var(--surface);border:1px solid var(--texte);
  transition:background-color var(--duree) ease,border-color var(--duree) ease}
/* Le bouton : la hauteur de piste moins sa bordure et ses deux marges. Tout se dérive des
   quatre tokens — reteinter la charte ne demande jamais de recalculer un pixel ici. */
.interrupteur input::after{content:"";position:absolute;
  top:var(--e-interrupteur);left:var(--e-interrupteur);
  width:calc(var(--h-interrupteur) - 2px - var(--e-interrupteur) * 2);
  height:calc(var(--h-interrupteur) - 2px - var(--e-interrupteur) * 2);
  border-radius:50%;background:var(--texte);
  transition:transform var(--duree) ease,background-color var(--duree) ease}
.interrupteur input:checked{background:var(--marque-encre);border-color:var(--marque-encre)}
.interrupteur input:checked::after{background:var(--surface);transform:translateX(var(--course-interrupteur))}
.interrupteur input:focus-visible{outline:2px solid var(--action);outline-offset:2px}
@media (prefers-reduced-motion: reduce){
  .interrupteur input,.interrupteur input::after{transition:none}
}
/* La LIGNE qui porte une case, ce que `.champ` est à un champ ordinaire. Trois gabarits s'y
   accrochaient déjà — le thème de formulaire partagé et les deux groupes de l'annuaire — sans
   qu'elle existe : `p{margin:0}` plus haut, donc des cases empilées sans le moindre espacement.
   Le rythme est celui d'un GROUPE (`--e-2`) et non d'un champ (`--e-4`) : ces cases sont les
   options d'une même question, pas des questions successives. */
.case-ligne{margin-bottom:var(--e-2)}
.case-ligne:last-child{margin-bottom:0}

/* ---- Messages ----
   role="alert" pour l'erreur, role="status" pour le reste : posé dans le
   gabarit, pas ici. Sans lui, un message qui apparaît n'est pas annoncé. */
.message{padding:var(--e-3) var(--e-4);border-radius:var(--radius-sm);font-size:var(--fs-sm);margin-bottom:var(--e-4);border:1px solid transparent}
.message-succes{background:var(--ok-bg);color:var(--ok);border-color:var(--ok)}
.message-erreur{background:var(--err-bg);color:var(--err);border-color:var(--err)}
.message-info{background:var(--info-bg);color:var(--info);border-color:var(--info)}

/* ---- Champ de mot de passe ----
   Le bouton d'affichage est POSÉ PAR JAVASCRIPT (public/js/champ-mot-de-passe.js) ;
   ces règles ne s'appliquent donc qu'une fois le script chargé. Sans lui, le champ
   reste un champ ordinaire — l'habillage ne suppose jamais que le script tourne.
   36×36 : au-delà des 24×24 du SC 2.5.8, et l'icône tient 6,58:1 sur la surface
   là où un élément non textuel n'en demande que 3. */
.champ-secret{position:relative;display:block}
.champ-secret input{padding-right:var(--e-12)}
.oeil{position:absolute;right:var(--e-1);top:50%;transform:translateY(-50%);display:flex;align-items:center;justify-content:center;width:var(--h-icone);height:var(--h-icone);padding:0;border:none;background:none;color:var(--texte);cursor:pointer;border-radius:var(--radius-sm)}
.oeil:hover{color:var(--texte-fort)}

/* Lu par les lecteurs d'écran, invisible à l'œil. `clip-path` et non `display:none`,
   qui retirerait l'élément de l'arbre d'accessibilité et le rendrait muet.

   `position:absolute` SANS coordonnées : la boîte reste là où est le texte, mais son bloc
   contenant est le premier ancêtre POSITIONNÉ. Une zone qui défile sans être positionnée ne la
   retient donc pas : le texte caché sort de sa découpe et élargit la page au lieu de défiler avec
   elle — mesuré sur neuf écrans à tableau, jusqu'à 658 px de trop. Toute zone à `overflow` qui peut
   porter ce texte se positionne, comme `.table-enveloppe` (appli.css).

   `!important` sur CHAQUE déclaration, et c'est la même raison que pour `[hidden]` plus haut : un
   élément caché n'a pas de forme à discuter. La classe ne pèse que (0,1,0), et une règle de
   composant qui vise le même élément la bat. `.champ input:not([type=checkbox]):not([type=radio])`,
   (0,3,1), rendait au champ de fichier caché du dépôt et de la photo de profil sa largeur de 100 % :
   sans ancêtre positionné, c'est la largeur de la fenêtre, à partir de l'endroit où se trouve le
   champ. Mesuré le 2026-09-15 à 1024 px, cela donnait un champ de 1009 px et une page qui défilait en
   largeur de 552 à 577 px sur la vitrine et de 284 px sur le formulaire d'un module engendré.
   `min-width` et `min-height` reviennent à zéro, parce que `min-height` l'emporte sur `height` : sans
   elles, ce champ gardait 38 px de haut, tout comme le bouton de repli `.btn.hors-ecran` de
   « Ajouter une société ou un service ». Exclure la classe du sélecteur des saisies réparait le champ,
   pas le bouton : c'est mesuré, et c'est ce qui a fait choisir ce remède-ci.
   HabillageTest::testLaBoiteHorsEcranLEmporteSurLesReglesDesComposants tient cette règle. */
.hors-ecran{position:absolute !important;width:1px !important;height:1px !important;min-width:0 !important;min-height:0 !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip-path:inset(50%) !important;white-space:nowrap !important;border:0 !important}

/* ---- Divers ---- */
.discret{color:var(--texte);font-size:var(--fs-sm)}
.mono{font-family:var(--font-mono)}
/* Le socle affiche des COMMANDES à recopier. Sans cette règle, `code` retombait sur le
   monospace générique du navigateur, dont les chasses larges font lire « app: rattacher »
   là où le texte dit « app:rattacher » — un client peut retaper la commande avec l'espace.
   La pile est celle des tokens, comme partout ailleurs. */
code,kbd,samp{font-family:var(--font-mono);font-size:.9375em}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
}

/* ---- Badge ----
   Une pastille qui porte un ÉTAT, jamais une action. Reprise de la base fournie, à ceci près
   que chaque paire fond/encre y est mesurée : les couleurs sémantiques de tokens.css tiennent
   toutes 4,5:1 sur leur propre fond, dans les deux lots.

   La couleur ne porte JAMAIS l'information seule (SC 1.4.1) : le badge contient toujours le
   mot. « Actif » reste lisible en noir et blanc, et pour qui ne distingue pas le vert du gris. */
.badge{display:inline-block;padding:var(--e-1) var(--e-3);border-radius:var(--radius-pastille);font-size:var(--fs-xs);font-weight:var(--gras-etiquette);white-space:nowrap;line-height:1.4}
.badge-ok{background:var(--ok-bg);color:var(--ok)}
.badge-attente{background:var(--warn-bg);color:var(--warn)}
.badge-err{background:var(--err-bg);color:var(--err)}
.badge-neutre{background:var(--neutre-bg);color:var(--texte-fort)}
/* Le rang, pas l'alerte : la pastille du rôle le plus élevé d'une liste. */
.badge-accent{background:var(--accent-bg);color:var(--accent)}
/* PLUSIEURS badges à la suite : `.badges` les range et les fait passer à la ligne SANS que deux rangées se
   touchent. Posées dans le texte, deux pastilles de deux lignes se collaient — l'interligne ne laisse rien
   entre deux boîtes `inline-block` qui remplissent leur ligne (relevé par le user le 2026-10-02, « par ses
   rôles » sur « Droits temporaires »). Le texte qui les annonce vit dans le groupe, aligné sur leur milieu. */
.badges{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e-1) var(--e-2);margin:0}
