/* =====================================================================
   HC Facturation — système de design
   =====================================================================
   CE FICHIER EST FIGÉ. Les neuf lots suivants ne le modifient JAMAIS :
   chacun ajoute son propre css/<lot>.css et se contente de composer avec
   les classes et les variables déclarées ici.

   La page /design montre l'intégralité de ce langage graphique, avec le
   nom de classe de chaque composant. C'est la référence à lire avant
   d'écrire une ligne de HTML.

   Public visé : des hôtesses d'accueil qui passent la journée sur cet
   écran, souvent debout, parfois pressées. D'où : lecture confortable
   (16 px de base, interlignage large), cibles de clic de 44 px minimum,
   contraste AA vérifié sur chaque paire texte/fond, animations courtes
   (150 à 200 ms) et jamais décoratives.

   Aucune ressource distante : la police est auto-hébergée dans
   app/static/fonts/. Le serveur de production tourne sans accès Internet
   sortant, et aucun appel à un tiers ne doit fuiter d'information.

   RÈGLES INTERNES DU FICHIER (vérifiées par tests/test_design.py) :
     * aucune couleur en dur hors d'un bloc :root ;
     * aucune valeur d'espacement en dur : margin, padding et gap ne
       prennent que les variables de l'échelle ;
     * aucun « outline: none » sans anneau de focus de remplacement.
   ===================================================================== */

/* --- Police auto-hébergée ----------------------------------------- */
/* Inter, sous-ensembles latin et latin-ext, graisses 400/500/600/700.
   Licence SIL OFL 1.1 : app/static/fonts/OFL.txt.
   Les fichiers viennent du paquet npm officiel @fontsource/inter ; ils
   sont versionnés dans le dépôt pour que l'installation ne dépende
   d'aucun réseau. font-display: swap — la pile système s'affiche
   immédiatement, Inter la remplace dès qu'elle est lue. */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter-latin-400-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-latin-500-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-latin-600-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/inter-latin-700-normal.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter-latin-ext-400-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-latin-ext-500-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-latin-ext-600-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/inter-latin-ext-700-normal.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
                 U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* =====================================================================
   VARIABLES — seul endroit du fichier où une couleur est écrite
   ===================================================================== */
:root {

  /* --- Palette de marque -------------------------------------------
     Bordeaux (« prune ») pour la marque, rose (« framboise ») pour
     l'accent. Les valeurs de départ imposées par le client sont
     conservées ; les dérivées ont été calculées pour tenir AA.        */
  --marque:          #8A1C4A;   /* prune, valeur client */
  --marque-survol:   #6E1339;
  --marque-actif:    #570E2C;
  --marque-fond:     #FDF2F6;   /* blush, valeur client */

  --accent:          #D6336C;   /* framboise, valeur client */
  --accent-survol:   #B82657;
  --accent-fond:     #F7D6E3;   /* voile, valeur client */

  /* --- Fonds --------------------------------------------------------
     Le fond général est gris BLEUTÉ : posé à côté du bordeaux, un gris
     neutre vire au sale.                                              */
  --fond:            #F2F5FA;
  --surface:         #FFFFFF;
  --surface-elevee:  #FFFFFF;   /* modale, infobulle : blanc + ombre */
  --surface-sourde:  #EDF1F7;   /* lignes paires, champs inertes */

  /* --- Textes -------------------------------------------------------
     #6B7280 (gris client) tombait à 4,39:1 sur le fond général :
     assombri en deux paliers pour rester lisible partout.             */
  --texte:             #1F2933;   /* ardoise, valeur client */
  --texte-secondaire:  #4C5666;
  --texte-attenue:     #616B7A;
  --texte-sur-marque:  #FFFFFF;

  /* --- Bordures ---------------------------------------------------- */
  --bordure:          #DCE1E9;
  --bordure-marquee:  #B6BECC;
  --bordure-focus:    #D6336C;

  /* --- États : texte / fond / bordure ------------------------------ */
  --succes-texte:   #0E7048;   /* vert client #128C5A assombri (4,26:1) */
  --succes-fond:    #E9F6F0;
  --succes-bordure: #A7DCC4;

  --avertissement-texte:   #96470A;  /* ambre client #B45309 assombri */
  --avertissement-fond:    #FDF3E4;
  --avertissement-bordure: #EFCB94;

  --erreur-texte:   #B42318;   /* rouge client, inchangé */
  --erreur-fond:    #FDECEA;
  --erreur-bordure: #F3B9B2;

  --information-texte:   #1F5F8B;
  --information-fond:    #E9F1F8;
  --information-bordure: #B3D0E6;

  /* --- Voiles et ombres (les seuls rgba du fichier) ---------------- */
  --voile-modale:      rgba(31, 41, 51, .48);
  --voile-chargement:  rgba(242, 245, 250, .78);
  --squelette-base:    #E4E9F1;
  --squelette-lueur:   #F3F6FB;
  --filet-sur-marque:  rgba(255, 255, 255, .32);

  --ombre-aucune:     none;
  --ombre-subtile:    0 1px 2px rgba(31, 41, 51, .05);
  --ombre-carte:      0 1px 2px rgba(31, 41, 51, .05),
                      0 6px 16px rgba(31, 41, 51, .05);
  --ombre-surelevee:  0 2px 4px rgba(31, 41, 51, .06),
                      0 12px 28px rgba(31, 41, 51, .10);
  --ombre-modale:     0 24px 64px rgba(31, 41, 51, .26),
                      0 2px 8px rgba(31, 41, 51, .12);
  --anneau-focus:     0 0 0 3px rgba(214, 51, 108, .38);
  --anneau-focus-danger: 0 0 0 3px rgba(180, 35, 24, .34);

  /* --- Couleurs d'impression ---------------------------------------
     Une facture s'imprime en noir sur blanc, quelle que soit la palette
     de l'écran.                                                       */
  --encre:           #000000;
  --papier:          #FFFFFF;
  --filet-imprime:   #767676;

  /* --- Échelle d'espacement ----------------------------------------
     Aucune autre valeur d'espace n'existe dans le projet.             */
  --espace-1: 4px;
  --espace-2: 8px;
  --espace-3: 12px;
  --espace-4: 16px;
  --espace-5: 24px;
  --espace-6: 32px;
  --espace-7: 48px;
  --espace-8: 64px;

  /* --- Rayons ------------------------------------------------------- */
  --rayon-petit:  6px;
  --rayon-moyen:  10px;
  --rayon-grand:  16px;
  --rayon-pilule: 999px;

  /* --- Typographie --------------------------------------------------
     Une hiérarchie tenue par la TAILLE, la COULEUR et l'ESPACEMENT ;
     les graisses restent contenues (600 au maximum pour les titres),
     un titre très gras fatigue sur une journée d'usage.               */
  --police: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
            Roboto, 'Helvetica Neue', Arial, sans-serif;
  --police-chiffres: 'Inter', -apple-system, BlinkMacSystemFont,
                     'Segoe UI', Roboto, sans-serif;
  --police-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --graisse-normale: 400;
  --graisse-moyenne: 500;
  --graisse-appuyee: 600;
  --graisse-forte:   700;

  --taille-display:  2.5rem;    --hauteur-display: 1.12; --graisse-display: 600;
  --taille-titre-1:  1.875rem;  --hauteur-titre-1: 1.2;  --graisse-titre-1: 600;
  --taille-titre-2:  1.375rem;  --hauteur-titre-2: 1.3;  --graisse-titre-2: 600;
  --taille-titre-3:  1.0625rem; --hauteur-titre-3: 1.4;  --graisse-titre-3: 600;
  --taille-corps:    1rem;      --hauteur-corps:   1.6;  --graisse-corps:   400;
  --taille-petit:    0.875rem;  --hauteur-petit:   1.5;  --graisse-petit:   400;
  --taille-micro:    0.75rem;   --hauteur-micro:   1.35; --graisse-micro:   600;

  --interlettre-titre: -.012em;
  --interlettre-micro: .07em;

  /* --- Gabarit ------------------------------------------------------ */
  --largeur-page:   1120px;
  --hauteur-cible:  44px;   /* cible de clic minimale, sans exception */
  --hauteur-entete: 64px;

  /* --- Géométrie du bouton compact ----------------------------------
     Son fond visuel ne fait que --bouton-compact-hauteur, mais un
     pseudo-élément ramène la ZONE CLIQUABLE à --hauteur-cible : elle
     déborde donc de --bouton-compact-debord au-dessus ET au-dessous du
     fond (rien sur les côtés, le pseudo-élément est calé sur les bords
     gauche et droit du bouton).

     Deux boutons compacts qui se suivent doivent par conséquent être
     séparés d'au moins DEUX débordements, sinon leurs zones cliquables
     se recouvrent. Dans le journal de caisse et l'écran des factures,
     les deux boutons voisins sont « Voir » et « Annuler » : une
     annulation de facture est définitive, un clic qui part sur le
     mauvais bouton coûte cher.

     --ecart-actions porte cet écart minimal et s'applique au « gap » de
     toutes les barres d'actions — donc aussi bien entre deux colonnes
     qu'entre deux lignes quand la barre passe à la ligne.

     test_les_zones_cliquables_des_boutons_compacts_ne_se_recouvrent_pas
     recalcule 2 x debord <= ecart à partir de ces variables : aucune
     évolution des valeurs ne peut réintroduire le recouvrement en
     silence.                                                          */
  --bouton-compact-hauteur: 32px;
  --bouton-compact-debord: calc(
      (var(--hauteur-cible) - var(--bouton-compact-hauteur)) / 2);
  --ecart-actions: var(--espace-3);

  /* --- Mouvement ----------------------------------------------------
     Discret et rapide. Rien au-dessus de 200 ms.                      */
  --duree-rapide: 150ms;
  --duree:        200ms;
  --courbe:       cubic-bezier(.2, .6, .3, 1);
}

