:root{
  --bg:#11100c; --bg2:#16140f; --panel:#1c1a13; --panel2:#211e16;
  --ink:#f3ecd9; --ink2:#c9c0a8; --muted:#8b8470; --line:#332f24; --line2:#433d2e;
  --gold:#d8a93a; --green:#5fb87a; --amber:#e0a32e; --red:#d65a4a; --blue:#6fa8c7;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 14px 40px rgba(0,0,0,.35);

  /* Compagnons RVB des couleurs ci-dessus. CSS ne sait PAS écrire `rgba(var(--gold), .09)` :
     pour un fond pâle il faut les composantes séparées. Sans eux, les pastilles garderaient la
     teinte de l'ancien thème le jour où l'on change la palette. Tenir chaque paire alignée. */
  --gold-rgb:216,169,58; --green-rgb:95,184,122; --red-rgb:214,90,74;
  --amber-rgb:224,163,46; --muted-rgb:139,132,112; --ink-rgb:243,236,217;
  --blue-rgb:111,168,199;

  /* ─── Couleurs d'INTERFACE, rangées ici le 2026-08-26 (cf. PLAN_couleurs.md) ───────────────
     Elles étaient écrites en dur dans les pages. Nommées PAR RÔLE, jamais par teinte : c'est ce
     qui rend un changement de thème possible — sinon on obtient soixante variables dont personne
     ne sait laquelle sert à quoi. Les valeurs sont IDENTIQUES à ce qui existait : on a déplacé,
     on n'a pas fusionné (deux verts proches restent deux verts, cf. §3 du plan).
     ⚠️ Ne PAS y ajouter les couleurs de GRAPHIQUES (carte, donuts, barres, marqueurs) : ce sont
     des couleurs de données, un rouge de perte reste rouge quel que soit le fond.
     ⚠️ Ni celles des CORPS D'E-MAIL ni des pages autonomes (« Accès refusé », blocage) : elles
     ne voient jamais cette feuille de style. */

  /* états : validé · en attente · alerte · information */
  --etat-ok:#4c9a76;              --etat-ok-fond:rgba(76,154,118,.16);   --etat-ok-fond-2:rgba(76,154,118,.10);
  --etat-attente:#d9a441;         --etat-attente-fond:rgba(217,164,65,.16);
  --etat-attente-fond-2:rgba(217,164,65,.10); --etat-attente-fond-3:rgba(217,164,65,.14);
  --etat-attente-bord:rgba(217,164,65,.5);    --etat-attente-sourd:#b99038;
  --etat-alerte:#e08a7a;          --etat-alerte-fond:rgba(200,90,74,.18);
  --etat-alerte-fond-2:rgba(224,102,102,.14); --etat-alerte-bord:rgba(224,102,102,.45);
  --etat-alerte-vif:#e06666;      --etat-signal:#e0813a;                 --etat-signal-2:#e0a33a;
  --etat-info:#7fa8d8;            --etat-info-fond:rgba(90,140,200,.16); --etat-info-fond-2:rgba(90,140,200,.18);
  --ligne-a-completer:rgba(180,90,40,.12);

  /* écarts chiffrés — ⚠️ DISTINCTS des états : un vert d'état et un vert de hausse sont à ΔE 20 */
  --ecart-hausse:#3fae6b;         --ecart-baisse:#d2674f;

  /* étiquettes de catégorie (fond · encre · bord) */
  --tag-retenu-fond:#1f5c3a;      --tag-retenu-encre:#cfeeda;  --tag-retenu-bord:#2c7a4f;
  --tag-second-fond:#33405a;      --tag-second-encre:#cfddee;  --tag-second-bord:#46587a;
  --tag-ecarte-fond:#5a3a1f;      --tag-ecarte-encre:#eed8cf;  --tag-ecarte-bord:#7a4f2c;
  --tag-danger-fond:#5a2424;      --tag-danger-bord:#7a3030;
  --tag-sourd-fond:#444;          --tag-sourd-fond-2:#555;     --tag-sourd-encre:#bbb;
  --tag-encre-pleine:#fff;        /* texte posé sur une pastille de couleur pleine */

  /* pastilles pleines, une par rôle */
  --plein-info:#3a557a;   --plein-alerte:#7a2b2b;   --plein-conso:#2b5a7a;
  --plein-conquete:#7a5a2b; --plein-actif:#1f5a52;  --plein-vivant:#3f7d5f;

  /* accent doré */
  --accent-bas:#9c7a26;           /* bas du dégradé d'une barre */
  --accent-voile:rgba(217,164,65,.06);
  --accent-encre:#1a1608;         /* texte posé SUR le doré (encre des boutons) */
  --accent-encre-forte:#000;      /* idem, au survol */
  --succes-encre:#0e2a17;         /* texte posé sur le vert plein */

  /* boutons destructeurs */
  --bouton-danger-fond:#c85a4a;   --bouton-danger-bord:#7a3a33;

  /* surfaces */
  --voile-modale:rgba(0,0,0,.6);  --voile-modale-2:rgba(0,0,0,.55);
  --ombre-flottante:rgba(0,0,0,.5);
  --survol-ligne:rgba(255,255,255,.02);  --survol-ligne-2:rgba(255,255,255,.028);
  --survol-ligne-3:rgba(255,255,255,.03);
  --jauge-fond:#2a2620;
  /* barres et jauges — rangées ici le 2026-08-29 avec l'arrivée du thème clair : elles étaient
     en dur dans index.php et budget.php, donc elles seraient restées SOMBRES sur fond blanc. */
  /* ⚠️ Texte posé sur le BOUTON d'accent — distinct de --accent-encre, qui sert au texte posé
     sur une pastille CLAIRE (planning). Les deux rôles ont la même valeur ici parce que l'or du
     thème sombre est clair ; ils DIVERGENT sur fond clair, où l'accent devient foncé et réclame
     du blanc. Séparés le 2026-08-29 : c'est le genre de collision qu'on ne voit qu'en
     transposant un thème, et qui aurait rendu tous les boutons illisibles (contraste 3,1). */
  --bouton-encre:#241f18;
  --barre-vide:#3a3527;           /* sparkline : mois sans activité */
  --plein-auto:#5b4a2b;           /* pastille « blocage automatique » (face à --plein-alerte, manuel).
                                     ⚠️ PAS --tag-ecarte-fond (#5a3a1f) : proche mais pas identique,
                                     et la règle est de déplacer sans fusionner. */
  --barre-budget:#5b6b7a;         /* budget prévu, face au réalisé doré */

  /* congés : présence partielle */
  --presence-partielle:#9dc0a6;   --presence-partielle-fond:rgba(157,192,166,.10);

  /* ─── Palette du PLANNING ───────────────────────────────────────────────────────────────────
     Couleurs des types d'absence et des personnes. Elles vivaient EN BASE en hexadécimal, choisies
     au sélecteur de couleur libre : elles n'auraient donc jamais suivi un changement de thème, et
     rien ne garantissait qu'une couleur saisie reste lisible sur le fond du calendrier.
     Désormais la base stocke une CLÉ (`or`, `brique`…) et l'écran affiche `var(--planning-<clé>)`.
     ⚠️ Seul endroit où l'on nomme par TEINTE et non par rôle, et c'est volontaire : ici la teinte
     EST le rôle — c'est un nuancier proposé à quelqu'un qui distingue des catégories à l'œil.
     ⚠️ Toutes doivent rester assez claires pour porter `--accent-encre` en texte : le calendrier
     écrit le motif d'absence EN SOMBRE sur la pastille. Vérifier avant d'en ajouter une — contraste
     WCAG mesuré, aucune en dessous de 4,5. `--planning-brique` valait `#c85a4a` (4,3, sous le seuil)
     et a été éclairci le 2026-08-26 : c'est la couleur de « Maladie », donc la plus lue de toutes. */
  --planning-or:#d9a441;        --planning-brique:#d97a68;   --planning-bleu:#7fa8d8;
  --planning-gris:#8b8470;      --planning-vert:#6fb98c;     --planning-turquoise:#5fb2ab;
  --planning-mauve:#a893d0;     --planning-rose:#d98fa8;
}
@import url('https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,500;0,600;0,700;0,800;1,500&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap');
*{box-sizing:border-box}
html,body{margin:0}
body{font-family:"IBM Plex Sans",system-ui,sans-serif;color:var(--ink);background:var(--bg);
  background-image:radial-gradient(circle at 12% -5%,rgba(var(--gold-rgb),.07),transparent 45%),radial-gradient(circle at 95% 110%,rgba(var(--blue-rgb),.05),transparent 40%);min-height:100vh}
.mono{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums}
a{color:var(--gold);text-decoration:none}
/* nav */
.nav{display:flex;align-items:center;justify-content:space-between;padding:16px 30px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,var(--bg2),transparent)}
.nav .brand{font-family:"Spectral",serif;font-weight:700;font-size:17px;letter-spacing:.01em}
.nav .mark{color:var(--gold)}
.nav .links{display:flex;align-items:center;flex-wrap:wrap;row-gap:6px}
.nav .links a{margin-left:22px;color:var(--ink2);font-weight:600;font-size:14px;padding-bottom:3px}
.nav .links a.on{color:var(--ink);border-bottom:2px solid var(--gold)}
/* Bouton d'ouverture du menu — MASQUÉ par défaut, révélé par le bloc « menu replié » plus bas.
   ⚠️ C'est un <button> : il hérite donc du style doré des boutons de formulaire, qu'il faut
   neutraliser ici (fond, encre, graisse), sinon un gros pavé doré s'installe dans la barre.
   44 px de côté = la cible tactile minimale recommandée par Apple. */
