  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  /* ── Écran de chargement (anti page-blanche au boot) ──────────────────────
     Visible par défaut (présent dans le HTML) → s'affiche AVANT le JS, le temps
     que les scripts se parsent et que l'auth se résolve. Masqué par auth.js dès
     que l'écran de connexion ou l'app est rendu. Couleurs = tokens tenant +
     dark mode ; @media prefers-color-scheme pour le tout 1er paint (avant que
     html[data-theme] ne soit posé). Failsafe : disparaît seul après 20 s si le
     JS ne le masquait pas (jamais d'écran de chargement figé). */
  #app-loading {
    position: fixed; inset: 0; z-index: 100001;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg, #eef4f8);
    animation: app-loading-failsafe 0s linear 20s forwards;
    flex-direction: column; gap: 18px;   /* message + « Réessayer » du chien de garde (js/chat-boot.js) */
  }
  @media (prefers-color-scheme: dark) { #app-loading { background: #11161f; } }
  html[data-theme="dark"]  #app-loading { background: var(--bg); }
  html[data-theme="light"] #app-loading { background: var(--bg); }
  #app-loading .app-loading__spinner {
    width: 40px; height: 40px; border-radius: 50%;
    border: 3px solid color-mix(in srgb, var(--accent, #1a5c8a) 22%, transparent);
    border-top-color: var(--accent, #1a5c8a);
    animation: app-loading-spin .8s linear infinite;
  }
  @keyframes app-loading-spin { to { transform: rotate(360deg); } }
  @keyframes app-loading-failsafe { to { opacity: 0; visibility: hidden; } }
  /* Chien de garde de la page Chat (js/chat-boot.js) : message + « Réessayer »
     sous le spinner quand le boot traîne. Tokens du thème → clair et nuit. */
  #app-loading .app-loading__msg { font-size: .9rem; line-height: 1.5; color: var(--muted, #5b6b7a); text-align: center; padding: 0 24px; }
  #app-loading .app-loading__retry { margin-left: 8px; padding: 6px 14px; border-radius: 999px; border: 1px solid var(--accent, #1a5c8a); background: transparent; color: var(--accent, #1a5c8a); font: inherit; font-weight: 600; cursor: pointer; }
  @media (prefers-reduced-motion: reduce) {
    #app-loading .app-loading__spinner { animation-duration: 2.4s; }
  }

  /* ── Ecran de login ── */
  #login-screen {
    /* Fond & carte : design partagé « Constellation » (login-constellation.css, .lgc-*).
       On garde ici position/centrage ; le fond est géré par .lgc-scene. */
    position:fixed; inset:0; z-index:100000;
    display:flex; align-items:center; justify-content:center;
    font-family:'DM Sans', sans-serif;
  }
  /* (.login-card / .login-input / .login-submit / .login-logo-wrap retirés le 30/09/2026 :
     l'écran de connexion est la carte .lgc-* de login-constellation.css — Z7a-14.) */

  /* Couleurs de MARQUE de scanner (--sv-*) — source unique, lue par l'onglet
     Digilab (.dgl-svc-*, js/digilab-ui-styles.js) ET par le filtre « marque de
     scanner » de la liste (.pf-scan). Teintes de PRODUIT (Medit, 3Shape…), donc
     communes à tous les labos : rien à tenantiser ici. */
  :root {
    --sv-medit-bg: #e8eaf6;  --sv-medit-fg: #1a237e;
    --sv-3shape-bg: #ffebee; --sv-3shape-fg: #c62828;
    --sv-dscore-bg: #eceff1; --sv-dscore-fg: #546e7a;
    --sv-shining-bg: #e0f7fa;--sv-shining-fg: #0097a7;
    --sv-itero-bg: #e8f5e9;  --sv-itero-fg: #2e7d32;
    --sv-dexis-bg: #fff3e0;  --sv-dexis-fg: #e65100;
    --sv-other-bg: #eef2f5;  --sv-other-fg: #5b7180;
  }
  html[data-theme="dark"] {
    --sv-medit-bg: color-mix(in srgb, #3949ab 30%, var(--surface)); --sv-medit-fg: #c5cae9;
    --sv-3shape-bg: color-mix(in srgb, #c62828 28%, var(--surface)); --sv-3shape-fg: #ef9a9a;
    --sv-dscore-bg: color-mix(in srgb, #546e7a 28%, var(--surface)); --sv-dscore-fg: #cfd8dc;
    --sv-shining-bg: color-mix(in srgb, #0097a7 28%, var(--surface)); --sv-shining-fg: #80deea;
    --sv-itero-bg: color-mix(in srgb, #2e7d32 28%, var(--surface)); --sv-itero-fg: #a5d6a7;
    --sv-dexis-bg: color-mix(in srgb, #e65100 26%, var(--surface)); --sv-dexis-fg: #ffcc80;
    --sv-other-bg: color-mix(in srgb, #5b7180 26%, var(--surface)); --sv-other-fg: #aab8c2;
  }

  :root {
    --bg: #eef4f8;
    --surface: #ffffff;
    --border: #d0e0ea;
    --accent: #1a5c8a;
    --teal: #5bc4c0;
    /* Couleur de marque utilisée comme COULEUR DE TEXTE.
       En mode JOUR : strictement identique à --accent / --teal.
       En mode NUIT : la MÊME teinte, mais éclaircie par js/tenant-branding.js
       (tenantCouleurNuit) jusqu'au seuil lisible — le bleu du labo sur le fond
       sombre tombe sinon à 2,3:1, illisible.
       ⚠️ NE JAMAIS s'en servir pour un FOND, une bordure, un halo ou un dégradé :
       ceux-là gardent --accent / --teal (la marque, saturée). Un seul token ne peut
       pas satisfaire les deux : un fond veut la couleur pleine, un texte veut du
       contraste. Repli sur --accent si le JS n'a pas encore tourné. */
    --accent-text: var(--accent);
    --teal-text:   var(--teal);
    /* Teintes claires dérivées dynamiquement du branding du tenant.
       --section-bg utilise la couleur intermédiaire du gradient (mix 50/50
       accent + teal) tintée très légèrement sur --surface (blanc en light
       mode, sombre en dark) -> très clair, façon "bleu pâle" d'origine mais
       en accord avec la palette choisie. */
    --accent-light: color-mix(in srgb, var(--accent) 12%, var(--surface));
    --teal-light:   color-mix(in srgb, var(--teal)   12%, var(--surface));
    --section-bg:   color-mix(in srgb, color-mix(in srgb, var(--accent) 50%, var(--teal)) 8%, var(--surface));
    --text: #1c2a35;
    --muted: #7a96a8;
    --success: #2d7a4f;
    --warn: #e08e0b;
    --danger: #c0392b;
    --grad: linear-gradient(120deg, #1a5c8a 0%, #5bc4c0 100%);

    /* ── Chrome cockpit partagé (brief #5 Ph3) — SOURCE UNIQUE des constantes
       dupliquées par les grandes modales premium. Consommées via var() par
       gc-ui-styles (.gc-modal-shell), digilab-ui-styles (.dgl-modal),
       decalage-ui-styles (.dc-modal) et dentist-view (.dv-header-inner).
       Changer la coquille ou le dégradé profond = ICI, une seule fois.
       (Les en-têtes restent des identités par module : cockpit sombre / blanc
       animé / rail — seules les CONSTANTES communes sont partagées.) */
    --ck-shell-w: 97vw;
    --ck-shell-maxw: 1860px; /* 1560 → 1860 le 25/09/2026 : toutes les grandes fenêtres à la taille de Livraison (Illan : « je veux de la cohérence ») */
    --ck-shell-h: 94vh;
    --ck-shell-radius: 22px;
    --ck-grad-deep: linear-gradient(125deg,
      color-mix(in srgb, var(--accent) 62%, #07131e) 0%,
      color-mix(in srgb, color-mix(in srgb, var(--accent) 50%, var(--teal)) 60%, #08161f) 52%,
      color-mix(in srgb, var(--teal) 55%, #06201c) 100%);

    /* ── Tokens design (redesign 2026, non-marque) ──
       Fixes ou dérivés ; n'écrasent PAS --accent/--teal/--bg/--grad, qui
       restent pilotés par le tenant (applyTenantCSSVariables). --surface-2 et
       --line sont dérivés → s'adaptent seuls au dark ET à la couleur du labo. */
    --surface-2: color-mix(in srgb, var(--surface) 70%, var(--bg));
    --line:      color-mix(in srgb, var(--border) 55%, var(--surface));
    /* ── Groupes de la modale Paramètres — SOURCE UNIQUE de leurs couleurs.
       Lues à la fois par l'étiquette de l'en-tête de panneau (.pmh-tag) et par
       le titre de groupe du rail (.pmx-side-group) : les deux disent la même
       chose, ils doivent porter la même teinte. « Atelier » suit la couleur du
       LABO (multi-tenant) ; les deux autres sont des couleurs de SECTION,
       identiques pour tous les tenants (même statut que --pmxh).
       Le doublon -c / -text suit la doctrine de --accent / --accent-text :
       la version -c sert aux FONDS, la -text au TEXTE (éclaircie en nuit,
       sinon le turquoise et le violet tombent sous le seuil lisible). */
    --pmg-atelier:      var(--accent);
    --pmg-atelier-text: var(--accent-text);
    --pmg-labo:         #16a3b0;
    --pmg-labo-text:    #0d7f8a;
    --pmg-avance:       #7c4dd6;
    --pmg-avance-text:  #6a3fc0;

    --rose:      #c2185b;
    --rosegrad:  linear-gradient(120deg, #c2185b 0%, #e0708f 100%);
    --gold:      #b8860b;
    --purple:    #7b2d8e;
    --green:     var(--success);
    --shadow-sm: 0 1px 2px rgba(20,45,70,.05), 0 1px 3px rgba(20,45,70,.06);
    --shadow-md: 0 6px 20px rgba(20,45,70,.10);
    --r:         14px;
    --r-lg:      18px;

    /* Motion system */
    --dur-fast: 140ms;
    --dur-base: 200ms;
    --dur-enter: 260ms;
    --dur-exit: 160ms;
    --dur-slow: 400ms;
    --ease-out: cubic-bezier(.22,1,.36,1);
    --ease-in-out: cubic-bezier(.77,0,.175,1);
    --ease-spring: cubic-bezier(.34,1.56,.64,1);

    /* Couleurs SÉMANTIQUES d'acte (catégorie, PAS branding tenant) — miroir des
       badges du résumé IA (.ais-d.*) : conjointe unitaire bleu, solidarisée vert,
       adjointe rose, implant violet, annexe orange. Réutilisées par l'Historique IA
       (.hix-c-*). Variante dark plus bas. */
    --acte-conj-bg:#e8f1fb;  --acte-conj-fg:#1a5c8a;
    --acte-solid-bg:#e3f3e9; --acte-solid-fg:#2d7a4f;
    --acte-adj-bg:#fce4ec;   --acte-adj-fg:#c2185b;
    --acte-imp-bg:#f3e5f5;   --acte-imp-fg:#6a1b9a;
    --acte-annexe-bg:#fbecd8; --acte-annexe-fg:#b5721a;
    /* Teinte : JAUNE. Ajouté le 11/08/2026 pour l'Historique IA (la teinte est un
       attribut d'acte, elle méritait sa couleur au même titre que les autres).
       Distinct de l'orange annexe, avec lequel il ne doit pas se confondre. */
    --acte-teinte-bg:#fdf6cf; --acte-teinte-fg:#7a6410;

    /* Couleurs SÉMANTIQUES de statut de fiche (étapes de la timeline — PAS du
       branding tenant). Source unique des pastilles .pill.st-* et des points
       .accent.st-* de la liste ; Digilab reprend les mêmes teintes (tokens
       locaux --st-* scopés #modal-digilab). Variante dark plus bas. */
    /* Point + texte = palette PARTAGÉE des états (js/etapes-cas.js, --ec-*) : les
       mêmes couleurs au portail Chine et chez le dentiste (Illan 07/09/2026).
       Repli hex = la même valeur, le temps que le module (defer) soit chargé. */
    --stp-attente-bg:#fff3cd;   --stp-attente-fg:var(--ec-t-envoye,#8a6400);  --stp-attente-dot:var(--ec-c-envoye,#e0a400);
    --stp-verifie-bg:#dcedc8;   --stp-verifie-fg:#4f7c1f;  --stp-verifie-dot:#6aa12e;
    --stp-importe-bg:#cce5ff;   --stp-importe-fg:#0a4d8c;  --stp-importe-dot:#2a7ad6;
    --stp-cogilog-bg:#f3e8ff;   --stp-cogilog-fg:var(--ec-t-en_production,#6b21a8);  --stp-cogilog-dot:var(--ec-c-en_production,#9b4fd6);
    --stp-reception-bg:#e0f7fa; --stp-reception-fg:var(--ec-t-revenu,#006570); --stp-reception-dot:var(--ec-c-revenu,#16a3b0);
    --stp-livraison-bg:#ffe0b2; --stp-livraison-fg:var(--ec-t-en_livraison,#c85a00); --stp-livraison-dot:var(--ec-c-en_livraison,#ef7d1a);
    --stp-livre-bg:#c8e6c9;     --stp-livre-fg:var(--ec-t-livre,#1f6b2c);    --stp-livre-dot:var(--ec-c-livre,#37974a);

    /* Note cabinet — couleurs sémantiques « post-it » JAUNE VIF (doit sauter aux
       yeux). Pas du branding tenant → fixes ici, variante dark plus bas. */
    --note-bg1:    #fff3b0;
    --note-bg2:    #ffe066;
    --note-border: #f3c218;
    --note-text:   #4a3a08;
    --note-accent: #9a5808;
    --note-shadow: 0 10px 30px rgba(214,158,18,.38), 0 2px 6px rgba(180,130,10,.28);

    /* Saturation globale de l'app — UN SEUL réglage pour tout colorer plus vif.
       Compense le rendu fade sur écran PC vs OLED. 1 = neutre, >1 = plus saturé. */
    --app-saturation: 1.28;
    /* Contraste global. 1 = neutre. <1 adoucit (blancs moins eclatants en clair). */
    --app-contrast: 0.90;
    /* Luminosite globale. 1 = neutre, <1 = plus sombre. */
    --app-brightness: 0.95;
    /* Indique au navigateur le thème natif courant (scrollbars, inputs date,
       menus déroulants) ET désactive son "forced dark mode" heuristique. */
    color-scheme: light;
  }

  /* ── Motion system : keyframes génériques + états d'ouverture/fermeture ──
     Réutilisés par toute l'app (modales, panneaux, voile lazy). Anime UNIQUEMENT
     transform + opacity. Fermeture : l'overlay racine reçoit .is-closing (posé
     par window.motionClose), le JS retire l'élément à la fin de l'animation. */
  @keyframes ilsFadeIn  { from { opacity: 0; } to { opacity: 1; } }
  @keyframes ilsFadeOut { from { opacity: 1; } to { opacity: 0; } }
  @keyframes ilsShellIn  { from { opacity: 0; transform: translateY(18px) scale(.985); } to { opacity: 1; transform: none; } }
  @keyframes ilsShellOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(8px) scale(.99); } }
  .is-opening { animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
  .is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }

  /* Sorties dédiées des overlays qui portent DÉJÀ une animation d'entrée
     (même spécificité que .is-closing → la règle générique perdrait la
     cascade et la fermeture resterait figée) : pmx (Paramètres/Admin/
     Facturation) et Voir-fiche, comme fait pour Digilab/GC/Implants. */
  .pmx-overlay.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
  .pmx-overlay.is-closing .pmx-shell { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }
  .vf-overlay.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
  .vf-overlay.is-closing .vf-modal { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }

  /* Confirm/Prompt (js/utils.js) — classes d'ANIMATION uniquement : le look
     (fond, boîte, ombres) reste porté par les styles inline existants. */
  .ils-cfm-overlay { animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
  .ils-cfm-box { animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
  .ils-cfm-overlay.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
  .ils-cfm-overlay.is-closing .ils-cfm-box { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }

  /* Voile d'attente des bundles lazy (js/lazy-modules.js) — div vide, le spinner
     est le ::after (même dessin que #app-loading, keyframe app-loading-spin). */
  .ils-lazy-veil {
    position: fixed; inset: 0; z-index: 100002;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--bg, #eef4f8) 55%, transparent);
    -webkit-backdrop-filter: var(--ov-blur, blur(2px)); backdrop-filter: var(--ov-blur, blur(2px));
    animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards;
  }
  .ils-lazy-veil::after {
    content: ""; width: 40px; height: 40px; border-radius: 50%;
    border: 3px solid color-mix(in srgb, var(--accent, #1a5c8a) 22%, transparent);
    border-top-color: var(--accent, #1a5c8a);
    animation: app-loading-spin .8s linear infinite;
  }

  /* View Transitions (window.vtSwitch) : cross-fade calé sur --dur-base. */
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: var(--dur-base); }

  /* Grade couleur global (saturation/contraste/luminosité) — MÊMES valeurs qu'avant.
     AVANT : filter sur <html>. Problème : un filtre sur la page QUI DÉFILE force le
     navigateur à tout redessiner sur le CPU à chaque cran de molette → scroll qui
     accroche. MAINTENANT : on applique exactement les mêmes réglages via un calque
     fixe (backdrop-filter) posé PAR-DESSUS. Le contenu n'est plus dans un élément
     filtré → il défile sur le GPU (fluide), et le calque regrade le résultat affiché
     → même rendu couleur. Réversible : remettre `html { filter: saturate(...) ... }`
     et supprimer body::after pour revenir exactement à avant. */
  html { filter: none; }
  body::after {
    content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 2147483000;
    -webkit-backdrop-filter: saturate(var(--app-saturation)) contrast(var(--app-contrast)) brightness(var(--app-brightness));
    backdrop-filter: saturate(var(--app-saturation)) contrast(var(--app-contrast)) brightness(var(--app-brightness));
  }
  /* Grade désactivé par le labo (Paramètres > Apparence) : on ne peint plus DU TOUT
     le calque → aucun backdrop-filter à recalculer au scroll = défilement le plus
     fluide possible (couleurs brutes). Posé par applyTenantCSSVariables(). */
  html.grade-off body::after { display: none; }

  /* ── Dark Mode ── */
  html[data-theme="dark"] {
    color-scheme: dark;
    --bg: #11161f;
    --surface: #1a2130;
    --border: #2a3242;
    --accent: #5bc4c0;
    --teal: #5bc4c0;
    /* --accent-light / --teal-light / --section-bg dérivés automatiquement
       de --accent / --teal / --bg (voir :root). */
    --text: #e6edf4;
    --muted: #8497a8;
    --success: #4caf50;
    --warn: #f0a830;
    --danger: #ef5350;
    --grad: linear-gradient(120deg, #2a7ab5 0%, #5bc4c0 100%);
    /* Ombres plus marquées sur fond sombre (--surface-2/--line se dérivent seuls). */
    --pmg-labo-text:   #4fd0d8;
    --pmg-avance-text: #b9a0f0;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.30), 0 1px 3px rgba(0,0,0,.35);
    --shadow-md: 0 8px 26px rgba(0,0,0,.45);
    /* Violet / or lisibles sur fond sombre (mêmes teintes que --acte-imp-fg et
       --stp-attente-fg) : consommés par .pb.a/.pb.p, popup Scan (--ppx-*),
       .alpx-special-title, .flag.e/.s, .fx-badge--scan… — plus d'override local. */
    --gold:      #e6c35a;
    --purple:    #ce93d8;
    /* Note « post-it » en dark : jaune ambré profond, texte/bord lumineux. */
    --note-bg1:    #5a4410;
    --note-bg2:    #43330b;
    --note-border: #d4a72c;
    --note-text:   #ffe9a6;
    --note-accent: #ffce5a;
    --note-shadow: 0 12px 32px rgba(0,0,0,.55), 0 0 0 1px rgba(212,167,44,.18);
    /* Couleurs d'acte en dark — miroir des .ais-d.* dark du résumé IA. */
    --acte-conj-bg:#1e3a4f;  --acte-conj-fg:#7fc4e8;
    --acte-solid-bg:#1c3326; --acte-solid-fg:#81c784;
    --acte-adj-bg:#3a1e2c;   --acte-adj-fg:#f48fb1;
    --acte-imp-bg:#2e1e3a;   --acte-imp-fg:#ce93d8;
    --acte-annexe-bg:#3a2a18; --acte-annexe-fg:#ffb74d;
    --acte-teinte-bg:#3a3512; --acte-teinte-fg:#ffe066;
    /* Statuts de fiche en dark : fonds profonds, textes lumineux (mêmes teintes). */
    --stp-attente-bg:#3a3318;   --stp-attente-fg:var(--ec-t-envoye,#e6c35a);  --stp-attente-dot:var(--ec-c-envoye,#e0a400);
    --stp-verifie-bg:#243a1e;   --stp-verifie-fg:#a5d08a;  --stp-verifie-dot:#6aa12e;
    --stp-importe-bg:#1e3a4f;   --stp-importe-fg:#7fc4e8;  --stp-importe-dot:#2a7ad6;
    --stp-cogilog-bg:#2e1e3a;   --stp-cogilog-fg:var(--ec-t-en_production,#ce93d8);  --stp-cogilog-dot:var(--ec-c-en_production,#9b4fd6);
    --stp-reception-bg:#123a3e; --stp-reception-fg:var(--ec-t-revenu,#6fd4de); --stp-reception-dot:var(--ec-c-revenu,#16a3b0);
    --stp-livraison-bg:#3a2a18; --stp-livraison-fg:var(--ec-t-en_livraison,#ffb066); --stp-livraison-dot:var(--ec-c-en_livraison,#ef7d1a);
    --stp-livre-bg:#1c3326;     --stp-livre-fg:var(--ec-t-livre,#81c784);    --stp-livre-dot:var(--ec-c-livre,#37974a);
  }

  /* ── Ambiances du mode nuit (presets curés — Préférences → Interface) ──
     'ardoise' = le dark historique ci-dessus (aucune règle : c'est le défaut).
     Chaque preset ne surcharge QUE les tokens NEUTRES (--bg/--surface/--border/
     --text/--muted/ombres) : la marque (--accent/--teal/--grad) reste pilotée
     par le tenant, --surface-2/--line/--accent-light se dérivent tout seuls,
     et le mode CLAIR est intact (le sélecteur exige data-theme="dark").
     Appliqué par applyDarkPreset() (js/dark-mode.js) via data-dark-preset. */
  html[data-theme="dark"][data-dark-preset="bleu-nuit"] {
    --bg: #0a1430;
    --surface: #101d40;
    --border: #26386b;
    --text: #dce7fb;
    --muted: #8fa6cf;
  }
  /* Minuit — bleu nuit TRÈS profond (plus sombre que Bleu nuit, quasi-noir teinté marine). */
  html[data-theme="dark"][data-dark-preset="minuit"] {
    --bg: #050a1a;
    --surface: #0a1330;
    --border: #1a2850;
    --text: #d5e0f5;
    --muted: #7a8fb8;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.60);
    --shadow-md: 0 8px 26px rgba(0,0,0,.70);
  }
  /* Graphite — gris neutre chaud, SANS teinte bleue (alternative « pas de bleu »
     répandue dans les logiciels pro : GitHub Dimmed, macOS, VS Code One Dark). */
  html[data-theme="dark"][data-dark-preset="graphite"] {
    --bg: #16181d;
    --surface: #21242b;
    --border: #363a44;
    --text: #e8e9ec;
    --muted: #9096a3;
  }
  html[data-theme="dark"][data-dark-preset="oled"] {
    --bg: #000000;
    --surface: #0b0f16;
    --border: #1c2430;
    --text: #e8edf3;
    --muted: #7f93a6;
    /* Sur du vrai noir, la profondeur vient d'ombres plus denses. */
    --shadow-sm: 0 1px 2px rgba(0,0,0,.60), 0 1px 3px rgba(0,0,0,.65);
    --shadow-md: 0 8px 26px rgba(0,0,0,.75);
  }

  /* Sélecteur d'ambiance (Préférences) : 3 vignettes-aperçus, compactes. */
  .pm-amb-row { display:flex; gap:10px; flex-wrap:wrap; }
  .pm-amb-btn {
    display:flex; flex-direction:column; align-items:center; gap:5px;
    padding:7px 9px 6px; border-radius:11px; cursor:pointer; font-family:inherit;
    border:1.5px solid var(--line); background:var(--surface-2);
    font-size:0.7rem; font-weight:600; color:var(--muted);
    transition:border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease, color var(--dur-fast) ease, transform var(--dur-fast) ease;
  }
  .pm-amb-btn:hover { transform:translateY(-1px); border-color:color-mix(in srgb, var(--accent) 45%, var(--line)); }
  .pm-amb-btn.active {
    border-color:var(--accent); color:var(--text);
    box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
  }
  /* La vignette montre les VRAIES couleurs du preset (fond + carte + ligne de texte). */
  .pm-amb-swatch {
    width:72px; height:44px; border-radius:8px; position:relative; overflow:hidden;
    border:1px solid rgba(255,255,255,.08);
  }
  .pm-amb-swatch::before { /* la « carte » posée sur le fond */
    content:""; position:absolute; left:7px; top:7px; right:7px; bottom:11px;
    border-radius:5px; border:1px solid var(--amb-border);
    /* + un petit bouton à la couleur du labo : on juge la teinte avec l'accent posé dessus */
    background:linear-gradient(var(--accent),var(--accent)) left 5px bottom 4px / 16px 5px no-repeat, var(--amb-surface);
  }
  .pm-amb-swatch::after { /* la « ligne de texte » sur la carte */
    content:""; position:absolute; left:13px; top:14px; width:26px; height:4px;
    border-radius:2px; background:var(--amb-text);
  }
  .pm-amb-swatch--ardoise { background:#11161f; --amb-surface:#1a2130; --amb-border:#2a3242; --amb-text:#e6edf4; }
  .pm-amb-swatch--bleu-nuit { background:#0a1430; --amb-surface:#101d40; --amb-border:#26386b; --amb-text:#dce7fb; }
  .pm-amb-swatch--minuit { background:#050a1a; --amb-surface:#0a1330; --amb-border:#1a2850; --amb-text:#d5e0f5; }
  .pm-amb-swatch--graphite { background:#16181d; --amb-surface:#21242b; --amb-border:#363a44; --amb-text:#e8e9ec; }
  .pm-amb-swatch--oled { background:#000; --amb-surface:#0b0f16; --amb-border:#1c2430; --amb-text:#e8edf3; }

  /* ── Zoom utilisateur (bulle du bouton 🔍 + carte Paramètres → Apparence) ──
     Tout est en tokens : le mode sombre et les 5 ambiances suivent
     automatiquement, aucune couleur en dur (Règle 11). */
  /* z-index 1400 et non 1500 : 1500 est déjà celui de .vf-overlay (modale
     plein écran) et, la bulle étant ajoutée en fin de <body>, elle passerait
     au-dessus à égalité. */
  .uz-pop{
    position:fixed; z-index:1400; min-width:212px;
    background:var(--surface); border:1px solid var(--border);
    border-radius:14px; box-shadow:var(--shadow-md);
    padding:12px 13px 10px;
  }
  .uz-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
  .uz-step{
    width:40px; height:40px; flex:none; border-radius:11px; cursor:pointer;
    border:1px solid var(--border); background:var(--bg);
    color:var(--text); font-size:1.25rem; font-weight:600; line-height:1;
    transition:background var(--dur-fast) var(--ease-out),
               border-color var(--dur-fast) var(--ease-out),
               transform var(--dur-fast) var(--ease-out);
  }
  .uz-step:hover:not(:disabled){ background:var(--surface-2); border-color:var(--accent); }
  .uz-step:active:not(:disabled){ transform:scale(.93); }
  .uz-step:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
  .uz-step:disabled{ opacity:.35; cursor:default; }
  .uz-val{
    font-family:'DM Mono',monospace; font-size:.94rem; font-weight:700;
    color:var(--text); text-align:center; flex:1; font-variant-numeric:tabular-nums;
  }
  .uz-foot{
    display:flex; align-items:center; justify-content:space-between; gap:8px;
    margin-top:9px; padding-top:8px; border-top:1px solid var(--border);
  }
  .uz-hint{ font-size:.68rem; color:var(--muted); }
  .uz-reset{
    border:none; background:transparent; cursor:pointer; padding:3px 5px;
    border-radius:7px; font-size:.7rem; color:var(--accent); font-weight:600;
    transition:background var(--dur-fast) var(--ease-out);
  }
  .uz-reset:hover{ background:var(--surface-2); }
  .uz-reset:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
  /* Rangée « Interface » (Auto / Mobile / PC) : forçage du rendu, mémorisé
     par appareil. Chips = gabarit .uz-step (tokens → dark + tenant auto). */
  .uz-iface{
    display:flex; align-items:center; gap:5px;
    margin-top:9px; padding-top:8px; border-top:1px solid var(--border);
  }
  .uz-iface-lbl{
    font-size:.6rem; font-weight:700; text-transform:uppercase;
    letter-spacing:.05em; color:var(--muted); margin-right:2px;
  }
  .uz-ifc{
    flex:1; border:1px solid var(--border); background:var(--bg); color:var(--text);
    font-size:.7rem; font-weight:600; padding:5px 4px; border-radius:9px; cursor:pointer;
    white-space:nowrap;
    transition:background var(--dur-fast) var(--ease-out),
               border-color var(--dur-fast) var(--ease-out);
  }
  .uz-ifc:hover{ border-color:var(--accent); }
  .uz-ifc:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
  .uz-ifc--actif{
    background:color-mix(in srgb, var(--accent) 14%, var(--surface));
    border-color:var(--accent); color:var(--accent-text); font-weight:700;
  }

  /* Au plafond de 100 %, la voie « encore plus gros » = l'interface mobile
     (polices 130 %) : la balise viewport, elle, est refusée au-dessus de 1 par
     l'appareil (17-18/08). Tokens uniquement → dark automatique. */
  .uz-natif{
    margin-top:9px; padding-top:8px; border-top:1px dashed var(--border);
    font-size:.68rem; line-height:1.5; color:var(--muted); max-width:236px;
  }
  .uz-natif b{ color:var(--text); }

  @media (prefers-reduced-motion: reduce){
    .uz-step,.uz-reset{ transition:none; }
    .uz-step:active:not(:disabled){ transform:none; }
  }

  body.theme-transition * {
    transition: background-color var(--dur-slow), color var(--dur-slow), border-color var(--dur-slow), box-shadow var(--dur-slow) !important;
  }

  html[data-theme="dark"] header {
    background: var(--surface);
    border-color: var(--border);
    /* Halo signature en dark : --accent = teal → glow doux. */
    box-shadow: 0 6px 32px color-mix(in srgb, var(--accent) 22%, transparent), var(--shadow-sm);
  }

  html[data-theme="dark"] input[type="text"],
  html[data-theme="dark"] input[type="date"],
  html[data-theme="dark"] input[type="number"],
  html[data-theme="dark"] input[type="email"],
  html[data-theme="dark"] textarea,
  html[data-theme="dark"] select {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border);
  }

  html[data-theme="dark"] .dent-btn {
    background: var(--surface);
    color: var(--muted);
  }

  html[data-theme="dark"] .teinte-chip {
    background: var(--surface);
    color: var(--text);
  }

  html[data-theme="dark"] .btn-secondary {
    background: var(--surface);
    color: var(--text);
  }

  html[data-theme="dark"] .btn-header-secondary {
    background: var(--surface);
    color: var(--accent-text);
  }

  html[data-theme="dark"] .btn-header-outline {
    background: var(--surface);
    color: var(--accent-text);
  }

  html[data-theme="dark"] .btn-pdf {
    background: var(--surface);
    color: var(--accent-text);
  }

  html[data-theme="dark"] .scan-panel {
    background: var(--surface);
  }
  html[data-theme="dark"] .scan-panel-warning {
    background: #2e2a1e;
    border-color: #5a4a20;
  }
  html[data-theme="dark"] .scan-panel-accent {
    background: var(--surface);
  }

  html[data-theme="dark"] .checkbox-label:has(input:checked) {
    background: #3a3520;
    color: #e6b800;
    border-color: #7a6a20;
  }

  html[data-theme="dark"] .gc-list-item.selected {
    background: #1e3040;
    color: var(--accent-text);
    border-color: #2a5070;
  }
  html[data-theme="dark"] .gc-list-item:not(.selected) { color: var(--text); }

  html[data-theme="dark"] .suggest-item { border-bottom-color: var(--border); }
  html[data-theme="dark"] .suggest-item:hover { background: var(--section-bg); }

  html[data-theme="dark"] .tarif-cab-btn:not(.selected) {
    background: var(--surface);
    border-color: var(--border);
    color: var(--text);
  }

  html[data-theme="dark"] .pa-item { color: var(--text); }
  html[data-theme="dark"] .pa-item:hover { background: #2e2848; border-color: #6a5aaa; }
  html[data-theme="dark"] .pa-item.has-aliases { background: #2e2540; border-color: #7a5aaa; }

  /* Boutons-date mignons (filtres Du/au) */
  html[data-theme="dark"] .imp-datebtn { background: #1a1f2e; border-color: #3a4055; color: #7fc4e8; }
  html[data-theme="dark"] .imp-datebtn:hover { border-color: #5bc4c0; box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
  /* Calendrier mignon partagé (#app-cal-pop, utils.js) en mode nuit */
  html[data-theme="dark"] #app-cal-pop { background: #242938 !important; border-color: #3a4055 !important; box-shadow: 0 14px 44px rgba(0,0,0,0.5) !important; }
  html[data-theme="dark"] #app-cal-pop span[style*="color:#1c2a35"] { color: #e0e6ed !important; }
  html[data-theme="dark"] #app-cal-pop .app-cal-day { color: #e0e6ed; }
  html[data-theme="dark"] #app-cal-pop .app-cal-day:hover { background: #2a3550; }
  html[data-theme="dark"] #app-cal-pop .app-cal-day.sel { background: #5bc4c0; color: #14202b; }
  html[data-theme="dark"] #app-cal-pop .app-cal-nav { background: #1a1f2e; border-color: #3a4055; color: #5bc4c0; }
  html[data-theme="dark"] #app-cal-pop .app-cal-nav:hover { background: #2a3550; }
  html[data-theme="dark"] #app-cal-pop button[id="app-cal-extra"] { background: #1a1f2e !important; border-color: #3a4055 !important; color: #7fc4e8 !important; }
  html[data-theme="dark"] #imp-order-table td { border-bottom-color: var(--border); }
  html[data-theme="dark"] #imp-order-table tr.cab-alt { background: var(--section-bg); }
  html[data-theme="dark"] #imp-order-table tr:hover { background: #1e3040; }

  html[data-theme="dark"] .imp-drop-zone { background: var(--section-bg); }

  html[data-theme="dark"] #acte-detail-popup {
    background: var(--surface);
    border-color: var(--border);
    box-shadow: 0 8px 28px rgba(0,0,0,0.5);
  }
  html[data-theme="dark"] #acte-detail-popup input[type=text] { border-color: var(--border); }

  html[data-theme="dark"] .filter-tag { background: #1e3040; color: #6ab4e8; }
  html[data-theme="dark"] .filter-tag-close { color: #6ab4e8; }

  html[data-theme="dark"] .gc-action-btn { background: var(--surface); color: var(--text); }
  html[data-theme="dark"] .gc-del-btn { background: #3a1a1a; border-color: #6a3030; }

  html[data-theme="dark"] .actions {
    background: linear-gradient(90deg, var(--teal-light), var(--accent-light));
    border-top-color: var(--border);
  }

  /* ═══════════════════════════════════════════════════════════════
     DARK MODE — MODALES (overrides globaux pour inline styles)
     ═══════════════════════════════════════════════════════════════ */

  /* --- Scope : toutes les modales --- */
  .dm-modal { /* alias selector below */ }
  html[data-theme="dark"] #modal-parametres > div,
  html[data-theme="dark"] #modal-tarifs > div,
  html[data-theme="dark"] #modal-implants > div,
  html[data-theme="dark"] #modal-digilab > div:not(#dlb-detail-modal),
  html[data-theme="dark"] #modal-aliases-cabinet > div,
  html[data-theme="dark"] #popup-unit-solid .us-modal {
    background: var(--surface) !important;
    box-shadow: 0 8px 40px rgba(0,0,0,0.5) !important;
    color: var(--text) !important;
  }

  /* Headers des modales (premier enfant div = barre supérieure)
     Cette règle vise les ANCIENNES modales dont le header inline est
     une teinte claire (ex: paramètres = gradient lavande).
     NE PAS inclure #modal-tarifs ni #modal-implants : leurs headers
     (.gc-header / .imp-header) utilisent un gradient bleu→teal
     conçu pour rester lisible en dark — l'override les casserait. */
  /* :not(.pmx-head) — cette règle date d'avant la refonte .pmx-* et vise
     l'en-tête par sa POSITION. Son !important écrasait le nouvel en-tête
     « hero » coloré en mode sombre (dégradé remplacé par un aplat). Le
     .pmx-head a désormais ses propres règles claires et sombres. */
  html[data-theme="dark"] #modal-parametres > div > div:first-child:not(.pmx-head) {
    background: var(--section-bg) !important;
    border-bottom-color: var(--border) !important;
  }

  /* Titres colorés dans les headers */
  html[data-theme="dark"] #modal-parametres span[style*="color:#4a148c"] { color: #ce93d8 !important; }
  html[data-theme="dark"] #modal-tarifs span[style*="color:#1a5c8a"] { color: var(--accent-text) !important; }
  html[data-theme="dark"] #modal-implants span[style*="color:#0277bd"] { color: #4fc3f7 !important; }
  html[data-theme="dark"] #modal-digilab span[style*="color:#00838f"] { color: #4dd0e1 !important; }

  /* Conteneurs d'onglets (pill groups) */
  html[data-theme="dark"] #modal-parametres div[style*="background:rgba(255"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:#e8eff5"] {
    background: rgba(255,255,255,0.08) !important;
  }

  /* Boutons fermer ✕ */
  html[data-theme="dark"] #modal-parametres button[style*="color:#999"],
  html[data-theme="dark"] #modal-tarifs button[style*="color:#999"],
  html[data-theme="dark"] #modal-implants button[style*="color:#999"],
  html[data-theme="dark"] #modal-digilab button[style*="color:#999"],
  html[data-theme="dark"] #modal-aliases-cabinet button[style*="color:#888"] {
    color: var(--muted) !important;
  }

  /* --- Override global : tout fond blanc/clair inline dans les modales --- */
  html[data-theme="dark"] #modal-parametres div[style*="background:white"],
  html[data-theme="dark"] #modal-parametres div[style*="background:#fafafa"],
  html[data-theme="dark"] #modal-parametres div[style*="background:#fafbfd"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:white"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:#fafafa"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:#fafcfe"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:#fafbfd"],
  html[data-theme="dark"] #modal-tarifs div[style*="background:#f0f4f8"],
  html[data-theme="dark"] #modal-implants div[style*="background:white"],
  html[data-theme="dark"] #modal-implants div[style*="background:#fafbfd"],
  html[data-theme="dark"] #modal-digilab div[style*="background:white"],
  html[data-theme="dark"] #modal-digilab div[style*="background:#f8fafb"],
  html[data-theme="dark"] #modal-digilab div[style*="background:#f8fbff"] {
    background: var(--section-bg) !important;
  }

  /* Borders internes (séparateurs, sidebars) */
  html[data-theme="dark"] #modal-tarifs div[style*="border-right:1px solid #e8e8e8"],
  html[data-theme="dark"] #modal-tarifs div[style*="border-bottom:1px solid #e0e8f0"],
  html[data-theme="dark"] #modal-tarifs div[style*="border-bottom:1px solid #e8e8e8"],
  html[data-theme="dark"] #modal-parametres div[style*="border-bottom:1px solid #ede7f6"] {
    border-color: var(--border) !important;
  }

  /* --- Inputs & selects dans toutes les modales --- */
  html[data-theme="dark"] #modal-parametres input,
  html[data-theme="dark"] #modal-parametres select,
  html[data-theme="dark"] #modal-parametres textarea,
  /* .gc-tarif-price exclu : les champs de prix sont tokenisés et partagés avec
     l'écran Grilles (js/tarifs-table-styles.js), qui n'a pas ce pansement — les
     deux écrans n'avaient donc pas la même tête en nuit. Le !important écrasait
     en plus les états « modifié » (orange) et « vide » (grisé). Même motif que
     #modal-aliases-cabinet, retiré le 12/08/2026 juste au-dessus. */
  html[data-theme="dark"] #modal-tarifs input:not(.gc-tarif-price):not(.gc-tarif-input),
  html[data-theme="dark"] #modal-tarifs select:not(.gc-tarif-select),
  html[data-theme="dark"] #modal-tarifs textarea,
  html[data-theme="dark"] #modal-implants input,
  html[data-theme="dark"] #modal-implants select,
  html[data-theme="dark"] #modal-digilab input,
  html[data-theme="dark"] #modal-digilab select {
  /* (#modal-aliases-cabinet retiré le 12/08/2026 : inputs .alcx-in tokenisés,
     le pansement !important cassait leur bordure de focus en nuit. #popup-ajout-client
     retiré le 30/09/2026 : coque .gcx-* tokenisée, js/gc-ui-styles.js.) */
    background: var(--surface) !important;
    border-color: var(--border) !important;
    color: var(--text) !important;
  }
  html[data-theme="dark"] #modal-parametres input::placeholder,
  html[data-theme="dark"] #modal-tarifs input::placeholder,
  html[data-theme="dark"] #modal-digilab input::placeholder {
    color: var(--muted) !important;
  }

  /* --- Boutons inline (fond blanc) dans les modales --- */
  html[data-theme="dark"] #modal-parametres button[style*="background:white"],
  html[data-theme="dark"] #modal-tarifs button[style*="background:white"],
  html[data-theme="dark"] #modal-implants button[style*="background:white"] {
    background: var(--surface) !important;
    border-color: var(--border) !important;
    color: var(--text) !important;
  }

  /* --- Textes gris inline (#666, #555, #888, #999, #333, #aaa) --- */
  html[data-theme="dark"] #modal-tarifs span[style*="color:#aaa"],
  html[data-theme="dark"] #modal-tarifs span[style*="color:#888"],
  html[data-theme="dark"] #modal-tarifs div[style*="color:#666"],
  html[data-theme="dark"] #modal-parametres div[style*="color:#666"],
  html[data-theme="dark"] #modal-parametres div[style*="color:#888"],
  html[data-theme="dark"] #modal-digilab span[style*="color:#666"] {
    color: var(--muted) !important;
  }

  /* --- Modale Paramètres — spécifiques --- */

  /* Lignes mapping/labels (alternance) */
  html[data-theme="dark"] #pm-mapping-tbody tr,
  html[data-theme="dark"] #pm-labels-tbody tr {
    background: var(--surface) !important;
    border-bottom-color: var(--border) !important;
  }
  html[data-theme="dark"] #pm-mapping-tbody tr:nth-child(odd),
  html[data-theme="dark"] #pm-labels-tbody tr:nth-child(odd) {
    background: var(--section-bg) !important;
  }
  html[data-theme="dark"] #pm-mapping-tbody td,
  html[data-theme="dark"] #pm-labels-tbody td {
    color: var(--text) !important;
  }

  /* Prefs sections */
  html[data-theme="dark"] #pm-prefs-content div[style*="background:#f8f4ff"],
  html[data-theme="dark"] #pm-prefs-content div[style*="background:#f5f5f5"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }
  html[data-theme="dark"] #pm-prefs-content h3 { color: #ce93d8 !important; }
  html[data-theme="dark"] #pm-prefs-content div[style*="color:#6a1b9a"] { color: #ce93d8 !important; }
  html[data-theme="dark"] #pm-prefs-content label { color: var(--text) !important; }
  html[data-theme="dark"] #pm-prefs-content label[style*="color:#888"],
  html[data-theme="dark"] #pm-prefs-content div[style*="color:#888"] { color: var(--muted) !important; }

  /* --- Modale Gestion Clients — spécifiques --- */

  /* --- Modale Gestion Clients --- */

  /* Sidebar cabinets */
  html[data-theme="dark"] #modal-tarifs div[style*="background:#fafcfe"] {
    background: var(--section-bg) !important;
    border-right-color: var(--border) !important;
  }

  /* Groupes cabinets dans sidebar */
  html[data-theme="dark"] #gc-cabinet-list div[style*="background:#e8f0fe"] {
    background: #1e2a40 !important;
  }
  html[data-theme="dark"] #gc-cabinet-list span[style*="color:#1a5c8a"] {
    color: var(--accent-text) !important;
  }
  html[data-theme="dark"] #gc-cabinet-list span[style*="background:#c8daf8"] {
    background: #2a3a55 !important;
    color: #8ab4e8 !important;
  }
  html[data-theme="dark"] #gc-cabinet-list div[style*="border-left:2px solid #c8daf8"] {
    border-left-color: var(--border) !important;
  }
  html[data-theme="dark"] #gc-cabinet-list div[style*="color:#aaa"] {
    color: var(--muted) !important;
  }

  /* Boutons filtre statut sidebar : surcharge retirée le 13/08/26. Elle ne visait
     que 2 des 3 boutons du segmenté et 1 des 4 tuiles (par leur id / leur onclick),
     et son !important battait le bloc scopé → en mode nuit le segmenté était
     asymétrique (« Tous » sans bordure, les deux autres avec) et la tuile
     « Groupes » ne ressemblait pas à ses voisines. Le style vit dans
     js/gc-ui-styles.js, en tokens, donc déjà correct en nuit. */

  /* Zone liaison tarifs : plus de surcharge dark en dur ici — la zone est stylée
     par classe (.gc-liaison-zone, js/gc-ui-styles.js) avec des tokens qui suivent
     déjà le thème. Une règle #id !important y regagnerait la main avec un hex figé. */

  /* Fiche client : sections inline claires → dark */
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#f8fafc"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#f0f4f8"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#fafcfe"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }
  /* Sections jaunes (notes, alertes) */
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#fff8e1"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#fffde7"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#fff3e0"] {
    background: #2e2a1e !important;
    border-color: #5a4a20 !important;
  }
  /* Section verte (tarif lié) */
  html[data-theme="dark"] #gc-panel-contacts div[style*="background:#f0fff4"] {
    background: #1e2e25 !important;
    border-color: #2a5040 !important;
  }
  /* Textes dans la fiche */
  html[data-theme="dark"] #gc-panel-contacts span[style*="color:#333"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="color:#333"],
  html[data-theme="dark"] #gc-panel-contacts td[style*="color:#333"] {
    color: var(--text) !important;
  }
  html[data-theme="dark"] #gc-panel-contacts span[style*="color:#555"],
  html[data-theme="dark"] #gc-panel-contacts span[style*="color:#888"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="color:#888"],
  html[data-theme="dark"] #gc-panel-contacts div[style*="color:#666"],
  html[data-theme="dark"] #gc-panel-contacts label[style*="color:#888"] {
    color: var(--muted) !important;
  }
  html[data-theme="dark"] #gc-panel-contacts textarea {
    background: var(--surface) !important;
    color: var(--text) !important;
  }
  /* Boutons action fiche client */
  html[data-theme="dark"] #gc-panel-contacts button[style*="background:#fff3e0"],
  html[data-theme="dark"] #gc-panel-contacts button[style*="background:#ffebee"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }

  /* --- Onglet Tarifs --- */

  /* Barre outils tarifs */
  html[data-theme="dark"] #gc-tarif-toolbar {
    background: var(--section-bg) !important;
    border-bottom-color: var(--border) !important;
  }

  /* Tableau tarifs — RIEN ICI.
     Il y avait a cet endroit une quinzaine de regles de mode nuit ciblant
     #tarif-tbody par son ID, en !important, ecrites avant les tokens (elles
     rattrapaient des styles inline qui n'existent plus). Deux problemes :
     • l'ID #tarif-tbody n'existe que dans l'onglet Tarifs d'un cabinet ;
       l'ecran Grilles rend LE MEME tableau dans #tarif-tbody-grilles. Les deux
       ecrans n'avaient donc pas la meme tete en mode nuit — les bandeaux
       d'univers y perdaient leurs couleurs metier (constate le 14/08/2026) ;
     • le !important battait les regles scopees, tokenisees, qui gerent
       aujourd'hui les deux themes.
     L'apparence du tableau (les deux ecrans, les deux themes) vit desormais
     dans js/tarifs-table-styles.js — source unique. Ne rien remettre ici. */

  /* --- Digilab — cas et détails --- */

  /* Contenu Digilab */
  html[data-theme="dark"] #modal-digilab div[style*="background:#f8fafb"],
  html[data-theme="dark"] #modal-digilab div[style*="background:#f8fbff"] {
    background: var(--section-bg) !important;
  }
  html[data-theme="dark"] #modal-digilab div[style*="background:#fffde7"] {
    background: #2e2a1e !important;
    border-color: #5a4a20 !important;
  }
  /* Textes inline digilab */
  html[data-theme="dark"] #modal-digilab span[style*="color:#555"],
  html[data-theme="dark"] #modal-digilab span[style*="color:#999"],
  html[data-theme="dark"] #modal-digilab span[style*="color:#888"],
  html[data-theme="dark"] #modal-digilab div[style*="color:#333"] {
    color: var(--muted) !important;
  }

  /* Boutons Digilab header */
  html[data-theme="dark"] #modal-digilab button[onclick="dlbRefresh()"] {
    background: var(--teal-light) !important;
    border-color: var(--border) !important;
    color: var(--accent-text) !important;
  }

  /* (Popups Groupes / Nouveau client : rattrapages de nuit retirés le 30/09/2026,
     coque .gcx-* tokenisée dans js/gc-ui-styles.js.) */

  /* Bouton Gestion clients (sous le formulaire principal) */
  html[data-theme="dark"] button[onclick="ouvrirModalTarifs()"] {
    background: var(--section-bg) !important;
    color: #ff8a65 !important;
  }

  /* --- Fiche client (#contacts-editor) contenu dynamique --- */

  /* Bloc coordonnées */
  html[data-theme="dark"] #contacts-editor div[style*="background:#f8fafc"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }
  /* Textes coordonnées (#444) */
  html[data-theme="dark"] #contacts-editor div[style*="color:#444"],
  html[data-theme="dark"] #contacts-editor span[style*="color:#444"] {
    color: var(--text) !important;
  }
  /* Liens */
  html[data-theme="dark"] #contacts-editor a[style*="color:#1a5c8a"] {
    color: var(--accent-text) !important;
  }
  /* Boutons Copier */
  html[data-theme="dark"] #contacts-editor button[style*="color:#666"] {
    color: var(--muted) !important;
    border-color: var(--border) !important;
  }

  /* Grille tarifaire (vert ou jaune) */
  html[data-theme="dark"] #contacts-editor div[style*="background:#f0fff4"] {
    background: #1e2e25 !important;
    border-color: #2a5040 !important;
  }
  html[data-theme="dark"] #contacts-editor div[style*="background:#fff8e1"],
  html[data-theme="dark"] #contacts-editor div[style*="background:#fffde7"] {
    background: #2e2a1e !important;
    border-color: #5a4a20 !important;
  }
  html[data-theme="dark"] #contacts-editor div[style*="background:#fff3e0"] {
    background: #2e2518 !important;
    border-color: #5a4020 !important;
  }

  /* Notes internes */
  html[data-theme="dark"] #contacts-editor textarea {
    background: var(--surface) !important;
    color: var(--text) !important;
    border-color: var(--border) !important;
  }

  /* Section prescriptions */
  html[data-theme="dark"] #contacts-editor div[style*="border:1px solid #e8eef4"] {
    border-color: var(--border) !important;
  }
  html[data-theme="dark"] #contacts-editor div[style*="background:#f0f4f8"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }
  /* Lignes prescriptions */
  html[data-theme="dark"] #contacts-editor div[style*="border-bottom:1px solid #f0f4f8"] {
    border-bottom-color: var(--border) !important;
  }
  html[data-theme="dark"] #contacts-editor span[style*="color:#333"] {
    color: var(--text) !important;
  }
  html[data-theme="dark"] #contacts-editor span[style*="color:#888"],
  html[data-theme="dark"] #contacts-editor span[style*="color:#aaa"],
  html[data-theme="dark"] #contacts-editor span[style*="color:#999"],
  html[data-theme="dark"] #contacts-editor div[style*="color:#aaa"],
  html[data-theme="dark"] #contacts-editor div[style*="color:#888"],
  html[data-theme="dark"] #contacts-editor div[style*="color:#666"] {
    color: var(--muted) !important;
  }

  /* Section praticiens */
  html[data-theme="dark"] #contacts-editor div[style*="background:#e8f4fb"] {
    background: #1e2a40 !important;
  }
  /* Zone ajout praticien */
  html[data-theme="dark"] #contacts-editor div[style*="background:#fafcfe"] {
    background: var(--section-bg) !important;
    border-top-color: var(--border) !important;
  }
  /* Lignes praticiens */
  html[data-theme="dark"] #contacts-liste > div {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
    color: var(--text);
  }
  html[data-theme="dark"] #contacts-liste span[style*="background:#ede7f6"] {
    background: #2e2540 !important;
    color: #ce93d8 !important;
  }
  html[data-theme="dark"] #contacts-liste div[style*="border-top:1px dashed"] {
    border-top-color: var(--border) !important;
  }
  /* Boutons modifier/supprimer fiche */
  html[data-theme="dark"] #contacts-editor button[style*="background:#fff3e0"] {
    background: var(--section-bg) !important;
    border-color: var(--border) !important;
  }
  html[data-theme="dark"] #contacts-editor button[style*="background:#ffebee"] {
    background: #3a1a1a !important;
    border-color: #6a3030 !important;
  }
  /* Titre cabinet */
  html[data-theme="dark"] #contacts-editor h3[style*="color:#1a5c8a"] {
    color: var(--accent-text) !important;
  }
  /* Notes header */
  html[data-theme="dark"] #contacts-editor span[style*="color:#1a5c8a"] {
    color: var(--accent-text) !important;
  }
  /* Aucune prescription (dashed) */
  html[data-theme="dark"] #contacts-editor div[style*="border:1px dashed"] {
    border-color: var(--border) !important;
    color: var(--muted) !important;
  }
  /* Badge COG */
  html[data-theme="dark"] #contacts-editor span[style*="background:#e8f5e9"] {
    background: #1e2e25 !important;
  }
  /* Statut select */
  html[data-theme="dark"] #contacts-editor select {
    background: var(--surface) !important;
  }

  /* Alias cabinet */
  html[data-theme="dark"] #modal-aliases-cabinet h3 { color: var(--text) !important; }

  body {
    font-family: 'DM Sans', sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    padding: 24px 16px 60px;
  }

  header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1500px;
    margin: 0 auto 32px;
    padding: 16px 22px;
    background: var(--surface);
    border-radius: var(--r-lg);
    /* Halo bleu signature du redesign (réagit au --accent du tenant). */
    box-shadow: 0 6px 32px color-mix(in srgb, var(--accent) 26%, transparent), var(--shadow-sm);
    border: 1px solid var(--border);
  }

  /* Le bloc logo est le seul élément à texte long du header : sans ceci il
     impose sa largeur minimale et pousse le reste hors de l'écran (les
     éléments flex ont `min-width: auto` et refusent de se comprimer).
     ⚠️ Ne PAS ajouter `flex-wrap: wrap` aux conteneurs du header : essayé et
     REJETÉ sur mesure — la rangée d'icônes passait alors sur deux lignes même
     quand la place ne manquait pas (+75 px de hauteur de header sur
     téléphone). La mise en page mobile a déjà ses propres règles de wrap sous
     html.mobile-zoom-default (cf. plus bas) ; les doubler casse plus que ça
     ne répare. */
  header .logo, header .logo-text { min-width: 0; }

  .logo {
    display: flex;
    align-items: center;
    gap: 18px;
    text-decoration: none;
  }
  .logo-img-wrap {
    position: relative;
    width: 104px;
    height: 104px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    /* Logo « libre » : pas de cadre rond ni de halo (fidèle maquette). */
    background: transparent;
  }
  .logo-img {
    width: auto;
    height: 74px;
    object-fit: contain;
  }
  .logo-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
  }
  .logo-labo {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
    line-height: 1.2;
    margin-top: 4px;
  }
  .logo-ilovesmile {
    font-family: var(--font-signature, 'Dancing Script', cursive);
    font-size: 2.6rem;
    font-weight: 700;
    /* Utilise --grad pour reagir au branding du tenant (Phase 2 white-label). */
    background: var(--grad);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    line-height: 1.05;
    letter-spacing: 0px;
    margin-top: 2px;
  }
  .logo-tagline {
    font-size: 0.6rem;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    font-weight: 700;
    margin-top: 6px;
    width: max-content;
    /* Ligne dégradée clip-text (§2) — réagit au branding tenant via --grad. */
    background: var(--grad);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
  .badge {
    font-family: 'DM Mono', monospace;
    font-size: 0.72rem;
    background: var(--grad);
    color: white;
    padding: 7px 16px;
    border-radius: 20px;
    letter-spacing: 0.5px;
    font-weight: 500;
    box-shadow: 0 2px 8px rgba(26,92,138,0.18);
  }

  .card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    max-width: 800px; /* 720 → 760 → 800 le 28/09/2026 (Illan : « élargir légèrement », deux fois) */
    margin: 0 auto;
    overflow: hidden;
    box-shadow: 0 4px 20px rgba(26,92,138,0.08);
  }

  /* SPLIT LAYOUT */
  /* Largeurs + position EXACTES de main : ordonnance ≤800px (720 puis 760 le 28/09/2026), visionneuse
     ≥560px/1fr, bloc centré (margin:0 auto) plafonné à 1500px. Le header et la
     liste partagent la même max-width:1500 + margin:0 auto → ils font pile la
     largeur ordonnance+visionneuse et s'alignent sur les mêmes bords verticaux. */
  .split-wrapper {
    display: grid;
    grid-template-columns: minmax(0, 800px) minmax(560px, 1fr);
    gap: 12px;
    max-width: 1500px;
    margin: 0 auto;
    align-items: start;
  }

  /* ── La visionneuse ne réserve ses 560 px que si elle est OUVERTE ──
     Fermée, elle les gardait quand même (largeur 560, hauteur 0 : mesuré) et
     affamait la prescription : entre 1000 et 1560 px de large, la fiche ne
     recevait que 389 à 708 px au lieu de ses 720, ses colonnes se resserraient
     et le texte des cases se tronquait (« montage stellit… »).
     On retire donc ce plancher par défaut — et RIEN D'AUTRE : la fiche reste
     plafonnée à ses 720 px d'origine. Lui donner toute la largeur a été essayé
     et REJETÉ (elle s'étirait à 1238 px, méconnaissable).
     Crochet = la classe .visible, déjà posée/retirée par form-editor.js.
     Aucune logique nouvelle ; :has() est disponible sur tous les moteurs. */
  .split-wrapper { grid-template-columns: minmax(0, 800px) minmax(0, 1fr); }
  .split-wrapper:has(.preview-panel.visible) {
    grid-template-columns: minmax(0, 800px) minmax(560px, 1fr);
  }

  /* ── Cas FUSIONNÉ : on va chercher la place libre à droite de la page ──
     L'app est centrée et plafonnée à 1500 px. Sur un écran plus large il reste
     des centaines de pixels de fond décoratif inutilisés à droite — et c'est
     précisément ce qu'Illan a pointé (01/09) : « regarde l'espace que j'ai en
     horizontal et pourtant ça se met en vertical ».
     Quand la visionneuse contient plusieurs bons (et SEULEMENT là : le crochet
     est .fusion-docs-un, qui n'existe que dans ce cas), le bloc s'élargit et la
     visionneuse récupère ~380 px. Elle passe alors la barre des 450 px par
     feuille et pose les bons CÔTE À CÔTE, à 540 px chacun, sans aucun ascenseur.
     La fiche de gauche NE BOUGE PAS de taille (toujours ses 720 px) : c'est la
     colonne de droite qui prend tout le surplus.
     Sur un écran qui n'a pas ce surplus, il n'y a rien à récupérer et
     on retombe naturellement sur l'empilement vertical.
     Le bloc s'étend UNIQUEMENT VERS LA DROITE : sa marge gauche est figée à ce
     qu'elle valait (le centrage d'un bloc de 1500), donc la fiche de gauche ne
     bouge pas d'un pixel à l'ouverture — seul le vide de droite est consommé.
     C'est ce qu'un simple max-width plus grand ne ferait pas : re-centré, tout
     le bloc glisserait de ~190 px vers la gauche à chaque cas fusionné. */
  .split-wrapper:has(.fusion-docs-un) {
    max-width: none;
    margin-left: max(0px, calc((100% - 1500px) / 2));
    margin-right: 0;
  }
  /* Le résumé IA n'a rien demandé : il garde sa largeur habituelle, aligné sur
     le bord gauche de la visionneuse. */
  .split-wrapper:has(.fusion-docs-un) #ai-summary { max-width: 768px; }

  /* Maquette : pas de carte englobante — colonne .fstack de cartes flottantes */
  .split-wrapper .card {
    max-width: 100%;
    margin: 0;
    background: transparent;
    border: none;
    box-shadow: none;
    overflow: visible;
    border-radius: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  /* Clip horizontal : la note déborde volontairement dans la marge droite ;
     on évite une scrollbar horizontale sur écrans étroits (clip n'affecte ni le
     scroll vertical ni un éventuel sticky). */
  #app-content { overflow-x: clip; }

  /* ⚠️ NE PAS poser de min-width sur #prescription-form pour l'empêcher de se
     comprimer : essayé et REJETÉ (mesuré). La colonne de gauche du
     .split-wrapper est plafonnée à 720 px (cf. sa grid-template-columns), donc
     la fiche déborderait de 290 px et chevaucherait la visionneuse.
     Le vrai problème est en dessous : la fiche RÉCLAME 1010 px mais la mise en
     page ne lui en accorde jamais plus de 720 — d'où le texte tronqué. Ça se
     règle en la faisant se replier, pas en la forçant à s'élargir. */

  /* Colonne droite (visionneuse + résumé IA) : contexte de positionnement pour
     la « note cabinet » posée dans la marge, à droite de la visionneuse. */
  .split-right { position: relative; }

  /* Note cabinet — rappel posé À DROITE de la visionneuse. DOIT SAUTER AUX YEUX :
     post-it JAUNE VIF, gros texte, léger angle, ombre chaude, pop à l'apparition.
     Couleurs = tokens --note-* (variante dark ambrée) → dark mode automatique,
     aucune couleur codée en dur. Markup posé par gcAfficherRappelNote. */
  /* La note est le CONTENU de la fenêtre flottante partagée (.ais-pop, posée sous le
     résumé IA par js/ai-summary.js — même mécanique que le schéma dentaire, demande
     Illan 17/08). Elle ne se positionne donc plus elle-même : cadre, largeur, scroll
     et animation viennent de la fenêtre ; il ne reste ici que l'encre du post-it.
     PLUS D'INCLINAISON (17/08) : elle se redressait au survol, ce qui bougeait le
     texte sous la souris — pénible à lire. Elle est droite, tout le temps. */
  .gc-note {
    color: var(--note-text);
    font-size: 0.92rem;
    line-height: 1.5;
  }
  /* Habillage post-it de la fenêtre quand c'est la note qu'elle porte. Deux classes
     dans le sélecteur : .ais-pop (déclaré plus bas dans ce fichier) peint sinon son
     fond neutre par-dessus. */
  .ais-pop.ais-pop--note {
    background: linear-gradient(168deg, var(--note-bg1) 0%, var(--note-bg2) 100%);
    border: 2px solid var(--note-border);
    box-shadow: var(--note-shadow);
    color: var(--note-text);
    /* Ouverte à droite du résumé, elle prend toute la marge libre (placement JS).
       Trop grande pour la place qu'on veut lui laisser ? La poignée du coin bas-droit
       permet de la rétrécir — dès qu'on y touche, le JS ne réécrit plus sa taille,
       il ne fait plus que la suivre (Illan 04/09). */
    resize: both;
    min-width: 240px;
    min-height: 120px;
  }
  /* Plus de bandeau de titre (Illan 04/09) : le ✕ vit dans le coin de la note et
     le nom du praticien occupe la 1re ligne — une ligne de hauteur regagnée. */
  .gc-note--rules { position: relative; }
  /* La fenêtre a maintenant une hauteur bornée : elle DÉFILE. Un ✕ en absolu sortait
     de vue au premier scroll et on ne pouvait plus fermer. Barre de hauteur nulle,
     collée en haut du cadre qui défile → le ✕ reste toujours atteignable, sans
     coûter une ligne. */
  .gc-note-xbar { position: sticky; top: 0; z-index: 2; height: 0; display: flex; justify-content: flex-end; }
  .gc-note-x { position: relative; top: -2px; right: -2px; }
  .gc-note-btn {
    background: color-mix(in srgb, var(--note-accent) 14%, transparent);
    border: none;
    cursor: pointer;
    color: var(--note-accent);
    font-size: 0.85rem;
    line-height: 1;
    padding: 3px 7px;
    border-radius: 8px;
    transition: background var(--dur-fast);
  }
  .gc-note-btn:hover { background: color-mix(in srgb, var(--note-accent) 28%, transparent); }
  .gc-note-cab {
    padding-right: 26px;            /* le ✕ du coin ne recouvre jamais le nom */
    font-weight: 800;
    font-size: 0.95rem;
    color: var(--note-accent);
    margin-bottom: 8px;
    padding-bottom: 8px;
    border-bottom: 1.5px dashed color-mix(in srgb, var(--note-accent) 38%, transparent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .gc-note-body {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 0.92rem;
    font-weight: 500;
  }
  /* Post-it « Rules » : ligne anglaise (ce qui part sur le PDF fournisseur) + séparation entre notes. */
  .gc-note-en {
    margin-top: 3px;
    font-size: 0.8rem;
    font-style: italic;
    color: color-mix(in srgb, var(--note-text) 62%, transparent);
    white-space: pre-wrap;
    word-break: break-word;
  }
  .gc-note--rules .gc-note-body + .gc-note-body,
  .gc-note--rules .gc-note-en + .gc-note-body {
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1.5px dashed color-mix(in srgb, var(--note-accent) 30%, transparent);
  }
  /* INVENTAIRE DES RÈGLES DU CLIENT (17/08). Le post-it ne montre plus seulement le
     texte qui part sur le bon fournisseur : il liste TOUTES les conventions du
     praticien/cabinet, même celles qui n'écrivent rien (acte remplacé, acte par
     défaut) — sinon on « recorrige » une fiche que la règle avait eu raison de
     modifier. La pastille dit ce que la règle FAIT.
     Toutes les teintes se mélangent au fond du post-it (tokens --note-*) : le clair
     et le dark suivent tout seuls, zéro hex en dur. */
  .gc-note-sec {
    margin: 10px 0 4px;
    padding-top: 8px;
    border-top: 1.5px dashed color-mix(in srgb, var(--note-accent) 30%, transparent);
    font-family: 'DM Mono', monospace;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--note-accent) 78%, var(--note-text));
  }
  /* Le nom du client porte déjà un trait de séparation : pas deux à la suite. */
  .gc-note-cab + .gc-note-sec { margin-top: 2px; padding-top: 0; border-top: none; }
  /* Flux inline (pas flex) : la pastille ouvre la première ligne et le texte reprend
     toute la largeur en dessous — dans 228 px, c'est ce qui tient le plus. */
  .gc-note-rule {
    padding: 5px 0;
    font-size: 0.78rem;
    line-height: 1.4;
    word-break: break-word;
    --gcnr-h: var(--note-accent);
  }
  .gc-note-rule + .gc-note-rule {
    border-top: 1px dashed color-mix(in srgb, var(--note-accent) 22%, transparent);
  }
  .gc-note-rule-tag {
    display: inline-block;
    margin-right: 5px;
    padding: 2px 6px;
    border-radius: 99px;
    font-family: 'DM Mono', monospace;
    font-size: 0.55rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--note-text);
    /* 20 % de teinte : mesuré, c'est le maximum qui garde ≥ 4.5:1 avec l'encre du
       post-it DANS LES DEUX THÈMES (en dark, une teinte claire délave le fond ambré
       et le texte crème passe sous la barre). Le liseré porte la couleur, pas le fond. */
    background: color-mix(in srgb, var(--gcnr-h) 20%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gcnr-h) 60%, transparent);
  }
  /* Une teinte par famille d'action : ce qui MODIFIE la fiche (acte remplacé/imposé,
     acte retiré) tire vers le rouge — c'est là qu'on risque de défaire le travail
     de la règle. */
  .gc-note-rule--com  { --gcnr-h: var(--accent); }
  .gc-note-rule--acte { --gcnr-h: var(--danger); }
  .gc-note-rule--off  { --gcnr-h: var(--danger); }
  .gc-note-rule--def  { --gcnr-h: var(--teal); }
  .gc-note-rule--sol  { --gcnr-h: var(--success); }
  /* Champ d'édition inline (✎). Thémé via tokens --note-* → clair + dark OK. */
  .gc-note-textarea {
    width: 100%;
    box-sizing: border-box;
    min-height: 96px;
    resize: vertical;
    background: color-mix(in srgb, var(--note-bg1) 45%, var(--surface));
    color: var(--note-text);
    border: 1.5px solid var(--note-border);
    border-radius: 9px;
    padding: 8px 10px;
    font-family: inherit;
    font-size: 0.9rem;
    line-height: 1.45;
    outline: none;
  }
  .gc-note-textarea:focus { border-color: var(--note-accent); }

  .preview-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 4px 24px rgba(0,0,0,0.06);
    /* Panneau normal, pose a cote du formulaire : il defile avec la page
       et ne "suit" jamais le scroll (pas de sticky/fixed). */
    position: static;
    display: none;
  }

  .preview-panel.visible { display: block; }

  /* Header viewer = label muted majuscule (maquette .ws-viewer .h), pas de barre */
  .preview-panel-header {
    background: transparent;
    color: var(--muted);
    padding: 14px 16px 10px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  /* Le titre « Prescription originale » a été retiré (18/09/2026) : restent
     l'étiquette « 🔗 N bons » et le nom du fichier, à gauche ; la barre d'outils
     à droite. Un clic sur l'en-tête (hors bouton) montre le bon en grand, comme un
     clic sur le document — le geste que faisait « ⛶ Agrandir ». */
  .preview-panel-header { cursor: zoom-in; }
  /* L'étiquette « 🔗 N bons » et le nom du fichier suivent les outils, poussés à
     droite — la gauche appartient aux GESTES (Illan 18/09/2026). */
  .pvh-titre { display: flex; align-items: center; gap: 7px; min-width: 0;
    margin-left: auto; color: var(--muted); }
  /* Les outils : tous à la MÊME HAUTEUR, dans l'ordre du bloc « Scan » de
     « Voir fiche ». Ils enveloppent plutôt que de pousser le panneau. */
  .pvh-outils { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    justify-content: flex-start; text-transform: none; cursor: auto; min-width: 0; }
  /* Gabarit un cran sous la famille (Illan 30/09/2026) : avec 3D + Digilab +
     plateforme + photo, « Ajouter photo » passait à la ligne et « Transférer »
     se centrait sur deux lignes. Même réglage que les cartes d'actions de
     « Voir fiche » (.vf-acts-grp, js/bouton-3d.js). */
  .preview-panel-header .bqv { height: 30px; font-size: .74rem; padding: 3px 11px 3px 3px; gap: 6px; }
  .preview-panel-header .bqv .bqv-ic { width: 24px; height: 24px; }
  .preview-panel-header .pvh-outils .b3d { height: 30px; padding: 3px 11px 3px 3px; font-size: .74rem; gap: 6px; }
  .preview-panel-header .pvh-outils .b3d .b3d-sc { width: 24px; height: 24px; }
  /* « Transférer » : en haut à droite, après l'étiquette du document — calé sur
     la PREMIÈRE ligne si la barre d'outils enveloppe quand même. */
  .pvh-partager { flex: none; align-self: flex-start; margin-left: 8px; text-transform: none; letter-spacing: normal; cursor: pointer; }
  /* Le document dit lui-même ce que le clic va faire. */
  .preview-panel #preview-panel-img { cursor: zoom-in; }
  /* Cas fusionné : « 🔗 2 bons » collé au titre de l'en-tête (aucune hauteur
     consommée, à la place du bandeau supprimé). ÉTIQUETTE, pas bouton : elle a
     été cliquable un temps (saut au bon suivant) et ça induisait en erreur —
     les bons sont déjà tous à l'écran. Donc ni curseur main, ni survol.
     Mêmes tokens que `.pvh-btn` : contraste du libellé mesuré à 4,70:1 en nuit
     et 6,92:1 en clair (une version à fond teinté tombait à 4,24, sous le seuil
     du petit gras). text-transform:none : l'en-tête est en majuscules. */
  .pvh-chip {
    display: inline-flex; align-items: center;
    border-radius: 999px; padding: 3px 9px;
    font-size: 0.72rem; font-weight: 600; line-height: 1;
    text-transform: none; letter-spacing: 0;
    background: var(--surface-2);
    border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
    color: var(--accent-text);
  }

  /* Corps viewer = fond surface (clair/dark via tenant), image inset radius 12
     comme l'image-slot de la maquette. Les « bordures » autour du scan sont
     donc de la couleur surface, jamais du noir. */
  .preview-panel-body {
    padding: 0 14px 14px;
    /* La fiche COLLE en haut (align flex-start) : centrée verticalement dans un
       panneau à min-height 600, une fiche courte flottait au milieu avec du vide
       au-dessus ET en dessous. Le min-height réduit sert seulement d'assise
       pendant le chargement ; ensuite le panneau épouse le contenu. */
    min-height: 240px;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    background: var(--surface);
    position: relative;
  }

  .preview-panel-body img {
    width: 100%;
    max-height: 90vh;
    object-fit: contain;
    display: block;
    border-radius: 12px;
    border: 1px solid var(--border);
  }

  .preview-panel-body iframe {
    width: 100%;
    height: 90vh;
    border: none;
    background: var(--surface);
  }

  .preview-panel-body .pdf-embed {
    width: 100%;
    height: 60vh;
    border: none;
  }

  .preview-panel-empty {
    color: var(--muted);
    font-size: 0.85rem;
    text-align: center;
    padding: 40px 20px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
  }
  /* Pastille halo de l'état vide (recette .pmt-empty adaptée surface claire,
     keyframe pmtHalo réutilisée). Cible le 1er enfant : couvre
     AUSSI les états vides regénérés par form-editor.js / folder-scanning.js
     (même squelette <div>emoji</div><div>texte</div>). */
  .preview-panel-empty > div:first-child {
    position: relative; width: 64px; height: 64px; border-radius: 20px;
    display: grid; place-items: center;
    font-size: 2rem; line-height: 1;
    background: color-mix(in srgb, var(--accent) 8%, var(--surface));
    border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border));
    box-shadow: var(--shadow-sm);
    margin-bottom: 12px;
  }
  .preview-panel-empty > div:first-child::before {
    content: ""; position: absolute; inset: -10px; border-radius: 25px; z-index: -1;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--teal) 32%, transparent), transparent 72%);
    filter: blur(6px); opacity: .5;
    animation: pmtHalo 2.8s ease-in-out infinite;
  }

  .preview-zoom {
    position: absolute;
    bottom: 12px;
    right: 12px;
    display: flex;
    gap: 6px;
  }

  .preview-zoom button {
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--muted);
    border-radius: 6px;
    width: 30px;
    height: 30px;
    font-size: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .preview-zoom button:hover { background: var(--border); }

  /* ═══ MODULE « Résumé IA » (sous la fiche originale) ═══════════════════
     Miroir FR du PDF anglais + schéma dentaire color-codé.
     Schéma : unitaire=bleu · solidarisé=vert · adjointe=rose · implant=violet
              · extraction=croix rouge. Rendu par js/ai-summary.js. */
  #ai-summary { display: none; margin-top: 12px; }
  .ais {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,.06);
    color: var(--text); font-size: 0.76rem;
  }
  /* Rendu lecture seule réutilisé hors formulaire (fiche dentiste) : fixe la
     base compacte sinon les libellés héritent de la grande police du contexte. */
  .ais-ro { font-size: 0.76rem; line-height: 1.5; color: var(--text); }
  .ais-ro .ais-acts { padding: 0; }
  .ais-bar { background: var(--grad); color:#fff; font-weight:700; font-size:.86rem; padding:8px 13px; }

  /* En-tête : labo > cabinet > Dr > patient .......... livraison (rouge) */
  .ais-headwrap { border-bottom:1px solid var(--border); }
  .ais-head { display:flex; align-items:center; gap:6px; flex-wrap:wrap; padding:5px 10px 3px; }
  /* Badge « même patient ×2 » : calé à droite pour tomber JUSTE AU-DESSUS de la
     date de livraison (.ais-flags-row .ais-livr, elle aussi en margin-left:auto).
     Couleurs et mode nuit viennent de .doublon-badge (rien à redéfinir ici). */
  .ais-head .doublon-badge { margin-left:auto; }
  .ais-flags-row { display:flex; align-items:center; gap:5px; flex-wrap:wrap; padding:0 10px 5px; }
  .ais-flags-row .ais-livr { margin-left:auto; }
  /* Le patient + l'interrupteur « Saisie continue » à droite de SA ligne (28/09/2026) : le bloc
     remplit la fin de ligne ; le nom se raccourcit (…) plutôt que de faire passer l'interrupteur à la ligne. */
  .ais-pat-grp { flex:1 0 auto; max-width:100%; min-width:0; display:flex; align-items:center; gap:6px; }
  .ais-pat-grp .ais-pat { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ais-pat-grp .ais-cont { margin-left:auto; flex:none; height:18px; margin-block:-2px; }
  .ais-pat-grp .doublon-badge { margin-left:0; flex:none; }
  /* Version courte (quand le patient passerait à la ligne) : la glissière et le nombre seuls. */
  .ais-cont.court > span:not(.ais-sw) { display:none; }
  .ais-head-l { display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0; }
  .ais-head-r { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
  .ais-lab { font-family:'DM Mono',monospace; background:#e8f4fb; color:#1a5c8a; border:1px solid #cfe3f2; border-radius:5px; padding:1px 7px; font-weight:800; font-size:.76rem; }
  .ais-cab { font-weight:700; }
  .ais-dr { color: var(--text); font-weight:700; }
  .ais-pat { font-weight:700; }
  /* Caducée du praticien (emoji, comme l'espace dentiste) : à la taille des objets voisins. */
  .ais-hico { font-size:14px; line-height:1; flex:none; }
  .ais-pat-det { color: var(--muted); font-weight:500; font-size:.7rem; }
  .ais-livr { color:#c0392b; font-weight:800; font-size:.74rem; white-space:nowrap; background:#fdecea; border:1px solid #f5c6c2; border-radius:5px; padding:1px 8px; }
  /* Largeur FIXE + contenu centré → la flèche ⇄ voisine ne bouge jamais
     quand le nom du sous-traitant change. Clics rapides fiables. */
  .ais-fourn { color:#1a5c8a; font-weight:800; font-size:.68rem; white-space:nowrap; background:#eef3f7; border:1px solid #d0e0ea; border-radius:5px; padding:1px 8px; display:inline-flex; align-items:center; justify-content:center; width:112px; box-sizing:border-box; flex:none; }
  /* Couleur par sous-traitant — identification au premier coup d'œil. La teinte
     vient de la config du labo : js/demo-mode.js n'injecte que la variable --f
     de chaque classe .fourn-c0…c7, toute la présentation est ici (donc mode nuit
     et changement de labo suivis automatiquement). */
  .ais-fourn[class*="fourn-c"] { background:color-mix(in srgb, var(--f, var(--accent)) 14%, transparent);
    color:color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); border-color:color-mix(in srgb, var(--f, var(--accent)) 45%, transparent); }
  /* Petite flèche de bascule entre les deux sous-traitants (position stable à côté du chip) */
  .ais-fourn-sw { cursor:pointer; font-weight:800; font-size:.68rem; line-height:1; border-radius:5px; padding:2px 6px; background:transparent; border:1px solid var(--border); color:var(--accent-text); }
  .ais-fourn-sw:hover { background:color-mix(in srgb, var(--accent) 12%, transparent); }
  /* ── Pastilles d'état de la ligne prescription : TAILLE UNIFORME + texte explicite ──
     Base commune .pi-badge (mêmes métriques pour toutes), variantes de couleur dessous. */
  /* ⚠️ -webkit-text-fill-color OBLIGATOIRE : .pi-num peint son texte en dégradé
     (background-clip:text + fill transparent, style.css .pi-num) et cette
     transparence S'HÉRITE → sans cette ligne le texte des badges est invisible. */
  .pi-badge { display:inline-flex; align-items:center; gap:2px; height:15px; padding:0 5px; font-size:.55rem; font-weight:800; border-radius:4px; margin-left:3px; white-space:nowrap; line-height:1; vertical-align:middle; border:1px solid transparent; box-sizing:border-box; background-clip:border-box; -webkit-background-clip:border-box; -webkit-text-fill-color:currentColor; font-family:'DM Sans',system-ui,sans-serif; }
  .pi-badge-refaire { background:#cc0000; color:#fff; border-color:#a30000; }
  .pi-badge-standby { background:#8a939b; color:#fff; border-color:#737c84; }
  .pi-badge-annule { background:#475569; color:#fff; border-color:#334155; }
  /* Remis en production : la fiche reste LIVRÉE et facturée, ce badge ne fait que
     signaler qu'elle est refaite ailleurs → teinte sobre, pas une alerte. */
  .pi-badge-remis { background:#0e7490; color:#fff; border-color:#0b5d73; }
  /* Problème signalé par le labo (note interne, js/probleme-cas.js). Rouge orangé :
     il doit se distinguer du rouge « À REFAIRE » (demande du dentiste), qui est un
     autre sujet — ici le travail n'est pas en cause, c'est le cas qui coince. */
  /* Seul badge CLIQUABLE de la ligne (il ouvre la raison du problème) : c'est un
     <button>, on lui rend les métriques des autres badges et un survol qui se voit. */
  .pi-badge-probleme { background:#e0630f; color:#fff; border-color:#b44d09;
    font-family:inherit; letter-spacing:.2px; cursor:pointer; }
  .pi-badge-probleme:hover { background:#c85608; }
  /* Soldée automatiquement (60 j sans livraison) : livraison DÉDUITE, pas
     constatée → teinte ambre sobre, ni alerte rouge ni statut normal. */
  .pi-badge-auto { background:#b45309; color:#fff; border-color:#92400e; }
  /* Portail fournisseur Chine : badge statut pose par le fournisseur (clic = panneau) */
  .pi-badge-fourn { background:var(--surface-2); color:var(--text); border:1px solid var(--border); font-weight:700; cursor:pointer; transition: transform var(--dur-fast), box-shadow var(--dur-fast); }
  .pi-badge-fourn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
  .pi-badge-fourn-alerte { box-shadow: 0 0 0 1px color-mix(in srgb, #dc2626 45%, transparent); }
  /* Empreinte physique (part en colis, pas de scan Digilab) : marqueur 📦 —
     teinte teal via tokens → dark mode + tenant automatiques (jamais de hex). */
  .pi-badge-phys { background: color-mix(in srgb, var(--teal) 15%, var(--surface)); color: var(--text); border: 1px solid color-mix(in srgb, var(--teal) 40%, var(--border)); font-weight: 700; }
  /* Réservation de fiche multi-utilisateur : badge « 👤 ouverte par » + compteur de lot */
  .fiche-claim-badge { background:#fff3cd; color:#7a5b00; border-color:#f0dfa0; }
  /* Bandeau « X a repris cette fiche » au-dessus du formulaire (js/fiche-claim.js).
     Tokens seulement (--warn existe en clair ET en sombre) → dark mode automatique.
     Une phrase + une action, pas de hauteur réservée : le nœud n'existe que quand
     il a quelque chose à dire. Entrée animée en opacité/translation (R25). */
  .fiche-reprise { display:flex; align-items:center; flex-wrap:wrap; gap:8px 12px; margin:8px 10px 0;
    padding:8px 12px; border-radius:10px; font-size:.8rem; font-weight:600; color:var(--text);
    background:color-mix(in srgb, var(--warn) 16%, var(--surface));
    border:1px solid color-mix(in srgb, var(--warn) 55%, var(--border));
    animation:fiche-reprise-in var(--dur-enter, .18s) var(--ease-out, ease-out); }
  .fiche-reprise-txt { flex:1 1 240px; }
  .fiche-reprise-btn { padding:5px 10px; border-radius:8px; font-size:.75rem; font-weight:700; cursor:pointer;
    color:var(--text); background:var(--surface); border:1px solid var(--border); }
  .fiche-reprise-btn:hover { border-color:var(--warn); }
  @keyframes fiche-reprise-in { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:none; } }
  @media (prefers-reduced-motion: reduce) { .fiche-reprise { animation:none; } }
  /* Fusion de bons : badge « même patient » + popup de choix + sections visionneuse empilée */
  .doublon-badge { background:#e67e22; color:#fff; border-color:#cf6d15; cursor:pointer; }
  .doublon-badge:hover { background:#cf6d15; }
  /* Cas fusionné : badge permanent « 🔗 N BONS » (clic = documents empilés) */
  /* Étiquette, pas bouton (01/09) : ni curseur main, ni survol — le clic a été
     retiré, il laissait croire à une action propre au badge alors que la ligne
     entière ouvre déjà la fiche, laquelle montre tous les bons. */
  /* Ambre doré = « cas relié », le MÊME repère côté labo et côté atelier (portail) —
     Illan, 30/09/2026 : « comme ça les interfaces se parlent ». Lisible en clair comme en sombre. */
  .fusion-fusionne-badge { background:#c2780a; color:#fff; border-color:#a16207; box-shadow:0 1px 3px rgba(194,120,10,.35); }
  /* Entrée/sortie animées (Règle 25) : l'overlay porte SA propre animation →
     règles de sortie DÉDIÉES (la cascade perdrait la règle .is-closing générique). */
  .fusion-pop { position:fixed; inset:0; background:rgba(15,35,55,.55); z-index:1400; display:flex; align-items:center; justify-content:center; font-family:'DM Sans',system-ui,sans-serif;
    animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
  .fusion-pop-card { background:var(--surface, #fff); color:var(--text, #1c2a35); border-radius:14px; padding:20px; width:92%; max-width:560px; max-height:88vh; overflow:auto;
    box-shadow: var(--shadow-md);
    animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
  .fusion-pop.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
  .fusion-pop.is-closing .fusion-pop-card { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }
  .fusion-pop-card h3 { margin:0 0 8px; font-size:1.05rem; }
  .fusion-pop-sub { font-size:.8rem; color:var(--muted, #7a8b98); margin-bottom:14px; line-height:1.45; }
  .fusion-btn-merge { background:var(--accent, #1a5c8a); color:#fff; }
  .fusion-btn-merge:hover { filter:brightness(1.08); }
  .fusion-btn-keep { background:color-mix(in srgb, var(--accent) 8%, var(--surface)); color:var(--accent-text); border:1px solid color-mix(in srgb, var(--accent) 26%, var(--border)) !important; }
  .fusion-btn-keep:hover { background:color-mix(in srgb, var(--accent) 14%, var(--surface)); }
  .fusion-btn-cancel { background:transparent; color:var(--muted, #999); }
  .fusion-btn-cancel:hover { color:var(--text); }
  /* Modale « Fusionner avec… » (clic droit) : recherche + liste des bons,
     même cabinet en tête */
  .fusion-rech-input { width:100%; box-sizing:border-box; padding:10px 12px; border:1px solid var(--border, #d0e0ea); border-radius:9px; font-size:.92rem; font-family:inherit; margin:2px 0 10px; background:var(--surface, #fff); color:var(--text, #1c2a35);
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
  .fusion-rech-input:focus { outline:none; border-color:var(--accent, #1a5c8a); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
  .fusion-rech-list { max-height:46vh; overflow-y:auto; display:flex; flex-direction:column; gap:6px; }
  .fusion-rech-row { padding:9px 12px; border:1px solid var(--border, #e2ebf1); border-radius:9px; cursor:pointer; font-size:.84rem; line-height:1.45;
    transition: background var(--dur-fast), border-color var(--dur-fast); }
  .fusion-rech-row:hover { background:color-mix(in srgb, var(--accent) 7%, var(--surface)); border-color:color-mix(in srgb, var(--accent) 35%, var(--border)); }
  /* Nom très ressemblant = sûrement le bon recherché → ligne orange, en tête */
  .fusion-rech-row.fusion-rech-ressemble { background:color-mix(in srgb, var(--warn) 12%, var(--surface)); border-color:color-mix(in srgb, var(--warn) 55%, var(--surface)); }
  .fusion-rech-row.fusion-rech-ressemble:hover { background:color-mix(in srgb, var(--warn) 20%, var(--surface)); border-color:color-mix(in srgb, var(--warn) 70%, var(--surface)); }
  .fusion-rech-tag-ressemble { background:color-mix(in srgb, var(--warn) 78%, var(--danger)); color:#fff; border-radius:10px; padding:1px 8px; font-size:.68rem; font-weight:700; margin-left:4px; vertical-align:1px; }
  .fusion-rech-row-sub { color:var(--muted, #7a8b98); font-size:.75rem; margin-top:1px; }
  .fusion-rech-memecab { background:color-mix(in srgb, var(--accent) 9%, var(--surface)); color:var(--accent-text); border:1px solid color-mix(in srgb, var(--accent) 22%, var(--border)); border-radius:10px; padding:1px 8px; font-size:.68rem; font-weight:700; margin-left:4px; vertical-align:1px; }
  .fusion-rech-standby { color:var(--muted, #999); font-size:.72rem; margin-left:4px; }
  .fusion-rech-vide { text-align:center; color:var(--muted, #999); padding:16px; font-size:.84rem; }
  /* Actes à la NORME du résumé IA (buildAisActs), comme l'onglet « À décaler » */
  .fusion-actes-ais { margin-top:4px; }
  .fusion-actes-ais .ais-acts { padding:0; }
  /* Chips d'actes utiles — SECOURS seulement (vieux cache sans ai-summary).
     Tokens sémantiques d'acte (--acte-*) : dark + cohérence résumé IA gratuits. */
  .fusion-acte-chip { display:inline-block; background:var(--acte-conj-bg); color:var(--acte-conj-fg); border:1px solid color-mix(in srgb, var(--acte-conj-fg) 22%, var(--surface)); border-radius:9px; padding:0 7px; font-size:.72rem; font-weight:600; margin:1px 3px 1px 0; line-height:1.55; vertical-align:1px; }
  .fusion-acte-chip.is-adjointe { background:var(--acte-adj-bg); color:var(--acte-adj-fg); border-color:color-mix(in srgb, var(--acte-adj-fg) 25%, var(--surface)); }
  /* Visionneuse UNIQUE des bons fusionnés : toutes les feuilles défilent dans
     UN SEUL ascenseur. Conteneur NU (01/09) — ni fond gris, ni marge intérieure,
     ni bandeau, ni intertitres : c'était ~130 px de hauteur pris pour redire ce
     que les feuilles montrent. Le compte des bons est dans l'en-tête de
     l'aperçu (.pvh-chip), collée au titre, qui ne coûte aucune hauteur. */
  /* RÈGLE ARRÊTÉE AVEC ILLAN LE 01/09 — la relire avant de retoucher quoi que
     ce soit ici, quatre variantes ont déjà été essayées et refusées.
     JAMAIS de défilement horizontal, et une feuille toujours lisible :
       • s'il y a la place de mettre les bons CÔTE À CÔTE avec au moins 470 px
         chacun → côte à côte, tout est visible d'un coup, aucun ascenseur ;
       • sinon → on repasse À LA VERTICALE, feuilles empilées, avec l'ascenseur
         vertical du bloc si besoin. Le bloc reste plafonné à 74vh justement
         pour que le résumé IA ne soit pas repoussé en bas de page.
     La feuille est plafonnée à 540 px (max-width plus bas) : c'est la taille
     validée à l'œil — « 366 px illisible », « 766 px trop gros ».
     Deux colonnes AU PLUS (plancher calc(50% - 3px)) : jamais trois miniatures. */
  .fusion-docs-un { width:100%; min-width:0; box-sizing:border-box; background:transparent; padding:0; max-height:74vh; overflow-y:auto; overflow-x:hidden; display:grid; grid-template-columns:repeat(auto-fit, minmax(max(450px, calc(50% - 3px)), 1fr)); align-content:start; gap:6px; }
  /* max-width 540 = la taille validée : la feuille ne grossit pas au-delà même
     si la colonne est large (sinon on retombe sur le « trop gros » pleine
     largeur). min-width:0 est indispensable : sans lui une feuille refuse de
     descendre sous la largeur de son contenu et déborde de sa colonne. */
  .fusion-doc-un-body { width:100%; min-width:0; max-width:540px; margin-inline:auto; min-height:30px; }
  /* Téléphone : une colonne, pleine largeur — l'écran est déjà étroit, il n'y a
     ni place pour deux feuilles ni marge à rogner sur une. Crochet = la classe
     posée par index.html, JAMAIS un @media (max-width:768px) : le S24 rend
     au-delà de 768 px (Règle 21). */
  /* Popup « Fiche originale » de l'écran À décaler (#dc-fiche-pop) : là, le bon
     est SEUL à l'écran — pas de résumé IA ni de formulaire à côté. La feuille
     remplit donc sa colonne (le plafond 540 px ci-dessus, calibré pour le
     panneau d'aperçu, ne laissait que des marges vides dans ce popup large). */
  #dc-fiche-pop .fusion-doc-un-body { max-width:none; }
  #dc-fiche-pop .fusion-docs-un { max-height:none; }
  html.mobile-zoom-default .fusion-docs-un { grid-template-columns:1fr; }
  html.mobile-zoom-default .fusion-docs-un .fusion-doc-un-body { max-width:none; }
  /* Téléphone : les feuilles l'une SOUS l'autre, pleine largeur. Le défilement
     horizontal est proscrit sur mobile (Règle 21) et l'écran est déjà étroit —
     il n'y a ni place pour deux feuilles, ni marge à rogner sur une.
     Crochet = la classe posée par index.html, JAMAIS un @media (max-width:768px) :
     le S24 rend au-delà de 768 px. */
  html.mobile-zoom-default .fusion-docs-un { flex-direction:column; overflow-x:hidden; }
  html.mobile-zoom-default .fusion-docs-un .fusion-doc-un-body { flex:0 0 auto; width:100%; }
  /* Chaque feuille remplit SA colonne, proportions gardées. */
  .fusion-docs-un .fusion-doc-un-body img { position:static !important; transform:none !important; cursor:default !important; width:100%; height:auto; }
  /* Idem pour les pages dessinées par la visionneuse PDF interne, qui se pose
     une largeur fixe en style inline (max-width:700px, js/folder-scanning.js) :
     dans une case étroite, ça débordait. */
  .fusion-docs-un .fusion-doc-un-body canvas { width:100% !important; max-width:100% !important; height:auto !important; }
  /* Boutons zoom par feuille : inutiles/cassés dans la vue empilée (id dupliqué,
     positionnés hors écran) → masqués ; le zoom se fait via l'ascenseur. */
  .fusion-docs-un .preview-zoom { display:none !important; }
  /* Aplatir les visionneuses internes (chacune crée sa propre boîte sombre 60vh
     à ascenseur) pour qu'elles deviennent de simples sections du conteneur unique */
  .fusion-docs-un div[id^="pdfjs-container"] { height:auto !important; max-height:none !important; overflow:visible !important; background:transparent !important; padding:0 !important; }
  /* Le bon EN GRAND, par-dessus l'écran (window.ficheEnGrand, js/fiche-render.js) :
     aperçu de saisie ET « Voir fiche ». Fond sombre dans les DEUX thèmes (comme
     une visionneuse photo). Chaque document tient dans la hauteur de l'écran ;
     un cas fusionné aligne ses bons CÔTE À CÔTE (Illan, 29/09/2026). Les
     !important battent les styles inline des visionneuses (img 80vh, cadre PDF
     60vh) et les règles de la pile fusionnée ci-dessus. */
  .fiche-grand-ov { position:fixed; inset:0; z-index:1600; background:rgba(0,0,0,.9); cursor:zoom-out;
    box-sizing:border-box; padding:calc(3 * var(--uzvh, 1vh)) calc(2 * var(--uzvw, 1vw)); overflow:auto; overscroll-behavior:contain; }
  .fiche-grand { width:100%; height:100%; display:flex; align-items:center; justify-content:center; color:#ccc; }
  .fiche-grand-x { position:fixed; top:14px; right:18px; z-index:1; width:40px; height:40px; border-radius:50%;
    border:1px solid rgba(255,255,255,.35); background:rgba(0,0,0,.45); color:#fff; font-size:1.1rem; cursor:pointer; }
  .fiche-grand-ov img { width:auto !important; max-width:100% !important; max-height:100% !important; height:auto !important;
    object-fit:contain; cursor:zoom-out !important; border-radius:8px; box-shadow:0 10px 40px rgba(0,0,0,.5); }
  .fiche-grand-ov div[id^="pdfjs-container"] { width:100% !important; height:100% !important; max-height:none !important;
    background:transparent !important; padding:0 !important; overflow:auto !important; justify-content:center; }
  .fiche-grand-ov canvas { width:auto !important; max-width:100% !important; height:auto !important; max-height:calc(100% - 24px) !important; }
  .fiche-grand-ov iframe { height:100% !important; max-width:1100px; background:#fff !important; border-radius:8px; }
  .fiche-grand-ov .fusion-docs-un { display:flex; flex-direction:row; gap:12px; height:100%; max-height:none; overflow:visible; }
  .fiche-grand-ov .fusion-docs-un .fusion-doc-un-body { flex:1 1 0; max-width:none; height:100%; margin:0;
    display:flex; align-items:center; justify-content:center; }
  .fiche-grand-ov .fusion-docs-un .fusion-doc-un-body canvas { width:auto !important; max-height:calc(100% - 24px) !important; }
  /* Téléphone : les bons l'un SOUS l'autre, pleine largeur, défilement vertical
     (pas de défilement horizontal sur mobile, Règle 21). */
  html.mobile-zoom-default .fiche-grand { height:auto; min-height:100%; }
  html.mobile-zoom-default .fiche-grand-ov .fusion-docs-un { flex-direction:column; height:auto; }
  html.mobile-zoom-default .fiche-grand-ov .fusion-docs-un .fusion-doc-un-body { flex:0 0 auto; height:auto; width:100%; }
  html.mobile-zoom-default .fiche-grand-ov img { max-height:none !important; width:100% !important; }
  .saisie-compteur { order:-1; margin-right:auto; white-space:nowrap; display:inline-flex; gap:6px; align-items:center; }
  /* Pastilles aux codes couleur des chips de statut : attente = ambre,
     en cours = orange, vérifiées = vert */
  /* Taille relevée (11/08) : « 9 en attente » est l'info qui dit s'il reste du
     travail à saisir — elle se lisait à peine à côté des boutons du formulaire. */
  .saisie-compteur .sc-badge { font-size:.84rem; font-weight:800; padding:5px 13px; border-radius:999px;
    letter-spacing:.2px; box-shadow:0 1px 2px rgba(20,45,70,.08); }
  .saisie-compteur .sc-att { background:#fff3cd; color:#856404; }
  .saisie-compteur .sc-enc { background:#ffe3c9; color:#c25e00; }
  .saisie-compteur .sc-ver { background:#d4edda; color:#155724; }
  /* Corps aligné sur le PDF anglais (7,6 pt) : ce sont des ALERTES, elles doivent
     se voir avant le reste — et l'écran et le bon doivent se ressembler. */
  .ais-flag { font-size:.66rem; font-weight:800; letter-spacing:.4px; text-transform:uppercase; padding:3px 9px; border-radius:5px; }
  .ais-flag.urg { background:#ffcdd2; color:#b71c1c; }
  .ais-flag.est { background:#fff3cd; color:#7a5b00; }
  .ais-flag.call { background:#ffcdd2; color:#b71c1c; }
  /* Empreinte physique (part en colis) : teinte teal via tokens → dark-safe. */
  .ais-flag.phys { background: color-mix(in srgb, var(--teal) 16%, var(--surface)); color: var(--text); }
  .ais-flag.scan { background: color-mix(in srgb, var(--accent) 16%, var(--surface)); color: var(--text); }

  /* Schéma dentaire — ouvert dans une PETITE FENÊTRE depuis un bouton (11/08).
     Un dépliant poussait tout le contenu vers le bas à chaque clic ; ici rien ne
     bouge dans la page. Bouton posé à gauche de « Mettre à jour » (résumé du scan)
     et en bas de la fiche « Voir » — même composant (js/ai-summary.js). */
  .ais-schema-tgl { display:inline-flex; align-items:center; gap:7px; align-self:flex-start;
    padding:5px 11px; border-radius:999px; cursor:pointer;
    font:700 .72rem 'DM Sans', system-ui, sans-serif; color:var(--muted);
    background:color-mix(in srgb, var(--accent) 7%, var(--surface));
    border:1px solid color-mix(in srgb, var(--accent) 22%, transparent);
    transition:background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast); }
  .ais-schema-tgl:hover { color:var(--accent-text, var(--accent));
    background:color-mix(in srgb, var(--accent) 14%, var(--surface));
    border-color:color-mix(in srgb, var(--accent) 40%, transparent); }
  .ais-schema-tgl:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .ais-schema-tgl .ic { font-size:.85rem; line-height:1; }
  /* Dans le pied du résumé, il précède « Mettre à jour » (poussé à droite par la
     marge auto du bouton save) — cf. .ais-foot. */
  .ais-foot .ais-schema-tgl { margin-left:auto; }
  .ais-foot .ais-schema-tgl + .ais-save { margin-left:8px; }
  /* Vue lecture seule (fiche « Voir ») : le bouton clôt le bloc, sous la teinte —
     il lui faut de l'air, sinon il se colle à la ligne « Teinte : … ». */
  .ais-ro .ais-schema-tgl { margin:12px 0 4px; }   /* aligné sur la ligne « Teinte » */
  /* Le panneau flottant : posé SOUS le résumé (position calculée en JS), au-dessus
     du contenu, SANS voile — le reste de l'app reste cliquable. */
  /* Sans titre (17/08) : la fenêtre s'ouvre collée au bouton « 🦷 Schéma dentaire »
     qu'on vient de cliquer → le répéter en en-tête ne servait qu'à manger 26 px de
     hauteur. Le ✕ occupe seul le coin, et .ais-pop .ais-schema lui réserve sa
     colonne à droite pour que l'arcade du haut ne passe jamais dessous. */
  .ais-pop { position:fixed; z-index:1500; background:var(--surface); border:1px solid var(--line);
    border-radius:14px; box-shadow:0 18px 50px rgba(0,0,0,.3); padding:12px 12px 10px;
    overflow:auto; outline:none; animation:aisPopIn var(--dur-fast) ease backwards;
    container-type:inline-size; }
  .ais-pop-x { position:absolute; top:6px; right:6px; width:24px; height:24px; border-radius:8px;
    cursor:pointer; border:1px solid var(--line); background:var(--surface); color:var(--muted);
    font-size:12px; line-height:1; transition:background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
  .ais-pop-x:hover { background:color-mix(in srgb,var(--danger) 12%,var(--surface));
    color:var(--danger); transform:rotate(90deg); }
  /* Dans la fenêtre, le schéma n'a plus besoin de séparateur ni de fond teinté. */
  .ais-pop .ais-schema { border:none; background:transparent; padding:0 22px 0 0; }
  /* Fenêtre étroite (petit écran) : les 32 dents ne tiennent plus dans la largeur,
     l'arcade du haut irait sous le ✕ → on la descend sous lui. Mesuré : la colonne
     réservée suffit dès ~400 px, seule la fenêtre plus étroite paie ces 20 px. */
  @container (max-width: 400px) {
    .ais-pop .ais-schema { padding:20px 0 0; }
  }
  @keyframes aisPopIn { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:none; } }
  @media (prefers-reduced-motion: reduce) {
    .ais-schema-tgl { transition:none; }
    .ais-pop { animation:none; }
    .ais-pop-x:hover { transform:none; }
  }
  .ais-schema { padding:6px 11px 5px; border-bottom:1px solid var(--border); background:color-mix(in srgb, var(--accent) 4%, var(--surface)); }
  .ais-sec-t { font-size:.62rem; font-weight:800; text-transform:uppercase; letter-spacing:.5px; color:var(--muted); margin-bottom:5px; }
  .ais-arch { display:flex; justify-content:center; gap:3px; margin:1px 0; }
  .ais-quad { display:flex; gap:2px; }
  /* L'écart de la LIGNE MÉDIANE est porté par la 9e dent, pas par un bloc voisin :
     une pièce qui franchit la médiane (bridge 13→23) doit pouvoir le supprimer et
     se dessiner d'un seul tenant. Avec deux quadrants séparés par une marge, la
     pièce était toujours coupée en deux au milieu. */
  .ais-th.mid { margin-left:9px; }
  .ais-th.mid.jl { margin-left:-3px; }
  .ais-th {
    width:19px; height:22px; border-radius:4px 4px 6px 6px; border:1px solid var(--border);
    background:var(--surface); color:var(--muted); font-size:.56rem; font-weight:700;
    display:flex; align-items:flex-end; justify-content:center; padding-bottom:2px; position:relative;
  }
  /* Couleurs pilotées par la SOURCE UNIQUE js/ai-summary.js (SCHEMA_COULEURS, qui
     pose ces variables au chargement) — la même table alimente le schéma du PDF
     anglais. Pas de valeur de repli, et c'est volontaire : le schéma n'existe que
     si ce module a tourné, c'est lui qui le construit. Changer une couleur = un
     seul endroit (Illan, 04/09/2026). Le mode sombre, plus bas, reste en CSS : il
     ne concerne que l'écran. */
  .ais-th.u    { background:var(--th-u-bg);    border-color:var(--th-u-bd);    color:var(--th-u-tx); }
  .ais-th.s    { background:var(--th-s-bg);    border-color:var(--th-s-bd);    color:var(--th-s-tx); }
  .ais-th.adj  { background:var(--th-adj-bg);  border-color:var(--th-adj-bd);  color:var(--th-adj-tx); }
  .ais-th.imp  { background:var(--th-imp-bg);  border-color:var(--th-imp-bd);  color:var(--th-imp-tx); }
  .ais-th.extr { background:var(--th-extr-bg); border-color:var(--th-extr-bd); color:var(--th-extr-tx); }
  .ais-th.extr::after { content:'✕'; position:absolute; top:0; left:0; right:0; font-size:.62rem; color:var(--th-extr-tx); }
  /* REPÈRES DE FORME — miroir du schéma du PDF anglais (js/export-pdf-en.js).
     Le PDF en a besoin parce qu'il s'imprime en noir et blanc (les cinq teintes y
     deviennent le même gris) ; l'écran les reprend pour qu'Illan retrouve à la
     vérification exactement ce que lira le fournisseur — c'est la règle du
     03/09/2026 : le résumé IA et le PDF disent la même chose.
       implant  → une petite vis (tige + trois filets)
       amovible → une barre : la base de l'appareil vue de profil
     La barre va d'un BORD à l'autre sur une dent soudée (.jl / .jr) : deux dents
     voisines d'une même selle forment ainsi UNE barre continue, pas deux traits. */
  /* La vis occupe le TIERS HAUT de la case, au-dessus du numéro — comme sur le PDF.
     Plus bas et plus grande, elle chevauchait le numéro de dent (Illan, 04/09/2026). */
  .ais-th.imp::before { content:''; position:absolute; top:3.4px; left:50%; margin-left:-2.5px;
    width:5px; height:1.2px; background:currentColor;
    box-shadow:0 2px 0 0 currentColor, 0 4px 0 0 currentColor; }
  .ais-th.imp::after  { content:''; position:absolute; top:2.6px; left:50%; margin-left:-.6px;
    width:1.2px; height:6.4px; background:currentColor; }
  .ais-th.adj::before { content:''; position:absolute; left:3px; right:3px; top:5px;
    height:2px; border-radius:1px; background:currentColor; }
  .ais-th.adj.jl::before { left:0; }
  .ais-th.adj.jr::before { right:0; }
  /* Une dent à extraire COMPRISE dans un appareil garde sa croix rouge et sa
     couleur, mais reste soudée à sa pièce (prothèse immédiate) : la barre de la
     selle ne doit pas la traverser, la croix occupe déjà le haut de la case. */
  .ais-th.extr::before { content:none; }
  /* Dents SOUDÉES (bridge solidarisé, selle d'adjointe) : les cases voisines se
     touchent et ne partagent qu'un trait — on lit UNE pièce, pas N couronnes.
     -3px = les 2px de gap + le 1px de bordure, pour que les deux bordures se
     superposent exactement. Les unitaires, implants et extractions gardent leur
     case individuelle (ce sont des actes dent par dent). Classes posées par
     js/ai-summary.js (archEl) d'après le voisinage RÉEL dans le quadrant.
     Chaque jonction ne montre qu'UN trait (les bordures se superposent), donc on
     compte encore les dents ; seules les extrémités du groupe restent arrondies. */
  .ais-th.jr { border-top-right-radius:0; border-bottom-right-radius:0; }
  .ais-th.jl { border-top-left-radius:0; border-bottom-left-radius:0; margin-left:-3px; }
  /* Une dent SOUDÉE prend le trait FRANC de sa famille (et non le liseré pâle) :
     c'est le même surlignage que la pastille « 43 42 » d'une ligne d'acte, et il
     dit la même chose — ces dents ne font qu'une pièce. Miroir du PDF anglais.
     Il porte aussi l'information à la place de la couleur sur un tirage noir et
     blanc, où tous les fonds pastel deviennent le même gris. */
  .ais-th.jl, .ais-th.jr { border-color:currentColor; }
  /* …mais PAS sur les JONCTIONS INTERNES. Là, le trait qui sépare deux dents est
     COURT et centré : pleine hauteur, il redécoupe la pilule en cases et lui fait
     perdre son sens de pièce d'un seul tenant. C'est la règle du PDF anglais
     (3 mm sur 7,2) — l'écran s'y aligne (Illan, 03-04/09/2026).
     ⚠️ CES DEUX RÈGLES DOIVENT RESTER DANS CET ORDRE : la précédente pose les
     quatre bordures d'un coup (border-color), elle écraserait la transparence si
     elle passait après — c'est exactement ce qui s'était produit.
     Le trait est peint en BACKGROUND : les deux pseudo-éléments de .ais-th servent
     déjà aux repères de famille (croix d'extraction, vis d'implant, barre
     d'amovible), il n'en restait aucun. */
  .ais-th.jl { border-left-color:transparent; }
  .ais-th.jr { border-right-color:transparent; }
  .ais-th.jl {
    background-image:linear-gradient(currentColor, currentColor);
    background-repeat:no-repeat;
    background-position:left center;
    background-size:1px 42%;
  }
  /* Libellé d'arcade à GAUCHE de sa rangée (miroir du PDF anglais : UPPER / LOWER).
     Largeur fixe pour que les deux rangées de dents démarrent au même x. */
  /* Bloc commun aux deux arcades : calé à gauche À L'INTÉRIEUR, puis centré d'un
     seul tenant. Sans lui, chaque rangée se centrait pour elle-même et l'arcade la
     plus soudée (donc la plus étroite) démarrait décalée de l'autre. */
  .ais-arches { display:flex; flex-direction:column; align-items:flex-start;
    width:max-content; margin:0 auto; }
  .ais-archrow { display:flex; align-items:center; gap:7px; margin:2px 0; }
  .ais-archlbl { flex:0 0 auto; width:30px; text-align:right; font-size:.54rem; font-weight:800;
    letter-spacing:1px; color:var(--muted); margin:0; }
  .ais-adjrow { display:flex; flex-wrap:wrap; gap:5px; justify-content:center; margin:1px 0 5px; }
  .ais-adjtag { font-size:.68rem; font-weight:600; background:#fce4ec; color:#c2185b; border:1px solid #f8bbd0; border-radius:6px; padding:2px 9px; }
  .ais-leg { display:flex; flex-wrap:wrap; gap:9px; justify-content:center; font-size:.58rem; color:var(--muted); margin-top:3px; }
  .ais-li { width:10px; height:10px; border-radius:3px; display:inline-block; margin-right:4px; vertical-align:-1px; border:1px solid rgba(0,0,0,.12); }
  .ais-li.u{background:var(--th-u-bg);border-color:var(--th-u-bd)}
  .ais-li.s{background:var(--th-s-bg);border-color:var(--th-s-bd)}
  .ais-li.adj{background:var(--th-adj-bg);border-color:var(--th-adj-bd)}
  .ais-li.imp{background:var(--th-imp-bg);border-color:var(--th-imp-bd)}
  .ais-li.extr{background:var(--th-extr-bg);border-color:var(--th-extr-bd)}

  /* Actes : 2 colonnes fixe | amovible — chaque acte = encadré (chip) fond blanc,
     bordure légèrement teintée par catégorie, nom coloré (conjointe bleu / adjointe rose). */
  .ais-acts { display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:6px 10px; }
  .ais-col { display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
  .ais-col-t { align-self:stretch; font-size:.62rem; font-weight:800; text-transform:uppercase; letter-spacing:.5px; margin-bottom:4px; padding-bottom:3px; border-bottom:2px solid; }
  .ais-col.fixe .ais-col-t { color:#1a5c8a; border-color:#cfe3f2; }
  .ais-col.amov .ais-col-t { color:#c2185b; border-color:#f8bbd0; }
  /* L'objet de la section du formulaire devant le titre (dent / dentier). */
  .ais-col-t { display:flex; align-items:center; gap:5px; }
  .ais-col-t .ilx { --ilx-t:15px; flex:none; }
  .ais-act { display:inline-flex; align-items:center; flex-wrap:wrap; max-width:100%; gap:6px; background:#fff; border:1px solid #dce4ec; border-radius:6px; padding:2px 9px 2px 4px; }
  .ais-act.adj { border-color:#f3c6d6; }
  .ais-act.imp { border-color:#dcc2e6; }
  .ais-act.dng { border-color:#f0b8b8; }
  .ais-act.anx { border-color:#f0d2a8; }
  /* Numéro des dents + arcade (haut/bas) placés juste à droite du nom de l'item */
  .ais-act .ais-d { order:1; }
  .ais-d { font-family:'DM Mono',monospace; font-weight:700; font-size:.66rem; background:#e8f4fb; color:#1a5c8a; border-radius:4px; padding:1px 7px; white-space:normal; overflow-wrap:normal; }
  .ais-arr { font-family:-apple-system,Segoe UI,sans-serif; font-size:1rem; font-weight:900; line-height:1; vertical-align:-1px; margin:0 1px; }
  .ais-sep { font-weight:900; opacity:.5; margin:0 3px; }
  /* Liseré sur les dents SOLIDARISÉES : il dit « ces dents ne font qu'une pièce »,
     comme le badge « Solidarisé ». Miroir du PDF anglais (demande Illan 03/09/2026).
     box-shadow inset plutôt que border : la pastille garde exactement sa taille. */
  .ais-d.gsolid { background:#e3f3e9; color:#2d7a4f; box-shadow:inset 0 0 0 1px #2d7a4f; }
  .ais-d.gunit  { background:#e8f1fb; color:#1a5c8a; }
  /* Dents unitaires (fixe bleu OU implant violet, non solidarisés) : fine bande blanche entre chaque dent.
     display:inline-flex + flex-wrap → une longue liste (ex. 17 facettes) passe à la ligne
     DANS le cadre au lieu de déborder. flex-shrink:0 + max-width:100% : tant que ça tient
     ça reste sur une ligne ; sinon le bloc descend à pleine largeur sous le nom et se coupe
     PILE à la transition haut/bas (chaque arcade = un .ais-arch insécable) → schéma dentaire. */
  .ais-d.ais-units { padding-left:0; padding-right:0; display:inline-flex; flex-wrap:wrap; align-items:flex-start; max-width:100%; flex-shrink:0; white-space:normal; }
  .ais-d.ais-units .ais-arch { display:inline-flex; flex-wrap:wrap; }
  .ais-d.ais-units .ais-tooth { padding:0 7px; }
  .ais-d.ais-units .ais-tooth + .ais-tooth { box-shadow:-2px 0 0 0 #fff; }
  .ais-act.adj  .ais-d { background:#fce4ec; color:#c2185b; }
  .ais-act.imp  .ais-d { background:#f3e5f5; color:#6a1b9a; }
  .ais-act.dng  .ais-d { background:#ffebee; color:#c62828; }
  /* Noms en noir (neutre) ; seuls implant (violet), annexe (orange) et extraction
     (rouge) restent colorés — le reste de l'identité passe par la bordure + le badge. */
  .ais-n { font-weight:600; color:var(--text); }
  /* Icône de l'article devant son nom (js/icones-articles.js, 29/09/2026) : petite,
     une seule finition claire, 25 px (Illan, 29/09 : « plus grand », puis « encore légèrement »). */
  .ais-n .ais-ico { --ilx-t:25px; vertical-align:-7px; margin-right:6px; }
  .ais-act.imp .ais-n { color:#6a1b9a; } .ais-act.dng .ais-n { color:#c62828; }
  /* Sous-item (implant sous sa couronne, ackers sous son stellite — comme PDF anglais) :
     chip indenté vers la droite + puce « · » devant. */
  .ais-act.sub { margin-left:18px; font-size:.94em; }
  .ais-act.sub .ais-n::before { content:"· "; font-weight:800; opacity:.7; }
  /* Produits annexes (📦) : identité orange, comme le bouton "Annexes" */
  .ais-act.anx .ais-n { color:#e65100; }
  .ais-act.anx .ais-d { background:#fff3e0; color:#e65100; }
  /* Annexe : le détail (dents/mâchoire) peut être long (« haut · bas · 13 12 11
     … ») → police réduite + retour à la ligne pour rester DANS le cadre. Mêmes
     classes pour l'annexe sous le bouton (#annexes-recap) et le résumé IA. */
  #annexes-recap { flex-wrap: wrap; gap: 6px; }
  .ais-act.anx { align-items: flex-start; flex-wrap: wrap; max-width: 100%; }
  .ais-act.anx .ais-n { font-size: .74rem; }
  .ais-act.anx .ais-d { white-space: normal; overflow-wrap: anywhere; font-size: .58rem; line-height: 1.4; }
  .ais-tag { font-size:.58rem; font-weight:800; text-transform:uppercase; letter-spacing:.4px; padding:2px 7px; border-radius:4px; }
  .ais-tag.solid { background:#e3f3e9; color:#2d7a4f; } .ais-tag.unit { background:#e8f1fb; color:#1a5c8a; }
  .ais-grpbadges { display:flex; gap:6px; margin-top:6px; }
  .ais-fin { font-size:.7rem; color:var(--muted); padding:4px 0; font-style:italic; }
  .ais-none { color:var(--muted); padding:4px 0; }

  /* Pied : teinte + commentaires */
  .ais-foot { display:flex; align-items:center; gap:12px; flex-wrap:wrap; padding:5px 10px; border-top:1px solid var(--border); background:color-mix(in srgb, var(--accent) 3%, var(--surface)); }
  .ais-teinte { font-size:.72rem; color:var(--muted); }
  /* Lecture seule : .ais-ro annule le padding de .ais-acts → la teinte se retrouvait
     collée PILE au bas du dernier badge (« Solidarisé »), 0px entre les deux, ce qui
     se lit comme un chevauchement. On ne la remet qu'ici (dans .ais-foot elle est
     déjà espacée par le gap du flex). */
  .ais-ro > .ais-teinte { margin-top: 9px; }
  .ais-tc { background:#fff8e1; color:#b86b00; border:1px solid #ffe08a; border-radius:5px; padding:1px 8px; font-weight:800; font-size:.72rem; font-family:'DM Mono',monospace; }
  .ais-piv { font-size:.72rem; color:var(--text); font-weight:700; display:flex; align-items:center; gap:6px; }
  .ais-pivc { background:#fff3e0; color:#e65100; border:1px solid #ffcc80; border-radius:5px; padding:1px 8px; font-weight:800; font-size:.68rem; font-family:'DM Mono',monospace; }
  html[data-theme="dark"] .ais-pivc { background:#3a2a18; color:#ffb74d; border-color:#5a4326; }
  .ais-com { padding:5px 10px; font-size:.72rem; color:var(--text); border-top:1px solid var(--border); line-height:1.4; }
  /* Édition inline */
  .ais-editable { cursor:pointer; border-radius:4px; transition:background var(--dur-fast), box-shadow var(--dur-fast); }
  .ais-editable:hover { background:color-mix(in srgb, var(--accent) 14%, transparent); box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent); }
  .ais-edit { font:inherit; font-size:.74rem; padding:1px 5px; border:1px solid var(--accent); border-radius:5px; background:var(--surface); color:var(--text); outline:none; flex:0 0 auto; min-width:0; box-sizing:content-box; }
  .ais-livr-edit { display:inline-flex; gap:4px; }
  .ais-save { margin-left:auto; background:#f59e0b; color:#fff; border:none; border-radius:7px; padding:4px 12px; font-size:.74rem; font-weight:700; cursor:pointer; white-space:nowrap; transition:filter var(--dur-fast); }
  .ais-save:hover { filter:brightness(1.07); }
  /* Pied du résumé (js/ai-summary.js buildFoot, 28/09/2026) : teinte à gauche ; à droite le
     schéma et la colonne « Mettre à jour » + l'INTERRUPTEUR « Saisie continue » collé dessous,
     à sa largeur (js/fiche-claim.js peindreSaisieContinue). */
  .ais-foot-act { margin-left:auto; display:flex; align-items:flex-start; gap:8px; }
  .ais-foot .ais-foot-act > .ais-schema-tgl { margin-left:0; }
  /* Badge RULES posé à gauche du schéma (30/09/2026) : centré sur la hauteur des boutons. */
  .ais-foot .ais-foot-act > .ais-rules { margin:0; align-self:center; }
  .ais-cont { display:flex; align-items:center; justify-content:flex-end; gap:6px; height:22px; box-sizing:border-box; padding:0 6px;
    border:0; border-radius:7px; background:none; color:var(--muted); font:inherit; font-size:.64rem; font-weight:700; cursor:pointer; white-space:nowrap;
    transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
  .ais-cont:hover { color:var(--text); background:color-mix(in srgb, var(--teal) 8%, var(--surface)); }
  .ais-cont:focus-visible { outline:2px solid color-mix(in srgb, var(--teal) 50%, transparent); outline-offset:1px; }
  .ais-cont[aria-pressed="true"] { color:var(--teal-text, var(--accent-text)); }
  /* La glissière : grise éteinte, teal allumée, le bouton rond glisse à droite. */
  .ais-sw { position:relative; flex:none; width:24px; height:14px; border-radius:999px; background:color-mix(in srgb, var(--muted) 40%, var(--surface));
    transition: background-color var(--dur-fast) var(--ease-out); }
  .ais-sw::after { content:''; position:absolute; top:2px; left:2px; width:10px; height:10px; border-radius:50%; background:var(--surface);
    box-shadow:0 1px 2px color-mix(in srgb, var(--text) 30%, transparent); transition: transform var(--dur-fast) var(--ease-out); }
  .ais-cont[aria-pressed="true"] .ais-sw { background:var(--teal); }
  .ais-cont[aria-pressed="true"] .ais-sw::after { transform:translateX(10px); }
  .ais-cont-n { min-width:16px; height:16px; box-sizing:border-box; padding:0 4px; border-radius:999px; font-size:.56rem; font-weight:800; line-height:16px; text-align:center;
    background:color-mix(in srgb, var(--warn) 22%, var(--surface)); color:var(--text); }
  @media (prefers-reduced-motion: reduce) { .ais-sw, .ais-sw::after { transition:none; } }
  /* Autocomplétion inline (cabinet / praticien) — dropdown en position:fixed */
  .ais-ac { position:fixed; z-index:100001; min-width:170px; max-width:300px; background:var(--surface); border:1px solid var(--border); border-radius:9px; box-shadow:0 10px 30px rgba(15,35,55,.22); max-height:230px; overflow-y:auto; display:none; }
  .ais-ac-item { padding:6px 10px; cursor:pointer; font-size:.74rem; display:flex; align-items:center; justify-content:space-between; gap:10px; border-bottom:1px solid color-mix(in srgb, var(--border) 55%, transparent); }
  .ais-ac-item:last-child { border-bottom:none; }
  .ais-ac-item:hover { background:color-mix(in srgb, var(--accent) 13%, transparent); }
  .ais-ac-n { font-weight:600; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ais-ac-s { font-family:'DM Mono',monospace; font-size:.66rem; font-weight:700; color:var(--accent-text); white-space:nowrap; }
  /* Mini-modale teinte */
  .ais-teinte-pop { position:fixed; z-index:100001; background:var(--surface); border:1px solid var(--border); border-radius:12px; box-shadow:0 12px 36px rgba(15,35,55,.24); padding:11px; width:240px; }
  .ais-teinte-pop .ais-tp-title { font-size:.66rem; font-weight:800; color:#d32f2f; text-transform:uppercase; letter-spacing:.4px; margin-bottom:7px; }
  .ais-teinte-pop .teinte-options { margin-bottom:8px; }
  .ais-teinte-pop .ais-tp-lbl { font-size:.64rem; color:var(--muted); margin:2px 0 4px; }

  /* ── Dark mode ── */
  html[data-theme="dark"] .ais-lab { background:#1e3a4f; color:#7fc4e8; border-color:#2a5570; }
  html[data-theme="dark"] .ais-livr { background:#3a1a1a; color:#ef9a9a; border-color:#5a2a2a; }
  html[data-theme="dark"] .ais-fourn { background:#1e3a4f; color:#7fc4e8; border-color:#2a5570; }
  /* Sous-traitants en mode nuit : même teinte de config (--f), éclaircie pour le contraste. */
  html[data-theme="dark"] .ais-fourn[class*="fourn-c"] { background:color-mix(in srgb, var(--f, var(--accent)) 42%, #101418);
    color:color-mix(in srgb, var(--f, var(--accent)) 30%, #ffffff); border-color:color-mix(in srgb, var(--f, var(--accent)) 62%, #101418); }
  html[data-theme="dark"] #filter-fournisseur option[class*="fourn-c"],
  html[data-theme="dark"] #filter-fournisseur[class*="fourn-c"] { color:color-mix(in srgb, var(--f, var(--accent)) 30%, #ffffff);
    border-color:color-mix(in srgb, var(--f, var(--accent)) 62%, #101418); }
  html[data-theme="dark"] #filter-fournisseur option.fourn-other { color:#7fc4e8; }
  html[data-theme="dark"] #filter-fournisseur.fourn-other { color:#7fc4e8; border-color:#2a5570; }
  html[data-theme="dark"] .fiche-claim-badge { background:#3a2a18; color:#ffb74d; border-color:#5a4326; }
  html[data-theme="dark"] .doublon-badge { background:#8a4a12; color:#ffd9b3; border-color:#b35f17; }
  html[data-theme="dark"] .pi-badge-refaire { background:#7a1a1a; color:#ffb3b3; border-color:#9a2a2a; }
  html[data-theme="dark"] .pi-badge-standby { background:#3a4254; color:#b8c2d0; border-color:#4a5468; }
  html[data-theme="dark"] .pi-badge-annule { background:#2a3142; color:#c8d0dc; border-color:#3a4254; }
  html[data-theme="dark"] .pi-badge-remis { background:#12414f; color:#9fdbe8; border-color:#1a5a6d; }
  html[data-theme="dark"] .pi-badge-probleme { background:#5a3007; color:#ffc98a; border-color:#7d4409; }
  html[data-theme="dark"] .pi-badge-probleme:hover { background:#6e3b09; }
  html[data-theme="dark"] .pi-badge-auto { background:#4a3212; color:#f0c98a; border-color:#6b4a1c; }
  html[data-theme="dark"] .pi-badge-fourn-alerte { box-shadow: 0 0 0 1px color-mix(in srgb, #ef9a9a 55%, transparent); }
  html[data-theme="dark"] .fusion-fusionne-badge { background:#c2780a; color:#fff; border-color:#d9920f; }
  /* Fusion : le gros des overrides dark a été retiré le 12/08/2026 — les règles
     de base sont passées aux tokens/color-mix (dark automatique). Ne restent que
     les ajustements que les tokens ne couvrent pas. */
  html[data-theme="dark"] .fusion-pop-card { background:var(--surface, #242938); color:var(--text, #e0e6ed); }
  html[data-theme="dark"] .saisie-compteur .sc-att { background:#3a3318; color:#e6c35a; }
  html[data-theme="dark"] .saisie-compteur .sc-enc { background:#3a2a18; color:#ff9e4d; }
  html[data-theme="dark"] .saisie-compteur .sc-ver { background:#1a3322; color:#7bc88a; }
  html[data-theme="dark"] .ais-flag.urg { background:#3a1a1a; color:#ef9a9a; }
  html[data-theme="dark"] .ais-flag.est { background:#3a2a18; color:#ffb74d; }
  html[data-theme="dark"] .ais-flag.call { background:#3a1a1a; color:#ef9a9a; }
  html[data-theme="dark"] .ais-th.u    { background:#1c3142; border-color:#3a6a8c; color:#7fc4e8; }
  html[data-theme="dark"] .ais-th.s    { background:#1c3326; border-color:#3a7a55; color:#81c784; }
  html[data-theme="dark"] .ais-th.adj  { background:#3a1e2c; border-color:#8a3a5c; color:#f48fb1; }
  html[data-theme="dark"] .ais-th.imp  { background:#2e1e3a; border-color:#7a4a9a; color:#ce93d8; }
  html[data-theme="dark"] .ais-th.extr { background:#3a1a1a; border-color:#8a3a3a; color:#ef9a9a; }
  html[data-theme="dark"] .ais-th.extr::after { color:#ef9a9a; }
  html[data-theme="dark"] .ais-adjtag { background:#3a1e2c; border-color:#8a3a5c; color:#f48fb1; }
  html[data-theme="dark"] .ais-d { background:#1e3a4f; color:#7fc4e8; }
  html[data-theme="dark"] .ais-d.gsolid { background:#1c3326; color:#81c784; }
  html[data-theme="dark"] .ais-d.gunit  { background:#1e3a4f; color:#7fc4e8; }
  html[data-theme="dark"] .ais-d.ais-units .ais-tooth + .ais-tooth { box-shadow:-2px 0 0 0 rgba(255,255,255,.28); }
  html[data-theme="dark"] .ais-act.adj .ais-d { background:#3a1e2c; color:#f48fb1; }
  html[data-theme="dark"] .ais-act.imp .ais-d { background:#2e1e3a; color:#ce93d8; }
  html[data-theme="dark"] .ais-act.dng .ais-d { background:#3a1a1a; color:#ef9a9a; }
  html[data-theme="dark"] .ais-act.imp .ais-n { color:#ce93d8; }
  html[data-theme="dark"] .ais-act.dng .ais-n { color:#ef9a9a; }
  html[data-theme="dark"] .ais-act.anx .ais-n { color:#ffb74d; }
  html[data-theme="dark"] .ais-act.anx .ais-d { background:#3a2a18; color:#ffb74d; }
  /* Chips actes en sombre : fond sombre + bordure teintée, noms conjointe bleu / adjointe rose */
  html[data-theme="dark"] .ais-act { background:#161d2a; border-color:#2a3a50; }
  html[data-theme="dark"] .ais-act.adj { border-color:#5a2840; }
  html[data-theme="dark"] .ais-act.imp { border-color:#4a2a5a; }
  html[data-theme="dark"] .ais-act.dng { border-color:#5a2a2a; }
  html[data-theme="dark"] .ais-act.anx { border-color:#5a4326; }
  /* Article annexe à la couleur de sa CATÉGORIE (25/09/2026, Illan) — remplace
     l'orange : bleu prothèse fixe, violet implant, rose amovible, neutre sinon.
     Mêmes teintes que les alias d'Actes & codes. Miroir papier : export-pdf-en.js. */
  .ais-act.anx.anxc-conj { border-color:#c5dcee; }
  .ais-act.anx.anxc-conj .ais-n { color:#1a5c8a; }
  .ais-act.anx.anxc-conj .ais-d { background:#e8f4fb; color:#1a5c8a; }
  .ais-act.anx.anxc-adj { border-color:#f3c6d6; }
  .ais-act.anx.anxc-adj .ais-n { color:#c2185b; }
  .ais-act.anx.anxc-adj .ais-d { background:#fce4ec; color:#c2185b; }
  .ais-act.anx.anxc-imp { border-color:#dcc2e6; }
  .ais-act.anx.anxc-imp .ais-n { color:#6a1b9a; }
  .ais-act.anx.anxc-imp .ais-d { background:#f3e5f5; color:#6a1b9a; }
  .ais-act.anx.anxc-neutre { border-color:#dce4ec; }
  .ais-act.anx.anxc-neutre .ais-n { color:var(--text); }
  .ais-act.anx.anxc-neutre .ais-d { background:var(--surface-2,#f1f5f9); color:var(--muted); }
  html[data-theme="dark"] .ais-act.anx.anxc-conj { border-color:#2a3a50; }
  html[data-theme="dark"] .ais-act.anx.anxc-conj .ais-n { color:#8fc0e6; }
  html[data-theme="dark"] .ais-act.anx.anxc-conj .ais-d { background:#16283a; color:#8fc0e6; }
  html[data-theme="dark"] .ais-act.anx.anxc-adj { border-color:#5a2840; }
  html[data-theme="dark"] .ais-act.anx.anxc-adj .ais-n { color:#f48fb1; }
  html[data-theme="dark"] .ais-act.anx.anxc-adj .ais-d { background:#3a1e2c; color:#f48fb1; }
  html[data-theme="dark"] .ais-act.anx.anxc-imp { border-color:#4a2a5a; }
  html[data-theme="dark"] .ais-act.anx.anxc-imp .ais-n { color:#ce93d8; }
  html[data-theme="dark"] .ais-act.anx.anxc-imp .ais-d { background:#2e1e3a; color:#ce93d8; }
  html[data-theme="dark"] .ais-act.anx.anxc-neutre { border-color:#2a3a50; }
  html[data-theme="dark"] .ais-act.anx.anxc-neutre .ais-n { color:var(--text); }
  html[data-theme="dark"] .ais-act.anx.anxc-neutre .ais-d { background:var(--surface-2); color:var(--muted); }
  html[data-theme="dark"] .ais-tag.solid { background:#1c3326; color:#81c784; }
  html[data-theme="dark"] .ais-tag.unit  { background:#1c3142; color:#7fc4e8; }
  html[data-theme="dark"] .ais-tc { background:#3a3220; color:#ffd54f; border-color:#5a4a2a; }
  html[data-theme="dark"] .ais-col.fixe .ais-col-t { color:#7fc4e8; }
  html[data-theme="dark"] .ais-col.amov .ais-col-t { color:#f48fb1; }

  @media (max-width: 1000px) {
    .split-wrapper { grid-template-columns: 1fr; }
    .preview-panel { position: static; }
    /* La note n'a plus rien à faire ici : elle vit dans la fenêtre flottante
       partagée (.ais-pop), posée sous le résumé et par-dessus le reste. */
  }

  /* L'interface MOBILE impose la structure téléphone PAR LA CLASSE, pas par la
     largeur : prescription pleine largeur, visionneuse en dessous. Le media
     ci-dessus ne couvre que les fenêtres étroites — il lâchait dès que la mise
     en page dépassait 1000 px avec la classe posée : interface mobile FORCÉE
     sur Fold déplié (1968 px), et même un vrai téléphone très dézoomé
     (cran -3 → 1088 px). Le 2e sélecteur bat la règle :has(.preview-panel
     .visible) du split (spécificité), sinon ouvrir la visionneuse remettait
     deux colonnes. */
  html.mobile-zoom-default .split-wrapper,
  html.mobile-zoom-default .split-wrapper:has(.preview-panel.visible) {
    grid-template-columns: 1fr;
  }
  html.mobile-zoom-default .preview-panel { position: static; }

  /* Barre code-labo « flottante » (maquette .codebar2) */
  .card-header {
    background: var(--grad);
    color: white;
    padding: 6px 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    border-radius: var(--r);
    box-shadow: 0 8px 22px rgba(26,92,138,0.2);
  }

  .card-header h1 { font-size: 0.8rem; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; }

  .n-commande {
    font-family: 'DM Mono', monospace;
    font-size: 1.1rem;
    font-weight: 500;
    opacity: 0.9;
  }

  .form-body { padding: 6px 10px; display: flex; flex-direction: column; gap: 6px; }

  .top-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }

  .section {
    background: var(--section-bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 6px 10px;
  }

  .section-title {
    font-size: 0.58rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--accent-text);
    margin-bottom: 3px;
    padding-bottom: 2px;
    border-bottom: 1px solid var(--border);
  }

  label { font-size: 0.7rem; color: var(--muted); display: block; margin-bottom: 1px; margin-top: 3px; }
  label:first-of-type { margin-top: 0; }

  input[type="text"], input[type="date"], input[type="number"], textarea, select {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 4px 7px;
    font-family: 'DM Sans', sans-serif;
    font-size: 0.76rem;
    background: var(--surface);
    color: var(--text);
    outline: none;
    transition: border-color var(--dur-fast);
  }

  input:focus, textarea:focus, select:focus { border-color: var(--teal); box-shadow: 0 0 0 3px rgba(91,196,192,0.15); }

  .sexe-row { display: flex; gap: 10px; margin-top: 0px; align-items: center; }
  .radio-label { display: inline-flex; align-items: center; gap: 5px; font-size: 0.74rem; color: var(--text); cursor: pointer; line-height: 1; }
  .radio-label input[type="radio"] { accent-color: var(--accent); width: 12px; height: 12px; flex-shrink: 0; margin: 0; }

  .checkbox-label { display: flex; align-items: center; gap: 5px; font-size: 0.74rem; color: var(--text); cursor: pointer; margin: 2px 0; line-height: 1.2; padding: 1px 4px; border-radius: 4px; transition: background var(--dur-fast), font-weight var(--dur-fast); }
  .checkbox-label:has(input:checked) { background: #fff8e1; font-weight: 600; color: #b8860b; border: 1px solid #e6a700; }
  /* Alias produits — items cliquables dans la modal */
  .pa-item { font-size:0.74rem; color:var(--text); cursor:pointer; padding:3px 8px; margin:2px 0; border-radius:6px; border:1px solid transparent; transition:background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast); position:relative; font-weight:500; }
  .pa-item:hover { background:#ede7f6; border-color:#b39ddb; }
  .pa-item.pa-sub { font-size:0.68rem; color:#666; margin-left:2px; font-weight:400; }
  .pa-item .pa-count { font-size:0.6rem; background:#7c4dff; color:white; border-radius:8px; padding:0 5px; margin-left:4px; display:none; font-weight:700; }
  .pa-item.has-aliases { background:#f3e8ff; border-color:#ce93d8; }
  .pa-item.has-aliases .pa-count { display:inline; }
  .pa-item.pa-active { background:#7c4dff; color:white !important; border-color:#7c4dff; }
  .pa-item.pa-active .pa-count { background:var(--surface); color:#7c4dff; }
  .pa-item.pa-active.pa-sub { color:white !important; }
  .checkbox-label input[type="checkbox"] { accent-color: #e6a700; width: 12px; height: 12px; flex-shrink: 0; margin: 0; vertical-align: middle; }
  /* Ancienne popup 🧩 « Articles du labo » supprimée (fusionnée dans 📦 Annexes).
     Le détail natures des articles réutilise désormais les classes .anx-* (cf.
     bloc « Popup Annexes »). On ne garde que le keyframe d'apparition partagé. */
  @keyframes alReveal{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}

  /* Popup Annexes (📦) — RÉUTILISE le rendu de la prescription (.sec-card/.ord-ck).
     Conjointe bleu / Adjointe rose via .sec-conj/.sec-adj. Orange = en-tête + récap. */
  #annexes-popup.anx-pop{position:fixed;z-index:2000;width:540px;max-width:94vw;max-height:78vh;overflow:auto;
    background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:12px 14px;
    box-shadow:0 16px 42px -12px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.14);
    animation:anatPop var(--dur-fast) var(--ease-out)}
  .anx-head{display:flex;justify-content:space-between;align-items:center;font-weight:700;font-size:.82rem;
    color:#e65100;margin-bottom:10px;cursor:move;user-select:none}
  .anx-close{border:none;background:transparent;color:var(--muted);cursor:pointer;font-size:1rem;line-height:1;padding:0 2px}
  .anx-cols{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:start}
  /* Petites catégories empilées dans une même colonne (_anxPiles, 25/09/2026) */
  .anx-pile{display:flex;flex-direction:column;gap:12px;min-width:0}
  .anx-note{font-size:.66rem;color:var(--muted)}
  .anx-row{margin-bottom:1px}
  .anx-row .ord-ck{white-space:normal;padding:2px 6px}
  .anx-row .ord-ck .t{flex:1}
  .anx-code{margin-left:6px;font-size:.55rem;color:var(--muted);font-family:'DM Mono',monospace;white-space:nowrap;flex:none;align-self:center}
  .anx-detail{margin:2px 0 6px 24px;display:flex;flex-direction:column;gap:5px;animation:alReveal var(--dur-fast) var(--ease-out)}
  .anx-jaw{display:flex;gap:5px}
  .anx-mat{display:grid;grid-template-columns:1fr 1fr;gap:5px}
  .anx-jaw-b{flex:1;padding:4px;border:1px solid var(--border);background:var(--surface);border-radius:7px;
    font-size:.67rem;cursor:pointer;color:var(--accent-text);font-weight:600;
    transition:transform var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast)}
  .anx-jaw-b:hover{transform:translateY(-1px);border-color:color-mix(in srgb, var(--accent) 45%, var(--border))}
  .anx-jaw-b.on{border-color:var(--accent);background:color-mix(in srgb, var(--accent) 16%, var(--surface));box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent)}
  .sec-adj .anx-jaw-b{color:var(--rose)}
  .sec-adj .anx-jaw-b:hover{border-color:color-mix(in srgb, var(--rose) 45%, var(--border))}
  .sec-adj .anx-jaw-b.on{border-color:var(--rose);background:color-mix(in srgb, var(--rose) 14%, var(--surface));box-shadow:0 0 0 1px color-mix(in srgb, var(--rose) 30%, transparent)}
  .anx-in,.anx-detail .anx-qty{padding:5px 8px;border:1px solid var(--border);border-radius:7px;background:var(--surface);color:var(--text);font:inherit;font-size:.74rem}
  .anx-in{width:100%;box-sizing:border-box}
  .anx-in:focus,.anx-detail .anx-qty:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent)}
  .sec-adj .anx-in:focus,.sec-adj .anx-detail .anx-qty:focus{border-color:var(--rose);box-shadow:0 0 0 3px color-mix(in srgb, var(--rose) 18%, transparent)}
  .anx-qtyrow{display:flex;align-items:center;gap:8px;font-size:.7rem;color:var(--muted)}
  .anx-detail .anx-qty{flex:0 0 66px;width:66px}
  /* Colonne « catégorie maison » (articles perso du labo) : couleur neutre =
     accent tenant. Les items .ord-ck gardent le bleu accent par défaut (voulu). */
  .sec-neutral .rail{ background: var(--accent); }
  .sec-neutral .sec-title{ color: var(--accent-text); border-color: color-mix(in srgb, var(--accent) 42%, var(--surface)); }

  .qty-input { display:none; width: 36px !important; min-width: 36px !important; max-width: 36px !important; height: 18px !important; border: 1px solid var(--border); border-radius: 3px; font-size: 0.65rem; text-align: left; padding-left: 4px !important; padding-right: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important; font-family: 'DM Sans',sans-serif; color: var(--accent-text); font-weight: 700; margin-left: 3px; box-sizing: border-box; flex: 0 0 36px; }
  .qty-input:focus { outline: none; border-color: var(--accent); }

  .date-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
  .nbr-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 3px; }
  input[type="number"] { -moz-appearance: textfield; }

  /* Rails CONJOINTE (bleu) / ADJOINTE (rose) — maquette §5 */
  .main-row .section:first-child {
    border-left: 4px solid var(--teal);
  }
  .main-row .section:last-child {
    border-left: 4px solid #d94f8a;
  }
  .main-row .section-title {
    text-align: center;
    font-size: 0.62rem;
    letter-spacing: 3px;
  }

  /* ── Flags §5 : URGENT / CALL ME / Cas esth. / Scan ── */
  .flag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 20px;
    border: 2px solid var(--border);
    background: var(--section-bg);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast);
  }
  .flag input[type="checkbox"] { cursor: pointer; }
  .flag label { cursor: pointer; }

  .section-sub-title {
    font-size: 0.62rem;
    font-weight: 600;
    color: var(--accent-text);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 6px 0 3px;
  }

  .checkbox-group { display: flex; flex-direction: column; }
  .checkbox-sub { margin-left: 14px; }

  .inline-input {
    display: flex;
    align-items: center;
    gap: 5px;
    margin: 2px 0;
    font-size: 0.72rem;
  }

  .inline-input input[type="text"] {
    width: auto;
    flex: 1;
    padding: 2px 5px;
    font-size: 0.72rem;
  }

  .inline-input input[type="checkbox"] { accent-color: var(--accent); width: 12px; height: 12px; }

  .dents-grid { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
  .dents-row { display: flex; justify-content: center; gap: 2px; }
  .dents-divider { width: 2px; background: var(--border); margin: 0 3px; border-radius: 2px; }

  .dent-btn {
    width: 24px; height: 24px;
    border: 1.5px solid var(--border);
    border-radius: 4px;
    background: var(--surface);
    font-size: 0.52rem;
    font-family: 'DM Mono', monospace;
    cursor: pointer;
    color: var(--muted);
    transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast);
    display: flex; align-items: center; justify-content: center;
    font-weight: 500;
  }

  .dent-btn:hover { border-color: var(--teal); color: var(--accent-text); background: var(--teal-light); }
  .dent-btn.selected { background: var(--grad); color: white; border-color: var(--accent); }

  .dents-labels { display: flex; justify-content: center; gap: 2px; font-size: 0.52rem; color: var(--muted); font-family: 'DM Mono', monospace; }

  .bottom-row { display: grid; grid-template-columns: 180px 1fr; gap: 8px; }

  /* ── Utilitaires pour remplacer les styles inline répétitifs ── */
  .flex-center { display: flex; align-items: center; }
  .flex-between { display: flex; justify-content: space-between; align-items: center; }
  .flex-col { display: flex; flex-direction: column; }
  .gap-4 { gap: 4px; }
  .gap-6 { gap: 6px; }
  .gap-8 { gap: 8px; }
  .gap-12 { gap: 12px; }
  .gap-16 { gap: 16px; }
  .mt-2 { margin-top: 2px; }
  .mt-3 { margin-top: 3px; }
  .mt-4 { margin-top: 4px; }
  .mt-5 { margin-top: 5px; }
  .mt-6 { margin-top: 6px; }
  .ml-14 { margin-left: 14px; }
  .w-100 { width: 100%; }
  .nowrap { white-space: nowrap; }
  .text-muted { color: var(--muted); }
  .text-accent { color: var(--accent-text); }
  .text-danger { color: var(--danger); }
  .text-xs { font-size: 0.68rem; }
  .text-sm { font-size: 0.72rem; }
  .fw-bold { font-weight: 600; }
  .fw-bolder { font-weight: 700; }

  /* Header buttons */
  .btn-header-primary {
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; background: var(--grad); color: white;
    padding: 0 18px; height: 36px; border: none;
    border-radius: 12px; font-size: 0.78rem; font-weight: 600;
    box-shadow: 0 2px 10px rgba(26,92,138,0.2); white-space: nowrap;
    font-family: 'DM Sans', sans-serif;
  }
  .btn-header-secondary {
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; background: var(--surface); color: var(--accent-text);
    border: 1.5px solid var(--teal); padding: 0 18px; height: 36px;
    border-radius: 12px; font-size: 0.78rem; font-weight: 600;
    box-shadow: 0 2px 8px rgba(91,196,192,0.12); white-space: nowrap;
    font-family: 'DM Sans', sans-serif;
  }
  .btn-header-outline {
    display: inline-flex; align-items: center; cursor: pointer;
    background: var(--surface); color: var(--accent-text); border: 1.5px solid var(--accent);
    padding: 0 18px; height: 36px; border-radius: 12px;
    font-size: 0.78rem; font-weight: 600;
    box-shadow: 0 2px 8px rgba(26,92,138,0.10); white-space: nowrap; gap: 6px;
    font-family: 'DM Sans', sans-serif;
  }
  /* Rebond doux au survol (redesign §2). */
  .btn-header-primary, .btn-header-secondary, .btn-header-outline {
    transition: transform var(--dur-fast), box-shadow var(--dur-base), border-color var(--dur-base);
  }
  .btn-header-primary:hover, .btn-header-secondary:hover, .btn-header-outline:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
  }
  /* Boutons d'action header empilés en colonne, collés à droite (§2). */
  .header-actions { align-items: flex-start; }
  .btn-col { display: flex; flex-direction: column; gap: 7px; align-items: stretch; }
  /* Admin + ❓ Help empilés (15/09/2026) : même colonne que les boutons de scan.
     L'admin est masqué pour la plupart des profils — le Help reste alors seul. */
  .tool-col { display: flex; flex-direction: column; gap: 7px; align-items: stretch; }
  .tool-col .tool { width: 100%; }
  .btn-col .btn-header-primary,
  .btn-col .btn-header-secondary,
  .btn-col .btn-header-outline {
    width: 100%;
    justify-content: flex-start;
    gap: 9px;
  }
  /* Boutons d'action : look uniforme teinté façon maquette (libellé sombre + teinte fonctionnelle). */
  .btn-col .btn-header-primary {
    background: color-mix(in srgb, #16a3b0 8%, var(--surface));
    border: 1px solid color-mix(in srgb, #16a3b0 24%, var(--surface));
    color: var(--text); box-shadow: var(--shadow-sm);
  }
  .btn-col .btn-header-secondary {
    background: color-mix(in srgb, #2a7ad6 8%, var(--surface));
    border: 1px solid color-mix(in srgb, #2a7ad6 24%, var(--surface));
    color: var(--text); box-shadow: var(--shadow-sm);
  }
  .btn-col .btn-header-outline {
    background: color-mix(in srgb, #e0a400 9%, var(--surface));
    border: 1px solid color-mix(in srgb, #e0a400 26%, var(--surface));
    color: var(--text); box-shadow: var(--shadow-sm);
  }
  /* Cluster utilitaire : icônes en ligne + pastille « Synchronisé » dessous (§2). */
  .header-utils { flex-direction: column; align-items: center; gap: 7px; }
  .util-row { display: flex; align-items: center; gap: 8px; }
  header .sep { width: 1px; background: var(--border); align-self: stretch; margin: 2px 4px; }
  /* Icônes utilitaires teintées : thème = accent, déconnexion = rouge. */
  #btn-dark-mode {
    background: color-mix(in srgb, var(--accent) 11%, var(--surface));
    border-color: color-mix(in srgb, var(--accent) 26%, var(--surface));
    color: var(--accent-text);
  }
  header .header-icon-btn--danger {
    background: color-mix(in srgb, #d2604f 11%, var(--surface));
    border-color: color-mix(in srgb, #d2604f 26%, var(--surface));
    color: #d2604f;
  }
  header .header-icon-btn:hover { transform: translateY(-1px); }

  /* ── Icônes SVG ligne (redesign, ILS.icon) — couleur via currentColor ── */
  svg.ic { display: inline-block; flex: none; vertical-align: middle; }
  /* Photo / Galerie / Dossiers portent des OBJETS illustrés (30/09/2026) : plus de
     teinte de trait à poser ici, l'objet a ses couleurs. */
  /* Bascule moon/sun selon le thème (pas de JS). */
  /* Spécificité (0,2,0) VOULUE : la case d'icône .ilx (js/icones-app.js) est
     injectée après cette feuille — à (0,1,0) contre (0,1,0), c'est elle qui
     gagnait et les deux icônes du thème s'affichaient en même temps. */
  .header-icon-btn .ic-sun { display: none; }
  html[data-theme="dark"] .header-icon-btn .ic-moon { display: none; }
  html[data-theme="dark"] .header-icon-btn .ic-sun { display: inline-grid; }
  /* Logo animé : flottement permanent + spin au clic (maquette). */
  /* will-change retiré : l'animation infinie promeut déjà l'élément sur le GPU →
     un will-change permanent ne faisait qu'épingler une couche GPU en continu pour
     rien (invisible à l'œil, gain mémoire GPU). */
  .logo-img-wrap { animation: logoFloat 5s ease-in-out infinite; cursor: pointer; transform-origin: center center; }
  .logo-img-wrap.spin { animation: logoSpin .85s var(--ease-out); }
  @keyframes logoFloat { 0%,100%{transform:translateY(0) rotate(0deg)} 25%{transform:translateY(-4px) rotate(-2.5deg)} 50%{transform:translateY(0) rotate(0deg)} 75%{transform:translateY(-2px) rotate(2.5deg)} }
  @keyframes logoSpin { from{transform:rotateY(0deg)} to{transform:rotateY(360deg)} }
  /* Pastille « Synchronisé » : point vert qui pulse quand sync OK (maquette).
     Halo converti box-shadow→pseudo (scale+opacity, compositable) : disque statique
     derrière le point (z-index:-1 dans le contexte du point), même couleur, même
     amplitude (7px autour du point de 7px → scale 3), même cadence 2.4s. */
  @keyframes ilsSyncPulse { 0%{transform:scale(1);opacity:1} 70%,100%{transform:scale(3);opacity:0} }
  .header-sync-dot { position: relative; z-index: 0; }
  .header-sync.ok .header-sync-dot::after {
    content: ""; position: absolute; inset: 0; border-radius: 50%; z-index: -1;
    background: rgba(55,151,74,.45); opacity: 0;
    animation: ilsSyncPulse 2.4s infinite;
  }
  @media (prefers-reduced-motion: reduce) {
    .logo-img-wrap, .logo-img-wrap.spin, .header-sync.ok .header-sync-dot,
    .header-sync.ok .header-sync-dot::after { animation: none; }
  }

  /* ── Actes ordonnance : cases custom « .ord-ck » (maquette §5) ──
     L'<input> est gardé (name/value) → câblage save intact ; .bx = case dessinée. */
  .ord-ck { display: flex; align-items: center; gap: 7px; padding: 1px 6px; border-radius: 6px; cursor: pointer; font-size: .72rem; color: var(--text); position: relative; border-left: 2px solid transparent; transition: background var(--dur-fast), border-color var(--dur-fast); white-space: nowrap; }
  .ord-ck:hover { background: var(--surface-2); }
  .ord-ck:hover .bx { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); transform: scale(1.14); }
  .ord-ck:hover .t { color: var(--accent-text); }
  .ord-ck input { position: absolute; opacity: 0; width: 0; height: 0; }
  .ord-ck .bx { width: 16px; height: 16px; border: 1.7px solid color-mix(in srgb, var(--accent) 30%, var(--border)); border-radius: 5px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--surface); transition: transform var(--dur-fast) var(--ease-spring), background var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast); }
  .ord-ck .bx svg { width: 11px; height: 11px; fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 13; stroke-dashoffset: 13; transition: stroke-dashoffset var(--dur-fast) ease; }
  .ord-ck input:checked + .bx { background: var(--grad); border-color: transparent; box-shadow: 0 2px 7px color-mix(in srgb, var(--accent) 36%, transparent); animation: pop var(--dur-fast) var(--ease-spring); }
  .ord-ck input:checked + .bx svg { stroke-dashoffset: 0; }
  .ord-ck:has(input:checked) { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); border-left-color: var(--accent); }
  .ord-ck:has(input:checked) .t { font-weight: 700; }
  .ord-ck.sub { font-size: .62rem; color: var(--muted); }
  .ord-ck.danger .t { color: #c0392b; font-weight: 800; }
  .ord-ck.danger input:checked + .bx { background: #c0392b; }
  .ord-ck.danger:has(input:checked) { background: color-mix(in srgb, #c0392b 10%, var(--surface)); border-left-color: #c0392b; }
  /* ADJOINTE (quand le conteneur portera .sec-adj — lot layout Sonnet) : rose. */
  .sec-adj .ord-ck input:checked + .bx { background: var(--rosegrad); }
  .sec-adj .ord-ck:has(input:checked) { background: color-mix(in srgb, var(--rose) 16%, var(--surface)); border-left-color: var(--rose); }
  /* Colonne IMPLANTS de la popup 📦 (25/09/2026) : le violet d'acte implant,
     déjà décliné en mode sombre (--acte-imp-fg). */
  .sec-imp .ord-ck input:checked + .bx { background: var(--acte-imp-fg); }
  .sec-imp .ord-ck:has(input:checked) { background: color-mix(in srgb, var(--acte-imp-fg) 14%, var(--surface)); border-left-color: var(--acte-imp-fg); }
  /* Solidaire = vert (style par data-act, sans câbler le clic-droit). */
  .ord-ck[data-act="Solidaire"] input:checked + .bx { background: #2d7a4f; box-shadow: 0 2px 7px color-mix(in srgb, #2d7a4f 36%, transparent); }
  .ord-ck[data-act="Solidaire"]:has(input:checked) { background: color-mix(in srgb, #2d7a4f 16%, var(--surface)); border-left-color: #2d7a4f; }
  @keyframes pop { 0% { transform: scale(.5); } 55% { transform: scale(1.18); } 100% { transform: scale(1); } }
  /* Coche d'une annexe reconstruite au clic : même tracé que les autres cases (js/ordonnance-sous-menus.js). */
  @keyframes ordTrace { from { stroke-dashoffset: 13; } to { stroke-dashoffset: 0; } }
  @keyframes chipIn { 0% { transform: scale(.5); opacity: 0; } 60% { transform: scale(1.12); } 100% { transform: scale(1); opacity: 1; } }
  @media (prefers-reduced-motion: reduce) { .ord-ck input:checked + .bx { animation: none; } }

  /* ============================================================
     FICHE « CARTES DENSES » — structure exacte de la maquette (§5)
     .fhead (3 fcard) · .fmain (2 sec-card rail+sbody) · .fbottom · .ffoot
     ============================================================ */
  .fhead { display: grid; grid-template-columns: 1fr 1.42fr 1fr; gap: 12px; }
  /* Rangée du haut (Cabinet/Patient/Dates) plus compacte en hauteur. */
  .fhead .fcard { padding: 5px 12px; }
  .fhead .fcard .ch { margin-bottom: 3px; }
  .fhead .in2 { padding: 3px 9px; }
  .fhead .fld2 { margin: 2px 0 1px; }
  .fcard { background: color-mix(in srgb, var(--accent) 3.5%, var(--surface)); border: 1.4px solid color-mix(in srgb, var(--accent) 18%, var(--border)); border-radius: var(--r); box-shadow: var(--shadow-sm); padding: 12px 13px; }
  .fcard .ch { font-size: .92rem; font-weight: 800; letter-spacing: -.01em; color: var(--accent-text); display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
  .fld2 { display: block; font-size: .62rem; color: var(--muted); font-weight: 600; margin: 7px 0 3px; }
  .fld2:first-of-type { margin-top: 0; }
  .in2 { width: 100%; border: 1.4px solid color-mix(in srgb, var(--accent) 20%, var(--border)); border-radius: 9px; padding: 7px 9px; font-family: inherit; font-size: .8rem; color: var(--text); background: var(--surface); outline: none; transition: border-color var(--dur-base), box-shadow var(--dur-base), background var(--dur-base); }
  .in2:focus { border-color: var(--teal); box-shadow: 0 0 0 3px rgba(91,196,192,.18); background: var(--surface); }
  .in2.mono { font-family: 'DM Mono', monospace; letter-spacing: .4px; }
  .miniA { font-size: .6rem; font-weight: 600; color: var(--accent-text); background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 3px 8px; cursor: pointer; white-space: nowrap;
    transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
  .miniA:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); transform: translateY(-1px); }
  .miniA:active { transform: translateY(0); }
  .miniA:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .miniA.big { font-size: .76rem; padding: 5px 12px; border-radius: 9px; }
  .miniA.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 32%, var(--surface)); }
  .miniA.danger:hover { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
  .rr { display: flex; gap: 6px; }
  .rad { display: flex; gap: 12px; margin-top: 6px; font-size: .74rem; }
  .rad label { display: flex; align-items: center; gap: 5px; cursor: pointer; }
  .rad input { accent-color: var(--accent); width: 14px; height: 14px; }
  .clk2 { border: 1.3px solid var(--border); border-radius: 8px; background: var(--surface-2); cursor: pointer; padding: 5px 8px; font-size: .88rem; line-height: 1; }

  /* ── Carte « Dates » (28/09/2026, js/dates-retour.js) : la livraison d'un seul tenant
        (date · heure · matin/après-midi), « Sans date » en pastille d'en-tête, le jour et
        le délai à droite des intitulés. ── */
  .dtx .ch { display: flex; align-items: center; gap: 6px; }
  .dtx-sd { position: relative; margin-left: auto; display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px 2px 6px; border-radius: 999px;
    border: 1px dashed color-mix(in srgb, var(--muted) 55%, var(--border)); color: var(--muted); font-size: .58rem; font-weight: 700; white-space: nowrap; cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
  .dtx-sd input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
  .dtx-sd:hover { color: var(--text); border-color: var(--text); }
  .dtx-sd:has(input:checked) { border-style: solid; border-color: var(--warn); background: color-mix(in srgb, var(--warn) 16%, var(--surface)); color: var(--text); }
  .dtx-sd:has(input:focus-visible) { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .dtx-fl { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; margin: 6px 1px 3px; min-width: 0; }
  .dtx .dtx-lab { display: inline-flex; align-items: center; gap: 4px; flex: none; margin: 0; font-size: .56rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); cursor: pointer; }
  .dtx .dtx-liv { color: var(--danger); }
  .dtx-wd { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: .6rem; font-weight: 600; color: var(--muted); white-space: nowrap; }
  .dtx-wd b { color: var(--accent-text); font-weight: 800; }
  .dtx-wd.alerte { color: var(--danger); font-weight: 800; }
  .dtx-grp { display: flex; align-items: center; gap: 5px; height: 28px; box-sizing: border-box; padding: 0 3px 0 8px; border-radius: 9px;
    border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border)); background: var(--surface);
    transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out); }
  .dtx-grp { cursor: text; }
  .dtx-grp:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
  .dtx-grp:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent); }
  .dtx-grp > .ilx { opacity: .8; }
  /* Le champ dans son groupe : plus de cadre ni de marge (le GROUPE porte le cadre) ; le fond reste
     celui de la règle générale (= la carte), pour que les alertes (date douteuse, date corrigée) gardent le leur. */
  .dtx-grp .dtx-in { flex: 1; min-width: 0; width: 100%; padding: 0; border: 0; border-radius: 4px; color: var(--text); font: 500 .74rem 'DM Mono', monospace; }
  .dtx-grp .dtx-in:focus { outline: none; }
  .dtx-grp .dtx-in::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); }
  .dtx-grp .dtx-in:disabled { opacity: .45; }
  .dtx-sep { flex: none; width: 1px; align-self: stretch; margin: 6px 0; background: var(--border); }
  .dtx-grp .dtx-h { flex: none; width: 40px; text-align: center; }
  .dtx-mp { flex: none; display: grid; place-items: center; width: 24px; height: 22px; padding: 0; border: 0; border-radius: 7px; background: none; cursor: pointer; font-size: .8rem; line-height: 1;
    transition: background-color var(--dur-fast) var(--ease-out); }
  .dtx-mp .ilx { --ilx-t: 16px; }
  .dtx-mp:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
  .dtx-mp:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .dtx-nodate { display: none; align-items: center; justify-content: center; gap: 6px; height: 28px; box-sizing: border-box; border-radius: 9px; border: 1px dashed var(--warn);
    background: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--warn) 10%, var(--surface)) 0 6px, var(--surface) 6px 12px); font-size: .64rem; font-weight: 700; color: var(--text); cursor: pointer; }
  .dtx:has(#sans-date-livraison:checked) .dtx-grp-liv { display: none; }
  .dtx:has(#sans-date-livraison:checked) .dtx-nodate { display: flex; }

  /* Flags patient (pilules) — override de la version Sonnet */
  /* Quatre cases ÉGALES et centrées (Illan, 24/09/2026 : « 4 cases centrées,
     même taille », chacune avec son objet) : grille de deux colonnes égales,
     contenu centré dans chaque case. */
  .flags { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 9px; }
  .flags > .flag { justify-content: center; min-width: 0; }
  .flag { display: flex; align-items: center; gap: 5px; border: 1.4px solid var(--border); border-radius: 999px; padding: 5px 12px; font-size: .68rem; font-weight: 700; cursor: pointer; color: var(--muted); user-select: none; box-shadow: 0 1px 3px rgba(20,45,70,.06); transition: transform var(--dur-fast) var(--ease-spring), border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast); white-space: nowrap; }
  .flag input { position: absolute; opacity: 0; width: 0; height: 0; }
  .flag label { margin: 0; cursor: pointer; }
  /* Toute la pastille coche la case, pas seulement le texte : le label
     s'étend en calque sur la pastille entière. Le ⚙ du Scan passe au-dessus. */
  .flag { position: relative; }
  .flag label::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
  .flag .g, .flag .fx-badge--scan { position: relative; z-index: 1; }
  .flag:hover { border-color: var(--accent); transform: translateY(-1px) scale(1.05); }
  .flag:has(input:checked) { animation: pop var(--dur-enter) var(--ease-spring); }
  .flag.u { color: #c0392b; }
  .flag.u:has(input:checked) { background: color-mix(in srgb, #c0392b 12%, var(--surface)); border-color: #c0392b; }
  .flag.c:has(input:checked) { background: color-mix(in srgb, #c0392b 12%, var(--surface)); border-color: #c0392b; color: #c0392b; }
  /* CALL ME : le combiné en ROUGE (l'objet « telephone » est vert partout
     ailleurs). Une propriété CSS fill l'emporte sur l'attribut du dessin. */
  .flag.c .b3d-ob svg > path:first-child,
  .ais-flag.call .b3d-ob svg > path:first-child,
  .dcm-flag.call .b3d-ob svg > path:first-child { fill: var(--danger); }
  .flag.e { color: var(--gold); }
  .flag.e:has(input:checked) { background: color-mix(in srgb, var(--gold) 14%, var(--surface)); border-color: var(--gold); }
  .flag.s { color: var(--purple); }
  .flag.s:has(input:checked) { background: color-mix(in srgb, var(--purple) 13%, var(--surface)); border-color: var(--purple); }
  .flag .g { cursor: pointer; opacity: .7; }

  /* CONJOINTE / ADJOINTE : sec-card avec rail couleur EN HAUT + titre chip centré */
  .fmain { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .sec-card { background: var(--surface); border: 1.4px solid color-mix(in srgb, var(--accent) 18%, var(--border)); border-radius: var(--r); box-shadow: var(--shadow-sm); overflow: hidden; display: flex; flex-direction: column; }
  .sec-card .rail { height: 4px; flex: none; }
  .sec-conj .rail { background: var(--grad); }
  .sec-adj .rail { background: var(--rosegrad); }
  /* sbody remplit toute la hauteur de la carte → pas de bande blanche en bas
     de la colonne la plus courte (ADJOINTE). */
  .sec-card .sbody { padding: 7px 13px 9px; background: color-mix(in srgb, var(--accent) 3.5%, var(--surface)); flex: 1; }
  .sec-title { display: flex; align-items: center; justify-content: center; gap: 7px; width: max-content; margin: 0 auto 7px; padding: 4px 16px; border-radius: 9px; border: 1.5px solid; font-size: .74rem; font-weight: 800; letter-spacing: .14em; background: transparent; transition: transform var(--dur-fast) var(--ease-spring); }
  .sec-title:hover { transform: scale(1.04); }
  .sec-conj .sec-title { color: var(--accent-text); border-color: color-mix(in srgb, var(--accent) 42%, var(--surface)); }
  .sec-adj .sec-title { color: var(--rose); border-color: color-mix(in srgb, var(--rose) 42%, var(--surface)); }
  .sec-imp .rail { background: var(--acte-imp-fg); }
  .sec-imp .sec-title { color: var(--acte-imp-fg); border-color: color-mix(in srgb, var(--acte-imp-fg) 42%, var(--surface)); }
  .sec-imp .anx-jaw-b { color: var(--acte-imp-fg); }
  .sec-imp .anx-jaw-b.on { border-color: var(--acte-imp-fg); background: color-mix(in srgb, var(--acte-imp-fg) 14%, var(--surface)); box-shadow: 0 0 0 1px color-mix(in srgb, var(--acte-imp-fg) 30%, transparent); }

  /* 2 colonnes internes avec séparateur vertical */
  .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
  .grid2 > div { min-width: 0; }
  .grid2 > div:first-child { border-right: 1.5px solid color-mix(in srgb, var(--accent) 15%, var(--border)); padding-right: 11px; }
  .grid2 > div:last-child { padding-left: 11px; }
  /* Aligne CCM (1er item colonne gauche) avec l'en-tête INLAY CORE de la colonne
     droite, qui a un margin-top:8px → on descend le bloc CCM d'autant. */
  .sec-conj .grid2 > div:first-child > .ord-ck[data-act="CCM"] { margin-top: 8px; }
  .ord-sep { height: 1.5px; background: color-mix(in srgb, var(--accent) 22%, var(--border)); border-radius: 2px; margin: 9px 0; }

  /* En-têtes de groupe (INLAY CORE, ADJONCTION, STELLITE…) */
  .ord-h { font-size: .67rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; margin: 8px 0 2px; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
  .sec-conj .ord-h { color: var(--accent-text); }
  .sec-adj .ord-h { color: var(--rose); }
  /* Libellés adjointe les plus longs (PEI/Cire/Réparation/Rebasage) : police un
     peu réduite + paddings resserrés pour que la flèche ⬇/⬆ tienne À DROITE
     de l'item au lieu de passer dessous (la sous-colonne est étroite). */
  .sec-adj .grid2 > div:first-child { padding-right: 4px; }
  .sec-adj label[data-act="PEI"],
  .sec-adj label[data-act="Réparation"],
  .sec-adj label[data-act="Rebasage"] { padding-left: 2px; padding-right: 2px; gap: 4px; }
  .sec-adj label[data-act="PEI"] .t,
  .sec-adj label[data-act="Réparation"] .t,
  .sec-adj label[data-act="Rebasage"] .t { font-size: 0.70rem; }
  .sec-adj label[data-act="PEI"] .ord-teeth,
  .sec-adj label[data-act="Réparation"] .ord-teeth,
  .sec-adj label[data-act="Rebasage"] .ord-teeth { padding: 1px 4px; }
  .ord-h.has-ack { justify-content: flex-start; gap: 9px; }
  /* Séparateur titre/ACKERS = barre droite NETTE (pseudo-élément en pixels
     entiers : un border-left sous-pixel rendait flou « comme une parenthèse »). */
  .ord-h.has-ack .ord-ack { padding-left: 10px; position: relative; }
  .ord-h.has-ack .ord-ack::before {
    content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
    width: 2px; height: 13px; border-radius: 0;
    background: color-mix(in srgb, var(--rose) 45%, var(--border));
  }
  .ord-ack { font-size: .61rem !important; padding: 1px 6px !important; letter-spacing: .03em; color: var(--rose) !important; }
  .inline2 { display: flex; flex-wrap: wrap; gap: 4px; }
  .opts3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 3px 10px; }
  .ord-optg .ord-oh { font-size: .57rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin: 0 0 3px; line-height: 1.3; white-space: nowrap; }
  /* Finitions (Maquillage…Limite) : les 5 groupes tiennent sur UNE ligne.
     C'est le TITRE qui passe à la ligne (« Maquillage⏎Sillon ») pour rétrécir
     chaque colonne → gain de hauteur sur toute la prescription. */
  .optrow { display: flex; flex-wrap: nowrap; gap: 4px 8px; align-items: flex-start; }
  .optrow .ord-optg { min-width: 0; flex: 1; }
  .optrow .ord-ck { padding: 1px 2px; gap: 4px; font-size: .7rem; align-items: flex-start; }
  .optrow .ord-ck .bx { width: 12px; height: 12px; flex: none; margin-top: 1px; }
  .optrow .ord-ck .t { white-space: normal; line-height: 1.15; }
  .optrow .ord-oh { font-size: .56rem; white-space: normal; line-height: 1.15; margin-bottom: 2px; }

  /* Étiquettes dents/mâchoire : à côté de l'acte si ça tient, sinon sous le
     libellé (aligné dessous) — sans jamais déborder de la colonne. */
  .ord-ck:has(.acte-detail-badge) { flex-wrap: wrap; white-space: normal; }
  .ord-ck:has(.acte-detail-badge) .t { white-space: nowrap; }
  /* Petit écart : le badge reste À DROITE de l'item tant qu'il y a la place,
     et ne passe dessous que s'il ne rentre pas (la grosse indentation de 23px
     le faisait passer dessous trop tôt). */
  .ord-ck .acte-detail-badge { margin-left: 0; max-width: 100%; }
  .tooth-tag { display: inline-flex; flex-wrap: wrap; gap: 3px; align-items: center; margin-left: 6px; }
  .tt-jaw { font-size: .74rem; font-weight: 800; color: #fff; background: var(--grad); border-radius: 6px; padding: 0 5px; line-height: 1.5; display: inline-flex; align-items: center; animation: chipIn var(--dur-enter) var(--ease-spring) backwards; }
  .tt-chip { font-family: 'DM Mono', monospace; font-size: .66rem; font-weight: 700; color: var(--accent-text); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); border: none; border-radius: 6px; padding: 2px 7px; line-height: 1.4; animation: chipIn var(--dur-enter) var(--ease-spring) backwards; }
  .tt-chip.solid { color: #2d7a4f; background: color-mix(in srgb, #2d7a4f 14%, var(--surface)); }

  /* Boutons pilule Annexes / Alias produits */
  .pbtns { display: flex; gap: 6px; justify-content: flex-end; margin-top: 9px; }
  .pb { font-size: .64rem; font-weight: 700; border-radius: 7px; padding: 4px 10px; cursor: pointer; border: 1.2px solid; white-space: nowrap;
    transition: transform var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast), border-color var(--dur-fast); }
  .pb:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
  .pb:active { transform: translateY(0); }
  .pb:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .pb.a { background: color-mix(in srgb, var(--gold) 12%, var(--surface)); border-color: color-mix(in srgb, var(--gold) 55%, var(--surface)); color: var(--gold); }
  .pb.p { background: color-mix(in srgb, var(--purple) 9%, var(--surface)); border-color: color-mix(in srgb, var(--purple) 40%, var(--surface)); color: var(--purple); }
  /* Compteur du bouton Annexes (badge orange annexe, dark via tokens d'acte). */
  .pb .pb-count { display: none; background: var(--acte-annexe-fg); color: var(--surface); padding: 0 5px; border-radius: 8px; font-size: .6rem; margin-left: 3px; }

  /* Bas de fiche : Teinte + Commentaires */
  .fbottom { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: stretch; }
  .fbottom .fcard { padding: 8px 12px; }
  .tcard { width: max-content; }
  .teinte-h { font-size: 1.02rem; font-weight: 800; letter-spacing: -.01em; color: #c0392b; margin-bottom: 4px; }
  /* Champs à icône à GAUCHE (cabinet, dentiste, fournisseur — 24/09/2026) : même
     retrait pour les trois → les icônes tombent dans une seule colonne. */
  .in-ico { position: relative; }
  .in-ico > .in-ico-i { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); pointer-events: none; z-index: 1; }
  .in-ico > .in-ico-emo { font-size: 14px; line-height: 1; width: 15px; text-align: center; }
  .in-ico > input.in2, .in-ico > select.in2 { padding-left: 31px !important; }
  /* Le suggestions du cabinet / praticien sont DANS le bloc : l'icône reste centrée
     sur le champ (le bloc ne contient que le champ en hauteur). */
  /* Code Cogilog à côté du cabinet : plus affiché (Illan, 24/09/2026) — le champ
     prend toute la largeur. Le badge reste dans la page (il porte le code pour
     les écrans qui le relisent), seulement invisible. */
  #cogilog-code-badge { display: none !important; }
  /* Fournisseur teinté comme la pastille du résumé IA (.ais-fourn). */
  #fournisseur[class*="fourn-c"] { background: color-mix(in srgb, var(--f, var(--accent)) 14%, var(--surface));
    color: color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); border-color: color-mix(in srgb, var(--f, var(--accent)) 45%, transparent); font-weight: 700; }
  /* Sigles ♀ / ♂ devant Femme / Homme. */
  .sx { font-weight: 800; margin-right: 3px; }
  .sx-f { color: var(--rose); }
  .sx-h { color: var(--accent-text); }
  /* Titres de carte avec leur objet illustré (Cabinet, Teinte — 24/09/2026). */
  .ch-t { display: inline-flex; align-items: center; gap: 6px; }
  .teinte-h { display: flex; align-items: center; gap: 6px; }
  /* Repère discret du geste (Illan 25/09/2026 : « un truc simple et petit ») : clic
     gauche = la teinte, clic droit = une 2ᵉ (dégradé). La phrase entière au survol. */
  /* « Autres » : ouvre les autres teintiers (js/teinte-autres.js) ; plein quand la teinte en vient. */
  .teinte-autres { margin-left: auto; display: inline-flex; align-items: center; gap: 2px; max-width: 92px; padding: 2px 5px 2px 8px; border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border)); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); color: var(--accent-text);
    font: inherit; font-size: .6rem; font-weight: 800; letter-spacing: .02em; white-space: nowrap; cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
  .teinte-autres-t { overflow: hidden; text-overflow: ellipsis; font-family: 'DM Mono', monospace; }
  .teinte-autres svg { flex: none; width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--dur-base) var(--ease-out); }
  .teinte-autres:hover, .teinte-autres[aria-expanded="true"] { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
  .teinte-autres[aria-expanded="true"] svg { transform: rotate(180deg); }
  .teinte-autres.on { background: var(--accent); border-color: var(--accent); color: var(--surface); }
  .teinte-autres:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  /* Les trois teintiers en boutons COLLÉS sous le titre (js/teinte-autres.js, 28/09/2026). */
  .teinte-gd { display: flex; margin: 0 0 6px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--surface); }
  .teinte-gd button { flex: 1 1 auto; min-width: 0; padding: 3px 2px; border: 0; background: none; color: var(--muted); font: inherit; font-size: .56rem; letter-spacing: -.01em; font-weight: 700;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
  .teinte-gd button + button { border-left: 1px solid var(--border); }
  .teinte-gd button:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
  .teinte-gd button[aria-expanded="true"] { color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
  .teinte-gd button.on { background: var(--accent); color: var(--surface); }
  .teinte-gd button:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: -2px; }
  .teinte-mini { display: grid; grid-template-columns: repeat(5, 26px); gap: 2px; width: max-content; }
  .ord-tn { border: 1.4px solid color-mix(in srgb, var(--accent) 22%, var(--border)); border-radius: 5px; padding: 0; width: 26px; height: 20px; font-size: .62rem; font-weight: 700; font-family: 'DM Mono', monospace; color: var(--text); background: var(--surface); cursor: pointer; transition: border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast), color var(--dur-fast); display: flex; align-items: center; justify-content: center; }
  .ord-tn:hover { border-color: var(--teal); transform: translateY(-2px) scale(1.08); box-shadow: 0 4px 10px color-mix(in srgb, var(--accent) 22%, transparent); }
  .ord-tn.on { background: #fff8e1; color: #b8860b; border-color: #e6a700; }
  .tcustom2 { border: 1.4px solid color-mix(in srgb, var(--accent) 22%, var(--border)); border-radius: 6px; padding: 4px 8px; font-size: .66rem; font-family: 'DM Mono', monospace; background: var(--surface); color: var(--text); outline: none; width: 182px; margin-top: 7px; }
  .tcustom2:focus { border-color: var(--teal); }
  .ch-btns { display: flex; gap: 6px; align-items: center; }
  .fcom { display: flex; flex-direction: column; }
  .fcom .ta2 { width: 100%; min-height: 74px; flex: 1; border: 1.4px solid color-mix(in srgb, var(--accent) 20%, var(--border)); border-radius: 9px; padding: 8px 10px; font-family: inherit; font-size: .78rem; color: var(--text); background: var(--surface); resize: vertical; outline: none; line-height: 1.45; }
  .fcom .ta2:focus { border-color: var(--teal); box-shadow: 0 0 0 3px rgba(91,196,192,.18); background: var(--surface); }

  /* Pied de fiche : compteurs + reset + save + saisie continue */
  .ffoot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
  .ffoot[hidden] { display: none; }
  .ffoot .ccount { margin-right: auto; display: flex; gap: 6px; }
  .f2-count { font-size: .72rem; font-weight: 700; border-radius: 20px; padding: 4px 11px; }
  .f2-count.amber { background: #fff3cd; color: #8a6400; }
  .f2-count.orange { background: #ffe0b2; color: #c85a00; }
  .f2-reset { border: 1px solid var(--border); background: var(--surface); border-radius: 9px; padding: 9px 16px; font-family: inherit; font-weight: 600; font-size: .82rem; color: var(--text); cursor: pointer;
    transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast), transform var(--dur-fast); }
  .f2-reset:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--accent-text); background: var(--surface-2); }
  .f2-reset:active { transform: translateY(1px); }
  .f2-reset:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 2px; }
  /* Bouton PRINCIPAL de l'app : ombre tenantisée (plus de bleu ILS en dur) + états. */
  .f2-save { background: var(--grad); color: #fff; border: none; border-radius: 9px; padding: 9px 20px; font-family: inherit; font-weight: 700; font-size: .84rem; cursor: pointer;
    box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 28%, transparent);
    transition: transform var(--dur-fast), box-shadow var(--dur-fast), filter var(--dur-fast); }
  .f2-save:hover { transform: translateY(-1px); filter: brightness(1.06);
    box-shadow: 0 7px 20px color-mix(in srgb, var(--accent) 38%, transparent); }
  .f2-save:active { transform: translateY(0); filter: brightness(.98);
    box-shadow: 0 3px 10px color-mix(in srgb, var(--accent) 28%, transparent); }
  .f2-save:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 2px; }

  @media (max-width: 680px) {
    .fhead, .fmain, .fbottom { grid-template-columns: 1fr; }
  }

  /* Fiche : colonne de cartes pleine largeur, sans padding englobant (maquette) */
  .form-body { gap: 8px; padding: 0; }
  /* Grille teinte rendue par JS (.teinte-chip) → look .ord-tn de la maquette */
  .teinte-mini.teinte-options { grid-template-columns: repeat(5, 26px); gap: 2px; width: max-content; display: grid; }
  .teinte-mini .teinte-chip {
    border: 1.4px solid color-mix(in srgb, var(--accent) 22%, var(--border));
    border-radius: 5px; padding: 0; width: 26px; height: 20px;
    font-size: .62rem; font-weight: 700; font-family: 'DM Mono', monospace;
    color: var(--text); background: var(--surface); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast), color var(--dur-fast);
  }
  .teinte-mini .teinte-chip:hover { border-color: var(--teal); transform: translateY(-2px) scale(1.08); box-shadow: 0 4px 10px color-mix(in srgb, var(--accent) 22%, transparent); }
  .teinte-mini .teinte-chip.on, .teinte-mini .teinte-chip.selected, .teinte-mini .teinte-chip[aria-pressed="true"] { background: #fff8e1; color: #b8860b; border-color: #e6a700; }

  /* Cluster utilitaire du header (sync cloud · mode sombre · deconnexion) */
  .header-utils {
    display: inline-flex; align-items: center; gap: 6px;
    margin-left: 2px; position: relative;
  }
  .header-sync {
    position: static;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 11px; border-radius: 20px;
    background: var(--surface-2); border: 1px solid var(--border);
    font-size: 0.7rem; font-weight: 600; color: var(--muted);
    font-family: 'DM Sans', sans-serif; white-space: nowrap; cursor: default;
    box-shadow: var(--shadow-sm);
  }
  .header-sync-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
    background: #e0a32e; box-shadow: 0 0 0 3px rgba(224,163,46,0.18);
    transition: background var(--dur-base), box-shadow var(--dur-base);
  }
  .header-sync.ok { color: var(--teal-text); }
  .header-sync.ok .header-sync-dot {
    background: #2fb344; box-shadow: 0 0 0 3px rgba(47,179,68,0.18);
  }
  /* ERR-2 p2 — écritures en file / hors ligne (js/sync-indicator.js).
     Déclaré APRÈS .ok : la pastille garde sa classe .ok une fois connectée, ces
     règles doivent l'emporter tant qu'il reste des écritures non confirmées.
     Tokens --warn / --danger → dark mode suivi automatiquement. */
  .header-sync.pending { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); }
  .header-sync.pending .header-sync-dot {
    background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 20%, transparent);
    animation: ilsSyncEnvoi 1.1s ease-in-out infinite;
  }
  .header-sync.offline { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
  .header-sync.offline .header-sync-dot {
    background: var(--danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 20%, transparent);
    animation: none;
  }
  @keyframes ilsSyncEnvoi { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
  @media (prefers-reduced-motion: reduce) {
    .header-sync.pending .header-sync-dot { animation: none; }
  }
  .header-icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 11px; padding: 0;
    background: var(--surface); border: 1px solid var(--border);
    font-size: 1rem; line-height: 1; cursor: pointer; color: var(--text);
    transition: transform var(--dur-fast), background var(--dur-fast), border-color var(--dur-fast);
  }
  .header-icon-btn:hover { background: var(--blue-light); border-color: var(--accent); }
  .header-icon-btn--danger:hover { background: #fdecea; border-color: #e05a4f; }

  /* Panels scan */
  .scan-panel {
    background: var(--surface); border: 1px solid var(--border);
    border-left: 3px solid var(--teal); border-radius: 10px;
    padding: 10px 16px;
  }
  .scan-panel-warning {
    background: var(--surface); border: 1px solid #ffe082;
    border-left: 3px solid #f59e0b; border-radius: 10px;
    padding: 12px 16px; margin-top: 8px;
  }
  .scan-panel-accent {
    background: var(--surface); border: 1px solid var(--border);
    border-left: 3px solid var(--accent); border-radius: 10px;
    padding: 14px 16px; margin-top: 8px;
  }

  /* Dossier tags */
  .folder-tag {
    display: inline-flex; align-items: center; gap: 5px;
    border-radius: 20px; padding: 3px 10px;
    font-size: 0.75rem; font-weight: 600;
  }
  .folder-tag-handle {
    background: var(--accent-light); border: 1px solid var(--border); color: var(--accent-text);
  }
  .folder-tag-entry {
    background: #f0faf9; border: 1px solid var(--teal); color: var(--teal);
  }
  .folder-tag-remove {
    cursor: pointer; color: var(--muted); font-size: 0.85rem; font-weight: 400;
  }

  /* Inline séparateur */
  .inline-sep { height: 1px; background: var(--border); margin: 6px 0; }

  /* GC cabinet list item */
  .gc-list-item {
    padding: 7px 9px; border-radius: 7px; cursor: pointer;
    font-size: 0.78rem; display: flex; justify-content: space-between;
    align-items: center; gap: 4px; margin-bottom: 1px;
    border: 1px solid transparent;
  }
  .gc-list-item.selected {
    background: #e3f2fd; color: #1a5c8a; border-color: #90caf9;
  }
  .gc-list-item:not(.selected) { background: transparent; color: var(--text); }
  .gc-list-item-name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
  }
  .gc-list-item.selected .gc-list-item-name { font-weight: 600; }
  .gc-list-item-badges { display: flex; gap: 2px; flex-shrink: 0; }
  .gc-badge-contacts {
    font-size: 0.62rem; background: #e3f2fd; color: #1565c0;
    border-radius: 3px; padding: 1px 4px;
  }
  .gc-badge-tarif {
    font-size: 0.62rem; background: #e8f5e9; color: #2e7d32;
    border-radius: 3px; padding: 1px 4px;
  }

  /* Filter tags */
  .filter-tag {
    background: #e3f2fd; color: #1565c0; border-radius: 20px;
    padding: 2px 10px; font-size: 0.73rem; font-weight: 600;
    display: flex; align-items: center; gap: 4px;
  }
  .filter-tag-close {
    background: none; border: none; cursor: pointer;
    color: #1565c0; font-size: 0.8rem; padding: 0; line-height: 1;
  }

  /* Autocomplete suggestion item */
  .suggest-item {
    padding: 7px 12px; cursor: pointer; font-size: 0.8rem;
    border-bottom: 1px solid #f0f0f0;
  }
  .suggest-item:hover { background: #f0f7ff; }

  /* Code labo badge in list */
  .code-labo-badge {
    font-size: 0.78rem; background: #1a5c8a; color: #ffffff;
    padding: 2px 10px; border-radius: 10px; font-weight: 700;
    letter-spacing: 0.5px; -webkit-text-fill-color: #ffffff;
  }

  /* Tarif cabinet toggle button */
  .tarif-cab-btn {
    padding: 3px 10px; border-radius: 20px; font-size: 0.72rem;
    cursor: pointer; font-weight: 600; white-space: nowrap; border: 1.5px solid;
  }
  .tarif-cab-btn { transition: border-color var(--dur-fast), background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast); }
  .tarif-cab-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
  .tarif-cab-btn:active { transform: translateY(0); }
  .tarif-cab-btn:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .tarif-cab-btn.selected {
    border-color: var(--accent);
    background: var(--grad);
    color: white;
  }
  .tarif-cab-btn:not(.selected) {
    border-color: color-mix(in srgb, var(--accent) 22%, var(--border)); background: var(--surface); color: var(--text);
  }
  .tarif-cab-btn:not(.selected):hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--border)); color: var(--accent-text); }

  /* Fournisseur badge dans la liste */
  .fournisseur-badge {
    background: #e8f4fd; color: #1a5c8a; border-radius: 4px;
    padding: 1px 5px; font-size: 0.65rem; font-weight: 600;
  }

  /* Bouton-lien GC */
  .gc-action-btn {
    background: none; border: 1px solid var(--border); border-radius: 5px;
    padding: 1px 7px; font-size: 0.68rem; cursor: pointer;
    transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast);
  }
  .gc-action-btn:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); color: var(--accent-text); }
  .gc-action-btn:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
  .gc-del-btn {
    background: color-mix(in srgb, var(--danger) 9%, var(--surface));
    border: 1px solid color-mix(in srgb, var(--danger) 38%, var(--surface));
    border-radius: 5px;
    padding: 2px 8px; font-size: 0.68rem; color: var(--danger); cursor: pointer;
    transition: background var(--dur-fast), border-color var(--dur-fast);
  }
  .gc-del-btn:hover { background: color-mix(in srgb, var(--danger) 16%, var(--surface)); border-color: color-mix(in srgb, var(--danger) 55%, var(--surface)); }
  .gc-del-btn:focus-visible { outline: 2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset: 1px; }
  .gc-lier-btn {
    background: var(--grad); color: white;
    border: none; border-radius: 8px; padding: 6px 14px;
    font-size: 0.78rem; font-weight: 600; cursor: pointer;
  }

  .teinte-options { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; margin-top: 3px; }
  .teinte-chip {
    border: 1.5px solid var(--border);
    border-radius: 5px;
    padding: 2px 2px;
    font-size: 0.62rem;
    cursor: pointer;
    background: var(--surface);
    transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast);
    font-family: 'DM Mono', monospace;
    text-align: center;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
  }
  .teinte-chip:hover { border-color: var(--teal); color: var(--accent-text); }
  /* Les autres teintiers (.tnx-c, js/teinte-autres.js) cochent avec les MÊMES couleurs que le VITA (Illan, 28/09/2026). */
  .teinte-chip.selected, .tnx-c.on { background: #fff8e1; color: #b8860b; border-color: #e6a700; font-weight: 700; }
  /* 2e teinte (clic droit) = dégradé. Couleur distincte (bleu) de la primaire (or). */
  .teinte-chip.selected-2, .tnx-c.on2 { background: #e1f0fb; color: #1565c0; border-color: #2a7ba8; font-weight: 700; box-shadow: none; }
  html[data-theme="dark"] .teinte-chip.selected, html[data-theme="dark"] .tnx-c.on { background: #3a3220; color: #ffd54f; border-color: #6a5520; }
  html[data-theme="dark"] .teinte-chip.selected-2, html[data-theme="dark"] .tnx-c.on2 { background: #1e3a4f; color: #7fc4e8; border-color: #2a5070; }

  textarea { resize: vertical; min-height: 60px; line-height: 1.4; }

  /* ============================================================
     TABLEAU « cadré » — grille exacte de la maquette (§7)
     ============================================================ */
  /* Photo de la dernière liste (js/liste-photo.js) : du dessin, rien au doigt. */
  #prescriptions-list[data-photo] > * { pointer-events: none; }
  /* …et ni la photo ni la vraie liste qui la remplace ne rejouent l'entrée des
     lignes (tblRowIn) : les mêmes lignes ne « réapparaissent » pas en fondu. */
  #prescriptions-list.liste-sans-entree .row { animation: none; }
  .prescriptions-list.tbl {
    display: block;
    /* Cabinet → patient → scanner → saisie → livraison restent calés à gauche. La colonne
       statut est flexible (minmax 215px,1fr) : elle absorbe tout l'espace libre,
       et la pastille y est alignée à DROITE (justify-self:end) → le statut se
       plaque au bord droit du cadre, le vide se loge entre livraison et statut.
       215px de mini = la pastille « En livraison · … après-midi » (≈204px) tient. */
    --cols: 22px 60px 104px minmax(150px,340px) minmax(180px,320px) 120px 92px 130px minmax(200px,1fr);
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
    overflow-x: clip; padding: 0;
    /* Halo bleu (comme le header) */
    box-shadow: 0 6px 32px color-mix(in srgb, var(--accent) 18%, transparent), var(--shadow-sm);
  }
  .tbl .thead, .tbl .row { display: grid; grid-template-columns: var(--cols); align-items: center; gap: 12px; padding: 0 14px; }
  /* Anti-chevauchement : chaque cellule reste dans sa colonne */
  .tbl .row > * { min-width: 0; }
  .c-saisie, .badge-livr { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  .tbl .thead { height: 42px; background: var(--surface-2); border-bottom: 1px solid var(--border); border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .tbl .thead > div { font-size: .66rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
  .tbl .thead .th-code { transition: color var(--dur-fast); }
  .tbl .thead .th-code:hover { color: var(--accent-text); }
  /* En-tête « Statut » : boîte de la largeur de la pastille (215px), ancrée à
     droite (comme les pastilles), texte centré → le mot est centré AU-DESSUS
     des pastilles et non collé au bord. max-width pour ne pas déborder en étroit. */
  .tbl .thead .h-end { justify-self: end; width: 215px; max-width: 100%; text-align: center; }
  .tbl .row { min-height: 58px; padding-top: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--line); position: relative; cursor: pointer; transition: background var(--dur-fast); animation: tblRowIn var(--dur-enter) var(--ease-out) backwards;
    /* Stagger d'entrée : --row-i posé inline par le JS, plafonné à 24 lignes. */
    animation-delay: calc(min(var(--row-i, 0), 24) * 12ms); }
  @keyframes tblRowIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
  @media (prefers-reduced-motion: reduce) { .tbl .row { animation: none; } }
  /* Mises à jour incrémentales (save, multi-poste, recherche/filtre) : pas de
     re-animation d'entrée → fini le clignotement des lignes sous le curseur.
     L'animation d'entrée reste au 1er affichage (rebuild complet = sans .no-anim). */
  .tbl .row.no-anim { animation: none; }
  /* Rendu à la demande (Baseline sur les 3 moteurs depuis 09/2025) : une ligne hors
     écran n'est ni mise en page ni peinte tant qu'on ne la voit pas — 200 lignes
     rendues → ~15 (18/09/2026). `auto 48px` = hauteur mémorisée dès qu'une ligne a été
     rendue une fois ; avant, 48 px de CONTENU (+ 20 px de padding + 1 px de bordure
     ≈ 69 px, la hauteur mesurée d'une ligne rendue au banc) : l'ascenseur ne saute pas.
     Le menu de ligne (#rowmenu) vit hors de la ligne, le halo de survol est la ligne
     elle-même : rien n'est rogné. S'applique aussi au tableau Historique IA (.hix-tbl.tbl),
     vérifié sans descendant absolu ni mesure de ligne. */
  .tbl .row { content-visibility: auto; contain-intrinsic-size: auto 48px; }
  .tbl .row:last-child { border-bottom: none; }
  .tbl .row:hover { background: var(--surface-2); }
  /* Capsule de statut verticale arrondie (maquette §7 — pas un trait) */
  .tbl .row .accent { position: absolute; left: 6px; top: 50%; transform: translateY(-50%); width: 6px; height: 26px; border-radius: 99px; }
  .tbl .row .prescription-cb { width: 16px; height: 16px; cursor: pointer; accent-color: var(--accent); justify-self: center; }
  .c-code { font-family: 'DM Mono', monospace; font-weight: 600; font-size: .78rem; justify-self: start; cursor: pointer;
    display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: 7px; padding: 3px 8px;
    background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
  .c-code:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); box-shadow: var(--shadow-sm); }
  .c-prim { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .c-prim .t1 { font-weight: 700; font-size: .9rem; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Nom de cabinet cliquable (ouvre la fiche client) : indiqué au survol. */
  .c-prim .t1 span[onclick] { transition: color var(--dur-fast); }
  .c-prim .t1 span[onclick]:hover { color: var(--accent-text); text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 2px; }
  .c-prim .t2 { display: flex; align-items: center; gap: 5px; font-size: .76rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .c-prim .t2 .ic { opacity: .7; flex: none; }
  .c-prim .t2 .ilx { --ilx-t: 14px; }
  /* Patient : nom en haut, n° de fiche dessous (gain de place vs en ligne). */
  /* ── Colonne « Scanner » : d'où vient l'empreinte ──────────────────────────
     Même code visuel que le filtre de la barre (.pf-scan) : pastille de la marque
     + teinte --sv-*. Volontairement plus discrète que la pastille de STATUT (plus
     petite, sans icône) pour ne pas lui voler la vedette — lues en colonne, les
     teintes forment une bande qui se parcourt d'un coup d'œil. Cliquable : filtre
     la liste sur cette marque. */
  .c-scan { min-width: 0; display: flex; align-items: center; }
  .scan-tag { display: inline-flex; align-items: center; gap: 5px; max-width: 100%;
    background: var(--sv-bg); color: var(--sv-fg);
    border: 1px solid color-mix(in srgb, var(--sv-fg) 20%, transparent);
    border-radius: 999px; padding: 2px 8px 2px 6px; font-size: .64rem; font-weight: 800;
    letter-spacing: .01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    cursor: pointer; transition: border-color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast); }
  .scan-tag:hover { border-color: color-mix(in srgb, var(--sv-fg) 55%, transparent);
    box-shadow: 0 2px 8px color-mix(in srgb, var(--sv-fg) 22%, transparent); transform: translateY(-1px); }
  .scan-tag:active { transform: none; }
  /* Logo de la marque à la place du nom (24/09/2026) : même hauteur de pastille.
     Mode nuit : les logos sont dessinés pour un fond clair → un petit cartouche
     blanc derrière, comme le bouton « voir l'original » (.bqv-logo). */
  .scan-logo { display: block; height: 15px; width: auto; max-width: 90px; object-fit: contain; margin: 0 auto; }
  .scan-tag--logo { padding: 0 8px 0 7px; gap: 6px; }
  /* Toutes les pastilles de MARQUE au même gabarit (Illan 25/09/2026 : « plus
     gros et à la même taille ; DS Core aussi gros que 3Shape ») : largeur de
     la plus large (DS Core, logo très étiré), logo centré dans la place restante.
     La colonne Scanner fait la même largeur (--cols ici, --dgl-cols dans Digilab). */
  .scan-tag[data-brand] { box-sizing: border-box; width: 120px; height: 24px; font-size: .7rem; }
  .scan-tag[data-brand]:not(.scan-tag--logo) { justify-content: center; }
  .pf-scan-logo { display: block; height: 14px; width: auto; max-width: 84px; object-fit: contain; }
  #scanner-label .pf-scan-logo { height: 13px; max-width: 70px; }
  /* Les fichiers n'ont pas le même « blanc » ni la même graisse : à hauteur égale,
     MEDIT (capitales pleines) écrase tout et Shining (deux lignes) devient
     illisible. Correction d'œil par marque, même rapport dans la colonne et le menu. */
  .scan-tag[data-brand="medit"] .scan-logo { height: 12px; }
  .scan-tag[data-brand="3shape"] .scan-logo { height: 17px; }
  .scan-tag[data-brand="shining"] .scan-logo { height: 20px; }
  .pf-scan-opt[data-brand="medit"] .pf-scan-logo, #filter-scanner[data-brand="medit"] .pf-scan-logo { height: 11px; }
  .pf-scan-opt[data-brand="3shape"] .pf-scan-logo, #filter-scanner[data-brand="3shape"] .pf-scan-logo { height: 15px; }
  .pf-scan-opt[data-brand="shining"] .pf-scan-logo, #filter-scanner[data-brand="shining"] .pf-scan-logo { height: 19px; max-width: 92px; }
  /* Mode nuit (Illan 25/09/2026 : le cartouche blanc « c'est moche, fais comme
     le fond blanc ») : le logo se pose DIRECTEMENT sur la pastille, ses teintes
     inversées — l'encre sombre devient claire, la couleur de la marque garde sa
     teinte (le hue-rotate annule le virage de couleur de l'inversion). Fichiers à
     fond transparent (assets/scanners/). Même règle pour .bqv-logo (bouton-3d.js). */
  html[data-theme="dark"] .scan-logo, html[data-theme="dark"] .pf-scan-logo { filter: invert(1) hue-rotate(180deg); }
  .scan-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--sv-fg);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--sv-fg) 22%, transparent); }
  /* Bon papier : un tiret, pas une pastille grise — ce serait du bruit sur la
     majorité des lignes, et l'absence de scanner n'est pas une marque. */
  .scan-none { color: var(--muted); opacity: .6; font-size: .78rem; }
  @media (prefers-reduced-motion: reduce) { .scan-tag { transition: none; } .scan-tag:hover { transform: none; } }

  /* Colonne des badges, empilés (Illan 30/09/2026) */
  .c-flags { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; min-width: 0; }
  .c-flags > .pi-badge { margin-left: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .c-pat { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; gap: 2px; min-width: 0; }
  /* Nom + badges (même patient, en pause, à refaire…) : on AUTORISE le retour
     à la ligne pour que les badges s'affichent TOUJOURS (avant : nowrap +
     ellipsis coupait tout, badges invisibles). Le nom et chaque badge restent
     insécables ; ils s'empilent en vertical si la colonne est trop étroite. */
  .c-pat .pname { font-size: .86rem; font-weight: 600; min-width: 0; max-width: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 3px; line-height: 1.3; }
  .c-pat .pname > .pname-nom { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .c-pat .fcode { flex: none; white-space: nowrap;
    font-family: 'DM Mono', monospace; font-size: .66rem; font-weight: 600;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px;
    background-image: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
  .c-work .lbl { font-size: .82rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .c-work .dents { display: inline-block; font-family: 'DM Mono', monospace; font-size: .68rem; font-weight: 600;
    color: color-mix(in srgb, var(--teal) 65%, #0a3b44); background: color-mix(in srgb, var(--teal) 15%, var(--surface));
    border-radius: 5px; padding: 1px 6px; margin-top: 2px; }
  .c-saisie { display: flex; align-items: center; gap: 5px; font-size: .76rem; color: var(--muted); }
  .badge-livr { display: inline-flex; align-items: center; gap: 5px; font-size: .8rem; font-weight: 600; color: #c0392b; white-space: nowrap; }
  .badge-livr .sepd { opacity: .5; }
  .tbl .pill { justify-self: end; display: inline-flex; align-items: center; gap: 6px; font-size: .74rem; font-weight: 700; padding: 6px 11px; border-radius: 20px; white-space: nowrap; }
  .tbl .pill .d { width: 8px; height: 8px; border-radius: 50%; flex: none; }
  .tbl .pill .ic { display: flex; flex: none; }
  .tbl .pill .ic svg { width: 13px; height: 13px; }
  /* couleurs de pills + capsule (accent) par statut. L'accent a un HALO doux
     (box-shadow couleur @ ~17%) = l'aura de la maquette. */
  /* Pastilles/points de statut : tokens --stp-* (source unique, dark automatique). */
  .pill.st-attente   { background: var(--stp-attente-bg);   color: var(--stp-attente-fg); }   .accent.st-attente   { background: var(--stp-attente-dot);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-attente-dot) 17%, transparent); }
  .pill.st-verifie   { background: var(--stp-verifie-bg);   color: var(--stp-verifie-fg); }   .accent.st-verifie   { background: var(--stp-verifie-dot);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-verifie-dot) 17%, transparent); }
  .pill.st-importe   { background: var(--stp-importe-bg);   color: var(--stp-importe-fg); }   .accent.st-importe   { background: var(--stp-importe-dot);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-importe-dot) 17%, transparent); }
  .pill.st-cogilog   { background: var(--stp-cogilog-bg);   color: var(--stp-cogilog-fg); }   .accent.st-cogilog   { background: var(--stp-cogilog-dot);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-cogilog-dot) 17%, transparent); }
  .pill.st-reception { background: var(--stp-reception-bg); color: var(--stp-reception-fg); } .accent.st-reception { background: var(--stp-reception-dot); box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-reception-dot) 17%, transparent); }
  .pill.st-livraison { background: var(--stp-livraison-bg); color: var(--stp-livraison-fg); } .accent.st-livraison { background: var(--stp-livraison-dot); box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-livraison-dot) 17%, transparent); }
  .pill.st-livre     { background: var(--stp-livre-bg);     color: var(--stp-livre-fg); }     .accent.st-livre     { background: var(--stp-livre-dot);     box-shadow: 0 0 0 3px color-mix(in srgb, var(--stp-livre-dot) 17%, transparent); }
  .kebab { justify-self: center; width: 30px; height: 30px; border-radius: 8px; border: 1px solid transparent; background: transparent;
    color: var(--muted); display: grid; place-items: center; cursor: pointer; font-size: 1.1rem; line-height: 1; transition: background var(--dur-fast), color var(--dur-fast); }
  .kebab:hover { background: var(--surface-2); color: var(--accent-text); }
  /* menu kebab (actions ligne) */
  .rowmenu { position: fixed; z-index: 90; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 16px 38px rgba(20,45,70,.2); padding: 5px; min-width: 194px;
    opacity: 0; transform: translateY(-6px) scale(.97); transform-origin: top right; pointer-events: none;
    transition: opacity var(--dur-fast) ease, transform var(--dur-base) var(--ease-out); }
  .rowmenu.open { opacity: 1; transform: none; pointer-events: auto; }
  .rowmenu .rm-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 11px; border: none; background: transparent;
    border-radius: 8px; font-family: inherit; font-size: .82rem; font-weight: 600; color: var(--text); cursor: pointer; text-align: left; transition: background var(--dur-fast); }
  .rowmenu .rm-item:hover { background: var(--surface-2); }
  .rowmenu .rm-item.sep-top { margin-top: 5px; border-top: 1px solid var(--line); padding-top: 11px; }
  .rowmenu .rm-item.danger { color: #d2604f; }
  /* L'OBJET ILLUSTRÉ de chaque entrée (jeu partagé js/bouton-3d.js, 19/09/2026) :
     une case de largeur FIXE, pour que tous les libellés s'alignent, emoji de
     repli compris. Le dessin porte ses propres couleurs — on ne lui applique
     donc aucune teinte, pas même sur l'entrée rouge « Supprimer ». */
  .rowmenu .rm-ic { flex: none; width: 21px; height: 21px; display: grid; place-items: center;
    font-size: .95rem; line-height: 1; }
  .rowmenu .rm-ic .b3d-ob, .rowmenu .rm-ic .b3d-ob svg { width: 19px; height: 19px; }
  /* Le cube 3D (bouton-3d.js) à l'échelle de la case : 14 px d'arête, faces à 7 px. */
  .rowmenu .rm-ic .b3d-sc { width: 21px; height: 21px; perspective: 52px; }
  .rowmenu .rm-ic .b3d-cube { width: 14px; height: 14px; }
  .rowmenu .rm-ic .b3d-cube i:nth-child(1) { transform: translateZ(7px); }
  .rowmenu .rm-ic .b3d-cube i:nth-child(2) { transform: rotateY(180deg) translateZ(7px); }
  .rowmenu .rm-ic .b3d-cube i:nth-child(3) { transform: rotateY(90deg) translateZ(7px); }
  .rowmenu .rm-ic .b3d-cube i:nth-child(4) { transform: rotateY(-90deg) translateZ(7px); }
  .rowmenu .rm-ic .b3d-cube i:nth-child(5) { transform: rotateX(90deg) translateZ(7px); }
  .rowmenu .rm-ic .b3d-cube i:nth-child(6) { transform: rotateX(-90deg) translateZ(7px); }
  /* Le libellé prend la place restante : le chevron des volets reste collé à
     droite (il l'obtenait par margin-left:auto, que le libellé lui reprenait). */
  .rowmenu .rm-lb { flex: 1 1 auto; min-width: 0; }
  /* Logo de la plateforme d'origine (volet Scan) : même taille que dans « Voir
     fiche » (.bqv-lb .bqv-logo), teintes inversées la nuit, comme .scan-logo. */
  .rowmenu .rm-lb .bqv-logo { display: inline-block; vertical-align: middle; height: 15px; width: auto; max-width: 108px; object-fit: contain; }
  html[data-theme="dark"] .rowmenu .rm-lb .bqv-logo { filter: invert(1) hue-rotate(180deg); }
  /* Sous-menus du menu de ligne (Documents, Scan) : volet latéral au survol.
     Masqué en visibility (pas display:none) pour rester MESURABLE — le placement
     JS a besoin de ses dimensions avant de l'afficher. */
  .rowmenu .rm-sub { position: relative; }
  .rowmenu .rm-sub .rm-chev { margin-left: auto; color: var(--muted); font-size: 1rem; line-height: 1;
    transition: transform var(--dur-fast) ease, color var(--dur-fast); }
  .rowmenu .rm-sub:hover > .rm-sub-head, .rowmenu .rm-sub.open > .rm-sub-head { background: var(--surface-2); }
  .rowmenu .rm-sub:hover > .rm-sub-head .rm-chev, .rowmenu .rm-sub.open > .rm-sub-head .rm-chev {
    color: var(--accent-text); transform: translateX(2px); }
  /* L'écart part du BORD DE L'ITEM, pas du menu : il faut franchir les 6px de
     padding+bordure du menu (10px) pour que le volet ne mange pas son cadre. */
  .rowmenu .rm-flyout { position: absolute; top: -5px; left: 100%; margin-left: 10px; min-width: 186px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 16px 38px rgba(20,45,70,.2); padding: 5px;
    opacity: 0; visibility: hidden; pointer-events: none; transform: translateX(-5px);
    transition: opacity var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out); }
  /* Pont invisible sur l'écart tête↔volet : sans lui, la souris qui traverse les
     5px de marge quitte le :hover et le volet se referme. */
  .rowmenu .rm-flyout::before { content: ''; position: absolute; top: 0; bottom: 0; left: -14px; width: 14px; }
  .rowmenu .rm-flyout.left { left: auto; right: 100%; margin-left: 0; margin-right: 10px; transform: translateX(5px); }
  .rowmenu .rm-flyout.left::before { left: auto; right: -14px; }
  .rowmenu .rm-sub:hover > .rm-flyout, .rowmenu .rm-sub.open > .rm-flyout {
    opacity: 1; visibility: visible; pointer-events: auto; transform: none; }
  @media (prefers-reduced-motion: reduce) {
    .rowmenu .rm-flyout, .rowmenu .rm-sub .rm-chev { transition: none; }
  }
  .tbl .empty-state { grid-column: 1 / -1; }
  /* Petit portable (< 1200px avec la colonne des badges) : on sacrifie Scanner, sinon
     le STATUT sort du cadre. Cellules visibles = colonnes du gabarit, toujours. */
  @media (max-width: 1200px) and (min-width: 981px) {
    .prescriptions-list.tbl { --cols: 22px 60px 104px minmax(150px,340px) minmax(180px,320px) 92px 130px minmax(200px,1fr); }
    .tbl .thead .h-scan, .c-scan { display: none; }
  }
  @media (max-width: 980px) {
    /* STATUT = max-content (sinon la pastille recouvrait le patient) ; Cabinet/Patient
       en minmax(0,…) se tronquent au lieu de la pousser. */
    .prescriptions-list.tbl { --cols: 22px 56px minmax(0,1fr) minmax(0,1.1fr) max-content; }
    /* La colonne Scanner suit Saisie/Livraison : masquée en étroit (le nombre de
       cellules VISIBLES doit rester égal au nombre de colonnes du gabarit, sinon
       les cellules en trop débordent sur une colonne implicite). Le filtre de la
       barre reste, lui, disponible sur téléphone pour isoler une marque. */
    .tbl .thead .h-saisie, .tbl .thead .h-livr, .tbl .thead .h-scan, .c-saisie, .badge-livr, .c-scan { display: none; }
    /* Badges : sous cabinet et patient, seulement s'il y en a */
    .tbl .thead .h-flags { display: none; }
    .tbl .row > .c-flags { grid-column: 3 / -1; grid-row: 2; flex-direction: row; flex-wrap: wrap; margin-top: -8px; }
    .tbl .row > .c-flags:empty { display: none; }
  }

  .actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 8px 14px;
    border-top: 1px solid var(--border);
    background: linear-gradient(90deg, var(--teal-light), var(--accent-light));
  }

  .btn {
    padding: 6px 16px;
    border-radius: 8px;
    font-family: 'DM Sans', sans-serif;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    border: none;
    transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), filter var(--dur-fast);
  }

  .btn-secondary {
    background: var(--surface);
    border: 1.5px solid var(--border);
    color: var(--text);
  }

  .btn-secondary:hover { border-color: var(--accent); color: var(--accent-text); }

  .btn-primary {
    background: var(--grad);
    color: white;
  }

  .btn-primary:hover { background: var(--grad); filter: brightness(0.9); }

  .btn-success {
    background: var(--success);
    color: white;
  }

  .btn-success:hover { background: #235f3d; }

  /* NOTIFICATIONS — toast « cockpit » : surface + bordure tokens, pastille d'icône
     selon le type (✅ succès / ⚠️ erreur via .err, posée par showToast). Dark
     automatique par les tokens + ombre dédiée plus bas. */
  .toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    display: flex; align-items: center; gap: 10px;
    background: var(--surface);
    color: var(--text);
    border: 1px solid color-mix(in srgb, var(--success) 45%, var(--border));
    padding: 11px 18px 11px 12px;
    border-radius: 13px;
    font-size: 0.85rem;
    font-weight: 600;
    box-shadow: 0 12px 30px -8px color-mix(in srgb, var(--success) 35%, rgba(20,45,70,.25)), var(--shadow-sm);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--dur-enter), transform var(--dur-enter);
    pointer-events: none;
    max-width: min(420px, calc(100vw - 48px));
    /* Un toast (validation / erreur) doit TOUJOURS rester au premier plan, quelle que
       soit la fenêtre ouverte : au-dessus de toutes les modales/menus (plafond app
       = 100003) mais SOUS le calque de colorimétrie body::after (2147483000) pour
       garder les mêmes couleurs. pointer-events:none → ne bloque jamais un clic. */
    z-index: 2000000000;
  }
  .toast .toast-ic {
    flex: none; width: 26px; height: 26px; border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    font-size: .8rem; line-height: 1;
    background: color-mix(in srgb, var(--success) 14%, var(--surface));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--success) 30%, transparent);
  }
  .toast.err { border-color: color-mix(in srgb, var(--danger) 50%, var(--border));
    box-shadow: 0 12px 30px -8px color-mix(in srgb, var(--danger) 35%, rgba(20,45,70,.25)), var(--shadow-sm); }
  .toast.err .toast-ic { background: color-mix(in srgb, var(--danger) 12%, var(--surface));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 32%, transparent); }
  html[data-theme="dark"] .toast { box-shadow: 0 12px 32px rgba(0,0,0,.55); }

  .toast.show { opacity: 1; transform: translateY(0); }

  /* ── Pastille de suivi coursier (module eager js/coursier-live.js) ──
     Fixe en bas-gauche (le toast est en bas-droite → pas de collision). Couleur du
     tenant via --clv-accent (posé en JS) avec repli sur --accent. Au-dessus du contenu
     mais SOUS les modales (le détail vit dans la fenêtre Coursiers). */
  .clv-badge {
    position: fixed; left: 20px; bottom: 20px; z-index: 1400;
    display: none; align-items: center; gap: 10px; max-width: 300px;
    padding: 10px 14px 10px 12px; border-radius: 14px;
    background: var(--surface, #fff); color: var(--text, #1c2a35);
    border: 1px solid color-mix(in srgb, var(--clv-accent, var(--accent, #1a5c8a)) 35%, var(--line, #e2ebf1));
    box-shadow: 0 12px 30px -10px rgba(15,35,55,.35);
    cursor: pointer; font-size: .85rem;
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    transition: transform var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
  }
  .clv-badge.clv-show { display: flex; }
  .clv-badge:hover { transform: translateY(-2px); box-shadow: 0 16px 36px -10px rgba(15,35,55,.45); }
  .clv-badge:focus-visible { outline: 2px solid var(--clv-accent, var(--accent, #1a5c8a)); outline-offset: 2px; }
  .clv-emoji { font-size: 1.25rem; line-height: 1; }
  .clv-txt { display: flex; flex-direction: column; min-width: 0; }
  .clv-client { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .clv-eta { font-size: .78rem; font-weight: 700; color: var(--clv-accent, var(--accent, #1a5c8a)); }
  .clv-count { margin-left: 2px; font-size: .7rem; font-weight: 800; color: #fff; border-radius: 999px; padding: 2px 7px; background: var(--clv-accent, var(--accent, #1a5c8a)); }
  .clv-badge.clv-searching .clv-emoji { animation: clvPulse 1.5s ease-in-out infinite; }
  @keyframes clvPulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
  @media (prefers-reduced-motion: reduce) { .clv-badge.clv-searching .clv-emoji { animation: none; } }
  html[data-theme="dark"] .clv-badge {
    background: #242938; color: #e0e6ed;
    border-color: color-mix(in srgb, var(--clv-accent, var(--accent, #1a5c8a)) 45%, #3a4055);
    box-shadow: 0 12px 30px -10px rgba(0,0,0,.6);
  }
  html.mobile-zoom-default .clv-badge { left: 12px; bottom: 14px; font-size: .95rem; padding: 12px 16px; max-width: 70vw; }

  @keyframes slideInRight {
    from { opacity: 0; transform: translateX(30px); }
    to   { opacity: 1; transform: translateX(0); }
  }

  /* LISTE DES PRESCRIPTIONS */
  /* Maquette : pas de carte blanche englobante — titre/stats/toolbar/tableau
     sont des éléments séparés sur le fond de page. */
  .list-card {
    background: transparent;
    border: none;
    border-radius: 0;
    max-width: 1500px;
    margin: 26px auto 0;
    overflow: visible;
    box-shadow: none;
  }
  /* Bandeau filtres (stats + recherche) : transparent, sans bordure ni padding latéral */
  .list-card .prescriptions-filters {
    padding: 0 !important;
    border-bottom: none !important;
    gap: 12px !important;
  }
  .list-card .list-header { padding: 0 2px 4px !important; border-bottom: none !important; align-items: flex-end !important; }
  .list-card .list-header h2 { font-size: 1.22rem !important; font-weight: 700; letter-spacing: -.01em; }

  .list-header {
    padding: 16px 24px;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .list-header h2 { font-size: 0.9rem; font-weight: 600; }

  .prescriptions-list { padding: 16px; display: flex; flex-direction: column; gap: 10px; max-height: 70vh; overflow-y: auto; }

  .prescription-item {
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--section-bg);
    cursor: pointer;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
  }

  .prescription-item:hover { border-color: var(--teal); box-shadow: 0 2px 12px rgba(91,196,192,0.15); }

  .pi-left { display: flex; flex-direction: column; gap: 4px; }
  .pi-num { font-family: 'DM Mono', monospace; font-size: 0.8rem; background: var(--grad); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-weight: 600; }
  .pi-patient { font-size: 0.9rem; font-weight: 500; }
  .pi-type { font-size: 0.78rem; color: var(--muted); }

  .pi-right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
  .pi-date { font-size: 0.78rem; color: var(--muted); }

  /* (Recette .status-badge/.status-* supprimée le 12/08/2026 : générée par aucun JS —
     resolveFicheStatut ne sert que converti en .pill.st-*, tokens --stp-* ci-dessus.) */

  /* ── Capsule statut verticale §7 (maquette) ── */
  .statusdot {
    width: 7px;
    height: 26px;
    border-radius: 99px;
    flex-shrink: 0;
    background: var(--border);
  }
  .prescription-item.status-attente   .statusdot { background: #d4a017; }
  .prescription-item.status-verifie   .statusdot { background: #5a9e3a; }
  .prescription-item.status-importe   .statusdot { background: #2a7ad6; }
  .prescription-item.status-cogilog   .statusdot { background: #7c3aed; }
  .prescription-item.status-reception .statusdot { background: #0891b2; }
  .prescription-item.status-livraison .statusdot { background: #ea7600; }
  .prescription-item.status-livre     .statusdot { background: #16a34a; }

  /* ── Suggestions « N° de fiche » (écran de saisie, #num-suggestions rempli par
     _rechercherNumFiche, js/form-editor.js) — refait le 30/09/2026 (audit Z1-11).
     Même grammaire que les lignes de la liste (.tbl .row) : capsule d'état à gauche
     et pastille .pill.st-* (palette partagée des états --stp-* → --ec-*), survol en
     CSS → le mode nuit suit les tokens. Le JS ne pose que display none/block. */
  .nsug-box {
    display: none; position: absolute; left: 0; right: 0; top: 100%; margin-top: 6px;
    min-width: 340px; max-width: calc(100vw - 24px); max-height: 240px; overflow-y: auto; z-index: 600;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-md);
  }
  .nsug-row {
    position: relative; display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 40px; padding: 7px 12px 7px 20px; font-size: .78rem; cursor: pointer;
    border-bottom: 1px solid var(--line); transition: background var(--dur-fast), box-shadow var(--dur-fast);
  }
  .nsug-row:last-child { border-bottom: none; }
  .nsug-row:hover {
    background: var(--surface-2);
    box-shadow: inset 2.5px 0 0 color-mix(in srgb, var(--teal) 85%, transparent);
  }
  .nsug-row .accent { position: absolute; left: 7px; top: 50%; transform: translateY(-50%); width: 5px; height: 20px; border-radius: 99px; }
  .nsug-num { font-family: 'DM Mono', monospace; color: var(--text); white-space: nowrap; }
  .nsug-num b { display: inline-block; min-width: 6ch; font-weight: 600; }
  .nsug-code { display: inline-block; min-width: 3.6ch; color: var(--teal-text); font-weight: 700; margin-right: 6px; }
  .nsug-meta { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .nsug-pill { display: inline-flex; align-items: center; flex: none; font-size: .64rem; font-weight: 700; padding: 3px 9px; border-radius: 20px; white-space: nowrap; }
  /* Largeur FIXE : les pastilles s'alignent en colonne d'une ligne à l'autre. */
  .nsug-who { width: 140px; color: var(--muted); font-size: .72rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Téléphone : l'ancienne largeur mini (280 px) et une colonne patient plus étroite —
     la liste part du champ N°, elle ne doit pas s'élargir vers le bord de l'écran. */
  html.mobile-zoom-default .nsug-box { min-width: 280px; }
  html.mobile-zoom-default .nsug-who { width: 84px; }

  /* État vide designé (Règle 22.5) : pastille emoji à halo + titre + sous-titre.
     Le conteneur .empty-state reste le même (généré par prescription-list.js) ;
     un simple texte nu y reste lisible (anciens rendus/caches). */
  .empty-state {
    text-align: center;
    padding: 40px 24px 44px;
    color: var(--muted);
    font-size: 0.85rem;
  }
  .empty-state .es-badge {
    width: 62px; height: 62px; margin: 0 auto 14px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 20px;
    background: linear-gradient(135deg,
      color-mix(in srgb, var(--accent) 14%, var(--surface)),
      color-mix(in srgb, var(--teal) 16%, var(--surface)));
    border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--border));
    box-shadow: 0 10px 30px -8px color-mix(in srgb, var(--accent) 30%, transparent),
      0 0 0 6px color-mix(in srgb, var(--accent) 6%, transparent);
    font-size: 1.7rem; line-height: 1;
  }
  .empty-state .es-title { font-size: .95rem; font-weight: 700; color: var(--text); margin-bottom: 4px; }
  .empty-state .es-sub { font-size: .78rem; color: var(--muted); line-height: 1.5; max-width: 380px; margin: 0 auto; }

  .btn-pdf {
    background: var(--surface);
    border: 1.5px solid var(--border);
    color: var(--accent-text);
    border-radius: 8px;
    padding: 6px 12px;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    font-family: 'DM Sans', sans-serif;
    transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
    white-space: nowrap;
  }
  .btn-pdf:hover { background: var(--accent); color: white; border-color: var(--accent); }
  .pi-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }

  @media (max-width: 680px) {
    .top-row { grid-template-columns: 1fr; }
    .main-row { grid-template-columns: 1fr; }
    .bottom-row { grid-template-columns: 1fr; }
  }

  /* Drag & drop dossiers */
  #folder-drop-zone.drop-hover {
    background: var(--teal-light);
    border-color: var(--accent);
    color: var(--accent-text);
    transform: scale(1.01);
  }
  /* Badges dents/précision — même code couleur que le résumé IA (cf. .ais-d) :
     conjointe bleu · solidarisé vert · adjointe rose · implant violet · extraction rouge.
     Dents façon résumé IA : flèche « → » pour les suites, « | » entre arcades, parenthèses. */
  .ord-teeth {
    display:inline-block; vertical-align:middle; cursor:pointer;
    font-family:'DM Mono', ui-monospace, monospace; font-weight:700;
    font-size:0.58rem; line-height:1.5;
    /* Flux texte normal : les numéros se suivent et se replient proprement,
       espacement cohérent, sans jamais déborder de la colonne. */
    white-space:normal; max-width:100%; min-width:0;
    border-radius:8px; padding:1px 6px;
  }
  .ord-teeth .ar { font-weight:800; opacity:.5; margin:0 1px; }   /* flèche suite (24→27) */
  .ord-teeth .sp { font-weight:800; opacity:.4; margin:0 2px; }   /* séparateur d'arcade */
  /* Flèche mâchoire ⬆/⬇/↕ : plus grosse pour rester lisible dans un long badge */
  .ord-teeth .jaw { font-size:1.35em; font-weight:900; vertical-align:-1px; margin-right:2px; }
  .ord-teeth .lk { width:9px; height:9px; margin-right:3px; vertical-align:-1px; opacity:.75; }
  /* Dents unitaires : chaque dent distincte, séparée par une fine cloison (= .ais-units) */
  .ord-teeth .tooth { padding:0 3px; }
  .ord-teeth .tooth + .tooth { box-shadow:-1.5px 0 0 0 #fff; }
  /* Conteneur transparent : une ou plusieurs pilules (vert solidarisé + bleu unitaire) */
  .acte-detail-badge { display:inline-flex; flex-wrap:wrap; align-items:center; gap:3px; cursor:pointer; vertical-align:middle; }
  /* Badge multi-pilules : sa propre ligne, pleine largeur de colonne (sans indent). */
  .ord-ck .acte-detail-badge.multi { flex-basis:100%; margin-left:2px; }
  .ord-teeth.t-conj  { background:#e8f4fb; color:#1a5c8a; }
  .ord-teeth.t-solid { background:#e3f3e9; color:#2d7a4f; }
  .ord-teeth.t-adj   { background:#fdf2f6; color:#72243e; }
  .ord-teeth.t-imp   { background:#f3e5f5; color:#6a1b9a; }
  .ord-teeth.t-extr  { background:#ffebee; color:#c62828; }
  .ord-teeth:hover   { filter:brightness(.97); }
  .us-badge { line-height:1; }
  /* Unitaire / Solidaire : 2 colonnes fixes — le label ne bouge jamais, ses dents
     s'affichent dessous et s'adaptent (wrap) dans la largeur de la colonne. */
  .us-row { display:flex; gap:12px; align-items:flex-start; margin-bottom:5px; }
  .us-cell { flex:1 1 0; min-width:0; display:flex; flex-direction:column; gap:3px; }
  html[data-theme="dark"] .ord-teeth.t-conj  { background:#1e3a4f; color:#7fc4e8; }
  html[data-theme="dark"] .ord-teeth.t-solid { background:#1c3326; color:#81c784; }
  html[data-theme="dark"] .ord-teeth.t-adj   { background:#3a1e2c; color:#f48fb1; }
  html[data-theme="dark"] .ord-teeth.t-imp   { background:#2e1e3a; color:#ce93d8; }
  html[data-theme="dark"] .ord-teeth.t-extr  { background:#3a1a1a; color:#ef9a9a; }
  html[data-theme="dark"] .ord-teeth .tooth + .tooth { box-shadow:-1.5px 0 0 0 rgba(255,255,255,.28); }
  #acte-detail-popup {
    position:fixed; z-index:2000; background:var(--surface); border-radius:12px;
    box-shadow:0 8px 28px rgba(0,0,0,0.22); padding:12px 14px; min-width:200px;
    border:1px solid #d0e0ea;
  }
  #acte-detail-popup input[type=text] {
    width:100%; box-sizing:border-box; padding:5px 8px; font-size:0.8rem;
    border:1px solid #c8daf8; border-radius:7px; margin-bottom:8px;
    font-family:'DM Sans',sans-serif;
  }
  #acte-qty-preview { font-size:.68rem; color:var(--success); min-height:14px; margin-bottom:6px; }

  /* Unitaire / Solidaire : voile de la modale (js/unitaire-solidaire.js). La
     carte, elle, est stylée plus bas (§ Modale Unitaire / Solidaire). */
  #popup-unit-solid { position:fixed;inset:0;background:rgba(0,0,0,0.28);z-index:2100; }

  /* Lasso sélection dents */
  #us-lasso-rect {
    position:fixed; border:1.5px solid var(--accent); background:color-mix(in srgb, var(--accent) 10%, transparent);
    border-radius:6px; pointer-events:none; z-index:9999; display:none;
  }

  /* ═══════ IMPLANTS — REDESIGN (cohérent avec dentist-view) ═══════ */
  /* Coque modale */
  /* Header gradient brand → teal (signature dentist-view) */
  .imp-header {
    background: linear-gradient(120deg, #1a5c8a 0%, #2a7ba8 60%, #5bc4c0 100%);
    color: white;
    padding: 14px 22px;
    display: flex; align-items: center; justify-content: space-between;
    flex-shrink: 0; gap: 14px; flex-wrap: wrap;
  }
  .imp-header-left { display: flex; align-items: center; gap: 12px; }
  .imp-header-ico {
    background: rgba(255,255,255,0.18);
    border-radius: 10px;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.2rem;
  }
  .imp-header-title { font-weight: 800; font-size: 1rem; line-height: 1.2; }
  .imp-header-sub { font-size: 0.72rem; opacity: 0.88; margin-top: 2px; }
  /* Tabs intégrés au header (pills translucides) */
  .imp-tabs { display: flex; align-items: center; gap: 6px; }
  .imp-tab-btn {
    background: rgba(255,255,255,0.12);
    border: 1px solid rgba(255,255,255,0.18);
    color: white;
    padding: 6px 14px;
    font-size: 0.78rem; font-weight: 600;
    border-radius: 8px; cursor: pointer;
    font-family: inherit;
    transition: background var(--dur-fast);
  }
  .imp-tab-btn:hover { background: rgba(255,255,255,0.22); }
  .imp-tab-btn.active {
    background: var(--surface); color: var(--accent-text);
    border-color: var(--surface);
  }
  .imp-btn-close {
    background: rgba(255,255,255,0.15);
    border: 1px solid rgba(255,255,255,0.2);
    color: white; cursor: pointer;
    width: 32px; height: 32px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem; padding: 0;
    margin-left: 4px;
  }
  .imp-btn-close:hover { background: rgba(255,255,255,0.25); }
  /* ── Indicateur coulissant des onglets Implants (mécanique Digilab .dgl-seg-ind).
     Le fond du pill actif .imx-tab.active (implants-ui-styles.js) est DÉPLACÉ sur
     #imp-tab-ind, qui glisse sous les boutons ; le bouton actif devient transparent.
     JS : _impMajTabInd (implants-module.js) — lire offsetWidth/offsetLeft PUIS écrire.
     Spécificité > aux styles injectés (#modal-implants .imx-tab.active). */
  #modal-implants .imx-tabs .imx-tab-ind {
    position: absolute; top: 0; bottom: 0; left: 0; width: 158px;
    border-radius: 999px; pointer-events: none;
    background: #eaf6fb; /* teinte EXISTANTE du .imx-tab.active (relocalisée, pas une couleur nouvelle) */
    box-shadow: 0 0 0 1px rgba(255,255,255,.5), 0 8px 22px rgba(0,0,0,.3), 0 0 26px color-mix(in srgb, var(--teal) 55%, transparent);
    transition: transform var(--dur-base) var(--ease-out), width var(--dur-base) var(--ease-out);
  }
  html[data-theme="dark"] #modal-implants .imx-tabs .imx-tab-ind { background: #cdeef0; } /* idem : teinte dark existante du pill actif */
  #modal-implants .imx-tabs .imx-tab { position: relative; z-index: 1; }
  #modal-implants .imx-tabs .imx-tab.active,
  html[data-theme="dark"] #modal-implants .imx-tabs .imx-tab.active {
    background: transparent; border-color: transparent; box-shadow: none;
  }
  #modal-implants .imx-tabs .imx-tab.active:hover { transform: none; background: transparent; }
  /* Toolbar blanc compact */
  .imp-toolbar {
    background: white;
    padding: 12px 18px;
    border-bottom: 1px solid #d0e0ea;
    flex-shrink: 0;
    display: flex; flex-direction: column; gap: 10px;
  }
  .imp-toolbar-row {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  }
  /* Drop zone — accent brand, étirée */
  .imp-drop-zone {
    flex: 1; min-width: 280px;
    border: 2px dashed #c8d6e2;
    border-radius: 10px;
    padding: 14px 18px;
    text-align: center; cursor: pointer;
    transition: border-color var(--dur-fast), background var(--dur-fast), color var(--dur-fast);
    background: #f8fafc;
    color: #7a96a8;
    font-size: 0.82rem;
    line-height: 1.3;
  }
  .imp-drop-zone:hover, .imp-drop-zone.drag-over {
    border-color: #5bc4c0;
    background: #e8f6f5;
    color: #1a5c8a;
  }
  .imp-drop-zone b { color: #1a5c8a; }
  /* Select & inputs */
  .imp-select, .imp-date {
    background: white;
    border: 1px solid #d0e0ea;
    border-radius: 8px;
    padding: 6px 11px;
    font-size: 0.78rem;
    color: #1c2a35;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    width: auto;
  }
  .imp-select { max-width: 220px; min-width: 160px; }
  .imp-date { width: 140px; }
  .imp-select:focus, .imp-date:focus { border-color: #2a7ba8; }
  .imp-date-label {
    font-size: 0.7rem; color: #7a96a8; font-weight: 600;
  }
  /* Bouton-date mignon (filtres Du/au) — même esprit que Gestion livraisons */
  .imp-datebtn {
    display: inline-flex; align-items: center; gap: 6px;
    border: 1.5px solid #a8d4eb; border-radius: 9px; padding: 7px 12px;
    font-family: 'DM Mono', monospace; font-weight: 600; font-size: 0.82rem;
    color: #1a5c8a; background: linear-gradient(180deg, #fff, #f3f9fd);
    cursor: pointer; white-space: nowrap;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast), transform 0.08s;
  }
  .imp-datebtn:hover { border-color: #2a7ba8; box-shadow: 0 2px 8px rgba(26,92,138,0.15); }
  .imp-datebtn:active { transform: translateY(1px); }
  /* Boutons d'action — unifiés. Tokens uniquement : le « bleu ILS » = var(--accent)
     (identique chez ILS, couleur du labo chez un autre tenant), pastels dérivés en
     color-mix de --success/--gold/--danger → dark mode + branding automatiques. */
  .imp-btn {
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--accent-text);
    border-radius: 8px;
    padding: 6px 12px;
    font-size: 0.76rem; font-weight: 600;
    cursor: pointer; font-family: inherit;
    transition: background var(--dur-fast), border-color var(--dur-fast);
  }
  .imp-btn:hover { background: color-mix(in srgb, var(--accent) 6%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 70%, var(--teal)); }
  .imp-btn-primary {
    background: var(--accent); color: #fff; border-color: var(--accent);
  }
  .imp-btn-primary:hover { background: color-mix(in srgb, var(--accent) 70%, var(--teal)); border-color: color-mix(in srgb, var(--accent) 70%, var(--teal)); }
  .imp-btn-success {
    background: color-mix(in srgb, var(--success) 12%, var(--surface));
    color: var(--success);
    border-color: color-mix(in srgb, var(--success) 30%, var(--surface));
  }
  .imp-btn-success:hover { background: color-mix(in srgb, var(--success) 24%, var(--surface)); }
  .imp-btn-warn {
    background: color-mix(in srgb, var(--gold) 10%, var(--surface));
    color: var(--gold);
    border-color: color-mix(in srgb, var(--gold) 34%, var(--surface));
  }
  .imp-btn-warn:hover { background: color-mix(in srgb, var(--gold) 22%, var(--surface)); }
  .imp-btn-danger {
    background: color-mix(in srgb, var(--danger) 10%, var(--surface));
    color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 32%, var(--surface));
  }
  .imp-btn-danger:hover { background: color-mix(in srgb, var(--danger) 22%, var(--surface)); }
  /* Segmented toggle (vue archive) */
  .imp-segment {
    display: inline-flex;
    background: #f0f4f8;
    border: 1px solid #d0e0ea;
    border-radius: 8px;
    padding: 2px;
    gap: 2px;
  }
  .imp-segment button {
    background: transparent; border: none;
    padding: 4px 11px;
    font-size: 0.72rem; font-weight: 600;
    color: #7a96a8; cursor: pointer;
    border-radius: 6px; font-family: inherit;
    transition: color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast);
  }
  .imp-segment button:hover { color: #1a5c8a; }
  .imp-segment button.active { background: white; color: #1a5c8a; box-shadow: 0 1px 3px rgba(15,35,55,0.08); }
  /* File info */
  .imp-file-info {
    font-size: 0.72rem; color: #7a96a8;
    padding: 2px 0;
  }
  .imp-file-info b { color: #1a5c8a; }
  /* Stats chips — palette unifiée */
  .imp-stats {
    display: flex; gap: 8px; flex-wrap: wrap;
    padding: 4px 0 2px;
  }
  .imp-stat-chip {
    font-size: 0.74rem; font-weight: 600;
    padding: 4px 11px; border-radius: 8px;
    background: #f0f4f8; color: #1a5c8a;
    border: 1px solid #d0e0ea;
    display: inline-flex; align-items: center; gap: 5px;
    cursor: default;
    font-family: inherit;
  }
  .imp-stat-chip.clickable { cursor: pointer; transition: background var(--dur-fast), border-color var(--dur-fast); }
  .imp-stat-chip.clickable:hover { background: #e8f4fb; border-color: #2a7ba8; }
  .imp-stat-chip .imp-stat-num { font-weight: 800; color: #1c2a35; }
  /* Variantes colorées sobres (limitées au sens métier) */
  .imp-stat-chip.cas { background: #e8f4fb; color: #1a5c8a; border-color: #c8e0f0; }
  .imp-stat-chip.enrichies { background: #e8f5e9; color: #2e7d32; border-color: #c8e6c9; }
  .imp-stat-chip.non-trouvees { background: #ffebee; color: #c62828; border-color: #ffcdd2; }
  .imp-stat-chip.cabinets { background: #fff3e0; color: #e65100; border-color: #ffe0a0; }
  .imp-stat-chip.marques { background: #f3e5f5; color: #6a1b9a; border-color: #e1bee7; }
  .imp-stat-chip.active { outline: 2px solid currentColor; outline-offset: -1px; }
  .imp-stat-chip.clear { background: #f0f4f8; color: #555; cursor: pointer; }
  .imp-stat-chip.clear:hover { background: #ffebee; color: #c62828; border-color: #ffcdd2; }
  /* Table commandes */
  .imp-search-input {
    width: 100%;
    margin-top: 8px;
    padding: 8px 12px;
    border: 1.5px solid #d0e0ea;
    border-radius: 9px;
    font-size: 0.82rem;
    font-family: 'DM Sans', sans-serif;
    color: #1c2a35;
    background: #fafbfd;
    outline: none;
    box-sizing: border-box;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
  }
  .imp-search-input:focus { border-color: #2a7ba8; box-shadow: 0 0 0 3px rgba(42,123,168,0.12); }
  .imp-search-input::placeholder { color: #9aafbd; }
  html[data-theme="dark"] .imp-search-input {
    background: #1a1f2e; border-color: #3a4055; color: #e0e6ed;
  }
  html[data-theme="dark"] .imp-search-input:focus { border-color: #5bc4c0; box-shadow: 0 0 0 3px rgba(91,196,192,0.18); }
  html[data-theme="dark"] .imp-search-input::placeholder { color: #6b7787; }

  .imp-table-wrap {
    flex: 1; overflow-y: auto;
    background: white;
    margin: 0 18px 18px;
    border: 1px solid #d0e0ea;
    border-radius: 10px;
    overflow-x: hidden;
  }
  #imp-order-table {
    width: 100%; border-collapse: collapse; font-size: 0.78rem;
  }
  #imp-order-table thead tr {
    background: linear-gradient(120deg, #1a5c8a 0%, #2a7ba8 60%, #5bc4c0 100%);
    color: white;
  }
  #imp-order-table th {
    padding: 9px 12px;
    text-align: left;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    white-space: nowrap;
    position: sticky; top: 0;
  }
  #imp-order-table td {
    padding: 8px 12px;
    border-bottom: 1px solid #eef4f8;
    vertical-align: top;
    color: #1c2a35;
    line-height: 1.4;
    word-break: break-word;
  }
  #imp-order-table tbody tr:nth-child(even) { background: #fafcfe; }
  #imp-order-table tbody tr:hover { background: #e8f4fb; }
  #imp-order-table tbody tr.cab-alt { background: #f5f9fc; }
  #imp-order-table tbody tr.cab-alt:hover { background: #e8f4fb; }
  #imp-order-table tbody tr:last-child td { border-bottom: none; }

  /* ═══════ GESTION CLIENTS — REDESIGN (cohérent avec dentist-view + implants) ═══════ */
  .gc-modal-shell {
    background: #eef4f8;
    border-radius: 16px;
    width: var(--ck-shell-w); max-width: var(--ck-shell-maxw); height: var(--ck-shell-h);
    display: flex; flex-direction: column;
    box-shadow: 0 16px 50px rgba(15,35,55,0.25);
    overflow: hidden;
    font-family: 'DM Sans', system-ui, sans-serif;
  }
  /* Header gradient (signature) */
  .gc-header {
    background: linear-gradient(120deg, #1a5c8a 0%, #2a7ba8 60%, #5bc4c0 100%);
    color: white;
    padding: 12px 20px;
    display: flex; align-items: center; justify-content: space-between;
    flex-shrink: 0; gap: 14px; flex-wrap: wrap;
  }
  .gc-header-left { display: flex; align-items: center; gap: 12px; }
  .gc-header-ico {
    background: rgba(255,255,255,0.18);
    border-radius: 10px;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.2rem;
  }
  .gc-header-title { font-weight: 800; font-size: 1rem; line-height: 1.2; }
  .gc-header-sub { font-size: 0.7rem; opacity: 0.85; margin-top: 2px; }
  /* Tabs intégrés dans le header */
  .gc-tabs {
    display: flex; align-items: center; gap: 4px;
    background: rgba(255,255,255,0.12);
    border-radius: 9px;
    padding: 3px;
  }
  .gc-tab-btn {
    background: transparent;
    border: none;
    color: rgba(255,255,255,0.85);
    padding: 5px 13px;
    font-size: 0.76rem; font-weight: 600;
    border-radius: 6px; cursor: pointer;
    font-family: inherit;
    transition: background var(--dur-fast), color var(--dur-fast);
  }
  .gc-tab-btn:hover { color: white; }
  .gc-tab-btn.active {
    background: var(--surface); color: var(--accent-text);
  }
  /* ── Indicateur coulissant des onglets Gestion Clients (mécanique Digilab
     .dgl-seg-ind) : le pill actif est porté par #gc-tab-ind (span statique,
     index.html) et GLISSE sous les boutons. JS : _gcMajTabInd (contacts-tariffs.js)
     lit offsetWidth/offsetLeft PUIS écrit width/transform (jamais l'inverse).
     Spécificité volontairement supérieure aux styles injectés par gc-ui-styles.js
     (#modal-tarifs .gc-tab-btn.active) pour rendre le bouton actif transparent :
     c'est l'indicateur qui porte le fond. */
  #modal-tarifs .gc-tabs { position: relative; }
  #modal-tarifs .gc-tabs .gc-tab-ind {
    position: absolute; top: 4px; bottom: 4px; left: 4px; width: 72px;
    border-radius: 999px; pointer-events: none;
    background: linear-gradient(180deg, var(--surface), color-mix(in srgb, var(--teal) 13%, var(--surface)));
    box-shadow: 0 0 0 1px rgba(255,255,255,.5), 0 6px 16px color-mix(in srgb, var(--teal) 45%, transparent), 0 2px 4px rgba(0,0,0,.15);
    transition: transform var(--dur-base) var(--ease-out), width var(--dur-base) var(--ease-out);
  }
  html[data-theme="dark"] #modal-tarifs .gc-tabs .gc-tab-ind {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--teal) 40%, transparent), 0 6px 16px color-mix(in srgb, var(--teal) 28%, transparent), 0 2px 4px rgba(0,0,0,.35);
  }
  #modal-tarifs .gc-tabs .gc-tab-btn { position: relative; z-index: 1; }
  #modal-tarifs .gc-tabs .gc-tab-btn.active,
  html[data-theme="dark"] #modal-tarifs .gc-tabs .gc-tab-btn.active {
    background: transparent; box-shadow: none; color: var(--accent-text);
  }
  /* Boutons d'action dans le header (variante translucide) */
  .gc-header-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .gc-hbtn {
    background: rgba(255,255,255,0.14);
    border: 1px solid rgba(255,255,255,0.22);
    color: white;
    border-radius: 7px;
    padding: 5px 11px;
    font-size: 0.72rem; font-weight: 600;
    cursor: pointer; font-family: inherit;
    transition: background var(--dur-fast);
  }
  .gc-hbtn:hover { background: rgba(255,255,255,0.24); }
  .gc-hbtn-primary {
    background: white; color: #1a5c8a;
    border-color: white;
  }
  .gc-hbtn-primary:hover { background: #f0f7fb; }
  .gc-hbtn-close {
    background: rgba(255,255,255,0.15);
    border: 1px solid rgba(255,255,255,0.2);
    color: white; cursor: pointer;
    width: 30px; height: 30px; border-radius: 7px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem; padding: 0;
    margin-left: 4px;
  }
  .gc-hbtn-close:hover { background: rgba(255,255,255,0.25); }
  /* Body : sidebar + panel principal */
  .gc-body { display: flex; flex: 1; overflow: hidden; background: #eef4f8; }
  .gc-sidebar {
    width: 250px; flex-shrink: 0;
    background: white;
    border-right: 1px solid #d0e0ea;
    display: flex; flex-direction: column;
    overflow: hidden;
  }
  /* Search (style dv-search) */
  .gc-search-wrap { padding: 12px 12px 6px; }
  .gc-search {
    display: flex; align-items: center;
    background: #f8fafc;
    border: 1px solid #d0e0ea;
    border-radius: 10px;
    padding: 6px 11px;
    gap: 6px;
    transition: border-color var(--dur-fast);
  }
  .gc-search:focus-within { border-color: #2a7ba8; }
  .gc-search-ico { color: #7a96a8; font-size: 0.85rem; flex-shrink: 0; }
  .gc-search input {
    border: none; background: transparent;
    flex: 1; min-width: 0;
    font-size: 0.82rem;
    font-family: inherit;
    color: #1c2a35; outline: none;
  }
  .gc-search input::placeholder { color: #7a96a8; }
  /* Filtres statut (.gc-filters/.gc-pill/.gc-pill-icon) : styles retirés le
     13/08/26 avec le passage à deux rangées. Ils vivent désormais UNIQUEMENT
     dans js/gc-ui-styles.js, scopés #modal-tarifs et en tokens tenant. Ceux
     d'ici étaient devenus contradictoires (couleurs de labo en dur, non
     tenant-aware) et fuyaient encore par les propriétés que le bloc scopé ne
     redéclarait pas — dont un min-width:0 qui rouvrait le rognage des libellés. */
  /* Liste cabinets (style dv-item) */
  .gc-cabinet-list {
    flex: 1; overflow-y: auto;
    padding: 4px 0 8px;
  }
  /* ── Panel Tarifs ── */
  .gc-tarif-toolbar {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 18px;
    background: white;
    border-bottom: 1px solid #d0e0ea;
    flex-wrap: wrap;
    flex-shrink: 0;
  }
  .gc-tarif-stat {
    flex: 1; min-width: 200px;
    display: flex; align-items: center; gap: 10px;
    font-size: 0.82rem;
  }
  .gc-tarif-stat-label {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    border-radius: 8px;
    font-weight: 600; font-size: 0.78rem;
  }
  .gc-tarif-stat-label.perso {
    background: #fff3e0; color: #e65100;
    border: 1px solid #ffcc80;
  }
  .gc-tarif-stat-label.cogilog {
    background: #e8f5e9; color: #2e7d32;
    border: 1px solid #c8e6c9;
  }
  .gc-tarif-stat-label b { font-weight: 800; }
  /* Bouton « Changer de grille » et champs de la barre Tarifs — RIEN ICI.
     C'etait du hex en dur (blanc, #d0e0ea, #1a5c8a), donc ni tenant ni mode nuit,
     rattrape plus bas par un correctif nuit lui aussi en hex. Leur dessin est
     desormais celui, tokenise, de l'ecran Grilles : source unique
     js/tarifs-table-styles.js (tarifsChromeCss). Ne rien remettre ici.
     Seules les LARGEURS restent, elles relevent de la mise en page. */
  .gc-tarif-input { width: 130px; }
  .gc-tarif-select { max-width: 160px; }
  .gc-tarif-tablewrap {
    flex: 1; overflow: auto;
    padding: 12px 18px 18px;
  }
  .gc-tarif-tablewrap > table {
    width: 100%; border-collapse: collapse;
    font-size: 0.78rem;
    background: white;
    border: 1px solid #d0e0ea;
    border-radius: 10px;
    overflow: hidden;
  }
  .gc-tarif-tablewrap > table thead tr th {
    /* Le JS injecte déjà le gradient sur les th — on garde la stickyness via CSS */
  }

  /* ═══════ Fiche client — système typographique cohérent ═══════ */
  /* En-tête fiche : nom + badges + actions */
  .gc-fiche-header {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 14px; margin-bottom: 14px;
  }
  .gc-fiche-titlewrap { flex: 1; min-width: 0; }
  .gc-fiche-titlerow {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  }
  .gc-fiche-name {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 800;
    color: #1a5c8a;
    letter-spacing: -0.01em;
    line-height: 1.15;
  }
  .gc-fiche-ville {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 0.72rem;
    color: #7a96a8;
    margin-top: 5px;
    font-weight: 500;
  }
  .gc-fiche-ville-dot { color: #5bc4c0; }
  /* Badges (COG, grille, statut) */
  .gc-fiche-badge {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 0.66rem;
    font-weight: 700;
    padding: 3px 9px;
    border-radius: 12px;
    letter-spacing: 0.3px;
    border: 1px solid transparent;
    transition: background var(--dur-fast), border-color var(--dur-fast);
  }
  .gc-fiche-badge.cog {
    background: #e8f4fb; color: #1a5c8a; border-color: #c8e0f0;
    font-family: 'DM Mono', monospace;
  }
  .gc-fiche-badge.grille-ok {
    background: #fff8e1; color: #8a6d00; border-color: #ffe082;
    cursor: pointer;
  }
  .gc-fiche-badge.grille-ok:hover { background: #fff3cd; border-color: #ffd54f; }
  .gc-fiche-badge.grille-ko {
    background: #fff3e0; color: #e65100; border-color: #ffcc80;
    cursor: pointer;
  }
  .gc-fiche-badge.grille-ko:hover { background: #ffe0b2; border-color: #ffa726; }
  .gc-fiche-statut {
    font-size: 0.7rem; padding: 3px 9px; border-radius: 12px;
    font-weight: 700; cursor: pointer; outline: none;
    font-family: inherit;
    transition: background var(--dur-fast);
  }
  /* Boutons d'action en haut de la fiche */
  .gc-fiche-actions {
    display: flex; gap: 6px; flex-shrink: 0;
    flex-wrap: wrap;
  }
  .gc-fiche-action {
    display: inline-flex; align-items: center; gap: 5px;
    background: white;
    border: 1px solid #d0e0ea;
    color: #1a5c8a;
    border-radius: 8px;
    padding: 5px 11px;
    font-size: 0.74rem; font-weight: 600;
    cursor: pointer; font-family: inherit;
    transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
  }
  .gc-fiche-action:hover { background: #f0f7fb; border-color: #2a7ba8; }
  .gc-fiche-action:active { transform: scale(0.97); }
  .gc-fiche-action.lier { color: #1565c0; border-color: #90caf9; background: #e3f2fd; }
  .gc-fiche-action.lier:hover { background: #bbdefb; }
  .gc-fiche-action.inviter { color: #2e7d32; border-color: #aed581; background: #e8f5e9; }
  .gc-fiche-action.inviter:hover { background: #c8e6c9; }
  .gc-fiche-action.editer { color: #e65100; border-color: #ffb74d; background: #fff3e0; }
  .gc-fiche-action.editer:hover { background: #ffe0b2; }
  .gc-fiche-action.danger { color: #c62828; border-color: #ef9a9a; background: #ffebee; padding: 5px 9px; }
  .gc-fiche-action.danger:hover { background: #ffcdd2; }
  /* Carte coordonnées */
  .gc-fiche-card {
    background: white;
    border: 1px solid #d0e0ea;
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 14px;
    display: flex; flex-direction: column;
    gap: 9px;
    box-shadow: 0 1px 3px rgba(15,35,55,0.04);
    transition: box-shadow var(--dur-fast), border-color var(--dur-fast);
  }
  .gc-fiche-card:hover { box-shadow: 0 4px 12px rgba(15,35,55,0.08); }
  .gc-fiche-row {
    display: flex; align-items: center; gap: 10px;
    font-size: 0.82rem;
    color: #1c2a35;
    line-height: 1.4;
  }
  .gc-fiche-ico {
    flex-shrink: 0;
    width: 28px; height: 28px;
    border-radius: 8px;
    background: #f0f7fb;
    color: #1a5c8a;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 0.9rem;
  }
  .gc-fiche-row-text {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .gc-fiche-row a {
    color: #1a5c8a; text-decoration: none;
    font-weight: 500;
  }
  .gc-fiche-row a:hover { text-decoration: underline; }
  .gc-fiche-copy {
    flex-shrink: 0;
    background: white;
    border: 1px solid #d0e0ea;
    color: #7a96a8;
    border-radius: 6px;
    padding: 3px 9px;
    font-size: 0.66rem; font-weight: 600;
    cursor: pointer; font-family: inherit;
    transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
  }
  .gc-fiche-copy:hover { background: #f0f7fb; color: #1a5c8a; border-color: #2a7ba8; }
  /* Sections (Praticiens / Notes / Cas envoyés) */
  .gc-fiche-section {
    background: white;
    border: 1px solid #d0e0ea;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 14px;
    box-shadow: 0 1px 3px rgba(15,35,55,0.04);
  }
  .gc-fiche-section-head {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 16px;
    background: #f4f9fc;
    border-bottom: 1px solid #e0eaf2;
  }
  .gc-fiche-section-title {
    font-size: 0.78rem;
    font-weight: 700;
    color: #1a5c8a;
    letter-spacing: -0.01em;
    flex-shrink: 0;
    display: inline-flex; align-items: center; gap: 7px;
  }
  .gc-fiche-section-count {
    background: #e8f4fb;
    color: #1a5c8a;
    font-size: 0.66rem;
    font-weight: 800;
    padding: 1px 8px;
    border-radius: 10px;
    font-family: 'DM Mono', monospace;
  }
  .gc-fiche-section-body {
    background: white;
  }
  /* Notes — alerte si remplie */
  .gc-fiche-section.notes-active {
    border-color: #ffe082;
  }
  .gc-fiche-section.notes-active .gc-fiche-section-head {
    background: #fff8e1; border-bottom-color: #ffe082;
  }
  .gc-fiche-section.notes-active .gc-fiche-section-title { color: #e65100; }
  /* ── Fusion de cabinets (contacts regroupés + picker) ── */
  .gc-fusion-row {
    display: flex; align-items: center; gap: 8px;
    padding: 5px 10px; background: #f5f9fc;
    border: 1px solid #d0e0ea; border-radius: 7px;
  }
  .gc-fusion-prac { font-size: 0.8rem; flex: 1; min-width: 0; }
  .gc-fusion-x {
    background: none; border: none; cursor: pointer;
    font-size: 0.78rem; color: #c62828; padding: 0; line-height: 1;
  }
  .gc-fusion-modal {
    background: #fff; color: #213547; border-radius: 14px; padding: 20px;
    width: 95%; max-width: 520px; max-height: 85vh;
    display: flex; flex-direction: column;
    box-shadow: 0 8px 32px rgba(0,0,0,0.25);
  }
  .gc-fusion-modal h3 { color: #1565c0; }
  .gc-fusion-modal-list {
    overflow-y: auto; flex: 1;
    border: 1px solid #eee; border-radius: 8px;
  }
  .gc-fusion-pick-row {
    padding: 8px 12px; border-bottom: 1px solid #f0f0f0;
    cursor: pointer; font-size: 0.78rem;
    display: flex; justify-content: space-between; align-items: center; gap: 8px;
  }
  .gc-fusion-pick-row:hover { background: #eef6ff; }
  html[data-theme="dark"] .gc-fusion-row { background: #2a3142; border-color: #3a4055; }
  html[data-theme="dark"] .gc-fusion-x { color: #ff6b6b; }
  html[data-theme="dark"] .gc-fusion-modal { background: #1e2433; color: #e0e6ed; }
  html[data-theme="dark"] .gc-fusion-modal h3 { color: #7eb6ff; }
  html[data-theme="dark"] .gc-fusion-modal-list { border-color: #3a4055; }
  html[data-theme="dark"] .gc-fusion-pick-row { border-bottom-color: #2a3142; }
  html[data-theme="dark"] .gc-fusion-pick-row:hover { background: #2a3142; }
  .gc-fiche-notes-input {
    width: 100%; box-sizing: border-box;
    min-height: 60px; padding: 12px 16px;
    border: none; outline: none;
    font-size: 0.82rem; font-family: 'DM Sans', sans-serif;
    color: #1c2a35; background: transparent;
    resize: vertical;
    line-height: 1.5;
  }
  .gc-fiche-notes-input::placeholder { color: #b0c8d8; }
  /* Bouton "Aperçu dentiste ↗" dans la section Cas envoyés */
  .gc-fiche-link-btn {
    display: inline-flex; align-items: center; gap: 5px;
    background: white;
    border: 1px solid #d0e0ea;
    color: #1a5c8a;
    padding: 4px 11px;
    border-radius: 7px;
    font-size: 0.72rem; font-weight: 600;
    text-decoration: none;
    transition: background var(--dur-fast), border-color var(--dur-fast);
  }
  .gc-fiche-link-btn:hover { background: #f0f7fb; border-color: #2a7ba8; text-decoration: none; }
  /* Ajouter praticien — input + bouton */
  .gc-fiche-add-row {
    display: flex; gap: 8px;
    padding: 10px 14px;
    background: #fafcfe;
    border-top: 1px solid #eef4f8;
  }
  .gc-fiche-add-input {
    flex: 1;
    padding: 7px 11px;
    border: 1px solid #d0e0ea;
    border-radius: 8px;
    font-size: 0.8rem; font-family: inherit;
    color: #1c2a35; background: white; outline: none;
    transition: border-color var(--dur-fast);
  }
  .gc-fiche-add-input:focus { border-color: #2a7ba8; }
  .gc-fiche-add-btn {
    background: linear-gradient(120deg, #1a5c8a 0%, #2a7ba8 100%);
    color: white; border: none;
    padding: 7px 14px;
    border-radius: 8px;
    font-size: 0.78rem; font-weight: 700;
    cursor: pointer; font-family: inherit;
    white-space: nowrap;
    transition: opacity var(--dur-fast), transform var(--dur-fast);
  }
  .gc-fiche-add-btn:hover { opacity: 0.92; }
  .gc-fiche-add-btn:active { transform: scale(0.97); }
  /* Alerte inactivité — peaufiné */
  .gc-fiche-alerte {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 16px;
    border-radius: 12px;
    margin-bottom: 14px;
    border: 1px solid;
    border-left-width: 4px;
  }
  .gc-fiche-alerte.warn {
    background: #fff8e1; border-color: #ffe082; border-left-color: #ffa000;
  }
  .gc-fiche-alerte.urgent {
    background: #fff3e0; border-color: #ffb74d; border-left-color: #e65100;
  }
  .gc-fiche-alerte-ico { font-size: 1.3rem; flex-shrink: 0; }
  .gc-fiche-alerte-title {
    font-size: 0.82rem; font-weight: 700; color: #e65100; line-height: 1.2;
  }
  .gc-fiche-alerte.urgent .gc-fiche-alerte-title { color: #bf360c; }
  .gc-fiche-alerte-sub {
    font-size: 0.72rem; color: #7a96a8; margin-top: 2px;
  }

  /* Badge « cas manquant » (recoupement email) sur le bouton Digilab, en HAUT À
     GAUCHE — distinct du compteur « nouveau » (haut-droite). Rouge = alerte forte. */
  .dlb-missing-badge {
    position:absolute; top:-6px; left:-6px;
    background:#e53935; color:#fff;
    font-size:0.6rem; line-height:1; font-weight:700;
    min-width:16px; height:16px; border-radius:8px;
    display:flex; align-items:center; justify-content:center;
    padding:0 4px; box-shadow:0 2px 6px rgba(229,57,53,0.45);
  }
  html[data-theme="dark"] .dlb-missing-badge { box-shadow:0 0 0 1px rgba(255,255,255,0.18), 0 2px 6px rgba(0,0,0,0.4); }

  /* ════════════════════════════════════════════════════════
     MOBILE AUTO-ZOOM (smartphones < 600px en pointer coarse)
     ════════════════════════════════════════════════════════
     Quand index.html detecte un smartphone, il :
     - regle viewport initial-scale=0.5 (CSS viewport x2)
     - ajoute la classe .mobile-zoom-default sur <html>
     Ici on bump la base typo a 140% pour compenser le scale.
     Resultat = rendu "zoom 50% + police 140%" par defaut.
     Cf. demande utilisateur valide sur S24 Ultra / iPhone 15+.
     ════════════════════════════════════════════════════════ */
  html.mobile-zoom-default { font-size: 130%; }  /* 140→130 (retour Illan 02/07 : dézoom léger pour une UI plus aérée/espacée). Ancienne valeur 140% si à revert. */

  /* Body : decaler le contenu vers le bas pour qu'il ne soit
     pas masque par la barre d'adresse du navigateur mobile.
     Couvre aussi la notch / dynamic island via safe-area-inset. */
  html.mobile-zoom-default body {
    padding-top: calc(env(safe-area-inset-top, 0px) + 50px) !important;
  }

  /* Landscape smartphone : viser la meme densite que le rendu PC.
     scale=0.4 (cf. JS) donne ~975px de hauteur CSS sur smartphone
     classique. On compresse tous les paddings vertical pour que
     "Mettre a jour" soit visible sans scroll. */
  @media (orientation: landscape) {
    html.mobile-zoom-default { font-size: 130%; }
    html.mobile-zoom-default body {
      padding-top: calc(env(safe-area-inset-top, 0px) + 6px) !important;
      padding-bottom: 12px !important;
    }

    /* Header tres compact, et masquable au clic sur les cotes
       (cf. body.header-hidden ci-dessous) */
    html.mobile-zoom-default header {
      padding: 6px 14px;
      margin: 0 auto 6px;
    }
    html.mobile-zoom-default .logo-img-wrap { width: 52px; height: 52px; }
    html.mobile-zoom-default .logo-img { height: 44px; }
    html.mobile-zoom-default .logo-ilovesmile { font-size: 1.6rem; }
    html.mobile-zoom-default .logo-labo { font-size: 0.55rem; letter-spacing: 3px; }
    html.mobile-zoom-default .logo-tagline { font-size: 0.5rem; }

    /* Onglets outils plus compacts en hauteur */
    html.mobile-zoom-default .onglets-outils > button {
      padding: 4px 12px !important;
      min-height: 28px !important;
      font-size: 0.7rem !important;
    }

    /* Card form + sections : padding/gap reduits pour densifier */
    html.mobile-zoom-default .card-header { padding: 5px 12px; }
    html.mobile-zoom-default .form-body { padding: 5px 8px; gap: 5px; }
    html.mobile-zoom-default .section { padding: 5px 8px; }
    html.mobile-zoom-default .section-title {
      font-size: 0.55rem;
      margin-bottom: 2px;
      padding-bottom: 1px;
    }
    html.mobile-zoom-default .top-row,
    html.mobile-zoom-default .main-row,
    html.mobile-zoom-default .bottom-row { gap: 6px; }

    /* Bouton Enregistrer en bas : compact */
    html.mobile-zoom-default .actions { padding: 6px 12px; }

    /* Split layout : moins de gap, preview sticky plus haut */
    html.mobile-zoom-default .split-wrapper { gap: 8px; margin-top: 0; }
    html.mobile-zoom-default .preview-panel { top: 6px; }

    /* Cases a cocher plus petites en landscape pour densifier
       (toujours plus grosses que natif 12px) */
    html.mobile-zoom-default input[type="checkbox"],
    html.mobile-zoom-default input[type="radio"] {
      width: 16px !important;
      height: 16px !important;
    }

    /* Lignes checkbox : font lisible + paddings minces pour ne pas
       trop gonfler la hauteur. Compromis lisibilite/densite. */
    html.mobile-zoom-default .checkbox-label {
      margin: 0 !important;
      padding: 2px 4px !important;
      line-height: 1.2 !important;
      font-size: 0.88rem !important;
    }
    html.mobile-zoom-default .checkbox-sub-title {
      margin: 4px 0 2px !important;
      font-size: 0.7rem !important;
    }
    html.mobile-zoom-default .checkbox-sub { margin-left: 12px !important; }
    html.mobile-zoom-default label {
      margin-top: 1px !important;
      margin-bottom: 0 !important;
      font-size: 0.82rem !important;
    }
    /* Inputs texte / select / date : taille lisible */
    html.mobile-zoom-default .card input[type="text"],
    html.mobile-zoom-default .card input[type="number"],
    html.mobile-zoom-default .card input[type="date"],
    html.mobile-zoom-default .card select,
    html.mobile-zoom-default .card textarea {
      font-size: 0.85rem !important;
    }
    /* Section title : un peu plus visible */
    html.mobile-zoom-default .section-title {
      font-size: 0.68rem !important;
    }
    /* Card header (CODE LABO + N°) : agrandir un poil */
    html.mobile-zoom-default .card-header h1 {
      font-size: 0.9rem !important;
    }

    /* Boutons "Reinitialiser / Mettre a jour" toujours visibles
       en sticky au bas du viewport. Necessite overflow visible
       sur le .card (sinon sticky ne fonctionne pas) — on garde
       les coins arrondis via border-radius explicite sur les
       enfants. */
    html.mobile-zoom-default .split-wrapper .card {
      overflow: visible !important;
    }
    html.mobile-zoom-default .card-header {
      border-radius: 16px 16px 0 0;
    }
    html.mobile-zoom-default .actions {
      position: sticky;
      bottom: 0;
      z-index: 30;
      border-radius: 0 0 16px 16px;
      box-shadow: 0 -2px 8px rgba(26,92,138,0.08);
    }
  }

  /* Header masque (toggle au clic sur les cotes blancs du body).
     Permet de liberer de la place verticale en landscape. */
  html.mobile-zoom-default body.header-hidden header { display: none !important; }

  /* Cibles de scroll auto (liste prescriptions, fiche photo) :
     reserver une marge en haut pour ne pas finir sous la barre. */
  html.mobile-zoom-default .list-card,
  html.mobile-zoom-default #preview-panel,
  html.mobile-zoom-default #split-wrapper {
    scroll-margin-top: 60px;
  }

  /* Modales : aligner en haut (au lieu de centre) avec un offset
     pour eviter que leur en-tete passe sous la barre d'adresse. */
  html.mobile-zoom-default [id^="modal-"] {
    align-items: flex-start !important;
    padding-top: calc(env(safe-area-inset-top, 0px) + 30px) !important;
  }
  /* COQUILLE COMMUNE SUR TÉLÉPHONE (Illan, 11/09/2026 : « la fenêtre doit
     s'ouvrir avec des bords arrondis, là ça fait une sorte de semi plein écran
     moche ») : Livraison, Digilab et Historique IA se collaient aux quatre bords
     avec un rayon nul, alors que Clients, Implants et Paramètres s'ouvrent en
     fenêtre. Les quatre constantes sont définies ICI une seule fois (cf. le bloc
     --ck-shell-* du :root) : une marge de 10 px sur les côtés, la place du
     padding du voile en haut, 16 px en bas, et le rayon conservé. */
  html.mobile-zoom-default {
    --ck-shell-w: calc(100vw - 20px);
    --ck-shell-maxw: calc(100vw - 20px);
    --ck-shell-h: calc(100dvh - 46px);
  }

  /* HEADER : CELUI DE L'ORDINATEUR, tel quel (Illan, 11/09/2026 : « pour le
     header on va reprendre celui sur PC aussi qui est mieux »).
     Le bloc d'ici gérait un header replié en deux lignes (wrap, actions en
     pleine largeur, séparateur masqué, pastille Cloud détachée en haut à
     droite). Mesuré à 860 px CSS (S24), la mise en page de l'ordinateur tient
     sur UNE ligne — logo | Admin + Photo/Galerie/Dossiers | icônes, Cloud,
     lettre du jour, modèle IA — sans un pixel de débordement, et le header
     passe de 224 à 168 px de haut. Il n'y a donc plus rien à surcharger ici :
     tout vient des règles de base (header, .header-utils, #firebase-status).
     ⚠️ Le @media (orientation: landscape) garde SA compaction du logo : là,
     c'est la hauteur d'écran qui manque, pas la largeur. */

  /* Cases a cocher et radios plus grandes en portrait (cible
     tactile). Scope explicite a @media portrait pour ne pas
     ecraser la regle 16px du @media landscape (meme specificite
     + !important = source order gagne, et portrait etait apres). */
  @media (orientation: portrait) {
    html.mobile-zoom-default input[type="checkbox"],
    html.mobile-zoom-default input[type="radio"] {
      width: 22px !important;
      height: 22px !important;
      cursor: pointer;
    }
  }

  /* ── MODALES (Gestion clients, Parametres, Implants, Digilab) ──
     Les en-tetes ont trop de boutons pour le viewport mobile :
     la croix de fermeture finit hors ecran. On la repositionne
     en bouton flottant top-right toujours visible.
     ────────────────────────────────────────────────────────── */
  html.mobile-zoom-default [id^="modal-"] > div {
    position: relative !important;
  }
  /* ⚠️ Digilab EXCLU depuis le 06/08/2026 : son bandeau ne porte plus que la croix,
     elle est donc déjà en haut à droite et stylée avec le reste (.dgl-x). Le rond
     blanc flottant ci-dessous la sortait du bandeau et ignorait le mode nuit
     (fond blanc, icône #333). Les autres modales gardent ce repêchage. */
  html.mobile-zoom-default [id^="modal-"]:not(#modal-digilab) button[onclick^="fermerModal"]:not(.sfh-close),
  html.mobile-zoom-default [id^="modal-"]:not(#modal-digilab) button[onclick^="ferm"]:not(.sfh-close) {
    position: absolute !important;
    top: 8px !important;
    right: 8px !important;
    z-index: 100 !important;
    background: white !important;
    border: 1px solid #ccc !important;
    border-radius: 50% !important;
    width: 40px !important;
    height: 40px !important;
    padding: 0 !important;
    font-size: 1.4rem !important;
    color: #333 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15) !important;
    margin: 0 !important;
  }
  /* En-tete des modales : autoriser le wrap pour eviter le crop
     horizontal des actions, reserver l'espace pour la croix. */
  html.mobile-zoom-default [id^="modal-"] > div > div:first-child {
    flex-wrap: wrap !important;
    gap: 8px !important;
    padding-right: 56px !important;
  }

  /* Digilab : le body en 2 colonnes (liste + detail) ne tient
     pas sur mobile. On stacke en colonne et on remet la liste
     pleine largeur (override du min-width:700px inline). */
  html.mobile-zoom-default #modal-digilab > div > div:nth-child(2) {
    flex-direction: column !important;
  }
  html.mobile-zoom-default #modal-digilab > div > div:nth-child(2) > div {
    min-width: 0 !important;
    border-right: none !important;
    border-bottom: 1px solid #e8eef2 !important;
  }
  /* Digilab : forcer la liste a prendre une hauteur min visible,
     et le detail a apparaitre sous la liste, pas a etre ecrase */
  html.mobile-zoom-default #modal-digilab > div > div:nth-child(2) > div:first-child {
    flex: 0 0 auto !important;
    max-height: 50vh !important;
  }
  html.mobile-zoom-default #modal-digilab > div > div:nth-child(2) > div:last-child {
    flex: 1 1 auto !important;
    border-bottom: none !important;
  }

  /* Onglets outils (Gestion clients / Parametres / Implants /
     Digilab) au-dessus du formulaire : wrap pour que les 4
     onglets restent visibles. Cibles tactiles plus grandes. */
  html.mobile-zoom-default .onglets-outils {
    /* MÊME DISPOSITION QUE L'ORDINATEUR : 4 colonnes, gap 10 (Illan,
       11/09/2026 : « reprends exactement la disposition qu'on a sur
       l'interface PC, c'est mieux au final »). Annule la grille 2 colonnes
       du 13/08 : mesurée à 860 px CSS (S24), la grille 4 colonnes donne des
       tuiles de 210 px, aucun libellé rogné (le plus long, « Historique IA »,
       demande 107 px), et rend 114 px de hauteur au formulaire (260 → 146).
       Seule différence avec l'ordinateur, voulue : le conteneur suit la
       prescription, qui prend ici toute la largeur (voir max-width ci-dessous),
       au lieu des 720 px de la colonne de gauche. */
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 10px !important;
    /* Les tuiles SUIVENT la prescription : même gabarit que le split (1500 px
       centré, cf. .split-wrapper) — chaque colonne = une demi-largeur de la
       prescription (Clients/Implants/Chine/Historique IA à gauche,
       Livraison/Digilab/Facturation/Paramètres à droite, ordre naturel de la
       grille). Sur téléphone, 1500 > l'écran → pleine largeur, rendu intact ;
       en interface mobile forcée sur écran large, elles épousent la carte. */
    max-width: 1500px !important;
    margin: 0 auto !important;
    padding-left: 4px !important;
    padding-right: 4px !important;
  }
  /* Gabarit de tuile de l'ordinateur (icône 40 px, libellé .85rem) : les
     cibles tactiles restent larges (210 × 56 px) sans surcharge à maintenir. */
  html.mobile-zoom-default .onglets-outils > button {
    min-height: 0 !important;
    font-size: .85rem !important;
    padding: 7px 16px 7px 8px !important;
    white-space: nowrap;
  }

  /* ════════════════════════════════════════════════════════
     SMARTPHONE — Écran principal (en-tête liste + stats + filtres)
     ════════════════════════════════════════════════════════
     Confort tactile, mesuré à 768px CSS (= rendu réel du tel après
     auto-zoom). Scopé .mobile-zoom-default → smartphones uniquement,
     n'affecte ni tablette ni desktop. Couleurs via variables → dark
     mode + branding tenant respectés automatiquement.
     ──────────────────────────────────────────────────────── */

  /* 1. Rangée de stats : 8 compteurs en grille 4×2 au lieu d'un
        scroll horizontal masqué (débordait de +234px → invisible).
        Padding + chiffre légèrement réduits = grille plus compacte. */
  html.mobile-zoom-default .stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    overflow-x: visible;
    gap: 8px;
  }
  html.mobile-zoom-default .stats > .stat { min-width: 0; padding: 7px 8px; }
  html.mobile-zoom-default .stats > .stat .num { font-size: 1.2rem; }
  html.mobile-zoom-default .stats > .stat .top { font-size: .66rem; }

  /* 2. En-tête liste : tout passe en lignes pleine largeur empilées
        (l'en-tête desktop côte-à-côte ne tient pas sur tel).
        • Ligne 1 : titre à gauche, « Stand by » / « Annulés » empilés
          l'un sous l'autre, collés au bord DROIT.
        • Ligne 2 : les 3 boutons d'export en parts égales sur toute
          la largeur → impossible qu'ils se chevauchent. */
  html.mobile-zoom-default .list-header { flex-wrap: wrap; row-gap: 10px; }

  html.mobile-zoom-default .lh-left {
    flex: 1 1 100%;                      /* pleine largeur, sa propre ligne */
    min-width: 0;
    display: grid;
    grid-template-columns: 1fr auto auto; /* titre étiré à gauche, les deux compteurs à droite */
    align-items: center;
    column-gap: 10px;
    row-gap: 4px;
  }
  /* Stand by et Annulés CÔTE À CÔTE, dans cet ordre (Illan, 11/09/2026 : « pour
     gagner de l'espace vertical ») : empilés, ils coûtaient deux fois 79 px à
     droite du titre alors que la place manque en hauteur, pas en largeur. */
  html.mobile-zoom-default .lh-left > .lt-stack { grid-column: 1; grid-row: 1; align-self: center; justify-self: start; }
  html.mobile-zoom-default .lh-left > .stat-standby { grid-column: 2; grid-row: 1; min-width: 112px; }
  html.mobile-zoom-default .lh-left > .stat-annule  { grid-column: 3; grid-row: 1; min-width: 112px; }

  html.mobile-zoom-default .list-exports { flex: 1 1 100%; gap: 8px; }
  html.mobile-zoom-default .list-exports > .tool { flex: 1 1 0; min-width: 0; justify-content: center; }
  html.mobile-zoom-default .list-exports > .tool .tl { white-space: nowrap; }

  /* 3. Barres de recherche : sur deux lignes équilibrées.
        • Ligne 1 : Cabinet + Praticien + Code labo (champs larges,
          ~298px utilisables au lieu de 70px illisibles).
        • Ligne 2 : recherche patient RÉDUITE (ne prend plus toute la
          largeur) partageant sa ligne avec le filtre « En cours ».
        !important car .pf-cabprat / .pf-search-free portent un flex +
        min-width EN STYLE INLINE (index.html) non surchargeable sinon. */
  /* ══ CHERCHER ET FILTRER — UNE GRILLE DE QUATRE COLONNES (maquette G) ══════
     Illan, 11/09/2026, après avoir écarté une première refonte : le désordre ne
     venait pas de l'alignement mais du fait que filtrer se faisait de DEUX
     façons — deux grands champs de saisie (cabinet, praticien) d'un côté, cinq
     petites pilules à menu de l'autre. Ici, tous les filtres deviennent la même
     case, dans la même grille de quatre colonnes que les boutons d'outils.
     Cabinet et praticien gardent la saisie directe au clavier (demande d'Illan) :
     ils en ont seulement la même forme que les autres.

         [ 🔍 recherche libre ......................... ] [ # Code labo ]
         [ 🏢 Cabinet…  ] [ 👤 Praticien…] [ Fournisseur ▾] [ 🦷 Acte ▾  ]
         [ Scanner ▾    ] [ Vérifié ▾    ] [ 📅 Période ▾ ] [ 🗂 En cours ▾]
         [ ☑️ Tout sélectionner        ] [ 📋 Création ↓ ]

     ⚠️ TOUT EN CSS, ET SCOPÉ AU TÉLÉPHONE : le HTML n'est pas touché et aucune
     règle ne sort de html.mobile-zoom-default, donc l'ordinateur ne bouge pas
     d'un pixel (Illan, 11/09 : « remets le PC comme avant »). Les contrôles
     vivent dans deux conteneurs différents (la rangée de recherche et celle des
     filtres) : display:contents les efface de la mise en page pour que leurs
     enfants deviennent les cases d'UNE seule grille, et la propriété order fait
     le reste. C'est le seul moyen de réunir des éléments de deux parents sans
     toucher au HTML — ce commentaire est long parce que le mécanisme l'est. */
  html.mobile-zoom-default .prescriptions-filters {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* !important : la rangée porte gap:8px en style inline (index.html). */
    gap: 6px !important;
    align-items: stretch;
  }
  /* Ce qui garde la pleine largeur : les compteurs du haut et les tags actifs. */
  html.mobile-zoom-default .prescriptions-filters > .stats,
  html.mobile-zoom-default .prescriptions-filters > #filter-active-tags { grid-column: 1 / -1; }
  /* Les trois conteneurs s'effacent : leurs enfants deviennent les cases. */
  html.mobile-zoom-default .prescriptions-filters > .pf-row-search,
  html.mobile-zoom-default .prescriptions-filters > div:has(> #btn-selection-mode),
  html.mobile-zoom-default .pf-row-search > .pf-cabprat { display: contents !important; }
  /* La rangée technique (select statut masqué, cases à cocher, dates cachées)
     ne doit pas occuper une case : elle ne montre rien. */
  html.mobile-zoom-default .prescriptions-filters > div:has(> #filter-statut) { display: none !important; }

  /* Ordre et largeur de chaque case. */
  html.mobile-zoom-default .pf-search-free { order: 1; grid-column: span 3; flex: none !important; min-width: 0 !important; }
  html.mobile-zoom-default .pf-cabprat > .pf-field:has(#filter-code-labo) { order: 2; flex: none !important; width: auto !important; }
  html.mobile-zoom-default .pf-cabprat > .pf-field:has(#filter-search-cabinet) { order: 3; flex: none !important; }
  html.mobile-zoom-default .pf-cabprat > .pf-field:has(#filter-search-praticien) { order: 4; flex: none !important; }
  html.mobile-zoom-default #filter-scanner { order: 5; }
  html.mobile-zoom-default #filter-acte { order: 6; }
  html.mobile-zoom-default .ils-sel:has(#filter-fournisseur) { order: 7; }
  html.mobile-zoom-default #filter-verif { order: 8; }
  html.mobile-zoom-default #filter-cal-wrap { order: 9; }
  html.mobile-zoom-default .ils-sel:has(#sort-btn) { order: 10; }
  html.mobile-zoom-default #btn-selection-mode { order: 11; grid-column: span 2; }
  html.mobile-zoom-default #archives-filter { order: 12; grid-column: span 2; }
  /* Le compte des cases cochées, en pastille DANS le bouton de sélection
     (js/prescription-list.js le déplace là sur téléphone) : il ne prend plus une
     case de la grille, et « Supprimer » se range juste sous le bouton. */
  html.mobile-zoom-default #btn-selection-mode { display: flex; align-items: center; gap: 8px; }
  html.mobile-zoom-default #btn-selection-mode > #selection-count {
    display: inline-flex !important; align-items: center; justify-content: center;
    margin-left: auto; min-width: 34px; height: 26px; padding: 0 9px; border-radius: 999px;
    background: color-mix(in srgb, var(--warn) 26%, transparent);
    color: var(--text) !important; font-size: .8rem !important; font-weight: 700;
    font-variant-numeric: tabular-nums;
  }
  /* Hors mode sélection, le bouton reste seul : la pastille est masquée en JS. */
  html.mobile-zoom-default #btn-delete-selected { order: 14; grid-column: span 2; min-height: 40px; border-radius: 11px; }

  /* Une seule et même case, quelle que soit sa nature (saisie ou menu). */
  html.mobile-zoom-default .prescriptions-filters .pf-field,
  html.mobile-zoom-default .prescriptions-filters .pf-arch,
  html.mobile-zoom-default .prescriptions-filters .ils-sel,
  html.mobile-zoom-default .prescriptions-filters #filter-cal-wrap,
  html.mobile-zoom-default .prescriptions-filters #btn-selection-mode { min-width: 0; }
  html.mobile-zoom-default .prescriptions-filters .pf-arch-trigger,
  html.mobile-zoom-default .prescriptions-filters .ils-sel-trigger,
  html.mobile-zoom-default .prescriptions-filters .pf-period-btn,
  html.mobile-zoom-default .prescriptions-filters .pf-field,
  html.mobile-zoom-default .prescriptions-filters #btn-selection-mode {
    width: 100%; min-height: 40px; border-radius: 11px;
    justify-content: flex-start; text-align: left;
    /* .pf-sort plafonne à 190 px : dans la grille, la case fait la largeur de
       sa colonne, sinon il reste un vide à droite (Illan, 11/09 : « il y a un
       trou, comble-le »). */
    max-width: none;
  }
  /* Le chevron des menus se cale à droite, comme la croix des champs. */
  html.mobile-zoom-default .prescriptions-filters .pf-arch-chev,
  html.mobile-zoom-default .prescriptions-filters .ils-sel-chev { margin-left: auto; }
  html.mobile-zoom-default .prescriptions-filters .pf-arch-label,
  html.mobile-zoom-default .prescriptions-filters .ils-sel-label {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Le compte d'archives est déjà dans le menu du filtre : sous le bouton, il
     déséquilibrait la case (Illan, 11/09). */
  html.mobile-zoom-default .pf-arch-count { display: none !important; }
  /* La période : son bouton prend la case, sa croix se superpose à droite. */
  html.mobile-zoom-default #filter-cal-wrap { position: relative; display: block !important; }
  html.mobile-zoom-default #filter-cal-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); }

  /* ════════════════════════════════════════════════════════
     AUDIT MOBILE 2026-07-02 — correctifs ergonomie téléphone (S24)
     Scopés html.mobile-zoom-default = hook smartphone FIABLE.
     (PAS @media 768 : le tel rend souvent >768px CSS → un @media
     max-width:768 ne se déclenche pas. La classe, elle, est posée
     par le JS uniquement sur smartphone → zéro impact desktop.)
     ════════════════════════════════════════════════════════ */

  /* ─ GC-3 : dashboard Clients — 1 colonne + montants/repères non tronqués ─ */
  html.mobile-zoom-default .gcd-grid { grid-template-columns: 1fr; }
  html.mobile-zoom-default .gcd-card.wide { grid-column: auto; }
  html.mobile-zoom-default #modal-tarifs .gcd-donut-item { overflow: visible; min-width: 0; }
  html.mobile-zoom-default #modal-tarifs .gcd-donut-amt { flex: none; margin-left: 8px; white-space: nowrap; }
  html.mobile-zoom-default #modal-tarifs .gcd-bar-name { flex-basis: 40%; }
  html.mobile-zoom-default #modal-tarifs .gcd-grp-cue { white-space: nowrap; }

  /* ─ PMX-1 : Paramètres/Admin — rail latéral → bandeau haut, les 3 groupes
       (Atelier / Mon labo / Avancé) en 3 COLONNES côte à côte (retour Illan :
       plus ergonomique que tout empilé à la suite). ─ */
  html.mobile-zoom-default .pmx-body { flex-direction: column; }
  html.mobile-zoom-default .pmx-side,
  html.mobile-zoom-default .pmx-shell--full .pmx-side {
    width: 100%; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start; gap: 2px 14px;
    border-right: none; border-bottom: 1px solid var(--border);
  }
  html.mobile-zoom-default .pmx-side-grp { min-width: 0; }
  html.mobile-zoom-default .pmx-side-group { margin: 6px 6px 2px; }
  html.mobile-zoom-default .pmx-item { flex: 0 0 auto; }
  html.mobile-zoom-default .pmx-head { flex-wrap: wrap; gap: 8px; padding: 12px 14px; }
  /* TÉLÉPHONE — liste des réglages PUIS réglage en plein écran (Illan, 11/09/2026).
     En mode détail, la liste s'efface et le panneau prend toute la hauteur de la
     fenêtre ; « ‹ Réglages » (ou le bouton retour du téléphone) ramène à la liste. */
  html.mobile-zoom-default .pmx-shell.pmx-m-detail .pmx-side { display: none; }
  html.mobile-zoom-default .pmx-shell.pmx-m-detail .pmx-body { min-height: 0; }
  html.mobile-zoom-default .pmx-shell.pmx-m-detail .pmx-panel-pad { max-height: none; }
  html.mobile-zoom-default .pmx-m-back {
    display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
    min-height: 40px; padding: 8px 16px; border-radius: 999px; cursor: pointer;
    border: 1px solid var(--border); background: var(--surface-2, var(--surface));
    color: var(--text); font: inherit; font-size: .82rem; font-weight: 700;
  }
  html.mobile-zoom-default .pmx-m-back[hidden] { display: none; }
  .pmx-m-back { display: none; }
  html.mobile-zoom-default .pmx-search-wrap { order: 3; flex-basis: 100%; }
  html.mobile-zoom-default .pmx-search,
  html.mobile-zoom-default .pmx-search:focus { width: 100%; box-sizing: border-box; }

  /* ─ PMX-2 : Paramètres/Admin — cibles tactiles ─ */
  html.mobile-zoom-default .pmx-close { width: 46px; height: 46px; font-size: 1.3rem; margin-left: auto; }
  html.mobile-zoom-default .ap-table th, html.mobile-zoom-default .ap-table td { padding: 8px 10px; }
  html.mobile-zoom-default .ap-mini { width: 40px; height: 40px; font-size: 1.1rem; }
  html.mobile-zoom-default .ap-input { padding: 9px 10px; }
  html.mobile-zoom-default .ap-table-wrap { -webkit-overflow-scrolling: touch; }
  html.mobile-zoom-default .adm-navbtn { width: 42px; height: 42px; font-size: 1.15rem; }
  html.mobile-zoom-default .adm-labo-metrics { gap: 12px; }
  html.mobile-zoom-default .adm-spark { display: none; }
  html.mobile-zoom-default .adm-labo-detail .adm-spark { display: flex; width: 100%; }
  html.mobile-zoom-default .pmx-btn { padding: 10px 18px; }

  /* ─ HEADER : volontairement laissé À L'IDENTIQUE (retour Illan : l'ancien
       header est mieux pour l'instant). Correctifs HDR-1/2/3 retirés. ─ */

  /* ─ LST-1 : barre d'outils liste — disposition PC (INLINE, pas 1 ligne/contrôle).
       Retour Illan : « pas besoin d'une ligne entière pour Tout sélectionner / filtres /
       fournisseur / période ». Contrôles compacts qui se suivent + wrap si besoin. ─ */
  html.mobile-zoom-default #btn-selection-mode,
  html.mobile-zoom-default .pf-sort,
  html.mobile-zoom-default #filter-fournisseur,
  html.mobile-zoom-default .pf-period-btn,
  html.mobile-zoom-default .pf-arch-trigger { min-height: 40px; padding-top: 5px; padding-bottom: 5px; font-size: .78rem; }
  html.mobile-zoom-default #filter-cal-clear { width: 28px !important; height: 28px !important; font-size: .78rem !important; }
  html.mobile-zoom-default .pf-arch-menu { left: auto; right: 0; max-width: calc(100vw - 24px); }

  /* ─ LST-2 : libellés stats non tronqués + barre export équilibrée ─ */
  html.mobile-zoom-default .stats > .stat { min-height: 62px; display: flex; flex-direction: column; justify-content: center; }
  html.mobile-zoom-default .stats > .stat .top { min-width: 0; line-height: 1.15; text-align: center; white-space: normal; }
  html.mobile-zoom-default .list-exports > #btn-undo { margin-left: 0 !important; min-height: 40px; padding: 6px 12px !important; flex: 0 0 auto; }
  html.mobile-zoom-default .list-exports > #export-corrections-btn { flex: 1 1 100%; min-height: 40px; }
  html.mobile-zoom-default .list-footer > button { min-height: 46px !important; padding: 12px 24px !important; }

  /* ─ SCAN-3 : cibles tactiles du scan (zoom aperçu, picker dossiers, tags, statut) ─ */
  html.mobile-zoom-default .preview-zoom button { width: 48px; height: 48px; font-size: 1.4rem; }
  html.mobile-zoom-default .preview-zoom { gap: 10px; bottom: 14px; right: 14px; }
  html.mobile-zoom-default #folder-picker-panel button { min-height: 44px; padding: 8px 16px !important; font-size: 0.9rem !important; }
  html.mobile-zoom-default .folder-tag-remove { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; min-height: 32px; margin-left: 2px; }
  html.mobile-zoom-default #folder-status { white-space: normal; overflow: visible; text-overflow: clip; flex-basis: 100%; text-align: left; margin-top: 4px; }

  /* ─ CMP-2 : composants partagés (calendrier, autocomplete, confirm, prompt, toast) ─ */
  html.mobile-zoom-default #app-cal-pop { width: 300px; padding: 14px; }
  html.mobile-zoom-default #app-cal-pop .app-cal-day { padding: 12px 0; font-size: .9rem; }
  html.mobile-zoom-default #app-cal-pop .app-cal-nav { padding: 8px 16px; font-size: 1.2rem; }
  html.mobile-zoom-default #app-cal-pop input[type="text"] { min-height: 34px; font-size: .9rem; }
  html.mobile-zoom-default .ais-ac-item { padding: 11px 12px; font-size: .8rem; }
  html.mobile-zoom-default #app-confirm button,
  html.mobile-zoom-default #app-prompt button { padding: 13px 22px; font-size: .92rem; }
  html.mobile-zoom-default #app-prompt-input { padding: 12px 14px; font-size: 1rem; }
  html.mobile-zoom-default .toast { left: 12px; right: 12px; bottom: 16px; max-width: none; text-align: center; font-size: .95rem; padding: 16px 20px; }

  /* ─ TRC-2 : Paramètres traçabilité — grille Apparence/matériaux en 1 colonne ─ */
  html.mobile-zoom-default .tba-grid2 { grid-template-columns: 1fr; }

  /* ─ ACTES & CODES (Paramètres) : table compacte pour TENIR SANS SCROLL H (retour Illan).
       Les th ont des min-width inline (~900px cumulés) qui forcent le débordement →
       on les neutralise (!important bat l'inline), on autorise le retour à la ligne,
       et on rétrécit inputs/selects à leur cellule. ─ */
  html.mobile-zoom-default #pm-actes-table { width: 100% !important; }
  html.mobile-zoom-default #pm-actes-table th,
  html.mobile-zoom-default #pm-actes-table td { min-width: 0 !important; white-space: normal !important; overflow-wrap: anywhere; padding: 4px 5px !important; font-size: 0.62rem !important; }
  html.mobile-zoom-default #pm-actes-table select,
  html.mobile-zoom-default #pm-actes-table input { width: 100% !important; max-width: 100% !important; min-width: 0 !important; box-sizing: border-box !important; font-size: 0.62rem !important; }

  /* ════════════════════════════════════════════════════════
     RESPONSIVE — Convention long terme
     ════════════════════════════════════════════════════════
     Breakpoints standards utilises dans toute la stylesheet :
       • Smartphone (portrait + paysage) : NON gere via @media.
         Strategie : auto-zoom + font 140% (cf. bloc ci-dessus)
         qui fait rendre le layout desktop sur tel avec texte
         lisible. Pas de regles @media smartphone-specifique.
       • <= 768px  → Tablette portrait (iPad / Galaxy Tab)
       • <= 1024px → Tablette paysage / petit laptop
       • > 1024px  → Desktop (rendu par defaut, mobile-last)

     Legacy (form-editor uniquement, a reorganiser un jour) :
       • <= 1000px → split-wrapper en colonne unique
       • <= 680px  → top/main/bottom-row en colonne unique

     Comment ajouter un nouveau composant responsive :
       1. Donner des classes au markup (eviter d'agir sur des
          inline styles : il faudra du !important sinon).
       2. Ajouter les regles dans la SECTION du breakpoint
          adapte ci-dessous, en groupant par composant.
       3. Pour smartphone : verifier d'abord si l'auto-zoom
          suffit avant d'ajouter du CSS dedie.

     Classes hooks deja en place (utilisables pour future
     mobile/tablette specifique) :
       .prescriptions-filters, .pf-row-search, .pf-cabprat,
       .pf-search-free, .pi-body
     ════════════════════════════════════════════════════════ */

  /* ════════════════════════════════════════════════════════
     ≤ 1024px — TABLETTE PAYSAGE / PETIT LAPTOP
     (vide — a remplir si necessaire)
     ════════════════════════════════════════════════════════ */
  /* @media (max-width: 1024px) { } */

  /* ════════════════════════════════════════════════════════
     ≤ 768px — TABLETTE PORTRAIT
     (vide — a remplir quand on attaque la tablette)
     ════════════════════════════════════════════════════════ */
  /* @media (max-width: 768px) { } */

  /* Smartphone portrait + paysage : voir bloc MOBILE AUTO-ZOOM
     en haut de cette section. Pas de @media smartphone ici. */

  /* ════════════════════════════════════════════════════════
     DARK MODE — completion pour .imp-* et .gc-*
     (Les .dc-* / .pd-* sont overridés dans decalage-ui-styles.js)
     Les headers gradient restent intacts, on adapte les surfaces
     claires (toolbar, sidebar, fiche, cards, inputs) au thème.
     ════════════════════════════════════════════════════════ */

  /* ───── Gestion Implants ───── */
  html[data-theme="dark"] .imp-toolbar {
    background: #242938;
    border-bottom-color: #3a4055;
  }
  html[data-theme="dark"] .imp-drop-zone {
    background: #1e2434;
    border-color: #3a4055;
    color: #8899aa;
  }
  html[data-theme="dark"] .imp-drop-zone:hover,
  html[data-theme="dark"] .imp-drop-zone.drag-over {
    background: #2a3550;
    border-color: #5bc4c0;
  }
  html[data-theme="dark"] .imp-drop-zone b { color: #5bc4c0; }
  html[data-theme="dark"] .imp-date-label { color: #8899aa; }
  html[data-theme="dark"] .imp-select,
  html[data-theme="dark"] .imp-date {
    background: #1a1f2e;
    border-color: #3a4055;
    color: #e0e6ed;
  }
  html[data-theme="dark"] .imp-select:focus,
  html[data-theme="dark"] .imp-date:focus { border-color: #5bc4c0; }

  /* .imp-btn & variantes : tokenisés (surface/border/success/gold/danger suivent
     le dark tout seuls) — seul le primary garde un habillage dédié, sur le
     dégradé de marque partagé (même recette que .f2-save / .imx-btn.cta). */
  html[data-theme="dark"] .imp-btn-primary {
    background: var(--grad);
    color: #fff;
    border-color: transparent;
  }

  html[data-theme="dark"] .imp-segment {
    background: #1e2434;
    border-color: #3a4055;
  }
  html[data-theme="dark"] .imp-segment button { color: #8899aa; }
  html[data-theme="dark"] .imp-segment button:hover { color: #5bc4c0; }
  html[data-theme="dark"] .imp-segment button.active {
    background: #2a3550; color: #5bc4c0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.35);
  }

  html[data-theme="dark"] .imp-file-info { color: #8899aa; }
  html[data-theme="dark"] .imp-file-info b { color: #5bc4c0; }

  /* Stat chips — toutes les couleurs assombries */
  html[data-theme="dark"] .imp-stat-chip {
    background: #1e2434;
    border-color: #3a4055;
    color: #8899aa;
  }
  html[data-theme="dark"] .imp-stat-chip .imp-stat-num { color: #e0e6ed; }
  html[data-theme="dark"] .imp-stat-chip.cas        { background: #1e3a4f; color: #5bc4c0; border-color: #2a5070; }
  html[data-theme="dark"] .imp-stat-chip.enrichies  { background: #1e3a26; color: #81c784; border-color: #2e5e3a; }
  html[data-theme="dark"] .imp-stat-chip.non-trouvees { background: #3a1a1a; color: #ef9a9a; border-color: #6a3030; }
  html[data-theme="dark"] .imp-stat-chip.cabinets   { background: #3a2a18; color: #ffb74d; border-color: #6a5520; }
  html[data-theme="dark"] .imp-stat-chip.marques    { background: #2e1e3a; color: #ce93d8; border-color: #5a4080; }
  html[data-theme="dark"] .imp-stat-chip.clear      { background: #1e2434; color: #8899aa; border-color: #3a4055; }
  html[data-theme="dark"] .imp-stat-chip.clear:hover { background: #3a1a1a; color: #ef9a9a; border-color: #6a3030; }
  html[data-theme="dark"] .imp-stat-chip.clickable:hover { background: #2a3550; border-color: #5bc4c0; }

  /* Tableau commandes implants */
  html[data-theme="dark"] .imp-table-wrap { background: #242938; border-color: #3a4055; }
  /* Texte des cellules en clair (sinon #1c2a35 illisible sur fond sombre) */
  html[data-theme="dark"] #imp-order-table td { color: #e0e6ed; border-bottom-color: #2f3647; }
  /* Striping sombre cohérent : lignes paires + cabinets alternés en bleu nuit,
     lignes impaires sur le fond du tableau. Avant : #fafcfe (blanc) = bandes
     blanches illisibles. */
  html[data-theme="dark"] #imp-order-table tbody tr:nth-child(even) { background: #1e2434; }
  html[data-theme="dark"] #imp-order-table tbody tr.cab-alt { background: #20283a; }
  html[data-theme="dark"] #imp-order-table tbody tr:hover,
  html[data-theme="dark"] #imp-order-table tbody tr.cab-alt:hover { background: #1e3040; }
  /* Cellule date (inline color:#888) → muted lisible */
  html[data-theme="dark"] #imp-order-table td[style*="color:#888"] { color: #8899aa !important; }
  /* Pastille code labo (inline bg bleu clair) → bleu nuit + texte clair */
  html[data-theme="dark"] #imp-order-table td span[style*="#e3f2fd"] { background: #1e3a4f !important; color: #7fc4e8 !important; }
  /* Placeholders "(vide)/(non trouvé)" (#bbb) un peu plus visibles */
  html[data-theme="dark"] #imp-order-table td span[style*="#bbb"] { color: #6b7787 !important; }

  /* ───── Gestion Clients ───── */
  html[data-theme="dark"] .gc-modal-shell { background: #1a1f2e; color: #e0e6ed; }
  html[data-theme="dark"] .gc-body { background: #1a1f2e; }
  html[data-theme="dark"] .gc-sidebar {
    background: #242938;
    border-right-color: #3a4055;
  }
  html[data-theme="dark"] .gc-search {
    background: #1a1f2e;
    border-color: #3a4055;
  }
  html[data-theme="dark"] .gc-search:focus-within { border-color: #5bc4c0; }
  html[data-theme="dark"] .gc-search-ico { color: #8899aa; }
  html[data-theme="dark"] .gc-search input { background: transparent; color: #e0e6ed; }
  html[data-theme="dark"] .gc-search input::placeholder { color: #707888; }

  /* (Le dark des filtres statut est parti avec eux : le bloc scopé
     #modal-tarifs de js/gc-ui-styles.js est déjà en tokens, donc dark natif.) */

  /* Tarifs panel */
  html[data-theme="dark"] .gc-tarif-toolbar {
    background: #242938;
    border-bottom-color: #3a4055;
  }
  html[data-theme="dark"] .gc-tarif-stat {
    background: #1e2434; border-color: #3a4055;
  }
  html[data-theme="dark"] .gc-tarif-stat-label.perso {
    background: #1e3a4f; color: #5bc4c0; border-color: #2a5070;
  }
  html[data-theme="dark"] .gc-tarif-stat-label.cogilog {
    background: #2e1e3a; color: #ce93d8; border-color: #5a4080;
  }
  /* (correctifs nuit du bouton et des champs Tarifs retires le 14/08/2026 :
     tokenises et partages avec l'ecran Grilles — cf. js/tarifs-table-styles.js) */
  html[data-theme="dark"] .gc-tarif-tablewrap { background: #1a1f2e; }

  /* Fiche client */
  html[data-theme="dark"] .gc-fiche-header { color: #e0e6ed; }
  html[data-theme="dark"] .gc-fiche-name { color: #e0e6ed; }
  html[data-theme="dark"] .gc-fiche-ville { color: #8899aa; }
  html[data-theme="dark"] .gc-fiche-ville-dot { color: #5bc4c0; }
  html[data-theme="dark"] .gc-fiche-badge.cog {
    background: #2e1e3a; color: #ce93d8; border-color: #5a4080;
  }
  html[data-theme="dark"] .gc-fiche-badge.grille-ok {
    background: #3a3220; color: #ffd54f; border-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-badge.grille-ok:hover { background: #4a4030; }
  html[data-theme="dark"] .gc-fiche-badge.grille-ko {
    background: #3a2a18; color: #ffb74d; border-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-badge.grille-ko:hover { background: #4a3520; }
  html[data-theme="dark"] .gc-fiche-statut {
    background: #1a1f2e; border-color: #3a4055; color: #e0e6ed;
  }

  html[data-theme="dark"] .gc-fiche-action {
    background: #242938; border-color: #3a4055; color: #5bc4c0;
  }
  html[data-theme="dark"] .gc-fiche-action:hover { background: #2a3550; border-color: #5bc4c0; }
  html[data-theme="dark"] .gc-fiche-action.lier {
    background: #1e3a4f; color: #64b5f6; border-color: #2a5070;
  }
  html[data-theme="dark"] .gc-fiche-action.lier:hover { background: #244555; }
  html[data-theme="dark"] .gc-fiche-action.inviter {
    background: #1e3a26; color: #81c784; border-color: #2e5e3a;
  }
  html[data-theme="dark"] .gc-fiche-action.inviter:hover { background: #244530; }
  html[data-theme="dark"] .gc-fiche-action.editer {
    background: #3a2a18; color: #ffb74d; border-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-action.editer:hover { background: #4a3520; }
  html[data-theme="dark"] .gc-fiche-action.danger {
    background: #3a1a1a; color: #ef9a9a; border-color: #6a3030;
  }
  html[data-theme="dark"] .gc-fiche-action.danger:hover { background: #4a2020; }

  html[data-theme="dark"] .gc-fiche-card,
  html[data-theme="dark"] .gc-fiche-section,
  html[data-theme="dark"] .gc-fiche-add-row {
    background: #242938;
    border-color: #3a4055;
    box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  }
  html[data-theme="dark"] .gc-fiche-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.4); }
  html[data-theme="dark"] .gc-fiche-row,
  html[data-theme="dark"] .gc-fiche-row-text { color: #e0e6ed; }
  html[data-theme="dark"] .gc-fiche-ico { color: #5bc4c0; }
  html[data-theme="dark"] .gc-fiche-row a { color: #5bc4c0; }
  html[data-theme="dark"] .gc-fiche-copy {
    background: #1e2434; border-color: #3a4055; color: #8899aa;
  }
  html[data-theme="dark"] .gc-fiche-copy:hover {
    background: #2a3550; color: #5bc4c0; border-color: #5bc4c0;
  }
  html[data-theme="dark"] .gc-fiche-section-head { border-bottom-color: #3a4055; }
  html[data-theme="dark"] .gc-fiche-section-title { color: #e0e6ed; }
  html[data-theme="dark"] .gc-fiche-section-count { color: #8899aa; }
  html[data-theme="dark"] .gc-fiche-section.notes-active {
    background: #3a2a18; border-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-section.notes-active .gc-fiche-section-head {
    border-bottom-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-section.notes-active .gc-fiche-section-title { color: #ffb74d; }
  html[data-theme="dark"] .gc-fiche-notes-input {
    background: #1a1f2e; border-color: #3a4055; color: #e0e6ed;
  }
  html[data-theme="dark"] .gc-fiche-notes-input::placeholder { color: #707888; }
  html[data-theme="dark"] .gc-fiche-link-btn {
    background: #1e2434; border-color: #3a4055; color: #5bc4c0;
  }
  html[data-theme="dark"] .gc-fiche-link-btn:hover {
    background: #2a3550; border-color: #5bc4c0;
  }
  html[data-theme="dark"] .gc-fiche-add-input {
    background: #1a1f2e; border-color: #3a4055; color: #e0e6ed;
  }
  html[data-theme="dark"] .gc-fiche-add-input:focus { border-color: #5bc4c0; }
  html[data-theme="dark"] .gc-fiche-add-input::placeholder { color: #707888; }
  html[data-theme="dark"] .gc-fiche-alerte.warn {
    background: #3a2a18; border-color: #6a5520;
  }
  html[data-theme="dark"] .gc-fiche-alerte.urgent {
    background: #3a1a1a; border-color: #6a3030;
  }
  html[data-theme="dark"] .gc-fiche-alerte-title { color: #ffb74d; }
  html[data-theme="dark"] .gc-fiche-alerte.urgent .gc-fiche-alerte-title { color: #ef9a9a; }
  html[data-theme="dark"] .gc-fiche-alerte-sub { color: #c0c8d0; }
  html[data-theme="dark"] .gc-fiche-add-btn {
    background: linear-gradient(120deg, #1a5c8a 0%, #2a7ba8 100%);
    color: white;
  }

  /* Badges contacts/tarif dans la sidebar */
  html[data-theme="dark"] .gc-badge-contacts {
    background: #1e3a4f; color: #5bc4c0;
  }
  html[data-theme="dark"] .gc-badge-tarif {
    background: #2e1e3a; color: #ce93d8;
  }

  /* ───── Toolbar outils §3 (maquette : boutons « cartoon » .tool) ───── */
  /* Même boîte centrée que le split (max-width 1500, margin auto) et sans
     padding horizontal → le 1er bouton s'aligne pile sur le bord gauche de
     l'ordonnance (et le dernier sur le bord droit de la visionneuse). */
  .onglets-outils {
    /* Grille homogène plutôt que flex-wrap : toutes les tuiles ont la MÊME
       largeur et s'alignent proprement en colonnes (2 rangées de 4). La liste
       s'allonge → bornée à la largeur de la colonne prescription (800px, cf.
       .split-wrapper). Le margin-left reprend EXACTEMENT le décalage d'un bloc
       centré à 1500px → bord gauche aligné pile sur la prescription à toute largeur. */
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    padding: 10px 0 12px;
    max-width: 800px;
    margin-left: max(0px, calc((100% - 1500px) / 2));
    margin-right: auto;
  }
  /* En grille, la tuile remplit sa colonne (largeurs égales = alignement vertical). */
  .onglets-outils > .tool { width: 100%; }
  .tool {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    border-radius: 16px;
    padding: 7px 16px 7px 8px;
    background: color-mix(in srgb, var(--c) 8%, var(--surface));
    border: 1.5px solid color-mix(in srgb, var(--c) 30%, var(--surface));
    cursor: pointer;
    /* Halo coloré (couleur du bouton) — j'adore les effets de halo */
    box-shadow: 0 4px 20px color-mix(in srgb, var(--c) 24%, transparent), var(--shadow-sm);
    font-family: inherit;
    font-weight: 700;
    font-size: .85rem;
    color: var(--text);
    transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-base), border-color var(--dur-base), background var(--dur-base);
  }
  .tool:hover {
    transform: translateY(-3px) scale(1.02);
    box-shadow: 0 8px 28px color-mix(in srgb, var(--c) 36%, transparent), var(--shadow-md);
  }
  .tool:hover .ti { transform: scale(1.13) rotate(-7deg); }
  .ti {
    width: 40px;
    height: 40px;
    border-radius: 13px;
    background: linear-gradient(140deg, color-mix(in srgb, var(--c) 78%, #fff) 0%, var(--c) 100%);
    display: grid;
    place-items: center;
    flex: none;
    border: 2px solid var(--surface);
    box-shadow: 0 5px 13px color-mix(in srgb, var(--c) 42%, transparent);
    transition: transform var(--dur-base) var(--ease-spring);
  }
  .ti svg {
    width: 20px;
    height: 20px;
    stroke: white;
    fill: none;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
    filter: drop-shadow(0 1px 1px rgba(0,0,0,.25));
  }
  .tl {
    color: var(--c);
    font-size: .85rem;
    font-weight: 700;
    letter-spacing: -.01em;
  }

  /* Titre de liste : wordmark Dancing Script + exports .tool compacts (maquette §7) */
  .lt-stack { display: flex; flex-direction: column; gap: 1px;
    /* Chip à fond blanc pour faire ressortir le titre */
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 8px 18px; box-shadow: 0 6px 32px color-mix(in srgb, var(--accent) 14%, transparent), var(--shadow-sm); }
  .lt-script { font-family: var(--font-signature, 'Dancing Script', cursive); font-weight: 700; font-size: 2.1rem; line-height: 1; width: max-content; background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
  .list-exports { display: flex; gap: 8px; flex-wrap: wrap; }
  .list-exports .tool { padding: 6px 13px 6px 7px; font-size: .78rem; }
  .list-exports .tool .ti { width: 32px; height: 32px; border-radius: 10px; }
  .list-exports .tool .ti svg { width: 18px; height: 18px; }
  .list-exports .tool .tl { font-size: .78rem; }

  /* ── OBJETS ILLUSTRÉS dans les pastilles d'index.html (30/09/2026) ──
     Pastille .ti d'un outil (en-tête, rangée des exports) : même carré, même taille,
     mais la teinte de l'outil passe en CLAIR — l'objet garde SES couleurs, deux
     couleurs ne se disputent pas la même pastille. Même classe .ti-ob au portail. */
  .tool .ti.ti-ob {
    background: linear-gradient(140deg, color-mix(in srgb, var(--c) 8%, var(--surface)) 0%, color-mix(in srgb, var(--c) 22%, var(--surface)) 100%);
  }
  .ti.ti-ob .ilx { --ilx-t: 24px; }
  /* Une MARQUE garde son logo officiel (Digilab : assets/scanners/digilab.png, pris sur
     digilab.dental le 30/09/2026) — le même carré que les objets, jamais redessiné. */
  .ti.ti-ob .ti-logo { display:block; width:26px; height:26px; border-radius:7px; }
  .list-exports .tool .ti.ti-ob .ilx { --ilx-t: 20px; }
  /* Logos d'écran (Paramètres, Facturation, Administration, Gestion Clients) : l'objet
     sur la pastille colorée de l'écran, comme le logo de l'Historique IA. */
  .pmx-title-ico--logo .ilx { --ilx-t: 22px; }
  #modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico .ilx,
  #facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico .ilx { --ilx-t: 26px; }
  #modal-tarifs .gc-logo-disc .ilx { --ilx-t: 28px; }
  .pmx-title-ico--logo .b3d-ob,
  #modal-tarifs .gc-logo-disc .b3d-ob { filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.28)); }
  /* Le trait BLANC des anciens pictogrammes (`.ti svg`, `.pmx-title-ico--logo svg`,
     `.gc-logo-disc svg` : stroke #fff, fill none) détourerait l'objet : on l'annule,
     et la taille suit la case .ilx. */
  .ti .b3d-ob svg,
  .list-exports .tool .ti .b3d-ob svg,
  .pmx-title-ico--logo .b3d-ob svg,
  #modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico .b3d-ob svg,
  #facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico .b3d-ob svg,
  #modal-tarifs .gc-logo-disc .b3d-ob svg {
    width: var(--ilx-t); height: var(--ilx-t);
    fill: initial; stroke: none; stroke-width: initial; stroke-linecap: initial; stroke-linejoin: initial;
    filter: none;
  }
  /* Implants : la loupe des champs de recherche reste posée DANS le champ. */
  #modal-implants .imx-searchbar > .ilx { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); pointer-events: none; }

  /* ───── Stats §4 (maquette : cartes compteurs .stat exactes) ───── */
  .stats {
    display: flex;
    gap: 10px;
    margin: 4px 0 2px;
    overflow-x: auto;
    padding: 5px 2px 8px;
    scrollbar-width: none;
  }
  .stats::-webkit-scrollbar { display: none; }
  /* Écran étroit (Fold déplié zoomé, fenêtre PC réduite) : le ruban défilant à
     barre INVISIBLE coupait les dernières pastilles sans aucun indice (mesuré :
     « Livrés » hors champ dès 911 px). On replie en grille 4 colonnes — même
     recette que le rendu téléphone (html.mobile-zoom-default .stats), qui a
     déjà fait ses preuves. Seul débordement du squelette relevé de 984 à
     729 px : ce bloc est ce qui rend la mise en page fluide sur cette plage. */
  @media (max-width: 1000px) {
    .stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow-x: visible; }
    .stats > .stat { min-width: 0; }
  }
  .stat {
    flex: 1 1 0;
    min-width: 112px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r);
    padding: 9px 14px;
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    position: relative;
    overflow: hidden;
    text-align: center;
    transition: transform var(--dur-fast), box-shadow var(--dur-base), border-color var(--dur-base);
  }
  .stat:hover {
    transform: translateY(-2px);
    box-shadow: 0 0 0 2px var(--sc, var(--accent)), var(--shadow-md);
    border-color: transparent;
  }
  /* Maquette : label + icône + numéro colorés dans la couleur du stat (--sc). */
  .stat .top {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    color: var(--sc-text, var(--sc, var(--muted)));
    font-size: .72rem;
    font-weight: 600;
  }
  .stat .top .tic { display: flex; }
  /* Objets illustrés (js/icones-app.js, 24/09/2026) : ils gardent LEURS couleurs,
     la case garde la sienne sur le libellé et le chiffre. `> svg` : ne pas écraser
     la taille du dessin de l'objet (.ilx fixe la sienne). */
  .stat .top .tic > svg { width: 14px; height: 14px; }
  .stat .num {
    font-size: 1.45rem;
    font-weight: 700;
    letter-spacing: -.02em;
    margin-top: 2px;
    text-align: center;
    color: var(--sc-text, var(--sc, var(--text)));
  }
  .stat .bar {
    position: absolute;
    left: 0; bottom: 0;
    height: 3px;
    width: 100%;
    opacity: .9;
    background: var(--sc, var(--accent));
  }
  .stat.total .num { background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
  /* Stat actif = fond TEINTÉ (pas opaque) + anneau coloré, façon maquette.
     Le label/icône/numéro restent dans la couleur du stat. */
  .stat.active { border-color: transparent; background: color-mix(in srgb, var(--sc, var(--accent)) 13%, var(--surface)); box-shadow: 0 0 0 2px var(--sc, var(--accent)), var(--shadow-md); }

  /* ───── Case « Stand by » (rouge) : même gabarit que .stat, posée dans
     l'en-tête à droite du titre (pas dans la rangée .stats). ───── */
  .lh-left { display: flex; align-items: center; gap: 18px; min-width: 0; }
  .stat-standby {
    --sc: #d32f2f;
    flex: 0 0 auto;
    min-width: 128px;
    align-self: center;
  }
  /* Pulsation rouge discrète quand au moins 1 cas est en pause (classe .pulse
     posée par updateStatChips). Neutre sinon. */
  @keyframes standbyPulse {
    0%, 100% { box-shadow: var(--shadow-sm); }
    50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc) 32%, transparent), var(--shadow-sm); }
  }
  .stat-standby.pulse { animation: standbyPulse 2.2s ease-in-out infinite; }
  html[data-theme="dark"] .stat-standby { --sc: #ff6b6b; }

  /* ───── Case « Annulés » (gris ardoise) : cas abandonnés, hors workflow.
     Même gabarit que .stat-standby, pas de pulsation (pas une alerte). ───── */
  .stat-annule {
    --sc: #64748b;
    flex: 0 0 auto;
    min-width: 128px; /* identique à .stat-standby pour une largeur égale */
    align-self: center;
  }
  html[data-theme="dark"] .stat-annule { --sc: #94a3b8; }

  /* ───── Barres de recherche liste = style maquette « .field » ─────
     Pilule bordée + icône inline (building/user/loupe) + focus ring teal.
     Scopé en .pf-field pour ne pas toucher au reste. */
  .pf-field { display: flex; align-items: center; gap: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 6px 11px; color: var(--muted); box-shadow: var(--shadow-sm); transition: border-color var(--dur-base), box-shadow var(--dur-base); }
  .pf-field:focus-within { border-color: var(--teal); box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 22%, transparent); }
  .pf-field .ic { color: var(--muted); display: flex; flex: none; }
  .pf-field .ic svg { width: 15px; height: 15px; }
  /* Bascule « code de scan » : l'icône du champ Code labo devient le REPÈRE du labo
     (« # »), cliquable. Éteinte elle reste discrète comme les autres icônes ; allumée
     elle est PLEINE et le champ se teinte — on doit voir au premier coup d'œil qu'on
     cherche dans les scans, sinon on tape un code et on ne comprend pas le vide. */
  /* Le signe est porté par un <span> : sur cette barre, une règle du thème neutralise
     color/background des <button> (vérifié : même un inline !important ne passe pas). */
  .pf-field .ic.pf-repere { cursor: pointer; border: none; background: none; padding: 0; flex: none; }
  .pf-field .ic.pf-repere .sg { display: block; font: 800 .9rem 'DM Mono', ui-monospace, monospace;
    line-height: 1; padding: 4px 8px; border-radius: 8px; color: var(--muted);
    border: 1px solid transparent; background: transparent;
    transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast); }
  .pf-field .ic.pf-repere:hover .sg { color: var(--teal);
    border-color: color-mix(in srgb, var(--teal) 40%, transparent);
    background: color-mix(in srgb, var(--teal) 12%, transparent); }
  .pf-field .ic.pf-repere:focus-visible .sg { outline: 2px solid var(--teal); outline-offset: 2px; }
  /* Actif : pastille pleine + halo. C'est le seul repère qui explique pourquoi une
     recherche ne renvoie rien — il doit sauter aux yeux. */
  .pf-field .ic.pf-repere.on .sg { color: #fff; background: var(--teal); border-color: var(--teal);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 26%, transparent); }
  .pf-field:has(.ic.pf-repere.on) { border-color: var(--teal);
    background: color-mix(in srgb, var(--teal) 7%, var(--surface)); }
  .pf-field input.pf-repere-on { font-weight: 700; letter-spacing: .3px; }
  .pf-field input.pf-repere-on::placeholder { color: color-mix(in srgb, var(--teal) 70%, var(--muted)); font-weight: 700; }
  @media (prefers-reduced-motion: reduce) { .pf-field .ic.pf-repere .sg { transition: none; } }

  .pf-field input { border: none; outline: none; background: transparent; font-family: 'DM Sans', sans-serif; font-size: .82rem; color: var(--text); min-width: 0; flex: 1; padding: 0; }
  .pf-field input::placeholder { color: var(--muted); }
  .pf-field .pf-clear { background: none; border: none; cursor: pointer; color: var(--muted); opacity: .55; font-size: .85rem; padding: 0; flex: none; display: flex; line-height: 1; }
  .pf-field .pf-clear:hover { opacity: 1; }

  /* ─ Pill "Période" (calendrier filtre date) ─ */
  .pf-period-btn { display: flex; align-items: center; gap: 5px; border: 1px solid var(--border); border-radius: 11px; padding: 5px 10px; font-size: .74rem; font-family: 'DM Sans', sans-serif; background: var(--surface); cursor: pointer; color: var(--muted); font-weight: 500; white-space: nowrap; transition: border-color var(--dur-fast), color var(--dur-fast); box-shadow: var(--shadow-sm); }
  /* Selects de la barre liste (tri + filtre fournisseur) : aligne sort-btn/fournisseur sur les boutons voisins (var → dark mode OK). */
  .pf-sort { border: 1px solid var(--border); border-radius: 11px; padding: 5px 9px; font-size: .74rem; font-family: 'DM Sans', sans-serif; background: var(--surface); color: var(--muted); font-weight: 600; cursor: pointer; white-space: nowrap; box-shadow: var(--shadow-sm); max-width: 190px; transition: border-color var(--dur-fast), color var(--dur-fast); }
  .pf-sort:hover { border-color: var(--accent); color: var(--accent-text); }
  /* Pastilles sous-traitant : même teinte que le résumé IA (variable --f de la
     config du labo, cf. .ais-fourn[class*="fourn-c"]), bleu neutre par défaut. */
  #filter-fournisseur option[class*="fourn-c"] { color: color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); }
  #filter-fournisseur[class*="fourn-c"] { border-color: color-mix(in srgb, var(--f, var(--accent)) 55%, transparent);
    color: color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); }
  #filter-fournisseur option.fourn-other { color: #1a5c8a; }
  #filter-fournisseur.fourn-other { border-color: rgba(26,92,138,.55);  color: #1a5c8a; }
  .pf-period-btn:hover { border-color: var(--teal); color: var(--teal-text); }
  .pf-period-btn.active { border-color: var(--accent); color: var(--accent-text); font-weight: 600; }

  /* ─ Filtre d'archivage : pilule déclencheur + menu déroulant (En cours / Tous /
     Archivés). Remplace l'ancienne case à cocher. Cohérent avec .pf-period-btn,
     tout en tokens → dark mode automatique. ─ */
  .pf-arch { position: relative; display: inline-flex; }
  .pf-arch-trigger { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border); border-radius: 11px; padding: 5px 9px; font-size: .75rem; font-weight: 600; font-family: 'DM Sans', sans-serif; color: var(--muted); background: var(--surface); cursor: pointer; white-space: nowrap; box-shadow: var(--shadow-sm); transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast); }
  /* Icône « boîte d'archive » en masque SVG (trait fin, façon icônes de l'app) →
     prend currentColor du déclencheur, donc se recolore selon l'état (muted / teal
     au survol / accent quand un filtre est posé). */
  .pf-arch-ic { width: 14px; height: 14px; flex: none; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='5' x='2' y='3' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='5' x='2' y='3' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E") center / contain no-repeat; }
  /* Largeur figée sur le libellé le plus long (« Archivés » ≈ 50px) → le bouton
     ne change PAS de taille quand on bascule de mode. Aligné à gauche. */
  .pf-arch-label { display: inline-block; min-width: 53px; text-align: left; }
  .pf-arch-chev { font-size: .62rem; opacity: .7; transition: transform var(--dur-fast) ease; }
  .pf-arch-trigger:hover { border-color: var(--teal); color: var(--teal-text); }
  .pf-arch-trigger:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent); outline-offset: 1px; }
  .pf-arch-trigger[aria-expanded="true"] .pf-arch-chev { transform: rotate(180deg); }
  /* Mode actif ≠ « En cours » → pilule en accent pour signaler qu'un filtre est posé. */
  .pf-arch.is-filtering .pf-arch-trigger { border-color: var(--accent); color: var(--accent-text); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }

  /* ─ Filtre « marque de scanner » : le MÊME composant .pf-arch, plus la couleur de
     marque de l'onglet Digilab (tokens --sv-*, source unique dans js/digilab-ui-styles.js).
     Signature : la pilule s'habille de la teinte du scanner choisi → la barre dit
     d'un coup d'œil ce qu'on regarde (vert = iTero, rouge = 3Shape…). Teintes de
     PRODUIT, jamais du labo → aucun impact multi-tenant. ─ */
  .pf-scan { --sv-bg: var(--surface); --sv-fg: var(--muted); }
  .pf-scan[data-brand="medit"],   .pf-scan-menu [data-brand="medit"], .scan-tag[data-brand="medit"]   { --sv-bg: var(--sv-medit-bg);   --sv-fg: var(--sv-medit-fg); }
  .pf-scan[data-brand="3shape"],  .pf-scan-menu [data-brand="3shape"], .scan-tag[data-brand="3shape"]  { --sv-bg: var(--sv-3shape-bg);  --sv-fg: var(--sv-3shape-fg); }
  .pf-scan[data-brand="itero"],   .pf-scan-menu [data-brand="itero"], .scan-tag[data-brand="itero"]   { --sv-bg: var(--sv-itero-bg);   --sv-fg: var(--sv-itero-fg); }
  .pf-scan[data-brand="dscore"],  .pf-scan-menu [data-brand="dscore"], .scan-tag[data-brand="dscore"]  { --sv-bg: var(--sv-dscore-bg);  --sv-fg: var(--sv-dscore-fg); }
  .pf-scan[data-brand="shining"], .pf-scan-menu [data-brand="shining"], .scan-tag[data-brand="shining"] { --sv-bg: var(--sv-shining-bg); --sv-fg: var(--sv-shining-fg); }
  .pf-scan[data-brand="dexis"],   .pf-scan-menu [data-brand="dexis"], .scan-tag[data-brand="dexis"]   { --sv-bg: var(--sv-dexis-bg);   --sv-fg: var(--sv-dexis-fg); }
  .pf-scan[data-brand="autre"],   .pf-scan-menu [data-brand="autre"], .scan-tag[data-brand="autre"]   { --sv-bg: var(--sv-other-bg);   --sv-fg: var(--sv-other-fg); }
  /* « Tous » et « Sans scanner » ne sont pas des marques : pas de teinte produit,
     mais un état sélectionné quand même visible → on prend l'accent du labo. */
  .pf-scan-menu [data-brand="__all"], .pf-scan-menu [data-brand="__none"] {
    --sv-bg: color-mix(in srgb, var(--accent) 12%, var(--surface)); --sv-fg: var(--accent-text); }
  /* Pastille : disque plein aux couleurs de la marque, cerclé d'un halo de la même
     teinte. « Sans scanner » et « Tous » = anneau creux (l'absence se voit). */
  .pf-scan-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--sv-fg);
    box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--sv-fg) 20%, transparent); transition: background var(--dur-fast), box-shadow var(--dur-fast); }
  /* Aucun filtre posé : l'OBJET du filtre (canule de scanner, sceau vérifié) à la
     place du rond vide (Illan 25/09/2026 : « trouve des meilleures icônes ») ;
     filtre posé : la pastille teintée de la marque / de la personne revient. */
  .pf-scan:not([data-brand]) .pf-arch-trigger .pf-scan-dot,
  .pf-scan[data-brand="__none"] .pf-arch-trigger .pf-scan-dot,
  .pf-verif:not(.is-filtering) #verif-trig-dot,
  .pf-scan[data-brand]:not([data-brand="__none"]) .pf-scan-ico,
  .pf-verif.is-filtering .pf-verif-ico { display: none; }
  .pf-scan:not([data-brand]) .pf-arch-trigger .pf-scan-dot,
  .pf-scan[data-brand="__none"] .pf-arch-trigger .pf-scan-dot,
  .pf-scan-menu [data-brand="__all"] .pf-scan-dot,
  .pf-scan-menu [data-brand="__none"] .pf-scan-dot { background: transparent; box-shadow: inset 0 0 0 1.6px var(--muted); }
  /* Déclencheur habillé de la marque (uniquement quand un filtre est posé). */
  .pf-scan[data-brand] .pf-arch-trigger { background: var(--sv-bg); color: var(--sv-fg); font-weight: 600;
    border-color: color-mix(in srgb, var(--sv-fg) 34%, transparent); }
  .pf-scan[data-brand] .pf-arch-trigger:hover { border-color: color-mix(in srgb, var(--sv-fg) 62%, transparent); color: var(--sv-fg); }
  .pf-scan[data-brand="__none"] .pf-arch-trigger { background: var(--surface); color: var(--muted); border-color: var(--border); }
  .pf-scan-label { display: inline-block; min-width: 56px; text-align: left; }
  /* Lignes du menu : pastille · marque · compteur, sur une seule ligne. Sélecteurs
     portés par .pf-scan-menu → passent devant .pf-arch-opt (colonne) sans !important. */
  /* max-width : la barre de filtres passe à la ligne (flex-wrap) — si la pilule
     finit en bord droit, le menu ne doit jamais provoquer de scroll horizontal. */
  .pf-scan-menu { min-width: 216px; max-width: calc(100vw - 24px); }
  .pf-scan-menu .pf-scan-opt { flex-direction: row; align-items: center; gap: 9px; padding: 7px 11px; }
  .pf-scan-menu .pf-scan-opt-t { font-size: .8rem; font-weight: 600; }
  .pf-scan-menu .pf-scan-n { margin-left: auto; font-size: .68rem; font-weight: 700; color: var(--muted);
    background: var(--surface-2); border-radius: 999px; padding: 1px 7px; min-width: 22px; text-align: center; }
  .pf-scan-menu .pf-scan-opt.is-active { background: var(--sv-bg); }
  .pf-scan-menu .pf-scan-opt.is-active .pf-scan-opt-t { color: var(--sv-fg); }
  .pf-scan-menu .pf-scan-opt.is-active .pf-scan-n { background: color-mix(in srgb, var(--sv-fg) 16%, transparent); color: var(--sv-fg); }
  .pf-scan-menu .pf-scan-opt:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent); outline-offset: -2px; }

  /* ─ Filtre « vérifié par » : le MÊME composant .pf-arch, plus une pastille à la
     couleur du profil de la personne (couleur choisie dans les profils → jamais un
     labo en dur, dark mode hérité des tokens). Jumeau visuel de .pf-scan. ─ */
  .pf-verif-label { display: inline-block; min-width: 56px; text-align: left; }
  /* Avatar d'une personne dans le menu « Vérifié par » (upAvatarHtml, base
     pf-verif-av) : photo ou initiales sur sa couleur, petit. */
  .pf-verif-avw { flex: none; display: grid; place-items: center; }
  .pf-verif-av { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
    background-size: cover; background-position: center; color: #fff; font-size: 8.5px; font-weight: 800;
    letter-spacing: .02em; line-height: 1; box-shadow: 0 0 0 1px color-mix(in srgb, var(--text) 12%, transparent); }
  .pf-verif-dot { width: 10px; height: 10px; border-radius: 50%; flex: none;
    background: var(--muted); box-shadow: 0 0 0 1px color-mix(in srgb, var(--text) 12%, transparent) inset; }
  .pf-verif-dot--all, .pf-verif:not(.is-filtering) #verif-trig-dot {
    background: transparent; box-shadow: inset 0 0 0 1.6px var(--muted); }
  .pf-verif.is-filtering .pf-arch-trigger { border-color: var(--accent); color: var(--accent-text);
    background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  .pf-verif-menu { min-width: 216px; max-width: calc(100vw - 24px); }
  .pf-verif-menu .pf-verif-opt { flex-direction: row; align-items: center; gap: 9px; padding: 7px 11px; }
  .pf-verif-menu .pf-verif-opt-t { font-size: .8rem; font-weight: 600; }
  .pf-verif-menu .pf-verif-n { margin-left: auto; font-size: .68rem; font-weight: 700; color: var(--muted);
    background: var(--surface-2); border-radius: 999px; padding: 1px 7px; min-width: 22px; text-align: center; }
  .pf-verif-menu .pf-verif-opt.is-active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  .pf-verif-menu .pf-verif-opt.is-active .pf-verif-opt-t { color: var(--accent-text); }
  .pf-verif-menu .pf-verif-opt:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent); outline-offset: -2px; }

  /* ─ Filtre « acte » : même composant .pf-arch que ses frères scanner/vérificateur.
     Deux différences assumées, parce qu'un labo a des dizaines d'actes là où il n'a
     que 6 marques de scanner : une barre de recherche collante en tête, et une liste
     qui défile, rangée par catégorie. Tout en tokens → dark mode + tenant hérités. ─ */
  .pf-acte-label { display: inline-block; min-width: 34px; text-align: left; }
  .pf-acte-ico { font-size: .82rem; line-height: 1; flex: none; }
  .pf-acte.is-filtering .pf-arch-trigger { border-color: var(--accent); color: var(--accent-text);
    background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  /* Deux classes : .pf-arch-menu (plus bas dans le fichier) impose sinon son
     min-width de 212 px, trop étroit pour des libellés comme « Gouttière souple
     intra dur extra ». */
  .pf-arch-menu.pf-acte-menu { min-width: 286px; max-width: calc(100vw - 24px); padding-top: 0; }
  /* La recherche reste visible quand la liste défile : c'est le geste principal. */
  .pf-acte-search { position: sticky; top: 0; z-index: 1; width: 100%; box-sizing: border-box;
    margin: 0 0 4px; padding: 8px 10px; border: none; border-bottom: 1px solid var(--border);
    border-radius: 10px 10px 0 0; font-family: 'DM Sans', sans-serif; font-size: .8rem;
    background: var(--surface); color: var(--text); }
  .pf-acte-search:focus { outline: none; border-bottom-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
  .pf-acte-search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
  .pf-acte-list { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow-y: auto; }
  /* Bandeau UNIVERS : mêmes teintes que la grille de tarifs et l'onglet Actes &
     codes (bleu conjointe / rose adjointe / gris neutre — règle métier des
     couleurs). Le rangement, lui, n'est pas recopié : il est LU du catalogue. */
  /* La couleur de l'univers est posée UNE fois sur le bloc (--pf-tint) ; le
     bandeau, le sous-titre de famille et le liseré de chaque ligne la lisent.
     Un seul endroit à corriger si une teinte change. */
  .pf-acte-univ-bloc { --pf-tint: #7a96a8; }
  .pf-acte-univ-bloc.is-conjointe { --pf-tint: #1a5c8a; }
  .pf-acte-univ-bloc.is-adjointe  { --pf-tint: #c2185b; }
  .pf-acte-univ-bloc.is-implant   { --pf-tint: #6a1b9a; }
  html[data-theme="dark"] .pf-acte-univ-bloc { --pf-tint: #8899aa; }
  html[data-theme="dark"] .pf-acte-univ-bloc.is-conjointe { --pf-tint: #5bc4c0; }
  html[data-theme="dark"] .pf-acte-univ-bloc.is-adjointe  { --pf-tint: #f48fb1; }
  html[data-theme="dark"] .pf-acte-univ-bloc.is-implant   { --pf-tint: #ce93d8; }

  .pf-acte-univ { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em;
    padding: 6px 10px; margin: 6px 0 2px; border-radius: 7px;
    color: var(--pf-tint); background: color-mix(in srgb, var(--pf-tint) 12%, var(--surface)); }
  .pf-acte-univ-bloc:first-of-type .pf-acte-univ { margin-top: 2px; }
  /* Sous-titre de famille : la couleur de l'univers, adoucie — même recette que
     .pm-acte-band--fam dans Actes & codes. */
  .pf-acte-grp { font-size: .6rem; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
    color: color-mix(in srgb, var(--pf-tint) 72%, var(--muted)); padding: 7px 10px 3px; }
  /* Liseré de catégorie sur CHAQUE ligne : on reconnaît un acte fixe / implant /
     amovible d'un coup d'œil, même dans un résultat de recherche loin de son
     bandeau. Même dispositif que le liseré des lignes d'Actes & codes, en
     inset-shadow pour ne décaler aucune géométrie. */
  .pf-acte-menu .pf-acte-opt { box-shadow: inset 3px 0 0 color-mix(in srgb, var(--pf-tint) 55%, transparent); }
  .pf-acte-menu .pf-acte-opt:hover { box-shadow: inset 3px 0 0 var(--pf-tint); }
  .pf-acte-menu .pf-acte-opt.is-active { box-shadow: inset 3px 0 0 var(--pf-tint); }
  .pf-acte-menu .pf-acte-opt[data-acte=""] { box-shadow: none; }   /* « Tous les actes » */
  .pf-acte-univ-bloc, .pf-acte-fam-bloc { display: flex; flex-direction: column; gap: 2px; }
  .pf-acte-univ-bloc[hidden], .pf-acte-fam-bloc[hidden],
  .pf-acte-grp[hidden], .pf-acte-opt[hidden], .pf-acte-vide[hidden] { display: none; }
  .pf-acte-menu .pf-acte-opt { flex-direction: row; align-items: center; gap: 9px; padding: 7px 11px; }
  .pf-acte-menu .pf-acte-opt-t { font-size: .8rem; font-weight: 600; }
  .pf-acte-menu .pf-acte-n { margin-left: auto; font-size: .68rem; font-weight: 700; color: var(--muted);
    background: var(--surface-2); border-radius: 999px; padding: 1px 7px; min-width: 22px; text-align: center; }
  .pf-acte-menu .pf-acte-opt.is-active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  .pf-acte-menu .pf-acte-opt.is-active .pf-acte-opt-t { color: var(--accent-text); }
  .pf-acte-menu .pf-acte-opt.is-active .pf-acte-n { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent-text); }
  .pf-acte-menu .pf-acte-opt:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 40%, transparent); outline-offset: -2px; }
  .pf-acte-vide { padding: 12px 10px; font-size: .76rem; color: var(--muted); text-align: center; }

  .pf-arch-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 200; min-width: 212px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-md); padding: 5px; display: flex; flex-direction: column; gap: 2px; animation: pfArchMenuIn var(--dur-fast) ease backwards; }
  .pf-arch-menu[hidden] { display: none; }
  @keyframes pfArchMenuIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
  .pf-arch-opt { display: flex; flex-direction: column; gap: 1px; text-align: left; border: none; background: none; cursor: pointer; padding: 7px 10px; border-radius: 8px; font-family: 'DM Sans', sans-serif; color: var(--text); transition: background var(--dur-fast); }
  .pf-arch-opt:hover { background: var(--surface-2); }
  .pf-arch-opt-t { font-size: .82rem; font-weight: 600; display: flex; align-items: center; }
  .pf-arch-opt-d { font-size: .68rem; color: var(--muted); }
  .pf-arch-opt.is-active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  .pf-arch-opt.is-active .pf-arch-opt-t { color: var(--accent-text); }
  .pf-arch-opt.is-active .pf-arch-opt-t::after { content: '✓'; margin-left: auto; color: var(--accent-text); font-weight: 700; padding-left: 10px; }
  /* Compteur d'archives : le filtre passe en colonne (bouton + petite ligne dessous). */
  .pf-arch { flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px; align-self: center; }
  .pf-arch-count { display: inline-flex; align-items: center; gap: 4px; padding-left: 3px; font-size: .64rem; font-weight: 600; line-height: 1; color: var(--muted); white-space: nowrap; letter-spacing: .01em; }
  .pf-arch-count[hidden] { display: none; }
  .pf-arch-count::before { content: ''; width: 11px; height: 11px; flex: none; background: currentColor; opacity: .8; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='5' x='2' y='3' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='5' x='2' y='3' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E") center / contain no-repeat; }
  .pf-arch-count b { color: var(--accent-text); font-weight: 800; }
  .pf-arch-opt-n { color: var(--accent-text); font-weight: 800; }
  .pf-arch-opt-n:empty::before { content: '…'; color: var(--muted); font-weight: 600; }

  /* ─ Calendrier flottant : jours ─ */
  .fcal-day { text-align: center; padding: 5px 0; border-radius: 7px; cursor: pointer; font-size: .8rem; color: var(--text); transition: background var(--dur-fast); }
  .fcal-day:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
  .fcal-day.edge { background: var(--accent); color: #fff; font-weight: 700; }
  .fcal-day.in-range { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent-text); }
  .fcal-day.today { font-weight: 700; color: var(--accent-text); }

  /* ───── gc-fiche : sections (Praticiens, Notes, Cas) ───── */
  html[data-theme="dark"] .gc-fiche-section-head {
    background: #1e2434;
    border-bottom-color: #3a4055;
  }
  html[data-theme="dark"] .gc-fiche-section-body {
    background: #242938;
  }
  html[data-theme="dark"] .gc-fiche-section-title { color: #e0e6ed; }
  html[data-theme="dark"] .gc-fiche-section-count {
    background: #1e3a4f; color: #5bc4c0;
  }
  /* Notes : si remplie -> alerte ambre (assombrie en dark) */
  html[data-theme="dark"] .gc-fiche-section.notes-active .gc-fiche-section-head {
    background: #3a2a18;
    border-bottom-color: #6a5520;
  }

  /* ───── Tarifs : lignes de groupe (Prothèses Mobiles, AUTRES, etc.) ───── */
  .gc-tarif-grpcat td {
    padding: 8px 14px;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    border-top: 1px solid;
    border-bottom: 1px solid;
  }
  .gc-tarif-grpcat.is-adjointe td {
    background: #fce4ec;
    color: #c2185b;
    border-top-color: #f8bbd0;
    border-bottom-color: #f8bbd0;
  }
  .gc-tarif-grpcat.is-conjointe td {
    background: #f0f7fb;
    color: #1a5c8a;
    border-top-color: #d0e0ea;
    border-bottom-color: #d0e0ea;
  }
  .gc-tarif-grpcat.is-autres td {
    background: #f5f5f5;
    color: #7a96a8;
    border-top-color: #e0e0e0;
    border-bottom-color: #e0e0e0;
  }
  /* Dark : assombri pour ne pas faire de bande lumineuse */
  html[data-theme="dark"] .gc-tarif-grpcat.is-adjointe td {
    background: #2a1620;
    color: #f48fb1;
    border-top-color: #5a2840;
    border-bottom-color: #5a2840;
  }
  html[data-theme="dark"] .gc-tarif-grpcat.is-conjointe td {
    background: #1e2c3e;
    color: #5bc4c0;
    border-top-color: #2a3a50;
    border-bottom-color: #2a3a50;
  }
  html[data-theme="dark"] .gc-tarif-grpcat.is-autres td {
    background: #1e2434;
    color: #8899aa;
    border-top-color: #3a4055;
    border-bottom-color: #3a4055;
  }

  /* ═══ Paramètres › Actes — tableau tokenisé (refonte, aligné .imx-/.pmx-/.cr-) ═══
     Zéro couleur en dur (dark mode + branding tenant gratuits) sauf les 2 teintes
     métier conjointe/adjointe du liseré (convention app). */

  /* Hero « cockpit » — gradient profond dérivé du branding tenant + grille + halo + faisceau */
  @keyframes pmaHalo{0%,100%{opacity:.4;transform:scale(.9)}50%{opacity:.85;transform:scale(1.1)}}
  /* Ping converti box-shadow→pseudo (scale+opacity) : 7px de halo autour du point
     de 8px → scale 2.75, même couleur, même cadence 1.9s. */
  @keyframes pmaSlide{from{transform:translateX(-120%)}to{transform:translateX(340%)}}

  /* Barre d'outils */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex-shrink:0;padding:11px 18px;background:var(--surface);border-bottom:1px solid var(--line)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-field{padding:6px 11px;border:1px solid var(--line);border-radius:10px;font-size:.76rem;font-family:'DM Sans',sans-serif;background:var(--surface);color:var(--text);transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) input.pm-actes-field{width:180px}
  /* Le filtre de famille prenait toute la largeur (règle générale select{width:100%}) et
     cassait la barre en deux rangées (vu le 28/09/2026). */
  :is(#modal-parametres,.acv-tarifs) select.pm-actes-field{width:auto;max-width:260px}
  /* Recherche à droite de « Réinitialiser » (Illan, 26/09/2026) : elle prend le reste de la ligne. */
  :is(#modal-parametres,.acv-tarifs) #pm-actes-search{flex:1 1 220px;min-width:180px}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-field:focus{outline:none;border-color:var(--teal);box-shadow:0 0 0 3px color-mix(in srgb,var(--teal) 18%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-check{display:flex;align-items:center;gap:6px;font-size:.74rem;color:var(--muted);cursor:pointer;user-select:none;white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-check input{width:14px;height:14px;accent-color:var(--accent)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn{display:inline-flex;align-items:center;gap:5px;padding:6px 12px;border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--text);font-size:.74rem;font-weight:600;font-family:inherit;cursor:pointer;transition:border-color var(--dur-fast),background var(--dur-fast),transform var(--dur-fast);white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn:hover{border-color:var(--accent);background:var(--surface-2)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn:active{transform:scale(.97)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn--primary{position:relative;overflow:hidden;border-color:transparent;background:var(--grad);color:#fff;box-shadow:0 4px 14px -6px color-mix(in srgb,var(--accent) 80%,transparent)}
  /* Shimmer converti left→translateX (compositable, zéro reflow). Course identique :
     left allait de -60% à 130% du BOUTON = 190% de sa largeur ; le reflet fait 45%
     du bouton → 190/45 ≈ 422% de SA propre largeur en translateX. */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn--primary::after{content:"";position:absolute;top:0;left:-60%;width:45%;height:100%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.4),transparent);transform:translateX(0) skewX(-18deg);animation:pmaShimmer 3.6s var(--ease-in-out) infinite;pointer-events:none}
  @keyframes pmaShimmer{0%,72%{transform:translateX(0) skewX(-18deg)}100%{transform:translateX(422%) skewX(-18deg)}}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn--primary:hover{filter:brightness(1.06);background:var(--grad);box-shadow:0 6px 20px -6px color-mix(in srgb,var(--accent) 90%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-btn--ghost{color:var(--muted);font-weight:500}

  /* Zone scroll + table */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-scroll{flex:1;overflow:auto;padding:0}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table{width:100%;border-collapse:collapse;font-size:.76rem}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table tbody{animation:pmaFade var(--dur-enter) ease backwards}
  @keyframes pmaFade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table thead th{position:sticky;top:0;z-index:2;text-align:left;padding:11px 12px;font-size:.66rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);background:var(--section-bg);border-bottom:1px solid var(--line);white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table thead th:first-child{padding-left:16px}

  /* Lignes + liseré univers (signature) */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row{transition:background var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row td{padding:5px 12px;border-bottom:1px solid color-mix(in srgb,var(--line) 60%,transparent);color:var(--text);vertical-align:middle}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row td:first-child{position:relative;padding-left:16px;text-align:center;width:34px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row td:first-child::before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:transparent;transition:width var(--dur-fast) ease,box-shadow var(--dur-fast) ease}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-conjointe td:first-child::before{background:#1a5c8a}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-adjointe td:first-child::before{background:#c2185b}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-neutre td:first-child::before{background:color-mix(in srgb,var(--muted) 40%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row:hover{background:linear-gradient(90deg,color-mix(in srgb,var(--teal) 10%,var(--surface)),color-mix(in srgb,var(--teal) 3%,var(--surface)))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row:hover td:first-child::before{width:3px;box-shadow:0 0 10px color-mix(in srgb,var(--accent) 60%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-parent td{background:color-mix(in srgb,var(--accent) 5%,var(--surface))}

  /* Bandeaux swimlane (Univers → Famille) dans le flux du tableau */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band td{border-bottom:1px solid var(--line)}
  /* Pas de bandeau collant ici, et c'est délibéré : dans un tableau, un td en
     position:sticky se cale sur le TABLEAU entier, pas sur sa section — tous les
     bandeaux se superposent au même endroit et le titre épinglé reste celui du
     premier univers quoi qu'on fasse (vérifié : « Prothèse fixe » encore affiché
     à 3000px de défilement, soit six sections plus bas). Un titre qui ment est
     pire que pas de titre. Le faire proprement demande un <tbody> par univers ;
     à reprendre le jour où on y touche. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ td{padding:9px 16px;font-size:.72rem;font-weight:800;letter-spacing:.7px;text-transform:uppercase}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-conjointe td{background:color-mix(in srgb,#1a5c8a 15%,var(--surface));color:#1a5c8a}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-adjointe td{background:color-mix(in srgb,#c2185b 13%,var(--surface));color:#c2185b}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-neutre td{background:var(--surface-2);color:var(--muted)}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-conjointe td{color:#7fb3d8}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-adjointe td{color:#f48fb1}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:currentColor;margin-right:9px;vertical-align:middle;box-shadow:0 0 8px currentColor;animation:pmaBandPulse 2.6s ease-in-out infinite}
  @keyframes pmaBandPulse{0%,100%{opacity:.45}50%{opacity:1}}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam td{padding:5px 16px 5px 30px;font-size:.63rem;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--muted);background:color-mix(in srgb,var(--muted) 5%,var(--surface))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-conjointe td{color:color-mix(in srgb,#1a5c8a 78%,var(--muted))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-adjointe td{color:color-mix(in srgb,#c2185b 72%,var(--muted))}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-conjointe td{color:#8fb8d8}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-adjointe td{color:#e79ab5}

  /* Compteur d'articles du bandeau — la seule information ajoutée aux titres,
     et celle qui manquait : « Couronnes 6 » situe, « Couronnes » non. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-n{display:inline-block;margin-left:8px;padding:0 6px;
    min-width:18px;text-align:center;border-radius:999px;font-size:.62rem;font-weight:700;
    letter-spacing:0;background:color-mix(in srgb,currentColor 15%,transparent);color:inherit}

  /* Sections HORS CATALOGUE (à coder / réglages de fabrication / anciennes cases).
     Repliables : ce sont les seules lignes du tableau qui ne sont pas des articles,
     on ne veut pas qu'elles allongent la page en permanence. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--hors td{padding:0;background:var(--surface-2)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-toggle{display:flex;align-items:center;gap:0;width:100%;
    padding:9px 16px;border:0;background:none;font:inherit;font-size:.72rem;font-weight:800;
    letter-spacing:.7px;text-transform:uppercase;color:var(--muted);cursor:pointer;text-align:left;
    transition:background var(--dur-fast) ease,color var(--dur-fast) ease}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-toggle:hover{background:color-mix(in srgb,var(--accent) 6%,transparent);color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-toggle:focus-visible{outline:2px solid var(--teal);outline-offset:-2px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-chev{display:inline-block;width:14px;flex:none;font-size:.7rem}
  /* Aide en clair : ces sections méritent d'expliquer ce qu'elles contiennent —
     « Réglages de fabrication » ne se devine pas. Masquée sur écran étroit. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band-aide{margin-left:12px;flex:1;min-width:0;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap;font-size:.63rem;font-weight:500;letter-spacing:0;
    text-transform:none;color:var(--muted);opacity:.85}
  html.mobile-zoom-default :is(#modal-parametres,.acv-tarifs) .pm-acte-band-aide{display:none}

  /* Nom de la case */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-name{font-size:.78rem;font-weight:500;color:var(--text)}
  /* Icône de l'article devant son nom (js/icones-articles.js) — la même que dans le résumé IA. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-name .acv-ico{--ilx-t:25px;vertical-align:-7px;margin-right:7px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-parent .pm-acte-name{font-size:.84rem;font-weight:800;color:var(--accent-text)}

  /* Statut : pastille tokenisée */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-dot{display:inline-block;width:9px;height:9px;border-radius:50%}
  /* Respiration convertie box-shadow→pseudo : glow fort STATIQUE sur le ::after,
     seul opacity respire (le glow doux reste sur le point). Même teinte, même cadence. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-dot.is-ok{background:var(--success);box-shadow:0 0 6px color-mix(in srgb,var(--success) 50%,transparent);position:relative;z-index:0}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-dot.is-ok::after{content:"";position:absolute;inset:0;border-radius:50%;z-index:-1;box-shadow:0 0 11px color-mix(in srgb,var(--success) 80%,transparent);opacity:0;animation:pmaDotBreath 2.8s ease-in-out infinite}
  @keyframes pmaDotBreath{0%,100%{opacity:0}50%{opacity:1}}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-dot.is-warn{background:var(--warn);box-shadow:0 0 7px color-mix(in srgb,var(--warn) 55%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-dot.is-empty{width:8px;height:8px;background:transparent;border:1.5px solid color-mix(in srgb,var(--muted) 55%,transparent)}

  /* Inputs de cellule */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input{width:100%;padding:5px 8px;border:1px solid var(--line);border-radius:7px;font-size:.74rem;font-family:'DM Sans',sans-serif;background:var(--surface);color:var(--text);box-sizing:border-box;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input:focus{outline:none;border-color:var(--teal);box-shadow:0 0 0 3px color-mix(in srgb,var(--teal) 16%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input--code{font-family:'DM Mono',monospace;font-weight:600;color:var(--accent-text);background:color-mix(in srgb,var(--accent) 5%,var(--surface));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 8%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input--code.is-valide{border-color:color-mix(in srgb,var(--teal) 55%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input.is-cog{background:color-mix(in srgb,var(--warn) 8%,var(--surface))}
  /* Flash « enregistré » : bref halo teal quand on modifie une cellule */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input.pm-cell-saved{animation:pmaSaved .7s ease}
  @keyframes pmaSaved{0%{box-shadow:0 0 0 3px color-mix(in srgb,var(--teal) 50%,transparent)}100%{box-shadow:0 0 0 3px transparent}}
  /* Dark : la règle générique « #modal-parametres input » force color/bg → on rétablit les variantes */
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-input--code{color:var(--teal-text) !important;background:color-mix(in srgb,var(--teal) 9%,var(--surface)) !important}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-input.is-cog{background:color-mix(in srgb,var(--warn) 14%,var(--surface)) !important}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-input:focus{border-color:var(--teal) !important}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-actes-field:focus{border-color:var(--teal) !important}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-input--code.is-valide{border-color:color-mix(in srgb,var(--teal) 55%,var(--line)) !important}

  /* Cellules texte (vide / lecture seule) + chip code */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-muted{font-size:.72rem;color:var(--muted);font-style:italic}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-ro{font-size:.72rem;color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-chip{font-family:'DM Mono',monospace;font-size:.72rem;font-weight:500;color:var(--accent-text);background:color-mix(in srgb,var(--accent) 12%,var(--surface));border:1px solid color-mix(in srgb,var(--accent) 24%,var(--line));padding:2px 8px;border-radius:6px}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-chip{color:var(--teal-text)}

  /* Colonne « Code produit » — étroite.
     Le tableau est en largeur automatique : sans borne, cette colonne prenait la
     place d'une colonne de texte alors qu'elle n'affiche qu'un code court. La
     place récupérée va aux colonnes de libellés, qui en ont besoin. La 4e colonne
     est bien le code dans les lignes normales COMME dans les sous-lignes « combo ».
     126px = mesuré sur les 87 codes du labo pilote pour que le PLUS LONG
     (« INLAY-CORE-F », 95px de texte) tienne sans être rogné. */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles th:nth-child(3),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(3){width:126px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-input--code{padding-left:6px;padding-right:6px;font-size:.72rem}
  /* Code en PASTILLE (article annexe, article maison — code non modifiable) : la
     colonne est étroite, un code long y passait sur deux lignes et doublait la
     hauteur de la ligne (« INLAY-CORE-F », 09/09/2026). */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(3) .pm-acte-chip{white-space:nowrap;padding:2px 6px}

  /* Badge combo + chevron */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-combo{display:inline-block;margin-left:6px;font-size:.62rem;padding:1px 8px;border-radius:999px;background:color-mix(in srgb,var(--accent) 12%,var(--surface));color:var(--accent-text);font-weight:700;cursor:help;border:1px solid color-mix(in srgb,var(--accent) 25%,var(--line))}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-combo{color:var(--teal-text)}

  /* ── Actes & codes en deux vues (25/09/2026, maquette validée par Illan) ──
     js/actes-codes-vue.js. Les pastilles « Commandé par » sont celles du résumé
     IA (.ais-act, style.css plus haut) : même lecture que la fiche. */
  :is(#modal-parametres,.acv-tarifs) .acv-seg{display:flex;align-items:flex-end;gap:6px;padding:12px 18px 0;background:var(--surface);flex-shrink:0}
  :is(#modal-parametres,.acv-tarifs) .acv-seg button{display:inline-flex;align-items:center;gap:8px;padding:8px 15px;border:1px solid var(--line);border-bottom:0;border-radius:12px 12px 0 0;background:var(--surface-2);color:var(--muted);font:inherit;font-size:.78rem;font-weight:700;cursor:pointer;transition:background var(--dur-fast),color var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .acv-seg button:hover{color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .acv-seg button.is-on{background:var(--surface);color:var(--text);box-shadow:0 -2px 0 var(--accent) inset}
  :is(#modal-parametres,.acv-tarifs) .acv-seg button:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
  :is(#modal-parametres,.acv-tarifs) .acv-seg-n{padding:0 7px;border-radius:999px;font-size:.64rem;background:color-mix(in srgb,currentColor 14%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .acv-seg-aide{margin-left:auto;align-self:center;font-size:.7rem;color:var(--muted)}
  /* Pastilles d'univers sous « Articles facturés » (25/09/2026) : une par univers, à la
     couleur MÉTIER de ses bandeaux (mêmes teintes que .pm-acte-band--univ). */
  :is(#modal-parametres,.acv-tarifs) .acv-univ{display:flex;flex-wrap:wrap;gap:6px;padding:10px 18px 2px;background:var(--surface);flex-shrink:0}
  :is(#modal-parametres,.acv-tarifs) .acv-univ[hidden]{display:none}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b{--u:var(--muted);display:inline-flex;align-items:center;gap:7px;padding:5px 12px;border:1px solid color-mix(in srgb,var(--u) 28%,var(--line));border-radius:999px;background:var(--surface);color:var(--u);font:inherit;font-size:.74rem;font-weight:700;cursor:pointer;transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out)}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-conjointe{--u:#1a5c8a}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-adjointe{--u:#c2185b}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-implant{--u:#6a1b9a}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-conjointe{--u:#7fb3d8}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-adjointe{--u:#f48fb1}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-implant{--u:#ce93d8}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b:hover{background:color-mix(in srgb,var(--u) 8%,var(--surface))}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-on{background:color-mix(in srgb,var(--u) 15%,var(--surface));border-color:var(--u)}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-neutre.is-on{color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
  /* Nom officiel + références CCAM en petit gris dessous */
  /* Largeurs : l'alias et les libellés se lisent en entier (le nom officiel,
     lui, passe à la ligne dans sa colonne). */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles th:nth-child(5),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(5){min-width:130px}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles th:nth-child(6),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(6),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles th:nth-child(7),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(7){min-width:140px}
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles td:nth-child(2){min-width:190px}
  :is(#modal-parametres,.acv-tarifs) .acv-ref{display:block;margin-top:1px;font-family:'DM Mono',monospace;font-size:.62rem;color:var(--muted);letter-spacing:.2px}
  /* Code à la couleur de son univers (Illan : « le code en rose quand c'est
     amovible, violet quand c'est implant ») */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-adjointe .acv-code{color:var(--acte-adj-fg);background:color-mix(in srgb,var(--acte-adj-fg) 9%,var(--surface));border-color:color-mix(in srgb,var(--acte-adj-fg) 28%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-implant .acv-code{color:var(--acte-imp-fg);background:color-mix(in srgb,var(--acte-imp-fg) 9%,var(--surface));border-color:color-mix(in srgb,var(--acte-imp-fg) 28%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-neutre .acv-code{color:var(--muted);background:var(--surface-2);border-color:var(--line)}
  /* « Commandé par » : les pastilles du résumé IA, empilées */
  :is(#modal-parametres,.acv-tarifs) .acv-cmd{display:flex;flex-direction:column;align-items:flex-start;gap:3px}
  /* « Commandé par » = le MOYEN (25/09/2026) : objet illustré + mot, sobre ; seule
     l'absence de moyen (« Rien sur la fiche ») se voit en couleur d'alerte. */
  :is(#modal-parametres,.acv-tarifs) .acv-moyen{display:inline-flex;align-items:center;gap:6px;font-size:.74rem;font-weight:600;color:var(--text);white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .acv-moyen .ilx{width:18px;height:18px;flex:none}
  :is(#modal-parametres,.acv-tarifs) .acv-moyen.is-rien{color:var(--danger)}
  /* Noms factorisés (25/09/2026) : un titre de groupe discret, puis les lignes en
     retrait qui ne portent que ce qui les distingue. Un retrait par étage. */
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe td{padding-top:7px;padding-bottom:2px;border-bottom:0}
  :is(#modal-parametres,.acv-tarifs) .acv-groupe-nom{font-size:.74rem;font-weight:700;color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe .acv-ref{display:inline;margin-left:8px}
  /* Un code, puis « +N » qui déroule la liste complète (25/09/2026). */
  :is(#modal-parametres,.acv-tarifs) .acv-ref-plus{display:inline-flex;align-items:center;gap:5px;padding:0;border:0;background:none;cursor:pointer;text-align:left}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-plus:hover{color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-plus:focus-visible{outline:2px solid var(--teal);outline-offset:1px;border-radius:3px}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-n{padding:0 5px;border-radius:999px;font-size:.58rem;font-weight:700;background:color-mix(in srgb,var(--muted) 16%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-plus[aria-expanded="true"] .acv-ref-n{background:color-mix(in srgb,var(--teal) 22%,transparent);color:var(--text)}
  /* Sous le nom, sur sa propre ligne (Illan : « le code chevauche le nom ») ; seuls
     les titres de groupe le gardent à côté (règle tr.acv-groupe plus bas). */
  :is(#modal-parametres,.acv-tarifs) .acv-refs{display:block;margin-top:1px}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-tout{display:block;max-width:240px;white-space:normal}
  :is(#modal-parametres,.acv-tarifs) .acv-ref-tout[hidden]{display:none}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe .acv-refs{display:inline-flex;flex-direction:column;margin-left:8px;vertical-align:middle}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe .acv-refs .acv-ref{margin-left:0}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe.acv-niv1 .acv-groupe-nom{padding-left:14px}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe.acv-niv2 .acv-groupe-nom{padding-left:28px}
  :is(#modal-parametres,.acv-tarifs) tr.acv-groupe.acv-niv3 .acv-groupe-nom{padding-left:42px}
  /* Case « Remplir le groupe… » d'un titre : un raccourci, pas un alias — bord pointillé. */
  #modal-parametres .ais-act.acv-pil-groupe{border-style:dashed;background:transparent}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-name.acv-niv1{padding-left:14px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-name.acv-niv2{padding-left:28px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-name.acv-niv3{padding-left:42px}
  :is(#modal-parametres,.acv-tarifs) .acv-case{display:block;padding:1px 4px;margin-left:-4px;border:0;background:none;font:inherit;cursor:pointer;border-radius:6px;transition:background var(--dur-fast) var(--ease-out)}
  :is(#modal-parametres,.acv-tarifs) .acv-case:hover{background:color-mix(in srgb,var(--accent) 10%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .acv-case:focus-visible{outline:2px solid var(--teal);outline-offset:1px}
  :is(#modal-parametres,.acv-tarifs) .acv-src{display:inline-block;padding:2px 8px;border-radius:999px;font-size:.66rem;font-weight:600;white-space:nowrap;border:1px solid var(--line);background:var(--surface-2);color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .acv-src--bouton{color:var(--text);border-color:color-mix(in srgb,var(--accent) 35%,var(--line));background:color-mix(in srgb,var(--accent) 8%,var(--surface))}
  :is(#modal-parametres,.acv-tarifs) .acv-src--fab{color:color-mix(in srgb,var(--warn) 70%,var(--text));border-color:color-mix(in srgb,var(--warn) 45%,var(--line));background:color-mix(in srgb,var(--warn) 10%,var(--surface))}
  /* Glisser-déposer : la poignée, la ligne en vol, la cible */
  /* Poignée discrète mais VISIBLE au repos : un labo qui ne lit pas le guide doit
     deviner qu'une ligne se glisse. */
  :is(#modal-parametres,.acv-tarifs) .acv-poignee{display:inline-block;width:10px;margin-right:4px;color:var(--muted);font-size:.7rem;letter-spacing:-2px;cursor:grab;opacity:.35;transition:opacity var(--dur-fast)}  :is(#modal-parametres,.acv-tarifs) .acv-row:hover .acv-poignee{opacity:.8}
  :is(#modal-parametres,.acv-tarifs) .acv-row.is-glisse{opacity:.35}
  :is(#modal-parametres,.acv-tarifs) .acv-row.is-cible td{box-shadow:inset 0 2px 0 var(--accent)}
  :is(#modal-parametres,.acv-tarifs) .acv-fam.is-cible td{background:color-mix(in srgb,var(--accent) 12%,var(--surface))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-retire td{opacity:.6}
  /* Labo sans nomenclature Cogilog : la colonne « Libellé facturation » n'a rien à
     lui dire (la facture prend le nom officiel) — masquée. */
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles.acv-sans-cogilog th:nth-child(6),
  :is(#modal-parametres,.acv-tarifs) .pm-actes-table.acv-articles.acv-sans-cogilog td:nth-child(6){display:none}
  /* ＋ sur chaque famille : créer un article directement à sa place */
  :is(#modal-parametres,.acv-tarifs) .acv-fam td{position:relative}
  :is(#modal-parametres,.acv-tarifs) .acv-plus{position:absolute;right:12px;top:50%;transform:translateY(-50%);width:20px;height:20px;padding:0;border:1px solid var(--line);border-radius:6px;background:var(--surface);color:var(--muted);font:inherit;font-size:.8rem;line-height:1;cursor:pointer;opacity:.55;transition:opacity var(--dur-fast),border-color var(--dur-fast),color var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .acv-fam:hover .acv-plus,:is(#modal-parametres,.acv-tarifs) .acv-plus:focus-visible{opacity:1}
  :is(#modal-parametres,.acv-tarifs) .acv-plus:hover{border-color:var(--accent);color:var(--accent-text)}
  /* Options : ce qu'elles changent à la facture */
  :is(#modal-parametres,.acv-tarifs) .acv-cible{font-size:.72rem;color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .acv-effet{font-size:.72rem;color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .acv-effet.is-code{color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .acv-effet code{font-size:.7rem;padding:0 4px;border-radius:4px;background:var(--surface-2);white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .acv-tag{display:inline-block;margin-right:6px;padding:1px 7px;border-radius:999px;font-size:.6rem;font-weight:800;letter-spacing:.3px;text-transform:uppercase;background:color-mix(in srgb,var(--accent) 14%,var(--surface));color:var(--accent-text)}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-tag{color:var(--teal-text)}
  /* Options de fabrication (27/09/2026) : une matière par ligne dans « S'applique
     à », face à son code dans « Effet » — les deux colonnes s'alignent ligne à ligne
     (même hauteur de ligne, cellules calées en haut) ; l'étiquette d'effet se pose
     à gauche de la colonne des codes, sans la décaler. */
  :is(#modal-parametres,.acv-tarifs) .acv-opt td{vertical-align:top}
  :is(#modal-parametres,.acv-tarifs) .acv-opt td:first-child .pm-acte-dot{margin-top:6px}
  :is(#modal-parametres,.acv-tarifs) .acv-lignes{display:flex;flex-direction:column;gap:2px}
  :is(#modal-parametres,.acv-tarifs) .acv-ligne{min-height:22px;line-height:22px;white-space:nowrap}
  :is(#modal-parametres,.acv-tarifs) .acv-effet.is-code{display:flex;align-items:flex-start;gap:4px}
  :is(#modal-parametres,.acv-tarifs) .acv-effet.is-code .acv-tag{flex:none;margin-top:3px}
  :is(#modal-parametres,.acv-tarifs) .acv-fl{color:var(--muted);padding:0 2px}
  :is(#modal-parametres,.acv-tarifs) .acv-effet code[title]{cursor:help}
  /* Petit panneau ancré à la pastille d'une case : changer le code qu'elle facture */
  .acv-pop{position:fixed;z-index:1100;width:260px;padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--surface);color:var(--text);box-shadow:var(--shadow-md);font-size:.74rem}
  .acv-pop-t{font-weight:700;margin-bottom:6px}
  .acv-pop-row{display:flex;gap:6px;align-items:center}
  .acv-pop-row .pm-acte-input{flex:1}
  .acv-pop-aide{margin-top:6px;font-size:.66rem;color:var(--muted)}
  /* Pastille « photo de consigne » : la VIGNETTE plutôt qu'une icône — on
     reconnaît la photo qui partira sans rien ouvrir. Cliquable (elle mène à la
     photothèque), donc curseur pointer et non `help` comme ses sœurs. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-photo{display:inline-flex;align-items:center;gap:4px;padding:1px 6px 1px 2px;cursor:pointer;vertical-align:middle}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-photo img{width:18px;height:18px;border-radius:4px;object-fit:cover;display:block;background:var(--surface-2)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-photo:hover{background:color-mix(in srgb,var(--accent) 22%,var(--surface))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-photo:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-chevron{background:none;border:none;cursor:pointer;padding:0 6px 0 0;font-size:.7rem;color:var(--muted);transition:color var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-chevron:hover{color:var(--accent-text)}

  /* Sous-ligne combo */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-subrow td{padding:3px 12px;border-bottom:1px solid color-mix(in srgb,var(--line) 45%,transparent);background:color-mix(in srgb,var(--accent) 4%,var(--surface));font-size:.72rem;color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-subrow td:first-child{position:relative;padding-left:16px;text-align:center;color:var(--muted)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-subrow em{font-style:italic;color:var(--muted)}

  /* Suppression */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-del{background:none;border:none;cursor:pointer;font-size:.9rem;line-height:1;color:var(--muted);opacity:.5;transition:opacity var(--dur-fast),color var(--dur-fast)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-del:hover{opacity:1;color:var(--danger)}

  /* Accessibilité : on coupe toute l'animation si l'utilisateur le demande */
  @media (prefers-reduced-motion: reduce){
    :is(#modal-parametres,.acv-tarifs) .pm-actes-btn--primary::after,
    :is(#modal-parametres,.acv-tarifs) .pm-actes-table tbody,
    :is(#modal-parametres,.acv-tarifs) .pm-acte-dot.is-ok,
    :is(#modal-parametres,.acv-tarifs) .pm-acte-band-dot,
    :is(#modal-parametres,.acv-tarifs) .pm-acte-input.pm-cell-saved{animation:none}
  }

  /* Colonne Famille (catalogue, brique 3) — dark-native, PAS de color-scheme:light */
  /* Spécificité ID + !important : la règle générique « selects dans toutes les
     modales » (html[data-theme="dark"] #modal-parametres select, plus haut)
     écraserait sinon nos teintes de classe. */
  .pm-fam-vide{color:var(--muted);font-size:.7rem}

  /* ── Modale Gérer les familles (.cfm-*, brique 3) ── */
  .cfm-overlay{position:fixed;inset:0;background:rgba(12,39,64,.5);backdrop-filter:var(--ov-blur, blur(4px));z-index:2600;display:flex;align-items:center;justify-content:center}
  .cfm-box{background:var(--surface);border-radius:14px;box-shadow:var(--shadow-lg,0 12px 40px rgba(0,0,0,.25));width:min(560px,92vw);max-height:82vh;display:flex;flex-direction:column;overflow:hidden}
  .cfm-head{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;font-weight:700;color:var(--text);border-bottom:1px solid var(--line)}
  .cfm-close{border:none;background:none;font-size:1.3rem;cursor:pointer;color:var(--muted)}
  .cfm-body{overflow-y:auto;padding:10px 14px;flex:1}
  .cfm-foot{display:flex;align-items:center;gap:12px;padding:8px 16px;font-size:.72rem;color:var(--muted);border-top:1px solid var(--line)}
  .cfm-foot > span{flex:1;min-width:0}
  /* Retour au patron : geste rare et lourd de conséquences → discret, jamais en
     avant, mais reconnaissable au survol. */
  .cfm-reset{flex:none;border:1px solid var(--line);background:var(--surface);border-radius:8px;padding:5px 10px;font-size:.72rem;font-family:inherit;color:var(--muted);cursor:pointer;white-space:nowrap;transition:color .15s ease,border-color .15s ease}
  .cfm-reset:hover{color:var(--gc-alert,#c62828);border-color:currentColor}
  html[data-theme="dark"] .cfm-reset:hover{color:#ef6b6b}
  @media (prefers-reduced-motion: reduce){ .cfm-reset{transition:none} }
  /* Bandeau d'univers : le nom prend la place, les actions restent à droite à
     une position stable d'un univers à l'autre (pas de bouton qui saute). */

  /* ══════════════════════════════════════════════════════════════════
     TEINTE « IMPLANT » = VIOLET — sur TOUTES les surfaces d'un coup.
     L'app peint déjà l'implant en violet partout (résumé IA .ais-*.imp,
     schéma dentaire, bons de livraison) ; seul le catalogue l'ignorait et
     rendait l'univers Implants en bleu conjointe. On reprend exactement les
     violets du résumé IA — clair #6a1b9a sur #f3e5f5, nuit #ce93d8 sur
     #2e1e3a — pour que ce soit LE même violet, pas un violet voisin.
     Chaque bloc reproduit la forme de son voisin .is-adjointe : si une
     surface change de recette, la ligne implant se corrige au même endroit.
     ══════════════════════════════════════════════════════════════════ */
  /* (Le filtre « acte » de la liste prend le violet par sa variable --pf-tint,
     posée sur le bloc d'univers — cf. section .pf-acte-* plus haut.) */
  /* Grille de tarifs (bandeaux univers + sous-titres famille) */
  .gc-tarif-univ.is-implant td, .gc-tarif-grpcat.is-implant td {
    background: #f3e5f5; color: #6a1b9a; border-top-color: #ce93d8; border-bottom-color: #ce93d8; }
  html[data-theme="dark"] .gc-tarif-univ.is-implant td,
  html[data-theme="dark"] .gc-tarif-grpcat.is-implant td {
    background: #2e1e3a; color: #ce93d8; border-top-color: #7a4a9a; border-bottom-color: #7a4a9a; }
  /* Paramètres › Actes & codes (liseré de ligne, bandeaux, sélecteur de famille) */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-implant td:first-child::before{background:#6a1b9a}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-implant td{background:color-mix(in srgb,#6a1b9a 13%,var(--surface));color:#6a1b9a}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-implant td{color:#ce93d8}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-implant td{color:color-mix(in srgb,#6a1b9a 72%,var(--muted))}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.is-implant td{color:#c9a3d8}
  /* Titre de FAMILLE dans Actes & codes (Illan, 25/09/2026 : « l'item principal en
     beaucoup plus grand et stylé, on doit tout de suite voir de quoi on parle ») :
     grand, en couleur métier, liseré à gauche, casse normale. */
  /* Bandeaux d'UNIVERS plus affirmés (Illan, 25/09/2026, sur « Orthodontie » : « il
     est presque invisible ») : plus grands que les titres de famille ne l'étaient,
     et l'univers gris (Études, Orthodontie) en ardoise franche au lieu du gris pâle. */
  /* Le titre d'UNIVERS est le plus gros niveau de l'écran (Illan : « c'est le
     titre principal d'une grosse catégorie ») — au-dessus des titres de famille. */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ td{padding:15px 16px 13px;font-size:1.2rem;letter-spacing:1px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ .pm-acte-band-dot{width:9px;height:9px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ .pm-acte-band-n{font-size:.72rem;vertical-align:3px}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-neutre td{background:color-mix(in srgb,#475569 15%,var(--surface));color:#334155}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-neutre td{background:color-mix(in srgb,#94a3b8 18%,var(--surface));color:#dbe4ee}
  /* ── INDIGO (Études & conception) et NEUTRE FONCÉ (Orthodontie) — 25/09/2026,
     Illan : « indigo pour Études et conception », « ortho, fais un gris bien foncé
     et visible ». Tous les écrans qui colorent un univers. ── */
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-indigo td{background:color-mix(in srgb,#4338ca 13%,var(--surface));color:#3730a3}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.is-indigo td{background:color-mix(in srgb,#818cf8 18%,var(--surface));color:#c7d2fe}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-indigo td:first-child::before{background:#4338ca}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-neutre td:first-child::before{background:#475569}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-indigo .acv-code{color:#3730a3;background:color-mix(in srgb,#4338ca 9%,var(--surface));border-color:color-mix(in srgb,#4338ca 25%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-neutre .acv-code{color:#334155}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-indigo .acv-code{color:#a5b4fc}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-row.is-neutre .acv-code{color:#cbd5e1}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-indigo{--fam:#3730a3}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-neutre{--fam:#334155}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-indigo{--fam:#a5b4fc}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-neutre{--fam:#cbd5e1}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-indigo{--u:#4338ca}
  :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-neutre{--u:#334155}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-indigo{--u:#a5b4fc}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .acv-univ-b.is-neutre{--u:#cbd5e1}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.ind{border-color:color-mix(in srgb,#4338ca 30%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.ind .pm-acte-input{color:#3730a3}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.ind .pm-acte-input{color:#a5b4fc}
  .pf-acte-univ-bloc.is-indigo { --pf-tint: #4338ca; }
  .pf-acte-univ-bloc.is-neutre { --pf-tint: #334155; }
  html[data-theme="dark"] .pf-acte-univ-bloc.is-indigo { --pf-tint: #a5b4fc; }
  html[data-theme="dark"] .pf-acte-univ-bloc.is-neutre { --pf-tint: #cbd5e1; }
  .gc-tarif-univ.is-indigo td, .gc-tarif-grpcat.is-indigo td { background: #e7eaf6; color: #3730a3; }
  html[data-theme="dark"] .gc-tarif-univ.is-indigo td, html[data-theme="dark"] .gc-tarif-grpcat.is-indigo td { background: #1e2146; color: #a5b4fc; }
  /* Fenêtre « Articles annexes » : la carte de l'univers indigo. */
  .sec-ind .rail { background: #4338ca; }
  .sec-ind .sec-title { color: #3730a3; border-color: color-mix(in srgb, #4338ca 42%, var(--surface)); }
  .sec-ind .ord-ck input:checked + .bx { background: #4338ca; }
  .sec-ind .ord-ck:has(input:checked) { background: color-mix(in srgb, #4338ca 14%, var(--surface)); border-left-color: #4338ca; }
  .sec-ind .anx-jaw-b { color: #4338ca; }
  html[data-theme="dark"] .sec-ind .sec-title { color: #a5b4fc; }
  /* Résumé IA : un article annexe d'Études en indigo. */
  .ais-act.anx.anxc-ind { border-color:#c7ccf0; }
  .ais-act.anx.anxc-ind .ais-n { color:#3730a3; }
  .ais-act.anx.anxc-ind .ais-d { background:#e7eaf6; color:#3730a3; }
  html[data-theme="dark"] .ais-act.anx.anxc-ind { border-color:#2e3470; }
  html[data-theme="dark"] .ais-act.anx.anxc-ind .ais-n { color:#a5b4fc; }
  html[data-theme="dark"] .ais-act.anx.anxc-ind .ais-d { background:#1e2146; color:#a5b4fc; }
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam{--fam:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-conjointe{--fam:#1a5c8a}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-adjointe{--fam:#c2185b}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-implant{--fam:#6a1b9a}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-conjointe{--fam:#8fc0e6}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-adjointe{--fam:#f19dbc}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.is-implant{--fam:#d4a8e6}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam td{padding:14px 44px 9px 16px;font-size:1.02rem;font-weight:800;letter-spacing:0;text-transform:none;color:var(--fam);background:color-mix(in srgb,var(--fam) 7%,var(--surface));box-shadow:inset 4px 0 0 var(--fam);border-top:1px solid color-mix(in srgb,var(--fam) 14%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam .pm-acte-band-n{font-size:.68rem;vertical-align:2px;background:color-mix(in srgb,var(--fam) 14%,var(--surface));color:var(--fam)}
  :is(#modal-parametres,.acv-tarifs) .acv-groupe-nom{font-size:.82rem}
  /* Alias et traduction EN = la pastille d'acte du résumé IA (.ais-act, style.css
     l. ~2022), éditable : le champ perd son cadre et prend la largeur de son texte. */
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil{padding:3px 9px;max-width:100%;cursor:text}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil:focus-within{box-shadow:0 0 0 2px color-mix(in srgb,var(--teal) 40%,transparent)}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil .pm-acte-input{border:0;background:transparent;padding:0;height:auto;min-width:6ch;max-width:100%;width:auto;field-sizing:content;font-size:.8rem;box-shadow:none;outline:none}
  /* Nom par DÉFAUT (case vide) : pâle et en italique — il se confondait avec un alias tapé (Illan, 29/09/2026). */
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil .pm-acte-input::placeholder{color:inherit;opacity:.5;font-style:italic;font-weight:500}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil .pm-acte-input{color:var(--text)}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.imp .pm-acte-input{color:#6a1b9a}
  /* Couleur de la catégorie (25/09/2026) : bleu fixe, violet implant, rose amovible. */
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.conj{border-color:color-mix(in srgb,#1a5c8a 30%,var(--line))}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.conj .pm-acte-input{color:#1a5c8a}
  :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.adj .pm-acte-input{color:#c2185b}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.imp .pm-acte-input{color:#ce93d8}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.conj .pm-acte-input{color:#8fc0e6}
  html[data-theme="dark"] :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.adj .pm-acte-input{color:#f19dbc}
  /* Gérer les familles */
  .cfm-arts{margin:2px 0 6px 26px;border-left:2px solid var(--line);padding-left:8px}
  /* Créer un univers = geste de premier niveau : détaché des « + famille ». */

  /* ── Modale ＋ Nouvel article (.artc-*, brique 4) — hérite de .cfm-overlay/.cfm-box ── */
  .artc-box{width:420px;max-width:92vw;animation:anatPop var(--dur-base) var(--ease-out)}
  .artc-lbl{display:block;font-size:.72rem;font-weight:600;color:var(--muted);margin:0 0 12px}
  .artc-in{display:block;width:100%;margin-top:4px;padding:8px 10px;font-size:.8rem;font-family:inherit;
    border:1px solid var(--border);border-radius:9px;background:var(--surface);color:var(--text);
    transition:border-color var(--dur-fast), box-shadow var(--dur-fast)}
  .artc-in:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent)}
  .artc-in:disabled{opacity:.55;cursor:not-allowed}
  .artc-hint{display:block;margin-top:4px;font-size:.66rem;color:var(--muted);font-weight:400;line-height:1.35}
  /* Aperçu « où va atterrir mon article » sous le choix de la famille. */
  .artc-apercu{margin:-4px 0 10px;padding:8px 10px;border:1px dashed var(--line);border-radius:9px;background:var(--surface-2)}
  .artc-ap-chem{font-size:.68rem;color:var(--muted);margin-bottom:6px}
  .artc-ap-chem b{color:var(--text)}
  .artc-ap-liste{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
  .artc-ap-art{font-size:.68rem;padding:2px 8px;border-radius:999px;background:var(--surface);border:1px solid var(--line);color:var(--muted);white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis}
  .artc-ap-art.is-moi{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:700}
  .artc-ap-vide{font-size:.68rem;color:var(--muted);font-style:italic}
  /* Ranger un acte depuis la grille de tarif */
  .cra-box{max-width:460px}
  .cra-actuel{font-size:.76rem;color:var(--muted);margin-bottom:10px}
  .cra-actuel b{color:var(--text)}
  .cra-hint{margin-top:8px;font-size:.68rem;color:var(--muted);line-height:1.4}
  /* Archivage d'un acte : bloc à part, sous une ligne de séparation — c'est la
     seule action de cette boîte qui change ce que le dentiste reçoit. */
  .cra-tag-arch{margin-left:8px;padding:1px 8px;border-radius:999px;font-size:.62rem;font-weight:800;
    letter-spacing:.4px;text-transform:uppercase;background:color-mix(in srgb, var(--warn) 16%, var(--surface));
    color:var(--warn);border:1px solid color-mix(in srgb, var(--warn) 32%, transparent)}
  .cra-arch{display:flex;align-items:center;gap:12px;margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
  .cra-arch-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .cra-arch-txt b{font-size:.76rem;color:var(--text)}
  .cra-arch-txt span{font-size:.66rem;color:var(--muted);line-height:1.4}
  .cra-arch-btn{flex:none;padding:7px 14px;border-radius:9px;cursor:pointer;font-family:inherit;
    font-size:.76rem;font-weight:700;color:var(--text);background:var(--surface);border:1px solid var(--border);
    transition:border-color var(--dur-fast), background var(--dur-fast), color var(--dur-fast)}
  .cra-arch-btn:hover{border-color:var(--warn);color:var(--warn);
    background:color-mix(in srgb, var(--warn) 10%, var(--surface))}
  .cra-arch-btn.is-on{border-color:var(--accent);color:var(--accent-text)}
  .cra-arch-btn.is-on:hover{background:color-mix(in srgb, var(--accent) 12%, var(--surface));color:var(--accent-text)}
  .cra-arch-btn:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
  .cra-arch-btn:disabled{opacity:.6;cursor:not-allowed}
  @media (prefers-reduced-motion: reduce){ .cra-arch-btn{transition:none} }
  /* Bouton « ranger » d'une ligne de tarif. Volontairement discret : révélé au
     survol de sa ligne (la grille en affiche plus de cent — pas de bruit
     permanent), mais focusable au clavier, où il se montre. Classe globale
     assumée : la même ligne est rendue dans deux modales (#modal-tarifs et
     #popup-gc-grilles) par la même fonction. */
  /* Étiquette « archivé » d'une ligne de tarif : l'acte garde son prix et reste
     facturable, il ne part simplement plus sur le PDF du cabinet. Ambre (un
     choix du labo), jamais rouge (ce n'est pas une anomalie). Classe globale
     comme .gc-tarif-ranger : la même ligne est rendue dans deux modales. */
  .gc-tarif-arch{margin-left:7px;padding:1px 7px;border-radius:999px;font-size:.6rem;font-weight:800;
    letter-spacing:.4px;text-transform:uppercase;vertical-align:middle;white-space:nowrap;
    background:color-mix(in srgb, var(--warn) 15%, var(--surface));color:var(--warn);
    border:1px solid color-mix(in srgb, var(--warn) 30%, transparent)}
  .gc-tarif-trow.is-archive .gc-tarif-td-acte{color:var(--muted);font-weight:500}
  .gc-tarif-ranger{margin-left:6px;padding:0 3px;border:none;background:none;border-radius:5px;cursor:pointer;font-size:.78rem;line-height:1;opacity:0;pointer-events:none;transition:opacity .12s ease}
  .gc-tarif-trow:hover .gc-tarif-ranger{opacity:.6;pointer-events:auto}
  .gc-tarif-ranger:hover{opacity:1;background:var(--surface-2)}
  .gc-tarif-ranger:focus-visible{opacity:1;pointer-events:auto;outline:2px solid var(--teal);outline-offset:1px}
  @media (prefers-reduced-motion: reduce){ .gc-tarif-ranger{transition:none} }
  /* Pose = contrôle segmenté : le choix actif s'allume dans l'accent */
  .artc-radios{display:flex;gap:6px;margin-top:4px;font-size:.78rem;color:var(--text)}
  .artc-radios label{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;cursor:pointer;
    font-weight:600;padding:7px 10px;border:1px solid var(--border);border-radius:9px;background:var(--surface);
    color:var(--muted);transition:transform var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast)}
  .artc-radios label:hover{transform:translateY(-1px);color:var(--text);border-color:color-mix(in srgb, var(--accent) 40%, var(--border))}
  .artc-radios label:has(input:checked){color:var(--accent-text);border-color:var(--accent);
    background:color-mix(in srgb, var(--accent) 13%, var(--surface));box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 24%, transparent)}
  .artc-radios input{accent-color:var(--accent);margin:0}
  .artc-chk{display:flex;align-items:center;gap:8px;font-size:.76rem;color:var(--text);margin:2px 0 12px;cursor:pointer;
    padding:8px 10px;border:1px solid var(--border);border-radius:9px;background:var(--surface);transition:border-color var(--dur-fast), background var(--dur-fast)}
  .artc-chk:hover{border-color:color-mix(in srgb, var(--accent) 40%, var(--border))}
  .artc-chk:has(input:checked){background:color-mix(in srgb, var(--accent) 7%, var(--surface));border-color:color-mix(in srgb, var(--accent) 30%, var(--border))}
  .artc-chk input{accent-color:var(--accent);margin:0}
  .artc-foot{display:flex;align-items:center;justify-content:space-between;gap:10px}
  .artc-btn-ok{padding:8px 16px;border:none;border-radius:9px;background:var(--accent);color:#fff;
    font-weight:700;font-size:.78rem;cursor:pointer;font-family:inherit;transition:transform var(--dur-fast), filter var(--dur-fast), box-shadow var(--dur-fast)}
  .artc-btn-ok:hover{filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 8px 20px -8px color-mix(in srgb, var(--accent) 70%, transparent)}
  .artc-btn-ok:active{transform:translateY(0)}
  /* Sélecteur de nature dans la fiche article */
  .artc-nature-row{display:flex;gap:8px;align-items:center;margin-top:4px}
  .artc-nature-row .artc-in{flex:1;margin-top:0}
  .artc-nature-manage{border:1px dashed var(--accent);background:transparent;color:var(--accent-text);
    border-radius:9px;padding:8px 12px;cursor:pointer;font:inherit;font-size:.76rem;white-space:nowrap;font-weight:600;
    transition:transform var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast)}
  .artc-nature-manage:hover{background:color-mix(in srgb, var(--accent) 10%, transparent);transform:translateY(-1px);
    box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent)}
  .artc-hint-inline{color:var(--muted);font-weight:400;font-size:.68rem}

  /* ── Gestionnaire de natures (.anat-*) — hérite de .cfm-overlay/.cfm-box ── */
  .anat-box{width:min(580px,94vw)}
  .anat-body{display:flex;flex-direction:column;gap:8px;max-height:60vh;overflow-y:auto;padding:14px 16px}
  .anat-row{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--border);
    border-radius:12px;background:var(--surface);flex-wrap:wrap;
    transition:transform var(--dur-fast), border-color var(--dur-fast), box-shadow var(--dur-fast)}
  .anat-row:hover{transform:translateY(-1px);border-color:color-mix(in srgb, var(--accent) 32%, var(--border));
    box-shadow:0 6px 18px -10px color-mix(in srgb, var(--accent) 45%, transparent)}
  .anat-name{flex:1 1 150px;min-width:110px;padding:7px 10px;border:1px solid var(--border);
    border-radius:9px;background:var(--surface);color:var(--text);font:inherit;font-size:.8rem;transition:border-color var(--dur-fast), box-shadow var(--dur-fast)}
  .anat-name:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent)}
  /* Puces « capacité » : chaque trait d'une nature s'allume dans l'accent du labo */
  .anat-chk{display:inline-flex;align-items:center;gap:6px;font-size:.76rem;font-weight:600;color:var(--muted);
    white-space:nowrap;cursor:pointer;padding:4px 10px;border:1px solid var(--border);border-radius:999px;
    background:var(--surface);transition:transform var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast)}
  .anat-chk:hover{transform:translateY(-1px);color:var(--text);border-color:color-mix(in srgb, var(--accent) 40%, var(--border))}
  .anat-chk input[type="checkbox"]{accent-color:var(--accent);width:13px;height:13px;margin:0;cursor:pointer}
  .anat-chk:has(input:checked){color:var(--accent-text);border-color:var(--accent);
    background:color-mix(in srgb, var(--accent) 13%, var(--surface));
    box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 24%, transparent)}
  .anat-row .anat-qty{flex:0 0 66px;width:66px;padding:5px 7px;border:1px solid var(--border);border-radius:8px;
    background:var(--surface);color:var(--text);font:inherit;font-size:.78rem}
  .anat-del{border:1px solid var(--border);background:var(--surface);border-radius:8px;cursor:pointer;
    padding:5px 9px;color:var(--muted);line-height:1}
  .anat-del:hover{color:var(--danger);border-color:var(--danger)}
  .anat-foot{display:flex;align-items:center;justify-content:space-between;gap:10px}
  .anat-add{border:1px dashed var(--accent);background:transparent;color:var(--accent-text);
    border-radius:8px;padding:7px 13px;cursor:pointer;font:inherit;font-size:.78rem;font-weight:600;
    transition:transform var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast)}
  .anat-add:hover{background:color-mix(in srgb, var(--accent) 10%, transparent);transform:translateY(-1px);
    box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent)}
  .anat-empty{color:var(--muted);font-size:.85rem;padding:18px;text-align:center}
  html[data-theme="dark"] .anat-row{background:var(--surface-2)}

  /* Apparitions douces (natures / popup articles / bulle) + garde-fou reduced-motion */
  @keyframes anatPop{from{opacity:0;transform:translateY(8px) scale(.985)}to{opacity:1;transform:none}}
  .anat-box{animation:anatPop var(--dur-base) var(--ease-out)}
  .acte-popup{animation:anatPop var(--dur-fast) var(--ease-out)}
  /* Sorties DÉDIÉES (Règle 25) : ces bulles portent leur propre animation d'entrée
     → la règle générique .is-closing perdrait la cascade. Fermées via motionClose. */
  .acte-popup.is-closing{animation:ilsFadeOut var(--dur-exit) var(--ease-out) both}
  .anx-pop.is-closing{animation:ilsFadeOut var(--dur-exit) var(--ease-out) both}
  /* Posée SUR la prescription (25/09/2026) : sa taille est celle du formulaire,
     calculée en JS (_anxPlacerSur) ; le contenu défile dedans. */
  #annexes-popup.anx-pop.is-ancre{position:absolute;z-index:40;max-width:none;max-height:none;overflow:visible;border-radius:12px;box-sizing:border-box}
  #annexes-popup.anx-pop.is-ancre .anx-cols{overflow:visible}
  /* Colonnes plus étroites sur la prescription : un titre long (« Options de
     fabrication », « Gouttières & orthèses ») ne déborde plus de sa carte. */
  #annexes-popup .sec-title{width:fit-content;max-width:100%;box-sizing:border-box;padding:4px 10px;letter-spacing:.08em;white-space:normal;text-align:center;line-height:1.25}
  @media (prefers-reduced-motion: reduce){
    .anat-box, .artc-box, .acte-popup,
    #annexes-popup.anx-pop, .anx-detail{animation:none}
    .anat-row, .anat-chk, .anat-add,
    .artc-in, .artc-radios label, .artc-chk, .artc-btn-ok, .artc-nature-manage,
    .anx-jaw-b{transition:none}
    .anat-row:hover, .anat-chk:hover, .anat-add:hover,
    .artc-radios label:hover, .artc-btn-ok:hover, .artc-nature-manage:hover,
    .anx-jaw-b:hover{transform:none}
  }

  /* ── Gestion livraisons : masquage de base de l'overlay ──
     Le markup #modal-decalage.dc-overlay est en dur dans index.html, mais ses
     styles (.dc-*) sont injectés par js/decalage-ui-styles.js qui est LAZY
     (chargé au 1er clic via lazy-modules.js). Sans cette règle statique,
     l'overlay s'afficherait brut au chargement de page tant que le bundle
     n'est pas chargé. La règle .dc-overlay.dc-open (2 classes, dans le bundle)
     reste prioritaire à l'ouverture. */
  .dc-overlay { display: none; }

  /* ═══════════════════════════════════════════════════════════════════
     MODE NUIT — compléments NON couverts ailleurs : Coursier (.dccour-*),
     popups Historique/Répartition (inline), modale Digilab et modale
     Comptes dentistes (.gccd-*).
     NB : les surfaces .dc-* / .ds-* / .pd-* (Gestion livraisons) sont déjà
     traitées dans js/decalage-ui-styles.js (fin de la template CSS) → NE PAS
     les redupliquer ici (Règle 11 : dark des classes injectées = dans leur
     fichier). Un sélecteur html[data-theme="dark"] .X (0,2,1) bat la base .X.
     Les styles INLINE (popups, Digilab) exigent !important.
     Palette : card #242938 · fond #1a1f2e · bord #3a4055 · texte #e0e6ed ·
     muted #8899aa · teal #5bc4c0.
     ═══════════════════════════════════════════════════════════════════ */

  /* ---- B. Panneau Coursier (.dccour-*) ---- */
  html[data-theme="dark"] .dccour { color: #e0e6ed; }
  html[data-theme="dark"] .dccour-card { background: #242938; border-color: #3a4055; }
  html[data-theme="dark"] .dccour-card h3 { color: #e0e6ed; }
  html[data-theme="dark"] .dccour-seg button { background: #242938; border-color: #3a4055; color: #8899aa; }
  html[data-theme="dark"] .dccour-seg .dccour-seg-action { background: #1e2a38; color: #5bc4c0; border-color: #2a4d6a; }
  html[data-theme="dark"] .dccour-seg .dccour-seg-action:hover { background: #243245; }
  html[data-theme="dark"] .dccour-field label { color: #8899aa; }
  html[data-theme="dark"] .dccour-field input,
  html[data-theme="dark"] .dccour-field select,
  html[data-theme="dark"] .dccour-search { background: #1a1f2e; border-color: #3a4055; color: #e0e6ed; }
  html[data-theme="dark"] .dccour-toggle { border-color: #3a4055; }
  html[data-theme="dark"] .dccour-toggle button { background: #242938; color: #8899aa; }
  html[data-theme="dark"] .dccour-btn.ghost { background: #242938; color: #5bc4c0; border-color: #3a4055; }
  html[data-theme="dark"] .dccour-btn.danger { background: #242938; color: #ef9a9a; border-color: #6a3030; }
  html[data-theme="dark"] .dccour-footer { border-top-color: #3a4055; }
  html[data-theme="dark"] .dccour-result.ok { background: #16302a; border-color: #2e5e4a; color: #81c784; }
  html[data-theme="dark"] .dccour-result.err { background: #3a1a1a; border-color: #6a3030; color: #ef9a9a; }
  html[data-theme="dark"] .dccour-result.info { background: #242938; border-color: #3a4055; color: #b8c4d0; }
  html[data-theme="dark"] .dccour-chip { background: #242938; border-color: #3a4055; color: #c0c8d0; }
  html[data-theme="dark"] .dccour-chip.on { background: #4a5562; border-color: #5a6570; color: #fff; }
  html[data-theme="dark"] .dccour-chips-lbl { color: #8899aa; }
  html[data-theme="dark"] .dccour-col h4 { color: #8899aa; }
  html[data-theme="dark"] .dccour-item { background: #1e2434; border-color: #3a4055; }
  html[data-theme="dark"] .dccour-item .meta { color: #8899aa; }
  html[data-theme="dark"] .dccour-item.has-cases { background: #16302a; border-color: #2e6e5a; }
  html[data-theme="dark"] .dccour-mini { background: #242938; border-color: #3a4055; color: #b0bcc8; }
  html[data-theme="dark"] .dccour-mini:hover { background: #2a3142; }
  html[data-theme="dark"] .dccour-empty,
  html[data-theme="dark"] .dccour-help { color: #8899aa; }
  html[data-theme="dark"] .dccour-course { border-color: #3a4055; }
  /* Suivi live : badges statut lisibles en nuit (le stepper/ETA utilisent déjà des tokens) */
  html[data-theme="dark"] .dccour-st.is-done { color: #81c784; }
  html[data-theme="dark"] .dccour-st.is-cancel { color: #ef9a9a; }
  html[data-theme="dark"] .dccour-st.is-progress,
  html[data-theme="dark"] .dccour-st.is-delivering { color: #ffb74d; }
  html[data-theme="dark"] .dccour-course--live { background: color-mix(in srgb, var(--accent, #1a5c8a) 12%, #242938); }

  /* ---- B-bis. Décalage/Coursier : derniers éléments INLINE clairs ---- */
  html[data-theme="dark"] #modal-decalage [style*="background:#fff"],
  html[data-theme="dark"] #modal-decalage [style*="background: #fff"],
  html[data-theme="dark"] #modal-decalage [style*="background:white"],
  html[data-theme="dark"] #modal-decalage [style*="background: white"] { background: #242938 !important; }
  html[data-theme="dark"] #modal-decalage [style*="background:#fbfdfe"],
  html[data-theme="dark"] #modal-decalage [style*="background:#f5f9fc"] { background: #1e2434 !important; }
  html[data-theme="dark"] #modal-decalage [style*="color:#1c2a35"],
  html[data-theme="dark"] #modal-decalage [style*="color: #1c2a35"] { color: #e0e6ed !important; }
  html[data-theme="dark"] #modal-decalage [style*="color:#6a7b88"],
  html[data-theme="dark"] #modal-decalage [style*="color:#7a8b98"],
  html[data-theme="dark"] #modal-decalage [style*="color:#5a6b78"],
  html[data-theme="dark"] #modal-decalage [style*="color:#9aa9b5"] { color: #8899aa !important; }
  html[data-theme="dark"] #modal-decalage [style*="color:#1a5c8a"] { color: #5bc4c0 !important; }
  html[data-theme="dark"] #modal-decalage [style*="color:#c0392b"] { color: #ef9a9a !important; }
  html[data-theme="dark"] #modal-decalage [style*="#e6b3ab"] { border-color: #6a3030 !important; }
  html[data-theme="dark"] #modal-decalage [style*="#cfdde7"],
  html[data-theme="dark"] #modal-decalage [style*="#e2ebf1"] { border-color: #3a4055 !important; }

  /* ---- C. Popups Historique / Répartition (markup INLINE → !important) ---- */
  html[data-theme="dark"] #br-hist-pop > div,
  html[data-theme="dark"] #br-assign-pop > div { background: #242938 !important; color: #e0e6ed !important; }
  html[data-theme="dark"] #br-hist-pop [style*="background:#fff"],
  html[data-theme="dark"] #br-assign-pop [style*="background:#fff"] { background: #2a3142 !important; }
  html[data-theme="dark"] #br-hist-pop [style*="background:#f5f9fc"],
  html[data-theme="dark"] #br-assign-pop [style*="background:#f5f9fc"] { background: #1e2434 !important; }
  html[data-theme="dark"] #br-hist-pop [style*="background:#eef4f8"],
  html[data-theme="dark"] #br-assign-pop [style*="background:#eef4f8"] { background: #1e3a4f !important; }
  html[data-theme="dark"] #br-hist-pop [style*="color:#1c2a35"],
  html[data-theme="dark"] #br-assign-pop [style*="color:#1c2a35"] { color: #e0e6ed !important; }
  html[data-theme="dark"] #br-hist-pop [style*="color:#7a8b98"],
  html[data-theme="dark"] #br-assign-pop [style*="color:#7a8b98"],
  html[data-theme="dark"] #br-hist-pop [style*="color:#7a96a8"],
  html[data-theme="dark"] #br-assign-pop [style*="color:#7a96a8"],
  html[data-theme="dark"] #br-hist-pop [style*="color:#999"],
  html[data-theme="dark"] #br-assign-pop [style*="color:#999"] { color: #8899aa !important; }
  html[data-theme="dark"] #br-hist-pop [style*="color:#1a5c8a"],
  html[data-theme="dark"] #br-assign-pop [style*="color:#1a5c8a"] { color: #5bc4c0 !important; }
  html[data-theme="dark"] #br-hist-pop [style*="#e2ebf1"],
  html[data-theme="dark"] #br-assign-pop [style*="#e2ebf1"],
  html[data-theme="dark"] #br-hist-pop [style*="#cfe1eb"],
  html[data-theme="dark"] #br-assign-pop [style*="#cfe1eb"] { border-color: #3a4055 !important; }

  /* ---- D. Modale Digilab (markup INLINE dans index.html → !important) ---- */
  html[data-theme="dark"] #modal-digilab > div:not(#dlb-detail-modal) { background: #1a1f2e !important; color: #e0e6ed !important; }
  html[data-theme="dark"] #dlb-detail-modal { color: #e0e6ed !important; }
  html[data-theme="dark"] #modal-digilab [style*="background:white"],
  html[data-theme="dark"] #modal-digilab [style*="background: white"],
  html[data-theme="dark"] #modal-digilab [style*="background:#fafbfd"],
  html[data-theme="dark"] #modal-digilab [style*="background:#fff"] { background: #242938 !important; }
  html[data-theme="dark"] #modal-digilab [style*="border-bottom:1px solid #e8e8e8"],
  html[data-theme="dark"] #modal-digilab [style*="border-bottom:1px solid #eee"],
  html[data-theme="dark"] #modal-digilab [style*="border:1px solid #e0e0e0"],
  html[data-theme="dark"] #modal-digilab [style*="1px solid #eee"],
  html[data-theme="dark"] #modal-digilab [style*="1px solid #e0e0e0"] { border-color: #3a4055 !important; }
  html[data-theme="dark"] #modal-digilab [style*="color:#888"],
  html[data-theme="dark"] #modal-digilab [style*="color: #888"],
  html[data-theme="dark"] #modal-digilab [style*="color:#666"],
  html[data-theme="dark"] #modal-digilab [style*="color: #666"] { color: #8899aa !important; }
  html[data-theme="dark"] #modal-digilab input,
  html[data-theme="dark"] #modal-digilab select { background: #1a1f2e !important; color: #e0e6ed !important; border-color: #3a4055 !important; }

  /* ---- E. Modale Comptes dentistes (.gccd-*) ---- */
  html[data-theme="dark"] .gccd-modal { background: #1a1f2e; color: #e0e6ed; }
  html[data-theme="dark"] .gccd-tools { border-bottom-color: #3a4055; }
  html[data-theme="dark"] .gccd-chip { background: #242938; border-color: #3a4055; color: #8899aa; }
  html[data-theme="dark"] .gccd-search { background: #242938; border-color: #3a4055; color: #e0e6ed; }
  html[data-theme="dark"] .gccd-row { background: #242938; border-color: #3a4055; }
  html[data-theme="dark"] .gccd-row .em { color: #8899aa; }
  html[data-theme="dark"] .gccd-b-compte { background: #16302a; color: #81c784; border-color: #2e5e4a; }
  html[data-theme="dark"] .gccd-b-invite { background: #2e2618; color: #ffb74d; border-color: #6a5520; }
  html[data-theme="dark"] .gccd-b-expire { background: #3a1a1a; color: #ef9a9a; border-color: #6a3030; }
  html[data-theme="dark"] .gccd-b-aucun { background: #242938; color: #8899aa; border-color: #3a4055; }
  html[data-theme="dark"] .gccd-act { background: #242938; border-color: #3a4055; color: #5bc4c0; }
  html[data-theme="dark"] .gccd-act.reset { background: #242938; color: #ffb74d; border-color: #6a5520; }
  html[data-theme="dark"] .gccd-act.danger { background: #242938; color: #ef9a9a; border-color: #6a3030; }

  /* ───── Modale Stock fournisseur (markup inline) en mode nuit ───── */
  /* Au labo, la coquille #modal-stock-fournisseur enveloppe toute Gestion Implants (29/09/2026) :
     ces règles ne visent que le panneau du stock, jamais les champs des autres onglets. */
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="background:white"],
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="background: white"],
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="background:#fafbfd"],
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="background:#f5f5f5"] { background: #242938 !important; }
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="1px solid #e8e8e8"],
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="1px solid #eee"],
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) [style*="2px solid #ccc"] { border-color: #3a4055 !important; }
  html[data-theme="dark"] :is(#modal-stock-fournisseur:not(.imx-stock-embed), #imp-panel-fournisseurs) input { background: #1a1f2e !important; color: #e0e6ed !important; border-color: #3a4055 !important; }
  html[data-theme="dark"] #modal-stock-title { color: #fff !important; }

  /* (Rattrapages de nuit des fenêtres « Ajouter / Modifier un fournisseur » et « Comptes
     clients » retirés le 30/09/2026 : refaites en classes .imx-fm-* à tokens,
     js/implants-ui-styles.js — audit Z3a-12.) */

  /* ───── Modale Stock fournisseur — en-tête gradient (standards UI) ─────
     ⚠️ `:not(.sfh)` — le header « cockpit » .sfh (js/implants-ui-styles.js) se teinte à la
     couleur de la MARQUE D'IMPLANT (décision Illan 22/07 : « le header doit prendre la
     couleur de la marque »). Cette règle-ci, elle, peint le dégradé du LABO et porte un
     `!important` + une spécificité (1,1,2) : sans l'exclusion elle gagnait toujours, et
     tous les headers restaient bleus quelle que soit la marque. On la laisse donc en place
     pour tout autre en-tête de cette modale, mais on lui retire le header .sfh. */
  #modal-stock-fournisseur > div > div:first-child:not(.sfh) {
    /* Dégradé de MARQUE du labo — jamais un hex ILS en dur : la modale doit suivre le
       tenant, comme .imx-seg.active / .imx-cs-add (js/implants-ui-styles.js:93/314/347).
       Ratio 60% = recette MAISON, reprise à l'identique de .gccd-head
       (js/contacts-tariffs.js:3130) et js/decalage-ui-styles.js:1585/1669 → ce bandeau
       matche enfin ses pairs. 3 arrêts (et non var(--grad), qui n'en a que 2 et
       aplatirait la rampe). L'ancien #2a7ba8 était un bleu tuné à la main, hors de la
       droite accent–teal : les EXTRÉMITÉS sont identiques au pixel, le point médian
       bouge (ΔE76 ≈ 12,7 en 60%, mesuré) — visible en A/B, c'est le prix de la
       tokenisation. Les couleurs suivent le labo jour comme nuit (--accent/--teal posés
       inline par applyTenantCSSVariables dans les 2 thèmes). `!important` OBLIGATOIRE :
       il doit battre le `background:var(--section-bg)` inline de index.html:1767. */
    background: linear-gradient(120deg, var(--accent) 0%, color-mix(in srgb, var(--accent) 60%, var(--teal)) 60%, var(--teal) 100%) !important;
    border-bottom: none !important;
  }
  #modal-stock-title { color: #fff !important; }
  #modal-stock-fournisseur > div > div:first-child:not(.sfh) button { color: rgba(255,255,255,0.85) !important; }
  #modal-stock-fournisseur > div > div:first-child:not(.sfh) button:hover { color: #fff !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   TABLEAU DE BORD — accueil modale Gestion Clients (.gcd)
   Clair + dark via variables de thème (--surface/--text/--border/--muted…).
   ═══════════════════════════════════════════════════════════════════════════ */
.gcd {
  /* Couleurs du LABO (multi-tenant) : surtout pas de bleu ILS en dur ici — cette règle
     s'applique SUR l'élément, elle battrait donc le remap tenant posé sur l'ancêtre. */
  --gcd-accent: var(--accent);
  --gcd-accent-text: var(--accent-text);
  --gcd-accent2: var(--teal);
  --gcd-track: #e8eef4;
  --gcd-card: #ffffff;
  --gcd-soft: #f6f9fc;
  color: var(--text, #2c3e50);
  font-size: 0.8rem;
  animation: gcd-in var(--dur-base) ease;
}
@keyframes gcd-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
html[data-theme="dark"] .gcd {
  --gcd-track: #2f3850;
  --gcd-card: var(--surface, #242938);
  --gcd-soft: #1f2535;
}

.gcd-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.gcd-title { font-size: 1.15rem; font-weight: 800; letter-spacing: -0.3px; color: var(--text, #1a3a52); }
.gcd-sub { font-size: 0.72rem; color: var(--muted, #8aa0b2); margin-top: 1px; }

/* Navigation période */
.gcd-nav { display: flex; align-items: center; gap: 10px; }
.gcd-modes { display: inline-flex; background: var(--gcd-track); border-radius: 9px; padding: 2px; }
.gcd-modes button { border: none; background: transparent; font: inherit; font-size: 0.72rem; font-weight: 700; color: var(--muted, #8298ab); padding: 4px 12px; border-radius: 7px; cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast); }
.gcd-modes button.on { background: var(--gcd-card); color: var(--gcd-accent-text, var(--gcd-accent)); box-shadow: 0 1px 4px rgba(30,60,90,0.12); }
.gcd-stepper { display: inline-flex; align-items: center; gap: 4px; }
.gcd-stepper button { width: 26px; height: 26px; border: 1px solid var(--border, #d8e2ec); background: var(--gcd-card); border-radius: 7px; cursor: pointer; color: var(--text, #33475b); font-size: 0.72rem; display: inline-flex; align-items: center; justify-content: center; transition: border-color var(--dur-fast), color var(--dur-fast), opacity var(--dur-fast); }
.gcd-stepper button:hover:not(:disabled) { border-color: var(--gcd-accent); color: var(--gcd-accent-text, var(--gcd-accent)); }
.gcd-stepper button:disabled { opacity: 0.35; cursor: default; }
.gcd-step-label { font-size: 0.76rem; font-weight: 700; color: var(--text, #1a3a52); min-width: 96px; text-align: center; text-transform: capitalize; }

/* ── Hero CA ── */
.gcd-hero {
  display: flex; align-items: stretch; gap: 18px;
  background: linear-gradient(120deg, var(--gcd-accent) 0%, #2a7ba8 55%, var(--gcd-accent2) 130%);
  border-radius: 16px; padding: 18px 22px; color: #fff;
  box-shadow: 0 10px 26px rgba(26,92,138,0.28); margin-bottom: 16px;
}
.gcd-hero-main { flex: 1; min-width: 0; }
.gcd-hero-label { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: rgba(255,255,255,0.85); }
.gcd-hero-tip { font-size: 0.62rem; opacity: 0.7; cursor: help; }
.gcd-hero-value { font-size: 2.1rem; font-weight: 800; line-height: 1.1; margin: 4px 0 6px; letter-spacing: -1px; }
.gcd-hero-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.gcd-hero-trend { font-size: 0.8rem; font-weight: 800; display: inline-flex; align-items: center; gap: 5px; padding: 3px 11px; border-radius: 20px; background: rgba(255,255,255,0.18); }
.gcd-hero-trend.up { color: #d6ffe2; }
.gcd-hero-trend.down { color: #ffd9d9; }
.gcd-hero-trend.flat { color: #eef4f8; }
/* Chiffre amputé (mois terminé sans résumé figé) — réutilise la puce de tendance. */
.gcd-hero-partiel { color: #ffe8bf; cursor: help; }
.gcd-hero-vs { font-size: 0.72rem; color: rgba(255,255,255,0.82); }
.gcd-hero-proj { font-size: 0.72rem; color: rgba(255,255,255,0.78); margin-top: 7px; }
.gcd-spark { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 5px; }
.gcd-spark-bars { display: flex; align-items: flex-end; gap: 5px; }
.gcd-spark-col { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.gcd-spark-bar { width: 13px; min-height: 3px; border-radius: 4px 4px 2px 2px; background: rgba(255,255,255,0.3); transition: height var(--dur-enter); }
.gcd-spark-bar.cur { background: #fff; }
.gcd-spark-lbl { font-size: 0.55rem; color: rgba(255,255,255,0.6); line-height: 1; }
.gcd-spark-cap { font-size: 0.62rem; color: rgba(255,255,255,0.7); }

/* ── Grille de cartes ── */
.gcd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.gcd-card {
  background: var(--gcd-card); border: 1px solid var(--border, #e4ecf3); border-radius: 13px;
  padding: 13px 15px; min-width: 0; box-shadow: 0 2px 8px rgba(30,60,90,0.05);
}
.gcd-card.wide { grid-column: 1 / -1; }
.gcd-card-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
.gcd-card-t { font-size: 0.82rem; font-weight: 700; color: var(--text, #1a3a52); }
.gcd-card-s { font-size: 0.66rem; color: var(--muted, #94a8b8); margin-left: auto; }
.gcd-card-b { min-width: 0; }
.gcd-card-empty, .gcd-empty { font-size: 0.74rem; color: var(--muted, #9fb0bf); padding: 8px 2px; }
.gcd-empty { text-align: center; margin-top: 50px; }
.gcd-more { font-size: 0.68rem; color: var(--muted, #9fb0bf); padding: 4px 2px 0; }

/* ── Barres horizontales (top cabinets / actes) ── */
.gcd-bar-row { display: flex; align-items: center; gap: 9px; padding: 4px 0; cursor: pointer; }
.gcd-bar-row[onclick]:hover .gcd-bar-name { color: var(--gcd-accent-text, var(--gcd-accent)); }
.gcd-bar-name { flex: 0 0 32%; font-size: 0.74rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text, #33475b); }
.gcd-bar-track { flex: 1; height: 9px; background: var(--gcd-track); border-radius: 6px; overflow: hidden; }
.gcd-bar-fill { height: 100%; border-radius: 6px; background: linear-gradient(90deg, var(--gcd-accent), var(--gcd-accent2)); }
.gcd-bar-fill.alt { background: linear-gradient(90deg, #7c5cbf, #b98bdb); }
.gcd-bar-val { flex: 0 0 auto; font-size: 0.72rem; font-weight: 700; color: var(--text, #1a3a52); min-width: 46px; text-align: right; }
.gcd-bar-row.has-ca .gcd-bar-name { flex-basis: 28%; }
.gcd-grp-cue { font-size: 0.66rem; font-weight: 700; color: var(--gcd-accent-text, var(--gcd-accent)); margin-left: 5px; opacity: 0.85; }
.gcd-bar-ca { flex: 0 0 auto; min-width: 70px; text-align: right; font-size: 0.72rem; font-weight: 800; color: var(--gcd-accent-text, var(--gcd-accent)); }

/* Filtre cabinet + caption + dérouler (carte Top actes) */
.gcd-acte-filter { margin-left: auto; width: 200px; max-width: 50%; font: inherit; font-size: 0.7rem; font-weight: 600; color: var(--text, #33475b); background: var(--gcd-soft); border: 1px solid var(--border, #dbe5ee); border-radius: 7px; padding: 4px 8px; cursor: text; box-sizing: border-box; }
.gcd-acte-filter:focus { outline: none; border-color: var(--gcd-accent); }
.gcd-refait-frac { flex: 0 0 auto; font-size: 0.66rem; font-weight: 600; color: var(--muted, #93a5b4); }
.gcd-acte-caption { font-size: 0.72rem; color: var(--muted, #708296); margin: -2px 0 8px; padding: 6px 9px; background: var(--gcd-soft); border-radius: 8px; }
.gcd-acte-caption b { color: var(--gcd-accent-text, var(--gcd-accent)); }
.gcd-expand { text-align: center; font-size: 0.7rem; font-weight: 700; color: var(--gcd-accent-text, var(--gcd-accent)); padding: 7px 0 1px; margin-top: 4px; cursor: pointer; border-top: 1px dashed var(--border, #e2eaf1); }
.gcd-expand:hover { opacity: 0.75; }

/* ── Donut concentration ── */
.gcd-donut-wrap { display: flex; align-items: center; gap: 16px; }
.gcd-donut { flex: 0 0 92px; width: 92px; height: 92px; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.gcd-donut-hole { width: 62px; height: 62px; border-radius: 50%; background: var(--gcd-card); display: flex; align-items: center; justify-content: center; }
.gcd-donut-pct { font-size: 1.15rem; font-weight: 800; color: var(--gcd-accent-text, var(--gcd-accent)); }
.gcd-donut-side { flex: 1; min-width: 0; }
.gcd-donut-cap { font-size: 0.68rem; color: var(--muted, #94a8b8); margin-bottom: 6px; }
.gcd-donut-item { display: flex; align-items: center; gap: 7px; font-size: 0.73rem; font-weight: 600; padding: 2px 0; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text, #33475b); }
.gcd-donut-item:hover { color: var(--gcd-accent-text, var(--gcd-accent)); }
.gcd-donut-rank { flex: 0 0 16px; height: 16px; border-radius: 50%; background: var(--gcd-track); color: var(--text, #5a7186); font-size: 0.62rem; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.gcd-donut-amt { margin-left: auto; font-weight: 700; color: var(--gcd-accent-text, var(--gcd-accent)); }

/* ── Listes (mouvement / sans presc) ── */
.gcd-li { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 8px; cursor: pointer; transition: background var(--dur-fast); }
.gcd-li:hover { background: var(--gcd-soft); }
.gcd-li-name { flex: 1; min-width: 0; font-size: 0.74rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text, #33475b); }
.gcd-tag { flex: 0 0 auto; font-size: 0.66rem; font-weight: 800; padding: 1px 8px; border-radius: 20px; }
.gcd-tag.up { background: #e3f7ea; color: #1f8a4c; }
.gcd-tag.down { background: #fdeaea; color: #c0392b; }
.gcd-tag.warn { background: #fff3e0; color: #e07c00; }
.gcd-tag.urg { background: #fdeaea; color: #c0392b; }
.gcd-tag.act { background: #eef2ff; color: #4f5bd5; }
html[data-theme="dark"] .gcd-tag.up { background: rgba(76,175,80,0.18); color: #6fe49a; }
html[data-theme="dark"] .gcd-tag.down, html[data-theme="dark"] .gcd-tag.urg { background: rgba(239,83,80,0.18); color: #ff9b98; }
html[data-theme="dark"] .gcd-tag.warn { background: rgba(224,124,0,0.2); color: #ffc06b; }
html[data-theme="dark"] .gcd-tag.act { background: rgba(99,111,213,0.22); color: #aab3ff; }

/* Carte cliquable → modale liste complète */
.gcd-card.gcd-clickable { cursor: pointer; transition: box-shadow var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast); }
.gcd-card.gcd-clickable:hover { border-color: var(--gcd-accent); box-shadow: 0 6px 18px rgba(30,60,90,0.12); }
.gcd-card-all { text-align: center; font-size: 0.7rem; font-weight: 700; color: var(--gcd-accent-text, var(--gcd-accent)); padding: 8px 0 1px; margin-top: 6px; border-top: 1px dashed var(--border, #e2eaf1); }
.gcd-card.gcd-clickable:hover .gcd-card-all { text-decoration: underline; }

/* ── Modale « liste complète + recherche » d'une carte ── */
.gcd-modal-overlay {
  position: fixed; inset: 0; z-index: 100000;
  background: rgba(18,32,46,0.5); backdrop-filter: var(--ov-blur, blur(2px));
  display: flex; align-items: center; justify-content: center; padding: 24px;
  animation: gcd-in var(--dur-fast) ease;
}
.gcd-modal {
  background: var(--gcd-card, #fff); color: var(--text, #2c3e50);
  width: min(560px, 100%); max-height: 80vh; display: flex; flex-direction: column;
  border-radius: 16px; box-shadow: 0 24px 60px rgba(15,35,55,0.35);
  border: 1px solid var(--border, #e4ecf3); overflow: hidden;
  /* idem .gcd : couleurs du LABO, jamais le bleu ILS en dur (la modale est un enfant direct
     du dashboard, elle redéclare donc les tokens pour elle-même). */
  --gcd-accent: var(--accent); --gcd-accent-text: var(--accent-text); --gcd-accent2: var(--teal);
  --gcd-track: #e8eef4; --gcd-soft: #f6f9fc; font-size: 0.8rem;
}
html[data-theme="dark"] .gcd-modal { --gcd-track: #2f3850; --gcd-card: var(--surface, #242938); --gcd-soft: #1f2535; }
.gcd-modal-h { display: flex; align-items: baseline; gap: 9px; padding: 15px 18px 11px; border-bottom: 1px solid var(--border, #eef3f8); }
.gcd-modal-t { font-size: 0.95rem; font-weight: 800; color: var(--text, #1a3a52); }
.gcd-modal-s { font-size: 0.68rem; color: var(--muted, #94a8b8); }
.gcd-modal-x { margin-left: auto; width: 28px; height: 28px; border: none; background: var(--gcd-soft, #f1f5f9); border-radius: 8px; cursor: pointer; color: var(--muted, #7a8ea0); font-size: 0.8rem; flex: 0 0 auto; }
.gcd-modal-x:hover { background: var(--gcd-track); color: var(--text, #33475b); }
.gcd-modal-search, .gcd-modal-cab { margin: 12px 16px 8px; font: inherit; font-size: 0.78rem; color: var(--text, #33475b); background: var(--gcd-soft, #f6f9fc); border: 1px solid var(--border, #dbe5ee); border-radius: 9px; padding: 8px 12px; }
.gcd-modal-cab { margin-bottom: 0; border-color: color-mix(in srgb, var(--gcd-accent) 40%, var(--border, #dbe5ee)); font-weight: 600; }
.gcd-modal-search:focus, .gcd-modal-cab:focus { outline: none; border-color: var(--gcd-accent); }
.gcd-modal .gcd-acte-caption { margin: 8px 16px 0; }
.gcd-modal-body { overflow-y: auto; padding: 2px 14px 14px; }
.gcd-modal-empty { text-align: center; font-size: 0.78rem; color: var(--muted, #9fb0bf); padding: 22px 0; }

/* ── Comparatif des sous-traitants (cas à refaire) ── */
.gcl-open { width: 100%; margin: 0 0 9px; padding: 8px; border: 1px dashed var(--gcd-accent); background: transparent; color: var(--gcd-accent-text, var(--gcd-accent)); border-radius: 9px; font: inherit; font-size: 0.75rem; font-weight: 700; cursor: pointer; transition: background var(--dur-fast); }
.gcl-open:hover { background: color-mix(in srgb, var(--gcd-accent) 10%, transparent); }
.gcl-modal { max-width: 700px; padding-bottom: 14px; }
.gcl-modal > :not(.gcd-modal-h) { margin-left: 14px; margin-right: 14px; }
.gcl-warn { margin-top: 10px; margin-bottom: 14px; padding: 9px 12px; border-radius: 9px; background: rgba(228,162,38,0.13); border: 1px solid rgba(228,162,38,0.34); color: var(--text, #5a4a2a); font-size: 0.77rem; line-height: 1.45; }
.gcl-labs { display: flex; gap: 12px; margin-bottom: 4px; }
.gcl-lab { flex: 1; border-radius: 14px; padding: 15px 12px; text-align: center; background: var(--gcd-soft); border: 1px solid var(--border, #e4ecf3); }
.gcl-lab-name { font-size: 0.78rem; font-weight: 800; letter-spacing: 0.04em; color: var(--muted, #6f8398); }
.gcl-lab-pct { font-size: 2.1rem; font-weight: 800; line-height: 1.15; margin: 3px 0; }
.gcl-lab.lo  .gcl-lab-pct { color: #1f9d57; }
.gcl-lab.mid .gcl-lab-pct { color: #d08a1e; }
.gcl-lab.hi  .gcl-lab-pct { color: #d24b4b; }
.gcl-lab-sub { font-size: 0.75rem; font-weight: 600; color: var(--text, #33475b); }
.gcl-sec-t { font-size: 0.82rem; font-weight: 700; color: var(--text, #1a3a52); margin: 16px 0 8px; }
.gcl-sec-t small { font-weight: 500; color: var(--muted, #94a8b8); }
.gcl-cols { display: flex; gap: 18px; }
.gcl-col { flex: 1; min-width: 0; }
.gcl-col-h { font-size: 0.73rem; font-weight: 800; color: var(--muted, #6f8398); margin-bottom: 5px; }
.gcl-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.gcl-row-n { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.73rem; font-weight: 600; color: var(--text, #33475b); }
.gcl-row-bar { flex: 0 0 54px; height: 7px; border-radius: 4px; background: var(--gcd-track); overflow: hidden; }
.gcl-row-bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--gcd-accent), var(--gcd-accent2)); }
.gcl-row-v { flex: 0 0 auto; min-width: 24px; text-align: right; font-size: 0.73rem; font-weight: 700; color: var(--text, #1a3a52); }
/* overflow-x : à partir de ~4 sous-traitants les colonnes dépassent la modale —
   on fait défiler le tableau plutôt que d écraser la colonne « Acte ». */
.gcl-head { flex: 1 1 auto; min-height: 96px; overflow-y: auto; overflow-x: auto; border: 1px solid var(--border, #e4ecf3); border-radius: 10px; }
.gcl-h-row { display: flex; align-items: center; min-width: max-content; border-bottom: 1px solid var(--border, #eef2f6); }
.gcl-h-row:last-child { border-bottom: 0; }
.gcl-h-head { position: sticky; top: 0; z-index: 1; background: var(--gcd-soft); }
.gcl-h-head .gcl-h-acte, .gcl-h-head .gcl-h-cell { font-weight: 800; font-size: 0.71rem; color: var(--muted, #6f8398); }
.gcl-h-acte { flex: 1 0 170px; min-width: 170px; padding: 7px 10px; font-size: 0.76rem; font-weight: 600; color: var(--text, #33475b); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gcl-h-cell { flex: 0 0 116px; padding: 7px 10px; text-align: center; font-size: 0.78rem; font-weight: 700; color: var(--text, #33475b); }
.gcl-h-cell small { font-weight: 500; font-size: 0.67rem; color: var(--muted, #97a8ba); }
.gcl-h-cell.best { color: #1f9d57; background: rgba(31,157,87,0.10); }
.gcl-empty { padding: 12px; text-align: center; font-size: 0.76rem; color: var(--muted, #9fb0bf); }
.gcl-grp { cursor: pointer; }
.gcl-grp .gcl-row-n, .gcl-grp .gcl-h-acte { font-weight: 700; }
.gcl-grp small { font-weight: 500; color: var(--muted, #97a8ba); }
.gcl-arrow { display: inline-block; font-size: 0.7em; color: var(--gcd-accent-text, var(--gcd-accent)); transition: transform var(--dur-fast); }
.gcl-grp.open .gcl-arrow { transform: rotate(90deg); }
.gcl-child .gcl-row-n, .gcl-child .gcl-h-acte { padding-left: 15px; opacity: 0.82; font-weight: 500; }
.gcl-child { background: color-mix(in srgb, var(--gcd-soft) 55%, transparent); }

/* ── Combobox « filtrer par cabinet » (popup ancré au champ) ── */
.gc-combo-pop {
  position: fixed; z-index: 100002; max-height: 280px; overflow-y: auto;
  background: var(--surface, #fff); border: 1px solid var(--border, #d8e2ec);
  border-radius: 10px; box-shadow: 0 14px 38px rgba(15,35,55,0.28); padding: 4px;
  animation: gcd-in var(--dur-fast) ease;
}
.gc-combo-opt {
  padding: 7px 10px; font-size: 0.78rem; border-radius: 7px; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text, #33475b);
}
.gc-combo-opt:hover { background: color-mix(in srgb, var(--accent, #2a7ba8) 13%, transparent); }
.gc-combo-all { font-weight: 700; color: var(--accent-text, #2a7ba8); border-bottom: 1px solid var(--border, #eef3f8); border-radius: 0; margin-bottom: 3px; padding-bottom: 8px; }

/* ── Drill-down « Cas à refaire » d'un client ── */
.rf-overlay { z-index: 100001; }   /* au-dessus de la modale liste */
.rf-modal { width: min(620px, 100%); }
.rf-modal .gcd-modal-x { margin-left: 8px; }
.rf-scope { margin-left: auto; }
.rf-body { padding: 14px 18px 18px; }
.rf-hero { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: 12px; background: var(--gcd-soft, #f6f9fc); margin-bottom: 6px; }
.rf-hero-rate { font-size: 1.8rem; font-weight: 800; line-height: 1; flex: 0 0 auto; }
.rf-hero-meta { font-size: 0.82rem; color: var(--text, #33475b); }
.rf-hero-meta b { font-weight: 800; }
.rf-ok { color: #1f8a4c; } .rf-warn { color: #e07c00; } .rf-urg { color: #c0392b; }
.rf-fiche { display: block; margin-top: 4px; font-size: 0.74rem; font-weight: 700; color: var(--gcd-accent-text, var(--gcd-accent)); cursor: pointer; }
.rf-fiche:hover { text-decoration: underline; }
.rf-sec { margin-top: 16px; }
.rf-sec-h { font-size: 0.8rem; font-weight: 800; color: var(--text, #1a3a52); margin-bottom: 7px; }
.rf-row .gcd-bar-name { flex-basis: 34%; }
/* Familles dépliables */
.rf-fam-h { cursor: pointer; }
.rf-caret { display: inline-block; font-size: 0.6rem; color: var(--muted, #94a8b8); margin-right: 4px; transition: transform var(--dur-fast); }
.rf-fam.open .rf-caret { transform: rotate(90deg); }
.rf-fam-h:hover .gcd-bar-name { color: var(--gcd-accent-text, var(--gcd-accent)); }
.rf-subwrap { display: none; padding: 2px 0 4px 16px; }
.rf-fam.open .rf-subwrap { display: block; }
.rf-sub .gcd-bar-name { flex-basis: 32%; font-weight: 500; font-size: 0.7rem; color: var(--muted, #6f8398); }
.rf-sub .gcd-bar-fill { background: linear-gradient(90deg, #9aa8bd, #c2ccda); }
.rf-sub .gcd-bar-val, .rf-sub .rf-frac { font-size: 0.66rem; }
.rf-frac { flex: 0 0 auto; min-width: 44px; text-align: right; font-size: 0.68rem; font-weight: 600; color: var(--muted, #93a5b4); }
.gcd-bar-fill.rf-warn { background: linear-gradient(90deg, #f0a23c, #ffc06b); }
.gcd-bar-fill.rf-urg { background: linear-gradient(90deg, var(--danger), color-mix(in srgb, var(--danger) 55%, #fff)); }
/* Évolution */
.rf-spark { display: flex; align-items: flex-end; gap: 8px; padding: 6px 2px 0; height: 64px; }
.rf-spark .gcd-spark-col { display: flex; flex-direction: column; align-items: center; gap: 4px; justify-content: flex-end; }
.rf-mbar { width: 16px; min-height: 2px; border-radius: 4px 4px 2px 2px; background: linear-gradient(180deg, var(--gcd-accent), var(--gcd-accent2)); }
.rf-mlbl { font-size: 0.58rem; color: var(--muted, #94a8b8); }
/* Liste des cas */
.rf-list { display: flex; flex-direction: column; gap: 2px; }
.rf-case { display: flex; align-items: baseline; gap: 10px; padding: 6px 8px; border-radius: 7px; font-size: 0.76rem; }
.rf-case:nth-child(odd) { background: var(--gcd-soft, #f6f9fc); }
.rf-case-pat { flex: 0 0 28%; font-weight: 700; color: var(--text, #33475b); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rf-case-actes { flex: 1; min-width: 0; color: var(--muted, #6f8398); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rf-case-side { flex: 0 0 auto; font-size: 0.68rem; font-weight: 600; color: var(--muted, #93a5b4); white-space: nowrap; }

/* Menu « choisir la période » (clic droit sur Période) */
.rf-pmenu {
  position: fixed; z-index: 100003; width: 232px; padding: 9px;
  background: var(--surface, #fff); border: 1px solid var(--border, #d8e2ec);
  border-radius: 12px; box-shadow: 0 16px 42px rgba(15,35,55,0.32); animation: gcd-in var(--dur-fast) ease;
}
.rf-pmenu-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px; font-size: 0.82rem; font-weight: 800; color: var(--text, #1a3a52); }
.rf-pmenu-h button { width: 24px; height: 24px; border: 1px solid var(--border, #d8e2ec); background: transparent; border-radius: 6px; cursor: pointer; color: var(--text, #33475b); }
.rf-pmenu-h button:disabled { opacity: 0.35; cursor: default; }
.rf-pm-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.rf-pm-m { padding: 6px 0; border: 1px solid transparent; background: color-mix(in srgb, var(--text, #334) 8%, transparent); border-radius: 7px; cursor: pointer; font-size: 0.72rem; color: var(--text, #33475b); text-transform: capitalize; }
.rf-pm-m:hover:not(:disabled) { border-color: var(--accent, #2a7ba8); }
.rf-pm-m.on { background: var(--accent, #2a7ba8); color: #fff; font-weight: 700; }
.rf-pm-m:disabled { opacity: 0.3; cursor: default; }
.rf-pm-year { width: 100%; margin-top: 7px; padding: 7px 0; border: 1px solid var(--border, #d8e2ec); background: transparent; border-radius: 7px; cursor: pointer; font-size: 0.74rem; font-weight: 700; color: var(--text, #33475b); }
.rf-pm-year.on { background: var(--accent, #2a7ba8); color: #fff; border-color: transparent; }

@media (max-width: 720px) { .gcd-grid { grid-template-columns: 1fr; } .gcd-card.wide { grid-column: auto; } }

/* ═══ MODALE « VOIR FICHE » (.vf-*) — halos/dégradé signature, dark + tenant ═══ */
.vf-overlay { position: fixed; inset: 0; z-index: 1500; display: flex; align-items: center; justify-content: center; padding: 16px;
  background: color-mix(in srgb, #0b2235 52%, transparent); -webkit-backdrop-filter: var(--ov-blur, blur(4px)); backdrop-filter: var(--ov-blur, blur(4px)); font-family: 'DM Sans', system-ui, sans-serif;
  animation: vfBackdrop var(--dur-base) ease backwards; }
/* Hauteur RÉSERVÉE dès l'ouverture (le format accueille la fiche → pas de reflow quand elle charge). */
/* Largeur plafonnée à 1520 px (au lieu de 1680) : au-delà, la colonne de la fiche
   s'étirait bien plus large que le document lui-même — la prescription tient en
   hauteur, donc tout ce surplus devenait du vide autour d'elle. À 1520, avec la
   colonne d'infos à 720 px, il reste ~800 px pour la fiche : la taille exacte
   d'un scan papier affiché en entier. */
.vf-modal { width: 100%; max-width: min(1520px, 96vw); height: min(95vh, 1040px); max-height: 95vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); color: var(--text);
  box-shadow: 0 26px 70px rgba(8,24,40,.45), 0 6px 32px color-mix(in srgb, var(--accent) 30%, transparent);
  animation: vfPop var(--dur-base) var(--ease-out) backwards; }
/* Changement de bon (‹ › ou balayage) : la carte GLISSE, elle ne CLIGNOTE pas.
   Trois fondus se cumulaient à chaque bon — la carte entière, puis le contenu de
   l'aperçu, avec un vide « Chargement… » entre les deux — alors que le bandeau et
   la colonne de gauche sont quasi identiques d'un bon au suivant : l'œil ne lisait
   pas un changement de page mais un clignotement. Le mouvement seul suffit à dire
   « on a changé de fiche ». Le fondu d'entrée de l'aperçu est gardé à la PREMIÈRE
   ouverture (où il n'y a rien avant), pas pendant la navigation. */
.vf-overlay.vf-nav .vf-modal { animation: vfSwap var(--dur-fast) var(--ease-out) backwards; }
.vf-viewer > * { animation: vfFadeIn var(--dur-enter) ease backwards; }
.vf-overlay.vf-nav .vf-viewer > * { animation: none; }
@keyframes vfPop { from { opacity: 0; transform: translateY(12px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes vfSwap { from { transform: translateY(4px); } to { transform: none; } }
@keyframes vfBackdrop { from { opacity: 0; } to { opacity: 1; } }
@keyframes vfFadeIn { from { opacity: 0; } to { opacity: 1; } }
/* ── Balayage tactile (js/voir-fiche-swipe.js) ──────────────────────────────
   La carte suit le doigt, puis part du côté du geste ; la suivante entre par le
   bord opposé. `animation: none` pendant le geste est INDISPENSABLE : le
   fill-mode de vfPop/vfSwap fige transform, l'inline du drag serait ignoré. */
.vf-overlay.vf-swiping .vf-modal { animation: none; transition: none; }
.vf-overlay.vf-swiping.vf-settling .vf-modal { transition: transform var(--dur-exit) var(--ease-out), opacity var(--dur-exit) var(--ease-out); }
.vf-overlay.vf-nav.vf-in-right .vf-modal { animation: vfSwipeInR var(--dur-enter) var(--ease-out) backwards; }
.vf-overlay.vf-nav.vf-in-left  .vf-modal { animation: vfSwipeInL var(--dur-enter) var(--ease-out) backwards; }
@keyframes vfSwipeInR { from { transform: translateX(30px); } to { transform: none; } }
@keyframes vfSwipeInL { from { transform: translateX(-30px); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .vf-overlay, .vf-modal, .vf-overlay.vf-nav .vf-modal, .vf-viewer > * { animation: none; }
  .vf-overlay.vf-nav.vf-in-right .vf-modal, .vf-overlay.vf-nav.vf-in-left .vf-modal { animation: none; }
  .vf-overlay.vf-swiping.vf-settling .vf-modal { transition: none; } }

/* Header « cockpit » — signature futuriste partagée avec Gestion Clients / Implants :
   dégradé profond tenant + quadrillage technique + halo radial + logo flottant + edge glissant. */
.vf-modal { --vf-grad-deep: var(--ck-grad-deep); /* source unique : :root (brief #5 Ph3) */
  --vf-grid: rgba(255,255,255,.09); }
.vf-head { position: relative; display: flex; align-items: center; gap: 13px; padding: 13px 18px; background: var(--vf-grad-deep); color: #fff; overflow: hidden; }
.vf-head::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(var(--vf-grid) 1px, transparent 1px), linear-gradient(90deg, var(--vf-grid) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(120% 120% at 12% 0%, #000, transparent 78%); mask-image: radial-gradient(120% 120% at 12% 0%, #000, transparent 78%); }
.vf-head::after { content: ""; position: absolute; top: -160px; right: -90px; width: 460px; height: 460px; pointer-events: none;
  background: radial-gradient(circle, color-mix(in srgb, var(--hd, var(--teal)) 40%, transparent), transparent 62%); filter: blur(4px); opacity: .62; }
/* ── Bandeau teinté par l'ÉTAT du bon ────────────────────────────────────────
   Mêmes couleurs métier que la frise et que les pastilles de la liste, passées
   dans la recette EXACTE de --ck-grad-deep (mêmes angles, mêmes ancres sombres) :
   le bandeau change de teinte sans changer de style. Les ancres quasi noires
   garantissent le contraste du texte blanc, y compris sur l'ambre « en attente ».
   ⚠️ Ce bandeau porte normalement le dégradé du labo (branding tenant) : ici
   l'état du cas prend le dessus. C'est un arbitrage assumé, pas un oubli — les
   teintes restent métier (aucune couleur de labo en dur). */
/* Ambre assombri POUR LE BANDEAU seulement : le #e0a400 des pastilles est la
   teinte la plus claire du jeu, le texte blanc y tombait à 3,84:1 (illisible).
   La frise, elle, garde l'ambre d'origine. */
/* Teinte du bandeau = palette PARTAGÉE des états (js/etapes-cas.js). */
.vf-head.vf-hd-attente    { --hd: var(--ec-c-envoye, #e0a400); }
.vf-head.vf-hd-recu       { --hd: var(--ec-c-revenu, #16a3b0); }
.vf-head.vf-hd-production { --hd: var(--ec-c-en_production, #9b4fd6); }
.vf-head.vf-hd-livraison  { --hd: var(--ec-c-en_livraison, #ef7d1a); }
.vf-head.vf-hd-livre      { --hd: var(--ec-c-livre, #37974a); }
.vf-head[class*="vf-hd-"] { --vf-grad-deep: linear-gradient(125deg,
    color-mix(in srgb, var(--hd) 52%, #07131e) 0%,
    color-mix(in srgb, var(--hd) 72%, #08161f) 52%,
    color-mix(in srgb, var(--hd) 58%, #06201c) 100%); }
.vf-head > * { position: relative; z-index: 1; }
.vf-code { font-family: 'DM Mono', monospace; font-weight: 500; font-size: 1.05rem; letter-spacing: .02em; padding: 5px 12px; border-radius: 11px;
  background: rgba(255,255,255,.96); color: var(--accent); -webkit-text-fill-color: var(--accent); box-shadow: 0 4px 14px rgba(0,0,0,.22); }
.vf-who { line-height: 1.25; min-width: 0; }
.vf-who .vf-nom { font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }
.vf-who .vf-sub { font-size: .76rem; color: rgba(255,255,255,.88); }
.vf-who .vf-lnk { text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.vf-sp { margin-left: auto; }
.vf-nav { display: flex; gap: 6px; }
.vf-hbtn { width: 34px; height: 34px; border: none; border-radius: 11px; background: rgba(255,255,255,.16); color: #fff; cursor: pointer;
  font-size: 1.2rem; line-height: 1; display: grid; place-items: center; transition: background var(--dur-fast), transform var(--dur-fast); }
.vf-hbtn:hover { background: rgba(255,255,255,.30); transform: translateY(-1px); }
/* Ligne lumineuse qui glisse sous le header (cohérence gc-edge / imx-edge). */
.vf-edge { position: relative; height: 2px; flex: none; overflow: hidden; background: var(--line); }
.vf-edge::after { content: ""; position: absolute; inset: 0; width: 42%;
  background: linear-gradient(90deg, transparent, var(--teal), var(--accent), transparent); animation: vfSlide 2.2s linear infinite; }
@keyframes vfSlide { from { transform: translateX(-120%); } to { transform: translateX(340%); } }
@media (prefers-reduced-motion: reduce) { .vf-edge::after { animation: none; }
  .vf-step.cur .vf-d { animation: none; box-shadow: 0 0 0 5px color-mix(in srgb, var(--vfc, var(--accent)) 22%, transparent); }
  .vf-step.cur .vf-d::after { animation: none; } }

/* Colonne infos raisonnable (résumé IA lisible) ; la FICHE reprend la grande
   largeur (1fr) — c'est elle qu'on lit. Même dimensionnement EXACT que la
   modale portail fournisseur. */
/* Colonne d'infos à largeur FIXE : en minmax(420,500) elle changeait de taille
   d'un écran à l'autre et d'une fiche à l'autre — les repères bougeaient sans
   raison. clamp(560, 100% - 800, 720) : elle prend toute la largeur restante une
   fois les ~800 px de la prescription réservés, et ne descend jamais sous les
   560 px d’avant — la fiche n’est JAMAIS rognée pour agrandir les infos. */
.vf-body { display: grid; grid-template-columns: clamp(560px, calc(100% - 800px), 720px) minmax(0,1fr); flex: 1; min-height: 0; }
.vf-info { padding: 16px; display: flex; flex-direction: column; gap: 12px; overflow: auto; background: var(--bg); }
.vf-fiche { padding: 16px; display: flex; flex-direction: column; min-height: 0; background: var(--section-bg); border-left: 1px solid var(--border); }

.vf-ct { font-size: .62rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }

/* Frise partagée (js/etapes-cas.js) dans la fiche : même gabarit que .vf-tl. */
.vf-info > .ec-frise { padding: 0; } /* .ec-tl porte déjà le 4px 6px 0 de l'ancienne .vf-tl */
.vf-tl { display: flex; align-items: flex-start; justify-content: space-between; position: relative; padding: 4px 6px 0; }
.vf-tl::before { content: ""; position: absolute; left: 24px; right: 24px; top: 11px; height: 2px; background: var(--line); }
.vf-step { position: relative; z-index: 1; flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.vf-d { width: 14px; height: 14px; border-radius: 50%; background: var(--surface); border: 2px solid var(--border); display: flex; align-items: center; justify-content: center; font-size: 9px; font-weight: 700; line-height: 1; color: #fff; }
.vf-step.done .vf-d { background: var(--teal); border-color: var(--teal); }
/* Couleur métier de l'étape — EXACTEMENT les teintes déjà utilisées par les
   pastilles de statut de la liste : la modale ne se paie pas sa propre palette.
   Deux tons par étape, comme --accent / --accent-text ailleurs : --vfc remplit la
   pastille (couleur pleine, celle des capsules .accent.st-*), --vfc-text écrit le
   nom (celle des pastilles .pill.st-*, éclaircie en nuit) — un seul ton ne peut
   pas servir à la fois de fond et de texte lisible.
   Ces deux variables ne sont lues que par l'étape EN COURS et par « Livré » : les
   étapes franchies restent turquoise et les suivantes grises, sinon la frise
   devient un arc-en-ciel et ne raconte plus l'avancement.
   Attente/Reçu n'ont pas de teinte métier propre → repli sur --accent. */
.vf-step.vf-st-production { --vfc: #9b4fd6; --vfc-text: #6b21a8; }
/* Orange : le #c85a00 des pastilles passe sur leur fond orange clair, pas sur le
   fond pâle de la colonne (3,85:1 mesuré) → foncé d'un cran pour rester lisible. */
.vf-step.vf-st-livraison  { --vfc: #ef7d1a; --vfc-text: #a34800; }
.vf-step.vf-st-livre      { --vfc: #37974a; --vfc-text: #1f6b2c; }
html[data-theme="dark"] .vf-step.vf-st-production { --vfc-text: #c79bf0; }
html[data-theme="dark"] .vf-step.vf-st-livraison  { --vfc-text: #f0a35e; }
html[data-theme="dark"] .vf-step.vf-st-livre      { --vfc-text: #6fc98a; }
/* Pulse converti box-shadow→pseudo (scale+opacity) : 8px de halo autour de la
   pastille de 14px → scale 2.14 ; inset:-2px couvre la bordure (box-sizing). */
.vf-step.cur .vf-d { background: var(--vfc, var(--accent)); border-color: var(--vfc, var(--accent));
  position: relative; z-index: 0; }
.vf-step.cur .vf-d::after { content: ""; position: absolute; inset: -2px; border-radius: 50%; z-index: -1;
  background: color-mix(in srgb, var(--vfc, var(--accent)) 55%, transparent); opacity: 0;
  animation: vfStepPulse 1.8s ease-out infinite; }
@keyframes vfStepPulse { 0% { transform: scale(1); opacity: 1; } 70%, 100% { transform: scale(2.14); opacity: 0; } }
/* Livré = état terminal validé : pastille verte + halo + ✓. Quand le cas est livré
   TOUTES les étapes portent aussi .done → .done .vf-lbl (plus bas) écrasait la
   couleur et le nom « Livré » ressortait en blanc. On double la classe pour passer
   devant, sans dépendre de l'ordre des règles. */
.vf-step.vf-final .vf-d { background: var(--vfc, var(--success)); border-color: var(--vfc, var(--success));
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--vfc, var(--success)) 22%, transparent); }
.vf-step.vf-final.vf-final .vf-lbl { color: var(--vfc-text, var(--success)); font-weight: 700; }
.vf-step-date { font-size: .56rem; color: var(--muted); margin-top: 1px; }
.vf-lbl { font-size: .62rem; color: var(--muted); text-align: center; }
.vf-step.done .vf-lbl { color: var(--text); }
.vf-step.cur .vf-lbl { color: var(--vfc-text, var(--accent-text)); font-weight: 700; }

.vf-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 12px 13px; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 6px; animation: vfCardIn var(--dur-enter) var(--ease-out) backwards; }
@keyframes vfCardIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .vf-card { animation: none; } }
.vf-card .vf-ct { margin-bottom: 3px; }
.vf-dl { display: flex; justify-content: space-between; align-items: center; font-size: .82rem; }
/* Dates en tête de la carte du résumé : les deux tiennent sur UNE ligne (elles
   occupaient une carte entière, ~90 px de haut pour deux dates). Elles se
   replient l'une sous l'autre quand la colonne est étroite (téléphone). */
.vf-dates { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; font-size: .82rem; }
.vf-d-one { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.vf-d-lbl { color: var(--muted); }
.vf-d-one b { font-weight: 700; }
/* Zone du problème vide : pas de gap fantôme dans la carte (flex column). */
.vf-prob-wrap:empty { display: none; }
.vf-dl > span:first-child { color: var(--muted); }
.vf-dl b { font-weight: 700; }
.vf-livr-red { color: #c0392b; font-weight: 800; font-size: .78rem; background: #fdecea; border: 1px solid #f5c6c2; border-radius: 6px; padding: 2px 9px; white-space: nowrap; }
.vf-decal { display: flex; align-items: center; gap: 7px; font-size: .72rem; color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, var(--surface)); border: 1px solid color-mix(in srgb, var(--gold) 32%, transparent); border-radius: 9px; padding: 6px 9px; }
.vf-flags { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 4px; }
.vf-ais { margin-top: 2px; }
/* Signataires (rempli / vérifié par) */
.vf-sig { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: .82rem; }
.vf-sig + .vf-sig { border-top: 1px solid var(--line); }
.vf-sig-lbl { flex: none; min-width: 78px; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.vf-sig-av { width: 24px; height: 24px; border-radius: 50%; flex: none; display: inline-flex; align-items: center; justify-content: center; font-size: .66rem; font-weight: 800; color: #fff; background-size: cover; background-position: center; overflow: hidden; }
.vf-sig-nm { font-weight: 700; color: var(--text); }
/* Chaîne des signataires : vérificateur puis modificateurs, alignés et repliables. */
.vf-sig-chain { flex-wrap: wrap; gap: 6px 8px; }
.vf-sig-one { display: inline-flex; align-items: center; gap: 6px; }
.vf-sig-sep { flex: none; color: var(--muted); font-size: .72rem; opacity: .7; }
/* Badge « empreinte physique » à droite du nom du patient (pas dans les flags). */
.vf-nom-phys { margin-left: 6px; vertical-align: 1px; }
/* Carte Historique fournisseur : titre + bouton « Ouvrir le chat » sur une ligne,
   liste scrollable (plafonnée pour ne pas étirer la modale sur un long historique). */
.vf-ct-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.vf-ct-row .vf-ct { margin-bottom: 0; }

/* En-tête de la fiche originale : le titre, rien d'autre. Les actions du cas sont
   descendues dans la colonne de gauche (carte « Actions ») — en haut à droite,
   elles volaient ~100px de hauteur au document, qui est le sujet de la modale. */
.vf-fiche-head { display: flex; align-items: center; margin-bottom: 10px; }
.vf-fiche-head > .vf-ct { white-space: nowrap; }
/* « Transférer » (partage WhatsApp/AirDrop) : en haut à droite de la fiche. */
.vf-fiche-head .vf-partager { margin-left: auto; height: 30px; flex: none; }
/* Carte « Actions » (colonne de gauche, sous le résumé IA). Deux familles nommées
   — mêmes mots que le sous-menu de la liste — en grille 2 colonnes égales : tous
   les boutons font la même largeur et les icônes s'alignent sur deux verticales,
   ce qu'un flex qui wrappe ne donne jamais. */
.vf-acts-lbl { font-size: .6rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 4px; }
.vf-acts-lbl + .vf-acts-grp { margin-bottom: 9px; }
/* Une famille = DEUX par ligne, tous à la même largeur (18/09/2026, Illan :
   « fais-les tous à la même taille »). Le flex d'avant dimensionnait chaque
   bouton à son texte, d'où des largeurs différentes à chaque ligne ; la base de
   50 % les aligne sur deux verticales, et flex-grow fait que le dernier d'une
   ligne s'étire tout seul au lieu de laisser un trou — un trou se lit comme un
   oubli, une pleine largeur non. Pas une grille : le portail cache certains de
   ces boutons, et :nth-child compte les [hidden] alors qu'un flex les ignore.
   Même mécanisme des deux côtés (supplier/styles.css). */
.vf-acts-grp { display: flex; flex-wrap: wrap; gap: 5px; }
.vf-acts-grp > * { flex: 1 1 calc(50% - 5px); min-width: 0; }
.vf-acts-grp .vf-tool { padding: 3px 8px; font-size: .71rem; border-radius: 8px; line-height: 1.5;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Le bloc « ACTIONS » — les gestes d'un cas, réunis (18/09/2026). Ils vivaient
   dans quatre endroits : la carte des dates, le bas de cette carte, le titre des
   croquis, le titre du journal et le bandeau violet. Un seul bloc, une seule
   forme, une seule taille. « Modifier ce cas » est l'action PRINCIPALE — la
   seule qui change vraiment le cas — et porte le liseré dégradé de la famille ;
   les autres sont des raccourcis carrés, TROIS par ligne, illustration au-dessus
   (le libellé passe à la ligne, il n'est jamais rogné). */
.vf-acts-cle { margin-bottom: 6px; }
.vf-acts-raccourcis > * { flex: 1 1 calc(33.333% - 5px); }
.vf-viewer { position: relative; flex: 1; min-height: 280px; border-radius: var(--r); overflow: auto; border: 1px solid var(--border);
  background: var(--surface); display: flex; align-items: flex-start; justify-content: center; box-shadow: inset 0 2px 14px rgba(15,40,65,.08); }
/* La fiche image tient ENTIÈREMENT dans le viewer (hauteur + largeur) → pas de scroll.
   !important : le rendu partagé pose un style inline (width:100%;max-height:80vh) calé sur
   la fenêtre, trop grand pour cette boîte ; on le ramène à la taille du viewer. */
/* La fiche tient TOUJOURS en entier dans la fenêtre : devoir faire défiler pour
   lire le bas d'une prescription est exclu. Elle est donc ajustée à la HAUTEUR
   disponible, et centrée. Le vide qui restait autrefois sur les côtés vient de la
   largeur de la carte, traitée plus bas (--vf-max) et non en étirant le document.
   Les marges blanches propres au scan sont rognées en amont (cropFicheWhitespace). */
.vf-viewer img { max-height: 100% !important; max-width: 100% !important; width: auto !important; height: auto !important; display: block; margin: 0 auto; }
/* Fiche figée VECTORIELLE : dessinée par la visionneuse PDF, mais elle doit se
   présenter comme la fiche image — même largeur, sans cadre gris ni bandeau de
   pagination. Le plafond de 700 px et le fond sombre viennent du panneau
   d'aperçu de saisie, bien plus étroit ; ici ils rapetissaient la prescription
   et la faisaient ressembler à un lecteur de PDF. */
/* height:100% (et non auto) : c'est LUI qui donne sa référence au max-height de
   la page dessinée. En auto, la page ne connaissait aucune limite et débordait
   de la fenêtre — le défilement qu'on veut éviter. */
/* ── Presentation UNIFORME du document, dans TOUTES les visionneuses ────────
   Le conteneur PDF arrive avec un cadre gris fonce et un bandeau de pagination
   (heritage du panneau de scan). Resultat : la meme fiche n'avait pas la meme
   tete selon l'ecran. On neutralise ce decor partout ; les regles de taille
   propres a la modale restent scopees a .vf-viewer plus bas. */
div[id^="pdfjs-container"] { background: transparent !important; padding: 0 !important; gap: 0 !important; }
div[id^="pdfjs-container"] > div:first-child { display: none !important; }
.vf-viewer #pdfjs-container, .vf-viewer #pdfjs-container-local {
  background: transparent !important; padding: 0 !important; height: 100% !important;
  overflow: hidden !important; gap: 0 !important; }
.vf-viewer #pdfjs-container > div:first-child,
.vf-viewer #pdfjs-container-local > div:first-child { display: none !important; }
/* Même règle pour la page dessinée (fiche vectorielle) : ajustée à la hauteur,
   centrée, jamais de défilement. */
.vf-viewer canvas,
.vf-viewer img.pdf-page-memo { max-height: 100% !important; max-width: 100% !important; width: auto !important; height: auto !important; display: block; margin: 0 auto; }
/* Page PDF déjà dessinée, reposée depuis le cache de la visionneuse : elle doit
   occuper EXACTEMENT la place du canvas qu'elle remplace — sinon la prescription
   changerait de taille selon qu'elle vient d'être dessinée ou remise de mémoire.
   Le plafond de 700 px vaut pour le panneau d'aperçu de saisie ; dans la
   visionneuse la règle .vf-viewer ci-dessus le lève (colonne bien plus large). */
img.pdf-page-memo {
  width: 100% !important; max-width: 700px !important; height: auto !important; max-height: none !important; }
.vf-viewer iframe { max-width: 100%; display: block; }
.vf-viewer iframe { width: 100%; height: 100%; min-height: 420px; border: 0; }

/* Compteur de position (« Fiche 1 / 200 ») dans le header, avant les flèches ‹ › */
.vf-counter { font-size: .74rem; color: rgba(255,255,255,.82); font-weight: 600; white-space: nowrap; letter-spacing: .01em; }
/* (Le bouton « Historique » du bandeau a disparu le 18/09/2026 — il a rejoint le
   bloc « Actions ». Ses règles sont parties avec lui : non scopées, elles
   tombaient aussi sur le <div class="vf-hist"> du journal du cas, à qui elles
   posaient un inline-flex de 34 px et un texte blanc. Le journal lui-même a
   quitté la fiche le 18/09/2026 — il est dans la modale « Historique ».) */

/* « Vérifié par » DANS le bandeau de la visionneuse (11/08) : c'est une info
   d'identité, pas une carte — elle occupait une carte entière de la colonne, qui
   est l'espace rare. Petit encadré translucide. */
.vf-head .vf-sig-box { display: inline-flex; align-items: center; gap: 8px; flex: none;
  height: 34px; padding: 0 12px 0 10px; border-radius: 11px;
  background: rgba(255,255,255,.13); border: 1px solid rgba(255,255,255,.22); }
.vf-head .vf-sig-lbl { min-width: 0; font-size: .58rem; line-height: 1.1; color: rgba(255,255,255,.78); }
.vf-head .vf-sig { padding: 0; gap: 6px; font-size: .76rem; }
.vf-head .vf-sig-nm { color: #fff; font-size: .76rem; }
.vf-head .vf-sig-av { width: 21px; height: 21px; font-size: .6rem; }
.vf-head .vf-sig-sep { color: rgba(255,255,255,.7); }
/* Écran étroit : l'encadré ne doit pas pousser les actions hors du bandeau —
   on ne garde que les avatars (le nom reste en infobulle). */
@media (max-width: 1180px) { .vf-head .vf-sig-lbl, .vf-head .vf-sig-nm { display: none; } }
@media (max-width: 900px) { .vf-head .vf-sig-box { display: none; } }

/* Boutons à halo coloré (signature app : couleur via --c) */
.vf-tool { --c: var(--accent); --c-text: var(--accent-text); display: inline-flex; align-items: center; gap: 7px; border-radius: 11px; padding: 7px 14px; cursor: pointer;
  font-family: inherit; font-weight: 700; font-size: .82rem; color: var(--c-text, var(--c));
  background: color-mix(in srgb, var(--c) 9%, var(--surface)); border: 1.5px solid color-mix(in srgb, var(--c) 30%, var(--surface));
  box-shadow: 0 4px 18px color-mix(in srgb, var(--c) 20%, transparent), var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-base), background var(--dur-base), border-color var(--dur-base); }
.vf-tool:hover { transform: translateY(-2px); box-shadow: 0 9px 26px color-mix(in srgb, var(--c) 34%, transparent), var(--shadow-md); }
.vf-tool:active { transform: translateY(0) scale(.98); }
.vf-accent { --c: var(--accent); --c-text: var(--accent-text); }
/* Couleur littérale → le jumeau TEXTE doit suivre --c (sinon il reste sur --accent-text hérité). */
.vf-gray { --c: #7a8a99; --c-text: var(--c); }
.vf-orange { --c: #ec6b2d; --c-text: var(--c); }
.vf-green { --c: #2d7a4f; --c-text: var(--c); }
.vf-wide { width: 100%; justify-content: center; }
.vf-ghost { background: var(--surface); box-shadow: var(--shadow-sm); padding: 5px 11px; font-size: .76rem; }

/* ── Problème d'un cas (Voir fiche) — js/probleme-cas.js ──────────────────────
   Encadré discret SOUS les dates : on vient y lire ce qui bloque avant de choisir
   une nouvelle date. Tokens uniquement (--danger/--surface) → dark mode suivi. */
.vf-prob { margin-top: 10px; padding: 9px 11px; border-radius: 11px; display: flex; flex-direction: column; gap: 6px;
  background: color-mix(in srgb, var(--danger) 8%, var(--surface)); border: 1.5px solid color-mix(in srgb, var(--danger) 28%, var(--surface)); }
.vf-prob-hd { font-size: .66rem; font-weight: 800; letter-spacing: .4px; text-transform: uppercase; color: var(--danger); }
.vf-prob-txt { font-size: .84rem; font-weight: 600; color: var(--text); line-height: 1.4; overflow-wrap: anywhere; }
.vf-prob-meta { font-size: .68rem; color: var(--text); opacity: .6; }
/* Contenu de l'explication dans le petit panneau ancré partagé (.ais-pop), ouvert
   depuis la mention de « À décaler ». Réutilise les lignes de la carte de la fiche
   — une seule écriture du texte et de sa signature. */
.ais-pop--prob { max-width: 340px; }
.prob-pop { display: flex; flex-direction: column; gap: 6px; padding: 2px 2px 0; }
.prob-pop .vf-prob-txt { font-size: .85rem; }

html[data-theme="dark"] .vf-livr-red { background: #3a1a1a; color: #ef9a9a; border-color: #5a2a2a; }
html[data-theme="dark"] .vf-viewer { background: #f4f6f9; }

/* 920 et non 760 : entre les deux, la colonne d'infos (min 560 px) laissait à la
   prescription 200-340 px — illisible. Empilée, la fiche reprend toute la
   largeur. Concerne les fenêtres PC étroites ET le Fold déplié zoomé (+1/+2 →
   mise en page 911/848 px). Le rendu téléphone a ses propres règles
   (html.mobile-zoom-default, plus bas) : rien ne change pour lui. */
@media (max-width: 920px) {
  .vf-body { grid-template-columns: 1fr; }
  .vf-fiche { border-left: none; border-top: 1px solid var(--border); }
}

/* ── MOBILE (S24, auto-zoom) ── Le @media 760 ne se déclenche PAS sur le tel (rend >768px) :
   on scope sur la classe `html.mobile-zoom-default` (posée uniquement sur smartphone).
   But : PDF en GRAND. Modale quasi plein écran → infos condensées en haut (frise pleine
   largeur + Dates & Résumé côte à côte) → prescription qui prend tout le bas. */
html.mobile-zoom-default .vf-overlay { padding: 8px; }
/* Modale ajustée à SON contenu (plafond 96vh) → elle se termine juste sous la fiche,
   sans bande vide (le viewer ne s'étire plus au-delà du PDF). */
html.mobile-zoom-default .vf-modal { width: 100%; max-width: 98vw; height: auto; max-height: 96vh; }
html.mobile-zoom-default .vf-body { display: flex; flex-direction: column; min-height: 0; }
html.mobile-zoom-default .vf-info { flex: none; display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: min-content;
  gap: 10px; padding: 12px 14px; overflow: visible; }
html.mobile-zoom-default .vf-info > .vf-tl, html.mobile-zoom-default .vf-info > .ec-frise { grid-column: 1 / -1; }
html.mobile-zoom-default .vf-fiche { flex: 0 1 auto; min-height: 0; border-left: none; border-top: 1px solid var(--border); }
html.mobile-zoom-default .vf-viewer { flex: none; min-height: 360px; }
/* Aperçu rendu dans un cadre isolé (<iframe> : bon HTML servi depuis R2) : le
   doigt ne traverse PAS un cadre — ni le balayage entre fiches, ni le tap
   « agrandir » n'y arriveraient. Sur téléphone l'aperçu redevient donc une
   image qu'on lit ; le document complet reste accessible en l'agrandissant. */
html.mobile-zoom-default .vf-viewer iframe { pointer-events: none; }
/* Colonne d'infos en 2 colonnes sur le tel : la carte Actions prend toute la
   largeur, sinon ses boutons tombent à ~85px et les libellés sont tronqués. */
html.mobile-zoom-default .vf-info > .vf-acts { grid-column: 1 / -1; }

/* ============================================================
   Onglet « Règles » (Paramètres) — design 2026 : halo, motion,
   segmented controls, cartes de choix, combobox. Réagit au
   branding tenant (var(--accent)/--teal/--grad) + dark mode.
   ============================================================ */
#pm-regles-content { font-family: 'DM Sans', sans-serif; }
.cr-hero-sub { font-size: .8rem; color: var(--muted); line-height: 1.5; margin: 0; max-width: 56ch; }

.cr-add { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 18px;
  padding: 11px 18px; border: none; border-radius: 13px; cursor: pointer;
  font-family: inherit; font-size: .84rem; font-weight: 700; color: #fff; background: var(--grad);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-fast); }
.cr-add:hover { transform: translateY(-2px) scale(1.015); box-shadow: 0 12px 32px color-mix(in srgb, var(--accent) 52%, transparent); }
.cr-add .ic { width: 18px; height: 18px; }

/* Bandeau « des règles font double emploi » — proposition de regroupement de
   l'existant. Teinté var(--teal) (et non --accent) pour se lire comme une
   SUGGESTION et non comme une alerte : rien n'est cassé, il y a juste mieux à
   faire. Tokens uniquement → suit le branding du labo et le mode nuit. */
.cr-dupes { display: flex; align-items: center; gap: 13px; margin: -6px 0 18px; padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--teal) 42%, var(--border)); border-radius: 13px;
  background: color-mix(in srgb, var(--teal) 9%, var(--surface));
  animation: crFadeUp var(--dur-base) var(--ease-out) backwards; }
.cr-dupes-ic { display: inline-flex; flex: none; color: var(--teal-text); }
.cr-dupes-ic .ic { width: 20px; height: 20px; }
.cr-dupes-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cr-dupes-t { font-size: .8rem; font-weight: 700; color: var(--text); }
.cr-dupes-d { font-size: .72rem; color: var(--muted); line-height: 1.45; }
.cr-dupes-btn { flex: none; padding: 8px 15px; border: none; border-radius: 10px; cursor: pointer;
  font-family: inherit; font-size: .76rem; font-weight: 700; color: #fff; background: var(--grad);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 32%, transparent);
  transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-fast); }
.cr-dupes-btn:hover { transform: translateY(-1px); box-shadow: 0 10px 24px color-mix(in srgb, var(--accent) 44%, transparent); }
.cr-dupes-btn:active { transform: translateY(0); }
/* Téléphone : le bouton passe sous le texte plutôt que d'écraser la phrase.
   Scopé par la classe (jamais @media : le S24 rend > 768px — CONVENTIONS R21). */
html.mobile-zoom-default .cr-dupes { flex-wrap: wrap; }
html.mobile-zoom-default .cr-dupes-btn { width: 100%; padding: 10px 15px; }

.cr-list { display: flex; flex-direction: column; gap: 10px; }
/* Liste groupée par portée (cabinet / praticien) */
.cr-group-block { display: flex; flex-direction: column; gap: 10px; }
.cr-group-block + .cr-group-block { margin-top: 16px; }
.cr-group { display: flex; align-items: center; gap: 8px; padding: 2px 2px 4px; }
.cr-group-ic { display: inline-flex; color: var(--accent-text); }
.cr-group-ic .ic { width: 15px; height: 15px; }
.cr-group-name { font-size: .82rem; font-weight: 700; color: var(--text); letter-spacing: .2px; }
.cr-group-count { font-size: .66rem; font-weight: 700; color: var(--accent-text); background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; }
.cr-card { position: relative; display: flex; gap: 12px; align-items: flex-start;
  padding: 13px 15px; border-radius: 15px; border: 1px solid var(--border); background: var(--surface);
  box-shadow: 0 4px 22px color-mix(in srgb, var(--accent) 8%, transparent);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out); }
.cr-card:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  box-shadow: 0 12px 34px color-mix(in srgb, var(--accent) 18%, transparent); }
.cr-card.is-off { opacity: .55; }
.cr-card-ic { flex-shrink: 0; width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-text); }
.cr-card-ic .ic { width: 20px; height: 20px; }
.cr-card-body { flex: 1; min-width: 0; }
.cr-card-badges { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 5px; }
.cr-card-text { font-size: .82rem; line-height: 1.5; color: var(--text); }
.cr-card-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.cr-pill { display: inline-flex; align-items: center; gap: 4px; font-size: .64rem; font-weight: 700;
  padding: 3px 9px; border-radius: 99px; white-space: nowrap; }
.cr-pill .ic { width: 12px; height: 12px; }
.cr-pill--portee { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent-text); }
.cr-pill--sur { background: color-mix(in srgb, var(--teal) 22%, var(--surface)); color: color-mix(in srgb, var(--teal) 65%, var(--text)); }
.cr-pill--ia { background: color-mix(in srgb, var(--gold) 26%, var(--surface)); color: color-mix(in srgb, color-mix(in srgb, var(--gold) 76%, var(--text)) 55%, var(--text)); }

.cr-iconbtn { width: 30px; height: 30px; border-radius: 9px; border: 1px solid transparent; background: transparent;
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--muted);
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast); }
.cr-iconbtn:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-text); border-color: var(--border); }
.cr-iconbtn.is-del:hover { background: color-mix(in srgb, var(--danger) 14%, var(--surface)); color: var(--danger); }
/* Œil « rappelée dans le post-it Rules » : allumé aux couleurs du post-it (le lien
   visuel avec la note jaune), éteint quand la règle est volontairement muette. */
.cr-iconbtn.cr-postit { color: color-mix(in srgb, var(--note-border) 72%, var(--text)); }
.cr-iconbtn.cr-postit:hover { background: color-mix(in srgb, var(--note-border) 16%, var(--surface));
  color: color-mix(in srgb, var(--note-border) 85%, var(--text)); border-color: var(--border); }
/* Masquée : l'œil BARRÉ doit se lire d'un coup d'œil — c'est le trait qui porte
   l'information, pas un effacement (un bouton pâle se lit « désactivé », pas
   « muet »). Encre neutre, pleine opacité. */
.cr-iconbtn.cr-postit.is-off { color: var(--muted); }
.cr-iconbtn .ic { width: 16px; height: 16px; }

/* ============================================================
   Onglet « Mes données » (export RGPD — js/export-donnees.js).
   Réutilise le vocabulaire .cr-card/.cr-add ci-dessus (l'en-tête vient de
   .pmh-*) ; ici uniquement les compléments (badge emoji,
   barre de progression). Tokens only → dark mode + tenant safe.
   ============================================================ */
#pm-donnees-content { font-family: 'DM Sans', sans-serif; }
.edx-badge { font-size: 26px; }
.edx-ic { font-size: 19px; }
.edx-card { align-items: center; }
.edx-btn { margin-bottom: 0; white-space: nowrap; }
.edx-note { margin-top: 7px; color: var(--muted); font-size: .76rem; }
.edx-progress { margin-top: 12px; }
.edx-progress-top { display: flex; align-items: center; gap: 8px; margin-bottom: 7px;
  font-size: .78rem; font-weight: 600; color: var(--text); }
.edx-spin { flex: none; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-top-color: var(--accent); animation: edxSpin .8s linear infinite; }
.edx-bar { height: 8px; border-radius: 99px; overflow: hidden; border: 1px solid var(--border);
  background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.edx-bar-fill { height: 100%; width: 0%; border-radius: inherit; background: var(--grad);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 45%, transparent);
  transition: width var(--dur-enter) ease; }
/* Terminé (ou échec) : le rouet se fige. Il continuait de tourner après
   « Terminé ✓ », donnant à croire qu'un export était encore en cours (n°181). */
.edx-progress.is-done .edx-spin { animation: none !important; opacity: .5;
  border-top-color: color-mix(in srgb, var(--accent) 55%, transparent); }
@keyframes edxSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .edx-spin { animation: none; }
  .edx-bar-fill { transition: none; }
}

.cr-switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; display: inline-block; cursor: pointer; }
.cr-switch input { opacity: 0; width: 0; height: 0; }
.cr-switch span { position: absolute; inset: 0; border-radius: 99px; background: var(--border); transition: background var(--dur-base); }
.cr-switch span::before { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform var(--dur-base) var(--ease-spring); }
.cr-switch input:checked + span { background: var(--accent); }
.cr-switch input:checked + span::before { transform: translateX(16px); }

.cr-form { border: 1px solid var(--border); border-radius: 18px; padding: 18px 18px 16px; background: var(--surface);
  box-shadow: 0 12px 44px color-mix(in srgb, var(--accent) 16%, transparent); margin-bottom: 18px; }
.cr-form-title { display: flex; align-items: center; gap: 9px; font-size: .95rem; font-weight: 800; color: var(--text); margin-bottom: 16px; }
.cr-form-title .ic { color: var(--accent-text); }
.cr-field { margin-bottom: 14px; }
.cr-label { display: block; font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: 7px; }
.cr-label b { color: var(--accent-text); font-weight: 800; }

.cr-seg { display: grid; gap: 6px; }
.cr-seg.cols3 { grid-template-columns: repeat(3, 1fr); }
.cr-seg.cols2 { grid-template-columns: repeat(2, 1fr); }
.cr-seg button { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 10px 6px;
  border: 1.5px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--muted);
  font-family: inherit; font-size: .74rem; font-weight: 600; cursor: pointer; transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast); }
.cr-seg button .ic { width: 19px; height: 19px; }
.cr-seg button:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); color: var(--text); }
.cr-seg button.active { border-color: var(--accent); color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 22%, transparent); }

.cr-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.cr-choice { display: flex; gap: 10px; align-items: flex-start; text-align: left; padding: 11px 12px;
  border: 1.5px solid var(--border); border-radius: 13px; background: var(--surface); cursor: pointer; font-family: inherit; transition: border-color var(--dur-fast), transform var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast); }
.cr-choice:hover { border-color: color-mix(in srgb, var(--teal) 45%, var(--border)); transform: translateY(-1px); }
.cr-choice.active { border-color: var(--teal); background: color-mix(in srgb, var(--teal) 9%, var(--surface));
  box-shadow: 0 6px 18px color-mix(in srgb, var(--teal) 22%, transparent); }
.cr-choice-ic { flex-shrink: 0; width: 32px; height: 32px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--teal) 16%, var(--surface)); color: color-mix(in srgb, var(--teal) 72%, var(--text)); }
.cr-choice.active .cr-choice-ic { background: var(--teal); color: #fff; }
.cr-choice-t { display: block; font-size: .78rem; font-weight: 700; color: var(--text); line-height: 1.25; }
.cr-choice-d { display: block; font-size: .66rem; color: var(--muted); margin-top: 3px; line-height: 1.35; }
.cr-choice--ia.active { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 10%, var(--surface)); box-shadow: 0 6px 18px color-mix(in srgb, var(--gold) 22%, transparent); }
.cr-choice--ia .cr-choice-ic { background: color-mix(in srgb, var(--gold) 18%, var(--surface)); color: color-mix(in srgb, var(--gold) 76%, var(--text)); }
.cr-choice--ia.active .cr-choice-ic { background: var(--gold); color: #fff; }

.cr-input, .cr-select, .cr-textarea { width: 100%; padding: 9px 11px; border: 1.5px solid var(--border); border-radius: 11px;
  font-family: inherit; font-size: .82rem; background: var(--surface); color: var(--text); box-sizing: border-box;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.cr-input:focus, .cr-select:focus, .cr-textarea:focus { outline: none; border-color: var(--teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 25%, transparent); }
.cr-textarea { resize: vertical; min-height: 54px; }
/* Bouton « Traduire » (note de règle FR → EN, encadré Rules du PDF anglais) */
.cr-translate { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 7px; padding: 6px 12px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 45%, var(--border)); border-radius: 9px; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 10%, var(--surface)); color: var(--accent-text); font-size: .76rem; font-weight: 600; }
.cr-translate:hover:not([disabled]) { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); }
.cr-translate[disabled] { opacity: .6; cursor: progress; }
.cr-translate .ic { width: 14px; height: 14px; }
.cr-row2 { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: center; }
.cr-arrow { color: var(--muted); display: flex; align-items: center; }

.cr-combo { position: relative; }
.cr-combo-lead { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--accent-text); pointer-events: none; z-index: 1; }
.cr-combo-lead .ic { width: 17px; height: 17px; }
.cr-combo .cr-input { padding-left: 34px; }
.cr-combo-pop { position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; right: 0; max-height: 240px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: 13px; padding: 5px;
  box-shadow: 0 16px 44px color-mix(in srgb, var(--accent) 22%, transparent), 0 4px 14px rgba(0,0,0,.12);
  animation: crPop var(--dur-base) ease backwards; }
.cr-combo-opt { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 9px; cursor: pointer; font-size: .8rem; color: var(--text); }
.cr-combo-opt .ic { width: 16px; height: 16px; color: var(--muted); flex-shrink: 0; }
.cr-combo-opt:hover, .cr-combo-opt.active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.cr-combo-opt mark { background: color-mix(in srgb, var(--teal) 38%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.cr-combo-empty { padding: 11px; font-size: .76rem; color: var(--muted); text-align: center; }
/* Combo multi : étiquettes des cibles choisies + champ de recherche */
.cr-combo-row { position: relative; }
.cr-combo-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 7px; }
.cr-chip--portee2 { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent-text); }
.cr-chip--portee2 .ic { width: 13px; height: 13px; }
.cr-combo-opt.sel { background: color-mix(in srgb, var(--accent) 13%, var(--surface)); font-weight: 600; }
.cr-combo-opt .cr-dd-check { margin-left: auto; color: var(--accent-text); }
.cr-combo-add { color: var(--accent-text); font-weight: 600; }

/* Menu d'actes custom (single + multi-sélection) */
.cr-dd { position: relative; }
.cr-dd-display { width: 100%; display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 7px 11px;
  border: 1.5px solid var(--border); border-radius: 11px; background: var(--surface); color: var(--text);
  font-family: inherit; font-size: .82rem; text-align: left; cursor: pointer; transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.cr-dd-display:hover { border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.cr-dd.open .cr-dd-display { border-color: var(--teal); box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 25%, transparent); }
.cr-dd-display > span:first-child { flex: 1; min-width: 0; }
.cr-dd-ph { color: var(--muted); }
.cr-dd-chev { margin-left: auto; color: var(--muted); flex-shrink: 0; transition: transform var(--dur-base); }
.cr-dd.open .cr-dd-chev { transform: rotate(180deg); }
.cr-dd-chips { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.cr-chip { display: inline-flex; align-items: center; gap: 2px; font-family: 'DM Mono', monospace; font-weight: 700; font-size: .68rem;
  padding: 3px 3px 3px 8px; border-radius: 6px; background: color-mix(in srgb, var(--accent) 13%, var(--surface)); color: var(--accent-text); }
.cr-chip--conj { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent-text); }
.cr-chip--adj { background: color-mix(in srgb, #d6457f 18%, var(--surface)); color: color-mix(in srgb, #d6457f 72%, var(--text)); }
.cr-chip--flag { background: color-mix(in srgb, #e8961e 20%, var(--surface)); color: color-mix(in srgb, #e8961e 74%, var(--text)); }
/* Jeton de GROUPE (catégorie entière / famille du catalogue) : même teinte que sa colonne,
   contour tireté pour dire « plusieurs actes » d'un coup d'œil. */
.cr-chip--groupe { outline: 1.5px dashed currentColor; outline-offset: -1.5px; }
.cr-chip-x { display: inline-flex; border: none; background: transparent; color: inherit; cursor: pointer; padding: 1px; border-radius: 50%; opacity: .7; }
.cr-chip-x:hover { opacity: 1; background: color-mix(in srgb, var(--accent) 22%, transparent); }
.cr-chip-x .ic { width: 12px; height: 12px; }
.cr-dd-pop { padding: 0; overflow: hidden; }
/* Deux onglets « Familles » / « Actes » (03/09/2026) : la liste unique devenait trop
   longue. Onglet actif = fond accent léger, comme les segments .cr-seg du formulaire. */
.cr-dd-tabs { display: flex; gap: 4px; padding: 6px 6px 0; background: var(--surface); }
.cr-dd-tab { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 6px; border: 1px solid transparent; border-radius: 9px; background: transparent;
  font-family: inherit; font-size: .7rem; font-weight: 700; color: var(--muted); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.cr-dd-tab:hover { color: var(--text); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.cr-dd-tab.is-on { color: var(--accent-text); background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
.cr-dd-tab .ic { flex-shrink: 0; }
.cr-dd-tab-n { font-style: normal; font-size: .58rem; font-weight: 700; opacity: .65; }
/* Bandeau « tu ne vois que cette famille » en tête de l'onglet Actes. */
.cr-dd-filt { display: flex; align-items: center; gap: 6px; margin: 4px 4px 2px; padding: 6px 8px; border-radius: 8px;
  background: color-mix(in srgb, var(--teal) 12%, var(--surface)); color: color-mix(in srgb, var(--teal) 72%, var(--text));
  font-size: .68rem; font-weight: 700; }
.cr-dd-filt > span { flex: 1; }
.cr-dd-filt > em { font-style: normal; font-size: .58rem; opacity: .75; }
.cr-dd-filt-x { display: inline-flex; border: none; background: transparent; color: inherit; cursor: pointer;
  padding: 2px; border-radius: 50%; opacity: .75; transition: opacity var(--dur-fast) var(--ease-out); }
.cr-dd-filt-x:hover { opacity: 1; background: color-mix(in srgb, var(--teal) 22%, transparent); }
.cr-dd-search { width: 100%; box-sizing: border-box; border: none; border-bottom: 1px solid var(--border);
  padding: 10px 12px; font-family: inherit; font-size: .8rem; background: var(--surface); color: var(--text); }
.cr-dd-search:focus { outline: none; }
.cr-dd-list { max-height: 230px; overflow-y: auto; padding: 5px; }
.cr-dd-group { font-size: .6rem; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); padding: 9px 10px 4px; }
.cr-dd-opt { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 9px; cursor: pointer; font-size: .8rem; color: var(--text); }
.cr-dd-opt:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.cr-dd-opt > span { flex: 1; }
.cr-dd-opt mark { background: color-mix(in srgb, var(--teal) 38%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.cr-dd-opt.sel { background: color-mix(in srgb, var(--teal) 12%, var(--surface)); color: color-mix(in srgb, var(--teal) 70%, var(--text)); font-weight: 600; }
.cr-dd-check { color: var(--teal-text); flex-shrink: 0; }
.cr-dd-fam { font-style: normal; font-size: .54rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--teal-text); background: color-mix(in srgb, var(--teal) 16%, var(--surface)); padding: 1px 5px; border-radius: 4px; margin-left: 6px; vertical-align: middle; }
/* Repère de colonne (03/09/2026) : bleu = prothèse fixe, rose = amovible, ambre = case
   spéciale — le même code couleur que les chips du formulaire et le résumé IA, pour
   reconnaître d'un coup d'œil ce qu'on est en train de choisir. */
.cr-dd-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--muted); opacity: .4; }
.cr-dd-opt.is-conj .cr-dd-dot { background: var(--accent); opacity: 1; }
.cr-dd-opt.is-adj  .cr-dd-dot { background: #d6457f; opacity: 1; }
.cr-dd-opt.is-flag .cr-dd-dot { background: #e8961e; opacity: 1; }
.cr-dd-opt.is-conj .cr-dd-fam { color: var(--accent-text); background: color-mix(in srgb, var(--accent) 16%, var(--surface)); }
.cr-dd-opt.is-adj  .cr-dd-fam { color: color-mix(in srgb, #d6457f 74%, var(--text)); background: color-mix(in srgb, #d6457f 16%, var(--surface)); }
.cr-dd-opt.is-conj:hover { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.cr-dd-opt.is-adj:hover  { background: color-mix(in srgb, #d6457f 12%, var(--surface)); }
.cr-dd-opt.is-flag:hover { background: color-mix(in srgb, #e8961e 12%, var(--surface)); }
.cr-dd-group.is-conj { color: var(--accent-text); }
.cr-dd-group.is-adj  { color: color-mix(in srgb, #d6457f 70%, var(--text)); }
.cr-dd-filt.is-adj { background: color-mix(in srgb, #d6457f 12%, var(--surface)); color: color-mix(in srgb, #d6457f 74%, var(--text)); }
.cr-dd-filt.is-adj .cr-dd-filt-x:hover { background: color-mix(in srgb, #d6457f 22%, transparent); }
.cr-dd-filt.is-conj { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-text); }
.cr-dd-filt.is-conj .cr-dd-filt-x:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }

/* Conditions supplémentaires (ET) — chaque ligne se lit comme une phrase :
   « ET [un acte est coché] [Implant] ». Grille : le libellé et la corbeille sont
   à largeur fixe, la valeur prend le reste (aucune colonne qui saute). */
.cr-conds { display: flex; flex-direction: column; gap: 7px; margin-top: 9px; }
.cr-cond { display: grid; grid-template-columns: auto minmax(0, 11.5rem) minmax(0, 1fr) auto; gap: 7px; align-items: center; }
.cr-cond-lead { font-size: .6rem; font-weight: 800; letter-spacing: .09em; color: var(--muted);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border-radius: 6px; padding: 3px 7px; }
.cr-cond-type { height: 36px; padding: 0 8px; font-size: .76rem; }
.cr-cond-val .cr-input { height: 36px; }
.cr-cond-val .cr-dd-display { min-height: 36px; padding-top: 4px; padding-bottom: 4px; }
.cr-addcond { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; padding: 6px 12px;
  border: 1.5px dashed color-mix(in srgb, var(--accent) 45%, var(--border)); border-radius: 9px; cursor: pointer;
  background: transparent; color: var(--accent-text); font-family: inherit; font-size: .72rem; font-weight: 700;
  transition: background var(--dur-fast), border-color var(--dur-fast); }
.cr-addcond:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border-style: solid; }
.cr-addcond .ic { width: 14px; height: 14px; }
.cr-cond-max { display: flex; gap: 6px; align-items: flex-start; font-size: .66rem; color: var(--muted); }
.cr-cond-max .ic { width: 13px; height: 13px; flex-shrink: 0; margin-top: 1px; }
@media (max-width: 640px) { .cr-cond { grid-template-columns: auto 1fr auto; } .cr-cond-val { grid-column: 1 / -1; } }
html.mobile-zoom-default .cr-cond { grid-template-columns: auto 1fr auto; }
html.mobile-zoom-default .cr-cond-val { grid-column: 1 / -1; }

/* Note « cette condition ne change rien » — signale une redondance sans bloquer
   (le réglage reste valide, on propose juste de le simplifier). */
.cr-hint { display: flex; gap: 7px; align-items: flex-start; margin-top: 8px; padding: 8px 10px; border-radius: 10px;
  font-size: .68rem; line-height: 1.45; color: var(--text);
  background: color-mix(in srgb, var(--gold) 10%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--gold) 32%, var(--border)); }
.cr-hint .ic { flex-shrink: 0; margin-top: 1px; width: 14px; height: 14px; color: color-mix(in srgb, var(--gold) 76%, var(--text)); }
.cr-hint-btn { border: none; background: none; padding: 0; font: inherit; font-weight: 700; cursor: pointer;
  color: var(--accent-text); text-decoration: underline; text-underline-offset: 2px; }
.cr-hint-btn:hover { text-decoration: none; }

.cr-apercu { display: flex; gap: 9px; align-items: flex-start; margin-top: 4px; padding: 11px 13px; border-radius: 12px;
  background: radial-gradient(130% 150% at 0% 0%, color-mix(in srgb, var(--teal) 12%, transparent), transparent 70%), color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border)); font-size: .8rem; color: var(--text); line-height: 1.5; }
.cr-apercu .ic { color: var(--accent-text); flex-shrink: 0; margin-top: 1px; width: 16px; height: 16px; }

.cr-actions { display: flex; gap: 9px; margin-top: 16px; }
.cr-save { display: inline-flex; align-items: center; gap: 7px; padding: 10px 18px; border: none; border-radius: 11px; cursor: pointer;
  font-family: inherit; font-size: .82rem; font-weight: 700; color: #fff; background: var(--grad);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--accent) 38%, transparent); transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-fast); }
.cr-save:hover { transform: translateY(-2px); box-shadow: 0 12px 30px color-mix(in srgb, var(--accent) 50%, transparent); }
.cr-save .ic { width: 16px; height: 16px; }
.cr-cancel { padding: 10px 18px; border: 1.5px solid var(--border); border-radius: 11px; cursor: pointer;
  font-family: inherit; font-size: .82rem; font-weight: 600; color: var(--muted); background: transparent; transition: color var(--dur-fast), border-color var(--dur-fast); }
.cr-cancel:hover { color: var(--text); border-color: var(--muted); }

.cr-empty { text-align: center; padding: 30px 18px; border: 1.5px dashed var(--border); border-radius: 16px; color: var(--muted); }
.cr-empty .ic { width: 34px; height: 34px; opacity: .5; margin-bottom: 8px; }
.cr-empty-t { font-size: .84rem; font-weight: 600; color: var(--text); }
.cr-empty-d { font-size: .74rem; margin-top: 3px; }

/* Barre de filtre de la liste (recherche + cabinet + praticien).
   Réutilise le vocabulaire des menus existants (.cr-combo-pop / .cr-dd-*) :
   seuls les compléments propres à la barre vivent ici. Tokens only → dark
   mode + branding tenant automatiques. */
.cr-filter { margin-bottom: 14px; padding: 10px 11px; border: 1px solid var(--border); border-radius: 15px;
  background: color-mix(in srgb, var(--accent) 5%, var(--surface)); box-shadow: var(--shadow-sm); }
.cr-filter-row { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px; align-items: center; }
.cr-filter-search { position: relative; display: flex; align-items: center; }
.cr-filter-search > .ic { position: absolute; left: 11px; width: 16px; height: 16px; color: var(--accent-text); pointer-events: none; }
.cr-filter-search .cr-input { height: 40px; padding-left: 34px; }
.cr-filter-search .cr-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

/* Sélecteur cabinet / praticien = un vrai champ de saisie : on clique, on tape,
   la liste se filtre. Croix (filtre posé) et chevron (champ libre) coexistent
   dans le DOM, .is-set choisit lequel s'affiche → bascule sans re-render. */
.cr-fdd { position: relative; display: flex; align-items: center; }
.cr-fdd-lead { position: absolute; left: 11px; display: inline-flex; color: var(--muted); pointer-events: none; z-index: 1;
  transition: color var(--dur-fast); }
.cr-fdd-lead .ic { width: 16px; height: 16px; }
.cr-fdd-input { height: 40px; padding-left: 34px; padding-right: 32px; font-weight: 600; text-overflow: ellipsis; }
.cr-fdd-input::placeholder { font-weight: 500; color: var(--muted); }
.cr-fdd-input:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.cr-fdd.is-set .cr-fdd-input { border-color: var(--accent); color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.cr-fdd.is-set .cr-fdd-lead { color: var(--accent-text); }
.cr-fdd-chev { position: absolute; right: 10px; display: inline-flex; color: var(--muted); pointer-events: none;
  transition: transform var(--dur-base); }
.cr-fdd-chev .ic { width: 15px; height: 15px; }
.cr-fdd.open .cr-fdd-chev { transform: rotate(180deg); }
.cr-fdd-x { position: absolute; right: 8px; display: none; border: none; background: transparent; color: var(--accent-text);
  cursor: pointer; padding: 3px; border-radius: 50%; opacity: .8; transition: opacity var(--dur-fast), background var(--dur-fast); }
.cr-fdd-x:hover { opacity: 1; background: color-mix(in srgb, var(--accent) 22%, transparent); }
.cr-fdd-x .ic { width: 13px; height: 13px; }
.cr-fdd.is-set .cr-fdd-x { display: inline-flex; }
.cr-fdd.is-set .cr-fdd-chev { display: none; }
.cr-fdd-nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cr-fdd-n { flex-shrink: 0; font-size: .62rem; font-weight: 700; color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; }

.cr-filter-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 9px; }
.cr-filter-count { font-size: .72rem; font-weight: 600; color: var(--muted); }
.cr-filter-count b { color: var(--accent-text); }
.cr-ftog, .cr-freset { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 99px; cursor: pointer;
  font-family: inherit; font-size: .68rem; font-weight: 700; border: 1px solid var(--border);
  background: var(--surface); color: var(--muted);
  transition: color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast); }
.cr-ftog .ic, .cr-freset .ic { width: 12px; height: 12px; }
.cr-ftog:hover, .cr-freset:hover { color: var(--text); border-color: var(--muted); }
.cr-ftog.on { color: var(--accent-text); border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
.cr-freset { margin-left: auto; }
.cr-card-text mark { background: color-mix(in srgb, var(--teal) 38%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.cr-empty-btn { margin-top: 13px; }

/* Entrée des cartes de règles : l'animation et le stagger (animation-delay posé
   par cabinet-rules.js) existaient sans jamais être branchés — les cartes
   apparaissaient d'un bloc (audit n°46). Motif .no-anim des autres listes : le
   décalage ne se rejoue pas à chaque filtre. */
.cr-list:not(.no-anim) .cr-card { animation: crFadeUp var(--dur-enter) var(--ease-out) backwards; }
@media (prefers-reduced-motion: reduce) { .cr-list .cr-card { animation: none; } }
@keyframes crFadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes crPop { from { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: none; } }

@media (max-width: 640px) { .cr-choices { grid-template-columns: 1fr; } .cr-filter-row { grid-template-columns: 1fr; } }
/* Téléphone : le S24 rend > 768px → on cible la classe, jamais un @media (R21). */
html.mobile-zoom-default .cr-filter-row { grid-template-columns: 1fr; }

/* ════════════════════════════════════════════════════════════
   BANNIÈRE « Nouvelle version disponible » (cf. js/sw-register.js)
   N'apparaît QUE si l'utilisateur est actif au moment de la MAJ (sinon
   reload silencieux direct). Couleurs via variables → dark mode +
   branding tenant respectés automatiquement.
   ════════════════════════════════════════════════════════════ */
.sw-update-banner {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  transform: translateX(-50%);
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px 9px 16px;
  max-width: calc(100vw - 24px);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-md);
  font-family: 'DM Sans', sans-serif;
  font-size: .92rem;
  animation: swUpdateIn var(--dur-base) ease backwards;
}
@keyframes swUpdateIn {
  from { opacity: 0; transform: translate(-50%, 14px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
.sw-update-ic {
  font-size: 1.05rem;
  color: var(--accent-text);
  line-height: 1;
}
.sw-update-txt { font-weight: 600; white-space: nowrap; }
.sw-update-btn {
  border: none;
  background: var(--grad, var(--accent));
  color: #fff;
  font-family: inherit;
  font-weight: 700;
  font-size: .88rem;
  padding: 7px 14px;
  border-radius: 10px;
  cursor: pointer;
  white-space: nowrap;
  transition: filter var(--dur-fast);
}
.sw-update-btn:hover { filter: brightness(1.06); }
.sw-update-btn:disabled { opacity: .7; cursor: default; }
.sw-update-close {
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 4px 6px;
}
.sw-update-close:hover { color: var(--text); }

/* ════════════════════════════════════════════════════════════════════
   SHELL PARAMÈTRES / ADMINISTRATION — refonte "clinical luxury" (2026-06-26)
   Namespace .pmx-* . Tout en tokens (var(--accent/--surface/--text/--border/
   --teal)) → dark-mode auto + multi-tenant (accent = couleur du labo).
   Animations CSS only, désactivées en prefers-reduced-motion.
   ════════════════════════════════════════════════════════════════════ */

.pmx-overlay {
  position: fixed; inset: 0; z-index: 900;
  display: flex; align-items: center; justify-content: center;
  padding: 3vh 2vw;
  background: color-mix(in srgb, #0a0e14 52%, transparent);
  -webkit-backdrop-filter: var(--ov-blur, blur(6px)); backdrop-filter: var(--ov-blur, blur(6px));
  animation: pmx-overlay-in var(--dur-base) var(--ease-out);
}
@keyframes pmx-overlay-in { from { opacity: 0; } to { opacity: 1; } }

.pmx-shell {
  position: relative;
  display: flex; flex-direction: column;
  width: var(--ck-shell-w); max-width: var(--ck-shell-maxw); height: var(--ck-shell-h);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  overflow: hidden;
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--text) 4%, transparent) inset,
    0 30px 80px -28px color-mix(in srgb, #000 60%, transparent),
    0 0 60px -20px color-mix(in srgb, var(--accent) 35%, transparent);
  animation: pmx-shell-in var(--dur-enter) var(--ease-out);
}
.pmx-shell--full { width: var(--ck-shell-w); max-width: var(--ck-shell-maxw); height: var(--ck-shell-h); }
@keyframes pmx-shell-in {
  from { opacity: 0; transform: translateY(14px) scale(.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ── Header avec aura accent/teal (profondeur, pas de "slop") ── */
.pmx-head {
  position: relative; flex-shrink: 0;
  display: flex; align-items: center; gap: 14px;
  padding: 15px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.pmx-head::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .9;
  background:
    radial-gradient(120% 180% at 0% 0%,   color-mix(in srgb, var(--accent) 13%, transparent), transparent 55%),
    radial-gradient(120% 180% at 100% 0%, color-mix(in srgb, var(--teal)   12%, transparent), transparent 55%);
}
.pmx-head > * { position: relative; }
.pmx-title { display: flex; align-items: center; gap: 11px; margin-right: auto; }
.pmx-title-ico {
  display: grid; place-items: center; width: 32px; height: 32px; border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 16%, var(--surface));
  color: var(--accent-text); font-size: 1rem;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent),
              0 0 18px -4px color-mix(in srgb, var(--accent) 55%, transparent);
}
/* Variante « pastille logo » (header Admin) : reprend le style des boutons de la
   barre principale (.tool .ti) — dégradé tenant + halo coloré + icône en contour
   blanc. Couleur via var(--accent) → multi-tenant. */
.pmx-title-ico--logo {
  background: linear-gradient(140deg, color-mix(in srgb, var(--ic, var(--accent)) 78%, #fff) 0%, var(--ic, var(--accent)) 100%);
  color: #fff; border: 2px solid var(--surface);
  box-shadow: 0 5px 14px color-mix(in srgb, var(--ic, var(--accent)) 45%, transparent);
}
.pmx-title-ico--logo svg {
  width: 19px; height: 19px; stroke: #fff; fill: none; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round; filter: drop-shadow(0 1px 1px rgba(0,0,0,.25));
}
.pmx-title-txt { font-size: 1.02rem; font-weight: 700; color: var(--text); letter-spacing: .1px; }
.pmx-title-sub { font-size: .76rem; color: var(--muted); margin-left: 2px; }

/* ═══ En-tête « hero » coloré — Paramètres & Facturation ═══
   Ces deux écrans gardaient un bandeau plat, alors que les autres onglets
   (Actes & codes, Historique IA, cockpit Digilab) ont un en-tête en dégradé
   profond. Recette dédiée — dégradé 125°, trame de 30px en fondu, halo radial,
   pastille d'icône à halo animé. (Elle était partagée avec .pm-actes-hero,
   retiré depuis au profit de la brique d'en-tête unique .pmh-*.)
   Une SEULE variable pilote la teinte : --pmxh, prise sur la couleur du
   bouton correspondant de la barre principale, pour que l'écran et son
   bouton se répondent. Les autres écrans en .pmx-head (Administration…)
   ne sont pas touchés : le sélecteur est scopé par identifiant. */
#modal-parametres > .pmx-shell > .pmx-head   { --pmxh: #8b4fd6; }  /* violet du bouton Paramètres */
#facturation-screen > .pmx-shell > .pmx-head { --pmxh: #0e8c5a; }  /* vert du bouton Facturation */

#modal-parametres > .pmx-shell > .pmx-head,
#facturation-screen > .pmx-shell > .pmx-head {
  border-bottom: none; overflow: hidden; color: #eaf6fb;
  background: linear-gradient(125deg,
    color-mix(in srgb, var(--pmxh) 66%, #07131e) 0%,
    color-mix(in srgb, var(--pmxh) 50%, #0a1020) 52%,
    color-mix(in srgb, var(--pmxh) 36%, #060a18) 100%);
}
html[data-theme="dark"] #modal-parametres > .pmx-shell > .pmx-head,
html[data-theme="dark"] #facturation-screen > .pmx-shell > .pmx-head {
  background: linear-gradient(125deg,
    color-mix(in srgb, var(--pmxh) 44%, #060d15) 0%,
    color-mix(in srgb, var(--pmxh) 34%, #060b14) 52%,
    color-mix(in srgb, var(--pmxh) 24%, #05080f) 100%);
}
/* ::before porte la trame ET le halo radial (deux calques de fond), ce qui
   libère ::after pour le faisceau animé du bas. */
#modal-parametres > .pmx-shell > .pmx-head::before,
#facturation-screen > .pmx-shell > .pmx-head::before {
  opacity: 1;
  background-image:
    radial-gradient(closest-side at 88% -40%, color-mix(in srgb, var(--pmxh) 55%, transparent), transparent),
    linear-gradient(rgba(255,255,255,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.07) 1px, transparent 1px);
  background-size: 420px 280px, 30px 30px, 30px 30px;
  background-repeat: no-repeat, repeat, repeat;
  -webkit-mask-image: linear-gradient(180deg, #000, transparent 92%);
  mask-image: linear-gradient(180deg, #000, transparent 92%);
}
/* Pastille d'icône — reprise de .dgl-logo (cockpit Digilab) et .hix-logo :
   ENCADRÉ BLANC (contour var(--surface), comme les boutons .tool .ti de la
   barre), dégradé à 3 arrêts, reliefs internes, flottement continu et halo
   pulsé. Les keyframes sont préfixées pmxh* pour ne rien écraser ailleurs. */
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico {
  position: relative; z-index: 1; width: 42px; height: 42px; border-radius: 13px;
  color: #fff; border: 2px solid var(--surface);
  background: linear-gradient(140deg,
    color-mix(in srgb, var(--pmxh) 55%, #fff) 0%,
    var(--pmxh) 58%,
    color-mix(in srgb, var(--pmxh) 72%, #000) 100%);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--pmxh) 55%, transparent),
              inset 0 1px 0 rgba(255,255,255,.38),
              inset 0 -6px 14px rgba(0,0,0,.22);
  animation: pmxhFloat 3.4s ease-in-out infinite;
}
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico:hover,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico:hover { animation-duration: 1.6s; }
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico::before,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico::before {
  content: ""; position: absolute; inset: -9px; border-radius: 17px; z-index: -1;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--pmxh) 72%, transparent), transparent 72%);
  filter: blur(6px); animation: pmxhPulse 2.8s ease-in-out infinite;
}
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico svg,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico svg {
  width: 22px; height: 22px; stroke: #fff; fill: none; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.35));
}
@keyframes pmxhFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes pmxhPulse { 0%,100% { opacity: .45; transform: scale(.92); } 50% { opacity: .9; transform: scale(1.08); } }
/* Faisceau lumineux qui balaie le bas de l'en-tête — même animation que la
   barre .hix-beam de l'Historique IA, pour que les onglets « respirent »
   pareil. Posé sur le bord bas, il remplace la bordure supprimée. */
#modal-parametres > .pmx-shell > .pmx-head::after,
#facturation-screen > .pmx-shell > .pmx-head::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 42%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.8), transparent);
  animation: pmxhBeam 3.6s ease-in-out infinite; pointer-events: none; z-index: 2;
}
@keyframes pmxhBeam { 0% { transform: translateX(-110%); } 100% { transform: translateX(340%); } }
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-txt,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-txt { color: #fff; }
#modal-parametres > .pmx-shell > .pmx-head .pmx-title-sub,
#facturation-screen > .pmx-shell > .pmx-head .pmx-title-sub { color: #cfe3f2; }
/* Croix et champ de recherche : posés sur le dégradé, donc en blanc translucide. */
#modal-parametres > .pmx-shell > .pmx-head .pmx-close,
#facturation-screen > .pmx-shell > .pmx-head .pmx-close {
  color: #eaf6fb; background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.22);
}
#modal-parametres > .pmx-shell > .pmx-head .pmx-close:hover,
#facturation-screen > .pmx-shell > .pmx-head .pmx-close:hover { background: rgba(255,255,255,.26); }
#modal-parametres > .pmx-shell > .pmx-head .pmx-search {
  color: #fff; background: rgba(255,255,255,.13); border-color: rgba(255,255,255,.24);
}
#modal-parametres > .pmx-shell > .pmx-head .pmx-search::placeholder { color: #cfe3f2; }
#modal-parametres > .pmx-shell > .pmx-head .pmx-search:focus {
  background: rgba(255,255,255,.2); border-color: rgba(255,255,255,.55);
  box-shadow: 0 0 0 3px rgba(255,255,255,.12);
}
@media (prefers-reduced-motion: reduce) {
  #modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico,
  #facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico,
  #modal-parametres > .pmx-shell > .pmx-head .pmx-title-ico::before,
  #facturation-screen > .pmx-shell > .pmx-head .pmx-title-ico::before,
  #modal-parametres > .pmx-shell > .pmx-head::after,
  #facturation-screen > .pmx-shell > .pmx-head::after { animation: none; }
}

.pmx-search {
  width: 210px; height: 34px; padding: 0 12px 0 32px;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface-2);
  color: var(--text); font-size: .82rem; font-family: 'DM Sans', sans-serif;
  transition: box-shadow var(--dur-fast), border-color var(--dur-fast), width var(--dur-base);
}
.pmx-search::placeholder { color: var(--muted); }
.pmx-search:focus {
  outline: none; border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); width: 240px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}
.pmx-search-wrap { position: relative; display: flex; align-items: center; }
.pmx-search-wrap::before {
  content: "\1F50D"; position: absolute; left: 10px; font-size: .8rem; opacity: .55; pointer-events: none;
}
.pmx-close {
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--muted); cursor: pointer; font-size: 1.05rem;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
}
.pmx-close:hover { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.pmx-close:active { transform: scale(.94); }

/* ── Corps : sidebar + contenu ── */
.pmx-body { flex: 1; display: flex; min-height: 0; }

.pmx-side {
  flex-shrink: 0; width: 210px; padding: 14px 12px; overflow-y: auto;
  border-right: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface-2) 60%, var(--surface));
}
.pmx-shell--full .pmx-side { width: 232px; }
.pmx-side-vide { padding: 14px 12px; font-size: .74rem; color: var(--muted); font-style: italic; }
:is(#modal-parametres,.acv-tarifs) .pm-acte-vide { padding: 26px 14px; text-align: center; color: var(--muted);
  font-size: .8rem; font-style: italic; }
.pmx-side-group {
  font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted); margin: 14px 10px 6px; opacity: .85;
}
.pmx-side-group:first-child { margin-top: 2px; }
/* Le titre de groupe du rail porte la MÊME couleur que l'étiquette de l'en-tête
   du panneau (voir .pmh-tag) : le rail et le panneau se répondent. Scopé au
   rail des Paramètres — les autres shells .pmx-* gardent le gris. */
#pm-sidebar .pmx-side-grp--atelier > .pmx-side-group { color: var(--pmg-atelier-text); opacity: 1; }
#pm-sidebar .pmx-side-grp--labo    > .pmx-side-group { color: var(--pmg-labo-text);    opacity: 1; }
#pm-sidebar .pmx-side-grp--avance  > .pmx-side-group { color: var(--pmg-avance-text);  opacity: 1; }

.pmx-item {
  position: relative; display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; margin: 2px 0; border-radius: 10px;
  color: var(--text); font-size: .84rem; font-weight: 500; cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-base), border-color var(--dur-fast);
  animation: pmx-item-in var(--dur-enter) backwards var(--ease-out);
  animation-delay: calc(var(--pmx-i, 0) * 20ms); /* --pmx-i posé par le JS (stagger) */
}
/* Une fois le shell ouvert (classe posée par le JS), le filtre de recherche ne
   rejoue plus l'animation d'entrée des items. */
.pmx-nav.pmx-settled .pmx-item, .pmx-side.pmx-settled .pmx-item { animation: none; }
.pmx-item .pmx-ico { font-size: 1rem; width: 18px; text-align: center; opacity: .9; flex-shrink: 0; }
.pmx-item:hover { background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.pmx-item.is-active {
  color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 13%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 26%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent),
              0 6px 18px -10px color-mix(in srgb, var(--accent) 60%, transparent),
              0 0 22px -10px color-mix(in srgb, var(--accent) 45%, transparent);
}
.pmx-item.is-active .pmx-ico { opacity: 1; }
.pmx-item::before {
  content: ""; position: absolute; left: -2px; top: 50%;
  width: 3px; height: 0; border-radius: 3px; transform: translateY(-50%);
  background: var(--accent); opacity: 0;
  box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: height var(--dur-base) var(--ease-out), opacity var(--dur-base);
}
.pmx-item.is-active::before { height: 60%; opacity: 1; }
@keyframes pmx-item-in { from { opacity: 0; transform: translateX(-7px); } to { opacity: 1; transform: translateX(0); } }

/* Admin · icônes de menu modernes : pastille colorée (couleur via --ic posé sur
   l'item, comme --c sur les boutons de la barre) + SVG line-art ; halo à l'actif.
   Scopé à #admin-screen → Paramètres et autres shells gardent leurs emojis. */
#admin-screen .pmx-item .pmx-ico {
  font-size: 0; width: 27px; height: 27px; border-radius: 9px; opacity: 1;
  display: grid; place-items: center; flex-shrink: 0;
  background: color-mix(in srgb, var(--ic, var(--accent)) 15%, var(--surface));
  color: var(--ic, var(--accent));
  transition: background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast);
}
#admin-screen .pmx-item .pmx-ico svg {
  width: 15px; height: 15px; stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
#admin-screen .pmx-item:hover .pmx-ico { transform: translateY(-1px) scale(1.05); }
#admin-screen .pmx-item.is-active {
  color: var(--ic, var(--accent));
  background: color-mix(in srgb, var(--ic, var(--accent)) 13%, var(--surface));
  border-color: color-mix(in srgb, var(--ic, var(--accent)) 26%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ic, var(--accent)) 16%, transparent),
              0 6px 18px -10px color-mix(in srgb, var(--ic, var(--accent)) 60%, transparent);
}
#admin-screen .pmx-item.is-active .pmx-ico {
  background: linear-gradient(140deg, color-mix(in srgb, var(--ic, var(--accent)) 80%, #fff) 0%, var(--ic, var(--accent)) 100%);
  color: #fff;
  box-shadow: 0 3px 9px color-mix(in srgb, var(--ic, var(--accent)) 40%, transparent);
}
#admin-screen .pmx-item::before {
  background: var(--ic, var(--accent));
  box-shadow: 0 0 10px color-mix(in srgb, var(--ic, var(--accent)) 70%, transparent);
}

.pmx-main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--surface); }
.pmx-main > .is-shown { animation: pmx-panel-in var(--dur-base) ease backwards; }
@keyframes pmx-panel-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: translateY(0); } }


.pmx-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 16px; border-radius: 9px; font-size: .8rem; font-weight: 600;
  font-family: 'DM Sans', sans-serif; cursor: pointer; border: 1px solid var(--border);
  background: var(--surface-2); color: var(--text);
  transition: background var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast), border-color var(--dur-fast);
}
.pmx-btn:hover { border-color: var(--accent); background: var(--surface); }
.pmx-btn:active { transform: scale(.97); }
.pmx-btn--save {
  /* Dégradé mémorisé dans une variable : .pmx-btn:hover (0,2,0) est PLUS
     spécifique que .pmx-btn--save (0,1,0) et remplaçait ce fond par
     var(--surface) — le bouton devenait blanc au survol (signalé 11/08 sur
     « Utiliser ce cabinet », mais tous les boutons Enregistrer étaient touchés).
     Le :hover ci-dessous réapplique donc le fond, sans le recopier. */
  --pmx-save-bg: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 60%, var(--teal)));
  border-color: transparent; color: #fff;
  background: var(--pmx-save-bg);
  box-shadow: 0 6px 18px -8px color-mix(in srgb, var(--accent) 75%, transparent),
              0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent) inset;
}
.pmx-btn--save:hover {
  background: var(--pmx-save-bg); border-color: transparent;
  filter: brightness(1.06); box-shadow: 0 8px 24px -8px color-mix(in srgb, var(--accent) 85%, transparent);
}

/* ── Cartes (sections Connexions / Conso / Abonnement / Admin) ── */
.pmx-section-head { padding: 18px 22px 4px; }
.pmx-section-title { font-size: 1rem; font-weight: 700; color: var(--text); margin: 0 0 2px; }
.pmx-section-sub { font-size: .8rem; color: var(--muted); margin: 0; }
.pmx-scroll { flex: 1; overflow-y: auto; padding: 12px 22px 22px; }
.pmx-card {
  display: flex; align-items: center; gap: 13px;
  padding: 14px 16px; margin-bottom: 11px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base), border-color var(--dur-fast);
}
.pmx-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
  box-shadow: 0 12px 28px -16px color-mix(in srgb, var(--accent) 55%, transparent);
}
.pmx-card-ico {
  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 11px; flex-shrink: 0;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-text); font-size: 1.1rem;
}
.pmx-card-body { flex: 1; min-width: 0; }
.pmx-card-title { font-size: .88rem; font-weight: 600; color: var(--text); }
.pmx-card-sub { font-size: .76rem; color: var(--muted); }
.pmx-pill {
  flex-shrink: 0; font-size: .72rem; font-weight: 600; padding: 4px 11px; border-radius: 20px;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--border);
}

/* ── Cartes de préférences (section Avancé) ── */
.pmx-pref-wrap { max-width: 640px; }
.pmx-pref-card {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 13px;
  padding: 15px 16px; margin-bottom: 12px;
}
.pmx-pref-h { font-size: .82rem; font-weight: 700; color: var(--accent-text); margin-bottom: 11px; display: flex; align-items: center; gap: 7px; }
.pmx-pref-note { display: block; font-size: .7rem; color: var(--muted); margin-top: 3px; line-height: 1.5; }
.pmx-chk { width: 16px; height: 16px; accent-color: var(--accent); margin-top: 1px; flex-shrink: 0; }
.pmx-num {
  width: 92px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text); font-size: .78rem; box-sizing: border-box;
}
.pmx-date {
  width: 100%; padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text); font-size: .78rem; box-sizing: border-box;
}
.pmx-info {
  background: color-mix(in srgb, var(--accent) 7%, var(--surface)); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; font-size: .74rem; color: var(--muted); line-height: 1.6;
}

/* ══ BADGES de statut tokenisés (réutilisés : Labos, Demandes, Dashboard) ══════
   Couleur via tokens uniquement → dark mode + couleur tenant automatiques. */
.pmx-badge {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: .7rem; font-weight: 600; line-height: 1; padding: 4px 10px; border-radius: 20px;
  background: color-mix(in srgb, var(--muted) 14%, var(--surface));
  color: var(--muted); border: 1px solid color-mix(in srgb, var(--muted) 26%, transparent);
}
.pmx-badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.pmx-badge--ok     { background: color-mix(in srgb, var(--success) 15%, var(--surface)); color: var(--success); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
.pmx-badge--warn   { background: color-mix(in srgb, var(--warn) 16%, var(--surface));    color: var(--warn);    border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.pmx-badge--danger { background: color-mix(in srgb, var(--danger) 14%, var(--surface));  color: var(--danger);  border-color: color-mix(in srgb, var(--danger) 30%, transparent); }
.pmx-badge--info   { background: color-mix(in srgb, var(--accent) 13%, var(--surface));  color: var(--accent-text);  border-color: color-mix(in srgb, var(--accent) 28%, transparent); }

/* ══ BRIQUES PARTAGÉES des onglets Paramètres (.pmt-*) ════════════════════════
   Squelette de chargement et état vide : grammaire de l'onglet Connexions
   (js/connexions.js, .cnx-skel/.cnx-guard) promue ici pour être réutilisée par
   les autres onglets sans dupliquer le CSS injecté. Tokens uniquement → dark +
   tenant automatiques.
   Le hero .pmt-hero qui vivait ici a été remplacé par la brique d'en-tête
   unique .pmh-* (js/pm-panel-header.js) ; pmtHalo lui a survécu, réutilisé
   par .pmt-empty-ico et la pastille d'état vide de l'aperçu. */
@keyframes pmtHalo{0%,100%{opacity:.4;transform:scale(.9)}50%{opacity:.85;transform:scale(1.1)}}

.pmt-skel{display:flex;gap:12px;align-items:center;border:1px solid var(--line);border-radius:var(--r);padding:15px 17px;margin-bottom:12px;background:var(--surface);animation:pmtPulse 1.5s ease-in-out infinite;}
.pmt-skel-ico{width:44px;height:44px;border-radius:13px;background:var(--surface-2);flex:none;}
.pmt-skel-l1{height:11px;width:140px;border-radius:6px;background:var(--surface-2);margin-bottom:8px;}
.pmt-skel-l2{height:9px;width:260px;max-width:60vw;border-radius:6px;background:var(--surface-2);}
@keyframes pmtPulse{0%,100%{opacity:1}50%{opacity:.55}}
.pmt-empty{text-align:center;color:var(--muted);font-size:.82rem;padding:30px 14px;border:1px dashed var(--border);border-radius:var(--r);}
/* Compléments PARTAGÉS de l'état vide : pastille emoji + titre + sous-titre.
   L'emoji est assumé (concret, coloré) mais il ne se pose JAMAIS nu dans le
   texte : il vit dans .pmt-empty-ico (dégradé accent→teal + halo pmtHalo).
   Utilisables seuls, sans le cadre .pmt-empty (ex. cellule de tableau).
   Tokens uniquement → dark mode + couleur tenant automatiques. */
/* z-index:0 = la pastille porte SA propre pile → le halo (::before en z-index:-1)
   reste visible quel que soit le fond du conteneur, et sous l'emoji. */
.pmt-empty-ico{position:relative;z-index:0;width:52px;height:52px;margin:0 auto 10px;border-radius:16px;display:grid;place-items:center;font-size:1.6rem;line-height:1;background:linear-gradient(140deg,color-mix(in srgb,var(--accent) 10%,var(--surface)),color-mix(in srgb,var(--teal) 12%,var(--surface)));border:1px solid color-mix(in srgb,var(--accent) 16%,var(--border));box-shadow:0 6px 16px -8px color-mix(in srgb,var(--accent) 40%,transparent);}
/* Cœur transparent : le halo entoure la pastille sans voiler l'emoji. */
.pmt-empty-ico::before{content:"";position:absolute;inset:-10px;border-radius:24px;z-index:-1;background:radial-gradient(closest-side,transparent 68%,color-mix(in srgb,var(--teal) 42%,transparent) 84%,transparent);filter:blur(5px);opacity:.7;animation:pmtHalo 2.8s ease-in-out infinite;}
.pmt-empty-title{font-size:.88rem;font-weight:700;color:var(--text);}
.pmt-empty-hint{font-size:.74rem;margin-top:6px;color:var(--muted);line-height:1.5;}
@media (prefers-reduced-motion: reduce){.pmt-skel,.pmt-empty-ico::before{animation:none;}}

/* ══ EN-TÊTE DE PANNEAU DES PARAMÈTRES (.pmh-*) — SOURCE UNIQUE ══════════════
   Remplace les TROIS recettes qui coexistaient (.pm-actes-hero bord-à-bord,
   .cr-hero, .pmt-hero) et dote enfin d'un en-tête les cinq panneaux qui n'en
   avaient pas (Traçabilité, Facturation, Apparence, Préférences, Raccourcis).

   Principe : le module reste NEUTRE ; la couleur vit dans l'ÉTIQUETTE rivetée
   en haut à gauche, qui dit à quel groupe du rail appartient le panneau. Une
   seule teinte par groupe, portée par --pmh-c :
     Atelier  = var(--accent)   → la couleur du labo, donc multi-tenant
     Mon labo = #16a3b0
     Avancé   = #7c4dd6
   Les deux teintes fixes identifient une SECTION et non un labo : elles sont
   les mêmes pour tous les tenants, exactement comme --pmxh (violet du bouton
   Paramètres) et le vert de Facturation. Tout le reste passe par des tokens
   (--surface / --border / --text / --muted) → dark mode automatique.
   Markup produit par window.pmPanelHeader() (js/pm-panel-header.js) : une
   seule fonction pour les 14 panneaux, jamais de HTML recopié. */
/* padding-bas 18px : l'ancien hero portait un margin-bottom de 18px et le
   contenu qui suit (bouton « Ajouter une règle », cartes…) se collait sans. */
.pmh { position: relative; flex: none; padding: 26px 22px 18px; --pmh-c: var(--pmg-atelier); }
.pmh--labo   { --pmh-c: var(--pmg-labo); }
/* Dans un conteneur déjà en retrait (.pmx-pref-wrap), l'en-tête ne rajoute
   pas de marge latérale : il s'aligne alors sur les cartes qu'il introduit. */
/* Les 14 panneaux ne portaient pas la même marge (12 en ont une de 20/24, deux
   n'en ont aucune) : l'en-tête changeait donc de place à chaque changement
   d'onglet — mesuré, il tombait à SIX endroits différents. Il sort maintenant
   du retrait de son panneau et se cale partout sur la même position, celle du
   panneau Actes. La marge est reprise à l'identique de .pmx-panel-pad ; si
   elle change là-bas, elle doit changer ici. */
#modal-parametres .pmx-panel-pad > .pmh,
#modal-parametres .pmx-panel-pad > div > .pmh { margin: -20px -24px 0; }
.pmh--avance { --pmh-c: var(--pmg-avance); }
.pmh-mod {
  position: relative; display: flex; align-items: center; gap: 15px;
  padding: 18px 18px 17px; border-radius: 13px;
  border: 1px solid color-mix(in srgb, var(--pmh-c) 24%, var(--border));
  background: linear-gradient(180deg, color-mix(in srgb, var(--pmh-c) 6%, var(--surface)), var(--surface) 78%);
  box-shadow: 0 10px 26px -20px color-mix(in srgb, var(--pmh-c) 90%, transparent), var(--shadow-sm);
}
/* L'étiquette rivetée : le SEUL endroit coloré. À cheval sur la bordure. */
.pmh-tag {
  position: absolute; top: -11px; left: 18px; z-index: 2;
  padding: 4px 12px; border-radius: 8px; white-space: nowrap; color: #fff;
  font-family: 'DM Mono', monospace; font-size: .6rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--pmh-c) 74%, #fff) 0%,
    var(--pmh-c) 62%,
    color-mix(in srgb, var(--pmh-c) 82%, #000) 100%);
  box-shadow: 0 7px 16px -8px color-mix(in srgb, var(--pmh-c) 90%, transparent),
              inset 0 1px 0 rgba(255,255,255,.32);
}
/* Pastille de l'emoji : fond de surface (blanc en jour, sombre en nuit) pour
   que les emoji PÂLES (🦷 📄 📋 ⌨️) gardent de la présence. */
.pmh-ico {
  position: relative; flex: none; width: 46px; height: 46px; border-radius: 13px;
  display: grid; place-items: center; font-size: 1.34rem; line-height: 1;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--pmh-c) 22%, var(--border));
  box-shadow: 0 3px 9px -5px color-mix(in srgb, var(--pmh-c) 60%, transparent);
  transition: transform var(--dur-base) var(--ease-spring);
}
.pmh:hover .pmh-ico { transform: translateY(-2px); }
.pmh-txt { flex: 1; min-width: 0; }
.pmh-title { font-size: 1.2rem; font-weight: 800; letter-spacing: -.025em; color: var(--text); line-height: 1.2; }
.pmh-sub { margin-top: 5px; font-size: .79rem; color: var(--muted); line-height: 1.5; max-width: 66ch; }
.pmh-sub b { color: var(--text); font-weight: 700; }
/* Emplacement à droite : recherche, navigation par mois, boutons du panneau. */
.pmh-actions { position: relative; z-index: 1; flex: none; display: flex; align-items: center; gap: 8px; }

/* Entrée à l'ouverture du panneau : l'étiquette se pose, puis le texte monte.
   ⚠ Volontairement en ANIMATION CSS et non en transition pilotée par une
   classe JS : une animation se joue seule dès que l'élément entre dans le DOM,
   donc un en-tête ne peut JAMAIS rester bloqué invisible si le JS n'ajoute pas
   la classe à temps. `both` fige l'état final. Se rejoue au changement
   d'onglet (le panneau est re-rendu) — c'est le moment voulu. R25 : transform
   + opacity uniquement, aucune boucle. */
@keyframes pmhTagIn  { from { opacity: 0; transform: translateY(-7px); } to { opacity: 1; transform: none; } }
@keyframes pmhTextIn { from { opacity: 0; transform: translateY(7px); }  to { opacity: 1; transform: none; } }
.pmh-tag   { animation: pmhTagIn  var(--dur-base)  var(--ease-spring) backwards; }
.pmh-title { animation: pmhTextIn var(--dur-enter) var(--ease-out) 70ms backwards; }
.pmh-sub   { animation: pmhTextIn var(--dur-enter) var(--ease-out) 115ms backwards; }
@media (prefers-reduced-motion: reduce) {
  .pmh-tag, .pmh-title, .pmh-sub { animation: none; }
  .pmh:hover .pmh-ico { transform: none; }
}
@media (max-width: 760px) { .pmh-mod { align-items: flex-start; flex-wrap: wrap; } }
html.mobile-zoom-default .pmh { padding: 24px 14px 0; }
html.mobile-zoom-default .pmh-mod { padding: 15px 14px 14px; gap: 12px; }
html.mobile-zoom-default .pmh-title { font-size: 1.08rem; }

/* ══ DASHBOARD super_admin (js/admin-dashboard.js) ════════════════════════════ */
@keyframes adm-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* Barre d'outils (titre conso + sélecteur de mois) */
.adm-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 2px 0 14px; flex-wrap: wrap; }
.adm-bar-title { font-size: .82rem; font-weight: 700; color: var(--text); }
.adm-month { display: flex; align-items: center; gap: 6px; }
.adm-month-lbl { min-width: 124px; text-align: center; font-weight: 600; font-size: .85rem; color: var(--text); text-transform: capitalize; }
.adm-navbtn {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
  cursor: pointer; font-size: .9rem; transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
}
.adm-navbtn:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.adm-navbtn:active:not(:disabled) { transform: scale(.92); }
.adm-navbtn:disabled { opacity: .4; cursor: not-allowed; }

/* Bandeau KPI */
.adm-kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); gap: 12px; margin-bottom: 20px; }
.adm-kpi-card {
  position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 14px; padding: 15px 16px;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 5%, transparent),
              0 20px 32px -26px color-mix(in srgb, var(--accent) 55%, transparent);
  animation: adm-in var(--dur-slow) backwards var(--ease-out); animation-delay: calc(var(--i, 0) * 35ms);
}
.adm-kpi-card::after {
  content: ""; position: absolute; top: -45%; right: -18%; width: 120px; height: 120px; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%);
  pointer-events: none;
}
.adm-kpi-card.is-warn   { border-left-color: var(--warn);   box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 5%, transparent), 0 20px 32px -26px color-mix(in srgb, var(--warn) 60%, transparent); }
.adm-kpi-card.is-warn::after   { background: radial-gradient(circle, color-mix(in srgb, var(--warn) 20%, transparent), transparent 70%); }
.adm-kpi-card.is-danger { border-left-color: var(--danger); box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 5%, transparent), 0 20px 32px -26px color-mix(in srgb, var(--danger) 60%, transparent); }
.adm-kpi-card.is-danger::after { background: radial-gradient(circle, color-mix(in srgb, var(--danger) 22%, transparent), transparent 70%); }
.adm-kpi-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.adm-kpi-value { font-size: 1.9rem; font-weight: 800; color: var(--text); line-height: 1.05; margin-top: 5px; }
.adm-kpi-sub { font-size: .7rem; color: var(--muted); margin-top: 2px; }

/* Total général (conso cumulée tous labos) */
.adm-total {
  display: flex; align-items: baseline; gap: 11px; margin: 0 0 14px; padding: 13px 18px;
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border)); border-radius: 14px;
}
.adm-total-v { font-size: 1.9rem; font-weight: 800; color: var(--accent-text); line-height: 1; }
.adm-total-l { font-size: .8rem; color: var(--muted); }

/* Carte labo (conso) */
.adm-labo {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 13px 16px; margin-bottom: 10px; cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base), border-color var(--dur-fast);
  animation: adm-in var(--dur-slow) backwards var(--ease-out); animation-delay: calc(var(--i, 0) * 35ms);
}
.adm-labo:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); box-shadow: 0 14px 30px -18px color-mix(in srgb, var(--accent) 55%, transparent); }
.adm-labo.is-zero { opacity: .6; }
.adm-labo.is-zero:hover { opacity: .85; }
.adm-labo-row { display: flex; align-items: center; gap: 14px; }
.adm-labo-head { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 1; }
.adm-labo-name { font-weight: 700; font-size: .92rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.adm-labo-metrics { display: flex; align-items: center; gap: 20px; flex-shrink: 0; }
.adm-metric { text-align: right; line-height: 1.1; }
.adm-metric-v { font-size: 1.1rem; font-weight: 700; color: var(--text); }
.adm-metric-l { font-size: .62rem; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.adm-chev { color: var(--muted); transition: transform var(--dur-base); flex-shrink: 0; }
.adm-labo.is-open .adm-chev { transform: rotate(90deg); }

/* Sparkline compacte */
.adm-spark { display: flex; align-items: flex-end; gap: 1px; height: 30px; width: 124px; flex-shrink: 0; }
.adm-spark-bar { flex: 1; min-width: 0; border-radius: 2px 2px 0 0; background: color-mix(in srgb, var(--accent) 70%, transparent); }
.adm-spark-bar.is-today { background: var(--teal); }
.adm-spark-bar.is-zero { height: 2px; background: var(--border); align-self: flex-end; }

/* Barre de plafond (forfait/jour) */
.adm-progress { height: 6px; border-radius: 4px; background: var(--border); overflow: hidden; margin-top: 9px; }
.adm-progress-fill { height: 100%; border-radius: 4px; transition: width var(--dur-slow); }
.adm-progress-fill.is-ok { background: var(--success); }
.adm-progress-fill.is-warn { background: var(--warn); }
.adm-progress-fill.is-danger { background: var(--danger); }
.adm-progress-lbl { font-size: .66rem; color: var(--muted); margin-top: 4px; display: flex; justify-content: space-between; }

/* Détail déplié (graphe journalier complet) */
.adm-labo-detail { display: none; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--border); }
.adm-labo.is-open .adm-labo-detail { display: block; animation: adm-in var(--dur-base) backwards; }

/* Boutons d'action (Labos) tokenisés */
.adm-btn { border: none; padding: 8px 14px; border-radius: 8px; cursor: pointer; font-size: .8rem; font-weight: 600; color: #fff; transition: filter var(--dur-fast), transform var(--dur-fast); }
.adm-btn + .adm-btn { margin-left: 8px; }
.adm-btn:hover { filter: brightness(1.08); }
.adm-btn:active { transform: scale(.97); }
.adm-btn--ok { background: var(--success); }
.adm-btn--muted { background: var(--muted); }
.adm-btn--danger { background: var(--danger); }

/* État vide / chargement / erreur */
.adm-empty { text-align: center; color: var(--muted); padding: 34px 12px; border: 1px dashed var(--border); border-radius: 12px; }
.adm-note { font-size: .74rem; color: var(--muted); margin: 0 0 14px; display: flex; align-items: center; gap: 7px; }

/* ── Admin · Tarifs & forfaits (admin-pricing.js) ── */
.ap-block { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 16px; margin-bottom: 16px; }
.ap-block-head { margin-bottom: 12px; display: flex; flex-direction: column; gap: 2px; }
.ap-h { font-size: .95rem; font-weight: 700; color: var(--text); margin: 0; }
.ap-hint { font-size: .78rem; color: var(--muted); }
.ap-table-wrap { overflow-x: auto; }
.ap-table { width: 100%; border-collapse: collapse; font-size: .82rem; }
.ap-table th { text-align: left; font-weight: 600; color: var(--muted); font-size: .72rem; text-transform: uppercase; letter-spacing: .03em; padding: 4px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ap-table td { padding: 6px 8px; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); vertical-align: middle; }
.ap-table tbody tr:last-child td { border-bottom: none; }
.ap-table tbody tr { transition: background var(--dur-fast); }
.ap-table tbody tr:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.ap-input { width: 100%; box-sizing: border-box; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); color: var(--text); font-size: .82rem; transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.ap-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.ap-input:disabled { opacity: .42; cursor: not-allowed; }
.ap-input--sm { max-width: 72px; }
.ap-input--num { max-width: 130px; }
.ap-actions { white-space: nowrap; text-align: right; }
.ap-mini { border: 1px solid var(--border); background: var(--surface); color: var(--text); border-radius: 6px; width: 27px; height: 27px; cursor: pointer; font-size: .82rem; line-height: 1; transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast); }
.ap-mini + .ap-mini { margin-left: 4px; }
.ap-mini:hover { border-color: var(--accent); color: var(--accent-text); }
.ap-mini--danger:hover { border-color: var(--danger); color: var(--danger); }
.ap-footer { display: flex; align-items: center; gap: 10px; padding-top: 2px; flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) {
  .pmx-overlay, .pmx-shell, .pmx-item, .pmx-main > .is-shown { animation: none; }
  .pmx-card, .pmx-item, .pmx-item::before { transition: none; }
  .adm-kpi-card, .adm-labo, .adm-labo-detail { animation: none; }
  .adm-labo, .adm-navbtn, .adm-chev, .adm-progress-fill, .adm-btn { transition: none; }
  .ap-input, .ap-mini, .ap-table tbody tr { transition: none; }
  #admin-screen .pmx-item .pmx-ico { transition: none; }
}

/* ════════════════════════════════════════════════════════════════════
   Onglet Apparence (js/tenant-branding-admin.js) — namespace .tba-*.
   Tout en tokens var(--accent/--teal/--surface/--text/--border/--grad)
   → dark-mode auto + couleurs du tenant. Halos & micro-interactions.
   ════════════════════════════════════════════════════════════════════ */
.tba-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.tba-fld { display: flex; flex-direction: column; gap: 5px; }
.tba-fld > span { font-size: .72rem; color: var(--muted); font-weight: 500; }
.tba-in {
  padding: 8px 11px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); color: var(--text); font-size: .82rem; font-family: 'DM Sans', sans-serif;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.tba-in:focus { outline: none; border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent); }
.tba-mini { font-size: .66rem; color: var(--muted); line-height: 1.5; }
.tba-hex { font-size: .7rem; color: var(--muted); font-family: 'DM Mono', monospace; }

/* Aperçu live — reflète couleurs + grade en temps réel */
.tba-preview {
  border: 1px solid var(--border); border-radius: 15px; overflow: hidden; background: var(--surface);
  box-shadow: 0 16px 38px -24px color-mix(in srgb, var(--accent) 65%, transparent),
              0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent);
  animation: tba-pv-in var(--dur-slow) var(--ease-out) backwards;
}
@keyframes tba-pv-in { from { opacity: 0; transform: translateY(8px) scale(.99); } to { opacity: 1; transform: none; } }
.tba-preview-hd { position: relative; padding: 15px 18px; background: var(--grad);
  display: flex; align-items: center; gap: 13px; min-height: 62px; }
.tba-preview-hd::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(130% 150% at 100% 0%, rgba(255,255,255,.20), transparent 60%); }
.tba-pv-mark { position: relative; width: 38px; height: 38px; border-radius: 11px; flex: none;
  background: rgba(255,255,255,.18); display: grid; place-items: center; font-size: 1.1rem;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.28); }
.tba-pv-logo { position: relative; font-family: var(--font-signature, 'Dancing Script', cursive); font-weight: 700;
  font-size: 1.5rem; color: #fff; text-shadow: 0 1px 5px rgba(0,0,0,.22); line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tba-pv-tag { position: relative; margin-left: auto; font-size: .6rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: rgba(255,255,255,.85); }
.tba-preview-bd { padding: 13px 16px; display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.tba-pv-btn { padding: 7px 15px; border-radius: 9px; border: none; color: #fff; font-size: .76rem;
  font-weight: 600; background: var(--grad); cursor: default;
  box-shadow: 0 7px 16px -8px color-mix(in srgb, var(--accent) 80%, transparent); }
.tba-pv-chip { padding: 5px 12px; border-radius: 20px; font-size: .72rem; font-weight: 600;
  color: var(--accent-text); background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); }
.tba-pv-tooth { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center;
  color: #fff; background: var(--grad); font-size: .7rem; font-weight: 700;
  box-shadow: 0 4px 10px -4px color-mix(in srgb, var(--accent) 70%, transparent); }

/* Palettes rapides */
.tba-presets { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.tba-preset { width: 30px; height: 30px; border-radius: 50%; cursor: pointer; border: none; padding: 0;
  box-shadow: 0 0 0 1px var(--border), 0 3px 8px -2px rgba(0,0,0,.22);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base); }
.tba-preset:hover { transform: translateY(-3px) scale(1.12);
  box-shadow: 0 0 0 1px var(--accent), 0 9px 18px -6px color-mix(in srgb, var(--accent) 65%, transparent); }
.tba-preset:active { transform: scale(.92); }

/* Lignes couleur + grade */
.tba-color-row { display: flex; gap: 16px; align-items: flex-end; flex-wrap: wrap; }
.tba-swatch { width: 46px; height: 34px; border: 1px solid var(--border); border-radius: 8px;
  cursor: pointer; padding: 0; background: none; }
.tba-range { width: 118px; accent-color: var(--accent); vertical-align: middle; cursor: pointer; }
.tba-gradbar { margin-top: 11px; height: 30px; border-radius: 9px;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text) 9%, transparent); }
.tba-grade-row { display: grid; grid-template-columns: 88px 1fr 46px; align-items: center; gap: 11px; }
.tba-chip-btn { background: var(--surface); border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; padding: 6px 11px; font-size: .72rem; font-weight: 600; cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast); white-space: nowrap; }
.tba-chip-btn:hover { border-color: var(--accent); color: var(--accent-text);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }

/* Vignettes de choix de police (« signature ») : chacune rend le nom du labo
   dans sa propre police. Sélection = liseré + halo accent (dark-safe via tokens). */
.tba-fonts { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.tba-font { display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 11px 13px; border-radius: 12px; cursor: pointer; text-align: left;
  background: var(--surface); border: 1.5px solid var(--border);
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-fast), background var(--dur-fast); }
.tba-font:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 14%, transparent); }
.tba-font.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  box-shadow: inset 0 0 0 1px var(--accent), 0 6px 18px color-mix(in srgb, var(--accent) 18%, transparent); }
.tba-font-demo { font-size: 1.45rem; font-weight: 700; line-height: 1.05; color: var(--text);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tba-font.on .tba-font-demo { background: var(--grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.tba-font-lbl { font-size: .66rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.tba-font.on .tba-font-lbl { color: var(--accent-text); }

/* En-tête de carte : pastille icône accent (halo) + titre. Remplace les emojis. */
.tba-h { display: flex; align-items: center; gap: 10px; margin-bottom: 13px; }
.tba-h-ico { display: grid; place-items: center; width: 27px; height: 27px; border-radius: 8px; flex: none;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent-text);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent),
              0 0 14px -5px color-mix(in srgb, var(--accent) 60%, transparent);
  transition: box-shadow var(--dur-base), transform var(--dur-fast); }
.pmx-pref-card:hover .tba-h-ico { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 32%, transparent),
              0 0 18px -4px color-mix(in srgb, var(--accent) 70%, transparent); }
.tba-h-txt { font-size: .85rem; font-weight: 700; color: var(--text); letter-spacing: .1px; }
.tba-h-sub { font-size: .7rem; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.tba-pv-mark { color: #fff; }
.tba-pv-mark svg { width: 19px; height: 19px; }
@media (prefers-reduced-motion: reduce) { .tba-preview, .tba-preset, .tba-h-ico { animation: none; transition: none; } }

/* ── Éditeur d'icône d'app (js/icon-editor.js) ─────────────────────────── */
#ie-overlay {
  position: fixed; inset: 0; z-index: 9000; display: flex; align-items: center; justify-content: center;
  background: rgba(15, 23, 35, 0.55); backdrop-filter: var(--ov-blur, blur(3px)); padding: 16px;
}
.ie-card {
  width: min(720px, 96vw); max-height: 92vh; overflow: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-md);
}
.ie-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--border); font-weight: 600; font-size: 0.95rem;
}
.ie-x { background: none; border: 0; color: var(--muted); font-size: 1rem; cursor: pointer; line-height: 1; padding: 4px; border-radius: 6px; }
.ie-x:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
.ie-ctxsel { display: flex; gap: 8px; padding: 12px 18px 0; }
.ie-ctxbtn { flex: 1; padding: 8px 10px; border-radius: 9px; border: 1px solid var(--border); background: var(--surface); color: var(--muted); font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.ie-ctxbtn.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.ie-dev[data-ctx], #ie-tabprev[data-ctx] { cursor: pointer; }
.ie-dev.ie-ctx-active .ie-dev-wp { outline: 2px solid var(--accent); outline-offset: 2px; }
#ie-tabprev.ie-ctx-active { outline: 2px solid var(--accent); outline-offset: 2px; }
.ie-body { display: flex; gap: 22px; padding: 18px; flex-wrap: wrap; }
.ie-left { flex: 1 1 300px; min-width: 280px; display: flex; flex-direction: column; gap: 12px; }
.ie-right { flex: 1 1 240px; min-width: 220px; }
.ie-stage {
  width: 300px; height: 300px; max-width: 100%; align-self: center; overflow: hidden;
  border: 1px solid var(--border); box-shadow: var(--shadow-sm);
  background: var(--bg);
}
.ie-stage canvas { width: 100%; height: 100%; display: block; touch-action: none; cursor: grab; }
.ie-stage canvas:active { cursor: grabbing; }
.ie-hint { font-size: 0.7rem; color: var(--muted); text-align: center; }
.ie-row { display: flex; gap: 8px; }
.ie-btn {
  flex: 1; padding: 9px 12px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font-size: 0.82rem; font-weight: 600; cursor: pointer;
}
.ie-btn:hover { border-color: var(--accent); }
.ie-btn-ghost { color: var(--muted); }
.ie-btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.ie-btn-primary:disabled { opacity: 0.6; cursor: default; }
.ie-ctl { display: flex; align-items: center; gap: 12px; font-size: 0.8rem; color: var(--muted); }
.ie-ctl > span { width: 44px; flex: none; }
.ie-ctl input[type="range"] { flex: 1; accent-color: var(--accent); }
.ie-bgs { display: flex; gap: 8px; align-items: center; }
.ie-bg { width: 30px; height: 30px; border-radius: 8px; border: 2px solid var(--border); cursor: pointer; padding: 0; position: relative; }
.ie-bg.ie-bg-on { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.ie-bg-tr {
  background-image: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(-45deg, #ccc 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(-45deg, transparent 75%, #ccc 75%);
  background-size: 10px 10px; background-position: 0 0, 0 5px, 5px -5px, -5px 0; background-color: #fff;
}
.ie-bg-pick { overflow: hidden; display: inline-flex; }
.ie-bg-pick input[type="color"] { width: 200%; height: 200%; margin: -25%; border: 0; padding: 0; cursor: pointer; background: none; }
.ie-prev-title { font-size: 0.72rem; color: var(--muted); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.04em; }
.ie-prev-img { background-size: cover; background-position: center; }
/* Aperçus réalistes : chaque OS masque l'icône avec une forme différente. */
.ie-devices { display: flex; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.ie-dev { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.ie-dev small { font-size: 0.62rem; color: var(--muted); }
.ie-dev-name { font-size: 0.6rem; color: var(--text); max-width: 74px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ie-dev-wp {
  width: 74px; height: 74px; border-radius: 16px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #3b4a6b 0%, #7a4f86 100%); box-shadow: var(--shadow-sm);
}
.ie-dev-wp .ie-prev-img { width: 60px; height: 60px; box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.ie-mask-ios { border-radius: 22.5%; }       /* iPhone : squircle iOS (approx.) */
.ie-mask-pixel { border-radius: 50%; }        /* Android Pixel : cercle */
.ie-mask-samsung { border-radius: 40%; }      /* Samsung One UI : squircle arrondi */
.ie-headerprev { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 12px; box-shadow: var(--shadow-sm); margin-bottom: 6px; }
.ie-hdr-ico { width: 44px; height: 44px; border-radius: 10px; flex: none; }
.ie-hdr-name { font-family: var(--font-signature, 'Dancing Script', cursive); font-size: 1.45rem; color: #fff; line-height: 1; }
.ie-browser { max-width: 270px; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; box-shadow: var(--shadow-sm); background: var(--surface); }
.ie-br-bar { display: flex; gap: 5px; align-items: center; padding: 7px 9px; background: color-mix(in srgb, var(--text) 8%, var(--surface)); }
.ie-br-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.ie-br-tabrow { display: flex; padding: 0 8px; background: color-mix(in srgb, var(--text) 8%, var(--surface)); }
.ie-br-tab { display: flex; align-items: center; gap: 7px; max-width: 200px; background: var(--surface); border: 1px solid var(--border); border-bottom: none; border-radius: 8px 8px 0 0; padding: 7px 10px; }
.ie-br-addr { padding: 8px 10px; }
.ie-addr-pill { display: flex; align-items: center; gap: 7px; background: color-mix(in srgb, var(--text) 7%, var(--surface)); border-radius: 14px; padding: 5px 11px; }
.ie-addr-ico { width: 14px; height: 14px; background-size: cover; background-position: center; flex: none; }
.ie-addr-url { font-size: 0.7rem; color: var(--muted); }
.ie-tab-ico { width: 16px; height: 16px; background-size: cover; background-position: center; flex: none; }
.ie-tab-txt { font-size: 0.74rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ie-tab-x { margin-left: auto; color: var(--muted); font-size: 0.7rem; }
.ie-tab-cap { font-size: 0.68rem; color: var(--muted); margin-top: 6px; }
.ie-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 14px 18px; border-top: 1px solid var(--border); }
.ie-foot .ie-btn { flex: none; min-width: 120px; }

/* ── Menu contextuel partagé (clic droit liste + actions Digilab) — dark-aware ──
   Remplace les styles inline `background:white` qui figeaient le menu en blanc en
   mode nuit. Les couleurs vivent ici → thème + couleurs tenant respectés. */
/* ── Menu contextuel (clic droit / bouton « Actions ») ────────────────────────
   Aligné sur le menu de filtre « scanner » (.pf-arch-menu/.pf-arch-opt, § plus
   haut) : même rayon, même ombre, même rythme d'animation, même trio
   « marqueur · libellé · compteur à droite ». Deux menus qui font le même geste
   dans l'app ne doivent pas avoir deux allures. Les emoji d'icône ont été
   remplacés par des SVG en contour (currentColor) : un emoji est multicolore et
   ne suit ni le thème ni l'état de la ligne. */
.ctx-menu { position: fixed; z-index: 10000; background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-md);
  padding: 5px; font-size: .85rem; min-width: 230px;
  display: flex; flex-direction: column; gap: 2px;
  animation: ctxMenuIn var(--dur-fast) ease backwards; }
@keyframes ctxMenuIn { from { opacity: 0; transform: translateY(-4px) scale(.985); }
                       to   { opacity: 1; transform: none; } }
.ctx-menu .ctx-item { display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: none; background: none; border-radius: 8px; cursor: pointer;
  user-select: none; white-space: nowrap; text-align: left;
  font-family: 'DM Sans', sans-serif; font-size: .82rem; font-weight: 600; color: var(--text);
  transition: background var(--dur-fast); }
.ctx-menu .ctx-item:hover { background: var(--surface-2); }
.ctx-menu .ctx-item:focus-visible { outline: none; background: var(--surface-2);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ctx-c) 45%, transparent); }
/* Pastille d'icône : le motif signature de l'app (.tool .ti, .pmx-title-ico),
   réduit. Colorée DÈS LE REPOS — grise, elle avait l'air désactivée.
   La teinte vient de --ctx-accent, posée par le module qui ouvre le menu : le menu
   Digilab prend la couleur du bouton Digilab, lue dans le DOM (--c), donc le menu
   s'accorde à l'écran d'où il sort. Sans cette variable, on retombe sur la couleur
   du labo (var(--accent)) : multi-tenant par défaut, jamais de couleur en dur. */
.ctx-menu { --ctx-c: var(--ctx-accent, var(--accent)); }
.ctx-menu .ctx-ico { width: 24px; height: 24px; flex: none; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--ctx-c) 16%, transparent);
  color: var(--ctx-c);
  transition: background var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast); }
.ctx-menu .ctx-item:hover .ctx-ico,
.ctx-menu .ctx-item:focus-visible .ctx-ico {
  background: color-mix(in srgb, var(--ctx-c) 28%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ctx-c) 32%, transparent); }
.ctx-menu .ctx-ico svg { width: 15px; height: 15px; fill: none; stroke: currentColor;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* Compteur en fin de ligne — même traitement que .pf-scan-n du menu scanner. */
.ctx-menu .ctx-n { margin-left: auto; padding: 1px 7px; border-radius: 99px;
  font-size: .68rem; font-weight: 700; color: var(--muted);
  background: color-mix(in srgb, var(--muted) 14%, transparent); }
.ctx-menu .ctx-item:hover .ctx-n { color: var(--ctx-c);
  background: color-mix(in srgb, var(--ctx-c) 16%, transparent); }
/* Action destructrice : isolée par un séparateur ET par sa couleur, au survol aussi. */
.ctx-menu .ctx-item.is-danger { color: var(--danger); }
.ctx-menu .ctx-item.is-danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.ctx-menu .ctx-item.is-danger:hover .ctx-ico,
.ctx-menu .ctx-item.is-danger .ctx-ico {
  background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
/* L'OBJET illustré d'une ligne du menu clic-droit (19/09/2026) : une case de
   largeur fixe, comme dans le menu de ligne, pour que les libellés s'alignent.
   Le dessin porte ses propres couleurs : pas de pastille teintée autour (ce que
   fait .ctx-ico pour les icônes en TRAIT du menu Digilab). */
.ctx-menu .ctx-ilx { flex: none; width: 19px; height: 19px; display: grid; place-items: center;
  font-size: .92rem; line-height: 1; }
.ctx-menu .ctx-ilx .b3d-ob, .ctx-menu .ctx-ilx .b3d-ob svg { width: 18px; height: 18px; }
.ctx-menu .ctx-sep { height: 1px; background: var(--border); margin: 3px 6px; }
.ctx-menu .ctx-item.is-muted { color: var(--muted); }
.ctx-menu .ctx-item[disabled] { cursor: default; opacity: .55; }
.ctx-menu .ctx-item[disabled]:hover { background: none; }
.ctx-menu .ctx-item[disabled] .ctx-ico,
.ctx-menu .ctx-item[disabled]:hover .ctx-ico {
  background: var(--surface-2); color: var(--muted); box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  .ctx-menu { animation: none; }
  .ctx-menu .ctx-item, .ctx-menu .ctx-ico { transition: none; }
}
/* Couleurs sémantiques de statut (mêmes teintes que les pills) */
.ctx-menu .ctx-item.st-bon  { color: #8a6d3b; }
.ctx-menu .ctx-item.st-recu { color: var(--accent-text); }
.ctx-menu .ctx-item.st-livr { color: #e65100; }
.ctx-menu .ctx-item.st-ok   { color: #2e7d32; }
html[data-theme="dark"] .ctx-menu .ctx-item.st-bon  { color: #d2a86a; }
html[data-theme="dark"] .ctx-menu .ctx-item.st-livr { color: #ff8a3d; }
html[data-theme="dark"] .ctx-menu .ctx-item.st-ok   { color: #5fc16e; }

/* ── Bouton « 3D » (empreintes Digilab) — frère de l'œil #btn-view-3d dans le
   header de la fiche ; masqué par défaut (style inline dans index.html), affiché
   par form-editor.js si la prescription est liée à un cas Digilab.
   Aucun style propre : il porte `.pvh-btn` comme tous ses voisins de l'en-tête.
   (Il gardait ici un texte blanc sur fond blanc translucide, hérité de l'époque
   où l'en-tête avait un fond dégradé accent → invisible en thème clair.) */

/* Focus clavier visible (boutons/liens/onglets) — n'affecte pas les inputs ni la souris */
:where(button, a, summary, [role="button"], [role="tab"], [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* Deux contrôles qui neutralisaient l'outline sans remplacement (gestion clients) */
.gc-fiche-statut:focus-visible {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
}
.gc-fiche-notes-input:focus {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
}

/* ── Modale Unitaire / Solidaire (js/unitaire-solidaire.js), refonte 25/09/2026.
   Même LANGAGE que le schéma dentaire (.ais-th, résumé IA + PDF anglais) : case en
   forme de dent, couleurs --th-u-* (unitaire) / --th-s-* (solidarisé) de la source
   unique SCHEMA_COULEURS (js/ai-summary.js), dents solidarisées SOUDÉES d'un seul
   tenant, libellé d'arcade à gauche, légende .ais-leg. La SÉLECTION porte l'accent
   du labo. Tout l'état passe par des CLASSES (usmPeindre) : les transitions jouent
   à chaque clic, rien n'est reconstruit. */
.usm { --usm-w: 38px; --usm-gap: 4px; --usm-mid: 12px;
  --usm-demi: calc((var(--usm-gap) + var(--usm-mid) + 1.5px) / 2);
  position: fixed; z-index: 2200; box-sizing: border-box; width: max-content; max-width: calc(100vw - 16px);
  max-height: 88vh; overflow-y: auto; padding: 14px 16px 12px; border-radius: 16px;
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  box-shadow: 0 18px 50px -18px rgba(15,35,55,.45), 0 2px 8px rgba(15,35,55,.08); outline: none; }
/* Nuit : les MÊMES valeurs que .ais-th.u / .ais-th.s en mode sombre (plus haut). */
html[data-theme="dark"] .usm { --th-u-bg: #1c3142; --th-u-bd: #3a6a8c; --th-u-tx: #7fc4e8;
  --th-s-bg: #1c3326; --th-s-bd: #3a7a55; --th-s-tx: #81c784; }
#popup-unit-solid .us-modal { animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
#popup-unit-solid.is-closing .us-modal { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }

.usm-hd { display: flex; align-items: center; gap: 10px; margin: -2px 0 12px; cursor: grab; user-select: none; touch-action: none; }
.usm-hd:active { cursor: grabbing; }
.usm-ttl { font-weight: 800; font-size: .95rem; color: var(--muted); display: inline-flex; align-items: center; gap: 7px; }
/* Chaque mot dans la couleur de son type, comme dans l'arcade (Illan 25/09/2026). */
.usm-ttl-u { color: var(--th-u-tx); }
.usm-ttl-s { color: var(--th-s-tx); }
.usm-meta { font-size: .72rem; font-weight: 700; color: var(--muted); padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.usm-meta:empty { display: none; }
.usm-meta.is-ok { color: var(--th-s-tx); background: var(--th-s-bg); }
.usm-x { margin-left: auto; width: 30px; height: 30px; border: none; border-radius: 9px; background: transparent;
  color: var(--muted); font-size: 1.25rem; line-height: 1; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.usm-x:hover { background: var(--surface-2); color: var(--text); }

/* Arcade : libellé à gauche puis 16 cases, l'écart du milieu porté par la 9e dent
   (.mid) — comme .ais-th, pour qu'un bridge 11-21 puisse le franchir. */
.usm-arch { padding: 12px 12px 8px; border-radius: 12px; overflow-x: auto; touch-action: none; user-select: none;
  background: color-mix(in srgb, var(--accent) 4%, var(--surface)); border: 1px solid var(--border); }
.usm-row { display: flex; align-items: stretch; gap: var(--usm-gap); width: max-content; margin: 0 auto; }
.usm-row--h { margin-bottom: 8px; }
.usm-archlbl { flex: 0 0 34px; align-self: center; text-align: right; margin-right: 6px; font-size: .6rem; font-weight: 800;
  letter-spacing: 1px; color: var(--muted); }
.usm-t { position: relative; box-sizing: border-box; flex: 0 0 var(--usm-w); width: var(--usm-w); height: 46px; margin: 0; padding: 0 0 5px;
  border-radius: 7px 7px 12px 12px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 3px;
  font: inherit; color: var(--text); background: var(--surface); border: 1.5px solid var(--border); cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); }
.usm-t.mid { margin-left: var(--usm-mid); }
.usm-t b { font-size: .8rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.usm-t i { font-style: normal; font-size: .48rem; font-weight: 800; letter-spacing: .02em; line-height: 1; min-height: .48rem;
  color: var(--muted); white-space: nowrap; }
.usm-t:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--border)); transform: translateY(-1px); }
.usm-t:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 2px; }
.usm-t--vide { background: transparent; border: 1.5px dashed color-mix(in srgb, var(--muted) 30%, transparent); cursor: default; }
.usm-t--vide b { color: color-mix(in srgb, var(--muted) 60%, transparent); font-weight: 600; font-size: .68rem; }
.usm-t--vide:hover { transform: none; border-color: color-mix(in srgb, var(--muted) 30%, transparent); }
/* Réparties : les couleurs du schéma dentaire. */
.usm-t.is-u { background: var(--th-u-bg); border-color: var(--th-u-bd); color: var(--th-u-tx); }
.usm-t.is-s { background: var(--th-s-bg); border-color: var(--th-s-bd); color: var(--th-s-tx); }
.usm-t.is-u i, .usm-t.is-s i { color: inherit; opacity: .75; }
/* SOUDURE (miroir de .ais-th.jl/.jr) : les cases d'un même bridge se touchent,
   trait franc de la famille autour, un trait COURT et centré à chaque jonction.
   ⚠️ Ordre voulu : border-color d'abord, puis la transparence des jonctions. */
.usm-t.jr { border-top-right-radius: 0; border-bottom-right-radius: 0; }
/* La case soudée s'ÉLARGIT vers sa voisine d'autant qu'elle recule : les dents
   suivantes ne bougent pas, le haut reste aligné sur le bas (21 au-dessus de 31). */
.usm-t.jl { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: calc(-1 * var(--usm-gap) - 1.5px);
  flex-basis: calc(var(--usm-w) + var(--usm-gap) + 1.5px); width: calc(var(--usm-w) + var(--usm-gap) + 1.5px); }
/* Par-dessus le milieu (11-21) : l'écart se PARTAGE moitié-moitié — la 11 déborde à
   droite, la 21 à gauche, les deux dents gardent la même largeur (Illan 25/09/2026 :
   « c'est inégal entre 11 et 21 »). Les voisines ne bougent pas. */
.usm-t.jr-mid { flex-basis: calc(var(--usm-w) + var(--usm-demi)); width: calc(var(--usm-w) + var(--usm-demi)); margin-right: calc(-1 * var(--usm-demi)); }
.usm-t.mid.jl { margin-left: calc(var(--usm-demi) - 1.5px - var(--usm-gap));
  flex-basis: calc(var(--usm-w) + var(--usm-demi)); width: calc(var(--usm-w) + var(--usm-demi)); }
.usm-t.jl, .usm-t.jr { border-color: currentColor; }
.usm-t.jl { border-left-color: transparent; background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: left center; background-size: 1.5px 40%; }
.usm-t.jr { border-right-color: transparent; }
.usm-t.jl:hover, .usm-t.jr:hover { transform: none; }
/* Sélection : l'accent du labo (plein), un halo. */
.usm-t.is-sel { background-color: var(--accent); border-color: var(--accent); color: #fff; transform: translateY(-2px);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent), 0 6px 12px -6px color-mix(in srgb, var(--accent) 70%, transparent); }
.usm-t.is-sel i { color: rgba(255,255,255,.85); opacity: 1; }
.usm-t.is-sel.jl, .usm-t.is-sel.jr { transform: none; }
/* Survol d'un groupe dans la liste → ses dents s'allument. */
.usm-t.is-hl { outline: 2px solid color-mix(in srgb, var(--text) 45%, transparent); outline-offset: 2px; }

.usm-leg { margin-top: 9px; }
.ais-li.usm-li-libre { background: var(--surface); border-color: var(--border); }
.ais-li.usm-li-sel { background: var(--accent); border-color: var(--accent); }

.usm-vide { display: grid; justify-items: center; gap: 4px; padding: 16px 20px; text-align: center; min-width: 420px; }
.usm-vide .ilx { --ilx-t: 30px; opacity: .8; }
.usm-vide b { font-size: .86rem; }
.usm-vide span { font-size: .74rem; color: var(--muted); max-width: 360px; }

/* Barre d'actions : les deux types aux couleurs du schéma, désactivés sans sélection. */
.usm-bar { display: flex; gap: 8px; margin-top: 12px; }
.usm-act { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 40px;
  border-radius: 11px; font: inherit; font-size: .84rem; font-weight: 800; cursor: pointer; border: 1.5px solid;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out); }
.usm-act--u { background: var(--th-u-bg); border-color: var(--th-u-bd); color: var(--th-u-tx); }
.usm-act--s { background: var(--th-s-bg); border-color: var(--th-s-bd); color: var(--th-s-tx); }
.usm-act:not(:disabled):hover { border-color: currentColor; transform: translateY(-1px); box-shadow: 0 6px 14px -8px currentColor; }
.usm-act:not(:disabled):active { transform: none; }
.usm-act:disabled { opacity: .42; cursor: not-allowed; }
.usm-act-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.usm-act kbd { font: 700 .62rem/1 'DM Mono', ui-monospace, monospace; padding: 2px 5px; border-radius: 5px;
  border: 1px solid color-mix(in srgb, currentColor 35%, transparent); opacity: .75; }
.usm-hint { min-height: 1.1em; margin: 7px 2px 0; font-size: .72rem; color: var(--muted); transition: color var(--dur-fast) var(--ease-out); }
.usm-hint.is-err { color: var(--danger); font-weight: 600; }

/* Groupes définis : pastilles aux couleurs du schéma (clic = resélectionner ses dents). */
.usm-groups { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.usm-groups:empty { display: none; }
.usm-g { display: inline-flex; align-items: center; border-radius: 999px; overflow: hidden;
  background: var(--th-u-bg); border: 1px solid var(--th-u-bd); color: var(--th-u-tx);
  animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
.usm-g.is-s { background: var(--th-s-bg); border-color: var(--th-s-bd); color: var(--th-s-tx); }
.usm-g-b { display: inline-flex; align-items: center; gap: 6px; padding: 4px 4px 4px 10px; border: none; background: none;
  color: inherit; font: inherit; font-size: .78rem; font-weight: 800; cursor: pointer; }
.usm-g-b .ilx { --ilx-t: 14px; }
.usm-g-x { width: 26px; height: 26px; border: none; background: none; color: inherit; opacity: .55; cursor: pointer;
  font-size: 1rem; line-height: 1; transition: opacity var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out); }
.usm-g-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }

/* Pied : actions de masse à gauche, « Terminé » à droite. */
.usm-ft { display: flex; align-items: center; gap: 6px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.usm-sp { flex: 1; }
.usm-lnk { display: inline-flex; align-items: center; gap: 5px; height: 32px; padding: 0 11px; border-radius: 9px; white-space: nowrap;
  border: 1px solid transparent; background: transparent; color: var(--accent-text); font: inherit; font-size: .76rem; font-weight: 700; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out); }
.usm-lnk:not(:disabled):hover { background: var(--surface-2); }
.usm-lnk:disabled { opacity: .4; cursor: default; }
.usm-lnk .ilx { --ilx-t: 15px; }
.usm-lnk--danger { color: var(--muted); }
.usm-lnk--danger:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
.usm-lnk--danger.is-arme { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, var(--surface)); background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
.usm-done { height: 36px; padding: 0 22px; border: none; border-radius: 10px; background: var(--grad); color: #fff;
  font: inherit; font-size: .84rem; font-weight: 800; cursor: pointer; box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--accent) 70%, transparent);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out); }
.usm-done:hover { transform: translateY(-1px); box-shadow: 0 10px 20px -8px color-mix(in srgb, var(--accent) 70%, transparent); }
.usm-done:active { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .usm-t, .usm-act, .usm-done, .usm-g, .usm-x, .usm-lnk, .usm-meta, .usm-hint, .usm-g-x,
  #popup-unit-solid .us-modal, #popup-unit-solid.is-closing .us-modal { transition: none; animation: none; }
  .usm-t:hover, .usm-t.is-sel, .usm-act:hover, .usm-done:hover { transform: none; }
}

/* ── Bouton 📦 Annexes (js/produits-annexes.js) — états actif/inactif par classes
   (remplace les btn.style.* inline, piège dark n°1). Identité ambre/orange du
   module conservée en clair ; fonds via color-mix → dark-safe. */
#btn-annexes.anx-off { background: color-mix(in srgb, #f0c040 14%, var(--surface)); border: 1px solid #f0c040; box-shadow: none; }
#btn-annexes.anx-on  { background: color-mix(in srgb, #e65100 12%, var(--surface)); border: 2px solid #e65100; box-shadow: 0 0 8px rgba(230,81,0,0.25); }
html[data-theme="dark"] #btn-annexes.anx-off { color: #f0c040; }
html[data-theme="dark"] #btn-annexes.anx-on  { color: #ff8a3d; box-shadow: 0 0 8px rgba(230,81,0,0.45); }

/* ══ Historique patient (js/patient-historique.js) — bouton + modale timeline ══
   Tout en tokens tenant (--accent/--teal/--surface/--border) + color-mix →
   dark-safe et multi-tenant sans override par couleur. Signature visuelle :
   le rail chronologique en dégradé de marque (accent→teal), un point par bon. */
/* ── La fiche du dentiste (POF) EN SUPERPOSITION ─────────────────────────────
   Elle s'ouvrait dans une popup — bloquée par les navigateurs — et, quand le
   proxy renvoyait application/octet-stream, le blob se TÉLÉCHARGEAIT au lieu de
   s'afficher (Illan 18/09/2026). z 1700 : au-dessus de la visionneuse (1500) et
   de l'historique patient (1600), puisqu'on la demande depuis l'une ou l'autre. */
.dlb-pof-ov { position: fixed; inset: 0; z-index: 1700; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(10, 22, 34, .62); -webkit-backdrop-filter: var(--ov-blur, blur(4px)); backdrop-filter: var(--ov-blur, blur(4px));
  font-family: 'DM Sans', system-ui, sans-serif; animation: phxFade var(--dur-fast) ease backwards; }
.dlb-pof-panel { display: flex; flex-direction: column; width: min(1000px, 96vw); height: min(92vh, 1180px);
  background: var(--surface); border: 1px solid var(--border); border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 70px rgba(10, 30, 50, .38); animation: phxRise var(--dur-base) ease backwards; }
.dlb-pof-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px 10px 16px; border-bottom: 1px solid var(--border); }
.dlb-pof-t { font-size: .92rem; font-weight: 800; flex: none; }
.dlb-pof-n { flex: 1; min-width: 0; font-size: .72rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlb-pof-tab, .dlb-pof-x { flex: none; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2, var(--surface));
  color: var(--muted); font: 700 .72rem 'DM Sans', system-ui, sans-serif; padding: 5px 10px; cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast); }
.dlb-pof-tab:hover, .dlb-pof-x:hover { border-color: var(--accent); color: var(--accent-text); }
.dlb-pof-x:hover { border-color: var(--danger); color: var(--danger); }
.dlb-pof-tab:focus-visible, .dlb-pof-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Fond BLANC sous le cadre : un POF est un document imprimé, pas une interface —
   il ne connaît pas le mode nuit et son fond est transparent (piège vécu sur
   l'aperçu du portail). */
.dlb-pof-frame { flex: 1; min-height: 0; width: 100%; border: 0; background: #fff; }
@media (prefers-reduced-motion: reduce) { .dlb-pof-ov, .dlb-pof-panel { animation: none; } }
/* Un PDF s'affiche « page entière » : la fenêtre prend la forme d'une page (A4 +
   la hauteur de l'en-tête), sinon le lecteur laisse deux bandes grises. */
.dlb-pof-a4 { width: auto; max-width: 96vw; aspect-ratio: 1 / 1.5; }
html.mobile-zoom-default .dlb-pof-panel { width: 100%; max-width: 98vw; height: 94dvh; border-radius: 14px; }
html.mobile-zoom-default .dlb-pof-a4 { width: auto; aspect-ratio: 1 / 1.5; }
/* Plusieurs bons (fiche fusionnée) : leurs fiches CÔTE À CÔTE, chacune sous son
   code — un seul bouton Digilab au lieu d'un par bon (Illan, 28/09/2026). La
   fenêtre prend la largeur ; au-delà de ce qui tient, on fait défiler les
   colonnes, jamais la page. */
.dlb-pof-multi { width: 98vw; }
.dlb-pof-cols { flex: 1; min-height: 0; display: flex; gap: 1px; background: var(--border); overflow-x: auto; scroll-snap-type: x mandatory; }
.dlb-pof-col { flex: 1 1 0; min-width: min(440px, 92vw); display: flex; flex-direction: column; background: var(--surface); scroll-snap-align: start; }
.dlb-pof-colhd { display: flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; border-bottom: 1px solid var(--border); }
.dlb-pof-code { flex: none; font-size: .8rem; font-weight: 800; color: var(--accent-text); }

/* z 1600 > visionneuse .vf-overlay (1500) : l'historique s'ouvre AUSSI depuis la
   visionneuse et doit passer devant ; « Voir » ferme la modale avant d'ouvrir la fiche. */
.phx-overlay { position:fixed; inset:0; z-index:1600; display:flex; align-items:center; justify-content:center;
  padding:16px; background:rgba(15,35,55,.55); -webkit-backdrop-filter:var(--ov-blur, blur(4px)); backdrop-filter:var(--ov-blur, blur(4px));
  font-family:'DM Sans',system-ui,sans-serif; animation:phxFade var(--dur-fast) ease backwards; }
.phx-panel { display:flex; flex-direction:column; width:min(720px, 94vw); max-height:86vh;
  background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:16px;
  box-shadow:0 24px 70px rgba(10,30,50,.35); overflow:hidden; animation:phxRise var(--dur-base) ease backwards; }
@keyframes phxFade { from { opacity:0; } to { opacity:1; } }
@keyframes phxRise { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
@media (prefers-reduced-motion: reduce) { .phx-overlay, .phx-panel { animation:none; } }

.phx-header { display:flex; align-items:flex-start; gap:10px; padding:14px 16px 10px;
  border-bottom:1px solid var(--border); }
.phx-title-wrap { flex:1; min-width:0; }
.phx-title { display:flex; align-items:center; gap:8px; font-size:1.02rem; font-weight:800; }
.phx-title .ic { color:var(--accent-text); flex:0 0 auto; }
.phx-subtitle { font-size:0.74rem; color:var(--muted); margin-top:2px; }
.phx-close { flex:0 0 auto; display:flex; align-items:center; justify-content:center; width:32px; height:32px;
  border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer;
  transition:background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.phx-close:hover { background:color-mix(in srgb, var(--danger) 10%, var(--surface)); color:var(--danger); transform:rotate(90deg); }
.phx-close:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

.phx-loading { padding:8px 16px 0; font-size:0.72rem; color:var(--muted); }
.phx-loading::before { content:''; display:inline-block; width:7px; height:7px; border-radius:50%;
  background:var(--accent); margin-right:6px; animation:phxPulse 1s ease-in-out infinite; vertical-align:1px; }
@keyframes phxPulse { 0%,100% { opacity:.25; } 50% { opacity:1; } }
@media (prefers-reduced-motion: reduce) { .phx-loading::before { animation:none; } }

/* Rail chronologique : dégradé de marque + un point par bon */
.phx-list { flex:1; overflow-y:auto; overflow-x:hidden; padding:14px 16px 14px 30px; position:relative;
  display:flex; flex-direction:column; gap:12px; }
.phx-item { position:relative; }
.phx-item::before { content:''; position:absolute; left:-15px; top:22px; bottom:-14px; width:2px;
  background:linear-gradient(180deg, var(--accent), var(--teal)); opacity:.35; }
.phx-item:last-child::before { display:none; }
.phx-item::after { content:''; position:absolute; left:-19px; top:13px; width:10px; height:10px; border-radius:50%;
  background:var(--surface); border:2px solid var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent); }
.phx-card { border:1px solid var(--border); border-radius:12px; padding:10px 12px; background:var(--surface);
  transition:border-color var(--dur-fast), box-shadow var(--dur-fast); }
.phx-card:hover { border-color:color-mix(in srgb, var(--accent) 45%, var(--border));
  box-shadow:0 2px 10px color-mix(in srgb, var(--accent) 8%, transparent); }
.phx-head { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.phx-date { font-size:0.78rem; font-weight:700; font-variant-numeric:tabular-nums; }
.phx-code { font-size:0.78rem; color:var(--accent-text); }
.phx-statut { font-size:0.7rem; font-weight:700; padding:1px 9px; border-radius:10px;
  background:color-mix(in srgb, var(--accent) 10%, var(--surface)); color:var(--accent-text); }
.phx-refaire { font-size:0.66rem; font-weight:800; padding:1px 8px; border-radius:10px;
  background:color-mix(in srgb, var(--danger) 12%, var(--surface)); color:var(--danger); }
.phx-voir { margin-left:auto; display:inline-flex; align-items:center; gap:4px; padding:4px 10px;
  border:1px solid var(--border); border-radius:8px; background:transparent; color:var(--accent-text);
  font:600 0.7rem 'DM Sans',system-ui,sans-serif; cursor:pointer; transition:border-color var(--dur-fast), background var(--dur-fast); }
.phx-voir:hover { border-color:var(--accent); background:var(--accent-light); }
.phx-voir:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.phx-sub { font-size:0.72rem; color:var(--muted); margin-top:3px; }
.phx-actes { margin-top:8px; max-width:100%; }
.phx-vide { padding:26px 10px; text-align:center; color:var(--muted); font-size:0.82rem; }
.phx-vide-sub { font-size:0.72rem; }

/* Deux colonnes quand l'historique s'ouvre DEPUIS un cas (18/09/2026) : à gauche
   les anciens bons du patient, à droite le journal de ce cas-ci. La carte
   « Journal du cas » a quitté la fiche — un seul endroit pour « ce qui s'est
   passé », et ~110 px de hauteur rendus à la colonne de la fiche. */
.phx-body { display:flex; flex:1; min-height:0; }
.phx-body > .phx-list { flex:1 1 auto; min-width:0; }
.phx-panel.phx-2col { width:min(1040px, 96vw); }
.phx-side { flex:0 0 288px; min-width:0; overflow-y:auto; padding:14px 16px;
  border-left:1px solid var(--border); background:color-mix(in srgb, var(--accent) 4%, var(--surface)); }
.phx-side-t { font-size:0.68rem; font-weight:800; text-transform:uppercase; letter-spacing:.04em;
  color:var(--muted); margin-bottom:9px; }

.phx-footer { display:flex; justify-content:flex-end; padding:10px 16px; border-top:1px solid var(--border); }
.phx-large { display:inline-flex; align-items:center; gap:6px; padding:6px 12px; border-radius:8px;
  border:1px dashed var(--border); background:transparent; color:var(--muted);
  font:600 0.7rem 'DM Sans',system-ui,sans-serif; cursor:pointer; transition:border-color var(--dur-fast), color var(--dur-fast); }
.phx-large:hover:not(:disabled) { border-color:var(--accent); color:var(--accent-text); }
.phx-large:disabled { cursor:default; opacity:.7; }
.phx-large:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

/* Bandeau « reprendre l'ancien bon » (cas à refaire dont le bon ne dit pas quoi
   refaire — 04/09/2026). Posé en tête de #prescription-form avec la classe
   .alerte-bandeau : il hérite de la palette orange du scan, jour ET nuit. Les
   boutons se peignent en currentColor pour suivre les deux thèmes sans copie. */
/* ── Lignes FANTÔMES du résumé IA : les actes du dernier bon du patient, proposés
   quand un cas « à refaire » ne dit pas QUOI refaire. Elles se posent LÀ OÙ la
   colonne affichait « — » (aucun bloc ajouté) et gardent le rendu d'une vraie
   ligne d'acte, en pointillé translucide : on voit tout de suite que ce n'est pas
   encore la commande du jour. Un « + » par acte (Illan 04/09). Palette héritée des
   .ais-* → jour et nuit sans une seule couleur nouvelle. */
.ais-fant-bloc { display:flex; flex-direction:column; align-items:flex-start; gap:4px;
  padding:6px 7px 7px; border:1px dashed var(--border); border-radius:8px;
  background:color-mix(in srgb, var(--muted) 6%, transparent); }
.ais-fant-t { display:flex; align-items:center; flex-wrap:wrap; gap:5px; margin-bottom:2px;
  font-size:.6rem; font-weight:800; text-transform:uppercase; letter-spacing:.4px; color:var(--muted); }
.ais-fant-t .ais-lab { font-size:.66rem; padding:0 6px; }
.ais-fant-d, .ais-fant-te { font-size:.6rem; font-weight:700; color:var(--muted); text-transform:none; letter-spacing:0; }
.ais-fant-te::before { content:'· '; }
/* La ligne elle-même : même gabarit que .ais-act, en attente d'être prise. */
.ais-act.ais-fant { background:transparent; border-style:dashed; opacity:.72;
  transition:opacity var(--dur-fast), border-color var(--dur-fast); }
.ais-act.ais-fant:hover { opacity:1; border-color:var(--accent); }
/* Le « + » ouvre la ligne (order:-1) : en dernier il passait à la ligne dès que la
   colonne se resserre — un bouton d'action orphelin sous son acte. */
.ais-fant-add { order:-1; margin-right:1px; width:18px; height:18px; flex:0 0 auto; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--accent); border-radius:50%; background:transparent; color:var(--accent-text);
  font:800 .82rem/1 'DM Sans',system-ui,sans-serif; cursor:pointer;
  transition:background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.ais-fant-add:hover { background:var(--accent); color:#fff; }
.ais-fant-add:active { transform:scale(.9); }
.ais-fant-add:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
/* Le « − » de la ligne fantôme : écarter une proposition qui ne correspond pas.
   Discret par défaut (c'est le « + » qu'on vise en général), rouge au survol. */
.ais-fant-hide { order:-1; margin-right:3px; width:18px; height:18px; flex:0 0 auto; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--border); border-radius:50%; background:transparent; color:var(--muted);
  font:800 .82rem/1 'DM Sans',system-ui,sans-serif; cursor:pointer;
  transition:background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast); }
.ais-fant-hide:hover { background:var(--danger); border-color:var(--danger); color:#fff; }
.ais-fant-hide:active { transform:scale(.9); }
.ais-fant-hide:focus-visible { outline:2px solid var(--danger); outline-offset:2px; }

/* Le « − » symétrique, sur l'acte DÉJÀ repris : même place, même gabarit que le
   « + » (l'œil le retrouve au même endroit), en gris tant qu'on ne le survole pas. */
.ais-fant-del { order:-1; margin-right:1px; width:18px; height:18px; flex:0 0 auto; padding:0;
  display:inline-flex; align-items:center; justify-content:center;
  border:1px solid var(--border); border-radius:50%; background:transparent; color:var(--muted);
  font:800 .82rem/1 'DM Sans',system-ui,sans-serif; cursor:pointer;
  transition:background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast); }
.ais-fant-del:hover { background:var(--danger); border-color:var(--danger); color:#fff; }
.ais-fant-del:active { transform:scale(.9); }
.ais-fant-del:focus-visible { outline:2px solid var(--danger); outline-offset:2px; }
@media (prefers-reduced-motion: reduce) { .ais-fant-add:active, .ais-fant-del:active, .ais-fant-hide:active { transform:none; } }

/* Nuit : l'ossature est déjà en tokens ; on ne force que l'ombre du panneau */
html[data-theme="dark"] .phx-panel { box-shadow:0 24px 70px rgba(0,0,0,.6); }

/* Téléphone (classe posée par index.html / dentiste.html — jamais @media 768px,
   cf. R21). Demande Illan 17/07 : PAS de plein écran — le même panneau centré
   qu'au labo, juste un peu plus large et des marges visibles autour (on voit que
   c'est une fenêtre posée par-dessus). Cible de calibration = S24 Ultra (860px
   de large en CSS effectif). Croix agrandie au doigt, zéro scroll horizontal. */
html.mobile-zoom-default .phx-overlay { padding:22px; }
html.mobile-zoom-default .phx-panel { width:min(720px, 90vw); max-height:78dvh; border-radius:16px; }
html.mobile-zoom-default .phx-close { width:42px; height:42px; }
html.mobile-zoom-default .phx-list { padding-left:26px; }
html.mobile-zoom-default .phx-panel.phx-2col { width:min(720px, 90vw); }
html.mobile-zoom-default .phx-body { flex-direction:column; }
html.mobile-zoom-default .phx-side { flex:0 0 auto; max-height:40dvh; border-left:none; border-top:1px solid var(--border); }

/* ── Badge OLD CASE (cas à refaire — référence de l'ancien bon du patient) ──
   Violet = couleur métier fixe (comme le rose adjointe), distincte des alertes
   jaunes « rules » et du rouge refaire. Cliquable → ouvre l'ancien bon.
   .ais-ocrow = sa ligne dans la carte (même gabarit que .ais-com) : la carte est
   en overflow:hidden, sans cette ligne la bulle est rognée par le bord arrondi. */
.ais-ocrow { display:flex; flex-wrap:wrap; align-items:center; gap:6px;
  padding:6px 10px; border-top:1px solid var(--border); }

.ais-oldcase { display:inline-flex; align-items:center; gap:4px; margin:0; padding:4px 10px;
  border:1.5px solid #7c3aed; border-radius:8px; font-size:.78rem; font-weight:700;
  background:color-mix(in srgb, #7c3aed 9%, var(--surface)); color:#6d28d9; cursor:pointer;
  transition:background var(--dur-fast), box-shadow var(--dur-fast); }
.ais-oldcase:hover { background:color-mix(in srgb, #7c3aed 16%, var(--surface));
  box-shadow:0 0 0 3px color-mix(in srgb, #7c3aed 14%, transparent); }
html[data-theme="dark"] .ais-oldcase { color:#c4b5fd; border-color:#8b5cf6; }
.ais-oldcase-x { margin-left:2px; padding:0 2px; font-weight:800; opacity:.55; transition:opacity var(--dur-fast), color var(--dur-fast); }
.ais-oldcase-x:hover { opacity:1; color:var(--danger); }

/* Badge RULES — même gabarit qu'OLD CASE, mais aux couleurs du post-it jaune
   (tokens --note-*, définis en clair ET en dark) : l'œil fait le lien avec la note
   posée à droite. Curseur main SEULEMENT quand le clic la rouvre (en lecture seule
   la note se poserait derrière la modale, le badge n'y est qu'un avertissement). */
/* margin-left:auto → le badge RULES part au BORD DROIT de sa ligne (Illan 04/09) :
   c'est un avertissement, pas une donnée de la fiche, et il tombe pile au-dessus de
   la fenêtre qui s'ouvre à droite. Seul sur sa ligne il reste à droite ; avec OLD
   CASE, il s'en écarte au maximum. */
.ais-rules { display:inline-flex; align-items:center; gap:4px; margin:0 0 0 auto; padding:4px 10px;
  border:1.5px solid var(--note-border); border-radius:8px; font-size:.78rem; font-weight:700;
  background:color-mix(in srgb, var(--note-border) 12%, var(--surface));
  /* L'ambre du post-it ramené vers l'encre du thème : --text bascule avec le thème,
     donc le mélange fonce en clair et éclaircit en dark, sans second réglage — utile
     aussi parce que les presets dark (minuit, graphite, oled) changent --surface.
     Mesuré sur les pixels rendus : 7.8:1 en clair, 9.5:1 en dark (5.2:1 avec l'ambre
     seul — ça passait déjà, le mélange donne juste de la marge). */
  color:color-mix(in srgb, var(--note-accent) 62%, var(--text));
  transition:background var(--dur-fast), box-shadow var(--dur-fast); }
.ais-rules.is-click { cursor:pointer; }
.ais-rules.is-click:hover { background:color-mix(in srgb, var(--note-border) 22%, var(--surface));
  box-shadow:0 0 0 3px color-mix(in srgb, var(--note-border) 18%, transparent); }
.ais-rules.is-click:focus-visible { outline:2px solid var(--note-border); outline-offset:2px; }

/* Bouton « Historique » de la fiche — UNIQUE (décision Illan 17/07 : plus de
   jumeau dans le bandeau). Section Patient, ligne Femme/Homme, poussé à droite :
   sous les yeux sans rogner la largeur du champ nom. */
.phx-btn { display:inline-flex; align-items:center; gap:5px; flex:0 0 auto; align-self:center; margin-left:auto;
  padding:4px 10px; border-radius:999px; border:1px solid var(--border);
  background:var(--surface); color:var(--accent-text); cursor:pointer; white-space:nowrap;
  font:600 .72rem 'DM Sans',system-ui,sans-serif;
  transition:border-color var(--dur-fast), box-shadow var(--dur-fast), background var(--dur-fast); }
.phx-btn:hover { border-color:var(--accent); background:var(--accent-light);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.phx-btn:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.phx-btn .ic { flex:0 0 auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   MODERNISATION POPUPS FORMULAIRE + ÉCRAN PRINCIPAL — 12/08/2026 (Lot A).
   Classes scopées par surface (rfx- / cmx- / alcx- / alpx- / fpk- /
   fhx- / hl- / fx- / scanld / ils-sel-). Tokens partout, dark automatique,
   entrées ilsShellIn + sorties .is-closing (motionClose). Règles 22 + 25.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Croix de fermeture partagée des popups du formulaire ── */
.fx-x { margin-left:auto; width:28px; height:28px; flex:none; display:flex; align-items:center; justify-content:center;
  border:none; border-radius:50%; background:transparent; color:var(--muted); font-size:1rem; line-height:1; cursor:pointer;
  transition: background var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.fx-x:hover { background:var(--surface-2); color:var(--text); transform: rotate(90deg); }
.fx-x:focus-visible { outline:2px solid color-mix(in srgb, var(--accent) 45%, transparent); }

/* ── Pastille d'emoji de titre (emoji ASSUMÉ, décision Illan 12/08) ── */
.fx-ico { width:32px; height:32px; flex:none; display:flex; align-items:center; justify-content:center; border-radius:10px;
  font-size:.95rem; line-height:1;
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 13%, var(--surface)), color-mix(in srgb, var(--teal) 13%, var(--surface)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent), 0 4px 12px -4px color-mix(in srgb, var(--accent) 30%, transparent); }
.fx-ico--danger { background: linear-gradient(135deg, color-mix(in srgb, var(--danger) 14%, var(--surface)), color-mix(in srgb, var(--danger) 6%, var(--surface)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 28%, transparent), 0 4px 12px -4px color-mix(in srgb, var(--danger) 35%, transparent); }
.fx-ico--warn { background: linear-gradient(135deg, color-mix(in srgb, var(--warn) 15%, var(--surface)), color-mix(in srgb, var(--warn) 6%, var(--surface)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--warn) 30%, transparent), 0 4px 12px -4px color-mix(in srgb, var(--warn) 35%, transparent); }
.fx-ico--purple { background: linear-gradient(135deg, color-mix(in srgb, var(--purple) 13%, var(--surface)), color-mix(in srgb, var(--purple) 5%, var(--surface)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--purple) 26%, transparent), 0 4px 12px -4px color-mix(in srgb, var(--purple) 32%, transparent); }

/* ── Popup « À refaire » (#popup-refaire) — affiché/masqué par JS (display inline).
      Refonte du 28/09/2026 : lignes souples (même famille que les sous-menus de la fiche),
      une coche dessinée, les dents en pastille, « Tout / Aucun » en liens discrets. */
.rfx-ov { position:fixed; inset:0; background:rgba(15,35,55,.55); z-index:1000;
  justify-content:center; align-items:center; animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
.rfx-card { background:var(--surface); color:var(--text); border:1px solid color-mix(in srgb, var(--danger) 22%, var(--border)); border-radius:16px;
  padding:14px 14px 12px; width:340px; max-width:92vw; max-height:80vh; overflow-y:auto; box-sizing:border-box;
  box-shadow: 0 24px 48px -18px color-mix(in srgb, var(--danger) 35%, transparent), 0 4px 14px color-mix(in srgb, var(--text) 10%, transparent);
  animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
.rfx-ov.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
.rfx-ov.is-closing .rfx-card { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }
.rfx-head { display:flex; align-items:center; gap:10px; margin-bottom:4px; }
.rfx-title { margin:0; font-size:.9rem; font-weight:800; letter-spacing:-.01em; color:var(--text); flex:1; }
.rfx-card .fx-x:hover { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); color:var(--danger); }
.rfx-hint { font-size:.66rem; color:var(--muted); margin:0 0 10px 42px; line-height:1.4; }
.rfx-liste { display:flex; flex-direction:column; gap:2px; margin-bottom:10px; }
.rfx-row { border-radius:10px; transition: background-color var(--dur-fast) var(--ease-out); }
.rfx-row:hover { background: color-mix(in srgb, var(--danger) 6%, var(--surface)); }
.rfx-row:has(input:checked) { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); }
.rfx-row label { display:flex; align-items:center; gap:9px; padding:7px 9px; cursor:pointer; font-size:.76rem; color:var(--text); }
.rfx-row input[type="checkbox"] { position:absolute; opacity:0; width:0; height:0; pointer-events:none; }
.rfx-ck { flex:none; width:16px; height:16px; display:grid; place-items:center; border-radius:5px; background:var(--surface);
  border:1.5px solid color-mix(in srgb, var(--danger) 40%, var(--border));
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); }
.rfx-ck svg { width:11px; height:11px; fill:none; stroke:var(--surface); stroke-width:2.3; stroke-linecap:round; stroke-linejoin:round; opacity:0;
  transition: opacity var(--dur-fast) var(--ease-out); }
.rfx-row input:checked + .rfx-ck { background:var(--danger); border-color:var(--danger); }
.rfx-row input:checked + .rfx-ck svg { opacity:1; }
.rfx-row input:focus-visible + .rfx-ck { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }
.rfx-acte { flex:1; min-width:0; }
.rfx-row:has(input:checked) .rfx-acte { font-weight:700; }
.rfx-dents-ref { flex:none; padding:1px 7px; border-radius:999px; background: color-mix(in srgb, var(--muted) 12%, var(--surface));
  color:var(--muted); font: 600 .62rem 'DM Mono', monospace; white-space:nowrap; }
.rfx-dents-wrap { margin:-2px 9px 7px 34px; }
.rfx-row .rfx-dents { width:100%; box-sizing:border-box; padding:4px 8px; font-size:.7rem; border:1px solid color-mix(in srgb, var(--danger) 25%, var(--border));
  border-radius:8px; font-family:inherit; background:var(--surface); color:var(--text);
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.rfx-row .rfx-dents:focus { outline:none; border-color:var(--danger); box-shadow:0 0 0 3px color-mix(in srgb, var(--danger) 14%, transparent); }
.rfx-empty { color:var(--muted); font-size:.76rem; margin:6px 9px 10px; }
.rfx-foot { display:flex; gap:4px; align-items:center; padding-top:9px; border-top:1px dashed var(--border); }
.rfx-btn { font-size:.68rem; background:none; border:0; border-radius:7px; padding:4px 8px; cursor:pointer; color:var(--muted); font-weight:700;
  transition: background-color var(--dur-fast), color var(--dur-fast); }
.rfx-btn:hover { background: color-mix(in srgb, var(--danger) 8%, var(--surface)); color:var(--text); }
.rfx-primary { margin-left:auto; font-size:.74rem; background:var(--danger); color:var(--surface); border:none; border-radius:999px; padding:6px 18px;
  cursor:pointer; font-weight:800; box-shadow:0 4px 12px -4px color-mix(in srgb, var(--danger) 55%, transparent);
  transition: transform var(--dur-fast), box-shadow var(--dur-fast); }
.rfx-primary:hover { transform: translateY(-1px); box-shadow:0 6px 16px -5px color-mix(in srgb, var(--danger) 65%, transparent); }
.rfx-btn:focus-visible, .rfx-primary:focus-visible { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }

/* ── Zone « À refaire » de la carte Cabinet (refonte du 28/09/2026) : un interrupteur ;
      allumé → le crayon « Qu'est-ce qu'on refait ? », l'étiquette SAV si la pièce est
      revenue, et la question de la pièce (retournée : oui / non). ── */
.rfx-zone { margin-top:7px; }
.rfx-l1 { display:flex; align-items:center; gap:5px; }
.rfx-tog { position:relative; display:inline-flex; align-items:center; gap:5px; height:26px; box-sizing:border-box; padding:0 11px 0 8px; border-radius:999px;
  border:1px solid color-mix(in srgb, var(--danger) 40%, var(--border)); background:var(--surface); color:var(--danger); font-size:.7rem; font-weight:800; cursor:pointer; white-space:nowrap;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); }
.rfx-tog input { position:absolute; opacity:0; width:0; height:0; pointer-events:none; }
.rfx-tog:hover { background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
.rfx-tog:has(input:checked) { background:var(--danger); border-color:var(--danger); color:var(--surface); }
.rfx-tog:has(input:focus-visible) { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }
/* Crayon « Qu'est-ce qu'on refait ? » (#btn-refaire-detail, affiché par JS en inline-block) + le nombre choisi. */
.rfx-edit { position:relative; width:26px; height:26px; box-sizing:border-box; padding:0; border-radius:50%; text-align:center; line-height:24px;
  border:1px solid color-mix(in srgb, var(--danger) 35%, var(--border)); background:var(--surface); color:var(--danger); cursor:pointer;
  transition: background-color var(--dur-fast), transform var(--dur-fast); }
.rfx-edit .ilx { vertical-align:middle; }
.rfx-edit:hover { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); transform: translateY(-1px); }
.rfx-edit:focus-visible { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }
.rfx-n { position:absolute; top:-5px; right:-6px; min-width:15px; height:15px; box-sizing:border-box; padding:0 3px; border-radius:999px;
  background:var(--danger); color:var(--surface); font-size:.52rem; font-weight:800; line-height:15px; text-align:center; }
.rfx-sav { display:none; padding:2px 7px; border-radius:999px; font-size:.56rem; font-weight:800; letter-spacing:.05em;
  background: color-mix(in srgb, var(--teal) 16%, var(--surface)); color:var(--teal); border:1px solid color-mix(in srgb, var(--teal) 40%, transparent); }
.rfx-zone:has(#a-refaire:checked)[data-piece="oui"] .rfx-sav { display:inline-flex; }
.rfx-ret { display:none; align-items:center; gap:6px; margin-top:6px; }
.rfx-zone:has(#a-refaire:checked) .rfx-ret { display:flex; }
.rfx-ret-l { font-size:.56rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--muted); white-space:nowrap; }
.rfx-seg { display:flex; gap:2px; padding:2px; border-radius:9px; background: color-mix(in srgb, var(--danger) 7%, var(--surface)); }
.rfx-seg button { display:inline-flex; align-items:center; gap:4px; padding:3px 9px; border:0; border-radius:7px; background:none; color:var(--muted);
  font:inherit; font-size:.66rem; font-weight:700; cursor:pointer; white-space:nowrap;
  transition: background-color var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast); }
.rfx-seg button:hover { color:var(--text); }
.rfx-seg button[aria-pressed="true"] { background:var(--surface); color:var(--text); box-shadow:0 1px 3px color-mix(in srgb, var(--text) 16%, transparent); }
.rfx-seg button:focus-visible { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }

/* ── Popup Commentaires agrandie (#commentaire-popup) ─────────────────────── */
/* Keyframes DÉDIÉES : la carte est centrée par transform translate(-50%,-50%),
   les keyframes génériques (transform:none) casseraient le centrage. */
@keyframes cmxIn  { from { opacity:0; transform: translate(-50%,-50%) translateY(14px) scale(.985); } to { opacity:1; transform: translate(-50%,-50%); } }
@keyframes cmxOut { from { opacity:1; transform: translate(-50%,-50%); } to { opacity:0; transform: translate(-50%,-50%) translateY(8px) scale(.99); } }
.cmx-pop { position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); z-index:700;
  width:500px; max-width:90vw; max-height:80vh; flex-direction:column;
  background:var(--surface); color:var(--text); border:1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius:16px; padding:16px; box-shadow: 0 12px 44px color-mix(in srgb, var(--accent) 20%, rgba(20,45,70,.25)), var(--shadow-sm);
  animation: cmxIn var(--dur-enter) var(--ease-out) backwards; }
.cmx-pop.is-closing { animation: cmxOut var(--dur-exit) var(--ease-out) both; }
.cmx-head { display:flex; align-items:center; gap:9px; margin-bottom:10px; }
.cmx-title { font-size:.82rem; font-weight:800; color:var(--accent-text); flex:1; }
.cmx-ta { flex:1; min-height:300px; font-size:.82rem; border:1px solid var(--border); border-radius:9px; padding:10px;
  font-family:'DM Sans',sans-serif; line-height:1.5; resize:vertical; background:var(--surface); color:var(--text);
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.cmx-ta:focus { outline:none; border-color:var(--teal); box-shadow:0 0 0 3px color-mix(in srgb, var(--teal) 16%, transparent); }
.cmx-foot { display:flex; justify-content:flex-end; gap:8px; margin-top:10px; }
.cmx-ghost { font-size:.75rem; background: color-mix(in srgb, var(--accent) 7%, var(--surface)); border:1px solid var(--border);
  border-radius:8px; padding:5px 12px; cursor:pointer; color:var(--accent-text); font-weight:600;
  transition: background var(--dur-fast), border-color var(--dur-fast); }
.cmx-ghost:hover { background: color-mix(in srgb, var(--accent) 13%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.cmx-primary { font-size:.75rem; background:var(--grad); border:none; border-radius:8px; padding:5px 16px; cursor:pointer;
  color:#fff; font-weight:700; box-shadow:0 3px 10px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: transform var(--dur-fast), filter var(--dur-fast); }
.cmx-primary:hover { transform:translateY(-1px); filter:brightness(1.06); }
.cmx-ghost:focus-visible, .cmx-primary:focus-visible { outline:2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset:1px; }

/* ── Modales Alias cabinet (.alcx-) et Alias produits (.alpx-) ────────────── */
.alcx-ov { position:fixed; inset:0; background:rgba(15,35,55,.55); z-index:900;
  justify-content:center; align-items:flex-start; padding-top:3vh; animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
.alcx-card { background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:16px; overflow:hidden;
  max-width:640px; width:94%; height:90vh; display:flex; flex-direction:column; box-shadow:var(--shadow-md);
  animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
.alcx-ov.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
.alcx-ov.is-closing .alcx-card { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }
.alcx-head { display:flex; align-items:center; gap:11px; padding:13px 18px; flex:none;
  background: linear-gradient(120deg, color-mix(in srgb, var(--accent) 11%, var(--surface)), color-mix(in srgb, var(--teal) 11%, var(--surface)));
  border-bottom:1px solid color-mix(in srgb, var(--accent) 18%, var(--border)); }
.alcx-title { margin:0; font-size:1rem; font-weight:800; color:var(--text); flex:1; }
.alcx-body { display:flex; flex-direction:column; flex:1; min-height:0; padding:13px 18px 16px; }
.alcx-sub { font-size:.78rem; color:var(--muted); margin:0 0 12px; flex-shrink:0; line-height:1.45; }
.alcx-in { width:100%; box-sizing:border-box; font-size:.82rem; padding:6px 10px; border:1px solid var(--border); border-radius:7px;
  background:var(--surface); color:var(--text); transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.alcx-in:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent); }
.alcx-search { margin-bottom:8px; flex-shrink:0; }
.alcx-list { margin-bottom:14px; flex-shrink:0; max-height:30vh; overflow-y:auto; }
.alcx-group { background:var(--surface-2); border:1px solid var(--line); border-radius:9px; padding:8px 10px; margin-bottom:8px; }
.alcx-gtitle { font-size:.78rem; font-weight:700; color:var(--accent-text); margin-bottom:4px; }
.alcx-gname { font-weight:400; color:var(--muted); }
.alcx-row { display:flex; align-items:center; gap:6px; padding:3px 0 3px 12px; }
.alcx-alias { flex:1; font-size:.74rem; color:var(--text); min-width:0; overflow:hidden; text-overflow:ellipsis; }
.alcx-default { color:var(--muted); font-size:.62rem; opacity:.8; }
.alcx-mod { flex-shrink:0; background: color-mix(in srgb, var(--accent) 10%, var(--surface)); border:none; border-radius:5px;
  padding:2px 7px; font-size:.66rem; color:var(--accent-text); cursor:pointer; transition: background var(--dur-fast); }
.alcx-mod:hover { background: color-mix(in srgb, var(--accent) 18%, var(--surface)); }
.alcx-del { flex-shrink:0; background: color-mix(in srgb, var(--danger) 9%, var(--surface)); border:none; border-radius:5px;
  padding:2px 7px; font-size:.66rem; color:var(--danger); cursor:pointer; transition: background var(--dur-fast); }
.alcx-del:hover { background: color-mix(in srgb, var(--danger) 16%, var(--surface)); }
.alcx-addlink { background:none; border:none; color:var(--accent-text); font-size:.68rem; cursor:pointer; padding:2px 0; text-decoration:underline; }
.alcx-addlink:hover { color:var(--accent); }
.alcx-addlink:focus-visible, .alcx-mod:focus-visible, .alcx-del:focus-visible { outline:2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset:1px; }
.alcx-lbl { font-size:.7rem; color:var(--muted); display:block; margin-bottom:2px; }
.alcx-add { background:var(--grad); color:#fff; border:none; border-radius:8px; padding:7px 16px; font-size:.82rem; cursor:pointer;
  font-weight:700; white-space:nowrap; box-shadow:0 3px 10px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: transform var(--dur-fast), filter var(--dur-fast); }
.alcx-add:hover { transform:translateY(-1px); filter:brightness(1.06); }
.alcx-add:focus-visible { outline:2px solid color-mix(in srgb, var(--accent) 50%, transparent); outline-offset:2px; }
.alcx-cancel { display:none; background:var(--surface-2); color:var(--muted); border:1px solid var(--border); border-radius:8px;
  padding:7px 12px; font-size:.78rem; cursor:pointer; white-space:nowrap;
  transition: color var(--dur-fast), border-color var(--dur-fast); }
.alcx-cancel:hover { color:var(--text); border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.alcx-sugg { flex:1; min-height:0; overflow-y:auto; border:1px solid var(--line); border-radius:9px; background:var(--surface-2); }
.alcx-sugg-hint { text-align:center; color:var(--muted); font-size:.78rem; padding:24px 12px; margin:0; }
.alcx-sugg-ok { text-align:center; color:var(--success); font-size:.78rem; padding:16px 12px; margin:0; }

.alpx-ov { position:fixed; inset:0; background:rgba(15,35,55,.55); z-index:900;
  justify-content:center; align-items:flex-start; padding-top:2vh; animation: ilsFadeIn var(--dur-fast) var(--ease-out) backwards; }
.alpx-card { background:var(--surface); color:var(--text); border:1px solid var(--border); border-radius:16px; overflow:hidden;
  max-width:780px; width:96%; height:94vh; display:flex; flex-direction:column; box-shadow:var(--shadow-md);
  animation: ilsShellIn var(--dur-enter) var(--ease-out) backwards; }
.alpx-ov.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
.alpx-ov.is-closing .alpx-card { animation: ilsShellOut var(--dur-exit) var(--ease-out) both; }
.alpx-head { display:flex; align-items:center; gap:11px; padding:11px 18px; flex:none;
  background: linear-gradient(120deg, color-mix(in srgb, var(--purple) 9%, var(--surface)), color-mix(in srgb, var(--accent) 9%, var(--surface)));
  border-bottom:1px solid color-mix(in srgb, var(--purple) 18%, var(--border)); }
.alpx-title { margin:0; font-size:1rem; font-weight:800; color:var(--text); flex:1; }
.alpx-body { display:flex; flex-direction:column; flex:1; min-height:0; padding:10px 16px 14px; }
.alpx-sub { font-size:.75rem; color:var(--muted); margin:0 0 10px; flex-shrink:0; line-height:1.45; }
.alpx-zone { flex:1; min-height:0; overflow-y:auto; border:1px solid var(--line); border-radius:10px; background:var(--surface-2); padding:14px; }
.alpx-sep { border-top:1px solid var(--line); margin:8px 0; }
.alpx-sec-title { text-align:center; font-size:.82rem; font-weight:700; letter-spacing:2px; color:var(--danger);
  margin-bottom:8px; border-bottom:2px solid var(--danger); padding-bottom:4px; }
.alpx-cat-title { font-size:.65rem; font-weight:700; color:var(--muted); margin:4px 0 2px; }
.alpx-annexe-title { text-align:center; font-size:.78rem; font-weight:700; letter-spacing:1px; color:var(--acte-annexe-fg); margin-bottom:6px; }
.alpx-special-title { text-align:center; font-size:.78rem; font-weight:700; letter-spacing:1px; color:var(--gold); margin-bottom:6px; }
/* Bulle alias d'un produit (#prod-alias-bulle) */
.alpx-bulle { position:fixed; z-index:950; min-width:280px; max-width:380px; max-height:50vh; overflow-y:auto;
  background:var(--surface); color:var(--text); border:2px solid var(--purple); border-radius:12px; padding:14px 16px;
  box-shadow:var(--shadow-md); animation: pfArchMenuIn var(--dur-base) var(--ease-out) backwards; }
.alpx-bulle.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
.alpx-bulle-title { font-weight:700; font-size:.88rem; color:var(--purple); }
.alpx-expr-row { display:flex; align-items:center; justify-content:space-between; padding:4px 6px;
  background: color-mix(in srgb, var(--purple) 7%, var(--surface)); border-radius:6px; margin:3px 0; }
.alpx-expr { font-size:.78rem; color:var(--text); font-weight:500; }
.alpx-expr-del { background: color-mix(in srgb, var(--danger) 9%, var(--surface)); border:1px solid color-mix(in srgb, var(--danger) 40%, var(--surface));
  border-radius:4px; padding:1px 8px; font-size:.65rem; cursor:pointer; color:var(--danger); flex-shrink:0; transition: background var(--dur-fast); }
.alpx-expr-del:hover { background: color-mix(in srgb, var(--danger) 16%, var(--surface)); }
.alpx-bulle-in { flex:1; font-size:.78rem; padding:5px 8px; border:1px solid var(--border); border-radius:6px;
  background:var(--surface); color:var(--text); transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.alpx-bulle-in:focus { outline:none; border-color:var(--purple); box-shadow:0 0 0 3px color-mix(in srgb, var(--purple) 15%, transparent); }
.alpx-bulle-add { background:var(--purple); color:#fff; border:none; border-radius:6px; padding:5px 12px; font-size:.78rem;
  cursor:pointer; font-weight:600; white-space:nowrap; transition: filter var(--dur-fast), transform var(--dur-fast); }
/* Dark : --purple devient CLAIR (#ce93d8) → texte sombre sur le bouton plein. */
html[data-theme="dark"] .alpx-bulle-add { color:#241430; }
.alpx-bulle-add:hover { filter:brightness(1.12); transform:translateY(-1px); }
.alpx-bulle-add:focus-visible { outline:2px solid color-mix(in srgb, var(--purple) 50%, transparent); outline-offset:1px; }

/* ── Zone de scan : état de chargement IA + barres + panneau dossiers ─────── */
.scanld-in { display:flex; align-items:center; justify-content:center; gap:13px; }
.scanld-badge { position:relative; width:38px; height:38px; flex:none; display:flex; align-items:center; justify-content:center;
  font-size:1rem; line-height:1; border-radius:50%; background: color-mix(in srgb, var(--accent) 9%, var(--surface)); }
.scanld-badge::after { content:""; position:absolute; inset:-4px; border-radius:50%;
  border:2.5px solid color-mix(in srgb, var(--accent) 18%, transparent); border-top-color: var(--accent);
  animation: app-loading-spin 1s linear infinite; }
.scanld-txt { display:flex; flex-direction:column; gap:1px; text-align:left; }
.scanld-txt b { font-size:.84rem; color:var(--accent-text); }
.scanld-txt span { font-size:.72rem; color:var(--muted); }
/* Carte du scan par dossiers (la barre = js/chaine-progression.js). */
.scan-progress-card { background:var(--surface); border:1px solid var(--border); border-left:3px solid var(--accent);
  border-radius:10px; padding:12px 16px; margin-top:8px; }
#folder-drop-zone { transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.fpk-btn { background:var(--surface); border:1.5px solid var(--teal); color:var(--teal-text); border-radius:8px; padding:4px 12px;
  font-size:.76rem; font-weight:600; cursor:pointer;
  transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast); }
.fpk-btn:hover { background: color-mix(in srgb, var(--teal) 10%, var(--surface)); transform:translateY(-1px); }
.fpk-primary { background:var(--grad); color:#fff; border:none; border-radius:8px; padding:4px 16px; font-size:.76rem; font-weight:600;
  cursor:pointer; box-shadow:0 3px 10px color-mix(in srgb, var(--accent) 25%, transparent);
  transition: transform var(--dur-fast), filter var(--dur-fast), box-shadow var(--dur-fast); }
.fpk-primary:hover { transform:translateY(-1px); filter:brightness(1.06); }
.fpk-x { background:var(--surface); border:1px solid var(--border); color:var(--muted); border-radius:8px; padding:4px 10px;
  font-size:.76rem; cursor:pointer; transition: color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast); }
.fpk-x:hover { color:var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); background: color-mix(in srgb, var(--danger) 6%, var(--surface)); }
.fpk-btn:focus-visible, .fpk-primary:focus-visible, .fpk-x:focus-visible { outline:2px solid color-mix(in srgb, var(--teal) 50%, transparent); outline-offset:1px; }

/* ── Boutons IA / rescan du bandeau de fiche (fond dégradé → blancs translucides) ── */
.fhx-btn { display:flex; align-items:center; gap:5px; background:rgba(255,255,255,.15); border:1px solid rgba(255,255,255,.5);
  border-radius:8px; padding:4px 12px; font-size:.9rem; font-weight:700; color:#fff; cursor:pointer; white-space:nowrap; line-height:1;
  transition: background var(--dur-fast), transform var(--dur-fast); }
.fhx-btn:hover { background:rgba(255,255,255,.3); }
.fhx-btn:active { transform: translateY(1px); }
.fhx-btn:focus-visible { outline:2px solid rgba(255,255,255,.75); outline-offset:2px; }
.fhx-btn--rescan { padding:4px 10px; font-size:.95rem; font-weight:600; }

/* ── Surbrillances d'état des champs (ex-element.style hex, piège n°1) ────────
   Classe doublée = spécificité (0,2,0) : passe devant .in2:focus / .flag:hover
   à égalité + ordre de fichier. Dark automatique (tokens). */
.hl-danger.hl-danger { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); border:2px solid var(--danger);
  box-shadow: 0 0 8px color-mix(in srgb, var(--danger) 30%, transparent); }
.hl-warn.hl-warn { background: color-mix(in srgb, var(--warn) 14%, var(--surface)); border:2px solid var(--warn);
  box-shadow: 0 0 8px color-mix(in srgb, var(--warn) 30%, transparent); }
.hl-scan.hl-scan { background: color-mix(in srgb, var(--purple) 12%, var(--surface)); border:2px solid var(--purple);
  box-shadow: 0 0 8px color-mix(in srgb, var(--purple) 30%, transparent); }
.hl-warn.hl-warn > input { font-weight:700; color:var(--warn); }
.hl-danger.hl-danger > input { font-weight:700; color:var(--danger); }

/* ── Badges du formulaire (code Cogilog, position scan) ── */
.fx-badge--code { background: color-mix(in srgb, var(--accent) 11%, var(--surface)); color:var(--accent-text);
  border-radius:6px; padding:3px 8px; font-size:.68rem; font-weight:700; font-family:'DM Mono',monospace; white-space:nowrap; flex-shrink:0;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent); }
.fx-badge--scan { font-size:.6rem; background: color-mix(in srgb, var(--purple) 11%, var(--surface)); color:var(--purple);
  padding:1px 6px; border-radius:8px; font-weight:700;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--purple) 22%, transparent); }

/* ── Liste : Tout sélectionner / Supprimer / annuler export ── */
.pf-selbtn { font-size:.75rem; padding:5px 12px; border:1px solid var(--border); border-radius:8px; background:var(--surface);
  cursor:pointer; font-weight:600; color:var(--accent-text); box-shadow:var(--shadow-sm);
  transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast); }
.pf-selbtn:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.pf-selbtn:focus-visible { outline:2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset:1px; }
.pf-selbtn.is-on { background: color-mix(in srgb, var(--warn) 16%, var(--surface)); border-color: color-mix(in srgb, var(--warn) 55%, var(--surface));
  color: color-mix(in srgb, var(--warn) 60%, var(--text)); }
.pf-delbtn { font-size:.72rem; padding:4px 10px; border:1px solid var(--danger); border-radius:8px;
  background: color-mix(in srgb, var(--danger) 7%, var(--surface)); cursor:pointer; color:var(--danger); font-weight:600;
  transition: background var(--dur-fast); }
.pf-delbtn:hover { background: color-mix(in srgb, var(--danger) 14%, var(--surface)); }
.pf-delbtn:focus-visible { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }
.lst-undo { background: color-mix(in srgb, var(--danger) 9%, var(--surface)); color:var(--danger);
  border:1px solid color-mix(in srgb, var(--danger) 55%, var(--surface)); border-radius:6px; padding:2px 6px; font-size:.8rem;
  cursor:pointer; margin-left:-4px; transition: background var(--dur-fast); }
.lst-undo:hover { background: color-mix(in srgb, var(--danger) 16%, var(--surface)); }
.lst-undo:focus-visible { outline:2px solid color-mix(in srgb, var(--danger) 45%, transparent); outline-offset:1px; }

/* ── Menus maison sur <select> natif (tri, fournisseur, lettre du jour) ──────
   Enhancer ilsSelectMenu (js/ui-helpers.js) : le <select> reste dans le DOM
   (source de vérité, les handlers existants continuent de lire .value), masqué ;
   le déclencheur réutilise .pf-sort et le menu la grammaire .pf-arch-menu. */
.ils-sel { position:relative; display:inline-flex; }
.ils-sel-native { position:absolute !important; width:1px !important; height:1px !important; opacity:0 !important;
  pointer-events:none !important; margin:0 !important; padding:0 !important; border:0 !important; clip-path: inset(50%); }
.ils-sel-trigger { display:inline-flex; align-items:center; gap:6px; }
.ils-sel-label { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:58px; text-align:left; }
/* Objet illustré d'une option (data-objet, ilsEnhanceSelect) : un petit écart avec le texte. */
.ils-sel-label .ilx, .ils-sel-opt .ilx { margin-right: 6px; }
.ils-sel-chev { font-size:.6rem; opacity:.65; transition: transform var(--dur-fast); }
.ils-sel.open .ils-sel-chev { transform: rotate(180deg); }
.ils-sel-menu { max-height:min(340px, 60vh); overflow-y:auto; }
.ils-sel-menu.ils-sel-menu--right { left:auto; right:0; }
.ils-sel-menu .ils-sel-opt { flex-direction:row; align-items:center; gap:8px; }
.ils-sel-menu .ils-sel-opt .pf-arch-opt-t { flex:1; }
/* Surbrillance CLAVIER (↓/↑ depuis le déclencheur, js ilsEnhanceSelect) : anneau
   accent (même formule que les :focus-visible de l'app), compose avec .is-active. */
.ils-sel-menu .ils-sel-opt.kb-focus { outline:2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset:-2px; }
/* Sortie animée des menus .pf-arch (entrée pfArchMenuIn = règle dédiée requise). */
.pf-arch-menu.is-closing { animation: ilsFadeOut var(--dur-exit) var(--ease-out) both; }
/* Teinte fournisseur (classes fourn-cN posées par prescription-list, var --f). */
.ils-sel-trigger[class*="fourn-c"] { border-color: color-mix(in srgb, var(--f, var(--accent)) 55%, transparent);
  color: color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); }
html[data-theme="dark"] .ils-sel-trigger[class*="fourn-c"] { color: color-mix(in srgb, var(--f, var(--accent)) 30%, #fff); }
.ils-sel-menu .ils-sel-opt[class*="fourn-c"] .pf-arch-opt-t { color: color-mix(in srgb, var(--f, var(--accent)) 78%, var(--text)); }
html[data-theme="dark"] .ils-sel-menu .ils-sel-opt[class*="fourn-c"] .pf-arch-opt-t { color: color-mix(in srgb, var(--f, var(--accent)) 30%, #fff); }
/* Fournisseur inconnu/archivé (.fourn-other, sans var --f) : bleu neutre —
   mêmes teintes que les anciennes règles #filter-fournisseur.fourn-other. */
.ils-sel-trigger.fourn-other { color:#1a5c8a; border-color:rgba(26,92,138,.55); }
html[data-theme="dark"] .ils-sel-trigger.fourn-other { color:#7fc4e8; border-color:#2a5570; }
/* Variante compacte du header (lettre du jour) : déclencheur nu, mono. */
.ils-sel--mono .ils-sel-trigger { background:transparent; border:none; box-shadow:none; padding:0; cursor:pointer;
  color:var(--text); font-family:'DM Mono',monospace; font-size:.72rem; font-weight:700; }
.ils-sel--mono .ils-sel-label { min-width:0; }
.ils-sel--mono .ils-sel-menu { min-width:150px; }
.ils-sel--mono .ils-sel-menu .pf-arch-opt-t { font-family:'DM Mono',monospace; font-size:.74rem; }

/* ── Scrollbars fines thémées — règle GLOBALE (recette gc-ui-styles/dentist-view).
   WebKit d'abord ; scrollbar-width réservé aux navigateurs sans ::-webkit-scrollbar
   (Firefox) : dans Chrome ≥121, poser scrollbar-width désactiverait les styles
   ::-webkit-scrollbar existants (gc-cabinet-list, portail dentiste). */
::-webkit-scrollbar { width:10px; height:10px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 38%, transparent); border-radius:8px;
  border:3px solid transparent; background-clip:padding-box; }
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 58%, transparent);
  border:3px solid transparent; background-clip:padding-box; }
::-webkit-scrollbar-corner { background:transparent; }
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 45%, transparent) transparent; }
}

/* ══ LUMIÈRE — liserés et halos lumineux du design ═══════════════════════════
   Ajoutée le 13/08/2026 : chaque élément s'allume dans SA propre teinte (les
   tuiles portent déjà --c). Fait partie du design, sans interrupteur.
   Uniquement des ombres/lueurs : zéro décalage de mise en page.
   NB : le halo coloré des tuiles existe DÉJÀ (.tool) — on n'en rajoute pas une
   couche, on ajoute le LISERÉ lumineux et la lumière interne qui manquaient. */

/* 1. Tuiles de modules : liseré lumineux dans leur couleur, avivé au survol. */
.tool { position: relative; }
.tool::after {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1.2px color-mix(in srgb, var(--c) 62%, transparent),
              0 0 20px -4px color-mix(in srgb, var(--c) 52%, transparent);
  opacity: 1; transition: box-shadow var(--dur-base) var(--ease-out);
}
.tool:hover::after {
  box-shadow: inset 0 0 0 1.2px color-mix(in srgb, var(--c) 85%, transparent),
              0 0 28px -2px color-mix(in srgb, var(--c) 65%, transparent);
}
/* Toute pastille posée sur une tuile (notification Digilab…) doit rester AU-DESSUS
   du liseré : le pseudo est dessiné en dernier, il la masquerait sans ce z-index. */
.tool > [class*="badge"], .tool > .dlb-notif-badge, .tool > .scx-tooldot, .tool > .adm-tooldot { z-index: 1; }
/* 2. Pastille d'icône : éclairée de l'intérieur plutôt que posée à plat. */
.tool .ti {
  box-shadow: inset 0 1px 0 rgba(255,255,255,.30),
              0 0 15px -3px color-mix(in srgb, var(--c) 62%, transparent);
}
/* 3. Codes labo : halo typographique très léger (le détail « néon » retenu). */
.fx-badge--code,
.tbl .row .cl { text-shadow: 0 0 10px color-mix(in srgb, var(--accent) 45%, transparent); }
/* 4. Ligne de liste survolée : liseré lumineux au bord gauche. */
.tbl .row:hover {
  box-shadow: inset 2.5px 0 0 color-mix(in srgb, var(--teal) 85%, transparent),
              0 0 16px -6px color-mix(in srgb, var(--teal) 55%, transparent);
}
/* 5. Champs : anneau de focus lumineux au lieu d'un contour plat. */
input:focus-visible, select:focus-visible, textarea:focus-visible {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent),
              0 0 15px -3px color-mix(in srgb, var(--teal) 55%, transparent);
}
/* 6. Bouton Enregistrer : s'allume au survol (il ne réagissait pas du tout). */
.f2-save { transition: box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); }
.f2-save:hover {
  transform: translateY(-1px);
  box-shadow: 0 0 20px -3px color-mix(in srgb, var(--teal) 60%, transparent);
}
/* En mode JOUR, la lumière se voit moins et salit vite : on la tempère. */
html:not([data-theme="dark"]) .tool::after { opacity: .55; }
html:not([data-theme="dark"]) .fx-badge--code,
html:not([data-theme="dark"]) .tbl .row .cl { text-shadow: none; }

/* ══ REDUCED MOTION — filet GLOBAL (doit rester en FIN de fichier) ════════════
   Coupe toute animation/transition décorative d'un coup pour qui préfère un
   affichage sans mouvement, PUIS ré-autorise les indicateurs de chargement
   essentiels (un spinner d'attente doit continuer de tourner, ralenti).
   Les blocs prefers-reduced-motion ciblés plus haut restent en place. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  /* Spinners essentiels : on redonne leur rotation, ralentie (précédent : le bloc
     reduced-motion historique de #app-loading tournait déjà à 2.4s). */
  #app-loading .app-loading__spinner { animation: app-loading-spin 2.4s linear infinite !important; }
  /* Le minuteur de secours de l'écran de chargement n'est PAS un mouvement : sans
     cette ligne, « animation-delay: 0s » ci-dessus le déclenchait tout de suite et
     l'écran disparaissait avant l'app → page blanche au démarrage (Z7a-12). */
  #app-loading { animation: app-loading-failsafe 0s linear 20s forwards !important; }
  .ils-lazy-veil::after { animation: app-loading-spin 2.4s linear infinite !important; }
  .scanld-badge::after { animation: app-loading-spin 2.4s linear infinite !important; }  /* analyse IA en cours */
  .edx-spin { animation: edxSpin 2.4s linear infinite !important; }
  .mv-spin { animation: mvspin 2.4s linear infinite !important; }   /* visionneuse 3D (keyframe injectée par medit-viewer.js) */
}

/* ── Acte RETIRÉ du catalogue par le labo (01/09/2026) ──────────────────────
   Sa case du formulaire est masquée tant qu'elle n'est pas cochée : le labo ne
   vend plus cet article (maquette du catalogue, onglet Grilles). L'attribut est
   posé/retiré par js/articles-labo.js — jamais sur une case COCHÉE, pour qu'une
   fiche ancienne qui porte l'acte reste lisible. Masquage pur : aucune couleur,
   donc rien à prévoir en mode nuit. Restaurer l'article rend la case. */
label[data-acte-retire] { display: none !important; }

/* ── Flou des VOILES sur téléphone (18/09/2026) ─────────────────────────────
   Chaque voile de modale porte `backdrop-filter: var(--ov-blur, blur(N))` : sur
   ordinateur le flou reste ; sur téléphone le GPU refloutait toute la fenêtre à
   chaque image pendant l'entrée/sortie d'une modale. Le voile teinté reste, seul le
   flou (2-6 px, invisible sur 6 pouces) est retiré. Le grade couleur (body::after,
   saturate/contrast) n'est PAS concerné — décision d'Illan, il le garde. */
html.mobile-zoom-default { --ov-blur: none; }

/* Pastille de non-lus 🏮 sur le bouton outils « Chine » (posée au boot par
   js/supplier-chat.js:updateToolDot). Vit ICI et non dans le CSS lazy du chat :
   sinon le compteur s'affichait en texte brut tant qu'aucun chat n'était ouvert. */
.scx-tooldot {
  position: absolute; top: -6px; right: -6px; min-width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: .6rem; font-weight: 700; color: #fff;
  background: var(--danger); border-radius: 8px; padding: 0 4px;
  box-shadow: 0 2px 6px color-mix(in srgb, var(--danger) 42%, transparent);
  pointer-events: none;
}

/* ══ ÉCRAN ❓ HELP — le guide de l'interface labo (js/help/guide.js) ═══════════
   La COQUILLE est celle des Paramètres (.pmx-… / .pmh-…, plus haut) : rien à
   redéclarer, téléphone compris. Ici : (1) la mise en page du guide (.hlp-*),
   portée du guide du portail fournisseur (supplier/styles.css) sur les tokens
   du labo, et (2) LE PEU qu'il faut pour poser un VRAI écran du labo dans un
   cadre — les maquettes reprennent le markup et les classes des écrans réels,
   leur CSS est donc déjà écrit plus haut et suit l'app. Reste à APLATIR. */

/* L'or du bouton ❓ Help (index.html, --c) : l'écran, ses numéros d'étape et
   ses repères ① le portent — la même chose a la même couleur qu'au portail.
   Ce n'est pas une couleur de marque : le branding du labo vit dans --accent. */
#help-screen { --hlp-or: #d8942a; }

#hlp-sidebar .pmx-side-grp--start  > .pmx-side-group { color: var(--success);        opacity: 1; }
#hlp-sidebar .pmx-side-grp--case   > .pmx-side-group { color: var(--pmg-labo-text);  opacity: 1; }
#hlp-sidebar .pmx-side-grp--around > .pmx-side-group { color: var(--gold);           opacity: 1; }
#hlp-sidebar .pmx-side-grp--you    > .pmx-side-group { color: var(--pmg-avance-text); opacity: 1; }
#hlp-sidebar .pmx-side-grp--help   > .pmx-side-group { color: var(--muted);          opacity: 1; }
#hlp-sidebar .pmx-item .hlp-rail-new { margin-left: auto; font-size: 9px; font-weight: 800; letter-spacing: .04em;
  padding: 1px 5px; border-radius: 6px; color: #fff; background: var(--accent); }

.pmx-main > .hlp-panel { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.hlp-pane { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 22px 22px; max-width: none; }
.hlp-p, .hlp-ul, .hlp-tip, .hlp-warn, .hlp-leg, .hlp-err, .hlp-go-wrap { max-width: 86ch; }
.hlp-p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.65; color: var(--text); }
.hlp-p b, .hlp-ul b, .hlp-tip b, .hlp-warn b, .hlp-leg b { font-weight: 700; }
.hlp-lib { font-weight: 700; color: var(--text); white-space: nowrap; }
.hlp-ul { margin: 4px 0 10px; padding-left: 18px; }
.hlp-ul li { font-size: 13.5px; line-height: 1.6; color: var(--text); margin-bottom: 5px; }

/* Une section = un numéro dans la marge + son contenu : la chronologie porte le guide. */
.hlp-step { display: flex; gap: 14px; padding: 16px 0; border-top: 1px solid var(--line); scroll-margin-top: 8px; }
.hlp-step:first-of-type { border-top: 0; padding-top: 6px; }
.hlp-step-n {
  flex: none; display: grid; place-items: center; width: 26px; height: 26px; margin-top: 1px;
  border-radius: 50%; font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums;
  color: #fff; background: linear-gradient(140deg, color-mix(in srgb, var(--hlp-or, var(--accent)) 82%, #fff), var(--hlp-or, var(--accent)));
  box-shadow: 0 3px 9px -4px color-mix(in srgb, var(--hlp-or, var(--accent)) 80%, transparent);
}
.hlp-step--flat { gap: 0; }
.hlp-step-b { flex: 1; min-width: 0; }
.hlp-step-t { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 2px 0 8px; font-size: 15px; font-weight: 700; letter-spacing: -.01em; color: var(--text); }
.hlp-step.is-cible .hlp-step-t { color: var(--accent-text); }
.hlp-new { font-size: 9.5px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 2px 6px; border-radius: 6px;
  color: #fff; background: var(--accent); }

.hlp-tip, .hlp-warn, .hlp-err {
  margin: 10px 0 2px; padding: 9px 12px; border-radius: 10px;
  font-size: 12.8px; line-height: 1.55; border: 1px solid transparent; color: var(--text);
}
.hlp-tip  { background: color-mix(in srgb, var(--teal) 10%, transparent); border-color: color-mix(in srgb, var(--teal) 34%, transparent); }
.hlp-warn { background: color-mix(in srgb, var(--warn) 10%, transparent); border-color: color-mix(in srgb, var(--warn) 34%, transparent); }
.hlp-err  { background: var(--surface-2); border-color: var(--line); }
.hlp-err b { color: var(--text); }

a.hlp-lien { color: var(--accent-text); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
a.hlp-lien:hover { color: var(--accent); }
.hlp-pane [data-hlp-checklist] .honb-check { margin: 6px 0 4px; max-width: 520px; }

/* Bouton « M'y emmener » : le deep-link de la section (js/help-actions.js). */
.hlp-go-wrap { margin: 10px 0 2px; }
.hlp-go {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px; border: none; border-radius: 10px;
  background: var(--grad); color: #fff; font: inherit; font-size: .78rem; font-weight: 700; cursor: pointer;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 38%, transparent);
  transition: transform var(--dur-fast), filter var(--dur-fast);
}
.hlp-go:hover { transform: translateY(-1px); filter: brightness(1.06); }

/* Repères ① sur une maquette + leur légende. Le repère vit DANS l'élément désigné. */
.hlp-pin {
  display: inline-grid; place-items: center; width: 15px; height: 15px; margin-left: 5px;
  border-radius: 50%; font-size: 9.5px; font-weight: 800; font-style: normal; line-height: 1;
  color: #fff; background: var(--hlp-or, var(--gold)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--hlp-or, var(--gold)) 24%, transparent);
  vertical-align: middle; flex: none; align-self: center;
}
.hlp-mock-doc *:has(> .hlp-pin) { position: relative; overflow: visible; }
.hlp-mock-doc .hlp-pin {
  position: absolute; top: -7px; right: -7px; margin: 0; z-index: 3;
  box-shadow: 0 0 0 2px var(--surface-2), 0 1px 4px rgba(0, 0, 0, .25);
}
.hlp-anchor { position: relative; display: inline-flex; }
.hlp-leg { margin: 10px 0 0; padding: 0; list-style: none; }
.hlp-leg li { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 5px; font-size: 12.8px; line-height: 1.55; color: var(--text); }
.hlp-leg .hlp-pin { margin-left: 0; margin-top: 2px; }

/* Le cadre d'une maquette : « ceci est une image ». */
.hlp-mock { margin: 12px 0 4px; }
.hlp-mock-cap {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-bottom: 6px; font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.hlp-mock-note { font-weight: 500; letter-spacing: 0; text-transform: none; opacity: .75; font-size: 11px; }
.hlp-mock-in {
  padding: 14px; border-radius: 14px; overflow-x: auto; display: flex;
  border: 1px solid var(--border);
  background: radial-gradient(120% 160% at 0% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 60%), var(--surface-2);
  box-shadow: var(--shadow-sm);
}
.hlp-mock-doc { pointer-events: none; user-select: none; flex: 1 0 auto; font-size: 0.86rem; }
.hlp-mock--wide   .hlp-mock-doc { min-width: 680px; }
.hlp-mock--xwide  .hlp-mock-doc { min-width: 880px; }
.hlp-mock--xxwide .hlp-mock-doc { min-width: 1040px; }
.hlp-mock--narrow .hlp-mock-doc { flex: 0 1 auto; width: 460px; }
.hlp-mock--geste  .hlp-mock-doc { flex: 0 1 auto; width: 560px; }
/* Micro-maquette de GESTE : le menu s'ouvre en boucle (respecte reduce-motion). */
.hlp-geste-anim { animation: hlpGeste 3.2s var(--ease-out) infinite; transform-origin: top left; }
@keyframes hlpGeste { 0%, 18% { opacity: 0; transform: translateY(-4px) scale(.98); } 30%, 84% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .hlp-geste-anim { animation: none; } }

/* Scène de concept (SVG sur tokens) : elle n'illustre jamais un écran. */
.hlp-scene { margin: 4px 0 14px; padding: 16px 18px; border-radius: 14px; border: 1px solid var(--border);
  background: radial-gradient(120% 160% at 100% 0%, color-mix(in srgb, var(--teal) 10%, transparent), transparent 60%), var(--surface-2); }
.hlp-scene svg { display: block; width: 100%; height: auto; max-width: 860px; margin: 0 auto; }
.hlp-scene .sc-t { font: 700 12px 'DM Sans', system-ui, sans-serif; fill: var(--text); }
.hlp-scene .sc-s { font: 500 10.5px 'DM Sans', system-ui, sans-serif; fill: var(--muted); }
.hlp-scene .sc-box { fill: var(--surface); stroke: var(--border); }
.hlp-scene .sc-acc { fill: var(--accent); }
.hlp-scene .sc-teal { fill: var(--teal); }
.hlp-scene .sc-arr { stroke: var(--muted); fill: none; stroke-width: 1.6; }
.hlp-scene .sc-pulse { animation: hlpPulse 2.6s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
@keyframes hlpPulse { 0%, 100% { opacity: .55; transform: scale(1); } 50% { opacity: 1; transform: scale(1.06); } }
@media (prefers-reduced-motion: reduce) { .hlp-scene .sc-pulse { animation: none; } }

/* Le schéma du parcours (carte du processus, pas une capture). */
.hm-flow { display: flex; align-items: stretch; gap: 6px; }
.hm-flow-s { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 14px 8px 10px; border-radius: 12px; text-align: center; border: 1px solid var(--border); background: var(--surface); box-shadow: var(--shadow-sm); }
.hm-flow-e { font-size: 19px; line-height: 1; }
.hm-flow-n { position: absolute; top: -8px; left: 50%; transform: translateX(-50%); display: grid; place-items: center;
  width: 18px; height: 18px; border-radius: 50%; font-size: 10px; font-weight: 800; color: #fff; background: var(--gold); box-shadow: 0 0 0 3px var(--surface-2); }
.hm-flow-t { font-size: 11px; font-weight: 600; line-height: 1.35; color: var(--text); }
.hm-flow-arr { align-self: center; color: var(--muted); font-size: 14px; }

/* ── APLATIR un écran réel posé dans un cadre (positionnement seulement). ── */
.hlp-mock-doc .pmx-overlay, .hlp-mock-doc .pmx-shell, .hlp-mock-doc .rowmenu, .hlp-mock-doc .sb-menu,
.hlp-mock-doc #modal-tarifs, .hlp-mock-doc #modal-decalage, .hlp-mock-doc #modal-implants, .hlp-mock-doc #modal-digilab, .hlp-mock-doc #modal-hix, .hlp-mock-doc .gc-modal-shell, .hlp-mock-doc .vf-overlay, .hlp-mock-doc .vf-modal,
.hlp-mock-doc .dgl-overlay, .hlp-mock-doc .imx-overlay, .hlp-mock-doc .scx-overlay, .hlp-mock-doc .dsx-overlay,
.hlp-mock-doc [class$="-overlay"], .hlp-mock-doc [class$="-modal"] {
  position: relative !important; inset: auto !important; transform: none !important; animation: none !important;
  width: auto !important; max-width: none !important; height: auto !important; max-height: none !important;
  margin: 0 !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
  background: var(--surface); display: block; padding: 0;
}
.hlp-mock-doc .pmx-overlay { background: transparent; }
/* Un tableau `table-layout:fixed` dont les colonnes sont en % a besoin d'une largeur
   de RÉFÉRENCE. Dans une maquette du guide, la modale passe en width:auto (règle
   ci-dessus) : la référence disparaît, les % deviennent circulaires et le tableau
   gonfle — mesuré le 18/09/2026 à 2,9e8 px, donc un zoom d'ajustement à 0,0017 et
   une maquette invisible. On lui rend la largeur de la maquette qui l'accueille. */
.hlp-mock-doc table.imx-dg { width: 680px !important; }
.hlp-mock--xwide  .hlp-mock-doc table.imx-dg { width: 880px !important; }
.hlp-mock--xxwide .hlp-mock-doc table.imx-dg { width: 1040px !important; }
/* Même piège, 30/09/2026 (33 554 432 px) : Délais, bon de livraison, recherche
   toutes marques. Ces tableaux ne sont pas pleine maquette : leur CADRE ne compte
   plus dans la largeur « idéale » et prend celle de son parent. Un nouveau tableau
   `fixed` + % qui rend une maquette invisible : ajouter son cadre ici. */
.hlp-mock-doc :is(.pd-delais-wrap, .blm-tblwrap, .imx-tt-liste) { contain: inline-size; }
/* Le bloc de scope n'existe que pour porter l'id sous lequel la feuille de
   l'écran est écrite : display:contents le retire de la mise en page, donc
   l'écran copié garde EXACTEMENT sa largeur et son cadrage d'origine. */
.hlp-mock-doc .hlp-scope { display: contents; }
.hlp-mock-doc header { position: static !important; top: auto; box-shadow: none; }
.hlp-mock-doc .lgc-scene { position: relative !important; inset: auto !important; width: auto; height: auto; min-height: 0; padding: 22px; border-radius: 14px; display: flex; justify-content: center; }
.hlp-mock-doc .lgc-scene canvas, .hlp-mock-doc .lgc-fx, .hlp-mock-doc .lgc-theme-toggle { display: none; }
.hlp-mock-doc .lgc-card { position: relative; margin: 0; animation: none; }
.hlp-mock-doc .pmx-shell { display: flex; height: auto !important; }
.hlp-mock-doc .pmx-body { min-height: 0; }
.hlp-mock-doc .pmx-side { animation: none; }
.hlp-mock-doc .pmx-item { animation: none !important; opacity: 1 !important; }
.hlp-mock-doc .rowmenu, .hlp-mock-doc .sb-menu { display: block; opacity: 1; visibility: visible; }
.hlp-mock-doc #pdfjs-container { height: auto !important; max-height: none !important; overflow: visible !important; background: transparent !important; }
.hlp-mock-doc .prescriptions-list { max-height: none; overflow: visible; }
.hlp-mock-doc .prescriptions-list .row { animation: none; }
/* Page de document grisée : jamais un vrai PDF. */
.hlp-mock-doc .hlp-pdf { display: flex; flex-direction: column; gap: 6px; height: 190px; padding: 14px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface); }
.hlp-mock-doc .hlp-pdf i { display: block; height: 6px; border-radius: 3px; background: var(--line); }
.hlp-mock-doc .hlp-pdf i.s { width: 55%; }

/* ── Recherche : les résultats prennent la place du panneau ── */
.hlp-res-head { padding: 22px 22px 6px; }
.hlp-res-q { font-size: 1.05rem; font-weight: 800; letter-spacing: -.01em; color: var(--text); }
.hlp-res-q b { color: var(--accent-text); }
.hlp-res-sub { margin-top: 3px; font-size: .78rem; color: var(--muted); }
.hlp-res { list-style: none; margin: 0; padding: 8px 22px 22px; display: grid; gap: 8px; max-width: 760px; }
.hlp-res li button {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left; padding: 11px 14px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface); color: var(--text);
  font: inherit; cursor: pointer; transition: border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast);
}
.hlp-res li button:hover, .hlp-res li button:focus-visible { border-color: var(--accent); transform: translateY(-1px); box-shadow: var(--shadow-sm); outline: none; }
.hlp-res li.is-first button { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); background: color-mix(in srgb, var(--accent) 5%, var(--surface)); }
.hlp-res-ico { font-size: 1.15rem; flex: none; }
.hlp-res-t { font-size: .88rem; font-weight: 700; }
.hlp-res-c { font-size: .74rem; color: var(--muted); margin-top: 1px; }
.hlp-res-c b { color: var(--text); font-weight: 600; }
.hlp-res-key { margin-left: auto; flex: none; font-size: .66rem; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; padding: 2px 6px; }
.hlp-vide { padding: 14px 22px; max-width: 70ch; }
.hlp-vide-t { font-size: .95rem; font-weight: 700; color: var(--text); }
.hlp-vide-s { margin-top: 4px; font-size: .82rem; color: var(--muted); line-height: 1.55; }

/* ── Pied du panneau : le chemin chronologique ── */
.hlp-nav { display: flex; justify-content: space-between; gap: 12px; margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--line); }
.hlp-navbtn {
  display: flex; flex-direction: column; gap: 2px; max-width: 46%; padding: 9px 13px;
  border: 1px solid var(--line); border-radius: 11px; background: var(--surface); color: var(--text);
  cursor: pointer; font-family: inherit; text-align: left;
  transition: border-color var(--dur-fast), background var(--dur-fast), transform var(--dur-fast);
}
.hlp-navbtn:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--surface)); transform: translateY(-1px); }
.hlp-navbtn span { font-size: 11px; color: var(--muted); }
.hlp-navbtn b { font-size: 13px; font-weight: 700; }
.hlp-navbtn--next { margin-left: auto; text-align: right; align-items: flex-end; }

/* Chapitre « Nouveautés » : une ligne par section neuve. */
.hlp-nouv { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; max-width: 760px; }
.hlp-nouv li button { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--text); font: inherit; cursor: pointer; }
.hlp-nouv li button:hover { border-color: var(--accent); }
.hlp-nouv-d { margin-left: auto; font-size: .7rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Pastille « nouveautés » sur le bouton ❓ de l'en-tête (sans chiffre). */

/* TÉLÉPHONE */
html.mobile-zoom-default .hlp-pane { padding: 4px 14px 14px; }
html.mobile-zoom-default .hlp-step { gap: 10px; }
html.mobile-zoom-default .hlp-nav { flex-direction: column; }
html.mobile-zoom-default .hlp-navbtn { max-width: none; }
html.mobile-zoom-default .hlp-navbtn--next { text-align: left; align-items: flex-start; }
html.mobile-zoom-default .hlp-res, html.mobile-zoom-default .hlp-res-head, html.mobile-zoom-default .hlp-vide { padding-inline: 14px; }

/* ══ COULEURS DE LA PALETTE (26/09/2026) ═══════════════════════════════════
   Une couleur hors des 5 « maison » (orange, rouge, vert…) choisie pour un
   univers, une famille ou un article : l'élément porte « tnt tnt-<id> » (voir
   catTeinteCls, js/catalogue.js), qui pose --tnt (trait) et --tnt-t (écriture),
   clair ET nuit. Ces règles ne lisent QUE ces deux variables : ajouter une
   couleur à la palette ne demande aucune ligne ici. « html:root » : même poids
   que les règles « html[data-theme=dark] » des teintes maison, qu'elles doivent
   battre sur une pastille d'acte colorée par le labo. */
/* ── Gérer les familles, refonte (26/09/2026, Illan : « de façon plus moderne ») ──
   Chaque univers est une carte à sa couleur (--tnt, posé par la classe tnt-<id> :
   la même variable pour les teintes maison et les autres). Une pastille ronde
   devant chaque nom ouvre la palette ; « monter / descendre » = deux chevrons
   empilés ; les actions se montrent au survol, toujours au doigt. */
#cfm-overlay .cfm-head{gap:12px;justify-content:flex-start;padding:14px 16px}
.cfm-head-ico{flex:none;display:grid;place-items:center;width:34px;height:34px;border-radius:10px;background:var(--surface-2)}
.cfm-head-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.cfm-head-t b{font-size:.98rem;font-weight:800;color:var(--text)}
.cfm-head-t small{font-size:.72rem;font-weight:500;color:var(--muted)}
.cfm-close{flex:none;display:grid;place-items:center;width:30px;height:30px;border-radius:50%;line-height:1;transition:background-color var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out)}
.cfm-close:hover{background:var(--surface-2);color:var(--text)}
#cfm-body{padding:12px 14px 14px;background:color-mix(in srgb,var(--surface-2) 45%,var(--surface))}
.cfm-u{margin:0 0 12px;border:1px solid color-mix(in srgb,var(--tnt) 22%,var(--line));border-radius:12px;background:var(--surface);overflow:hidden;box-shadow:0 1px 2px color-mix(in srgb,var(--text) 6%,transparent)}
.cfm-u-hd{display:flex;align-items:center;gap:9px;padding:9px 10px 9px 12px;background:color-mix(in srgb,var(--tnt) 10%,var(--surface));border-bottom:1px solid color-mix(in srgb,var(--tnt) 16%,var(--line))}
.cfm-u-nom{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.76rem;font-weight:800;letter-spacing:.6px;text-transform:uppercase;color:var(--tnt-t)}
.cfm-u-n{flex:1;font-size:.68rem;font-weight:600;color:var(--muted);white-space:nowrap}
.cfm-u-fams{padding:6px 6px 4px}
.cfm-f{display:flex;align-items:center;gap:8px;min-height:34px;padding:2px 6px 2px 4px;border-radius:9px;transition:background-color var(--dur-fast) var(--ease-out)}
.cfm-f:hover, .cfm-f:focus-within, .cfm-f.is-open{background:var(--surface-2)}
.cfm-f-nom{flex:1;min-width:0;display:flex;align-items:center;gap:7px;padding:4px 0;border:0;background:none;font:inherit;font-size:.84rem;font-weight:600;color:var(--text);text-align:left;cursor:pointer}
.cfm-n{flex:none;min-width:20px;padding:1px 7px;border-radius:999px;background:color-mix(in srgb,var(--tnt) 12%,var(--surface));color:var(--tnt-t);font-size:.66rem;font-weight:700;text-align:center}
.cfm-car{flex:none;display:grid;place-items:center;width:22px;height:22px;padding:0;border:0;border-radius:6px;background:none;color:var(--muted);cursor:pointer}
.cfm-car::before{content:"";width:6px;height:6px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform var(--dur-fast) var(--ease-out)}
.cfm-car[aria-expanded="true"]::before{transform:rotate(45deg) translate(-1px,-1px)}
.cfm-car:hover{background:color-mix(in srgb,var(--text) 7%,transparent);color:var(--text)}
.cfm-sw{flex:none;width:16px;height:16px;padding:0;border-radius:50%;border:2px solid var(--surface);background:var(--tnt);box-shadow:0 0 0 1px color-mix(in srgb,var(--tnt) 50%,var(--line));cursor:pointer;transition:transform var(--dur-fast) var(--ease-spring)}
.cfm-sw:not(.is-propre){background:color-mix(in srgb,var(--tnt) 55%,var(--surface))}
.cfm-sw:hover{transform:scale(1.18)}
.cfm-sw:focus-visible, .cfm-car:focus-visible, .cfm-ic:focus-visible, .cfm-pas-b:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
.cfm-act{flex:none;display:flex;align-items:center;gap:4px;opacity:0;transition:opacity var(--dur-fast) var(--ease-out)}
.cfm-u-hd:hover .cfm-act, .cfm-u-hd:focus-within .cfm-act, .cfm-f:hover .cfm-act, .cfm-f:focus-within .cfm-act, .cfm-a:hover .cfm-act, .cfm-a:focus-within .cfm-act{opacity:1}
html.mobile-zoom-default .cfm-act{opacity:1}
.cfm-ic{display:grid;place-items:center;width:28px;height:28px;padding:0;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out)}
.cfm-ic:hover{background:var(--surface);border-color:var(--line)}
.cfm-pas{display:inline-flex;flex-direction:column;border:1px solid var(--line);border-radius:8px;background:var(--surface);overflow:hidden}
.cfm-pas-b{display:grid;place-items:center;width:26px;height:13px;padding:0;border:0;background:none;color:var(--muted);cursor:pointer}
.cfm-pas-b + .cfm-pas-b{border-top:1px solid var(--line)}
.cfm-pas-b::before{content:"";width:5px;height:5px;border-left:1.6px solid currentColor;border-top:1.6px solid currentColor;transform:translateY(1.5px) rotate(45deg)}
.cfm-pas-b.is-bas::before{transform:translateY(-1.5px) rotate(225deg)}
.cfm-pas-b:hover:not(:disabled){background:color-mix(in srgb,var(--tnt, var(--accent)) 12%,var(--surface));color:var(--tnt-t, var(--text))}
.cfm-pas-b:disabled{opacity:.3;cursor:default}
.cfm-tag{flex:none;font-size:.6rem;font-weight:700;font-style:normal;letter-spacing:.3px;color:var(--accent-text);border:1px solid color-mix(in srgb,var(--accent) 35%,var(--line));border-radius:999px;padding:0 6px;text-transform:none}
.cfm-arts{margin:2px 4px 8px 34px;padding:4px 0 4px 10px;border-left:2px solid color-mix(in srgb,var(--tnt) 30%,var(--line))}
.cfm-a{display:flex;align-items:center;gap:8px;min-height:30px;padding:2px 6px;border-radius:8px;font-size:.78rem}
.cfm-a:hover, .cfm-a:focus-within{background:var(--surface-2)}
.cfm-a .cfm-sw{width:12px;height:12px;border-width:1.5px}
.cfm-a-code{flex:none;min-width:78px;padding:1px 6px;border-radius:6px;background:var(--surface-2);font-family:'DM Mono',monospace;font-size:.66rem;color:var(--muted)}
.cfm-a-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.cfm-vide{font-size:.74rem;color:var(--muted);padding:6px 4px;font-style:italic}
.cfm-add{display:flex;align-items:center;gap:6px;width:calc(100% - 8px);margin:4px;padding:7px 10px;border:1px dashed color-mix(in srgb,var(--tnt, var(--accent)) 35%,var(--line));border-radius:9px;background:transparent;color:var(--tnt-t, var(--accent-text));font:inherit;font-size:.76rem;font-weight:700;cursor:pointer;transition:background-color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out)}
.cfm-add:hover{background:color-mix(in srgb,var(--tnt, var(--accent)) 8%,var(--surface));border-style:solid}
.cfm-add-univ{justify-content:center;width:100%;margin:4px 0 0;padding:10px;border-width:1.5px;color:var(--accent-text)}
@media (prefers-reduced-motion: reduce){ .cfm-close, .cfm-f, .cfm-car::before, .cfm-sw, .cfm-act, .cfm-ic, .cfm-add{transition:none} }
/* Palette (panneau ancré au bouton 🎨) */
.cfm-pal{position:fixed;z-index:2700;width:252px;padding:10px 12px 10px;background:var(--surface);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-lg,0 12px 40px rgba(0,0,0,.25));animation:ilsFadeIn var(--dur-fast) var(--ease-out) backwards}
.cfm-pal-h{font-size:.78rem;font-weight:800;color:var(--text);margin-bottom:6px;line-height:1.3}
.cfm-pal-t{font-size:.62rem;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--muted);margin:8px 0 5px}
.cfm-pal-g{display:grid;grid-template-columns:repeat(7,26px);gap:6px}
.cfm-pal-b{width:26px;height:26px;padding:0;border-radius:50%;border:2px solid var(--surface);background:var(--tnt);box-shadow:0 0 0 1px color-mix(in srgb,var(--tnt) 45%,var(--line));cursor:pointer;transition:transform var(--dur-fast) var(--ease-spring)}
.cfm-pal-b:hover{transform:scale(1.12)}
.cfm-pal-b:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
.cfm-pal-b.is-on{box-shadow:0 0 0 2px var(--tnt);position:relative}
.cfm-pal-b.is-on::after{content:'✓';position:absolute;inset:0;display:grid;place-items:center;color:#fff;font-size:.8rem;font-weight:800}
html[data-theme="dark"] .cfm-pal-b.is-on::after{color:var(--surface)}
.cfm-pal-b.is-mini{display:inline-block;width:12px;height:12px;border-width:1px;vertical-align:-1px;cursor:inherit}
.cfm-pal-b.is-mini:hover{transform:none}
.cfm-pal-orig{display:flex;align-items:center;gap:7px;width:100%;margin-top:10px;padding:6px 8px;border:1px solid var(--line);border-radius:8px;background:var(--surface);color:var(--text);font:inherit;font-size:.74rem;cursor:pointer}
.cfm-pal-orig:hover:not(:disabled){background:var(--surface-2)}
.cfm-pal-orig:disabled{opacity:.45;cursor:default}
@media (prefers-reduced-motion: reduce){ .cfm-pal{animation:none} .cfm-pal-b{transition:none} }
/* Actes & codes */
html:root :is(#modal-parametres,.acv-tarifs) .pm-acte-band--univ.tnt td{background:color-mix(in srgb,var(--tnt) 13%,var(--surface));color:var(--tnt-t)}
html:root :is(#modal-parametres,.acv-tarifs) .pm-acte-band--fam.acv-fam.tnt{--fam:var(--tnt-t)}
html:root :is(#modal-parametres,.acv-tarifs) .pm-acte-row.tnt td:first-child::before{background:var(--tnt)}
html:root :is(#modal-parametres,.acv-tarifs) .pm-acte-row.tnt .acv-code{color:var(--tnt-t);background:color-mix(in srgb,var(--tnt) 9%,var(--surface));border-color:color-mix(in srgb,var(--tnt) 25%,var(--line))}
html:root :is(#modal-parametres,.acv-tarifs) .acv-univ-b.tnt{--u:var(--tnt)}
html:root :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.tnt{border-color:color-mix(in srgb,var(--tnt) 30%,var(--line))}
html:root :is(#modal-parametres,.acv-tarifs) .ais-act.acv-pil.tnt .pm-acte-input{color:var(--tnt-t)}
:is(#modal-parametres,.acv-tarifs) .acv-tnt-b{display:inline-grid;place-items:center;width:18px;height:18px;margin-left:6px;padding:0;border:0;background:none;cursor:pointer;vertical-align:-3px;opacity:.35;transition:opacity var(--dur-fast)}
:is(#modal-parametres,.acv-tarifs) .acv-row:hover .acv-tnt-b, :is(#modal-parametres,.acv-tarifs) .acv-tnt-b.is-propre, :is(#modal-parametres,.acv-tarifs) .acv-tnt-b:focus-visible{opacity:1}
/* Filtre « acte » (liste, photothèque) */
.pf-acte-univ-bloc.tnt, .pf-acte-fam-bloc.is-fam-tnt{--pf-tint:var(--tnt)}
/* Fenêtre Articles annexes */
.sec-tnt .rail{background:var(--tnt)}
.sec-tnt .sec-title{color:var(--tnt-t);border-color:color-mix(in srgb,var(--tnt) 42%,var(--surface))}
.sec-tnt .ord-ck input:checked + .bx{background:var(--tnt)}
.sec-tnt .ord-ck:has(input:checked){background:color-mix(in srgb,var(--tnt) 14%,var(--surface));border-left-color:var(--tnt)}
.sec-tnt .anx-jaw-b{color:var(--tnt)}
/* Résumé IA : annexe d'une autre couleur, ou acte que le labo a coloré — bord, nom ET
   pastilles de dents (règle universelle, Illan 28/09/2026 : « la couleur des dents en
   accord avec la couleur de l'item ») ; seul le vert des dents solidarisées reste. */
html:root .ais-act.tnt{border-color:color-mix(in srgb,var(--tnt) 32%,var(--line))}
html:root .ais-act.tnt .ais-n{color:var(--tnt-t)}
html:root .ais-act.tnt .ais-d:not(.gsolid){background:color-mix(in srgb,var(--tnt) 12%,var(--surface));color:var(--tnt-t)}
@keyframes oxSmIn { from { opacity: 0; transform: translateY(-4px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes oxSmOut { to { opacity: 0; transform: translateY(-3px) scale(.98); } }
.anx-row.anx-absent .ord-ck { opacity: .45; cursor: not-allowed; }
.anx-row.anx-absent .ord-ck:has(input:checked) { opacity: 1; box-shadow: inset 0 0 0 1px var(--warn); }

/* ── SCAN BODY (js/scanbody-fiche.js) : la ligne « Scan body ▾ » + une pastille par pièce ;
      le panneau reprend celui des sous-menus (.ox-sm-pop), en plus large. ── */
/* En ORANGE (Illan, 28/09/2026) : la couleur « à vérifier » du thème, clair comme sombre. */
.sbf, .sbf-pop { --k: var(--warn); --tnt-t: color-mix(in srgb, var(--warn) 80%, var(--text)); }
.sbf { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 3px 0 2px 10px; }
.sbf-b { display: inline-flex; align-items: center; gap: 4px; padding: 0; border: 0; background: none; font: inherit; font-size: .64rem; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase; color: var(--tnt-t, var(--k)); cursor: pointer; }
.sbf-c { display: grid; place-items: center; width: 15px; height: 15px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--k) 22%, var(--border)); background: color-mix(in srgb, var(--k) 5%, var(--surface));
  color: color-mix(in srgb, var(--k) 70%, var(--muted)); transition: background-color var(--dur-fast) var(--ease-out); }
.sbf-c svg { width: 9px; height: 9px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--dur-fast) var(--ease-out); }
.sbf-b:hover .sbf-c { border-color: var(--k); background: color-mix(in srgb, var(--k) 12%, var(--surface)); }
.sbf-b:focus-visible { outline: 2px solid color-mix(in srgb, var(--k) 45%, transparent); outline-offset: 2px; border-radius: 4px; }
.sbf.ouvert .sbf-c { background: var(--k); border-color: var(--k); color: var(--surface); }
.sbf.ouvert .sbf-c svg { transform: rotate(180deg); }
.sbf-pils { display: contents; }
.sbf-pil { display: inline-flex; align-items: center; gap: 4px; padding: 1px 6px; border-radius: 6px; font-size: .62rem; font-weight: 600; white-space: nowrap;
  color: var(--tnt-t, var(--k)); background: color-mix(in srgb, var(--k) 10%, var(--surface)); }
.sbf-pil b { font-weight: 800; }
.sbf-vide { font-size: .6rem; font-style: italic; color: var(--muted); }
.sbf-pop { width: 300px; }
.sbf-top { margin: 4px 2px 6px; }
.sbf-dt { flex: none; width: 34px; padding-top: 3px; font-size: .74rem; font-weight: 800; color: var(--tnt-t, var(--k)); }
.sbf-e { position: relative; margin: 2px 0 4px; padding: 7px 26px 7px 8px; border-radius: 9px; background: color-mix(in srgb, var(--k) 5%, var(--surface)); }
.sbf-x { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; font-size: .9rem; }
.sbf-l { display: flex; align-items: flex-start; gap: 6px; }
.sbf-l + .sbf-l { margin-top: 5px; }
.sbf-k { flex: none; width: 52px; padding-top: 4px; font-size: .56rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sbf-v { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 3px; }
.sbf-seg button { padding: 3px 6px; }
.sbf-seg button:disabled { opacity: .4; cursor: not-allowed; }
.sbf-d { padding: 3px 7px; border: 1px solid color-mix(in srgb, var(--k) 22%, var(--border)); border-radius: 7px; background: var(--surface); color: var(--text);
  font: inherit; font-size: .66rem; cursor: pointer; transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); }
.sbf-d:hover { border-color: var(--k); }
.sbf-d.on { background: var(--k); border-color: var(--k); color: var(--surface); font-weight: 700; }
.sbf-in { flex: 1 1 70px; min-width: 60px; width: 60px; padding: 3px 7px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); font: inherit; font-size: .66rem; }
.sbf-in-ref { flex-basis: 100%; }
.sbf-in:focus { outline: none; border-color: var(--k); box-shadow: 0 0 0 3px color-mix(in srgb, var(--k) 16%, transparent); }
.sbf-plus { display: block; width: 100%; margin-top: 2px; padding: 5px; border: 1px dashed color-mix(in srgb, var(--k) 35%, var(--border)); border-radius: 8px;
  background: none; color: var(--tnt-t, var(--k)); font: inherit; font-size: .66rem; font-weight: 700; cursor: pointer; }
.sbf-plus:hover { background: color-mix(in srgb, var(--k) 8%, var(--surface)); }

/* ── Panneau « Autres teintiers » (js/teinte-autres.js) : même famille que les sous-menus,
      un onglet par teintier, grandes cases. ── */
.tnx-tabs { display: flex; gap: 2px; padding: 2px; margin: 4px 4px 9px; border-radius: 9px; background: color-mix(in srgb, var(--k) 8%, var(--surface)); }
.tnx-tabs button { flex: 1; padding: 4px 0; border: 0; border-radius: 7px; background: none; color: var(--muted); font: inherit; font-size: .62rem; font-weight: 700; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out); }
.tnx-tabs button:hover { color: var(--text); }
.tnx-tabs button.on { background: var(--surface); color: var(--accent-text); box-shadow: 0 1px 3px color-mix(in srgb, var(--text) 14%, transparent); }
.tnx-g { display: grid; gap: 3px; padding: 0 4px 2px; }
.tnx-g-chromascop { grid-template-columns: repeat(5, 1fr); }
.tnx-g-blanchiment { grid-template-columns: repeat(4, 1fr); }
.tnx-c { height: 24px; padding: 0; border-radius: 7px; border: 1px solid color-mix(in srgb, var(--k) 22%, var(--border)); background: var(--surface); color: var(--text); font: 700 .66rem 'DM Mono', monospace; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); }
.tnx-c:hover:not(:disabled) { border-color: var(--k); transform: translateY(-1px); }
.tnx-c:disabled { opacity: .3; cursor: default; border-style: dashed; }
.tnx-c:focus-visible { outline: 2px solid color-mix(in srgb, var(--k) 45%, transparent); outline-offset: 1px; }
.tnx-3d { display: grid; gap: 5px; padding: 0 4px 2px; }
.tnx-3r { display: grid; grid-template-columns: 24px 1fr; align-items: center; gap: 4px; }
.tnx-3l { font-size: .52rem; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); white-space: nowrap; cursor: help; }
.tnx-3b { display: flex; gap: 3px; }
.tnx-3b .tnx-c { flex: 1; min-width: 0; }
@media (prefers-reduced-motion: reduce) { .tnx-c:hover:not(:disabled) { transform: none; } }
/* Cartes Conjointe / Adjointe AÉRÉES (Illan, 28/09/2026 : « allonger ces 2 onglets avec l'espace
   qu'on a gagné ») : la barre d'actions, la ligne Fournisseur et « Sans date » partis (~58 px),
   la place revient aux LIGNES des deux cartes — cases plus espacées, plus faciles à viser —
   plutôt qu'à du vide. Mesuré : 414 → 472 px, la hauteur d'avant. Ordinateur seulement.
   Allongées encore le 30/09/2026 (Illan : « allonge la zone de conjointe et adjointe », en
   hauteur) : 472 → 538 px, cases et titres plus espacés. */
html:not(.mobile-zoom-default) .main-row .sbody .grid2 .ord-ck { padding-top: 5px; padding-bottom: 5px; }
html:not(.mobile-zoom-default) .main-row .sbody .grid2 .ord-h { margin-bottom: 7px; }
html:not(.mobile-zoom-default) .main-row .sbody .grid2 .ord-h:not(:first-child) { margin-top: 16px; }
/* Flèche d'arcade dessinée (window.ordFleche) : badges, bulle, boutons Haut / Bas. */
.ord-fleche { display: inline-block; width: 1.12em; height: 1.12em; vertical-align: -.2em; flex: none; }
.ord-fleche path { fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.ord-teeth .jaw:has(.ord-fleche) { font-size: 1em; font-weight: 700; vertical-align: 0; margin-right: 3px; }