/* =====================================================================
   RÉINITIALISATION
   ===================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--police);
  font-size: var(--taille-corps);
  font-weight: var(--graisse-corps);
  line-height: var(--hauteur-corps);
  color: var(--texte);
  background: var(--fond);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

img, svg { max-width: 100%; }
svg { display: block; }

/* L'attribut `hidden` doit gagner sur les composants. Sans cette ligne,
   un bouton porteur de `hidden` resterait visible : la règle
   `display: none` du navigateur est couverte par toute déclaration
   `display` de cette feuille, quelle que soit sa spécificité. Masquer
   par cet attribut est ce que les technologies d'assistance savent déjà
   lire — c'est donc celui-là qu'on rend fiable, plutôt qu'une classe de
   plus. */
[hidden] { display: none !important; }

/* =====================================================================
   TYPOGRAPHIE
   ===================================================================== */
h1, .titre-1 {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-titre-1);
  line-height: var(--hauteur-titre-1);
  font-weight: var(--graisse-titre-1);
  letter-spacing: var(--interlettre-titre);
  color: var(--texte);
}

h2, .titre-2 {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-titre-2);
  line-height: var(--hauteur-titre-2);
  font-weight: var(--graisse-titre-2);
  letter-spacing: var(--interlettre-titre);
  color: var(--texte);
}

h3, h4, .titre-3 {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-titre-3);
  line-height: var(--hauteur-titre-3);
  font-weight: var(--graisse-titre-3);
  color: var(--texte);
}

.display {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-display);
  line-height: var(--hauteur-display);
  font-weight: var(--graisse-display);
  letter-spacing: var(--interlettre-titre);
  color: var(--texte);
}

p, .texte-corps {
  margin: 0 0 var(--espace-3);
  font-size: var(--taille-corps);
  line-height: var(--hauteur-corps);
}

.texte-petit {
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
}

.texte-micro {
  font-size: var(--taille-micro);
  line-height: var(--hauteur-micro);
  font-weight: var(--graisse-micro);
}

/* Étiquette de champ ou de colonne : petite, appuyée, espacée. */
.etiquette {
  display: block;
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  font-weight: var(--graisse-appuyee);
  color: var(--texte);
}

/* Information secondaire : même taille que le corps, couleur retenue. */
.info-secondaire {
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  color: var(--texte-attenue);
}

/* Sur-titre de section : la plus petite marche de la hiérarchie. */
.surtitre {
  display: block;
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-micro);
  line-height: var(--hauteur-micro);
  font-weight: var(--graisse-micro);
  letter-spacing: var(--interlettre-micro);
  text-transform: uppercase;
  color: var(--texte-attenue);
}

a {
  color: var(--marque);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--duree-rapide) var(--courbe);
}
a:hover { color: var(--accent-survol); }

/* Chasse tabulaire : sans elle, les colonnes de prix ne s'alignent pas
   et un total ne se lit plus en diagonale. */
.chiffres,
.montant,
.tableau td.montant,
.tableau th.montant,
.saisie--montant,
.saisie--nombre,
.montant-vedette {
  font-family: var(--police-chiffres);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.montant-vedette {
  display: block;
  font-size: var(--taille-display);
  line-height: var(--hauteur-display);
  font-weight: var(--graisse-display);
  letter-spacing: var(--interlettre-titre);
  color: var(--marque);
}
.montant-vedette__legende {
  display: block;
  margin: 0 0 var(--espace-1);
  font-family: var(--police);
  font-size: var(--taille-micro);
  font-weight: var(--graisse-micro);
  letter-spacing: var(--interlettre-micro);
  text-transform: uppercase;
  color: var(--texte-attenue);
}

/* =====================================================================
   FOCUS CLAVIER
   ---------------------------------------------------------------------
   Un anneau visible sur TOUT élément interactif. Les rares « outline:
   none » du fichier sont systématiquement suivis d'un box-shadow de
   remplacement, dans la même règle.
   ===================================================================== */
:focus-visible {
  outline: 2px solid var(--bordure-focus);
  outline-offset: 2px;
  border-radius: var(--rayon-petit);
}

.lien-evitement {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--espace-3) var(--espace-4);
  background: var(--surface);
  color: var(--marque);
  font-weight: var(--graisse-appuyee);
  border-radius: var(--rayon-moyen);
  box-shadow: var(--ombre-surelevee);
}
.lien-evitement:focus { left: var(--espace-3); top: var(--espace-3); }

/* =====================================================================
   EN-TÊTE ET NAVIGATION  (.entete)
   ---------------------------------------------------------------------
   UNE seule bande : marque, navigation, établissement, agent. Fond clair
   plutôt que bordeaux plein — le bordeaux garde alors toute sa force
   pour les actions, et la lecture reste reposante sur une journée.
   ===================================================================== */
.entete {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--surface);
  border-bottom: 1px solid var(--bordure);
  box-shadow: var(--ombre-subtile);
}