.nav .navtoggle{display:none;align-items:center;gap:8px;margin-left:auto;
  background:transparent;color:var(--ink2);border:1px solid var(--line2);border-radius:10px;
  font-size:14px;font-weight:600;padding:0 14px;min-height:44px;cursor:pointer}
.nav .navtoggle .barres{display:inline-block;width:18px;height:2px;background:currentColor;
  position:relative}
.nav .navtoggle .barres::before,.nav .navtoggle .barres::after{content:"";position:absolute;
  left:0;width:18px;height:2px;background:currentColor}
.nav .navtoggle .barres::before{top:-6px} .nav .navtoggle .barres::after{top:6px}
.nav.ouvert .navtoggle{color:var(--ink);border-color:var(--gold)}
/* sous-menu déroulant (Configuration) */
.nav .dd{position:relative;display:inline-block;margin-left:22px}
.nav .dd>.ddlabel{color:var(--ink2);font-weight:600;font-size:14px;cursor:default;padding-bottom:3px}
.nav .dd:hover>.ddlabel{color:var(--ink)}
.nav .dd.on>.ddlabel{color:var(--ink);border-bottom:2px solid var(--gold)}
.nav .dd .menu{position:absolute;right:0;top:100%;padding-top:10px;min-width:190px;display:none;z-index:60}
.nav .dd:hover .menu{display:block}
.nav .dd .menu .inner{background:var(--panel);border:1px solid var(--line2);border-radius:10px;box-shadow:var(--shadow);padding:6px}
.nav .dd .menu a{display:block;margin:0;padding:8px 12px;border-radius:7px;white-space:nowrap;color:var(--ink2);font-weight:600;font-size:14px}
.nav .dd .menu a:hover{background:var(--panel2);color:var(--ink)}
.nav .dd .menu a.on{color:var(--ink);border:0;background:var(--panel2)}
/* Sous-menu de 2e niveau (ex. « Noah ▸ ») — s'ouvre au SURVOL, comme le menu Configuration.
   Panneau FLOTTANT déployé vers la GAUCHE (le menu parent étant calé à droite de l'écran) : il se
   superpose au fond de page, jamais aux entrées voisines, qui restent donc toutes lisibles.
   `padding-right` sert de passerelle : la souris peut aller du libellé au panneau sans le refermer. */
.nav .dd .menu .sub{position:relative}
.nav .dd .menu .sub>.sublabel{display:flex;justify-content:space-between;gap:14px;padding:8px 12px;border-radius:7px;white-space:nowrap;color:var(--ink2);font-weight:600;font-size:14px;cursor:default}
.nav .dd .menu .sub:hover>.sublabel{background:var(--panel2);color:var(--ink)}
.nav .dd .menu .sub.on>.sublabel{color:var(--ink);background:var(--panel2)}
.nav .dd .menu .sub>.sublabel .chev{font-size:11px;opacity:.7}
.nav .dd .menu .sub .submenu{position:absolute;right:100%;top:-6px;padding-right:10px;display:none;z-index:70}
.nav .dd .menu .sub:hover .submenu{display:block}
.nav .dd .menu .sub .submenu .inner2{background:var(--panel);border:1px solid var(--line2);border-radius:10px;box-shadow:var(--shadow);padding:6px;min-width:215px}
.wrap{max-width:1320px;margin:0 auto;padding:26px 30px 70px}
h1{font-family:"Spectral",serif;font-weight:800;font-size:30px;margin:6px 0 6px}
h2{font-family:"Spectral",serif;font-weight:700;font-size:19px;margin:0 0 14px;display:flex;gap:12px;align-items:baseline}
h2 small{font-family:"IBM Plex Sans";font-size:12px;font-weight:500;color:var(--muted)}
.lede{color:var(--ink2);max-width:760px;line-height:1.55;margin:0 0 22px}
.muted{color:var(--muted)} code{font-family:"IBM Plex Mono";background:var(--panel2);padding:1px 6px;border-radius:5px;font-size:.9em;color:var(--ink2)}
/* flash */
.flash{padding:13px 16px;border-radius:11px;margin:0 0 20px;font-size:14px;border:1px solid var(--line2)}
.flash.ok{background:rgba(var(--green-rgb),.1);border-color:rgba(var(--green-rgb),.4)}
.flash.err{background:rgba(var(--red-rgb),.1);border-color:rgba(var(--red-rgb),.45)}
/* cards / upload */
.card{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:22px;margin:0 0 20px;box-shadow:var(--shadow)}
.card h2{font-size:16px}
.upload{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
.drop{position:relative;flex:1;min-width:260px;border:1px dashed var(--line2);border-radius:12px;padding:22px;text-align:center;color:var(--ink2);cursor:pointer;font-weight:600}
.drop:hover{border-color:var(--gold);color:var(--ink)}
.drop input{position:absolute;inset:0;opacity:0;cursor:pointer}
button{font:inherit;font-weight:700;font-size:14px;background:var(--gold);color:var(--bouton-encre);border:none;padding:13px 26px;border-radius:11px;cursor:pointer}
button:hover{filter:brightness(1.08)}
/* topbar / filter */
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;flex-wrap:wrap;gap:14px}
.filterform{display:flex;gap:20px;align-items:center;flex-wrap:wrap}
select{font:inherit;font-weight:600;font-size:13px;background:var(--panel);color:var(--ink);border:1px solid var(--line2);border-radius:10px;padding:9px 12px}
.period{color:var(--muted);font-size:13px}
/* band */
.band{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:26px}
.band.band5{grid-template-columns:repeat(5,1fr)}
/* band6 : 2 groupes de 3 KPIs cote a cote (primo / renouvellement sur la fiche prescripteur).
   A 1100px on passe a 3 colonnes, ce qui garde chaque groupe sur sa propre ligne. */