/* Trois zones sur une ligne, et un partage de largeur explicite :

     * la navigation ne se comprime JAMAIS — ses libellés sont
       insécables, la comprimer la ferait déborder par-dessous le nom de
       l'agent, ce qui donnait « Journal de caisseResponsable accueil » ;
     * la marque et la zone agent, elles, se partagent tout le reste et
       se COUPENT proprement (min-width: 0 + ellipse) : un nom
       d'établissement long et un nom d'agent long se disputent l'espace
       entre eux, jamais avec les rubriques ;
     * dès que la navigation ne tient plus (point de repli, tout en bas
       de ce fichier), elle passe ENTIÈRE dans le menu repliable. Aucune
       largeur intermédiaire ne peut donc produire un chevauchement.

   Le partage est fait par flex, pas par des largeurs devinées : c'est ce
   qui le rend vrai à 1440, 1200, 1024, 834 et 390 px, et à tout ce qu'il
   y a entre. test_l_entete_ne_deborde_jamais_avec_des_valeurs_longues
   recalcule le budget de largeur à chacune de ces cinq tailles. */
.entete__interieur {
  display: flex;
  align-items: center;
  gap: var(--espace-4);
  max-width: var(--largeur-page);
  min-height: var(--hauteur-entete);
  margin: 0 auto;
  padding: 0 var(--espace-5);
}

.entete__marque {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  flex: 1 1 auto;
  min-width: 0;
}

.entete__logo {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-2);
  flex: none;
  min-height: var(--hauteur-cible);
  color: var(--texte);
  text-decoration: none;
  font-size: var(--taille-titre-3);
  font-weight: var(--graisse-appuyee);
  letter-spacing: var(--interlettre-titre);
  white-space: nowrap;
}
.entete__logo:hover { color: var(--marque); }

.entete__logo-pastille {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--rayon-petit);
  background: var(--marque);
  color: var(--texte-sur-marque);
  font-size: var(--taille-micro);
  font-weight: var(--graisse-forte);
  letter-spacing: var(--interlettre-micro);
}

.entete__logo-texte { color: inherit; }

/* Établissement connecté : discret, mais toujours visible — une hôtesse
   ne doit jamais douter de la clinique dans laquelle elle saisit.

   Aucune largeur maximale en dur : la pastille prend ce qui reste et
   coupe à l'ellipse quand il ne reste plus rien. Un nom coupé garde son
   attribut title, et le nom complet reste écrit en toutes lettres en
   tête de chaque écran. */
.entete__etablissement {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-2);
  flex: 0 1 auto;
  min-width: 0;
  padding: var(--espace-1) var(--espace-3);
  border-radius: var(--rayon-pilule);
  background: var(--marque-fond);
  color: var(--marque);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-moyenne);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.entete__etablissement svg { flex: none; }

/* flex-basis: auto et grow 0 : la navigation occupe exactement la place
   de ses rubriques. Elle ne s'étire pas, et surtout elle ne se comprime
   pas — c'est cette compression qui la faisait déborder sur la zone
   agent. */
.entete__navigation { flex: 0 0 auto; }

.entete__liste {
  display: flex;
  align-items: center;
  gap: var(--espace-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.entete__lien {
  display: inline-flex;
  align-items: center;
  min-height: var(--hauteur-cible);
  padding: 0 var(--espace-3);
  border-radius: var(--rayon-petit);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-moyenne);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--duree-rapide) var(--courbe),
              color var(--duree-rapide) var(--courbe);
}
.entete__lien:hover {
  background: var(--marque-fond);
  color: var(--marque);
}
.entete__lien:active { background: var(--accent-fond); }
.entete__lien:focus-visible {
  outline: 2px solid var(--bordure-focus);
  outline-offset: 2px;
}

/* Rubrique active : couleur de marque, fond teinté ET filet dessous —
   trois signaux, pour que ce soit évident d'un coup d'œil. */
.entete__lien--actif,
.entete__lien[aria-current="page"] {
  background: var(--marque-fond);
  color: var(--marque);
  font-weight: var(--graisse-appuyee);
  box-shadow: inset 0 -2px 0 0 var(--accent);
}

.entete__lien--desactive,
.entete__lien[aria-disabled="true"] {
  color: var(--texte-attenue);
  opacity: .55;
  pointer-events: none;
}

/* Symétrique de .entete__marque : même souplesse, même coupe. Les deux
   zones de texte se partagent la largeur restante ; celle qui a le nom
   le plus long en garde le plus. */
.entete__agent {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--espace-3);
  flex: 1 1 auto;
  min-width: 0;
}
.entete__nom {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--taille-petit);
  font-weight: var(--graisse-appuyee);
  white-space: nowrap;
}
.entete__deconnexion { flex: none; margin: 0; }

/* Bouton de repli, visible seulement sous le point de repli de l'en-tête
   (voir la section RESPONSIVE). */
.entete__bascule {
  display: none;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--hauteur-cible);
  height: var(--hauteur-cible);
  padding: 0;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-petit);
  background: var(--surface);
  color: var(--texte);
  cursor: pointer;
}
.entete__bascule:hover { background: var(--marque-fond); color: var(--marque); }

/* =====================================================================
   GABARIT DE PAGE
   ===================================================================== */
.page {
  flex: 1;
  width: 100%;
  max-width: var(--largeur-page);
  margin: 0 auto;
  padding: var(--espace-6) var(--espace-5) var(--espace-7);
}

.page__messages:empty { display: none; }

.page__entete {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--espace-4);
  margin: 0 0 var(--espace-6);
}

.titre-page {
  margin: 0 0 var(--espace-1);
  font-size: var(--taille-titre-1);
  line-height: var(--hauteur-titre-1);
  font-weight: var(--graisse-titre-1);
  letter-spacing: var(--interlettre-titre);
}

.sous-titre {
  margin: 0;
  font-size: var(--taille-corps);
  color: var(--texte-secondaire);
}

.section { margin: 0 0 var(--espace-6); }
.section__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--espace-3);
  margin: 0 0 var(--espace-4);
}

.pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-2);
  width: 100%;
  max-width: var(--largeur-page);
  margin: 0 auto;
  padding: var(--espace-5) var(--espace-5) var(--espace-6);
  border-top: 1px solid var(--bordure);
  color: var(--texte-attenue);
  font-size: var(--taille-petit);
}
.pied__mention { color: var(--marque); font-weight: var(--graisse-moyenne); }

/* --- Grille -------------------------------------------------------- */
.grille { display: grid; gap: var(--espace-4); align-items: stretch; }
.grille--2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grille--3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grille--4 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

/* =====================================================================
   CARTES  (.carte)
   ---------------------------------------------------------------------
   Colonne flexible : le corps s'étire, les actions restent collées en
   bas. Deux cartes d'une même rangée ont donc leurs boutons alignés,
   quelle que soit la longueur du texte.
   ===================================================================== */
.carte {
  display: flex;
  flex-direction: column;
  padding: var(--espace-5);
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-grand);
  box-shadow: var(--ombre-carte);
  transition: box-shadow var(--duree) var(--courbe),
              border-color var(--duree) var(--courbe),
              transform var(--duree) var(--courbe);
}

.carte__icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0 0 var(--espace-4);
  border-radius: var(--rayon-moyen);
  background: var(--marque-fond);
  color: var(--marque);
  flex: none;
}
.carte__icone svg { width: 20px; height: 20px; }

.carte__titre {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-titre-3);
  line-height: var(--hauteur-titre-3);
  font-weight: var(--graisse-titre-3);
  color: var(--texte);
}

.carte__texte {
  margin: 0;
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
}

/* Pousse .carte__actions vers le bas de la carte. */
.carte__corps { flex: 1; margin: 0 0 var(--espace-5); }