.band.band6{grid-template-columns:repeat(6,1fr)}
@media(max-width:1100px){.band.band6{grid-template-columns:repeat(3,1fr)}}
@media(max-width:900px){.band{grid-template-columns:repeat(2,1fr)}.band.band5{grid-template-columns:repeat(2,1fr)}}
.kpi{background:linear-gradient(165deg,var(--panel2),var(--panel));border:1px solid var(--line);border-radius:16px;padding:18px 20px;position:relative;overflow:hidden;box-shadow:var(--shadow)}
.kpi::after{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--gold);opacity:.7}
.kpi.red::after{background:var(--red)}.kpi.green::after{background:var(--green)}.kpi.amber::after{background:var(--amber)}
.kpi .lab{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.kpi .val{font-family:"Spectral",serif;font-weight:700;font-size:28px;margin:8px 0 2px;line-height:1}
.kpi .sub{font-size:12.5px;color:var(--ink2)}
/* sections */
.sec{margin-bottom:32px}
.up{color:var(--green)}.down{color:var(--red)}.flat{color:var(--muted)}
/* alerts */
.alert{display:flex;gap:14px;align-items:center;background:var(--panel);border:1px solid var(--line);border-left-width:4px;border-radius:12px;padding:13px 16px;margin-bottom:9px}
.alert.red{border-left-color:var(--red)}.alert.amber{border-left-color:var(--amber)}
.alert .dot{width:9px;height:9px;border-radius:50%;flex:none}
.alert.red .dot{background:var(--red)}.alert.amber .dot{background:var(--amber)}
.alert .abody{flex:1}
.alert .who{font-weight:700;font-size:14px}
.alert .who .tag{font-weight:600;font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);border:1px solid var(--line2);border-radius:999px;padding:1px 8px;margin-left:8px}
.alert .what{font-size:12.5px;color:var(--ink2);margin-top:3px;line-height:1.45}
.alert .what b{color:var(--ink)}
.alert .aside{text-align:right;font-family:"IBM Plex Mono";font-size:13px;color:var(--ink2);white-space:nowrap}
.alert .aside .spk{display:block;margin-top:4px}
/* table */
.tablewrap{background:var(--panel);border:1px solid var(--line);border-radius:16px;overflow:auto;box-shadow:var(--shadow);-webkit-overflow-scrolling:touch}
table{width:100%;border-collapse:collapse;font-size:13px}
thead th{background:var(--bg2);text-align:right;padding:11px 12px;font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);font-weight:600;white-space:nowrap;border-bottom:1px solid var(--line2)}
thead th:first-child{text-align:left}
thead th a{color:inherit}thead th.sorted{color:var(--gold)}thead th:hover a{color:var(--ink)}
tbody td{padding:10px 12px;text-align:right;border-bottom:1px solid var(--line);white-space:nowrap}
tbody td.name{text-align:left;font-weight:600}
tbody tr:hover{background:var(--panel2)}
tbody tr:last-child td{border-bottom:none}
/* pied de tableau : mêmes padding/alignement que le corps (sinon les totaux apparaissent décalés à gauche) */
tfoot td{padding:10px 12px;text-align:right;white-space:nowrap}
tfoot td:first-child{text-align:left}
.spk{text-align:center}
.flag{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:9px;vertical-align:middle}
.flag.green{background:var(--green)}.flag.amber{background:var(--amber)}.flag.red{background:var(--red)}
.note{font-size:11.5px;color:var(--muted);margin-top:12px;line-height:1.55}
.empty{text-align:center;padding:80px 20px;color:var(--muted)}
.empty .big{font-family:"Spectral",serif;font-size:24px;color:var(--ink);margin-bottom:8px}
.check{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--ink2);cursor:pointer;width:100%;margin-top:4px}
.check input{width:16px;height:16px;accent-color:var(--gold)}
.btnlink{display:inline-block;font-weight:700;font-size:13px;background:var(--gold);color:var(--bouton-encre);padding:11px 18px;border-radius:11px;text-decoration:none;margin-top:6px}
.btnlink:hover{filter:brightness(1.08)}
h3{font-family:"IBM Plex Sans",sans-serif}

/* ============ GRAND ÉCRAN ============ */
/* Au-delà de ~1460 px, on laisse le contenu occuper la largeur disponible : les tables larges
   (Suivi patients, Essais, CA…) débordaient dans .tablewrap et imposaient un défilement
   horizontal alors que l'écran avait de la place inutilisée de chaque côté.
   Plafonné à 2000 px : au-delà, s'étaler encore rendrait les lignes de tableau illisibles
   (l'œil perd la ligne en balayant). En dessous du seuil, rien ne change. */
@media(min-width:1460px){
  .wrap{max-width:min(2000px, calc(100vw - 96px))}
  /* les blocs de texte, eux, gardent une longueur de ligne lisible */
  .note, .flash{max-width:1100px}
}

/* ============ RESPONSIVE (tablette / mobile) ============ */
/* tablette : on resserre la nav et les marges */
@media(max-width:1024px){
  .wrap{padding:24px 20px 60px}
  .nav{padding:14px 20px}
  .nav .links a, .nav .dd{margin-left:16px}
}
/* ============ MENU REPLIÉ DERRIÈRE UN BOUTON ============
   Ajouté le 2026-08-30. La barre empilée mesurait 289 px — 30 % du premier écran d'un iPhone,
   sur CHAQUE page : on voyait le menu, le titre, les filtres, et deux KPI. Repliée, elle tient
   en une ligne et rend ces 240 px au contenu.

   ⚠️ LE SEUIL N'EST PLUS 760 px, ET CE N'EST PAS UN DÉTAIL. À 744 px (iPad mini en portrait)
      l'ancienne règle servait le menu d'un TÉLÉPHONE à une tablette : 289 px au lieu des 117 px
      que prend le menu horizontal, mesurés à cette largeur et sans débordement. Le repli s'arrête
      donc à 700 px.
   ⚠️ La seconde condition rattrape les téléphones EN PAYSAGE (jusqu'à 956 px de large, mais
      seulement 390 à 440 px de haut) : sans elle, un menu horizontal de 117 px mangerait 30 % de
      leur hauteur. Aucun iPad n'y tombe — le moins haut fait 744 px en paysage.

   ⚠️ LE SEUIL EST ÉCRIT ICI, UNE SEULE FOIS. Le script de _nav.php ne le redéclare pas : il lit
      --menu-replie ci-dessous. Une seconde copie en JavaScript aurait divergé au premier
      ajustement, et c'est le menu qui aurait cessé de s'ouvrir — sans rien dans le journal.
      (Même leçon que les deux catalogues de pages, cf. CLAUDE.md §7.) */
@media (max-width:700px), (max-width:1024px) and (max-height:500px){
  :root{ --menu-replie:1; }              /* lu par le script de _nav.php — ne pas retirer */

  /* la barre reste sur une ligne : marque à gauche, bouton à droite, liens en dessous si ouverts */
  .nav{flex-wrap:wrap;align-items:center;gap:8px;padding:12px 16px}
  .nav .navtoggle{display:inline-flex}
  .nav .links{display:none;order:3;width:100%;gap:6px 16px}
  .nav.ouvert .links{display:flex}

  .nav .links a{margin-left:0}
  .nav .dd{margin-left:0;width:100%}
  .nav .dd>.ddlabel{display:inline-block;margin-top:4px;border-bottom:1px solid var(--line2);padding-bottom:4px;width:100%}
  /* Tactile : le survol n'existe pas. Plutôt que de tout déplier (le menu occupait alors trois
     écrans sur un iPhone), Configuration et son sous-menu Noah sont REPLIÉS et s'ouvrent au
     toucher (classe .open posée par le script de _nav.php, qui déplie aussi d'office la section
     contenant la page courante). */
  .nav .dd .menu{position:static;display:none;padding-top:6px;min-width:0}
  .nav .dd.open>.menu{display:block}
  .nav .dd>.ddlabel{cursor:pointer;-webkit-user-select:none;user-select:none}
  .nav .dd .menu .inner{background:transparent;border:0;box-shadow:none;padding:0;display:flex;flex-wrap:wrap;gap:6px 16px}
  .nav .dd .menu a{padding:0;font-size:14px}
  .nav .dd .menu .sub{width:100%;position:static}
  /* les noms de groupe passent en casse normale, comme les en-têtes de tableau : à 11 px en
     capitales interlettrées, ils étaient le plus petit texte du menu (cf. bloc de lisibilité) */
  .nav .dd .menu .sub>.sublabel{display:inline-block;padding:0;font-size:12.5px;text-transform:none;letter-spacing:normal;color:var(--muted);background:none;cursor:pointer;-webkit-user-select:none;user-select:none}
  .nav .dd .menu .sub>.sublabel .chev{display:inline-block;transition:transform .15s}
  .nav .dd .menu .sub.open>.sublabel .chev{transform:rotate(90deg)}
  .nav .dd .menu .sub .submenu{position:static;display:none;padding:0}
  .nav .dd .menu .sub.open>.submenu{display:block}
  .nav .dd .menu .sub .submenu .inner2{background:transparent;border:0;box-shadow:none;padding:0;min-width:0;display:flex;flex-wrap:wrap;gap:6px 16px}
}

/* contenu fluide — ⚠️ SEUIL DISTINCT de celui du menu ci-dessus (700 px) : ces règles-ci
   concernent la mise en page, et l'iPad mini en portrait (744 px) a bien besoin de marges
   resserrées et de filtres empilés, même s'il garde un menu de tablette. */
@media(max-width:760px){
  .wrap{padding:18px 14px 50px}
  h1{font-size:24px}
  h2{font-size:17px}
  .lede{font-size:14px}
  .card{padding:16px}
  .kpi{padding:14px 15px}
  .kpi .val{font-size:23px}
  .band{gap:10px}

  /* filtres : empilés et pleine largeur (faciles à toucher) */
  .topbar{gap:10px}
  .filterform{flex-direction:column;align-items:stretch;gap:10px;width:100%}
  .filterform label{display:flex;flex-direction:column;gap:4px}
  .filterform select{width:100%}

  /* alertes : le montant passe en dessous */
  .alert{flex-wrap:wrap}
  .alert .aside{text-align:left;width:100%;margin-top:4px}
}
/* Téléphones : DEUX colonnes de KPI, pas une.
   ⚠️ Le seuil était à 440 px — soit EXACTEMENT la largeur d'un iPhone 16 Pro Max. Une colonne
   unique s'appliquait donc à TOUS les iPhone, du SE (375) au plus grand, alors que le nombre le
   plus large de toute l'application mesure 115 px (« 5 200 492 € », mesuré le 2026-08-30) : il
   restait plus de 200 px de vide à droite de chaque chiffre, et six KPI faisaient 600 px de
   défilement au lieu de 300.
   Deux colonnes offrent 138 px utiles dès 375 px — le nombre tient partout. Seule la ligne de
   commentaire (« au 29/08/2026 · mois en cours », 218 px) se replie sur deux lignes : elle est
   faite pour ça, contrairement au chiffre. */
@media(max-width:560px){
  .band, .band.band5, .band.band6{grid-template-columns:1fr 1fr}
}
@media(max-width:440px){
  h1{font-size:22px}
}
/* En dessous de 360 px (iPhone SE 1ʳᵉ génération et antérieurs), deux colonnes ne laisseraient
   que 111 px : moins que le nombre. On revient à une colonne — le seul cas où elle se justifie. */
@media(max-width:360px){
  .band, .band.band5, .band.band6{grid-template-columns:1fr}
}

/* ============ LISIBILITÉ SUR PETIT ÉCRAN (téléphone + iPad portrait) ============
   Ajouté le 2026-08-30. Motif : la majorité des utilisateurs a 50 ans ou plus, et l'application
   plaçait ses plus petits caractères EXACTEMENT là où se trouve le sens — l'en-tête qui nomme la
   colonne (10,5 px), le libellé qui dit ce que le nombre signifie (11 px), la note qui avertit
   (11,5 px). Les deux plus petits étaient en MAJUSCULES avec interlettrage, la combinaison la plus
   coûteuse à lire de près : les capitales effacent la silhouette du mot.

   ⚠️ LE CONTRASTE N'EST PAS EN CAUSE — vérifié le 2026-08-30, les six rôles de texte passent AA
      dans les deux thèmes, et le corps de tableau est à 14,8 (sombre) / 16,4 (clair), donc AAA.
      Ne pas « corriger » les couleurs en croyant aider : c'est la TAILLE qu'il faut reprendre.
      Seul --muted, qui porte les petits textes, monte au niveau AAA (7:1) ci-dessous.

   ⚠️ RIEN DE TOUT CECI NE TOUCHE LE GRAND ÉCRAN (décision du DG : « sur ordi c'est très bien »).
      D'où le plafond à 1024 px, qui couvre les téléphones et l'iPad en portrait, et s'arrête avant
      l'iPad en paysage. Recette : empreinte de mise en page comparée avant/après à 1400 px.

   ⚠️ Le prix est mesuré, pas supposé : le tableau de bord passe de 1151 à 1237 px de large (+7,5 %)
      et de 9392 à 10280 px de haut (+9 %). C'est le coût assumé de la lisibilité — et il est plus
      que compensé par la colonne collante ci-dessous. */