.carte__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ecart-actions);
  margin-top: auto;
}

.carte__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--espace-3);
  margin: 0 0 var(--espace-4);
}

.carte--serree { padding: var(--espace-4); }
.carte--plate  { box-shadow: var(--ombre-aucune); }

/* Carte principale d'un écran : c'est la HIÉRARCHIE qui la distingue
   (titre plus grand, icône pleine, ombre marquée), pas une couleur
   criarde. */
.carte--vedette {
  border-color: var(--accent-fond);
  box-shadow: var(--ombre-surelevee);
}
.carte--vedette .carte__icone {
  width: 48px;
  height: 48px;
  background: var(--marque);
  color: var(--texte-sur-marque);
}
.carte--vedette .carte__icone svg { width: 24px; height: 24px; }
.carte--vedette .carte__titre {
  font-size: var(--taille-titre-2);
  line-height: var(--hauteur-titre-2);
}
.carte--vedette .carte__texte { font-size: var(--taille-corps); }
.carte--vedette:hover { box-shadow: var(--ombre-modale); }

.carte--voile {
  background: var(--marque-fond);
  border-color: var(--accent-fond);
  box-shadow: var(--ombre-aucune);
}

/* Carte en rangée : icône à gauche, texte au centre, actions à droite.
   Une carte pleine largeur qui ne contient que trois lignes paraît vide
   en colonne ; en rangée elle occupe la bande sans la remplir de vide. */
@media (min-width: 721px) {
  .carte--rangee { flex-direction: row; align-items: center; gap: var(--espace-5); }
  .carte--rangee .carte__icone { margin: 0; }
  .carte--rangee .carte__corps { margin: 0; }
  .carte--rangee .carte__actions { margin: 0; flex: none; }
}

/* =====================================================================
   BLOC DE CONFIDENTIALITÉ  (.confidentialite)
   ---------------------------------------------------------------------
   La règle d'or du projet, rappelée sans écraser les actions : une bande
   basse, rose très pâle, un bouclier, deux lignes.
   ===================================================================== */
.confidentialite {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  background: var(--marque-fond);
  border: 1px solid var(--accent-fond);
  border-radius: var(--rayon-moyen);
}
.confidentialite__icone { flex: none; color: var(--marque); }
.confidentialite__icone svg { width: 20px; height: 20px; }
.confidentialite__corps { min-width: 0; }
.confidentialite__titre {
  margin: 0;
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  font-weight: var(--graisse-appuyee);
  color: var(--marque);
}
.confidentialite__texte {
  margin: 0;
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  color: var(--texte-secondaire);
}

/* =====================================================================
   BOUTONS  (.bouton)
   ---------------------------------------------------------------------
   Quatre variantes, même hauteur, même rayon, même typographie, mêmes
   transitions. Cinq états : normal, survol, actif, focus visible,
   désactivé — plus l'état « chargement ».
   ===================================================================== */
.bouton {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-2);
  min-height: var(--hauteur-cible);
  padding: 0 var(--espace-5);
  border: 1px solid transparent;
  border-radius: var(--rayon-moyen);
  font-family: var(--police);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-appuyee);
  line-height: 1;
  letter-spacing: 0;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--duree-rapide) var(--courbe),
              border-color var(--duree-rapide) var(--courbe),
              color var(--duree-rapide) var(--courbe),
              box-shadow var(--duree-rapide) var(--courbe),
              transform var(--duree-rapide) var(--courbe);
}
.bouton:active { transform: translateY(1px); }
.bouton:focus-visible {
  outline: none;                       /* remplacé par l'anneau ci-dessous */
  box-shadow: var(--anneau-focus);
}

.bouton__icone { flex: none; }
.bouton__icone svg { width: 18px; height: 18px; }

/* --- Primaire : l'action attendue de l'écran ---------------------- */
.bouton--primaire {
  background: var(--marque);
  border-color: var(--marque);
  color: var(--texte-sur-marque);
  box-shadow: var(--ombre-subtile);
}
.bouton--primaire:hover {
  background: var(--marque-survol);
  border-color: var(--marque-survol);
  color: var(--texte-sur-marque);
}
.bouton--primaire:active {
  background: var(--marque-actif);
  border-color: var(--marque-actif);
}

/* --- Secondaire : action de même écran, moins engageante ---------- */
.bouton--secondaire {
  background: var(--surface);
  border-color: var(--bordure-marquee);
  color: var(--texte);
}
.bouton--secondaire:hover {
  background: var(--marque-fond);
  border-color: var(--accent-fond);
  color: var(--marque);
}
.bouton--secondaire:active { background: var(--accent-fond); }

/* --- Tertiaire : lien d'action, sans poids visuel ----------------- */
.bouton--tertiaire {
  background: transparent;
  border-color: transparent;
  color: var(--marque);
}
.bouton--tertiaire:hover { background: var(--marque-fond); color: var(--marque-survol); }
.bouton--tertiaire:active { background: var(--accent-fond); }

/* --- Danger : suppression, annulation, action irréversible -------- */
.bouton--danger {
  background: var(--erreur-texte);
  border-color: var(--erreur-texte);
  color: var(--texte-sur-marque);
  box-shadow: var(--ombre-subtile);
}
.bouton--danger:hover { background: var(--marque-actif); border-color: var(--marque-actif); }
.bouton--danger:active { background: var(--marque-actif); }
.bouton--danger:focus-visible {
  outline: none;                       /* remplacé par l'anneau ci-dessous */
  box-shadow: var(--anneau-focus-danger);
}

/* --- Tailles : deux, et deux seulement ----------------------------
   La taille compacte sert les barres d'action des tableaux. Son fond
   visuel ne fait que 32 px de haut, mais un pseudo-élément transparent
   ramène la ZONE CLIQUABLE à 44 px : la règle des 44 px tient partout,
   sans faire enfler les lignes du tableau. */
.bouton--compact {
  min-height: var(--bouton-compact-hauteur);
  padding: 0 var(--espace-3);
  font-size: var(--taille-petit);
}
/* La zone cliquable déborde en haut et en bas, jamais sur les côtés :
   left et right restent calés sur les bords du bouton. Deux boutons
   côte à côte ne peuvent donc pas se recouvrir ; deux boutons empilés,
   si — d'où --ecart-actions sur les barres d'actions. */
.bouton--compact::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: var(--hauteur-cible);
  transform: translateY(-50%);
}

/* Filet de sécurité : si un lot pose des boutons compacts dans un
   conteneur générique plutôt que dans une barre d'actions, l'écart
   minimal s'applique quand même. */
.pile:has(> .bouton--compact),
.rangee:has(> .bouton--compact),
.grille:has(> .bouton--compact) {
  gap: var(--ecart-actions);
}

.bouton--bloc { width: 100%; }

/* --- Désactivé ----------------------------------------------------- */
.bouton[disabled],
.bouton[aria-disabled="true"] {
  background: var(--surface-sourde);
  border-color: var(--bordure);
  color: var(--texte-attenue);
  box-shadow: var(--ombre-aucune);
  cursor: not-allowed;
  opacity: 1;
  transform: none;
}

/* --- Chargement : indicateur intégré, bouton inerte ---------------- */
.bouton--charge {
  cursor: progress;
  pointer-events: none;
}
.bouton--charge .bouton__libelle { opacity: .65; }
.bouton__rouet {
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--rayon-pilule);
  animation: hc-tourner 600ms linear infinite;
}

@keyframes hc-tourner { to { transform: rotate(360deg); } }