@media(max-width:1024px){
  /* --muted porte les en-têtes, les libellés et les notes : il passe de AA (4,67) à AAA (7,08).
     La valeur du thème clair vit dans styles-clair.css, qui est chargé APRÈS celle-ci. */
  :root{ --muted:#aaa597;
         --liste-courte:1; }   /* lu par le script de _nav.php — ne pas retirer */

  /* tableaux : le corps grandit, l'en-tête cesse de crier en capitales */
  table{font-size:14.5px}
  thead th{font-size:12px;text-transform:none;letter-spacing:normal;padding:12px}
  tbody td, tfoot td{padding:12px}

  /* KPI : le libellé DIT ce qu'est le nombre — il ne peut pas être le plus petit texte de l'écran */
  .kpi .lab{font-size:12.5px;text-transform:none;letter-spacing:normal}
  .kpi .sub{font-size:13.5px}

  /* textes explicatifs */
  .note{font-size:13px}
  .alert .who{font-size:15px}
  .alert .what{font-size:13.5px}
  .alert .who .tag{font-size:11.5px}   /* reste en capitales : ce sont des sigles (ORL, CSS…) */
  .alert .aside{font-size:14px}
  .period, .lede{font-size:14px}
  h2 small{font-size:13px}

  /* ⚠️ CHAMPS DE SAISIE À 16 px — ce n'est PAS qu'un confort de lecture : en dessous de 16 px,
     Safari sur iPhone AGRANDIT la page dès qu'on touche un champ, et NE LA REMET PAS ensuite.
     Il fallait repincer à chaque fois. Un seul réglage, deux problèmes réglés.
     Mesuré avant : 120 champs de saisie dans l'application, UN SEUL déclarait une taille. */
  select, input, textarea, button, .btnlink{font-size:16px}
  /* ⚠️ …ET IL FAUT L'IMPOSER. Relevé le 2026-08-30 sur les 41 pages : **436 champs restaient sous
     16 px**, donc Safari continuait d'agrandir la page à chaque toucher. La règle ci-dessus est en
     effet battue soit par un `style=` en ligne (demande_avis_config, avis_envois), soit par une
     règle de page PLUS SPÉCIFIQUE (`.exform select` d'essais.php, `.rowform input` de
     notoriete_admin.php) — la spécificité seule ne peut pas gagner contre une classe. */
  select, input, textarea{font-size:16px !important}
  /* Seule exception : les GRILLES DENSES de saisie du budget, où des champs de 56 à 82 px de large
     ne peuvent pas porter 16 px sans se disloquer. On y accepte le zoom de Safari : saisir 216
     montants mensuels ne se fait pas depuis un téléphone.
     ⚠️ Classe explicite plutôt que `.grid input` : `.grid` sert aussi à une mise en page sans
     champs dans suivi_patients.php — ça marcherait par coïncidence, pas par intention. */
  .grille-dense input{font-size:12px !important}
  /* ⚠️ ET bornés à la largeur disponible. Un <select> prend par défaut la largeur de sa plus
     longue option : en passant de 13 à 16 px, celui de panneaux.php est passé à 447 px et faisait
     DÉBORDER la page entière (défilement horizontal sur toute la hauteur, pour un seul champ).
     C'est l'effet de bord à surveiller quand on agrandit une police : ce ne sont pas les blocs de
     texte qui cassent, ce sont les champs dont la largeur est dictée par leur contenu. */
  select, input, textarea{max-width:100%}
  /* ⚠️ …et `max-width:100%` NE SUFFIT PAS quand le champ est dans un <label> placé en élément
     FLEX : le minimum automatique d'un élément flex vaut la largeur minimale de son CONTENU, donc
     celle du menu déroulant. Le label refuse alors de rétrécir et pousse la page hors de l'écran,
     le `max-width:100%` du champ se calculant sur ce label déjà trop large. `min-width:0` lève ce
     minimum. Sans effet sur un label en flux normal, dont la largeur vient déjà du parent. */
  label{min-width:0}
  .check{font-size:15px}

  /* zones tactiles : Apple recommande 44 px, un tiers d'entre elles étaient en dessous */
  .check input{width:22px;height:22px}
  button, .btnlink{min-height:44px;padding:12px 22px}
  .nav .links a{padding:5px 0}
}