.barre-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ecart-actions);
  margin: var(--espace-5) 0 0;
}
.barre-actions--fin { justify-content: flex-end; }

/* =====================================================================
   FORMULAIRES
   ===================================================================== */
.formulaire { margin: 0; }

/* `display: block` n'est pas décoratif : `.champ` se porte presque
   toujours sur un `<label>`, dont l'affichage par défaut est INLINE — et
   une marge verticale sur un élément inline ne produit rien. Le défaut ne
   se voyait pas dans une `.grille`, qui blockifie ses enfants ; il se
   voyait partout ailleurs, où deux champs consécutifs se retrouvaient
   collés l'un à l'autre, l'aide du premier touchant le libellé du second
   (constaté sur /admission/ et sur l'écran de clôture d'un séjour). */
.champ { display: block; margin: 0 0 var(--espace-4); }

.champ__libelle {
  display: block;
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  font-weight: var(--graisse-appuyee);
  color: var(--texte);
}
.champ__obligatoire { color: var(--accent); }

.champ__aide {
  display: block;
  margin: var(--espace-2) 0 0;
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  color: var(--texte-attenue);
}

.champ__erreur {
  display: flex;
  align-items: center;
  gap: var(--espace-1);
  margin: var(--espace-2) 0 0;
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
  font-weight: var(--graisse-moyenne);
  color: var(--erreur-texte);
}
.champ__erreur svg { width: 14px; height: 14px; flex: none; }

.saisie,
.selection,
.zone-texte {
  display: block;
  width: 100%;
  min-height: var(--hauteur-cible);
  padding: var(--espace-2) var(--espace-3);
  font-family: var(--police);
  font-size: var(--taille-corps);
  line-height: var(--hauteur-corps);
  color: var(--texte);
  background: var(--surface);
  border: 1px solid var(--bordure-marquee);
  border-radius: var(--rayon-moyen);
  transition: border-color var(--duree-rapide) var(--courbe),
              box-shadow var(--duree-rapide) var(--courbe);
}
.saisie::placeholder, .zone-texte::placeholder { color: var(--texte-attenue); }

.saisie:hover, .selection:hover, .zone-texte:hover { border-color: var(--texte-attenue); }

.saisie:focus, .selection:focus, .zone-texte:focus {
  outline: none;                       /* remplacé par l'anneau ci-dessous */
  border-color: var(--bordure-focus);
  box-shadow: var(--anneau-focus);
}

.zone-texte { min-height: 108px; resize: vertical; }

/* Liste déroulante habillée : la flèche native est remplacée par un
   chevron dessiné en CSS (deux bordures pivotées). Ni image, ni police
   d'icônes, ni data-URI — donc aucune couleur figée hors de :root.
   Une .selection employée seule, sans l'enveloppe, garde la flèche du
   système : les deux usages restent corrects. */
.champ-selection { position: relative; display: block; }
.champ-selection .selection { appearance: none; padding-right: var(--espace-7); }
.champ-selection::after {
  content: "";
  position: absolute;
  top: 50%;
  right: var(--espace-4);
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--texte-secondaire);
  border-bottom: 2px solid var(--texte-secondaire);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

.saisie--montant, .saisie--nombre { text-align: right; }

/* --- Erreur de champ ----------------------------------------------- */
.saisie[aria-invalid="true"],
.selection[aria-invalid="true"],
.zone-texte[aria-invalid="true"],
.champ--erreur .saisie,
.champ--erreur .selection,
.champ--erreur .zone-texte {
  border-color: var(--erreur-texte);
  background: var(--erreur-fond);
}
.champ--erreur .champ__libelle { color: var(--erreur-texte); }

/* --- Champ inerte --------------------------------------------------- */
.saisie[readonly], .zone-texte[readonly] {
  background: var(--surface-sourde);
  color: var(--texte-secondaire);
}
.saisie[disabled], .selection[disabled], .zone-texte[disabled] {
  background: var(--surface-sourde);
  border-color: var(--bordure);
  color: var(--texte-attenue);
  cursor: not-allowed;
}

/* --- Case à cocher et bouton radio ---------------------------------- */
.champ-case,
.champ-radio {
  display: flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--hauteur-cible);
  cursor: pointer;
}
.champ-case input, .champ-radio input {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--marque);
  cursor: pointer;
}
.champ-case input[disabled], .champ-radio input[disabled] { cursor: not-allowed; }
.champ-case__texte, .champ-radio__texte { font-size: var(--taille-corps); }
.champ-case input[disabled] ~ .champ-case__texte,
.champ-radio input[disabled] ~ .champ-radio__texte { color: var(--texte-attenue); }

/* --- Interrupteur ---------------------------------------------------- */
.interrupteur {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-3);
  min-height: var(--hauteur-cible);
  cursor: pointer;
}
.interrupteur__entree {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.interrupteur__piste {
  position: relative;
  flex: none;
  width: 44px;
  height: 26px;
  border-radius: var(--rayon-pilule);
  background: var(--bordure-marquee);
  transition: background-color var(--duree) var(--courbe);
}
.interrupteur__piste::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: var(--rayon-pilule);
  background: var(--surface);
  box-shadow: var(--ombre-subtile);
  transition: transform var(--duree) var(--courbe);
}
.interrupteur__entree:checked + .interrupteur__piste { background: var(--marque); }
.interrupteur__entree:checked + .interrupteur__piste::after { transform: translateX(18px); }
.interrupteur__entree:focus-visible + .interrupteur__piste {
  outline: none;                       /* remplacé par l'anneau ci-dessous */
  box-shadow: var(--anneau-focus);
}
.interrupteur__entree[disabled] + .interrupteur__piste { opacity: .5; cursor: not-allowed; }
.interrupteur__texte { font-size: var(--taille-corps); }

/* --- Groupes de champs ---------------------------------------------- */
.groupe-champs {
  display: grid;
  gap: var(--espace-3) var(--espace-4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

fieldset.bloc {
  margin: 0 0 var(--espace-5);
  padding: var(--espace-4);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-moyen);
  background: var(--surface);
}
fieldset.bloc legend {
  padding: 0 var(--espace-2);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-appuyee);
  color: var(--marque);
}

/* =====================================================================
   BARRE D'OUTILS DE FILTRES  (.barre-filtres)
   ===================================================================== */
.barre-filtres {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--ecart-actions);
  padding: var(--espace-3) var(--espace-4);
  margin: 0 0 var(--espace-4);
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-moyen);
}
.barre-filtres__groupe {
  display: flex;
  flex-direction: column;
  gap: var(--espace-1);
  min-width: 160px;
}
.barre-filtres__groupe .champ { margin: 0; }
.barre-filtres__etiquette {
  font-size: var(--taille-micro);
  font-weight: var(--graisse-micro);
  letter-spacing: var(--interlettre-micro);
  text-transform: uppercase;
  color: var(--texte-attenue);
}
.barre-filtres__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ecart-actions);
  margin-left: auto;
}

/* =====================================================================
   TABLEAUX  (.tableau)
   ===================================================================== */
.tableau-cadre {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-grand);
}
.tableau-cadre--defilant { max-height: 480px; overflow-y: auto; }

.tableau {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--taille-petit);
}

.tableau th, .tableau td {
  padding: var(--espace-3) var(--espace-4);
  text-align: left;
  border-bottom: 1px solid var(--bordure);
}

/* En-tête collant : la ligne de titres reste lisible quand la table
   défile — indispensable sur un journal de caisse de 200 lignes. */
.tableau thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-sourde);
  color: var(--texte-secondaire);
  font-size: var(--taille-micro);
  font-weight: var(--graisse-micro);
  letter-spacing: var(--interlettre-micro);
  text-transform: uppercase;
  white-space: nowrap;
}

.tableau tbody tr { transition: background-color var(--duree-rapide) var(--courbe); }
.tableau tbody tr:nth-child(even) { background: var(--marque-fond); }
.tableau tbody tr:hover { background: var(--accent-fond); }
/* `th` autant que `td` : les tableaux clé/valeur du projet portent leur
   intitulé dans un `<th scope="row">`, et la règle qui ne visait que les
   `td` laissait un filet orphelin sous la SEULE première colonne de la
   dernière ligne — un trait qui s'arrêtait au milieu du cadre. Visible
   sur le dossier d'un séjour, le diagnostic de liaison et l'export
   comptable. */
.tableau tbody tr:last-child td,
.tableau tbody tr:last-child th { border-bottom: none; }
.tableau tbody tr.tableau__ligne--selectionnee {
  background: var(--accent-fond);
  box-shadow: inset 3px 0 0 0 var(--accent);
}

.tableau td.montant, .tableau th.montant { text-align: right; white-space: nowrap; }

.tableau tfoot td, .tableau tfoot th {
  background: var(--surface-sourde);
  border-top: 2px solid var(--bordure-marquee);
  border-bottom: none;
  font-size: var(--taille-corps);
  font-weight: var(--graisse-appuyee);
  color: var(--texte);
}

.tableau__vide {
  padding: var(--espace-6);
  text-align: center;
  color: var(--texte-attenue);
}

.tableau__actions {
  display: flex;
  gap: var(--ecart-actions);
  justify-content: flex-end;
}

/* =====================================================================
   ONGLETS  (.onglets)
   ===================================================================== */
.onglets {
  display: flex;
  flex-wrap: wrap;
  gap: var(--espace-1);
  margin: 0 0 var(--espace-5);
  padding: 0;
  border-bottom: 1px solid var(--bordure);
  list-style: none;
}
.onglets__lien {
  display: inline-flex;
  align-items: center;
  min-height: var(--hauteur-cible);
  padding: 0 var(--espace-4);
  border-bottom: 2px solid transparent;
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-moyenne);
  text-decoration: none;
  transition: color var(--duree-rapide) var(--courbe),
              border-color var(--duree-rapide) var(--courbe);
}
.onglets__lien:hover { color: var(--marque); border-bottom-color: var(--accent-fond); }
.onglets__lien--actif,
.onglets__lien[aria-selected="true"] {
  color: var(--marque);
  font-weight: var(--graisse-appuyee);
  border-bottom-color: var(--accent);
}
.onglets__lien[aria-disabled="true"] { color: var(--texte-attenue); pointer-events: none; }

/* =====================================================================
   FIL D'ARIANE  (.fil-ariane)
   ===================================================================== */
.fil-ariane {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-2);
  margin: 0 0 var(--espace-4);
  padding: 0;
  list-style: none;
  font-size: var(--taille-petit);
  color: var(--texte-attenue);
}
.fil-ariane__element { display: inline-flex; align-items: center; gap: var(--espace-2); }
.fil-ariane__lien { color: var(--texte-secondaire); text-decoration: none; }
.fil-ariane__lien:hover { color: var(--marque); text-decoration: underline; }
.fil-ariane__separateur { color: var(--bordure-marquee); }
.fil-ariane__actuel { color: var(--texte); font-weight: var(--graisse-moyenne); }

/* =====================================================================
   PAGINATION  (.pagination)
   ===================================================================== */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--espace-2);
  margin: var(--espace-4) 0 0;
  padding: 0;
  list-style: none;
}
.pagination__lien {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--hauteur-cible);
  min-height: var(--hauteur-cible);
  padding: 0 var(--espace-3);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-petit);
  background: var(--surface);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-moyenne);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: background-color var(--duree-rapide) var(--courbe),
              color var(--duree-rapide) var(--courbe);
}
.pagination__lien:hover { background: var(--marque-fond); color: var(--marque); }
.pagination__lien--actif,
.pagination__lien[aria-current="page"] {
  background: var(--marque);
  border-color: var(--marque);
  color: var(--texte-sur-marque);
}
.pagination__lien[aria-disabled="true"] {
  background: var(--surface-sourde);
  color: var(--texte-attenue);
  pointer-events: none;
}
.pagination__info { margin-left: auto; color: var(--texte-attenue); font-size: var(--taille-petit); }

/* =====================================================================
   BADGES ET PASTILLES
   ===================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--espace-1);
  padding: var(--espace-1) var(--espace-3);
  border: 1px solid transparent;
  border-radius: var(--rayon-pilule);
  font-size: var(--taille-micro);
  line-height: var(--hauteur-micro);
  font-weight: var(--graisse-micro);
  white-space: nowrap;
}
.badge--neutre  { background: var(--surface-sourde);       color: var(--texte-secondaire);     border-color: var(--bordure); }
.badge--info    { background: var(--information-fond);     color: var(--information-texte);    border-color: var(--information-bordure); }
.badge--succes  { background: var(--succes-fond);          color: var(--succes-texte);         border-color: var(--succes-bordure); }
.badge--attention { background: var(--avertissement-fond); color: var(--avertissement-texte);  border-color: var(--avertissement-bordure); }
.badge--danger  { background: var(--erreur-fond);          color: var(--erreur-texte);         border-color: var(--erreur-bordure); }

.pastille {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--rayon-pilule);
  vertical-align: middle;
}
.pastille--neutre    { background: var(--texte-attenue); }
.pastille--info      { background: var(--information-texte); }
.pastille--succes    { background: var(--succes-texte); }
.pastille--attention { background: var(--avertissement-texte); }
.pastille--danger    { background: var(--erreur-texte); }
/* Alias métier : états de chambre et de séjour. */
.pastille--libre     { background: var(--bordure-marquee); }
.pastille--programme { background: var(--avertissement-texte); }
.pastille--actif     { background: var(--succes-texte); }
.pastille--clos      { background: var(--texte-attenue); }
.pastille--echec     { background: var(--erreur-texte); }

.pastille-compteur {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 var(--espace-2);
  border-radius: var(--rayon-pilule);
  background: var(--accent-survol);
  color: var(--texte-sur-marque);
  font-size: var(--taille-micro);
  font-weight: var(--graisse-forte);
  font-variant-numeric: tabular-nums;
}

/* =====================================================================
   ALERTES  (.bandeau)
   ===================================================================== */
.bandeau {
  display: flex;
  align-items: flex-start;
  gap: var(--espace-3);
  padding: var(--espace-3) var(--espace-4);
  margin: 0 0 var(--espace-3);
  border: 1px solid var(--bordure);
  border-left-width: var(--espace-1);
  border-radius: var(--rayon-moyen);
  background: var(--surface-sourde);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
}
.bandeau__icone { flex: none; }
.bandeau__icone svg { width: 18px; height: 18px; }
.bandeau__corps { flex: 1; min-width: 0; }
.bandeau__titre {
  display: block;
  margin: 0 0 var(--espace-1);
  font-size: var(--taille-petit);
  font-weight: var(--graisse-appuyee);
}
.bandeau__texte { margin: 0; }