/* ============ TABLEAUX LARGES : LE LIBELLÉ RESTE VISIBLE ============
   Ajouté le 2026-08-30, sur les quatre tableaux les plus larges (classe `collant`, posée à la
   main : ce n'est PAS une règle générale, cf. l'avertissement plus bas).

   Le problème mesuré : le tableau de bord fait 1151 px dans une fenêtre de 410, et sa seule
   colonne « Prescripteur » en occupe 326. On voyait donc un nom et rien d'autre ; en faisant
   glisser vers la droite pour atteindre les chiffres, le nom disparaissait — on lisait des
   montants sans savoir de qui. Avec la colonne collante : 1037 px, le nom TOUJOURS là, et 210 px
   de chiffres à côté, soit deux colonnes lisibles d'un coup.

   ⚠️ Ça sert aussi sur TABLETTE, ce n'est pas un correctif « téléphone » : l'iPad en portrait
      n'affiche que 68 % de ce tableau (820 px). D'où le plafond à 1024 px.

   ⚠️ POURQUOI PAS SUR TOUS LES TABLEAUX : la première cellule ne contient pas qu'un libellé. Sur
      index.php elle porte aussi le badge « ORL », ailleurs des liens ou des pastilles. Une règle
      posée partout couperait ces informations à 150 px. Chaque tableau doit être regardé avant
      d'ajouter la classe.

   ⚠️ LE FOND EST OBLIGATOIRE sur une cellule collante : sans lui, les colonnes qui défilent
      passent EN TRANSPARENCE dessous et les deux textes se superposent. Le survol de ligne doit
      être répété pour la même raison (il est posé sur <tr>, qui ne peint pas la cellule collante).

   ⚠️ L'EN-TÊTE N'EST PAS COLLANT, et ce n'est pas un oubli : `position:sticky` se cale sur le plus
      proche conteneur de défilement, or .tablewrap en est un (overflow:auto, indispensable au
      défilement horizontal). L'en-tête se figerait donc en haut d'un cadre qui défile lui-même
      avec la page — c'est-à-dire nulle part. Le rendre vraiment collant imposerait de plafonner
      la hauteur du cadre, donc d'imbriquer deux zones de défilement : sur écran tactile c'est un
      piège, on reste coincé dans l'une ou dans l'autre. Écarté volontairement. */
@media(max-width:1024px){
  .tablewrap.collant thead th:first-child,
  .tablewrap.collant tbody td:first-child,
  .tablewrap.collant tfoot td:first-child{
    position:sticky; left:0; z-index:2;
    /* ⚠️ Largeur ADAPTATIVE, pas figée à 150 px : la colonne collante sert aussi à des tableaux
       dont le premier champ est court (une date, un code INNO, un mois). Un 150 px imposé y
       gaspillait la moitié de l'écran. Bornée en bas pour rester lisible, en haut pour laisser
       de la place aux chiffres. */
    min-width:92px; max-width:150px;
    white-space:normal; overflow-wrap:break-word;
    box-shadow:1px 0 0 var(--line2);
  }
  /* le nom se REPLIE plutôt qu'il ne se tronque : à 150 px seulement 42 % des noms tiennent sur
     une ligne (nom médian 133 px, le plus long 246). Un nom complet sur deux lignes se lit ;
     un nom coupé se devine. Le prix est une hauteur de ligne irrégulière — assumé. */
  .tablewrap.collant thead th:first-child{background:var(--bg2); z-index:3}
  .tablewrap.collant tbody td:first-child{background:var(--panel)}
  .tablewrap.collant tbody tr:hover td:first-child{background:var(--panel2)}
  .tablewrap.collant tfoot td:first-child{background:var(--panel)}

  /* ⚠️ La ligne « voir plus » (posée par le script de _nav.php) NE DOIT PAS être collante :
     sa cellule unique hériterait des 150 px et du fond de la colonne de libellés, et le bouton
     se retrouverait coincé dans une colonne étroite au lieu de traverser le tableau. */
  .tablewrap.collant tbody tr.voirplus td{position:static;width:auto;min-width:0;max-width:none;
    box-shadow:none;background:transparent;text-align:center}
}

/* ⚠️ La cellule de libellé empilait quatre choses (pastille, nom sur deux lignes, badge, bouton
   d'administration) : les lignes du tableau de bord faisaient 103 px là où les autres tables du
   site en font 42, soit 25 écrans de défilement pour 197 prescripteurs. Sur téléphone, le bouton
   « ± ORL » n'a pas sa place — c'est un geste de classement, qui se fait depuis Classement ORL —
   et le badge suffit à dire ce qu'il dirait. Il reste entier sur tablette et sur ordinateur.
   ⚠️ `!important` OBLIGATOIRE : ce formulaire porte `style="display:inline"` écrit dans la page, et
   un style en ligne bat toute règle de feuille. C'est la TROISIÈME fois dans ce chantier (après les
   grilles de KPI et les blocs à deux colonnes) — devant une règle qui « ne s'applique pas » alors
   qu'elle est bien chargée et active, regarder l'attribut `style=` de l'élément AVANT tout le reste. */
@media(max-width:760px){
  .tablewrap.collant tbody td:first-child form{display:none !important}
}

/* ============ BLOCS DISPOSÉS EN COLONNES PAR LA PAGE ============
   Certains blocs (deux tableaux côte à côte, un formulaire sur quatre champs) reçoivent leur
   grille d'un `style=` écrit dans la page, parce que la disposition n'a de sens que là.
   ⚠️ UN STYLE EN LIGNE BAT TOUTES LES REQUÊTES MÉDIA : ces blocs restaient donc à quatre colonnes
      sur un téléphone. D'où le `!important`, seul moyen de reprendre la main — c'est déjà la
      technique employée par .presc-cols, .ca-cols et .appair, restées dans leurs pages ; les
      rassembler ici le jour où on y touchera.
   La disposition du grand écran reste dans la page : cette classe ne décrit QUE le repli. */
/* ⚠️ `minmax(0,1fr)` ET NON `1fr` : un `1fr` vaut `minmax(auto,1fr)`, dont le minimum est la
   LARGEUR MINIMALE DU CONTENU. Quand la colonne contient un tableau (cellules en `nowrap`), elle
   refuse donc de descendre sous cette largeur et déborde de la page au lieu de se replier.
   Constaté sur audios.php : bloc de 606 px dans une fenêtre de 390, la page défilait
   horizontalement. `minmax(0,…)` autorise la colonne à rétrécir, le tableau reprend son propre
   défilement dans son cadre — qui est fait pour ça. */