.bandeau--info {
  background: var(--information-fond);
  border-color: var(--information-bordure);
  border-left-color: var(--information-texte);
  color: var(--information-texte);
}
.bandeau--succes {
  background: var(--succes-fond);
  border-color: var(--succes-bordure);
  border-left-color: var(--succes-texte);
  color: var(--succes-texte);
}
.bandeau--attention {
  background: var(--avertissement-fond);
  border-color: var(--avertissement-bordure);
  border-left-color: var(--avertissement-texte);
  color: var(--avertissement-texte);
}
.bandeau--erreur {
  background: var(--erreur-fond);
  border-color: var(--erreur-bordure);
  border-left-color: var(--erreur-texte);
  color: var(--erreur-texte);
}

.bandeau__fermer {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--hauteur-cible);
  height: var(--hauteur-cible);
  margin: 0;
  padding: 0;
  border: none;
  border-radius: var(--rayon-petit);
  background: none;
  color: inherit;
  font-family: var(--police);
  font-size: var(--taille-titre-3);
  line-height: 1;
  cursor: pointer;
}
.bandeau__fermer:hover { background: var(--surface); }

/* =====================================================================
   INFOBULLE  (.infobulle)
   ---------------------------------------------------------------------
   Apparaît au survol ET au focus clavier : une information réservée à
   la souris n'existe pas pour la moitié des utilisatrices.
   ===================================================================== */
.infobulle { position: relative; display: inline-flex; }
.infobulle__contenu {
  position: absolute;
  bottom: 100%;
  left: 50%;
  z-index: 30;
  width: max-content;
  max-width: 260px;
  margin: 0 0 var(--espace-2);
  padding: var(--espace-2) var(--espace-3);
  border-radius: var(--rayon-petit);
  background: var(--texte);
  color: var(--surface);
  font-size: var(--taille-micro);
  line-height: var(--hauteur-micro);
  font-weight: var(--graisse-normale);
  text-align: left;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, var(--espace-1));
  transition: opacity var(--duree-rapide) var(--courbe),
              transform var(--duree-rapide) var(--courbe),
              visibility var(--duree-rapide) var(--courbe);
}
.infobulle:hover .infobulle__contenu,
.infobulle:focus-within .infobulle__contenu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

/* =====================================================================
   MODALE  (.modale)
   ===================================================================== */
.modale {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--espace-4);
}
.modale[hidden] { display: none; }

.modale__voile {
  position: absolute;
  inset: 0;
  background: var(--voile-modale);
  animation: hc-apparaitre var(--duree) var(--courbe);
}

.modale__boite {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 86vh;
  padding: var(--espace-5);
  background: var(--surface-elevee);
  border-radius: var(--rayon-grand);
  box-shadow: var(--ombre-modale);
  animation: hc-monter var(--duree) var(--courbe);
}

.modale__entete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--espace-3);
  margin: 0 0 var(--espace-4);
}
.modale__titre {
  margin: 0;
  font-size: var(--taille-titre-2);
  line-height: var(--hauteur-titre-2);
  font-weight: var(--graisse-titre-2);
  color: var(--texte);
}
.modale__fermer {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--hauteur-cible);
  height: var(--hauteur-cible);
  margin: 0;
  padding: 0;
  border: none;
  border-radius: var(--rayon-petit);
  background: none;
  color: var(--texte-secondaire);
  font-family: var(--police);
  font-size: var(--taille-titre-2);
  line-height: 1;
  cursor: pointer;
}
.modale__fermer:hover { background: var(--surface-sourde); color: var(--texte); }

.modale__corps {
  flex: 1;
  overflow-y: auto;
  margin: 0 0 var(--espace-5);
  color: var(--texte-secondaire);
}
.modale__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ecart-actions);
  justify-content: flex-end;
}

@keyframes hc-apparaitre { from { opacity: 0; } to { opacity: 1; } }
@keyframes hc-monter {
  from { opacity: 0; transform: translateY(8px) scale(.99); }
  to   { opacity: 1; transform: none; }
}

/* =====================================================================
   CHARGEMENT
   ===================================================================== */
.rouet {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2px solid var(--bordure-marquee);
  border-top-color: var(--marque);
  border-radius: var(--rayon-pilule);
  animation: hc-tourner 600ms linear infinite;
}
.rouet--grand { width: 32px; height: 32px; border-width: 3px; }

/* Zone en cours de chargement : le contenu reste en place, voilé. */
.chargement-zone {
  position: relative;
  min-height: 120px;
}
.chargement-zone::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--voile-chargement);
  border-radius: var(--rayon-grand);
}
.chargement-zone__indicateur {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--espace-3);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
}

/* Page entière : réservée aux transitions longues (édition d'une
   facture, clôture de caisse). */
.chargement-page {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--espace-4);
  background: var(--voile-chargement);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
}
.chargement-page[hidden] { display: none; }

/* Squelettes : garder la forme de la page pendant l'attente évite le
   saut de mise en page à l'arrivée des données. */
.squelette {
  display: block;
  height: 14px;
  border-radius: var(--rayon-petit);
  background-color: var(--squelette-base);
  background-image: linear-gradient(90deg,
      var(--squelette-base), var(--squelette-lueur), var(--squelette-base));
  background-size: 200% 100%;
  animation: hc-miroiter 1200ms ease-in-out infinite;
}
.squelette--titre { height: 22px; width: 45%; }
.squelette--ligne { width: 100%; }
.squelette--court { width: 60%; }

.squelette-tableau { display: flex; flex-direction: column; gap: var(--espace-3); }
.squelette-tableau__ligne {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: var(--espace-4);
  padding: var(--espace-3) var(--espace-4);
  border-bottom: 1px solid var(--bordure);
}

@keyframes hc-miroiter {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* =====================================================================
   ÉTAT VIDE  (.etat-vide)
   ===================================================================== */
.etat-vide {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--espace-8) var(--espace-5);
  background: var(--surface);
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-grand);
}
.etat-vide__icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin: 0 0 var(--espace-4);
  border-radius: var(--rayon-pilule);
  background: var(--marque-fond);
  color: var(--marque);
}
.etat-vide__icone svg { width: 26px; height: 26px; }
.etat-vide__titre {
  margin: 0 0 var(--espace-2);
  font-size: var(--taille-titre-3);
  font-weight: var(--graisse-titre-3);
  color: var(--texte);
}
.etat-vide__texte {
  max-width: 46ch;
  margin: 0 0 var(--espace-5);
  color: var(--texte-secondaire);
  font-size: var(--taille-petit);
  line-height: var(--hauteur-petit);
}
.etat-vide__action { margin: 0; }

/* =====================================================================
   RÉFÉRENCES DE CODE ET ÉCHANTILLONS
   ---------------------------------------------------------------------
   Sert à la page /design et, plus généralement, partout où un écran
   doit citer un nom de classe, une clé technique ou une couleur.
   ===================================================================== */
code, .code {
  padding: var(--espace-1) var(--espace-2);
  border-radius: var(--rayon-petit);
  background: var(--surface-sourde);
  color: var(--marque);
  font-family: var(--police-mono);
  font-size: var(--taille-micro);
  white-space: nowrap;
}

.echantillon {
  display: block;
  width: 100%;
  height: 44px;
  border: 1px solid var(--bordure);
  border-radius: var(--rayon-moyen);
}

/* =====================================================================
   UTILITAIRES
   ===================================================================== */
.muet { color: var(--texte-attenue); }
.gras { font-weight: var(--graisse-appuyee); }
.sans-marge { margin: 0; }

/* Un utilitaire d'alignement doit GAGNER, sinon il ne sert à rien.
   `.tableau th, .tableau td { text-align: left }` pèse (0,1,1) contre
   (0,1,0) pour une classe seule : `<th class="a-droite">Montant TTC</th>`
   restait donc calé à gauche au-dessus d'une colonne de montants alignés
   à droite. Vingt-sept en-têtes du produit étaient dans ce cas — sur
   l'écran des factures, sur le journal de caisse, sur l'export comptable,
   et sur la facture qui part chez le patient.
   Le `!important` est ici à sa place : c'est le seul cas où il l'est,
   celui d'une classe dont l'unique raison d'être est de trancher. */
.centre { text-align: center !important; }
.a-droite { text-align: right !important; }

.pile { display: flex; flex-direction: column; gap: var(--espace-3); }
.pile--serree { gap: var(--espace-2); }
.rangee { display: flex; align-items: center; flex-wrap: wrap; gap: var(--espace-3); }
.rangee--espacee { justify-content: space-between; }

.invisible {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =====================================================================
   RESPONSIVE
   ---------------------------------------------------------------------
   Vérifié à 1440, 1200, 1024, 834 et 390 px.

   POINT DE REPLI DE L'EN-TÊTE : 1100 px.

   C'est la largeur en dessous de laquelle les cinq rubriques, le logo et
   le bouton de déconnexion ne tiennent plus ensemble sur une ligne sans
   ronger la place des deux noms (établissement et agent). Plutôt que de
   les réduire à trois lettres, la navigation passe ENTIÈRE dans le menu
   repliable : mieux vaut un menu à ouvrir qu'une barre illisible.

   Ce n'est pas un chiffre choisi à l'œil : il est recalculé par
   test_l_entete_ne_deborde_jamais_avec_des_valeurs_longues, qui mesure
   le budget de largeur incompressible de la barre (logo + rubriques +
   bouton + écarts + marges) et vérifie qu'il tient à cette largeur.
   Ajouter une rubrique ou allonger un libellé fait échouer ce test tant
   que le point de repli n'a pas été remonté.
   ===================================================================== */
@media (max-width: 1100px) {
  .entete__interieur { flex-wrap: wrap; }
  .entete__bascule { display: inline-flex; order: 3; }

  /* La navigation bascule en menu repliable, sur sa propre ligne. */
  .entete__navigation {
    flex: 1 1 100%;
    order: 4;
    display: none;
    padding: var(--espace-2) 0 var(--espace-3);
    border-top: 1px solid var(--bordure);
  }
  .entete__navigation[data-ouvert="oui"] { display: block; }
  .entete__liste { flex-direction: column; align-items: stretch; gap: var(--espace-1); }
  .entete__lien { justify-content: flex-start; }

  .entete__marque { order: 1; }
  .entete__agent { order: 2; flex: 0 1 auto; }
}

@media (max-width: 900px) {
  .entete__interieur { padding: var(--espace-2) var(--espace-4); }

  /* Sur tablette, quatre colonnes laissent une carte orpheline en
     deuxième rangée : deux colonnes pleines valent mieux. */
  .grille--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .page { padding: var(--espace-5) var(--espace-4) var(--espace-6); }
  .pied { padding: var(--espace-4); }
  /* Sur un téléphone, la première ligne ne peut porter que trois choses :
     la pastille de marque, la déconnexion et le menu. Le mot
     « Facturation » et le nom de l'agent s'effacent — le premier est
     répété par le titre de la page, le second est connu de qui tient le
     téléphone. L'établissement, lui, ne s'efface PAS : il passe sous le
     logo, en pleine largeur. Une hôtesse ne doit jamais douter de la
     clinique dans laquelle elle saisit. */
  .entete__logo-texte { display: none; }
  .entete__nom { display: none; }
  .entete__marque { flex-wrap: wrap; }
  .entete__etablissement { flex-basis: 100%; }
  .display, .montant-vedette { font-size: var(--taille-titre-1); }
  .grille--2, .grille--3, .grille--4 { grid-template-columns: 1fr; }
  .barre-filtres__groupe { min-width: 100%; }
  .barre-filtres__actions { margin-left: 0; width: 100%; }
  .modale__boite { padding: var(--espace-4); }
}

/* =====================================================================
   MOUVEMENT RÉDUIT
   ---------------------------------------------------------------------
   Durées, délais et transitions neutralisés — pas seulement ralentis.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   IMPRESSION
   ---------------------------------------------------------------------
   C'est cette feuille qui porte les factures papier : noir sur blanc,
   sans habillage, sans ce qui ne sert qu'à l'écran.
   ===================================================================== */
@media print {
  :root {
    --fond: #FFFFFF;
    --surface: #FFFFFF;
    --surface-elevee: #FFFFFF;
    --surface-sourde: #FFFFFF;
    --marque-fond: #FFFFFF;
    --accent-fond: #FFFFFF;
    --texte: #000000;
    --texte-secondaire: #000000;
    --texte-attenue: #000000;
    --marque: #000000;
    --bordure: #767676;
    --bordure-marquee: #000000;
    --ombre-subtile: none;
    --ombre-carte: none;
    --ombre-surelevee: none;
    --ombre-modale: none;
  }

  body {
    background: var(--papier);
    color: var(--encre);
    font-size: 11pt;
    line-height: 1.45;
  }

  /* `.page__messages` est masquée À L'IMPRESSION, et c'est la coque
     commune qui le fait — pas chaque lot qui imprime.

     Le défaut, constaté par le lot « factures » sur une vraie sortie
     papier : la zone des messages est remplie par `flash()`, dont la
     session survit à une redirection interrompue ou à un retour arrière.
     Un « Règlement enregistré. » émis vers un AUTRE écran atterrissait
     ainsi en tête d'une facture définitive partant chez un patient.
     Masquer `.bandeau__fermer` ne suffisait pas : c'est le bandeau
     entier qui n'a rien à faire sur un document comptable.

     Un message de session s'adresse à l'agent devant l'écran, jamais au
     destinataire du papier. La règle vaut donc pour TOUT lot qui
     imprime — factures, journal de caisse, export — et c'est pour cela
     qu'elle est ici. Le lot « factures » l'avait posée chez lui, bornée
     à ses écrans ; sa règle locale a été retirée le 7 août 2026. */
  .entete, .pied, .modale, .barre-actions, .barre-filtres,
  .onglets, .pagination, .bandeau__fermer, .lien-evitement,
  .page__messages,
  .chargement-page, .chargement-zone__indicateur, .infobulle__contenu,
  .ne-pas-imprimer { display: none !important; }

  .page { max-width: none; margin: 0; padding: 0; }

  .carte, .etat-vide {
    border: none;
    box-shadow: none;
    padding: 0;
    margin: 0 0 var(--espace-5);
    break-inside: avoid;
  }
  .carte__icone { display: none; }

  .tableau-cadre { border: none; overflow: visible; max-height: none; }
  .tableau { font-size: 10pt; }
  .tableau thead th {
    position: static;
    background: none;
    color: var(--encre);
    border-bottom: 2px solid var(--encre);
  }
  .tableau tbody tr:nth-child(even),
  .tableau tbody tr:hover { background: none; }
  .tableau th, .tableau td {
    border-bottom: 1px solid var(--filet-imprime);
    padding: var(--espace-1) var(--espace-2);
  }
  .tableau tfoot td, .tableau tfoot th {
    background: none;
    border-top: 2px solid var(--encre);
  }

  .badge {
    background: none !important;
    color: var(--encre) !important;
    border: 1px solid var(--encre);
  }

  a[href]::after { content: ""; }

  .a-imprimer-seulement { display: block !important; }
}

.a-imprimer-seulement { display: none; }