@media(max-width:760px){
  .repli-mobile{grid-template-columns:minmax(0,1fr) !important}
  /* ⚠️ Et les enfants qui réclament DEUX colonnes (`grid-column:span 2`, écrit en ligne dans
     securite.php et panneaux.php) doivent lâcher prise : sur une grille à une seule colonne, un
     `span 2` fait naître une SECONDE colonne implicite, et l'on se retrouve avec deux champs de
     137 px côte à côte — exactement ce qu'on cherchait à supprimer. Le repli n'a donc pas l'air
     de fonctionner alors que la règle ci-dessus s'applique bien. */
  .repli-mobile > *{grid-column:auto !important}
}
@media(min-width:761px) and (max-width:1024px){
  .repli-mobile{grid-template-columns:minmax(0,1fr) minmax(0,1fr) !important}
}

/* ============ UN TABLEAU DEVENU LISTE DE FICHES (petit écran) ============
   Ajouté le 2026-08-30 pour `utilisateurs.php`, marqué par la classe `fiches` sur le `.tablewrap`.

   ⚠️ C'EST L'EXCEPTION, PAS LA RÈGLE. Partout ailleurs on garde le tableau et son défilement
      horizontal : transformer vingt pages en fiches coûterait deux présentations à entretenir par
      tableau. Ici la table a NEUF colonnes pour NEUF comptes, dont deux ne contiennent que des
      boutons — 1204 px de large dans 326, et des lignes de 225 px. Le tableau n'était plus la
      bonne forme pour cette page-là.

   ⚠️ ET LA FICHE NAÏVE EST PIRE QUE LE TABLEAU : mesurée à 574 px par compte, soit 10,6 écrans
      contre 6,6. C'est le REPLI qui fait le gain — une ligne par compte (nom · rôle · état), le
      détail au toucher : 64 px fermée, 0,7 écran pour les neuf comptes, et plus rien à faire
      glisser latéralement. Ne pas déplier tout par défaut en croyant simplifier.

   L'en-tête de fiche est rendu par le PHP (identité + état), pas recomposé en JavaScript à partir
   des autres cellules : le script se contente d'ouvrir et de fermer. */

/* Sur grand écran, rien de tout ceci n'existe : la cellule d'en-tête et le bouton sont retirés.
   ⚠️ Ces deux lignes doivent rester AVANT la requête média, sinon elles l'annuleraient. */
.tablewrap.fiches td.tete{display:none}
.repliable > .deplier{display:none}

@media(max-width:760px){
  .tablewrap.fiches{overflow:visible;background:transparent;border:0;box-shadow:none}
  .tablewrap.fiches table,.tablewrap.fiches tbody,.tablewrap.fiches tr,.tablewrap.fiches td{display:block;width:auto}
  .tablewrap.fiches thead{display:none}
  .tablewrap.fiches tr{background:var(--panel);border:1px solid var(--line);border-radius:14px;
    margin:0 0 9px;box-shadow:var(--shadow);overflow:hidden}

  /* le détail est replié tant qu'on n'a pas touché l'en-tête */
  .tablewrap.fiches td{display:none}
  .tablewrap.fiches tr.ouvert td{display:grid;grid-template-columns:96px 1fr;gap:8px;
    align-items:baseline;text-align:left;white-space:normal;max-width:none;
    border-top:1px solid var(--line);padding:7px 14px;font-size:13.5px}
  .tablewrap.fiches tr.ouvert td::before{content:attr(data-lib);color:var(--muted);font-size:12px}
  /* une cellule sans libellé (les actions) prend toute la largeur */
  .tablewrap.fiches tr.ouvert td:not([data-lib]){grid-template-columns:1fr}
  .tablewrap.fiches tr.ouvert td:not([data-lib])::before{content:none}
  /* une cellule dont le contenu est DÉJÀ dans l'en-tête de la fiche : on ne le répète pas */
  .tablewrap.fiches tr.ouvert td.dans-tete{display:none}

  /* en-tête : TOUJOURS visible, c'est lui le bouton d'ouverture.
     ⚠️ Déclaré après la règle ci-dessus, sinon `tr.ouvert td{display:grid}` le reprendrait. */
  .tablewrap.fiches td.tete,
  .tablewrap.fiches tr.ouvert td.tete{display:block;padding:0;border-top:0}
  /* ⚠️ C'est un <button> : il faut annuler le fond doré des boutons de formulaire. */
  .fiche-tete{position:relative;display:flex;flex-wrap:wrap;align-items:baseline;gap:3px 9px;width:100%;
    background:transparent;color:var(--ink);border:0;border-radius:0;box-shadow:none;
    padding:13px 34px 13px 14px;font-weight:700;font-size:15px;text-align:left;min-height:0;cursor:pointer}
  .fiche-tete .quoi{font-weight:400;font-size:12.5px;color:var(--muted)}
  /* ⚠️ Le chevron est SORTI DU FLUX : en simple `margin-left:auto` il passait à la ligne dès que le
     nom et le rôle remplissaient la première, et se retrouvait seul sur une deuxième ligne. */
  .fiche-tete .chev{position:absolute;right:14px;top:14px;color:var(--muted);transition:transform .15s}
  .tablewrap.fiches tr.ouvert .fiche-tete .chev{transform:rotate(180deg)}

  /* dernière cellule : les boutons d'action se suivent et reviennent à la ligne */
  .tablewrap.fiches tr.ouvert td:last-child{display:flex;flex-wrap:wrap;gap:7px;justify-content:flex-start}
  .tablewrap.fiches tr.ouvert td:last-child button,
  .tablewrap.fiches tr.ouvert td:last-child .btnlink{min-height:38px;padding:8px 12px;font-size:13px}

  /* carte repliée (le formulaire de création) */
  .repliable > .deplier{display:inline-flex;align-items:center;gap:6px}
  .repliable > .corps{display:none}
  .repliable.ouvert > .corps{display:block}
  .repliable.ouvert > .deplier{display:none}
}
